流行软件架构代码技术分析

 1.       系统架构或软件架构的定义

系统架构(Framework 或Architecture)或软件架构的定义很难明确。在面向对象范畴中,就是通过若干类、抽象类及其接口有机组成的软件系统,其中类起的作用好比建筑物中的砖瓦钢筋水泥楼板,而接口和抽象类中没有实现的方法好比其中的一个个空间,包括大厅,走廊,房间,厨房,卫生间....,架构使用者的任务就是往这些空间中填充东西,也就是实现那些接口和抽象方法,从而可以创建一座定制了的建筑物。进一步,可以对这个建筑进行修饰使其外观更加漂亮。当然也可以进行改动,以便结构更加合理。

在《Rational 统一过程实践者指南》(RUP)认为,系统架构为:1. 系统中最重要的组成部分和它们的接口,以及做出的创建、购买或是重用这些组成部分的决定;2.描述这些组成部分在运作时如何交互来实现系统中最重要的脚本;3.实现并测试系统架构的原型,以验证架构是否可行、是否化解了重大风险,以及验证它是否打到了重要的质量指标:性能、可扩展性和成本等。

2.       Dot net 设计模式

2.1.    桥接模式

1、概述

“将抽象部分与它的实现部分分离,使它们都可以独立地变化”,这是GOF在《设计模式》一书中的解释。这里的抽象和实现并不一定是同一层次的概念,例如数据库操作可以归结为“增加、删除和修改”。很多业务过程都是通过对数据库的操作实现的,例如“库存管理”中的“入库”,这个业务动作的软件实现可以描述为“在库存表中增加一条记录”,而“入库”和“插入记录”处于不同的业务层次。

2、使用场合

(1)不希望在业务和业务的软件实现之间存在因定的绑定关系。例如,不希望“入库”业务过程和具体的数据库访问技术或数据库管理系统有过于密切的关系。最好是数据库访问技术的升级,或数据库管理系统的改变对业务模块没有影响,甚至在运行期间可以通过动态绑定来选择不同数据库技术或数据库管理系统。

(2)希望类的抽象和实现部分可以扩充,进而实现不同的抽象接口和实现部分的组合。

(3)修改实现部分对用户不产生影响,即代码无须重新编译。

(4)复用实现部分。由于实现部分所处的层次较低,因此可以被多种业务模块复用。例如,数据库访问模块可以用在多种业务单元中。

2.2.    抽象工厂

1、概述

提供一个创建一系列相关或互相依赖的对象的接口,而无须指定其具体的类。

2、使用场合

(1)一个系统要独立于其产品的创建、组合和表示时。

(2)一个系统要由多个产品系列中的一个来配置时。

(3)需要提供一个产品类库,而只想显示它们的接口,而隐藏其实现时。

2.3.    工厂方法模式

1、概述

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到子类,这个接口所指的是一个抽象方法。该方法说明需要创建一个对象,但并不给出具体的创建方法和创建什么类型的对象。

工厂方法是粒度很小的设计模式,因为模式的表现只是一个抽象的方法。工厂方法经常用于创建与某个类相关的类的实例,.NET中的数据库连接对象就是产生数据命令对象的工厂,其中的CreateCommand方法就是工厂方法,其结构如图所示。

在IDbConnection中定义了产生IdbCommand对象的工厂方法CreateCommand,具体的Command对象由具体的Connection对象创建。它与具体的数据库相关,不同数据库创建不同类型的Command对象。

IdbConnection定义了CreateCommand的接口: IdbConnectio CreateCommad( );具体的Connection类中定义了对应的实现,例如针对Oracle数据库:

       public OracleCommand CreateCommand( );

2、使用场合

当一个类不知道它所必须创建对象的类或一个类希望由子类来指定它所创建的对象时,可以使用工厂方法。

2.4.    简单工厂

1、概述

简单工厂的作用是实例化对象,而不需要客户了解这个对象属于哪个具体的子类。

在GOF的设计模式中并没有简单工厂,而是将其作为工厂方法的一个特例加以解释。可以这样理解,简单工厂是参数化的工厂方法。

2、使用场合

简单工厂实例化的类具有相同的接口,类类有限并且基本不需要扩展时,可以使用简单工厂。例如,数据库连接对象,常用的数据库类类可以预知,则使用简单工厂。

3、使用效果

采用简单工厂的优点是可以使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性;缺点是可实例化的类型在编译期间已经被确定,如果增加新类型,则需要修改工厂。简单工厂需要知道所有要生成的类型,当子类过多或者子类层次过多时不适合使用。

