首页 / 资讯中心 / 文章详情

ChatGPT编写代码实战:提示词、验收与团队规范

ChatGPT编写代码实战:提示词、验收与团队规范 ★ FEATURED ARTICLE
1. 先把定位想明白ChatGPT 编写代码到底强在哪一环我把 ChatGPT 真正接进日常编码流程是从一次很普通的批量数据处理任务开始的。当时要写一个带失败重试、带并发上限、带超时控制的小工具逻辑不复杂但边角料特别多异常分类、退避时间、日志格式、参数校验写起来零零碎碎能耗掉小半天。我试着把需求按结构描述给它第一版代码出来之后我只改了三个地方就能跑。从那以后ChatGPT 编写代码这件事在我这里就不再是玩具而是变成了随手可用的生产力工具——它加速开发的部分并不在写出惊天动地的算法而在把你脑子里已经想清楚的东西快速落成可运行的样子并且顺手帮你把容易漏的错误兜住。先把话说透这个工具解决的问题是从想清楚到写出来之间的落差。你有清晰的输入输出、有明确的技术栈、有已知的边界条件那么它非常快你要是自己都没想清楚要干什么它只会把你的混乱翻译成一段更难读的混乱。所以这篇文章适合三类人看一是刚开始写业务代码、还处在知道要做什么但不确定怎么写才规范阶段的新手二是有几年经验、想把手上的重复劳动压缩掉的老手三是团队里负责代码质量、想搞清楚该怎么定规矩再放开用的人。不管你属于哪一类核心结论是一样的它的价值上限由你的提问质量决定它的风险下限由你的验收习惯决定。1.1 它在编码流程里实际承担的三种角色很多人对它的期待是帮我写完这个功能这个期待太大容易失望。我实际操作下来它在三个具体角色上表现最稳。第一种是需求翻译器。你手里有一段含糊的产品描述、一份看不懂的第三方接口文档、一段别人留下的没有注释的代码你需要先把它变成结构化的、能落地的东西。这时候让它做翻译而不是创作准确率会高很多。比如把一段中文需求翻译成接口签名、字段定义、状态机转移表这件事它做得又快又稳因为本质上是在做语言之间的映射而不是在发明新逻辑。第二种是样板代码生成器。CRUD、参数校验、DTO 转换、单元测试骨架、正则表达式、SQL 建表语句、日志埋点、配置文件的组装这类工作有固定套路、几乎没有创造性、但极其耗时。把它们交出去你省下的是最枯燥的那部分时间而且它生成的样板代码通常比你手敲的更整齐因为它不会因为困了就少写一个判空。第三种是审查者与解释器。这个角色被严重低估了。你把一段代码贴给它问这段在并发下有没有问题、这个异常分支会不会吞掉错误、帮我看看有没有更简单的写法它给出的意见经常能点醒你。它不会疲倦不会因为你问了蠢问题而不好意思也不会因为代码是同事写的就嘴下留情。我在做代码自查的时候这个用法出现的频率已经超过了生成代码本身。1.2 为什么加速和减少错误能同时成立表面看这是矛盾的写得快通常意味着错得多。它之所以能两头兼顾原因在于它压缩的是机械劳动时间而不是思考时间。人写代码的时候真正容易出错的地方往往不是逻辑设计而是那些高度重复、注意力最容易涣散的环节——第五个字段忘了加非空校验、第三个分支忘了关闭资源、第七个接口忘了处理超时。人在做第 N 次重复动作时出错率是上升的而机器做第 N 次和第 1 次是一样的。另一个原因是它默认会写得比你啰嗦。这个特点很多人嫌烦但在减少错误这件事上恰恰是优点它倾向于显式判空、显式捕获异常、显式写日志、显式声明类型。你自己写的时候为了快会省掉这些看起来没用的东西而错误往往就藏在被省掉的那几行里。我现在的习惯是让它先写一版啰嗦的然后我再决定哪些可以精简——做减法的成本远低于做加法这个顺序不能反。注意它生成的啰嗦里也包含大量无意义的防御性代码比如对一个已经确定为非空的主键再判一次空。这类冗余要删否则代码会越来越难读。判断标准很简单这个判空在当前调用链上有没有可能真的发生。1.3 能力边界哪些活给它哪些活碰都别碰我把任务分成三档。绿灯区样板代码、格式转换、正则、测试骨架、报错解释、代码注释与文档、小范围重构、SQL 语句初稿、脚本工具。这些任务的共同点是结果可以立刻验证跑一下就知道对不对。黄灯区业务核心算法、涉及金额与权限的判断、并发与事务控制、第三方库的深度用法。这些不是不能问而是必须逐行读懂再改绝不能直接合入。红灯区涉及密钥与凭证的处理逻辑、生产环境的运维脚本、加密与鉴权实现、数据库迁移脚本。这些一旦出错代价太大而且模型生成的内容你很难从表面看出问题。还有一个硬边界必须清楚它不能运行代码也不能看到你的运行环境。它不知道你的 Java 是 8 还是 17不知道你的依赖里那个库已经升到不兼容的大版本不知道你的数据库字段实际是什么类型。这些信息必须由你在提示词里补齐或者干脆把报错原文贴给它。指望它猜对你的环境是新手最常见的翻车原因。2. 提示词怎么写代码质量其实在第一句话就定了调我见过太多人说这东西写的代码不能用仔细一看他的提问是帮我写个登录功能。这种提问得到的必然是网上随处可见的教学级代码因为模型只能按最通用的场景去猜。你把约束给足了它的输出质量会有质的变化。我的经验是同一个人、同一个模型提示词从一句话变成结构化五段代码可用率能从三成提到八成以上。2.1 五段式结构把猜的空间压到最小我现在写提示词基本固定五段顺序也不怎么变。第一段交代角色与背景这段代码在什么项目里、上下游是谁、跑在什么环境。第二段说目标与输入输出函数的签名、参数含义、返回值结构、调用方期望什么。第三段列技术约束语言版本、框架版本、允许用哪些依赖、禁止用哪些写法。第四段写边界与异常空值怎么办、超时怎么办、失败重试几次、日志打什么级别。第五段给验收标准怎么算写对了需要配套哪些测试。段落作用常见缺失导致的问题角色与背景锁定场景避免通用教学代码给出与项目风格完全不匹配的写法目标与输入输出锁定接口契约参数名、返回结构反复返工技术约束锁定版本与依赖用了项目里没有的库、用了过时语法边界与异常锁定健壮性要求空值不判、异常被吞、日志缺失验收标准锁定完成定义不知道什么时候算写完无限迭代这里有个反直觉的点约束条件比需求描述更重要。需求描述决定它写什么约束条件决定它不能写什么。而实践中最容易出问题的恰恰是后者——它用了你项目里没有的工具类、它写了一个你的语言版本不支持的语法、它把配置硬编码在代码里。与其事后一行行改不如一开始就把只能用标准库不要引入新依赖必须兼容某个版本这些话写进去。2.2 让它先给方案再给代码直接要代码的最大问题是你拿到手发现思路就不对前面全白费。我改成了一个两步走第一步让它先说方案——数据结构怎么设计、分几步、每步的输入输出是什么、有哪些坑第二步我确认或者修正方案再让它落成代码。多花的这一轮对话通常能省掉后面三四轮返工。这个做法还有个副作用是好的方案阶段的文字是你能读懂的。代码你可能要逐行看但一段中文方案你扫一眼就知道有没有跑偏。对新手尤其推荐因为你在这个过程中顺便学到了这个问题通常怎么拆而不是只拿到一个黑盒结果。2.3 三个可以直接抄的模板下面几个是我用得最顺的改改就能用。第一个是生成函数背景一个内部数据同步任务Python 3.9只用标准库禁止引入第三方包。 目标实现 fetch_all(urls, max_workers8, timeout5, retries2) 返回 [(url, 状态, 内容或错误信息)] 的列表。 约束并发数不得超过 max_workers单个请求超时 5 秒 失败重试 2 次退避时间 0.5s、1s不得因单个失败中断整体。 异常网络错误、超时、非 2xx 状态码分别记录不同错误类型。 验收给出可运行的完整代码附 3 个单元测试用例覆盖全成功、 部分失败、全部失败三种情况。第二个是排错下面这段代码在我本地报错完整报错信息附在后面。 环境Python 3.9依赖版本已固定不能升级。 请先判断根因再给两种修法改动最小的 / 更规范的 最后说明为什么会出现这个报错。 代码…… 报错……第三个是审查请以代码评审的视角看下面这段代码只关注四件事 1. 可能的空值与越界2. 异常是否被正确传播3. 并发安全 4. 资源是否释放。每条问题指出具体行号、说明触发条件、 给出修改建议。不要评价命名风格和缩进。第三个模板里的不要评价命名风格很重要。不加这句它会给你一堆无关痛痒的格式建议把真正要命的问题淹没掉。提问时把范围收窄输出才有密度。提示如果它给的答案明显跑偏不要在原对话里反复修补直接开新对话重写提示词。旧对话里的错误上下文会持续污染后续回答越改越乱。3. 完整实操从一句需求到跑通的模块光说方法太虚我拿一个真实用过的小工具走一遍全流程。需求是批量请求一批接口地址收集结果失败的要重试整体要有并发上限最后输出一份汇总。这个场景足够通用你换成批量发消息、批量导数据、批量校验文件逻辑是同一套。3.1 第一步先把接口契约钉死我没有直接让它写代码而是先让它输出函数签名和返回结构。这一步的价值在于签名一旦定了后面所有代码都是围绕它填肉不会出现写着写着发现返回结构不对、整段推倒重来的情况。我最终确定的签名是fetch_all(urls, max_workers, timeout, retries)返回一个三元组列表分别是地址、状态、内容或错误。这里我特意要求错误信息也作为正常返回值而不是抛异常。理由很实际批量任务里单个失败是常态如果每个失败都抛异常调用方就得写一堆 try而且拿不到哪些成功了的完整结果。把失败当成一种正常结果返回调用方处理起来最省事。这类决策模型不会主动替你想你得先想清楚再告诉它。3.2 第二步生成骨架先跑通再优化第一版代码它给得很快结构大致是线程池加信号量控制并发每个任务内部做了重试循环。我拿到之后先做了一件事不看代码先跑一遍。跑通说明大方向没错跑不通就把报错贴回去。这一步不要急着逐行读因为很可能你读半天的地方它下一版就改掉了浪费时间。跑通之后我才开始读重点看三处并发数是不是真的被限制住了、重试的退避时间是不是按预期递增、超时是不是作用在单次请求而不是整个任务。这三处是这类代码最容易出问题的地方也是看起来对但实际不对的高发区。3.3 第三步把参数算清楚别拍脑袋参数这块我踩过坑值得单独说。重试次数和退避时间的关系是总耗时上限约等于单次超时乘以尝试次数再加上所有退避时间之和。按超时 5 秒、重试 2 次总共 3 次尝试、退避 0.5 秒和 1 秒算最坏情况下单个地址耗时是 5×3 0.5 1 16.5 秒。如果你的上游调用方设置的整体超时是 10 秒这个配置就是错的会先把调用方拖死。并发数也是同理。假设你要处理 800 个地址并发 8单个平均耗时 200 毫秒那么理论总耗时约 800÷8×0.2 20 秒。如果对端有每秒请求数限制比如限制在 20 QPS那并发 8 在 200 毫秒响应下正好顶到 40 QPS直接超限。这时候要么降并发到 4要么加令牌桶限流。我通常选后者因为限流比调并发更精确不会因为响应变慢就浪费吞吐。import time class TokenBucket: def __init__(self, rate, capacity): self.rate rate # 每秒补充的令牌数即允许的 QPS self.capacity capacity # 桶容量允许的瞬时突发 self.tokens capacity self.last time.monotonic() def acquire(self, n1): while True: now time.monotonic() self.tokens min(self.capacity, self.tokens (now - self.last) * self.rate) self.last now if self.tokens n: self.tokens - n return time.sleep((n - self.tokens) / self.rate)这段限流器是我让它生成的第三版。前两版分别用了time.time()和固定间隔 sleep前者在系统时间被调整时会出问题后者在突发流量下会误伤。第三版换成monotonic加令牌桶之后就稳了。这个迭代过程本身就是减少错误的典型样本错误不是靠一次写对避免的是靠一轮轮把边界想清楚挤掉的。3.4 第四步让它先写测试再让它改代码这是我认为收益最高的一步。让模型先写测试用例会逼它把什么算对想清楚而你想清楚的东西它写出来的代码自然会贴合。我通常要求覆盖四类全成功、部分失败、全部失败、参数非法。前三个覆盖主干第四个覆盖入口校验这四类能兜住八成的低级错误。有个细节要注意测试用例本身也要审。它写的断言有时候会顺着自己实现里的错误逻辑来形成测试通过但代码错的假象。比如它把重试次数实现成总共 3 次而不是额外 3 次测试里也按总共 3 次去断言看起来全绿实际不符合需求。所以断言必须对着需求文档看不能对着实现看。3.5 第五步重构交给它决策权留给自己代码能跑、测试通过之后我会让它做一轮重构提示词里限定只做三件事消除重复、简化嵌套、明确命名不改变任何外部行为。限制改动范围很关键不加这句它会顺手改逻辑把好不容易验证过的东西又搞乱。重构完必须重新跑一遍全量测试。这一步我用过的最笨也最有效的办法是重构前后各跑一次测试对比结果完全一致才接受。测试覆盖不到的地方宁可不重构——能跑的丑代码好过不能跑的漂亮代码这话在赶进度的时候尤其成立。3.6 一个容易被忽略的环节让它解释自己的代码最后一步我固定会做让它逐段解释刚生成的代码特别是那些我不太熟的写法。这个过程有两个好处一是你能立刻发现理解偏差二是它会暴露出自己其实没想清楚的地方——有时候它解释到某一行会开始绕那一行往往就是问题所在。我自己就靠这招揪出过一个把异常类型判断写反的分支。4. 踩过的坑这些问题不提前知道一定翻车下面这些全是我在实际使用中真实撞上的按出现频率排。新手看完这一节能省掉至少一半的调试时间。4.1 幻觉不存在的函数和过时的写法最常见的问题是它给出一个库函数名字看着特别合理实际根本不存在或者参数顺序不对。这类错误在 Java、Python 的第三方库里出现频率最高。判断方法很土但有效凡是你不认识的函数先查官方文档再信。它不会主动告诉你这个方法我不确定语气永远是那么笃定。另一个变种是过时写法。它可能给你一个三年前很流行、现在已经废弃的 API或者用了旧版本的语法。解决办法是在提示词里明确版本号并且要求如果某个 API 在当前版本已废弃请用官方推荐的替代写法并注明。这句话能过滤掉相当一部分问题。4.2 边界条件它默认世界是美好的它的默认假设是输入是正常的、网络是通的、文件是存在的。所以空列表、超长字符串、负数、零、重复元素、缺失字段这些情况它经常不处理。我现在的做法是在提示词里直接列一张边界清单让它逐条处理比事后自己补要省事。问题现象常见根因排查动作生成的函数不存在模型幻觉查官方文档确认签名再决定是否替换本地跑报语法错用了高版本语法提示词补语言版本要求兼容写法空输入直接崩缺少入口校验补空值、空集合、非法参数三类用例异常被静默吞掉过宽的 catch 块检查捕获范围要求区分异常类型并发下数据错乱共享可变状态检查是否有跨线程复用的容器或缓存测试全绿但功能不对断言顺着实现写断言对着需求文档重新核一遍依赖装不上引用了不存在的包或版本冲突限定只用现有依赖禁止新增性能突然变差循环内重复计算或重复建连检查循环体把不变的部分提到外面4.3 安全与合规三类代码必须人工把关第一类是拼接出来的查询语句。它有时候会为了省事直接用字符串拼接构造查询条件这在有外部输入的场景下是明显的风险点。规则很简单只要涉及外部输入必须是参数化写法不接受任何形式的字符串拼接。第二类是凭证与密钥。它倾向于把配置直接写成常量放在代码里因为这样示例最简洁。这在演示里没问题进仓库就是事故。我的做法是在提示词里明确要求所有敏感配置从环境变量读取代码中不得出现任何硬编码凭证。第三类是命令执行与反序列化。涉及执行外部命令、加载外部数据的代码一律逐行人工确认不接受看起来对。这类代码的错误往往不在语法层而在输入来源是否可信这一层模型看不到你的部署环境它给不出可靠判断。4.4 三个不出现在文档里的实操心得第一个让它把不确定的地方标出来。在提示词末尾加一句如果你对某个 API 或参数不确定请在代码注释里标注待确认。加上这句之后我审代码的效率明显提高因为注意力可以直接聚焦到它自己没底的地方。第二个不要在一次对话里跨领域切换。前面聊 Python 后端突然问 CSS 布局它的上下文会混乱答案质量下降。分开对话成本几乎为零收益很明显。第三个保存好用的提示词。我建了一个简单的文本文件按场景分类存模板用的时候复制改参数。这件事看起来笨但半年下来省的时间相当可观因为好提示词是试出来的试出来就该留住。5. 把它变成团队能力从个人技巧到可复用的规矩个人用得好是一回事团队里放开用是另一回事。我参与过一个小团队的试点最初两个月问题不少有人直接把它生成的代码合入主干评审时才发现风格完全不合有人把整段业务逻辑丢进去结果拿到一堆似是而非的东西。后来靠几条简单规矩稳住了。5.1 三条底线规矩第一条生成的代码合入前必须能说清每一行在干什么。这条听起来苛刻实际执行下来并不难因为大部分生成代码是样板读起来很快。真正的目的是拦住复制粘贴但不懂的情况这种代码出问题最难排查。第二条测试先行。凡是让它生成的功能代码必须配套测试且测试要经过人工审核断言是否对着需求写的。这条规矩把看起来能跑和确实正确区分开了效果立竿见影。第三条敏感区域禁止使用。凭证处理、权限判断、数据迁移这三块明确划为人工区不做讨论。有了明确边界反而没人再有争议执行阻力比想象中小。5.2 关于效率的真实体感关于到底能省多少时间我不太喜欢给一个漂亮的百分比因为不同任务的差异太大。我的真实体感是样板类任务的耗时大概能压掉六到七成理解类和设计类任务几乎不省时间甚至更慢因为你要花时间写清楚提示词、审代码。所以正确的用法是把省下来的时间投到设计和评审上而不是用来接更多任务。这一点想明白了工具带来的才是正向收益。另外有个现象值得注意用得越久提问会越短。因为你会逐渐摸清它的能力边界知道哪些信息必须给、哪些给了也没用。这跟带新人有点像前期沟通成本高磨合好了效率就上来了。我现在的提示词长度大概是刚开始的三分之一但产出可用率反而更高。5.3 我个人的一点使用习惯最后一个习惯分享给大家每次拿到生成结果我会先问自己一句如果这段代码上线后出问题最可能是哪里。答案往往就指向需要重点检查的那几行。这个动作花不了二十秒但拦住过我好几次。工具再好也只是工具判断力始终在人这边这句话我在用了两年之后体会比刚开始更深。
阅读完成 · 觉得有帮助?
咨询建站