ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI编程基本功:需求拆解、代码审查与上下文管理实战

AI编程基本功:需求拆解、代码审查与上下文管理实战

1. 被“提示词焦虑”带偏的这一年

过去大半年,我身边做开发的朋友几乎都在焦虑同一件事:提示词写得不够好。各种“万能模板”“咒语大全”在群里疯传,好像只要背下几百条句式,就能让AI乖乖写出生产级代码。我自己也经历过这个阶段——收藏夹里塞满了几十篇提示词教程,每次让AI写代码前都要翻半天,试图拼凑出一个“完美指令”。

结果呢?代码该出bug还是出bug,逻辑该跑不通还是跑不通。更讽刺的是,有次我花二十分钟打磨了一段自认为精妙的提示词,AI洋洋洒洒生成了两百行代码,我贴进项目里一跑,编译直接报错三十七处。那一刻我突然意识到:问题根本不在提示词上,而在我自己都没想清楚要什么。

这个认知转变花了我不少时间。后来我观察那些真正把AI编程用得很顺的同行,发现他们身上有个共同点——不是提示词写得多花哨,而是工程基本功扎实得可怕。他们能精准描述需求边界,能快速判断AI生成的代码哪里有问题,能设计出AI容易理解和扩展的模块结构。这些东西,跟提示词技巧几乎无关。

所以这篇文章想聊的,就是那些被“提示词热”掩盖掉的真正基本功。如果你也经历过“提示词背了一堆,代码质量却没提升”的困惑,那接下来的内容应该能帮你把方向调回来。我会从需求拆解、代码审查、上下文管理、验证策略这几个维度,结合我自己踩过的坑,把每个基本功拆开揉碎讲清楚。

2. 需求拆解:AI听不懂“帮我写个登录功能”

2.1 为什么模糊需求是AI编程的第一杀手

“帮我写个用户登录功能”——这是我见过最多的AI编程指令,也是效果最差的指令之一。你把这句丢给AI,它大概率会给你生成一个包含用户名密码输入框、一个提交按钮、一段验证逻辑的代码。看起来没问题对吧?但等你真正往项目里集成时,问题就炸出来了:登录态怎么保持?Token存哪里?密码加密用哪种算法?失败几次锁定账号?这些AI全都没考虑,因为它根本不知道你的项目上下文。

我刚开始用AI写代码时,犯的就是这个毛病。脑子里有个模糊的想法,直接甩给AI,然后对着生成结果挑三拣四,觉得AI“不够聪明”。后来才明白,AI不是不够聪明,是我自己没想清楚。一个合格的后端在接到“写登录功能”这个需求时,脑子里会自动展开几十个决策点:认证方式用Session还是JWT、密码哈希用bcrypt还是argon2、登录失败要不要限流、多端登录怎么处理、Token过期时间设多久。这些决策点,才是真正决定代码质量的东西。

AI没有这些默认假设,它只会按照训练数据里最常见的模式来生成。而“最常见”往往意味着“最通用”,通用就意味着跟你的具体场景不匹配。所以需求拆解的本质,是把你脑子里那些隐性的工程决策显性化,变成AI能理解的明确约束。

2.2 把“一句话需求”拆成AI能执行的规格说明

我现在让AI写任何功能之前,都会先花五到十分钟做一件事:把需求拆成一份简短的规格说明。这份说明不需要多正式,但必须包含几个关键要素。

第一是输入输出定义。比如登录功能,输入是什么?是用户名加密码的JSON,还是手机号加验证码?输出是什么?是返回Token字符串,还是设置Cookie?这些必须写清楚。第二是边界条件。密码长度限制多少?用户名允许哪些字符?连续失败几次触发锁定?这些边界条件不写,AI就会自己编,编出来的往往不是你想要的。第三是依赖约束。项目里已经用了什么框架?数据库是什么?有没有现成的工具类可以复用?这些信息能帮AI生成更贴合项目的代码。

我通常会这样写规格说明:

