京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

京东云开发者
• 阅读 110

软件系统架构设计的目标不在于设计本身,而在于架构设计意图的传达。图形化有助于在团队间进行高效的信息同步,但不同的图形化方式需要语义一致性和效率间实现平衡。C4模型通过不同的抽象层级来表达系统的静态结构,并提供了最小集的抽象建模元素,为设计人员提供了一种低认知负载、易于学习和使用的高效建模方式。


1 为什么要进行架构可视化?

软件系统架构设计的目标不在于设计本身,而在于架构设计意图的传达。如果不能清晰、一致的在干系人间进行设计意图的同步,即使再好的设计也只是空中楼阁。软件架构设计本质上也是一种抽象和建模的过程(对模型和抽象的本质参考文章《 领域驱动设计开篇 》),软件架构设计模型的表达有多种方式:图形化、语言和文字。绝大部分场景下,图形化在架构设计的表现力层面效果更佳。因此,对于软件系统架构进行可视化表达是有价值,且是必要的。

软件架构可视化的方式有多种,不同的团队有不同的实践方式,最为常见的由如下几种:

线框图:通过线框图和连线表达架构元素及之间的关系

UML:统一建模语言,表达系统的静态结构和动态行为

草图:非正式的图形

不同的可视化方式各有优劣,以下部分将对不同的表现形式进行说明

1.1 可视化方式-线框图

线框图是最为通用的可视化表达方式之一,架构师或设计人员大量的架构图,比如技术架构、功能架构、数据架构、逻辑架构等等都通过线框图的形式表达。该种可视化方式的优势是:

建模工具多样化:你可以基于Viso、Drawio、PPT等任何一款支持线框图的软件进行建模工作

学习成本低:设计人员几乎不需要进行专门的建模语言以及建模工具的学习,门槛较低

但,基于线框图表达软件系统架构存在的问题也非常明显:语义的一致性问题

你可能自己画过很多软件系统架构图,也可能参与评审过其他团队的架构图,我相信,对你而言并不是的所有的图都是“清晰且易于理解的”。举个简单的场景,如果我们在百度搜索 “架构图” ,你可能得到以下结果:

京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

各式各样的 “架构图”:不同形状和颜色的图形元素、不同形状和颜色的连线、不同的意图。

我们可以看出:线框图虽然简单,但其其图形化的语义一致性是大问题。虽然都是通过线框表达软件系统架构,但不同的人可能使用不同的元素、不同的颜色、不同的连线和分层等等,线框自由表达的灵活性和图形化语义的一致性存在潜在冲突,最终都会阻碍架构设计意图传达。

1.2 可视化方式-UML

UML是统一建模语言,相比于线框图而言,其优势是在软件建模层面提供了一致性的建模元语言。简单来说,UML提供了大家达成一致的(UML支持扩展的场景除外)建模元素。如果团队成员比较熟悉UML,那么通过UML表达的系统架构图天然具有认知一致性。

丰富灵活的建模元语言在提升语义一致性的同时,也必然会导致复杂性的上升。掌握UML具有一定的学习成本,而熟练的应用对研发人员也提出了更高的要求。基于 Simon Brown给出的数据,实际情况只有少数团队真正使用UML。不论是UML的复杂度和学习成本原因,还是敏捷化下对UML的排斥,很多团队都放弃了UML。

我们不能否认UML的价值,基于统一建模语言能够更有效的进行架构设计的信息传递和沟通,也能基于UML提供的详细的模型图元素进行充分的设计表达。团队中是否要基于UML进行沟通需要权衡,虽然UML不能表达你所要传达的全部的架构信息,但其在某些维度的表达相对比较适合。

• 表达流程和工作流可以采用UML活动图

• 表达运行时的交互可以采用UML时序图

• 表达领域模型或者设计模式可以采用UML类图

• 表达状态转换可以采用UML状态机

• 表达系统的部署结构可以使用UML部署图

1.3 可视化方式-草图

