Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DDD: can a Repository return entities inside an aggregate?

I have a City aggregate, having a list of PointOfInterest entities. This latter entity lies logically inside the City aggregate for reasons that won't be explained here. No entity holds a link to PointOfInterest, apart from the aggregate root, City.

However, we have a web page for PointOfInterest, browsable from the City page, that (mainly for SEO reasons) only has the PointOfInterest id in its URL.

Thus, from the controller, it would be handy to query the CityRepository for a PointOfInterest directly, such as CityRepository.findPointOfInterestById().

The other option would be to query CityRepository.findCityByPointOfInterestId(), then City.findPointOfInterestById(), which looks a bit cumbersome in this case.

Is there anything wrong with the first approach?

like image 728
BenMorel Avatar asked Aug 05 '12 10:08

BenMorel


People also ask

Can aggregate roots share entities?

As you rightly pointed out, Entity instances shouldn't be shared between aggregates, as one aggregate wouldn't be aware of changes to the entity made through another aggregate and couldn't enforce its invariants.

What is aggregate repository?

In the Context of a Repository the Aggregate Root is an Entity with no parent Entity. It contains zero, One or Many Child Entities whose existence is dependent upon the Parent for it's identity. That's a One To Many relationship in a Repository. Those Child Entities are plain Aggregates.

Is an aggregate an entity?

An aggregate is a collection of one or more related entities (and possibly value objects). Each aggregate has a single root entity, referred to as the aggregate root. The aggregate root is responsible for controlling access to all of the members of its aggregate.

What is the role of an aggregate in Domain-Driven Design?

Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An example may be an order and its line-items, these will be separate objects, but it's useful to treat the order (together with its line items) as a single aggregate.


1 Answers

Since PointOfInterest is part of the City aggregate, you have to accept that all references to PointOfInterests must be obtained by traversal of a City. It doesn't seem appropriate for CityRepository to expose GetPoI() methods because it would allow an outside object to get a direct reference to a PoI, defeating the whole purpose of an aggregate. Besides, it doesn't really seem like a natural responsibility of a CityRepository to deal with PoIs.

As Wouter points out, your feeling the need to do convoluted things like this might be a sign that the current design is not quite appropriate. If PointOfInterest turns out to be one of the major entities in your application and if the user can access it right from the start of his navigation without necessarily going through a City first, why not consider giving PoI its own aggregate ? As for the PoI / PoIType relationship, it seems more logical for a PoI to have a PoIType than the other way around.

like image 67
guillaume31 Avatar answered Oct 22 '22 22:10

guillaume31