本章讲解如何架构你的程序以及提供了创建面向对象的应用程序的一些设计指导.
程序结构
本节将讲解如何架构你的程序来同时适应Mach-II和我们标准目录结构指导.
Mach-ii.xml
这已经在Mach-II核心文件章节讲过了.它是Mach-II程序的核心配置文件,定义了所有的listener,event以及view等等.如之前讲的,它存在于文档根目录之外.
模型,过滤器以及插件(model, filters & plugins)目录
这是Mach-II用来给组件分类用的目录结构.虽然它不是必须的,但是它的确是个好惯例.在你的程序组件目录下,创建三个目录: model
, filters
, plugins
. 在Macromedia,所有组件放在文件根目录之外,像这样:
{cfmxroot}/extensions/components/{appname}/model/
{cfmxroot}/extensions/components/{appname}/filters/{cfmxroot}/extensions/components/{appname}/plugins/
Model目录是存放继承了MachII.framework.Listener
的listener组件和普通的框架事务模型组件.
Filter
目录是存放继承了MachII.framework.EventFilter的过滤器组件.
Plugin
目录是存放继承了MachII.framework.Plugin的插件组件.
其他组件可以存放在model目录或者其他配套目录下.
为了保持model目录的组织性,最好为listener创建独立的子目录,甚至可以直接创建一个listener目录在你的程序目录下;
.../components/{appname}/model/listeners/ - 只放listeners
.../components/{appname}/model/ - 其他的
或者:
.../components/{appname}/listeners/ - 只放listeners
.../components/{appname}/model/ - 其他的
其他区分listener与其他事务对象的方法是为listener起特别的名称,例如SomethingListener.cfc
.
采取哪种方法取决于程序里有多少listner以及你是否希望将事务对象用于其他背景(context)下.
View目录
另一个目录结构惯例,又来区分.cfm文件与普通的HTML文件.这些.cfm文件被放置在程序目录下的view目录里,可以是在文件根目录也可以是在程序的include目录下.在Macromedia,我们将view放在文档根目录之外:
{cfmxroot}/extensions/includes/{appname}/views/
因为我们已经将/cfinclude映射到{cfmxroot}/extensions/includes/,
所以我们在mach-ii.xml定义Mach-II全局变量applicationRoot,用"/cfinclude/{appname}"
代替"/{appname}"
,这样Mach II可以找到这些view .cfm
文件.
程序设计需要考虑的因素
本节提供了设计Mach-II程序的一些指导.我们先在本节讲讲大体的设计帮助,在以后章节讲分类讲各个模型,设计模式,view,事件句柄,事件过滤器以及插件.
整体设计考量
可以从两个角度来看Mach-II应用程序的设计:以方面从事务模型,一方面从用户体验.大多数情况下,你可以同时实现这两方面的设计.下面你将看到,事务模型组件的射界与实现可以被独立于项目其他部分(而且独立出Mach-II框架自身).用户界面同样可以独立设计,并且在大多数情况下,可以独立实现.用户界面的交互推动了事件模型的设计,进而推动了事件句柄和listener的设计,而不是拘泥于事务模型接口.用户界面可以分配给独立的团体和个人来做,这将为早期的产品开发带来更高效率.更深层看,这种Mach-II带来的低耦合性使项目更加有弹性更易于维护.
一些基本的面向对象的设计指导
对于很多开发人员来说,特别是那些刚接触面向对象设计的朋友,创建面向对象类型应用程序最难的部分就是决定需要哪些组件.如果你能够连贯地描述出事务逻辑之间的交互关系,那么你将发现描述中的大多数名词本身可以作为组件,大多数的动词可以作为组件的方法.当然我说了,是大多数,不是全部.注意不是所有东西都被作为组件,有的东西没有重要到需要建模的地步.在我们的项目里,人的名字可能足够重要到需要建立一个组件模型来接收头衔,称呼,名字,姓,以及前缀等等,但在另一个项目里,这只需要一个全称(或者只是姓和名字)字符串就够了.这里没有硬性规定.
一旦命名了组件,你需要决定如何适当地定义它..每个组件最好高度内聚—就是说,它只可以用来做好或者描述好一件事.组件间还需要较低的耦合性—它们不需要为完成共同任务而相互了解或依赖.为此,要准备好增强你的代码内聚性,降低其耦合性—首先选出那些功能明显的组件,而不需要它们完美呈现你的事务逻辑.如果你发现很难呈现两个或更多组件间的关系,那么有可能这个关系本身就相当重要,需要你为它设置一个组件—有时候这关系实际上比它联结的事务还要重要.同时要注意,组件间的关系体现了组件之间耦合性.把关系抽象化到组件中可以降低组件间耦合性,进而使之更加灵活.
另一个关键点是与复合相对的继承.很多面向对象的新手随处可以看到继承,并试着用组件扩展其它组件.继承是组件间的一种特殊关系:它意味着”是一个(is-a)”.它实际上没有想象的那样普遍,它还是组件与其子组件之间高耦合性的一种表现形式.除非关系确实呈现”是一个”的特点,即子组件实例在人很用例都完全套用父组件,不然最好使用复合来代替继承.符合一般可以描述为”有一个(has-a)”或者”引用一个(refers-to)”的关系.一个很好的例子是雇员/经理模型.新手往往试图用继承关系描述它—经理”是一个”雇员—可是当你考虑到晋升或替换等状况时会发现这行不通.更准确的模型是经理”是一个”角色,雇员”有一个”角色.当普通员工升迁了,它实际上只是它们的角色变了,在一些公司里, 特别是那些拥有"matrix reporting"系统的或者经常在雇员中安排临时角色的公司,雇员可以是多重角色.
好的面向对象设计的(使用了设计模式的)作品很容易被理解和掌握.它们是你的朋友!