Is the Product Category an Aggregate or not?

1,312 views
Skip to first unread message

Eric Quist

unread,
Feb 3, 2011, 7:44:34 PM2/3/11
to DDD/CQRS
Lets say that we have a Product and a Category. The Product would be
an aggregate, but what about Category?

One solution would be to have Product.Categorize(string categoryName)
and Category would only be a value object in this case. It would still
be possible to let the read model store information so that we could
ask for all products belonging to a certain category. One thing that
worries me with this solution is the quality of the information (I
have seen a lot of bad data quality and the pain this causes the
business). The domain can’t really be sure that the category isn’t
spelled differently or using different case for the same category on
different products, resulting in more than one almost identical
category in the read model.

Another solution would be to have Category as an aggregate to. If I
understand Event Sourcing correctly this would mean that I would have
Product.Categorize(Category category) with an event that just contains
the Category id? I mean the event would not reference Category object
and serialize that when storing the event?

The third solution would be to have Category as a regular Entity and
Product.Categorize(Category category). But I could only ask the
repository for the aggregate roots, so there is no way for me to get
the Category object?

I understand that the aggregate should be the conceptual and
transactional boundary, but in some situations I find it hard to know
how to determine if I should have an Aggregate, an Entity or even a
Value object.

Chris Nicola

unread,
Feb 3, 2011, 9:23:49 PM2/3/11
to DDD/CQRS
I had a similar problem today actually so it's funny you should add
this. I think it is very context specific to your problem so my
answer may not help you.

In my case the general concept being modeled is that of a product
catalog. I decided (for now at least the domain model will probably
be refactored a few more times) to model two aggregates:

Product (which encapsulates the state and exposes the behavior of an
individual product)

Catalog (which encapsulated more general concepts about the catalog
including categories and some other stuff)

The behaviors are going to look a bit like this (I'm going to
encapsulate the arguments to save some typing)

So adding a category to a catalog is pretty simple and the state
change would be handled by the event:

Catalog.CreateCategory(CategoryInfo categoryInfo){
ApplyEvent(new CategoryCreated(categoryInfo));
}

Then adding a product to that category would start with this command:

CommandHandler.Execute(AddProductToCategoryCommand command) {
var catalog = repository.Get<Catalog>(command.CatalogId);
var product = repository.Get<Product>(command.ProductId);
catalog.AddProductToCategory(product, command.CategoryName)
}

Catalog.AddProductToCategory(Product product, string categoryName) {
if (CatalogContainsCategory(categoryName))
product.AddToCategory(_categories[categoryName]);
}

Product.AddToCategory(CategoryInfo catInfo) {
ApplyEvent(new ProductAddedToCategory(catInfo));
}

Again this isn't exactly the code, but it's the gist of it. I worked
some of this out today, so it's certainly not perfect and like you I'd
love some feedback on the ideas presented here.

Chris

@seagile

unread,
Feb 4, 2011, 3:10:19 AM2/4/11
to DDD/CQRS
When in doubt, read the blue book to refresh the definition of
aggregate, entity and value object.

Eric Quist

unread,
Feb 4, 2011, 3:14:33 AM2/4/11
to DDD/CQRS
I understand that it is context specific, and in your case it is
probably the correct thing to let category be an aggregate, because it
also encapsulate behavior.
In my case the category is just the category name, no behaivor. When I
think of it like this it feels like it must be a value object, but I
get a little bit concerend about the data quality when creating
category only based on the name. This might very well be the case once
again that I'm to stuck in my old more data-driven thinking. It is
very possible that I should not be affraid, because in the reality the
category will not be misspelled since the user will have the list of
the existing categories from the read model.
If I don't do this I guess that I will end up with a lot of
aggregates, and that also feel like a smell?

Your post brought my own thinking one step forward (but not all the
way, or I want more perspectives).
Thank you!
> > Value object.- Dölj citerad text -
>
> - Visa citerad text -

@seagile

unread,
Feb 4, 2011, 6:09:09 AM2/4/11
to DDD/CQRS
Isn't it rather an issue of who owns that "data"? Does your user have
FixCategoryNameTypoCommand, AddCategoryCommand, ... at his disposal?
Your app may not be about managing categories, but do question how
that data enters into your system. Don't bypass the write model.

Nuno Lopes

unread,
Feb 4, 2011, 7:01:49 AM2/4/11
to ddd...@googlegroups.com

> In my case the category is just the category name, no behaivor. When I
> think of it like this it feels like it must be a value object, but I
> get a little bit concerend about the data quality when creating
> category only based on the name.

1) If you can change anything part of a Category is no longer a value object :)

2) If by changing anything you got a new Category then it would be a value object.

It seams to me that your case in context is the first. It's parts don't describe its value.

Hope it helps,

Nuno


Eric Quist

unread,
Feb 4, 2011, 9:58:13 AM2/4/11
to DDD/CQRS
Hmm ... I had almost decided to let it be a simple value object, My
thought for this was that the Category has nothing more than a name.
This could be handled as an immutable object, aka a value object.

So when using CQRS I was thinking that I could create a list of
Categories in the read model that could be used for filling a combo
box in the GUI so that they could be choosed as category for the
product, but also letting the user enter a new category name. The read
model could also have a list of all products belonging to a category
so that the user could browse the products having a category.

If I would have taken a more traditionally DDD approach, I guess I
would have let the Category be an aggregate in itself. And for me with
a strong entity relationship background, my gut feeling says it should
be an aggreaget. It would probably be good to let the user have a
FixCategoryNameTypeCommand too. One problem for me though, is that
almost everything becomes an aggregate for me than.

Of course I should read the "blue book", but I still value to here how
different people think.

Thanks, Eric

Nuno Lopes

unread,
Feb 4, 2011, 10:18:02 AM2/4/11
to ddd...@googlegroups.com

> So when using CQRS I was thinking that I could create a list of
> Categories in the read model that could be used for filling a combo
> box in the GUI so that they could be choosed as category for the
> product, but also letting the user enter a new category name. The read
> model could also have a list of all products belonging to a category
> so that the user could browse the products having a category.

Well in that case you can't change category names and it has no life cycle. So it is a value object.

Can an Category be deactivated? What happens to say a product with a classification that has been deactivated or removed? So you have any kind of semantics that would suggest this to be possible?

I'm not stating that a Category should be a value object or not. I'm just leaning towards questions you should ask yourself before deciding.

Cheers,

Nuno

Reply all
Reply to author
Forward
0 new messages