前言
目前我們所開發(fā)SDK的目的是為了流程簡(jiǎn)化的同時(shí),保證數(shù)據(jù)邏輯安全;說(shuō)到底,我們就是為了要讓流程變簡(jiǎn)潔而已。但隨著這些年所開發(fā)出來(lái)的SDK,不斷的經(jīng)由客戶的考驗(yàn)和反饋;越發(fā)覺(jué)得開發(fā)SDK的工作前期設(shè)計(jì)部分非常重要,因?yàn)槊恳话嫠l(fā)布的SDK,在接口上不能產(chǎn)生太大的變化,為了讓SDK有更好的兼容性,我大概總結(jié)了下面的一些方法。
1、提供全能類型的初始化方式
這個(gè)方法是我在Objective-c的一些優(yōu)化語(yǔ)言中找到的,因?yàn)槲覀兯O(shè)計(jì)的接口是基于開發(fā)者的角度,所以初始化最好提供全面的初始化方法。
需要盡量提供可能會(huì)用到的所有接口,這樣有助于二次開發(fā)(當(dāng)然這些事情是不可以一步到位的)
- (instancetype) init {
if (self = [super init]) {
[self commonInit:6];
}
return self;
}
- (instancetype) initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self commonInit:6];
}
return self;
}
-(instancetype)initWithFrame:(CGRect)frame withCount:(int)index{
self = [super initWithFrame:frame];
if (self) {
[self commonInit:index];
}
return self;
}
-(instancetype)initWithFrame:(CGRect)frame withCount:(int)index withType:(int)type{
self = [super initWithFrame:frame];
if (self) {
[self commonInt:index with:type];
}
return self;
}
2、對(duì)象多使用不可變對(duì)象
這個(gè)是需要看情況而定的,但是對(duì)于封裝的類對(duì)象,尤其是用于數(shù)據(jù)操作類的,建議盡量創(chuàng)建使用不可變的對(duì)象,如果想支持可操作的屬性,可以提供方法來(lái)實(shí)現(xiàn)修改屬性。
3、使用前綴命名來(lái)避免沖突
在使用到更多的類庫(kù)以后,就更容易出現(xiàn)名字相同的沖突,尤其是在一些功能性相仿的類,我們之前寫過(guò)的DV12的類庫(kù)和DFUnit還有最新的DV16的庫(kù)就存在過(guò)沖突,通常這類沖突在編譯的時(shí)候就能檢索出來(lái)。
為了避免這種情況,我們可以通過(guò)以下的方法來(lái)實(shí)現(xiàn):
- 命名的引申義:通過(guò)類的功能可以使用駝峰法來(lái)命名,但功能總有相似性,于是我們可以使用公司前綴或者簡(jiǎn)稱等來(lái)命名類以及類方法
- 第三方庫(kù)的引用:對(duì)于我們引用的第三方庫(kù)的引用,我們通常也能發(fā)現(xiàn)他們具備了自己獨(dú)特的類命名方式,而這個(gè)時(shí)候,我們要做的就是保留他們?cè)械拿?,這不僅僅是避免命名沖突的問(wèn)題,更多的是對(duì)原作者的尊重。
- 為私有類提供前綴:對(duì)于私有不開放的類,我們也可以通過(guò)前綴的方式來(lái)做區(qū)分,這樣有利于我們?cè)诎l(fā)布或者打包的時(shí)候有效區(qū)分那些是私有的,那些是應(yīng)該公布出去的。
4、API的層級(jí)處理
SDK是應(yīng)該具備層級(jí)架構(gòu)的,這不僅僅是功能性的體現(xiàn),更是一個(gè)庫(kù)的核心所在,如果層級(jí)架構(gòu)做得好,那么在二次開發(fā)的時(shí)候就能避免很多的問(wèn)題,邏輯也變得更加的清晰,每個(gè)層級(jí)關(guān)系的嵌套要清晰。
- 通過(guò)類別或功能來(lái)進(jìn)行層級(jí)劃分

- 關(guān)于內(nèi)部流程的控制
因?yàn)镾DK的工作本來(lái)就是需要將復(fù)雜的流程封裝起來(lái),讓二次調(diào)用的人更簡(jiǎn)單、更方便的去使用,但是我們的SDK并不是一次開發(fā)不需要后期維護(hù)的,所以為了以后的維護(hù)和方便些,我們需要對(duì)涉及業(yè)務(wù)流程的流程圖和相關(guān)邏輯記錄下來(lái),可以通過(guò)類內(nèi)部的注釋或者流程圖的方式來(lái)記錄。
另外流程也需要獨(dú)立性高一點(diǎn),盡量提高一些簡(jiǎn)單流程的復(fù)用性,避免整個(gè)SDK的庫(kù)非常臃腫。
5、錯(cuò)誤結(jié)果的處理
由于SDK是給開發(fā)者二次開發(fā)的,所以log記錄很重要,它可以在第一時(shí)間替我們找到問(wèn)題的發(fā)生點(diǎn),為此我在SDK中添加了Log打印的等級(jí)控制,方便控制打印,還有一個(gè)就是需要對(duì)這些打印內(nèi)容保存,保存在文件里,當(dāng)出現(xiàn)問(wèn)題的時(shí)候就可以翻出來(lái)查找問(wèn)題所在了。
錯(cuò)誤內(nèi)容的反饋還不局限體現(xiàn)在打印上,也可以通過(guò)增加錯(cuò)誤碼列表,來(lái)分析定位問(wèn)題。
6、SDK中消息的傳遞
我們的SDK涉及到較多的數(shù)據(jù)交互,這些是不能局限于庫(kù)的內(nèi)部,還要通過(guò)協(xié)議上傳給上層,讓二次開發(fā)更加清晰、簡(jiǎn)單的獲取到所需的數(shù)據(jù),目前iOS上的消息傳遞大概分為以下幾種,我們可以根據(jù)他們的優(yōu)缺點(diǎn)來(lái)進(jìn)行選擇,當(dāng)然最好在設(shè)計(jì)接口的時(shí)候能夠考慮到都用上。
| 傳遞方式 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|
| Delegate:代理 | 數(shù)據(jù)回調(diào)屬于類對(duì)象擁有內(nèi)容,數(shù)據(jù)回調(diào)高效可靠,可實(shí)現(xiàn)多個(gè)函數(shù)來(lái)回調(diào)不同數(shù)據(jù)內(nèi)容 | 局限于當(dāng)前類,如果要多個(gè)類之間傳遞,實(shí)現(xiàn)起來(lái)的代碼會(huì)非常臃腫 |
| block:代碼塊 | 輕量級(jí)的回調(diào),代碼簡(jiǎn)潔,邏輯清晰 | 容易造成循環(huán)引用,臨時(shí)性;代碼塊存放在堆棧上,容易造成內(nèi)存泄露 |
| KVO:觀察者 | 提供了簡(jiǎn)單的實(shí)現(xiàn)兩個(gè)對(duì)象同步屬性的方法,能對(duì)非我們創(chuàng)建的對(duì)象進(jìn)行狀態(tài)監(jiān)聽,不需要高邊內(nèi)部對(duì)象 | 觀察屬性比較單一,適用的場(chǎng)景較少 |
| NSNotification:通知 | 整個(gè)APP內(nèi)都可以監(jiān)聽這個(gè)通知消息,屬于ARC,不用管理內(nèi)存問(wèn)題 | 需要配對(duì)remove使用,會(huì)導(dǎo)致多處接收,多處處理,代碼整體架構(gòu)處理很混亂 |
整體的腦圖如下:
