揭秘腾讯MTA SDK模块化发展历程

引语

SDK是一种方便常见的开发者工具形式,但愈来愈多的内嵌功能,可能让SDK服务愈来愈全,可能会出现功能的重复,形成SDK包愈来愈重,给App自身带来负担……
为App减负,MTA踏上了探索的道路。前端

做者介绍

陈翔,腾讯大数据平台高级开发工程师。
从2009年工做至今,在前端和终端开发领域有着丰富的实战经验。
目前为MTA、腾讯移动推送(信鸽)等项目iOS端研发负责人。编程

随着移动互联网的高速发展, 出现了大量的公司以SDK的形式为App提供服务,例如统计、推送、Crash监控等等领域。接入各类SDK服务作开发,相对App从零开始自研的话,极大的提高了App的开发效率,节约了大量的时间和成本。开发一个爆款软件再也不是几年,可能就是几个月时间。bash

MTA的产品定位是移动统计分析工具,在伴随着与开发者共同成长的道路上,也在不断响应用户的需求,提供更多更丰富的开发者服务,好比最近升级的Crash监控。同时也在提供更多的运营服务,好比最近上线的可视化埋点功能。网络

在MTA的成长道路上,不断的提供更多更好的服务,因而乎问题来了,这也是业界广泛的一个问题:SDK体积愈来愈大。架构

这对许多App来讲是个噩梦,由于不仅是增长了流量,可能也会带来更多的额外计算工做,形成卡顿,用户的电量也在加速消耗。编程语言

MTA技术总监顾孙炬(Raygu)适时提出:为App减负,MTA势在必行。ide

MTA怎么作

为了致力于提供最佳的体验,咱们在思考,怎样可以保证SDK足够小,又能提供用户所需的各类服务,知足各类大小客户们的需求。截至如今经历了三个阶段。模块化

第一阶段:定制服务

在早期MTA有新功能的话, SDK版本就是一个体积一直累加的过程。有一天,忽然有重要客户提出是不能接受体积大的。因而针对这个客户,经过沟通的方式,肯定他们须要的核心功能,而后拉代码分支,作相应的修改。而后又有相似的第二个客户、第三个客户…… 看着分支愈来愈多,不管是新特性的增长或者bug的修复,对于终端来讲,维护的成本很是高。不由要打个冷颤,再这样发展下去,维护的工做量不可估量。函数

图1. 苦逼的各类历史定制版本工具

第二阶段: 精简服务

针对第一阶段的问题,作了这样的设计,将SDK分红三种大版本。

超级精简版: 提供给各类二次封装SDK使用,或者对SDK体积有超级严格要求的App。
适度精简版: 提供最经常使用的功能。
完整版: 全部功能的集合版本。
备注:二次封装SDK是指各类聚合SDK,也就是包含了不少SDK服务的大SDK。

从上看出,经过对需求功能和客户分组的方式,三个版本可做为绝大多数客户的基线版本。在相对稳定的基线的基础上作不大的调整,相对第一阶段维护成本小了很多。

图2. 3种版本应对种种需求

在推广的过程当中,由于知足了二次封装SDK的标准,可是超级精简版的功能不够彻底,有的客户有独立接入MTA的需求。这样当App同时接入超级精简版和其余版本的时候,会产生许多” duplicate symbols”的错误。


图3. 不当心就报错了
项目的改造: 咱们知道Objective-C这门编程语言是没有命名空间的,经过修改一个个类名前缀和字符串前缀,能够作到编译和运行级别的兼容。

经过短期的实践,后来发现彻底不可维护,由于有N家二次封装SDK的客户,这样只是超级精简版就要修改出N个项目,而一份代码有N个类和N个字符串,工做量大且容易出错。

回到初衷,咱们想尽可能下降维护的成本,在Objective-C命名空间上,咱们作出了以下的设计:

在预编译文件(.pch)中,作一个相似这样的宏定义

#define symbol prefix##symbol复制代码

经过对prefix作一次修改,则能够全局修改符号的前缀。举个例子:

#define MTA QQ##MTA复制代码

