Aggregate in tactical DDD
07.10.2021

SafeValue must use [property]=binding: First of all, the aggregate is the pattern of the tactical DDD. It represents a cluster of entity or value objects, thus being the fundamental element of data storage transfer. These objects are considered as an organic whole from the point of view of changing data. Thus, tactical DDD keeps track of the components of a domain model.
The Aggregate Root represents the entity with a globally unique identifier that is placed inside the aggregate. The Aggregate Root is considered to be the point of entry to the aggregate. Any links from outside must go to the Aggregate Root. Wherein the reference between different aggregates can't be performed through object references. They are replaced by unique identifiers, which prevents unnecessary coupling between aggregates. It facilitates the process of crushing large domains into smaller groups of aggregate.
Obviously, the aggregate has boundaries. All internal objects of the aggregate placed within boundaries have only a local identity; they can refer to each other in any way. But the external objects can only store a reference to the root, not to the internal objects.
Within the boundaries, we are dealing with invariants. The Invariant in object-oriented programming is the expression defined as the consistent internal state of the object. It is the transactional consistency within boundaries that must always be satisfied. In other words, we may say that the aggregate is a transactional consistency boundary, within which invariant rules are executed, regardless of what operations are performed in this case.
Aggregates are sometimes confused with collection classes. Aggregates in DDD are domain concepts, but the collections are generic. An aggregate often contains multiple collections along with simple fields. The term "aggregate" is generic and is used in various contexts, in which case it does not refer to DDD.
It is useful to note that it is necessary to analyze the true invariants of the model to determine which objects should be combined into an aggregate when trying to identify aggregates in a bounded context.
It is necessary to remain that large-cluster aggregates are inferior to small aggregates in performance and scalability. Furthermore, it is clear that loading a large aggregate needs more memory.
On the other side, the smaller aggregates run faster and are helping in making transactions progress. The usage of the value objects rather than entities inside an aggregate is much effective because of the most accessible maintenance, testing, etc.
Despite the fact that each aggregate can store the reference as the roots of other aggregates, it does not place this aggregate within the boundaries of consistency of the first aggregate. Thus, the links do not generate a coherent Aggregate.
Also, it's important to say that in a single transaction in a bounded context, only a single aggregate must be changed.
In order to reduce the amount of memory of objects, for ease of scaling, and, as a result, to speed up the download, it is reasonable not to store direct links as objects but to refer to the global identifiers of the Aggregate Root.
When faced with multiple aggregates that participate in a transaction, you should use the ultimate consistency principle, which foresees the publication of an event after changing one aggregate, and then publications of changes of the one and other, and more other aggregates which provides consistency in the system. (see http://g.co/ng/security#xss)