本文将由eBay Payments Team分享自主研发的Funding Instrument Materials 物料库,主要包括现有基础组件库存在的问题、新型组件库的设计思路、全物料生态的搭建和效果,以及调整实际效果的方法。希望能对同业人员有所启发。
开门见山,物料就是元素(element)、组件(component)、业务组件(business logic component)、页面(page)和工作流(flow)的聚合。
早期,社区和eBay内部出现基于UI的基础组件库。慢慢地,组件汇聚成页面,页面配合场景串联成流,最后Payments Team将需求细化,分割场景,按需所取,汇总形成了我们今天讨论的物料(Material)库。赋能,大家早就在各种新词汇的炒作下听到耳朵起茧了,比如数据赋能,比如工具赋能。但是这篇文章真正讨论的是什么,我必须要在全文开头给一个通俗而明确的定义,那就是:而不是“我把我的本职工作踢给其他team使得我自己的效率提高了”。这句话就是抛弃了【更强的业务能力】这一关键核心的典型,相信很多小伙伴对这一点都深有体会。工欲善其事,必先利其器。调研学习市面上已有的成熟架构很重要。大家很容易想到许多国内外优秀公司的团队赋能的案例,最为突出的一种架构就是【大中台-小前台】的方案,用巨大的中台支撑业务逻辑从而快速搭建与分拆合并各种前台业务。这个方案在很多体量大的公司里都有应用,看似十分高效。但是,这恰恰是拖累业务本身的病因所在,在实际执行层面也会产生较多不易发现的短板。业务部门因为从一开始受控于中台,使得业务前台逐渐沦为中台的附庸,反过来中台就承担了更多前台细碎的需求,配置也越来越多,变得积重难返,最终与设计初衷背道而驰。而eBay Payments本身就有很多历史包袱,业务盘根错节,我们考虑再三创造了另一种方案 ——打造物料库与生态。接下来着重介绍我们是如何开发和完善这套物料库的。
“我理解eBay已经有这一套东西了,你不要重复造轮子。”
这句话,我相信是很多看到这里的人或者刚看到标题的同学第一个从脑海里蹦出来的。这个问题也是之前一位“资深工程师”对我们提出的。回答这个问题,我们先要搞明白“已有的这套东西”。显然,eBay Skin,eBay Payments自研的基础组件库已经有了,但是同时大家要明白,基础组件库的设计原则就是配置多而灵活,通俗一点来说就是“所有可以暴露给使用者的都应该暴露,所有可以被用户控制的逻辑都应该被用户控制”,甚至可以更直白地理解成是“纯UI交互稿对原生元素的包装”,唯有这样才能保证组件库的泛用性。而实际进行开发时,就会经常出现需要复制粘贴业务逻辑代码和加入一些自定义逻辑的情况,因为主要的业务逻辑是被使用者掌握的。先给一个典型的例子,一个卡片添加与管理的页面,是多次出现在eBay的各个业务里的,支付的时候需要,管理支付手段的时候需要,退款等等操作的时候也可能需要。过去这种矛盾不突出,很大程度上是因为支付手段添加与编辑的功能已经放在PayPal里了。而当下的eBay亟需能够脱离PayPal依赖独立管理支付的手段,并且这种需求越来越急迫,导致同样的功能和页面多处实现,甚至复制粘贴的情况也多了起来,基础组件库显然是不能满足这样的复用需求的,也无法把业务逻辑耦合进普通的组件里。
图2:某典型支付管理页面(点击可查看大图)
此外,随着基础组件库的升级迭代,极端情况下现有业务逻辑冲突甚至出现bug的情况也不可避免。我们以Payments自有的基础组件库为例:如图3所示,基础的input的框不具备格式化format的能力,因为输入的每四位加一个空格这个逻辑是实际业务开发者必须做的事情。图3(点击可查看大图)
技术层面上,因为React的特点就在于更新状态(update state)这种特性,所以,当格式化加入空格之后的值(new value)的长度,与基于原生input的基础组件里用户输入的值(origin value)长度不符合时,光标的位置就会丢失从而自动重置到最后。
图4(点击可查看大图)
(一小段可以复现这个问题的代码例子,大家可以试试看)为了解决这个问题,就不得不改写组件内部的逻辑。事实上,笔者所了解的其他知名公司产品(比如腾讯文档,阿里语雀,字节跳动的lark)都针对性地改写了底层组件的逻辑,甚至弃用了原生input元素。
基于此,我们得到现有组件库的一个现状和两个痛点:
现状:
我们确实有一套组件库,它的配置足够灵活和泛用,但是用起来并不方便。
- 基础组件库不能也做不到代替相同业务需求开发的重复劳动。
基础组件库不能为特殊的业务逻辑写兼容性代码,可能会导致极端情况的发生。
痛点诞生需求。
回到开始,回答标题的问题:这不是“重复造轮子”,而是因为现有的组件库仍无法满足需求,甚至很多的配置会带来技术上的冲突导致”写bug”,为了解决这些一线开发的痛点,我们需要打造新工具。
曾几何时,开发自己也对复制粘贴不是亲手写的代码深恶痛绝,更痛苦的是最后还得肩负“擦屁股”的责任。“我没动啊,我都是原样照抄之前的逻辑啊,出了bug怎么能怪我?”“这之前的代码简直***,我要重构!”为了解放大家日益发白的ctrl和command键,我们决定,第一步是剥离出可复用页面,优先解决产品开发共同的需求——减少重复开发页面的需要。设计思路很明确,页面要如同组件一样方便使用。设计一个SDK,通过参数配置初始化页面,然后返回页面内容的形式有这么几种:- 设计一个黑盒页面,只返回页面的url+id token,页面自己通过收到id token映射对应的配置,自己渲染出来。
针对Payments现有的项目架构,1号方案对原有页面侵入比较大甚至可能覆盖已有的样式和功能,故而采用了侵入量较小的2号方案。很快,可配置可复用的业务页面就上线了。如上所示,页面内部的逻辑状态,保存下来的数据,提交的表单,甚至错误处理完全交给内部实现,使用者只需要接收最后的成功回调即可,一下节省了大把纠结页面里逻辑问题的时间。图6(点击可查看大图)
实际效果参考如上两图,通过配置不同的参数,可以按需求展示差分的页面。看起来似乎效果不错,不过另一个问题就来了——配置项太多。“你这个页面要传几十个配置,学习成本太高了,我记不住。”“能不能记住一套配置,让我们给一个id或者key就可以了呢?”于是我们基于复用页面扩展出新的架构,那就是可复用工作流(flow)。以卡片管理为例,我们知道整个用户的操作逻辑都是一致的,从选择卡片类型->输入卡片信息,保存->选择卡片用途->同意授权协议->更新卡片到用户支付手段列表。入口可以是多种多样的,比如在A业务中是先选择用途,B业务则是先同意授权,无非是多个页面的排列组合,而如果可复用页面的参数配在复用流的数据表中,用户就不需要一个个页面参数配置过去了。图8(点击可查看大图)
这下,使用者可以说是彻底把复杂的配置抛弃,只需要一个A flow的key即可。一旦这个flow被建立,那么在任何需要开放A flow业务入口的地方都不需要再次配置了。至此,快速接入占据了上风,开发者们从“灵活丰富”的配置项里得到了解脱。
让我们回到文章一开始提出的【大中台】方案之所以不通过的原因:中台会承担原来越多实际的业务需求,最终把所有的锅都接下来。
屠龙者终成龙。当使用者不需关心复用工作流的内部业务逻辑时,关心的人就转移到了我们自己身上。于是我们反问PM:“在不同入口下,同一套业务逻辑的细节真的都是完全一致的吗?”
PM会“无邪”地回答:“哦那当然,我的老伙计,除了A项目的A需要多个blabla,B site的B需要少个blabla……”
这些PM眼里动动嘴的小要求,恰恰成了压垮全组开发的最后一根稻草。
渐渐地,你会发现,最占用开发时间的就是处理边界情况(edge case)和细小改动(minor changes),甚至我们可能需要为了一个“细小改动”做出一个全新的复用页面,那就和设计初衷背道而驰了。
于是我们整合出了终极的方案——搭建全物料库和生态,简单来说就是:你全都要我全都给你。
很显然我们现在拥有了物料里的两类:页面(page)和工作流(flow),于是我们的下一步就是提炼有着高度复用需求同时不易发生改变的业务组件(business logic component)。举两个例子,当下复用频率最高同时又不容易改变的就是卡片输入表单和账单地址管理表单,如下图所示:图9(点击可查看大图)
很明显,由于不同业务的布局和细节不同,表单内容有多有少,于是我们又细化出卡号输入和识别组件、日期输入组件,通知支持自定义格式化形式。同时和数据接口层商量表达性一致的接口格式,使得使用者在接入业务组件时既确保了接口的形式,又让来回扯皮的“定接口会”不复存在(理想情况下全平台客户端的接口格式都可以保证一致)。至此,我们来回顾全物料生态下对于整个支付业务开发效率的提升:首先,灵活的配置完整地得到了保留,如果需要自由搭配,可以接入组件与业务组件库。从最简单的输入到格式化输入再到卡号输入与识别,全都提供,产品改需求不用怕,业务刁钻也不用怕。哪里不会选哪里,经理再也不用担心你的排期~其次,使用者想要快速接入,保证大部分Payments的业务场景下开发者不用写重复的代码,不用再为了格式化一个输入重新改写一个输入框。如果业务的定制性不高,可以直接使用工作流或者页面搭页面。同时,如果你的页面有PM的特定需求,需要自己微调,可以在页面和业务组件之外自行编写纯数据流通和服务器通信的逻辑,UI交互、组件间联动、表单提交和校验、过滤数据和错误处理与展示完全交给页面内在的业务组件。可以看到我们设计的物料库是全粒度的:想要控制页面每个元素选组件,想要控制前后关系选页面,想要完全放手不管选工作流,总有一款适合你。下一步,甚至可以将属于你们自己业务的物料提交到私有和共有仓库,丰富物料库,做到“想复用就复用,想定制就定制”。
“你说那么多,有没有0成本调试实际效果的方法呢?”
都说万事开头难,开头读文档难。普通的文档除了官方examples之外,我想要试试别的参数怎么办呢?我想要看看组件放在我自己的逻辑里正不正常怎么办呢?难道我还得搭项目,下载包,编译打包好才能看到效果么?引用广大程序员最喜欢说的一句格言“Talk is cheap,show me the code.”
如果能让我自己改几行代码看看效果,那就会是最直观有效的学习方式。
为了解决这个使用者“最后一公里”的问题,我们开发了可以“所见即所得”的文档。这样,就可以直接在我们的线上文档编辑实时渲染效果了,甚至你可以自己调整添加删除元素获得属于你自已的代码。
目前,已有多个业务接入了Payments Team的物料库。
图13(点击可查看大图)
我们相信未来的开发模式会是以使用页面+工作流复用为主,以自行拼搭业务组件为辅的开发模式。配置的灵活性与使用者的方便快捷永远是在业务发展过程中此消彼长的一对矛盾。问题的本质在于,我们常常苦于为了方便快捷开发而过于定制,等到需求发生了变化,又不得不打补丁式添加上一个个配置。而我们决定跳出问题的小范围,不做选择,打造了全粒度的工具生态,在更大的范围内找到了更好的解决办法。- 完善物料开发者文档,支持把基本前端页面源码导出到 IDE 中,供不熟悉UI开发的同学进行业务逻辑的开发。
开发物料库的初衷还是为了解决“怎么开发简单,怎么开发快”的问题,我们将致力于让开发用“更少的资源”获得“更高的效率与更强的业务能力”。