In the last lesson the smallest building blocks came into being: Money, Quantity and the IDs. Now you put them together into a quote.
A quote is more than the sum of its parts. It has rules that apply across several parts: all lines are in
the same currency, after sending nothing changes anymore, and above a certain total, the approval needs a second person. These rules
need a place where they always hold. That place is called an aggregate.
At the end of this lesson, Kladde.Quotes.Domain contains the Quote aggregate with all the rules from the conversation with the domain expert, and
every rule has a test.
What an aggregate is
An aggregate is a group of objects that have to keep their rules together. One of them is the root (aggregate root). Only the root can be reached from outside, and every change goes through it. For the quote, that means:
- The root is
Quote. - The lines (
QuoteLine) and the value objects in them belong to the aggregate. - Whoever wants to add a line calls
quote.AddLine(...). There is no way to put a line into the list past the root.
The rules an aggregate always keeps are called invariants. “Always” is meant literally here: before and after every method call,
not just mostly and not only after saving. One invariant of the quote is “all lines have the quote's currency”. It
holds because AddLine rejects a line in a foreign currency, and because there is no other way to add a line.
Invariants are the reason aggregates exist, and they determine their boundary. What an invariant has to protect together belongs in the same aggregate. What has no common invariant doesn't belong in it, even if it is related in the business.