手写SDK的秘诀

news2024/9/22 21:23:17

目录

  • 什么是SDK?
  • 使用SDK的好处?
  • 手写SDK经验总结
    • 易用性
      • 如何提高易用性?
        • 1、统一调用
        • 2、集中配置
        • 3、良好的命名
    • 可理解性
      • 1、结构清晰
      • 2、统一风格
      • 3、编写注释
      • 4、说明文档
    • 可扩展性
      • 轻量依赖
      • 自定义实现
    • 高效稳定
  • 写在最后

什么是SDK?

SDK(Software Development Kit)即 软件开发工具包 ,就是帮助我们开发出软件的工具集合,除了代码之外,一般还要搭配文档、示例等。

一般 SDK 都是需要 引入 到项目中使用的。比如学 Java 的朋友最早接触的 JDK,就是用来开发 Java 软件的工具包,使用时需要编写 类似 import java.util.* 的语法来引入。此外,大部分的 SDK,都是需要通过人工或项目管理工具,将其文件下载到指定路径才能引入。

使用SDK的好处?

比如公司有许多系统都需要实现文件上传的功能

文件上传设计:https://mp.weixin.qq.com/s/3QXe4MSObJTP43M2gXWSlA

显然我们不需要给每个系统都去开发文件上传,而是只要有一个团队编写一套通用的文件上传SDK,然后让需要实现同样功能的系统去引入即可。可以大大提高开发效率。

在这里插入图片描述

因此,编写SDK也就是写一个功能、造一个轮子。好的轮子可以减少一些项目在相同功能上的差异,也可以省去每个系统都去开发同样功能的时间。至此,我们已经了解了什么是SDK,来看看如何写出优秀的SDK。

手写SDK经验总结

好的 SDK 应该具有简单易用、通俗易懂、便于扩展、高效稳定等特点。

易用性

在技术选型的时候一般选择简单易用的SDK,最好是几行代码就能轻松使用,而不是必须要读完很长的一份文档,再写个几十行代码才能生效。

如何提高易用性?

1、统一调用

将复杂的功能进行封装,对外提供统一的调用入口,尽量屏蔽一些实现细节,减少用户调用的流程和对参数的理解成本。

举个例子,下面是两种日期处理函数。用户不需要关心他们是如何实现的,只需要知道怎么用、传递哪些参数、得到哪些返回值就行了。

// 第 1 种:需要 new 对象
DateUtils dateUtils = new DateUtils();
dateUtils.setDate('2021-08-31');
Date date = dateUtils.parse();

// 第 2 种:直接调用
Date date = DateUtils.parse('2021-08-13');

显然是第二种更加方便快捷一些。

2、集中配置

将复杂的参数配置化,不需要让用户到处写参数,而是通过一个配置文件统一管理。

Java主流开发框架Springboot就是典型的例子,假如用户想要改变内嵌服务器启动的端口、亦或者改变数据库连接的地址,不需要写代码,而是改一下配置文件即可:

# 服务器配置
server:
  port: 8081
# 数据库配置
db:
 ip: 10.0.0.1

此外,这样也便于维护项目和实现多环境

3、良好的命名

给 SDK 的函数取名称时,尽量让它符合用户的习惯。

比如具有解析功能的函数,可以叫 “parseXXX”;判断是否为空的函数,可以叫 “xx.isEmpty” 等。最好能做到让用户不看文档,只通过函数名称和参数,就知道你这个函数是做什么的。

因此,想要写出好的 SDK,首先要多用、多参考别人的 SDK,养成习惯后你就会发现,大家起名儿都差不多。

但也要注意一点,如果可以,尽量不要让你 SDK 中的类名(函数名)和别人的完全一致,否则可能给用户带来困扰:这么多同名的函数,我该用哪个呢?哪个是你开发的 SDK 呢?

可理解性

有的时候用户不满足于简单的使用你的SDK,而是希望阅读SDK源码来进一步理解,因此除了易用意外还需要让SDK便于理解,而这一点就和编码有很大的关系,需要做到以下几点:

1、结构清晰

把代码按照功能或类别进行整理,放到指定的目录下。常见的做法有分包、分层等,让人一眼就知道每个目录下的文件的作用。

