前谷歌 AI 总监的 LLM 编程工作流:让 AI 辅助编程真正高效

AI教程22小时前更新 程序员阿超
373 0 0

一、背景:为什么顶尖工程师都在重构自己的编程流

Addy Osmani 曾长期负责 Google 的 Web 与 AI 开发者体验工作,他每天面对的问题很典型:需求模糊、代码库庞大、模型能力强但不稳定。用大模型写代码有两种极端:一种是把整段需求丢给模型”一键生成”,结果得到几百行看似能跑、实则埋雷的代码;另一种是只把模型当补全工具,效率提升有限。Osmani 在 2026 年初总结的工作流走的是中间路线——把 LLM 当作”执行力极强但需要严密规格的初级工程师”,人负责规格、拆分与验收,模型负责高速实现。这套流程的核心只有三句话:规格先行、切碎任务、测试驱动。

这套方法对普通开发者同样有效,因为它解决的不是”模型不够强”,而是”协作界面不清晰”。本教程把这套工作流拆成可落地的操作步骤,配完整模板与代码示例,你可以直接套用到下一个需求上。

二、原理:为什么 spec + 切碎 + TDD 能放大模型能力

2.1 规格先行降低歧义熵

LLM 的错误大多不是”笨”,而是”猜”。当需求文档只写”做个登录功能”,模型必须同时猜测技术栈、会话机制、错误处理、接口形状,猜错任何一个都是返工。一份好的 spec.md 把这些自由度提前锁死:技术选型、数据结构、接口签名、边界行为、非目标。规格越具体,模型的采样空间越小,一次通过率越高。Osmani 的经验是:写规格的时间会在实现阶段数倍赚回来。

2.2 切碎任务匹配模型工作记忆

大模型处理超长上下文时会”顾头不顾尾”,一次生成 500 行代码的缺陷率远高于 5 次各生成 100 行。把任务切成”每步 15 分钟可验证”的小块,每块有明确的输入输出与验收标准,模型每次只需关注一个子问题,人也能逐块 review,而不是最后面对一坨无法审查的大泥球。

2.3 TDD 给模型一个客观裁判

没有测试时,”代码写完了吗”由模型自己说了算,它倾向于报喜。测试先行把验收标准变成可执行的断言:测试红了就是没做完,绿了才能进入下一步。测试还顺手沉淀为回归资产,下一轮模型改代码改坏了能立刻发现。

三、环境准备

工具链不挑,任何主流 LLM 编程助手(Claude Code、Codex、Cursor、 Gemini CLI 等)都适用。建议准备:

# 示例项目骨架(Python + pytest),其他语言同理
mkdir llm-workflow-demo && cd llm-workflow-demo
python -m venv .venv && source .venv/bin/activate
pip install pytest pytest-cov
git init && mkdir -p specs src tests docs

约定三个文件为协作界面:specs/spec.md(规格)、specs/tasks.md(任务拆分)、AGENTS.md 或 CLAUDE.md(仓库级约束,如代码风格、测试命令)。先把约束写进 AGENTS.md,模型每次开工前都会读:

# AGENTS.md
- 语言:Python 3.11,风格 ruff,行宽 100
- 测试:pytest,新增功能必须带测试,覆盖率不低于 80%
- 不准事项:不引入新依赖(除非 spec 批准),不提交密钥
- 验证命令:pytest -q

四、分步实战

下面以”给一个 CLI 工具加--since增量导出功能”为贯穿例子演示全流程。

步骤 1:写 spec.md(规格先行)

不要直接让模型写代码,先让它帮你把需求问清楚。提示词模板:

你是资深工程师。先阅读 AGENTS.md,然后就下面的需求向我提问,
把模糊点全部挖出来,再输出 specs/spec.md:
需求:给 exporter 工具加 --since 参数,只导出该日期之后的记录。

合格的 spec.md 长这样(可直接复用结构):

# spec:增量导出 --since

## 1. 背景与目标
支持按日期增量导出,避免每次全量扫描。成功标准:100万行数据下
增量导出耗时 < 全量 20%。

## 2. 非目标
- 不做增量删除同步;- 不改现有全量导出默认行为。

## 3. 接口设计
- CLI:`exporter --since 2026-01-01 [--format json|csv]`
- 日期格式严格 ISO-8601(YYYY-MM-DD),非法输入 exit code 2 并打印用法。
- 库函数:`export_records(since: date | None) -> Iterable[Record]`

## 4. 数据与边界
- since 为空 = 全量;since 早于最早记录 = 全量;晚于最新记录 = 空输出 + 警告。
- 时区:统一按 UTC 日期比较,记录时间为 naive 按 UTC 解释。