2.5.    反射工厂

1、概述

如果采用传统方式实现了简单工厂、工厂方法和抽象工厂在有些场合下如此处理,代码会变得冗余并且难以维护。

假设我们需要创建一种交通工具,可以是汽车、火车或者轮船,结构如图所示。

有没有可能将需要创建类的类型传递到工厂方法中,由工厂方法根据类型返回相应的实例?

解决这个问题的关键是需要动态决定需要创建的类,这不是设计模式能解决的问题属于软件平台的功能范畴。.NET可以提供相应的功能,即反射技术。

2、使用效果

使用反射工厂的优点是极大地减少了工厂类的数量、降低了代码的冗余,并且系统更容易扩展,在增加新类型后,不需要修改工厂类。

使用反射工厂的代价是工厂与产品之间的依赖关系不明显,由于是动态绑定,因此理论上可以用一个工厂完成很多类型的实例化,从而使得代码不容易理解。另外增大了测试难度,创建是动态完成的,测试用例的编写和测试执行要比传统的工厂困难。

2.6.    生成器模式

1、概述

将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。需要注意如下几点。

(1)构建与表示分离:表明生成器模式的结构,构建过程被封装在导航器中,生成器则负责实现具体的表示。

(2)同样的构建过程:生成器模式关注的是构建过程,即构建过程是相同的。

(3)不同的表示:生成器模式并不在意产生对象的结果,其构造的产品不一定有相同的类型。

2、使用场合

创建复杂对象的算法应该独立于该对象的组成部分及其装配方式,以及构造过程必须允许被构造的对象有不同表示情况下使用生成器模式。

2.7.    原型模式

1、概述

采用原型模式是将已经存在的对象作为原型,用户可以通过复制这些原型创建新的对象。

.NET中的很多类支持原型模式。例如我们希望获得一个与现有数据集结构相同的数据集,即可采用克隆的方法:ds.Clone

注意,与数据相关的类还有一个方法Copy。与克隆不同,该方法不仅复制对象的结构,还复制对象中包含的数据,例如,我们希望复制现有数据集的结构和数据,则采用该方法: ds.Copy

2、使用场合

当一个系统应该独立于产品的创建、构成和表示时,可以使用原型模式。在原型模式中,产品的创建和初始化在类的Clone方法中完成。在使用时,我们可以用一些列原型对象来代替生成相应对象的工厂对象,并且可以使拷贝、粘贴等操作独立于需要复制的对象。

3、使用效果

(1)在运行时增加或删除产品:只要通过客户原型实例即可将新产品类型增加到系统中,例如组态软件中工具箱中的每个工具可以对应一个注册的原型对象,可以通过增加原形对象扩展工具箱。
(2)很容易地创建复杂的对象:在图形编辑和组态等软件中,经常需要创建复杂的图元。这些图元是由简单图元组成的,采用原型模式可以很容易地将复杂图元作为一般图元来使用,使软件的工具箱具有自扩展功能。
(3)减少工厂的层次:由于在.NET中可以使用反射工厂,因此这个优势并不明显。

使用原型模式的缺点是在有些情况下克隆功能不容易实现,特别是遇到对象的循环引用时。

2.8.    单件模式

1、概述

单件模式保证应用只有一个全局惟一的实例,并且提供一个访问它的全局访问点。

单件模式的结构非常简单,包括防止其他对象创建实例的私有构造函数、保存惟一实例的私有变量和全局访问接口等。

2、使用场合

当类只能有一个实例存在,并且可以在全局访问时。这个惟一的实例应该可以通过子类实现扩展,并且用户无须更改代码即可使用。

前面介绍的工厂类经常被实例化为全局惟一的单件,可能的单件还有管理日志的对象、关键字生成对象和外部设备接口对象等。

3、使用效果

单件提供了全局惟一的访问入口,因此易于控制可能发生的冲突。

单件是对类静态函数的一种改进,首先它避免了全局变量对系统的污染;其次农业经济可以有子类,可以定义虚函数,具有多态性。而类中的静态方法是不能定义为虚函数的,因此不具有多态性。

单件模式可以扩展为多件,即允许有受控的多个实例存在。

2.9.    适配器模式

1、概述

使接口不兼容的类能够协同工作。通常情况下,这些接口不兼容的类在逻辑上的功能是一致或者相似的。例如采用RS232协议和TCP/IP的目的都是为了传输数据,支持这两种协议的API却是截然不同的。

