实战剖析三层架构

引言:本文不是从理论的角度来探讨三层架构,而是用一个示例来介绍如何建设一个三层架构的项目,并说明项目中各个文件所处的层次与作用。写本文的目的,不是为了说明自己的这个方法有多对,别人的肯定不对,而是希望给那些初学三层架构却不知从何入手的朋友提供一点帮助。因为网上的文章,大多是注重理论的介绍,而忽略了具体的实践应用,或者有示例但讲得不透彻。导致看了之后,理论上又学习了一遍,但还是不知道代码怎么写。所以想从这个方面入手写一下,让从来没做过三层架构的初学者也能照猫画虎,写出代码来。文章表述的是笔者个人对三层架构的认识,肯定有许多不足的地方,欢迎大家指正,小弟也会根据反馈来修改这篇文章。文中的代码是伪代码,仅用来阐明思路。
    正文:
    一提三层架构,大家都知道是表现层(UI),业务逻辑层(BLL)和数据访问层(DAL),而且每层如何细分也都有很多的方法。但具体代码怎么写,到底那些文件算在哪一层,却是模模糊糊的。下面用一个简单的例子来带领大家实战三层架构的项目,这个例子只有一个功能,就是用户的简单管理。
    首先建立一个空白解决方案,添加如下项目及文件
    1、添加ASP.NET Web Application项目,命名为UI,新建Web Form类型文件User.aspx(含User.aspx.cs
    2、添加ClassLibrary项目,命名为BLL,新建Class类型文件UserBLL.cs
    
3、添加ClassLibrary项目,命名为DAL,新建Class类型文件UserDAL.cs。添加SQLHelper引用。(这个是微软的数据访问类,也可以不用,直接编写所有的数据访问代码。我一般用自己写的数据访问类DataAccessHelper )。
    4、添加ClassLibrary项目,命名为Model,新建Class类型文件UserModel.cs
    5、添加ClassLibrary项目,命名为IDAL,新建Interface类型文件IUserDAL.cs
    6、添加ClassLibrary项目,命名为ClassFactory
    相信大家已经看出来了,这个和Petshop的示例没什么区别,而且更简单,因为在下也是通过Petshop学习三层架构的。但一些朋友对于这几个项目所处的层次,以及它们之间的关系,可能比较模糊,这里逐个说明一下:
    1User.aspxUser.aspx.cs
    这两个文件(以及文件所属的项目,下面也是如此,不再重复强调了)都属于表现层部分。User.aspx比较好理解,因为它就是显示页面了。User.aspx.cs有些人觉得不应该算,而是要划到业务逻辑层中去。如果不做分层的话,那么让User.aspx.cs来处理业务逻辑,甚至操作数据库都没什么问题,但是做分层的话,这样就不应该了。在分层结构中,User.aspx.cs仅应该处理与显示有关的内容,其它部分都不应该涉及。
    举例:我们实现用列表方式显示用户的功能,那么提取信息的工作是由BLL来做的,UI(本例中是User.aspx.cs)调用BLL得到UserInfo后,通过代码绑定到User.aspx的数据控件上,就实现了列表的显示。在此过程中User.aspx.csUI没有起到什么作用,仅是用来传递数据,而且因为实际编码中大部分情况都是如此的实现,所以使有些人觉得User.aspx.cs不应该算UI,而应该并入BLL负责逻辑处理。继续往下看,这时提出了一个新需求,要求在每个用户的前面加一个图标,生动地表现出用户的性别,而且不满18岁的用儿童图标表示。这个需求的实现,就轮到User.aspx.cs来做了,这种情况下User.aspx.cs才算有了真正的用途。
    2NewBLL.cs
    添加如下方法:
    public IList<UserInfo> GetUsers():返回所有的用户信息列表
    public UserInfo GetUser(int UserId):返回指定用户的详细信息
    public bool AddUser(UserInfo User):新增用户信息
    public bool ChangeUser(UserInfo User):更新用户信息
    public void RemoveUser(int UserId):移除用户信息
    此文件就属于业务逻辑层了,专门用来处理与业务逻辑有关的操作。可能有很多人觉得这一层唯一的用途,就是把表现层传过来的数据转发给数据层。这种情况确实很多,但这只能说明项目比较简单,或者项目本身与业务的关系结合的不紧密(比如当前比较流行的MIS),所以造成业务层无事可做,只起到了一个转发的作用。但这不代表业务层可有可无,随着项目的增大,或者业务关系比较多,业务层就会体现出它的作用来了。
    此处最可能造成错误的,就是把数据操作代码划在了业务逻辑层,而把数据库作为了数据访问层。
    举例:有些朋友感觉BLL层意义不大,只是将DAL的数据提上来就转发给了UI,而未作任何处理。看一下这个例子
    BLL
    SelectUserUserInfo userInfo)根据传入的usernameemail得到用户详细信息。
    IsExistUserInfo userInfo)判断指定的usernameemail是否存在。
    然后DAL也相应提供方法共BLL调用
    SelectUserUserInfo userInfo
    IsExistUserInfo userInfo
    这样BLL确实只起到了一个传递的作用。
    
