作者|郭玉鹏,在软件架构领域,框架的功能类似于基础设施服务,是为实现某个业界标准而形成的组件规范。简单理解,框架就是制定一套规范或者规则,开发同学在该规范或者规则下工作。本文通过剖析框架实体 ServiceKit/Adapter ,来窥探其底层结构和架构设计。,随着抖音业务的发展,为保障整体工程演进和迭代计划的高效运行,体系化建设已加速提上日程,Codebase(可通称为产物)融合是其中项目之一。该项目主要为开发同学提供底层复用能力、增强研发团队效能,致力于帮助开发同学轻松高效地研发、管理代码。,
,Codebase 融合过程中,技术团队在各个业务线方向进行着差异化探索;演进路程上,业务线间耦合越来越强,开发同学迫切需要一套解决方案来做差异化代码隔离。如下图抖音与抖音极速版模块差异所示。,
,回顾痛点,在过往的开发中,开发者们一般使用宏隔离( isLite or isPad )来区分不同产物之间的差异,但这种方式严重破坏了整个抖音工程的架构体系,以下从几个维度分析。,研发效率:需要支持不同宏变量进行 lint ,有重复 lint ,单个组件很难区分项目控制二进制发版频率,二进制需要频繁更新,宏会导致很多混编二进制,影响编译效率,如果以单个文件作为编译缓存单元,宏隔离也会降低编译缓存命中率。,可扩展性:扩展性差,缺乏动态能力和插件能力,添加新功能和修改原有功能会导致类实现的代码急剧膨胀。,圈复杂度:宏隔离的代码分散,修改和重构成本高。,组件粒度:无法支持项目间差异业务独立成组件,背离高内聚、低耦合原则。,我们的目标愿景是要做一套符合抖音工程架构体系,具备高效、通用、便捷能力的框架规范,让开发同学在标准规则下进行编码工作。,启蒙设计是着手做事之前的抽象意识,如下图,在多个产物的研发环境下,将共同代码能高效的复用,差异性代码优雅的隔离开。,
,为了帮助新同学快速入手架构框架,笔者在做此框架 Swift 建设的过程中,基于近段时间经历的几个项目经验,总结出了一套系统性的脑图,下面和大家分享下框架系统化的全景。,
,基于上述框架系统化的思路铺开,整个篇章会先介绍一些设计思想,再进行性能等相关的技术细节。由于篇幅有限,我们将精简出我们认为比较重要的技术点进行重点讲解。,
,开发同学不用关心各个模块的复杂度、业务的逻辑性、是选择类对象还是实例对象、如何初始化各自单元等,仅需要基于包装好的适配器来做各自的任务调度,类似于万能充电器( 90 后同学时代的产物 :> ),无需关注电池是华为的,还是 OPPO 的,即插即用。,
,
,
,简单了解微服务后,以服务角度来看,多个 Target 产物根据各业务模块可划分为多个 Adapter 服务,搭配绑定多个适配器协议,这样能达成一对多效果。,我们深入性的介绍下内部设计思路。在使用阶段,一个主类可以向多个适配器类发送消息;在注册过程,一个适配器类可以绑定到多个适配器协议,并且满足两种场景:一是多产物必须实现的接口,可以放在一个公共的协议上,二是单个产物必须实现的接口放在独立的协议上,公共协议 + 独立协议可以进行组合,由同一个有上下文关联的适配器类来实现。,
,提到微服务,我们不得不了解下两个概念,服务注册与发现。,服务注册,服务发现,
,
,
,接下来我们进行下流程性实战演练。,代码实战中,订阅类在 App 内存创建一个实例,订阅者的生命周期由所有关联的发布者决定,比如多个控制器汇总埋点逻辑到一个加工者, 或比如一个父控制器对应多个子控制器。,
,常规思路下,注册会放到 App 启动阶段,但这样做容易拖缓 App 的启动速度。要想做到在最早的时机注册但又不影响启动速度,需要基于编译器特性:__attribute__((section("name"))) 实现,通过 attribute 指令,编译时期写在 .data 段,然后在运行时期读出来。下图介绍编译注解的简单流程。,
,代码示例,利用上述编译注解的能力,搭配协议反射,就能达到在使用的时候,get 协议进而读取到存储在 .data 段中的内存地址来加载,这个能力也称为懒加载。,核心思路如下(伪代码),在注册阶段暴露出代码块模型,可以在块中做类似 AB 的逻辑切面。,为了防止 subscriber 与 publisher 在 block 使用或者主类与适配器的关联情况下导致循环引用,适配器底层运用了 NSProxy 来实现。如以下的 case 无需关心内存不释放问题。,
,绑定关联共分为两部分,强关联与弱关联。,Swift 环境下不能在注册阶段友好的使用 attribute 编译指令,去自定义段能力,要想高性能的使用懒注册能力只能另辟蹊径。,
,E.g.,接口均用宏来封装。,Swift 环境下不能友好的使用宏封装,此时我们可以通过对 Protocol 进行扩展,以达到封装效果。,服务注册,
,
,
,服务发现,
,服务注册,
,
,服务发现,
,就如很多人都喜欢玩的网游地下城与勇士( DNF ),辅助工具“连发”(顾名思义,连续发动,可以联想到传统单发步枪与自动步枪的区别)不仅让玩家节省了不少的按键成本,而且在连招上增强了打击节奏感。同样的道理,我们推荐使用 Xcode 自定义模板工具编程,让使用者减少打出代码的时间成本,在开发中更加聚焦处理编码逻辑。,
,为让开发同学更加规范使用,我们在代码静态检查阶段进行代码的拦截矫正,同时基于现状列一下几个 Badcase 。,场景例一,场景例二,场景例三,目前为止,多产物适配器框架实体 Adapter 已经在抖音数个平台业务线中批量使用,大部分 OC 业务场景均已覆盖,而且 Swift 场景能力也已建设完毕,框架母体 ServiceKit 已接入 20 + 个 App 。,对于核心框架,我们写出的也许只有一行代码,但是会有几百万行甚至上千万行代码会经过它,一定要慎重思考。
© 版权声明
文章版权归作者所有,未经允许请勿转载。