中午吃飯和@趙總聊天,談到了iOS項(xiàng)目中出現(xiàn)的關(guān)于不理性的import問題,以本文來聊一聊關(guān)于在一個工程中從import關(guān)系中如何找出一些設(shè)計上的問題
下面是個循環(huán)import的例子:
>>> A.h
#import "B.h"
@interface A : NSObject
@end
>>> B.h
#import "C.h"
@interface B : NSObject
@end
>>> C.h
#import "A.h"
@interface C : NSObject
@end
這種引用關(guān)系在很多工程中都有出現(xiàn),我認(rèn)為這種引用關(guān)系并不健康
效率
復(fù)雜的引用關(guān)系會在編輯工程時會嚴(yán)重拖慢編譯效率,GCC編譯的時候默認(rèn)會緩存已編譯過的文件,當(dāng)再次編譯時只編譯相關(guān)的修改。當(dāng)一個文件被修改時,所有#import該文件的文件都會被重新編譯。所以當(dāng)引用關(guān)系過于復(fù)雜的時候,每個修改都有可能下次大面積的重新編譯。
架構(gòu)
筆者認(rèn)為從工程的架構(gòu)來講,樹狀關(guān)系更為合理。首先,循環(huán)import使代碼變得更難讀,當(dāng)觸及到實(shí)現(xiàn)代碼的時候,很可能開發(fā)者要在相關(guān)聯(lián)的幾個文件中反復(fù)跳轉(zhuǎn),這種情況無疑增加了工程本身的理解成本。這種引用關(guān)系帶來最嚴(yán)重的問題就是耦合性的問題,環(huán)狀引用的關(guān)系就意味著環(huán)內(nèi)的模塊是有依賴關(guān)系的,而循環(huán)依賴的關(guān)系導(dǎo)致了代碼中很大概率會出現(xiàn)比較嚴(yán)重的耦合。在面向?qū)ο缶幊讨蟹庋b性是最重要的特點(diǎn)之一。當(dāng)出現(xiàn)循環(huán)依賴的時候證明這段代碼沒有被合理的封裝,進(jìn)而,無論在移植還是擴(kuò)展都會受到嚴(yán)重的制約。
方案
像上面提到的,一個健康的工程中,引入關(guān)系應(yīng)該以樹狀引用為主。這種引用很容易可以將一個模塊剝離出來,最簡單的就是將文件中引用的子關(guān)系全部抽離出來就可以當(dāng)作一個單獨(dú)的模塊進(jìn)行使用,而環(huán)狀引用中在環(huán)內(nèi)每多一個節(jié)點(diǎn)就意味著有很多文件與當(dāng)前模塊耦合,而如果出現(xiàn)環(huán)環(huán)相扣的情況,當(dāng)想從工程中抽離出某個模塊的時候可能需要抽出半個工程來。
生活中很多時候也好像環(huán)狀引用的代碼一樣,筋疲力盡之后才發(fā)現(xiàn)一直在原地轉(zhuǎn)圈。轉(zhuǎn)著轉(zhuǎn)著,累了,迷惑了,彷徨了,或許最后就放棄了。像設(shè)計代碼一樣來設(shè)計生活,或者像設(shè)計生活一樣來設(shè)計代碼。我想,都會是一種精彩的體驗(yàn)。
太極生兩儀,兩儀生四象,四象生八卦,八卦生萬物