How to query a child object within an aggregate root on demand

aggregatedomain-driven-design

I'm learning DDD. For a practice, I'm trying to convert my own app to DDD aggregates.

What I understand so far on aggregate.

  1. Aggregate defines transactional boundary
  2. Design aggregate as small as possible
  3. If there is no invariant to protect, I might not need an aggregate.
  4. You need to load everything from an aggregate.

I have a simple example. When a user uploads an image and information on the image, my app creates products based on the image.

I have Asset aggregate and Asset has many Product entities (?)

class Asset
{
     public function newProduct(ProductType $productType) {
       // return a new Product object then save id internally
     }
}

When I add a new product to Asset, I save product id to Asset.
When I load Asset from its own repository, I get a problem. Since I have more than 30+ product types, it is not optimal to load all products together. Since a Product can't exist without an Asset and a Product id must be persisted to an Asset, I have a business logic to protect.

Do I really need to load all products when I load an Asset?

Can I have a method in Asset that accepts a DAO to retrieve a product on demand? or a domain service to retrieve a product from an Asset?

class Asset
{
    public function getProduct(ProductType $productType, aDAO $dao){

    }
}

Update: Asset can't have duplicate Product

Best Answer

In such situations, I'd ask myself if the business logic or model is right, not what I've implemented or what is best for software. One other thing that is important for Aggregate and DDD is ubiquitous language and implementation as business logic dictates, not what is best in software sense. So stuff like copy/paste in DDD is allowed (of course, this is a broad subject and should not be taken literary).

What puzzles me is the following sentence:

When a user uploads an image and information on the image, my app creates products based on the image.

You say that product is created based on information that are entered with the image. So, a user enters an image and some information about it and based on these information you create products. As I understood, Asset is not based on products but on informations contained in images. Also, I don't really think that products don't share the same information or images. Therefore it's more of a many to many relation based on information and, probably, information can be interconnected with multiple images.

Like you said, aggregates define transactional boundary. In that case you can ask yourself a business logic question (irrelevant of how you've implemented it)

If I delete an Asset, MUST all related products be deleted as well? Are these products independent from other Entities?

If the answer is yes, ask yourself if the model is right, have you really implemented the model according to business logic. Go to the roots, the business logic defined by domain expert and business folks, not what is currently implemented.

Related Topic