In my previous blog entry, Improving on POCO Properties, we looked at the benefits we can reap for our domain objects if we represent properties with dedicated helper objects instead of restricting ourselves to the usual C# syntax.
As you may have guessed by now, there are improvements that can be made in other areas as well. In this post, the focus will be on composite objects.
As a concept, an
Order is a single item - a request for a set of desired items to be supplied. As a matter of
modelling, the set of items is usually broken out into a list of related
OrderLine instances. Approaching the model in
this manner is very pragmatic, as it allows us to leverage the power of our tooling, but it is important to remember
OrderLine is mostly a modelling artifact.
In C#, our
OrderLine classes might include details something like this:
Using a simple List to contain the lines provides a minimal set of semantics - lines may be added, removed, and iterated - but nothing more.
Significantly, exposing a list in this manner opens our domain
Order up for external manipulation. Instead of the
Order having sovereign control over its own information, as you would normally expect, any snippet of code with the
will to do so may change the list of order-lines, even if that would make no sense given the current state of the
One way to address this limitation is to change the declarations to this:
This puts our object in the execution path for modifications to the list of order-lines, but has drawbacks of it’s own.
Importantly, any methods to modify the list of order-lines are no longer found on
Lines, but instead on the parent
object , mixed in with other
Order methods, thus impairing discoverability. The author of the
Order class has to
resolve an implementation tension - either spend a tedious time writing simple code to simulate a full IList
implementation (although without actually achieving IList compatibility), or write a minimal interface that perhaps
won’t meet the needs of consuming code.
Fortunately, there is a better way - by using a specialist helper object to provide the additional semantics we
require. The declaration of
Of course, this only becomes interesting when the declaration for
DomainCollection is reviewed:
As you will recall from our previous discussion of the
Property object, the
provide for true dirty tracking, though (of course) in this situation the logic required for the test is more complex.
Also included here is full support for transactionality, permitting changes to be committed or reverted as necessary.
IList<T> interface provides for maximum compatibility - even to passing
into methods expecting a simple
IList<T> or even
IEnumerable<T>. Another possibility introduced by this
implementation is the ability to leverage Linq to Objects functionality in useful ways:
Addressing the problem discussed earlier, where external code might manipulate the list in violation of the current
object state, the events
ItemRemoving allow the parent object to exert veto rights over any attempted
modification. These events would be hooked when the helper object is created, usually within the constructor of the
I hope that you will now be thinking of other ways that the
DomainCollection<T> class might be used to make life
easier. What other ways might simple helper classes make our Domain Model more expressive?