
1. 大模型写代码这件事先把预期摆正先说一个我反复验证过的结论大模型生成的代码质量上限取决于你能不能把问题描述清楚下限取决于你有没有能力审查它。这两件事都跟模型本身关系不大跟你自己的工程素养关系极大。很多人第一次用大模型写代码输入一句“帮我写一个用户登录功能”拿到一段看起来像模像样的代码复制进项目里跑不通然后得出结论“大模型不行”。这个结论下得太快了真正的问题在于你给的信息量约等于零模型只能靠猜猜出来的东西当然不能直接用。我自己在项目里用大模型辅助编码有相当长一段时间了从最早的代码补全工具到现在的对话式生成踩过的坑能写满一个笔记本。最核心的体会是大模型是一个极度勤奋但完全没有上下文的初级工程师。它读过海量代码知道几乎所有常见写法的套路但它不知道你的项目结构、你的命名规范、你的依赖版本、你的业务约束、你的性能要求。你让它写代码本质上是在做一次“需求传递”传递质量决定输出质量。这篇文章想聊的不是“大模型能不能写代码”这种已经被讨论烂了的话题而是在实际软件工程项目里怎么用大模型才不至于给自己挖坑。适合两类人看一类是刚接触大模型辅助编程、还在兴奋期的新手另一类是用了一段时间、发现生成代码越来越难维护、想找到系统方法的中级开发者。我会从代码为什么会变成“屎山”、怎么写出能让模型理解的提示、生成之后怎么做审查和重构、以及哪些场景压根不该用大模型这几个角度把这件事讲透。先给一个判断标准你可以拿来自测如果你无法在五分钟内说清楚一段生成代码的输入、输出、边界条件和异常处理那这段代码就不该进你的项目。这个标准听起来苛刻但它能帮你挡掉百分之八十的麻烦。2. 生成代码变成“屎山”的四个真实成因2.1 上下文缺失模型在真空里写代码大模型生成代码时它看到的只有你输入的那段文字。你的项目里已经有一个UserService类里面封装了用户查询逻辑但你没告诉它它就会自己再造一个。你的项目用的是某个特定版本的框架API 签名和最新版不一样但你没说它就按训练数据里最常见的版本来写。你的团队约定所有数据库操作必须走统一的仓储层但你没提它就直接在业务逻辑里拼 SQL。这些问题的根源不是模型笨是信息不对称。我见过一个典型的例子有人让模型写一个分页查询模型生成了一段带LIMIT和OFFSET的 SQL。代码本身没问题但那个项目的数据库是分布式架构分页必须走特定的中间件 API直接写 SQL 会在数据量大时出现性能灾难。模型不知道这个约束它给出的就是“教科书上正确的答案”但在你的场景里是错的。解决这个问题的办法只有一个在提示里把上下文喂饱。不是简单说“帮我写个分页”而是把项目用的技术栈、已有的相关类、必须遵守的约束都写进去。这确实费事但比事后改代码省时间得多。2.2 过度自信模型不会说“我不确定”大模型有一个非常危险的特点它对错误的答案和正确的答案表现出同样的自信。你问它一个冷门库的用法它可能编出一个根本不存在的函数名但语气笃定得像是在引用官方文档。这种“幻觉”在代码生成里特别致命因为代码是要跑的编出来的 API 一跑就报错。我印象很深的一次是让模型帮忙写一个特定格式的日期解析。它给了一个看起来很合理的方案用了某个库的一个方法参数名和用法都写得有模有样。我差点就直接用了幸好习惯性地去查了一下文档发现那个方法根本不存在是模型把两个不同库的 API 混在一起编出来的。如果当时没查这段代码会在运行时直接抛异常而且报错信息可能很隐晦排查起来很费劲。提示凡是模型生成的、涉及第三方库 API 调用的代码必须逐个方法去官方文档核对。不要相信“看起来对”的代码。2.3 风格漂移每次生成都不一样同一个功能你让模型生成三次会得到三段风格不同的代码。第一次用for循环第二次用列表推导第三次用map。变量命名也是一会儿userList一会儿users一会儿userArray。如果把这些代码都塞进同一个项目读起来就像三个人各写各的维护成本极高。这个问题在单人开发时还不明显一旦团队协作就暴露了。代码审查的时候 reviewer 会疯掉为什么这个文件里有两种完全不同的错误处理风格为什么这个模块的命名规范和隔壁模块对不上这些不一致会慢慢累积最终让整个代码库变得难以理解。2.4 缺乏全局视角局部正确整体冲突模型生成代码是“局部”的它只关心你当前问的这个问题。但软件工程是“全局”的一个功能的实现可能影响到缓存策略、事务边界、日志规范、权限校验等一堆横切关注点。模型不会主动考虑这些它只负责把你问的那段逻辑写出来。举个例子你让模型写一个“更新用户余额”的方法。它写了一段很干净的代码查余额、判断是否足够、扣减、保存。逻辑上完全正确。但它没考虑并发问题——两个请求同时进来都查到余额足够都执行扣减结果余额变成负数。它也没考虑事务问题——扣减和保存之间如果抛异常数据就不一致了。它更没考虑审计日志——金融场景下每笔余额变动都必须留痕。这些都不是模型“写错了”而是它根本不知道这些约束存在。3. 把大模型当“高级实习生”用的正确姿势3.1 提示工程在代码场景下的具体写法网上讲提示工程的文章很多但大部分是泛泛而谈。在代码生成这个具体场景里有效的提示需要包含五个要素技术栈声明、输入输出定义、边界条件说明、已有代码引用、禁止事项列表。技术栈声明不用多说了Python 3.10 和 Python 2.7 写出来的代码完全不一样Django 3 和 Django 5 的 API 也有差异。输入输出定义要具体到类型和格式不要只说“传入用户信息”要说“传入一个字典包含 user_id整数、nickname字符串长度不超过 20、email字符串需要校验格式”。边界条件说明是很多人忽略的比如“当查询结果为空时返回空列表而不是 None”“当参数为负数时抛出 ValueError”。已有代码引用是最关键的一步。如果你项目里已经有一个工具函数format_response就把它的签名和用途贴给模型让它复用而不是重新造。禁止事项列表则是用来挡掉模型的一些“坏习惯”比如“不要使用全局变量”“不要直接打印日志使用项目统一的 logger”“不要引入新的第三方依赖”。我自己的习惯是维护一个“项目上下文模板”每次让模型写代码时先把模板贴上去再写具体需求。模板里包含项目结构说明、核心工具类列表、编码规范要点。这样做虽然前期要花点时间整理但后面每次生成代码的质量都会明显提升。3.2 让模型先“说思路”再“写代码”这是一个非常实用的技巧不要一上来就让模型输出代码先让它用自然语言描述实现思路。比如你可以说“我要实现一个功能需求是 XXX。你先不要写代码先用文字描述你打算怎么实现包括会用到哪些数据结构、处理流程是怎样的、有哪些边界情况需要考虑。”这样做有两个好处。第一你能快速判断模型是否理解了需求。如果它的思路跑偏了你在这一步就能发现不用等到代码写完再返工。第二思路描述本身可以作为代码的注释和文档后面维护的时候能快速理解这段代码的意图。等思路确认没问题了再让它基于思路写代码。这时候可以加一句“按照你上面描述的思路写出完整的代码加上必要的注释。” 实测下来这种“先思路后代码”的方式生成代码的可用率比直接要代码高不少。3.3 分而治之不要让它一次写太多大模型有一个上下文窗口限制虽然现在的窗口越来越大但生成质量会随着输出长度增加而下降。你让它一次写五百行代码它写到后面就会开始偷懒该处理的异常不处理了该加的注释不加了甚至逻辑都开始简化。正确的做法是拆分成小任务。一个完整的模块拆成数据结构定义、核心逻辑、边界处理、单元测试几个部分分别让模型生成。每次生成的代码控制在几十行到一百行左右这样质量最稳定。生成完一部分你审查通过之后再让它基于已有的代码写下一部分。这样模型始终在“小范围”内工作出错概率低而且你能及时发现问题。3.4 用测试用例反向约束生成质量如果你先写好测试用例再让模型写实现代码效果会好很多。测试用例本身就是最精确的需求描述输入是什么、期望输出是什么、异常情况怎么处理全都写清楚了。模型看到测试用例就知道自己要满足什么条件生成的代码会更有针对性。而且测试用例还有一个好处它是可执行的验证手段。模型生成的代码到底对不对跑一遍测试就知道了不用靠肉眼审查。我现在的习惯是对于逻辑比较复杂的函数先花十分钟写测试用例再让模型写实现最后跑测试。如果测试不通过把失败信息贴回给模型让它修正。这个循环通常两三轮就能得到可用的代码。4. 生成之后的审查与重构比生成更重要的一步4.1 代码审查的四个必查项模型生成的代码不管看起来多顺眼都必须经过审查。我总结了一个四步检查法按顺序过一遍能挡掉大部分问题。第一步查 API 真实性。所有调用的第三方方法、函数、类逐个去官方文档核对。重点看方法名是否拼写正确、参数顺序和类型是否匹配、返回值格式是否符合预期。这一步最枯燥但绝对不能省。模型编造 API 的情况比你想象中频繁得多。第二步查边界处理。看代码对空值、零值、负数、超长字符串、并发访问这些情况有没有处理。模型默认生成的代码通常是“快乐路径”只考虑正常情况异常分支需要你手动补上。你可以拿几个极端输入在脑子里过一遍看看代码会不会崩。第三步查资源管理。文件句柄、数据库连接、网络请求这些资源有没有正确释放有没有用try-finally或上下文管理器保证异常时也能清理模型有时候会忘记这些特别是在它专注于业务逻辑的时候。第四步查安全漏洞。SQL 注入、命令注入、路径穿越、敏感信息硬编码这些经典安全问题模型不一定每次都能避开。特别是当你的提示里没有强调安全要求时它可能直接用字符串拼接来构造 SQL。这一步需要你有基本的安全意识知道常见漏洞长什么样。4.2 把生成代码“翻译”成项目风格即使代码逻辑正确风格也可能跟项目格格不入。这时候需要做一次“风格翻译”把变量名改成项目统一的命名规范把错误处理换成项目统一的异常类把日志输出改成项目统一的 logger把配置读取改成项目统一的配置管理方式。这个过程听起来繁琐但其实很快因为逻辑已经对了你只是在做“表面调整”。我通常会在这一步顺便加上类型注解和文档字符串让代码更完整。如果项目有代码格式化工具跑一遍自动格式化能省不少事。4.3 什么时候该重写而不是修改有些生成代码改起来比重写还费劲。我的判断标准是如果修改点超过五处或者需要调整核心逻辑结构就直接重写。重写的时候可以参考模型的思路但代码自己写。这样虽然多花点时间但你对代码的掌控力更强后面维护也更容易。还有一种情况必须重写模型用了你不熟悉的库或写法。比如它用了一个冷门的工具库来实现某个功能代码看起来能跑但你不了解那个库的坑和限制。这种代码就是定时炸弹出了问题你都不知道从哪查。宁可自己用熟悉的方案重写一遍也不要留一个你看不懂的依赖在项目里。5. 那些不该交给大模型的编码场景5.1 核心业务逻辑与领域模型大模型可以帮你写工具函数、数据转换、格式解析这些“通用型”代码但核心业务逻辑和领域模型不建议交给它生成。原因很简单这部分代码承载了业务规则和领域知识而模型对这些一无所知。它生成的代码可能在语法上完美在逻辑上却违背了业务约束。比如一个电商系统的优惠券计算逻辑涉及叠加规则、互斥规则、有效期判断、用户等级折扣等一堆约束。这些规则是业务方经过反复讨论确定的模型不可能从你的简短描述里还原出来。让它写它只会写一个“看起来合理”的计算逻辑但细节全是错的。这种代码如果上了生产造成的资损可能非常严重。5.2 涉及安全与权限的代码认证、授权、加密、签名验证这些安全相关的代码也不建议让模型生成。不是说模型一定写不对而是安全代码的正确性验证成本极高你很难通过简单的审查确认它没有漏洞。而且安全领域有很多“反直觉”的最佳实践模型训练数据里可能包含一些过时或不安全的写法。我见过模型生成的密码哈希代码用了某个已经不推荐的算法虽然能跑但安全性不达标。如果开发者没有足够的安全知识很可能就直接用了。这种风险不值得冒。5.3 性能敏感的底层代码如果你的代码对性能有极致要求比如高频交易、实时渲染、大规模数据处理那模型生成的代码大概率不达标。模型倾向于选择“最常见”的写法而不是“最快”的写法。它可能会用一些方便但低效的数据结构或者忽略内存分配和缓存友好的问题。这类代码需要针对具体硬件和场景做深度优化模型没有这个能力。它可以帮你写一个能跑的版本作为参考但最终的性能关键路径必须自己打磨。5.4 与遗留系统深度耦合的代码遗留系统往往有一堆“历史遗留”的约定和坑比如某个字段虽然叫status但实际存的是枚举的字符串值某个接口虽然文档说返回 JSON 但实际返回的是 XML。这些信息不在任何文档里只存在于老员工的脑子里。模型不知道这些生成的代码必然对不上。跟遗留系统打交道的代码最好的方式是自己写或者让了解系统的人写。模型可以帮你写一些独立的工具来辅助调试但核心的集成代码不要交给它。6. 把大模型用出价值的几个实战习惯6.1 建立自己的“提示词库”用大模型写代码最浪费时间的事情是每次都要重新描述项目背景。我的做法是建一个文档把常用的提示词模板存下来。比如“写一个 Python 函数”的模板、“写一个单元测试”的模板、“重构这段代码”的模板。每个模板里都预置了项目的基本信息、编码规范、常用工具类。用的时候直接复制模板改一下具体需求就行。这个习惯能省下大量重复描述的时间而且保证每次给模型的信息量是一致的生成质量更稳定。6.2 保留“生成-审查-修改”的记录我建议把每次让模型生成代码的过程记录下来原始提示是什么、模型生成了什么、你做了哪些修改、为什么修改。这个记录有几个用处。第一下次遇到类似需求可以直接参考之前的提示和修改经验。第二如果团队里其他人也想用大模型辅助编码这份记录就是最好的培训材料。第三过一段时间回头看你能清楚看到自己在哪些地方容易踩坑有针对性地改进。6.3 定期评估哪些任务适合模型哪些不适合用了一段时间之后你应该对自己项目里“哪些任务交给模型效率高、哪些任务交给模型反而添乱”有一个清晰的判断。这个判断因人而异、因项目而异没有标准答案。我的经验是越是独立、越是通用、越是边界清晰的任务越适合交给模型越是耦合、越是特殊、越是需要领域知识的任务越应该自己动手。你可以做一个简单的分类把日常编码任务列出来标上“模型友好度”和“审查成本”。模型友好度高、审查成本低的任务放心交给模型模型友好度低或者审查成本高的任务自己写。这个分类会随着你使用经验的增加而不断调整。6.4 不要停止学习底层知识这一点可能是最重要的。大模型能帮你写代码但不能替你理解代码。如果你不懂数据结构、不懂算法复杂度、不懂操作系统原理、不懂网络协议你就无法判断模型生成的代码好不好、对不对、快不快。模型是放大器它放大你的能力也放大你的无知。我见过一些人用了大模型之后就不再看文档、不再学新知识遇到问题就丢给模型。短期看效率很高长期看能力在退化。一旦遇到模型解决不了的问题或者需要做架构决策的时候就完全抓瞎了。大模型是工具不是替代品。该学的底层知识还是要学该读的源码还是要读该踩的坑还是要踩——只是有了模型你可以踩得少一点、快一点。7. 一个具体的对比案例同一个需求两种用法为了把上面的观点讲得更具体我拿一个真实的需求来对比。需求是写一个函数从一段文本里提取所有邮箱地址去重后按字母序返回。用法一典型的新手用法直接输入“帮我写一个提取邮箱的函数”。模型生成了一段代码用了正则表达式逻辑基本正确。但有几个问题正则表达式没有考虑一些边缘格式去重用的是列表遍历而不是集合排序没有处理大小写。代码能跑但不够健壮。用法二有经验的用法输入一段完整的提示“用 Python 写一个函数extract_emails(text: str) - list[str]。要求1. 从 text 中提取所有邮箱地址2. 邮箱格式遵循常见规则本地部分允许字母数字和点号域名部分允许字母数字和连字符顶级域名至少两位字母3. 结果去重忽略大小写4. 按字母序排序排序时也忽略大小写5. 如果 text 为空或没有匹配返回空列表6. 不要引入第三方库只用标准库7. 加上类型注解和文档字符串。”模型生成的代码明显更完整正则表达式考虑了更多情况去重用了集合排序用了keystr.lower边界情况也处理了。虽然还是需要审查但修改量小得多。这两个用法的差距就是“把模型当搜索引擎”和“把模型当需要明确指令的实习生”的差距。你给的信息越精确模型的输出越可用。这不是模型的能力问题是使用方法的问题。8. 关于“GPT-6”这类新模型的理性预期每次有新模型发布都会有一波“编程要完了”“程序员要失业了”的讨论。我的看法是新模型确实会更强但不会改变上面说的这些基本规律。模型再强它也不知道你的项目上下文模型再强它也会编造 API模型再强它也需要你审查代码。这些问题的根源在于“信息不对称”和“责任归属”不是模型能力不够。新模型带来的提升更多是在“理解复杂需求”和“生成更长代码”这两个方面。以前需要拆成五步的任务可能现在两步就能搞定。以前生成两百行代码质量就下降现在可能五百行还能保持。但这些提升是量变不是质变。只要你还得为代码的正确性负责审查和修改的环节就省不掉。所以我的建议是对新模型保持关注但不要指望它替你解决根本问题。把精力花在提升自己的需求描述能力、代码审查能力、架构设计能力上这些能力不管模型怎么进化都是稀缺的。模型越强能清晰描述需求、能准确判断代码质量的人价值就越高。9. 我在实际项目里踩过的三个坑第一个坑是过度依赖模型的“自信”。早期我用模型写代码看它写得头头是道就懒得去查 API 文档。结果有一次用了一个不存在的方法代码在本地跑没问题因为那个分支没走到上了生产环境才报错。排查了半天才发现是模型编的。从那以后凡是模型生成的涉及外部调用的代码我一定逐个核对。第二个坑是让模型一次生成太多。有一次赶进度让模型一口气写了一个模块的完整代码大概四百多行。生成出来看着挺完整但仔细一查后面三分之一明显在“敷衍”异常处理全是pass注释也少了有几个函数甚至逻辑都不完整。后来我改成每次只让它写一个函数写完审查完再写下一个虽然看起来慢但总体返工少反而更快。第三个坑是忘了模型不知道项目约定。有一次让模型写一个数据导出功能它直接用了print来输出日志。但项目里明确规定必须用统一的 logger而且日志格式有严格要求。这段代码在代码审查时被打回来重写。后来我在提示模板里加了一条“禁止使用 print所有日志走项目统一的 logger”这个问题就再没出现过。这三个坑的共同点是问题不在模型在我给的信息不够或者审查不够。把这两个环节做好了大模型确实能显著提升编码效率。做不好它就是制造屎山的加速器。10. 最后分享几个实用小技巧如果你只记一件事记这个把大模型当成一个需要你带的新人而不是一个可以甩锅的专家。你带新人的时候会怎么做给他清晰的任务描述给他参考代码告诉他项目规范检查他的产出有问题让他改。用大模型也是一样的流程。另外几个零碎但有用的技巧生成代码时让它“加上详细注释解释每一步在做什么”这样审查的时候更容易发现逻辑问题让它“列出这段代码可能出错的三种情况”能帮你发现一些没想到的边界如果生成的代码用了你不熟悉的写法直接问它“有没有更简单、更常见的写法”通常能得到一个更好维护的版本。还有一个习惯我坚持了很久每次用模型生成代码之后问自己一句“如果这段代码出问题了我能快速定位吗”如果答案是“不能”那就说明这段代码要么太复杂要么用了你不熟悉的东西要么缺少必要的日志和注释。这时候要么简化它要么重写它要么补上足够的可观测性。这个习惯帮我挡掉了很多潜在的维护噩梦。大模型是个好工具但它不会替你思考。代码的质量最终还是取决于写代码的人——不管这个“人”是你还是模型把关的都是你。