从让AI写代码到为AI设计系统:Harness Engineering的第一性原理
大多数人在问:“AI什么时候能替代程序员?”
这是一个错误的问题。
真正的变化不是AI取代了谁,而是工程的重心从“写代码”转移到了“设计AI工作的系统”。
你不会问一匹马:“汽车什么时候能替代你?”你会问:“道路该怎么修?”
一、真正的转变
过去二十年,软件工程师的核心能力是把想法变成代码。
现在,AI可以写代码了。而且写得越来越快,越来越便宜。
但这不意味着工程师消失了。恰恰相反——工程师的价值正在从“生产代码”跃迁到“定义代码生产的边界”。
想想看:工厂出现后,铁匠没有消失,他们变成了工程师。他们不再亲手锤打每一块金属,而是设计模具、定义工艺流程、把控质量标准。
软件行业正在经历同样的跃迁。
你不再是铁匠。你是设计锻造系统的人。
这个过程有一个名字:Harness Engineering。
它不是一个新框架,不是一个工具,不是一个可以npm install的东西。它是一种根本性的思维方式转变——从“我如何写好这段代码”到“我如何让AI在正确的约束下持续产出好代码”。
大多数团队还没意识到这个转变已经发生了。他们还在用旧的思维框架理解新的现实。
二、隐性知识的显性化
每个资深工程师脑子里都有一套没写下来的规则。
“这个模块不能直接调那个服务。”“日志要这样打,不能那样打。”“这里用事件驱动,不要用轮询。”“这段遗留代码别碰,碰了会塌。”
这些规则从来没有文档化。它们活在老员工的大脑里,通过code review口口相传,在午餐时间偶然提起,在新人踩坑后才被发现。
AI不吃午饭,也不做code review。它只认识被写下来的东西。
所以,Harness Engineering的第一个动作是:把隐性知识变成显性规则。
这听起来很简单,但它是整个范式转变的核心。因为——
你的经验如果不能被编码为约束条件,它在AI时代就等于不存在。
想想这有多深刻。你十年积累的技术直觉,你对系统架构的精微理解,你知道哪些“看起来优雅但实际上是坑”的设计模式——如果这些东西没有被转化为AI可以理解和遵守的规则,它们的价值就是零。
不是接近零。是零。
因为AI会绕过你所有的隐性知识,直接按照它训练数据里的“最佳实践”来干。而训练数据里的最佳实践,往往是脱离上下文的通用方案。
Harness Engineering就是把经验变成环境。不是教AI你知道什么,而是构建一个系统,让AI只能在你定义的边界内行动。
就像河流不需要“知道”应该流向哪里。河床决定了一切。
你不是在训练AI。你是在塑造河床。
三、从手艺到工厂
软件工程一直被视为一种“手艺”。
每个程序员都是工匠,代码是他们的作品。我们甚至用“craft”这个词——software craftsmanship。我们谈论“优雅的代码”“漂亮的架构”,好像在谈论一件艺术品。
这个时代结束了。
软件正在从“手艺模式”进入“工厂模式”。这不是降级,这是升维。
手艺模式里,价值在于你能亲手做出什么。工厂模式里,价值在于你能设计什么样的生产系统。
一个木匠可以做出精美的椅子。但设计宜家平板包装系统的人,改变了全世界的人坐什么椅子。
哪个创造了更大的杠杆?
人在上移,不是在出局。 从执行层上移到设计层,从操作层上移到架构层,从写代码上移到定义代码的生成规则。
这里有一个关键区别:上移不是变得更“抽象”。不是画更多的架构图,开更多的会议,写更多的PRD。
上移意味着你的工作变成了:
- 定义系统的边界条件
- 设计验证循环
- 构建AI可以在其中安全工作的“赛道”
- 当AI产出偏离时,调整赛道而不是修改产出
你不是在管理AI。你是在工程化AI的工作环境。
这就是Harness这个词的含义——驾驭,束缚,利用。不是控制每一步,而是设计让正确行为自然涌现的结构。
四、AI的过度设计倾向
给AI一个简单的任务,它会给你一个复杂的方案。
这不是bug,这是特性。或者说,这是它的本性。
AI被训练来展示能力,不是来展示克制。
你让它写一个用户登录功能,它会给你加上OAuth2.0、JWT刷新机制、多因素认证、设备指纹、风控引擎的接口预留、国际化支持、无障碍访问优化。
你只需要一个简单的邮箱密码登录。
这就是AI在设计阶段的核心问题:过度设计。
为什么?因为在AI的训练数据里,“更完善”的方案得到了更多的正面反馈。Stack Overflow上获赞最多的回答,往往是最全面的那个,不是最简洁的。技术博客里被转发最多的架构设计,往往是最精巧的那个,不是最朴素的。
AI学会了一个错误的等式:复杂 = 专业。
但真正的工程智慧恰恰相反。
最好的架构不是你再也无法添加什么的架构,而是你再也无法删除什么的架构。
AI不懂得删除。它只懂得添加。
它不会说“这里不需要”。它会说“这里可以加上”。每一次“可以加上”,都是技术债务的种子。
一百个种子长成一片杂草丛,你的系统就窒息了。
这就是为什么在设计阶段,AI的输出必须被视为“初始提案”而非“最终方案”。它是原材料,不是成品。
需要有人做减法。
五、人类审查的核心价值:做减法
大多数人以为code review的价值是找bug。
错了。
在AI时代,code review的核心价值是做减法。
Bug可以通过测试找到。逻辑错误可以通过形式化验证发现。安全漏洞可以通过扫描工具检测。
但“这个东西根本不应该存在”——这个判断,只有人能做。
AI擅长回答“怎么做”。人擅长回答“该不该做”。
当你review一个AI生成的PR时,你最重要的工作不是检查代码是否正确。而是检查——
这段代码是否多余?
这个抽象是否必要?
这层封装解决了真实问题还是想象中的问题?
这个配置项真的会被改变吗?
这个接口预留是基于真实需求还是基于“万一以后要用呢”?
每一行你删掉的代码,都比你写的代码更有价值。
因为删除的代码永远不会有bug,永远不需要维护,永远不会成为技术债务。
这就是为什么在Harness Engineering的框架下,人类审查不是瓶颈。它是系统中最关键的过滤器。
不是AI写得不够好。是AI不知道什么时候该停下来。
一个好的工程师,不是写了什么惊天动地的代码。而是挡住了一百个不应该存在的功能,删掉了一千行不需要的代码,说了一万次“不”。
这种能力——知道什么不该做的能力——是AI最难学会的东西。
因为“不做”在训练数据里没有正面样本。没有人会因为“什么都没做”而获得GitHub star。
但最好的系统,恰恰是被无数个“不做”雕刻出来的。
六、系统原语:AI放大的基础
现在我们来谈一个核心概念:系统原语(System Primitives)。
系统原语是你架构中不可再分的基本构件。它们是AI构建一切的地基。
日志系统是原语。错误处理模式是原语。数据访问层的接口契约是原语。消息队列的使用规范是原语。配置管理的层级结构是原语。
原语不是你“选择”的。它们是你“定义”的。区别很大。
选择意味着从现有选项中挑一个。定义意味着你决定了这个东西在你的系统里是什么样子,有什么行为,有什么边界。
AI是一个放大器。它放大你的原语。好的原语被放大成好的系统。坏的原语被放大成灾难。
这就像复利。
如果你的利率是正的,时间是你的朋友。如果你的利率是负的,时间是你的敌人。
原语就是你的利率。
一个设计良好的错误处理原语,会让AI在每个模块里都产出一致的、可追踪的、容易调试的错误处理代码。一千个模块,一千次正确。
一个设计糟糕的错误处理原语——比如“catch所有异常然后打个日志”——会让AI在每个模块里都吞掉异常。一千个模块,一千个定时炸弹。
你不需要审查AI写的每一行代码。你需要确保你的原语是对的。
因为原语对了,AI的输出大概率是对的。原语错了,无论AI多强大,输出都会系统性地偏离。
这就像物理学。如果牛顿定律是对的,你可以推导出整个经典力学。如果牛顿定律是错的,你推导得越多,错得越远。
原语是你的定律。
投资时间在原语上。这是整个Harness Engineering中杠杆最大的一个动作。
七、真原语与伪抽象
但这里有一个陷阱。
不是所有看起来像原语的东西都是原语。很多时候,我们创造的是伪抽象——看起来像基础设施,实际上是不必要的复杂性。
真原语简化系统。伪抽象复杂化系统。
怎么区分?
真原语有三个特征:
第一,它解决了一个你真实遇到过的问题,不是一个你想象中可能遇到的问题。
第二,它减少了使用者(包括AI)需要做的决策数量。好的原语让你不用想。坏的抽象让你想得更多。
第三,它在不同上下文中的行为是可预测的。你不需要查文档就知道它在这个场景下会怎么表现。
伪抽象恰恰相反:
它解决的是假设性问题。“万一以后我们需要换数据库呢?”于是你建了一个数据库抽象层。三年后你没换数据库,但每个新功能都要跟这个抽象层搏斗。
它增加了决策数量。“我应该用AbstractBaseRepository还是ConcreteRepositoryAdapter?它们有什么区别?为什么有两个?”
它的行为因上下文而异。“在这个场景下用configV2,在那个场景下用legacyConfig,但如果是测试环境要用mockConfig,除非是集成测试。”
AI特别擅长制造伪抽象。因为伪抽象在代码层面看起来很“专业”。
它有清晰的接口定义,有完整的类型标注,有详细的文档注释。一切看起来都很好。除了一个事实——这些东西根本不需要存在。
所以当你为AI定义系统原语时,坚守一个原则:
如果你不能用一句话解释为什么这个原语必须存在,它就不应该存在。
不是“它很有用”。不是“它很优雅”。是“如果没有它,系统会在某个具体场景下出问题,而这个场景我们真实遇到过”。
从真实的痛苦中提炼原语,而非从想象中的完美中推导原语。
这是第一性原理思维的核心。
八、验证循环比更强的模型重要
行业里有一种迷信:模型越强,问题越少。
这就像说“司机技术越好,就越不需要交通规则”。
不是这样的。
GPT-7不会让你不需要验证。Claude 5不会让你不需要测试。未来的模型不管多强,在你的特定业务上下文中,它仍然会犯错。
因为它不了解你的业务上下文。它不可能了解。你的上下文是独特的、动态的、充满历史遗留决策的。
真正决定AI工程质量的,不是模型的能力上限,而是验证循环的严密程度。
什么是验证循环?
AI生成代码 → 自动化测试 → 静态分析 → 规则校验 → 人工审查 → 反馈修正 → AI再次生成。
这个循环的每一个环节都在做同一件事:缩小AI的可能输出空间,直到它只能产出正确的答案。
想象一个漏斗。
AI的原始输出是漏斗的顶端——巨大,充满可能性,也充满错误。每一层验证都收窄一点。最终流出来的,是经过多层过滤的、高度可靠的代码。
漏斗设计得越精密,你对模型本身的依赖就越小。
这意味着:一个普通模型配上精密的验证循环,胜过一个顶级模型配上松散的流程。
这是一个违反直觉但极其重要的洞察。
大多数团队把80%的时间花在选择和调优模型上,把20%的时间花在设计验证流程上。
应该反过来。
验证循环是可以被你完全控制和持续改进的。模型是别人的产品,你无法控制。
把精力花在你能控制的事情上。这是Harness Engineering的基本纪律。
一个好的验证循环应该具备什么特征?
快。快到AI每次生成后都能在秒级得到反馈。如果验证需要半小时,AI就会在错误的方向上走半小时。
全面。覆盖功能正确性、代码规范、架构约束、安全规则、性能边界。每一层都是一道防线。
可解释。当验证失败时,失败信息必须清晰到AI可以理解并自我修正。“测试失败”是没用的。“在处理空列表时,期望返回空数组但实际返回了null”——这才有用。
可演进。每发现一个新的问题模式,就新增一条验证规则。系统像免疫系统一样,遇到的病原体越多,就越强壮。
验证循环是活的。它不是你搭建一次就忘记的基础设施。它是你最重要的工程资产,需要持续投入和迭代。
九、每个Bug都是一条未被书写的规范
当AI产出了一个bug,大多数人的反应是修复bug。
这是正确的。但不够。
每个bug都是一条未被书写的规范。
这句话值得反复读。
AI为什么会在这里犯错?不是因为它“笨”。是因为在你的系统规范中,有一个空白地带——一条你以为是“常识”但从未明确写出来的规则。
用户ID不能为负数——你觉得这是常识。但你写在规范里了吗?
金额计算不能用浮点数——你觉得这是常识。但你的原语里有这条约束吗?
删除操作必须软删除——你觉得这是常识。但AI不知道。
在AI的世界里,没有“常识”这个概念。只有“已定义”和“未定义”。
未定义的空间,就是bug的温床。
所以,当你修复一个AI产出的bug时,不要只修复代码。要回溯:
这个bug对应的规则是什么?
这条规则为什么没有被写下来?
把这条规则写下来之后,它应该在验证循环的哪一层被检查?
如果这条规则更早被写下来,AI一开始就不会犯这个错误吗?
每修复一个bug,就多一条规范。规范越完善,AI犯错的空间就越小。这是一个正向飞轮。
最好的团队不是bug最少的团队。是规范增长最快的团队。
因为规范的增长速度决定了AI可靠性的提升速度。
这也回到了前面说的——经验的显性化。每个bug都是一次显性化的机会。不抓住这个机会,同样的bug就会以不同的面貌反复出现。
你消灭的不是bug本身,而是产生这类bug的条件。
这才是真正的根因分析。不是“为什么这段代码有bug”,而是“为什么我的系统允许这种bug存在”。
前者修复一个点,后者封堵一个面。
十、从“写代码的人”到“定义边界的人”
让我们把这一切串起来。
工程师的角色正在经历一次根本性的重新定义。
过去,你的工作是写代码。你的价值由你写的代码的质量和数量决定。
现在,代码由AI写。你的工作变成了——
定义AI工作的边界。
什么是边界?
边界是规则。“在这个系统中,所有API响应必须遵循这个格式。”
边界是约束。“任何数据库操作必须通过这个原语层,不允许直接SQL。”
边界是验证。“每次提交必须通过这组检查,不通过不允许合并。”
边界是接口。“这个模块对外暴露这三个方法,其余全部私有。”
边界是“不”。“不,我们不在这一层做缓存。”“不,这个功能不需要配置化。”“不,这个抽象不必要。”
你的价值不再是“我能写什么”,而是“我能定义什么样的边界,让AI在其中产出正确的东西”。
这是一种完全不同的能力。
写代码需要的是技巧——语言特性、算法知识、框架用法。
定义边界需要的是判断力——什么是必要的,什么是多余的,系统的真正约束在哪里,灵活性应该开放在哪里。
技巧可以被训练。判断力只能通过经验和反思获得。
这就是为什么资深工程师在AI时代不会贬值。恰恰相反——他们的判断力,是整个系统中最稀缺的资源。
一个初级工程师可以学会使用AI写代码。任何人都可以。
但只有经历过系统崩溃的人,才知道哪些边界是不可逾越的。
只有维护过遗留系统的人,才知道哪些“优雅的设计”最终会变成噩梦。
只有上线过大规模服务的人,才知道哪些假设在真实流量下会崩塌。
这种经验无法通过训练获得。这就是Naval所说的“specific knowledge”——独属于你的、无法被标准化传授的知识。
AI时代,specific knowledge的载体从“手指上的代码能力”变成了“脑子里的系统判断力”。
载体变了,本质没变。
十一、如何面对那些贩卖焦虑的口号
“程序员将在两年内被取代!”
“AI已经可以独立完成项目了!”
“不学AI你就完了!”
深呼吸。
口号的目的是制造情绪,不是传递信息。
每一次技术变革都伴随着同样的叙事结构:新技术出现 → “旧技能将消亡” → 恐慌 → 卖课 → 现实逐渐展开 → 变化确实发生了但远没有口号说的那么极端。
还记得“no-code will replace developers”吗?
还记得“blockchain will replace databases”吗?
还记得“agile will eliminate project failure”吗?
变化是真实的。口号描述的方式是失真的。
判断一个变化是否真实,看它是否改变了底层的激励结构。判断一个口号是否失真,看它是否过度简化了这个改变。
AI确实改变了底层激励结构。写代码的边际成本趋近于零——这是真实的。这意味着能写代码不再是竞争优势——这也是真实的。
但“程序员消失”?这就是过度简化了。
代码生产的自动化不等于软件工程的自动化。代码只是软件的一部分——甚至不是最难的部分。
最难的部分是什么?
理解业务需求中的矛盾和模糊。
在不确定性中做出不可逆的技术决策。
管理一个系统在多年演进中的复杂性。
协调多个团队对“什么是正确的”的不同理解。
在紧急故障中快速判断根因。
这些能力,AI在可预见的未来都无法替代。不是因为AI不够强。是因为这些问题本身没有确定的答案,需要在特定上下文中做出权衡。
AI能解决有确定答案的问题。人解决需要权衡的问题。
所以,面对口号,保持两种能力:
第一,区分信号和噪音。AI改变工程方式——这是信号。“程序员两年消失”——这是噪音。
第二,把焦虑转化为行动。与其恐惧被取代,不如问自己:我的哪些能力是AI放大器的一部分?我的哪些能力只是在做AI已经可以做的事情?
聪明的人不恐惧变化,也不无视变化。他们重新定位自己在变化中的位置。
十二、普通团队的实操系统
理论说够了。谈谈一个普通团队,明天早上该怎么做。
好的系统不需要英雄。它需要流程。
以下是一个Harness Engineering的实操工作系统,你可以从明天开始使用。
第一步:盘点你的系统原语
花一天时间,和团队一起列出你们系统中的所有原语。
不要想象。去看代码。
你们的错误处理是怎么做的?有统一模式吗?还是每个模块各自为政?
你们的日志是怎么打的?有规范吗?还是每个人凭感觉?
你们的API设计遵循什么约定?URL命名?参数校验?响应格式?错误码?
数据库访问有统一的抽象吗?事务怎么管理?连接池怎么配置?
列出来,分成三类:已有且好的、已有但差的、缺失的。
第二步:补齐和修正原语
先修正“已有但差的”。这些是你系统中正在被AI放大的负面模式。
再补齐“缺失的”。每个缺失的原语都是一个AI可能犯错的灰色地带。
每个原语都应该有三样东西:一个清晰的接口定义,一组使用示例,一组反面示例(“不要这样用”)。
反面示例特别重要。AI很容易从正面示例中“过度泛化”。告诉它“不要”比告诉它“要”更有效。
第三步:建立验证循环
从最简单的开始:
一套覆盖核心路径的自动化测试。不需要100%覆盖率。先覆盖最重要的20%路径。
一组架构规则检查。“不允许直接导入内部模块。”“不允许在Controller层调用数据库。”“不允许在工具函数中使用全局状态。”这些可以用简单的lint规则实现。
一个PR review检查清单。不是代码层面的,而是架构层面的:“这个PR是否引入了新的依赖?”“是否修改了公共接口?”“是否新增了抽象层?”如果答案是“是”,就需要更严格的人工审查。
第四步:建立“Bug→规范”的转化流程
每次修复AI产出的bug时,多做一步:
这个bug对应什么规范?规范是否已经存在?如果不存在,创建它。创建后,添加到验证循环中。
这个流程不需要复杂的工具。一个共享文档加上纪律就够了。
关键不是工具,是纪律。
第五步:渐进式信任
不要一开始就让AI做所有事情。
从低风险的任务开始:写测试、写文档、做简单的CRUD。验证AI在你的原语系统中是否表现良好。
逐步扩大范围:更复杂的业务逻辑、跨模块的功能、性能敏感的代码。每扩大一步,都确认验证循环能捕获问题。
信任是earned,不是granted。对AI也是一样。
第六步:持续迭代
每周回顾:
本周AI产出了多少需要大幅修改的代码?
哪些修改是因为原语不清晰导致的?
哪些修改是因为验证循环有漏洞导致的?
哪些修改是因为模型本身的局限导致的?
前两类是你能控制的。第三类不是。
把精力花在前两类上,持续缩小AI犯错的空间。
这不需要专门的“AI工程师”。这是每个工程师的日常工作的一部分。就像测试不需要专门的QA团队(虽然有也好),原语维护和验证循环也是每个工程师的责任。
十三、真正的竞争优势
最后,让我们谈谈竞争。
AI模型是公共资源。GPT、Claude、Gemini——所有人都能用同样的模型。
模型不是竞争优势。从来不是。
真正的竞争优势是:谁能最快地把组织经验转化为AI可执行的系统。
想想这意味着什么。
公司A有十年的行业经验,但这些经验全在老员工的脑子里。AI对公司A来说就是一个通用工具——能写代码,但写出来的代码跟任何其他公司的AI写出来的没有本质区别。
公司B同样有十年的行业经验,但他们把这些经验编码成了系统原语、验证规则、架构约束、反面模式库。AI在公司B的系统中工作,就像一个浸泡了十年的资深员工——它自动遵循公司B独有的实践,产出的代码体现了公司B独有的工程哲学。
公司A的AI是通用AI。公司B的AI是定制AI。两者之间的差距,就是Harness Engineering的差距。
这不是关于谁用了更贵的模型。这是关于谁把自己的独特知识变成了系统。
再说直白一点:
模型是发动机。你的Harness是底盘、悬挂、轮胎、导航系统。同一台发动机装在不同的车身上,表现天差地别。
大多数公司在拼发动机。聪明的公司在造车身。
而造车身的能力——把组织经验系统化的能力——是不可复制的。因为每个组织的经验是独特的。这就是你的护城河。
不是AI的能力。是你驾驭AI的能力。
不是模型有多聪明。是你的系统有多聪明。
结语:回到第一性原理
把所有的噪音去掉,AI对软件工程的影响可以用一句话概括:
代码生产的边际成本趋近于零。
从这一个事实出发,所有的推论都是必然的:
既然代码便宜了,那么决定代码质量的因素——原语、约束、验证——就变得更重要了。
既然AI能写代码了,那么人的价值就从“写代码”转移到“定义什么样的代码应该被写”。
既然产出变多了,那么过滤和审查——做减法——就成了最稀缺的能力。
既然模型是公共资源,那么竞争优势就在于你的Harness——你的系统、原语、验证循环、组织知识的编码化。
这就是Harness Engineering。不是一套工具。是一种思维方式。
它的核心信念是:
AI不需要被“管理”。它需要被“约束”在正确的结构中。
人的价值不在于做AI做不了的事。而在于定义AI应该做什么。
系统的质量不取决于最强的那个组件。取决于组件之间的边界定义得有多清晰。
不要追逐更强的模型。构建更好的系统。
模型会过时。系统会积累。
这是属于你的复利。
写代码的时代正在结束。设计系统的时代正在开始。你准备好了吗?