您的位置:首页 > 其它

经典教程翻译系列: 间接调用体系入门

2006-01-29 20:49 519 查看
原作者: Benjamin Edwards 译者: Franks Pan

表单从属于功能 – 这是一个误解.表单与功能是相互独立的.
--Frank Lloyd Wright

ColdFusion的初衷是为了迎合”站长们(webmasters)”创建动态网站的需求的.它成功地做到了这一点.不过对于团队,”站长”的称呼是一个时代错误,它应该留给真正的网络应用.随着这些应用程序变得更加棘手和强大,ColdFusion开发人员们发现光有标签和函数是不够的.为了升级强壮的--尤其那些可以成功扩充的--应用程序,开发人员就不许建立适当的软件工程体系.

在本文,我将讨论一些软件体系中涉及到的问题,然后具体讲讲以基于事件为标记的,独特而灵活的软件体系, 间接调用(implicit invocation).

软件体系

在<<软件体系入门>>的报告中, Carnegie Mellon大学的David Garlan和Mary Shaw运用架构程序用的运算法则和数据结构来描述软件体系.报告认为”结构的问题包括全体组织和全局控制;通讯、同步以及数据访问的协议 ;用于设计元素的模块任务;缩放比例与性能;设计方案的选择。”

程序设计发生在不同层次上.在面向对象的系统中,需要决定应用程序的接口,实现这些接口所用的类,以及类之间交流和关联途径的选择(这最后一个通常就是实际模式的目标).各个设计呈现一个新的组织层.应用程序的体系包含了绝大多数设计决定.

实际应用中,软件体系通常被加工为组件(component)和连接器(connector)的集合。组件是系统的功能元素。比方说,一个购物车,一个通讯录,或者一个数据库都可以是软件体系的组件。连接器是用于组件间通讯的协议,包括方法的调用,SQL查询和HTTP请求。系统所选择的体系决定了组件和连接器的词汇表(vocabulary),一种定义如何组合二者的约束的集合。

对软件体系的选择是依据系统整体组织情况—也就是说没有固定,十全十美的体系.随时间推移,一些不同的软件体系风格被推出—每一个都有其优势和劣势.最流行的体系包括:
l 管道与过滤器(Pipes and filters)
l 数据提取与面向对象组织(Data abstraction and object-oriented organization)
l 分层体系(Layered systems)
l 仓储机制(Repositories)
l 基于事件的间接调用(Event-based, implicit invocation)

对定义体系中的组件和连接器外露界面的这一事项来说,很重要的风格特征(metrics)就是系统的内聚和耦合。内聚是组件用途单一性的度量标准。组件的内聚性越高,它的功能就越专注,复用所承担的假设就越少。
耦合性可用来度量组件间依赖程度。组件间依赖程度越低(它们的联系越松散),它就越独立、复用性也越好。最大化的内聚和最小化的耦合是灵活、易维护体系结构的两大特点.

基于事件的间接调用

基于事件,II(implicit invocation××)是具有高内聚和低耦合的精工体系的范例。因此,它被软件工程普遍接受。II体系的例子随处可见,事实上包括所有现代的操作系统、完整的开发环境和数据库管理系统等。

Garland和Shaw对间接调用的描述是:“II的思想就是以组件通告(或者广播)一个或更多的事件的方式替代程序的直接调用。系统的其他组件可通过事件联结程序来注册对事件的影响。当该事件被通告,系统将调用所有注册给该事件的程序。如此,一个事件’间接地(implicitly)’地促成了程序在其他模块的调用。”

II系统由事件驱动。事件在系统需要做某事时被触发——比如像对引入请求的响应。事件在不同类型的实现中采用不同的形式;通常对于基于对象的系统来说,事件是属性值里包含运行该事件所需上下文信息的对象(类似HTTP请求携带它所有表单和查询语句变量的方式)。

