关于使用接口解耦模块的一点体会

Posted on March 23, 2012

看过不少资料,凡是谈到接口,基本上都会提到依赖注入,组合编程,模块解耦这三个概念。这些概念在《软件框架设计的艺术》这本书里都有提到。这本书的前言里有一段话是说,之所以称之为艺术,是因为很难用语言去描述它,有些人可能已经在使用了,但是却说不出其中为啥好的道理来。今天在试图优化框架编译文件大小的过程中,对接口的使用又有些体会,记录一下。

先说关于包结构定义的体会。

之前移植了Flex的绘图元素模块。今天看了下库编译大小,275K。我想测试了下,移除掉绘图元素模块会是多少。当初就是想要可以随时删掉这个模块。所以就把所有绘图元素相关的类都放在同一个包里。我一删除,却发现报错了。有几个components包下面的组件引用了绘图元素里的几个接口。我回头去看Flex里这几个接口原始的包结构。它们都是被放到了框架的core包下面的。瞬间明白了。我之前一直认为core这个包是跟它的名字一样是放最核心的类和接口的。其实不然。有很多类比core包里的核心多了,比如LayoutManager,所有的UI组件都基于这个类的自动布局机制运行的。但是它没在core包里。重新看了一遍core包的内容。发现必须放在这里面的类和接口都有一个共同点:它们有可能被很多模块同时引用。所以跟贴切的理解应该是这样:框架里不管怎么设计,总是会有存在模块依赖的。而core包里就应该放置这些无法解耦被公共依赖的部分。然后其他模块都引用core包的内容,而各自之间就能保持独立了。这样分的包结构,物理上隔离了各个模块,只要保证core包的内容不变,其他模块都应该是可以直接删除而不影响另外一个模块的编译的。也就不存在我现在遇到的报错的这个问题了。

再回到接口使用上

再看一遍core包里的内容,会发现还有一个共同点:绝大部分文件都是接口和常量定义。只有一个组件UIComponent,因为它是所有UI的基类。根据前面的结论,我们不难得出一个结论:框架的公共依赖部分都应该是接口。也就是说,各个模块之间并没有直接的引用,而都是通过接口间接引用的。没有直接引用带来的好处是在编译阶段体现出来的。比如一个有10个模块的框架,在项目中,我只用到了其中的1个模块,但是由于模块之间存在类的直接引用,而不是接口。因为类的引用都是跟蜘蛛网一样不断扩展的,类引用的任何类都会被编译。最终编译进项目的框架代码就可能会同时有10个模块的代码!这样显然不是我们愿意看到的。而如果是用接口来隔离类的直接引用。不管使用的是哪个模块,最终都会只编译对应的模块,附加core包里的几个接口进去。仅此而已,显然更加经济。这样,其实我如果做好了框架的解耦,根本都不需要去考虑移除掉绘图模块来达到精简的目的。项目中如果不需要,不使用即可,不会增加最终编译的文件大小。

所以,如果使用对了接口,可以很好地解决耦合问题。但是以上的方式不是万能的,只能解决一部分,对于还是不能有效解决耦合的部分,就要试试依赖注入了。