最近团队在从 0 到 1 做一个 AI 产品。在 AI 开发的时代,难免会接触到 OpenSpec、BMAD 等 SDD(Spec-Driven Development,规范驱动开发)框架。我们采用前后端分离的开发方式,使用 OpenSpec 规范驱动开发,平时我也将该框架应用于多个个人项目的开发中。
相比于一个人用 OpenSpec 开发全栈项目的丝滑体验,在前后端分离的开发流程中运用 OpenSpec 时,我却遇到了一些出乎意料的场景:前后端各写各的 change,流程就会卡在 explore 阶段。希望往后推进时,常常发现要先等对方确认某个细节才能继续;而对方那里也常常在等我,最终双方就隔着 change 互相尬住了。
这不禁让我思考,为什么在使用同样工具、同样流程的情况下,多了一个开发者,流程就不再那么丝滑了。又经过几天的体验和思考,我才逐渐想明白其中的一些卡点。
卡顿的两层原因
为了搞清楚卡点在哪,我先回顾了一下我和后端的协作方式。流程大概是这样的:一个新需求产生后,我们各自使用 OpenSpec 开自己的 change,前端和后端各自 explore 探索、头脑风暴,结束后产出提案。但探索过程中慢慢就会发现,我要消费的接口形态,依赖于后端的实现设计;而后端要确定字段设计,又得看前端打算怎么使用。于是我去翻后端的设计和代码,后端也来看我的设计和代码,谁都没法独立往下走,explore 阶段就这么卡住了。
相比于一个人进行全栈开发,双人配合协作开发有什么区别?为什么一个人开发时没遇到过这个问题?答案其实很简单:一个人全栈开发时,前后端全在我手里,接口、字段的定义都由我来拍板,两端在我脑子里本身就是对齐的。而两个人合作的场景中,这种”对齐”就需要显式地摆到台面上来,我们又恰恰缺少了摆放它的地方。
再深入想想,这其中其实还有两层原因。第一层是产品阶段。对于一个从 0 到 1 的 AI 创新型产品来说,需求常常是不停变化的。需求一变,接口契约就得跟着变,今天定下的字段可能明天就推翻了。换句话说,契约的稳定是靠需求的稳定撑起来的,而从 0 到 1 的阶段恰恰很容易发生需求的反复。于是双方谁也不敢、谁也没法先把契约钉死,大家只能一边猜一边写,写完了再互相对,对不上就回头改,改完再对,如此循环往复。
第二层更隐蔽一些:我们双方之间,始终没有一份先立起来、能直接照着走的契约。前后端的 change 往往是同时向前推进的,接口的样子是从两边的实现中一点点磨合出来的。这就意味着,对于需求来说,从头到尾都没有一个双方都认可的”真相源”。每次想往前推进,都要深入对方的实现细节去确认,然而对方的实现也一直在变化。
想到这里,我隐隐约约有一种感觉:卡顿的根因,是前后端之间的边界模糊了。
缺失的契约
顺着边界模糊继续往下想:前后端之间的边界,原本应该是什么样的?
其实这个问题在传统开发流程中早就有答案:一份接口文档就是前后端之间的边界,或者说契约。需求确定后,先把接口定义出来,形成一份双方都认可的 OpenAPI 文档,后端照着它实现,前端照着它消费。对前端来说,这份契约就是唯一真相源,后端内部怎么设计、怎么实现,前端并不需要关心;同样,后端也不需要知道前端会怎么使用数据。双方各自把细节收在契约后面,边界自然就清楚了。
对照这个答案回头看我们的协作方式,问题就明显了。我们把彼此的设计和实现细节摊开给对方看,却始终没有立起一份契约。本该隐藏的细节全都透明了,本该立起来的约定却一直缺席。
一开始我以为,改进的办法是”后端制定契约,前端消费契约”,毕竟接口是后端提供的,由提供方来定义似乎天经地义。但后来体验下来更顺畅的模式,反而是前后端按不同的需求和模块,各自产出契约,另一方来配合。这让我意识到,“谁来制定”其实没那么重要,重要的是,每份契约都要有一个明确的产出方,由这一方独立、先行、稳定地把契约立起来,另一方把它当作真相源来遵守。至于产出方是前端还是后端,完全可以按需求、按模块来回切换。
想清楚这一点后,我对”透明”有了一个新的判断标准:该不该透明,取决于双方之间有没有一份唯一的契约。有契约,就让契约说话,实现细节应当隐藏起来;没有契约,才需要把细节摊开来对齐。而我们的卡顿,正是在本该由契约说话的地方,退回到了互相看细节的模式。
没有契约的协作
按照这个标准再看我和 AI 之间的协作,情况就完全反过来了。
回头想想我和 AI 之间有契约吗?似乎没有,而且也立不起来,因为契约的前提是”约定好之后,双方照着执行”,而 AI 每次生成的方案和代码,都是一个当场产生的新答案。同一句需求,今天生成的和明天生成的可能就不一样。不借助特殊手段的情况下,我没有办法提前和它约定好”你会怎么实现”,再照着约定去验收。前后端之间那种”立一份契约、各自隐藏细节”的模式,在这种情况下并不成立。
没有契约可立,就只剩下一条路:把细节摊开。这也是我在使用 OpenSpec 的过程中慢慢确认的一件事。保证 AI 产出可用、准确的关键,就是认真阅读它生成的方案细节,对其中不正确或者偏离方向的地方,及时、详细地修正。方案里的每一段设计、每一个假设,都是 AI 思考过程的显影。读得越细、纠正得越早,后面实现阶段的返工就越少。反过来,如果图省事跳过方案直接往下走,问题往往会在代码里以更隐蔽的方式冒出来。
有意思的是,Claude Code 本身并没有像 Web 端一样把 thinking 过程完整展开给用户(不知道是出于什么考虑,可能是终端显示内容量上的权衡),而 OpenSpec 恰好通过文档把这个过程显化了出来,某种程度上正好补上了这块透明。
所以同样是”摊开细节”,在前后端之间是边界模糊的病因,在我和 AI 之间反而是质量保证的核心。透明本身没有好坏,关键还是那个判断标准:双方之间有没有一份可以依靠的契约。
透明的两面
想明白这个判断标准之后,我发现它能解释的东西其实比开发协作更多。
《三体》里的三体人就是一个极端的例子。三体人的思考和交流是完全透明的,念头一起,同类就能立刻知晓其想法。对内,这种透明让它们的交流几乎零损耗,效率极高,文明和科技也因此发展迅猛;可一旦面对人类这样利益对立的对手,同样的透明就成了无法隐藏、无法欺骗的破绽,反过来被人类利用。同一种性质,隔着一条阵营的边界,利弊就完全颠倒。
DeepSeek-R1 则是另一个方向的例子。它刚发布时震动了整个 AI 圈:在大家普遍认为模型能力只能靠堆算力往上抬的时候,它用强化学习让模型把推理链显式地写出来,靠”摊开思考”找到了新的提升路径。对需要被人审视、被人纠正的 AI 来说,透明本身就是能力的一部分。
一个是透明成了破绽,一个是透明成了能力。放在一起不难体会到,透明这件事本身没有绝对的好坏,重要的是它发生在哪条边界的哪一侧。
结语:一条判断法则
回到开发协作上,这次的经历给我留下了一条实用的判断法则:和别人协作时,先问一句:有没有一份可以遵守的唯一契约?
如果有,就把契约当真相源,各自把实现细节收在自己这一侧,别越界去看对方怎么做;如果没有,就先看看契约能不能立起来。能立起来,就尽早立契约;立不起来(比如面对 AI),就把细节彻底摊开,认真审阅、及时纠正。
这篇文章记录的只是我在一个从 0 到 1 的项目里的一段体验,未必适用于所有团队和阶段。不过下一次再遇到流程莫名其妙卡住的时候,我大概会先从这个问题问起:卡住的地方,缺的是一份契约,还是一次开诚布公?
评论