当一个事件被通告,系统就开始为该事件查找listener组件。Listener符合我们刚刚已经讨论过的组件创建标准——它们是系统的功能模块。请求作为listener的组件在配置时段里被(XML文件)注册,进而在运行时由确定的事件通告。当事件被触发,所有注册的该事件关联的listener经由动态确定(dynamically-determined)方法调用的手段,传递给该事件。通过这种方式,功能被间接地调用。事件通告(notify)listener的这种处理方式被称作事件宣告(event announcement)。

事件和listener可以自行触发其他的事件.我们来分析假象的登录/确认处理(ogin/authentication)如何使用事件和listener来呈现.在这个例子中,登录表单被填入用户名并提交.随后HTTP请求触发生成LoginEvent,系统将带有信息的事件装入请求中.

接下来,系统为LoginEvent确定listener;这个例子里只有一个-- AuthenticationListener.由一个配置文件确定后,系统将调用AuthenticationListener的tryLogin()方法,把事件传递给它.根据事件里的信息,tryLogin()方法会查询以确认是否有此用户.如果确认成功,一个新的事件LoginAcceptedEvent会被触发.如果确认失败,新事件LoginFailedEvent会被触发.周期将由被通告的新事件的listener维持下去.

间接调用体系与直接调用体系的不同之处在于,间接调用系统组件使用事件来相互交流.体系中连接器将事件与组件方法绑定.因为这些绑定是在运行过程动态决定的,组件之间是低耦合的;编译阶段无需确定哪个方法需要调用.低耦合性有助于软件体系灵活性和易维护性:新组件的添加仅需要像其他listener那样注册一下.

低耦合性组件在一起工作,无需彼此依赖,便可以完成任务.这种交互策略隔离交互性组件,来提高灵活性.组件只需要注册为系统事件就可以被投入使用,极大提高了复用性.新组件的引入不需要改动其他组件的接口,为功能添加创造了可测量性.总之间接调用极大方便了系统的扩展.

体系与设计模式

软件设计开始于一个满足功能无关要求的体系骨架(提高常用框架.例如:在Mach-II里就是指那个MachAppSkeleton文件包.原文这一节主要讲non-functional requirements(功能无关要求)的意义.直译很难理解,所以我拿MachAppSkeleton来举例,就是说像MachAppSkeleton这样不涉及项目具体特性,因此具有可以用于不同项目的万用性—译者按)
体系风格不同于设计模式.体系是为系统定义必要的组件和连接器的,而模式则为这些组件和连接器提供执行策略.好的体系利用了设计模型,但有其更深远的目标.例如流行的设计模式Model-View-Controller (MVC,模型—界面—控制器).MVC不是体系;它是执行体系的一种设计策略.不同的体系会或多或少地借助于设计模式.对于面向对象的II体系来说,MVC似乎是最合适不过的.
之前我们就已经说过,II会在重置和添加组件时发挥优势.在II体系下控制器把更新的模型和页面组件通知给系统,不是使用直接的方法调用,而是使用事件的生成.模型,页面,和控制器的元素都可以生成事件,供控制器用来通报listener—完全不需要listener组件之间的相互了解.

总结

基于事件,II体系为软件编程提供了更好的复用性,健壮性,尤其是可维护性给.高聚合性与低耦合性(动态启动事件的办法来实现)的结合,使得建立在II体系结构上的应用程序可以灵活应对需求的变动和众多商业软件提出的新应用.
虽然II体系已经被普遍应用于软件工程的诸多领域,但是它并没有应用在网络应用方面.不过情况已经发生变化.名为"Mach-II"的基于事件的,间接调用体系已经诞生.它的第一个应用是,使用ColdFusion组件(CFC)执行真正意义上的MVC,基于事件的体系.Mach-II提供了一个可以结合CF组件,Java类,网络服务,以及Flash平台于一身的框架,来创建同时具有健壮性与易维护性的应用程序.

更多信息,请访问www.mach-ii.com.

资源
· www.cs.cmu.edu/afs/cs/project/able/ftp/intro_softarch/intro_softarch.pdf
· www.mach-ii.com
· www.halhelms.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: