本系列内容来自《架构师修炼之道》。在自己的笔记中以半摘录的方式,用 blockquote 穿插自己的思考和感悟,以加深对内容的理解和消化。
全书整体分为三个部分
-
第一部分介绍软件架构的基础知识和架构师必备的设计思维
-
第二部分讲解架构师需要掌握的核心技能和知识
-
第三部分讨论一系列使用的架构设计方法
前两部分适合从头到尾通读,第三部分用于参考和检索。
优秀的架构描述是有用的资产,它能促进沟通与协作,将设计决策和思想有效传递给每个人,提高软件开发的质量。用人性化的、简洁的形式向受众展示确切的信息。
11.1 讲述完整的故事
架构描述的重要性主要体现在以下几个方面:
**组织有序。**开发软件既要与人打交道,也要与技术打交道,两者同样重要,架构描述展示了所有东西是如何组织在一起的。为了管理和协调开发工作,每个人都需要知道系统中的组件如何系统运作。
在开发人员与业务相关方之间建立通用语。所有利益相关方都有权理解架构。架构模型建立了设计词汇,架构描述则将这些模型转化为利益相关方可以理解的形式。架构描述最重要的作用之一是向业务相关方展示软件架构是如何实现业务目标和提升质量属性的。
突出质量属性。 质量属性通常不是那么清晰可见,容易被忽略。架构描述将质量属性视为一等公民,将质量属性清晰呈现出来,化虚为实,让人们可看、可读、可谈。
理清思路。如果不试着写架构描述,很容易会以为所有东西都清楚了。笔尖触到纸的那一刻,你会发现脑子里的想法不过是一团糨糊。写架构描述强迫我们搞清楚什么是我们知道的,什么是我们认为我们知道的,还有什么是我们不知道的。
创建可评估的媒介。我们无法推演看不见、摸不着的东西。我们也不能等到设计决策在代码里实现后再来做评估。架构描述提供了一种分析设计决策的媒介,以便及时发现错误。花一个下午解释一个愚蠢的想法,总比花一个月开发要好的多。
展示架构。软件架构很酷!你倾尽全力设计的系统,应该让所有人都来欣赏!架构描述是展示系统的有效方式,它能让客户和管理层对你的设计产生信心。架构描述中清晰的目标、计划、愿景将彰显你的领导能力。
11.2 因地制宜,选择描述方法
为了决定如何描述和记录架构,架构师应该问自己两个问题。设计决策发生变更的可能性大吗?将来准备在多大程度上分享设计决策?你的回答决定了应该采用下述四种方法中的哪一种。
11.2.1 部落描述:口述历史
部落描述方式严重依赖口头约定。故事、隐喻、草图都属于部落描述方法。我们的工作总是从这里开始。部落描述很容易修改,尤其符合初期架构设计的快速探索要求。
虽然部落描述很容易生成和修改,但很难共享。当大家聚在一起工作时,系统隐喻可以很好地发挥运作。不过这种口头约定只在有人擅长讲解时才奏效,而且频繁讲解会让人筋疲力尽,哪怕是只有六个人的小团队。
11.2.2 社区描述:传播得更远
根据经验,如果你发现自己不止一次向同时讲解某一处架构设计,那么就应该设法采用更易于分享的方式描述架构。社区描述方法就派上用场了。
社区描述方法的重点是可以在社区内蓉香,而不仅仅靠口口相传。架构主旨、架构显见的编码风格、架构决策记录都是社区描述方法。社区描述也有易于修改的特点,而且比部落描述容易分享。
随着架构逐渐成熟,大多数团队会自然地从部落描述过渡到社区描述。社区描述方法对于许多团队来说已经够用了。如果项目还需要一些更持久的东西,则可以采用正式描述方式。
11.2.3 正式描述方式:必要时才采用
正式描述由传统的架构藐视文件和正式模式组成。这类文档很长,需要更多精力创建。正式模型(用数学模型定义的那种架构)需要更高的准确度和精度。如果系统风险和架构决策风险较高,或是需要高度协作,可以考虑采用正式描述方法。另外,有些行业可能要求使用正式文档。即便如此,创建正式描述之前,最好还是从部落描述和社区描述开始。
11.2.4 创建传统的软件架构描述
每个架构师都应该会写传统的软件架构描述(SAD)文档。虽然写这类文档非常耗时,但它们有重要的价值。我不是说要文档写得很长,只是说传统的SAD在合适的时候也能发挥作用。
大多数利益相关方,甚至是开发人员,可能从未见过整个架构。而 SAD 可以将所有东西汇总在一起。
写传统架构描述的第一步是创建或者查找文档模板。网上有许多现成的模板。所有传统架构描述都包含相同的基本部分:
引言和导读信息。 包含标题页、版本说明、签名页、目录、图表目录、许可和法律声明等。目录和图表目录可用于检索。其余部分旨在表明文件中所掌握信息的重要性。有的利益相关方可能认为这些内容很重要。
文档综述和简介。 简要介绍文档的目录以及组织和创建文档的方法。SAD 可能是某些利益相关方第一次读到的架构描述。你可以借此机会适当介绍背景知识,以便读者能够欣赏你的架构设计。
利益相关方诉求、业务目标和关键架构需求概述。 架构中的所有决策都基于利益相关方的诉求,因此在描述设计之前有必要列出这些诉求。如果你已经创建了ASR工作簿,可以在这里说明,并给出链接。架构描述应该做到尽量简洁,避免重复,就像代码一样。
系统情景图。 简要介绍软件系统所处的背景和环境
相关视图。 围绕受众关心的问题组织视图。
风险、未解决问题及后续工作。 总结已知的风险和未解决问题。这样做的目的是在已知的“雷区”周围点亮红灯,提醒以后的设计人员。
附录。 至少应该给出术语表。我建议将质量属性分类方案作为附录。有些正式文档的附录还包括变更流程和变更请求模板。
创建 SAD 可能会让人精疲力尽,需要团队协作完成。可以制定一个人负责创建模板并分配编写任务,同时确保文件内容、风格统一。
11.2.5 徒劳描述
徒劳描述指的是难以更改、难以分享的描述方法。在实际工作中,最好不要采用这种描述方法。让我们来看看徒劳描述的例子。用精美的幻灯片描述架构就属于徒劳描述,这是一种浪费时间的做法。精美的幻灯片不是不好,但制作起来费时。你需要花数小时调整标题、字体等细节。投入这么多精力后,即使内容有变化,也没有人愿意再去修改那些精美的布局。与部落描述方法相比,幻灯片就像是刻在了石头上,很难擦洗。不过,无论采用哪种描述方法,出色的描述都有以下四个特征:
-
根据受众的需求定制。
-
用多个视图展示架构。
-
清晰定义元素及其功能。
-
解释设计决策的逻辑依据。
11.3 尊重受众
设计思维的四条原则指出:设计的本质是社交。谁会读你的架构描述?他们需要什么?如何才能提供他们需要的信息?之前通过换位思考,我们已经确定了利益相关方的需求。我们设计了架构,用来解决他们的问题,现在要做的就是设法分享这些信息。只有了解受众,才能写好架构描述。你写得越好,人们越愿意阅读,这又会进一步扩大设计决策的影响。
我们都见过某些开源项目的代码库,用一个文件夹装数百个源文件。你花了很多精力推测这些系统是如何运行的,仍然免不了犯错。
如果换个方式组织代码,理解起来会容易很多,比如将代码按层次组织,这样就可以随时放大查看细节,缩小纵观全局。分层有助于清晰思考。如果你希望别人理解你的代码,就必须自己创建层次,讲清楚系统的故事。同时充分利用架构模式提供的通用名称,如连接器、层等。
分层需要花时间进行调整,才能做到清晰无误。今天你可能只有三个连接器,放在一个文件夹里没问题,但你需要不断调整,否则等出现几十个连接器,还放在一个文件夹里就麻烦了。小洞不补,大洞吃苦。
将注意力集中在源代码上是相对容易的,但系统的运行同样值得关注,还有如何将其分配到硬件和容器里。如果你希望清晰地思考,不妨从多个层次讲故事。
考虑利益相关方及其关心的问题。他们在项目中的角色和职责是什么?他们如何处理信息?他们如何使用你提供的信息?有时,创建受众的移情图(empathy map)是个不错的办法。下图是一位开发人员的移情图。
从这张移情图中不难看出,这位开发人员需要一份清晰的、有逻辑依据的文档,因为他喜欢就每个决策展开辩论。他对部署感兴趣,并且关注技术细节。
明白受众需要的信息和消化信息方式后,我们来看看如何为他们提供易理解的架构描述。
11.3.1 提高可理解性
写架构描述的目的在于与受众沟通。请使用受众熟悉的领域语言,提高架构描述的可理解性。如果利益相关方总是提到物料主编码(material master number),请尊重他们的习惯,而不要引入新的词汇(比如产品ID)。
描述复杂、抽象的想法时尤其要小心。尽量使用大白话,避免使用生僻的行话。必要时,可以对架构概念做简单的解释,以确保受众掌握必要的背景知识。沿用利益相关方已经使用的设计术语(除非存在误用)。例如,如果对方习惯使用非功能性需求,那么你就不要使用质量属性。首先保证有效沟通。
符号的使用也会影响可理解性。不是所有人都了解设计符号的用法,尤其是 UML 的用法。UML有几种风格,虽然它可以表现设计构思,但有时并不是那么直观。你可能精通 UML 图表的用法,但并非所有人都对 UML 了如指掌。第10.2节提到过,所有图表都应该附上图例,用图例说明符号的意义和元模型。
最后,请用标准模板写文档,这样看起来更专业。统一对齐方式,考虑版式在屏幕上显示和打印的效果。漂亮的文档能给读者留下好印象,说明内容是由专业人士创建的,值得信赖。
11.4 围绕利益相关方关注点组织视图
对你正在开发的软件,不同的人有不同的关注点。开发人员希望了解代码结构、部署方式、组件交互方式。测试人员希望了解接口和通信协议。产品负责人希望了解技术依赖和整体进度。新成员可能会被文档淹没,需要帮助才能起步。另外,架构描述至少还应包含设计决策、决策依据和架构结构。
这些信息的组织方式很重要。设计以人为本,这条原则既适用于设计本身,也适用于对设计细节的分享。两者同样重要。
从利益相关方的角度出发,组织架构视图和各种设计文档,对方理解架构就会容易得多。我们应该考虑对方想了解什么,然后从这个角度创建架构视图。
11.4.1 建立视点
视点(viewpoint)决定了你如何从利益相关方的角度描述架构。视点不仅决定了应该展示哪些视图,也决定了视图的受众,以及视图使用的符号、词汇、规则。
视点的定义虽然来自传统的架构描述,但其原则适用于我们讨论过的所有架构描述方法。软件行业已经有一些制定好的视点集。我推荐软件工程研究所 (Sofware Engincering Institute, SEI)的超越视图方法、Phillipe Krutchen 的 4+1 视图模型(4+1 View Model) 、Rozanksi 和 Woods 的视点与视角 (Viewpoints and Perspectives),以及 Simon Brown 的C4 模型。
视点通常是围绕质量属性组织的。你也可以构建视点来满足特定利益相关方的需求。这里有一些例子:
-
可扩缩性视点、安全性视点、可维护性视点可以展示架构如何满足这些质量属性场景。
-
监管视点可以为关心监管信息的利益相关方提供所需信息,用于审计。
-
指导视点可以让新成员初步熟悉架构和开发方式,让他们在第一天就能提交代码。
-
业务视点可以展示架构的不同部分如何贡献业务价值。
视点在传统架构描述中是必不可少的。我们可以使用部落描述和社区描述将其简化。例如,如果代码库己经有多个 ADR,就可以创建一个视点页面将这些决策的链接汇总起来。
视图帮助我们组织想法,以便有效地共享架构信息。架构描述不仅仅包含视图和设计决策,还应该说明为什么这样决策。
11.5 阐述决策的逻辑依据
设计的逻辑依据 (design rationale)是你做出设计决策的理由,比如为了提升某个质量属性选择某种架构模式,或者为了节省成本选择某种技术。每个决策都有利有弊,设计的逻辑依据说明了我们是如何权衡利弊,最后做出决策的。
后续设计人员越了解决策依据,就越容易接受你的设计意图。其他人越了解决策意图,就越容易在系统的演变过程中维护架构的完整性。
架构描达中的逻辑依据有多种形式,比如文字描述或几条要点。有时候,列出所有淘汰的方案比冗长的解释更有说服力。
11.5.1 描述未选择的道路
开发软件就像一趟旅程。道路蜿蜒曲折,也许有数十条路通往同一目的地。你的每一次决策,都能帮助别人明白为什么要这样设计。有一种描述方式是列出那些被淘汰的方案。
我们做决策时不是所有人都在场。列出淘汰方案相当于对决策过程进行回放,以便其他人理解我们是怎么走到这里的。如果省略这些信息,就如同看电影只看到了最后五分钟——错过了所有的剧情,也就难以理解角色最后的行为。
我们淘汰的想法远远多于留下的。人们可以在眨眼间闪过几十个念头,有些甚至连自己都没有意识到。经团队讨论做出的任何决定都应该正式记录下来。如果你发现自己有强烈的表达愿望,试着将你的想法记录下来,其他人也将丛中受益。
结束语
架构描述的好坏取决于编写的人,你必须了解受众希望看到哪些内容,从他们的角度组织架构视图。别忘了描述元素及其共呢个,还有选择它们的原因。另外要选择恰当的描述方法,冗长死板的文档并不是解释设计决策的唯一办法。最重要的是有效地向他人解释架构设计。
描述架构为我们提供了检验系统设计的第一次机会。能够在早期检验架构,这是一件好事情。接下来我们需要开展架构评估,减少后续的麻烦。