views:

589

answers:

2

I have some problems designing the aggregate root. Here is how I see it in my mind :)

Store (the aggregate root)
-> Sales - A store create a sale every day
 -> Zones - A store is divided into zones
    -> Styles - A zone has x number of styles
       --> Colors - A style has x number of colors
    etc..

Now based on this my aggregate root would be the store. However if I were now to create a Repository around that, would it look something like this?

public class StoreRepository()
{
  Store GetById() {...}
  StoreZone GetZone() {...}
  List<StoreZoneStyle> GetStylesByZone() {...}
  List<Color> GetColorsByStyle() {...}
}

Is that a good way to continue? Needless to say that I am new to DDD.

+1  A: 

It seems that "Store" isn't aggregate root because you don't want to hide all functionality for "Zones", "Sales" etc behind "Store" object. That way "Store" object might be very bloated.

"Store", "Zone" and "Sale" could have it's own repository.

Marek Tihkan
Wouldnt it be bloated to have a Repository for each object? After all they are all related to the Store, correct?
vikasde
If there is Repository for each object it's not bloated. They are smaller and more understandable objects (Single Responsible Principle). If you have base class for repository (Repository<TEntity>), then its even less code writing. That way you probably have to write only special queries for those entities.
Marek Tihkan
+1  A: 

I think you need to look at the aggregate boundaries and the entities as something more than just a hierarchy. Chances are, you will have a richer model than that.

The first way to tell if your aggregate is right, is that you can look at each of the entities within it and ask "Does this need to be directly accessed?" If you answer yes, then that entity is likely not a part of the aggregate.

Without knowing more about your domain, I might assume that Store is indeed an aggregate. Sales, on the other hand, are more complex. Yes, sales occur in a store, but do you have a need to look use a sale independently? If you need them outside of the scope of just working with a store, Sales is probably outside of that aggregate.

I am imagining that both Styles and Colors are immutable and repeatable, so they would likely be Value Objects in this case. Are Zones unique to a store, or do they vary?

Personally, I find value in identifying all of the items in the domain on paper (or whiteboard). I will go through a discovery phase with the stakeholder and just get them out there. Then, use these words as leaders in the conversation, trying to understand how they relate. If you interview the stakeholder well enough, the description he/she gives will actually define most of what you are looking for.

Not to beat a dead horse, but the Evans book is definitely worth getting/reading. It is a little dry, but very insightful. For a quick jumpstart, you can read the free book up on InfoQ that is basically a summary of the Evans book.

joseph.ferris
Yes, I would like to access the sales directly as well, probably by just passing the StoreId. I guess I would create a SaleRepository in that case? Zones vary by store. Every store can have separate x amount of zones. Would I create a ZoneRepository here as well? I ordered evans book, however would start already researching my domain. Please let me know if you need any other information. The more knowledge I can get the better I will understand DDD. Thanks again.
vikasde
Aggregate boundaries are probably the most difficult thing in DDD, in my opinion. If you are looking to have to pass a store identifier into a proposed sales repository, there are two possibilities that are immediate. First would be that Sales could be part of the Store aggregate that you have mentioned. The other one could be that a Store could be part of a Sales aggregate. The only way they would really both be aggregates would be if you would need to access both independently and without them requiring direct knowledge of each other. Note that doesn't prevent you from....
joseph.ferris
...holding a reference to another aggregate root. For example, if you determined that both Store and Sales were aggregate roots, nothing prevents a Sale from having a reference to a Store identifier, which you can then use to call the Store repository to get the Store when you need it. As for the Zones, there is a definite relationship to the Store. This strengthens the case that Store *is* an aggregate root and Zone is an entity (since they are not necessarily immutable in the context you described). So, right now, we are sure that Store is an aggregate, containing Zones...
joseph.ferris
... Colors are likely a value object related to a Style. I am still not sure how to treat a Style, though. Can the same Style exist in multiple Zones?
joseph.ferris
Thanks Joseph. Why do you think that there is a definite relationship for a Zone with a Store, but not a Sale with a Store? Both are pretty much part of a Store. However I guess I would like to be able to access them independently by just passing the StoreId. I assume that fact makes them separate aggregates? RE Styles: Yes, same styles can exist in other zones as well.
vikasde
My assumption about Zones would be because they seemingly need to exist within a Store. Although, a Zone could easily be independent of them in the way that you implement it. For example, if you have want to access Zones independently, your domain service for Stores could have a method like GetStoresByZone(), where you would return Stores for a Zone. Conversely, your domain service for Zones could have a method like GetZonesByStore() where only the relevant stores are returned. What would make Zone an aggregate would be if the only way to work with a Zone needs to be be through...
joseph.ferris
...the Zone's identifier. If you are fine with making changes to a Zone through a Store and that shared Zone's changes would impact other Stores, you can leave the Zone as an entity within the Store aggregate.
joseph.ferris
Makes sense. Thanks a lot for your help.
vikasde
Not a problem. Glad I could help. DDD is still relatively new to us, as well. We have been working with it for about six months and just deployed our first "real" project using these practices. You will find that understanding how to build the domain is going to be a trial and error process. Don't be afraid to refactor if you need to. We definitely had changes of heart about aggregate boundaries and value object vs. entity decisions throughout the release, and refactoring helped us to adjust our gameplan on the fly.
joseph.ferris