AI时代谈编程范式,总会听到两种声音:一种鼓吹“让AI写代码,人只要提需求”,另一种强调“AI写的是垃圾,必须严格工程化”。我自己的实践体会是,这两种说法都偏了。用两个军事概念来类比,刚好能说清问题:一种是“游击战”,轻装快跑,小步试探,打完就走;另一种是“阵地战”,挖壕沟、修工事、稳扎稳打,不图一时快,只求长期防线稳固。这两种范式在AI辅助编程的今天,不是二选一,而是要根据战场情况灵活切换。这篇文章把我这两年在实际项目里怎么用AI、怎么切换这两种策略的经验整理出来,包括踩过的坑和总结出的判断标准。1. 两种范式的定义与核心差异1.1 游击战:快、变、试错所谓“游击战”式的编程,核心特征是小、快、灵。你有一个想法,需要马上验证,于是写出一个可能是临时的脚本,可能是一次性数据处理,也可能是一个用来验证AI辅助编码工具的交互式原型。这种代码的生命周期很短,通常以小时或天为单位,写完之后可能就丢弃或者重写。我经常用这种方式处理三类任务:一是对AI编程助手“投喂”一个小需求让它生成一段函数,然后我快速跑个测试看结果对不对;二是自己脑中有个算法思路,但不确定边界条件,直接用示例数据让AI帮我把思路变成可执行代码,我再手工改;三是做一些“探索性”的实验,比如测试某个第三方库的新接口能不能满足性能需求,这时候写一个临时压测脚本,跑完就丢。游击战的优点非常明显:代价低、反馈快。因为你不指望这段代码活很久,所以不需要过多考虑扩展性、健壮性,也不需要写冗长的文档和注释。AI在这种场景下是完美的放大器。我把自然语言需求翻译成代码草稿,再人工审查关键逻辑,原本需要半天的工作可能十几分钟就完成了。但游击战也有致命弱点:它不适合需要长期维护的产物。如果你把游击战式的代码直接丢进生产环境,就像把临时搭建的茅草屋当作常驻营房。头几天没问题,一旦遇到并发增加、需求变更、团队协作,茅草屋就会漏风漏雨。我曾经接手过一位同事留下的“快速验证代码”,后来它变成核心服务的一部分,结果每次加需求都要花大量时间理清那团毛线球。1.2 阵地战:稳、全、长期“阵地战”式编程则完全相反。它强调系统设计、模块划分、接口约定、单元测试、持续集成、代码审查、完整文档。这种范式适合那些需要存活数年、多人协作、承载核心业务的产品。在这种模式下,AI的角色不是替你把代码“一口气写出来”,而是充当“副驾驶”——帮你在既定架构内生成符合模式的代码片段,补全重复性的模板代码,甚至协助你生成测试用例和文档。阵地战的核心价值是可预测性和可控性。你可能听过“如果代码跑得好就不要去动它”这句话。在阵地战里,宁可牺牲一点开发速度,也要保证代码的行为是可预期的。每一段代码被合入主分支之前,都要经过设计评审和测试验证。AI生成的东西再快,如果无法满足这层约束,就不能直接用。阵地战当然有代价:开发速度慢、开销大。一个小功能要经过设计、实现、测试、评审、发布流程,可能比游击战多花几倍时间。但中长期来看,这笔投入是值得的。因为它减少了后来人的认知负担,也降低了出事故的概率。尤其在金融、医疗、基础设施等“失败成本极高”的领域,阵地战几乎是唯一选择。1.3 为什么AI让这个对比更明显如果没有AI,这两种范式的区别虽然存在,但没有那么显眼。因为传统编程无论哪种方式,代码都需要人一行行写出来,游击战写得快也只是相对的。AI的介入让天平两端都变得更极端。一方面,AI让游击战的“快”达到了新的数量级——以前写一个原型可能还要手动敲几百行代码,现在基于清晰的提示词,AI能在一两分钟内生成一个可运行的最小版本。另一方面,AI也让阵地战的“雷区”变得更加隐蔽——生成的代码表面上结构完整、注释齐全,但里面可能藏有被篡改的逻辑、隐藏的安全漏洞,甚至引用了并不存在的包。如果不经过严格的代码审查和测试,你根本发现不了问题。这就是为什么现在讨论“AI时代编程范式”特别有意义。AI既可以是游击战中最锋利的匕首,也可能是阵地战中最容易引爆的地雷。关键不是选择哪一种,而是知道什么场景用匕首、什么场景必须修筑工事。2. AI工具对两种范式的影响2.1 AI助手如何放大游击战的效率先说说AI如何在游击战场景里发挥作用。这里不说具体某款产品,就聊通用的能力和用法。用AI做游击开发,我最常用的模式是“目标-验证-修正”循环。给AI一个清晰的目标描述,附带约束条件和示例输入输出,让它产出代码。然后我立刻用真实的样例数据去验证。如果结果不对,就根据报错信息或边界情况继续追问AI,让它修正,直到通过验证。这个循环里,人的关键动作有两个:写清楚提示词和设计验证用例。写清楚提示词不是把需求一句话丢过去就完事。你需要告诉AI输入输出的格式、边界条件、性能要求、禁止使用的库,以及代码应放在什么上下文中。我通常会这样组织提示词:我需要一个Python函数,接收一个整数列表,返回列表中的中位数。 要求: - 输入列表可能包含重复值,也可能为空 - 列表长度在0到10万之间 - 不要使用统计库之外的高级库 - 返回float类型 - 时间复杂度尽量接近O(n) 请同时给出三个边界测试用例。这种提示词生成的结果,往往比“帮我写个中位数函数”靠谱得多。因为AI不知道上下文,你必须替它把“战场地图”画清楚。至于验证,就算AI生成的代码看起来逻辑完美,也必须跑实际数据。我的经验是,AI生成的代码中初版的正确率可能在六成到八成之间,直接相信就等于给自己埋雷。但在游击战里,这个修正成本很低,失败也无所谓,大不了换个思路再来。这正是AI和游击战理念契合的地方:快速试错,允许失败。还有一类场景是“探索性任务”。比如你面对一个复杂的第三方SDK,不知道某个方法的具体行为。可以不用去看整个手册,直接让AI按你的理解生成一段调用代码,然后跑个测试看结果和你预想的是否一致。这种“用AI帮忙做实验”的方式,能把原本需要一两个小时查阅文档的工作压缩到十几分钟。这也是我在新项目启动时最常用到的能力。2.2 阵地战中AI如何成为“防御工事”一提到阵地战,很多人以为就是“不用AI,靠人写”,那就错了。阵地战恰恰可以充分利用AI,把它变成加固防线、降低重复劳动的工具。阵地战里AI最有价值的方向有三个。第一是生成模板代码和重复性结构。比如微服务中的配置类、DTO对象、Mapper接口、OpenAPI定义。这些代码本身技术含量不高,但量大且容易出错。让AI生成初稿,再由人审查和修改,能节省大量时间。不过要注意,AI生成的模板代码通常基于它训练时见过的“普遍风格”,不一定符合你项目的特定架构。你必须把项目中的既有模式作为示例放进提示词,让AI照着写,否则它生成的东西可能风格突兀,难以融入现有代码库。第二是辅助编写测试和补充边界输入。写单元测试往往是对人的耐心考验。你可以让AI根据被测函数的描述生成测试骨架和边界值组合。但不要盲目全收,测试代码至少要保证三点:断言是可验证的、没有忽略内部实现细节(过度模拟)、每个用例针对单一行为。一个容易踩的坑是AI生成的测试里大量使用了mock,导致测试跑了一堆但什么都没验证。这种情况在审查时要格外小心。第三是帮助解读分析和安全反馈。现代开发流程里,静态扫描和依赖审计结果是一堆冗长的报告。用AI把报告摘要成“问题严重性、影响范围、修复建议”的简洁方案,能极大降低阅读成本。这不算投机取巧,而是让AI做它擅长的事情——从混沌中提取重点。阵地战用AI的关键原则是:AI用于生成素材,人负责决策。你可以让AI产出初稿,但最终是否合入、如何合入,必须经过完整评审流程。把AI的输出当作一个水平不错的初级工程师提交的PR(Pull Request,合并请求),你不会直接合入,而是要review(审查)、提出修改意见、跑测试,再决定是否合入。这样想,既不会抗拒AI,也不会被AI带偏。2.3 工具选择的误区在聊这两种范式的应用时会遇到一个误区:把使用AI的工具类型和编程范式强行绑定。比如有人觉得用交互式对话生成代码就是游击战,而用带有项目级代码索引的AI插件就是阵地战。这个认知是片面的。工具只是载体。你用对话式窗口也可以做阵地战——比如在明确架构约束下,让AI生成某个服务模块的骨架代码;你用项目级AI插件也可以做游击战——比如在一个临时目录里快速建一个脚本,分析日志并输出结论。真正决定范式的是你对代码生命周期和质量的预期,而不是工具形态。我见过有人把能自动识别整个项目的AI助手当成“免死金牌”,让它在大型遗留代码库中盲目重构。结果AI基于不完整上下文生成了大段“看起来合理”的改动,经过测试后发现线上性能退化,最后只能回滚。这不是AI的错,是使用者用阵地战的逻辑去要求AI做一件只能在游击战中做的事情。反过来,也有团队坚持所有代码必须手写,禁止任何AI生成。这在如今已经越来越不现实。即便你不直接使用AI工具,你的协作者会用;而且AI生成的代码经过严格审查后,质量往往不低于人手写的平均水平。正确的做法是建立一个合理的使用规范:明确哪些环节可以交给AI,哪些必须人肉完成,以及每条AI生成代码的合入路径。3. 实战决策:什么时候打游击,什么时候打阵地3.1 判断规则:成本、重要性、可逆性说了这么多,落到实际项目里,最关键的问题是:怎么判断当前这个任务该用游击战还是阵地战?我这里有一套自己的判断标准,基于三个维度:失败成本、生命周期、可逆性。失败成本指如果这个代码写错了或后期出问题,会带来多大的损失。如果只是本地分析一个临时数据文件,写错了大不了重新分析,失败成本几乎为零,那就适合游击战。如果这是用户登录鉴权模块,写错了可能导致数据泄露或用户无法登录,失败成本极高,那就必须采取阵地战。生命周期指这段代码预计要存活多久。一次性脚本可能用完即弃,不需要过度工程化。但一个订单服务可能要存活五年以上,那从第一行代码起就要考虑可持续维护性。生命周期越长,越需要阵地战。可逆性则更微妙。有些任务即便失败成本高,但如果你能随时回滚到上一个稳定版本,那就不妨先以游击战的方式快速试探,拿到结果后如果决定确定方案,再转入阵地战做正式实现。可逆性高意味着可以大胆试错,可逆性低则必须小心。我通常用这三个维度给任务打个分。如果三项都指向“低保持性”,就痛快地打游击;如果有一项指向“高长期性”,就要提前设计阵地战路径。3.2 典型场景拆解:快速原型 vs 生产功能拿一个具体例子说明。假设你要开发一个“根据用户历史行为生成个性化推荐列表”的功能。第一步,你可能需要验证一种候选算法在你的数据集上是否有效。这时你可以快速写一个Python脚本,读取一小份采样数据,实现一个几十行的推荐逻辑,然后看效果指标。这段脚本的生命周期可能就是半天,不需要模块化,不需要错误处理,跑完就丢。这就是典型的游击战。第二步,算法验证成功后,你要把它集成到线上服务中。你必须考虑输入校验、异常处理、数据格式兼容、性能约束、日志监控、配置管理、单元测试等。这时候再让AI帮你写一个函数已经远远不够,你需要架构设计、接口定义、依赖管理。你甚至可以把游击队里验证过的算法逻辑作为参考输入给AI,让它按照目标架构生成嵌入代码,但同时要配合严格的代码审查和自动化测试。这是阵地战。两个阶段看起来是同一件事,但范式完全不同。如果你在第一步就用阵地战的思维去做,那你会花很多时间在建模和抽象上,结果发现算法不适用,白白浪费。如果你在第二步还用游击战的思维,直接把第一步的脚本部署到线上,后面维护成本会让你哭不出来。这种“先游击试探,再阵地固化”的路径,是我认为AI时代最实用的研发模式。AI让游击阶段的成本变得更低,也让阵地阶段的“生成初稿”变得更快,但两个阶段的转换不能错乱。3.3 结合案例演示:某跨平台系统的开发过程我在前几个月刚参与一个模拟项目X,是一个面向内部使用的跨平台数据填报系统。客户端需要支持Web和桌面两种环境,服务端需要对接多个第三方数据源。我们团队只有三个人,工期很紧。当时我们的做法就是用两阶段混合策略。最初一周,每人用AI辅助在本地写各种验证脚本:测Web端某个组件的性能是否能达标,测桌面端某个跨进程通信方案是否可行,测服务端对接第三方接口的认证流程能不能跑通。这些全部是游击战,一共留下了十几个临时脚本,但换来了我们对技术选型的信心。选型确定后,我们开始阵地战。先用AI把整个项目的目录结构和核心接口定义生成一个骨架,然后一个人负责服务端,一个人负责Web端,一个人负责桌面端。所有合入代码都必须通过另一个人review,并且跑完单元测试和集成测试才合入主干。AI在我们开发过程中主要用来生成DTO结构、API测试用例、跨平台的接口调用代码,但每次生成后我们都会基于真实签名和实际运行结果去修正。最后项目按期完成,后来接手维护的人也反映代码结构还算清晰。这个例子想说明的是:游击战帮你选方向,阵地战帮你修长城。两者不是对立,而是接力。4. 实操技巧与注意事项4.1 游击战中的纪律底线有些人觉得游击战就是“怎么快怎么来”,完全没有纪律。我得说,游击战也要有底线,否则后面容易翻车。第一,做好后事处理。既然知道是临时代码,写完后要么删掉,要么通过版本控制留在独立分支,不要让它混入主线的代码库。我见过太多项目源码库里留着各种“test1.py”、“final_final.py”,都是游击战留下的遗物,后来变成维护噩梦。我的习惯是:临时脚本统一放到一个名为/scratch的目录下,并添加.gitignore忽略掉,确保不会被误提交。第二,明确时间盒。为一个想法设置一个时间限制,比如3小时。无论是否成功,时间一到要么转入正式开发,要么彻底放弃。这样做的好处是防止你在“看看能不能跑通”这个无尽循环里浪费一整天。我有一次为了优化一个查询,让AI改了二十多轮提示词,结果最后发现最优方案是换一个索引。那次如果早一点停止游击、去读执行计划,就不会浪费那么多时间。第三,标注“未验证”状态。如果某些用AI生成的代码块虽然跑通了单个样例,但没有经过完整的测试,你仍然又不得不暂时保留它在项目里,必须用清晰的注释或文档标记它处于“原型状态”,告知后来人不要直接复用到生产代码中。这是对团队负责。4.2 阵地战的AI辅助工程实践阵地战里用AI,最怕的就是“黑箱信任”。我觉得有一套比较稳的实践路径,可以分享。第一,喂规则,不喂需求。在让AI生成代码前,先把项目的编码规范、目录结构、已有类似代码示例发给它,让它进行模仿。你甚至可以编写一份项目专属的“编码契约”文档,里面规定错误处理方式、日志格式、命名规范、禁止使用的依赖等。然后让AI严格遵循这个契约生成内容。这样生成结果至少有七成符合标准,后续人工改造成本大幅下降。第二,强制双人评审。无论AI生成的代码看起来多完善,都必须有至少一个其他人参与评审。哪怕是小型项目,也要养成这个习惯。AI生成代码的问题往往不在语法,而在意图偏差和盲区。比如某个函数看起来能工作,但它在极端输入下会抛出不合理的错误码;或者它用了某个副作用,会影响上游调用方。这些只有靠经验审出来,而不是靠AI发现。第三,善用AI生成测试和CICD流水线脚本,但需实测。AI生成CI/CD配置、Dockerfile、部署脚本也是节省时间的利器。但这两个领域潜藏环境差异问题。AI不了解你目标服务器的具体环境变量、网络限制和版本策略,所以生成的脚本可能有“本机可跑、线上跑不了”的问题。每个生成的脚本都要在干净环境里跑一遍,而不是直接推到仓库。第四,持续重构。不要认为进入了阵地战,代码就一成不变。随着需求演进,架构也要调整。AI可以帮助你分析现有代码的结构、识别重复模块、提出重构建议,但最终是否重构、怎样重构,仍需人来决策。阵地战不是死守,而是用纪律保证每一次移动都是有计划的。4.3 两者切换的过渡策略在实际项目中,细想之下你会发现游击战和阵地战并不是独立的阶段,它们之间需要一个平滑的过渡过程。我从一个阶段切到另一个阶段有一套固定的动作。先说从游击到阵地:准备正式开发时,我会先开一个“交接清单”。清点游击队产物中哪些可以被复用、哪些需要重写。然后把这些脚本的依赖整理清楚,写一份简短的方案文档,说明原型的处理逻辑和验证结论。接着再开始搭建正式的模块结构。这样做的目的是避免“把临时代码复制到正式项目里算完事”的衔接问题。从阵地到游击的情况也存在。有时候在主代码库中发现某个新功能存在多种实现思路,不想直接动代码,这时我可能新建一个分支,写个尽可能快的实验版本对比性能,再决定主分支怎么改。这个分支只需要验证结果,不需要保持质量,但必须明确它是实验分支,开发完成后就弃用。这相当于在阵地战中做一次有限范围内的前沿侦察。最忌讳的是在两者之间反复横跳,没有明确边界。比如在正式代码里边改边试,今天加一个临时if调试,明天不删就继续叠加功能。这会让代码库变成“游击区和阵地混杂”的无人区,既没有临时实验的灵活性,也没有正式代码的稳定性。我的经验是:代码存放的位置和主线的状态,必须明确区分。要么在实验分支,要么在主分支,不存在“半实验半正式”的中间状态。5. 常见问题与排查实录5.1 游击过头了怎么办?如果你发现代码库已经开始失控,到处都是没有注释的AI生成片段,而且没人能说清哪段是可靠的,那么恭喜,你已经“游击过头”了。处理办法是“重启阵地”。我和团队遇到过类似情况。当时我们做的解决方案分三步。第一步,先冻结新功能开发,把当前主线定为“非稳定状态”,所有后续工作都基于分支进行。第二步,对每个主要模块执行“重写评估”:判断代码是否可维护?是的话保留并补充测试;不是就基于现有行为重写,让AI生成初稿,然后人工修改并通过测试。第三步,把这次清理学到的经验写进团队规范,规定哪些目录不允许出现临时脚本。这个过程很痛苦,可能比一开始就用阵地战更慢。但它能止损。如果在失控早期发现,代价还可控。所以建议每个团队在立项时先约定“临时代码可以随意写,但不能随意进入主线”。一句话就能省很多事。5.2 阵地战过于僵化怎么办?反过来,有些团队在AI时代反而比过去更谨慎,所有代码都要求事先设计、层层审批。结果一个小功能要排期两周,最后被隔壁团队用批量脚本几天就做完了。这种僵化的阵地战会扼杀创新,导致团队失去敏捷性。我的建议是给阵地战加入“实验区”。在每个迭代里预留20%的“侦察时间”,允许成员在这个时间里做任何游击战式的小实验,包括在沙箱环境里测试新库、用AI快速搭建模拟场景、验证某个技术假设。实验的结果不要求进入产品,只要求总结成一份简报。这样既保持了产品稳定性,又不会错过技术革新。另外,对阵地战里的“防御工事”也要定期审视。比如某些模块的注释比逻辑还长、测试变成了单纯为了覆盖率而写、评审变成了走形式。这些都属于“防线腐烂”,并不是阵地战的本质。阵地战的本质是可控,而不是繁琐。当你觉得流程阻碍了合理生产力,就应该简化流程,而不是硬扛着。5.3 AI生成代码的质量评估最后聊一个非常具体的问题:我拿到AI生成的代码,怎么快速判断能不能收?虽然不能替代完整测试,但我有一个“快速体检清单”可以分享。查依赖。AI是否会生成不存在的库引用?是否用了一些不再维护或安全性存疑的包?我常在提示词里要求它列出全部依赖,然后再逐一核实。查异常处理。正常逻辑往往不难写,但异常分支最容易暴露出AI的盲区。我常问自己:“如果这个输入的值为空/超大/非法格式,这段代码会怎么办?”如果AI没有处理,就让它补全。查隐式副作用。比如函数是否修改了传入的对象、是否发起网络请求、是否读写全局变量。这些在生成代码中很常见,稍不留意就影响调用方。查性能,哪怕只是渐进复杂度。AI可能用了一个嵌套循环解决看起来简单的问题,在数据量小的时候无感,量大的时候直接卡死。给你的场景设定一个数据量上限,用最大输入去做一次抽检。刚才说的这些,说到底就是一句话:把AI生成代码当作一个不太可靠的初稿,而不是最终答案。你省下的时间应该在审查和测试上,而不是在赞叹AI的速度上。我在最初使用AI的时候也犯过省掉验证的错,结果上线后出了故障,当时花了一整天才定位到问题,定位后发现就是AI生成的那一小段缓存逻辑在低概率偶发时返回了脏数据。那次之后,我的所有项目都强制要求“AI生成代码必须走完整测试链”。我的几点实际体会我个人的感受是,AI没有把编程变成不需要思考的流水线,反而让“思考该采用什么范式”这件事变得更加重要。以前我不会去纠结临时脚本要不要做工程化,现在我会明确地给任务分类:这是游击,那个是阵地。分完之后再动手,效率反而更高了。最后再分享一个小技巧。我给电脑设置了一个别名命令,叫guerrilla,用来快速创建一个带时间戳的临时目录,所有探索性、一次性、验证性的脚本都扔在那里。目录里自动生成一个README.md,记录“这个实验想验证什么、结论是什么”。一周后如果目录里还有超过24小时没被读取的脚本,我会直接清空。这个习惯帮我保持了工作区的整洁,也让我在游击和阵地之间切换时,心里始终有数。不妨你也试试。
AI时代谈编程范式,总会听到两种声音:一种鼓吹“让AI写代码,人只要提需求”,另一种强调“AI写的是垃圾,必须严格工程化”。我自己的实践体会是,这两种说法都偏了。用两个军事概念来类比,刚好能说清问题:一种是“游击战”,轻装快跑,小步试探,打完就走;另一种是“阵地战”,挖壕沟、修工事、稳扎稳打,不图一时快,只求长期防线稳固。这两种范式在AI辅助编程的今天,不是二选一,而是要根据战场情况灵活切换。这篇文章把我这两年在实际项目里怎么用AI、怎么切换这两种策略的经验整理出来,包括踩过的坑和总结出的判断标准。1. 两种范式的定义与核心差异1.1 游击战:快、变、试错所谓“游击战”式的编程,核心特征是小、快、灵。你有一个想法,需要马上验证,于是写出一个可能是临时的脚本,可能是一次性数据处理,也可能是一个用来验证AI辅助编码工具的交互式原型。这种代码的生命周期很短,通常以小时或天为单位,写完之后可能就丢弃或者重写。我经常用这种方式处理三类任务:一是对AI编程助手“投喂”一个小需求让它生成一段函数,然后我快速跑个测试看结果对不对;二是自己脑中有个算法思路,但不确定边界条件,直接用示例数据让AI帮我把思路变成可执行代码,我再手工改;三是做一些“探索性”的实验,比如测试某个第三方库的新接口能不能满足性能需求,这时候写一个临时压测脚本,跑完就丢。游击战的优点非常明显:代价低、反馈快。因为你不指望这段代码活很久,所以不需要过多考虑扩展性、健壮性,也不需要写冗长的文档和注释。AI在这种场景下是完美的放大器。我把自然语言需求翻译成代码草稿,再人工审查关键逻辑,原本需要半天的工作可能十几分钟就完成了。但游击战也有致命弱点:它不适合需要长期维护的产物。如果你把游击战式的代码直接丢进生产环境,就像把临时搭建的茅草屋当作常驻营房。头几天没问题,一旦遇到并发增加、需求变更、团队协作,茅草屋就会漏风漏雨。我曾经接手过一位同事留下的“快速验证代码”,后来它变成核心服务的一部分,结果每次加需求都要花大量时间理清那团毛线球。1.2 阵地战:稳、全、长期“阵地战”式编程则完全相反。它强调系统设计、模块划分、接口约定、单元测试、持续集成、代码审查、完整文档。这种范式适合那些需要存活数年、多人协作、承载核心业务的产品。在这种模式下,AI的角色不是替你把代码“一口气写出来”,而是充当“副驾驶”——帮你在既定架构内生成符合模式的代码片段,补全重复性的模板代码,甚至协助你生成测试用例和文档。阵地战的核心价值是可预测性和可控性。你可能听过“如果代码跑得好就不要去动它”这句话。在阵地战里,宁可牺牲一点开发速度,也要保证代码的行为是可预期的。每一段代码被合入主分支之前,都要经过设计评审和测试验证。AI生成的东西再快,如果无法满足这层约束,就不能直接用。阵地战当然有代价:开发速度慢、开销大。一个小功能要经过设计、实现、测试、评审、发布流程,可能比游击战多花几倍时间。但中长期来看,这笔投入是值得的。因为它减少了后来人的认知负担,也降低了出事故的概率。尤其在金融、医疗、基础设施等“失败成本极高”的领域,阵地战几乎是唯一选择。1.3 为什么AI让这个对比更明显如果没有AI,这两种范式的区别虽然存在,但没有那么显眼。因为传统编程无论哪种方式,代码都需要人一行行写出来,游击战写得快也只是相对的。AI的介入让天平两端都变得更极端。一方面,AI让游击战的“快”达到了新的数量级——以前写一个原型可能还要手动敲几百行代码,现在基于清晰的提示词,AI能在一两分钟内生成一个可运行的最小版本。另一方面,AI也让阵地战的“雷区”变得更加隐蔽——生成的代码表面上结构完整、注释齐全,但里面可能藏有被篡改的逻辑、隐藏的安全漏洞,甚至引用了并不存在的包。如果不经过严格的代码审查和测试,你根本发现不了问题。这就是为什么现在讨论“AI时代编程范式”特别有意义。AI既可以是游击战中最锋利的匕首,也可能是阵地战中最容易引爆的地雷。关键不是选择哪一种,而是知道什么场景用匕首、什么场景必须修筑工事。2. AI工具对两种范式的影响2.1 AI助手如何放大游击战的效率先说说AI如何在游击战场景里发挥作用。这里不说具体某款产品,就聊通用的能力和用法。用AI做游击开发,我最常用的模式是“目标-验证-修正”循环。给AI一个清晰的目标描述,附带约束条件和示例输入输出,让它产出代码。然后我立刻用真实的样例数据去验证。如果结果不对,就根据报错信息或边界情况继续追问AI,让它修正,直到通过验证。这个循环里,人的关键动作有两个:写清楚提示词和设计验证用例。写清楚提示词不是把需求一句话丢过去就完事。你需要告诉AI输入输出的格式、边界条件、性能要求、禁止使用的库,以及代码应放在什么上下文中。我通常会这样组织提示词:我需要一个Python函数,接收一个整数列表,返回列表中的中位数。 要求: - 输入列表可能包含重复值,也可能为空 - 列表长度在0到10万之间 - 不要使用统计库之外的高级库 - 返回float类型 - 时间复杂度尽量接近O(n) 请同时给出三个边界测试用例。这种提示词生成的结果,往往比“帮我写个中位数函数”靠谱得多。因为AI不知道上下文,你必须替它把“战场地图”画清楚。至于验证,就算AI生成的代码看起来逻辑完美,也必须跑实际数据。我的经验是,AI生成的代码中初版的正确率可能在六成到八成之间,直接相信就等于给自己埋雷。但在游击战里,这个修正成本很低,失败也无所谓,大不了换个思路再来。这正是AI和游击战理念契合的地方:快速试错,允许失败。还有一类场景是“探索性任务”。比如你面对一个复杂的第三方SDK,不知道某个方法的具体行为。可以不用去看整个手册,直接让AI按你的理解生成一段调用代码,然后跑个测试看结果和你预想的是否一致。这种“用AI帮忙做实验”的方式,能把原本需要一两个小时查阅文档的工作压缩到十几分钟。这也是我在新项目启动时最常用到的能力。2.2 阵地战中AI如何成为“防御工事”一提到阵地战,很多人以为就是“不用AI,靠人写”,那就错了。阵地战恰恰可以充分利用AI,把它变成加固防线、降低重复劳动的工具。阵地战里AI最有价值的方向有三个。第一是生成模板代码和重复性结构。比如微服务中的配置类、DTO对象、Mapper接口、OpenAPI定义。这些代码本身技术含量不高,但量大且容易出错。让AI生成初稿,再由人审查和修改,能节省大量时间。不过要注意,AI生成的模板代码通常基于它训练时见过的“普遍风格”,不一定符合你项目的特定架构。你必须把项目中的既有模式作为示例放进提示词,让AI照着写,否则它生成的东西可能风格突兀,难以融入现有代码库。第二是辅助编写测试和补充边界输入。写单元测试往往是对人的耐心考验。你可以让AI根据被测函数的描述生成测试骨架和边界值组合。但不要盲目全收,测试代码至少要保证三点:断言是可验证的、没有忽略内部实现细节(过度模拟)、每个用例针对单一行为。一个容易踩的坑是AI生成的测试里大量使用了mock,导致测试跑了一堆但什么都没验证。这种情况在审查时要格外小心。第三是帮助解读分析和安全反馈。现代开发流程里,静态扫描和依赖审计结果是一堆冗长的报告。用AI把报告摘要成“问题严重性、影响范围、修复建议”的简洁方案,能极大降低阅读成本。这不算投机取巧,而是让AI做它擅长的事情——从混沌中提取重点。阵地战用AI的关键原则是:AI用于生成素材,人负责决策。你可以让AI产出初稿,但最终是否合入、如何合入,必须经过完整评审流程。把AI的输出当作一个水平不错的初级工程师提交的PR(Pull Request,合并请求),你不会直接合入,而是要review(审查)、提出修改意见、跑测试,再决定是否合入。这样想,既不会抗拒AI,也不会被AI带偏。2.3 工具选择的误区在聊这两种范式的应用时会遇到一个误区:把使用AI的工具类型和编程范式强行绑定。比如有人觉得用交互式对话生成代码就是游击战,而用带有项目级代码索引的AI插件就是阵地战。这个认知是片面的。工具只是载体。你用对话式窗口也可以做阵地战——比如在明确架构约束下,让AI生成某个服务模块的骨架代码;你用项目级AI插件也可以做游击战——比如在一个临时目录里快速建一个脚本,分析日志并输出结论。真正决定范式的是你对代码生命周期和质量的预期,而不是工具形态。我见过有人把能自动识别整个项目的AI助手当成“免死金牌”,让它在大型遗留代码库中盲目重构。结果AI基于不完整上下文生成了大段“看起来合理”的改动,经过测试后发现线上性能退化,最后只能回滚。这不是AI的错,是使用者用阵地战的逻辑去要求AI做一件只能在游击战中做的事情。反过来,也有团队坚持所有代码必须手写,禁止任何AI生成。这在如今已经越来越不现实。即便你不直接使用AI工具,你的协作者会用;而且AI生成的代码经过严格审查后,质量往往不低于人手写的平均水平。正确的做法是建立一个合理的使用规范:明确哪些环节可以交给AI,哪些必须人肉完成,以及每条AI生成代码的合入路径。3. 实战决策:什么时候打游击,什么时候打阵地3.1 判断规则:成本、重要性、可逆性说了这么多,落到实际项目里,最关键的问题是:怎么判断当前这个任务该用游击战还是阵地战?我这里有一套自己的判断标准,基于三个维度:失败成本、生命周期、可逆性。失败成本指如果这个代码写错了或后期出问题,会带来多大的损失。如果只是本地分析一个临时数据文件,写错了大不了重新分析,失败成本几乎为零,那就适合游击战。如果这是用户登录鉴权模块,写错了可能导致数据泄露或用户无法登录,失败成本极高,那就必须采取阵地战。生命周期指这段代码预计要存活多久。一次性脚本可能用完即弃,不需要过度工程化。但一个订单服务可能要存活五年以上,那从第一行代码起就要考虑可持续维护性。生命周期越长,越需要阵地战。可逆性则更微妙。有些任务即便失败成本高,但如果你能随时回滚到上一个稳定版本,那就不妨先以游击战的方式快速试探,拿到结果后如果决定确定方案,再转入阵地战做正式实现。可逆性高意味着可以大胆试错,可逆性低则必须小心。我通常用这三个维度给任务打个分。如果三项都指向“低保持性”,就痛快地打游击;如果有一项指向“高长期性”,就要提前设计阵地战路径。3.2 典型场景拆解:快速原型 vs 生产功能拿一个具体例子说明。假设你要开发一个“根据用户历史行为生成个性化推荐列表”的功能。第一步,你可能需要验证一种候选算法在你的数据集上是否有效。这时你可以快速写一个Python脚本,读取一小份采样数据,实现一个几十行的推荐逻辑,然后看效果指标。这段脚本的生命周期可能就是半天,不需要模块化,不需要错误处理,跑完就丢。这就是典型的游击战。第二步,算法验证成功后,你要把它集成到线上服务中。你必须考虑输入校验、异常处理、数据格式兼容、性能约束、日志监控、配置管理、单元测试等。这时候再让AI帮你写一个函数已经远远不够,你需要架构设计、接口定义、依赖管理。你甚至可以把游击队里验证过的算法逻辑作为参考输入给AI,让它按照目标架构生成嵌入代码,但同时要配合严格的代码审查和自动化测试。这是阵地战。两个阶段看起来是同一件事,但范式完全不同。如果你在第一步就用阵地战的思维去做,那你会花很多时间在建模和抽象上,结果发现算法不适用,白白浪费。如果你在第二步还用游击战的思维,直接把第一步的脚本部署到线上,后面维护成本会让你哭不出来。这种“先游击试探,再阵地固化”的路径,是我认为AI时代最实用的研发模式。AI让游击阶段的成本变得更低,也让阵地阶段的“生成初稿”变得更快,但两个阶段的转换不能错乱。3.3 结合案例演示:某跨平台系统的开发过程我在前几个月刚参与一个模拟项目X,是一个面向内部使用的跨平台数据填报系统。客户端需要支持Web和桌面两种环境,服务端需要对接多个第三方数据源。我们团队只有三个人,工期很紧。当时我们的做法就是用两阶段混合策略。最初一周,每人用AI辅助在本地写各种验证脚本:测Web端某个组件的性能是否能达标,测桌面端某个跨进程通信方案是否可行,测服务端对接第三方接口的认证流程能不能跑通。这些全部是游击战,一共留下了十几个临时脚本,但换来了我们对技术选型的信心。选型确定后,我们开始阵地战。先用AI把整个项目的目录结构和核心接口定义生成一个骨架,然后一个人负责服务端,一个人负责Web端,一个人负责桌面端。所有合入代码都必须通过另一个人review,并且跑完单元测试和集成测试才合入主干。AI在我们开发过程中主要用来生成DTO结构、API测试用例、跨平台的接口调用代码,但每次生成后我们都会基于真实签名和实际运行结果去修正。最后项目按期完成,后来接手维护的人也反映代码结构还算清晰。这个例子想说明的是:游击战帮你选方向,阵地战帮你修长城。两者不是对立,而是接力。4. 实操技巧与注意事项4.1 游击战中的纪律底线有些人觉得游击战就是“怎么快怎么来”,完全没有纪律。我得说,游击战也要有底线,否则后面容易翻车。第一,做好后事处理。既然知道是临时代码,写完后要么删掉,要么通过版本控制留在独立分支,不要让它混入主线的代码库。我见过太多项目源码库里留着各种“test1.py”、“final_final.py”,都是游击战留下的遗物,后来变成维护噩梦。我的习惯是:临时脚本统一放到一个名为/scratch的目录下,并添加.gitignore忽略掉,确保不会被误提交。第二,明确时间盒。为一个想法设置一个时间限制,比如3小时。无论是否成功,时间一到要么转入正式开发,要么彻底放弃。这样做的好处是防止你在“看看能不能跑通”这个无尽循环里浪费一整天。我有一次为了优化一个查询,让AI改了二十多轮提示词,结果最后发现最优方案是换一个索引。那次如果早一点停止游击、去读执行计划,就不会浪费那么多时间。第三,标注“未验证”状态。如果某些用AI生成的代码块虽然跑通了单个样例,但没有经过完整的测试,你仍然又不得不暂时保留它在项目里,必须用清晰的注释或文档标记它处于“原型状态”,告知后来人不要直接复用到生产代码中。这是对团队负责。4.2 阵地战的AI辅助工程实践阵地战里用AI,最怕的就是“黑箱信任”。我觉得有一套比较稳的实践路径,可以分享。第一,喂规则,不喂需求。在让AI生成代码前,先把项目的编码规范、目录结构、已有类似代码示例发给它,让它进行模仿。你甚至可以编写一份项目专属的“编码契约”文档,里面规定错误处理方式、日志格式、命名规范、禁止使用的依赖等。然后让AI严格遵循这个契约生成内容。这样生成结果至少有七成符合标准,后续人工改造成本大幅下降。第二,强制双人评审。无论AI生成的代码看起来多完善,都必须有至少一个其他人参与评审。哪怕是小型项目,也要养成这个习惯。AI生成代码的问题往往不在语法,而在意图偏差和盲区。比如某个函数看起来能工作,但它在极端输入下会抛出不合理的错误码;或者它用了某个副作用,会影响上游调用方。这些只有靠经验审出来,而不是靠AI发现。第三,善用AI生成测试和CICD流水线脚本,但需实测。AI生成CI/CD配置、Dockerfile、部署脚本也是节省时间的利器。但这两个领域潜藏环境差异问题。AI不了解你目标服务器的具体环境变量、网络限制和版本策略,所以生成的脚本可能有“本机可跑、线上跑不了”的问题。每个生成的脚本都要在干净环境里跑一遍,而不是直接推到仓库。第四,持续重构。不要认为进入了阵地战,代码就一成不变。随着需求演进,架构也要调整。AI可以帮助你分析现有代码的结构、识别重复模块、提出重构建议,但最终是否重构、怎样重构,仍需人来决策。阵地战不是死守,而是用纪律保证每一次移动都是有计划的。4.3 两者切换的过渡策略在实际项目中,细想之下你会发现游击战和阵地战并不是独立的阶段,它们之间需要一个平滑的过渡过程。我从一个阶段切到另一个阶段有一套固定的动作。先说从游击到阵地:准备正式开发时,我会先开一个“交接清单”。清点游击队产物中哪些可以被复用、哪些需要重写。然后把这些脚本的依赖整理清楚,写一份简短的方案文档,说明原型的处理逻辑和验证结论。接着再开始搭建正式的模块结构。这样做的目的是避免“把临时代码复制到正式项目里算完事”的衔接问题。从阵地到游击的情况也存在。有时候在主代码库中发现某个新功能存在多种实现思路,不想直接动代码,这时我可能新建一个分支,写个尽可能快的实验版本对比性能,再决定主分支怎么改。这个分支只需要验证结果,不需要保持质量,但必须明确它是实验分支,开发完成后就弃用。这相当于在阵地战中做一次有限范围内的前沿侦察。最忌讳的是在两者之间反复横跳,没有明确边界。比如在正式代码里边改边试,今天加一个临时if调试,明天不删就继续叠加功能。这会让代码库变成“游击区和阵地混杂”的无人区,既没有临时实验的灵活性,也没有正式代码的稳定性。我的经验是:代码存放的位置和主线的状态,必须明确区分。要么在实验分支,要么在主分支,不存在“半实验半正式”的中间状态。5. 常见问题与排查实录5.1 游击过头了怎么办?如果你发现代码库已经开始失控,到处都是没有注释的AI生成片段,而且没人能说清哪段是可靠的,那么恭喜,你已经“游击过头”了。处理办法是“重启阵地”。我和团队遇到过类似情况。当时我们做的解决方案分三步。第一步,先冻结新功能开发,把当前主线定为“非稳定状态”,所有后续工作都基于分支进行。第二步,对每个主要模块执行“重写评估”:判断代码是否可维护?是的话保留并补充测试;不是就基于现有行为重写,让AI生成初稿,然后人工修改并通过测试。第三步,把这次清理学到的经验写进团队规范,规定哪些目录不允许出现临时脚本。这个过程很痛苦,可能比一开始就用阵地战更慢。但它能止损。如果在失控早期发现,代价还可控。所以建议每个团队在立项时先约定“临时代码可以随意写,但不能随意进入主线”。一句话就能省很多事。5.2 阵地战过于僵化怎么办?反过来,有些团队在AI时代反而比过去更谨慎,所有代码都要求事先设计、层层审批。结果一个小功能要排期两周,最后被隔壁团队用批量脚本几天就做完了。这种僵化的阵地战会扼杀创新,导致团队失去敏捷性。我的建议是给阵地战加入“实验区”。在每个迭代里预留20%的“侦察时间”,允许成员在这个时间里做任何游击战式的小实验,包括在沙箱环境里测试新库、用AI快速搭建模拟场景、验证某个技术假设。实验的结果不要求进入产品,只要求总结成一份简报。这样既保持了产品稳定性,又不会错过技术革新。另外,对阵地战里的“防御工事”也要定期审视。比如某些模块的注释比逻辑还长、测试变成了单纯为了覆盖率而写、评审变成了走形式。这些都属于“防线腐烂”,并不是阵地战的本质。阵地战的本质是可控,而不是繁琐。当你觉得流程阻碍了合理生产力,就应该简化流程,而不是硬扛着。5.3 AI生成代码的质量评估最后聊一个非常具体的问题:我拿到AI生成的代码,怎么快速判断能不能收?虽然不能替代完整测试,但我有一个“快速体检清单”可以分享。查依赖。AI是否会生成不存在的库引用?是否用了一些不再维护或安全性存疑的包?我常在提示词里要求它列出全部依赖,然后再逐一核实。查异常处理。正常逻辑往往不难写,但异常分支最容易暴露出AI的盲区。我常问自己:“如果这个输入的值为空/超大/非法格式,这段代码会怎么办?”如果AI没有处理,就让它补全。查隐式副作用。比如函数是否修改了传入的对象、是否发起网络请求、是否读写全局变量。这些在生成代码中很常见,稍不留意就影响调用方。查性能,哪怕只是渐进复杂度。AI可能用了一个嵌套循环解决看起来简单的问题,在数据量小的时候无感,量大的时候直接卡死。给你的场景设定一个数据量上限,用最大输入去做一次抽检。刚才说的这些,说到底就是一句话:把AI生成代码当作一个不太可靠的初稿,而不是最终答案。你省下的时间应该在审查和测试上,而不是在赞叹AI的速度上。我在最初使用AI的时候也犯过省掉验证的错,结果上线后出了故障,当时花了一整天才定位到问题,定位后发现就是AI生成的那一小段缓存逻辑在低概率偶发时返回了脏数据。那次之后,我的所有项目都强制要求“AI生成代码必须走完整测试链”。我的几点实际体会我个人的感受是,AI没有把编程变成不需要思考的流水线,反而让“思考该采用什么范式”这件事变得更加重要。以前我不会去纠结临时脚本要不要做工程化,现在我会明确地给任务分类:这是游击,那个是阵地。分完之后再动手,效率反而更高了。最后再分享一个小技巧。我给电脑设置了一个别名命令,叫guerrilla,用来快速创建一个带时间戳的临时目录,所有探索性、一次性、验证性的脚本都扔在那里。目录里自动生成一个README.md,记录“这个实验想验证什么、结论是什么”。一周后如果目录里还有超过24小时没被读取的脚本,我会直接清空。这个习惯帮我保持了工作区的整洁,也让我在游击和阵地之间切换时,心里始终有数。不妨你也试试。