怎么样的SDK算是一个好的SDK?
在做SDK的过程中我们走过非常多的弯路,是一个难以想象的学习过程,我们总结一个好的SDK应该具备的特质:
易用性,稳定性,轻量,灵活,优秀的支持.
一、易用性
因为工作的关系我接触了很多的开发者,其中有行业知名的公司的开发者,也有极小的个人开发者.有一个现象很有意思,不管是能力较强的开发者还是能力一般的开发者,他们都会不停的对你的SDK吐槽.因为他们对于好用的标准是不一样的,所以你必须要将你的SDK易用性考虑到极致,不然后续的技术支持将是一个十分痛苦的事情.
- 不要过度设计,过度设计是程序员常常犯的错误,如果只是一个演示demo,应该尽量的简单,简单到最基础的程序员都能够看懂.
- 接口尽量的见名知义.
- 要相信绝大多数的开发者都是不看文档的.于是根据开发者的直觉去设计API,这样听起来是不是太靠谱?事实上比如你的SDK的生命周期设计方法跟系统差异性不大,比如你的播放器的接口设计跟系统播放器相差不大,那对开发者来讲就是福音.
- 接口能够统一的尽量统一,比如iOS和Android的接口,应该尽量的统一.
尽量多的默认参数,这里面有一些小的技巧,以下我提一个小的例子,比如我们的SDK,我们有一个跳转录制的接口,事实上就是将一堆的参数给到下一个SDK页面,让SDK接收参数,我们选择给一个结构体暴露给用户,如下:
AliyunVideoParam recordParam = new AliyunVideoParam.Builder() .setResulutionMode(resolutionMode) //设置录制分辨率,目前支持360p,480p,540p,720p .setRatioMode(ratioMode) //设置视频比例,目前支持1:1,3:4,9:16 .setRecordMode(RecorderDemo.RECORD_MODE_AUTO) //设置录制模式,目前支持按录,点录和混合模式 .setFilterList(eff_dirs) //设置滤镜地址列表 .setBeautyLevel(80) //设置美颜度 .setBeautyStatus(true) //设置美颜开关 .setCameraType(CameraType.FRONT) //设置前后置摄像头 .setFlashType(FlashType.ON) // 设置闪光灯模式 .setNeedClip(true) //设置是否需要支持片段录制 .setMaxDuration(max) //设置最大录制时长 .setMinDuration(min) //设置最小录制时长 .setVideQuality(videoQuality) //设置视频质量 .setGop(gop) //设置关键帧间隔 .build(); AliyunVideoRecorder.startRecordForResult(this,REQUEST_RECORD,recordParam);
这样有什么好处呢,我们事实上可以预制N个参数。这样用户调用一个录制功能只需要做什么呢?,如下:
AliyunVideoParam recordParam = new AliyunVideoParam.Builder().build(); AliyunVideoRecorder.startRecordForResult(this,REQUEST_RECORD,recordParam);
- 上面还说了开发者对于易用性的标准是不一样的,面向的需求也是不一样的,上面的需求只能满足最基础的简单需求,如果要自定义界面,这个时候就需要暴露更加深
的接口.于是我们将我们的接口设计分为多层.这样就基本能够满足用户最初级的要求和自定义属性的要求.
DEMO--->AliyunVideoRecorder(第一层接口)---->AliyunIRecorder(第二层接口)
- 上面还说了开发者对于易用性的标准是不一样的,面向的需求也是不一样的,上面的需求只能满足最基础的简单需求,如果要自定义界面,这个时候就需要暴露更加深
二 、稳定性
如何保证一个SDK的稳定性?自动化测试、适配测试、API的稳定、代码审查、内存检测、可测试性都缺一不可.
- 自动化测试:依赖系统的自动化测试工具就可以完成人工绝大多数的自动化UI测试.能够解放黑盒测试的双手,这个时候如果有使用Jenkins之类的持续集成的系统,你还能够让你的开发者及时的能够发现问题、解决问题。
- 适配测试:一个安卓永远的痛,现在基本没有很多好的方法,只有去找一些规律找机器适配,但是做多了就会发现还是有规律可循的,比如GPU的型号,系统版本,使用的硬件差异,甚至品牌.早期我们也是按CPU,GPU型号去买机器的.
- API的稳定: 一个好的SDK设计的API应该从一开始就需要考虑扩展性,尽量多的考虑将来可能的需求,尽量将这些需求包进来.我见过很多开发者懊恼如果让我再设计一次一定能够将这个接口设计的更好一些 :)
- 代码审查:一个好的团队在代码质量上会下很大的功夫,所以不让代码审查沦为形式是一个好leader应该考虑的事情.大团队会做一些交叉review,开启git的pull request,写单元测试等都是不错的方式
三、轻量
现如今手机App的大小直接决定用户买单不买单(16G的iPhone哭晕在厕所),在我接触客户中发现越是大公司越在乎对App的大小增加,因为他们的应用已经非常庞大了,像微信,手淘,支付宝这样的大体量他们都对大小有着极其严苛的态度,产品和技术团队会直接评估大小增加对用户的影响.所以你的SDK是否轻量直接决定用户是不是选择你的SDK.那如何做到轻量?
- 尽量少的使用第三方库,如果非要使用这个库需要考虑这个库中的源码是否能够裁剪,有必要时需要产品一起评估这个功能对大小的增加,有必要时要求产品干掉这个功能
- 代码耦合度尽量的低,比如用户只要一个录制功能,这个时候就需要评估你的录制模块是否独立,能不能单独的抽离.你应该尽量的让你的代码耦合度低
- 第三方库需要暴露实现给用户.特别是非常常见的库,比如你一个json解析的代码。你应该定义一些接口,然后实现的类直接暴露给用户.如果用户有强烈的替换第三方库要求,应该让用户有权利去替换
- SDK不要包含view层实现和资源,如果有必要,将view层的实现暴露出去.比如:我们在做SDK的时候我们始终在考虑怎么样让用户尽量简单的接入我们的SDK,尽量少的让用户接入的成本低,尽量少的让用户少写代码.这样就不可避免需要做一些应用层的事情,于是我们就将View层的所有实现都暴露给用户,然后让用户只修改UI即可.这样资源用户也可以替换,十分方便.
四、灵活
灵活包括几个点:API灵活可扩展,API的可测试性,API的健壮性性要强. 要做到以上任何一点都需要经验的支持,绝对不要想当然,尽量的从开发者的角度去设计,会让自己收获很多.
- API可扩展:在业务过程中我们总是面对产品不断的需求压迫,但是从设计开始的时候就需要尽可能的考虑多的业务需求的可能性,这里有一个技巧,如果你不能确定你未来的需求增加,你应该保证尽量少的接口支持尽可能多的业务,不然到后期你会发现你的对外接口越来越多,一堆冗余接口.:)
- 接口可测试性,一些小的技巧可以让你的SDK具备可测试性
- 为了测试,有时我们需要进行模拟,模拟(mock)类作为真实类的仿制类,它没有真实操作,并且允许被重写调用和验证.
- 如果有些类是final的就很难模拟,并且是一个基于状态的单例的话,就比较恶心了,这时候我们就需要考虑考虑在设计上尽量的规避.比如尽量避免单例,避免final.
- 需要有测试用例,不管是开发人员还是测试开发人员都需要根据测试用例编写.
- API的健壮性
- 大多数的开发者经常都是不耐烦的,他们看到很长时间都找不到出错的原因是会有非常负面的情绪的,所以有一些错误应该尽早的抛出,这就好像比如你要build一个项目,如果一些错误能够在编译期间就暴露,一定好于完成编译之后才出现错误.所以你需要写清楚一些exception抛出给用户.
- 尽量的保证接口的生命周期,如果是有序的需要在文档说明.
五、优秀的支持
如果以上四点你已经做得非常好了,这个时候你的文档和技术支持直接就决定用户是否选择你的SDK.也直接决定用户对你的评级.所以好的支持就非常重要了.你需要建立开发者社区,apple文档,javadoc,readme.甚至集成文档,示例教程.
- 给对外暴露的代码尽可能多的注释,最好是相关联的说明使用示例,比如你的这个接口跟另外一个接口是配套使用的.
- 需要有demo代码,demo代码应该尽可能的简单.让使用的人可以遵循你的代码进行尝试.一定一定不要让你的示例代码写的过于复杂.不要在无关紧要的交互模式上纠结.不然没有用户会花大量的时间去学习你的示例代码.而且他们还会有很多疑问,或者bug. (解决方案除外)
- 如果有些接口需要废弃,你应该添加废弃的注解
- 一定要有一个更新list.清晰的版本更新日志.要相信不是所有的开发者会选择最新版本的,你需要保证你的每一个版本都是稳定可用的.
- 作为一个SDK,你的功能一定不能是自己臆想出来的.你应该常常跟开发者交流,了解用户的需求。每个功能都需要有客户反馈作为依据.
以上几个点肯定不是建设一个伟大的库的全部.只是我们在开发短视频SDK的时候的一些思考.如果觉得有一定意义,欢迎交流.:)