你怎么知道软件在工作?
I’m happy to translate the article for you, but I need the full text of the post. Could you please paste the content you’d like translated (excluding the source line you already provided)? Once I have the article text, I’ll translate it into Simplified Chinese while preserving the original formatting, markdown, and any code blocks or URLs.
我们将覆盖的内容
- 思维模式 – 你将承担的多种角色:产品设计师、项目经理、技术负责人和质量保证工程师。
- 头脑风暴 – 将功能想法转化为具体规范。
- 管理编码代理 – 如何强制执行规则、规则为何重要,以及如何让代理保持正轨。
- 发布 – 自信地将 AI 生成的代码部署到生产环境(是的,我们会在生产中进行一些“氛围编码”)。
顺序可能会有所变化。系好安全带!
回顾
在上一篇文章中,我们展示了如何让 Claude 遵守约定(简而言之 – skills + hooks 能解决这个问题)。Claude 现在遵循规则了,但……
Marcin,所有任务都已完成。
我打开浏览器看到:
NoMethodError: undefined method 'hallucinated_method' for an instance of User (NoMethodError)
“干得好,Claude!击个掌…我们准备上线到生产环境… 不。”
这就提出了一个根本性的问题:
你怎么知道软件真的在正常工作?
真实案例 (2017)
- Company: Paladin Software
- Task: 处理巨大的 YouTube 收益 CSV 文件(千兆字节级别)。
- Context: 我是值班工程师,负责确保及时、可靠的处理。
一个美好的星期四下午,我在克拉科夫我最喜欢的地点——Dolnych Młynów。星期五是休息日。客户在星期五上传了他们的电子表格;当我星期一回来时,收益仍未被处理。
查看 Sidekiq 的失败作业队列:
NoMethodError: undefined method 'hallucinated_method' for an instance of User (NoMethodError)
我在大语言模型流行之前就是它吗?我肯定像它一样在交付代码。
为什么大型语言模型需要严格的防护措施
- 前向性失忆症: LLM 在会话开始后无法形成新记忆。它们记得训练数据,但 新经历不会留下。
- 非确定性: AI 代理在一次运行中可能生成出色的代码,而在下一次运行中却产生错误的代码。
因此我们必须在模型每次编写代码时提供 严格的规则(参见之前关于强制规则的帖子) 并 添加 检查和审查。
工作流中的确定性检查
以下是我对 本地 CI 应该包含内容的看法:
| 工具 | 目的 | 推荐标志 |
|---|---|---|
| Rubocop | 静态代码分析器和代码检查器(开启自动修复) | bundle exec rubocop -A |
| Prettier | ERB、CSS、JS 的格式化工具 | yarn prettier --config .prettierrc.json app/packs app/components --write |
| Brakeman | 安全漏洞静态分析 | bundle exec brakeman --quiet --no-pager --except=EOLRails |
| RSpec | 测试框架(使用你喜欢的) | bundle exec parallel_rspec --serialize-stdout --combine-stderr |
| SimpleCov | 覆盖率报告(由 RSpec 使用) | – |
| Undercover | 警告未测试的变更代码(使用 git 差异、代码结构、SimpleCov) | bundle exec undercover --lcov coverage/lcov/app.lcov --compare origin/master |
这为我们带来的好处
- 统一的代码风格 – 一致的格式化。
- 安全性 – 早期标记已知漏洞。
- 测试覆盖率 – 对新代码和变更代码进行测试。
- 无运行时错误 – 失败在 CI 中显现,而不是在生产环境。
“有多少次 AI 代理告诉你测试失败与其更改无关?”
模板代码的担忧?
没有。单元测试运行快速,配合编码代理后,它们变得比以往更易维护。可靠性收益远远超过少量的模板代码。
示例 CI 输出
Continuous Integration
Running checks...
Rubocop
bundle exec rubocop -A
✅ Rubocop passed in 1.98s
Prettier
yarn prettier --config .prettierrc.json app/packs app/components --write
✅ Prettier passed in 1.57s
Brakeman
bundle exec brakeman --quiet --no-pager --except=EOLRails
✅ Brakeman passed in 8.76s
RSpec
bundle exec parallel_rspec --serialize-stdout --combine-stderr
✅ RSpec passed in 1m32.45s
Undercover
bundle exec undercover --lcov coverage/lcov/app.lcov --compare origin/master
✅ Undercover passed in 0.94s
✅ Continuous Integration passed in 1m45.70s
如果你使用 Rails 8.1+,大多数检查已经内置在框架中。对于 Rails 8.0 及更早版本,你可以使用我的 移植实现,或自行实现。
我的早期职业经验(2014)
- 职位: Netguru 的初级 Rails 开发者。
- 入职培训: “The Netguru way” — 特定的库和模式。
- 反馈: 我的模型“臃肿”。我被指向 Code Climate 的文章 “7 Ways to Decompose Fat ActiveRecord Models.”
我听到了这些规则,但当时太专注于业务逻辑,未能付诸实践。
“The CLAUDE.md says ‘ALWAYS STOP and ask for clarification rather than making assumptions,’ and I violated that repeatedly. I got caught up in the momentum of the Rails 8 upgrade and stopped being careful.”
这并不是软件行业的新问题。解决办法?代码审查。 每个 pull request 必须由另一位开发者审查,为经验不足的开发者提供安全网,并确保整体质量更高。
…
(本文将在下一篇继续。)
三阶段审查流程
目标:
- 教授良好实践。
- 让有经验的开发者能够指导他人并传承知识。
- 强制执行规则,使所有人受益。
记住: 永远不要让开发者审查自己的代码。对 AI 代理同样适用。
为什么采用三阶段审查?
- 规格符合性 – 验证实现是否完全符合功能规格(既不多也不少)。
- Rails 与项目特定约定 – 加载所有约定(参见前一篇文章)并检查它们:
- 接口是否简洁?
- 是否使用视图组件而非局部模板?
- 作业是否幂等且简洁?
- 测试是否验证行为?
- 通用代码质量审查 – 评估架构、设计、文档、标准和可维护性。
每个阶段由不同的审查者执行,拥有全新的视角且不对该功能产生情感依赖,从而对实现及可能的偏差提供全面的概览。
示例完整报告
1. 规格符合性 – 逐行验证
| 需求 | 实现 | 状态 |
|---|---|---|
列:delay_peer_reviews | :delay_peer_reviews | ✅ 匹配 |
2. Rails 约定 – 检查清单
| 约定 | 状态 |
|---|---|
| 可逆迁移 | PASS |
| 处理已有数据 | PASS |
3. 代码质量 – 结构化报告
- 优势
- 关键 / 重要 / 次要问题(附引用)
- 合并评估
最终汇总表
| 检查项 | 状态 |
|---|---|
| ✅ 规格符合性 | Passed |
| ✅ Rails 约定 | Passed |
| ✅ 代码质量 | Approved with minor suggestions |
| ✅ 本地 CI | Passed |
准备合并。
发现问题时
审查会将问题汇总为一个可操作的列表,便于作者在最终合并前逐项处理。