好文推荐:
作者:Ant_way


1. 前言

从事 ​​SDK​​​ 的研发工作有近两年的工作时间了,期间一直在维护和开发公司的 Android 数据采集埋点 SDK​。主要想通过这篇总结简要介绍下 ​​SDK​​ 开发过程中的一些经验。

1.1 什么是 SDK

相信做 ​​Android​​​ 开发的同学,肯定使用过很多第三方的 ​​SDK​​​,比如​​极光 SDK​​​、​​支付宝 SDK​​​、​​微博 SDK​​​ 等等。所谓 ​​SDK​​​ 就是一个开发工具包,全称是 ​​Software Development Kit​​​,翻译过来是软件开发工具包。​​SDK​​ 通常是为辅助开发某类软件而编写的特定软件包。

​App​​​ 开发与 ​​SDK​​​ 开发的工作有什么区别呢?​​App​​​ 开发更偏向于用户层面,从 ​​UI​​​ 展示到业务逻辑处理,全程处理用户的行为。而 ​​SDK​​​ 开发更偏向于功能方面,注重功能的开发实现,轻 ​​UI​​。

2. SDK 设计原则

2.1 核心原则

核心原则:一定要稳定,不能引起客户 App 的崩溃。

由于我们的 ​​SDK​​​ 是服务于 ​​2B​​​ 行业,所以会有很多 ​​App​​​ 集成我们的 ​​SDK​​​,这就要求 ​​SDK​​​ 的核心原则不能引起客户 ​​App​​​ 的崩溃。一旦 ​​SDK​​​ 的出现引起崩溃的 ​​bug​​​,这将对众多 ​​App​​​ 造成灾难性的影响,如果出现这种情况,是非常致命的。所以对于 ​​Android SDK​​​ 开发来说,要注意 ​​try...catch​​ 的使用、对象的检查等等。

2.2 SDK 设计原则

首先需要明确,一方面,​​SDK​​​ 的价值是给调用者带来价值。所以要努力降低用户的上手难度,易于理解。另一方面要时 ​​SDK​​ 代码易于维护。

1. 接口易用性

做 App 开发时,我也抱怨过XX 的 ​​SDK​​​ 真难用。一个 ​​SDK​​​ 好不好用,关键就看接口的设计是否简单易用,对于接入方来说他不会关注你的实现细节,能用一个 ​​API​​ 接口搞定的业务,坚决不用两个。注意控制接口的数量。

另一方面,**注意接口的命名。**一个好的 ​​API​​​ 接口的命名能够让调用者见名思意,做到不需要借助帮助文档就能使用的程度就说明这个接口命名是成功的。比如对于 ​​Android​​​ 中设置点击事件的接口 ​​setOnClickListener​​。

2. 命名规范要统一

对于 ​​SDK​​ 开发来说,统一命名规范很重要,最好的状态是**接入方看到接口命名就能知道是哪家厂商的 SDK。**换句话说就是 SDK 的命名规范统一,形成自己公司的品牌效应。同时也方便接入方使用。

对于编码规范,网上都有各个大厂的规范模板,可以选择其中一个或自定义自己团队的规范,尽早统一代码风格。

3. 跨端接口尽量保持一致

对于同一套 ​​SDK​​​,尽量保持各端接口命名、实现逻辑要一致。在我们的开发过程中,也出现由于跨端之间的逻辑有差异导致客户在 ​​Android​​​ 和 ​​iOS​​ 上体验不一致的问题,同时也会带来额外的支持工作。所以对于涉及到多个端的需求设计,一定要进行详细的沟通和确认,防止出现接口命名和实现不一致的情况。

4. 尽量不依赖第三方库

随着开源的普及,​​GitHub​​​ 上有很多经典的开源项目供开发者使用。对于 ​​App​​​ 开发者,会经常使用到开源项目,比如网络请求 ​​OkHttp​​​、图片加载 ​​Glide​​​ 等等。但是在 ​​SDK​​ 的开发中,一般的原则是尽量避免使用开源项目库。主要有以下几点原因:

  • 原因是为了避免与调用方由于使用相同的库引起的冲突,增加调用方集成的工作量,降低集成方的体验。
  • 开源库的不断更新,所以​​SDK​​ 需要及时保持更新,会增加额外的维护的工作量。
  • 由于引入开源库,出现问题排查困难。
