如何构建长期运行的软件系统

发布: (2025年12月15日 GMT+8 01:56)
8 min read
原文: Dev.to

Source: Dev.to

大多数软件系统的失败并不是因为技术选型错误。
它们之所以失败,是因为停止了学习。框架会老化,架构会时兴时衰,团队也会变动。致命的问题在于系统对业务的内部认知逐渐偏离现实——即使是微小的改动也会变得风险大、成本高且不可预测。

为什么系统会失败

当领域模型不再反映业务时,人们会提出重写、采用新架构或新框架,但根本问题仍然是技术无关的。一个长期存活的系统并不是保持不变,而是能够持续、增量地演进而不导致自身不稳定。

长期存活系统的特征

  • 新功能通常可以在局部添加。
  • 引入新特性时,已有行为很少会被破坏。
  • 开发者用 领域术语 而不是技术术语来思考系统。
  • 即使经过多年演进,也不需要大规模重写。
  • 代码库反映了业务的真实运作方式,并“说”业务语言。

这些属性只有在概念模型与业务同步演进时才会出现。当演进停止,概念张力累积,职责不再清晰对齐,增量改动变得不可能。

用户故事作为领域验证

用户故事是对系统应支持的功能切片的平面描述——它捕捉 要做什么,而不是 内部职责应如何组织。把故事仅当作工作单来处理会侵蚀领域模型。

实现前需要问的问题

  1. 这个故事如何契合当前的领域模型?
  2. 哪些已有对象(按其原始定义)应参与其中?
  3. 这个故事是否揭示了缺失的概念或职责?
  4. 现有的职责边界仍然成立吗?
  • 如果模型能够自然地容纳该故事,实施就很直接。
  • 如果不能,摩擦本身就是 建模信号,而不是实现问题。跳过这一步会把职责决策转移到服务、工作流和编排代码中,悄然削弱模型。随着时间推移,领域模型不再主导行为,退化为被动的数据结构。

“模型优先”原则

“模型优先”并不意味着事先设计好所有东西或脱离现实抽象。它的含义是:

  • 领域模型 是首要产物。
  • 实现是为模型服务的。
  • 职责边界驱动代码结构。
  • 技术便利永远不能凌驾于概念正确性之上。

框架、库和架构应随时间可互换;而准确反映业务的领域模型则不应被替换。

贫血领域模型的危险

贫血领域模型常被描述为 “没有逻辑的实体”,但这一定义不完整。领域模型是 职责的结构;状态是职责的结果,而非定义本身。当职责被转移到代码的其他部分时,就会出现贫血模型。

即使对象中有逻辑,也可能出现贫血模型,若满足以下任意情况:

  • 决策在拥有相关职责的对象 之外 做出,无论状态如何。
  • 逻辑在定义概念边界的对象 之外 实现,即使这些对象在模型中存在。
  • 不变式通过过程(工作流或服务)而非结构(模型)强制执行。
  • 领域对象沦为仅仅的协调工具,真正的行为被推到外部编排器中。

示例:领域交互对象

领域交互对象可能定义:

  • 何时以及如何进入领域。
  • 适用的“一致性”或事务范围。
  • 交互期间必须保持的哪些不变式。

它可能几乎没有持久化状态,却拥有关键职责。如果事务管理或一致性边界在该交互 之外 引入(例如在服务层或基础设施层),对象即使仍然存在,也失去了意义。

框架影响——Spring Boot 示例

框架对系统形态施加强大的引力,尤其在企业环境中。选择 Spring Boot,就等于让团队:

  • 每年进行一次框架升级。
  • 承担持续的许可证或支持费用。

这种被迫的 churn 会消耗工程师的注意力,即使业务领域本身没有变化。即便在稳定的领域,团队也必须不断:

  • 适配框架的演进。
  • 处理废弃特性。
  • 重新验证基础设施关注点。

Spring 的默认配置和生态系统强烈倾向于 过程化、服务中心的设计

  • 无状态服务。
  • 依赖注入的编排。
  • 事务工作流。
  • 被动的领域对象。

结果是职责碎片化,模型贫血。

事务管理作为领域关注点

事务常被视为纯技术关注点——只需在服务层配置或标注即可。实际上,事务定义了 业务层面的“一致性边界”,并回答如下问题:

  • 什么构成有意义的工作单元?
  • 哪些变更必须一起成功或一起回滚?
  • 何时可以观察到中间状态?
  • “全有或全无”在该领域到底意味着什么?

当事务边界在定义领域交互的对象 之外 引入时,模型失去了核心职责的所有权。系统可能在技术上是正确的,但在概念上变得不稳定。

持续建模提升交付速度

人们常误以为持续建模会拖慢交付。实际上往往恰恰相反。那些有意识地实践 演进式领域开发——把每个故事都视为建模机会的团队,往往能够显著更快地交付功能。

通过让领域模型始终与业务保持一致,团队可以降低意外复杂度,避免大规模重写,并保持一个能够安全、增量变化的系统。

Back to Blog

相关文章

阅读更多 »