Torbjørn
Torbjørn

Reputation: 6503

DDD repositories as singletons?

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.

Upvotes: 5

Views: 3629

Answers (5)

inf3rno
inf3rno

Reputation: 26137

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.

Upvotes: 0

Marcin Kurpiel
Marcin Kurpiel

Reputation: 175

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.

Upvotes: 0

gljivar
gljivar

Reputation: 440

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.

Upvotes: 0

Mendelt
Mendelt

Reputation: 37483

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.

Upvotes: 2

kͩeͣmͮpͥ ͩ
kͩeͣmͮpͥ ͩ

Reputation: 7846

Use your dependency injection container to decide how and where repositories are created.

By using

UserRepository.Instance.Find(userId);

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.

Upvotes: 3

Related Questions