I'm working on an e-commerce solution and as part of this we have concepts of things like Stores, Currencies, Payment Methods, Shipping Methods to name a few. For each of these, we have an admin interface so developers can setup a new currency or payment method and configure it's settings. For example, for a currency they could configure to say use a specific symbol for price formatting.
Because these things require direct administration like this, I've understood this to mean that each of these things are DDD aggregate roots and so this is how I've implemented them.
Now, when we come on to the Order aggregate, this then needs to hold reference to some of these other aggregates and also use their values, for example, an order has a Currency property and that Currency needs to be used to format prices in the order.
The thing I'm struggling with is that as I understand it, it's recommended not to reference aggregates directly, instead only reference it's ID. If that is the case, how would I then be able to use the Currency values to format prices without performing constant lookups?
Is my understanding of aggregates correct here? and if so, how should I make reference to the other aggregates without providing folks with the ability to perform actions on those aggregates? (ie, yes an Order has a Currency, but people shouldn't be able to do
My current thought is that I pass the other aggregates into the order like
order.ChangeCurrency(currency); but inside this method convert
CurrencyAggregate into some kind of
CurrencyReferenceEntity which holds the info I will need from the aggregate. Does this sound logical? Or I'm not understanding a key element?
Currencyan entity? Most domains would treat
Currencyas a value object. Following suit would alleviate your problem. FWIW the difference between and entity and an aggregate is conceptual semantics. This "label" can be useful to help understand how a domain works, but from the outside a client (i.e service layer) needn't know the difference. They are both single objects with a unique identity/life-cycle that enforce invariants. The inner-workings are (and should be) a black box.