基于.NET平台的分层架构实战(一)——综述2008-06-1620:29byEricZhang(T2噬菌体),9802visits,网摘,收藏,编辑通过浏览博客园的文章发现,很多朋友对分层架构特别感兴趣,刚好我刚做完的毕业设计就是专门研究.NET平台上分层架构的(题目叫“基于.NET平台的分层架构与设计模式应用研究”)。通过做这篇论文,我对分层架构有了一定的了解,所以,就萌发了想写一个文章系列,详述一下分层架构。然而,论文的理论性太强,不适合在网上发布,尤其不适合初学者理解,所以,我想在这个文章系列中,少讲理论,而是通过做一个完整的案例来讨论分层架构的基本方法,这样会直观很多。希望在这个文章系列的写作过程中,能和朋友们一起学习,一起进步。为了让朋友们把主要精力放在理解分层架构而不是案例本身,我准备选择一个相对简单的留言本系统作为Demo,这个系统的名字就叫做NGuestBook。初步计划将这个文章系列分为以下几篇:1.综述2.系统需求分析及数据库设计3.架构概要设计4.实体类的实现5.接口的设计与实现6.依赖注入及IoC的设计与实现7.数据访问层的第一种实现——Access+动态生成SQL语言8.数据访问层的第二种实现——SQLServer+存储过程9.数据访问层的第三种实现——基于NBear框架的ORM实现10.业务逻辑层的实现11.表示层的实现当然,以上只是初步计划,在写文章的过程中可能会根据具体情况适当调整,但是内容大体就是这些。这个文章系列不会对所用到的技术进行详细讲解,具体请参考相关文献,阅读文章前最好能对以下技术有一个了解:1.C#语言2.ASP.NET3.设计模式4.关系数据库基础知识5.软件架构基本原则与软件工程基础知识6.基于NBear框架的ORM技术7.JavaScript,Ajax8.ASP.NETAJAX框架(特别是客户端编程)9.HTML,CSS,标准化布局另外,本文章系列是基于.NETframework2.0框架平台进行讨论,3.5平台的新特性(如LINQ、ASP.NETMVC等)不会讨论,IDE使用VisualStudio2005,数据库会用到SQLServer2005Express和Access2003。基于.NET平台的分层架构实战(二)——需求分析与数据库设计2008-06-1709:05byEricZhang(T2噬菌体),8611visits,网摘,收藏,编辑在实际的项目中,需求分析和数据库的设计是很重要的一个环节,这个环节会直接影响项目的开发过程和质量。实际中,这个环节不但需要系统分析师、软件工程师等计算机方面的专家,还需要相关领域的领域专家参与才能完成。但是,在这个文章系列中,所要使用的Demo仅仅是一个例子,而且其业务极为简单,因此,这里并不是真正的需求分析和数据库设计,而是将Demo的需求和数据库罗列至此,使朋友们对Demo有一个大体的了解,方便后续文章中开发过程的理解。需求分析:这个项目是一个留言本,其业务极为简单,现将其描述如下。1.任何访问者可以进行留言,留言完成后,不会立即显示正文,而是要经过管理员验证后才可显示。2.任何访问者可以对留言发表评论,未通过验证的留言不可以评论。3.管理员可以对留言进行回复(这个回复不同于评论,是直接显示在正文下面,而且是一个留言只能有一个回复),并可对留言与评论实行删除,以及对留言进行通过验证操作。4.管理员分为超级管理员和普通管理员。超级管理员只有一个,负责对普通管理员实行添加、删除操作。普通管理员可偶多个,负责对留言的管理,并可以修改自己的登录密码。这个项目的用例图如下:图2.1、NGuestBook的用例图数据库设计:设计数据表之前,首先进行实体和关系的识别与确定。通过需求分析,可以观察得出,本项目的实体有:管理员(不包括超级管理员),留言,评论。本项目的关系有:留言与评论间的一对多关系。进一步,数据库各表的设计如下:管理员表(TAdmin)IDint管理员IDNotNull主键,自增Namevarchar(20)登录名NotNullPasswordvarchar(50)登录密码NotNull使用MD5加密留言表(TMessage)IDint留言IDNotNull主键,自增GuestNamevarchar(20)留言者用户名NotNullGuestEmailvarchar(100)留言者E-mailNullContenttext留言内容NotNullTimedatetime发表留言时间NotNullReplytext回复NullIsPassvarchar(10)是否通过验证NotNull评论表(TComment)IDint评论IDNotNull主键,自增Contenttext评论内容NotNullTimedatetime发表评论时间NotNullMessageIDint所属留言的ID外键作者:T2噬菌体出处:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。本文基于署名-非商业性使用3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名张洋(包含链接),且不得用户商业目的。如您有任何疑问或者授权方面的协商,请与我联系。基于.NET平台的分层架构实战(三)——架构概要设计2008-06-1710:25byEricZhang(T2噬菌体),8619visits,网摘,收藏,编辑本文主要是对将要实现的架构进行一个总体的描述,使朋友们对这个架构有个宏观上的认识。这篇文章理论性的东西会偏多一点,从下篇开始,将进行实际项目的开发。这篇文章的许多内容摘自我的毕业论文。架构基本原则:这里,将描述一些在这个架构设计中的基本原则,其中很多都是经典的设计原则,不过针对分层架构的特点,用我自己的语言进行了描述。其中也有我自己提出的原则。逐层调用原则及单向调用原则现在约定将N层架构的各层依次编号为1、2、…、K、…、N-1、N,其中层的编号越大,则越处在上层。那么,我们设计的架构应该满足以下两个原则:1.第K(1K=N)层只准依赖第K-1层,而不可依赖其他底层。2.如果P层依赖Q层,则P的编号一定大于Q。其中第一个原则,保证了依赖的逐层性,及整个架构的依赖是逐层向下的,而不能跨层依赖。第二个原则,则保证了依赖的单向性,及只能上层依赖底层,而不能底层反过来依赖上层。针对接口编程,而不是针对实现编程这里所指的接口,不是特指编程语言中的具体语言元素(如C#中由Interface定义的语言接口),而是指一种抽象的,在语义层面上起着接合作用语义体。它的具体实现,可能是接口,可能是抽象类,甚至可能是具体类。我认为,从不同的视角,接口可以有以下两种定义:1.接口是一组规则的集合,它规定了实现本接口的类或接口必须拥有的一组规则。体现了自然界“如果你是……则必须能……”的理念。2.接口是在一定粒度视图上同类事物的抽象表示。注意这里我强调了在一定粒度视图上,因为“同类事物”这个概念是相对的,它因为粒度视图不同而不同。具体到N层架构中,针对接口编程的意义在部分上是这样的:现仍约定将N层架构的各层依次编号为1、2、…、K、…、N-1、N,其中层的编号越大,则越处在上层,那么第K层不应该依赖具体一个K-1层,而应该依赖一个K-1层的接口,即在第K层中不应该有K-1层中的某个具体类。依赖倒置原则在软件设计原则中,有一种重要的思想叫做依赖倒置。它的核心思想是:不能让高层组件依赖底层组件,而且,不管高层组件和底层组件,两者都应依赖于抽象。那么,这个原则和我们上面的原则是否矛盾呢?其实并不矛盾。因为这个原则定义中的“依赖”是指“具体依赖”,而上面定义中的依赖全部指“抽象依赖”。我对这两种依赖的定义如下:具体依赖——如果P层中有一个或一个以上的地方实例化了Q层中某个具体类,则说P层具体依赖于Q层。抽象依赖——如果P层没有实例化Q层中的具体类,而是在一个或一个以上的地方实例化了Q层中某个接口,则说P层抽象依赖于Q层,也叫接口依赖于Q层。从这两个定义可以看到,所谓的依赖倒置原则,正是上面提到针对接口编程,而不是针对实现编程,两者在本质上是统一的。综上所述,可以看出,本课题设计的分层架构,应该是这样一种架构:1.N层架构的各层依次编号为1、2、…、K、…、N-1、N,其中层的编号越大,则越处在上层。2.架构中仅存在一种依赖,即第K层接口依赖第K-1层,其中1K=N。封装变化原则封装变化的原则定义为:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混杂在一起。开放-关闭原则开发-关闭原则定义为:对扩展开放,对修改关闭。具体到N层架构中,可以描述为:当某一层有了一个新的具体实现时,它应该可以在不修改其他层的情况下,与此新实现无缝连接,顺利交互。单一归属原则在这个架构中,任何一个操作类都应该有单一的职责,属于单独的一层,而不能同时担负两种职责或属于多个层次(实体类及辅助类可以被多个层使用,但它们不属于任何一个层,而是独立存在)。层次划分:目前,典型的分层架构是三层架构,即自底向上依次是数据访问层、业务逻辑层和表示层。这种经典架构经历了时间的考验和实践的多次检验,被认为是合理、有效的分层设计,所以,在本文中,将沿袭这种经典架构,使用数据访问层、业务逻辑层和表示层的三层架构体系。职责划分:目前,在典型的三层架构中,对层次各自的职责划分并没有一个统一的规范,综合现有的成功实践和.NET平台的特殊性,在本文中将三层架构的职责划分如下:数据访问层——负责与数据源的交互,即数据的插入、删除、修改以及从数据库中读出数据等操作。对数据的正确性和有效性不负责,对数据的用途不了解,不负担任何业务逻辑。业务逻辑层——负责系统领域业务的处理,负责逻辑性数据的生成、处理及转换。对流入的逻辑性数据的正确性及有效性负责,对流出的逻辑性数据及用户性数据不负责,对数据的呈现样式不负责。表示层——负责接收用户的输入、将输出呈现给用户以及访问安全性验证。对流入的数据的正确性和有效性负责,对呈现样式负责,对流出的数据正确性不负责,但负责在数据不正确时给出相应的异常信息。模块划分及交互设计:综合以上分析,可在宏观上将整个系统分为一下几个模块:实体类模块——一组实体类的集合,负责整个系统中数据的封装及传递。数据访问层接口族——一组接口的集合,表示数据访问层的接口。业务逻辑层接口族——一组接口的集合,表示业务逻辑层的接口。数据访问层模块——一组类的集合,完成数据访问层的具体功能,实现数据访问层接口族。业务逻辑层模块——一组类的集合,完成业务逻辑层的具体功能,实现业务逻辑层接口族。表示层模块——程序及可视元素的集合,负责完成表示层的具体功能。IoC容器模块——负责依赖注入的实现。辅助类模块——完成全局辅助性功能。各模块间交互关系如下:图3.1、总体架构图本文基于署名-非商业性使用3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名张洋(包含链接),且不得用户商业目的。如您有任何疑问或者授权方面的协商,请与我联系。基于.NET平台的分层架构实战(四)——实体类的设计与实现2008-06-1815:15byEricZhang(T2噬菌体),8435visits,网摘,收藏,编辑实体类是现实实体在计算机中的表示。它贯穿于整个架构,负担着在各层次及模块间传递数据的职责。一般来说,实体类可以分为“贫血实体类”和“充血实体类”,前者仅仅保存实体的属性,而后者还包含一些实体间的关系与逻辑。我们在这个Demo中用的实体类将是“贫血实体类”。大多情况下,实体类和数据库中的表(这里指实体表,不包括表示多对多对应的关系表)是一一对应的,但这并不是一个限制,在复杂的数据库设计中,有可能出现一个实体类对应多个表,或者交叉对应的情况。在本文的Demo中,实体类和表是一一对应的,并且实体类中的属性和表中的字段也是对应的。在看实体类的代码前,先看一下系统的工程结构。图4.1、工程结构图如上图所示