比如下面这个经典的 Java 项目结构,service 目录是编写业务逻辑的、constant 是存放常量的、utils 是存放工具类的等等,都很清晰:

2、统一风格

比如代码缩进都用 4 个空格、命名都用驼峰式等。尤其是功能相似的代码,一定要保持命名和用法的统一!比如解析文本的函数,不要一会叫 “parseXXX”、一会儿又叫 “jiexiXXX”

但实际上,团队开发中,很难做到这点。因此才需要有一套通用的代码规范,大家都去遵守规范,才能让项目更好理解、更便于维护。

在这里插入图片描述

3、编写注释

最好给 SDK 中的每个类和函数的 开头 都加上注释,这样用户在使用 SDK 时,甚至都不需要看文档,直接看代码注释就能知道它是干嘛的、怎么用。

随便打开 Java SDK 或者网上知名 SDK 中的一个函数,一般都能看到这些注释,包括对函数功能的描述、参数含义、返回值含义等:

在这里插入图片描述

4、说明文档

除了注释外,还要编写一个说明文档(用户手册),包括如何引入 SDK 、有哪些功能、应该怎么使用等等,甚至还可以补充一些关键的实现细节、以及常见的问题列表。

这点也会极大地影响用户的选择。就我个人而言,没有文档的 SDK 我一般是不会选用的,万一出了事我找谁呢?

可扩展性

编写 SDK 的一大难点是:不仅要考虑到大部分通用的使用场景,还要满足小部分用户定制化的需求。

因此,SDK 的可扩展性是很重要的,但怎么提升呢?

轻量依赖

一方面,我们可以尽量减少 SDK 本身对其他类库的依赖。

举个例子,假如你要做一个很轻小的工具类,可能只有几十 KB,那就没有必要再引入一个几百 KB 的依赖库了,得不偿失!别人也不乐意用啊!

轻量依赖不仅可以减少 SDK 的体积,更关键的是可以减少依赖冲突的可能性。我自己也曾经遇到过很多次这样的尴尬局面:引入一个工具类后,整个项目就跑不起来了!

自定义实现

为了提高SDK的通用性和灵活性,在设计SDK的时候,除了提供默认的实现外,建议提供一个通用的接口或者抽象类,让用户来集成,编写自己的实现方式。

举个例子,假设我们要编写一个日期解析类,默认的解析规则是按照短横分割字符串:

// 按照 '-' 切分
date = DateUtils.parse('2023-10-24')

如果只能做到这点,那这个 SDK 就很死板。因为用户可能想按照冒号或其他规则来解析。

怎么实现呢?

我们可以允许用户自己传入分割字符:

// 按照 '-' 切分
parseRule = ':'
date = DateUtils.parse('2023-10-24', parseRule)

还可以让用户自己来控制解析的方式:

// 自定义解析器
interface MyParser extends Parser {
  // 需要用户自己实现
  void doParse();
}
// 指定解析器
date = DateUtils.parse('2023-10-24', MyParser.class);

这两种方式在 SDK 的设计中屡见不鲜,此外还可以让用户自行编写或指定配置文件,也能提高灵活性。

高效稳定

随着使用你 SDK 的用户越来越多,可能会发现各种各样莫名其妙的问题;而且 SDK 作为相对底层的依赖,对使用方的影响也是无法估量的。所以,不想经常加班改 Bug 的话,就要保证你 SDK 的稳定性。

我们需要注意以下几点:

  1. 测试

为了保证每个功能都是正常的,我们可以编写 单元测试(UT)来最大程度上地覆盖 SDK 的功能和代码。

尤其是每次改动代码后、发布新版本之前,都要再完整地执行一遍测试,不要盲目自信。

此外,还可以通过 压力测试 来估算 SDK 的执行效率,比如每秒最多同时执行 3 次、每次要执行 500 毫秒等。建议将这些信息补充到说明文档中,给用户一些预期。当然也可以尝试通过压测来优化 SDK 的性能。

  1. 兼容性

重要的函数和接口尽量减少改动,尤其是函数名、入参和返回值!

