小弟有这样一个方法,按页大小和页索引查询产品,如下。
        /// <summary>
        /// 获取产品
        /// </summary>
        /// <param name="manufacturerID">厂商ID,为null时不做查询条件。</param>
        /// <param name="categoryID">类别ID,为null时不做查询条件。</param>
        /// <param name="typeID">类型ID,为null时不做查询条件。</param>
        /// <param name="name">产品名称,模糊匹配。</param>
        /// <param name="description">描述,模糊匹配。</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="pageIndex">页索引</param>
        /// <returns></returns>
        public DataTable GetProduct(int? manufacturerID, int? categoryID, int? typeID, string name, string description, int pageSize, int pageIndex)
        {
           ......
        }
可以看到小弟这个方法参数比较多,有7个,这时有人就说了:“这么多参数,应该封装成一个对象传递!”要写成下面这个样子。
    public class QueryProduct
    {
        private int? manufacturerID;        /// <summary>
        /// 厂商ID,为null时不做查询条件。
        /// </summary>
        public int? ManufacturerID
        {
            get { return manufacturerID; }
            set { manufacturerID = value; }
        }        private int? categoryID;        /// <summary>
        /// 类别ID,为null时不做查询条件。
        /// </summary>
        public int? CategoryID
        {
            get { return categoryID; }
            set { categoryID = value; }
        }        private int? typeID;        /// <summary>
        /// 类型ID,为null时不做查询条件。
        /// </summary>
        public int? TypeID
        {
            get { return typeID; }
            set { typeID = value; }
        }        private string name;        /// <summary>
        /// 产品名称,模糊匹配。
        /// </summary>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }        private string description;        /// <summary>
        /// 描述,模糊匹配。
        /// </summary>
        public string Description
        {
            get { return description; }
            set { description = value; }
        }        private int pageSize;        /// <summary>
        /// 页大小
        /// </summary>
        public int PageSize
        {
            get { return pageSize; }
            set { pageSize = value; }
        } 
        
        private int pageIndex;        /// <summary>
        /// 页索引
        /// </summary>
        public int PageIndex
        {
            get { return pageIndex; }
            set { pageIndex = value; }
        }
    }            /// <summary>
        /// 获取产品
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <returns></returns>
        public DataTable GetProduct(QueryProduct query)
        {
            ......
        }
小弟心里就想了 ,这才几个参数,连10个都不到,封装成一个对象有必要吗?下面是各自对问题的看法应该封装成对象:
1.不封装成对象,代码看起来很乱。
2.可维护性强,以后这个方法如果需要加查询参数,只需要在QueryProduct类中增加一个属性即可,方法不用改。
3.方法的参数越少越好,能少一个,绝不多一个。
4.方法的参数超过3个就要封装成对象。应该直接传递参数:
1.直接将查询条件写在方法参数上,可读性强,便于后来人维护。
2.封装成对象,项目中就需要增加一个对象,对象越多,越不利于维护,10个以内的参数,如果没有特殊原因,不需要封装成对象。
3.这里的参数每一个都有业务意义,并不是要持久化到数据库的实体属性,在数量不多的时候,不应该封装成对象。下面是小弟对“应该封装成对象”一派3个理由的回复
1.不封装成对象,代码看起来很乱。
一点都不乱,封装成对象反倒增加了阅读成本。
2.可维护性强,以后这个方法如果需要加查询参数,只需要在QueryProduct类中增加一个属性即可,方法不用改。
可维护性绝对没有增强,反倒因为项目中多了一堆查询条件对象,增加了阅读成本,降低了维护性。当增加查询条件时,改了查询对象的定义,方法的参数就变了,方法也100%的变了,只是方法的代码没改,但方法的定义已经改了,这完全没有优势。都是改代码,都是改方法的参数,都改变了方法的定义。
3.方法的参数越少越好,能少一个,绝不多一个。
这里没有一个参数是多余的,少任何一个参数都不能满足需求,方法的参数越少越好是毋庸置疑的,但绝不是用这种坑爹的方式减少参数。
4.方法的参数超过3个就要封装成对象。
是否要将参数封装成对象,不能只看参数的数量,还要看它的业务意义,作为数据载体的实体类,即使只有两个属性,也要用对象传递。但像这种,不需要持久化,而且每个参数都有各自的业务意义,没有特殊原因,就应该写在方法的参数列表里。关于这个问题,小弟希望看看大家是怎么对待的,希望大家能在回复时除了表述自己的观点,同时告知在项目中会采取哪种方式。

