架构工作的本质 - 第三部分
摘要
本文继续探讨架构工作本质的系列文章,介绍了其目的的三个层面:经济、认知和人文。文章开始探讨经济目的,讨论质量属性及其在软件架构中的作用。
<p><a href="https://lobste.rs/s/vaw8oy/essence_architectural_work_part_3">评论</a></p>
查看缓存全文
缓存时间: 2026/06/27 09:51
# 架构工作的本质 - 第三部分
来源:https://www.ufried.com/blog/essence_of_architecture_3/
## 架构工作的本质 \- 第三部分
在上一篇文章(https://ufried.com/blog/essence_of_architecture_2/)中,我们讨论了几种架构反模式。我们了解到,如果不理解*为什么*做架构工作(即理解其目的),我们就更容易陷入这些反模式。我们明白了,如果对做架构工作缺乏清晰的理解,那么工作的焦点和价值就变得随机。
因此,在这篇文章中,我们将开始探讨架构工作的目的。
多年来,我提炼出关于架构工作目的的三个不同方面¹ (https://www.ufried.com/blog/essence_of_architecture_3/#fn:1):
- 经济目的
- 认知目的
- 人道目的
这三个方面都相关。每个方面从不同视角关注架构工作。可能还有我尚未发现的更多方面,但重要的是要明白,额外的方面并不会使现有方面失效。它们只是增加了更多视角,补充了目的。它们并没有创造不同的目的,而是创造了一个更完整的目的,完善了它为我们提供的焦点。
根据上下文,不同方面可能被赋予不同的权重。根据我职业生涯中的观察,第一个方面在与决策者讨论时总是相关的——至少在商业软件开发中是这样。第二个方面也非常重要,但它经常被误解,因此以曲折的方式实施。我个人认为第三个方面非常有力,但这个方面经常被完全忽视,这对我们所有人都是不利的。
让我们从第一个方面开始。
## 架构工作的经济目的
当被问及为什么需要做架构工作时,我有时会眨着眼睛说:
> 我们需要架构来解决——一个**随时间变化的优化问题**——在**不断变化的约束**下
如果这让你产生“什么鬼”的感觉,那完全正常。老实说,我不期望任何人能理解它。这更像是一个引子。如果没有额外的解释,我自己也不明白这句高度晦涩的话想表达什么。因此,让我解释一下我这句话的意思。
## 质量属性
许多架构师(包括我在内)都会谈论很多关于质量属性的话题。我们试图用质量属性来表达架构的特性。更准确地说:我们首先尝试理解一个解决方案必须满足的质量属性。然后我们尝试设计一个架构,确保解决方案实现所需的质量属性。通常,找出所需的质量属性是任何架构工作中非常早期的活动。
质量属性通常被称为“*ilities”,因为它们中的大多数以“-ility”结尾,例如:
- 可访问性(Accessibility)
- 可用性(Availability)
- 有效性(Effectiveness)
- 效率(Efficiency)
- 可演进性(Evolvability)
- 容错性(Fault Tolerance)
- 功能性(Functionality)
- 可安装性(Installability)
- 互操作性(Interoperability)
- 可学习性(Learnability)
- 可维护性(Maintainability)
- 可观测性(Observability)
- 可操作性(Operability)
- 可移植性(Portability)
- 可恢复性(Recoverability)
- 可靠性(Reliability)
- 资源利用率(Resource utilization)
- 可伸缩性(Scalability)
- 安全性(Security)
- 时间行为(Time behavior)
- 可理解性(Understandability)
- 可用性(Usability)
- 有用性(Usefulness)
- ...
这是我常用来作为项目定制基础的一个子集。我从各种来源编译了它,例如软件工程质量标准ISO/IEC 9126 (https://en.wikipedia.org/wiki/ISO/IEC_9126)及其后继者ISO/IEC 25010 (https://www.iso.org/standard/35733.html),以及其他来源如SEI的质量属性描述 (https://resources.sei.cmu.edu/library/asset-view.cfm?assetid=12433)或系统质量属性列表 (https://en.wikipedia.org/wiki/List_of_system_quality_attributes)(部分也适用于软件)。
这个列表并不详尽,根据你的上下文,你可能需要创建略有不同的列表作为定制基础。我写了一整个关于软件系统质量的博客系列 (https://ufried.com/blog/quality_1/)。因此,我不会在这里深入探讨这个话题。如果你有兴趣深入探讨质量和质量属性的理念,你可能想阅读那个博客系列。
我提到质量属性是出于不同的原因。如果你仔细思考它们,你可以得出一个有趣的观察。所有属性基本上可以分为两类:
- 影响解决方案在**开发时**(包括构建和测试)的外观和行为的属性
- 影响解决方案在**运行时**的外观和行为的属性,这不仅包括操作,还包括用户如何体验解决方案
我见过很多关于软件架构的讨论陷入僵局,因为一个人想到的是一类属性,而另一个人想到的是另一类。因此,让我们仔细看看这两类属性。
开发时相关的质量属性,例如代码的可理解性、可变更性、可演进性或可移植性,从开发的角度描述了系统的期望行为² (https://www.ufried.com/blog/essence_of_architecture_3/#fn:2)。它们主要影响系统被修改的效率,即它们针对的是**变更成本**。变更成本很重要,因为软件通常需要定期修改。这是软件的一个特殊属性。然而,人们对它普遍理解不足(参见,例如,我的博客系列“软件——它不是你想的那样” (https://ufried.com/blog/software_fallacies_1/)了解更多细节,特别是关于*价值保存困境*的部分)。
但不仅仅是理解不足使得开发时相关的质量属性难以把握。更大的问题是,为满足这种属性而采取的措施的有效性只能事后衡量。
为了说明这个问题,假设我们有一个架构决策,有两个选项:选项A和选项B,我们想决定哪个选项在变更成本方面更优。要做出准确的决定,我们需要做以下事情:
首先,我们需要识别软件生命周期内所有未来的变更,因为只有这些变更与变更成本相关。非常重要的是要理解,只有实际发生的未来变更才重要。我们可能觉得某个选项会对变更成本产生负面影响。然而,只要实现该选项不会对任何*实际*的未来变更产生负面影响,我们的感觉就无关紧要。它可能是你能想象到的最丑的黑客。我们光想想就皱眉。但如果它不影响解决方案的任何未来变更,那么它在变更成本方面就没有任何影响。³ (https://www.ufried.com/blog/essence_of_architecture_3/#fn:3)
然后,我们计算实施选项A后所有这些变更的成本,并求和。之后,我们对选项B做同样的事情。最后,我们比较选项A和选项B的未来变更成本总和,选择总和较小的选项,因为这在变更成本方面是更好的选择。
读完这个描述,问题所在就很明显了。要进行这种计算,我们需要能够将我们的时间线分成两条时间线。在一条时间线上,我们实施选项A。在另一条时间线上,我们实施选项B。然后,我们需要能够穿越到未来,直到软件生命周期结束,以识别所有未来的变更并计算它们的成本。
虽然时间旅行和多元宇宙在科幻和奇幻作品中是可能的,但在我们当前的现实中并非如此。我们无法创建两条时间线,也没有办法知道我们的软件直到生命周期结束的所有未来变更。因此,我们无法准确评估我们的两个选项A和B。相反,我们需要依赖概率和启发式方法。
这就是为什么我们看到如此多的“神秘猜测”以及关于如何创建可维护和可变更架构的热烈讨论。我们既不能证明也不能反驳选项A在变更成本方面是否优于选项B、C或D。虽然有一些基于经验证明有用的通用启发式方法,但其他一切更像是信仰而非知识。这是意见往往占上风、争论开始的地方。此外,我们很难向软件开发之外的人证明我们在变更成本方面的需求。
尽管如此,在考虑变更成本时,最优架构应该允许我们以最少的精力和成本实现包括生命周期内所有变更在内的软件解决方案。但由于我们无法以确定的、确定性的方式找到这样的最优架构,我们需要依赖概率和启发式方法,接受我们的决策——虽然旨在接近最优解——永远不会产生*那个*最优解。因此,我们将应用我们所知的启发式方法以及其他一些有助于增加做出良好变更成本决策概率的工具⁴ (https://www.ufried.com/blog/essence_of_architecture_3/#fn:4)。但这将始终是一个在不确定性下的优化过程。
这就是我所说的(解决方案生命)时间上的优化问题。
运行时相关的质量属性,例如可用性、可伸缩性、安全性、性能,还有可操作性(从操作员角度的可用性)或可用性、可访问性和功能正确性(决定解决方案从用户角度的有用性)则完全不同。它们基于使用和操作的视角描述系统的期望行为,即它们针对的是解决方案在所需属性方面的**正确性**。⁵ (https://www.ufried.com/blog/essence_of_architecture_3/#fn:5)
我们不优化任何东西。要么解决方案满足所需的质量属性,要么不满足。这样,运行时相关的质量属性定义了约束我们解决方案空间的不变量。它们支持我们在给定问题上评估不同的选项。如果被评估的选项不能满足给定的运行时相关质量属性,那么该选项不是合适的选择。这更像是“进”或“出”的问题。
例如,如果我们有一个质量要求,应用程序对99%的请求应在500毫秒内响应,那么平均响应时间为1秒的解决方案就不是一个可行的选项。或者,如果我们需要确保99.9%的正常运行时间(每年停机时间少于9小时),我们不能选择一个每月需要2小时维护停机的选项。
这些约束往往会随着时间变化,因为运行时相关的需求和期望也会随时间变化。例如,现有解决方案可能增加新的用户群体,导致不同的可用性、可伸缩性、性能或安全性需求。或者新的法律要求可能导致不同的持久性需求。等等。
这就是我提到的不断变化的约束。
## 总体成本优化
只看质量属性,我们可以就此打住。在不违反运行时相关质量属性的前提下优化变更成本已经足够困难了。
然而,有一个很大的陷阱:**变更成本**忽略了许多与IT系统在整个生命周期中相关的成本类型。即使我们能够找到关于变更成本的最优架构,它也可能在整体成本方面是一个糟糕的选择。
一个非常简单的例子:我曾经见过一个团队打算将Kafka引入他们的解决方案,因为他们预期使用Kafka会降低实施工作量。这与吞吐量、性能或任何你听到“Kafka”时会期望的东西无关。这些需求非常低。这个决策只针对预期的变更成本。该团队期望在项目中节省几天的实施时间,可能以后还会再节省一些。在系统生命周期内,总体节省最多大约50个工作日,即大约20,000到50,000欧元(取决于谁实施变更)。
然而,他们完全忽略了许可成本和运营成本。该公司当时没有使用Kafka,也没有理由很快引入它。他们需要雇佣专家来运行Kafka,因为他们当前的运营团队无法接手新技术。此外,他们还需要支付许可费用(你不会想在生产环境中运行OSS版本,因为它缺少一些对生产运行Kafka至关重要的功能)。
总的来说,这每年会增加大约50万欧元,即在软件生命周期内增加数百万欧元。即使该公司在该团队决策后仅一年就会引入Kafka,从整体成本来看,这也是一个非常糟糕的决定。
然而,仅从变更成本来看,这个决定是有道理的。
看这个小小的例子,我们立即看到变更成本作为唯一的优化目标是不够的,因为它忽略了所有其他相关的成本类型。相反,我们需要优化所有成本类型在系统生命周期内的累计成本。除了变更成本,这还包括:
- 所有其他开发成本
- 测试成本
- 部署成本
- 运营成本
- 维护成本
- 许可成本
- 基础设施成本
- 使用成本
- 管理成本
- 培训成本
- 收入损失
- 以及更多,取决于你的上下文
不幸的是,这些其他成本类型并没有被质量属性覆盖。我们必须自己添加它们来完成全貌。
这使得架构工作的优化方面更加困难,因为我们不得不覆盖更多维度,而质量属性(包括如何实现它们的知识)在这里帮助不大。我们必须自己将这个部分添加到我们的架构师工具箱中。
另一个问题是,大多数人只关注即时的开发成本,即他们只关注软件开发*现在*产生的成本。他们忽略了未来的成本以及所有其他成本类型。说服这样的人仅考虑变更成本就已经够难了。讨论系统生命周期内的整体成本视角很快会变成一项不可能完成的任务。
## 总结
经过所有这些解释,我们可以用更好、更易理解的方式重写最初晦涩的关于为什么需要架构工作的解释:
> 通过架构,我们试图——**最小化系统在其生命周期内的总成本**——同时确保其**运行时行为的正确性**
这就是架构的经济目的。虽然事后看来可能显而易见,但我看到很少有架构工作朝着这个目的努力。根据我的经验,要达到这一点需要大量的工作和经验。大多数现有文献帮助不大,因为它们只关注质量属性,有时也关注变更成本。因此,这可能是一个停下来思考片刻并反思这个定义及其对架构工作影响的好时机。
在下一篇文章中(链接稍后附上),我们将继续探讨架构工作目的的其他两个方面:认知目的和人道目的。敬请期待……
相似文章
优秀的架构不需要胡萝卜,也不需要大棒
这篇博客文章主张,良好的软件架构应当是不言自明且毫无阻力的,倡导采用 Netflix/Spotify 式的“铺平道路”模式,而非依赖强制性的治理委员会或嵌入式架构师。
学习软件架构
一位软件工程师分享了学习软件架构的见解,强调组织架构与激励机制优先于代码本身,并结合 rust-analyzer 与科学计算代码的实例进行了说明。
你必须感受它
一篇反思性文章,强调除了满足规格和交付演示之外,优秀的软件必须能在用户心中唤起恰当的感受——这种品质无法单靠复选框来衡量。
Martin Fowler:技术债、认知债与意图债
Martin Fowler 反思 AI 对代码质量的影响,指出人类的“懒惰”反而促成清晰抽象,而 LLM 则可能用不必要的复杂性把系统拖胖。
@hasantoxr: 每个AI代理构建者都需要知道的3种架构
这条推文强调了构建AI代理的开发者应该知道的三种关键架构,可能链接到某个资源或文章。