写点什么

移动端组件化架构方案设计

2020 年 12 月 29 日

移动端组件化架构方案设计

一、背景


组件化作为移动端应用架构的主流方式之一,近年来一直是业界积极探索和实践的方向。我们自 2018 年起也在不断尝试各种组件化方案,在智慧政务的多个应用中也进行了实践。我们踩过一些坑,也收获了很多宝贵的经验,并沉淀出了符合我们自身实际业务需求的组件化架构方案。


二、什么是组件化


通常讲到组件化,很多人会认为我们去把一些可以抽象出来的通用的功能模块比如网络库,本地数据存储等等封装出来,以三方库的形式提供给 App 的开发者,这样就算是组件化的开发,严格上来讲,这只能算功能模块的组件化,而我们这里要探讨的是移动端整体架构的组件化,除了提供功能模块的组件化,更多的是强调将 App 的总体业务拆分成不同的业务模块,去实现各个业务模块间的解耦合,甚至包括业务模块和主工程文件之间的解耦合,最终实现业务模块的分布式开发,以及业务模块级别的代码共享。我个人觉得“业务模块化”这个定义相对“组件化”似乎更合适一些。组件强调物理拆分,以便复用;模块强调逻辑拆分,以便解耦。


三、组件化架构总体方案设计


在 App 项目开发中,如果项目比较小,普通的单工程架构就可以满足大多数需求了,但是像大型项目,或者公司 App 数量越来越多时,那原有的单工程架构就不足以满足架构需求了,其存在的问题主要有:


  1. 当项目越来越大时,单工程架构的业务模块间没有明确的划分,模块之前的耦合度大,后期维护成本较高,往往修改一处可能会影响别的耦合模块,出现问题也比较难定位。

  2. 当 App 数量越来越多时,重复工作的可复用性低,即便复用也是代码级的拷贝复用,复用后再修改也需要多处同步更新,不方便同一代码的后期统一升级维护。

  3. 所有模块代码都编写在一个工程中,调试某个模块或功能,需要编译运行整个大的单一工程,编译一次时间很长


为了提升移动端整体的开发效率和产出质量,我们在原有的单工程架构的基础上提出来组件化架构的方案,下面是我们组件化架构的整体分层架构图:



组件化架构从 App 运行时角度来说分为四层,横向层之间是相互不依赖完全解耦的,纵向层之间上层依赖下层,调用下层提供的服务:


业务组件层,整个 App 实际上是由多个业务组件组装而成的,也就是说,在创建 App 时,首先创建一个主工程,然后确认总体业务的拆分,每一个拆分出来的业务组件是一个独立的子工程,主工程负责将所有业务组件当作二方库集成到主工程里,每个子工程可以单独维护、独立编译运行,业务组件之间是完全解耦的。业务组件层的运行依赖下面的三层:


  • 基础组件层,共包括 UI 组件集、数据处理组件集和通用功能组件集。为业务组件层的开发提供具体技术点的支撑。

  • 底层容器层,容器层为整个架构的核心,它是业务组件间解耦合的技术核心,其中路由总线解决组件间一对一的通信(包括页面的跳转和功能函数的调用),消息总线解决组件间一对多的通信,路由总线+消息总线,为组件间的解耦合提供了底层支撑,生命周期的管理解决的是业务组件和主工程之间的解耦合,总结之,底层容器层为组件化框架打好了底层通信基础。

  • 平台系统层,所有的上层封装的组件都依赖于平台系统的接口,这里的平台系统包括 iOS 和安卓。


组件化架构方案的核心在于,将业务按模块划分,通过底层容器和基础组件层的支撑,实现业务模块间的解耦,方便后面的开发和维护,同时,底层容器层和基础组件层作为通用组件沉淀出来复用,后面由专人统一开发和维护,大大节省了实施组的开发工期。下面是基础我们提出来的组件化架构方案落地实施的目标工程结构图:


四、核心技术实现