这样就实现了开发时,在XCode项目中是MTA,编译后生成的符号是QQMTA,字符串也能够作相似的处理,给不一样客户配置不一样的前缀。由于解决了符号重名问题,这样的话,超级精简版就能够轻松的给各个二次封装SDK提供服务,同时和其余版本(适度精简版或完整版衍生的版本)共同生存。

伪代码示例:

Prefix.pch文件
//处理类名
#define ARK(symbol) prefix##symbol

//处理字符串
#define ARKNSSTR (symbol) @ #prefix #symbol

#define MTA ARK(MTA)
#define MTAConfig ARK(MTAConfig)

某个.m文件
static NSString *const  BUSINESS_ID = ARKNSSTR(MTA);复制代码

第三阶段: 模块化

作到第二阶段时,较少人力已经足够维护好MTA项目了。可是在最近一年,需求愈来愈多,人力的匹配速度却没有跟上,这样形成MTA的多版本维护变得有些吃力。这样就须要思考是否能进一步减小维护的成本。

经过从新梳理,以及在MTA技术总监顾孙炬(Raygu)的支持下,根据特色MTA被分红几大部分: 必需模块,重要模块,独立模块。

必需模块: MTA运行必需的模块,属于核心中的核心。
重要模块: 依赖必需模块,功能很是重要,客户也能够不须要使用的功能。
独立模块: 轻度依赖必需模块,大部分逻辑都是独立运行。

在此划分的构想上,提出插件和组件机制。架构图以下:

图4. 清晰可拆解的模块化构建

首先,最底层是core,对应必需模块,包含上报模块和基础功能,这二者表明是MTA最基础的核心功能,做为一切组件和插件的基础。同时是一个Service Provider的角色,把最基础的上报、网络、存储、通用函数等基础能力暴露出来复用。

往上是组件层,对应重要模块,这里是一些MTA重点服务的功能,依赖core层的功能。在本来组件都打包在一块儿的时候,MTA须要用到组件就直接使用。这里作了个代理的设计。把须要用到组件的功能作个对应的protocol定义,在MTA工做流程中一个组件对应一个delegate,delegate链接了对应的组件,组件实现了对应的protocol。这样在MTA工做流程中经过对delegate的判断,若是链接了组件,就可使用对应模块,反之缺失对应组件的功能。即便没有组件,而增长这个逻辑带来体积的增长几乎能够忽略。

再往上是MTA的插件层,对应独立模块,这一层的模块基本都是能够独立运行或者和MTA主流程耦合很小。MTA核心状态的变动,会发出响应的通知,插件会订阅这些通知,也就是观察者模式。好比初始化完成后的状态通知,插件收到通知后才会进行自身的初始化,这样能够保证MTA核心功能的完整服务可用,使插件运行的更加稳定。

至此,MTA只须要维护一份代码,便可实现灵活的功能拼接,知足各个用户的需求,而且不会出现” duplicate symbols”的冲突问题。实现了一套代码N个版本。

编译和打包
MTA的架构,若是用XCode来打包,会很是复杂,不可控。实际上从第二阶段开始,咱们已经进行脚本化打包,基于Xcode command line tools。经过灵活的参数传递,能够快速的生成各类binary和fat binary文件,很是方便。

最后,附上MTA官方版本的物理结构图, 下载地址请到MTA官网SDK下载页进行下载,或点击文末下载连接。

图5. 灵活可选的各个模块

用户须要什么功能,引用相应的.a文件便可,实现了用户本身灵活组装MTA功能。其中有部分组件打包在libmtasdk.a里,若是有特殊需求,也能够联系咱们分离出来。

小编有话说:

MTA是一款为开发者提供服务的工具产品,核心是围绕开发者的需求,对外输出咱们的能力与服务。
因此,若是你们在MTA使用过程当中有任何问题,均可以随时联系咱们哦~咱们一直都在努力,请协助咱们共建更棒的数据工具产品!


差很少就这么美的小编 ↑

联系咱们:

若是您但愿试用或者体验 MTA Crash分析,请访问MTA官网接入试用。

若是您对该功能有疑问、或者在使用中遇到了困难,欢迎您联系mta官网在线客服,或者发送您的问题邮件至:dtsupport@tencent.com

商务合做或业务咨询,请联系如下邮箱:mta@tencent.com

相关文章
相关标签/搜索