适配器有类适配器和对象适配器两种类型,二者的意图相同,只是实现的方法和适用的情况不同。类适配器采用继承来实现,对象适配器则采用组合的方法来实现。

.NET中的适配器——DataAdapter

ADO.NET为统一的数据访问提供了多个接口和基类,其中最重要的接口之一是IdataAdapter。与之相对应的DataAdpter是一个抽象类,它是ADO.NET与具体数据库操作之间的数据适配器的基类。DataAdpter起到了数据库到DataSet桥接器的作用,使应用程序的数据操作统一到DataSet上,而与具体的数据库类型无关。甚至可以针对特殊的数据源编制自己的DataAdpter,从而使我们的应用程序与这些特殊的数据源相兼容。

2、使用场合

(1)需要使用一个已经存在的类,但接口与设计要求不符。

(2)希望创建一个可以复用的类,该类可以与其他不相关的类或者是将来不可预见的类协同工作。

在使用适配器时应注意理解适配器的方向性,即注意区分适配器中的Adaptee(适配对象)和Target(目标),在适配器的原理图中很容易看出Target,即被客户操作的是目标。

2.10.        外观模式

1、概述

外观模式定义了一个将子系统的一组接口集成在一起的高层接口,以提供一个一致的界面。通过这个界面,其他系统可以方便地调用子系统中的功能,而忽略子系统内部发生的变化。

2、使用场合

(1)为一个比较复杂的子系统提供一个简单的接口。

(2)将客户程序与子系统的实现部分分离,提高子系统的独立性和可移植性。

(3)简化子系统间的依赖关系。

3、使用效果

外观模式为用户提供了使用子系统组件的简化的接口,使用户减少了处理对象的数目,并且使子系统使用简单。

使用外观模式使子系统和客户之间实现松耦合关系,由于客户针对其接口编程,因此子系统的变化不会影响客户的变化,即其有助于分层体系结构的实现。

外观模式并没有限制客户使用子系统类,仍可以直接使用子系统中的类。

2.11.        装饰模式

1、概述

装饰模式是在不改变对象的前提下,动态增加其功能,即我们不希望改变原有的类,或采用创建子类的方法增加功能,这种情况下需要采用装饰模式。

修饰一个对象后,其接口不应该发生变化;否则这个对象不能被原有调用者使用,修饰失去了意义。由此引出了装饰模式结构最重要的一点,即装饰者和被装饰者具有相同的接口。换句话说,动态增加的功能不应该破坏已有的接口。

2、使用场合

(1)在不影响其他对象的情况下,以动态且透明的方式添加单个对象的功能。

(2)处理那些可以撤销的功能。

(3)不能采用生成子类的方法扩充时。

3、使用效果

使用装饰模式的优点是比静态继承灵活,并可避免在层次结构高层的类有太多的特征;缺点是产生许多小对象。

3.       .net多层架构设计

3.1.    三层架构介绍

目前,在典型的三层架构中,对层次各自的职责划分并没有一个统一的规范,综合现有的成功实践和.NET平台的特殊性,将三层架构的职责划分如下:

数据访问层——负责与数据源的交互,即数据的插入、删除、修改以及从数据库中读出数据等操作。对数据的正确性和有效性不负责,对数据的用途不了解,不负担任何业务逻辑。

业务逻辑层——负责系统领域业务的处理,负责逻辑性数据的生成、处理及转换。对流入的逻辑性数据的正确性及有效性负责,对流出的逻辑性数据及用户性数据不负责,对数据的呈现样式不负责。

表示层——负责接收用户的输入、将输出呈现给用户以及访问安全性验证。对流入的数据的正确性和有效性负责,对呈现样式负责,对流出的数据正确性不负责,但负责在数据不正确时给出相应的异常信息。
模块划分及交互设计:

实体类模块——一组实体类的集合,负责整个系统中数据的封装及传递。

数据访问层接口族——一组接口的集合,表示数据访问层的接口。

业务逻辑层接口族——一组接口的集合,表示业务逻辑层的接口。

数据访问层模块——一组类的集合,完成数据访问层的具体功能,实现数据访问层接口族。

业务逻辑层模块——一组类的集合,完成业务逻辑层的具体功能,实现业务逻辑层接口族。

表示层模块——程序及可视元素的集合,负责完成表示层的具体功能。

辅助类模块——完成全局辅助性功能。

3.2.    三层架构项目实战

项目整体展示

业务逻辑层方法类

业务逻辑层类基本成员方法

