将存储库接口作为参数传递给域类中的方法是否被认为是错误的设计? [英] Is it considered bad design to pass a repository interface as an argument to a method on a domain class?

查看:81
本文介绍了将存储库接口作为参数传递给域类中的方法是否被认为是错误的设计?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的域模型现在非常贫乏。我们的实体大多是空壳,几乎纯粹是为保存值和导航到集合而设计的。

Our domain model is very anemic right now. Our entities are mostly empty shells, almost purely designed for holding values and navigating to collections.

我们使用的是EF 4.1代码优先的ORM,到目前为止,该设计一直在保护我们的新手开发人员免受可怕的 LINQ to Entities无法将blablabla转换为商店早期迭代期间针对上下文查询时出现表达式异常。

We are using EF 4.1 code-first ORM, and the design so far has been to shield our novice developers against the dreaded "LINQ to Entities cannot translate blablabla to a store expression" exception when querying against the context during early iterations.

我们在EF上有各种聚合的根存储库接口。但是,impls中的某些代码块似乎应该由域负责。只要在域中声明了存储库接口,并且impl在基础架构中(注入了依赖项),将存储库接口作为参数传递给实体(或其他域)类的方法是否被认为是错误的设计?

We have various aggregate root repository interfaces over EF. However some blocks of code in the impls seems like they should be the domain's responsibility. As long as the repository interface is declared in the domain, and the impl is in the infrastructure (dependency injected), is it considered bad design to pass a repository interface as an argument to a method on an entity (or other domain) class?

例如,这不好吗?

public class EntityAbc {
    public void SaveTo(IEntityAbcRepository repos) {...}
    public void DeleteFrom(IEntityAbcRepository repos) {...}
}

如果特定实体需要访问其他汇总根存储库怎么办?可以吗?为什么?

What if a particular entity needed access to other aggregate root repositories? Would this be ok or not, and why?

public void Save() {
    var abcRepos = DependencyInjector.Current.GetService<IEntityAbcRepository>();
    var xyzRepos = DependencyInjector.Current.GetService<IEntityXyzRepository>();
    // work with repositories
}

更新1

我没有提到将代码移至应用程序层,因为我认为某些使用IEntityAbcRepository的代码涉及业务规则实施。仓库的impl应该尽可能的原始,对吧?它的主要职责应该只是对ORM的简单抽象,从而允许您查找/添加/更新/删除实体。是吗?

I did not mention moving code to an application layer because I consider some of the code that uses IEntityAbcRepository to involve business rule enforcement. The repository impl should be as vanilla as possible, right? Its main responsibility should just be a simple abstraction over the ORM, allowing you to find / add / update / delete entities. Wrong?

这个问题也适用于其他非实体域类的方法-工厂,服务,无论哪种模式都合适。重要的是,我要问的是有关域类的任何方法的问题,而不仅仅是实体类。 @Eranga,这是可以使用构造函数注入的地方,因为factory&服务不属于ORM。

Also, this question applies to methods on other non-entity domain classes -- factories, services, whatever pattern may be appropriate. Point being, I'm asking the question about any method on a domain class, not just an entity class. @Eranga, this is one place where you can use constructor injection because factories & services are not part of the ORM.

然后,应用程序层可以通过将存储库impl注入其构造函数并将其作为参数传递给域服务或工厂来协调流程。这是不好的做法吗?

The application layer could then coordinate flow by injecting a repository impl into its constructor, and passing it as an argument to a domain service or factory. Is this bad practice?

更新2

在此处添加另一个说明。如果域只需要访问IEntityAbcRepository即可执行其Find()方法,该怎么办?在上面的示例中,SaveTo和DeleteFrom方法不会在存储库界面上调用任何add / update / delete方法。

Adding another clarification here. What if the domain only needs access to the IEntityAbcRepository in order to execute its Find() method(s)? In the example above, the SaveTo and DeleteFrom methods would not invoke any add / update / delete methods on the repository interface.

到目前为止,为简单起见,我们已经在单个聚合根存储库界面上组合了fi​​nd / add / update / delete方法。但是我想并没有阻止我们将它们分成2个接口的方法,例如:

So far we've combined the find / add / update / delete methods on a single aggregate root repository interface for simplicity. But I suppose there's nothing stopping us from separating them out into 2 interfaces, like so:


  1. IEntityAbcReadRepository<-定义了所有查找方法签名

  2. IEntityAbcWriteRepository<-定义所有添加/更新/删除方法sigs

情况下,将IEntityAbcReadRepository作为参数传递给域方法会不是一个好习惯?

In this case, would it be bad practice to pass IEntityAbcReadRepository as a parameter to a domain method?

推荐答案

与第一种方法相比,第二种方法使用服务定位器模式。在第一种方法中,依赖性更加明显。

Your first approach is better compared to the second approach which uses "Service Locator" pattern. Dependencies are more obvious in the first approach.

以下是一些链接,解释了为什么服务定位器是错误的选择

Here are some links that explains why "Service Locator" is a bad choice

这两种解决方案均源于EF不允许您使用构造函数注入的事实。但是,您可以按照在此答案中所述使用属性注入。但这不能保证存在强制性依赖性。

Both of these solutions stem from the fact that EF does not allow you to use constructor injection. However you can use property injection as explained in this answer. But that does not guarantee that mandatory dependencies are present.

因此,您的第一种方法是更好的解决方案。

So your first approach is the better solution.

这篇关于将存储库接口作为参数传递给域类中的方法是否被认为是错误的设计?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