1、业务模块间的解耦合


传统的 App 架构设计更多强调的是分层,基于设计模式六大原则之一的单一职责原则,将系统划分为基础层,网络层,UI 层等等,以便于维护和扩展。但随着业务的发展,系统变得越来越复杂,只做分层就不够了。App 内各子系统之间耦合严重, 边界越来越模糊,经常发生你中有我我中有你的情况。这对代码质量,功能扩展,以及开发效率都会造成很大的影响,非组件化的架构业务间的相互调用通常会产生如下图所示的强耦合的调用关系:



此时,通常会采取将各个子系统划分为相对独立的模块,通过中介者模式收敛交互代码,把模块间交互部分进行集中封装, 所有模块间调用均通过中介者来做,如下图所示:



这时架构逻辑会清晰很多,但因为中介者仍然需要反向依赖业务模块,这并没有从根本上解除循坏依赖等问题。时不时发生一个模块进行改动,多个模块受影响编译不过的情况。进一步的,通过技术手段,消除中介者对业务模块依赖,即形成了业务模块化架构设计,如下图所示:



通过业务模块化架构,一般可以达到明确模块职责及边界,提升代码质量,减少复杂依赖,优化编译速度,提升开发效率等效果。


我们在具体实现业务模块间的解耦合采用的是路由总线设计+消息总线设计的方式。


1.1 路由总线


路由总线的原则是解除组件间耦合,让 App 业务开发这只需要遵守规则调用,不用关心底层/其它业务的具体实现。内部的路由设计,主要需要解决两个问题:各个组件之间的页面跳转问题和各个组件之间相互调用。通过路由总线的设计,真正确保组件间实现高内聚、低耦合。下面是路由总线的详细设计图:



在具体的技术实现细节上:路由总线是一个单例对象,我们在这里命名为 JXURLRouter,在其内部维护着一个 “URL -> block” 格式的注册表,通过这个注册表来保存所有业务组件服务方注册的 block,以及使调用方通过 URL 映射出 block,并通过 JXURLRouter 对服务方发起调用。并管理该注册表的增删改操作。服务方 URL 的提供可以分为两种:


  • 1、不带返回值的页面跳转;

  • 2、带返回值功能调用。


关于业务组件服务方的 block 何时注册,这里需要在业务组件源文件被加载后,main 函数执行前注册,这样保证 app 启动后的所有业务逻辑里都可以任意调用注册后的服务方,所以注册是在组件源文件的+Load 函数里操作的。目的是提前注册时机,后续任意调用。


拓展


正因为 URL 路由可以发起调用也可以接受返回值,同时 URL 设计可扩展为:通过后台配置某个操作的跳转 URL,URL 如果可以被解析(路由表里能查找到)就直接拿来调用,如果不能被解析就跳转 H5 页面。这样就完成了一个对不存在组件调用的兼容,使用户手中比较老的版本依然可以显示新的组件,不过这还需要 H5 页面功能的配合。


1.2 消息总线


路由总线实现一对一的进行消息派发和调用,如果多次注册同一个 URL,则会被覆盖掉,为满足针对一对多的消息派发,我们增加消息总线的设计,用来做为相互解耦的组件间交互通信的补充。


应用通过消息总线进行事件的中心分发,例如 App 系统用户登录,退出等事件,都可以通过消息总线分发到想订阅此消息的各个组件。


下图是消息总线的详细设计图:


2、业务模块和主工程之间的解耦合


组件之间一对一的页面跳转和功能的调用。解决方案是路由总线,组件之间一对多的消息传递,解决方案是消息总线,那解决完组件间的通信之后,接下来是实现主工程和各业务组件间的业务解耦,也就是生命周期的管理,将主工程中生命周期钩子函数里的业务逻辑处理都下发到各个业务组件中去。


五、总结


