Search code examples
java.netdomain-driven-designmicroservices

Does Aggregate root class holds only publicly exposed methods


I'm trying to understand the concept of AggregateRoots. Let's say that I have a classes Customer, Holiday, Address, Document.

If I understood correctly an aggregate root should be a class which is in charge of manipulation for certain business rules. In this case, I recognize a Customer class which should be responsible for assigning a holiday record for a given customer as well as other info (address and document).

My question(s) is:

  • Should I follow some filename convention for my aggregate root (CustomerAggregate) instead of Customer?
  • Should I make all other classes (Holiday, Address, Document) as non-visible to the outside world (aggregate root is the only entry point which uses further those classes, if so what is the best practice for this?
  • Should I structure my aggregate root in a way as domain service class with all possible public entry points (Customer do this, Customer do that) together with all properties for that class?

Solution

  • In , the usual starting point for aggregates is the Eric Evans book.

    An AGGREGATE is a graph of domain model entities that change together. Many aggregates will have only a single entity within them, but in general there can be more than one.

    An AGGREGATE ROOT is the single entity within an aggregate that the application is allowed to interact with -- the root entity acts as the interface for the entire aggregate. This makes it easier to ensure that the invariant is maintained - all changes have to pass through a single choke point.

    Should I follow some filename convention for my aggregate root (CustomerAggregate) instead of Customer?

    It doesn't matter a lot, but in most examples the root objects use the naming conventions of an entity in the domain model, rather than having a special convention of their own. So Customer would be what you expect to see.

    Should I make all other classes as non-visible to the outside world

    Not necessarily - the important thing is to ensure that the outside world always goes through the choke point. Using discipline and code review to enforce that is fine. If you are using the repository pattern, you can limit those interfaces to only expose the root objects. In java, you can put all of the entities of an aggregate into a single package, and ensure that only the root object has the public access level modifier.

    In many cases, it is sufficient to protect against accidental misuse of the model.

    Should I structure my aggregate root in a way as domain service class with all possible public entry points (Customer do this, Customer do that) together with all properties for that class?

    This question is hard to answer, because domain service is used as a pattern name in -- entities and domain services are different things, so making an aggregate root (which is an entity, see above) like a domain service is a step the wrong direction.

    The domain entity will normally include an interface that describes the messages it expects, and also the encapsulated data structure it uses to keep track of its own state.