ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

小公司接口治理:RESTful、共用接口与前后端分离实践

小公司接口治理:RESTful、共用接口与前后端分离实践 1. 为什么一家小公司也需要RESTful、共用接口和前后端分离1.1 人少、活儿急接口慢慢失控提到小公司的后端开发第一反应往往是“能跑就行”。业务变化快产品迭代恨不得按天算前端催要接口后端加班赶工。我所在的团队规模不大一开始也是这种状态。今天给活动页加个查询明天给表单加个提交都是随手来。久而久之接口文档就散落在微信聊天记录里前端想知道某个字段的含义只能来后端问后端想改动某个字段还得挨个通知前端。这还不是最头疼的真正让我决定做一次专项治理的是接口本身开始变得不可维护。随便举几个当时真实存在的接口路径/getUserInfo、/delete_user、/updateUser/1、/queryOrderByMobile、/orders/updateStatus。命名风格五花八门动词和名词随意混用请求方法也混乱——POST能删数据GET也能改数据。如果你在别的公司见过更夸张的版本比如/getUserInfoList和/UserInfoList同时存在那也完全正常。这背后其实不是某个人的问题而是没有一套统一约定的时候任何后端都会按照自己当时最顺手的方式写出一个接口。接口一旦多起来每个接口都有各自的“小脾气”前后端联调就会变成一个不断踩雷的过程。等到公司同时推进H5、小程序和App三个端时问题彻底暴露了。同一个“订单列表”需求前端希望数据结构各不相同。H5要的是页面卡片所需的完整字段小程序要的是精简数据 App还要带上本地缓存需要的版本号。于是后端被迫为每个端各写一套接口三个端就是三套。一个业务规则调整比如订单状态增加一个“已取消”后端的改动量直接翻三倍。这时候我意识到必须做点什么了。1.2 我们的两个核心目标多端复用和前后端并行那次专项治理目标其实非常朴素。第一一套接口给多个端共用而不是每个端一套。多端共用的前提是接口不能绑定页面。业务能力是相对稳定的页面是天天变的。只要接口围绕业务能力设计H5、小程序、App 这些前端都调用同一份接口后端只维护一套逻辑。第二前后端能够真正并行开发。以前前端想开发页面必须等后端把接口写出来不然没有数据可以渲染。这种串行开发模式在小公司特别浪费人力。要打破它唯一的办法是让接口约定先行。后端按照约定先出接口定义前端根据这一定义直接模拟数据开始干活。后端实现完成后再切换真实接口。只要约定足够清晰并行开发就不会在后面联调时爆炸。这两个目标最后都指向同一个支撑点接口约定。这也是本文标题里“接口约定”四个字的分量所在。它不是一份应付差事的文档而是前后端之间唯一的契约。后面我会详细说这份契约应该包含哪些内容、怎么落地。1.3 为什么是RESTful而不是其他方案当时团队里也有过讨论到底要不要采用RESTful还是沿用随手写的风格或者说再上一些更重的框架。我的结论很直接RESTful 不是最炫的但在小公司场景下它是最划算的。RESTful 的核心思想就是“面向资源”。URL 里只放名词表示资源和资源之间的关系操作交给 HTTP 方法GET、POST、PUT等来表达。比如“获取用户信息”就是GET /users/123“创建订单”就是POST /orders。这种风格的新人学习成本极低半天就能明白怎么写。同时市面上的调试工具、Mock工具、API网关对RESTful的适配也最好这能省下我们大量时间。我这里说的RESTful严格来说是“RESTful风格”不是学术论文里那种完全体REST。真正的REST对超媒体、HATEOAS这些东西有很高要求小团队完全没必要追求。我们要的是一套能写进文档、新成员半天学会、工具生态支持良好的接口风格。从这个角度看RESTful几乎是唯一选项。它让“共用接口”和“接口约定”这两件事都有了扎实的落点——因为有了统一的资源名词、方法语义和状态码语义前端和后端才不需要在聊天记录里反复沟通“这个接口是干嘛的”。2. 接口定义阶段把RESTful落实成可执行规范目标定了接下来要做的不是马上写代码而是先把规范定出来。这一步如果偷懒后面所有工作都会变成无效功。我们最终落地的规范大致包含四个方面URL设计、HTTP方法、HTTP状态码和统一返回体。每一条都经过了实际项目的验证下面逐个说明。2.1 URL只关心资源不要出现动词URL设计的核心原则是只描述资源不描述行为。资源名用名词复数全部小写单词之间用中划线连接。为什么要小写因为URL对大小写敏感服务端路由配置不当会出现404为什么用中划线而不用下划线主要因为一些CDN和网关对中划线更友好显示也更清晰。我们约定好的例子GET /users用户列表GET /users/{id}单个用户POST /orders创建订单DELETE /orders/{id}删除订单GET /users/{id}/orders某个用户下的订单列表嵌套关系表达资源从属但层级不要超过两级。超过两级之后比如GET /users/{id}/orders/{orderId}/items/{itemId}不管是维护还是调试都会变得困难。这时候我们一般建议拆开比如GET /orders/{orderId}/items先定位订单再看订单明细。动词改起来其实很快。我给大家列一个常见的对照清单原来的写法改成RESTful/getUserInfoGET /users/{id}/createOrderPOST /orders/deleteOrder?orderId1DELETE /orders/1/updateUserInfoPUT /users/{id}或PATCH /users/{id}/getOrdersByUserGET /users/{id}/orders做这个改造时前端天然的疑问是我按个按钮“下单”为什么不是POST /placeOrder这里的解释是“下单”这个动作的结果是在订单资源集合里新建了一条记录所以应该POST /orders。用资源的角度看问题接口的可读性就会好很多。2.2 HTTP方法、幂等性和安全方法HTTP方法定义了动作的语义。我们在规范里明确区分五类GET读数据不产生副作用安全且幂等。POST新增数据每次调用都可能产生一条新记录不保证幂等。PUT整体更新一个资源幂等调用多少次结果一致。PATCH局部更新一个资源包含少量字段不强制幂等。DELETE删除资源幂等。“幂等”这个词前端同事一开始不太理解。我用一个简单的类比解释GET和DELETE就像按电梯关门键按一次和按十次门还是以同样方式关POST就像下订单点一次“提交订单”和连点十次可能就生成了十笔订单所以要靠后端做幂等控制。对后端来说这个约定的意义在于GET和DELETE在生产环境可以放心重试POST则需要格外注意防重。前端也会注意比如提交按钮在请求发出后立即置灰就是因为POST不幂等。2.3 状态码不要所有情况都返回200这是前端最头疼的一部分。早年间后端接口无论什么结果都返回HTTP 200甚至参数错误也是200只不过body里放着error: 1。这种模式在联调初期确实简单但后期维护成本极高因为前端要从返回数据里先解析“业务到底成没成”再去判断下一步逻辑。HTTP状态码这一层信息被丢弃了。我们后来约定一套语义化的状态码使用方式前端可以直接依赖它做统一处理状态码使用场景前端处理方式200查询成功正常渲染201创建成功提示成功并跳转204删除/修改成功无返回体提示成功无数据解析400参数格式错误展示后端给的错误信息401未登录或登录过期跳转登录页403已登录但无权限提示无权限404资源不存在展示404页面409资源冲突重复提交提示重复操作422参数合法但业务规则不允许展示业务错误信息500服务器内部错误展示“系统繁忙”不重试这里最关键的认知是4xx 代表是前端的问题5xx 是后端的问题。前端收到4xx不应该弹出“系统繁忙”而应该将后端返回的message呈现给用户收到5xx再走兜底的“稍后重试”逻辑。这是状态码语义化最大的价值。有个细节提醒一下有些后端出于安全考虑对不存在的路径一律返回404这个没问题但不要在鉴权之前就返回404因为会泄露“资源是否存在”的信息。正规做法是先鉴权再返回404或403。2.4 统一返回体HTTP状态码之外还需要业务码你可能会有疑问既然状态码已经这么详细了为什么还要在body里再包一层业务码因为业务层面的异常远比HTTP状态码丰富。比如“订单已支付不能取消”你不能简单说它是400还是422前端需要的是针对这种具体情况的处理指令而不是泛泛的一类错误。我们最终定的统一返回结构是这样的{ code: 0, message: success, data: { id: 1234567890, status: paid } }code业务码。0表示业务成功其他值表示具体业务错误。message人类可读的提示信息后端直接返回给前端展示。data真正的业务数据成功时存在失败时可能是null。HTTP状态码和业务码的分工是HTTP状态码表示“请求是否走到了业务层”业务码表示“业务层的具体处理结果”。比如参数校验不通过HTTP状态码是400业务码是40001message是“用户名不能为空”。这样前端拦截器可以先判断HTTP状态码再判断业务码逻辑清晰且不会混淆。当初为了“code为0表示成功还是1表示成功”这个事我们内部还争论过。由于不同公司习惯不同最终结论是团队内统一即可但建议用0表示成功因为!code在前端判断时写法最顺不容易因为“等于1”这种判断漏掉一些异常。3. 共用接口怎么设计一个后端服务服务多个前端3.1 把“接口面向页面”改成“接口面向业务能力”说到共用接口最核心的转变是设计视角接口到底为谁服务。以前我们怎么做前端打开某个页面发现缺数据就跑来和后端说“给我加个接口”。后端正忙着别的需求随口问“要什么数据”前端一报字段后端就照着拼一个。这种模式下接口写了没几天页面一改版接口就废了。更麻烦的是三个端如果页面结构不一致就得给每个端造一个接口最典型的例子就是/getHomePageDataH5首页数据拉了一堆组合字段/getMiniHomePageData小程序首页精简版/getAppHomePageDataApp首页带缓存版本号看起来是三个接口其实每个接口背后的业务逻辑重叠度高达80%以上。后面凡是前端提“首页要加个模块”后端就要改三个接口改了一个漏了一个问题层出不穷。共用接口的解决办法是把接口定位成“业务能力单元”而不是“页面渲染单元”。上述首页场景我们不应该设计一个“首页数据”接口而是应该拆成几个稳定能力比如GET /banners拉横幅、GET /categories拉分类、GET /products?featuredtrue拉推荐商品。H5的首页由前端自己把这些接口组合起来小程序首页只需要精简数据那就分别调用并各自取自己需要的字段。后端只维护一套接口页面怎么组合是前端的事。这个转变一开始会很难。因为前端会觉得“明明一个接口能搞定的事为什么要调三个”。但在多端并存的项目里这个前期成本非常值得。前端组合页面虽然多写了几行代码但后端维护成本大幅下降业务规则改动只需要动一处。3.2 共用接口的参数化设计接口面向业务能力之后三个端的需求差异仍然客观存在。H5页面需要用户头像、昵称、手机号小程序可能只需要昵称和头像App可能想多拿一个会员等级。这些差异不能靠“定制接口”解决要靠参数化。我们约定了一套通用查询参数任何列表接口都支持page页码从1开始page_size每页条数默认20最大100sort排序字段支持-created_at表示按创建时间倒序fields返回字段白名单用逗号分隔如fieldsid,name,avatarfields参数是我们比较满意的一个设计。以用户信息接口为例GET /users/123返回完整字段但移动端可能会传GET /users/123?fieldsid,nickname,avatar这样后端只返回这三个字段既减小了响应体也降低了弱网下的流量压力。该参数是可选的不传就返回默认完整字段。还有一类差异如App端需要知道“有没有更多缓存更新”这可以通过响应头扩展而不是改接口。总之原则是能通过参数解决的就用参数能用响应头解决的用响应头尽量不要写if (clientType mini)这种分支。每加一个分支接口就离“专用接口”近一步离“共用接口”远一步。3.3 共用接口下的认证与权限共用接口并不等于无差别开放。三个端都使用同一套登录体系登录后拿到的token是一致的请求头带Authorization: Bearer token。后端统一有一个中间件来解析token解析出当前用户ID后放到上下文里业务逻辑只要拿到这个ID就行不需要关心是哪个端发来的。权限校验要服务端做不能指望前端。前端只是控制按钮显隐真正的重要操作比如取消订单、修改价格后端必须再次校验当前用户是否有权限。特别是共用接口场景下同样的接口被H5和App同时调用App端可能会有更高级的权限逻辑后端不能因为某个接口只在H5出现就放松校验。越权问题比如用户A尝试通过GET /orders/123查看用户B的订单必须在后端就拦截掉。这里的排查经验是接口共用后权限bug不像以前那样容易发现。因为三个端测试时会各自覆盖不同场景但如果后端没有统一鉴权很容易出现“App能查H5也能查但小程序测不出来”的情况。所以我们后来加了安全测试步骤专门用另一个用户的token请求当前用户的资源路径看是否返回403。4. 前后端分离的协作方式接口约定怎么写才不打架4.1 接口文档必须存在而且先于代码“先有文档再写代码”这句话说起来容易落地很难。小团队最常犯的错是把接口文档当成后补的记录。需求上线了前端已经调完接口后端才想起来补一份文档然后文档里大部分字段都是凭记忆写的实际接口又改了几轮文档很快就过时了。我们的做法是任何新接口必须先把接口定义写到文档平台然后才能进入开发。即使是一个很小的下拉菜单接口也先写GET /users/{id}/addresses这种定义。定义中包含URL、方法、请求参数、返回体示例。前端拿到这份定义之后先用Mock数据开发后端按定义去实现。整个过程里文档就是需求代码只是实现。文档工具的选择我们尝试过好几种。总结一下Swagger/OpenAPI后端用注解生成自动化程度高支持在线调试但要求写注解对后端有一定的侵入式负担。Apifox或YApi集接口文档、Mock、调试于一体团队协作体验好适合非微服务团队。Markdown最轻量适合快速原型但容易过期不推荐作为正式团队的唯一文档。我们最后采用的核心方案是正式项目用OpenAPI定义团队在Apifox里查看和调试小而快的临时接口用统一Markdown模板但必须维护变更历史。4.2 参数、类型、时间、精度这些细节必须写死接口约定最怕的就是“这个应该没问题吧”。很多联调时的低级bug根源都在细节没约定清楚。下面几条是我们用真实教训换来的规范。参数命名所有请求参数和返回字段统一小驼峰命名比如userName、createdAt。数据库字段如果用了下划线后端需要转换为小驼峰再返回这个转换工作由后端承担不能让前端去猜映射关系。时间格式统一使用ISO 8601字符串例如2024-06-01T13:30:00Z统一UTC时区展示层再转本地时间。以前有个接口返回的是Unix时间戳前端每次都要自己new Date(timestamp * 1000)烦且容易错。字符串时间更可读调试时一眼就能看出问题。大整数与金额在前后端分离架构里JSON 数字类型在某些语言中会丢精度。比如Java的Long类型最大值远超JavaScript安全整数范围当订单ID是12345678901234567890时前端解析后末尾几位会变。我们统一的纪律是所有超过JavaScript安全整数范围的整型字段返回时序列化为字符串所有金额字段用整数字符串单位是“分”比如1990而不是19.9。这条如果不写死订单ID和金额都会在联调后期出幺蛾子。空值约定有三类空值要区分清楚。没有值用null空列表用[]字符串可以为空串但不是默认值。比如用户没有昵称时返回null表示“该用户没有设置昵称”前端知道要显示一个默认占位而返回则会被误认为用户设置了一个空昵称。分页返回体我们也固定了一套标准结构{ items: [], page: 1, page_size: 20, total: 98, has_more: true }has_more这个字段后来帮了大忙。前端不用自己去算page * page_size total后端直接告诉他还有没有下一页分页逻辑就不会出错。4.3 错误码规范让前端不用猜业务错误码的设计也是接口约定的重头戏。我们按错误来源做了分码段规划码段含义示例0成功40000-40099参数错误40001 用户名不能为空40100-40199认证错误40101 登录已过期40300-40399权限错误40301 无操作权限40400-40499资源不存在40401 订单不存在40900-40999冲突40901 订单重复提交42200-42299业务规则校验失败42201 订单已支付不能取消后端返回错误时message字段必须是可读的、具体的描述。比如“订单已支付不能取消”是合格的“系统繁忙”不是。因为前端大多数时候会直接把message弹出给用户看。如果担心信息泄密那就把可读提示放在message里内部具体错误放在detail或者日志中detail不返回给前端。前端这边则统一封装一个拦截器。以axios为例先判断HTTP状态码再判断业务码遇到401就跳转登录页遇到不带0的code就直接显示message代码写一遍全站通用。前端同事再也不用在每个接口请求回调里都写一遍错误弹窗了。4.4 接口版本管理什么时候升级不兼容版本接口版本是小团队容易忽略、但早晚要吃教训的一项。我们最初的接口没有版本后来前端陆续改版导致同一个语义的字段在不同时期含义不同后端只能靠if分支兼容老逻辑代码越来越脏。后来我们在所有URL前统一加了/v1/比如GET /api/v1/users/{id}。新增字段、新增可选参数属于兼容变更不升级版本删除字段、修改字段语义、修改必填规则属于不兼容变更必须升级到/v2/。这里要分享一个实际经验小团队不要频繁升级大版本。每次升级都意味着前端同步改造多端还要一起排期。规则是能在老接口上兼容就尽量兼容后端通过新老参数并存来过渡只有实在无法兼容时才发布新版本而且至少提前一周通知前端在接口文档上明确变更记录和废弃时间。5. 前后端分离的协作流程接口先行、Mock并行规范定了文档有了真正让这套体系转起来的是协作流程。你可能听过“前后端分离”这个词很多次但实际运作起来最核心的不是技术而是流程节奏。5.1 接口评审哪怕只有5分钟每次需求评审后我们专门留出一个接口评审环节哪怕只有5分钟。后端把接口草稿列在白板上前端逐个核对业务场景“你开这个页面需要调哪几个接口每个接口需要什么字段”这个环节能提前发现很多问题。比如前端本来以为需要一个“查询用户订单”的组合接口但聊下来发现现有的GET /users和GET /users/{id}/orders分别调用就够了于是避免了一个多余接口的产生。接口评审的另一个作用是在开发前统一语义。有一次前端坚持用POST /users/{id}/resetPassword表示重置密码后端希望是POST /users/{id}/password/reset。这种争执如果没人主持就会迁就前端做成动词式URL。现在统一按“资源动作后置”的规则去设计评审时只需对照规范判断不用每次都靠人情世故沟通。5.2 Mock服务前端不用再等后端接口评审通过后后端把接口定义录入Apifox同时生成Mock数据。前端直接切到Mock环境开发页面不需要等后端的真实代码。这里要强调Mock数据的质量。很多人做Mock只是随机生成一些字符串结果前端页面是画出来了但联调时候才发现少处理了很多边界情况。我们在生成Mock数据时特意加入三类数据空数据列表返回空数组字段返回null测试前端空态样式。超长数据很长的ID、很长的用户昵称测试前端截断逻辑。异常状态返回业务错误码测试前端错误提示是否正常展示。前端利用这些Mock数据把页面健壮性做好真实联调时就能把主要精力放在业务逻辑的一致性上而不是反复因为“字段为空导致页面崩溃”这种低级问题来回切。5.3 联调到底在调什么联调不是后端和前端坐在一起逐条核对每个字段。真正高效的做法是把联调当测试执行按清单逐条过。我们通常的联调清单是后端先用curl或Postman自测关键路径确认返回结构和文档一致。前端把请求从Mock环境切到真实环境先跑一遍主流程。核对核心字段类型ID是不是字符串、金额是不是字符串、时间是不是ISO格式。跑边界场景空列表、超大分页、token过期、权限不足。回归一次老功能确认没有因为改动影响其他端。联调中最常出现的问题不是“接口不存在”而是“字段返回了但类型不符合约定”。比如约定ID是string后端却返回了number约定金额字段是字符串但某些逻辑分支把数字传了出来。这种问题靠肉眼联调很难发现所以我们后来在测试工具里增加了字段类型断言后端接口返回的每个字段都会被自动校验是否匹配契约。6. 落地过程中的典型坑与排查链路这部分写的是实践里的真实问题也是我觉得对后来者最有价值的内容。每一条我们都是踩过坑、花时间定位过的现在整理成完整的排查链路。6.1 跨域问题为什么前端总说连不上后端前后端分离之后前端域名是app.example.com后端接口域名是api.example.com浏览器默认会发起跨域请求。现象就是浏览器控制台报Access to XMLHttpRequest at http://api.example.com/users from origin http://app.example.com has been blocked by CORS policy: No Access-Control-Allow-Origin header is present排查链路基本是三步第一确认是否真的跨域前端页面URL的协议域名端口与后端API的协议域名端口三者中任意一个不一致就是跨域。实际项目里80端口和8080端口不同也算跨域。第二检查后端是否配置了CORS响应头。例如Access-Control-Allow-Origin: http://app.example.com Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS Access-Control-Allow-Headers: Authorization, Content-Type Access-Control-Allow-Credentials: true如果前端请求带了Authorization头或Content-Type: application/json会触发浏览器的预检请求OPTIONS。后端必须对OPTIONS请求返回204而且Access-Control-Allow-Headers里要包含前端实际发送的header否则预检直接失败真实请求压根不会发送。第三如果接口前面还有Nginx确认Nginx和后端没有同时设置CORS头。两边都设置会造成重复响应头浏览器仍然判定失败。我们后来统一在Nginx层设置CORS后端不再配置避免一处改动影响所有域。6.2 JSON大数字精度用户ID明明是对的却返回404这是个很隐蔽的坑。有一次前端报告说某些用户点击订单详情总是404其他用户正常。我一开始怀疑是权限逻辑问题排查了好久。后来发现登录用户的ID是12345678901234567890前端调GET /users/{id}时请求路径里带上的是12345678901234567000后端正则校验不匹配自然返回404。根因就是JavaScript的Number类型双精度浮点数能表示的最大安全整数是9007199254740991超过这个范围的数传给JSON.parse时就已经丢失精度了。Java后端的Long可以轻松超过这个范围。问题不在请求方也不在响应方而在于JSON这种文本格式本身没有区分整数类型的原则性方案。解决办法是全局约定所有超过JavaScript安全整数范围的整型字段序列化为字符串。用户ID、订单号、支付流水号全部转字符串字符串在JSON里不会被解析成数字因此不会丢精度。这条约定一定要写进接口规范的显眼位置而且要前置提醒。我们后来在脚手架层做了统一序列化配置凡是Long类型的字段默认输出字符串避免每个后端同事都要手动处理。前端也要注意不要在拿到字符串ID后自己parseInt回去那等于自己把坑又踩了一遍。6.3 接口约定被绕过总有人临时加一个“快捷接口”规范推行一段时间后出现了新情况某些后端同事为了赶需求绕过统一返回壳直接返回一个数组或者接口路径不符合RESTful规范直接在controller里写了一堆自定义路由。这种问题的根源通常是“业务催得急没时间走接口评审”。我理解的难处毕竟小公司就是灵活优先但接口约定一旦被破坏痛苦会转嫁给前端和后来的维护者。我们的应对方式分三步第一新接口必须走文档登记哪怕是“临时接口”。没有文档的接口视为不存在联调时不承认。 第二代码评审时重点检查controller入口看是否使用了统一返回类型。 第三在网关或路由层做兜底检查所有进入生产环境的API路径必须匹配/v1/{resource}的模式不匹配直接拦截。这套机制之下临时加接口的成本变高了但接口治理的收益也稳定了。前端不再因为后端“临时快捷接口”而维护一堆无文档调用。6.4 接口数量失控向“页面定制接口”说不上线几个月后我统计过一次接口清单发现多了不少雷同接口比如GET /orderList和GET /ordersV2同时存在。追溯下来都是有前端提需求说“我现在需要一个列表只要这几个字段”后端没有去复用既有接口而是又新写了一个。接口数量失控的直接后果是维护成本上升。一个业务规则要改需要同时改多个相似接口。这其实就是3.1节讲的“面向页面设计接口”的问题会在项目中期集中爆发。我们的对策是双管齐下一方面新接口必须过评审如果已有类似接口优先在旧接口上扩展字段而不是新造接口另一方面每个月做一次接口梳理把调用量低、功能重叠的接口标记出来在前端确认没有引用后下线。这里我想强调接口数量不是越少越好而是“每一个接口都要有明确存在的理由”。共用的意思是每个接口都能被多个场景复用不是把所有接口挤成一个万能接口。如果一个接口被三端调用、但各自传的参数完全不同那它其实还是三个“隐式接口”。真正合理的状态是接口定义稳定参数可适配合法差异。回到最初的问题为什么一个后端要折腾RESTful、共用接口、前后端分离和接口约定我的体会是小团队没有大厂的基建和人力但同样会被接口混乱拖慢速度。RESTful提供了一套低门槛的统一语言共用接口让后端维护成本降下来前后端分离让开发节奏快起来而接口约定是所有这些能运转起来的黏合剂。这套体系不需要多少高级工具核心就是先定规则再写代码先写文档再做开发面向业务能力不面向页面细节写死不留猜的空间。如果再来一次我会把接口约定放到比业务开发更靠前的位置先把文档模板、返回体、类型规则、错误码段全部定好再启动第一个接口的开发。小技巧是接口文档上线后不要默默修改任何变更都要在文档变更记录里留一条前端才能明确知道自己依赖的接口是不是悄悄变了。做到这一步前后端之间的沟通成本会肉眼可见地降下来。
返回列表