Rich domain model. Anti anemic domain model

558 views Asked by At

A lot of discussions, like this and this, go with RICH DOMAIN MODEL

and there are 2 strong reason about amenic, like 1 and 3:

Now let's say that I need to make sure that I need to validate that the product exists in inventory and throw exception if it doesn't.

so there is a question: If we don't need an object to be dependent on ISomeRepository like service, can we just make this:

public void Order.AddOrderLine(IEnumerable<Product> products, Product product)
{
    if(!prosucts.Contains(product))
         throw new AddProductException

    OrderLines.Add(new OrderLine(product));
}

and call it like this:

Order.AddOrderLine(ISomeRepository.GetAll(), product);
2

There are 2 answers

0
Euphoric On

If you read about DDD, you would see that Repository is core concept of DDD. In DDD, repository is part of domain and says what kind of behavior the domain requires from it's persistence to work. In your case, you could simply pass the repository into the method and have the method pull the necessary data.

public void Order.AddOrderLine(ISomeRepository repo, Product product)
{
    if(!repo.ProductExists(product))
         throw new AddProductException

    OrderLines.Add(new OrderLine(product));
}

// call it like
Order.AddOrderLine(someRepository, product);

I think the problem of your confusion is that repository, or more precisely, it's abstraction, is often tied to the persistence itself. Which is actually misconception caused by misunderstanding of the whole pattern. Correct repository consists of 2 parts: the abstraction, usually represented by interface, which defines what kind of operations the domain requires from the persistence. And the concrete implementation, that implements those operations over used persistence technology.

8
MattDavey On

It sounds like there's a missing concept in your domain here. I'd think about introducing some kind of StoreInventory entity, such that products move out of the inventory and into an order (this is called 'picking' in many commerce domains).

interface StoreInventory
{
    IEnumerable<Product> AvailableProducts { get; }
    Product PickProduct(guid productId); // This doesn't have to be an Id, it could be some other key or a specification.
}

void Order.AddOrderLine(StoreInventory inventory, Product product)
{
    if (!inventory.AvailableProducts.Contains(product.Id))
        throw new AddProductException();

    var item = inventory.Pick(product);
    OrderLines.Add(new OrderLine(item);
}

This would seem to be more closely aligned to reality to me. But as always in DDD, only your domain experts can tell you how things are supposed to flow.

This also seems more extensible in the future, for example with this model it would be easy to introduce multiple stores - each with their own inventory.