架构可视化另一个非常常见的方式是:草图。草图是一种非正式的、易于快速沟通的图形化方式。团队基于特定的场景,可以通过草图的形式进行快速的沟通,以便高效的在干系人间拉齐关键信息。

但,草图的劣势与线框图一样:语义一致性低

我们可以在白板上 “随心所欲” 的画各式各样的草图,草图上的元素、连线,又或者布局都可能是涌现式的、临时性的,这些草图的价值在于 “会话周期内的高效沟通”。如果干系人没有完全参与到草图的讨论,又或是后置查看,大概也很难精准捕获这些草图所要表达的设计意图。

京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

2 C4 模型

2.1 C4模型的统一抽象

团队需要统一语言进行高效沟通 !!!

C4模型在不同的级别提供了统一的抽象以表达软件系统的静态结构。如下图所示:

京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

软件系统:最顶层的抽象,其对用户提供价值。包含待构建的系统以及外部依赖的系统

容器:表示一个应用或者数据存储,容器需要运行以支持系统的正常运转。每个容器都是独立部署或运行的单元,容器间的通信一般式跨进程交互

组件:提供一定能力封装的单元。在C4模型上下文中,组件不是独立部署的单元,一般情况下运行于容器之中

代码:系统的实现细节相关

:系统的使用用户

2.2 上下文图:System Context Diagram

我们要构建的系统不会孤立存在,都会依赖现有的IT设施。要明确我们构建的系统是什么,宏观上需要回答:我们的系统如何融入到现有的IT设施

系统上下文图正是从高层视角表述待构建系统与当前IT设施的交互及边界。通过上下文图:

• 展示与软件系统交互的各方及相互关系

• 展示软件系统与外部环境的边界

• 作为了解系统架构的切入点

• 确保所有人都理解、认可系统的工作范围

京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

2.3 容器图:Container Diargram

更进一步的剖析核心系统,回答:系统由哪些容器组成?容器的职责是什么?以及相关的高层的技术选型是什么?

与Docker的容器概念不同,C4模型的容器是在 “系统” 作用域之下,其表达的是组成系统的可独立可部署的物理单元。以下图为例:单个容器元素重包含了名称、职责描述、技术选型,同时,容器间的连线及标注标识了其高层的交互协议及交互形式。

京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

2.4 组件图:Component Diagram

进一步的剖析容器,回答:容器由哪些组件组成?这些组件的职责及组件间的交互形式是什么?

具体到每个容器内部,通过多个组件及组件间的关系表达容器的组成。“组件” 本身是一个泛化的概念,C4模型的组件是在 “容器” 的作用域之下,其表现形式可能是独立的Jar包,或者是应用内独立的包,也可能是类级别,但逻辑上都能够表达一个组件的概念。对于组件图关键的是要表示清楚组件的实现选型、组件职责以及组件间的交互关系。

京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

2.5 代码

代码处于C4模型的最低层,且是可选的,其关注的是实现相关。C4模型并没有对实现层面的可视化进行统一抽象,开发人员可以选择UML类图、E-R图等进行可视化。是否需要提现代码层面研发人员基于具体情况具体分析,一般情况下,如果系统中需要重点关注的部分可以考虑一些代码级别的图支持,比如,我们非常关注系统设计的可扩展性,则关键部分可能需要一些类图表达;又或者非常关注底层数据模型,则E-R图可以纳入考虑范围。

京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

3 C4模型实践中的决策和问题

连线表达依赖关系还是数据流向 ?

都可以,C4模型中的连线既可以表达依赖方向,也可以表达数据流向。原则上,设计人员需要保证其清晰且无歧义。实践中一般通过合理的文字说明来明确的表达元素间的关系。

Jar或类库应该建模为“容器”? “组件” ?

Jar包或类库一般是链接到调用方的进程中,作为进程中的一部分存在,这种依赖一般不表示为容器,而是组件。当然,是否要将Jar,比如SDK表示为组件并体现在组件图上需要设计人员具体情况具体分析。

数据存储系统应该建模为 “软件系统” 还是 “容器” ?

