DDD 存储库作为单例?
简单的问题:将我的领域驱动设计风格存储库实现为单例是好还是坏主意? 为什么?
或者我应该使用依赖项注入器容器来管理我的存储库并决定它们是否是单例?
我仍在阅读快速DDD,并且希望看到一些好的存储库示例。
Quick question: Would it be a good or a bad idea to implement my domain-driven design style repositories as singletons? Why?
Or should I maybe use a dependency injector container to manage my repositories and decide if they are singletons or not?
I'm still reading DDD Quickly, and would like to see some good repository examples.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用依赖项注入容器来决定创建存储库的方式和位置。
通过使用
你会造成测试障碍。
如果您的存储库使用构造函数注入传递到服务中,那么您还可以轻松地用模拟替换它们。
Use your dependency injection container to decide how and where repositories are created.
By using
you're creating a barrier to testing.
If your repositories are passed into services using Constructor Injection, then you can also easily replace them with mocks.
我已经看到了几种方法可以做到这一点。
最常见的方法是使用依赖项注入将存储库注入到使用它们的对象中。 通常这些是演示者或控制器类,但在某些情况下模型会调用存储库。 通常,避免这种情况会更好。 如果你可以使用双容器来做到这一点,那就去做吧。
您还可以使存储库实现单例模式。 我会尽量避免这种情况,因为单例通常使用静态方法。 这可能会使测试调用单例的代码变得更加困难。 如果您必须以这种方式执行操作,那么请确保分离出调用单例的代码,并使用“手动”依赖项注入将单例注入到调用它们的类中。 这消除了您原本会遇到的一些紧密耦合。
我见过一些存储库从未被调用的例子。 当有人浏览模型中的对象图并请求未加载的对象时,模型只会引发一个事件,并且存储库对此事件做出反应。 这样就不会调用存储库,并且它与模型完全解耦。 我自己没有使用过这个架构,但它看起来很干净。
I've seen a couple of ways to do this.
The most common way is to use dependency injection to inject the repositories into the objects that use them. Usually these are presenter or controller classes but in some cases the model calls into the repository. Usually it's better if you avoid this. If you can use a di-container to do this then go for it.
You can also make the repositories implement the singleton pattern. I'd try to avoid this because singletons usually use static methods. This can make testing the code that calls into the singletons more difficult. If you have to do things this way then make sure you separate out the code that calls the singleton and use "manual" dependency injection to inject the singletons into the classes that call them. This gets rid of some of the tight coupling you'd otherwise get.
I've seen some examples where the repositories never get called. When someone navigates the object graph in the model and requests an object that isnt loaded the model just raises an event and the repository reacts to this event. This way there are no calls into the repository and it's completely decoupled from the model. I havn't used this architecture myself but it seems very clean.
我对此不确定,我也有同样的问题。 我认为当存储库所使用的对象经常使用时,您应该将存储库设置为单例。 如果您使用很少使用的对象,则不应将其设置为单例,因为存储库会占用对象的大量内存,并且在应用程序的使用过程中可能只会调用一次并且永远不会再次调用它。
正如我所说,这可能不是正确的想法。
I am not sure about this and I have the same problem. I think that you should make a repository a singleton when the objects that it works with are used often. And that it shouldn't be made a singleton if you use objects that it works with rarely, because the repository would take a lot of memory for objects and maybe it would be called only once and never again during usage of the application.
As I said, this may not be correct thinking.
假设我有一个非常大的项目,并且我想添加新服务,假设它将是我系统中的一些硬件代表。 我希望可以通过许多类访问该服务,我想确保只有一个服务实例或层控制对服务的访问。 通过我的所有系统(200 多个类)注入此服务将需要大量工作。 对我来说,“单例”或某些“服务定位器”非常适合这项任务。
Lets say I have really huge project, and I want to add new service lets say it would be some hardware representative in my system. I want this service to be accessible through many classes, I want to be sure that there is only one instance of service or layer that controll access to service. Injecting this service through all of my system (200+ classes) would be lot of work. For me "Singleton" or some "Service Locator" suits well for this task.
据我了解,该域仅包含一个存储库接口,这意味着单个接口可以有许多存储库实现。 因此,存储库当然不能是静态类,因为您不能在接口中定义静态方法。 (注意:在某些语言中,您可以在接口中定义静态方法,但这对我来说没有多大意义。)
存储库通常用于将实体与数据库、文件等同步。因此它们具有不稳定的依赖关系。 这意味着它们不能是单例,只能具有环境依赖项。 这是一篇关于它的文章。 有趣的是,即使作者告诉你,你可以在你的域中使用单例。
据我了解,创建一个存储库来确保您只有一个实体而不是多个实体要干净得多。 如果您希望您的代码满足单一职责原则。
5年后,在我的框架中,域包含存储库接口,基础设施包含存储库实现。 我在上层容器中创建一个域容器,该域容器实例化并包含存储库实例。 通常每个存储库接口只有一个存储库。 可以有多个类实现该接口。 例如,我可以根据项目制作 MySQL 存储库、MongoDB 存储库、FileSystem 存储库等。 为了测试域,即使是内存存储库也可以。 我通常将大部分逻辑移至域中,而存储库仅执行非常基本的 CRUD。 如果我因此发现瓶颈,那么我会向实际存储库添加一个新方法,并将一些代码移至 SQL 以使其更快,但到目前为止还不错,即使在出现瓶颈的情况下,也可能会更好只需扩展服务而不是编写更快的 SQL,因为与数据库不同,它很容易扩展。 我正在考虑练习 CQRS 和 ES,但它们对于大多数项目来说通常都太过分了。 到目前为止我从来不需要它们。 我真的很喜欢使用 DDD 概念,使用这种方法让我的生活变得更加轻松,而不是让数据库结构和表示泄漏到业务逻辑中。
As far as I understand the domain contains only a repository interfaces, which means there can be many repository implementations for a single interface. So a repository certainly can't be a static class, since you can't define static methods in an interface. (Note: In some languages you can define static methods in an interface, but it does not make much sense to me.)
Repositories are usually about syncing the entities with databases, files, etc.. so they have non-stable dependencies. Which means they cannot be singletons can have only ambient dependencies. Here is an article about it. The funny part even the authors tell you that you can use singletons in your domain.
To my understanding it is much cleaner to make a repository that makes sure that you have only a single entity instead of many. That is the resposibility of the repository, not the entity if you want your code to meet the single responsibility principle.
In my framework after 5 years the domain contains repository interfaces, the infrastructure contains repository implementations. I create a domain container in an upper level container and the domain container instantiates and contains the repository instances. Usually there is only a single repository for each repository interface. There can be multiple classes though which implement that interface. E.g. I can make a MySQL repository, a MongoDB repository, a FileSystem repository, and so on depending on the project. For testing the domain even an in-memory repository is ok. I usually move most of the logic into the domain and the repositories do only very basic CRUD. If I find a bottleneck because of this, then I add a new method to the actual repository and move some code to the SQL to make it faster, but so far it is fine and even in the case of a bottleneck it might be better to just scale the service instead of writing a faster SQL, because it is easy to scale unlike the database. I am thinking on practicing CQRS and ES, but they are usually overkill for most of the projects. So far I never needed them. I really like to use the DDD concepts, it makes my life a lot easier to use this approach instead of letting the database structure and the presentation leaking into the business logic.