功能:用户登录接口 输入:POST /api/login,body为 {username: string, password: string} 输出:成功返回 {token: string, expiresIn: number},失败返回 {error: string} 约束: - 使用项目现有的 UserService 查询用户 - 密码验证使用 bcrypt.compare - Token 使用 jsonwebtoken 生成,有效期 2 小时 - 连续失败 5 次锁定账号 15 分钟 - 用户名长度 3-20 字符,密码长度 8-32 字符

这份说明写下来也就几分钟,但AI生成的代码质量会有质的提升。因为它不再需要猜测你的意图,所有的决策点都被你提前锁定了。需求拆解的能力,本质上就是工程思维的外化——你能不能把一个模糊的想法,拆成一组明确的、可验证的约束条件。

2.3 拆解粒度:拆到什么程度才算够

这里有个常见的误区:有人觉得拆得越细越好,恨不得把每一行代码的逻辑都写出来。但这样做的结果是,你其实已经自己把代码写完了,AI只是帮你打字而已,完全失去了提效的意义。

我的经验是,拆解到“接口级别”就够了。也就是说,你定义清楚每个模块的输入输出和边界条件,但具体内部怎么实现,留给AI去发挥。比如登录功能,你定义清楚“验证密码用bcrypt”“生成Token用jsonwebtoken”,但具体怎么组织代码结构、怎么处理异常,让AI自己决定。这样既保证了方向正确,又保留了AI的灵活性。

另一个判断标准是:如果你把这份规格说明交给一个初级工程师,他能不能独立完成?如果能,那说明拆解粒度刚好;如果他看完还是一头雾水,那说明你漏掉了关键约束;如果他看完觉得“这不就是让我照着抄吗”,那说明你拆得太细了。

我踩过的一个坑是,有次让AI写一个数据导出功能,规格说明里只写了“导出用户数据为CSV”。结果AI生成了一个把全表数据加载到内存再拼接字符串的版本,数据量一大直接内存溢出。后来我补上了“分页查询,每批1000条,流式写入文件”的约束,问题才解决。边界条件和性能约束,是最容易被忽略但最致命的部分。

3. 代码审查:AI生成的代码,你敢直接合并吗

3.1 AI代码的典型问题模式

用AI写了一段时间代码之后,我总结出它最容易出问题的几个地方。这些模式反复出现,几乎成了AI代码的“指纹”。

第一个是过度防御。AI特别喜欢加各种用不上的空值检查、类型判断、异常捕获。有次它给我生成了一个函数,光参数校验就写了二十行,而实际上这个函数的调用方已经保证了参数合法性。这些冗余代码不仅让文件变长,还增加了维护负担。第二个是幻觉依赖。AI会引用一些根本不存在的库或方法,比如调用一个array.groupBy()——这个方法是某个新版本才有的,而我的运行环境根本不支持。第三个是逻辑漏洞。AI生成的代码在正常路径下往往没问题,但边界情况处理得很粗糙。比如循环里的索引越界、异步操作的竞态条件、错误处理的遗漏。

我印象最深的一次是让AI写一个文件上传的接口。它生成的代码看起来完美:接收文件、校验类型、保存到磁盘、返回URL。但我review的时候发现,它没有限制文件大小,也没有对文件名做安全处理。如果用户上传一个超大文件,服务器磁盘直接爆掉;如果文件名里包含路径穿越字符,可能覆盖系统文件。这些安全问题,AI完全没有考虑。

3.2 审查清单:我每次必查的五个点

经过反复踩坑,我整理了一份AI代码审查清单。每次AI生成代码后,我都会对照这五个点过一遍。

第一,依赖是否存在。AI引用的每个库、每个方法,我都会去确认它在当前项目版本里是否真实存在。这个检查花不了几分钟,但能避免大量“代码看起来对但跑不起来”的问题。第二,边界条件是否覆盖。空输入、超长输入、非法字符、并发调用,这些情况AI经常漏掉。第三,错误处理是否合理。AI要么不处理错误,要么把所有异常都吞掉。我会检查每个可能失败的操作是否有对应的处理逻辑。第四,性能是否有隐患。循环里有没有重复查询数据库?有没有把大数组反复遍历?这些在数据量小的时候看不出来,上线后就是事故。第五,安全是否有漏洞。SQL注入、XSS、路径穿越、权限校验缺失,这些是AI代码的高发问题。

