核心导读: 在一个拥有数百万行历史代码的商品库中,“加一个字段”往往是引发系统级灾难的导火索。本文记录了一次真实的开发演练:为复杂的商品系统增加“默认单位”功能。 我们将对比 Vibe Coding(氛围编程)的“打补丁”惨剧,并详细演示如何使用 EARS 语法书写验收标准,如何通过 Delta Spec 引导 AI 做出新建聚合表的架构防腐决策,最终用真实数据量化 SDD 带来的提效与质量飞跃。
引言:“深水区”里的蝴蝶效应
在绿地项目(从零开始的新项目)中,AI 几乎是无敌的。但大多数企业级开发者每天面对的是棕地项目(Brownfield)——那里充满了十年前老员工留下的神秘逻辑、错综复杂的微服务依赖,以及千万级数据的数据库表。
本次演练的真实业务背景如下: 系统现状: 一个运行了 3 年的 PIM(商品信息管理)系统。商品原本只有单一单位(如“个”)。 新需求: 业务方要求支持“多单位换算”,并允许为每个商品设置一个**“默认销售单位(Default Unit)”**(例如:一箱啤酒包含 24 瓶,前端默认按“箱”售卖并展示价格)。
如果你用 Vibe Coding 的方式,直接对 Cursor 说:“给商品结算和展示加上默认单位的支持”。 灾难就会按照以下剧本上演:
- 粗暴的表修改: AI 会立刻在你的核心表
products中加上default_unit_name和conversion_rate两个字段。 - 逻辑碎片化: AI 搜遍了所有涉及商品的地方,在购物车、订单、结算页的 20 多个文件中,写下了无数个
if (product.default_unit) { price = price * rate }的恶心判断。 - 隐性崩溃: 它没有考虑老数据的兼容性,导致原先没有设置默认单位的存量商品在查询时直接报
NullPointerException;且破坏了与 WMS(仓储系统)的单位解耦边界。
“加一个功能,搞崩三个模块”,这就是没有规范约束的 AI 在深水区里的日常。 现在,让我们按下回退键,用 SDD(规范驱动开发) 的标准流程重新跑一遍这个需求。
第一阶段:意图澄清与 EARS 验收标准设计
在 SDD 流程中,我们绝不允许 AI 直接去碰代码库。
人类架构师首先打开 Delta_Spec_DefaultUnit.md,并在 AI 的辅助下,结构化地锁定业务意图。
为了防止自然语言的歧义,在撰写验收标准(Acceptance Criteria)时,我们强制 AI 使用业界著名的 EARS(Easy Approach to Requirements Syntax,需求语法简单方法) 模板格式。这种格式大模型解析起来极其精准。
🛠️ 【实战产出】意图与 EARS 规范片段
# 📦 Delta Spec: 商品默认单位支持 (Feature-DU-001)
## 1. 业务上下文 (Business Context)
引入多单位体系。核心诉求:不破坏原有的基础库存单位(Base Unit,如"瓶"),而在销售端支持默认单位(如"箱")的展示与计算。
## 2. 验收标准 (Acceptance Criteria - EARS 格式)
### 场景 1:基础计算逻辑
- **Ubiquitous (普遍要求):** The system shall 始终以“基础单位”向 WMS 系统同步库存。
- **Event-driven (事件驱动):** **WHEN** 用户在 C 端请求商品详情时,系统必须返回按“默认单位”折算后的价格。
### 场景 2:边界与异常处理
- **State-driven (状态驱动):** **WHILE** 商品未配置默认单位时,**WHEN** 发生计价请求,**THEN** 系统必须无缝降级,使用基础单位进行计算。
- **Unwanted behavior (异常行为):** **IF** 发现单位转换率 (Conversion Rate) <= 0,**THEN** 系统必须阻断上架操作,并抛出 `InvalidConversionRateException`。
人类架构师仔细 Review 了这段由 AI 整理的 EARS 规范。确认无误后,业务的“What(做什么)”和“边界”被彻底锁死。
第二阶段:架构防腐——拒绝打补丁,捍卫领域边界
接下来是技术计划(Plan)阶段。我们让 AI(架构智能体)读取刚才的 Spec 以及当前代码库的上下文,提出数据库修改方案。
起初,AI 为了“偷懒”,依然提出了 ALTER TABLE products ADD COLUMN default_unit 的提案。
这时候,人类架构师的**“一票否决权”**发挥了作用。人类指出:“products 表是核心基础数据,严禁添加任何与销售展示相关的字段。请重构数据模型,采用领域驱动设计(DDD)中的聚合思想。”
在人类的强制纠偏下,AI 更新了 Spec,给出了完美的架构防腐(Anti-Corruption)方案。
graph TD
subgraph Vibe_Coding_Bad_Design["❌ 反面教材:AI 随意打补丁"]
A["核心商品表 (products)"] -->|"直接修改表结构"| B["default_unit (强耦合)"]
A -->|"直接加字段"| C["conversion_rate (破坏范式)"]
end
subgraph SDD_Good_Design["✅ SDD 规范:架构防腐设计"]
D["核心商品表 (products)"] -.->|"保持纯洁, 零修改"| D
E["新建聚合表 (product_unit_profiles)"] -->|"引用 product_id"| D
E -->|"记录"| F["unit_type (销售/采购)"]
E -->|"记录"| G["conversion_rate"]
end
style B fill:#ffcdd2,stroke:#c62828,stroke-width:2px
style C fill:#ffcdd2,stroke:#c62828,stroke-width:2px
style D fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style E fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
图 1:通过 Spec 约束 AI 的数据库设计决策
通过新建 product_unit_profiles 表,我们完美解耦了“商品基础信息”与“单位转换策略”。这就是 SDD 中**“人类把握方向(必要复杂性),AI 负责执行(偶然复杂性)”**的最佳体现。
第三阶段:任务原子化与 AI 编码执行
架构敲定后,AI 自动将 Spec 拆解成了 4 个原子任务:
- Task 1: 创建
product_unit_profiles的数据库 Migration 脚本及 Entity。 - Task 2: 编写
UnitConversionService及相关单元测试。 - Task 3: 重构
ProductQueryService,在组装数据时联表查询单位配置。 - Task 4: 修复受影响的老旧 API 测试用例。
接下来,就是 AI 展现其恐怖算力的时候了。
我们唤醒 Cursor 或 Claude Code(编码智能体),它读取 Delta_Spec_DefaultUnit.md 中的 Task 2。
强制 TDD 闭环的魔力
还记得上一篇的 TDD 吗?AI 首先生成了一个测试文件,断言 convert(100, 24) 应该返回 4.16 等边界情况。
由于测试在前,AI 在编写 UnitConversionService 时,一次性写出了处理精度丢失、处理零除数异常的工业级代码。整个过程耗时不到 15 秒。
AI 逐个打勾,终端绿光不断闪烁。当 Task 4 完成时,整个系统已经具备了“默认单位”功能,且没有破坏任何一行核心底层的原有逻辑。
第四阶段:两阶段审查与提效量化
最后,我们通过 Spec Kit 等 CI 工具,执行了双轨 Review。
AI 交叉审查确保了代码 100% 遵守了 EARS 验收标准;人类架构师最后扫了一眼聚合类的设计,满意地按下了 Merge PR。
让我们用真实的数据,来量化对比这三种开发模式在此次中型需求中的表现:
| 评估维度 | 传统纯手工开发 | AI 氛围编程 (Vibe Coding) | SDD 规范驱动开发 |
|---|---|---|---|
| 文档与设计耗时 | 4 小时 (写 PRD 与详设) | 0 小时 (直接聊) | 1.5 小时 (写 Spec + 审查架构) |
| 编码与测试耗时 | 2 天 | 2 小时 (极其神速) | 3 小时 (受限于严格的 TDD) |
| 调试与修 Bug 耗时 | 1 天 | 3 天 (陷入幻觉和架构冲突) | 0.5 小时 (极少的集成问题) |
| 代码可维护性 | 良 (依赖人类水平) | 极差 (满屏打补丁) | 极优 (完全遵循 DDD 与范式) |
| 总计交付周期 | 约 3.5 天 | 约 3 天 (且留下深坑) | 约 5 小时 |
结论显而易见: 在最初的 1 小时里,SDD 看起来比 Vibe Coding 慢得多,因为人类在逼迫 AI 写文档、抠边界。但这 1 个小时的前置思考,彻底免去了后期长达 3 天的屎山排雷工作。 慢,就是快。
结语:控制欲是高级工程师的美德
在这个案例中,如果我们有一丝懈怠,放任 AI 去修改了 products 原表,未来的系统就会像一颗定时炸弹一样,在某次双十一大促时因为缓存雪崩而引爆。
大模型极大地拉平了语法的门槛,这意味着在未来,“会写代码”将不再是稀缺能力。真正的稀缺能力是:在极其复杂的系统交互中,能够预见变更带来的连锁反应,并通过结构化的语言(Spec)将这种预见转化为对机器的刚性约束。
这种近乎偏执的“控制欲”,正是高级软件工程师在 AI 时代最大的底气。
然而,凡事皆有两面性。既然 SDD 如此强大,为什么在一些团队中推行时却以失败告终?规范是如何成为团队的“紧箍咒”甚至阻碍开发的? 在下一篇文章 《【风险规避】避坑指南:SPEC 为什么会失败?及应对策略》 中,我们将揭露那些可能导致 SDD 破产的真实场景,并教你如何建立“审阅-挑战-修正”的健康循环。
敬请期待。