基于UML和ASP.NET实现三层B/S结构学籍管理系统开发
架构设计是软件开发的基础,并往往决定一个项目的成败。三层结构是目前流行的架构设计模式,它是在由Buschmann等提出的“层模式”[1]基础上发展起来的,由表示层、业务逻辑层和数据访问层三个层次结构组成。它通过分解来管理问题的复杂性,同时还可以有效地重复使用业务逻辑并保留与昂贵资源(如数据库)的重要连接[2,3]。
基于ASP.NET能够充分发挥其完全面向对象的技术特点,实现三层结构B/S系统架构,从而提高开发效率,增强系统的可维护性和扩展性。本文结合一个“学生成绩管理系统”的开发,研究如何基于UML进行三层B/S结构的系统建模,及其在ASP.NET下的应用实现。
1 三层结构系统模型
架构设计是非常高级的设计,也是系统设计的关键,主要是定义和说明包(子系统),以及包与包之间的相互依赖与通信机制。系统构架模型的合理与否将决定系统的可维护性、扩展性和开发效率。
包通常所需要处理的是要么是一个具体的功能区域(业务逻辑),要么是一个具体的技术区域(技术逻辑)。业务逻辑主要考虑的是对系统业务功能的实现,而技术逻辑则是进一步考虑用户界面、数据库或通信机制等形成的技术方案。把技术逻辑和业务逻辑区分开来是极其重要的,这是为了当修改程序的某一部分时不会对另一部分产生影响,更加便于进行“复用”,同时易于应对来自业务逻辑的变更需求。
三层结构是一种成熟、简单并得到普遍应用的应用程序架构,它将应用程序结构划分三层独立的包,包括用户表示层、业务逻辑层、数据访问层。其中将实现人机界面的所有表单和组件放在表示层,将所有业务规则和逻辑的实现封装在负责业务逻辑组件中,将所有和数据库的交互封装在数据访问组件中。其结构如下图1所示:
图1 三层结构示意图
三层结构是一种严格分层方法,即数据访问层只能被业务逻辑层访问,业务逻辑层只能被表示层访问,用户通过表示层将请求传送给业务逻辑层,业务逻辑层完成相关业务规则和逻辑,并通过数据访问层访问数据库获得数据,然后按照相反的顺序依次返回将数据显示在表示层。
2 三层B/S结构的学生管理系统开发
下面通过一个学生管理系统的开发,说明三层B/S结构系统从UML建模到基于ASP.NET进行实现的完整开发过程,UML建模工具采用的是Rational Rose。
2.1 需求分析
软件需求分析是系统开发的第一步也是最重要的一个环节,其基本任务是准确地回答“系统做什么?”这个问题,这需要在对用户需求进行充分调研的基础上,深入理解并描述出软件的功能、性能、接口等方面的需求,可以使用UML建模作为需求分析和系统设计的有效方法。
分析的目的是为了获得和描述系统中所有的要求,因此分析阶段是一种典型的与用户或客户合作的过程,通常由开发人员同用户或客户共同完成。在这个阶段,开发人员不应该考虑代码或程序实现的细节,而应该把精力放在对现有业务逻辑的理解上,通过与用户之间的充分沟通,逐步理解并描述出得到用户确认的系统模型,包括用例模型和领域(domain,系统中关键的类)模型。
2.1.1 用例模型
软件开发人员在对用户进行需求调研的过程中,用户往往并不能立即准确描述出未来系统应该提供一些什么样的功能。因此,需要开发人员理解和分析需求,并将系统应该具有的功能通过用例图直观的描述出来,方便用户理解并做出评判,开发人员从而可以根据用户的反馈不断调整用例模型,直至完全正确、充分描述清楚系统功能。
用例建模主要是分离出系统的活动参与者(Actor)和用例(Use Case),用例是指对系统提供的功能的一种描述,而活动参与者是那些可能使用这些用例的人或外部系统,通过用例图可以描述出系统外部的执行者、系统的用例,以及它们之间的联系。本学生管理系统的用例图见图2。
用例模型还需要进一步对每个用例进行详细描述,进一步说明用例的名称、基本事件流和备选事件流、前置条件和后置条件等,并形成文档。限于篇幅,这里就不多说了。
图2 用例图
2.1.2 领域建模
分析过程中还要详细地列举领域(domain ,系统中关键的类),为了进行领域分析,需要充分理解用例模型,也可以与用户及领域专家组织一次集体研讨会谈,尝试找出所有必须处理的关键概念以及它们之间的相互关系,并最终分析出域类图。下图3为本系统的域类图。
图3 域类图
需要强调的是:在本阶段,对领域进行分析的类图还是处于“草图”状态。定义的操作和属性不是最后的版本,只是在本阶段看来比较合适。后期将通过动态行为分析不断得出新的操作,这是一个逐步完善和发展的过程。
2.2 系统设计
系统设计的目的是产生一个可用的、完整的解决方案,并且能够比较容易地将方案转换成程序代码。这个阶段在三层结构的架构设计模型基础上,将考虑所有的实现技术问题,对分析阶段的模型进行扩展和细化,分析阶段定义的类进一步扩充,定义新的类来处理技术方面的问题,并形成最后的UML模型。
推动不断进行详细设计的方法是对每个用例进行动态建模,描述如何通过类图中的对象协作实现用例中的功能,由于一开始对系统的认识是很不够的,前面建立的类往往随着动态建模的深入,发现存在缺陷或不够完整,需要对分析中得到的域类图进行不断修正和调整,扩展形成业务逻辑包。同时,随着对用户界面、数据库访问等技术实现的深入建模,不断建立新的用户界面类(如窗体、控件)和数据访问类,形成用户界面包和数据访问包。
本学生管理系统经过详细设计后,在域类图基础上进行扩展后形成的业务逻辑包类图如下图4所示。
图4 业务逻辑包类图
新建立的数据访问包类图如下图5所示。所有的数据访问类都定义了一个基类DBCommon,该基类包含属性DBConnectionString,通过该属性可以获得数据库连接字符串。还包括一个方法GetDataView,可以实现在数据库中执行查询获得一个DataView。这些属性和方法被所有的数据访问类继承,可以直接使用。
图5 数据访问包
关于用户界面包的类图比较简单,主要是通过界面设计,设计出窗体及控件等界面元素,并根据动态建模时需要涉及的用户界面访问动作,定义所引起的相关事件,这些方面都在窗体类中进行定义,并组成用户界面包,这里就不详细介绍。
动态建模通常采用的方法是使用UML中的时序图描述用例,一个时序图针对某个用例中的一个“场景”进行分析。所谓“场景”是指一个用例中事件发展的一条路线。根据活动参与者的不同输入或行为,通常一个用例会有多个“场景”,也就需要分析出多个时序图。通过时序图描述一个场景中各个对象之间所进行的通信,同时可以分析出系统中相应的类需要具备的操作,从而不断扩充和细化类的设计。如果需要进一步描述类的状态变化情况和操作流程,可以使用UML中的状态图和活动图。
图6 登录场景
动态建模时产生的时序图较多,这里无法一一阐述。图6给出了登录系统场景的时序图,在用户界面包中定义了一个LoginForm类,其对应的Web窗体为用户登录窗体页面Login.aspx,图6描述了在该窗体中实现用户登录的场景。
2.3 基于ASP.NET的系统实现
前面系统设计动态模型时,通过时序图已经对每个用例的各项功能所涉及的场景进行了详尽的描述,按照时序图的规定把每个用例都分别进行编码实现即可。下面结合学生管理系统中的“登录系统”用例,介绍基于ASP.NET进行系统实现的方法。
首先需要考虑分包,ASP.NET中包对应的就是命名空间。在本学生管理系统中,规定业务逻辑包的命名空间为ResultManage.BusinessRule,数据访问包的命名空间为ResultManage.DataAccess,而用户界面包的命名空间为ResultManage.Web。
然后进行业务逻辑包和数据访问包中相关类的设计,对于“登录系统”用例,从上图6的登录场景时序图中可以看出,相关的类有业务逻辑包的Users类和数据访问包的UsersDB类,分别对这些类的属性和方法进行定义和实现,并设计一些测试用例或测试程序对其进行单元测试。
最后按照用户界面包和上图6的登录场景时序图中的规定,对用户登录窗体页面Login.aspx进行设计实现,其实现登录的代码如下所示:
private void btnLogin_Click(object sender, System.EventArgs e) { //获得用户登录信息 string UserName = txbUserName.Text; string Password = txbPassword.Text; try { if (Users.Login(UserName , Password)) //检查用户登录信息 { //创建身份验证票 FormsAuthentication.SetAuthCookie(UserName, false); //显示欢迎信息 ShowWelcomeMessage(UserName); } else { Message.Text = "用户登录失败!"; } } catch (SqlException sqlexception) { //提示数据库操作错误信息 Response.Write(sqlexception.Message); } } 代码中对于业务的处理,通过调用业务逻辑包Users类的Login方法实现登录信息的检查,其代码如下: public static bool Login(string UserName , string Password) { if (UserName == "") { return false; } else { //检查数据库中是否存在符合的用户 return UsersDB.CheckLogin(UserName , Password); } } |
上述Users类的Login方法的代码中,首先进行业务逻辑检查,判断用户名是否为空,涉及数据库访问则通过数据访问类完成,通过数据访问包的UsersDB类的CheckLogin方法从数据库中检查是否存在符合相应登录信息的用户。
前面已经提到,包括UsersDB类在内的数据访问层所有类都从一个基类DBCommon继承,该基类封装了所有数据库访问类公共的特性,其中包括定义了公共属性:数据连接字符串DBConnectionString。UsersDB类的CheckLogin方法中使用DBConnectionString进行数据库的连接,并调用数据库中存储过程CheckLogin查找用户登录信息是否正确。
3 结束语
本文介绍了三层B/S结构系统的UML建模和基于ASP.NET进行实现的过程和方法,实现的三层结构不仅程序逻辑上结构清晰,而且由于容易发生需求变更的业务逻辑部分实现了分离,因此具有更强的可扩展性和可维护性。同时这种系统在部署时具有很强的灵活性,可以将各个包分别编译成.NET组件,安装在多台服务器。较典型的是用户界面包安装在Web服务器,业务逻辑包安装在应用服务器,数据访问包安装在数据库服务器或进一步分离,从而实现多级分布的部署方式,实现更好的可伸缩性和安全性,满足大规模的企业级B/S应用系统的需求。