数据访问层类方法

3.3.    功能较完整的架构代码生成器—动软代码生成器

批量代码生成主要界面如下

生成的工厂模式项目架构截图如下

 

4.       .NET平台下敏捷开发架构代码分析

摘要:为适应快速多变的需求,提高系统开发的效率,缩短开发周期,本文提出了一种基于.NET平台的敏捷化开发N层架构。

运用强类型数据集进行各层之间的数据传递并利用.NET平台提供的命令构造器和XML架构定义工具结合参数替换的方法实现了各层代码的自动生成,最后结合具体项目验证了这一构架的敏捷性及有效性。

4.1.    引文

近年来,随着.NET技术的日臻完善,.NET平台已发展成为能与JAVA平分天下的开发平台,因此对.NET平台下多层架构的研究也逐渐得到人们的关注,越来越多的研究者开始转向.NET平台下软件架构的研究,与之相关的代码自动生成技术成为该领域的研究热点之一。目前,将一些传统的设计模式进行改造、融入某种思想以及基于某种技术是体系结构发展的主要方式,例如:崔清华采用B/S结构,基于.NET平台,提出了一种新的新型办公自动化平台;吴宏森利用MVC设计架构思想结合.NET平台及WebService技术提高了系统的维护性和可扩展性;为适应动态需求和实现需求到设计的映射,曹敢提出了基于目标和模式的软件体系结构;庄亮在.NET平台上将Facade设计模式引入N层架构的设计,提高了多人分层开发的效率;根据当前软件开发的现状和发展趋势,本文提出了一种基于.NET平台的敏捷化开发架构,并研究了针对这一架构的代码自动生成技术。

4.2.    敏捷开发系统架构

客户需求的多变性和系统间集成的异构性使得人们对传统的三层结构在扩展性、低耦合性以及代码自动生成方面提出了更高的要求,一些针对三层架构的商业化代码生成工具也应运而生,例如CodeSmith,Codematic2等,这些工具可以根据数据库设计方案生成对应的存储过程、查询语句、类文件等,从很大程度上提高了系统开发的效率。由于这些工具具备很大的通用性,这就限制了其代码生成自动化的程度,在很多情况下,仍然需要人工添加一些辅助代码。事实上,对于一个给定的模式及对应的框架,是可以提高其代码自动化程度。为降低系统间集成难度,提高系统的松耦合程度及代码自动生成效率,本文提出了如下的敏捷化开发架构。

该架构由公共数据层(CommonData)、公共方法层(Common-Function)、用户界面层(UI)、业务外观层(BusinessFacade)、业务规则层(BusinessRule)、数据外观层(DataAccessDF)、数据扩展层(DataAccessDE)、数据访问层(DataAccessD)和数据连接层(DataAccessCommon)构成。各层功能如下:

(1)数据连接层(DataAccessCommon):该层负责数据库连接及连接池的管理,例如针对不同类型的数据库,构建对应的数据连接字符串等操作。

(2)数据访问层(DataAccessD):数据库中每一张实体表将根据需求,在该层中映射为一个实体类,该实体类包含针对这张表的数据查询和操作函数。因此该层是直接与数据库交互的层之一;该层的数据库连接来自于数据连接层。

(3)数据扩展层(DataAccessDE):该层中所有的类都继承与数据访问层中的实体类,该层的功能在于满足对各种查询需求,特别是一些需要调用存储过程或构造查询条件的复杂查询操作,也包括一些统计函数的构建。

 (4)数据外观层(DataAccessDF):该层负责启动数据操作事物,并提交事物,当操作失败时,还必须进行相应的回滚处理及抛出错误。对于一些较为复杂的数据更新流程(往往涉及到多表同

时更新),其操作必须在该层中进行,需要指出的是,该层用于启动事务的连接,也来自数据连接层。

(5)业务规则层(BusinessRule):该层负责对业务规则的处理,例如对于优化问题,目前常用的启发式算法或仿真算法都可以放置在这一层;这一层也是数据外观层与业务外观层的桥梁。

(6)业务外观层(BusinessFacade):该层上接用户界面层,下连业务规则层;主要承接界面层传递下来的数据查询、更新等方面的请求,同时对数据格式进行校验;对于数据查询请求,将直接调用数据扩展层相应的函数,对于数据更新方面的请求则调用业务规则层内相应的函数。

(7)用户界面层(UI):该层主要接收用户输入的信息,对输入信息进行校验,根据将信息封装进强类型数据集中,并将数据传入业务外观层。

