背??景微信支付作为一项重要的业务,在客户端面临着各种各样的问题。核心问题是不同平台实现带来的问题:iOS和Android实现不一致,容易出bug,无法通过沟通保证质量,扩展性差,无法快速响应业务需求和变化。迭代周期长,数据上报不全面。设计知识沉淀协议管理松散缺乏统一的自动化测试用户体验不一致比如下图是安卓和iOS不统一之前的收银机。为了解决分平台实现的核心问题,解决之前的技术债。我们构建了一套基于C++的跨平台框架,重构了核心支付流程。微信支付跨平台从iOS7.0.4版本开始,安卓7.0.7版本开始全面覆盖。线上性能指标以iOS上线为例:上线前后crash率保持稳定,不影响微信的稳定性,跨平台支付不一定需要Crash,让用户切换无忧洞察力。比如你可以用微信发个红包,拉起的收银和支付流程都是基于C++编写的跨平台代码驱动。效率提升以核心支付流程代码为例,跨平台需要3512行,iOS原生需要6328行。代码减少了近45%。以开发新需求为例:7.0.4版本需求一:收银台改版7.0.4版本需求二:精简版收银台跨平台实现:iOS+Android共耗时3人天,原生实现为关闭时间前完成:iOS,Android关闭时间后一周基本完成跨平台实现:iOS+Android共计5人日,关闭时间前完成原生实现:iOS和Android基本完成Android关闭时间后一周。支付跨平台软件架构如何?有效地进行质量保证和提高生产力?这是本文的主要内容。什么是软件架构什么是软件架构?正如IvarJacobson(UML之父)所说,让五个人来回答这个问题,五个人可能都有不同的答案。架构定义可以有多种说法,从代码规范到发布过程都可以是架构的一部分。根据微信支付的业务特点,这里对架构的定义是:架构是系统的组成部分及其相互关系(通信方式)。这更符合我们程序员日常写业务代码时对架构的理解。即通俗意义上的MVC、MVVM等。为什么需要软件架构早在1986年,《人月神话》的作者在讨论软件的复杂性时就??说过,软件的本质复杂性存在于复杂的业务需求中。管理复杂性的最基本方法是职责分离。为了实现职责分离,代码复用,架构慢慢复现。架构的本质是管理复杂性。关注微信公众号:Java技术栈,后台回复:架构,可以领取我整理的N个架构干货。没有架构,我们所有的代码都耦合在一起。人类心智模型不擅长处理这种复杂性。架构的建立,本质上与图书馆的图书分类、企业的组织划分等同。它是关于管理复杂性以提高生产力。从零到一搭建支付跨平台软件架构在移动客户端领域,业界都是基于C++编写业务代码,没有成熟的架构。即使业务逻辑是用C++写的,也不涉及UI,也不涉及界面的跳转过程。既然业界没有成熟的架构可以借鉴,那么是不是就简单套用全行业的架构呢?1、抽象业务流程现在业界常用的有MVC、MVP、MVVM。这些软件架构大家都很熟悉了。但是这些软件架构存在一个问题:就是业务流程没有处理好,界面过渡。微信支付有很多流程。流程由接口(ViewController、Activity)和相关的业务逻辑组成。上面的MV(X)模式忽略了一个很重要的点,就是业务流程,谁来负责界面的过渡。即谁来维护ViewController和ViewController之间的关系,业务流程的逻辑写在哪里。如果还是按照传统的MVC模式,那么ViewController负责与不同的ViewController进行通信。然后ViewController不能被重用。更致命的是,业务流程的代码非常不清晰。业务流程的代码分散在各个Controller中,一个Controller可能会耦合多个业务的代码。比如:一个普通的转账流程可能涉及到风控拦截、实名验证、收银、卡绑定、支付成功页面等,如果基于MVC架构,代码很快就会变得难以维护。所以,为了适应微信支付流程多,界面跳转复杂的特点。架构抽象的第一步是将业务流程抽象成一个独立的角色UseCase。同时将接口抽象为UIPage。一个大的业务流程可以分解成小的业务流程。与刚才基于MVC的混乱架构相比:业务流程的代码可以聚合到UseCase中,而不是分散到原来的iOS和Android的ViewController和Activity中。业务流程和接口被重用。契合微信支付流程多、界面跳转复杂的业务特点。2、添加路由机制既然流程已经抽象出来了,这时候就需要对业务流程进行更深入的思考。在开发支付业务流程时,开发者绕不开的问题是:1.流程与页面之间的通信。比如我们要给朋友转账,输入金额,确认支付,触发Cgi。下一个流程是可变的。有可能用户需要去实名,有可能用户需要进入一个安全拦截的WebView,或者正常拉起收银台。本文中的CGI这个词可以理解为网络请求,类似于HTTP请求。所以以前iOS和Android分别实现的时候,没有统一的处理机制。要么通过网络返回包的某个字段来判断,要么在本地维护一些状态来决定接下来要进行什么处理,等等。非常繁琐且容易出错。2、特殊流程的处理支付业务流程还有一个比较特殊的地方,就是在正常流程中间,往往需要插入一些特殊流程。比如有的地方需要跳转到Webview,有的地方需要跳转到小程序,有的地方需要弹窗告知用户风险,或者终止当前进程等等。我们经常需要在业务代码中重复添加这样的处理。这些问题让我想到微信支付需要路由机制。首先了解路由机制。路由机制的核心思想是将数据传递给路由器,然后路由器解析数据并做出响应。结合微信支付与互联网密切相关的特点。创新性地使用支付领域模型作为传递数据。那么如何构建这个支付领域模型呢?建模就是创建映射。领域知识+建模方法=领域建模。那么这里的领域知识就是对支付业务流程的理解。对于建模方法,我采用了UML建模。最终会实现为一个Proto协议,供客户端和后台一起使用。首先,微信支付业务的特点是与网络密切相关,进程和页面往往通过Cgi串联起来。因此,在建立模型时,最外层是网络返回包。对于路由机制,这里我们只关心路由数据模型。路由数据模型由路由类型和每个路由类型所需的信息组成。路由类型明确定义了要触发的行为。是打开一个UseCase,还是打开一个界面,或者是网页、小程序、弹窗等等。然后就是这些动作需要的数据。比如打开小程序需要的参数,弹窗需要的参数等等。建立支付领域模型之后,我们对路由的分析就变得非常清晰了。路由解析后,会根据路由类型触发不同的动作。比如流程和界面流程都会交给UseCase处理。而特殊流程,如打开小程序、打开webview、弹窗等,统一处理。我们在第一步中将业务流程抽象为UseCase。第二步是加入路由机制。加入路由机制后,支付跨平台软件架构演变成了这样。加入路由机制后,与iOS和Android原有的老架构相比:流程统一,页面流向统一。清晰且易于维护。特殊工序统一处理,减少重复劳动。在添加路由机制时,结合微信支付与网络密切相关的特点,对支付字段进行了建模。支付后端协议重构2.0的核心思想也是围绕着这个路由机制展开的。我们来看看加入路由机制后生产力的提升。以支付流程打开WebView、小程序为例,减少代码近83%。更重要的是,这里的特殊流程在路由机制中统一处理,没有耦合到业务代码,可以复用。3.管理网络请求首先我们来看一下iOS在处理支付网络请求时的缺陷:原来的支付请求是通过单实例网络中心发起的,收到返回包后抛出通知或者调用闭包的方法被召回业务方。会出现这样的问题:1.CGI一对多通讯问题。举一个之前遇到的问题的例子。那么钱包发起的Cgi返回包就会覆盖收付页面的数据。之前在iOS上只能通过修修补补,增加场景值,加点标记位来解决。说不定哪天又出新坑了。1、进入钱包页面后,启动一个Cgi2,然后进入支付页面时,启动同一个Cgi。3.如果支付发起的退货包先到,4.然后钱包首页的退货包到。5.CGI生命周期问题。时不时会有用户反馈,为什么没有操作,突然弹出网络错误。原因是cgi的生命周期有问题。业务结束后,仍然处理Cgi的返回包。解决方案:1.将Cgi抽象为一个独立的对象在架构设计上,老架构是通过单例模式实现的密集API,而我们的新架构是通过命令模式实现的离散API。也就是把Cgi封装成一个独立的对象。我们整合了与Cgi相关的属性和功能。开发业务时,只需简单继承BaseCgi并设置参数即可。2、划分职责,明确生命周期中由谁发起Cgi。Android和iOS之前都没有统一的方法。有些人会将Activity、ViewController和UI代码放在一起。因此,在跨平台软件架构中,我们统一由业务流程UseCase发起。而且生命周期是一对一的。一个Cgi只能被一个UseCase处理。UseCase被销毁后,Cgi也会被销毁。与旧架构相比:消除了一对多通信带来的bug生命周期和业务逻辑绑定,不会有业务端,Cgi回来后触发action。高内聚,低耦合。cgi相关数据和能力集中处理,业务方无需感知。提供统一的缓存和加密能力。在第一步和第二步中,我们对业务流程进行了抽象,并添加了路由机制。第三步之后管理网络请求。我们的软件架构是这样演变的。4.规范数据传输iOS和Android的旧架构都存在信息传输不当和数据污染的问题。这个问题是最糟糕的。iOS和Android都有很多错误。首先我们来看看最近在现网出现的问题:在iOS出现之前,很多内部同事和外部用户反馈:执行更改页面后,无缘无故弹出一个空白框。而且支付与钱有关,导致用户恐慌。具体原因是:进入支付首页,后台返回数据,然后写入一个公共Model。然后进入钱包页面,再进入找零页面。这个公共模型是一路传递的。然后变更页面读取了publicModel的数据,但是代码无法处理,导致了这个让用户恐慌的问题。另外,在安卓和iOS上也出现了很多错误,比如钱包页面的零钱显示。付款时。银行卡故障等。这些问题形形色色,大小不一,似乎发生的地点和场景也各不相同。每次遇到这种问题,我只能修复它。但如果深入下去,你会发现真正的原因是软件架构的问题:旧的支付架构采用的是黑板模式,虽然数据读写方便。但是问题和收益完全不成比例:1.有公共读写的数据类型。Android传递的数据类型是字典,而iOS是Model对象。所有接口和业务逻辑共享一个数据。2.无序数据流。数据流向不可追溯,任何使用公共数据的地方都可能发生数据修改。然后支付跨平台软件架构,以杜绝此类问题。我是这样做的:去掉公共读写的数据类型,传值类型(ValueType)数据。后续流程修改数据时,不会影响到之前的流程。单向传输数据,仅依赖于注入必要的数据。如果数据修改需要通知上一个进程,使用代理模式通信。规范数据通过后。与旧架构相比:从架构上,从根本上解决了长期以来困扰微信支付的数据污染问题。数据流向是单向的,数据流向是可追溯的。前三步,我们将业务流程抽象出来,加入路由机制,统一管理网络请求。那么在规范了数据传输之后,我们的软件架构就演变成了这样。总结软件的本质复杂性存在于复杂的业务需求中。软件架构的本质是管理复杂性。所以,真正好的架构,是从复杂的业务需求反复抽取和总结中衍生出来的,解决的是实实在在的业务问题,而不是一句空话。除了清理旧的历史架构的缺陷外,软件架构是我们业务发展的基石。它还可以为业务赋能,为业务带来价值。在建立软件架构的基础上,还围绕软件架构构建微信支付、防重复支付、安全横切等跨平台数据自动上报机制,带来巨大的商业效益。如果有机会,我会进一步写相关的文章与大家交流讨论。架构是一个不断进化的过程。由于新的支付业务是基于跨平台软件架构不断编写的,我会不断更新迭代这个架构。让这个软件架构更适合微信支付,更健壮和完整。
