Articles · AI Engineering
AI 时代,为什么设计原则、设计模式与 DDD 仍然重要
AI 降低了代码生产成本,却没有消除软件设计的复杂性。本文从 SOLID、设计模式与 DDD 出发,讨论如何把领域语义、模块边界和业务不变量转化为 Coding Agent 可以遵循并验证的工程约束。
AI 正在显著降低软件实现的成本:生成类、接口、API、数据库访问代码和测试,比过去更快。但代码生成速度提升,并不意味着系统复杂性同步下降。恰恰相反,当实现变得廉价,系统可能更快地产生大量模块、抽象和调用路径。如果缺乏明确的领域边界与架构约束,AI 可以很快地把一个错误的理解扩展成一套看似完整、实际上难以演进的软件。
因此,我更愿意把 AI 时代的软件工程理解为一次工作重心的迁移:
实现越来越便宜,正确地定义问题、建立抽象、约束变化并验证结果,反而更加重要。
SOLID 等设计原则、设计模式和领域驱动设计(DDD)并没有过时。它们分别处理不同层次的问题,也可以成为 Coding Agent 的工程约束基础。
一、设计原则:约束模块如何变化
通常所说的六大设计原则,是 SOLID 五项原则加上迪米特法则。它们不是要求开发者机械地拆分类,而是帮助我们控制模块之间的变化关系。
| 原则 | 核心问题 | AI 工程中的意义 |
|---|---|---|
| 单一职责(SRP) | 一个模块为什么会变化? | 避免把多个业务职责堆进同一个服务或类 |
| 开闭原则(OCP) | 新需求是否必须修改稳定代码? | 让新工具、新模型和新策略通过扩展接入 |
| 里氏替换(LSP) | 不同实现是否遵守同一契约? | 确保不同 Runtime Adapter 的行为可以替换 |
| 接口隔离(ISP) | 调用方是否被迫依赖无关能力? | 给 Agent 提供职责清晰、权限明确的工具接口 |
| 依赖倒置(DIP) | 业务逻辑是否绑定具体基础设施? | 让业务层不依赖特定模型、数据库或 Agent 框架 |
| 迪米特法则(LoD) | 一个模块是否知道了太多内部细节? | 限制跨模块穿透访问,减少修改的连锁影响 |
例如,一个业务服务直接创建 DeepAgents 实例,后续切换到 Pi 或其他 Runtime 时,业务代码可能需要跟着修改。引入稳定的 Runtime 接口与适配器,可以把变化限制在基础设施边界内。
但抽象并非越多越好。如果目前只有一个实现,也没有明确的变化需求,提前设计多层接口可能只是增加理解成本。原则的价值在于识别变化原因,而不是为了符合形式而增加类和文件。
二、设计模式:为反复出现的变化提供结构
设计原则描述约束,设计模式则提供处理常见设计问题的可复用结构。在 Agent 系统里,常见模式有清晰的落点:
| 模式 | 典型应用 |
|---|---|
| Strategy(策略) | 模型路由、安全策略、计费策略 |
| Adapter(适配器) | 统一 DeepAgents、Pi、不同模型供应商的接口 |
| Factory(工厂) | 根据配置创建 Agent、工具或 Provider |
| Chain of Responsibility(责任链) | 输入检查、授权、风险审核与工具执行前检查 |
| Decorator(装饰器) | 为工具增加鉴权、限流、日志、重试和指标 |
| Observer(观察者) | 收集任务状态、工具调用与审计事件 |
| State(状态) | 管理任务的等待、运行、审批、成功和失败状态 |
| Command(命令) | 将设备操作或业务动作封装为可授权、可追踪的命令 |
例如,工具调用链可以组织为:
Agent
↓
Tool Gateway
↓
身份校验 → Policy Strategy → 风险检查
↓
Command 执行
↓
结果反馈与审计
这些模式能够帮助我们分离变化,但模式本身并不保证架构正确。把简单逻辑拆成十几个对象,也可能让系统更难理解。选择模式前,应先确认要隔离的变化是什么,以及这种变化是否真的会发生。
三、DDD:先弄清楚业务到底是什么
设计原则和模式解决了模块组织问题,但它们不能替代业务建模。DDD 的价值在于明确领域语言、业务规则、限界上下文和数据所有权。
以 Token 中转平台为例,表面链路可能只是“用户请求模型,平台转发并扣费”。实际业务却包含不同概念:
- UsageRecord:一次模型调用产生的用量事实;
- BillingPolicy:如何把用量转换为费用;
- Account:当前账户额度与状态;
- LedgerEntry:一笔不可随意覆盖的账务记录;
- Settlement:一个结算周期内的核算结果。
如果不先区分这些概念,AI 很容易生成一个包含充值金额、赠送额度、消费金额和供应商成本的通用 balance 字段。原型可能很快跑通,但在退款、奖励、额度过期、并发扣费和供应商对账出现后,系统就会暴露出概念混乱的问题。
领域建模可以进一步识别限界上下文,例如 Identity、Billing、Account、Routing、Provider 和 Settlement。它们不必一开始就拆成独立微服务;模块化单体也可以拥有清晰的领域边界。关键是明确谁负责什么规则、谁拥有哪份数据,以及跨上下文如何交换信息。
DDD 最重要的产物不只是实体类,而是业务语言与不变量。
- 同一笔充值不能重复入账;
- 账务流水不能被普通更新随意覆盖,更正需要通过可追踪的冲正或调整;
- 并发扣费不能突破账户允许的额度边界;
- 用量事实、计费结果和实际结算成本不能被混为同一个数字。
这些规则应落在领域模型、数据库约束、事务边界和测试中,而不只是写在需求文档或 Prompt 里。
四、AI 时代的关键变化:从生成代码转向生成可验证的实现
AI 可以生成符合某些设计模式的代码,但这并不意味着它理解了业务边界。代码能够编译,也不代表领域规则正确;测试通过,也不代表测试覆盖了真正重要的不变量。
因此,Coding Agent 的工程流程应该从“根据需求生成代码”进一步发展为:
需求
↓
领域分析:概念、边界、业务不变量
↓
架构设计:模块职责、依赖方向、接口契约
↓
Coding Agent:实现代码与测试
↓
自动验证:类型、架构、业务规则、集成行为
↓
反馈:修复、重试、重新验证
这要求我们把设计思想分成两类:
可以机器验证的约束,应尽量转化为工具和自动化检查:
- 依赖规则:禁止基础设施模块反向依赖领域层;
- 接口契约:不同 Runtime Adapter 必须满足共同的行为约定;
- 数据库约束:通过唯一键、事务和幂等机制避免重复入账;
- 业务不变量:用单元测试、属性测试和并发测试验证额度与状态转换;
- 运行时权限:每次敏感工具调用都必须经过可信授权入口。
需要结合语境判断的设计决策,则由开发者和 Agent 协同审查:一个模块是否真的只有一个变化原因、某个抽象是否值得存在、限界上下文划分是否符合业务语言,以及某种模式是否增加了不必要的复杂度。工具可以提供证据、检测风险,但不能把所有设计判断简化成一条静态规则。
五、把设计约束放进 Agent Runtime,而不只放进 Prompt
如果希望 Coding Agent 长期遵守架构规则,单纯在系统提示词里写“遵循 SOLID 和 DDD”是不够的。提示词是一种指导,不是强制边界。
- 上下文层:提供领域词汇表、模块职责、架构决策记录和代码规范;
- 规划层:要求任务先识别影响的领域、接口与不变量;
- 执行层:通过工具权限、分支隔离和受控工作区约束修改范围;
- 验证层:执行测试、静态分析、架构依赖检查和契约测试;
- 反馈层:把失败信息反馈给 Agent,允许其修复后重新验证;
- 审查层:对业务边界变更、数据迁移和高风险操作保留人工判断。
Prompt 让 Agent“知道”规则,工具和验证机制让 Agent“必须面对”规则的执行结果。比如,Agent 修改 Billing 模块后,如果架构测试发现它直接依赖 Provider 的数据库实现,流水线就应失败;如果改动扣费逻辑,就必须运行并发扣费和幂等性测试。这样,设计约束才从口头要求变成工程闭环。
六、三者如何协同:先建模,再约束,最后选择实现模式
DDD:定义业务语义与边界
↓
设计原则:约束模块职责与依赖
↓
设计模式:组织具体实现与变化点
↓
Coding Agent:生成代码与测试
↓
Harness:执行检查并反馈结果
这不是严格的单向流水线。实现与测试会不断暴露领域模型中的歧义,领域建模也可能反过来调整模块边界。但这三个层次不应混淆:
- DDD 回答:系统里的业务概念是什么,规则归谁负责?
- 设计原则回答:模块之间应该如何依赖,变化应被限制在哪里?
- 设计模式回答:面对某类重复出现的设计问题,可以采用什么结构?
- Harness 回答:如何让 Agent 按照约束工作,并用可重复的证据验证结果?
结语:设计能力将成为 AI 工程的放大器
AI 并没有让软件设计失去价值,而是改变了设计价值的体现方式。当代码需要大量手工编写时,开发者的时间经常消耗在实现细节;当 AI 能够快速生成实现时,真正的瓶颈更可能转向问题定义、领域语义、架构边界、验证标准和反馈闭环。
设计原则避免模块关系失控,设计模式帮助隔离变化,DDD 保证系统围绕正确的业务概念组织,而 Harness 则把这些思想转化为 Coding Agent 能够执行、接受检查并持续修正的工程过程。
AI 负责加速实现;工程设计负责定义什么才算正确;验证机制负责提供证据。
未来更有价值的能力,不只是让 Agent 写出更多代码,而是让它在清晰的领域模型和架构约束下,持续生成可理解、可验证、可演进的软件。