数据存储系统,比如MySQL、DFS等一般是作为独立的外部存储集群存在,集群的运维可能归属于公司的运维团队。以OSS为例,但从应用角度而言,即使集群的运维不归属当前开发团队,团队也会申请租户隔离的专属空间,因此,在C4模型中这种情况应该表述为 “容器”。

消息系统应该如何建模 ?

消息系统一般作为两个容器间的交互媒介,因此在C4模型中消息系统的建模存在两种方式:

• 依赖消息系统的容器都显示与消息系统交互,明确的表达各自与消息系统的依赖关系或数据流向

• 屏蔽消息系统,只提现容器间的依赖关系,并对依赖进行明确说明

图形化的过期问题

C4模型本身也是一种文档化机制,同样也存在过期问题。只不过C4模型通过对系统在不同的层级进行抽象,每个抽象层级的过期频率不同,由上到下逐渐增大,上下文图的变化频率最小,而代码级则变化最大。

为什么C4不涉及业务流、状态机、数据模型等建模

C4模型仅对系统的静态结构进行建模,并不试图囊括或替代其它建模方式,C4模型并不适合所有维度的可视化表达。对于业务流可以基于BPML、UML活动图进行表达,状态机可以基于UML状态机图进行表达,而数据模型可以通过E-R图表达,不同建模语言相互补充。

4 系统架构设计关注不同维度

作为架构师或系统设计人员,在进行系统架构设计时一般会关注不同维度,一般情况下,对于业务系统建设而言,会关注以下维度。在架构设计(架构和设计)过程中,基于C4模型、UML及BPML等多种建模方式相互补充,不同表现维度下可以采用不同的建模方式

• 业务流程:泳道图或UML活动图,表达核心的业务流

• 业务用例、系统用例:UML用例图

• 领域模型:UML类图

• 系统边界:C1,系统上下文图

• 高层技术选型:C2,容器图

• 系统职责分配:用线框图表示功能架构

• 关键部分的实现:C3,组件图

• 系统关键的交互逻辑:UML时序图

• 数据模型:E-R图

• 关键实体的状态机:UML状态机图

• 不同的高优先级架构属性的设计:比如,缓存方案、幂等性设计方案、定时任务补偿策略、降级限流策略等等,这些都与具体的需求所关注的高优先级的架构属性相关。

• 部署架构:UML部署图

5 总结

软件架构设计的终极目标不在于设计本身,而在于架构设计意图的传达。图形化有助于在团队间进行高效的信息同步,但不同的图形化方式在语义一致性和效率间存在平衡。C4模型通过不同的抽象层级来表达系统的静态结构,并提供了最小及的抽象建模元素,为设计人员提供了一种低认知负载、易于学习和使用的高效的建模方式。在实际项目落地过程中,结合C4模型以及UML、线框图等组合方式对架构设计进行可视化表达,一定程度上能够提升团队对架构设计认知的一致性以及建模效率。

作者:倪新明

