Reputation: 9008
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
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