凯尔·布朗 撰写
出了什么问题?
自软件架构学科成立以来,软件架构师与开发人员之间几乎一直存在冲突。自20世纪60年代以来(当时这种比较出现在1968年软件工程的北约会议上),人们就开始将软件设计与实体建筑进行比较。不出所料,一些对实体建筑的负面看法也随之出现(比如超级明星建筑师设计的东西根本无法建造)。在20世纪90年代到2010年代,随着软件架构成为一个成熟的学科领域,开发人员最常见的抱怨之一变得更加普遍——即架构师们在“象牙塔”中工作,远离开发人员的日常事务。
已经有其他书籍和文章讨论了这种脱节的许多根本原因(例如,参见 Simon Brown 的《开发者视角的软件架构》),但在本文中,我想特别解决一个特定的问题。特别地,这个问题是,架构师所产出的工件往往并不以一种易于开发人员和运营团队使用的格式存在,而且这些工件脱离了开发人员常用的工具集。接下来,我将介绍我们在 IBM Garage 使用的一种解决方案,这种方案已经持续了数年(至少从 2016 年开始),该方案有助于弥合这种差距,使开发人员和运营团队更易获取架构师的产出。但是在介绍解决方案之前,我想先讨论一下之前尝试过的解决方案及其各自优缺点。
以前试过什么?
为面对这个问题,各个公司和团队尝试了各种不同的方法。然而,为了使讨论更加简洁,让我们来看看三种最常见的方法。
多功能绘图和文档处理软件
如今,最常用来创建软件架构和设计图的工具是微软 PowerPoint,其次是微软 Visio。尽管存在许多免费和开源的绘图工具,如 draw.io 等,还有一些工具如 OmniGraffle 等拥有其忠实用户,但由于 PowerPoint 和 Visio 的普及,它们在工业界和学术界被广泛采用。
然而,忽略在使用通用繪圖工具繪制軟件圖表時遇到的圖形問題,第一個主要問題是您還需要一個額外的工具來處理這些圖表所需的文本。因此,軟件架構文檔通常用Microsoft Word編寫,並插入Visio圖表以滿足需要。
问题是这种方法导致开发人员的工作流程难以与 Microsoft Word 或 PDF 文件同步。他们首先需要找到该文件并阅读文件,然后对发现的问题进行注解或报告。在实施文档中介绍的概念时遇到问题,还需要找到解决问题的方法。因此,许多人多年以来尝试了第二种主要方法,即专用的软件架构工具。
专有的 软件架构设计工具
由于使用通用工具来记录软件存在一些问题,因此开发出更贴近开发人员工作流程的软件工程工具的行业变得非常活跃也就不足为奇了。一个例子是 IBM 的 Rational Software Architect (RSA),这款产品最初在 2000 年中期开发出来,允许架构师使用统一建模语言(UML)构建文档,并将这些图加入到 ClearCase 或其他开发人员用于存储代码的代码库中。在同一时期,应用模型驱动设计 (MDD) 和模型驱动架构 (MDA) 技术从图中生成初始代码工件的想法也变得流行起来,从而将工作流程的这两部分更加紧密地连接在一起。
然而,实际情况往往是这种做法通常演变成了所谓的“大规模前期设计”(BDUF),在这种模式下,架构师们会为系统开发所有图表,然后用这些图表生成代码生成——这些代码生成在开发阶段往往会脱离实际需求。尽管许多工具(包括RSA)包含反向工程功能,但由于难以将最初设计的图表与实际实现的代码相匹配,这些功能往往未被使用。此外,架构师和开发人员在工具使用上的差异导致开发人员常常忽视架构师生成的图表和文档。这导致了我们之前提到的“架构被看作是象牙塔里的工作”的感知。这种不满促使许多团队尝试使用维基来记录他们的决策,认为这种方式更加平等和非正式,因此更便于沟通。
维基
沃德·坎宁安最初创建的第一个Wiki网站的初衷是作为他的波特兰模式库的基础。其目的是提供一个互动工具,便于软件开发、架构和设计模式的收集和记录方面的协作。
维基引入了一种简单直观的标记语言,这种语言让建筑师和设计师能够轻松更新文档,从而避免文档变得静态和过时。更重要的是,大多数维基已经发展到可以嵌入自由形式的文本和图形内容。总的来说,它们极大地促进了建筑师和开发人员之间的合作,使他们能够共同创建能够随时间变化的互动文档。
然而,尽管维基相比于之前有了很大的进步,它们仍然不是完美的。特别是,许多维基页面往往会演变成为一种被人们称为“线程模式”的状态。
在“讨论模式”下,贡献者不愿意改动页面的原始内容(无论是出于不是页面原始创建者的考虑,还是出于保留页面原始内容的历史价值的考虑)。相反,他们在页面底部添加额外内容,通常在分隔线下方。这开始类似于许多电子邮件程序、聊天室和Reddit以及Slashdot等平台上的线程对话,这些平台的互动功能源于BBS。线程对话的问题是,最重要的信息(如更改或修订)往往位于页面的底部,而不是最上方,而是应该位于页面的顶部。因此,尽管它们确实是一种改进,然而,维基的社会机制使得它们的实际使用效果不如预期。
然而,最大的问题不是在于社会机制方面,也不是在于维基的特性,而在于维基并没有融入开发者的日常工作流程。因此,尽管维基可以参与架构决策的制定,特别是在组织结构化讨论方面,但如果它们应该成为开发者日常工作的一部分,那么维基就无法很好地反映架构决策、模式和设计的主要文档。
走进开发者的日常生活
我们得出的结论是,在 Git 仓库中,存储架构相关的决策、模式和参考架构,以及设计文件的最佳位置是与源代码(包括基础设施即代码和配置即代码的形式)一同存放的地方。
每个人应该都熟悉Git作为代码仓库的概念。你也可能熟悉GitOps(由Weaveworks提出)的概念,它利用Git作为代码和配置的存储库,用于代码即基础设施(IAC)和配置即代码(CAC),并利用Git的特性和流水线来自动化基础设施管理。你可能不太熟悉的是,Git已被证明是一个非常灵活和强大的工具,用于开发设计文档并记录设计决策的过程。我们亲身感受到使用Git的主要好处有:
- Markdown 是一种非常简单易学的语言,用于编写内容。仅通过使用 Markdown 编辑器(例如 GitHub.com 提供的编辑器或像 Xcode 这样的商业工具),你就可以轻松写出格式优美的文档,而无需记忆复杂的标记指令。
- Markdown 使得通过超链接将文档页面链接在一起变得非常容易。虽然点击未激活的本地链接不会创建新页面,但未激活链接(例如 Markdown 中的括号内无链接)与已激活链接之间的视觉差异,使你知道哪些链接页面需要填充。这使得编写链接的 wiki 风格页面就像在维基上一样简单。
- 内置的版本控制系统(毕竟它是 Git!)使合并多个作者的工作非常简单。这尤其有助于避免线程模式——你可以随时还原或轻松地对比 Markdown 页面以合并多个贡献。一旦开发人员、运维人员和架构师习惯将 Markdown 页面视为代码工件,他们更容易表现出与代码工件相同的适当行为——清理工作变得更加自然。
- 在 Github 上处理图形与文本一样简单。你可以使用任何在线工具(如 draw.io)创建图形,并直接检查到 Github,或者你可以在笔记本电脑上使用任何你喜欢的工具创建图形,并轻松地将它们提交到 Git。
- 最终的优点当然是,你可以直接在同一个存储库或你的源代码的子存储库中整合你的文档和设计决策。将两者保持在一起几乎不可能让它们脱节——特别是像处理代码那样,在设计文档上打开 Github 问题。
轻量级架构文档指南
这些优势带来的是一种构建非常轻量级的架构文档记录的方法,这种方法避免了我们使用其他工具时遇到的大多数问题。然而,为了使文档更有效,我们需要记住一些简单的规则。
-
你的主要文档应该都用 Markdown 编写,并存储在你的 Git 仓库中。你应该使用与代码相同的仓库——在仓库中创建单独的目录是可以的,但你希望将文档与代码保存在同一仓库中,以便让开发人员在需要时能够快速查阅。同样的方法也适用于“基础设施即代码”——将 Kubernetes Operator 代码和 Ansible 脚本及相关的设计决策一起保存到 Git 中。另一个需要记住的关键点是,虽然形式主义是有用的,但简单的散文叙述往往是最有帮助的。讲述决策背后的理由并提供决策的描述。
-
关注一些具有通用符号的关键图。没有什么比让架构师质疑其符号选择更令他们不高兴的了,没有哪个话题比这更容易产生分歧。对于我们这里提到的内容——几乎任何符号都可以使用。真正的关键是保持图表数量很少,并且要足够简单,让没有专门训练的人也能理解。如果需要复杂的解释说明,符号可能过于复杂。我们最喜欢的是 Simon Brown 的 C4 符号,但 UML 的子集也能很好地工作。我们提供了一个 服务符号模板,适合多种常用绘图工具。
- 不要在模板和结构上过分复杂化。需要一些结构——架构文档的每一页不能完全自由书写。但保持结构简洁。通常只需要为捕获架构决策提供一个标准格式,以及为捕获示例或参考架构的元素提供另一个格式即可。
作为示例,在IBM车库架构中心中,我们仅使用了几种类型的图表来表示我们的参考架构。我们使用框图来表示高层次的概念,然后使用简单的图表格式来表示云服务和概念的低层次的细节。下面是一个低层次图示的例子。
简单的云服务示意图(来自Github)
这样的例子都可以在IBM车库架构中心的许多架构中找到,例如用于其运行时现代化的Java EE应用程序的架构,例如这里。
建筑设计文档的标准
项目团队最常见的一种需求是保存架构决策——这只是记录在某个时间点做出的决策,这样每个人不仅能够理解该决定,也可以在未来遵循它。
架构决策通常涉及跨领域决策——如平台选择、语言选择、框架选择等。由于它们横跨多个领域,它们往往会对多个团队产生影响。然而,它们仍然需要对开发人员易于访问和使用。这意味着这些决策应该存放在一个所有人都能访问的顶级git仓库中,比如部落或公会中的仓库。
一个简单的选项是创建一个 Markdown 模板文件,你可以用具体决策的细节来“填充”这个模板。例如,在与客户的几个项目中,我们使用了包含以下项目的模板(这大致遵循了 IBM 内部工作的“ARC100”方案)。以下是一些部分:
- 名称
- 建筑设计摘要
- 问题
- 动机
- 考虑的替代方案
- 解决方案(及影响)
正如你所看到的,它的结构与模式文档的结构非常相似(参见Hillside Group可以找到多个示例)。事实上,模式经常出现在我们制作的架构文档中。例如,在我们的事件驱动的参考架构中,我们不得不添加诸如CQRS等常用模式的定义,这些模式已被参考架构采用。我们在此架构中使用的另一个技巧是利用GitPages来发布更长且类似教程的内容。如果你需要讲述一个较长的故事,GitPages提供的格式和呈现选项比单纯使用GitHub标记要更丰富。
我们为一些客户使用过的另一个选项是使用 GitHub 的问题功能,并利用标签来表示决策过程。这设置起来稍微复杂一点,但却能带来其他好处,比如明确指定问题和决策的责任人,更符合上下文情境。
我们的技术经验
自2016年在IBM云架构中心创建第一批解决方案以来,我们一直在广泛使用这些方法。Roland Barcia是最初倡导这一理念的人,并带领团队构建了我们最初的微服务解决方案。从那时起,我们已经扩展到超过20个使用这些技术构建的解决方案,并将这种方法应用于数百个客户中。Shahir Daya领导了一些早期的客户项目,其中包括在GitHub中引入了问题跟踪,以及使用GitHub存储架构文档页面。架构中心的页面浏览量已超过60万次浏览,我们使用这些技术编写的解决方案已被证明在帮助客户采用IBM技术方面具有持久影响。
将您的计划带到IBM车库
您想了解更多关于DevSecOps以及如何用IBM车库交付成果的信息吗?我们随时准备帮助您。今天就联系我们,预约时间与IBM车库专家交流您的下一个大想法。了解我们的IBM车库方法,我们所在的的设计、开发和初创社区,以及我们带来的深厚专业知识和能力。