点赞
收藏
评论区
推荐文章
Stella981 Stella981
1年前
Service Mesh 最火项目: Istio 架构解析
Istio是一个开源的服务网格,可为分布式微服务架构提供所需的基础运行和管理要素。随着各组织越来越多地采用云平台,开发者必须使用微服务设计架构以实现可移植性,而运维人员必须管理包含混合云部署和多云部署的大型分布式应用。Istio采用一种一致的方式来保护、连接和监控微服务,降低了管理微服务部署的复杂性。从架构设计上来看,Istio服务网格在逻辑上分为
腾讯云原生 腾讯云原生
1年前
宙斯盾 DDoS 防护系统“降本增效”的云原生实践
作者tomdu,腾讯云高级工程师,主要负责宙斯盾安全防护系统管控中心架构设计和后台开发工作。导语宙斯盾DDoS防护系统作为公司级网络安全产品,为各类业务提供专业可靠的DDoS/CC攻击防护。在黑客攻防对抗日益激烈的环境下,DDoS对抗不仅需要“降本”还需要“增效”。随着云原生的普及,宙斯盾团队持续投入云原生架构改造和优化,以提升系统的处理能力及
Wesley13 Wesley13
1年前
ARM与X86架构的对决
CISC(复杂指令集计算机)和RISC(精简指令集计算机)是当前CPU的两种架构。它们的区别在于不同的CPU设计理念和方法。早期的CPU全部是CISC架构,它的设计目的是 CISC要用最少的机器语言指令来完成所需的计算任务。RISC和CISC是设计制造微处理器的两种典型技术,虽然它们都是试图在体系结构、操作运行、软件硬件、编译时间和运行时间等诸多因素中做出
Stella981 Stella981
1年前
NET Core Web API下事件驱动型架构CQRS架构中聚合与聚合根的实现
NETCoreWebAPI下事件驱动型架构在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅、通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件总线的实现。接下来对于事件驱动型架构的讨论,就需要结合一个实际的架构案例来进行分析。在领域驱动设计的讨论范畴,CQRS架构本身就是事件驱动的,因此,我打算首先介
Wesley13 Wesley13
1年前
SOA面向服务的分布式架构详解
导语:SOA作为一种面向服务的架构,是一种软件架构设计的模型和方法论。从业务角度来看,一切以最大化“服务”的价值为出发点,SOA利用企业现有的各种软件体系,重新整合并构建起一套新的软件架构。这套软件架构能够随着业务的变化,随时灵活地结合现有服务,组成新软件,共同服务于整个企业的业务体系。简单的理解,我们可以把SOA看作是模块化的组件,每个模块都可以实现独立功
Wesley13 Wesley13
1年前
API设计的一点思路
API是模块或者子系统之间交互的接口定义。好的系统架构离不开好的API设计,而一个设计不够完善的API则注定会导致系统的后续发展和维护非常困难。以下谈一点API设计的原则。业务层业务语义简单明确一个接口或者说一个api,必定是为外部使用者服务的,因此必须具有明确的业务/使用意图。api的从命名到定义,都必须围绕着这个意图来进行
Wesley13 Wesley13
1年前
#分布式系统架构之# 事件驱动模式以及与之匹配的长时间处理过程讨论
     在分布式系统下,可以很多种架构从事设计,或者分布式系统对技术架构本身没有做严格的限制。但是结合自己的实践以及基于《领域驱动设计》的推荐,采用【事件驱动模式】是比较好的一种分布式系统架构方式。该模式充分实现了不同系统之间的代码解耦,所有的业务流转是通过事件广播进行驱动的。所有业务都是在针对名为【事件总线】的组件在编程,也无需知道事件的生产者
Wesley13 Wesley13
1年前
InfoQ 趋势报告:架构和设计领域技术演变详解
https://www.infoq.cn/article/R7lWXd0R4VFf3E0bB\38本文概述了我们对当前“架构和设计”领域的看法,这个领域侧重于基础设施模式、技术框架模式的实现,以及软件架构师必须掌握的设计流程和技能。关键要点:我们看到了“演化式架构”设计需求的增长,这种架构建立在可替换性设计和关注“胶水”
Easter79 Easter79
1年前
Tedis:基于 TiKV 构建的 NoSQL 数据库
作者介绍:陈东明,饿了么北京技术中心架构组负责人,负责饿了么的产品线架构设计以及饿了么基础架构研发工作。曾任百度架构师,负责百度即时通讯产品的架构设计。具有丰富的大规模系统构建和基础架构的研发经验,善于复杂业务需求下的大并发、分布式系统设计和持续优化。个人微信公众号dongming\_cdm。Tedis(https://github.
Wesley13 Wesley13
1年前
Java内存模型详解
内存模型(memorymodel)内存模型描述的是程序中各变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存取出变量这样的低层细节.不同平台间的处理器架构将直接影响内存模型的结构.在C或C中,可以利用不同操作平台下的内存模型来编写并发程序.但是,这带给开发人员的是,更高的学习成本.相