开发者现在将Markdown规范交给AI执行代码生成,Cucumber等工具规范化这一新的AI驱动工作流。
现在,每个人都在为 AI 编写规格说明。我们把一个 markdown 文件交给模型,告诉它我们想要什么,然后期待它构建出正确的东西。大多数时候确实有效——直到它失效。
Markdown 已悄然成为规格说明语言。人们把它当作 AI 驱动工作流的 DSL:标题、项目列表,偶尔再加个表格——然后将这种松散的结构视为一份契约。问题在于,它并不是 DSL。它只是 markdown,是一种散文格式,没有可强制执行的语法,没有能够执行的结构,没有共同的词汇体系,也无法判断规格说明与代码是否仍然一致。你是在让一种文档格式承担它从未被设计用来完成的工作;而当你希望规格说明真正具备机器可检查的含义时,立刻就会触及它的极限。
在你继续沿着这条路走下去之前,我想提出一个小小的、略显荒谬的建议。
Gherkin 是 Cucumber 背后的纯文本语言。Cucumber 是 BDD(行为驱动开发)领域中一款已经存在多年的工具。它看起来是这样的:
Feature: User login
Scenario: Successful login with valid credentials
Given a registered user "ada@example.com"
When she logs in with the correct password
Then she should land on her dashboard
And she should see a welcome message
Scenario: Rejected login with wrong password
Given a registered user "ada@example.com"
When she logs in with an incorrect password
Then she should see an "invalid credentials" error
And she should remain on the login page
就是这样。Feature、Scenario、Given/When/Then。它的结构足够明确,机器可以解析;同时又足够灵活,产品经理也能编写。
大多数规格说明都处于两个极端之一。
一端是书面规格说明:文档、工单、markdown 文件。任何人都能读懂,但它们是静态的。没有任何机制检查其中的内容是否仍然成立。代码一旦继续演进,它们便开始腐化。
另一端是测试:精确、可执行,而且始终诚实——但它们由代码编写,对于真正关心这些行为的人来说,有一半根本看不懂。
Gherkin 位于两者之间。它是带有恰到好处结构骨架的自然语言,你可以把每一个 Given/When/Then 步骤连接到真实代码。同一个文件既是人类可读的规格说明,也是测试运行器实际执行的内容。当行为发生变化时,Scenario 就会失败。规格说明无法悄无声息地偏离现实,因为规格说明本身就是检查机制。
这就是人们所说的“活文档”:一种不会对你撒谎的文档,因为它能够运行。
你不应该仅仅因为理念不同就切换格式。只有当文档开始难以承载它所要表达的内容时,才需要切换。以下三个信号说明你已经到了这个阶段。
一份规格说明最初可能只是一段对意图的描述。接着,有人针对边界情况添加了一个项目;然后又为边界情况中的例外添加了一个子项目;最后再用括号补充闰年时应该如何处理。此时,散文已经开始假装自己是一台状态机。
这些具体情况中的每一个,实际上都是一个 Scenario——一组明确的 Given/When/Then。markdown 无法将其标记为 Scenario,更不用说对它进行检查。Gherkin 可以做到:每一种具体行为都会成为一个独立命名的 Scenario,你可以单独指向它、运行它,并对它进行推理。
这是最明显的信号。当你的规格说明中出现表格——输入 A 得到输出 X,输入 B 得到输出 Y——你就已经不再是在描述行为,而是在枚举案例。
markdown 表格只会静静地待在那里,没有任何机制验证第三行是否仍然成立。Gherkin 通过 Scenario Outline 和 Examples 原生支持这种形式:
Scenario Outline: Discount applied by tier
Given a customer on the "<tier>" plan
When they check out with a cart total of <total>
Then the discount applied should be <discount>
Examples:
| tier | total | discount |
| free | 100 | 0 |
| pro | 100 | 10 |
| premium | 100 | 25 |
还是同一张易于阅读的表格——但现在每一行都是一个可执行的测试用例。添加一行,就相当于添加了一个测试。数据表本身就是规格说明。
如果一项需求永远不会改变,那么在代码里写一条注释就足够了。只有当事情会发生变化时,活文档的成本才值得付出——而 AI 驱动的工作始终在变化。
当一条规则发生改变时,你希望只在一个地方进行编辑,并立即知道哪些东西被破坏了。使用 markdown 时,你修改文字,然后期待有人同步更新代码;没有任何机制会标记二者之间的偏差。使用 Gherkin 时,你修改 Scenario 并运行它,失败结果会准确告诉你现实在哪些地方不再与规格说明一致。规格说明成为你重新评估现实的依据,而不再是一份因忘记更新而过时的产物。
如果你要把规格说明交给 LLM 来生成或验证代码,那么与自由形式的 markdown 文件相比,Gherkin 可以提供三样东西:
模型不必猜测你自行发明的结构。Gherkin 的词汇很少、有完善的文档,而且几乎可以肯定已经存在于模型的训练数据中。
AI 可以生成代码,而你能够立即运行这些 Scenario,查看它是否真的完成了任务——不再需要由人重新阅读 markdown 并作出判断。
你可以让模型根据描述编写 Scenario、根据 Scenario 编写代码,或者检查现有代码是否满足这些 Scenario。每个方向都有清晰且可检查的产物。
你既能获得自己想从 markdown 中得到的可读性,也能拥有一套可由机器强制执行的“完成”定义。
你不需要采用整套 BDD,也不需要重组团队。挑选一个正准备为 AI 工具编写规格说明的功能,把它写成 .feature 文件,而不是一大段 markdown。亲自感受一下让规格说明和测试成为同一份文档是什么体验。
你已经在把一种文档格式当作规格说明语言使用了。而 Gherkin 从一开始就是为此而生的——它早已存在,已经在每一种主流语言中拥有配套工具,也早已解决了 markdown 一直在悄然应付失败的问题。
所以,把 markdown 放回它该在的地方。吃掉这根黄瓜吧。
如需采取进一步行动,你可以考虑屏蔽此人和/或举报滥用行为。