Question

Let's say i got 2 entities - Foo and Bar. Foo is an aggregate root and contains Bar. As far as i understand, it should look like this:

public class Foo{
    private readonly Bar Bar;
}

I want to provide functionality for users to choose Bars for Foos from a defined list (and change it).

If repositories are supposed to be for aggregate roots only it means that there will be no repository for Bar entity.

This leads to problem - Bar can't be created/updated independently without a reference to Foo.

Does that mean that Bar is supposed to have a repository despite that it has no meaning without a Foo?

Was it helpful?

Solution

If you want to select from a list of Bars where they're not associated with Foo, then this is not an aggregate root. For example, you can't get list of OrderItems without their Order, so this is single aggregate root (Order), but you can get list of Products to assign to OrderItems, so Product is not part of the Order aggregate root.

Notice that while OrderItem is part of Order aggregate root, you can still create and update it independently. But, you cannot get it without reference to Order. Same for your Bar, even if it was part of Foo, you could get each(Foo.Bars) and work with it, or do Foo.AddBar(new Bar()). But if you need to get List without Foo, Bar is not part of Foo aggregate. It is a separate entity.

Well, that's how I see DDD here, but I'm not Eric Evans, of course.

OTHER TIPS

The reasons for having Aggregate roots are:

  1. They provide controlled and directed access to composite entities
  2. They can enforce rules to ensure that the entire aggregate is valid

My take: If you need to select Bar objects without a Foo, use a BarRepository.

But... What if you update a Bar, and it breaks a validation rule for it's parent Foo? If this could happen, you should access Bar via it's parent Foo.

If, however, you need to access a bunch of Bar objects (e.g for a batch job or report), and you know that Foos won't get broken, go ahead and access them via BarRepository.

Remember that aggregate roots can be composed of other aggregate roots. You may discover that Bar is an aggregate root itself, giving you justification for a BarRepository :)

Are you sure that Bar need to be a entity? Do you have the need to track it and change it in the domain? If you can look at it as a value object, I would suggest that you fetch it from a service and then "connect" the selected value object to the Foo entity. For instants through a dropdown list.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top