商业产业 Hacker News AI 2026-09-20T11:37 正文 ok 1196 words

🔶 如果 AI 编程正在拉低代码质量,问题在于你没有管理好质量

英文标题:🔶 If AI coding is lowering your code quality, you're not managing quality right

作者认为,AI 编程代理确实能将产出提升至原来的 2—3 倍,但前提是不能盲目合并 PR 并直接上线,而要建立多层质量防线。通过规格驱动开发、AI 审查需求与技术设计、正确实施 TDD、人工测试、E2E 测试及多轮代码审查,团队不仅能控制缺陷数量,甚至可能减少缺陷。作者指出,AI 很适合承担测试覆盖、专项检查、PR 审查和生产故障诊断等工作,但复杂变更仍需要人类审查和手动验证。对开发团队而言,AI 的关键价值不只是更快写代码,更在于以更低成本增加测试、审查与线上监控的深度。
打开原文相关 3 · 机会 0
media423 B media1.4 KB media41.0 KB

中文

我经常看到一种关于编程代理的观点,大致是这样的:“当然,AI 能帮你产出更多代码,但代码质量不会下降吗?”

如果你只是盲目合并 PR,然后把它们直接发往生产环境,质量当然会下降。但如果你采取周到、分层的质量管理方法,我发现不仅可以让 bug 数量保持稳定,实际上还能减少 bug——同时依然将产出提高到原来的 2—2 倍。

其中许多防御层与 Claude/Copilot/Codex 等工具出现之前并没有本质区别(尽管 AI 让它们更容易实施),另一些则是新的做法。以下是一套我见过在实践中成功使用的防御体系,包括我所在的团队以及其他团队。

在我开始采用规格驱动开发后,最令人意外的收获之一,是新写代码中的 bug 显著减少。采用规格驱动开发之前,例如在开发一个新功能时,我所在的团队经常要将总工作量多达三分之一投入开发后的“打磨”阶段,也就是发现并修复各种 bug。许多 bug 的出现,要么是因为我们没有预见到某些交互和边界情况,要么是因为开发者当天太疲惫、没有投入足够思考,要么是设计师或 PM 没有把某些场景考虑周全。其中一部分 bug 会被遗漏,最终进入生产环境。

在我开始采用规格驱动开发后,我代码中的这类 bug 数量大幅下降;我也在一些(但不是所有)队友身上看到了同样的下降。就我所知,这种下降的主要原因是流程中的一个特定步骤:让 AI 审查需求或技术设计,并找出其中的缺口、边界情况、与现有代码的意外交互,或其他类似问题。

AI 不会疲倦,而且在提示得当时,它放弃寻找潜在问题的概率要低得多。如果说有什么问题,那就是它有时可能过于积极;我必须仔细审查它对需求提出的修改建议,以确保它没有凭空制造实际上并不存在的问题。

如今,编程代理让测试驱动开发(TDD)变得轻而易举,几乎没有理由不采用它。不过,必须以正确的方式实施:你不希望代理为它刚刚在代码中引入的任何 bug,盲目编写能够通过的测试。因此,我见过的最佳规划与实现方法通常遵循以下模式:

  • 指示代理基于需求,充分思考测试场景和测试用例;

  • 编写测试用例;

  • 编写实现;

  • 根据测试用例测试实现,并修复发现的所有问题;

  • 也许再补齐剩余的覆盖率缺口——但同样要始终牢记需求。

此外,既然测试由代理来写,就没有理由不追求接近全量的覆盖率,也没有理由拖延补齐缺失的单元测试。

不过,仍然无法替代由人类(你、QA、PM 或其他人)亲自试用功能、走遍所有边界情况,并确认一切是否按预期工作,还是需要进行修改。

这些人工测试可能需要不少时间,尤其是在测试场景本身需要花精力搭建时。这是目前生产率提升仍较为有限的步骤之一,也是我的产出只提高到原来的 2—3 倍、而不是 10 倍左右的主要原因。尽管现在想来,我可能错过了一些可以自动化的机会。

端到端(E2E)测试可以说是代码库中最重要的测试,因为它们验证了新增改动是否破坏了终端用户实际体验到的既有功能。理想情况下,它们应当在 PR 上运行、在测试/预发布环境中运行,并在每次部署后于生产环境中运行。理想情况下,它们也应由编写常规代码的同一批开发者维护,但我理解有些组织的架构并不支持这样做。

