
Dex Horthy 的 AI That Works 已经更新到第 72 期这一期的主题是“面向可扩展软件的 Code Mode”。先说我的判断Code Mode 不是一个“帮你写更多代码”的功能开关它代表的是 AI 编程工具从“回答代码问题”进入“直接管理代码仓库变化”的工作方式。如果你维护的软件不是一次性脚本而是会持续迭代、会加模块、会被别人接着维护的产品那这个主题就非常值得研究。我在这里不会把第 72 期的原文内容一段段转述出来。博客的价值不在复述而在于把你听到的概念拆成能自己实验的步骤Code Mode 到底是什么跑之前要准备什么单任务怎么验证批量修改怎么控制出了问题按什么顺序排查。1. Code Mode 解决的不是“写代码”而是“持续修改代码库”1.1 普通问答模式缺少的是什么先解释一下这里说的 Code Mode 取什么含义。现在很多 AI 编程助手都有模式区分一种是问答式你问它“这段代码哪里有问题”它给你解释或者给出一段示例另一种是传统补全式你在编辑器里写注释它补函数体。Code Mode 通常指向另一种能力它把整个代码仓库当作工作现场可以检索文件、读取相关模块、直接编辑代码、运行命令、执行测试然后根据报错继续调整。不同产品里这个功能的名字可能不一样有的叫 Agent有的叫 Build Mode有的直接叫 Code Mode。名字会变本质接近。问答模式和 Code Mode 最大的差异不是“回答质量”而是“有没有改变文件状态”。问答模式再怎么生成代码最终动作发生在你的复制粘贴和手动提交里Code Mode 会真的去改文件、建目录、移动代码、运行测试。也就是说你需要为自己的代码仓库状态变化负责。1.2 “可扩展软件”为什么是一个特殊场景普通脚本写出来跑一遍正确就行。可扩展软件不是这样。“可扩展”说的是软件长得大以后还能被维护模块边界清晰接口稳定数据流可追踪依赖方向不会混乱新人接手不需要靠猜。这些性质很难用单次测试结果衡量。Code Mode 改代码时并不会天然把“可扩展性”当作最高优先级。它更倾向于先把眼前任务跑通。所以“面向可扩展软件”这个限定语正确的理解大概是这样不是意味着 Code Mode 已经成熟到能自动架构大型系统而是提醒使用者当你想让 AI 在一次多轮修改里处理多个文件、跨模块的需求时必须用更工程化的方式去约束它。否则它改得越快制造的问题可能越隐蔽。我对 Code Mode 的使用原则比较保守小任务可以放手让它自己试涉及公共接口、数据模型、跨模块重构时一定要每一步都看住。注意不要因为代码模式能一口气改十个文件就把复杂的架构决策也一起交给它。它在逻辑正确性上可以帮你在组织边界和长期成本判断上仍然需要人把关。2. 在跑 Code Mode 之前先把这些环境确认好2.1 仓库本身要允许“快速试错”很多 Code Mode 失败的问题不在模型而在项目环境不支持它快速试错。我建议至少确认这几件事当前代码能不能在一个干净分支上随意改动并方便回滚。构建、编译、测试命令能不能在本地快速执行。改动涉及的核心模块是否已经有基础测试覆盖。代码仓库是否已经建立索引或者工具是否允许你限制只扫描某几个目录。为什么要这么确认因为 Code Mode 的工作方式是“改代码、跑测试、看报错、再改”。如果一次完整验证需要三分钟它迭代十次的成本就是三十分钟如果测试需要人工介入它根本无法自动闭环。常见的跨平台大仓库里光是一个模块编译就要几分钟这种环境就不适合让 AI 做大量自主尝试。正确做法是把改动边界收窄。Code Mode 一次只负责一个模块或一条链路避免在一个巨大 monorepo 里无限制检索。低配置机器也一样能跑但你要把范围缩小而不是让它在整个仓库里乱找文件。2.2 权限、路径、依赖与索引比“聪明提示词”更容易出问题有一次我遇到 Code Mode 说“完成”但实际上一个文件都没改。排查了很久原因是目标目录权限不对工具只能读不能写。这类问题非常常见。正式开工前按照这个顺序检查一圈仓库路径里不要出现特殊字符或过长路径。Windows 和 Linux 对路径分隔符、大小写、文件权限的处理不一样如果团队里有人用 Mac、有人用 Windows还要额外注意换行符和可执行权限。需要运行的命令能直接在当前环境执行。Python 虚拟环境有没有激活Node 依赖有没有安装Go 模块缓存是否正常。代码索引是否覆盖目标文件。有的工具对大仓库需要先构建索引如果索引只建到一半Code Mode 会找不到某些符号然后给你生成一个“看起来合理但并没有复用现有函数”的新版本。依赖版本是否和项目锁文件一致。AI 生成的代码可能在你的机器上没问题但它假设的依赖版本和项目的实际版本不一致就会出现接口不存在或者行为不同。这些不是 Code Mode 自己能判断的。它看到的是文字你掌握的是真实运行环境。你要做的不是给它一个无比惊艳的提示词而是把环境调成可预测状态。3. 把可扩展需求拆给 Code Mode 的通用流程3.1 用“任务描述”而不是口头聊天我不太建议你用“帮我优化一下这个模块”这种话去驱动 Code Mode。这句话的信息量太低模型不知道“优化”指性能、可读性还是接口拆分也不知道边界在哪里。我一般会写一份任务描述包含目标、范围、约束、验收标准四块。结构类似这样目标 在支付结果处理模块中增加一个可配置的重试策略。 当前入口src/payment/handler.process_result 范围 只修改 src/payment 目录下的代码。 不允许改动数据库表结构和对外 API 签名。 约束 重试间隔必须可配置不能写死常量。 日志中要记录每次重试的原因。 验收标准 1. 单元测试覆盖“第一次失败后成功”和“持续失败达到上限”两种情况。 2. 配置项不设置时默认重试 3 次。 3. 现有测试全部通过。 请先输出修改计划不要直接改代码。任务不能太大。一个任务尽量只解决一个横切关注点。Code Mode 擅长的是把一个局部变化做完整而不是替你完成整个系统的重构规划。写完任务描述后不要马上点“执行”。先让它输出方案。这一步会浪费一点时间但能避免它拿着错误的架构假设直接动手。3.2 先“Plan Only”再“Do It”实际使用 Code Mode 时我会把过程拆成两个阶段。第一阶段只让它读代码、分析目标、给出修改方案。方案里要能回答几个问题涉及哪些文件、每个文件大致怎么改、会新增什么配置项、会不会影响其他调用方、需要补哪些测试。第二阶段才是执行。而且执行后不要急着让它继续写下一个功能先做代码评审。这个流程背后的原因是成本不对称。一个坏方案被拒绝了损失只是一个想法如果模型直接带着坏方案改完十个文件你要花数倍时间去回滚和解释。看 diff 的时候重点不是看代码能不能运行而是看它是否遵守了你设定的范围。我经常发现的问题包括说好只改一个模块它顺手改了公共目录说好不改数据库结构它在迁移文件里加了字段。这些问题单看测试不一定暴露但会让你的可扩展性设想一点点失效。4. 能不能算“可扩展”不能只看测试通过4.1 单条任务的验收标准Code Mode 跑完一项任务最简单的判断当然是“有没有报错、测试是否通过”。但如果课题是“面向可扩展软件”这个标准远远不够。测试通过说明它在当前环境、当前输入下表现正确不能说明新代码会不会阻碍后续三个功能的扩展。例如为了快速满足需求模型可能直接复制了一段类似逻辑而没有抽成公共函数也可能为了通过类型检查给对象加了一个很宽泛的 any还可能把一个本来只由 A 模块调用的入口暴露给 B、C、D 到处引用。对可扩展软件来说这些问题的恶劣程度往往比“某个边界条件没处理”更高。因为它们是结构性的越晚发现越难改。4.2 从五个维度看新增代码这里整理了一个我评审时常用的检查维度。它不是工具自带的标准但比较接近做架构评审的人会关心的问题。检查维度看什么可接受信号模块边界是否绕过了已有的分层是否引入了反向依赖新代码只依赖下层模块不窃听兄弟模块内部接口稳定是否改动了对外签名是否破坏既有调用方新增独立函数或接口而不是偷偷改掉公共契约数据流参数是显式传递还是散落在全局状态里输入输出路径清晰副作用容易追踪性能假设循环内有没有数据库查询缓存是否无界复杂操作用批量或异步资源消耗有上限可观测性关键分支有没有日志、错误类型和上下文失败时能从日志判断是配置、网络还是业务问题你可以根据自己项目的类型调整维度。如果是数据团队可能要看 SQL 是否会全表扫如果是前端项目可能要看组件状态是否提升合理如果是基础服务就要重点看并发安全和资源释放。重要的是验收动作要包含“结构评审”而不仅仅是“跑通”。注意Code Mode 给的总结里经常说自己“为了可扩展性做了抽象”这不一定是真的。你要翻开 diff 看抽象是否过度是否用额外的一层间接性换来了不必要的复杂性。5. 需要批量改多个模块时怎么防止 Agent 失控5.1 一次只拆一个可独立验证的边界当需求涉及多个模块不要把所有改动塞进同一个任务描述里。表面上看“让 AI 一次做完”效率更高实际上会有三个问题上下文长度有限改动范围越大它对每个文件的关注度越低。如果中间某个模块测试失败它会带着错误状态继续处理另一个模块错误会传染。产生的 diff 巨大人工评审很难发现哪里改错了可扩展性也就无从谈起。我倾向于把一个批量需求按模块拆成多个阶段每个阶段对应一次可验证的变更。例如先改数据访问层不急着改上层接口等数据层的测试和代码评审通过后再让 Code Mode 改业务逻辑层。这样做成本看起来高一些但它能保证任何一步出问题时影响范围是可控制的。增量交付本来就是可扩展软件开发的常态。5.2 批量任务里要有失败重试和日志留痕Code Mode 在做批量任务时不能只设置一句“把所有文件都处理一遍”。你需要考虑几件事是普通脚本和自动任务都会遇到的失败重试、输出命名、日志位置、恢复点。如果你是让 Code Mode 连续处理多个业务接口最好为每个接口创建独立的分支或独立的提交而不是让所有改动都堆在一个工作目录里。这样当第三个接口改坏时你不需要撤销前两个接口的成果。如果任务之间有关联例如都需要先拉取某个配置那就把“公共准备工作”单独作为一个任务先跑完。Code Mode 自己也会尝试推理但公共步骤重复执行容易产生冲突。另外一个容易忽略的点是输出和日志。很多 Code Mode 工具允许你查看执行记录你要把执行记录保存下来而不仅仅依赖模型最后那句“完成”。当批量任务跑到一半失败时日志能告诉你它停在哪里、执行了什么命令、报错内容是什么。这比从头开始一个新会话要可靠得多。6. Code Mode 报错、跑偏、没改文件时按这个顺序排查6.1 先看现象和输入不要急着调提示词我见过很多人第一次碰到 Code Mode 表现不佳第一反应是“我的提示词不够好”然后开始加各种复杂的措辞。但很多时候问题根本不在提示词而在环境或者输入约束。排查我建议按这个顺序查看实际现象是报错、卡住、没改文件还是改了文件但行为不符合预期。查看它实际改动了哪些文件。有的工具会列出所有编辑过的文件直接看这个列表比看它的文字总结靠谱得多。回头检查任务描述里说的范围、路径、名称是否和代码仓库里的真实情况一致。如果模块已经被重命名而你还写着旧路径Code Mode 可能花了半天找不存在的东西。再检查仓库索引和权限。工具能不能正常搜索到这个文件对它来说这个目录是否只读路径和权限问题是“没改文件”这个现象的高频原因。不要以为模型没有理解你的需求它可能理解了但写不进去。6.2 看日志、看资源、看版本再改参数如果是代码能改、但测试一直失败要去看真实的报错信息。具体操作是先本地手动执行它失败的那条命令。不要只看 Code Mode 转述的“失败”要自己复现一次。这样能确认是代码本身问题还是执行环境问题。例如依赖没有安装、环境变量缺失、数据库没启动这些都会让它反复重试却没有结果。如果工具运行很慢或者不断卡住检查机器资源。内存不足时代码索引和上下文加载会非常慢磁盘满了日志写入会失败并发开得太大某些本地模式会直接超时。不要一上来就调高并发先把单个任务跑稳。还要留意版本问题。AI 编程工具经常更新不同版本的模型对工具调用的支持不一样。如果某个环境之前能跑今天不行先确认工具版本、插件版本、依赖版本是否有变化。6.3 始终准备一个最小可复现样例当问题很难定位时我会把任务缩小到最小可复现样例只用一个文件、一个入口、一个明确输出看 Code Mode 能不能完成。如果最小样例能过说明整体流程没问题问题出在大任务拆分不够清晰或者仓库里某些历史代码干扰了它的判断。如果最小样例也过不了那大概率是环境、依赖或工具配置出了问题。这一步看起来很多余却是最快的定位方式。因为 Code Mode 的失败链路通常很长报错可能来自它执行的第五步而不是你最初让它改的那个函数。7. 什么情况我建议你别急着上 Code Mode7.1 小任务和学习场景用简单问答更划算如果你的需求只是“这个排序算法怎么写”“这个报错是什么意思”不需要让 Code Mode 获得修改权限。这类任务用普通问答模式更轻不会污染仓库不会留下大 diff也更安全。学习代码时也建议用问答模式。让 AI 直接改代码你会错过“为什么这样改”的思考过程。学习的目标是建立自己的判断力不是让 AI 替你做决定。7.2 约束不完整的老项目先补测试和边界再上 Agent老项目通常是最容易被 Code Mode 改乱的地方。没有测试、文档缺失、模块之间互相偷调用、公共函数里塞着一百个分支。在这种项目里Code Mode 很难判断哪些依赖是必须保留的哪些是历史包袱。如果你还是想用第一步不是写任务描述而是先把要改动的那条链路补上少量测试。测试不一定要多只要能把核心行为锁住。有了测试之后Code Mode 出问题时会更容易暴露至少你不会在毫不知情的情况下破坏原有功能。7.3 不能让 AI 自我判定架构合理性Code Mode 是一个执行意志很强的工具但它不具备你对产品未来的理解。它不知道你下个月要加什么功能不知道团队里谁负责维护这个模块也不知道公司里哪些约定是“看起来不优雅但绝对不能改”。因此架构层面的判断必须留在人这边。AI 可以分析依赖图、给出重构建议、实现你确认好的方案但“什么情况下值得引入抽象、在哪里划模块边界、要不要迁移数据模型”这类问题本质上依赖业务判断。你可以把 Code Mode 看作一个很强的实习生理解力不错执行速度快但你对它做的事仍然有最终审查责任。真正落地的时候最该盯住的不是它列出的能力清单而是输入范围、资源占用、失败重试和代码评审这几个环节。把这些控制好了“面向可扩展软件”的 Code Mode 才有意义。