发布时间:2023-11-27 10:40:24 浏览量:159次
在公司做了两年多的 SDK 开发,结合自己的所知所学,分享一些 SDK 开发的经验。
相信做 Android 开发的朋友,一定使用过第三方的 SDK,比如推送 SDK、分享 SDK 等。SDK 的全称是 Software Development Kit,翻译为“软件开发工具包”。SDK 通常是为辅助开发某类软件而编写的特定软件包、框架集合等。
SDK 可以分为系统 SDK 和应用 SDK。所谓系统 SDK 是为使用特定的软件框架、硬件平台等所开发的工具集合。而应用 SDK 则是基于系统 SDK 开发的独立于具体业务、拥有特定功能的工具集合。
SDK 的使用者主要是 B 端客户,最终交付产品是代码、示例和文档,客户接入 SDK 也是和 SDK 提供方交流的过程,对外沟通的成本比对内更高,遇到的问题也会更多。所以 SDK 开发对开发者的要求比对应用开发更高。能开发好 SDK 一定能开发好应用,但能开发好应用,未必能开发好 SDK。
SDK 的实现目标,概括来说:简洁、稳定、高效。
简洁
对于用户而言,一款好的产品应该是简洁易用的,不该让他们花费太长的时间学习。SDK 也当如此,它不该出现复杂繁琐的对接工作,使用者通过阅读代码和文档,花费很少的时间就能做好 SDK 的对接。
比如当开发者需要使用 SDK 的服务时,只需要在代码中新增一行即可。在项目中初始化 SDK 只要一行代码,开发者不用关心 GLContext,内部已做好处理,也不用关心同步或异步问题。
public class FURenderer {
// 定义
public static void setup(Context context) {
//...
}
}
// 一行代码调用
FURenderer.setup(context);
站在 SDK 使用者角度来看,我们期望第三方 SDK 的服务是稳定高效的,体现在提供稳定可靠的服务,同时运行时性能要高效。这就要求我们在设计实现 SDK 时要尽可能做到以下几点:
无论是普通的应用开发还是 SDK 开发,都应该考虑到性能问题,SDK 设计者要着重考虑以下问题:
SDK 的架构实现决定了后续的维护难度,所以最好能够结合实际业务确定合适的方案。以项目中的模块化开发为例,讲讲架构设计的原则。
遵循面向对象开发的几大原则,目的是达到三个目标:可维护性、可重用性和可扩展性。具体来讲:
比如项目第三方 demo 的功能模块借鉴了 Java 集合框架的架构,分为契约接口、抽象类和具体实现三部分。
API 设计在任何开发中都非常重要,许多时候软件的质量好坏体现在 API 的设计上。
在普通的应用开发中,API 只会在开发人员间流通,不会暴露给非本应用开发的其他人员。但是 SDK 作为一种服务,需要向开发者暴露一部分 API,这样才能使用 SDK 的服务。
下面列出一些应该重点关注的原则。
1. 方法名表明其用途
好的方法名最直观表明它的功能,名字是自解释的,不需要额外的文档,这样做会减少不必要的沟通成本。对于开发者而言,还有什么比直接读代码更直观呢?《重构》一书中讲到,要像给自己孩子起名一样给每个变量命名,这个要求不算过分吧。
2. 参数的合法性检验
如果程序运行时出现异常,会破坏使用者的体验,影响非常不好。我们采用“防御式编程”的思想,能够避免非法输入对系统的破坏性。
当合法性校验不通过时,针对方法权限不同分别对应不同不同的处理策略:
需要注意的是,如果检查的代价太大,那就需要综合考量。
3. 方法只实现单一功能
一个方法应该具有单一的功能,尽可能做更少、更专的事情,这也是单一职责原则的体现。“阿里巴巴代码规约”规定一个方法 最好不要超过 80 行,对庞大的方法要拆分成更小的。
另外注意,宁可提供小而美的方法也不要提供大而全的方法,大而全的方法往往经常发生变动,产生风险的可能性更高。因此不如提供更小的方法以便组合使用,小而美的方法更易做到代码复用。
4. 访问权限控制
包括类方法的权限和变量的权限,能声明私有的不要公开,外部知道得越少越好。能声明静态的方法就用静态,静态方法天然线程安全,体现继承关系的用 protected 修饰,确保公开的方法和变量是安全可靠的。
5. 避免过长参数
过长的参数会造成记忆上困难,还有调用传参容易出错,应当尽力避免。在无法避免过长参数的情况下,考虑其他的方法进行解决:
例如,项目里有个方法,参数非常多。
public class VideoFrame {
private int width;
private int height;
private byte[] data;
private byte[] readback;
private int readbackWidth;
private int readbackHeight;
private int pixelFormat;
// ...
}
int onDrawFrameSingleInput(VideoFrame videoFrame);
重构后,把参数封装成对象,调用方法只用构造一个对象传入,避免大量参数带来不好的体验感。
public class VideoFrame {
private int width;
private int height;
private byte[] data;
private byte[] readback;
private int readbackWidth;
private int readbackHeight;
private int pixelFormat;
// ...
}
int onDrawFrameSingleInput(VideoFrame videoFrame);
6. 慎用方法重载
滥用重载容易让开发者感到疑惑,在需要重载方法的时候,可以使用不同方法名来代替。对于构造函数,可以通过静态工厂来代替重载。
Java 中提供的 ObjectOutputStream 类就是个很好的示范:它的 write 对于每个基本类型都有一个变形,比如写出字符、写出 boolean 等操作。设计者并没有使用重载将其设计成 write(Long l)、write(Boolean b),而是将其设计为 writeLong(l)、writeBoolean(b)。
例如,项目对外的处理方法全部是重载,只能根据参数区分,迷惑性非常大。修改为不同的方法名后,看到名字就知道要调用的方法,清楚了不少。
// 重构前
int onDrawFrame(byte[] img, int tex, int w, int h);
int onDrawFrame(byte[] img, int w, int h);
// 重构后
int onDrawFrameDualInput(byte[] img, int tex, int w, int h);
int onDrawFrameSingleInput(byte[] img, int w, int h, int format);
7. 避免方法直接返回 null
对于需要返回数组或集合的方法,不要返回null。比如我们去买糕点店买面包,面包没了是一种正常状态,就不应该返回 null,而是返回长度为 0 的数组或集合。Java 提供了 Collections.emptyXXX() 表示空集合。
8. 避免引入第三方库
GitHub有许多开源的第三方库,比如网络请求 OkHttp、图片加载 Glide 等,但在 SDK 开发中,遵循的基本的原则是:
引入第三方库可能带来下面几个问题:
9. 保证兼容性
SDK 是不断迭代的,每次发布都会有新功能和 bug 修复。对于使用者来说,升级版本不该有太大的改动,一般直接替换库文件或者修改远程依赖库的版本号就够了。避免直接对公开接口的重命名,如果旧接口废弃,要通过 @Deprecated 关键字标明,并给出替代方案和废弃的时间。
10. 减少入侵性
要保证较少的代码侵入主要在对外提供服务时,充分考虑开发者的使用场景来设计优良的 API。一套优良的 API 在定义时要满足绝大数开发者预期的方式——语义上要求通俗易懂,使用上要求简单可靠。具体的表现是,在正常情况下能够稳定可靠地运行,在异常情况下及时地反馈错误信息。
比如使用 Gradle 下载依赖库,AAR 包中有不必要的 bundle 资源,我们提供了打包 apk 时的构建配置,自由选择要打包的 bundle,减少了对宿主应用的侵入性。
applicationVariants.all { variant ->
variant.mergeAssetsProvider.configure {
doLast {
delete(fileTree(dir: outputDir,
// 删除不必要的 bundle 文件
includes: ['model/ai_face_processor_lite.bundle',
'model/ai_gesture.bundle',
'graphics/controller.bundle',
'graphics/tongue.bundle']))
}
}
}
5SDK 交付
Android 平台通常使用 jar 和 aar 发布 SDK,区别是 jar 只包含代码,aar 可以包含代码、资源和动态库。一般而言 aar 是最合适的交付方式,把它上传到 maven 服务器,使用者就可以一行代码集成。对于需要灵活定制的客户,我们也会提供 SDK 的源码,弊端就是升级困难,要改动很多的代码。
对于代码混淆,公开接口和 native 使用的接口不要混,内部的实现细节可以混淆,以减少 SDK 包的大小。
接入文档用来告诉 SDK 使用者,如何使用 SDK、详细使用步骤和可能发生的问题。文档内容包括:更新记录、基本信息、API 说明、集成步骤、FAQ等。好文档的标准就是清晰明了,通俗易懂。一个完全不懂 SDK 的开发者看着文档就能对接,对于经常遇到的问题要逐条列出,专业名词要有对应的解释。
集成 Demo 通常是一个简单的 App,用来展示如何快速地接入 SDK。Demo 的源码托管到 GitHub,方便使用者参考,其版本变更策略和 SDK 版本的变化保持一致。尽管是个 Demo,它的开发原则也要与 SDK 一致,确保高质量的交付。
热门资讯
探讨游戏引擎的文章,介绍了10款游戏引擎及其代表作品,涵盖了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戏设计领域和数字艺术教育的重要性,欢迎点击咨询报名。
游戏中玩家将面临武侠人生的挣扎抉择,战或降?杀或放?每个抉定都将触发更多爱恨纠葛的精彩奇遇。《天命奇御》具有多线剧情多结局,不限主线发展,高自由...
3. B站视频剪辑软件「必剪」:免费、炫酷特效,小白必备工具
B站视频剪辑软件「必剪」,完全免费、一键制作炫酷特效,适合新手小白。快来试试!
4. 手机游戏如何开发(如何制作传奇手游,都需要准备些什么?)
如何制作传奇手游,都需要准备些什么?提到传奇手游相信大家都不陌生,他是许多80、90后的回忆;从起初的端游到现在的手游,说明时代在进步游戏在更新,更趋于方便化移动化。而如果我们想要制作一款传奇手游的
5. 3D动画软件你知道几个?3ds Max、Blender、Maya、Houdini大比拼
当提到3D动画软件或动画工具时,指的是数字内容创建工具。它是用于造型、建模以及绘制3D美术动画的软件程序。但是,在3D动画软件中还包含了其他类型的...
三昧动漫对于著名ARPG游戏《巫师》系列,最近CD Projekt 的高层回应并不会推出《巫师4》。因为《巫师》系列在策划的时候一直定位在“三部曲”的故事框架,所以在游戏的出品上不可能出现《巫师4》
众所周知,虚幻引擎5(下面简称UE5)特别占用存储空间,仅一个版本安装好的文件就有60G,这还不包括我们在使用时保存的工程文件和随之产生的缓存文件。而...
一、声音优化在绝地求生游戏中能够提前听到脚步声往往能提前取得战机,主要有两种方法:1、利用SoundLock软件,软件的功能主要是限制最大音量。百度搜索...
UI设计师、动画设计师、特效设计师每一个职位的功能和负责的方面都不同。所以,3D美术这方面需要大量的人才。但是要成为一个3D游戏建模师,也不是那么...
想让你的3D打印模型更坚固?不妨尝试一下Cura参数设置和设计技巧,让你轻松掌握!
最新文章