AI 的确能让编写 E2E 测试变得更容易,但要有效做到这一点,它需要访问能够帮助其调试测试失败的工具或 MCP 服务器——例如浏览器工具,或者日志的 MCP 访问权限。不过,重要的是要记住:E2E 测试不能替代人工测试,因为它们只是对“没有重要功能被破坏”的一种粗略且不完整的检查。

我发现,编程代理不太擅长遵循 AGENTS.md 或 CLAUDE.md 中的复杂指令。但如果你增加一个独立的步骤,专门查找并修复特定问题,它们的表现会相当不错。这些问题可以包括:

  • 安全问题;

  • 查找过度复杂或重复的代码;

  • 是否符合命名、文件组织或格式规则;

  • 进行一次通用代码审查,寻找逻辑上的任何问题;

  • 用 AI 腔写成、过于冗长的注释,而不是正常英文;

  • 任何其他你希望发现并修复的特定问题。

如果将这些步骤加入规划或实现技能中,它们几乎可以算是“免费”的补充:实现时间可能只增加 5—15 分钟,而且无需额外关注。

如果你希望在应用修复之前先查看评论,也可以将它们加入 PR 审查流程。

我想,我正越来越相信:对于小改动和简单的 bug 修复,人类审查可以变为可选项——前提是其他防御层依然到位。

但对于复杂改动,我发现审查 AI 编写的代码仍然是必要的。我仍会经常发现宏观层面的错误、遗漏的与其他功能的不利交互、过度复杂或并非最优的实现,以及其他问题。更不用说诸如用“mint”代替“generate”,或用“stamp”代替“set”这样的奇怪措辞。

AI 代码审查也是非常出色的补充。在我目前的团队中,我们会同时对 PR 运行 Claude 和 Cursor 审查;令人意外的是,它们各自会发现不同的问题。你还可以从不同角度加入其他自定义审查,例如安全性、效率、与其他代码库的交互等等。不过要注意,AI 在审查中可能过于吹毛求疵,因此还应有一个步骤,让另一个代理剔除那些实际上没有意义的 AI 生成 PR 评论。

代码进入生产环境后,至少应当有人定期浏览日志,或查看 Fullstory 等工具中的用户录屏,或者审查追踪错误率、延迟及其他问题的各类仪表盘。

更好的做法是使用 Sentry 或 GCP Error Reporting 这类错误追踪服务,来检测错误并进行去重。

不过,最佳做法是进一步让 Claude/Cursor 或其他工具自动诊断这些错误、找出根本原因,并创建包含建议修复方案的 PR。

我确信自己遗漏了维持高质量的其他重要组成部分,但核心观点是:只要具备正确的一组防御层,产出增加不必以可靠性为代价。恰恰相反,编程代理如今让我们能够以比过去更低的成本增加更多、更深入的检查:更多测试、更多审查轮次,以及更快诊断生产环境问题。

因此,如果你对质量投入足够的关注,我认为完全有可能在控制 bug 的同时,将交付速度提高一倍。甚至可能进一步减少 bug。

English / 原文

One common take on the coding agents that I see goes something like this: “Sure, AI helps you output more code, but won’t the quality suffer?”

It certainly will if you just blindly merge the PRs and send them off to prod. But if you take a thoughtful, layered approach to managing quality, I find that it’s possible to not just keep the number of bugs stable but actually reduce it—while still increasing the output by 2-2x.

Many of these defensive layers are pretty much the same as before Claude/Copilot/Codex/etc. (though they’re made easier now by AI), while others are new. Here’s a defensive setup that I’ve seen successfully used in practice, both on my team and elsewhere.

One of the biggest surprises after I started using spec-driven development was the drop in bugs in the freshly written code. Before spec-driven development, when building, e.g., a new feature, the teams I was on often spent up to a third of the total effort on the post-development “polishing,” i.e., discovering and fixing various bugs. Many of these bugs occurred either because we didn’t foresee certain interactions and edge cases, or because the developer was tired that day and didn’t put in enough thought, or because the designer or PM didn’t think through certain scenarios. Some of these bugs were missed and ended up in production.

After I started using spec-driven development, the number of these bugs in my code sharply dropped, and I’ve seen the same drop for some (but not all) of my teammates. As far as I can tell, the main cause of this drop is one specific step in the process: having the AI review the requirements or the tech design and find any gaps, edge cases, unexpected interactions with the existing code, or other similar problems.

