Alex Rivera | Logout

Techniques for dealing with anemic domain model

Asked 2009-03-04T07:00:58.213
21

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 thi
Edit
Report

1 Answer

0

One approach that you haven't mentioned is using AOP to handle your data access. An example of my recent use of this approach (though vastly simplified for posting purposes) was that I had an Account domain entity which had a debit method, encapsulating the business logic required in order to make a successful debit from the account.

N.B. All code is Java with AspectJ AOP notation...

public boolean debit(int amount) {
    if (balance - amount >= 0) {
        balance = balance - amount;
        return true;
    }
    return false;
}

With the appropriate repository injected into my aspect, I then used a pointcut to intercept calls to this method...

pointcut debit(Account account,int amount) :
    execution(boolean Account.debit(int)) &&
    args(amount) &&
    target(account);

...and applied some advice:

after(Account account, int amount) returning (boolean result)  : debit(account,amount) {
    if (result) getAccountRepository().debit(account, amount);
}

In my opinion this gives a nice separation of concerns, and allows your domain entities to focus entirely on the business logic of your application.

answered 2009-12-19T10:19:08.613

Your Answer