(8)公共数据层(CommonData):该层存储了所有的强类型数据集的类型文件,由于.NET平台提供的强类型数据集具有封装性强、数据类型校验等优势,因此各层之间的数据传递,主要以强类型的数据集为主。

(9)公共方法层(CommonFunction):该层主要是对文件序列化存储函数、正则表达式的匹配函数、数据格式转化等一些公用函数的管理。因此该层中的函数广泛应用在从用户界面至数据扩展层中。各层之间的依赖关系如下表所示。

4.3.    代码自动生成原理

随着计算机技术的不断进步,应用软件的自动生成趋势,使得行业类软件向着实现简单、设计方便的方向发展。事实上,无论业务规则如何变化,最终都将反映在对数据的操作上,顶层所有的操作都将映射为对底层数据的查询及更新操作,因此实现对数据操作代码的自动生成是实现其他各层代码的基础,这包含三个方面的内容:(1)强类型数据集的自动生成;(2)数据访问组件定义及调用代码的自动生成;(3)数据操作语句(DML)的自动生成;为此本文提出一种参数替换结合CommandBuilder及XML架构定义工具的代码自动生成方法。CommondBuilder是.NET框架内的命令构造器,通过在运行时动态指定SelectCommand(查询命令)的方式,CommandBuilder可以自动生成对应的增加、删除、更新SQL语句。由于不同类型的数据库,数据类型名称各不相同,甚至SQL语句也有所区别(T-SQL和PL-SQL),因此采用CommandBuilder在保证代码生成质量的同时也可以提高代码自动生成的效率。XML架构定义工具(xsd.exe)可以根据数据表的字段信息及约束信息生成强类型数据集,代码生成器结构如下图所示。

代码生成器由5个相对独立的层组成:数据对象层、信息获取层、代码构造层、代码组装层和代码文件层。信息获取层从数据对象层中获取实体表及字段等相关信息,并将获取的数据结构信息传递给代码构造层,代码构造层中的命令构造器和XML架构定义工具根据数据结构生成数据访问代码和强类型数据集代码,再根据数据库类型应用参数替换规则,生成完整的代码段;代码组装层将生成的代码段根据组装规则进行组装,生成最终的代码文件。需要指出的是,开发人员可以通过设定自定义属性,来控制代码文件的生成路径、代码文件的类型及并发控制的类型。

代码生成器界面如图3所示。

开发人员可以选择数据表及代码层,以便生成对应层的代码文件。在生成路径方面,可以设定自动匹配路径使得代码文件直接生成在对应的文件夹中。实践表明,在系统开发初期,敏捷化开发平台可以快速构建一个完整的系统框架,并满足基本的数据操作要求;在系统开发中期,由于需求的变化可能导致数据结构局部的微调,运用代码生成器可以迅速的将改动反应到系统中,最大程度降低了数据结构变动对系统开发产生的影响。

4.4.    4实例验证及应用

本文提出的敏捷化开发架构及代码生成技术已应用于国防基础科研项目“数控生产车间数字化工程研究”。该项目系统开发环境采用.NET2003ASP.NET,后台数据库为Oracle9i,B\C\S混合结构,实现了计算机辅助刀具设计、计算机辅助刀具库存管理及计算机辅助加工仿真、计算机辅助工艺管理、设备信息管理及能力评价系统、数控车间调度系统等信息系统的开发和系统间的集成。通过运用敏捷化开发结构并配合代码自动生成器的使用,项目开发时间大大缩短,同时保证了代码的质量,由于各个子系统都基于该架构进行开发,系统集成难度以及维护成本都有一定程度的降低。

4.5.    总结及展望

提出的基于.NET平台的敏捷化架构具有良好的可扩展性,尤其适合需要系统间集成的大型项目的开发。强类型数据集作为各层数据传递的主要媒体,使得整个系统在对象与数据展现之间的转化开销相对减少,并且能很好的处理批量对象的更新。.NET平台的命令构造器及XML架构定义器,保证了代码生成的质量及效率。下一步工作是研发Web界面的代码自动生成技术,由于Web界面涉及HTML的元素,其生成过程和其他层的代码有所区别,同时还要考虑对输入数据的正确性校验以及一些业务上的数据呈现。

本文创新点:提出了一种基于.NET的敏捷化开发平台,利用强类型数据集作为各层之间数据传递的载体,并使用命令构造器和XML构架定义工具基于参数替换的思想开发了适用于该平台的代码自动生成器。

 

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