The AI doesn’t get tired and, when prompted right, is a lot less likely to give up hunting for potential issues. If anything, it can sometimes be overzealous, and I have to carefully review its proposed edits to the requirements to make sure that it doesn’t invent any issues that aren’t there.

Coding agents now make test-driven development (TDD) trivial to the point where there’s no reason not to do it. However, it needs to be done right: you don’t want the agent to blindly write passing tests for any bugs it just added to the code. So the best planning and implementation skills I’ve seen usually follow this pattern:

  • Instruct the agent to think through the test scenarios and test cases based on the requirements,

  • Write the test cases,

  • Write the implementation,

  • Test the implementation against the test cases and fix any issues that come up,

  • Maybe backfill any remaining coverage gaps—but again, keeping the requirements in mind.

Also, with the agents writing the tests, there’s no excuse not to shoot for near-universal coverage or to wait on backfilling any missing unit tests.

There’s still no substitute for a human (you, QA, PM, or someone else) actually trying out the feature, going through all the edge cases, and seeing whether everything works as expected or whether you need to make changes.

These manual tests can take a while, especially if the test scenarios take some effort to set up. This is one of the steps that so far has seen only modest gains in productivity, and it’s the main reason that my output has increased only 2-3x instead of something like 10x. Though now that I think about it, there may be a few opportunities for automation here that I’ve missed.

End-to-end (E2E) tests are arguably the most important tests in the codebase because they verify that new changes haven’t broken any existing functionality as experienced by the end user. Ideally, they’d run on the PRs, in the test/stage environments, and in production after every deployment. Ideally, they’d also be maintained by the same developers who write regular code, but I understand that some organizations aren’t really set up for that.

AI does make it easier to write E2E tests, but to do that effectively, it needs access to the tools or MCP servers that let it debug test failures—e.g., a browser tool or MCP access to the logs. However, it’s important to keep in mind that E2E tests aren’t a substitute for manual testing because they’re just a rough, incomplete check that nothing important broke.

I find that coding agents aren’t great at following complex instructions in AGENTS.md or CLAUDE.md. But they do pretty well if you add a separate pass to find and fix specific issues. These can be:

  • Security issues,

  • Finding overcomplicated or duplicated code,

  • Compliance with naming, file organization, or formatting rules,

  • A general code review pass to find any issues with the logic,

  • Overly long comments written in AI-ese instead of regular English,

  • Any other specific things that you’d like to find and fix.

If added to the planning or implementation skills, these can be pretty much “free” additions, adding maybe 5-15 min to the implementation time with no additional attention required.

They can be also added to the PR reviews if you prefer to take a look at the comments before applying any fixes.

I think I’m becoming convinced that for minor tweaks and simple bug fixes, human reviews can become optional. Provided that other defensive layers are still in place.

But for complex changes, I find that it’s still necessary to review AI-written code. I still regularly find big-picture mistakes, missed adverse interactions with other features, overcomplicated or suboptimal implementations, and other problems. Not to mention weird word choices like “mint” instead of “generate” or “stamp” instead of “set.”

AI code reviews have also been a really great addition. On my current team, we run both Claude and Cursor reviews on the PRs, and surprisingly, each of them finds different problems. You can also add other custom reviews from various angles, like security, efficiency, interactions with other repos, and so on, though be aware that AI can be overly nitpicky in its reviews, so it’s important to also have a pass where another agent prunes the proposed AI-generated PR comments that aren’t actually meaningful.

Once the code is in production, at a minimum, it’s good to have someone periodically scroll through the logs or watch any user recordings in something like Fullstory, or review various dashboards that track error rates, latencies, and other issues.

Even better would be an error tracking service like Sentry or GCP’s Error Reporting that detects and deduplicates errors.

The best approach, however, would be to then have Claude/Cursor/whatever auto-diagnose these errors, figure out the root cause, and make PRs with the proposed fix.

I’m sure I’ve missed other important components of maintaining high quality, but the main idea is that with the right set of defensive layers, the increased output doesn’t have to come at the cost of reliability. If anything, coding agents now make it cheaper to add more and deeper checks than before: more tests, more review passes, faster diagnosis of production issues.

So if you’re sufficiently focused on quality, I think it’s entirely possible to double the delivery speed while keeping the bugs under control. Or maybe even reducing them.