
文章目录
壹:一场说不清为什么的反对
最近在跟团队探索怎么用 SDD 盘活现有项目。从需求梳理到落地实现,大家的思路都还算一致。但聊到重构这一块时,有个同事说了句:重构也应该走 SDD,所有变化都应该有规格驱动。
我当时的反应是直觉性地反对,但又说不上来为什么。嘴上反驳了几句,底气却不足。
这种感觉很多做技术的人都经历过。你明明觉得一个方向不对,但当下就是组织不出有力的反驳。不是没有道理,是道理还没浮上来。
后来有天突然想明白了。那个藏在直觉背后的东西,其实就是软件工程里一条最基本的原则:面向抽象编程,而不是面向具体。
贰:直觉背后,是面向抽象的本能
面向抽象编程这句话,写了这么多年代码的人大概都听过。接口优于继承、依赖倒置、面向接口编程,底层都在讲同一件事——把"什么不该变"定住,让"怎么实现"自己演化。
这个原则为什么重要?因为它解决的不是某个具体问题,而是一类问题的复杂度控制。当你把精力集中在抽象层——接口契约、业务规则、边界条件——具体的实现就有空间去适配不同的场景、不同的阶段、不同的约束。
回到 SDD 那个讨论。SDD 的价值是让抽象层变得可描述、可传递、可验证。这件事在需求阶段、在新功能设计阶段,非常有效。因为这时候抽象层本身是模糊的,人需要先把它定住。
但重构不一样。重构的本质是等价变换——外部行为不变,内部实现调整。也就是说,抽象层已经定了,变的只是具体层。
如果你非要为这种重构写一份完整的规格文档,那本质上就是在用定义"道"的方式去规定"术"。方向没错,但层级搞错了。
叁:AI Ready 的分界线
想明白这一层之后,一个更大的问题就浮出来了。
在 AI Ready 的工程里,人和 AI 的边界到底该怎么划?
这个问题不是只存在于重构这一个场景。它贯穿在整个 AI 协作的工作方式里:写新功能的时候,人该参与多少?修 bug 的时候,人该干预到什么程度?架构调整的时候,哪些决策该由人做,哪些可以交给 AI?
如果用面向抽象的思路来回答,答案其实很朴素:
人守住抽象层,AI 负责具体层。
展开来说:
人该做的是定义"不变"——原则、架构方向、业务逻辑、风险边界、优先级取舍。这些东西决定了系统的骨架和底线。它们不因具体的实现方式而改变,也不该因为换了工具、换了框架就动摇。
AI 该做的是处理"万变"——具体的代码实现、结构优化、接口适配、问题定位。这些事情服务于骨架,但每一步怎么走,该由现场的约束条件来决定,而不是由一个事无巨细的流程来规定。
这不是一个漂亮的说法,而是一个可以反复验证的判断标准:如果一件事换一个具体任务它仍然成立,那它属于抽象层,该由人来定。如果它只在某类任务、某个场景下才有意义,那它属于具体层,该由 AI 来做。
肆:落到 CLAUDE.md,你到底在写什么
说完了原则,落到具体的东西上。
现在越来越多项目开始用 CLAUDE.md(或者类似的 AI 指令文件)来给 AI 交代项目上下文。但很多人写这个文件的时候,其实没想清楚一个问题:你到底是在写原则,还是在写步骤?
CLAUDE.md 本质上是项目的抽象层文档。它的职责是告诉 AI:这个项目的骨架是什么,底线在哪,哪些东西不能碰,遇到复杂现场该怎么判断。
如果用面向抽象的标准来审视,一份好的 CLAUDE.md 应该满足几个特征:
第一,规则应该跨任务成立。 也就是说,不管 AI 在做新功能、修 bug 还是做结构调整,这些规则都应该起作用。如果一条规则只在某个特定任务里有意义,那它大概率不属于 CLAUDE.md,而属于某个具体的执行流程。
第二,规则应该约束判断,不约束动作。 "修改老系统前先做影响面分析"是一条好的规则,因为它约束的是决策倾向。"分析影响面时先 grep 搜索 Service 类,再搜索 Mapper"就未必属于这里,因为它约束的是具体动作。前者告诉你"往哪看",后者规定你"怎么走"。
第三,规则应该是可观察、可判断的。 "保持高质量输出"这种话,看起来对,但 AI 没法判断自己做到了没有。"修改数据库相关代码时,必须同步更新对应的索引和查询计划检查"——这条就能观察,能判断,能验证。
举几个具体的对比。
该写的:
- 修改涉及多个模块的功能前,先梳理影响范围,确认改动不会破坏现有行为
- 遇到历史遗留的硬编码和魔法值,优先标注风险,不擅自清理
- 接口变更必须保持向下兼容,除非明确标注为 breaking change
- 数据库变更必须包含回滚方案
这些是抽象层的规则。它们不管 AI 具体怎么写代码、怎么搜索、怎么组织文件,但它们界定了判断的边界。换一个任务——不管是加功能、修 bug 还是做性能优化——这些规则照样成立。
不该写的:
- 修改代码前先用 grep 搜索相关文件
- 阅读 Service 和 Mapper 层的实现
- 按照 Controller -> Service -> Mapper 的顺序修改
- 每次修改后运行完整的测试套件
这些不是原则,是流程。它们只在特定任务类型下有意义,而且会随着项目的演化而过时。把它们写进 CLAUDE.md,表面上是给了 AI 更多指导,实际上是把它捆在了一个固定的操作路径上。
伍:放手不是放任,约束反而更强
很多人听到"让 AI 自己决定怎么做",第一反应是不放心。觉得不盯紧就会出事。
但做工程的人仔细想想,真正强的约束从来不是事无巨细的流程,而是清晰纯粹的规则。
举一个很多人有体感的例子。你带过一个新人,如果你告诉他"每一步都按这个流程做,别自己发挥",他大概率会变成一个只会机械执行的机器。遇到流程没覆盖的情况就卡住,遇到需要变通的地方就僵住。
但如果你告诉他"这几条底线不能碰,其他你看着办,出了问题找我讨论",他反而会更快成长,也更有判断力。
AI 也是一样。你用死板的流程去锁死它的每一步,它就只能在你的想象范围内活动。你把规则定纯粹,把边界划清楚,它反而能在规则框架内做出超出你预期的结果。
回到 CLAUDE.md。当你把它写成一份干净的抽象层文档——只放原则、不放步骤,只管判断、不管动作——你实际上在做两件事:
你给 AI 划了一道清晰的边界,让它知道什么不能碰。 这比"什么都管"的约束力更强,因为规则越纯粹,越不容易被遗漏或矛盾。
你给 AI 留了一片清晰的自由区,让它知道什么可以自己决定。 这比"什么都规定"的创造力更大,因为 AI 不用每一步都去猜你的意图。
这就是面向抽象的工程思路在 AI 协作里的真正价值:约束越纯粹,边界越清晰,AI 能发挥的空间反而越大。
陆:说到底,是信任边界的问题
回到最开始那个问题:重构要不要走 SDD?
这只是一个小切口。它背后真正的问题是:在 AI Ready 的工程里,人该管什么,该放什么?
面向抽象编程给了我们一个经得起检验的回答:管好"不变"的东西——原则、架构、业务逻辑、风险边界。让 AI 去处理"万变"的东西——实现方式、代码组织、结构优化、具体方案。
落到 CLAUDE.md 上,就是把它当成项目的抽象层来写。不是操作手册,不是流程文档,而是这个项目这么多年积累下来的判断力和分寸感。
这些年做技术,最大的感触之一就是:好的架构不是什么都管,而是知道什么不该管。 把精力集中在那些真正不该变的东西上,让变的部分自己去找最优解。
AI 时代也是一样。人定义好"不变"的架构,AI 负责"万变"的实现。这不是偷懒,这是信任边界的合理划分,也是面向抽象编程在 AI Ready 工程里的自然延伸。