Is it considered Anemic Domain Model Anti-pattern if

a data object is stored inside the domain model? Like this sample script provided?


class User extends DomainModel{
    protected $id = -1; // a primary key
    protected $data; // stores basic data for user in primitive type format
    protected $profile; // a proxy field for user profile object
    protected $validator; // a user validator reference
    protected $mapper; // a user mapper reference

    public function __construct(UserData $data = NULL){
        if($data){
            $this->id = $data->getID();
            $this->data = $data;
        }
    }

    public function getID(){
        return $this->id;
    }

    public function getUserName(){
        return $this->data->getUserName();
    }

    public function setUserName($username){
        $this->data->setUserName($username);
    }

    public function getPassword(){
        return $this->data->getPassword();
    }

    public function setPassword($password){
        $this->data->setPassword($password);
    }

    public function getEmail(){
        return $this->data->getEmail();
    }

    public function setPassword($email){
        $this->data->setEmail($email);
    }

    public function getProfile(){
        if(!$this->profile){
            $this->getMapper();
            $profileMapper = $this->mapper->getProfileMapper();
            $this->profile = $profileMapper->findByID($this->id);
        }
        return $this->profile;
    }

    public function getMapper(){
        if(!$this->mapper) $this->mapper = new UserMapper;
        return $this->mapper;
    }

    public function getValidator(){
        if(!$this->validator) $this->validator = new UserValidator;
        return $this->validator;
    }

    public function setValidator(UserValidator $validator){
        $this->validator = $validator;
    }

    public function validate(){
        $this->getValidator();
        return $this->validator->validate();
    }

    // other domain logic goes below
}


So the domain model class does have business logic in it, it can validate, calculate and even act as factory for other models that has one to one or one to many dependency on it(a userprofile model to a user model is a good one). However, its data is encapsulated inside a data object, which has only protected fields and public getter/setter methods. My question is, is this design considered anemic domain model anti-pattern? Its a bit tricky here though, 'cause the domain model itself does not look like an anemic domain model, but if you look at the data object it does not have domain logic. I am actually still a bit confused at what the precise definition for anemic domain model is. Anyone mind elaborating this a bit and Id like to know if this kind of domain model in which the data fields are stored in a data object is considered an anti-pattern. Thx.

umm no one knows the answer? Is this question too complex?

I think it is more that it is very subjective and not really related to models but just general design.

  1. Moving clumps of related data into an object is good (http://sourcemaking.com/refactoring/data-clumps)
  2. Using delegation instead of passing the object straight out in an accessor can also be viewed as good.
    http://sourcemaking.com/refactoring/hide-delegate
    Though there is an inverse refactoring called remove middle man
    http://sourcemaking.com/refactoring/remove-middle-man

The way to look at it is the design of software is both reactive and opportunistic, you try and put behaviour
in the best place behaviour can go. Primitives block this which is why primitive obsession is viewed as not and
ideal practice (http://sourcemaking.com/refactoring/primitive-obsession). They block the balanced spread of behaviour
that would of naturally occured while doing iterative design.

For example having a UserData class instead of primitives allows the opportunity of adding behaviour to the UserData class
instead of being forced into the user Model such as instantiating a UserData variant that can be viewed as
equivelent to Null similar to a NullObject( http://sourcemaking.com/refactoring/introduce-null-object ). This
is more about how you want it to fail if the $user->getID() != -1 check is not done externally prior to accessing
the getUserName method as should it really possibly fatal, if it should be fatal would an
exception with a stacktrace be better?

eg. using the override method technique to trigger exceptions


class InvalidUserData extends UserData {
	
	public function getPassword(){
		throw new BadMethodCallException();
	}
}


It is a big topic from just a little bit of code.

Thanks for your input. I am not sure if you really were answering the exact question I was asking, but the details you provided such as NullObject were really interesting and practical.

Well all those articles are actually from the Refactoring book by Martin Fowler who is often referenced on things like the AnemicDomainModel(http://martinfowler.com/bliki/AnemicDomainModel.html) by other authors so the question really is would he not use the techniques he has made of lot off of promoting when creating/modifying a domain model, basically is the domain model so different from any other piece of code it is exempt from following those practices. I personally believe it does not and I don’t think he would either judging from everything I have read, especially when doing TDD as if you were not allowed to inject any behaviour into a domain model you would end up with something very fat to test( such as UserData->setId could actually handle int validation and throw an exception etc if it was not satisfied and be tested in isolation ).

What denotes the behaviour of the class is the external contract ( public or protected methods ) not the internal implementation so if a model has the public/protected methods to achieve the end result it is achieving the end result, the external consumer of the model doesn’t really care as all it is concerned with is that it does not have to do the work the model should in the end be doing. If the model is not doing enough then feature envy (http://sourcemaking.com/refactoring/feature-envy) may become apparent.

Basically I think what indicates an Anemic Domain Model is not how it is composed but what type of interactions it forces when consumed throughout a project.