I'm learning about DDD and have come up with a strange situation which I'm not entirely sure how to handle. It is my understanding that an aggregate, or an entity with an aggregate, can have a reference to another aggregate root. I have the following scenario, where I want to model a very basic e-commerce website. ShoppingCart and Product are their own aggregate roots
class ShoppingCart {
public id: int
public maxRemainingPrice: number (will be VO in future)
public List<Product> products
addProduct(p: Product) {
if (maxRemainingPrice - p.price > 0) {
maxRemainingPrice -= p.price
products.append(p)
}
}
}
class Product {
public id: number
public price: number (will be V0 in future)
public setPrice(price: number) {
this.price = price
}
}
Now lets say we want to update the price of a Product. This might invalidate the invariant in multiple shopping carts where there is a maximum spending limit. My questions are
- what principal of DDD does this model not follow? I imagine that it has something to do with encapsulating all invariants inside of one aggregate root, so that changes to a Product must go through a shopping cart. But this feels quite backwards.
Lets say I introduce a new entity which is apart of the ShoppingCart, named CartItem
class CartItem {
public id: number
public price: number (will be VO in future)
}
Now lets say that I update ShoppingCart like so
class ShoppingCart {
public id: int
public maxRemainingPrice: number (will be VO in future)
public List<CartItem> items
addProduct(p: Product) {
if (maxRemainingPrice - p.price > 0) {
maxRemainingPrice -= p.price
items.append(new CartItem(p.id, p.price)
}
}
}
This way now the prices are tied to the time that a product is added to a cart, and no changes to a Product can effect the shopping Cart's invariants of price limits. But lets say the business imposes an invariant that "if a product's price is changed, then it must be removed from all shopping carts"
- How would I "remove" an item from a cart if the price changes? It seems like I would have to have a transaction spanning both of these aggregates, Price and ShoppingCart. I really am looking for any solution to changing the model that can mitigate this!