演进式架构

演进式架构以持续交付和DevOps为前提,支持跨多个维度的引导性增量变更,主要由三方面构成:适应度函数、增量变更和适当的耦合。

本书的书名其实可以取作“演进式系统构建之架构思想”,作者分析了不同架构模式的演进能力,为企业团队实践演进式架构提供了依据与参考。

架构是个面向问题的过程,适应度函数可看作是对架构决议的复核手段。本书也可用于印证《我的架构思想》、《程序原本》与《架构整洁之道》所述之内容,比如:

  • 团队决策考虑的对象有两点,其一是对架构整体的把握,其二是对团队整体的把握。

  • 系统本身的复杂性并不是由这些领域带来的,领域间的交叉与交互才是系统规模问题的根源。

  • 软件架构师的目标是创建一种系统形态,该形态会以策略为最基本的元素,并让细节与策略脱离关系,以允许在具体决策过程中推迟或延迟与细节相关的内容。

文摘

持续架构指构建架构的过程没有最终状态,它会随着软件开发体系的不断变化而演进,并保护重要的架构特征。

在适应度函数为某些架构特征提供了客观的完整性评估,用于计算潜在的解决方案与既定目标的差距。全系统适应度函数,可看作是适应度函数的集合。所谓“适应度函数引导演进式架构”,指的是通过单独的适应度函数评估单个架构选择,同时通过全系统适应度函数确定变更的影响。

增量变更描述了软件架构的两个方面:如何增量地构建软件和如何部署软件。使用部署流水线,架构师可以决定执行适应度函数的类别、时间和频率。架构量子是具有高功能内聚并可以独立部署的组件,它包括了支持系统正常工作的所有结构性元素。

虽然架构模式对于成功演进至关重要,但是它并不是唯一的决定性因素。必须结合架构模式固有的特征和系统定义的附加特征才能完整定义演进性的各个维度。

数据库的演进式设计是指开发人员能够根据需求的不断变化来构建数据库结构并使其演进。数据库模式是抽象的,和类的层次结构类似。当现实世界发生变化,这些变化需要反映在开发人员和DBA所建立的抽象当中;否则,抽象将逐渐脱离与现实世界的同步。

/assets/bookshelf/演进式架构/扩展-收缩模式.jpg

数据库重构之扩展/收缩模式

在设计系统时,组织所交付的方案结构将不可避免地与其沟通结构一致。

—梅尔文•康威

系统绝不是其组成部分的总和,而是各部分相互作用的产物。

—Russel Ackoff

如果无法构建单体应用,为什么你认为微服务能解决问题呢?

—Simon Brown

计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,除非该问题是由间接层太多导致的。

—Dave Wheeler & Kevlin Henney

  • 构建与目标系统架构相仿的团队结构,这样项目会更容易实现。

  • 将适应度函数的执行结果可视化至明显的公共区域,能使开发人员记得在日常编码中考虑它们,保持关键部分和相关适应度函数的活力。

  • 每年至少审查一次适应度函数。

  • 架构在开始运行、具有生命力前是抽象的。

  • 确保架构与问题领域匹配,不要尝试强行使用不合适的架构。

  • 架构量子越小,架构的演进能力越强。

  • 数据库事务好像强核力一样,将架构量子结合在一起。

  • 拒绝重构数据库模式或删除旧数据会使架构耦合到过去,这将导致重构难以进行。

  • 选择架构前,需要理解面临的业务问题。

  • 我们应努力使集成点保持一定的成熟度,如果无法做到这一点,那么你需要意识到系统的某些部分将更易于演进。

  • 不要仅仅因为元工作有趣而构建架构。

  • 在重建架构时,需要考虑所有受影响的维度。

  • 识别并去除不需要的可变因素。

  • 尽可能多地使决策可逆(在不过度工程化的前提下)。

  • 构建即时防腐层来隔离库的更新。

  • 使用服务模板仅将合适的架构部分耦合在一起(例如基础设施组件),团队可以从耦合中获益。

  • 积极地更新框架依赖,消极地更新库。

  • 相比快照,我们倾向于通过持续交付来处理(外部)依赖。

  • 在版本化服务时,我们倾向于内部版本化,一次只支持两个版本,而不是用版本号。

  • 不要将你的架构耦合,使得供应商为王。

  • 了解复杂技术栈的脆弱部分,并通过适应度函数自动保护它们。

  • 代码复用性越高,其可用性就越低。

  • 当耦合点妨碍了演进或其他重要的架构特征时,通过分叉或重复来打破耦合点。

  • 架构师必须持续评估架构特征的适应度,保证它们仍在提供价值,避免沦为反模式。

  • 不要为了架构而构建架构,构建架构是为了解决问题。

  • 演进的速度和生产周期成正比,生产周期越短,演进的速度就越快。

  • 理性对待软件中的定制部分。

  • 按照业务能力而非职能来组织团队。

  • 尽量减少开发团队之间的连接数。