Single Responsibility Principle vs Anemic Domain Model anti-pattern

Viewed 5692

I'm in a project that takes the Single Responsibility Principle pretty seriously. We have a lot of small classes and things are quite simple. However, we have an anemic domain model - there is no behaviour in any of our model classes, they are just property bags. This isn't a complaint about our design - it actually seems to work quite well

During design reviews, SRP is brought out whenever new behaviour is added to the system, and so new behaviour typically ends up in a new class. This keeps things very easily unit testable, but I am perplexed sometimes because it feels like pulling behaviour out of the place where it's relevant.

I'm trying to improve my understanding of how to apply SRP properly. It seems to me that SRP is in opposition to adding business modelling behaviour that shares the same context to one object, because the object inevitably ends up either doing more than one related thing, or doing one thing but knowing multiple business rules that change the shape of its outputs.

If that is so, then it feels like the end result is an Anemic Domain Model, which is certainly the case in our project. Yet the Anemic Domain Model is an anti-pattern.

Can these two ideas coexist?

EDIT: A couple of context related links:

SRP - http://www.objectmentor.com/resources/articles/srp.pdf
Anemic Domain Model - http://martinfowler.com/bliki/AnemicDomainModel.html

I'm not the kind of developer who just likes to find a prophet and follow what they say as gospel. So I don't provide links to these as a way of stating "these are the rules", just as a source of definition of the two concepts.

7 Answers

Before I get into my rant, here's my opinion in a nutshell: somewhere everything has got to come together... and then a river runs through it.

I am haunted by coding.

=======

Anemic data model and me... well, we pal around a lot. Maybe it's just the nature of small to medium sized applications with very little business logic built into them. Maybe I am just a bit 'tarded.

However, here's my 2 cents:

Couldn't you just factor out the code in the entities and tie it up to an interface?

public class Object1
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }

    private IAction1 action1;

    public Object1(IAction1 action1)
    {
        this.action1 = action1;
    }

    public void DoAction1()
    {
        action1.Do(Property1);
    }
}

public interface IAction1
{
    void Do(string input1);
}

Does this somehow violate the principles of SRP?

Furthermore, isn't having a bunch of classes sitting around not tied to each other by anything but the consuming code actually a larger violation of SRP, but pushed up a layer?

Imagine the guy writing the client code sitting there trying to figure out how to do something related to Object1. If he has to work with your model he will be working with Object1, the data bag, and a bunch of 'services' each with a single responsibility. It'll be his job to make sure all those things interact properly. So now his code becomes a transaction script, and that script will itself contain every responsibility necessary to properly complete that particular transaction (or unit of work).

Furthermore, you could say, "no brah, all he needs to do is access the service layer. It's like Object1Service.DoActionX(Object1). Piece of cake." Well then, where's the logic now? All in that one method? Your still just pushing code around, and no matter what, you'll end up with data and the logic being separated.

So in this scenario, why not expose to the client code that particular Object1Service and have it's DoActionX() basically just be another hook for your domain model? By this I mean:

public class Object1Service
{
    private Object1Repository repository;

    public  Object1Service(Object1Repository repository)
    {
        this.repository = repository;
    }

    // Tie in your Unit of Work Aspect'ing stuff or whatever if need be
    public void DoAction1(Object1DTO object1DTO)
    {
        Object1 object1 = repository.GetById(object1DTO.Id);
        object1.DoAction1();
        repository.Save(object1);
    }
}

You still have factored out the actual code for Action1 from Object1 but for all intensive purposes, have a non-anemic Object1.

Say you need Action1 to represent 2 (or more) different operations that you would like to make atomic and separated into their own classes. Just create an interface for each atomic operation and hook it up inside of DoAction1.

That's how I might approach this situation. But then again, I don't really know what SRP is all about.

Related