这份清单看起来简单,但坚持执行下来,能拦掉八成以上的AI代码问题。代码审查的能力,才是AI编程时代最核心的竞争力——因为AI可以帮你写代码,但没法帮你判断代码对不对。

3.3 从“能跑就行”到“能维护才行”

刚开始用AI写代码时,我的标准很低:能跑通就行。但很快我就发现,这种心态会积累大量技术债。AI生成的代码往往缺乏一致性——这个文件用驼峰命名,那个文件用下划线;这个模块用类,那个模块用函数。单个看都没问题,合在一起就是灾难。

后来我把标准提高了一档:AI生成的代码,必须能通过项目的lint检查,必须符合现有的代码风格,必须有基本的注释说明。这些要求我会直接写进给AI的指令里。比如我会说“使用项目现有的ESLint配置”“函数命名遵循camelCase”“每个导出函数添加JSDoc注释”。加上这些约束后,AI生成的代码明显更“合群”了。

还有一个容易被忽略的点是可测试性。AI生成的代码经常把逻辑和副作用混在一起,导致很难写单元测试。比如一个函数既做数据计算又直接写数据库,你就没法单独测试计算逻辑。我会要求AI把纯逻辑抽成独立函数,副作用通过参数注入。这样虽然多写了几行代码,但后续维护和测试的成本大大降低。

4. 上下文管理:为什么AI总是“忘记”你之前说过的话

4.1 对话窗口的物理限制与应对策略

用AI写代码时,最让人抓狂的就是它“失忆”。你前面刚说过项目用TypeScript,聊了十几轮之后它突然给你生成JavaScript代码。你前面刚定义了数据模型,后面它就用了完全不同的字段名。这不是AI故意捣乱,而是对话窗口的物理限制——每个模型能记住的上下文长度是有限的,超出部分会被截断。

我刚开始不理解这个机制,总觉得是自己提示词写得不够好。后来才明白,再好的提示词也对抗不了物理限制。正确的做法不是试图让AI记住所有东西,而是主动管理上下文,把关键信息反复“喂”给它。

我的做法是维护一份“项目上下文摘要”,每次开新对话或者感觉AI开始跑偏时,就把这份摘要贴进去。摘要内容不多,但覆盖了最关键的约束:

项目技术栈:TypeScript + Node.js + PostgreSQL 代码风格:camelCase命名,2空格缩进,使用async/await 数据模型:User { id, username, email, createdAt } 现有工具:db.query(), hashPassword(), generateToken() 当前任务:实现用户注册接口

这份摘要每次贴进去也就几十个token,但能极大减少AI“失忆”的概率。上下文管理的本质,是把AI当成一个短期记忆有限但能力很强的协作者——你不能指望它记住所有细节,但你可以把最重要的细节反复强调。

4.2 用文件结构代替对话历史

除了贴摘要,我还有一个更彻底的做法:把项目结构直接告诉AI。具体来说,就是在对话开始时,把相关的目录树和关键文件的内容贴进去。这样AI就能“看到”项目的真实结构,而不是靠猜。

比如我要让AI写一个新的API路由,我会先贴出路由目录的结构:

src/ routes/ users.ts posts.ts services/ userService.ts models/ user.ts

然后再贴出users.ts的现有内容作为参考。这样AI生成的代码就会自然地遵循现有的模式,而不是自己发明一套。这个做法看起来笨拙,但效果出奇地好。因为AI最擅长的就是模式匹配——你给它看一个例子,它就能照着写出类似的代码;你不给它看,它就只能从训练数据里找“最常见”的模式,而那个模式往往跟你的项目不匹配。

4.3 长任务的上下文接力技巧

对于跨多个文件、需要多轮对话才能完成的大任务,上下文管理就更重要了。我的策略是分阶段推进,每个阶段结束时做一次“上下文交接”。

