小项目实战系列写到第二篇了。上一篇我们搭了一个能跑的最小系统,但说实话,越往后做,越发现真正让项目变“工程化”的不是功能和页面,而是接口设计和异常处理这两块。这俩东西平时不起眼,一旦线上出问题,全是它们埋的雷。所以这篇我就拿一个真实练手项目来聊聊,怎么让AI当帮手,把接口设计和异常处理这件事补齐、补好。
先说清楚这次要干什么:不是让AI一键生成整个后端,而是让它做你身边的“方案顾问+代码助理”——你定方向,它补细节;你定边界,它补异常分支。很多朋友用AI写代码的最大误区,是把它当搜索引擎,丢一句话就想要完整系统,结果生成出来的东西华丽但不落地。这次我们换个玩法,分阶段、带上下文地让AI参与设计,最后产出的是一套自己心里有数、代码也过得去的接口层。
这篇内容适合谁呢?适合那种已经能手写几个接口、但对“接口怎么设计才算完整”“异常处理到底要处理哪些东西”还没形成体系的人。不管是独立开发者还是团队内部做小工具,这套思路都能复用。
1. 先理清思路:AI在这个项目里到底帮你干了什么
动手之前,我花了十分钟想清楚一个问题:AI在我这个项目里,是写代码的,还是帮我想事情的?答案是后者,至少第一步是后者。接口设计和异常处理这两件事,本质上是“设计决策问题”,不是“编码问题”。你让AI直接甩给你50行代码很容易,但它为什么这么设计、漏了哪些边界条件,它不会主动告诉你。
1.1 这不是让AI自动写代码,而是让AI当编码搭档
我观察过不少AI编程翻车现场,问题都出在协作方式上。开发者把要求往对话框里一贴,AI一口气生成200行接口代码,看着挺完整,实际审代码的时候发现:鉴权逻辑写死了、错误码命名风格跟项目里其他模块对不上、数据库字段和DTO字段混淆、该做幂等的地方完全没处理。为什么会这样?因为AI在单轮对话里没有足够的上下文,只能基于“最常见的惯例”猜测你的需求。
我这次的做法是反过来:把AI当团队里的“方案评审同事”。先我自己想清楚这个接口要解决什么问题、调用方是谁、在什么场景下失败,然后把我的半成品思路喂给AI,问它“帮我看看这里有没有漏掉的情况”。AI吃进去的是结构化的思考过程,吐出来的才是能用的建议和代码。这个过程有点像写论文时的“导师修改意见”和“文字校对”的角色分离——方向你定,细节它补。
从实操反馈看,这个协作方式有两点好处。第一,AI的建议通常是枚举型的,它会像背过教科书一样列出“可能还需要考虑参数校验、鉴权失败、数据库异常、第三方超时……”这些分支场景,等于帮你做了一次系统的检查清单复核。第二,因为上下文是你喂的,它补出来的代码风格能贴合你的项目结构,而不是天马行空另起炉灶。
1.2 接口设计和异常处理为什么容易出问题
做小项目的时候,我们往往会觉得接口设计“不重要”——反正就自己用,或者就前后端两个人联调,能跑通就行。这种想法短期没问题,但项目一旦开始加功能、换人维护、被外部系统调用,之前偷的懒全都要还。接口设计的本质是“契约设计”,契约定得含糊,联调阶段就会来回扯皮:谁参数格式不对、谁错误码理解错了、谁把异常吞了。这些问题最后都会变成“隐藏债务”,在某个深夜上线的时候集中爆发。
异常处理则是另一个极端。不少开发者只在主流程写了try/catch,异常往上抛、往下吞,或者干脆不处理。最典型的是两种情况:第一种,把异常吞掉(catch后什么都不干),导致问题发生但完全无迹可寻;第二种,把异常直接堆给前端,返回一个500,前端拿到之后只能弹个“服务器错误”,用户完全不知道是自己参数错了还是没权限还是系统繁忙。
所以这次小项目实战,我把重心放在“设计”阶段,用AI辅助我们把接口的细节和异常的边界都补完整,再进入编码。我习惯把这套东西叫做“接口的七件事”和“异常三层设计”,后面小节我会拆开讲。
2. 接口设计的核心要素与AI协作分工
接口设计这件事,说复杂其实也简单,无非是把“我要提供什么能力”“别人怎么调用我”“失败长什么样”讲清楚。难的是每次都面面俱到,尤其是小项目里时间紧,很容易漏项。这里我把自己常用的接口设计检查清单分享出来,再讲讲怎么用AI生成第一版草稿、怎么评审和修订。
2.1 一个接口必须交代清楚的七件事
我在实战里总结了一个“接口七件事”清单,凡是写接口设计文档,我都会对着这个清单过一遍。AI在这里的作用,就是帮我把这些事项按项目上下文一一展开。
第一,接口的URL和版本号。URL怎么设计?是RESTful风格还是自定义路径?要不要把版本号放在路径里,比如/api/v1/order?第二,HTTP方法。GET/POST/PUT/DELETE各表示什么语义,是否幂等,是否会被缓存——这些细节很多人不在意,但真出了问题很难排查。第三,请求参数。Query参数、Path参数、Body参数各是什么,哪些必填哪些选填,参数格式是什么(JSON还是表单),最大长度限制,枚举值列表。第四,响应结构。成功时返回什么结构,直接返回业务数据还是包一层统一响应体,分页怎么表示。第五,错误码。业务错误码和HTTP状态码怎么对应,错误信息用什么语言和格式,是否给调用方提供排查ID。第六,鉴权方式。Token怎么放,过期怎么办,哪些接口公开哪些需要登录态。第七,限流与幂等。这个接口会不会被刷,关键操作是否需要幂等键。
这七件事我不可能在每轮跟AI对话里都重复一遍,所以我准备了一个“接口设计提示词模板”,每次把业务场景往里面一填,AI就能基于这个固定骨架生成完整方案。这比每次换措辞重新描述需求要稳定得多。
2.2 怎么给AI下需求:提示词模板与案例
我用过一次很失败的AI设计接口经历,就是只丢了一句“帮我设计一个订单接口”,结果它给了我三十多行代码和一个极其简陋的返回体。后来我学了一个教训:想要正交输出,就必须正交输入。AI对你的项目情况一无所知,它只能根据你的描述去推测标准做法。
下面是我现在实测下来比较稳定的一套提示词模板,你可以直接抄走:
我正在维护一个[模块]服务,技术栈是[语言/框架],需要新增一个[业务场景]接口。 下面是已有的项目背景: - 用户体系:[简单说明用户身份和鉴权方式] - 数据库表:[列出关键表名和字段] - 已存在的统一响应结构:[贴一个例子] 请按以下结构帮我完成接口设计: 1. 接口路径和HTTP方法,并解释为什么这样设计; 2. 请求参数表(字段名、类型、是否必填、校验规则、示例值); 3. 成功响应示例和失败响应示例; 4. 可能的异常场景清单,至少列出10种,每条注明对应的HTTP状态码和业务错误码; 5. 是否需要幂等/重试机制,如果需要,给出建议方案。把这段模板扔进去之后,AI给出来的内容质量明显提升了一个档次。它不再只给代码,而是先给设计决策,再给具体字段,最后给异常场景。我在实战项目里用这个模板设计了一个“订单状态查询”接口,AI列出的异常场景里就有“订单号不存在、订单不属于当前用户、订单已被删除、订单状态尚未初始化、下游支付系统超时”等细节,其中至少有3个是我自己一开始没想到的。
2.3 AI给出的方案怎么评审和修订
AI给出方案只是第一步,真正的重头戏是评审。我习惯问AI这么几个问题:“你设计的参数校验和现有项目里的统一异常处理方式是否匹配?”“如果这个接口被高频调用,哪些地方会成为瓶颈?”“请求量上来之后,这个方案最大的风险点是什么?”用这几个问题反复追问,能逼出AI方案里的隐藏假设。
比如我这次设计的订单查询接口,AI第一版建议把订单详情直接透传给前端,但我追问了一句“如果订单数据中有内部备注字段,是否需要区分字段权限”,它立刻补充了字段裁剪逻辑,把内部备注和信息分离开。这个点如果我不追问,等联调完再发现,又要改后端响应结构和前端渲染逻辑,来回成本翻倍。
还有一个技巧:让AI在输出方案的同时标注“我在这里做了哪些假设”。这样你在评审的时候就有了一个“假设清单”,逐条确认即可。AI默认假设的东西,往往恰好是项目里最需要你拍板的东西——比如“ID生成方式默认用雪花算法”“鉴权默认用Bearer Token”“错误信息默认返回中文”。这些假设要全部变成明确决策,接口设计才算真正落地。
3. 异常处理的完整设计:从错误码到全局兜底
接口设计定下来之后,紧接着就是异常处理。我见过很多项目接口文档写得很漂亮,但异常处理部分空空如也,只有一句“发生错误时返回错误信息”。真到排查问题的时候,全靠日志肉眼扫描。
3.1 异常处理的三层结构
我在实战中把所有异常处理归纳成三层,每层各管一件事。第一层是接口入口层,负责拦截所有进入接口的异常,把业务异常和系统异常翻译成统一的响应格式。第二层是业务逻辑层,负责处理“可预期的异常分支”,比如订单不存在、余额不足、权限不足,这一层要抛出业务异常,携带明确的错误码和提示信息。第三层是基础设施层,负责捕获第三方调用超时、网络抖动、数据库连接失败等不确定异常,做降级和重试决策。
用AI辅助的时候,我会先让它把这三层结构梳理成一张检查表,然后针对每一层脑暴异常场景。AI比较擅长做这种“枚举式思考”,你问它“这个接口在业务逻辑层可能抛哪些异常”,它能一口气列十几条,虽然不全对,但用来当检查清单绝对够用。我再人工筛一遍,把不符合项目场景的删掉,把遗落的补上,效率比自己凭空想快很多。
这里有个严重的反模式,必须提醒一下:不要在每一层都try/catch然后吞掉异常。三层结构的核心原则是“异常只处理一次,在入口统一出口”。如果你在业务逻辑层catch了异常但不抛,在入口层就永远看不到真实原因,排查问题会极其痛苦。我自己的习惯是:业务逻辑层的异常不捕获,直接抛到入口层统一处理;只有跟外部系统交互时才会在基础设施层做捕获,因为要决定是否重试。
3.2 用AI生成错误码表和边界case
错误码是接口设计里最琐碎、最容易被糊弄的部分。很多项目直接返回HTTP状态码,比如用户密码错误也返回400“Bad Request”,前端根本不知道具体哪里错了。我在实战项目里设计了一套简单但有效的错误码体系:统一用6位数字,前两位代表模块,中间两位代表场景,后两位代表具体错误原因。
这个体系也是我和AI一起敲定的。我先定好规则,然后让AI按规则帮我生成整个错误码表。比如订单模块是01,支付模块是02,用户模块是03。订单号不存在就是010101,订单不属于当前用户是010102,订单状态非法是010103……这样定完之后,前后端联调用错误码对状态,非常高效。
除了错误码,我还让AI生成了边界case清单。所谓边界case,不是“系统挂了怎么办”这种宏观问题,而是“列表页传page=-1怎么办”“搜索关键字全是空格怎么办”“批量接口里混入重复ID怎么办”。这些细节特别适合让AI枚举,因为它见过大量框架的校验惯例,能给出很全面的候选清单。我再逐个决定:哪些拒绝、哪些截断、哪些去重、哪些容忍。
3.3 超时、重试、幂等这些易忽略的点
接口设计里最容易忽略的,其实是超时和重试。你设计的接口响应再快,也架不住下游服务慢或者网络抖动。有一次我做一个AIGC相关的工具接口,内部要调用一个大模型的推理服务,正常情况下2秒返回,但高峰期能拖到30秒。如果前端接口超时设置的是5秒,用户大概率在推理还没结束时就看到“网络错误”了。
这个问题的解决思路我是这么定的:接口本身不做同步等待,改成异步任务模式,先返回taskId给前端,前端轮询或走WebSocket接收结果。AI在这里帮了大忙,我给它描述了“大模型推理耗时不确定”这个约束后,它帮我补了任务状态机的设计(PENDING/RUNNING/SUCCEED/FAILED/CANCELLED),还顺带提示了任务过期清理策略。这个方案不是说AI有多聪明,而是它提醒了我去考虑“耗时不确定”这一类场景。
幂等性也是一个高频但容易被忽略的点。你自己写一个创建订单接口,重复提交两次,如果没有任何幂等机制,就会产生两笔一模一样的订单。我习惯用一个简单方案:客户端生成一个UUID作为Idempotency-Key放在Header里,服务端记录这个Key的处理状态,重复请求直接返回第一次的处理结果。这个方案的完整代码逻辑,我直接描述给AI让它补写出来了,它甚至帮我处理了“并发重复提交”时数据库唯一索引冲突的问题。
4. 实操:从零到一做一个带完整异常处理的接口
理论说了那么多,现在手把手过一遍实操。这次我把场景设定为一个“订单查询接口”,因为订单场景天然带用户鉴权、数据权限、状态流转、外部依赖,非常适合演示接口设计和异常处理。整个流程我会拆成三部分:先搭接口设计文档,再让AI生成代码,最后做一次模拟走查。
4.1 场景设定:订单查询接口
假设我们有一个电商小系统,用户登录后可以查询自己的订单列表和订单详情。技术栈选我最常用的Node.js + Express,数据库用PostgreSQL。表结构很简单:orders表有id、user_id、order_no、status、total_amount、created_at、updated_at字段;order_items表是子订单明细;users表有用户基本信息。鉴权方案用JWT,登录后前端把Token放在Authorization头里。
我这次要设计的接口是“订单详情查询”:GET /api/v1/orders/:orderId。它需要承载几个明确的需求——只能查到自己的订单,管理员可以查任意订单;订单状态需要返回给前端可读的状态文案;如果订单还在“待支付”状态,前端需要能拿到支付倒计时。这些业务规则是接口设计的基础约束,是不能省的前提。
动手之前我先自己把核心流程捋了一遍:从Header取Token解析出userId,然后查订单表,校验订单归属,组装返回体。每一步可能出什么问题,也在纸上列了一遍。接下来就该AI上场了。
4.2 用AI生成接口设计文档的一版草稿
我把前面提到的提示词模板填好业务场景发给AI,要求它输出完整的设计文档。这一版草稿出来后,我重点检查几个地方:第一,异常场景清单是否覆盖了鉴权失败、订单不存在、订单不属于当前用户、数据库异常;第二,返回字段是否包含前端真的需要的渲染信息;第三,错误码是否符合我预设的6位数字规范。
AI给的草稿里有几个亮点,让我觉得这个协作方式确实值得推广。它主动补了一个“order_id格式校验”的规则,建议把ID格式约束为纯数字且长度不超过20位,防止用户传入恶意超长字符串拖垮数据库查询。它还在返回结构里加了“server_time”字段,方便前端统一做倒计时校准——这个跨时钟域的问题我自己一开始完全没考虑到。
当然,AI的草稿也免不了要改。它默认把错误信息设计成英文“Not Found”,但我们的请求里明确说了错误信息返回中文。它还建议把“订单详情”做成包含子订单列表的嵌套结构,但我预期前端会分两个接口分别拉取,所以做主从结构更合适。这个“AI给出草稿、人工校正决策”的过程,反复迭代两三轮之后,文档基本就能用了。
4.3 在IDE里让AI补齐代码和异常分支
设计文档定稿后,进入编码阶段。我用的是目前开发圈子里比较流行的AI编程插件,直接在IDE里对话补全代码。我的习惯是一段代码一个小目标,不一次性让AI生成整个文件。拿订单查询接口举例,我把目标拆成三层:先补“根据订单ID查订单并校验归属”的核心逻辑,再补“统一异常处理中间件”,最后补“参数校验”。
第一阶段,我给AI的上下文是:已有Orders模型、JWT鉴权中间件、统一响应格式工具函数。要求它实现“查询订单详情并校验订单归属”的服务函数。AI补出来的代码把查询和归属校验都放进了一个Service函数,这符合我们项目的分层习惯。
代码里有两个细节我觉得值得提。第一,AI查询订单后用了一个显式的空判断,而不是直接通过“if err”一路抛,这样能在空订单时给出业务层面的明确提示。第二,AI自动把“订单号”和“订单ID”两个概念分开处理了,避免在接口参数里混用语义不清的字段。这些小细节看似不起眼,但对于代码可读性影响很大。
第二阶段,我让AI写全局异常处理中间件。我给它定了两条规矩:业务异常(BizError)统一返回错误码和中文提示,未预期异常记录日志并统一返回“系统繁忙”。AI按照这个约定生成了异常过滤器,并在日志里记录了完整的请求路径、参数、错误堆栈和耗时。这样排查问题时不再需要去翻每段代码找打点,一个全局出口全部搞定。
第三阶段,参数校验。我没用第三方校验库,而是让AI手写了一个轻量校验函数,校验orderId格式、Authorization头是否存在、是否Bearer前缀。AI给出的方案很克制,没有过度设计,只做了必需的三项。这让我再次确认了一个经验:让AI补齐代码时,限定范围比开放问答可靠得多。
5. 常见问题与排查技巧实录
实操过程中肯定会踩坑,我把我遇到的几个典型问题整理在这里,再附上排查思路。这部分的经验比前面的方案更值钱,因为它们都是常规文档里找不到的。
5.1 AI生成内容跑偏怎么办
AI经常出现“我以为你说的是A,结果做成了B”的情况。比如我让它设计订单查询接口,它在响应示例里默认加入了“优惠信息”“物流信息”字段,而我当前项目的订单还没有这些功能。跑偏的本质是上下文不足,应对办法只有一个:在提示词里收紧边界。
我通常会在提示词的最后加一段“本项目当前不包含以下能力,请勿加入设计:优惠券、物流、售后”。这种负向约束往往比正向要求更有效,因为AI在生成时会倾向于“雨露均沾”地把常见电商功能都塞进去。另一招是让AI先输出“我理解的需求如下”,等它复述完需求、确认无误后,再让它输出设计文档。这个“先对齐需求,再展开设计”的流程能省掉大量返工。
5.2 接口文档与实现不同步
实战中另一个常见问题:接口文档改了三版,但代码里还有旧版的影子。AI编程工具尤其容易放大这个问题——你之前让它生成的旧代码还留在某个文件里,新对话里改了设计后,它没有能力自己追溯所有相关文件去同步更新。
我的应对方法是,在项目里放一个“接口契约文件”(api-contract.md),把当前生效的接口设计、字段定义、错误码表都维护在这个文件里。每次让AI生成或修改代码时,把契约文件的关键段落直接贴进对话,告诉它“这里是以官方契约为准,请确保代码和契约完全一致”。实测这样可以显著减少实现与文档脱节的问题。另一个技巧是,修改契约后主动提醒AI“哪些旧接口已废弃”,避免它在生成新代码时又调用旧的接口签名。
5.3 提示词技巧速查
结合这些小项目实战,我整理了一份自己常用的提示词技巧速查表,和新手朋友分享时也用这一份:
| 场景 | 推荐做法 | 不推荐的做法 |
|---|---|---|
| 首次设计接口 | 给项目背景+已有代码结构+明确字段约束 | 一句话描述让AI自由发挥 |
| 补齐异常场景 | 要求AI按“鉴权、参数、业务、基础设施”四层枚举 | 问AI“这个接口有什么异常” |
| 生成错误码表 | 先定义编号规则,让AI按规则填充 | 直接问AI错误码怎么设计 |
| 审查AI方案 | 追问“你的方案假设了哪些前提” | 全盘接受AI输出 |
| 修改历史代码 | 贴上接口契约文件的最新版 | 在旧代码上打补丁式修改 |
这几条是我在多次实战里磨出来的,不一定全都适合你的项目,但思路是通用的。推荐大家先把第一条试起来,给AI喂一次结构化上下文,你会立刻感受到输出质量的差别。
我个人在整个项目做完后最深的体会是,AI编程工具目前最擅长的不是“从零创造”,而是“在你给定的框架内做细节填充”。接口设计和异常处理恰好是细节最多的领域,所以这套协作方式能发挥出AI的最大价值。你只要负责拍板边界和约束,剩下的一万种边界case让AI来抛,你来做筛选和决策。这样写出来的接口,既不像纯手工那样累死累活,也不像纯AI那样虚浮不落地。
后面如果继续做这个系列,我打算把鉴权方案、缓存策略、日志规范这些也各写一篇。每一步都是从小项目实战里真实遇到的问题出发,不搞大而全,只求能落地。如果你也在做类似的接口层设计,欢迎照着这篇文章的思路试一遍,大概率能帮你少踩几个坑。