AI 写 Demo 很快,返工也是真的快

最近拿 AI 起一个 C++ 小项目,最容易傻眼的时刻,不是它写不出来,而是它三分钟给你拼出一套像模像样的目录树,顺手再塞几个三方库,Demo 还真能跑。问题也在这。你连新引进来的库到底支持什么、编译链路怎么走、边界在哪,都还没摸清,后面返工基本跑不掉。

我现在越来越觉得,AI 编程最怕的不是模型笨,而是起手太贪。尤其是 C++ 这种没什么脚手架兜底的语言,你前面少想一步,后面就得在编译、链接、库版本、目录结构上多还几步。

这事我自己的结论很直接,AI 更适合当一个推进很快的结对程序员,不适合一上来就替你把前期设计和依赖决策全包了。GitHub 的文档建议一开始先给简单一点的任务,先让 agent 把 bug、文档、测试、技术债这种边界更清楚的活干明白;Anthropic 的 Plan Mode 文档则更像是给复杂改动上的保险,先读代码、先出计划,再决定改不改。两边说法不完全一样,但指向差不多,别一上来就把最难、最乱、依赖最多的那一坨全扔给 AI。

所以这篇不聊一大堆规范,就给一个能直接练手的小案例。你拿任意一个空 C++ 仓库都能照着来。

不是 AI 不行,是起手太贪

人工写项目,尤其是 C++,很多时候就是很土的办法。

  • 先从 main.cpp 起一个最小可运行版本
  • 先把编译链路跑通
  • 再决定引什么库
  • 每加一步都保证还能编
  • 等业务轮廓出来了,再开始重构

这套办法看起来慢,其实很稳。因为每一步你都知道自己到底换来了什么,也知道问题是从哪一步长出来的。

AI 容易把这套节奏打乱。它很喜欢一步到位地“帮你完整一下”:

  • 配置文件顺手给你上了
  • 日志模块顺手给你抽了
  • 错误码、工具类、目录结构顺手一起整理了
  • 三方库的接入方式,它也替你选了

结果就是,Demo 看起来完整了,你的心智模型却是空的。后面只要有一个库的能力边界和你想的不一样,返工就不是一处,而是一串。

先拿一个小项目练手

我觉得很适合练手的,是做一个很小的日志扫描工具,名字随便起,比如 logscan

它只做一件事:扫一个目录下的日志文件,统计 errorwarn 的数量,然后把结果打印出来。这个题目不大,但正好够你把 C++ 小项目里最常见的几块都走一遍:

  • main 和参数入口
  • 输出格式化
  • 日志
  • 配置文件
  • 业务模块拆分

关键不是题目多高级,关键是拆法。

我会把它拆成四步,而且每一步只允许 AI 做当前这一小步。

第一步,先把输出做好

第一步别碰日志,别碰配置,别想着抽象。

就做两件事:

  • 建一个最小 main.cpp
  • 引入 fmt,把扫描目录和统计结果打印出来

fmt 官方文档给了很清楚的 CMake 用法,它有 fmt::fmtfmt::fmt-header-only 两个 target,文档还明确更推荐编译版,理由也很朴素,编译时间更友好。CMake 的 FetchContent 文档也很适合新项目起步,因为它是在 configure 阶段把依赖拉进来,不是 build 阶段才临时下载。

这一步我会直接把依赖策略定死,不让 AI 自由发挥。

  • 要么统一 FetchContent
  • 要么统一 find_package
  • 不要一会 vcpkg,一会 add_subdirectory,一会再手拷头文件

如果是练手项目,我一般会这么约束 AI:

不要一次性优化架构。
当前目标只有这一步,而且项目必须始终可编译。

这一步只做 3 件事:
1. 在根 CMakeLists.txt 里引入 fmt
2. main.cpp 用 fmt 打印传入目录和扫描结果
3. 保持现有目标名和目录结构,不新增日志、配置、测试框架

先给我修改清单,再给代码。
完成后给出编译命令和预期输出。

这里有个细节挺重要。AI 一旦没被约束,它很容易把“顺手把后面也做了”当成加分项。你得明确告诉它,这一轮不准越界。

第二步,再上日志

等第一步能编、能跑、输出也顺眼了,再加 spdlog

spdlog 官方 README 其实已经把它能干什么写得很直白了。它既能做控制台日志,也能做普通文件、滚动文件、按天切分,甚至还有 backtrace ring buffer。问题就在这。能力一多,AI 就容易兴奋,恨不得第一版把彩色控制台、滚动日志、按天归档、全局 logger factory 一把梭。

没必要。

这一步我只会让它做控制台日志,或者最多加一个最简单的文件日志。因为你这时候真正要学的,不是“怎么把日志系统设计完整”,而是三件事:

  • 日志初始化放哪
  • 业务里怎么拿到 logger
  • 出错时日志和正常输出怎么分工

如果你一上来就上 rotating_file_sinkdaily_file_sink,你虽然很快拥有了一套“功能很全”的日志模块,但你其实还不知道自己到底需不需要轮转、按天切分,还是只要调试阶段打印到终端就够了。

说白了,先把 spdlog::info() 用明白,比先把日志工厂画漂亮更重要。

第三步,才碰配置文件

