开发成功的软件架构虽简单,但并不容易。理解 QAR(质量属性需求)并做出最大程度满足 QAR 的权衡需要洞察力和经验,其中很大一部分必须通过对架构本身的迭代实验来获取。这个过程本身很简单,但需要权衡的地方往往很棘手,而且很少有简单的答案。
对于团队来说,知道哪里有潜在的陷阱至关重要,让他们知道沿着某一条特定道路不会达到他们想要的目标。在本文中,我们将分享一些我们遇到的无用路径,希望能够更好地帮助你做出与权衡和后果相关的决策。
1. 不要让一个人做出或影响所有决策,适当地让团队成员参与决策
架构是各种力量之间的平衡,是一系列次优权衡的结果,这些权衡通常不会完全令人满意。想要良好的性能、良好的可伸缩性、良好的安全性、良好的可维护性和出色的可用性?祝你好运!
当一个人独自做出所有决策时,架构将反映出他们的经验、偏见和偏好。这些决策对于某些场景可能刚好合适,但往往在某些方面表现良好,在其他方面则表现糟糕。
不同经验的人,他们之间的意见交换会形成讨论,从而暴露出开发团队需要做出的竞争性权衡。由个人做出或受其影响的决策(也被称为 HiPPO,Highest Paid Person’s Opinion,收入最高的人的意见)通常是由团队中最资深的人做出的,很少能够得到所有团队成员的支持。因为担心影响工作岗位,他们可能不会公开反对这些决定,但很快他们会提出批评意见,不再为团队提供支持,甚至在这个决定造成问题时离开。
这并不意味着多数意见应该占主导地位,由委员会设计的架构往往过于臃肿和缺乏重点。根据我们的经验,多个拥有不同经验和观点的人挑战断言并达成更为明智的决策,才能达到理想的平衡。
2. 不要为了达成可重用性目标而做出糟糕的决策,应该只在有意义时才进行重用
重用代码、组件、设计,甚至配置,在一开始听起来是个好主意。管理层喜欢提倡这个概念,认为这会降低成本,甚至可以实现更快的交付和更高的质量。团队可能会为了更快地交付 MVP 决定重用大部分已有的应用程序,甚至重用已成功交付了产品的架构。
如果重用的是函数,很容易取得成功,因为函数的范围很狭窄,副作用有限,因此可以在不同的上下文中使用。不幸的是,重用的预期好处很少能够兑现,至少在架构层面上是这样,因为架构所做出的广泛而基本的假设很难适应不同的上下文。
除非新架构的 QAR 与现有架构的 QAR 相匹配,否则重用现有架构很少能取得成功。过去的表现并不能保证未来的成功!通过重用现有应用程序的部分内容来快速实现 MVP 可能会因为设计中包含了遗留技术而限制了相关的 MVA。通过扩展现有组件来实现重用可能会使设计复杂化,并使它们的维护变得更加困难和昂贵。
在评估可重用性时,问问自己这样做是否会使你的架构变得更加复杂。如果是这样,为了完全满足你的需求,你最好自己重新编写。
3. 不要裁掉有解决架构挑战经验的人,要留住他们并在必要时重新培训他们
管理层着迷于降低成本,有时候会通过奖金激励管理者将成本降低一定比例。他们深信软件开发技能是一种商品,他们可能会被低成本供应商可以提供与具有多年或数十年经验的团队成员相同的技能的承诺所诱惑。
有时候这是真的。正如一位前同事曾看到的,拥有十年经验和将一年经验重复十次之间有很大的区别。换句话说,软件开发中真正的技能不在于编码,也不在于语法知识,也不在于熟悉特定一套框架——软件开发的重点是解决问题。
架构工作是一项解决问题的工作,在解决特定类型的问题时,还需要具备能够根据经验做出权衡的额外技能。没有解决架构问题经验的开发人员也会学习,但他们在学习之前会犯很多错误。与其假设你需要的只是聪明人(不管他们的经验如何),不如雇佣或留住那些已经经历过学习周期的人,这样更为划算。
4. 不要让业务决策主导架构,架构决策应该要满足明确的 QAR(质量属性需求)
业务决策通常具有短期性质:季度和年度计划周期往往主导着业务决策。那些专注于未来而牺牲当前业绩的高管往往无法在自己的职位上呆上足够长的时间,看到自己的长期梦想得以实现。
软件架构不一样。虽然即时结果很重要,但企业在构建系统方面的投入通常需要数年才能达到收支平衡,而许多系统的寿命可长达几十年。虽然企业希望立竿见影,但它也负担不起每隔几年就要构建一个新系统来解决某个特定问题的费用。
然而,业务有时会试图介入架构决策,通常是因为他们最近读到了一些关于“区块链是新生事物”或“生成式人工智能将改变一切,不跟进的公司将被抛在后面”的文章。技术确实以颠覆现状的方式创造了公平的竞争环境,但从来不是像专家们所预测的那样。
虽然新技术提供了有趣的功能,但它们总是伴随着权衡和意想不到的副作用。新技术并不能从根本上或神奇地使满足 QAR 变得不重要或微不足道。在许多情况下,新技术满足 QAR 的能力是完全未知的。这就是处理架构问题经验的重要性所在:知道在哪里以及如何提出正确的问题,并且知道如何设计实验来获得这些问题的答案。
5. 不要为了更快交付而牺牲质量,应该在保持架构可行性的同时管理好技术债务
最小可行产品(MVP)及其相关的 最小可行架构(MVA) 之间总是存在紧张的关系。MVP 的目的是测试解决方案是否改善了客户 / 用户体验。MVA 的目的是确保 MVP 可以在经济和技术层面得到持续的支持。如果 MVP 没有价值,那么在 MVA 上的投入就浪费了,但如果 MVA 不可行,MVP 也毫无意义。
过于专注于 MVP 的组织可能会发现,他们的用户满意度不高,虽然他们喜欢产品背后的理念,但对产品的糟糕表现感到失望。这为竞争对手敞开了大门,他们可以简单地复制 MVP,并随着时间的推移更有效地实现它。所谓的“先发优势”(率先推出解决方案的优势)被高估的原因在于:用户会惩罚那些提供劣质产品的公司。
随着敏捷软件开发方法和重构实践的兴起,一些组织被误导,认为速度是唯一重要的东西,因为他们总是可以在后面修复 / 重构问题。现实情况是,补救性工作的效果有限。补救性工作,即所谓的“稍后再修复”和重构,成本很高,因为团队必须花时间弄清楚代码的功能,然后才能以一种不一样且更有效的方式重写它。重构或使用敏捷软件开发方法并不能从根本上降低工作的复杂性。
6. 不要为了完善架构而延迟交付(和反馈),应该利用你所掌握的信息来设计架构,并利用反馈来改进它
前面的部分可能会让一些读者相信,软件开发团队应该小心翼翼,永远不要发布有缺陷的架构。但这也不是一个好的策略。没有哪个架构是完美的,它由一系列不完美的权衡决定的,其中一些甚至是错误的,在系统运行之前无法识别出来。有时在系统运行时也无法知道,直到发生了异常情况。认为架构可以完美无缺,一劳永逸,这是一种危险的心态,它会阻止团队开发出能够适应未预见需求的弹性和可适应性架构。
“超前大架构”综合症对系统来说往往是致命的。在设计系统之前,不可能确定所有的架构需求。这并不是说我们要反对构建初始架构,毕竟一切都需要从一个起点开始。但基于当前你所掌握的信息来构建初始架构,然后利用反馈进行改进,比为了获得新信息而不断延迟初始发布要好。
需要注意的是,再多的评审会议也不能代替实际构建至少部分架构并在各种条件下进行测试来评估其适应性。评审会议,即使由经验丰富的架构师主持,也只能发现与会者以前经历过的问题,并不能发现应用新技术时可能出现的新问题。
7. 不要让功能需求驱动架构,架构应该由现实的 QAR(质量属性需求)驱动
每个人都认为需求很重要,因此大多数开发团队花费大部分时间开发满足功能需求的解决方案。处理功能需求相对直接,因为业务利益相关者通常非常清楚他们想要什么,但他们往往难以清晰表达质量属性需求。
不幸的是,良好的架构设计是由明确定义的质量属性需求驱动的,仅使用功能需求来设计软件架构会导致软件产品可能缩放性不佳、在高负载下可能性能不佳,或者难以持续保持弹性。如果开发团队只专注于功能需求,其架构解决方案很可能不足以满足用户的实际需求。
8. 不要复制别人成功的架构,要根据你自己的 QAR(质量属性需求)来设计架构
一些热门的文章和技术大会演讲会分享大公司或某些供应商使用特定方法来满足特定 QAR 的经验。这些演讲和文章分享了重要的见解,是重要的学习资源,但它们也有局限性。所谓的“最佳实践”或“架构模式”也是如此。了解别人使用某些特定的方法取得成功是有好处的,但仅仅到某个程度上。
每一个架构都是不同力量之间的平衡,是一系列在其特定上下文中有意义但通常无法很好地适应其他上下文的次优权衡。了解所涉及的力量和你自己的解决方案的可能权衡是至关重要的,因为它们可能会让你得出与其他大公司不同的结论……而你们可能都是对的。
要理解其他人的选择,你必须了解他们的上下文和 QAR。只知道他们最终做出的选择并不能告诉你太多信息。如果只基于他们的选择而不了解他们的上下文来做决定,可能会让你走上失败的道路,而不是复制他们的成功。
9. 不要把决策外包给供应商和顾问,你要确保对架构保持可控
复制他人架构的一个方法是将架构决策外包(或放弃)给声称具有类似经验的供应商或顾问。他们的解决方案在其他环境中可能运行良好,但你仍然需要自行评估他们的提议或想法。他们的方案有可能完美适合你的情况,但如果不适合,那就是你的问题了,而不是他们。从一开始就理解这一点可以帮助你提出更好的问题,从而做出更好的决定。
顾问可以为你的组织带来急需的专业知识和不同的视角,但他们并非无所不知,他们也有盲点。他们可以在你做决策时给你建议,但不能为你做出决策。
在不了解其质量属性需求、安全漏洞、维护问题和许可问题的情况下使用开源框架,实际上是另一种外包决策的方式。开源组件是现代应用程序的重要组成部分,但它们可能支持也可能不支持你的质量属性需求。在采用它们之前,你需要了解其创建者所做的决策以及这些决策是否适合你。
10. 不要过于泛化架构,应该只为满足你的 QAR(质量属性需求)而设计架构
软件架构并不具备普适性,它们反映了依赖于上下文和应用程序的权衡。满足了质量属性需求的架构就是好的架构。
有时候会感觉这还不够,似乎存在更通用的解决方案,可以解决更大范围的质量属性需求,为组织中不同类型应用程序提供通用架构。但解决更通用的问题并不会带来额外的好处,并且没有证据表明确实需要这样的通用架构。许多行业标准的第二次修订都陷入了这个陷阱,试图满足可能出现的任何可想象到的需求,并在这个过程中变得臃肿而无用。
11. 不要一次性完成架构,而要逐步构建和测试,降低风险和浪费
软件架构就是软件,了解它是否达到目标的唯一方法是先设定目标,然后构建部分架构,看看是否朝着这些目标取得了进展。
软件架构的目标是满足其 QAR(质量属性需求),或者至少做出一组合理的选择,让大多数人满意,因为完美地满足所有人是不可能的。架构设计的技巧在于权衡。
如果“超前大架构”遭遇失败,那是因为团队需要做出权衡所需的一些信息只能通过构建和测试架构的某些部分来获得。无论开发团队成员有多聪明或技术经验有多丰富,在设计架构时可能都需要处理他们以前从未见过的情况。因此,他们需要进行实验。
这并不意味着架构评审不重要,特别是当评审人员(比如开发团队之外的人)可能有一些可以为开发团队节省大量工作的经验时,或者他们至少可以指出一条可能值得探索的方向。出于"如果我们想要按时交付,就没有时间进行这些架构评审"的想法而跳过架构评审的做法通常是目光短浅的,可能会导致更多的返工。
12. 不要只依赖内部的软件架构评审,应该尽早发布产品并获得真实的反馈
在软件架构中,发现错误的唯一方法是将产品放到现实世界中。一旦系统运行起来,改进架构的唯一方法就是将其置于现实世界的评审之下,不受系统开发人员及其协作者社区的偏见的影响。
结论
我们很难明确地说什么会导致成功的软件架构,但很容易说出不会导致成功的因素,就像我们上面所概述的哪样。指望别人来定义你的软件架构或者复制他人的架构是导致无法构建成功软件架构的两个重要原因。不去考虑你自己的 QAR 也是一个原因,就像期望神奇的供应商或流程为你做好这件事一样。
可能会破坏软件架构的功能障碍几乎是无穷无尽的。我们在本文中提供的清单可以让你了解可能出问题的地方,我们希望也给了你一些处理它们的建议。毫无疑问,你还会遇到其他问题。正如我们很久以前听说过的一句话:“好的判断来自经验,而经验大多来自糟糕的判断。”
原文链接:
评论 9 条评论