作者:闲鱼技术-兰昊
前言
Flutter一体化研发模式在闲鱼落地探索已有半年多了,前面也有多篇文章已经分享过阶段性成果,今天我给大家以总的视角来分享下在这个过程中闲鱼探索出来的一条路。
业务痛点
时间回到2019年8月。在那之前闲鱼上每年会有不少创新型交易模式在做探索,但是交易链路代码年久失修,维护成本很高,无法快速支撑到业务。例如下图所示:
- 所有引起金额变化的操作全部都在云端各做一遍,买卖家订单状态判断以及操作订单的逻辑也全部都在端上。这样每次新增交易类型,就会进一步增加端上状态机的逻辑复杂度。
- 一个下单页面需要发出5次网络请求才能拿到全部的渲染信息,因为分属不同领域,所以没有一个服务端同学愿意来包成一个接口。
所以那时候想到尝试用Flutter一体化的方式来重构交易链路,从而在研发上提速,以更好地支撑到创新型业务。
演进过程
整个的演进过程都是围绕着如何来降低客户端同学做一体化的成本,对整个研发进行提速,并且解决业务开发过程中的痛点。
通信一体
在下单这个场景,我们设计了如下的通信方式。将每一次的端上改动和当前数据都以request的形式发送给服务端,由服务端算出在该操作下新的价格应该是多少,并以response返回给客户端。双方之间的一纸约定仅仅是靠一个Json。这种情况下,服务端的代码和客户端的代码写起来,是明显有不同的目的性的。即我需要知道当前是在写客户端代码还是写服务端(FaaS)的代码,然后按照之前的Json结构约定去拼出对方想要的数据结构。
但是,我们希望客户端同学去写FaaS层的代码时尽量不要有明显的感知。想到FaaS里实际上封的是一个个函数,例如客户端去调增加购买商品数量(仅针对玩家的宝贝),返回值是全新的state数据,包括价格。那么其实端上也有一些操作是可以理解为一个个函数,例如弹出一个toast(显示库存不足),亦或者是打开一个指定页面或者唤起收银台。将双端的能力函数化后,可以设计出如下图所示的通信方式。
在这种通信方式理念下,我们设计了一套横跨FaaS和客户端的框架用来处理这层通信协议,屏蔽了网络层具体的Json格式,并且双端注册函数的方法以及发出Action的调用方式都是一样的,让开发者无感知调用的函数具体是在哪里。下图是一个代码示例:
编程模型一体
在屏蔽了具体通信协议降低通信成本之后,接下来要考虑新的编程模型应该如何设计。客户端同学写代码经历了MVC、MVP、MVVM时代,随着Flutter起来,因为其与Native完全不同的渲染方式,使得Flux的理念得以落地。Flux定义了一套单向数据流的原则,在Flutter一体化下,我们基于前后一体的整体考虑,设计了如下的一套新的编程模型。总共包含3个模块:Render、Converter、Model。其中只有Render部分在端上,页面上的渲染数据全部来自FaaS层转好的ViewModel(State)。当界面上有交互发生要改变State时,就将事件(Event)发出去,最后路由到Model层来处理,Model层根据这个事件可能会去从后端领域里拉下原始业务数据,然后由框架将数据再交给Converter去转成渲染所需要的State。通过这样的方式以前后一体的思路来组织代码和模块化代码。这套设计也得益于前面的工作将通信的成本降低。
前后端分工
前面的一系列工作降低了客户端同学写FaaS代码的复杂度,那么新的生产关系得以落地和推广。除了在交易链路,我们还在其他一些业务逐渐落地,慢慢地摸索出来了新的一套前后端同学的工作划分。其中FaaS那层,我管它叫做SFC(Serverless For Client)层,里面主要负责的还是面向用户的功能,以支持多变的功能为主。这一层主要负责聚合、裁剪和结构各领域数据,服务于客户端本身用户那一层。而服务端同学会更加专注做好领域建设。
工程一体
对于端侧开发同学来说,我要开发FaaS代码和Flutter代码时需要同时打开两个IDE来回切换,这也是一个很麻烦的事情,尤其是对State有修改时。基于此,我们做了工程一体的工作,将FaaS业务代码和Flutter业务代码放到一个工程目录下,且都单向依赖通用代码(例如State和工具方法),Flutter主工程再以git依赖的方式将工程引到工程里。最后在编译和部署时,编译工具分别选择对应目录下的代码进行操作,从而达到了一开始的目的。
成本
通过在通信层、编程模型、学习领域和中间件知识、工程组织等方式,可以大大降低客户端同学写FaaS层代码的成本。相比之前用Flutter+服务端的研发模式,一体化的研发模式抹掉了前后端接口约定、mock数据开发、编写前后端重复代码、前后端联调、定位问题时前后端转交bug、遇到问题前后端沟通修改接口协议等环节。主要都是协作沟通的成本。随之而来的问题是,客户端同学需要学习业务领域接口,熟悉各个接口的QPS、RT、降级策略,并做好业务整体技术方案的设计。但是这个成本只在一开始的时候存在,随着熟练度的提升,这块成本是可以逐渐趋于0的。
提速效果
当我们把交易链路的架构升级为一体化的架构后,承接了今年的两个创新型业务需求,做评审和开发时,都仅需要一位客户端同学参加,并且只花了半天不到的时间就完成全部开发了,这对新业务上线来讲大大缩短了上线时间。即使有用户层的bug存在,也只要一个人来看,因为代码都是他一个人写的,他能快速定位到bug的具体位置。
未来
未来我希望客户端这套新的研发模式能够在更多的业务场景下落地,去发现更多的问题,让整个一套基础建设更加完善,不断完善出更好的AliFlutter,最后再反哺业务为业务带来更多价值。