具体来说,我会把大任务拆成几个阶段:先定义数据模型,再写服务层,再写路由层,最后写测试。每个阶段结束后,我会让AI总结一下当前阶段的产出,包括新增了哪些文件、定义了哪些接口、有哪些约定。然后下一阶段开始时,我把这份总结贴进去,作为新阶段的起点。

这样做的好处是,每个阶段的上下文都是干净的、聚焦的,不会因为对话太长而混乱。而且阶段总结本身就是一份很好的文档,后续回顾时能快速了解当时的决策。我试过用这种方式完成一个包含十几个文件的模块,全程AI没有出现明显的“失忆”问题。

5. 验证策略:怎么知道AI写的代码真的对

5.1 先写测试再让AI实现

这是我最近半年养成的新习惯,也是我觉得最有效的一个策略:先让AI写测试,再让AI写实现。

具体操作是这样的:我先用自然语言描述功能需求,让AI生成一组测试用例。然后我审查这些测试用例,确认它们覆盖了正常路径、边界条件和异常情况。确认无误后,我再让AI根据这些测试用例来实现功能。这样做的妙处在于,测试用例本身就是一份精确的规格说明——它比自然语言更严谨,比代码注释更可执行。

举个例子,我要写一个“计算订单折扣”的函数。我先让AI生成测试:

describe('calculateDiscount', () => { it('普通用户满100减10', () => { expect(calculateDiscount(150, 'normal')).toBe(140); }); it('VIP用户满100减20', () => { expect(calculateDiscount(150, 'vip')).toBe(130); }); it('不满100不打折', () => { expect(calculateDiscount(80, 'vip')).toBe(80); }); it('金额为0返回0', () => { expect(calculateDiscount(0, 'normal')).toBe(0); }); });

这些测试写出来之后,功能逻辑其实已经定义清楚了。AI再根据测试写实现,几乎不会跑偏。而且测试本身可以反复运行,后续修改代码时也能快速验证有没有破坏原有逻辑。

5.2 用“反向提问”逼出AI的逻辑漏洞

AI生成的代码,表面上看往往逻辑通顺,但仔细推敲就会发现漏洞。我的一个技巧是反向提问:让AI解释它生成的代码,特别是那些关键判断和边界处理。

比如AI生成了一个函数,我会追问:“如果输入是空数组,这个函数会返回什么?”“如果两个参数类型不一致,会发生什么?”“这个循环在什么情况下会提前退出?”这些问题会逼着AI重新审视自己的代码,很多时候它自己就会发现之前没考虑到的情况。

这个技巧的原理是,AI在生成代码时是“顺向”的,它按照最常见的路径往下写;但在回答问题时是“逆向”的,它需要重新推理逻辑。逆向推理往往能发现顺向生成时忽略的细节。我试过很多次,让AI解释自己的代码后,它会主动说“这里确实有问题,如果输入为null会抛异常,需要加个判断”。

5.3 小步验证:不要一次性生成几百行

最后一个验证策略是控制单次生成的代码量。我刚开始用AI时,喜欢让它一次性生成整个模块,几百行代码一口气出来,看着很爽。但验证起来极其痛苦——你得逐行读,还得在脑子里模拟执行流程,很容易漏掉问题。

后来我改成小步验证:每次只让AI生成一个函数或一个类,生成后立刻写个小测试跑一下,确认没问题再继续下一个。这样虽然对话轮次多了,但每步都是可验证的,出了问题也能快速定位。这其实就是敏捷开发的思想——小步快跑,持续验证。AI编程的效率优势,不应该体现在“一次生成很多代码”上,而应该体现在“快速生成可验证的小块代码”上。

我现在的节奏是:一个函数一个函数地生成,每个函数配一个测试,跑通了再进下一个。一个包含十个函数的模块,大概需要二十轮对话,但全程几乎没有返工。相比之前“生成一大坨再慢慢调”的方式,总体时间反而更短。

6. 那些没人告诉你的实操细节

6.1 什么时候该放弃AI,自己动手

