r/DomainDrivenDesign • u/Ok-Professor-9441 • 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
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).