但如果这样做:
    BLL.IsExistUserinfo userinfo
    {
          UerInfo user = DAL.SelectUserUser);
        
return (userInfo.Id != null); 
    }
    那么DAL就无需实现IsExist()方法了,BLL中也就有了逻辑处理的代码。
    3UserModel.cs
    实体类,这个东西,大家可能觉得不好分层。包括我以前在内,是这样理解的:UIßàModelßàBLLßàModelßàDAL,如此则认为Model在各层之间起到了一个数据传输的桥梁作用。不过在这里,我们不是把事情想简单,而是想复杂了。
    Model是什么?它什么也不是!它在三层架构中是可有可无的。它其实就是面向对象编程中最基本的东西:类。一个桌子是一个类,一条新闻也是一个类,intstringdoublie等也是类,它仅仅是一个类而已。
    这样,Model在三层架构中的位置,和intstring等变量的地位就一样了,没有其它的目的,仅用于数据的存储而已,只不过它存储的是复杂的数据。所以如果你的项目中对象都非常简单,那么不用Model而直接传递多个参数也能做成三层架构。
    那为什么还要有Model呢,它的好处是什么呢。下面是思考一个问题时想到的,插在这里:    
    Model
在各层参数传递时到底能起到做大的作用?
    在各层间传递参数时,可以这样:
    AddUseruserIduserNameuserPassword,)
    也可以这样:
    AddUseruserInfo
    这两种方法那个好呢。一目了然,肯定是第二种要好很多。
    什么时候用普通变量类型(int,string,guid,double)在各层之间传递参数,什么使用Model传递?下面几个方法:
    
SelectUserint UserId
    SelectUserByNamestring username
    SelectUserByNamestring usernamestring password
    SelectUserByEmailstring email
    
SelectUserByEmailstring emailstring password
    可以概括为:
    SelectUseruserId
    SelectUseruser
    这里用user这个Model对象囊括了usernamepasswordemail这三个参数的四种组合模式。UserId其实也可以合并到user中,但项目中其它BLL都实现了带有id参数的接口,所以这里也保留这一项。 
    传入了userInfo,那如何处理呢,这个就需要按照先后的顺序了,有具体代码决定。
    这里按这个顺序处理
    首先看是否同时具有usernamepassword,然后看是否同时具有emailpassword,然后看是否有username,然后看是否有email。依次处理。
    这样,如果以后增加一个新内容,会员卡(number),则无需更改接口,只要在DAL的代码中增加对number的支持就行,然后前台增加会员卡一项内容的表现与处理即可。 
    4UserDAL.cs
    public IList<UserInfo> SelectUsers():返回所有的用户信息列表
    public UserInfo SelectUser(int UserId):返回指定用户的相信信息
    public bool InsertUser(UserInfo User):新增用户信息
    public bool UpdateUser(UserInfo User):更新用户信息
    public void DeleteUser(int UserId):移除用户信息
    很多人最闹不清的就是数据访问层,到底那部分才算数据访问层呢?有些认为数据库就是数据访问层,这是对定义没有搞清楚,DAL是数据访问层而不是数据存储层,因此数据库不可能是这一层的。也有的把SQLHelper(或其同类作用的组件)作为数据访问层,它又是一个可有可无的东西,SQLHelper的作用是减少重复性编码,提高编码效率,因此如果我习惯在乎效率或使用一个非数据库的数据源时,可以丢弃SQLHelper,一个可以随意弃置的部分,又怎么能成为三层架构中的一层呢。
    可以这样定义:与数据源操作有关的代码,就应该放在数据访问层中,属于数据访问层
    5IUserDAL
    数据访问层接口,这又是一个可有可无的东西,因为Petshop中带了它和ClassFactory类工厂,所以有些项目不论需不需要支持多数据源,都把这两个东西做了进来,有的甚至不建ClassFactory而只建了IDAL,然后“IUserDAL iUserDal = new UserDAL();”,不知意义何在。这就完全是画虎不成反类犬了。
    
