将一长串参数包装为单个对象

时间:2016-04-20 22:14:30

标签: c#

考虑以下界面:

>>> a = "foo,bar"
>>> b = "foo"
>>> len(a.split(','))
2
>>> len(b.split(','))
1
>>> a.split(',')[1]
'bar'
>>> b.split(',')[1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

这样做有什么好处吗?

public interface SomeRepo
{
    public IEnumerable<IThings> GetThingsByParameters(DateTime startDate,
        DateTime endDate,
        IEnumerable<int> categorIds,
        IEnumerable<int> userIds,
        IEnumerable<int> typeIds,
        string someStringToFilerBy);
}

其中public IEnuemrable<IThings> GetThingsByParamters(IParameter parameter); 是如此定义的对象:

IParameter

我没有看到public interface IParameter { DateTime startDate { get; } DateTime endDate { get; } IEnumerable<int> categorIds { get; } IEnumerable<int> userIds { get; } IEnumerable<int> typeIds { get; } string someStringToFilerBy { get; } } 做任何好处,除了它使它更具可读性,但额外的复杂层似乎并不值得。

我可能遗失的任何东西?感谢。

3 个答案:

答案 0 :(得分:5)

如果那只是针对那个地方的话,可能不值得这么多。

创建一个类本身确实有一些可能的好处,但它们完全依赖于它;是否可以重复使用它。

您可以为IParameter实施添加某种早期数据验证(例如IParameters不能早于endDate - 它的常识,你不需要成为一个存储库对象来知道这一点。

如果某些值是可选的而某些值不是,则startDate类会让您有机会清楚地区分这两个类别。

在您的代码中找到Parameters的所有用法比在原始&#34;开始日期/结束日期/ ID&#34;中找到所有用法要容易得多。包。

话虽如此,可读性并不是一个小问题。我觉得每种方法6个参数是两倍太多。根据经验,我不会打赌它会停在6点。

答案 1 :(得分:1)

你可以在书中看到清洁代码(罗伯特C.马丁)在一个方法中使用很多参数不是一个好主意(书建议最多使用3个),如果你有一个需要这么多参数的方法你必须再考虑一下你的设计,或者它表明你的模型还需要一个类。

答案 2 :(得分:0)

极端的是开发自己的表达式系统,其中IParameter有一个字符串运算符("Equals""LessThanOrEqualTo""Plus"等等,然后有一个数组被称为IParameter[]的{​​{1}}或其他内容。当然,如果您要这样做,为什么不使用内置的内容,如LINQ或C#Children?如果这不是由数据库支持,您需要使用字符串过滤,这是一个很好的选择(或者使用Expression的内置过滤/解析表达式,如果你不喜欢#39;关心表现)。

如果这是由数据库支持的,那么通常在存储库上公开任意查询是个坏主意,例如,与SQL数据库绑定,因为最终开发人员可能不知道哪些列被编入索引并且可能写错了 - 特定的查询(特别是如果他们不能轻松访问生产规模的数据) - 提供特定的查询方法会更好,这些方法会采用映射到基本上是SQL DataTable的特定方法,微调每个查询(假设您的存储库由SQL数据库支持)。

这是更高效的,因为现在您通过公开一个接受显式参数的方法显式地控制最终开发人员可以查询哪些索引。

这也使您的存储库的单元测试依赖性变得更加容易,因为它很容易模拟存储库这样的强类型方法 - 您最终会使用虚假的内存中抽象数据库LINQ-to-Objects如果允许您的服务定义自己的查询 - 有时会产生误报。

没有什么本质上绝对错误 - 我只是看到了典型的用例,例如,如果由数据库支持,或者如果没有充分利用已经存在的过滤/表达系统-Memory。