Amirhosein Al
Amirhosein Al

Reputation: 500

DDD - Can an aggregate method with an aggregate parameter block an action based on that aggregate parameter's state?

Imagine two aggregates Product and Order. An Order instance can have multiple Products as order line items and this association is done using an OrderLine class.
Here are the classes:

public class Order {
    .
    .

    Set<OrderLine> orderLines; 
    public void addProductToOrder(Product product) {
        ...
    }
    .
    .       

}
public class Product {
    .
    .

    int stock
    boolean isProductOutOfStock(int quantity) {
        return stock - quantity < 0;
    }
    .
    .
}

Now imagine the scenario where I want to add a product to an Order. So the application service method would be something like:

{
    order.addProductToOrder(Product product);
}
  1. Given that an aggregate (by definition) must hold its own invariants only the product.isProductOutOfStock check inside order.addProductToOrder is not advised.
  2. Application service should not make business decisions so the check cannot be there either.
    The question is: is this a good place to create a domain service?

Upvotes: 0

Views: 236

Answers (1)

Neil W
Neil W

Reputation: 9112

Given that an aggregate (by definition) must hold its own invariants only

I would restate as:

Given that an aggregate should enforce its own invariants

The invariant in this case would be something like:

"An order cannot be created with products that are out of stock."

And, in your case, it is the Order that is enforcing that invariant. The Product is simply providing a method that allows the Order to enquire about the product stock level.

So, in principle, your approach is fine.

However, be aware that that product and associated stock level will have been retrieved by the Application layer from the repository before it is added to the order. Therefore the value of the (int) stock property in the Product is only as fresh as the last retrieval from the database. Therefore two Orders being created at the same time could result in the first-to-complete assuming enough stock and the second-to-complete also assuming enough stock (without being aware that the first to complete order depleted that stock).

You'll need a strategy to solve that.

Upvotes: 1

Related Questions