许多人在这里有一个误解,那就是以为存在这样的关系:BLLßàIDALßàDAL,认为IDAL起到了BLLDAL之间的桥梁作用,BLL是通过IDAL来调用DAL的。但实际是即使你如此编码:“IUserDAL iUserDal = ClassFacotry.CreateUserDAL();”,那么在执行“iUserDal.SelectUsers()”时,其实还是执行的UserDAL实例,而不是IUserDAL实例,所以IDAL在三层中的位置是与DAL平级的关系。
    通过上面的介绍,基本上将三层架构的层次结构说明了。其实,本人有一个判断三层架构是否标准的方法,那就是将三层中的任意一层完全替换,都不会对其它两层造成影响,这样的构造基本就符合三层标准了(虽然实现起来比较难^_^)。例如如果将项目从B/S改为C/S(或相反),那么除了UI以外,BLLDAL都不用改动;或者将SQLServer改为Oracle,只需替换SQLServerDALOracleDAL,无需其它操作等等。本来想在文中加入一些具体的代码的,但感觉不是很必要,如果大家觉得需要的话,我再补充吧。
    总结:不要因为某个层对你来说没用,或者实现起来特别简单,就认为它没有必要,或者摒弃它,或者挪作它用。只要进行了分层,不管是几层,每一层都要有明确的目的和功能实现,而不要被实际过程所左右,造成同一类文件位于不同层的情况发生。也不要出现同一层实现了不同的功能的情况发生。

转载于:https://www.cnblogs.com/sier/archive/2011/10/12/5676434.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263132.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动态代理的事务封装

在上篇博客中介绍了使用ThreadLocal维护Connection的方法&#xff0c;这样做的最大的优点就是不用来回的传递Connection了&#xff0c;可是我们有会发如今我们使用事务的时候不可避免的会写很多反复的代码&#xff0c;这些都是与业务逻辑无关的&#xff1a; Connecti…

EF 从sqlserver2008 迁移到 2005出现的BUG

在VS10Server08中使用EF4.4&#xff0c;发布数据库为SQL05&#xff0c;发生错误的问题 问题描述环境描述&#xff1a;工具为VS2010SQL08 R2&#xff0c;EntityFramework版本为4.4&#xff08;在Framework4.5中为5.0&#xff09;&#xff0c;在本机完全测试完成后&#xff0c;发…

[新闻]Ubuntu7.04于4月19日全球同步发布

[新闻]Ubuntu7.04于4月19日全球同步发布!!!鼓掌欢迎,准备更新!!!http://www.ubuntu.com/转载于:https://www.cnblogs.com/cime63/archive/2007/04/19/720131.html

解决Docker构建时出现的 WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.13/main: Permission denied

解决Docker构建时出现的 WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.13/main: Permission denied在根据官网的Docker-compose构建示例项目时遇到的问题&#xff0c;原因是因为无法访问官网给出的外网镜像&#xff0c;可能还会出现WARNING: Ignoring https://…

可耻的客户端,可怕的征兆,必须趁早消灭它

最近在我的Android手机上安装一个小软件&#xff0c;不知为何&#xff0c;顶部的消息提示有软件推荐&#xff0c;最开始还以为是某些软件的更新提示&#xff0c;于是点击一次&#xff0c;却发现直接安装该软件。当时我感到非常愤怒。真是一个可耻的程序员做了一个可耻的客户端&…

Table还是CSS,请您说说您的见解

这两天在对网页进行排版&#xff0c;可是觉得Table总是很烦&#xff0c;后来使用CSS&#xff0c;可是CSS也有CSS的问题&#xff0c;无论是什么好像都不能十全十美。请朋友们发现您的意见&#xff0c;您觉得如何&#xff1f; 转载于:https://www.cnblogs.com/edrp/archive/2007/…

Google Android开发精华教程

Android是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称&#xff0c;该平台由操作系统、中间件、用户界面和应用软件组成&#xff0c;号称是首个为移动终端打造的真正开放和完整的移动软件。本文汇总整理了时下关于Google Android技术教程的下载资源&…

转盘不转动的问题

2019独角兽企业重金招聘Python工程师标准>>> Stack Overflow is a question and answer site for professional and enthusiast programmers. Its 100% free, no registration required. jQuery Rotate - IE7 & IE8 Issues up vote 11 down vote favorite 3 I a…

主机无法连接虚拟机中的redis服务

