Use the Aggregate Design Pattern to Reduce Coupling

From WikiContent

(Difference between revisions)
Jump to: navigation, search
Current revision (21:58, 6 July 2009) (edit) (undo)
 
(9 intermediate revisions not shown.)
Line 1: Line 1:
-
Despite that fact that architects and developers know that tight coupling leads to increased complexity, we experience large object models growing out of control on an almost daily basis. In practice, this leads performance problems and lack of transactional integrity. There are many reasons why this happens: the inherent complexity of the real world, which has few clear boundaries; insufficient programming language support for dynamic multi-object grouping; and weak design practices.
+
Despite that fact that architects and developers know that tight coupling leads to increased complexity, we experience large object models growing out of control on an almost daily basis. In practice, this leads to performance problems and lack of transactional integrity. There are many reasons why this happens: the inherent complexity of the real world, which has few clear boundaries; insufficient programming language support for dynamic multi-object grouping; and weak design practices.
-
To illustrate the problem think of a simple order management system built from three object classes: <code>Order</code>, <code>OrderLine</code>, and <code>Item</code>. The object model can be traversed as <code>order.orderLine.item</code>. Assume now that the item price must be updated. What should happen with confirmed and delivered orders? Should their price also be changed? In most cases certainly not. To secure that rule, item price can be copied into <code>orderLine</code> together with the quantity.
+
To illustrate the problem, consider a simple order management system built from three object classes: <code>Order</code>, <code>OrderLine</code>, and <code>Item</code>. The object model can be traversed as <code>order.orderLine.item</code>. Assume now that the item price must be updated. What should happen to confirmed and delivered orders? Should their price also be changed? In most cases, certainly not. To secure that rule, the item price at the time of purchase can be copied into <code>orderLine</code> together with the quantity. Another example is to think about what happens when an order is canceled, and its corresponding object deleted. Should attached <code>orderLines</code> be deleted? Most likely, yes. Should the referenced items be deleted as part of an order? Most likely not.
-
Dealing with this type of problem at large leads us to a set of design heuristics that was first published by Eric Evans in his book Domain-Driven Design under the heading ''aggregates''. An aggregate is a set of objects defined to belong together and, therefore, should be handled as one unit when it comes to updates. The pattern also defines how an object model is allowed to be connected, with the following three rules considered to be the most important:
+
Dealing with this type of problem at large leads us to a set of design heuristics first published by Eric Evans in his book [http://domaindrivendesign.org/books/index.html Domain-Driven Design] under the heading ''aggregates''. An aggregate is a set of objects defined to belong together and, therefore, should be handled as one unit when it comes to updates. The pattern also defines how an object model is allowed to be connected, with the following three rules considered to be the most important:
# External objects are only allowed to hold references to the ''aggregate root''.
# External objects are only allowed to hold references to the ''aggregate root''.
Line 9: Line 9:
# Member objects exist only in context of the ''root''.
# Member objects exist only in context of the ''root''.
-
Applying these rules on our simple order management system the following can be stated: <code>Order</code> is the ''root'' entity of the order aggregate. The aggregate has one member object <code>orderLine</code>. <code>Item</code> is the ''root'' of another aggregate. Deleting an order implies that all of its <code>orderLines</code> are deleted within the same transaction. Items are not affected by changes to orders. Orders are not affected by changes to items.
+
Applying these rules on our simple order management system the following can be stated: <code>Order</code> is the ''root'' entity of the order aggregate while <code>orderLine</code> is a member. <code>Item</code> is the ''root'' of another aggregate. Deleting an order implies that all of its <code>orderLine</code>s are deleted within the same transaction. Items are not affected by changes to orders. Orders are not affected by changes to items.
-
Identifying aggregates can be a difficult design task, where refactoring and domain expertise is a must.
+
Identifying aggregates can be a difficult design task, with refactoring and domain expertise a must. On the other hand, the aggregate pattern is a powerful tool to reduce coupling, taking out enemy number one in our struggle for good design.
By [[Einar Landre]]
By [[Einar Landre]]
-
This work is licensed under a Creative Commons Attribution 3
+
This work is licensed under a
 +
[http://creativecommons.org/licenses/by/3.0/us/ Creative Commons Attribution 3]
Back to [[97 Things Every Programmer Should Know]] home page
Back to [[97 Things Every Programmer Should Know]] home page

Current revision

Despite that fact that architects and developers know that tight coupling leads to increased complexity, we experience large object models growing out of control on an almost daily basis. In practice, this leads to performance problems and lack of transactional integrity. There are many reasons why this happens: the inherent complexity of the real world, which has few clear boundaries; insufficient programming language support for dynamic multi-object grouping; and weak design practices.

To illustrate the problem, consider a simple order management system built from three object classes: Order, OrderLine, and Item. The object model can be traversed as order.orderLine.item. Assume now that the item price must be updated. What should happen to confirmed and delivered orders? Should their price also be changed? In most cases, certainly not. To secure that rule, the item price at the time of purchase can be copied into orderLine together with the quantity. Another example is to think about what happens when an order is canceled, and its corresponding object deleted. Should attached orderLines be deleted? Most likely, yes. Should the referenced items be deleted as part of an order? Most likely not.

Dealing with this type of problem at large leads us to a set of design heuristics first published by Eric Evans in his book Domain-Driven Design under the heading aggregates. An aggregate is a set of objects defined to belong together and, therefore, should be handled as one unit when it comes to updates. The pattern also defines how an object model is allowed to be connected, with the following three rules considered to be the most important:

  1. External objects are only allowed to hold references to the aggregate root.
  2. Aggregate members are only allowed to be accessed through the root.
  3. Member objects exist only in context of the root.

Applying these rules on our simple order management system the following can be stated: Order is the root entity of the order aggregate while orderLine is a member. Item is the root of another aggregate. Deleting an order implies that all of its orderLines are deleted within the same transaction. Items are not affected by changes to orders. Orders are not affected by changes to items.

Identifying aggregates can be a difficult design task, with refactoring and domain expertise a must. On the other hand, the aggregate pattern is a powerful tool to reduce coupling, taking out enemy number one in our struggle for good design.

By Einar Landre


This work is licensed under a Creative Commons Attribution 3

Back to 97 Things Every Programmer Should Know home page

Personal tools