一种常见但不完美的比喻是将软件系统中的架构漂移和侵蚀与物理建筑的架构相比。虽然这个比喻很直观,但它存在一个根本性的误解,这也常常引发软件开发中的架构问题。
试想一下,一个设计良好的摩天大楼或房屋建成后,我们期望它基本保持不变,顶多因为偶尔的现代化或扩建而发生变化。
令人惊讶的是,如今许多工程师(甚至可能是无意识地)将同样的逻辑套用到软件架构上:认为一旦系统架构设计完成,如果设计得当,它就不需要进一步修改,直到需求变化和遗留代码迫使进行大规模重写。
这是一个关键的误解。与物理结构不同,软件本质上是动态的,不断变化,需要定期更新以保持活力。一旦软件停止演变,就会开始衰亡。
此外,这种比喻通常强调软件系统的结构和行为,但忽略了同样重要的决策、权衡和妥协,这些因素共同塑造了架构。理解架构决策背后的原因对于未来的修改以及管理和演变软件架构至关重要。
本文旨在加深你对架构技术债务的理解,并强调有效管理架构漂移和侵蚀的关键因素。
架构技术债务概述
"在软件密集型系统中,技术债务指的是那些在短期内权宜的设计或实现,这些构造设置了一个技术背景,使得未来的变更更为昂贵甚至不可能。技术债务是一种或有负债,其影响主要限于系统内部质量,特别是可维护性和可演化性。" ------Avgeriou等人,2016年
技术债务总结了软件开发中过去决策和捷径累积的后果,包括低质量代码、缺失的文档和严重耦合等问题。这些问题可能源自多种原因,如战略性权衡或需求的意外变化等。
尽管许多工程团队记录了他们管理技术债务的策略------如谷歌和 ThoughtWorks 的做法------但关于特定类型的技术债务,即架构技术债(ADT),讨论较少。
ADT 源于系统设计过程中的有意或无意决策,导致维护性降低、复杂性增加、性能下降和可扩展性受限等问题。由于软件架构定义了系统的关键属性和约束,ADT 对系统演变及组织实现目标的能力构成重大风险。
ADT 是不可避免的,特别是在目标是快速交付和后续迭代时,有时甚至是必要的。因此,团队必须识别 ADT 并实施有效管理策略,以防止架构退化------即逐渐变得过时、不可靠,无法适应不断变化的业务需求或技术进步。
首先,关键的是在 ADT 的广泛范围内区分两个独特的现象:系统架构漂移和系统架构侵蚀。
架构漂移与架构侵蚀
架构漂移指的是在系统中引入不在原始架构计划中的设计决策,但这些决策并不一定会违反基础架构原则。架构侵蚀是指引入的新设计直接与系统的预期架构相冲突,破坏了系统的指导原则。
以建筑架构为比喻,架构漂移就像是建造一栋地中海风格的房子,然后添加一个哥特式的塔楼和一个后现代的扩建。这虽然导致了风格混杂(可能并不美观),但不会破坏结构的完整性。
在软件工程中,一个系统可能以干净的架构开始,但由于架构漂移,最终演变成包含多种架构范式、不一致编码实践、冗余组件和依赖项的复杂结构。
深入探讨架构漂移 by Vladi Stevanovic
另一方面,架构侵蚀类似于进行改造时破坏了房屋的结构完整性。例如,为了创建开放式布局而拆除承重墙却没有适当的支撑,或者在没有考虑原始墙体承重能力的情况下加建一层楼。
在软件架构中,架构侵蚀引入了违反系统基础原则和预期设计模式的行为,使系统变得脆弱,最终导致劣质架构,未来出现问题。
这些违规行为可能表现为紧密耦合的模块、绕过安全协议、忽略性能约束,或在无状态系统中引入有状态组件等。
DALL-E 对架构侵蚀的诠释
应对架构技术债务的策略
架构技术债务积累过多会导致架构全面退化。团队通常会采取两种策略之一:不断调整代码以应对突发问题,或者进行大规模重构。不幸的是,这两种策略常常失败,甚至可能加剧现有的技术债务。
调整代码通常只是表面解决方案。如果团队缺乏对系统架构的全面了解或对问题根源的理解,他们只能被动应对,这难以解决根本问题。
另一方面,即使是有意的重构------无论是渐进式还是一次性重构------如果不解决导致债务的根本原因,仍可能失败,技术债务也会再次出现。
最有效的方式是摒弃这些被动措施,转向整体的、主动的方法。在开发过程中整合持续的、前置的系统设计审查,使团队能够更持续地管理技术债务。例如,与其通过快速修复强行将新需求加到现有系统架构中,或不断替换遗留系统,不如采取更有效的方法,使系统设计始终包含新特性,然后无缝集成实际特性。
正如敏捷宣言的签署者之一、极限编程创始人 Kent Beck 所言:"对于每一个期望的变更,先让变更变得容易(警告:这可能很难),然后再进行容易的变更。"
架构恢复的可持续策略
许多团队误以为采用敏捷方法就能确保持续的系统设计审查,并防止架构技术债务的积累。然而,现实情况往往与这种期望存在差距。
敏捷团队注重频繁交付功能增量,可能无意中忽视了长期的架构完整性。快速交付模式还可能导致文档和设计不够清晰,使开发人员难以理解系统的整体架构及其组件的交互方式。这种疏忽会使系统维护和扩展越来越困难,最终导致技术债务的积累。
应对已累积的架构技术债务(ADT)并防止其进一步增加,需要采取以下关键步骤:
- 实施架构可观测性。首先,对现有架构进行彻底检查,了解应用程序在生产环境中的行为,并列出其最关键的问题。这一步对于评估系统设计的架构漂移程度至关重要。
- 现代化开发流程。架构漂移和侵蚀往往源于缺乏有效的流程,而不是缺乏技能。随着业务环境和软件需求的演变,缺乏系统化的方法来引入新变化以及处理团队成员的入职和离职,会使软件架构偏离其预期设计。制定系统设计、管理和文档的最佳实践,对于长期维护架构完整性至关重要。
最后的思考
在技术变革加速和竞争加剧的背景下,适应性是现代技术世界的关键。拥有一个积累了大量技术债务的复杂系统,就像是背负沉重的枷锁。在依赖关系和错误的迷宫中穿梭,使得适应变化的世界变得越来越困难,机会也因此流失。
从财务角度来看,修改负担沉重的架构债务系统的成本,总是高于那些经过深思熟虑的前期设计的系统。
虽然适量的技术债务是可管理的,并且可以通过战略性方法解决,但过度积累往往会导致系统瘫痪,带来重大挑战。
驾驭架构技术债务的复杂性,必须采取有意识且主动的策略。团队必须优先进行持续的架构评估,并整合强大的可观测性工具,以准确监控系统演变。此外,通过严格的设计、管理和文档实践来现代化开发流程,这对于维护系统的完整性和可扩展性至关重要。
管理技术债务的最有效方法是将软件变更和演化置于开发过程的核心。