5. SDK 包尽量小

​SDK​​ 包一定要小而精。

小是指包的体积要尽可能的小。避免造成接入方的 ​​App​​ 增加很大,不然会引起接入方的不满,甚至下架。

精是指功能要专注。比如我们的 ​​SDK​​ 是用于埋点的,那里面设计提供很多常见的工具类显然是不合适的。

6. 兼容性

兼容性是每个开发者都会遇到的问题。在 SDK 开发中更要保证新版本对于旧版本的兼容。常见的兼容性问题分为两类。

新老接口兼容

一般出现接口兼容性的问题主要是由于最初需求考虑不完善,导致后面进行方案优化时引起接口的变更,使之前的接口成为历史的老大难问题,最终造成删除难度大。

新功能兼容性

这里的兼容性问题分为两个方面:接入新功能的 ​​App​​​ 和未接入新功能的 ​​App​​​。举个例子,当初我们 ​​SDK​​​ 适配 ​​OAID​​​ 的方案时,由于需要使用 ​​MSA​​​ 提供的集成包才能获取,但是在 ​​SDK​​​ 中一般是不轻易集成一个第三方的库,所以在设计这个方案时,就需要让接入方自己集成库,​​SDK​​ 中提供获取的代码逻辑。最终在确定开发方案时,就需要考虑到一部分接入方使用了该功能,需要保证该功能正常读取。一部分接入方没有使用到该功能,要确保无异常出现。一般这种兼容性问题会决定开发方案的技术实现。

3. 集成与维护

3.1 SDK 集成

集成方式要多样同时灵活方便。比如对于 ​​Android​​​ 来说,我们提供通过​​maven​​​、​​gradle​​​ 依赖引入等方式,也是推荐的集成方式。但是对于一些接入方由于网络的限制,无法直接依赖 ​​maven​​​,这里就需要提供 ​​aar​​ 包或源码来集成。

3.2 集成指南

对于 ​​SDK​​​ 的集成和使用,以及版本更新内容和 ​​API​​​ 接口介绍,一定要准备比较完善的用户接入指南。比如我们的 ​​SDK 接入指南​​分为:

  • 基本使用
  • 常见问题
  • 高级应用
  • 插件配置

尽管根据经验来看,有些开发者没有看文档的习惯,但是一份完整的指导文档还是非常有必要,它可以节省很多集成的成本和时间。

同时文档要注意合理的规划设计,避免一份文档内容太多,造成阅读困难。对于使用性的部分,最好有示例代码进行展示。

3.3 完备的测试报告

在实际的接入过程中,有很多接入方需要提供相关的性能测试说明,这部分的内容需要及早准备。测试报告的工作可以研发和测试一起协助进行输出,最终方便后续的支持工作,降低维护成本。

4. 开发经验

4.1 不做想太多需求

在最初开发 ​​SDK​​​ 时,经常会由客户的一个简单需求扩展很多需求,导致最终增加了多个接口,尽管看似 ​​SDK​​ 非常灵活,但是多出来的接口增加了很多维护成本。

曾经我们做过一个开启 ​​Fragment​​​ 名称采集的需求,客户提出的需求是通过文件配置,然后 ​​SDK​​ 进行读取。在实施的过程中就出现很多想太多。

  • 如果有别的客户不想通过配置文件,想使用接口怎么办?
  • 如果用户想删除配置文件中已配置项怎么办?
  • 如果客户想恢复忽略的配置怎么办?

这些想太多的需求,会增加很多额外的工作和交付成本,所以在 ​​SDK​​ 开发中一定要避免想太多的需求。

4.2 配置项不提倡提供读取方法

在 SDK 中经常会有很多初始化开关配置接口,这类接口一般是暴露 ​​set​​​ 方法让用户去设置,常见在初始化一次性配置,所以这类配置项一般就不需要提供 ​​get​​ 方法,防止接口太多。