问题
- “一云多端”成为趋势,终端类型越来越多。比如,现在PC Web网站的产品已经有了,现在想扩展APP,小
程序... ...怎么办?一个直接能想到的方法就是在原来的基础上,为APP等增加API接口,如下图所示:
![](https://upload-images.jianshu.io/upload_images/1186939-3546f4b4cfd34e24.png?imageMogr2/auto-orient/strip|imageView2/2/w/1080/format/webp)
![](https://upload-images.jianshu.io/upload_images/1186939-8549415974a5deb0.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp)
这样做是可以的,然而一旦遇到修改,那么要同时修改几个端的代码,很麻烦,不是很完美。
-
“前后端分离”成为趋势。一开始的PC Web网站,大多是采用服务端渲染的前后端一体化的模式。随着技术的发展,前后端分离,前端渲染逐渐成为趋势。相应地,前端开发人员也从后端团队中独立出来。
最近兴起的APP,小程序等,天生就是前后端分离的。
前端,APP,小程序等各自独立成专门的团队,当然可以满足这种趋势。
相应地服务端需要为每一个前端部门提供服务,在实践中常常发现,重复的内容很多,有没有办法增加复用?或者说后端能否只对接一个“大前端”部门,剩下的“大前端”部门内部自己解决?
image.png -
服务端设计的API接口,面向通用服务,还是面向UI?各个端对数据的显示要求不同,给一个公共的API还是分别给不同的API?
比如,时间显示,PC端可能要求“2018-6-11”的格式,而APP端可能要求“2018/6/11”的格式,接口怎么给?
再比如,相同功能的一个接口,PC Web端需要20个字段,已经做好了。现在APP端因为屏幕小,只要10个字段就够了,是复用老的API,让APP忍受垃圾信息,还是为APP额外新增一个接口?
前端和服务端人员可能会有不同意见,这就带来了冲突。大家都有一定的道理,怎么协调? -
产品经理提出PRD-》UED设计交互稿-》UI设计界面-》后台设计API接口-》后台实现服务-》前后端联调... ...
以上是一般的开发流程,整个过程还是比较长的。前端在开发完静态页面之后,常常需要等后台服务开发好了,才能联调,这里往往有等待时间的浪费。等后台服务好了,往往提测时间也临近了,气氛很紧张。整个开发体验,往往就是“一半是海水,一半是火焰”。有没有办法缩短这个流程,并且能够让前端不依赖后台服务的完成,独自完成开发?
架构
从现状来看,前后端分离之后,服务端直接给各种端提供服务是很自然能够想到的一种方式。这种方式的优点是简单直接,缺点是不够灵活。因此,考虑在前端和后端之间插入一个中间层,作为前后端之间的桥梁,增加灵活性。
对于这个中间层的称呼,一种是“网关层或者接入层”,这个可能会和后台现有的网关和接入层造成混淆。另一种叫法叫做BFF(Backend for Frontends,为前端而存在的后端),这种称呼相对比较准确,不会带来混淆。
- 网关层或者接入层
![](https://upload-images.jianshu.io/upload_images/1186939-825dc43726360c4a.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp)
- BFF(Backend for Frontends,为前端而存在的后端)
![](https://upload-images.jianshu.io/upload_images/1186939-9ff424166a5e568e.png?imageMogr2/auto-orient/strip|imageView2/2/w/410/format/webp)
解决方法
-
针对“一云多端”,可以在BFF层做适配。可以考虑MVVM的模式,从服务器来的数据当做Model,在BFF中针对各种端,提供不同的ViewModel。如果数据变了,只要修改Model就可以了。如果要增加一种端,只要增加一个ViewModel就可以了。在这里集中修改,就可以解放各个终端的格式转化工作。
-
“前后端分离”之后,各种端可以融合为一个“大前端”,跟后端对话的窗口就是BFF。对于后端来说,只要满足BFF的数据需求就可以了,剩下的事情,就让“大前端”内部自己解决。
![](https://upload-images.jianshu.io/upload_images/1186939-09f0425fdc089359.png?imageMogr2/auto-orient/strip|imageView2/2/w/1080/format/webp)
-
服务端设计的API接口,面向通用服务,不需要面向UI。各种端的UI差异,由BFF层负责适配。这样的话,可以让后端更加专注于业务逻辑和数据服务,不需要操心各种端的差异。
-
整个开发流程太长,导致相互等待,造成浪费。针对这个问题,可以考虑在BFF层将开发流程分为两部分。“大前端”作为一个独立开发部门,领先后端一个版本发布周期。
具体做法是,对于新业务,将Mock数据生成在BFF层,对于各种端来说,相当于后端服务已经好了,可以直接进行联调,不需要等待。这样就把前端对后端的数据依赖去除了,更加灵活。
组织结构
针对上面提到的“大前端”技术架构,需要相应的“大前端”组织结构相对应。
分类思路
-
“大前端”是针对整个后端来说的,所以这一层是按照职能来分的
-
在“大前端”下面,是否仍然按照职能来分呢?比如iOS开发,Android开发,H5开发等等。这种分法是可行的,然而收益不是很大。这只是将一个个小部门“组合成”一个相对大的部门,融合度不是很高。
另外一种融合度更高的划分方法是在“大前端”下划分为“基础服务”,“业务开发”两个子部门。
![](https://upload-images.jianshu.io/upload_images/1186939-cc6bed3b0fbbf23b.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)
-
“基础服务”的主要职责是为整个“大前端”部门提供公共服务,公共组件,周边设施等等。根据需要和实际情况可以分为“架构”、“工具”、“组件”等小组
-
“业务开发”的主要职责完成业务部门的需求。根据业务发展情况,按照具体业务划分小组。
人员组成
人员还是按照专业分工的角度去找,按照每个角色最少2人,防止单点风险的思路,人员需求如下:
iOS开发:2人
Android开发:2人
H5开发:4人
Node或者Java开发(BFF):2人
管理
管理方式跟组织结构相适应,采用职能管理和敏捷管理相结合的方式。
职能管理
“大前端”是按照职能分的,跟后端相对应,是技术部下面的一个子部门,按照职能管理方式进行统一管理。
敏捷管理
- “大前端”内部,主要还是按照业务分组的,并且由于BFF的引入,“大前端”内部可以形成开发的闭环,可以考虑引入敏捷管理。
- 要实行敏捷管理,需要产品和测试的支持。根据业务,将相关的产品、设计、测试、开发(“大前端”)组成虚拟团队。
流程
和管理模式相对应,采用瀑布模型和敏捷模型相结合的方式。
瀑布模型
职能型组织,采用瀑布模型的开发流程是合适的。产品部,技术部,测试部一般跟产品开发相关度比较大,按照瀑布模型联系起来。这里考虑前后端分离的开发模式,“大前端”可以独立完成开发闭环,虽然BFF层的数据是Mock的。
另外,大前端版本的开发要求领先后端一个版本以上,这样也方便对于后端服务的测试。简单讲,就是将通常的“后端功能推动型”改为“大前端产品拉动型”
-
产品PRD -》交互/UI设计 -》大前端开发 -》大前端测试 -》大前端内部发布
-
后端服务开发 -》后端测试 -》对接大前端合适版本(主要是BFF的工作,Mock数据改为从后端服务取数据) -》预发环境验证 -》产品上线
敏捷模型
产品,测试,大前端可以考虑合作,按照敏捷模型进行开发。目的是打破部门墙,加强沟通;以业务开发为共同目标,形成合力。
-
开发周期为4周,按照1周预研、2周开发测试、1周重构的比例进行分配。
-
1周预研:这周的主要任务是产品、测试、开发进行充分沟通,对这一期的业务目标达成共识。
产品的主要工作是讲解需求、原型、设计,进行场景化的描述,定出优先级,确保团队成员对本期业务有正确的理解。
测试的主要工作是进行测试用例编写,用例评审,最终通过相应工具,将测试用例数据在BFF层形成可执行的Mock数据。
开发的主要工作是根据业务需求进行技术预研,技术选型,技术设计,任务划分,工作评估等等。完成“计划会议”所要求的内容,将开发任务分配到人。 -
2周开发:按照敏捷的模式进行开发,将业务落地。“每日站会”要坚持开,及时沟通。开发每完成一项,测试就可以直接验证,注重效率。Mock数据由测试统一负责,开发测试用同一套数据,减少误会。这期的结束标志是2周之后的“评审会议”,开发测试向产品演示完成的业务场景。
-
1周重构:这周对应的是敏捷开发里面的“回顾会议”,也是产品、测试、开发进行充分沟通的一周。产品在公司内部试运行一周,进行验收,收集反馈,为下一期的产品设计提供数据支持。开发一方面可以修改bug,更重要的是根据“回顾会议”的内容,进行流程改进,对“技术债”及时进行重构。也可以进行组件开发,提高今后代码的复用度。
特殊之处
Mock数据
-
以前的Mock数据由开发自己负责,要么直接代码写死,要么借助Charles等工具。现在,将Mock数据由测试统一负责,直接生成在BFF层。
-
以前开发要写自测代码,单元测试代码;测试设计出用例数据之后,一般通过流程工具,比如JIRA,要求开发自测。现在的模式是测试专职维护BFF上的Mock数据,将设计的用例转化为实际可用的Mock数据,开发测试用同一套标准,减少流程和沟通上的损耗。
内部版本
-
“大前端”开发测试完成的内部版本是半成品,是缺乏后台实际支撑的。内部发版之后,在内部的测试服务器上试运行。(开发版本运行在开发服务器上)。运行需要的数据由测试负责Mock。
-
这个内部版本不能交给实际的用户使用,但是内部的产品,开发,测试可以使用,用来体验,查找bug等等。
-
对于后端开发来说,也很便利,服务开发好之后,有现成的产品用来测试,能省很多事。
-
向老板汇报,或者向客户展示,也很方便,有实际可用的产品可以体验,虽然数据是Mock的。这个跟看word文档,ppt,原型设计,或者UI图,感觉是完全两样的。
-
修改成本小,一般来说,70%的工作在后台开发,30%的工作在“大前端”页面。在内部试用的那一周中,发现的问题,或者需求变更,可以非常容易的在下一个版本迭代完成。这个时候,后台服务的开发还没开始,或者刚刚开始,变更成本很小。
需求拉动
-
以前,想开发一个功能,首先考虑的是后端逻辑是怎么样的。很多时候,要根据后端现有的逻辑,修改页面的展示,交互的顺序等等。是一种“后端功能推动的模式”
-
现在,产品和“大前端”一起,领先后端至少一个迭代以上。遇到需求变更强烈的点,或者争论较大的点,可以考虑让内部版本运行时间长一点,比如领先两三个版本。等产品想清楚了,基本稳定了,后端再上。这样,产品思考问题的重点,就从后端现有的功能转移到客户现实需求上来。“需求拉动型开发模式”,解放了产品的思维,更容易设计出符合客户期望的产品。
-
原来的模式是由后端推着前端走,现在的模式是产品和前端拉着后端走,思维模式是完全不一样的。
-
“大前端需求拉动型开发模式”:先有个可用的产品,搞清楚用户喜欢什么,再接上后端实现。
-
“后端功能推动型开发模式”:先做需求分析,评估现有后端功能,然后想办法满足客户需求。
-
问题是:“客户或者用户知道自己想要什么吗?需求分析能有效吗?”。相对来讲,如果有个可用的东西,真正用起来了,用户更加容易知道自己想要什么。比如“这个颜色最好改一下”,“这里的按钮碍眼,最好去掉”,“这里我想看更多的信息,最好能加上”。诸如此类
平稳的节奏
-
职能型组织,瀑布式开发模型,有利于控制风险,缺点是时间过长,一般项目至少1个月以上,面对需求变更能力较弱。是一种偏重计划的模式。
-
敏捷开发模式,有利于团队沟通,时间一般较短,一般是2~4周。至于风险,考虑较少,一般是先用了再说,发现问题,下个周期再改。是一种偏重经验的模式。
-
将这两者结合,是希望达到风险和速度的平衡,形成平稳的节奏。将敏捷模型中原本只有4小时的计划会议和回顾会议扩展为一周,是为了让跨部门沟通更充分,让产品验收更全面,降低风险。
-
集中资源做“重要而不紧急的事情”。客户需求很重要,但从想法到落地,并没有那么快。所以发挥“大前端”灵活的优势,让客户早一点看到想法落地,可以超越客户期望。
-
“需求变更”本身,也是一种潜在的客户需求。在用上实际可用的产品前,很多时候,客户也不知道自己想要什么。所以,采用两阶段交付的方式,用总开发成本30%左右的“大前端”半成品,挖掘客户的潜在需求,可以提高客户的满意度。
-
“可用的产品胜过完备的文档”,虽然是个半成品,站在客户的角度,比word文档,原型设计等更实在,更靠谱。
重视重构
-
技术债怎么办?是立即处理还是等累积到一定程度,再集中处理?
-
让业务停下,专门做重构,这种机会只能说可遇而不可求。
-
将原来敏捷中不超过4小时的回顾会议,扩展为1个星期的重构阶段,正是为了解决技术债不断累积的问题。达到“一边飞行,一边换引擎”的效果。
-
这个阶段,产品和业务也没有停,在试用,在体验,在验证一开始的设计理念是否符合实际。这样就促成了产品和技术的双赢局面。
重视预研
-
这里将敏捷开发中原本4小时的“计划会议”扩展为1周。
-
敏捷模型在介绍时有个假设,那就是需求确定,原型设计,UI资源,前后端接口设计等各种资源都准备好了,相关的可行性,也就是预研都完成了,再开“计划会议”
-
实际情况是,上面提的那些条件往往都没准备好,或者有缺失。开发在进行到一半的时候,经常发现交互逻辑不落地,要改原型。或者发现UI资源缺少,接口定义不合理等等。
-
特别是职能型组织,跨部门沟通,这种信息缺失的事情更容易发生。
-
在正式开发之前,花1周时间,集中进行沟通,进行技术预研,做好充分准备,将问题发现在工程开始之前,对减少不必要的返工是很有意义的。
面向BFF编程
-
BFF成了“大前端”和后端之间的抽象接口
-
BFF需要做好两边的适配
-
可以考虑将一些公共业务也接过来,实现“轻客户端”的目标
-
自然而然的“热更新”,BFF采用了后端的技术,做的是“大前端”的工作。有修改,更新服务,就生效了,天然的热更新。
-
天生的“跨平台”,BFF这一个地方修改,各种端都能起作用。
-
增加掌控力。BFF由企业维护,而各种端掌握在用户手里。将业务由各种端移到BFF,可以显著提供企业的掌控力。
这里的边界是:“能服务端(BFF)实现的,就不要放到客户端去,除非遇到严重的性能问题”。 -
注意性能瓶颈,这是关键节点,是前后端的对接点。并且还要注意,对接之后,Mock数据要清除干净,保证生产版本的数据是来自真正的后端。
效率和安全并重
-
“大前端”注重效率,快速响应用户的需求变更。
-
后端注重安全,按照瀑布模型或者迭代模型,注重风险管控。
-
通过BFF解耦,让前后端各自独立运行。
思考
-
“大前端”是最近起来的概念。和传统的前端相比,“大前端”有两个方面的扩展。一个是端的多样性,比如新增了iOS,Android,小程序,公众号等等。另外一个是往后端扩展,比如Node.js的兴起,或许写后端服务没有Java成熟,写BFF还是可以胜任的。
-
“大前端”是相对于传统的前端,iOS,Android,H5等独立小团队而言的。从基础服务+业务支持两个方面,促进团队的融合。在架构,工具链,组件化等几个方面提高复用,提升效率。
-
“大前端”是随着前后端分离的趋势逐步提出来的,是相对于后端来讲的,因此,要达到和后端既相互独立、减少依赖,又相互合作、沟通清晰的目标。
-
“大前端”概念最初是从阿里传出来的,后来饿了么发展最出名,现在很多公司在用,和微服务一起,接受度也在增加,成为一种趋势... ...
-
“大前端”在具体落地的时候,还没有固定的模式,各家的方案也不尽相同。有可供参考的成功案例,没有可供复制的成熟模式。需要根据自身的具体情况,摸索前进。
参考文章
微服务下使用GraphQL构建BFF
前后端分离演进:不能微服务,那就使用 BFF 隔离
一个可供创业公司参考的移动APP服务端架构演进方案
蚂蚁财富的BFF实践
了解BFF架构
大前端技术大会
当我们在谈大前端的时候,我们谈的是什么
如何落地和管理一个“大前端”团队?饿了么大前端团队解密
我理解中的“大前端”/“大无线”
漫极客 CTO 李焱:大前端之路 - 如何用Web技术一统三端(Web、Desktop、Mobile)开发