4

Sometimes my Aggregate will be very simple; some scenarios are simply not complex enough to require deep trees of objects and relations.

Consider a Website Monitoring application, which periodically pings a URL to check if it is alive.

The Web App will have:

  • Id
  • FriendlyName
  • ‎URL
  • ‎IsAlive

It doesn't have much data, doesn't have child objects (except maybe for URL being a Value Object) and will certainly not have much invariants - if any - to enforce either, at least not at this time.

Now some say that because it is not modelling a more complex model, with relationships and internals and whatnot, it is not an Aggregate, it is only an Entity.

The thing is, I don't think that complexity or size should be dictating if it's an Aggregate, Entity or Value Object, but rather its MEANING.

For the Web Application Monitoring domain, that Web App "entity" is the root model, it's what is going to be returned from a Repository. If the domain expert brings new requirements, they will be related to that Web App model.

So, for me, I believe it makes it a WebAppAggregate, rather than a WebAppEntity.


Question: is my line of thinking correct, or did I get it all wrong? Thanks in advance.

Levidad
  • 798
  • 1
  • 7
  • 10

2 Answers2

6

The thing is, I don't think that complexity or size should be dictating if it's an Aggregate, Entity or Value Object, but rather its MEANING.

The thing is, these terms have definitions spelled out in the blue book

From chapter Five. A Model Expressed in Software

Does an object represent something with continuity and identity--something that is tracked through different states or even across different implementations? Or is it an attribute that describes the state of something else? This is the basic distinction between an ENTITY and a VALUE OBJECT.

From chapter Six. The Life Cycle of a Domain Object.

AGGREGATES mark off the scope within which invariants have to be maintained at every stage of the life cycle.

An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes.

It's entirely consistent to have an aggregate that contains only a single entity, that entity having only a single interesting property, and only simple behaviors that change that property from one value to another.

I would like to know your thoughts on my solution attempt.

The basic shape is fine: your WebApp entity is also the root of the aggregate, which is consistent with the pattern as described by Evans.

Raising the domain event in the constructor may be an error; it's certainly a code smell (raising a domain event certainly counts as real work).

VoiceOfUnreason
  • 32,131
  • 2
  • 42
  • 79
  • please take a look at my comments for [Erik's answer](https://softwareengineering.stackexchange.com/a/363306/20115) below. I would like to know your thoughts on my solution attempt. – Levidad Jan 03 '18 at 11:46
  • Thanks for looking at the code. Your latest feedback led me to finding some complementary articles, like this one: [Strengthening your domain: Aggregate Construction](https://lostechies.com/jimmybogard/2010/02/24/strengthening-your-domain-aggregate-construction/), by Jimmy Bogard. – Levidad Jan 03 '18 at 19:49
5

The thing is, I don't think that complexity or size should be dictating if it's an Aggregate, Entity or Value Object, but rather its MEANING.


I read someplace you're not supposed to return anything except Aggregates from the Repository.

You seem to be thinking in the terms that an item is either Aggregate, an Entity, or a Value Object. However, the notion of Aggregate is not the same as Entity and Value Object; Aggregate is not a third alternative but a different notion.

An aggregate is a logical collection of Entities (and Value Objects) and their relationships. An aggregate has a single special entity, called the root entity. This root entity is referred to as the Aggregate Root. It is the only entity within the Aggregate that is allowed to be referred to from outside of that aggregate. As the point of contact from outside of the aggregate, the root is generally expected to enforce integrity of the aggregate.

Note that the Aggregate Root is an Entity! The Aggregate itself is the logical collection of related entities. It is a boundary around these entities (with some rules).

If you don't have a collection, you don't have an Aggregate. But that's fine, you simply have an entity.

(In my opinion it is also reasonable to think of a lone entity having an identity that can be referred to, as a degenerate case of an Aggregate having only one entity, the root entity, if you like.)

Even if you do have a collection you still have to have at least one Entity, in this case one of the entities must be the root entity, which is your Aggregate Root. Again Aggregate Root is an Entity whereas an Aggregate is a logical collection (having an Aggregate Root).

Erik Eidt
  • 33,282
  • 5
  • 57
  • 91
  • 1
    Thanks, answers like this clear up a lot of things for me. For the sake of illustrating what you said, how would you write code for this? First, an [aggregate AS entity](http://bit.ly/2CxapP3), containing the properties directly, or this one [aggregate WITH entity](http://bit.ly/2lJIn9f)? – Levidad Jan 03 '18 at 10:50
  • Complementing: I read things again, and what they actually said is that you should have one repository per aggregate. So I get the concept of what you say, it makes sense, but then I write code like the aggregate WITH an entity and then it seems I'll need a repository for the entity, not the aggregate... – Levidad Jan 03 '18 at 10:52
  • Microsoft in its [eShop On Containers](https://github.com/dotnet-architecture/eShopOnContainers) seems to go with a third "root entity as aggregate" notion. For the Ordering domain, there is a "BuyerAggregate" (which is just a folder), containing the [Buyer](http://bit.ly/2Ad6Rfs) class, which extends Entity and IAggregateRoot, and for which there is an [IBuyerRepository](http://bit.ly/2lLqmYt) interface. – Levidad Jan 03 '18 at 11:11
  • Finally, please take a look at [this code](https://gist.github.com/phillippelevidad/a981edd0bcfef5ad3bda569b9ee2db17) I just wrote. It is my attempt to model an eficient and clean solution to this problem we're discussing. What do you think of it? – Levidad Jan 03 '18 at 11:41