## 5. 性能与兼容
- 100万行增量 < 2s;不新增第三方依赖。

## 6. 验收标准(对应测试)
- T1 非法日期报错码 2;T2 空区间输出空;T3 百万行性能达标。

要点:每个验收标准都有编号,后续任务与测试直接引用编号,形成可追溯链。

步骤 2:切碎任务(tasks.md)

根据 specs/spec.md,把实现拆成 tasks.md,要求:
- 每个任务 ≤15 分钟可完成、有明确验收(引用 T 编号);
- 标注依赖顺序;- 第一个任务必须是测试脚手架。

拆完示例:

# tasks
- [ ] K1 测试脚手架:tests/test_export.py + 百万行 fixture 生成器(验收:pytest 能跑通空测试)
- [ ] K2 日期解析器 parse_since(),非法输入抛 UsageError(验收 T1)
- [ ] K3 export_records(since) 过滤逻辑(验收 T2 相关用例)
- [ ] K4 CLI 接线 --since/--format(验收 T1/T2 端到端)
- [ ] K5 性能优化 + 基准脚本 bench.py(验收 T3)

步骤 3:TDD 红灯——先写测试

只做 K1+K2 的测试部分,不写实现。测试引用 spec 的 T1。
# tests/test_export.py
import pytest
from datetime import date
from exporter import parse_since, UsageError, export_records

def test_bad_date_exits_code2():
    with pytest.raises(UsageError):
        parse_since("2026-13-40")

def test_since_after_all_returns_empty(records):
    out = list(export_records(records, since=date(2099, 1, 1)))
    assert out == []

def test_since_none_returns_all(records):
    assert len(list(export_records(records, since=None))) == len(records)

先跑 pytest -q 看到失败(红灯),这一步确认测试真的在测东西。

步骤 4:绿灯——最小实现

实现 K2,要求:只做 K2,不碰 K3/K4;跑通相关测试后用 ruff 自检。
# exporter.py
from datetime import date, datetime

class UsageError(Exception):
    code = 2

def parse_since(s: str | None) -> date | None:
    if s is None:
        return None
    try:
        return datetime.strptime(s, "%Y-%m-%d").date()
    except ValueError:
        raise UsageError(f"非法日期: {s!r},请用 YYYY-MM-DD")

pytest -q 变绿后再进入下一任务。每个任务都是”红-绿-重构”小循环。

步骤 5:逐块实现 + 即时 review

每完成一块,要求模型输出变更摘要而非整文件重贴:

K3 已完成。请给出:1) diff 摘要;2)  risks;3) 回归测试结果。
不要继续 K4,等我确认。

人的 review 清单:接口是否与 spec 一致、有无引入新依赖、边界用例是否覆盖、复杂度是否失控。Osmani 特别强调”小步合入”:每块通过就 git commit,模型走偏时回滚成本极低。

步骤 6:端到端验收与文档收尾

# bench.py(K5 验收脚本)
import time
from datetime import date
from exporter import export_records
from tests.conftest import make_million_rows

rows = make_million_rows()
t0 = time.time()
n = sum(1 for _ in export_records(rows, since=date(2026, 6, 1)))
print(f"rows={n} cost={time.time()-t0:.2f}s")
对照 spec 第6节逐条验收:T1/T2/T3 是否全过?
通过后更新 README 的 --since 用法,并输出本次变更日志。

五、常见坑

  1. 规格写一半就开工:表现为模型反复问”这个字段什么意思”。解法是立规矩——spec 没有验收编号就不许写实现代码。
  2. 任务块太大:”实现整个导出模块”一次生成 600 行,review 不动。切到 15 分钟粒度,宁可任务多,不可块头大。
  3. 测试后补等于没测:先实现后补测试,测试只会给现有行为背书。用”测试文件时间戳早于实现”来硬约束顺序。
  4. 一次让模型做两件事:”顺手把 K3 K4 一起做了吧”是最常见的返工源,一次只派一个任务号。
  5. 不锁依赖导致漂移:模型悄悄 pip install 新库。AGENTS.md 明令禁止,CI 里加 pip freeze 校验。
  6. 上下文污染:长对话后期模型开始遗忘 spec。新开会话时只喂 AGENTS.md + spec.md + 当前任务,而不是 whole history。
  7. 把 review 外包给模型:模型自己 review 自己通过率虚高。关键 diff 必须人眼过,模型只做 checklist 初筛。

六、总结

