發(fā)布時(shí)間:2023-11-27 10:40:24 瀏覽量:203次
在公司做了兩年多的 SDK 開發(fā),結(jié)合自己的所知所學(xué),分享一些 SDK 開發(fā)的經(jīng)驗(yàn)。
相信做 Android 開發(fā)的朋友,一定使用過第三方的 SDK,比如推送 SDK、分享 SDK 等。SDK 的全稱是 Software Development Kit,翻譯為“軟件開發(fā)工具包”。SDK 通常是為輔助開發(fā)某類軟件而編寫的特定軟件包、框架集合等。
SDK 可以分為系統(tǒng) SDK 和應(yīng)用 SDK。所謂系統(tǒng) SDK 是為使用特定的軟件框架、硬件平臺(tái)等所開發(fā)的工具集合。而應(yīng)用 SDK 則是基于系統(tǒng) SDK 開發(fā)的獨(dú)立于具體業(yè)務(wù)、擁有特定功能的工具集合。
SDK 的使用者主要是 B 端客戶,最終交付產(chǎn)品是代碼、示例和文檔,客戶接入 SDK 也是和 SDK 提供方交流的過程,對(duì)外溝通的成本比對(duì)內(nèi)更高,遇到的問題也會(huì)更多。所以 SDK 開發(fā)對(duì)開發(fā)者的要求比對(duì)應(yīng)用開發(fā)更高。能開發(fā)好 SDK 一定能開發(fā)好應(yīng)用,但能開發(fā)好應(yīng)用,未必能開發(fā)好 SDK。
SDK 的實(shí)現(xiàn)目標(biāo),概括來說:簡(jiǎn)潔、穩(wěn)定、高效。
簡(jiǎn)潔
對(duì)于用戶而言,一款好的產(chǎn)品應(yīng)該是簡(jiǎn)潔易用的,不該讓他們花費(fèi)太長(zhǎng)的時(shí)間學(xué)習(xí)。SDK 也當(dāng)如此,它不該出現(xiàn)復(fù)雜繁瑣的對(duì)接工作,使用者通過閱讀代碼和文檔,花費(fèi)很少的時(shí)間就能做好 SDK 的對(duì)接。
比如當(dāng)開發(fā)者需要使用 SDK 的服務(wù)時(shí),只需要在代碼中新增一行即可。在項(xiàng)目中初始化 SDK 只要一行代碼,開發(fā)者不用關(guān)心 GLContext,內(nèi)部已做好處理,也不用關(guān)心同步或異步問題。
public class FURenderer {
// 定義
public static void setup(Context context) {
//...
}
}
// 一行代碼調(diào)用
FURenderer.setup(context);
站在 SDK 使用者角度來看,我們期望第三方 SDK 的服務(wù)是穩(wěn)定高效的,體現(xiàn)在提供穩(wěn)定可靠的服務(wù),同時(shí)運(yùn)行時(shí)性能要高效。這就要求我們?cè)谠O(shè)計(jì)實(shí)現(xiàn) SDK 時(shí)要盡可能做到以下幾點(diǎn):
無(wú)論是普通的應(yīng)用開發(fā)還是 SDK 開發(fā),都應(yīng)該考慮到性能問題,SDK 設(shè)計(jì)者要著重考慮以下問題:
SDK 的架構(gòu)實(shí)現(xiàn)決定了后續(xù)的維護(hù)難度,所以最好能夠結(jié)合實(shí)際業(yè)務(wù)確定合適的方案。以項(xiàng)目中的模塊化開發(fā)為例,講講架構(gòu)設(shè)計(jì)的原則。
遵循面向?qū)ο箝_發(fā)的幾大原則,目的是達(dá)到三個(gè)目標(biāo):可維護(hù)性、可重用性和可擴(kuò)展性。具體來講:
比如項(xiàng)目第三方 demo 的功能模塊借鑒了 Java 集合框架的架構(gòu),分為契約接口、抽象類和具體實(shí)現(xiàn)三部分。
API 設(shè)計(jì)在任何開發(fā)中都非常重要,許多時(shí)候軟件的質(zhì)量好壞體現(xiàn)在 API 的設(shè)計(jì)上。
在普通的應(yīng)用開發(fā)中,API 只會(huì)在開發(fā)人員間流通,不會(huì)暴露給非本應(yīng)用開發(fā)的其他人員。但是 SDK 作為一種服務(wù),需要向開發(fā)者暴露一部分 API,這樣才能使用 SDK 的服務(wù)。
下面列出一些應(yīng)該重點(diǎn)關(guān)注的原則。
1. 方法名表明其用途
好的方法名最直觀表明它的功能,名字是自解釋的,不需要額外的文檔,這樣做會(huì)減少不必要的溝通成本。對(duì)于開發(fā)者而言,還有什么比直接讀代碼更直觀呢?《重構(gòu)》一書中講到,要像給自己孩子起名一樣給每個(gè)變量命名,這個(gè)要求不算過分吧。
2. 參數(shù)的合法性檢驗(yàn)
如果程序運(yùn)行時(shí)出現(xiàn)異常,會(huì)破壞使用者的體驗(yàn),影響非常不好。我們采用“防御式編程”的思想,能夠避免非法輸入對(duì)系統(tǒng)的破壞性。
當(dāng)合法性校驗(yàn)不通過時(shí),針對(duì)方法權(quán)限不同分別對(duì)應(yīng)不同不同的處理策略:
需要注意的是,如果檢查的代價(jià)太大,那就需要綜合考量。
3. 方法只實(shí)現(xiàn)單一功能
一個(gè)方法應(yīng)該具有單一的功能,盡可能做更少、更專的事情,這也是單一職責(zé)原則的體現(xiàn)?!鞍⒗锇桶痛a規(guī)約”規(guī)定一個(gè)方法 最好不要超過 80 行,對(duì)龐大的方法要拆分成更小的。
另外注意,寧可提供小而美的方法也不要提供大而全的方法,大而全的方法往往經(jīng)常發(fā)生變動(dòng),產(chǎn)生風(fēng)險(xiǎn)的可能性更高。因此不如提供更小的方法以便組合使用,小而美的方法更易做到代碼復(fù)用。
4. 訪問權(quán)限控制
包括類方法的權(quán)限和變量的權(quán)限,能聲明私有的不要公開,外部知道得越少越好。能聲明靜態(tài)的方法就用靜態(tài),靜態(tài)方法天然線程安全,體現(xiàn)繼承關(guān)系的用 protected 修飾,確保公開的方法和變量是安全可靠的。
5. 避免過長(zhǎng)參數(shù)
過長(zhǎng)的參數(shù)會(huì)造成記憶上困難,還有調(diào)用傳參容易出錯(cuò),應(yīng)當(dāng)盡力避免。在無(wú)法避免過長(zhǎng)參數(shù)的情況下,考慮其他的方法進(jìn)行解決:
例如,項(xiàng)目里有個(gè)方法,參數(shù)非常多。
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);
重構(gòu)后,把參數(shù)封裝成對(duì)象,調(diào)用方法只用構(gòu)造一個(gè)對(duì)象傳入,避免大量參數(shù)帶來不好的體驗(yàn)感。
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. 慎用方法重載
濫用重載容易讓開發(fā)者感到疑惑,在需要重載方法的時(shí)候,可以使用不同方法名來代替。對(duì)于構(gòu)造函數(shù),可以通過靜態(tài)工廠來代替重載。
Java 中提供的 ObjectOutputStream 類就是個(gè)很好的示范:它的 write 對(duì)于每個(gè)基本類型都有一個(gè)變形,比如寫出字符、寫出 boolean 等操作。設(shè)計(jì)者并沒有使用重載將其設(shè)計(jì)成 write(Long l)、write(Boolean b),而是將其設(shè)計(jì)為 writeLong(l)、writeBoolean(b)。
例如,項(xiàng)目對(duì)外的處理方法全部是重載,只能根據(jù)參數(shù)區(qū)分,迷惑性非常大。修改為不同的方法名后,看到名字就知道要調(diào)用的方法,清楚了不少。
// 重構(gòu)前
int onDrawFrame(byte[] img, int tex, int w, int h);
int onDrawFrame(byte[] img, int w, int h);
// 重構(gòu)后
int onDrawFrameDualInput(byte[] img, int tex, int w, int h);
int onDrawFrameSingleInput(byte[] img, int w, int h, int format);
7. 避免方法直接返回 null
對(duì)于需要返回?cái)?shù)組或集合的方法,不要返回null。比如我們?nèi)ベI糕點(diǎn)店買面包,面包沒了是一種正常狀態(tài),就不應(yīng)該返回 null,而是返回長(zhǎng)度為 0 的數(shù)組或集合。Java 提供了 Collections.emptyXXX() 表示空集合。
8. 避免引入第三方庫(kù)
GitHub有許多開源的第三方庫(kù),比如網(wǎng)絡(luò)請(qǐng)求 OkHttp、圖片加載 Glide 等,但在 SDK 開發(fā)中,遵循的基本的原則是:
引入第三方庫(kù)可能帶來下面幾個(gè)問題:
9. 保證兼容性
SDK 是不斷迭代的,每次發(fā)布都會(huì)有新功能和 bug 修復(fù)。對(duì)于使用者來說,升級(jí)版本不該有太大的改動(dòng),一般直接替換庫(kù)文件或者修改遠(yuǎn)程依賴庫(kù)的版本號(hào)就夠了。避免直接對(duì)公開接口的重命名,如果舊接口廢棄,要通過 @Deprecated 關(guān)鍵字標(biāo)明,并給出替代方案和廢棄的時(shí)間。
10. 減少入侵性
要保證較少的代碼侵入主要在對(duì)外提供服務(wù)時(shí),充分考慮開發(fā)者的使用場(chǎng)景來設(shè)計(jì)優(yōu)良的 API。一套優(yōu)良的 API 在定義時(shí)要滿足絕大數(shù)開發(fā)者預(yù)期的方式——語(yǔ)義上要求通俗易懂,使用上要求簡(jiǎn)單可靠。具體的表現(xiàn)是,在正常情況下能夠穩(wěn)定可靠地運(yùn)行,在異常情況下及時(shí)地反饋錯(cuò)誤信息。
比如使用 Gradle 下載依賴庫(kù),AAR 包中有不必要的 bundle 資源,我們提供了打包 apk 時(shí)的構(gòu)建配置,自由選擇要打包的 bundle,減少了對(duì)宿主應(yīng)用的侵入性。
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 平臺(tái)通常使用 jar 和 aar 發(fā)布 SDK,區(qū)別是 jar 只包含代碼,aar 可以包含代碼、資源和動(dòng)態(tài)庫(kù)。一般而言 aar 是最合適的交付方式,把它上傳到 maven 服務(wù)器,使用者就可以一行代碼集成。對(duì)于需要靈活定制的客戶,我們也會(huì)提供 SDK 的源碼,弊端就是升級(jí)困難,要改動(dòng)很多的代碼。
對(duì)于代碼混淆,公開接口和 native 使用的接口不要混,內(nèi)部的實(shí)現(xiàn)細(xì)節(jié)可以混淆,以減少 SDK 包的大小。
接入文檔用來告訴 SDK 使用者,如何使用 SDK、詳細(xì)使用步驟和可能發(fā)生的問題。文檔內(nèi)容包括:更新記錄、基本信息、API 說明、集成步驟、FAQ等。好文檔的標(biāo)準(zhǔn)就是清晰明了,通俗易懂。一個(gè)完全不懂 SDK 的開發(fā)者看著文檔就能對(duì)接,對(duì)于經(jīng)常遇到的問題要逐條列出,專業(yè)名詞要有對(duì)應(yīng)的解釋。
集成 Demo 通常是一個(gè)簡(jiǎn)單的 App,用來展示如何快速地接入 SDK。Demo 的源碼托管到 GitHub,方便使用者參考,其版本變更策略和 SDK 版本的變化保持一致。盡管是個(gè) Demo,它的開發(fā)原則也要與 SDK 一致,確保高質(zhì)量的交付。
熱門資訊
探討游戲引擎的文章,介紹了10款游戲引擎及其代表作品,涵蓋了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戲設(shè)計(jì)領(lǐng)域和數(shù)字藝術(shù)教育的重要性,歡迎點(diǎn)擊咨詢報(bào)名。
2. 手機(jī)游戲如何開發(fā)(如何制作傳奇手游,都需要準(zhǔn)備些什么?)
?如何制作傳奇手游,都需要準(zhǔn)備些什么?提到傳奇手游相信大家都不陌生,他是許多80、90后的回憶;從起初的端游到現(xiàn)在的手游,說明時(shí)代在進(jìn)步游戲在更新,更趨于方便化移動(dòng)化。而如果我們想要制作一款傳奇手游的
3. B站視頻剪輯軟件「必剪」:免費(fèi)、炫酷特效,小白必備工具
B站視頻剪輯軟件「必剪」,完全免費(fèi)、一鍵制作炫酷特效,適合新手小白。快來試試!
4. Steam值得入手的武俠游戲盤點(diǎn),各具特色的快意江湖
游戲中玩家將面臨武俠人生的掙扎抉擇,戰(zhàn)或降?殺或放?每個(gè)抉定都將觸發(fā)更多愛恨糾葛的精彩奇遇?!短烀嬗肪哂卸嗑€劇情多結(jié)局,不限主線發(fā)展,高自由...
5. Bigtime加密游戲經(jīng)濟(jì)體系揭秘,不同玩家角色的經(jīng)濟(jì)活動(dòng)
Bigtime加密游戲經(jīng)濟(jì)模型分析,探討游戲經(jīng)濟(jì)特點(diǎn),幫助玩家更全面了解這款GameFi產(chǎn)品。
6. 3D動(dòng)漫建模全過程,不是一般人能學(xué)的會(huì)的,會(huì)的多不是人?
步驟01:面部,頸部,身體在一起這次我不準(zhǔn)備設(shè)計(jì)圖片,我從雕刻進(jìn)入。這一次,它將是一種純粹關(guān)注建模而非整體繪畫的形式。像往常一樣,我從Sphere創(chuàng)建它...
7. 3D動(dòng)畫軟件你知道幾個(gè)?3ds Max、Blender、Maya、Houdini大比拼
當(dāng)提到3D動(dòng)畫軟件或動(dòng)畫工具時(shí),指的是數(shù)字內(nèi)容創(chuàng)建工具。它是用于造型、建模以及繪制3D美術(shù)動(dòng)畫的軟件程序。但是,在3D動(dòng)畫軟件中還包含了其他類型的...
?三昧動(dòng)漫對(duì)于著名ARPG游戲《巫師》系列,最近CD Projekt 的高層回應(yīng)并不會(huì)推出《巫師4》。因?yàn)椤段讕煛废盗性诓邉澋臅r(shí)候一直定位在“三部曲”的故事框架,所以在游戲的出品上不可能出現(xiàn)《巫師4》
9. 3D打印技巧揭秘!Cura設(shè)置讓你的模型更堅(jiān)固
想讓你的3D打印模型更堅(jiān)固?不妨嘗試一下Cura參數(shù)設(shè)置和設(shè)計(jì)技巧,讓你輕松掌握!
10. Unity3D入門:手把手帶你開發(fā)一款坦克大戰(zhàn)的游戲
Unity工程創(chuàng)建完成后如圖所示: 接下來應(yīng)該導(dǎo)入此項(xiàng)目所需的Unity Package文件,要用到的Unity package文件大家可以去Unity3D的官方網(wǎng)站下載(地址:ht...
最新文章
同學(xué)您好!