Starbucks-fueled Developer

Wednesday, April 06, 2005

Aggregates, Ho!!!

I discovered my first Aggregate!!! Cha-ching!!! Finally, all this model/test-driven design research has "paid off"...

If only that were the case.

In finding the Holy Grail of OO design, I also found that my persistance layer, drafted ever-so-horribly by yours truly, doesn't appear to easily accomodate such a design...

Thinking about this more, however, has posed an interesting question: why should the persistance layer care about Aggregates? Unless I'm terribly missing something, the mechanism by which objects are persisted shouldn't have an knowledge or interest of what an Aggregate is or what objects compose which Aggregates...Right?

I think I'm still stuck on the same path that I was before I took that blogging hiatus. Here (I hope...) is an Aggregate scenario that has me stuck in the "Procedural Age". I wish I was able to write this out as a User Story but, unfortunately, I'm just not there yet...

In a Product/Inventory System, you need a method of abstracting all the different kinds of products you're going to be selling. Hense, the Product class is born. Each product type (more on this to come) subclasses Product so that they inherit all the necessary/required data and add their own. For Example, Book subclasses Product and adds properties like ISBN and Title and inherits Product Number and Description.

Here's where, I feel, it gets ugly...In fact, I'm sure some will cring in reading this but I'm not sure how else to convey what I'm thinking :)

Let's say there's some business rule that says, "If it's a Book, the Price has to be at least $15". Again, as a developer from the "Procedural Age" my code gets...well, knarly...trying to apply this business logic in the UI. It's like I need a Product Type object, or something, that says "hey, this is a Book, so we need to make sure the Price is at least $15". I say that I need a Product Type object because this is precisely the kind of data that the users maintain; the company gets a new CEO and he says "nope, if it's a Book, the Price needs to be at least $10 because we're not selling enough of them". By creating this Product Type Entity, the users are then able to update it ONCE, effect each appropriate Product, and not have to issue a change order to my company because we hard-coded the validation "If Book.Price < $15 Throw New ArgumentOutOfRangeException()"

So I have Product Type, Product, and all my subclassed-Product entities...This is an Aggregrate, correct? I cannot create a new Product if I do not also assign it a Product Type...I almost wrote "Create a new Product Type"...Wow...Am I getting lost in all this...

The Bottom Line

In my scenario above, each Product Type helps determine how to further validate new Products. However, since I decided to build my Products by subclassing from a base object, I already have "types". If I combine the information that I'm looking to store in my Product Type entity into the Product entity, I believe that will produce duplicate data as every time a new Book is created, the user will be forced, in this scenario, to re-enter the values for determining a valid Price.

Where do you draw the line?!


  • Not everything is a subclass, so you shouldn't be surprised to find that inheritance doesn't solve all domain problems.

    Your pricing looks like it might be solved by associating a PricePolicy object with the Product.

    You can create a PricePolicy interface and create implementations of it that have the correct rules for the different types of pricing. Put a reference to the PricePolicy on the product class (or interface, depending on which you used). For an instance of a Product, you should be able to retrieve the appropriate PricePolicy, and to change the price policy if needed by assigning another PricePolicy object to the Product.

    Here's a pretty good description of aggregates:

    Essentially, aggregates are groups of logically associated objects, like Order and LineItem. An aggregate has a root. In this case, Order would be the root.

    Best not to take my word for it though. Look around, and try it out.

    By Anonymous Scott Bellware, at Wednesday, April 06, 2005 1:36:00 AM  

Post a Comment

Links to this post:

Create a Link

<< Home