
先把话说清:vibe coding 是什么
vibe coding 指的是一种强依赖大模型的编程方式:你用自然语言描述目标,模型生成代码,你更多依赖运行结果而不是逐行理解代码。这个说法来自 Andrej Karpathy 在 2025 年初的公开描述,随后被社区广泛引用。(Wikipedia: Vibe coding)
它的好处是速度快、试错成本低;问题是行为不稳定、回归成本高。你写得很快,但不知道系统到底“保证了什么”。
为什么 BDD 反而在这个时代更重要
BDD 的核心是“可执行的行为规格”。它把需求变成 Given / When / Then 这样的场景,不只是文档,而是能跑的验收标准。Dan North 在 2006 年把这一套从 TDD 里抽出来,强调“行为”比“测试”更有用,需求本身也应该是可执行的验收标准。(Introducing BDD)
Gherkin 规范把这套结构标准化:Given 是前置状态,When 是动作,Then 是可观察结果。(Gherkin Reference)
对 vibe coding 来说,这等于给“模型生成代码”配了一条安全带:
- 先写清楚行为
- 让模型生成实现
- 用场景验收
- 行为不对就回到场景,而不是乱改代码
实战:Go + Godog + LLM 的最小工作流
Go 里最主流的 BDD 实现是 Cucumber 官方维护的 Godog。(cucumber/godog)
1) 写行为规格(Gherkin)
features/discount.feature
Feature: discount
Scenario: VIP gets 10% off
Given a user is VIP
And the cart total is 200
When I calculate the price
Then the final price should be 180
这不是测试代码,这是需求。任何人都能看懂。
2) 让 LLM 生成步骤定义(你可以直接用下面的提示)
你是 Go 工程师。基于以下 Gherkin 场景生成 godog 步骤定义:
- 每个 Step 用正则匹配
- 使用一个上下文结构体保存状态
- Then 阶段断言计算结果
输出 Go 代码:add_test.go
模型会生成类似下面的结构。你只要把业务逻辑补进去即可。
3) 步骤定义(Go + Godog)
add_test.go
package calc
import (
"fmt"
"testing"
"github.com/cucumber/godog"
)
type ctx struct {
isVIP bool
total int
final int
}
func (c *ctx) userIsVIP() error {
c.isVIP = true
return nil
}
func (c *ctx) cartTotalIs(total int) error {
c.total = total
return nil
}
func (c *ctx) calcPrice() error {
discount := 0.0
if c.isVIP {
discount = 0.1
}
c.final = int(float64(c.total) * (1.0 - discount))
return nil
}
func (c *ctx) finalShouldBe(expect int) error {
if c.final != expect {
return fmt.Errorf("expected %d, got %d", expect, c.final)
}
return nil
}
func TestFeatures(t *testing.T) {
c := &ctx{}
godog.TestSuite{
ScenarioInitializer: func(s *godog.ScenarioContext) {
s.Step(`^a user is VIP$`, c.userIsVIP)
s.Step(`^the cart total is (\d+)$`, c.cartTotalIs)
s.Step(`^I calculate the price$`, c.calcPrice)
s.Step(`^the final price should be (\d+)$`, c.finalShouldBe)
},
Options: &godog.Options{
Format: "pretty",
Paths: []string{"features"},
TestingT: t,
},
}.Run()
}
这套结构与官方 README 一致(godog.TestSuite + ScenarioInitializer)。(cucumber/godog)
4) 运行
go test -test.v -test.run ^TestFeatures$
关键点:用 BDD 驯服 LLM,而不是让它决定行为
在 vibe coding 里,最大的问题不是“代码能不能跑”,而是“行为是否稳定”。BDD 的实用价值就是把“可执行行为”前置,让模型围绕行为去产出。
一个可落地的流程是:
- 业务先写 3 个场景
- LLM 生成步骤定义
- LLM 生成实现逻辑
- 场景不通过就改场景/实现
- 场景通过才允许合并
这能显著降低“生成代码很爽,但后期维护很崩”的风险。
结尾:vibe coding 不是答案,行为才是
vibe coding 会让你更快做出东西,但只有行为规格能让东西“可持续”。
如果你不想被模型牵着走,就用 BDD 先定义边界,再让模型去填细节。
参考资料:
Vibe coding(Wikipedia)
Introducing BDD(Dan North)
Gherkin Reference(Cucumber)
cucumber/godog(GitHub)