你有没有遇到过:前端代码刚写完,后台界面又变了。接口文档永远不会正确。在接近上线之前,永远不要开始测试。为什么前后端分离,你比以前更痛苦?前后端分离已经不是新闻了。真正分开之后,你们遇到了更多的问题。要想解决当前的痛点,就必须知道痛点的根源:为什么界面会频繁变化?我在设计之初并没有考虑到这一点。这就需要提高理解需求的能力和接口设计能力。改变的成本更低。德国有一句谚语:“吐在汤里”。只有这样,人们才能放弃那碗汤,停止不合理的行为。当前后端同学坐在一起,一起工作时,效率会得到提升。当后端同学的接口发生变化时,只需要口头通知即可。我们没有文档,我们非常敏捷。没错,我们需要承认这种合作开发的效率会很高,但是频繁的变更会导致不断的返工,造成另一种浪费,这种浪费是可以减少甚至杜绝的。为什么接口文档总是出错?接口文档起到一定的定义接口的作用,写完接口就没有用了。随着后期接口的频繁变更,文档总会滞后于实际的接口,文档的维护带来了一定的成本却无法带来价值。除非对外提供接口,谁来阅读文档?没人看,有什么用?有的公司干脆把接口文档扔掉,说要拥抱敏捷。所以接口文档之所以落后,是因为它没有给我们带来价值。为什么只有临近发布时才能开始测试工作?一个需求,后端开发4天,前端开发4天,联调4天,留给测试同学的时间只有2天或者更短,如果测试不完,只能带着bug来行。在开发阶段,测试学生不能干预。界面在变,前端也在变。自动化?想都不敢想,Kong有一技之长,“拥抱变化”之后,只能靠人工测试了。偶尔也会约前台的美眉来客串试探小姑娘。手动测试枯燥乏味,繁琐的工作容易出错,而且不能快速重复,不能快速返回被测功能。怎么破?要解决以上问题,必须让接口文档发挥其价值,增加更改接口的成本,尽快测试。接口文档要发挥它的价值,就要赋予契约的含义,就像谁也不能更改签名一样,约束我们只认契约不认人。契约要由前端同学驱动,前后端共同协商。因为前端同学接触UX比较近,对页面需要的数据和整个UserJourney了解的比较多,前端同学开车会比较合理。合约敲定后,为了帮我们生成MockServer(后面会介绍一个工具),前后端同学要按照合约分别开发。MockServer可以暂时替代后台服务,帮助前端开发。同时测试同学也可以根据合约文档编写测试脚本,使用MockServer进行脚本验证。当后台界面发生变化时,除了口头通知外,还必须修改合约,前台同学和测试同学可以单独修改。这样一来,修改合约的成本就变高了,人们在做合约的时候也会更加谨慎,这也会促使我们提高自己的界面设计能力。看到图中没有“联调”环节,不是看错了,而是“联调”已经不是工作了。部署完成后,只需更改代理的配置即可。即使使用现代前端框架(如Vue或React),只要在开发时配置好,之后就不需要调整任何代码。“测试”呢?测试一直在进行,所以不再有“测试”环节。不管前端还是后端完成开发,测试同学都可以进行测试。理论终于讲完了,说起来容易做起来难,我们需要工具来帮助我们。接口描述的工具有很多,比较有名的有Swagger和Raml,我个人比较喜欢Raml。描述工具生成文档还不够,还要生成MockServer。如果描述工具和MockServer分开,会带来额外的工作。幸运的是,有her-raml-mocker。raml-mockerraml-mocker是一个基于Raml,用Nodejs开发的MockServer工具。只需使用Raml描述界面中设置响应的示例命令即可。Raml-mocker会解析Raml文件,启动一个MockServer,并将示例的内容返回给浏览器。开始初始化项目gitclonehttps://github.com/xbl/raml-mocker-starter.gitraml-apidraml-apigitremotermorigininstallyarn#ornpminstallstartmockserveryarnstart#ornpmstarttestcurl-ihttp://localhost:3000/api/v1/users/1/books/#orcurl-ihttp://localhost:3000/api/v1/users/1/books/1生成API可视化文档yarnrunbuild#ornpmrunbuild该功能使用raml2html。configuration.raml-config.json{"controller":"./controller","raml":"./raml","main":"api.raml","port":3000,"plugins":[]}controller:controller目录路径,在进阶章节会详细说明。raml:raml文件目录main:raml目录下的入口文件port:mockserver服务端口号plugins:GettingStartedwithPlugins:MockServerAddexample:/books:/:id:post:body:application/json:type:abcresponses:200:body:application/json:type:song#ReturnedMock数据示例:!include./books_200.jsonbooks_200.json{"code":200,"data":[{"id":1,"title":"bookstitle","description":"booksdescription1"},{"id":2,"title":"bookstitle","description":"booksdesccription2"}]}通过curl请求:curl-ihttp://localhost:3000/api/v1/users/1/books会得到示例数据,唯一不足的是不能根据参数动态返回不同的数据。别着急,请往下看。进阶:DynamicServer如果静态的mock数据不能满足你的需求,Raml-mocker也提供了动态的功能。在raml文档中添加(controller)命令来添加动态Server,如:/books:type:resourceList:get:description:获取用户的图书(controller):user#getBookresponses:200:body:type:song[]example:!include./books_200.json文档(controller)中表示controller目录下user.js中的getBook函数。controller/user.jsexports.getBook=(req,res,webApi)=>{console.log(webApi);res.send('HelloWorld!');}raml-mocker是在expressjs、req、res的基础上开发的您可以参考快递文档。webApi会返回文档中的配置:{"absoluteUri":"/api/:version/users/:user_id/books","method":"get","controller":"user#getBook","re??sponses":[{"code":"200","body":"...example...","mimeType":"application/json"}]}所以,raml-mocker提供了更多的可扩展空间,我们可以甚至在控制器中实现某些逻辑。插件Raml-mocker提供了一种插件机制,可以让我们在不使用controller命令的情况下处理响应的内容,比如使用Mockjs。.raml-config.json{"controller":"./controller","raml":"./raml","main":"api.raml","port":3000,"plugins":["./plugins/mock.js"]}./plugins/mock.jsvar{mock}=require('mockjs');module.exports=(body)=>{try{returnmock(JSON.parse(body));}catch(e){}returnbody;}总结前后端分离可以让我们的职责更加清晰,打破前端性能的限制,工作解耦后提高开发效率。但是由于我们没有规划好开发过程,没有发挥出应有的价值,造成了更多的浪费。Raml-mocker可以帮助我们解决工具上的某些问题,更重要的是持续改进的思路。只有团队的思想统一,才有可能实现快速交付。希望能帮到你,谢谢!
