Imagine we have two entities, EntityA
and EntityB
. Both entities have a repository to query the database, EntityARepository
and EntityBRepository
. There are also services for both of them, EntityAService
and EntityBService
.
Now there is a method in the EntityBService
, which also needs to use EntityA
. What would be the right way of doing this?
EntityBService
use the EntityARepository
directly?EntityBService
use the EntityAService
?I could see how using the repository directly might be very convenient, but also it seems to get kind of messy when having not only two entities.
Is there common design pattern around this topic or recommendations?
TLDR; it depends!
If you're trying to follow Domain Driven Design, I think it's a good idea to differentiate service
and repository
. There are different definitions which may differ in details but I'll stick to Martin Fowler's one for Repository:
(...) A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. (...)
and for service:
A Service Layer defines an application's boundary [Cockburn PloP] and its set of available operations from the perspective of interfacing client layers. It encapsulates the application's business logic, controlling transactions and coor-dinating responses in the implementation of its operations.
It is worth pointing out that service
isn't just repository
+ business logic. For most simple scenarios repository
just wraps up accessing single database, but for advanced scenarios creating single entity may require accesing multiple databases, so repository
role is to remove this woffle from service
layer.
And here is what you could come up with:
EntityARepository
directly in EntityBService
if what you're trying to do is just fetching EntityA
without any business logic related to EntityA
. Here is a simple example:
EntityBService
performs operation onEntityB
, but it depends on purelyEntityA
state.
EntityAService
in EntityBService
if requesting EntityA
involves some business logic related to EntityA
. Here is a simple example:
EntityBService
performs operation onEntityB
andEntityA
and later needs to be created if it doesn't exist - creation involves a business logic like checking is it allowed (e.g. based on user role).
Is there common design pattern around this topic or recommendations?
One common practice is to avoid changing entities that are stored in different places in the same transaction. One way to ensure that you never do that is to have only one entity active in any transaction.
So we might reasonably have entityA, and a copy of the information we need from B. Or we might have entityB, and a copy of the information we need from A.
For use cases where we aren't changing either entity, we can just use copies of the data.
In the case where we are using entityA
and recent-copy-of-B
, we know that entityA comes from a repository. Where does recent-copy-of-B
come from? Well, it comes from an abstraction that looks something like a repository, except (a) it fetches values, rather than entities and (b) it is read only.
recent-copy-of-B
looks something like a DTO. And while you might use the same one everywhere, it is actually safe (because values are immutable) to create specialized versions for different use cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With