zoukankan      html  css  js  c++  java
  • 浅谈三层架构中的实体类(C#)

             最近因为三层架构中的实体类,引发了不少小问题,下面列举一下,谈谈自己的感想。

             本文所指的实体类仅限于三层中的实体类,即数据库表的映射。

     

    一、为什么要用实体类?

     

             |  使程序简洁易懂,便于维护。

             |  暗合接口不变原则。

             |  体现面向对象思想。

     

            举例说明:

     

             不用实体类的三层



            假如程序有所变动,需要增加一个参数,学生年龄


            用实体类的三层


            同样增加一个参数,学生年龄


             很明显的看出,用实体类之后,代码明显变得简洁,面向对象封装思想。

             最重要的是,如果将来有所改动,只需要改动实体类,方法间调用接口,完全不需要变动,大大减少了程序修改量,迎合了面向对象中接口不变的思想。

             甚至在程序设计时,就把将来可能需要的属性预先放在实体类中,这样以后变动时,连实体类都不用变动。

     

    二、实体类缺点在哪(仅是个人观点)?

     

             虽然实体类有明显的优势,但亲身使用时会发现一个明显的问题:代码可读性貌似降低了。

             上边例子中体现的不是很明显。再来一个简单的例子。

             假如有一个方法(没有用实体类):

             selectByPartDate(DateTime startDate,DateTime endDate){}

             此方法用来查询某段时间内的记录,两个参数:一个是起始时间,一个是结束时间。

             虽然没有用实体类,可是让人看起来很舒服,一看就知道要干什么。

             用了实体类后(假设实体类名是LoginLog):

             selectByPartDate(LoginLog startDate, LoginLog endDate){}

             让人看了不知所措,难以理解到底想做什么。

             当然,这种不知所措可以通过两个途径解决:

             |  良好的命名规范,达到 “见名知意”。

             |  良好的文档说明或者代码注释。

     

             在这,引出一个问题:三层中,所有的方法都要用实体类传递参数吗?

             最明显的就是上边selectByPartDate例子,还有诸如:deleteByID(longid){}这样的方法。真的有必要传递实体类吗?

             实体类的确是容易扩展、修改,可这不违反设计原则吗?

             设计原则是:尽量避免对原有代码的修改,而是通过增加代码的方式去解决。

             诸如selectByPartDate、deleteByID这样的方法,目的已经很明确了:查询某段时间内的记录、根据id删除记录。换句话说,这就是它们存在的意义。

             程序再怎么扩展,能涉及到这类方法?假如真的把这类方法扩展了,那么它们完全失去了自己的意义!

             deleteByID就是根据id删除,扩展了,就不是根据id删除了!这时候你可以再添加一个新的方法,何必和deleteByID过不去呢?

             对于参数极少,目的明确的方法,个人认为没必要用实体类。

             这只是我的个人看法,欢迎高人指点!

            

    三、源自实体类的灵感!

     

             三层中,大家都知道U层的逻辑应该尽量少,尽可能的转移到B层。

             但是实际应用中如何转移却是个问题。

             就拿删除记录来说,U层调用B层,B层调用D层,由D层返回布尔值,来说明删除是否成功。

             这样传递参数,最终U层得到的是一个布尔值,真或假,携带的信息太少了,只能反馈给用户成功或者失败(同时多了一次判断逻辑),而为什么失败,就无从得知了。

             现实应用中有很多这样的例子,有时候为了给出用户更详细的提示,不惜把B层分的很细,然后在界面大量的调用B层方法,加上大量的判断,才能给用户一个完整的提示。

             这样的情形显然不是我们想要的?那么怎么解决呢?

             造成这种情况的根本原因就是布尔型返回值携带的信息太少,哪个类型多?当然是字符串型!

             在D层,可以返回布尔值,让B层判断使用。但是B层返回给U层的值,强烈反对是布尔型的!

             按照这个思路,在B层使用复杂的逻辑,然后把执行结果以字符串的形式的返回。这样一来,U层无需任何判断,直接把B层返回的字符串显示出来就行了!

             举个例子(B层的一个方法):

    public string deleteMail(string domainName, Mail mail) 
    {
        try
        {
            //删除POP3服务器中的邮箱
            CMDHelper cmdHelper = new CMDHelper();
            string cmdString = "";
            cmdString = cmdHelper.execute("DEL " + mail.mailName + "@" + domainName + " /DELETEUSER");
            if (cmdString.ToLower().IndexOf("successfully") >= 0) //删除成功
            {
                //同步数据库
                IMailDAO mailDAO = creater.createMailDAO();
                if (mailDAO.deleteByID(mail))
                {
                    return "删除成功!数据库同步成功!";
                }
                else
                {
                    return "删除成功!但数据库同步失败!";
                }
            }
            else if (cmdString.IndexOf("系统找不到指定的文件") >= 0) //不存在
            {
                return "该邮箱不存在!";
            }
            else
            {
                return "未知原因错误!请联系管理员!";
            }
        }
        catch (Exception ex) 
        {
            throw ex;
        }
    }

             很明显的看出,一切判断都是在B层完成的,然后把结果以字符串形式返回给U层,简洁明了,U层不需要任何逻辑,直接show就行了!

             这样看上去很好,但是字符串还是比较让人不舒服,既然是面向对象,为何不返回一个实体类呢?

             我们可以定义一个实体类,名字就叫LayerParameter。给这个实体类加一个字符串型的resultString属性,就把刚刚的字符串返回值封装进来了。就用这个实体类作为B层给U层的返回值。

             这样做简直完美!

             有经验的朋友可能遇到过刷新界面的问题,也就是U层需要根据实际情况来刷新界面数据,在B/S结构中尤其明显。有了实体类做返回值,就啥都不怕了!不就是刷新吗?在LayerParameter实体类中加一个布尔型属性refresh,U层调用B层后,show一下返回值(LayerParameter类实例)的resultString属性,把执行信息告诉用户,然后再判断一下refresh属性,决定是否刷新界面数据(U层一点逻辑都没有是不可能的!),此时B层给U层的返回值,仍然是LayerParameter,接口无需任何改动。

             以上仅仅是个人想法,希望大牛指点!

     

             最后,申明一点:

             一切的一切还是要以项目实践为基础,经验才是王道,否则一切讨论都是空穴来风!

  • 相关阅读:
    《Code Complete》ch.18 表驱动法
    libevent I/O示例
    Unity3d 与 Objective-C 数据交互,持续更新中
    progress 相关事件 异步 ajax
    数据结构chapter01_C++基础
    vue环境搭建
    时间复杂度和空间复杂度
    linux内核数据结构之链表
    linux内核数据结构之kfifo
    c++ iterator(迭代器)分类及其使用
  • 原文地址:https://www.cnblogs.com/iyangyuan/p/2801815.html
Copyright © 2011-2022 走看看