marcosh
marcosh

Reputation: 9008

Provide dependencies to give behaviour to Entities

This is kind of a general question, so I'll try to describe my use case hoping that it'll be clear enough

I have created a set of entities to model my domain. Every entity has its own attributes describing its properties.

Suppose one is the User entity (I use PHP for the example)

class User
{
    private $email;
    private $password;
}

Now I would like to give my entities some more advanced behaviour than getting and setting its attributes.

For example suppose I'd like to create such a method

public function authenticate($email, $password) 

To do this, the methods I'd like to write need some dependencies. In the example this could be an AuthenticationService.

Now, my question is, which one is the best practice to pass these dependencies to my method?

Some options could be:

1) Do not pass dependencies. Put all the entity behaviour in some other service.

2) Pass the dependencies in the constructor on my Entity. If so my question is: is it correct that an Entity depends on an external service?

class User
{
    private $authenticationService

    public __construct($authenticationService)
    {
        $this->authenticationService = $authenticationService;
    }
}

3) Pass the dependencies as arguments of my method call

public function authenticate($email, $password, $authenticationService)

Which is the best solution? Are there any options other than the one that I listed above?

Upvotes: 1

Views: 41

Answers (1)

Henrique Barcelos
Henrique Barcelos

Reputation: 7900

Well, this is a very old discussion about what Martin Fowler calls the anemic domain model anti-pattern.

Although I by no means think I am more qualified to talk about this than the great Martin Fowler, I pretty much agree this article about anemic domain models being more respectful to the SOLID design principles.

So, IHMO, if User is an entity, so it should be something like a POPO (Plain Old PHP Object), or maybe have some logic inherent to itself, like for example:

class User {
    //...
    public function isAdmin() {
        return $this->role == self::ROLE_ADMIN;
    }
    //...
}

When you make an AuthenticaionService object part of your entity through composition, you are probabaly breaking the Single Responsibility Principle (SRP) and surely breaking the Separation of Concerns principle (SoC).

Also, you can think this way:

An User is an entity because it exists by itself, it does not require anything else to be an user. While an AuthenticationService is a service (duh!) that will check for previleges of an user. So, it depends on an user to be useful.

Therefore, an User object should be a parameter of the AuthenticationService object and not the other way around.

Upvotes: 2

Related Questions