
背景
基于洋葱学园 iOS 端组件化重构之路[一]-现状梳理 得出的结论与方案,需要验证方案的可行性及实施成本,设计完整架构图和演示工程,包括后续持续集成的改造思路等。
实施目标
- 中间件的方案,产出完整调度能力的中间件Demo,包含下沉依赖关系演示
- 列出现有功能的基于中间件改造成本
- 如何梳理职能范围,拆分力度如何确认(依赖链是否保持单一)
- 设计完整架构图,确保双端都可基于组件的独立运行单元测试、运行、迭代
- Jenkins 基于独立工程改造(能设置指定工程路径)
以分支切换的形式
调度演示
具体效果见实际 Demo
演示流程
流程1: C 端用户进入备考
单元测试 APP 启动 -> (首次)中间件调度 C 端用户登录组件进行登录 -> 登录组件完成,通过中间件调度用户数据组件进行 C 端用户数据缓存 ->进入单元测试 APP 首页 -> 点击首页备考入口,通过中间件调度用户数据组件读取已缓存的 C 端用户数据 -> 通过中间件调度备考业务组件

流程2: B 端用户进入备考
单元测试 APP 启动 -> (首次)中间件调度 B 端用户登录组件进行登录 -> 登录组件完成,通过中间件调度用户数据组件进行 B 端用户数据缓存 ->进入单元测试 APP 首页 -> 点击首页备考入口,通过中间件调度用户数据组件读取已缓存的 B 端用户数据 -> 通过中间件调度备考业务组件

流程3: C 端用户进入抖葱
单元测试 APP 启动 -> (首次)中间件调度 C 端用户登录组件进行登录 -> 登录组件完成,通过中间件调度用户数据组件进行 C 端用户数据缓存 ->进入单元测试 APP 首页 -> 点击首页备考入口,通过中间件调度用户数据组件读取已缓存的 C 端用户数据 -> 通过中间件调度抖葱业务组件

