R – Techniques for dealing with anemic domain model

business-logicdomain-driven-design

I've read some of the questions regarding anemic domain models and separation of concerns. What are the best techniques for performing/attaching domain logic on anemic domain objects? At my job, we have a pretty anemic model, and we're currently using "helper" classes to perform the database/business logic on the domain objects. For example:

public class Customer
{
    public string Name {get;set;}
    public string Address {get;set;}
}

public class Product
{
    public string Name {get;set;}
    public decimal Price {get;set;}
}

public class StoreHelper
{
    public void PurchaseProduct(Customer c, Product p)
    {
         // Lookup Customer and Product in db
         // Create records for purchase
         // etc.
    }
}

When the app needs to do a purchase, it would create the StoreHelper, and call the method on the domain objects. To me, it would make sense for the Customer/Product to know how to save itself to a repository, but you probably wouldn't want Save() methods on the domain objects. It would also make sense for a method like Customer.Purchase(Product), but that is putting domain logic on the entity.

Here are some techniques I've come across, not sure which are good/bad:

  1. Customer and Product inherit from an "Entity" class, which provides the basic CRUD operations in a generic fashion (using an ORM maybe).
    • Pros: Each data object would automatically get the CRUD operations, but are then tied to the database/ORM
    • Cons: This does not solve the problem of business operations on the objects, and also ties all domain objects to a base Entity that might not be appropriate
  2. Use helper classes to handle the CRUD operations and business logic
    • Does it make sense to have DAOs for the "pure database" operations, and separate business helpers for the more business-specific operations?
    • Is it better to use non-static or static helper classes for this?
    • Pros: domain objects are not tied to any database/business logic (completely anemic)
    • Cons: not very OO, not very natural to use helpers in application code (looks like C code)
  3. Use the Double Dispatch technique where the entity has methods to save to an arbitrary repository
    • Pros: better separation of concerns
    • Cons: entities have some extra logic attached (although it's decoupled)
  4. In C# 3.0, you could use extension methods to attach the CRUD/business methods to a domain object without touching it
    • Is this a valid approach? What are pros/cons?
  5. Other techniques?

What are the best techniques for handling this? I'm pretty new to DDD (I'm reading the Evans book – so maybe that will open my eyes)

Best Answer

Martin Fowler has written a lot about domain models, including anemic domain models. He also has brief descriptions (and UML class diagrams) of many design patterns for domain models and databases that might be helpful: Catalog of "Patterns of Enterprise Application Architecture".

I would suggest looking at the Active Record and Data Mapper patterns. From the description of your problem, it sounds like your helper classes contain both domain/business rules and database implementation details.

The Active Record would move the helper's domain logic and database code into the other domain objects (like your Entity base class). The Data Mapper would move the helper's domain logic into the domain objects and the database code into a separate map object. Either approach would be more object-oriented than procedural-style helper classes.

Eric Evans' "Domain Driven Design" book is excellent. It gets a bit dry, but is definitely worth it. InfoQ has a "Domain Driven Design Quickly" mini-book that is a good introduction to Evans' book. Plus "Domain Driven Design Quickly" is available as a free PDF.

Related Topic