Hey,

Considering the discussion about almost-infinitely scalable systems it 
seems like a good to continue trying to figure out how to design 
aggregates, since the aggregate border is so important for that.

To start with, some definitions and assumptions, take from the DDD book 
and elsewhere. An Aggregate is an Entity which encompasses or "owns" a 
set of Entities. One of the main points of Aggregates is to "guarantee 
the consistency of changes to objects in a model with complex 
associations. Invariants need to be maintained that apply to closely 
related groups of objects, not just discrete objects. Yet cautious 
locking schemes cause multiple users to interfere pointlessly with each 
other and make a system unusable" (DDD book, p126).

Aggregates may have references to Entities within them, but no Entity 
may have a reference to an Entity within another. Therefore, if we have 
a way to mark an Entity as being an Aggregate root, then for each 
Association from an Entity to another we can detect whether the 
associated Entity is within the same Aggregate by simply checking if it 
is marked as an Aggregate. This way, if we start from the root of an 
Aggregate and follow all Associations, transitively, we can get the 
extent of the Aggregate by just following all associations and 
collecting the references. When the Aggregate is removed we can then 
know what Entities are to be removed by this.

Also, if there is a schema change any rules for transformation of 
existing data should be applied to the Aggregate rather than single 
Entities. Properties may have been moved from one Entity in the 
Aggregate to another, and this cannot be handled if we view all Entities 
as "the same". If however we view the Aggregate as being the unit to be 
migrated, it's fine.

Another thing which becomes simpler is serialization. Only aggregate 
roots can be serialized, and Entities within it can almost be viewed as 
being identity-less for the purpose of serialization. If an Aggregate 
root is being loaded by a client it is very likely that we should load 
the Aggregate as a whole rather than just the Aggregate root. This can 
help with some lazy-loading problems. Also, for the purposes of 
remote-loading and caching, the last-modified timestamp becomes the 
latest timestamp of all involved Entities, which should make it easy to 
do remote loading of Entities efficiently.

All access to an Aggregates internals comes through the Aggregate root. 
If you then consider what was stated in the Amazon research paper on 
almost-infinitely scalable systems, it feels like those methods quite 
often should be message-oriented, i.e. when invoked they will be sending 
a message to the Entity rather than just invoking a method in an 
RPC-style. The message should assume that it's potentially going over a 
network, so doing it in a document-style and asynchronously is probably 
a good idea. There's lots of interesting things that can be done here I 
think, when it comes to calling Aggregate methods and automatically 
convert them into messagebased conversations.

Locking and consistency checks should probably also be done on an 
Aggregate basis, i.e. when updating an Entity we need to verify that its 
owning Aggregate's version has not been changed, since the validation 
rules should apply to the Aggregate level (e.g. when we change a 
lineitem we need to verify that the Aggregate Order is still valid).

As for Queries, one question is whether it should be allowed to Query 
for Entities within an Aggregate. But, since the references into an 
Aggregates Entities is maintained automatically I think it might be ok 
to "find" Entities within Entities this way. The main rule is to not 
have references to those Entities from Entities in another Aggregate, 
which is the main problem to be avoided.

These are just some of the thoughts on Aggregates. However, it seems to 
me that the main API change might be to have an AggregateComposite 
subtype of EntityComposite, which is used as a marker interface for 
Aggregate roots. Most of the other logic follows from that I think. Not 
sure if the Aggregate root has to have any new methods, but that might 
be required.

/Rickard

_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to