Table of Contents
那天我之前的同事突然在领英上给我发消息:
他说的是指我一直在前东家的组里面推一种叫做 C4 的模型。
什么叫做 C4 模型?
C4 模型是一种描述软件系统的建模方式,其中的 C4 指的是 Context(系统上下文),Container(容器),Component(组件),Code(代码)。这四个层级从高到低,从全局到局部,从不同的层级来描述一个软件系统。
Context 系统上下文
系统上下文是最高层的描述了,描述了系统之间的关系。如下图所示,蓝色的方块表示一个 Internet Banking System, 箭头表示系统之间的交互。注意,因为完全是面向系统上下文的描述,系统之间的交互描述是功能,而不是具体的技术细节。调用 E-mail System 发邮件的时候,可能是通过 HTTP 接口有可能是通过消息队列,但是这种实现细节是不应该出现在 Context 这一层的。
Container Diagram 容器
当我们将一个系统放大(zoom in), 就得到了某个系统的容器构成。如图,当我们仔细去看上面 Context 中的 Internet Banking System, 就会看到这个系统中的各个容器,包括数据库,前端,后端等等。在这一层里面,也会涉及到技术栈的选择,例如选择关系型数据库还是 NoSQL 数据库等等。
Component 组件
当我们进一步将某个 Container 放大的时候,就会得到了代码库中一个个的组件。这些组件往往完成代码中的某一部功能,例如 Controller 提供 HTTP 接口,Repository 提供数据库的访问等等。
Code 代码
如果针对某个组件,想记录一下它是怎么实现的,就可以得到代码层的描述。通过使用 UML,ER 模型来描述。实际上 UML 用得很少,但是 ER 模型来描述数据设计还是用得挺多的。
在系统设计面试中使用 4C 模型
在系统设计面试中,面试官往往要求面试者设计一个整个业务系统。例如设计一个订票系统,设计一个网站卖书等等。系统设计往往是决定最后 offer 层级的关键性一轮,但是很多面试者其实并没有从头去建设一个新系统的工作经验,所以往往无从下手。
这个时候,4C 中的 Context 和 Container 就是一种非常清晰和有条理的来描述系统的方式。我一般进行系统面试的流程是首先问清楚需求,然后划分清楚业务领域模型,最后画出一个 Context 图。接着我会给面试官解释,Context 中的每个系统都是完成什么业务功能的。但是我不会深入到具体的技术栈选择细节中,比如我不会谈A 系统和 B 系统之间的是用消息队列通信还是 HTTP 通信,这是接下来要做的事情。
等面试官认可这种系统划分方式以后,他通常会就某一个系统深入进行问。这个时候,就是需要把 Context 某个系统扩展成 Container 的时候了。基本上,你需要完成的事情是:
- 定义 Container 对外的接口,如果是 HTTP 通常是 Restful,如果是消息队列通常需要定义一个 JSON schema。
- 定义本地存储的中的 Entity,例如数据库的表等。
接着面试官可能会深入讨论一些技术选型,例如用关系型数据库还是 NoSQL 啊,HTTP 是同步还是异步处理等等,不过这个不在本文的讨论范围。
在平时工作中使用 4C 模型
就像开头我的前同事说的一样,我一直是在平时的工作也使用这种方式来描述系统的。当然平时工作肯定不会每天都搞一个新的系统,所以主要是用 Component 层来描述一个个服务。等你把一个微服务的 Component 层都画好以后,任务的划分就非常自然了。一般情况下,一个 Component 我会划分成一个 Jira 上的任务,比如一个 Jira 实现一个 HTTP controller 等等。如果要是多人合作的情况下,我甚至会把定义接口和实现划分成两个子任务,一来方便 review,二来方便估算任务量。
总结:
4C 模型是一种系统化的描述系统的方式。从粗到精,从全局到局部。不光用在系统设计面试中,在平时工作中也能帮我们理清系统之间的业务关系,理解服务中的代码关系。