How do you properly reference an entity inside an aggregate? For example, by the index of a list (doesn't seem smart if you re-order the list); a GUID (thought it was supposed to be local?); or some other incrementing counter?

For example:

class Cart
  public IReadOnlyList<Item> Items => _items.ToList();

  public AddItem(Item item)

  public RemoveItem(/* Item or ItemId or index (int)? */) <- Here
    _items.Remove(xxxxx); // <- And here

  private readonly List<Item> _items = new List<Item>(); // Maybe need different data structure

class Item
  // Local identity here? 

  public int Quantity { get; private set; }

  public Item(Product product)
    // use product properties needed

  // other item properties

It seems wrong for a client to have to return an List<Item> from the Cart to then use the index to remove the Item. Additionally, if I instantiate the Item outside the class prior to adding it, how do I impose a local Id (I would have a GUID if instantiating outside)?

TL;DR how to deal with local identities of entities (i.e. how local is "local")?

  • You should use a GUID to reference a nested entity. Nov 15, 2018 at 5:28
  • DDD doesn't enforce a specific format for internal IDs, only that one should not reference a mutable nested-entity outside the Aggregate.l Nov 15, 2018 at 6:09

1 Answer 1


A client does not add or remove an Item to/from Cart. A client commands the Cart to add/remove Product (VO) and quantity. It’s only an Item once it is in the Cart. Does that make sense? Allowing a client to hold a reference to an Item could potentially break invariants should it modify the Item from outside the Cart aggregate.

In terms of how the Cart keeps track of each Item, this is up to you. Don’t overthink it. Focus on the behavior you would like to achieve and let the data that enables it be an implementation detail. It’s really not important how the inner workings of your Cart are organized. If you want to use a GUID or counter, just do it. Don’t worry about what “seems” right. Maybe you don't even need a List<Item>. There are other ways of organizing the data.

I know that’s probably not what you want to hear, but offering a specific solution would mean bringing the focus of this discussion on the data of your system instead of its behavior. That’s not the DDD way.

  • if Product is a VO wouldn't this imply that it would not hold a SKU since that's a form of identity?
    – keelerjr12
    Nov 14, 2018 at 21:08
  • 1
    The term "Value Object" does not mean an object has no identity, rather, that it's identity is the aggregate of it's values such that two objects are the same if their values are equal (e.g. an EmailAddress). Maybe a Product only has a single SKU property? I have no clue. You are passing Product to Item in your example. For the same reason you don't want to let a client have a reference to an Item, you don't want them to hold a reference to Product either (or make it a VO). Maybe the signature to add an Item to your Cart looks like Cart.Add( string sku, int quantity ). Nov 14, 2018 at 21:37
  • @king-side-slide your thinking makes a lot of sense, but supposing Product lives in another Bounded Context (say, Catalog), where would you make the transition? I'm still learning, but I'd say not to make Cart (BC1) accept a Product (BC2) because that would cause a hard coupling between these two BCs. Then accepting a CartItem into Cart also makes sense because CartItem would be the representation of a Product in the Cart's BC. What do you suggest?
    – Levidad
    May 24, 2019 at 16:52
  • @king-side-slide I just realized the answer to my question above lies in your previous comment: maybe passing the product SKU or something like that. Please disregard the question.
    – Levidad
    May 24, 2019 at 16:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.