中午吃饭和@赵总聊天,谈到了iOS项目中出现的关于不理性的import问题,以本文来聊一聊关于在一个工程中从import关系中如何找出一些设计上的问题
下面是个循环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
这种引用关系在很多工程中都有出现,我认为这种引用关系并不健康
效率
复杂的引用关系会在编辑工程时会严重拖慢编译效率,GCC编译的时候默认会缓存已编译过的文件,当再次编译时只编译相关的修改。当一个文件被修改时,所有#import该文件的文件都会被重新编译。所以当引用关系过于复杂的时候,每个修改都有可能下次大面积的重新编译。
架构
笔者认为从工程的架构来讲,树状关系更为合理。首先,循环import使代码变得更难读,当触及到实现代码的时候,很可能开发者要在相关联的几个文件中反复跳转,这种情况无疑增加了工程本身的理解成本。这种引用关系带来最严重的问题就是耦合性的问题,环状引用的关系就意味着环内的模块是有依赖关系的,而循环依赖的关系导致了代码中很大概率会出现比较严重的耦合。在面向对象编程中封装性是最重要的特点之一。当出现循环依赖的时候证明这段代码没有被合理的封装,进而,无论在移植还是扩展都会受到严重的制约。
方案
像上面提到的,一个健康的工程中,引入关系应该以树状引用为主。这种引用很容易可以将一个模块剥离出来,最简单的就是将文件中引用的子关系全部抽离出来就可以当作一个单独的模块进行使用,而环状引用中在环内每多一个节点就意味着有很多文件与当前模块耦合,而如果出现环环相扣的情况,当想从工程中抽离出某个模块的时候可能需要抽出半个工程来。
生活中很多时候也好像环状引用的代码一样,筋疲力尽之后才发现一直在原地转圈。转着转着,累了,迷惑了,彷徨了,或许最后就放弃了。像设计代码一样来设计生活,或者像设计生活一样来设计代码。我想,都会是一种精彩的体验。
太极生两仪,两仪生四象,四象生八卦,八卦生万物