对于比较大的改动,可以新写一个函数,并且给老函数打上类似 @Deprecated 的注释,表示已过时,引导用户去用新的。

此外,还可以在 版本号 上做做文章,小改动时只改变小版本号,比如 0.0.1 到 0.0.2;大改动时才改变大版本号,比如 1.0 到 2.0。这样可以给用户一个预期:这次改动很大,可能会存在不兼容。

  1. 暴露异常

要让用户感知到 SDK 代码中可能抛出的异常,交给他们去进行相应的处理,防止出现一些意料之外的错误。

此外,SDK 要合理地打印日志,尤其是异常日志,在出了问题时要让调用者知道是出了什么问题,便于排查。

写在最后

本文是我在学习如何开发一个合格的SDK后将笔记分享出来,如果大家对这系列感兴趣的话,后续将分享一篇开发企业微信机器人的SDK。
今天也是2023.10.24,程序员节,祝各位节日快乐,天底下再也没有难改的bug。按时下班,好好休息!!💪

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1132021.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记一次大型微服务项目本地打包迁移部署

记一次大型微服务项目本地打包迁移部署 引代码合并发布过程本地部署服务配置服务打包自启动测试外部依赖排除部分外部依赖 引 服务的运维也是一个挺复杂工作,如项目上线后的一次小版本发布,开发人员需要基于工程最新代码拉取feature分支,本地…

CPU性能优化——“瑞士军刀“

背景 最近在做一些工具的预研工作,会涉及到对工具的压力测试,分析工具的资源消耗等问题,其中CPU 资源消耗是关键指标之一。为了后续性能优化做准备,回顾了以前相关CPU优化知识,并做总结分享。希望能帮助到正在遇到相关…

如何为3D模型设置自发光材质?

1、自发光贴图的原理 自发光贴图是一种纹理贴图,用于模拟物体自发光的效果。其原理基于光的发射和反射过程。 在真实世界中,物体自发光通常是由于其本身具有能够产生光的属性,如荧光物质、发光材料或光源本身。为了在计算机图形中模拟这种效…

Zabbix出现 404Not FoundThe requested URL /zabbix was not found on this server.

目录 一、问题: 二、原因: 三、解决方法: 一、问题: Not Found The requested URL /zabbix was not found on this server. 二、原因: 未找到 在此服务器上找不到请求的 URL /zabbix。 /etc/httpd/conf.d 目录…

AI是未来?——知识导航

AI是未来?——知识导航 文章目录 AI是未来?——知识导航一、问题记录:1. LoRA微调的原理?网络层是什么?2. P-tuning v2原理?3. 词嵌入,word embedding4. 下图含义?5. 过拟合6. loss定…

蓝桥杯双周赛算法心得——摆玩具(分段的差不计入结果)

大家好,我是晴天学长,这是一道可以牢记的数学技巧题。 1) .摆玩具 2) .算法思路 1.创建一个Scanner对象以从用户读取输入。 2.从用户读取n和k的值,分别表示数组的大小和k的值。 3.创建一个大小为n的整数数组a,用于存储输入的数…

C语言 sizeof 函数内部进行计算

直接看代码 #include <stdio.h> int main() {int i 2;int j;j sizeof(i i);printf("i %d, j %d", i ,j);return 0; }执行结果&#xff1a; 可以看到 i的值一直是没有变的&#xff0c; j 是int类型下 sizeof占用的大小为 4个字节&#xff0c;不是i的 22…

百看不厌的85M²现代极简装饰设计。福州中宅装饰,福州装修

简而不凡 设计&#xff0c;是美好生活的序章 每个人&#xff0c;对家都有不同的想法 但对未来美好新居的向往是相同的 ABOUT THE CASE 案例简介&#xff1a; 作品&#xff1a;尽兴 风格&#xff1a;极简 面积&#xff1a;82平方 户型&#xff1a;SOHO 本套案例85㎡的公…

程序员自我修养-思考度

① 自警 考虑太少&#xff0c;牵连少&#xff0c;深度欠缺&#xff0c;易造成浅尝辄止&#xff0c;贻笑大方&#xff1b; 考虑太多&#xff0c;纬度多&#xff0c;关系复杂&#xff0c;易造成画地为牢&#xff0c;寸步难行。 ② 自励 “一个人能同时保有全然相反的两种观念&…

