从 ABP 到 CleanDDD:关于软件长期演进的一些思考


从 ABP 到 CleanDDD:关于软件长期演进的一些思考

最近在项目中接触到了 CleanDDD,也重新审视了我们长期使用的 ABP 技术栈

这并不是一篇“反 ABP”的文章,而是一次站在时间维度上的技术反思

如果你也在维护一个已经运行多年、并且还会继续演进的系统,或许会对下面的内容产生共鸣。


一、站在时间轴上看软件开发的变化

如果把时间拨回十年前,软件开发面临的核心问题其实很简单:

  • 有没有系统
  • 能不能尽快上线
  • 能不能稳定跑起来

在那个阶段,交付本身就是最大的价值

但今天,情况已经完全不同了。系统不再稀缺,真正昂贵的反而变成了:

  • 系统维护成本
  • 需求频繁变更的风险
  • 人员流动带来的不确定性
  • 业务规则不断叠加后的复杂度

软件开发的核心矛盾,已经从:

“能不能做出来”

转变为:

“还能不能持续演进”


二、CleanDDD 在解决什么问题

很多人第一次看到 CleanDDD,会觉得它:

  • 结构清晰
  • 分层明确
  • 代码“看起来很干净”

但真正让我开始认真看待它的,并不是这些表象。

CleanDDD 真正试图回答的,是一个非常现实的问题:

这个系统在 3~5 年之后,还能不能被安全地修改?

在大量项目中,系统难以维护,往往不是因为业务本身有多复杂,而是因为:

  • 业务规则分散在各个角落
  • 没有人能说清楚「改这个需求到底该动哪一层」

CleanDDD 做的一件事其实很“笨”,但非常有效:

强制把业务规则收敛到领域层

这不是为了形式上的 DDD,而是为了:

对抗系统复杂度的自然增长


三、真正的风险:系统没人敢改

在实际工作中,我越来越觉得一个系统最大的风险,并不是开发速度慢,而是:

关键人员离开后,系统没人敢动

很多系统不是不能改,而是:

  • 不知道会影响哪里
  • 不确定会不会引发连锁问题
  • 最终选择「能不动就不动」

CleanDDD 的一个重要价值,在于它试图把业务知识:

  • “人的经验” 转移到 “模型和代码结构”

这本质上是在降低组织层面的风险,而不仅仅是技术问题。


四、交付速度 vs 长期成功率

快速交付本身没有问题,真正的问题在于:

很多系统只对第一次交付负责

在后期需求中,我们经常看到这样的情况:

  • 一个看似很小的改动
  • 引发多个模块的连锁修改
  • 最终演变成一次高风险操作

CleanDDD 关注的并不是:

“这个功能能不能尽快上线”

而是:

“第 20 次、第 30 次需求调整时,系统还能不能稳住”

这是一次性交付成功,与长期演进成功之间的差别。


五、一些非常实际的工程收益

从工程角度看,CleanDDD 带来的变化是非常具体的:

  • 业务逻辑只存在于领域层
  • 每个聚合都有清晰的职责边界
  • 行为具备明确的输入与输出

当需求变化时:

  • 你大致知道该从哪个领域模型入手
  • 也能明确哪些地方不应该被修改

而这,恰恰是很多 ABP 项目在后期最容易失控的地方。


六、为什么 CleanDDD 更适合长期演进的系统

CleanDDD 从一开始的设计目标,就不是:

“这个功能能不能快点上线”

而是:

“五年之后,这个系统还能不能继续加新规则”

一个非常直观的对比如下:

场景 常见 ABP 项目 CleanDDD
新增规则 AppService 中不断加 if 新的领域行为
行为复用 复制业务逻辑 复用聚合能力
业务重构 高风险 局部替换
新人接手 需要较长熟悉期 更快理解业务

七、CleanDDD 与 AI 编码的一点关系

这是一个相对新的视角,但我认为非常重要。

AI 编码本质上依赖几件事:

  • 清晰的上下文
  • 稳定的边界
  • 可预测的结构

而这些,恰好都是 CleanDDD 所强调的。

领域模型、统一语言、明确的行为边界,使得代码空间本身是:

低熵的、可组合的

相比之下,典型的 ABP 项目中:

  • ApplicationService
  • Repository
  • UnitOfWork
  • 各种框架约定

往往混杂在一起。这种结构对人尚且吃力,对 AI 来说更容易误判上下文

这不是未来的假设,而是已经在发生的现实。


八、关于框架老化的问题

有一句话我越来越认同:

所有框架都会老,但业务不会

CleanDDD 的一个隐性优势在于:

  • 框架升级,主要影响基础设施层
  • 领域层可以长期保持稳定

而在 ABP 中,领域模型往往:

  • 继承框架基类
  • 生命周期与框架深度绑定

在 5~10 年周期的系统中,这种差异会被不断放大。


九、关于 ABP:不是对错,而是取舍

需要强调的是,这并不是一篇否定 ABP 的文章。

ABP 的设计目标非常明确:

  • 快速交付 CRUD 系统
  • 提供完善的权限、多租户、审计能力
  • 降低团队协作成本

为了实现这些目标,它必然做出一些取舍:

  • ApplicationService 权力较大
  • Repository 支持灵活查询
  • 实体继承框架基类

这些设计,天然更接近事务脚本模型,而不是严格的 DDD。


十、为什么 ABP 天然不追求“纯 DDD”

这更多是由历史背景决定的。

ABP 诞生于 2013~2016 年,当时:

  • .NET 企业开发以 N 层架构为主
  • 系统多为 ERP / OA / 管理后台
  • 企业最关心的是交付速度和通用能力

DDD 在国内更多停留在理论层面,并非主流实践。

因此,ABP 的定位从来都是:

企业级应用框架

DDD 只是它兼容的一种思想,而不是第一性原则。


十一、一个更工程化的总结

如果把话说得更直白一些:

ABP 解决的是:如何规模化交付软件
CleanDDD 解决的是:如何长期演进业务系统

这并不是谁对谁错,而是面对的问题不同。


十二、一个更现实的建议

与其“反 ABP”,不如“驯服 ABP”。

在 ABP 技术栈下,完全可以:

  • 用 CleanDDD 构建领域层
  • 用 ABP 提供基础设施能力
  • 显式使用领域事件
  • 避免在 AppService 中堆积业务规则

这可能不是最快的路,但很可能是:

未来几年风险最低的路


写在最后

CleanDDD 本质上并不是一种“更高级的写法”,而是一种:

为未来不确定性预留空间的工程选择

在系统复杂度还可控的时候,
为未来 3~5 年留一条安全的演进路径,本身就是一件非常值得投入的事情。

CleanDDD项目地址:
https://github.com/netcorepal/netcorepal-cloud-framework


posted @ 2025-12-31 14:53  红泥巴煮雪  阅读(224)  评论(5)    收藏  举报