中间件设计
YCMediator
基于维护成本 、解耦力度 、扩展性 及现有工程侵入性 的综合评估,决定采取 Runtime 方案实现中间件,并在业内知名中间件 CTMediator 基础上进行强化改造,后续自行维护
1 |
|
改造成本
按照现有工程的组件化现状,将改造成本分为解决依赖链问题的「解耦成本」 ,和填补目前没有中间件调度能力的「通信改造成本」 。
解耦成本
基本评估
复杂度:★★☆☆☆
挪动代码并没有什么复杂度,复杂度基本体现在需要职能拆分时,如何拆分、合并和重组。
人力成本:★★★☆☆
涉及的实际库比较多,需要实际过一遍代码,且属于前置项,要尽短批量的完成,所以需要完成会花费较多人力的时间成本。
涉及范围
- 全部中台库
- 中学基础库(不含业务库)
解耦内容
按照后文梳理出的职能范围规范,拆分代码,各司其职,该下沉的下沉至基础服务中,该上提的提入到通用服务或业务中。
⚠️⚠️非必要情况,只挪动代码,不调整代码逻辑,建议整类迁移⚠️⚠️
如果类中掺杂了不属于该库只能的代码,则继续秉持职能范围规范,并入其他现有库或与其他同职能散落代码合并独立成库。
通信改造成本
基本评估
复杂度:★☆☆☆☆
仅需要在目标库中建立一个Target类,和一个基于中间件建立目标库的 Category 库,共同负责对外通信,无侵入,不涉及旧代码已有逻辑,考虑到组件对外调度接口都不多,所以复杂度很低。
人力成本:★☆☆☆☆
因为不涉及业务入侵,所以引入单元测试时再进行开发即可(只增加通信代码),不会占用多少人力成本。
涉及范围
- 全部中台库
- 全部中学库
- 全部教师/入校库
改造内容
在需要中间件调度通信(同层横向依赖)时,在需要被调度的库当中建立一个Target类,再建立一个与被调度的库相对应的,基于中间件的 Category 库即可。需要横向依赖才进行改造,无横向依赖时不需要改造,理论上,基础服务库之间不应存在横向依赖(具体见架构图)。
梳理职能范围
职能按照基础服务 、通用服务 、基础业务 、通用业务 、独立业务来划分
⚠️注意:非洋葱自行维护的第三方库不在职能范围内,因为第三方库不会主动与洋葱内部职能库产生依赖关系,只存在单向被引用的依赖关系。
基础服务
基础服务属于能力基建,不与任何具体业务、具体功能挂钩,只提供应用程序的最基本支撑能力,应当放之四海皆通用,是组成应用程序的充分必要条件,由现有中台继成维护。
基础服务应足够 “干净”,不应存在任何形式的彼此横向依赖,如果产生了就需要抽离拆分。
⚠️基础服务原则上不直接提供给业务方使用,由上层通用服务封装后向上层业务提供能力,其目的是保证基建不依赖某一特定技术项目,可随时迁移、替换。
网络
- 基础网络库
数据库
- 基础数据库
日志
- 基础日志库
APM
- 性能监控
- 崩溃防护
通用服务
通用服务属于依赖于基础服务之上的,面向业务层的通用服务,同样是提供能力而不是具体业务,不关心具体业务细节,面向洋葱所有业务线提供通用服务能力,是组成应用程序的充分不必要条件,但在洋葱内部同样属于充分必要条件,可供洋葱所有 APP 使用的能力,由现有中台继承维护。
通用服务之间可由中间件进行横向调度,只单向依赖于基础服务
环境/配置
- 通用宏/静态变量配置(不含业务字段)
- 热更新
- 函数扩展/类扩展
- 环境校验
视频播放器
- 基础播放器(不含插件、不含特定业务功能)
支付
- 基础 IAP 内购
- 第三方支付
分享
- 通用分享
浏览器
- 基础通用浏览器
- 通信桥(Riki)
埋点
- 数仓日志上报
- 阿里云日志上报
数据缓存
- 视频下载缓存
- 偏好管理
基础业务
基础业务面向业务,向下依赖通用服务,属于面向洋葱内部所有 APP 的通用性的基础业务组件的集合。基础业务兼具能力与功能,可通过配置兼容不同具体业务线的具体业务要求。是组成应用程序的不充分不必要条件,在洋葱内部属于不充分必要条件
⚠️基础业务必须是具有可根据参数动态配置的能力,各业务线开箱即用的状态,或拥有极佳的扩展性帮助业务线快速扩展所需能力
⚠️基础业务只向下依赖通用服务,不依赖其他业务内容
业务播放器
- 基础功能播放器插件
支付中心
- 基于通用业务封装的支付功能
分享中心
- 基于通用业务封装的分享功能
鉴权
- 通用鉴权
用户数据
- 基础用户模型
登录
- 基础登录功能(可配置的不包含具体业务线的登录业务能力,不含UI)
动态化
- DSL
通用业务
通用业务主要包含可复用的细颗粒度业务功能,非完整业务功能,主要由具体业务线内部负责维护,是该业务线内部可重复使用的功能。
⚠️原则上同样只向下依赖基础业务,不横向依赖其他业务
业务播放器
- 学习播放器
- 短视频播放器
- 简单播放器
用户数据
- 各端基于基础用户模型扩展的本业务线具体用户模型
登录
- 基于基础登录扩展的本业务线具体登录功能
客服中心
- 通用客服中心
鉴权
- 基于基础鉴权扩展的本业务线的通用鉴权
浏览器
- 基于基础浏览器扩展的本业务线浏览器
独立业务
顾名思义,基于通用业务构建而成的纯业务组件,向下雨来通用业务,横向由中间件调度进行通信。有个具体业务线负责维护,无需考虑复用性,只做组件下沉
具体业务
- 业务线登录组件
- 备考组件
- 抖葱组件
完整架构设计

持续集成
只需要在 Jenkins 上维护一个单元测试工程即可,用企业包维护测试环境和线上后门环境即可,通过 branch 来区分具体的测试单元。
单元测试工程
- 集成配置:包含中学、教师和校园的 request host 等基础配置即可
Jenkins
- 维护 UnitTest_Test 和 UnitTest_Release 两个 Job
- 每次独立的单元测试用独立的 branch 进行区分,master 分支只保留包含了集成配置和中间件的空主工程,各组件由各 branch 独立添加