DDD repository and factory
Asked Answered
W

2

20

In my application a few layers. In this topic will focus on Domain and Infrastructure layers.

I have repository interface ClientRepositoryInterface in Domain layer. And I have implementation of this interface ClientRepositoryImpl in Infrastructure layer.

But to reconstitute the object in the middle of the cycle of its existence I need factory(ReconstitutionClientFactory). Call the factory will be in the repository. The book by Eric Evans is described as a normal practice.

But where this factory(ReconstitutionClientFactory) should be located? In Domain or in Infrastructure layer?

I think in Domain... BUT! But then the lower layer will directly call a higher layer! This is wrong, but how to do right?

Wulfe answered 21/7, 2015 at 0:14 Comment(1)
In DDD, both the concepts of "Repository" and "Factory" belong to the domain model, and therefore to the domain layer. They can use components from infrastructure, but they themselves (interface and implementation) are solely part of the domain. Infrastructure must be free of application- and domain-specific details.Lesson
C
19

First of all, the layers approach is kinda obsolete. When talking layers think 'context', who's on top of who isn't important.

The repository is in charge of restoring an object. A factory just creates a new object. Note the different semantics. The repository knows how saving/restoring to/from persistence is done and that depends on the storage and the method of access.

So, everything is done inside the repository i.e in the Infrastructure. If you serialize things, then you need just to deserialize back (this is how a document db does things anyway). If you're using an ORM or store things in tables then you'll do all the query required to get the data and repopulate the object. An ORM is the easiest way since it can use reflection to populate private properties. In this case the ORM itself is the factory.

One more thing, restoring, while technically can be done by a domain factory, it isn't the factory's purpose to do that because it breaks the layer boundaries. We want to keep everything persistence related in the Infrastructure.

Coefficient answered 21/7, 2015 at 2:29 Comment(7)
Couldn't you have a SQLResultsetClientFactory which knows how to reconstitute a domain object from a raw resultset? Not saying that this is a common practice, but in this case it would live in the infrastructure, right?Projector
MikeSW, thank you very much for your reply, but my basic question is identical to a question of plalx. I want to create something like SQLResultsetClientFactory. But where is it located? And about domain... from DDD(Eric Evans) book: "making the REPOSITORY delegate object creation to a FACTORY, which (in theory, though seldom in practice) could also be used to create objects from scratch."Wulfe
@Wulfe Eric's book was published 14 years ago, keep that in mind. Everything related to persistence should be kept in Infrastructure. If you really want a SqlResultsetClientFactory, go for it but keep it in the Infrastructure.Coefficient
Firstly, layered architecture is perfectly fine for the vast majority of business applications, today and always - it's not obsolete; layering is just a way to organize a codebase, a way that simplifies the compile-time dependency graph. Secondly, repository implementations belong in the domain, not the infrastructure layer. Don't confuse the code organizing principle of layering with the (often overkill) desire to facilitate the "swapping" of implementations (in the case of repositories, we achieve that by using an ORM library, not by having multiple implementations of each repository).Lesson
@Rogério Repository implementation deal with data (persistence) access. It's NEVER part of the domain. And an ORM is useless if you switch parts of your db from rdbms to document or key/value.Coefficient
I know what a Repository is (I have both books which describe it: Fowler's, and the DDD book by Evans). If you search the DDD book (as I did), nowhere does it say that a Repository would belong anywhere else than the domain model/layer. You are probably confused about the nature of the code that can go inside the implementation of domain layer classes. There is no reason to think that it needs to exclude code that uses JDBC, JPA, or code that embeds SQL statements; it's all fine to be there; such code does not belong in the infrastructure layer.Lesson
Also, regarding use of an ORM in the context of switching from RDBMS/SQL to NoSQL: a) in Java, the JPA API supports at least some NoSQL databases, so a Repository implemented with JPA could (at least in theory, don't know in practice) be used without changes between SQL & NoSQL; b) more importantly, there is no actual requirement for a Repository interface to support radically different implementations, or to allow for multiple implementations selected through external configuration (a Repository merely provides a collection-like interface, that's all).Lesson
M
50

Factory & Repository Concepts

To answer your question, I think it's important to focus on responsibilities of the concepts defined by DDD.

In the blue book, there is a section that deals with the problem that you describe:

A FACTORY handles the beginning of an object’s life; a REPOSITORY helps manage the middle and the end.

and specifically for your question:

Because the REPOSITORY is, in this case, creating objects based on data, many people consider the REPOSITORY to be a FACTORY—indeed it is, from a technical point of view.

(both quotes from Evans, chapter 6, section "The relationship with factories")

To keep the concepts pure, it is important that the interface of your factories and repositories are clean. So don't allow creating new business objects through the repository interface, and don't allow querying existing ones through the factory interface.

Keeping the interfaces clean does however not mean that you should not use a factory from the repository implementation, because, after all, the repository creates an instance at some point, and if that instance creation is complex, a factory is the appropriate solution.

To quote Evans again:

Whenever there is exposed complexity in reconstituting an object from another medium, the FACTORY is a good option.

