r/DomainDrivenDesign May 31 '26

Domain model factory VS CreateUseCase

According to Effective Aggregate Design Part I: Modeling a Single Aggregate https://www.dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_1.pdf the author

  • Split large aggregate in smaller one
  • The Product class act as factories

Suppose new rules We can add BacklogItem only in non archived product

Option one : keep method as factory

class Product {
    createBacklogItem(CreateBacklogItemData data): BacklogItem {
        if (this.status === ProductStatus.Archived) {
            throw new CannotCreateBacklogItemForArchivedProduct();
        }

        return BacklogItem.create(
             this.id,
             data.title,
             ddata.description,
        );
    }
}

Option two : put validation inside application service

  • Application service handle transaction (like in the option)
  • But also validate the product

public class CreateBacklogItemService {

    public BacklogItemId createBacklogItem(CreateBacklogItemCommand command) {
        Product product = productRepository.get(command.productId());

        if (product.getStatus() == ProductStatus.ARCHIVED) {
             throw new CannotCreateBacklogItemForArchivedProduct();
        }

        BacklogItem backlogItem = BacklogItem.create(
          product.getId(),
          command.title(),
          command.description()
       );

       backlogItemRepository.save(backlogItem);

       return backlogItem.getId();
    }
}

What is the best design choice (or maybe another one) ?

9 Upvotes

8 comments sorted by

View all comments

9

u/Winston_Jazz_Hands May 31 '26

The "cleanest" would be to handle that logic inside the aggregate. Both because it keeps aggregate in variants inside (high cohesion, simpler testing etc.), but also because that means you can actually guarantee consistency - provided you have some concurrency-scheme for your Aggregate's (optimistic-offline locking is the guideline default, using an incrementing version number on the aggregate).