移动应用的组件化架构设计,其真正的目标是提升开发质量和效率。单从实现角度来看并没有什么黑魔法,更多的是结合团队实际开发协作方式和业务场景的具体考量,我们建议所有业务模块划分进入稳定期的 App 采用组件化架构设计。即使模块划分还没完全明确,也可以考虑对部分明确了的模块进行组件化改造。因为随着 App 业务的不断迭代累加,团队规模的不断壮大,迟早要用,晚用不如早用。而且目前基于路由 URL 协议注册的模块间通讯方式,对开发效率基本无损。


本文转载自:金科优源汇(ID:jkyyh2020)

原文链接:移动端组件化架构方案设计

2020 年 12 月 29 日 08:001187

评论

发布
暂无评论
发现更多内容

用最少人力玩转万亿级数据,我用的就是MongoDB

dbaplus社群

滴滴夜莺社区文章有奖征集

Obsuite

最佳实践 奖品 案例分享 滴滴夜莺

如何基于Spring Aware和InitializingBean接口实现策略模式

技术进阶之路

Java spring 5 Java设计模式

最简单的map,filter,forEach,every,some的使用教学

coolFish(呔呆)

方法 Vue 前端 数组 js

Java并发包源码学习系列:阻塞队列实现之SynchronousQueue源码解析

云流

Java 编程

全新演绎!阿里甩出2021最新秒杀系统设计实录!这也太香了吧

程序员小毕

Java 架构 面试 系统设计 高并发

看完字节大佬的算法刷题宝典,我直接手撕了500道算法算法题

云流

程序员 面试 算法

区块链电子签章解决方案--区块链助力电子签章

135深圳3055源中瑞8032

年终总结:华为|字节|腾讯|京东|网易|滴滴面经分享(斩获6个offer)

Java架构之路

Java 程序员 架构 面试 编程语言

Gradle Docker插件将SpringBoot应用程序打包为Docker镜像

wjchenge

Docker SpringBoot 2 Gradle

夕四今晚加班到2点30,而王二还不打算走《打工人的那些事》

谙忆

区块链数字版权保护解决方案--开创了新的维权思路

135深圳3055源中瑞8032

十里选一终拿offer,准阿里java程序员分享面试经验!

Java架构之路

Java 程序员 架构 面试 编程语言

架构训练营大作业(二)

一期一会

作业3

瑾瑾呀

2021最新「阿里」Java高级工程师面试高频题:JVM+Redis+并发+算法+框架

比伯

Java 编程 架构 面试 计算机

PanoVideoCall 的 Electron Demo 开源了

拍乐云Pano

html Mac windows Electron js

Varchar竟然会自动存储成lob类型?

dbaplus社群

webpack | 进阶用法2:代码分割和动态引入的实现方式

梁龙先森

前端工程 webpack 28天写作 2月春节不断更

驱动力读后感之一

张老蔫

28天写作

产品经理训练营课后作业-第三周-产品思维和产品意识

.nil?

产品经理训练营

如何基于Spring 事件驱动模型实现业务解耦

技术进阶之路

Java spring 架构

科技,亲吻这个特别的春节

脑极体

「抖音同款播放器」上市:有效解决卡顿、黑屏和模糊

字节跳动技术团队

架构训练营大作业(一)

一期一会

满满的干货!阿里开源Java程序员2021年金三银四面试指南

Java架构之路

Java 程序员 架构 面试 编程语言

三顾茅庐,七面阿里,25k*16offer,还原我的大厂面经

周老师

Java 编程 程序员 架构 面试

中国为什么加快推进数字人民币

CECBC区块链专委会

数字货币

区块链在数字版权领域的应用发展报告(2020)

CECBC区块链专委会

版权保护

欢迎来到,2021摄像机竞技场

脑极体

区块链--另一场改变社会组织方式的工业革命

CECBC区块链专委会

区块链

2021年全国大学生计算机系统能力大赛操作系统设计赛 技术报告会

2021年全国大学生计算机系统能力大赛操作系统设计赛 技术报告会

移动端组件化架构方案设计-InfoQ