C++ 从10万行hbcore实战总结AI代码3条工程纪律
当 AI 遇上 10 万行 C++ 工程
hbcore 是一个累计超过 10 万行的工业级 C++ 基础库,涵盖网络通信、序列化协议、并发调度、内存管理等核心模块。在过去一年中,我们逐步将 AI 编程助手引入日常开发流程——从最初的好奇尝试,到踩坑、复盘、沉淀,最终形成了一套可复用的工程纪律。本文提炼最核心的 3 条经验,它们不是「能不能用 AI」的泛泛而谈,而是经过大规模代码实战验证的硬约束。
第一条纪律:上下文窗口是战略资源,人工裁剪优先于全量投喂
AI 编程助手的能力边界受制于上下文窗口。10 万行代码显然不可能一次性塞进去,而盲目地「能塞多少塞多少」会导致三个致命问题:
- 注意力稀释:上下文越长,AI 对核心逻辑的把握越弱,生成代码的耦合度和出错率同步上升。
- 幻觉放大:无关代码在上下文中形成噪声,AI 会「虚构」不存在的 API 或依赖关系,尤其在宏展开和模板特化交织的 C++ 代码中尤为严重。
- 反馈延迟:超大上下文导致推理时间倍增,从「即时辅助」退化为「等待编译」,破坏心流。
我们的做法是:人工裁剪,模块隔离。在让 AI 修改某个模块前,只投喂该模块自身的头文件、直接依赖的接口声明,以及一个简短的调用示例。对于跨模块重构,先让 AI 输出影响面分析,再由人工确认后分批执行。效果是生成准确率从初期约 40% 提升到 80% 以上,且每次生成时间从分钟级降至秒级。
第二条纪律:生成 = 草稿,审核才是生产环节的核心工序
AI 生成的代码在语法上越来越接近正确,但在语义上仍存在系统性盲区。尤其在 C++ 这种需要手写资源管理、考虑平台差异(libuv/asio/io_uring)、权衡零拷贝与安全性的语言中,错误不总是编译期可见。我们总结了三类高频问题:
- 生命周期误判:AI 生成的 lambda 捕获了局部引用并在异步回调中使用,导致悬垂引用。这在事件驱动框架中是典型的「编译过,运行崩」。
- RAII 边界破坏:在原始指针和智能指针混用的上下文里,AI 会错误地转移所有权,或在析构顺序敏感的模块中插入看似无害的中间变量。
- 宏展开歧义:hbcore 为跨平台和编译优化定义了大量宏,AI 常将其视为纯文本替换并错误展开,生成不可达分支或条件编译漏洞。
因此,我们将 AI 的输出定位为结构正确、语义待审的草稿。每条生成代码必须经过三步审核:编译通过 → 单元测试覆盖新增路径 → 人工走查关键逻辑(尤其是资源管理路径)。实践证明,这一纪律让 AI 辅助代码的线上故障率与传统手写代码接近。
第三条纪律:测试先行于信任,一次性生成多段代码是反模式
AI 最危险的使用场景是「一次性生成整个模块,然后跑起来看效果」。在 hbcore 中,我们强制要求:
- 先写测试,后让 AI 生成实现:给出明确的接口契约和测试用例(包括正常路径和边界条件),再让 AI 填充实现。这不是把 TDD 套在 AI 上,而是利用测试作为「精确的需求描述语言」——它比自然语言 PRD 的歧义性低一个量级。
- 增量生成,逐段合入:复杂功能必须拆分为不超过 50 行的粒度,每段生成后立即编译、测试、评审,再进入下一段。一次生成 300 行代码的调试时间通常是 3×50 行的 5 倍以上。
- 回滚成本必须为零:每次 AI 生成的内容都要能一键还原。我们将 AI 辅助开发的每个步骤都纳入 git 细粒度提交,确保出问题时不是「改代码」,而是「回滚到确定性状态」。
这条纪律的本质是:将 AI 的不确定性封装在最小的可验证单元内,避免偏差在长链路中累积。
代码示例:一个受约束的 AI 辅助开发流程
以 hbcore 中的ByteBuffer零拷贝切片接口为例,我们在 AI 辅助下遵循了上述三条纪律:
// === 第 1 步:人工提供接口契约与测试(纪律一:裁剪上下文)=== // 只投喂 ByteBuffer 的核心定义和以下契约: class ByteBuffer { public: // 返回从 offset 开始的 length 字节的切片视图 // 约束:共享底层内存,不允许独立释放 ByteBuffer slice(size_t offset, size_t length) const; }; // 测试先行(纪律三:以测试驱动生成) TEST(ByteBufferSliceTest, BasicSlice) { ByteBuffer buf("hello world"); auto s = buf.slice(0, 5); EXPECT_EQ(s.toString(), "hello"); EXPECT_EQ(s.size(), 5); } TEST(ByteBufferSliceTest, OutOfRangeThrows) { ByteBuffer buf("hi"); EXPECT_THROW(buf.slice(0, 10), std::out_of_range); } TEST(ByteBufferSliceTest, SliceSharesMemory) { ByteBuffer buf("test"); auto s = buf.slice(1, 2); // 修改原 buf 不应影响切片内容 buf.clear(); EXPECT_EQ(s.toString(), "es"); }然后将这段测试和接口声明投喂给 AI,让其生成实现。生成后立即编译运行测试(纪律二:审核为核心工序),人工走查 shared_ptr 引用计数和越界检查逻辑,确认无误后提交。
反思:纪律不是束缚,是让 AI 可信的杠杆
回顾近一年的实践,我们从「AI 能写多少代码」的热情,转向了「AI 写的代码有多少能安全上线」的冷静评估。三条纪律——人工裁剪上下文、审核即生产工序、测试先行与增量合入——本质上是在 AI 的高产出速度与 C++ 工程的高可靠性要求之间建立了一道防火墙。
如果你的项目也达到了数万行规模,希望这些经验能帮你少踩一些坑。AI 是放大器:它能放大一个优秀工程师的生产力,也能放大一个松懈流程的缺陷。纪律,就是那个决定放大方向的控制变量。