Note, however, that the repository will most likely call a different method on the factory than the clients that really want to create a new domain object (as opposed to reconstitution).

There is even an example in Evans' book that illustrates approach:

Domain object reconstitution with help of a factory

Answer to your question

Now that it is clear that this is allowed, lets focus on your question of where to put the factory:

The DDD factory interface belongs in the domain, because your domain logic uses this to create domain objects.

The DDD reconstitution factory interface does not belong in the domain, since this is only relevant for your repository. It does not exist in the real world of your domain.

Now if you're using an architecture that prohibits dependencies from the domain to the infrastructure (which you probably should when applying DDD), it's clear that the factory implementation belongs in the infrastructure. Note that it does not matter whether you call your layers layers, rings, realms or whatever, the dependencies are the important part.

Mantling answered 21/7, 2015 at 11:45 Comment(5)
"The DDD reconstitution factory interface does not belong in the domain". How can this be when the reconstitution factory is returning a domain object? Your two statements "prohibits dependencies from the domain to the infrastructure" and "it's clear the factory implementation belongs in the infrastructure" seem to come to the very opposite conclusion that I do :) Wouldn't these mean it does not belong in the infrastructure?Helban
@Helban Returning a domain object is not a reason to put something in the domain. The reconstitution factory is a purely technical construct, a domain expert wouldn't know what it is and why it is even required.Mantling
@Matt: The reconstitution factory is only used by the repositories, which live in the infrastructure. The only factory-like thing that needs to be accessed from the domain is the (non-reconsitution) factory interface. That interface should thus be placed in the domain, whereas its implementation can go in the infrastructure.Mantling
Perhaps I'm reading your last comment incorrectly, but I don't agree that repositories live in the infrastructure. This dialogue should probably move outside of StackOverflow comments; I do appreciate your insights though - fun stuff. Thanks for taking the time.Helban
How does client "query" repository?Soluk
C
19

First of all, the layers approach is kinda obsolete. When talking layers think 'context', who's on top of who isn't important.

The repository is in charge of restoring an object. A factory just creates a new object. Note the different semantics. The repository knows how saving/restoring to/from persistence is done and that depends on the storage and the method of access.

So, everything is done inside the repository i.e in the Infrastructure. If you serialize things, then you need just to deserialize back (this is how a document db does things anyway). If you're using an ORM or store things in tables then you'll do all the query required to get the data and repopulate the object. An ORM is the easiest way since it can use reflection to populate private properties. In this case the ORM itself is the factory.

One more thing, restoring, while technically can be done by a domain factory, it isn't the factory's purpose to do that because it breaks the layer boundaries. We want to keep everything persistence related in the Infrastructure.

Coefficient answered 21/7, 2015 at 2:29 Comment(7)
Couldn't you have a SQLResultsetClientFactory which knows how to reconstitute a domain object from a raw resultset? Not saying that this is a common practice, but in this case it would live in the infrastructure, right?Projector
MikeSW, thank you very much for your reply, but my basic question is identical to a question of plalx. I want to create something like SQLResultsetClientFactory. But where is it located? And about domain... from DDD(Eric Evans) book: "making the REPOSITORY delegate object creation to a FACTORY, which (in theory, though seldom in practice) could also be used to create objects from scratch."Wulfe
@Wulfe Eric's book was published 14 years ago, keep that in mind. Everything related to persistence should be kept in Infrastructure. If you really want a SqlResultsetClientFactory, go for it but keep it in the Infrastructure.Coefficient
Firstly, layered architecture is perfectly fine for the vast majority of business applications, today and always - it's not obsolete; layering is just a way to organize a codebase, a way that simplifies the compile-time dependency graph. Secondly, repository implementations belong in the domain, not the infrastructure layer. Don't confuse the code organizing principle of layering with the (often overkill) desire to facilitate the "swapping" of implementations (in the case of repositories, we achieve that by using an ORM library, not by having multiple implementations of each repository).Lesson
@Rogério Repository implementation deal with data (persistence) access. It's NEVER part of the domain. And an ORM is useless if you switch parts of your db from rdbms to document or key/value.Coefficient
I know what a Repository is (I have both books which describe it: Fowler's, and the DDD book by Evans). If you search the DDD book (as I did), nowhere does it say that a Repository would belong anywhere else than the domain model/layer. You are probably confused about the nature of the code that can go inside the implementation of domain layer classes. There is no reason to think that it needs to exclude code that uses JDBC, JPA, or code that embeds SQL statements; it's all fine to be there; such code does not belong in the infrastructure layer.Lesson
Also, regarding use of an ORM in the context of switching from RDBMS/SQL to NoSQL: a) in Java, the JPA API supports at least some NoSQL databases, so a Repository implemented with JPA could (at least in theory, don't know in practice) be used without changes between SQL & NoSQL; b) more importantly, there is no actual requirement for a Repository interface to support radically different implementations, or to allow for multiple implementations selected through external configuration (a Repository merely provides a collection-like interface, that's all).Lesson

© 2022 - 2024 — McMap. All rights reserved.