架构愿景的层次
我们根据架构适用范围的不同,把架构愿景分为几个类别讨论:
软件全局
软件全局的架构是我们所最关心的,因此也会花费最多的笔墨。
软件全局中的架构愿景一般很难具体化到代码级别,其实你会发现,就算是具体化到了代码级别,也会因为实际中存在的问题,导致代码没有太多的价值。因此,为软件全局设置的架构愿景可以以原则、或是模式名的方式体现,并用自然语言或伪代码描述。例如,可以为一个系统规定三层架构作为其愿景,并指出三层的分类原则。注意,我们需要指出分类原则,否则规定三层架构并没有太大的意义,因为三层架构随着实现平台的不同、开发人员的不同而有很大的差异,如果不能够规定一个可操作的规范,那么愿景是没有意义的。在Java环境下,我们可以这样说:
"客户端采用前端浏览器界面,业务逻辑采用servlet,配合JSP编写,浏览器到服务器的数据采用集中处理,具体的方法是在业务逻辑和前端浏览器之间采用Front Control模式,接受前端浏览器传送过来的数据,并指派给相应的业务逻辑处理。数据的合法性检验分为两个部分:和业务逻辑无关的基本合法性验证在前端使用Java Script处理,和业务逻辑相关的合法性验证在业务逻辑层处理,可以使用一个集中的servlet专门处理错误情况。"
而在Windows环境下,我们知道三层结构的分界和Java中的并不相同(关于这一点,下一篇的文章中将会有详细的描述),我们可以在业务逻辑层或显示层直接操纵数据,非常的方便,因此,在Windows中的架构愿景的描述又不一样。另外,在非面向对象的环境中,在分布式的环境中,在Lotus Notes的环境中,其架构的描述都不一样。
注意到,架构愿景的制定是根据不同的应用环境而变化的,这一点我们在文章的一开始就强调过,这里又出现了相同的问题。我们可以通过一个简单的例子来加深对这个问题的理解。在Java的环境下,特别是J2EE的环境下面,经典的设计思路是把数据库的一张表视作一个类,表中的每一行都是这个类的一个具体的实例,表的每一个字段对应了类的一个变量,类一般支持Find方法,来获取数据不同的实例。这是一种很自然的设计思路,而且可以通过CMP等技术来简化设计的繁琐步骤。可是,在Windows环境下,相信没有多少人会这么做。常用的处理方法是使用记录集(RecordSet)的方式,也就是说针对一组的记录来进行操作,而不是单个的记录。这些记录可以是跨表的(使用SQL的连接),也可以是单表的。由于Windows环境下大多数的编程语言都能够支持记录集方式,因此编写基于记录集方式的程序是相当简单的。当然,我们也可以采用J2EE平台的编程方式,但是会导致编程量的激增,同时也难以达到预计的效果。这种平台的差别导致了架构愿景的差别。
此外,我们注意到我们对架构的描述其实还是不够仔细,这是非常正常的,因为随着开发的深入,我们会不断的完善架构的描述。例如,我们可以写出Front Controll的类框架,写出主要的几个Servlet,以及他们之间的关系。这个时候,使用UML类图会是一个不错的选择,实际上,我非常推崇在架构设计中大量的使用类图。不过在实际的运作中,每个软件团队大多数都有自己熟悉的架构设计思路,使用何种工具并不是主要的问题。
我们从源自需求模式中,学习到架构的设计是来自于需求的,而应用于软件全局的架构则来自于最重要的需求。还记得我们在那个模式中提到的网上宠物店的例子吗?系统采用了MVC模式,sun的官方文档一开始说明了为什么采用MVC模式,MVC模式解决了什么问题,然后开始分析MVC模式的几个组成部分:Model、View、和Controll。其实,MVC中的每一个部分,在真正的代码中,大都代表了一个子系统,但是在目前,我们就非常的清楚系统大致上会是一个什么样子,虽然这时候它还十分的朦胧。
不要视图在全局的架构愿景中就制定出非常细致的规划,更不要视图生成大量的实际代码。因为,你的架构愿景还没有稳定(我们在其后的稳定化的模式中将会讨论稳定的问题),还没有获得大家的同意,也没有经过证明。因此,从整个的开发周期来看,全局架构愿景是随着迭代周期的进行不断发展、修改、完善的。
我们如何确定全局架构愿景工作的完成?一般来说,你的架构设计团队取得了一致的意见就可以结束了,如果问题域是团队所熟悉的,一两个小时就能够解决问题。接下来设计团队把架构愿景传播到整个的开发团队,大家形成一致的认识,不同的意见将会被反馈会来,并在本次的迭代周期(如果时间比较紧迫)或下一次的迭代周期中(如果时间比较宽松)考虑。
子模块级、或是子问题级的架构愿景
这时候的架构愿景已经是比较明确的了,因为已经存在明确的问题域。例如界面的设计、领域模型的设计、持久层的设计等。这里的愿景制定本质上和全局的愿景制定差不多,具体的例子我们也不再举了。但是要注意一点,你不能够和全局愿景所违背。在操作上,全局愿景是设计团队共同制定出来的,而子模块级的架构愿景就可以分给设计子团队来负责,而其审核则还是要设计团队的共同参与。这有两个好处,一是确保各个子模块(子问题)间不至于相互冲突或出现空白地带,二是每个子设计团队可以从别人那里吸取设计经验。
在设计时,同样我们可以参考其它的资料,例如相关的模式、或规范(界面设计指南)。在一个有开发经验的团队,一般都会有开发技术的积累,这些也是可供参考的重要资料。
我们在这个层次的愿景中主要谈一谈子模块(子问题)间的耦合问题。一般来说,各个子模块间的耦合程度相对较小,例如一个MIS系统中,采购和销售模块的耦合度就比较小,而子问题间的耦合程度就比较大,例如权限设计、财务,这些功能将会被每个模块使用。那么,我们就需要为子模块(子问题)制定出合同接口(Contact Interface)。合同的意思就是说这个接口是正式的,不能够随意的修改,因为这个结构将会被其它的设计团队使用,如果修改,将会对其它的团队产生无法预计的影响。合同接口的制定、修改都需要设计团队的通过。此外,系统中的一些全局性的子问题最好是提到全局愿景中考虑,例如在源自需求模式中提到的信贷帐务的例子中,我们就把一个利息计算方式的子问题提到了全局愿景中。