如何避免 12 大软件架构常见误区 [译]
核心观点
- 不直接参与架构构建的人不应负责做出架构决策。只有深入理解架构的构建过程,才能有效进行关键的技术权衡。
- 质量属性需求(QARs)是推动架构设计的核心。忽略或定义不清楚这些需求,很可能导致项目失败。
- 不要完全依赖供应商来决定你的架构设计。他们可能不了解你的具体情况和 QARs,也不应为你做出关键的决策。
- 避免盲目模仿其他组织的架构,即使他们看似非常成功。因为他们的情况和 QARs 与你不同。
- 架构评估唯有通过实际构建和测试才有效。延迟实施以追求完美设计,往往会导致失败。
虽然构建成功的软件架构的过程看似简单,实际上却颇具挑战。要理解 QARs,并在此基础上做出最优权衡,需要深刻的洞察力和丰富的经验,而这些往往需要通过对架构本身的不断试验和调整来积累。虽然过程本质上不复杂,但所涉及的权衡决策通常充满挑战,而且难以找到简单的解决方案。
了解可能出现的陷阱,可以帮助团队避免误入歧途,确保不会走上与目标背道而驰的路。在这篇文章中,我们将分享一些我们在实践中遇到的常见误区,希望能帮助你在进行关键权衡和面对可能的后果时做出更明智的决策。
不要让单一个人独断所有决策,而应鼓励团队中合适的成员共同参与决策过程。
架构设计其实是在多种力量之间寻找平衡,是一连串并不总是完美的折中方案。想要达到良好的性能、可扩展性、安全性、可维护性以及出色的用户体验?这可不容易!
如果只由一个人来做出所有的决策,那么设计的架构就只会反映出这个人的经验、偏好和局限。虽然有时这可能恰好符合项目需求,但更多时候可能在某些方面做得很好,而在其他方面则表现不佳。
由来自不同背景的团队成员进行的健康讨论,有助于揭示开发团队需要作出的各种权衡。通常由团队中最高级别的人(即所谓的“HiPPO: 最高薪酬者的意见”现象)单独决定或影响的决策,很难得到所有团队成员的认可。他们可能出于对工作安全的考虑而不敢公开反对,但如果由于这些决策导致问题,他们会很快开始批评,停止支持团队,甚至选择离开。
这并不是说应该由多数人作主,由委员会设计的架构通常过于臃肿且缺乏重点。我们的经验是,最理想的平衡是让几位拥有不同经验和观点的同事一起质疑和探讨,从而做出更加明智的决策。
不要因为重用目标而做出错误的决策。只有在合适的时候才去重用。
重用代码、组件、设计甚至是配置听起来似乎是个不错的选择。管理层常常推崇这个理念,认为这能够减少成本,甚至还能加快交付速度,提高产品质量。有些团队可能会选择重用大部分现有的应用程序来加快最小可行产品(MVP)的开发,或者甚至重用一套已经成功交付产品的架构。
当重用的范围限定在某个函数时,使用服务或类/类型通常是简单且有效的,因为函数的范围较小,副作用有限,因此可以适用于不同的场景。但遗憾的是,至少在架构层面,重用所期望的好处往往难以实现。这是因为架构会做出广泛且根本的假设,而这些假设很难适应不同的环境。
除非新架构的质量属性要求(QARs)与原有架构设计的要求相匹配,否则重用现有架构往往不会成功。过去的成绩并不能保证未来的成功!为了快速实现 MVP 而部分重用现有应用程序可能会因为在设计中包含了过时技术而限制其最小可行体验(MVA)。为了重用而对现有组件进行扩展,可能会使其设计变得复杂,维护更加困难,从而导致成本增加。
在考虑是否重用时,要考虑这样做是否会使架构变得更加复杂。如果会的话,你可能更好地从头开始编写,以完全满足自己的需求。
不要轻易放弃那些有经验的人,他们在解决架构挑战方面很有价值。相反,应该保留并在必要时对他们进行再培训。
管理层常常只关注于削减成本,有时这种做法是受到奖金激励的影响,鼓励经理通过减少特定比例的成本来获得奖励。他们可能会误以为软件开发技能是普遍可得的,因此被承诺说低成本的供应商可以提供与有多年甚至几十年经验的团队成员同等的技能所吸引。
有时候这是对的。正如我一位前同事所说,拥有十年经验和重复十次一年经验是完全不同的。换句话说,软件开发的真正技能并不仅仅是编码、掌握语法或熟悉某些框架,更重要的是解决问题的能力。
架构工作本质上是解决问题的过程,还需要能够根据以往解决类似问题的经验做出明智的权衡。那些没有在架构方面经验的开发者虽然能学习,但在学习过程中会犯很多错误。与之相比,雇佣或保留那些已经经历过这一学习过程的人,可能会更加经济实惠,这比仅仅依靠聪明才智而忽视经验更为重要。
不应让商业决策左右你的软件架构,而是应侧重于满足清晰界定的质量属性需求 (QARs)。
商业决策通常以短期为导向,以季度和年度计划为主。那些过分关注未来、忽略当前成绩的高管往往难以长期留任,无法见证自己长远梦想的实现。
软件架构则不同。虽然即时效果重要,但组织在系统构建上的投资常需数年才能回本,很多系统的使用寿命更是长达数十年。业务虽追求即刻成效,但频繁更新系统以应对各种问题显然不切实际。
然而,商界人士偶尔会试图干涉架构决策,这通常是受到他们最近读到的关于“区块链是最新趋势”或“生成式 AI (Generative AI) 将颠覆一切,不立即投入的公司将落后”的文章影响。技术的确能在某种程度上打破常规,但从未像专家预测的那样。
新技术虽具吸引力,但总伴随着权衡和意外后果。它们并不能根本上简化或轻视满足 QARs 的重要性;在很多情况下,新技术能否满足 QARs 还是未知数。这就体现了处理架构问题的经验的重要性:懂得如何提出恰当的问题,并设计实验来寻找答案。
不应为了快速交付而牺牲产品质量。我们应当合理管理技术债务,以维持架构的有效性。
在最小可行产品 (MVP) 和它的架构基础——最小可行架构 (MVA) 之间总存在一种拉锯战。MVP 的目的是验证解决方案是否能够提升顾客和用户的体验效果,而 MVA 则确保这种解决方案能在技术和经济上持续支撑。如果 MVP 本身没有价值,那么对 MVA 的投入就是白费,反之亦然。
那些过度关注 MVP 的组织可能会面临顾客的不满。这些顾客可能喜欢产品的理念,但对产品的实际表现感到失望。这就给竞争对手留下了机会,他们可以模仿 MVP,但在长期内更有效地执行。所谓的“先发优势”之所以被过高评价,是因为顾客通常会对那些提供劣质产品的公司进行惩罚。
随着敏捷软件开发和诸如代码重构之类的实践的兴起,一些组织开始误认为速度才是关键,因为他们认为可以随时修正或重构后期的问题。但实际上,补救措施的效果是有限的。补救措施,也就是所谓的“稍后修正”或重构,其实是代价高昂的,因为团队必须花费大量时间来理解现有代码,才能对其进行有效的重写。仅仅标榜为重构或采用敏捷开发方式,并不能根本上降低这些工作的复杂性。
不要因追求架构完美而推迟产品交付和反馈。更好的做法是,依据现有最佳信息设计架构,并通过反馈持续改进。
前文可能让人误以为软件开发团队应该避免发布任何有缺陷的架构,但这种想法并不理想。事实上,没有任何架构是完美无缺的,它总是基于一些不完美的权衡,其中有些可能是错误的,而且直到系统真正运行起来,这些错误才会显现。即使如此,有时候需要等到发生非常特殊的情况才能发现问题。坚信架构可以做到完美、一成不变是危险的,这种思维会妨碍团队开发出能适应未知需求的灵活和可适应的架构。
“一开始就大规模设计架构”的做法通常会对系统造成致命的影响。即使不至于致命,这种做法也会无谓地延迟系统的发布,从而阻碍真正的学习过程。在设计系统前就确定所有架构要求是不现实的。这并不是说不应该有一个初步架构;毕竟,每个项目都需要一个起点。但是,基于当前的最佳信息建立起始架构,并利用反馈进行改进,要比不断推迟首次发布以等待新信息更为高效。
另外,值得一提的是,再多的评审会议也无法取代至少构建架构的一部分并在多种条件下进行测试来评估其适用性。即便是经验丰富的架构师主持的评审会议,也只能发现已知的问题,对于使用新技术或方法时可能出现的新问题则往往束手无策。
不要让功能需求主导架构设计。相反,应确保架构设计受现实的质量属性要求(QARs)的驱动。
大家都认为需求至关重要,因此大多数开发团队投入大量时间来满足功能需求。处理功能需求相对直接,因为业务利益相关者通常能清晰表达他们的需求,但他们在阐述质量属性要求时往往难以言之。
然而,优秀的架构设计应由明确的质量属性要求驱动。仅依赖功能需求进行软件架构设计可能会导致软件产品在扩展性、负载下的性能或随时间的耐用性方面存在不足。如果开发团队仅专注于功能需求,他们解决方案的架构很可能无法满足用户的真实需求。
不要简单模仿别人的成功架构,而应根据自己的质量属性要求(QARs)来设计架构。
市面上的热门文章和会议演讲经常介绍一些知名公司或供应商是如何通过特定方法满足他们的质量属性要求(QAR)。虽然这些资料提供了很多有价值的见解,对学习很有帮助,但它们并不是放之四海而皆准的。同理,“最佳实践”或“架构模式”也有其局限性。虽然了解别人如何成功应用某种方法很有用,但这种用处是有限的。
每个架构都是在不同因素之间寻求平衡,这些权衡在特定的环境中可能是合理的,但在其他环境中可能就不适用。因此,理解涉及的因素和可能的权衡对于你自己的解决方案至关重要,因为它们可能会引导你得出与那些知名公司截然不同的结论——而你们都可能是正确的。
要理解别人的选择,首先需要了解他们的上下文和质量属性要求(QARs)。仅仅知道他们最后做了什么选择,并不能给你提供太多信息。如果你只是基于他们的选择而不考虑其背景来做决策,可能会导致失败,而不是复制他们的成功。
不要将决策完全交给供应商和顾问手中。相反,你应该确保对自己的架构保持控制权。
一个常见的问题是将架构决策外包给那些声称有处理类似问题经验的供应商或顾问,这其实是一种变相的模仿。虽然他们的解决方案在其他情况下可能行之有效,但你还是需要亲自评估他们的提议。他们的方案可能很适合你的需求,但如果不合适,解决问题的责任仍然落在你的肩上。从一开始就清楚这一点,有助于你提出更有洞察力的问题,从而做出更明智的决策。
顾问能够为你的组织带来宝贵的专业知识和新的视角,但他们并非无所不知,也有自己的盲点。他们可以为你的决策提供建议,但最终的决定还是要你自己来做。
在不了解其质量属性要求(QARs)、安全漏洞、维护问题和许可问题的情况下使用开源框架,实际上也是在外包决策。开源组件是现代应用程序不可或缺的一部分,但它们可能并不完全适合你的质量属性要求(QARs)。在采用这些组件之前,你需要了解其开发者所做的决策,以及这些决策是否适合你的需求。
不要一概而论地设计架构。相反,应专注于满足你的特定质量属性要求(QARs)。
软件架构并不是放之四海而皆准的,它们体现了特定于上下文和应用程序的权衡。只有当软件架构能满足其 QARs 时,它才算是成功的。
有时,我们会觉得还有更广泛适用的解决方案,能够解决更多的 QARs,并在组织中不同应用程序间提供一个通用架构。但实际上,试图解决更广泛问题并不会带来额外的好处,也没有确凿证据表明这种通用架构确实必要或会被使用。很多行业标准的第二版就犯了这个错误,试图应对所有可能的需求,结果却变得过于庞大,失去了实用性。
不要一次完成架构建设。相反,应分步骤地构建和测试,以减少风险和浪费。
软件架构本质上是软件;确定其是否达到目标的唯一方式是设定目标,然后构建一部分来检验是否朝着这些目标前进。
软件架构的目的是要满足其 QARs。至少需要做出合理的选择,让大部分 QARs 得到满足,因为要完美满足所有 QARs 并非总是可能的。架构的艺术在于平衡这些权衡。
采用“一开始就做大型架构”的方法失败,是因为团队需要通过构建和测试架构的一部分来获取做出权衡的信息。不管开发团队成员多聪明或技术经验丰富,架构可能会遇到他们以前未曾遇到的问题。因此,他们需要进行试验。
这并不意味着可以忽视架构同行评审的重要性,特别是当团队外部的同行可能有能够帮助开发团队省去大量工作的经验。或者至少能为他们指明一个值得探索的方向。因为“我们要赶上交付期限,没时间做这个”而忽略架构同行评审通常是短视的,可能会导致以后更多的重复工作。
结论
明确指出什么因素能导致软件架构的成功并不容易,但我们可以清楚地指出哪些因素不会,正如我们之前所讨论的。依赖他人来定义你的软件架构,或者简单模仿别人的架构,是通往成功软件架构的两大绊脚石。同样,忽略你的质量属性要求 (QARs) 或期待某种神奇的供应商技术或流程来帮你完成任务,也是常见的误区。
能够破坏软件架构的问题几乎数不胜数。然而,我们这里列出的一些问题,希望能给你一些启示,了解事情可能出错的地方,并提供一些建议来应对这些问题。当然,你可能还会遇到其他问题。有句古话说得好,“好的判断源于经验,而大部分经验又来自于糟糕的判断。”