30天内用 Claude Code 构建生产级 AI 平台:真实故事
那是周二凌晨两点,我意识到计费系统正在向用户收取双倍费用。这个 bug 已经在生产环境中运行了六个小时。那天下午,Claude Code 生成了支付对账逻辑,我审阅了它,测试了它,然后发布了它。代码看起来很完美。它通过了每一项测试。但它从根本上就是错的。
这就是构建 LemonData 的故事——274 个 API 路由,46 个数据库模型,100,000 多行代码——全部使用 AI 编程助手完成。这不是那种被粉饰过的“看 AI 让你变得多么高效”的故事。这是一个真实的故事,充满了失败、凌晨三点的调试环节,以及我质疑 AI 辅助开发是否真的是个好主意的时刻。
愿景 vs. AI 辅助开发的现实
AI 编程助手的愿景非常诱人:你描述你想要的,AI 编写代码,你审阅并发布。理论上,一名开发者现在可以完成整个团队的工作。
而在实践中?前两周的感觉非常棒。Claude Code 理解我的代码库,生成完整的功能,跨文件进行重构。我发布代码的速度比我职业生涯中的任何时候都要快。如此迅速地关闭 issue 带来的多巴胺冲击让人陶醉。
然后裂痕开始显现。
同一个函数出现在三个不同的文件中,实现方式略有不同。配置值被硬编码在随机的地方。不同包之间的类型定义相互矛盾。代码库增长很快,但也变成了一个“能运行但我不确定为什么”的代码迷宫。
至于那个计费 bug?Claude 生成了一个看起来非常合理的对账函数。但它没有考虑到我们异步支付确认流程中的竞态条件(race condition)。AI 无法知道那个边缘情况,因为我没有明确告诉它,而且测试套件(部分也是由 AI 生成的)也没有覆盖到它。
不断导致崩溃的七种模式
在使用 Claude Code 构建一个月后,我开始记录一份清单。不完全是 bug 清单,而是模式清单。同样类型的失败不断发生,这不全是 Claude 的错——或者至少不完全是。它们是 AI 优化“现在的可用代码”而非“未来的可用代码”所带来的必然结果。
1. 一致性问题
Claude 会根据它正在处理的文件、它最近看到的示例,或者似乎只是随机的变化,以不同的方式实现相同的逻辑。一个 API 端点会返回 { data: users },另一个则返回 { users }。两者都能运行,但互不匹配。调试变成了考古。
2. 复制粘贴问题
当复制代码更快且没有破坏现有功能的风险时,AI 为什么要创建一个共享工具呢?每当我要求一个与现有功能类似的新功能时,我都会得到一个新的实现,而不是重构后的共享解决方案。三周后,我的代码库中散布着五个不同的“格式化货币”函数。
3. 类型漂移问题
一个新的状态值会被添加到一个文件中,但没有添加到 enum 定义中。一个字段在 API 响应中是可选的,但在前端类型中是必需的。TypeScript 捕捉到了其中的一些问题,但没有捕捉到语义不匹配——即类型在技术上正确但在逻辑上不一致的情况。
4. 配置分散问题
数据库 URL、API key、功能标志、速率限制——Claude 会把它们放在对当前任务方便的任何地方。有时在环境变量中,有时在配置文件中,有时是硬编码。寻找定义某个值的所有地方变成了一场寻宝游戏。
5. 测试覆盖幻觉
AI 生成的测试往往会彻底测试正常路径(happy path),而完全忽略边缘情况。计费 bug 就是一个完美的例子:测试套件完美地覆盖了正常的支付流程。它从未测试过当两个支付确认在同一毫秒内到达时会发生什么。
6. 静默失败问题
Claude 会添加 catch (error) { console.log(error) } 块来吞掉异常。在开发中,这看起来没问题——错误出现在控制台中。在生产环境中,关键故障被静默记录后就被遗忘了。
7. 文档缺口
Claude 能写出出色的代码注释。但它写的架构文档很糟糕。它可以解释一个函数的作用,但无法解释系统为什么要这样构建,或者是什么约束导致了特定的设计决策。
CLAUDE.md 解决方案
转折点出现在第三周,当时我创建了 CLAUDE.md——一个位于项目根目录的文件,包含 Claude 需要知道的每一个约定、约束和架构决策。
这不是给人类看的文档。这是给 AI 看的文档。
## API 响应格式
始终使用:{ success: true, data: T } 或 { success: false, error: string }
严禁返回不带包装的原始数据。
## 货币
内部存储:USD。显示:formatCurrency(amount, currency, rate)。
严禁硬编码汇率。严禁直接存储 CNY。
## 错误处理
严禁使用 catch(e) { console.log(e) }。
始终使用 logger:logger.error('context', { error })。
效果立竿见影。Claude 开始一致地遵守约定。当它生成的代码违反规则时,我可以指向 CLAUDE.md 中的特定行,它就会自我修正。
但仅有 CLAUDE.md 是不够的。我需要自动化的强制执行。
构建安全网:AI 生成代码的 CI 门禁
我们构建了一个 CI 流水线,其中的门禁在传统代码库中可能显得过于偏执——因为它们的存在是为了在用户发现之前捕捉 AI 生成的 bug:
- 全 monorepo 类型检查(捕捉类型漂移)
- SSOT 审计,验证是否存在重复实现
- Enum 同步检查,确保数据库枚举与 TypeScript 枚举匹配
- API 响应格式验证(解决一致性问题)
- 安全门禁,针对计费、权限和身份验证代码
核心见解:Claude 是放大器,而不是替代品。它放大了你的生产力,但也放大了你的错误。如果你没有强大的约定,Claude 就会发明它自己的约定——而且它们不会是一致的。如果你没有自动化检查,Claude 的 bug 就会比人类的 bug 更快地到达生产环境。
计费 bug 不再可能发生了。不是因为 Claude 变聪明了,而是因为流水线现在要求显式处理异步竞态条件,并由检查支付流程中正确锁机制的门禁进行验证。
“AI 原生开发”的真正含义
当我称 LemonData 为“AI 原生基础设施”时,我并不是指我们在现有产品中添加了 AI 功能。我的意思是,整个开发过程都是由与 AI 编程伙伴合作的现实所塑造的。
我们的文档比通常情况下更详细——因为 Claude 需要人类队友可能推断出的显式上下文。我们的类型系统比必要的更严格——因为 Claude 会利用任何歧义。我们的 CI 流水线拥有在传统代码库中显得偏执的门禁——因为它们的存在是为了在用户发现之前捕捉 AI 生成的 bug。
结果是,这个代码库实际上比我处理过的大多数代码库更易于维护。不是因为 AI 写出的代码比人类好,而是因为为 AI 辅助开发而构建迫使我将通常只存在于资深开发者脑海中的所有约定和检查都显式化了。
关于 AI 原生作为一种哲学的更多信息,请参阅 什么是 AI 原生?
给使用 AI 编程助手开发的开发者的建议
如果你正准备使用 Claude Code、Cursor 或任何 AI 编程助手开始一个项目:
- 第一天就创建你的 CLAUDE.md——不要像我一样等到第三周
- 自动化约定强制执行——不要依赖 AI 记住规则
- 像审阅初级开发者的代码一样审阅 AI 代码——它速度快、能力强,但缺乏上下文
- 手动测试边缘情况——AI 生成的测试覆盖正常路径,而不是竞态条件
- 从一开始就集中化配置——分散问题会迅速恶化
- 使用严格的 TypeScript——这是你对抗类型漂移的最佳防线
- 尽早构建 CI 门禁——它们在第一周内就能回本
我还会再做一次吗?
绝对会。但我会在第一天就开始使用 CLAUDE.md,而不是第三周。我会记住,10 倍的生产力乘数也意味着错误后果的 10 倍乘数。
我们构建的平台——300 多个 AI 模型、统一的 API、多货币计费、13 种语言的国际化——如果由传统团队来做,可能需要数月时间。我们用 30 天就发布了。Bug 是真实的,但速度也是真实的。
AI 辅助开发不是魔法。它是一种新型的工程学科。和所有学科一样,它奖励那些尊重其约束的人。
常见问题
一名开发者真的能用 Claude Code 构建生产级平台吗?
可以,但有前提条件。AI 以惊人的速度处理代码生成和重构,但你仍然需要强大的架构判断力、自动化的质量门禁,以及仔细审阅一切的纪律。如果你不小心,10 倍的速度也意味着 bug 产生的速度快 10 倍。
什么是 CLAUDE.md?
CLAUDE.md 是一个项目级指令文件,AI 编程助手通过读取它来获取上下文。它包含 AI 应该遵循的编码约定、架构决策和约束。可以把它看作是你 AI 队友的入职文档。
如何防止生产环境中出现 AI 生成的 bug?
自动化的 CI 门禁至关重要:类型检查、SSOT 审计、枚举同步验证以及特定领域的安全门禁。核心见解是 AI 放大了生产力和错误——你需要自动化检查来捕捉被放大的错误。
AI 辅助开发适用于计费和支付系统吗?
适用,但要格外小心。支付代码需要显式的竞态条件处理、正确的锁机制和彻底的边缘情况测试。AI 生成的测试往往覆盖正常路径——你必须手动测试失败场景和并发操作。
LemonData 让您通过单个 API 访问 300 多个 AI 模型。我们用 AI 构建它,为 AI 服务。免费开始使用——新用户可获得 $1 额度。