使用C4模型来记录软件架构的实例教程

849 阅读6分钟

很久以前,我曾经是UML的支持者,我甚至启动了一个名为MonoUML的开源项目(已经停用)。MonoUML的目的是,自动帮助开发者使用基于UML的图表来记录他们的代码,几乎不需要人工干预。

遗憾的是,我很快意识到使用UML不是办法,当然有一些伟大的想法和一些有用的图表,但最终有太多的细节需要记住,以正确有效地使用这种建模语言。

在离开UML之后,我开始使用框图和线图,没有什么花哨的东西,而且肯定不是标准化的这也是可行的,但是几年前我看到了Simon Brown创建的这个模型,叫做C4模型,C4是指Context、Containers、Components和Code

C4是一种细长的UML,只有相关的数据才会呈现给对所描述的软件架构感兴趣的用户。这意味着在实践中,图的消费者是驱动显示多少信息的人,官方网站使用了谷歌地图这个伟大的比喻,根据你的目标是什么,你会看到不同的细节地图

C4模型定义了四个层次的图。

  • 背景(L1):最高级别,它显示了系统与用户和其他系统的关系。它被用来作为系统的快速介绍,通常是为了介绍给利益相关者,这是一个大的图示。
  • 容器(L2):将系统分解成相互关联的容器,容器是可执行和可部署的子系统。它是为了与那些需要更多关于系统组成的技术细节的人分享。
  • 组件(L3):将容器分解为相互关联的组件,将它们与其他容器或其他系统联系起来。它的目的是让那些不熟悉该系统的工程师在计划工作时阅读。
  • 代码(L4):提供关于实际代码如何实现的更多细节。它是为了清楚地显示系统中最复杂的部分的一些具体细节。

在使用C4模型几年后,我发现这四个层次足以描述复杂的软件架构,我发现实现前三个层次,而把第四个层次作为工程师需要审查和理解的实际代码

注意事项

所有与文档有关的东西都有注意事项,软件架构的文档也不例外。在这种情况下,这些注意事项是以问题的形式出现的。什么时候? 怎么做?还有谁?

  • 我们应该什么时候更新文档?
  • 我们应该如何更新文档?
  • 应该更新文档?

这三个问题如果没有足够的关于试图实现这个模型的团队的细节,是很难单独回答的,这是因为它们取决于团队本身以及他们所遵循的现有工具和流程。

理想情况下,这个文档是由从事系统工作的团队更新的,这是有道理的,因为他们真正接近正在实施的变化。通常情况下,使用基础设施作为代码的团队作为正在构建的系统的一部分,也许使用AWS的CloudFormation,也许使用Terraform这样的通用工具,保持这些文件的更新不那么困难,因为更新基础设施的细节会提醒作者在需要时也要重新审视这些文件。

在实践中,我还没有找到一种方法在提交变更到版本库时强制执行类似的变更,目前还没有针对这些的linter

推荐给所有团队成员的准则是,在做新的改动时,如果影响到与这些不同层次的任何东西,都应该更新图表。

例子

下面是一个具体的例子,使用我上次在视频《Go Tools: counterfeiter(博客链接)中介绍的假设的书店系统。这一次,这个系统将得到更多的扩展,像往常一样,这个例子的完整代码可以在我的Gitlab仓库里找到。

让我们从上下文图开始。

上下文图

Level 1 Context

当试图传达我们需要与利益相关者分享的关于我们的Books System 的三个细节时,这张图是绰绰有余的。

  • 它有两种不同类型的用户。公共的授权的
  • 依赖于一个外部授权系统进行授权,以及
  • 依赖于两个外部系统Publisher 1 SystemPublisher 2 System来实现目录目的。

接下来是容器图

容器图

Level 2 Container

这张图放大了,提到了实际系统的更多技术细节,它明确指出了我们使用的技术,比如Go、PostgreSQL、ElasticSearch和Kafka;根据所使用的技术,它调出了负责处理该工作的具体容器,具体我们看到(从左到右,从上到下)。

  • Search Web API:HTTP处理程序,使用ElasticSearch作为搜索数据库来搜索只读记录。
  • Admin Web API:HTTP 处理程序,使用 PostgreSQL 作为读写关系数据库来管理记录。
  • ElasticSearch Events Consumer:二进制监听Kafka域事件,用于按需更新搜索数据库
  • Publisher 1 Recurrent Updater:每隔X时间运行一次的二进制文件,负责从Publisher 1导入数据,它使用Admin Web API来更新这些数据。
  • 发布者2事件消费者:使用Kafka监听来自发布者2系统的外部事件,它使用Admin Web API来更新数据,和
  • 公共Web API:HTTP处理程序,使用PostgreSQL的只读零售商数据库来获取只读记录。

最后,组件图

组件图 - Admin Web API

Level 3 Component

这次我涉及的最后一张图是Admin Web API的具体组件图,请记住,如果你看一下上面的列表,有六个容器,我们可能要实现所有的容器或部分容器,这取决于它们的复杂程度;在这种情况下,我只实现这一个,但在实现其他五个时,想法应该是一样的。

这张图更多地放大了,描述了具体的容器以及彼此之间的交互情况,目的是给工程师提供更多关于事情如何实现的细节,例如指出什么具体的包或类型负责正在进行的工作。

结论

我发现C4模型比UML更适合记录软件架构,然而我们多年来的问题仍然存在,特别是我在开始时提到的问题,目前没有办法在对实际代码或基础设施进行修改时强制更新图表。

工程师们应该在进行这些改变时留心观察,并作出相应的反应,这说起来容易做起来难,可能需要一段时间让团队习惯,但这应该是努力保持文档更新时的最初步骤。