http://www.cnblogs.com/yukaizhao/archive/2007/03/08/layer_develop_errors.html

三层开发中容易犯的错误

前记:

相信大家对三层开发都已经耳熟能详,可是我却发现新公司的既有代码中有一些违背分层开发思想的东西,现在与大家分享这些错误,我们共勉之。

如果有人觉得对三层开发拿捏得不是太准,请参照李天平的文章:分层开发思想与小笼包,这篇文章用隐喻说明分层开发,是非常好的一篇文章。

正文:

1.界面层参与非界面逻辑,抢业务逻辑层的饭碗

什么是界面逻辑:

界面层应该有的逻辑就是显示的逻辑,例如根据逻辑结果显示某一个Panel不显示另外一个Panel,或者有一个数据集应该在界面上怎么呈现,这是界面层的逻辑

例子场景:

用户登录时首先验证用户输入的用户名是否有效,如果用户名有效,然后再验证用户输入的密码是否和用户名匹配,如果匹配则表示用户可以登录,增加用户的登录次数,然后将用户的信息写入Session中;否则返回错误。在这个过程中除了将用户信息写入Session这一步属于界面逻辑以外其他的操作都应该放在业务逻辑层。

错误代码示例:

private void buttonLogin_Click(object sender, EventArgs ev)
        {
            string userName = textBoxUserName.Text;
            string password = textPassword.Text;

            if (Business.Account.Exists(userName))
            {
                bool success = Business.Account.Login(userName, password);
                if (success)
                {
                    Business.Account.AddLoginTime(userName);

                    Session["user"] = new User(userName, password);
                    Redirect("/");
                }
                else
                {
                    this.labelMessage.Text = "登录失败。";
                }
            }
            else
            {
                this.lableMessage.Text = "用户名不存在。";
            }
        }

分析:在上面的代码中一个UI层的一个事件中调用了三次rules层的方法:

Business.Account.Exists(userName)

Business.Account.Login(userName, password)

Business.Account.AddLoginTime(userName);

还附加有条件判断,这种方法在执行效果上面是没有什么错误的,可是却造成了逻辑前移;本来应该在逻辑层执行的判断放在了界面层,是不合适的。

2.数据访问层参与了大量的业务逻辑

这种现象经常出现在大量使用存储过程的系统中,将一大堆逻辑统统放在一个存储过程中实现了,乍一看可能很有效率,其实造成了系统结构的失调,给维护带来困难,数据访问层甚者数据库要抢逻辑层的饭碗了。

还以用户登录为例:

下面是业务逻辑层的登录方法:

//业务逻辑层的登录方法
        public int Login(string userName, string password) 
        {
            return DataAccess.UserAccount.Login(userName, password);
        }

下面是数据层的登录方法:

//数据访问层的登录方法
        public int Login(string userName, string password)
        
            SqlParameter[] parameters = new SqlParameter[]{
                // 
            };
            return SqlHelper.ExecuteProcedure("Login",parameters);
        }

下面是登录的存储过程:

CREATE PROC Login
            @userName varchar(20),
            @password varchar(20)
         AS 
            IF NOT EXISTS(SELECT * FROM UserAccount WHERE UserName = @userName)
                RETURN -1
            IF NOT EXISTS(SELECT * FROM UserAccount WHERE UserName = @userName AND password = @password)
                RETURN 1
         
            UPDATE UserAccount
            SET LoginTimes = LoginTimes + 1
            WHERE UserName = @userName
         
            RETURN 0

分析:从上面三段代码中我们可以很显然得看到登录的业务逻辑已经全部被后移到了数据库的存储过程中。这样使用的三层结构就失去了意义,逻辑层名存实亡了;而数据库的压力会越来越大;我们修改业务逻辑的时候不是到逻辑层修改,而是要到数据库中去修改了。

3.将界面层上的数据组件(如SqlDataSource)作为参数传递到业务逻辑层去赋值

这样做的坏处很明显,本来是界面层依赖于业务逻辑层的,现在业务逻辑层反过来去依赖界面层的类,需要逻辑层引用System.Web命名空间,显然是错误的。

4.为了省事儿,不是直接将参数传递到业务逻辑层,而是通过HttpContext直接获得界面层应该传递的参数

例子:在系统设计的初期没有记录用户登录的IP地址,而到了后期发现了这个问题,要求纪录用户IP了,为了不修改业务逻辑层方法的定义,也不用修改界面层的调用方法,于是便写出了下面的代码:

public int Login(string userName, string password)
        {
            string userIP = System.Web.HttpContext.Current.Request.UserHostAddress;
            //follow is login steps
        }

这一点犯的错误和3中的错误相同,导致层之间形成了依赖环。

5.将事务处理放在数据访问层来做

事务处理应该放在业务逻辑层处理,原因是

1)事务的划分是根据业务逻辑来定义的,通常一个事务就代表完成了一个完整的逻辑操作;

2)一个业务逻辑可能有几个数据操作,修改几个表中的数据,而通常数据层的类的划分是根据数据库表来划分的,如果把事务处理放在数据访问层,那么业务层的方法需要调用两个以上的数据层方法时,就会出现执行两个事务的情况,显然这是不合理的。

总结:

