基于BREW平台的松耦合设计III-可移植、可复用软件的设计原则
毛晓冬 2007-10-26
一、 概述:
本文主要阐述基于BREW平台的可移植/可复用软件的最通用的设计原则,以便利用BREW平台自身的优势,加快开发。
二、 高低层(应用和底层实现)组件间的设计原则:
高低层组件间的设计原则,如上图描述的那样,归纳而言就是:
高层组件依赖接口抽象,不依赖与低层实现。
低层实现依赖接口抽象,不依赖高层组件。
其本质,就是要将高层组件和低层组件间进行解耦,通过接口抽象联系在一起,每一部分都可以单独的变化,这种变化被封装起来,对外体现不变的抽象(接口)。这使得,当系统(需求)变化时,两者可以独立的变化而不影响对方,从而达到可移植,可复用,可扩展性。
该原则对应到BREW,其实就是要求App只允许以接口方式访问一切服务(实现)。即,App就是高层组件,通过BREW的接口(标准的,或者扩展的),访问底层的服务。通过接口隔离耦合。
在BREW中,高层组件依赖低层组件的情况,典型的就是App绕过接口抽象,直接调用了底层实现(以函数或者全局变量的方式)。而低层组件依赖高层组件的情况,典型的就是接口的内部实现中,直接引用了App的类成员或者直接发事件给特定CLSID的App。
对于这种违背原则的做法,直接的后果,就是由于没有隔离耦合,进而没有隔离/封装变化点,从而导致面对需求变化时,可重用,可移植,可扩展性的低下。因为对于上层应用,随着客户需求的变化,可能发生改变,这是一个变化点,需要封装。对于底层实现,随着硬件,平台的差异,也可能发生变化,这又是一个变化点,也需要封装。此时,我们就需要引入一个接口抽象层来隔离,封装变化点。从而保证高层组件(App)和低层组件(底层实现)的可移植性,因为它们都依赖于接口抽象。典型的,在新项目中,上层UI可以直接移植。对于底层实现,只需要保证对上依赖的接口抽象不变即可,这一步(底层实现)可以和UI同步的进行。
反之,则会带来可观的额外负担!且随着时间和变化的推进,负担将越来越大。
三、 高层间(应用间)的设计原则:
如图所示,高层间的设计原则,应该是:
使用一组规约解耦高层组件间的通信,将绑定延迟到运行时。对应与BREW,这里的高层组件很明显就是App,这里的规约可以是模块暴露的扩展接口,MIME Type等等任何可以用来解耦BREW App间交互的手段。
这种设计原则的好处在于,每个应用对外提供的服务和从外界索取的服务都通过一组规约来定义,从而避免了组件间的直接交互。
这种设计原则典型的用途在于,App的移植或者替代升级。只需要实现升级后应用的所有必要规约,其他的应用就不需要作任何变动。
注:如果能找到比事件更好的方案,就尽量不要使用事件。
四、 总结:
基于本文提到的原则,其实将一个系统抽象来看,最重要的就是一组组件间(应用间)的规约,以及一组高/低层组件间的依赖抽象(接口)。此时,不管是移植整个平台,还是单独升级某个应用或者底层实现,都变得简单而可控。
附:
本文所指的接口,是对象的一种规格,具体到语言层次,就是C++中的纯虚基类,Java/C#中的接口,或者C中的虚表。在编译期代表抽象,在运行期绑定实现,决不是简单的(全局,静态)函数和(全局,静态)变量。