
Nick Tune:AI 工程化编码实践
在 AI 编程工具层出不穷的当下,工程师们逐渐摸索出自己的工作方式:有人直接通过网页调用 LLM,有人依赖 GitHub Copilot 或 Claude Code。然而真正决定最终代码质量的,并非工具本身,而是工作流程的设计。本文整理自 Nick Tune 在播客与公开分享中的实践精华,涵盖他如何将开发流程建模为状态机、如何用确定性规则守护架构、如何借助 TDD 与分层审核&查验实现高效自主开发。
Nick 是谁
Nick Tune 是一名高级软件工程师(Senior Staff Software Engineer),目前在 PayFit(欧洲薪资与 HR 服务商)任职。他著有《Architecture Modernization》(Manning 出版社),专注于遗留系统迁移、领域驱动设计(DDD)和持续交付领域,现居英国伦敦。
Nick 的 AI 工具使用心法
核心原则:全面尝试 + 严格计时
Nick 的策略是在所有场景中尝试 AI,再通过计时追踪实际收益。具体做法如下:
- 每接触一项新任务,先问"AI 能帮我做什么?"
- 给实验设定明确的时间上限(如 1 小时),防止沉没成本
- 记录每次尝试的产出,积累自己的"AI 效率账本"
Nick 坦承,并非所有实验都能成功——有时结局是浪费时间与挫败感。但他认为,最优结果往往需要前期投入,关键在于控制风险、持续迭代。
实战案例:客户工单处理工具
Nick 分享了一个典型案例:他负责处理客户支持工单时,意识到需要一个统一的工具来管理工单并为 AI 代理提供记忆,从而并行处理 10 个工单。
起初他顾虑旺季积压风险,但最终还是用 1 小时完成了初步构建。结果令人意外:
- 2–2.5 天后达到盈亏平衡点(工单处理量已超过手动完成的数量)
- 到周末结束时,效率提升约 20–40%
- 更复杂的是:某工单涉及 3 个代码库的数据关联分析,Claude 自主追踪到了问题根因
Nick 总结:"就是那 1 小时的计时实验带来了后续的持续回报。"
主流 AI 编码工具现状
目前工程师群体中流行的方案主要包括:
- 纯 LLM(网页端):门槛最低,适合快速探索
- GitHub Copilot:深度集成 IDE,适合日常辅助
- Claude Code:命令行优先,适合自主执行完整任务
Nick 的判断是:工具差异并非决定性因素,工作流程的设计才是核心。他自己的实践完全围绕这一理念展开。
状态机设计:Submitting 阶段的行为约束
在 Nick 的 AI 编程工作流中,"Submitting"是一个独立状态,专门处理 Pull Request 提交流程。该状态具有以下关键约束:
状态前缀与指令注入
每次 agent 发送消息时,系统会自动添加 🚀SUBMITTING 前缀,确保开发者始终了解当前工作流阶段。相关指令定义在 states/submitting-pr.md 文件中,仅在两种场景下触发注入:
- agent 转换到该状态时
- agent 出错需要重新提醒时
合法的状态转换
从 Submitting 状态只能转换到 AWAITING 或 BLOCKED,试图转向其他状态将被阻止,错误消息中会重新注入 submitting-pr.md 的内容。
可执行的操作
- 允许调用:
record-pr工作流操作(更新工作流状态) - 允许使用:
git push和gh pr(全局禁止的命令在此阶段例外放行) - 禁止操作:写入文件、调用其他工作流方法
PR 编号的强制要求
状态转换时,若 ctx.state.prNumber 未被设置,转换将直接失败。这是 Submitting 阶段的核心前置条件——必须创建 PR 并记录 PR 编号,否则后续所有工作流步骤都无法执行,整个流程将中断。
规划先行:不同项目的规划策略
Nick 根据项目类型采用差异化规划方法,而非一刀切的流程。
开源项目的 PRD 专家 Agent
对于开源项目,Nick 使用专门的 PRD 专家 Agent,帮助团队讨论项目需求、定义架构,并产出结构化的 PRD 文档。PRD 模板结构如下:
# PRD: [功能名称] 状态: Draft | Planning | Awaiting Architecture Review | Approved ## 1. Problem [问题描述、目标用户、重要性] ## 2. Design Principles [优化目标、权衡取舍、原因] ## 3. What We're Building [详细需求] ## 4. What We're NOT Building [明确的范围边界] ## 5. Success Criteria [成功衡量标准] ## 6. Open Questions [待解决的疑问,仅 Draft 阶段] ## 7. Milestones [主要里程碑,仅 Planning 阶段] ### M1: [ 名称 ] #### Deliverables - D1.1: [交付物名称] - 关键场景(正向流程 + 已知边界情况) - 验收标准 - 验证方式 ### M2: [ 名称 ]... ## 8. Parallelization [可并行推进的工作流] ## 9. Architecture [架构评审阶段补充]
tracks: - id: A name: [ 轨道名称 ] deliverables: - M1 - D2.1 - id: B name: [ 轨道名称 ] deliverables: - D1.2 - M3
PRD 完成后,Nick 通过命令在 GitHub 创建任务(作为 Issue)。选择 GitHub 的原因很实际:提交 PR 时会自动关联 Issue,代码审核&查验者(人工或 AI)可以基于完整上下文进行审核&查验。
Nick 强调,PRD 讨论阶段投入大量时间,PRD 专家 Agent 的定位是"教练"——提出好问题、挑战既有假设,而非机械执行流程。
遗留系统迁移的团队 Agent
对于遗留系统迁移项目,Nick 组建 Agent 团队并行工作:
- 扫描代码库、映射当前状态
- 识别迁移选项
- 产出草稿级 ADR(架构决策记录)供人工审核
具体任务如:
- "识别代码库中所有 API 端点,进行完整的端到端分析(为优化上下文窗口,每个 API 端点使用独立 subagent)"
- "对比遗留系统与目标系统中现有 API 端点的差异,判断最佳匹配方案或是否需要新建端点"
这类任务的指令需要高度结构化和精确,Nick 倾向于将自身思维过程固化到文档中,而非给 AI 过多自主空间。
代码实现:自主开发工作流
核心流程
Nick 的默认实现方式是一条自主开发工作流:启动 Claude 后,它将完成整个功能实现,目标是产出通过全部检查、经 CodeReview Agent 和 CodeRabbit 审核&查验的 Pull Request。
工作流定义在 docs/workflow.md 中,主要面向 agent 读取,包含状态描述和对应命令。值得注意的是,Nick 混合使用斜杠命令和实际代码,追求最大程度的确定性。
TDD 与防护栏
Claude 遵循 Nick 的 TDD 工作流进行需求实现。项目中设置了多重检查机制:
- pre-commit hooks:禁止提交无法编译或 lint 不通过的代码
- 禁用
--no-verify:Claude 无法绕过这些安全约束
真实代码优于 Markdown 文档
Nick 的一个核心原则是:任何需要确定性执行的流程,必须用真实代码实现,而非依赖 agent 读取 Markdown 文件中的指令。
例如,Nick 编写了创建 GitHub PR、等待检查通过、获取 PR 反馈的自动化脚本。相比写在 prompt 或文档中的流程说明,真实代码具有:
- 确定性:每次执行结果一致
- 可测试性:可以通过单元测试验证行为
Nick 在实践中吃过太多亏——反复要求 agent 遵循流程却总是失败。转向代码化工作流后,可靠性大幅提升。下面的单元测试展示了如何验证工作流步骤的严格顺序:
describe('executeCompleteTask', () => {
it('passes workflow steps in correct order', () => {
executeCompleteTask()
const steps: unknown[] = mockRunWorkflow.mock.calls[0][0]
const stepNames = steps.map((s) => {
const step = s && typeof s === 'object' && 'name' in s ? s : null
return step?.name
})
expect(stepNames).toStrictEqual([
'verify-build',
'code-review',
'submit-pr',
'fetch-pr-feedback',
])
})
// ...
})
持续改进:Lint 规则与架构约束
持续改进是 AI 编程的关键。每次 Agent 生成糟糕的代码,都需要一种机制来确保它今后不再犯同样的错误。最有效的做法是使用确定性工具来强制执行规范。
代码质量规则集
Nick 维护了一套丰富的 Lint 规则,覆盖以下维度:
- 文件大小规则:防止单个文件过度膨胀
- 函数复杂度规则:避免过于复杂的逻辑
- 命名规则:统一代码风格
- 注释规则:确保关键逻辑有适当说明
- 禁止语法规则:例如在 TypeScript 中禁止使用
as和let,强制写出类型安全且不可变的代码
这些规则通过 ESLint 配置实现,详见 GitHub 仓库。
架构分层约束
除了代码风格,Nick 还使用 dependency-cruiser 来强制执行架构规则。典型约束包括:domain 层文件不得依赖 infra 层文件。其 DDD/CQRS 架构定义在 GitHub 仓库 中,目录结构如下:
features/
├── platform/
├── shell/
│ ├── checkout/
│ │ └── domain/
│ └── cli.ts
├── entrypoint/
│ └── tax-calc/
│ └── commands/
└── infra/
├── queries/
├── external-clients/
├── domain/
├── http/
└── infra/
├── cli/
│ ├── mappers/
├── persistence/
└── persistence/
├── config/
└── logging/
└── refunds/
├── entrypoint/
│ ├── commands/
│ ├── queries/
│ └── domain/
功能模块隔离规则
规则 SoC-006 明确了入口层的职责边界:入口层是外部世界与命令/查询之间的薄翻译层,执行"解析外部输入 → 调用命令/查询 → 映射结果到外部响应"这一流程,除此之外不承担其他逻辑。
Pre-commit 钩子和 PR 检查会通过 dependency-cruiser 规则自动拒绝违反架构约束的代码提交。例如,以下规则确保各功能模块(垂直切片)之间相互独立,不得跨模块导入:
{
name: "no-cross-feature-imports",
severity: "error",
comment: "Features must not import from other features",
from: { path: "features/([^/]+)/.+" },
to: { path: "features/([^/]+)/.+" , pathNot: "features/$1/.+" }
}
Nick 指出,Claude Code 在代码放置决策上常常遇到困难,因此严格规则和清晰指引是核心保障。
代码审核&查验
CodeRabbit:AI 驱动的 PR 审核&查验
Nick 在所有项目(个人项目和工作项目)中都使用 CodeRabbit 进行代码审核&查验。其优势不仅在于识别不良代码和安全漏洞,还能配置为读取团队的编码规范和 ADR(架构决策记录)并检测违规。CodeRabbit 还支持学习机制,可以告诉它"下次记住审核&查验这个"或"不要建议那个"。
Nick 也会在创建分支前通过 CLI 运行 CodeRabbit 进行预检。
本地专用审核&查验 Agent
除 CodeRabbit 外,Nick 还配置了多类本地审核&查验 Agent:
- Code Review Agent:代码质量审核&查验
- Architect Review Agent:架构合规性审核&查验
- Test Review Agent:测试覆盖度审核&查验
- QA Check Agent:验证功能是否真正实现了需求
- Bug Check Agent:潜在缺陷检测
工作流强制执行
在部分项目中,Nick 实施了严格的工作流即代码规范:在 PR 创建前,必须完成上述所有审核&查验。具体通过一个 Git 钩子实现——禁止直接执行 git push,而必须使用 /complete-task 命令,该命令会运行完整的验证流水线(Lint → 测试 → 代码审核&查验 → PR 提交)。
{
pattern: /bgits+pushb/,
reason: 'Blocked: Direct git push bypasses required workflow. Use /complete-task command instead, which runs the complete verification pipeline.'
}
工作流脚本会强制要求本地代码审核&查验通过后才能提交 PR:
runWorkflow<CompleteTaskContext>(
[verifyBuild, codeReview, submitPR, fetchPRFeedback],
buildCompleteTaskContext,
(result: WorkflowResult, ctx: CompleteTaskContext) => formatCompleteTaskResult(result, ctx)
)
审核&查验要精确,不要模糊
Nick 总结出一条关键经验:审核&查验描述要精确。不要笼统地说"根据这些原则审核&查验代码",而应明确要求"针对每个修改的文件,逐条对照各审核&查验原则(Nick 为每条原则分配了 CR-001 这样的编号)并写出审计表"。这种精确性避免了 Agent 为了速度而牺牲正确性的倾向。
当然,Nick 本人也会亲自审核&查验代码。对于他来说,未经自己审阅的代码绝不部署到生产环境。核心观点是:PR 收到反馈本身就是流程失败的信号,说明 AI 第一次没有做对。因此,反馈中包含的经验应固化到 Agent 的工具链中,使其在未来自动应用。
测试策略
Nick 在职业生涯中一直推行 TDD,也会引导 Agent 遵循类似流程。核心原则是:
- 先写测试:测试驱动实现
- 用最简单的方案实现:避免过度设计
- 结构化的前置条件定义:状态转换有清晰的边界
TDD 实战技巧与测试规范
RED 阶段:只实现错误信息要求的内容
在 TDD 的 RED 阶段,核心原则是只实现错误信息明确要求的内容,不要猜测或提前添加额外逻辑。
具体检查步骤如下:
- 错误要求什么:错误信息字面上要求什么?
- 硬编码是否可行:yes/no
- 如果可以:使用什么硬编码值?
- 如果不行:为什么必须用真实逻辑?
执行时需严格遵循以下流程:
- 仅实现错误信息要求的内容(尽可能硬编码)
- 不提前解决未来可能的错误
- 执行测试,确认 PASS(绿色条)
- 执行编译检查,确认 SUCCESS
- 执行 lint 检查,确认 PASS
- 将所有成功输出展示给用户
过渡到 GREEN 阶段的前提:测试必须 PASS、代码必须编译通过、lint 必须无错误,三者缺一不可。
测试代码的严格规范
Nick 为测试代码设置了极高的门槛:
- 覆盖率 100%:CI 构建会在覆盖率不足时失败
- 每个测试最多 4 条断言:避免过度测试
- 禁止条件断言:确保测试行为可预测
- 单文件最多 400 行:强制将测试拆分为描述性片段,并使用
it等模式组织
此外,Nick 还部署了一个专注于测试的 code-review agent,实时审核&查验测试质量。
自定义 CLI 工具:快速启动专属角色
Nick 开发了自己的 CLI 启动工具,用于快速启动 Claude Code 会话。
该工具通过 claude --system-prompt 加载特定角色的系统提示,例如执行 claude prd opus 会启动 PRD 专家角色。好处包括:
- 提示嵌入系统提示:提高 AI 遵从度
- 按角色按需加载:PRD 角色仅加载 PRD 相关规则,无需加载测试规则等无关内容
- 效率更高:无需在会话启动后读取额外文件
建议:动手构建自己的工具
AI 时代最大的红利是工具构建门槛极低。Nick 的建议是:
- 思考当前工作中最耗时的环节
- 问自己:什么 CLI 命令、界面或知识管理工具能提升效率?
- 如何自动化那些繁琐的步骤,让自己专注于核心价值?
- 然后让 AI 代理帮你设计并实现这个工具
Nick 自己就构建了一整套项目管理工具,用于规划和交付遗留系统现代化项目——相当于在等待 AI 处理任务时,自己在另一个终端顺手完成了整个功能。


评论