关键要点
我们尝试通过创建架构图(作为技术文档的一部分)来反映应用程序的内部状态,但大多数时候我们都没能做对。由此产生的架构图可能非常全面,也可能非常模糊。有时,架构图根本就是不相关的。我之前写过一些关于如何创建有用架构图的技巧。
即使创建了相关的架构图,我们也很少更新它们,作为持续开发过程的一部分。实际上,我们只是时不时地更新文档,可能是在某些 sprint 期间(当有时间更新文档时)或在发布特定版本之前。另一方面,大多数开发人员(参加我的软件架构课程的同事或学生)不赞成创建和维护技术文档,他们认为这些任务乏味、耗时,而且价值不如其他任务,他们甚至认为如果源代码写得足够好,文档不是必需的。虽然总会有例外,但我很确定,在架构图方面,对于大多数项目来说几乎都是一样的。
首先,最重要的是要了解谁是架构图和技术文档的真正受益者。文档的数量和质量应该反映出利益相关者的需求,因为只有这样,我们才能创建准确且恰到好处的文档。
主要受益者应该是直接参与项目的团队(开发人员、测试工程师、业务分析师、DevOps 工程师,等等)。根据我的经验,在团队之外,很少有利益相关者真正关心文档。在最好的情况下,他们可能对一两个高级架构图(例如上下文图、应用程序或软件组件图)感兴趣,这些图粗略地描述了系统的结构并提供了高层次的系统视图。
但是,在大多数情况下,我们并没有确定真正的受益者及其真正的需求,直接就创建了过多的文档。这些文档很快就会成为维护负担,并且很快就会过时。而在其他一些情况下,我们直接省略了架构图,因为没有时间,或者没有兴趣,或者没有人愿意接受这个任务。除此之外,敏捷宣言宣称,团队应该更加重视软件本身而不是文档,也就是不鼓励繁琐的文档处理过程。
为了找到恰当的文档级别平衡点,可以尝试在团队中这么做:
询问每个同事,他们需要文档为他们提供怎样的内容,以及应该包含哪些类型的架构图。收集他们的意见,然后进行集体讨论,并就团队真正需要哪些的东西达成一致。团队之外可能会有一两个有影响力的利益相关者,他们会提出额外的需求,架构师也有责任将这些人的需求考虑在内。在这个基础上,创建适当数量和质量的技术文档,以满足利益相关者的需求。如果开发人员能够了解文档的真正价值,并对其剩余的价值感兴趣,可以让他们参与更新和维护文档。最后,每个人都会变得很愉快。但是,如果他们不了解文档的必要性或者他们根本不在乎,你几乎可以忽略它,因为很难由一个人(架构师)来维护文档,这应该是团队成员的共同责任。
过去,在瀑布式项目中,因为采用了综合性的企业架构方法(我故意不说出是哪些方法),或者是一些象牙塔架构师提出的要求,我们创建了太多的文档。当软件项目开始大规模拥抱敏捷方法时,一个常见的误解是人们认为他们不需要文档,因为软件比文档更重要。当然,这是两个极端的情况。并不存在什么精确的方法或科学的过程来明确地指定项目需要多少文档才是恰当的。所有当前的软件架构方法都是纯建议或指南。过去遵循的那些综合性的架构过程在现今的项目中被大大简化,甚至已经不存在了。这并不意味着我们应该创建更少的文档,或者根本不创建文档,而是应该专注于创建具备真正价值的文档,同时不妨碍团队的进展。除此之外,并不是所有的文档都会提供价值。但这并不等同于“所有的文档都没有价值”。此外,因为不同的环境(如经济、政治等)、业务目标和利益相关者等因素,对一个项目有意义的文档对于另一个项目来说可能并没有那么有用。
在这些情况下,很难得出这个问题的正确答案:多少文档(即架构图)才算是适当的?最后,它关系到每个项目和架构师的经验,可以说是“视情况而定”。适当的能够提供价值的文档数量取决于团队需要什么。我的建议是与团队一起决定需要创建多少技术文档,无论这对团队来说意味着什么。如果文档对你的项目来说毫无意义(为什么会这样?),这也是可以接受的。将团队做出的决定记录下来,让所有利益相关者都知晓。如果有两三个架构图是有用的,那么请确保随时更新它们,保持它们的一致性,并且总是能反映系统的状态。不要专注于任何不会带来价值的事情。
一般而言,架构图和文档应该主要用于团队内部和团队之间的协作、沟通、愿景和指导。它们还应该包含项目的重要设计决策(在某个特定时刻采取)。
架构图应该帮助每个人看到大局,了解周围的环境。在我看来,这应该是创建和维护架构图背后的根本原因。
例如,上下文架构图完全满足了这种需求,并提供了关于系统边界的大量细节,从而可以看到全局。它有助于团队在不同的利益相关者之间达成共识,并简化沟通。我参加了很多会议,当大屏幕上出现这样的上下文架构图时,省去了很多问题,并消除了关于高级系统架构的不确定性。
不过,我们经常会尝试创建综合性的文档来反映系统的内部状态,它们可以是状态图、活动图、类图、实体图、并发图等形式。但这些很快就会过时,除非它们是基于源代码通过一些“神奇”的工具自动生成的。
如果人们不需要它们,那么创建这些详细的架构图有什么意义呢?业务利益相关者的抽象图绰绰有余了。在大多数情况下,对于开发人员来说,源代码(即单一事实来源)才是他们真正需要的。因此,请停止为代码中自解释的内容创建详细的架构图,或者当没有真正受众时。
因此,创建有意义的小型架构图,并将它们加到技术文档中。对于大多数应用程序,可能需要两三种架构图。最常见的是上下文图、组件图、系统图或部署图。
在我的项目中,我主要使用两种类型的架构图:
上下文图
应用程序或软件组件图
请将这些图视为简单的示例,主要作为每种图应该提供哪些合理信息的指导。图中的信息应该与相应的抽象级别相关,还必须满足利益相关者的需求。
在实践中,你可能倾向于向图中添加越来越多的细节,但是如果它们对利益相关者没有真正的用处,就会导致额外的噪音,增加维护成本,而且容易过时。这些图中的一些细节,例如协议和数据格式,可能对技术利益相关者来说比较方便,因为它们是必要的实现细节。然而,正如之前所述,并不存在精确的方法来确定图中包含多少数量的细节才算是恰当的,这完全取决于不同的项目。不过,架构师需要知道对利益相关者来说真正有用的是什么,并创建和维护架构图来正确地反映这一点。
除了这些架构图之外的任何额外细节,我可以在源代码中找到,或者通过某些工具自动生成(例如运行时视图、开发视图、系统或基础设施视图等)。
我还在会议室中绘制软件架构图(包括所有应用程序组件)。在我们的站会和其他会议期间,人们边指着墙上的这些架构图边谈论他们的任务、状态和遇到的问题。这样,每个团队成员,从产品所有者到开发人员,都能理解系统的全局,并预见到整体障碍和其他集成挑战。除此之外,在 Sprint 期间,它还为整个团队提供了更准确的进度状态,尤其是在分布式架构中,且人与人之间存在依赖关系时。
我建议你也在团队中这么做。通过使用足够的架构图继续加强协作、沟通、愿景和指导,否则就不要创建它们,特别是如果团队不使用它们的话。在大多数情况下,手动创建和维护架构图,以此来反映代码行为纯粹是在浪费时间。如果你这样做了,随着源代码的演变,你可能会想要添加越来越多这样的架构图,这是一个危险的陷阱。与其创建大量令人精疲力尽的架构图,不如坚持使用两到三个从不同抽象层次描述系统的架构图,这对于团队来说是非常必要的。经常性地更新它们,如果这个任务不包含太多的细节,并且是团队文化的一部分,那么它将变得更容易。
另外,请记住,团队应该是架构图的主要受益者。如果它们没有表现出任何兴趣,那么你应该停止创建它们,因为这可能是在浪费时间。我们不应该只是“为了拥有它们”,或者为了遵循综合性的架构方法,或者纯粹为了证明我们作为架构师的角色而去创建架构图。
关于作者
Ionut Balosin 是 Luxoft 的软件架构师,在各种商业应用程序方面拥有超过 10 年的经验,热衷于性能和调优以及软件架构。他经常在各种技术大会上发表演讲,是一个技术培训师。
查看英文原文:
https://www.infoq.com/articles/why-architectural-diagrams
文本链接:
https://www.infoq.cn/article/GhprrUlOYyOqS8*FR1pH
关键要点
- 由于向敏捷转型,软件架构图的使用规模已经大幅缩减。即使有在使用软件架构图,它们往往也混淆不清。
- C4 模型由一系列分层的软件架构图组成,这些架构图用于描述上下文、容器、组件和代码。C4 图的层次结构提供了不同的抽象级别,每种抽象级别都与不同的受众有关。
- 为了避免出现含糊不清的情况,可以在图中包含足够数量的文本和关键的图例。
软件架构图是一种非常好的表达方式,可以用它们来表达你将如何构建一个软件系统(预先设计)或者现有的软件系统是如何工作的(回顾文档、知识分享和学习)。
然而,你所看到的大多数软件架构图很可能只是由混乱的框和线组成。敏捷软件开发宣言的一个副作用就是让很多团队停止或缩减了他们的图表和文档工作,包括使用UML。
现在,这些团队倾向于依靠他们在白板上绘制的临时图表,或者使用通用的图表工具(如微软的 Visio)。Ionut Balosin 在去年写了一篇叫作“软件架构图的艺术”的文章,他在文章中描述了一些常见问题,这些问题与不可理解的符号和不明确的语义有关。
含糊不清的软件架构图容易导致误解,这可能会拖慢一个优秀团队的前进步伐。在我们的行业中,我们真的应该努力创建出更好的软件架构图。多年来,我自己参与软件开发,并与世界各地的团队合作,基于这些经验,我建立了一个称之为“C4 模型”的东西。C4 代表上下文(Context)、容器(Container)、组件(Component)和代码(Code)——一系列分层的图表,可以用这些图表来描述不同缩放级别的软件架构,每种图表都适用于不同的受众。可以将其视为代码的谷歌地图。
要为你的代码创建地图,首先需要一组通用的抽象来创建一种无处不在的语言,用来描述软件系统的静态结构。C4 模型使用容器(应用程序、数据存储、微服务等)、组件和代码来描述一个软件系统的静态结构。它还考虑到使用软件系统的人。
第 1 层是系统上下文图,它显示了你正在构建的软件系统,以及系统与用户及其他软件系统之间的关系。以下是一个系统上下文图的示例,描述了一个互联网银行系统的系统上下文:
银行的个人客户使用互联网银行系统查看有关银行账户的信息并进行支付。互联网银行系统使用银行现有的大型机银行系统来执行此操作,并使用银行现有的电子邮件系统向客户发送电子邮件。图中的颜色表示哪些软件系统已经存在(灰色)以及待构建的系统(蓝色)。
第 2 层是一个容器图,将软件系统放大,显示组成该软件系统的容器(应用程序、数据存储、微服务等)。技术决策也是该图的关键部分。以下是互联网银行系统的容器图示例。它显示了互联网银行系统(虚线框)由五个容器组成:服务器端 Web 应用程序、客户端单页面应用程序、移动应用程序、服务器端 API 应用程序和数据库。
Web 应用程序是一个 Java/Spring MVC Web 应用程序,它仅提供静态内容(HTML、CSS 和 JavaScript),包括组成单页应用程序的内容。单页面应用程序是一个运行在客户网络浏览器中的 Angular 应用程序,提供所有的网上银行功能。或者,客户可以使用跨平台 Xamarin 移动应用程序访问互联网银行的部分功能。单页应用程序和移动应用程序都调用 JSON/HTTPS API,这是由服务器端运行的另一个 Java/Spring MVC 应用程序提供的。API 应用程序从数据库中获取用户信息(关系数据库模式)。API 应用程序还使用专有的 XML/HTTPS 接口与现有的大型机银行系统进行通信,以获取有关银行账户或交易的信息。如果需要向客户发送电子邮件,API 应用程序还会调用现有的电子邮件系统。
第 3 层是组件图,将单个容器放大,以显示其中的组件。这些组件映射到代码库中的真实抽象(例如一组代码)。下面是一个虚拟的网上银行系统的组件图示例,显示了 API 应用程序中的一些组件(而不是全部)。
两个 Spring MVC REST 控制器为 JSON/HTTPS API 提供访问点,每个控制器随后使用其他组件访问数据库和大型机银行系统中的数据。
最后,如果你确实想要,或者说有这个必要,可以放大个别组件,以显示该组件的实现方式。以下是一个虚拟的网上银行系统的 UML 类图示例(部分),显示了组成 MainframeBankingSystemFacade 组件的代码元素(接口和类)。
它表明该组件由很多类组成,实现细节直接反映了代码。我并不建议创建在这种详细程度的图表,有时候你可以直接从大多数 IDE 中获取它们。
C4 模型没有预定义任何特定的符号,你在这些示例图中看到的是一个个简单的符号,适用于白板、纸张、便签、索引卡片和各种图表工具。你也可以使用 UML 作为符号,并适当使用包、组件和原型。无论你使用哪种符号,我都会建议让每个元素都包含名称、元素类型(即“人”、“软件系统”,“容器”或“组件”)、技术选型(如果有的话),以及一些描述性文字。在图表中包含如此多的文本可能看起来很不寻常,但这些附加文本有助于消除软件架构图中通常会出现的不明确的表示。
即使符号对你来说是显而易见的,仍然要确保为这些符号提供图例。图例中应该包括颜色、形状、首字母缩略词、线条样式、边框、尺寸等。理想情况下,符号应该在每个细节层次上保持一致。下面是前面显示的容器图的图例。
最后,不要忘记了标题,它应该出现在每个图表上,以明确地描述每个图表的类型和范围(例如,“网上银行系统的系统上下文图表”)。
C4 模型是一种在不同抽象层次上交流软件架构的简单方法,可以向不同的受众讲述不同的故事。这也是向软件开发团队介绍(通常是重新引入)严谨和轻量级建模的一种方式。有关 C4 模型的更多信息,以及补充图(运行时和部署)的示例、符号清单、常见问题解答、会议讲座视频和工具选项,请参阅 c4model.com 。
Simon Brown 是一位专门从事软件架构的独立顾问,也是“Software Architecture for Developers”(面向开发人员的软件架构、技术领导力和敏捷性平衡的指南)的作者。他还是 C4 软件架构模型的创建者,这是一种创建代码映射的简单方法。Simon 在国际软件开发会议上经常发表演讲,并在世界各地旅行,以帮助组织可视化和记录他们的软件架构。
查看英文原文:https://www.infoq.com/articles/C4-architecture-model/
本文链接:https://www.infoq.cn/article/C4-architecture-model/