jakehallas
jakehallas

Reputation: 2506

DDD Handling Associations Between Two Domain Models Dependent Upon Each Other

Diving into the world of DDD is something of a whirlwind for me. While I've done a lot of research I'm struggling to change my thought process.

So, I have a package and a products entity. A package cannot function without products; vice-versa. The problem comes in when I'm needing to get the products belonging to a package (Note: the package is customisable, this means the products belonging to the package could be different the next time round). It seems that this belongs on neither entity, furthermore applying this to the package or product entity would make them tightly coupled.

I must stress that I'm using the word association because I'm trying to figure this out on a domain level rather than infrastructure.

A little thinking has led me to the following thoughts:

It would be great if someone could turn me sane again! Thanks in advance!

Upvotes: 0

Views: 1161

Answers (2)

tomliversidge
tomliversidge

Reputation: 2369

The problem comes in when I'm needing to get the products belonging to a package (Note: the package is customisable, this means the products belonging to the package could be different the next time round).

This sounds like a query. It often helps to separate the modelling of commands (things that can alter your domain model) and queries.

Upvotes: 0

Chris Simon
Chris Simon

Reputation: 6505

Ubiquitious Language

DDD is all about language - the key here is to listen to your domain experts talk about products and packages - how do they think about them? And about the processes involved in working with them?

When they create a package, do they really think to themselves "I must define products with this package", or do they think "I'll setup a package, and then link a few products to it" - if the latter, although it may on first blush feel like a package can't exist without products, notice the subtle implication in the timing - that the package can exist without products, because they expect to link products to it as a second step.

Given that, you might model the link as a completely independent aggregate with a single entity as the root, e.g. PackageProduct (or better yet, some term your domain experts use to define the assocation) and simply create new instances of this aggregate when a product is linked to a package. This entity would have a PackageId and a ProductId on it.

However, if there are business rules, e.g. a Package can only have one product of a given type, or at most 5 products, then make the PackageProduct entity an entity within the Package aggregate, which has Package as the aggregate root. The PackageProduct would have a reference to the Package and a property of the ProductId. See below for some terminology clarification.

Entities vs Aggregates

Based on your question, it seems there might be some confusion about terminology. In DDD, we have:

  • Entities:
    • Have an identity that outlasts any given property
    • Has a mutable state
    • Generally, modelling business processes is all about working out how to mutate the state of entities
  • Aggregate
    • A group of entities over which invariants must be enforced
      • invariants are business rules that MUST hold at all times
    • A single entity is always nominated as the 'aggregate root'
    • Other entities can only refer to the aggregate by the root
    • When modelling a business process in order to mutate state, the aggregate is the boundary within which the states of all entities must be consistent with the invariants.
    • Outside the aggregate boundary, other entities may get updated asynchronously - aiming for eventual consistency
  • Domain Service
    • A service that contains business logic that doesn't belong in a single entity
    • It is generally not just a wrapper around a piece of infrastructure

See https://lostechies.com/jimmybogard/2008/05/21/entities-value-objects-aggregates-and-roots/ for more info.

Read vs Write Operations

The problem comes in when I'm needing to get the products belonging to a package

This sounds a lot like it might be in order to support a UI or a report? In which case - don't stress about the entity model. The entity model is there to ensure the business rules hold while users are trying to modify the state of the system. When doing a read operation, there is no need to modify the state, so you can bypass the model. Define a query that projects your data store onto a DTO and tailor the the projection to suite the needs of the UI or report.

Upvotes: 2

Related Questions