使用示波器探头的一些技巧和注意事项

使用保护电阻。差分探头的引脚可能存在电压过高的风险&#xff0c;因此使用保护电阻可以有效避免引脚损坏。 接地方式的影响。不管单端信号还是差分信号的测量都对接地非常敏感&#xff0c;不同的接地方式可能会对测量结果产生影响。 校准差分探头。定期校准差分探头可以确保…

16结构型模式-组合模式

我们很容易将“组合模式”和“组合关系”搞混。组合模式最初只是用于解决树形结构的场景&#xff0c;更多的是处理对象组织结构之间的问题。而组合关系则是通过将不同对象封装起来完成一个统一功能. 1 组合模式介绍 将对象组合成树形结构以表示整个部分的层次结构.组合模式可…

红日靶场复现1

红日靶场复现1&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f388;&#x1f388;&#x1f389;&#x1f388;&#x1f388;&#x1f389; 一、主机发现&#x1f388;&#x1…

CV计算机视觉每日开源代码Paper with code速览-2023.10.23

精华置顶 墙裂推荐&#xff01;小白如何1个月系统学习CV核心知识&#xff1a;链接 点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【目标检测】Zone Evaluation: Revealing Spatial Bias i…

【C语言】【goto语句】复习捡拾~

goto语句可以在同一个函数内跳转到设定好的位置&#xff1a; #include<stdio.h> int main() {printf("hello world\n");goto next;printf("hehe"); next:printf("leap here\n");return 0; }goto 语句如果使⽤的不当&#xff0c;就会导致在…

Quantinuum联合中部大学量子物理学家突破“量子+AI”研究

近期&#xff0c;集成量子计算公司Quantinuum和日本中部大学宣布建立新合作&#xff0c;由AI量子模型领域的两位全球专家Bob Coecke和小泽正直&#xff08;Masanao Ozawa&#xff09;教授共同领导。作为各自领域公认的技术领导者&#xff0c;他们将建立一个跨学科团队来探索量子…

判断是否为Base64加密无意间发现特殊字符无法判断

一&#xff1a;思路 判断一个字符串是否为base64编码的流程&#xff1a; 步骤 描述 1 将字符串转换为字节数组 2 判断字节数组的长度是否是4的倍数 3 将字节数组的每个字节转换为对应的base64字符 4 判断base64字符是否合法 二&#xff1a;代码 /*** 判断是否…

《算法通关村——双指针妙用》

《算法通关村——双指针妙用》 删除元素 描述 给你一个数组 nums 和一个值 val&#xff0c;你需要原地移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。要求&#xff1a;不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并原地修改输入数组…

代碼隨想錄算法訓練營|第四十五天|1049. 最后一块石头的重量 II、494. 目标和、474.一和零。刷题心得(c++)

目录 讀題 1049. 最后一块石头的重量 II 自己看到题目的第一想法 看完代码随想录之后的想法 494. 目标和 自己看到题目的第一想法 看完代码随想录之后的想法 474.一和零 自己看到题目的第一想法 看完代码随想录之后的想法 1049. 最后一块石头的重量 II - 實作 思路 …

Redis -- 基础知识2

1.Redis客户端介绍 1.基础介绍 Redis是一种客户端-服务器结构的程序&#xff0c;通过网络进行互动 客户端的多种形态 1.自带了命令行客户端&#xff1a;redis-cil 2.图形化界面的客户端&#xff1a;依赖windows系统&#xff0c;连接服务器有诸多限制&#xff0c;不建议使用 3.基…

简单而高效:使用PHP爬虫从网易音乐获取音频的方法

概述 网易音乐是一个流行的在线音乐平台&#xff0c;提供了海量的音乐资源和服务。如果你想从网易音乐下载音频文件&#xff0c;你可能会遇到一些困难&#xff0c;因为网易音乐对其音频资源进行了加密和防盗链的处理。本文将介绍一种使用PHP爬虫从网易音乐获取音频的方法&…