Reputation: 388
I have a aggregate called Investor; investor is composed on various entities (say stocks, bonds), some value objects as well (address)
I would like to make a service that return an Investor for some investor ID (/get-investor/id/:id)
The data for stocks for an investor is stored in database 1; bonds in database 2, address in database 3.
Where should the actual fetching of data from other microservices live?
In the domain model? (does not seem right)
Coordinated by a service (gets the data from various repositories) which then composes the domain model with all that information?
Upvotes: 0
Views: 155
Reputation: 57249
The data for stocks for an investor is stored in database 1; bonds in database 2, address in database 3.
If that's the case (and it certainly makes sense that you might break things out that way), then investor probably isn't an AGGREGATE, in the Eric Evans sense.
(Rolling back transactions across multiple databases is not usually a good time.)
I would like to make a service that return an Investor for some investor ID (/get-investor/id/:id)
You seem to be describing a report that combines information copied from multiple databases. In that case, a domain model isn't really necessary because we're not interested in trying to change the official copy of the data, and therefore we don't really need the rules that describe how you constrain changes.
Depending on the liveness requirements you have, you might reasonably query the different databases from the application layer when you get a request for a page. Alternatively, you might perform those queries in the background, copying the information you need into a local cache (which in turn is queried by the application layer).
The same ideas can work when you are trying to change the official copy of some information, and need reference data from somewhere else to compute the right changes to make. That's the ideal case - when the logic of deciding what data you need from somewhere else is trivially determined.
When you need to do work in the domain model to determine what reference data you need, there are at least two candidate approaches.
By far the most common is to use a "domain service" that acts as a facade in front of the query implementation - you pass the service to the model with your other arguments, and it invokes the service when it needs to.
Rare, but viable is to instead design a protocol between the domain model and the application code, such that the domain model can ask for the information it needs and the application code can run the query and pass that information back to the domain model. It has the advantage of getting some of the (possibly implicit) error handling out of the domain model, and putting it into the application code with the other I/O concerns. But it certainly isn't as "easy" as just calling the query when you want it.
(Remember: the machine doesn't care very much how you do it - any correct implementation is fine. But some designs are easier for the human beings that need to maintain them, and different human beings in different contexts have different priorities.)
Upvotes: 1