1.在三层结构的划分中我们应该使三层各负其责,谁也不能越权,谁也不能懒惰,通常情况下,逻辑层应该在满足各负其责的条件下,尽可能的厚。

2.三层结构中的依赖关系很明确,界面层依赖于逻辑层,逻辑层依赖于数据访问层,不能互相依赖,而形成依赖环。

转载于:https://www.cnblogs.com/smallfa/archive/2007/07/18/822420.html

三层开发中容易犯的错误相关推荐

  1. javascript中易犯的错误有哪些

    javascript中易犯的错误有哪些 一.总结 一句话总结: 比如循环中函数的使用 函数中this的指向谁(函数中this的使用) 变量的作用域 1.this.timer = setTimeout( ...

  2. 网站设计中常犯的错误

    平面 | 包装 | 广告 | 环艺 | 工业 | 网页 | 服装 | 数码 | 摄影 | 绘画 | 人才 | 论坛 | 沙龙 | 字体 首页 网页资讯 网页作品 酷站欣赏 设计文章 网页沙龙 我的空间 ...

  3. 5个golang中易犯的错误

    点击上方蓝字关注我们 To err is human,to forgive divine. -Alexander Pope 初学golang我们经常会犯一些错误,虽然它们不会产生类型检查的异常,但是它 ...

  4. 开发中常见的低级错误--被自己气哭

    开发中常见的低级错误--被自己气哭 前言 踩过的坑 请求路径写错 用生产地址测试本地代码 看错项目 变量名拼错 提交了相似分支 复制粘贴的分支逻辑忘记改过来 数据库存储超限制后会被自动截断 再会 前言 ...

  5. [转] 三层开发中的层次划分

        先举一个曾经在哪本书上看到的例子:现在你想在1米宽的小溪上建一座桥,你会在上面放块木板就完了.如果想在宽一点的小河上建这桥,你就需要计算木材用料,价格等,如果需要别人帮忙,你还要多一些图纸什么 ...

  6. C语言中常犯的错误(一)

    程序出错有三大类:语法错误.逻辑错误和运行错误 对于语法错误,编译器会给出精确到行的提示:逻辑错误则需要在流程图的辅助下,重点关注留意花括号,进行判定:而运行错误则是指程序在接收到某些数据时因为处理不 ...

  7. 前端中容易犯低级错误的地方

    由于自己基础比较薄弱,也可以说知识的深度不够,在写前端代码的时候,往往会出现这样那样的低级问题,以及低级错误,在这里我总结出来了,还是那句话,大神可以绕道了 1.关于页面中js文件和css文件的位置( ...

  8. Xamarin.Android 开发中遇到旋转屏幕错误

    错误信息 : System.NotSupportedException: Unable to find the default constructor on type App5.MyFragment. ...

  9. C语言指针学习中易犯的错误

    1.向null地址处copy数据 char *str = NULL; strcpy(str,"aaaaabbbbb"); 错误! NULL是操作系统保护的空间,不能往里面拷贝数据: ...

最新文章

  1. window mysql安全设置_mysql安全配置方案
  2. SAP WM 确认TO单据的时候修改目的地Storage Bin
  3. 计算机英语文章阅读网站,关于电脑的英语美文阅读
  4. Google工程师:如何看待程序员普遍缺乏数据结构和算法知识?
  5. 一步一步实现iOS QQ第三方登录
  6. antd 中table上加不同字体颜色_字体渲染系统!微软终于决定优化Win10字体模糊问题...
  7. Timus Online Judge:ural:1006. Square Frames
  8. 阿尔法大蛋智能机器人功能_智能机器人怎么选?阿尔法蛋大蛋2.0助力孩子新学期...
  9. delphi7升级delphi2007可以互用马_马爹利鼎盛周末饭局暂停营业,未来再见
  10. 分治比赛选手循环问题
  11. Python封装的获取文件目录的函数
  12. .NET利用委托实现动态查询
  13. LeetCode刷题——11. 盛最多水的容器
  14. 面试题之Spring工作原理
  15. TensorFlow2学习笔记:3、鸢尾花数据集载入
  16. LVGL V8之Animation timeline
  17. 网线简介及交换机原理和模式浅谈
  18. 计算机网络ip地址划分计算机,计算机网络IP地址协议、分类、子网掩码
  19. 远程控制PLC实际案例——西门子SIMATIC S7-1200
  20. CAD图层亮度的设置

热门文章

  1. linux 串口控制read()的说明
  2. java web 柱状图_使用JFreeChart实现基于Web的柱状图
  3. accessdeniedexception: 不允许访问_一招解决JDK9以上非法反射访问警告
  4. 阿里云IoT何云飞:智物Cloud AIoT Native 为何能让设备智能更快一步
  5. 技术干货 | 阿里云数据库PostgreSQL 13大版本揭秘
  6. 阿里 双11 同款流控降级组件 Sentinel Go 正式GA,云原生服务稳稳稳
  7. 字节跳动 Flink 单点恢复功能实践
  8. 5G改变物联网解决方案的6种方式
  9. 从《无主之地3》探讨,为什么刷子游戏能让玩家心甘情愿的肝硬化
  10. 基于RadeonRays的光线追踪全局光照实现方案