配置文件这块更容易被 AI 搞成大工程。

我更偏向拿 toml++ 这种简单一点的库来练手,不是因为它“最强”,而是因为它很适合新项目前几步。它本身就是 C++17 的 header-only TOML parser,README 里给的例子也很短,toml::parse_file("configuration.toml") 就能直接读。更关键的是,它单头文件模式真的很省事,官方原话都挺有意思,single-header 方案就是“把 toml.hpp 扔进源码树里”,然后“没有第二步了”。

这一步别做“配置中心”,就读三个字段:

  • 扫描目录
  • 关键字列表
  • 输出是否写文件

然后把它们塞进一个很薄的 AppConfig 结构体里。

就够了。

很多返工,其实就出在这里。你自己还没想清楚配置到底是启动时读一次,还是运行时热更新;是只给本地 CLI 用,还是以后还要给服务进程复用。AI 已经提前替你抽了五六层。后面你一改方向,之前那点“完整设计”就都成了包袱。

第四步,再拆业务模块

fmtspdlogtoml++ 都是你自己看过一遍官方说明,也都实际跑通过了,再让 AI 帮你拆模块。

这时候拆,心里才有数。

我一般会收成这么几个文件:

  • main.cpp 只负责组装
  • app_config.{h,cpp} 只负责配置读取
  • logger.{h,cpp} 只负责日志初始化
  • log_scanner.{h,cpp} 放业务逻辑

注意,是到这一步才拆,不是第一步就拆。第一步就把目录排得整整齐齐,很多时候只是视觉上舒服,认知上并没有更清楚。

真正有用的,不是什么复杂规范

网上很多 AI 编程规范写得很复杂,十几条、几十条,看着就累。我自己现在留下来的,其实就三条,够用了。

第一条,先做一张“引库卡”。

每次准备引三方库,我先让 AI 只回答这四个问题:

  • 这个库解决什么问题
  • 官方已经支持到哪
  • 我这次只准备先用哪 1 到 2 个能力
  • 它会给构建、部署、运行带来什么新约束

如果这张卡说不明白,就先别接。

第二条,一次只让 AI 过一个检查点。

比如这一轮只允许它完成:

  • 能编过
  • 能运行
  • 能看到预期输出

别在同一轮里再加“顺手重构一下目录”“顺手补个配置类”“顺手把异常体系也统一了”。C++ 项目里,越是“顺手”,越容易把问题来源弄脏。

第三条,每轮都要留一个回滚点。

哪怕你不 commit,也得能回答:

  • 这一步到底改了什么
  • 如果错了,要删哪几处
  • 退回上一步以后,项目是不是还能编

你会发现,这套思路其实跟人工开发很像。区别只是以前你自己敲代码,现在是你盯着 AI 不让它乱跑。

一个更像实战的 AI 用法

如果你真想把这套东西练熟,我建议你连续做三轮。

第一轮,只让 AI 帮你接 fmt,你自己读一遍 CMake 配置和输出代码。

第二轮,只让 AI 接 spdlog,你自己决定到底是控制台日志还是文件日志,不准两种一起上。

第三轮,只让 AI 接 toml++,你自己定配置项,不准 AI 帮你脑补未来需求。

这三轮走完,你对 AI 编程的感觉会变很多。以前是“它怎么一下子给我生成这么多”,后来会慢慢变成“我该把下一步压到多小,才最划算”。

我觉得这才是现在 AI 编程里最值钱的能力。

不是把一个 Demo 变出来。

而是把一个项目稳稳地往前推。

说实话,这套办法没什么新鲜的,甚至有点土。但是土办法往往抗返工。尤其 C++ 这种语言,你前面让 AI 少做一点,自己多确认一点,后面真的会轻松很多。不然三分钟起飞,三小时回炉,傻眼的还是自己。

参考资料

写作附记

原始提示词

提示词:人工写项目,针对 C++ 这种不用手脚架的语言,第一个弄个 框架,从 main 开始拓展逻辑,逐步增加模块,比如配置文件、日志模块、迭代业务模块。我的习惯是每次都能确保编译,逐步重构,可能一开始不是最优解。AI 编程,现在很多时候,跳过了步骤,前期思考的太少,特别是引入新的三方库,AI 是能快速出个 Demo,但是由于我不清楚新引入三方库的细节,支持哪些功能,相关逻辑的返工率明显高于人工开发。有没有好的实战案例,让我学下,我知道网上有很多复杂的 AI 编程规范,我想要简单一些的,能快速落地的。

写作思路摘要

  • 把题目收窄到 tooling lane,重点写 AI 改变工作流以后,哪里省事了,哪里反而更别扭。
  • 不写成泛泛的规范清单,改成一个 C++ 小项目的递进式练手案例。
  • 保留用户“从 main 开始、每一步都能编译、逐步重构”的核心判断,把它写成全文主线。
  • 补了 Anthropic、GitHub、CMake、fmt、spdlog、toml++ 的一手资料,避免对工具能力和依赖方式瞎猜。
  • 文章结构按 fmt -> spdlog -> toml++ -> 模块拆分 推进,故意不让 AI 一步到位。
金融IT程序员的瞎折腾、日常生活的碎碎念
使用 Hugo 构建
主题 StackJimmy 设计