有个场景我印象很深。我们的应用服务需要原子化修改共享内存里的一批数据。这套多服务共享的内存数据由系统统一管理:跨进程的锁、内存序、版本切换都封装在动态库.so里,外部通过统一的头文件调用。

但动态库里当时没提供“批量原子修改”的接口。AI 的处理方式极其简单粗暴:直接通过 mmap 拿到物理地址,按它自己的理解逐字段覆盖,中间还随手捏了个标志位充当“正在修改”的锁。

单进程跑,没问题,测试也过了。问题是它绕过的不是一个普通函数,而是一整套系统契约:跨进程锁被击穿,内存序的保证荡然无存,其他读进程随时可能读到写了一半的脏数据。更麻烦的是这种绕过不留痕迹——未来动态库要加审计或改内存布局时,这些直接操作物理地址的“幽灵调用点”无从查起。

AI 不是在蓄意破坏。它只是在遇到“外部没提供能力”时,选了一条阻力最小的路。而这条路,恰好把“原子性由底层保证”的契约,稀释成了“每个调用点自己瞎保证”。

用得越久,这类“局部完美跑通、全局千疮百孔”的时刻就越多。这往往体现在三个方面:

第一,抽象边界失守。 就像上面那个 mmap 的例子。传统开发中,如果底层库缺接口,接口调用方和接口提供方需要商量边界在哪,如何定义。AI 不做这种判断,只要规矩没覆盖到,它就会自行脑补。

第二,基础层无法沉淀。 有经验的工程师会顺手把通用逻辑抽成公共类。但 AI 倾向于就地解决:这个功能需要,就在当前文件里建个方法;下一个功能还需要,就在另一个文件里再写一遍。基础层不是被谁破坏了,而是根本建不起来。

第三,分层约定被无视。 稍微复杂些的系统,技术约束都是分层的。比如我们开发的工业控制与数据采集系统,平台层严格遵循 C++11 且禁用异常,而上层应用可以用 C++14。这意味着创建智能指针时,平台层只能老老实实写 std::unique_ptr p(new T(args...)),应用层却能用 std::make_unique。但在 AI 眼里,整个代码仓库是平的。开发环境的 gcc 版本较新,平台层混入了 make_unique 照样能编译,这个问题只有到集成测试阶段才会暴露出来。

人脑或许能记住这条 C++11 规则,但很难在一下午驱动 AI 连开十几个会话、写五个功能的高频切换中,始终记住“当前会话站在这张分层图的哪一格”。

把这些现象收拢,原因指向了同一件事:在跨会话的 AI 编码中,功能间的契约失去了载体。

系统软件必然由成百上千个功能拼装而成。你不可能“不需要契约”,你只能选择把契约明确写下来,还是靠脑子记、靠提示词带。事实证明,靠人脑记不住,靠提示词填则是一场豪赌——一旦漏写一层上下文,就是一次生产事故。

有人可能会问:现在流行的 SDD(规格化驱动开发)和 Code Plan First(计划优先模式)不就是干这个的吗?

并不是。这两个模式的射程边界,终止于“把当前任务做对”。你在会话 1 的 Spec 里明确了接口规范,没有任何机制能保证 AI 在会话 50 时还记得。你固然可以在每一个功能的详细设计里,不厌其烦地重复抄写“必须走动态库统一入口”、“平台层禁用 make_unique”。但这不仅反人类,而且必然会漏。模式边界本身的问题,靠“把工具用得更好”是补不上的。

至于传统的文档体系,更是指望不上。它们按岗位职能被分割在需求、架构、测试的孤岛里,格式五花八门,我甚至见过有些公司的需求文档为了方便汇报居然用 PPT。代码迭代几轮后,文档之间早已互相矛盾。你无法要求 AI 去参考这样一堆过时的“死物”。

所以,问题根本不在 AI 的理解力或生成质量——这些甚至超出了我的预期。明确地说:AI 没问题,是我们的组织方式出了问题,是我们目前的项目管理组织方式不能适应新的生产力。

要想管住系统软件的功能间的契约,我们需要一个独立的、跨会话的契约载体——它必须能被人和 AI 同时精确读取,并且能把“哪条规则管哪一层”的判断明确在文档结构里。

那么,这份长效的文档载体,究竟该按什么维度去组织才不会重蹈覆辙?


原文地址: https://www.cveoy.top/t/topic/qHUB 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录