- 推荐序一:架构师真正要学会的事情
- 推荐序二
- 译者序 2.0
- 序
- 关于本书
- Part Ⅰ 什么是软件架构
- 第 1 章 什么是架构
- 第 2 章 架构的种类
- 第 3 章 软件架构是什么
- 第 4 章 敏捷软件架构是什么
- 第 5 章 架构对上设计
- 第 6 章 软件架构重要吗
- 第 7 章 问题
- Part Ⅱ 软件架构的角色
- 第 8 章 软件架构的角色
- 第 9 章 软件架构师应该编码吗
- 第 10 章 软件架构师应该是建造大师
- 第 11 章 从开发者到架构师
- 第 12 章 拓展 T
- 第 13 章 软技能
- 第 14 章 软件架构不是接力运动
- 第 15 章 软件架构要引入控制吗
- 第 16 章 小心鸿沟
- 第 17 章 未来的软件架构师在哪里
- 第 18 章 每个人都是架构师,除非他们有其他身份
- 第 19 章 软件架构咨询师
- 第 20 章 问题
- Part Ⅲ 设计软件
- 第 21 章 架构驱动力
- 第 22 章 质量属性(非功能需求)
- 第 23 章 处理非功能需求
- 第 24 章 约束
- 第 25 章 原则
- 第 26 章 技术不是实现细节
- 第 27 章 更多分层等于更高复杂度
- 第 28 章 协同设计是一把双刃剑
- 第 29 章 软件架构是对话的平台
- 第 30 章 SharePoint 项目也需要软件架构
- 第 31 章 问题
- Part Ⅳ 可视化软件
- 第 32 章 沟通障碍
- 第 33 章 对草图的需要
- 第 34 章 无效的草图
- 第 35 章 C4:语境、容器、组件和类
- 第 36 章 语境图
- 第 37 章 容器图
- 第 38 章 组件图
- 第 39 章 是否包含技术选择
- 第 40 章 你会那样编码吗
- 第 41 章 软件架构和编码
- 第 42 章 你不需要 UML 工具
- 第 43 章 有效的草图
- 第 44 章 C4 的常见问题
- 第 45 章 问题
- Part Ⅴ 为软件生成文档
- 第 46 章 代码不会讲述完整的故事
- 第 47 章 软件文档即指南
- 第 48 章 语境
- 第 49 章 功能性概览
- 第 50 章 质量属性
- 第 51 章 约束
- 第 52 章 原则
- 第 53 章 软件架构
- 第 54 章 外部接口
- 第 55 章 代码
- 第 56 章 数据
- 第 57 章 基础设施架构
- 第 58 章 部署
- 第 59 章 运营和支持
- 第 60 章 决策日志
- 第 61 章 问题
- Part Ⅵ 开发生命周期中的软件架构
- 第 62 章 敏捷和架构的冲突:神话还是现实
- 第 63 章 量化风险
- 第 64 章 风险风暴
- 第 65 章 恰如其分的预先设计
- 第 66 章 初识软件架构
- 第 67 章 问题
- Part Ⅶ 金融风险系统
- 第 68 章 金融风险系统
- Part Ⅷ 附录:技术部落 的软件指南
第 35 章 C4:语境、容器、组件和类
在任何软件系统的开发周期内,代码都是最受关注的部分。这很正常,因为最终交付的只有代码。但如果要向别人解释系统如何工作,你会一来就说代码吗?
可惜,代码并非全部。在缺少文档的情况下,人们通常会在白板或纸上画框线,来解释哪些是主要的结构单元以及它们如何相互连接。用图片描述软件时,我们会倾向于制作一个超级图,尽可能多地把各个抽象层次的细节都塞进去。这可能是因为我们在预设问题,或者有点过于关注系统在代码层面的运行细节。这样的图往往乱成一团,既复杂又令人费解。选择一个Microsoft Visio、Rational Software Architect或Sparx Enterprise Architect之类的工具,不但不会让事情变得简单,往往更复杂。
更好的方法是制作一些抽象层次各异的图。比起一张试图讲清所有事情的复杂图,多张简单图可以更有效地描述软件。
通用的抽象集合
如果软件架构是关于软件系统的结构,那就有必要理解哪些是主要结构单元,以及它们如何在不同的抽象层次上相互融合。
架构结构的简单模型
假设一个软件使用了面向对象的编程语言,我喜欢用如下方式来思考它的结构:软件系统由多个容器构成,容器又由多个组件构成,组件由一个或多个类实现。大多数软件系统都可以用这种简单的逻辑结构单元的层级关系来建模。
类:对我们大多数人来说,在一个面向对象的世界里,类是软件系统的最小结构单元。
组件:组件可以想象成一个或多个类组成的逻辑群组。比如,其他组件可以使用审计组件或认证服务,来确定对特定资源的请求是否放行。组件通常由多个类在更高层次的约束下组合而成。
容器:容器是指一个在其内部可以执行组件或驻留数据的东西。它可以是从网络或应用服务器直到富客户端应用或数据库的任何东西。作为整个系统的一部分,容器通常是可执行文件,但未必是各自独立的流程。比如,我把每个Java EE网络应用或.NET网站都看作一个独立的容器,不管它们是否运行在同一个物理服务器流程中。从容器的角度理解一个软件系统的关键在于,任何容器间的通信可能都需要一个远程接口,比如SOAP网络服务、RESTful接口、Java RMI、Microsoft WCF、报文,等等。
系统:系统是最高的抽象层次,代表了能够提供价值的东西。一个系统由多个独立的容器构成,例如金融风险管理系统、网络网银行系统、网站等。
通过精确定义各种结构单元并特化它们之间的联系,我们不难看出如何更进一步。但是我不确定这会特别有用,因为它会限制和复杂化我们的目标:理解软件系统的结构,并建立能描述它的、简单的抽象集合。
总结软件的静态视图
我总结软件的静态视图时,大概会凭借脑海中的抽象集合,画出如下几类图。
1.语境:设定场景的高层次图,包括关键的系统依赖和参与者。
2.容器:容器图显示了高层次的技术选择,容器如何分担职责、如何通信。
3.组件:组件图可以让你看到每个容器的关键逻辑组件及之间的关系。
4.类:这是一个可选的细节层次。如果想解释某个模式或组件将(或已经)被怎样实现,我会画少量高层次UML类的图。促使我给软件系统的部分分类画图的原因包括软件的复杂性,团队的规模和经验。我画的UML图通常会是草图而非综合性的模型。
通用标记法的通用抽象
画简单草图对我和合作过的很多团队都管用。但这是为了提供结构性的想法和指导,而非制订标准。目标是帮助团队以有效且高效的方式沟通他们的软件设计,而非创造另一套综合性的建模标记。
UML提供了一套通用的抽象和用于描述它们的通用标记,但我几乎看不到哪个团队可以有效地使用它们。我更愿意看到团队能够以通用的抽象来讨论他们的软件系统,而不是绞尽脑汁去理解各种标记元素想要展现的东西。至于我嘛,一套通用抽象比通用标记更重要。
大多数地图在履行这一准则上都是很好的例子。它们都显示了道路、河流、湖泊、森林、城镇、教堂等,但通常依据颜色编码、线条样式、图标等,使用不同的标记。理解它们的关键就是放置在地图一角的图例。在软件架构图中,我们同样可以使用图例。
必须重申,非正规的框线草图提供灵活性的代价就是一致性,因为你创造了你自己的标记,而不是使用UML等的标准。我的建议是注意颜色编码、线条样式、形状等,让你的团队自然发展出一致的标记。给每个图都添加一个解释标记的简单图例,这会很有帮助。如果命名真的是软件开发中最难的事情,就尽量避免一个图里都是带标签的框。标出框的含义有助于避免歧义,同时提供一个“一目了然”的友好视图。
图应该简单且脚踏实地
似乎有一个普遍的误解,“架构图”只能展示高层次的概念视图,所以难怪软件开发者常常认为它们毫无意义。软件架构图应该脚踏实地,软件架构流程应该关乎编码、指导和合作,而不是象牙塔。在架构图中包含技术选择(或可选项)通常是朝正确方向迈出的一步,可以让图看起来不像由一堆概念组件神奇地组合成一个端到端软件系统的象牙塔架构。
一张图可以很快变得乱七八糟,但一组简单的图让你可以有效地从不同抽象层次展示软件。这意味着说明你的软件会是一个又快又简单的任务,只需要花一点精力随时更新那些图。你永远不知道,其他人也可以看懂它们。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论