用了这么久AI编程,我最大的体会是:AI不是万能的,知道什么时候不用它,比知道怎么用它更重要。

有几类任务,我试过之后发现AI的效果很差,后来就果断自己写了。第一类是高度依赖业务上下文的逻辑。比如复杂的权限判断、特殊的计费规则,这些逻辑往往有大量隐性的业务约束,很难用几句话描述清楚,AI生成的代码看着对但细节全是错的。第二类是性能敏感的底层代码。AI生成的代码往往追求可读性,不太考虑性能,对于需要精细控制内存和CPU的场景,自己写更靠谱。第三类是调试类任务。让AI帮你找bug,它经常给出一些似是而非的建议,反而把你带偏。

判断标准很简单:如果你自己都说不清楚要什么,就别指望AI能写对。这时候正确的做法是先自己想清楚,或者先写个原型验证思路,等思路清晰了再让AI帮你实现。

6.2 建立自己的代码片段库

AI生成的代码,有些质量很高,可以直接复用。我养成了一个习惯:把AI生成的好代码片段收藏起来,按功能分类整理。比如“数据库分页查询”“JWT生成与验证”“文件上传处理”这些常见功能,我都会存一份经过验证的版本。

下次遇到类似需求时,我直接把之前的代码片段贴给AI,让它在此基础上修改。这样比从零生成快得多,而且质量更稳定。这个片段库其实就是你的“个人框架”——它积累了你对项目的理解、对代码风格的偏好、对常见问题的解决方案。AI可以帮你填充细节,但框架本身是你自己的。

我现在的片段库大概有几十个文件,覆盖了日常开发的大部分场景。每次开新项目,我都会先把片段库过一遍,看看哪些可以直接用。这个习惯让我的开发效率提升了很多,而且代码质量越来越稳定。

6.3 保持“手写代码”的能力

最后说一个可能有点反直觉的观点:越是依赖AI编程,越要保持手写代码的能力。

原因很简单:AI生成的代码,最终责任是你的。如果AI写了一段有问题的代码,你没看出来就合并了,出了事故背锅的是你,不是AI。而看出问题的能力,恰恰来自于你自己写代码的经验。如果你长期不手写代码,对代码的“手感”就会退化,审查AI代码时就会变得迟钝。

我现在的做法是,每周至少留出半天时间,完全不借助AI,自己从头写一个完整的功能。这个习惯让我保持对代码结构的敏感度,也让我在审查AI代码时能更快发现问题。AI是工具,不是替代品——它可以帮你写得更快,但不能帮你思考得更清楚。思考这件事,永远得你自己来。

7. 把基本功练成肌肉记忆

回过头看,我从“提示词焦虑”到“基本功回归”这个过程,其实是一个认知升级的过程。一开始我以为AI编程的核心是“怎么跟AI说话”,后来发现核心是“怎么把工程问题想清楚”。提示词只是表达方式,真正决定代码质量的,是你对需求的理解、对边界的把握、对质量的判断。

这些基本功,没有捷径可走。需求拆解能力,来自于一次次把模糊想法变成明确规格的练习;代码审查能力,来自于一行行读代码、一次次踩坑的经验积累;上下文管理能力,来自于对AI工作机制的理解和主动干预;验证能力,来自于对测试和调试的重视。这些东西,AI帮不了你,只能自己练。

但好消息是,这些基本功一旦练成,就会变成肌肉记忆。现在我看到一个需求,脑子里会自动展开成规格说明;看到一段AI代码,眼睛会自动扫描那几个高风险点;开新对话时,手会自动把上下文摘要贴进去。这些动作已经不需要刻意提醒了,就像骑自行车一样自然。

如果你现在还在纠结提示词怎么写,我的建议是:先放一放,去把需求拆解和代码审查练熟。这两项基本功到位了,哪怕你用最朴素的提示词,AI也能帮你写出靠谱的代码。反过来,提示词再花哨,基本功不到位,生成出来的东西还是没法用。这个道理,我花了大半年才真正明白,希望你能少走点弯路。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进