最近这段时间,我一直在参与一个前端项目。每当我从庸碌的生活中赢得片刻喘息的时候,我不由得感慨,在程序员朴实无华且枯燥的职业生涯里,写自己喜欢的代码的机会少之又少,写别人喜欢的代码的机会俯拾皆是,更多的时候像是“”,当每天面对着被改得面目全非的代码的时候,内心固然早已波澜不惊、宠辱偕忘,可还是会期待美好的事情发生,因为从工程化的角度而言,每天都在思考的事情,其实就是怎么样做会更好一点。过去这些年里,微服务、前后端分离的呐喊声不绝于耳,实际应用过程中则是会遇到各种各样的问题。在今天这篇文章里,我想和大家聊聊 Vue.js 结合 Mock.js 实现接口模拟这个话题,为什么选择这个话题呢?我个人认为,它实际上触及了前后端分离的“”,并且由此可以引出像文档管理、流程控制等等一系列研发协同的问题。你或许会忍不住问道,前后端分离的“
在谈到前后端分离这个话题的时候,在公司层面上对应地往往是组织架构的分离,典型的做法就是让前端和后端成为两个不同的团队,其中,前端团队负责表示层的实现,不限于页面布局、样式风格、交互逻辑等等;后端团队负责数据接口的实现,不限于数据库设计、接口设计、编写 API 等等。对应到 Vue.js 里,前端团队负责写各种各样的页面/组件、数据绑定,后端团队负责提供各种各样的数据接口,这听起来非常地合理,对不对?的确,主流的前后端分离实践都是这样讲的,所以,我们只要套用这个模型,就可以达到预期的效果,对不对?可惜,人类习惯于为这个世界寻找某种颠扑不破的真理,可恰恰人类本身才是这个世界里最不稳定的存在?疫情常态化的当下,每次都被病毒一通嘲讽,抄作业都不会抄啊!
首先,第一个问题,前、后端团队没有形成“契约”,前端团队拿到原型以后就开始设计页面,ViewModel 中的字段命名、定义完全是由前端团队凭“感觉”写出来的,人类离谱就离谱在,可以靠“感觉”这种玄之又玄的东西决定很多事情。这样做的后果就是,后面真正对接后端接口的时候,发现大量的字段没法对应上,不得不再折腾一遍数据绑定,如果是中途由别人来接手,那么面对的可能就是不同的数据结构间的映射转换。试想,后端程序员尚有AutoMapper和Mapster可以用,前端程序员可就没有那么幸运啦!更不必说,前端天生比后端面临更频繁的改动,只要涉及到页面布局、交互逻辑的变化,ViewModel 的修改基本无可避免,这样就导致同一个页面多次返工,我相信这个结果大家都不想看到。
其次,当前、后端团队约定好接口文档以后,双方都按照这份接口文档去完成各自的开发工作,这样听起来简直不能更合理对不对?实际上,在后端团队完成接口开发以前,前端团队会有一段时间的“真空期”或者“黑写期”,因为前端并不知道这段代码能否在真实的环境下工作。此时,前端团队可能会造一点假数据来进行接口模拟,得益于 JavaScript 这门语言的高度灵活、自由,前端团队可能会直接调用一个本地函数来返回假数据,这意味着它并不会触发真实地 HTTP 请求。那么,当有一天后端团队完成了接口开发,你将会把这些本地函数替换为Axios的方法,甚至在更极端的情况下,前端团队不能访问后端团队的接口,此时,双方会就本地函数还是Axios方法产生一场拉锯战,你告诉我,还有什么比这更折磨一个人的吗?
前、后端团队如何制定一份对协同有利的接口文档,这份文档是通过工具生成还是人工编写
。我个人是特别讨厌用 IM 或者邮件来发送接口文档的,因为没办法做到版本控制或者说让所有手中都有一份最新的接口的文档。
如何管理项目中用到的各种假数据,以及如何让项目在假数据和真实接口中“无痛”切换
。前端项目的特点是所见即所得,这让它比看不见、摸不着的后端项目更受用户青睐,毕竟还有什么比能让用户亲眼看到更亲切的东西呢?
在“小步快跑、快速迭代”的敏捷思想的驱使下,我们经常需要给用户演示各种功能。也许,在某个时刻,页面上的数据亦真亦假,你还会觉得,管理这些假数据没什么意义吗?而这正是驱使我了解Mock.js的动力所在,世上的很多事情,你未必能如愿以偿、做到最好,可你依然要了解什么是最好,“山不厌高,海不厌深”,向不那么完美的世界妥协是现实,永远值得去追寻更完美的世界是理想,这两者在我心目中并不冲突,你觉得呢?
OK,既然找到了问题的症结所在,我们逐一对症下药即可,就像“三过家门而不入”的大禹,选择用疏导的方式治水,让洪水通过疏通的河道流到大海中去,而不是靠一味地“堵”,程序中 90% 的代码都是在给用户“打补丁”,防止对方做出什么骚操作来,那么,是不是可以用某种方式去引导对方呢?我最讨厌听到的话就是,用户想要怎么怎么样,这是没有办法的事情,如果只需要一个传话筒,我们为什么不直接用传呼机呢?作为一个老古董,恐怕现在的 00 后都不知道什么是传呼机。你生命中当下流行或者推崇的东西,总有一天会过期。可即便如此,你还是要全力以赴。显然,这是个哀伤的故事。
对于接口文档的管理问题,我自始至终都推荐Swagger这个神器,因为我和这个世界上的绝大多数的程序员一样,都认同一种相对朴素的价值观,即 “懒惰是一种美德”。因为我不喜欢靠人工来维护接口文档,所以,只要有机会用上 Swagger,我一定会用 Swagger 来管理接口文档。不管是过去写 API 和 MVC,还是现在写 gRPC。对我来说,选择 Swagger 是一件自然而然的事情,因为我懒,因为我不理解为什么有人需要导出 Word 或者 Pdf 格式的接口文档。也许,Swagger 那千篇一律的页面风格会让人感到无所适从,喜欢的人非常喜欢,讨厌的人非常讨厌。在前、后端分离的项目中,有一份白纸黑字的接口文档,显然要比“口口相传”靠谱得多。当然,如果你有足以媲美 Swagger 的接口文档管理工具/平台,欢迎大家在评论区留言分享。下面是我曾经写过的关于 Swagger 的文章:
好了,下面我们来介绍今天这篇博客的主角:Mock.js。如果你有养成写单元测试的好习惯,那么,你一定对 Mock 的概念了如指掌。在 .NET 的生态中,有一个大名鼎鼎的模拟库:Moq,它可以让我们更加方便地模拟各种对象的行为。什么情况下需要模拟呢?我想,是目标对象不可用的时候。如果把这个认知迁移到前端开发中,我们就会发现前端依赖最多的其实是后端的接口。那么,有没有一种方案,可以让前端在后端接口不可用的情况下,模拟出调用后端接口的效果呢?而这,就是 Mock.js 存在的意义。事实上,我一开始就讲到,在后端团队完成接口开发以前,前端团队会有一段时间的“真空期”或者“黑写期”,而这段时间显然是最需要进行模拟的一个环节。综上所述,不管是技术层面还是流程层面,这个模拟的阶段都是真实存在着的,并非是人为捏造或者臆想出来的东西。
在考虑引入Mock.js以前,项目中充斥着类似于下面这样的代码。你不得不承认,JavaScript 是一门灵活而且强大的编程语言,考虑到它返回的是一个 Promise,所。