解决方案 »

  1.   

    你的这个是根据条件获取Product,你传递那么多参数,实在不是一种好办法。那个人说的没错!
      

  2.   

    额。  俺们没用存储过程的话,就直接传SQL了。 没有过多是想法
      

  3.   

    还是得封装!增加重用。
    我觉得并不会增加阅读成本
    读到 public DataTable GetProduct(QueryProduct query)
            {
                ......
            }
    这里根本不需要跳转QueryProduct类中查看,读者就能明白代码的意思
      

  4.   

    i love the post! thank you for your sharing!
    north face sale
    north face outlet
      

  5.   

    从哪里明白代码的意思的?GetProduct?
      

  6.   

      if 该方法需要频繁用到   封装;
    else  不封装;
     
      

  7.   

    参数太多了你每次调用这个方法的时候,都要填写那么多个参数呀!
    如果是对象的话,你就可以new出对象,然后选择性的填充参数……
    而且,C++里面一样,明明很多东西就是int类型,但是却用一个宏来代替。
      

  8.   

    我不做MIS和数据库连接这一块,但是我觉得对于这些查询条件封装成一个对象比较好,如果多处使用的话,封装比较好,如果查询属性要扩展的话,那么封装也比较好。
      

  9.   

    Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> 委托  发送反馈
    封装一个方法,该方法具有 16 个参数并且不返回值。这个参数多不多?
    楼主的说法还是挺有道理的。我觉得楼主的问题不在于是否把参数封装为类,而是在于如何多条件查询。楼主的参数每个字段只给了一个条件,而且查询方式单一,而且各条件之间的关系也是固定的。
      

  10.   

    GetProduct的方法体里面肯定会出现QueryProduct的字段,所以读者也没必要跳转到QueryProduct类中查看。而且以后项目扩张QueryProduct很可能还会被用到,
    再说调用这个方法写一个参数当然比写7个方便把,特别是这个方法被经常调用的话,一不小心就错了,至少类型已经固定了不会出错,也不会有第二个参数写到第四个上去的可能
      

  11.   

    在博客园已经回复过除非这个对象本身来源自是model层或业务层的类,否则我个人是很不赞同使用查询对象,因为这个对象基本没什么复用性,也只会在这个查询的方法中做为参数出现为了一个方法的参数就创建一个类,是否是设计过度呢?
      

  12.   

    上面很多人提到了方法重载问题是方法重载也面临困境,因为方法签名要求唯一性m(string s1,string s2),假设我现在重载地正好也是 两个string参数,vs不让你过地,他会说你签名一样
      

  13.   

    目前我还不适应用set……,get……
      

  14.   

    实际上我认同老p的说法我也是XP开发,与瀑布模型不同的是,我们不太愿意预先抽象,因为我们承认信息不完整,我们愿意保留抽象,只到他必须抽象的时候才抽象所以对于参数问题我的态度是
    1.如果我不确定参数有多少,我会先抽象一下(虽然信息不完整,但是正是因为不完整,不确定所以才抽象,这里不是故意去抽象,只是我不知道,所以只能抽象)2.参数过多,调用写着太麻烦。而且需要处理一些默认值,我会选择抽象。以简化调用者的负担3.当加入变化,测试红灯,已经需要重构和抽象的时候,我会选择抽象。因为环境到了你该抽象的时候了
      

  15.   

    你这是面向对象的编程吗,要是我,我会想,getproduct,只有一个参数where