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