Osmani 工作流的本质是把”人机协作界面”从自然语言闲聊升级为工程契约:spec.md 锁定义,tasks.md 锁节奏,测试锁质量,AGENTS.md 锁约束。人做三件事——写清规格、切小任务、逐块验收;模型做一件事——高速实现。按这个流程跑两周,你会发现模型一次通过率显著上升,返工 mostly 消失,沉淀下来的 spec 与测试还是长期资产。下次开新需求时,先别急着写代码,先写 spec。 点击阅读原文

参考资料:Addy Osmani《My LLM Coding Workflow Going into 2026》(1行)。 点击阅读原文

七、深度扩展:多会话协作与度量复盘

7.1 长需求的多会话管理

真实需求动辄跨 3~5 个会话。跨会话不失忆的做法:每个会话结束强制输出”状态快照”追加到 specs/progress.md——已完成任务号、当前 diff 摘要、未决问题、下一步任务号。新会话开场白固定为:”读 AGENTS.md、spec.md、progress.md,然后复述当前进度,等我确认再动手。”复述环节看似多余,实则是低成本的对齐校验,模型复述错了立刻纠正,比做错再返工便宜得多。

7.2 Review 清单深讲:五个必查项怎么查

口径一致性:打开 spec 口径节逐条对实现,时区、精度、排序、错误码四个最易错。依赖漂移:git diff --stat 看有无新增文件与依赖,超范围的一律打回。边界覆盖:在测试文件里搜 empty/invalid/none 关键词,边界矩阵每行必须有对应测试名。复杂度:单函数超 50 行或嵌套超 3 层就要求拆,模型写的”大函数”后期维护成本极高。魔法数字:grep -rn "utcnow\|0.5\|86400" src/,裸常量必须收敛到命名常量。

7.3 一次真实复盘:规格省下的两小时

某次给导出工具加时区支持,第一版 spec 只有三行。模型按 UTC 实现,做完才发现业务要 Asia/Shanghai,返工 2 小时。复盘后立规矩:涉及时区的 spec 必须写明”输入时区/存储时区/展示时区”三栏。从此同类需求一次通过。每个团队都值得维护这样一份”返工账本”,它比任何方法论文档都更有说服力。

7.4 度量工作流是否变好

跟踪三个数:一次通过率(无需返工的任务占比)、返工率(打回重做的任务占比)、测试覆盖率。跑四周看趋势,一次通过率上升 20 个点以上说明流程生效。若返工集中在某类任务(如 CLI 接线),就把该类任务的 checklist 写进 AGENTS.md。用数据驱动流程改进,而不是凭感觉。

八、总结(扩展版)

规格先行、切碎任务、测试驱动,这九个字背后是同一原则:把”人机协作界面”从闲聊升级为契约。契约越清晰,模型的强执行力越是资产而非负债。再加上多会话快照、review 清单、返工账本与三数度量,这套工作流就从个人技巧变成团队制度。下一需求开工前,先问自己:spec 的验收编号写好了吗?

九、附录:提示词工具箱与会话开场白

整理四个可直接复制的提示词。需求澄清用:”你是资深业务分析师,先读 AGENTS.md 与相关代码,然后就该需求一次性问完所有模糊点,按口径、边界、性能分类并给出推荐选项,等我答复后再写 spec,不要提前写代码。”任务拆分用:”按 spec 拆成 tasks.md,每个任务十五分钟可完成、有验收编号引用与依赖标注,第一个任务必须是测试脚手架。”实现派工用:”只做某任务号,不碰其他任务,跑通测试后附完整测试与检查输出,等我确认。”收尾用:”对照 spec 验收节逐条验收,通过后更新文档与变更日志,并把踩坑追加到记忆文件。”新会话开场白固定为:”先读 AGENTS.md、spec.md 与进度快照,复述当前进度与下一步,等我确认再动手。”把这五个句子存进团队手册,新人第一天就能跑出老手一半的效果。工具箱每季度回顾一次,把高频返工点沉淀为新的检查项,工作流就有了自我进化的能力。

十、附录二:坏味道速查与升级路径

当出现以下信号时说明流程正在退化:任务描述超过两百字还讲不清验收标准、单个提交改动超过五个文件、测试文件提交时间晚于实现文件、连续两个任务被打回。这些都是把大象塞回冰箱的征兆,处理办法一律是停下来拆任务。升级路径分三级:第一级个人工作流,把五个提示词存成模板;第二级团队制度,把 AGENTS 清单与覆盖率门禁写进仓库;第三级组织资产,把各项目的记忆文件定期评审,沉淀为跨项目手册。每一级的投入产出比都很清晰,建议按季度推进一级,不要贪多。最终你会发现,模型换了一代又一代,沉淀下来的规格、测试与记忆才是团队真正的护城河。

© 版权声明

相关文章

暂无评论

暂无评论...