在存储库界面中使用可选参数是否会被视为糟糕的设计?

发布于 2024-10-02 21:00:52 字数 1075 浏览 1 评论 0原文

我创建了两个类来外部控制存储库上的页码 (Page) 和排序 (Order)。该存储库公开 IEnumerable 而不是 IQueryable,因为我希望存储库具有很强的可测试性。

举例来说,如果我有以下存储库:

interface IUserRepository
{
    public IEnumerable<User> GetAll();
}

如果我希望调用者控制响应的子集,他们将需要传入页面/订单。所以首先想到的是添加重载:

interface IUserRepository
{
    IEnumerable<User> GetAll();
    IEnumerable<User> GetAllOrderedAndPaged(Order order, Page page);
}

我发现的问题是我必须创建多个重载,我发现这非常乏味。

我正在考虑(但不确定)做的是让 OrderPage 成为可选参数:

interface IUserRepository
{
    IEnumerable<User> GetAll(Order order = null, Page page = null);
}

这样调用代码可以轻松排序/分页,但不能使用主查询(这是我试图通过公开IEnumerable而不是IQueryable来避免的)。

这看起来是一个好还是坏的设计?我知道这可能被认为有点主观,但我正在尝试看看这是否存在功能错误。主要的关键是我的存储库是可测试的,并且调用者不能过多地玩弄/更改查询。我想既然排序/排序对于返回的数据集来说是一个非常常见的任务,为什么不将它们合并到存储库界面的设计中呢?同样,在测试时,我只关心返回正确的数据集,但调用者可以说“现在,给我这个页面/数据的有序子集”。

I have created two classes to externally control page number (Page) and ordering (Order) on a repository. The repository exposes IEnumerable<T> and not IQueryable<T> since I want the repository to have strong testability.

Say, for example, if I had the following repository:

interface IUserRepository
{
    public IEnumerable<User> GetAll();
}

If I want the caller to control the subset of the response, they would need to pass in the page/order. So first thought would be to add overloads:

interface IUserRepository
{
    IEnumerable<User> GetAll();
    IEnumerable<User> GetAllOrderedAndPaged(Order order, Page page);
}

The problem I find with this is that I have to create multiple overloads which I find to be pretty tedious.

What I'm thinking (but not sure) of doing is having Order and Page be optional parameters:

interface IUserRepository
{
    IEnumerable<User> GetAll(Order order = null, Page page = null);
}

This way the calling code can easily sort/page, but not play with the main query (which is what I'm trying to avoid by exposing IEnumerable<T> instead of IQueryable<T>).

Does this seem like a good or bad design? I know that could be considered a bit subjective, but I'm trying to see if there is functionally wrong with this. The main key is that my repositories are testable and the caller can't play around/change the query too much. I figured that since sorting/ordering are a very common task for a returning set of data, why not incorporate them into the design of the repository interface. Again, when testing, I only care that the right set of data is returned, but the caller can say "Now, give me this page/ordered subset of the data".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吻安 2024-10-09 21:00:52

我会警告不要使用可选参数,因为默认值将被编译到调用者中。这意味着如果默认值发生更改,则任何使用原始默认值的代码都需要重新编译。

如果将来您认为 null 不是有效值,更改了默认值,并开始抛出 ArgumentNullException,则这可能会在您的特定示例中出现问题传入了 null。任何使用您的接口的代码都必须重新编译,否则可能会引发 ArgumentNullExceptions

您可以阅读对此的更好解释 此处此处

从中得出的关键结论是:一旦在公共方法上公开了默认参数值,您就永远无法更改它,除非重新编译依赖于它的所有客户端。对于库编写者来说,这绝不意味着永远

I would caution against using optional parameters since the default values will be compiled into the caller. This means that if the default values ever change, any code that uses the original default values will need to be recompiled.

This could be a problem in your specific example if, in the future, you decided that null wasn't a valid value, changed the defaults, and started throwing a ArgumentNullException if null was passed in. Any code that uses your interface will have to recompiled or potentially start throwing ArgumentNullExceptions.

You can read a much better explanation of this here and here.

The key take-away from this: once you expose a default parameter value on a public method, you can never change it without recompiling all clients that depend on it. For library writers, this never means never ever.

寂寞清仓 2024-10-09 21:00:52

我决定使用这两个参数作为存储库本身的属性。考虑到默认值将被编译到调用者中的事实,以及在每个可能的存储库上的每个方法上写入这些参数可能会很乏味的事实。

I've decided to use both parameters as properties on the repository itself. Taking into consideration the fact that the default value will be compiled into the caller, but also the fact that writing these parameters on every method on every possible repository could be tedious.

满栀 2024-10-09 21:00:52

对于我的编程风格来说,有很多 lambda 的可选参数不太适合。

C# 4.0 功能 – 命名和命名可选参数 - 呃,不用了,谢谢:
http://blogs.ijw.co.nz/chris/index.php/2010/05/c-4-0-features-named-optional-parameters-uh-no-thanks/

作为更好的设计,我会使用元组作为参数。或者使用默认字段值聚合页面和订单的命名类。
抱歉,这当然是主观的。

For my style of programming with a lot of lambda's optional parameters are not well suitable.

C# 4.0 Features – Named & Optional Parameters – Uh, no thanks:
http://blogs.ijw.co.nz/chris/index.php/2010/05/c-4-0-features-named-optional-parameters-uh-no-thanks/

As a better design I would use a tuple as parameter. Or named class that aggregate page and order with default fields values.
Sorry it's of course subjective.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文