解决&#xff1a;主机<本地>无法连接虚拟机中的redis服务首先保证虚拟机网络已经和主机网络互通&#xff0c;即相互ping对方IP&#xff0c;能ping通但是仍然连不上redis服务&#xff0c;可能是以下问题。redis服务配置问题 配置redis.conf如下 protected-mode no #关闭…

重构机房收费系统(二)

接上篇《机房收费系统重构&#xff08;一&#xff09;》 二、概要设计 完成了用例图&#xff0c;并用结合用例图完善了一下需求分析说明书&#xff0c;忘记是第几次修订需求分析说明书。有了用例图&#xff0c;很自然就进入了概要设计阶段。我认为这一阶段就是结合包图解决系统…

VS 2005 安装一个的小问题

今天通过 添加/删除 安装了VC的部分功能之后&#xff0c;在 程序》Visual Studio 2005 》Visual Studio 2005 Tools 里面竟然找不到 ActiveX Control Test Container 了&#xff0c;但是却有 Spy和 MFC-ATL Trace Tool&#xff0c;建了MFC ActiveX功能在IDE里面 工具 菜单中也找…

《Windows核心编程》学习笔记(9)– 在win7或者vista系统下提升一个进程的运行权限...

win7或者vista默认运行程序是在受限制的环境下运行的&#xff0c;以减轻病毒对于系统的破坏。那么我们怎样才能提升一个进程的权限以至让它在 管理员模式下运行。当然CreateProcess函数没有提供这个功能。相反我们需要调用的是ShellExecuteEx函数&#xff1a; BOOL ShellExecu…

2015第29周二AOP

1、问题&#xff1a;想要添加日志记录、性能监控、安全监测 2、最初解决方案2.1、最初解决方案&#xff1a;在每个需要的类函数中重复写上面处理代。 缺点&#xff1a;太多重复代码&#xff0c;且紧耦合2.2、抽象类进行共性设计&#xff0c;子类进行个性设计&#xff0c;此处不…

Docker-compose配置Mysql,Redis,MongoDB

Docker-compose下配置Mysql&#xff0c;Redis&#xff0c;MongoDB详解一、docker-compose简介二、构建一个实例项目1.前后端实现2.Dockerfile及docker-compose.yml3. 生成镜像三、实例程序源码一、docker-compose简介 Compose是用于定义和运行多容器Docker应用程序的工具。通过…

初学者应该了解的一些SQL语句及hr 用户解锁相关

初学者应该了解的一些SQL语句 1.显示当前连接用户SQL> show user&#xff1b; 2.查看系统拥有哪些用户SQL> select * from all_users; 3.连接到新用户SQL> conn 用户名/密码 4.查询当前用户下所有对象SQL> select * from tab; 5.建立第一个表SQL> create table …

用Delphi 6开发ASP上传组件详解

文件上传是WEB开发中经常要用到的功能&#xff0c;但ASP本身和内置的组件都不支持文件上传功能。网上流传的一些第三方组件虽然能够解决这个问题&#xff0c;但大多是要收费的&#xff0c;更别说Open Source了。本文将详细剖析WEB文件上传的原理&#xff0c;以及一步步指导读者…

使用WebDeployment Project改善VS2005发布网站问题

VS2005发布网站时不会像VS2003一样生成规则的DLL文件、而生成的DLL文件名含有随机数且不能一个项目生成一个DLL文件、让人有一些遗憾、为了做到像vs2003一样&#xff0c;微软发布了WebDeployment Project插件可解决此问题&#xff1a;下载地址1、下载后安装、右键选择vs2005中的…

03 - const static extern

const是一个C语言的关键字&#xff0c;它限定一个变量不允许被改变。使用const可以在一定程度上提高程序的安全性和可靠性&#xff0c;再者在看别人的代码作品的时候也可以有助于清晰理解const所起的作用。 1、const和#define的区别 &#xff08;1&#xff09;编译器处理的方式…

Linux、Windows、Mac下Docker的安装与使用

Linux、Windows、Mac下Docker的安装与使用一、Linux下的安装二、Windows与Mac下的安装三、Docker的使用一、Linux下的安装 这里以Centos 7为例&#xff0c;首先&#xff0c;确保系统已经正确运行了Centos 7并已经联网。yum安装gcc环境 yum -y install gcc yum -y install gcc…

[智能架构系列]什么是Buddy智能开发框架

buddy框架&#xff0c;秉承国内优秀框架THINKPHP的优点并增加了很多的商业特性和集成了全版本的商业项目模块&#xff0c;提供给创业者一个最好的选择 组建图: 转载于:https://www.cnblogs.com/scotoma/archive/2011/10/17/2215553.html