Reputation: 553
I am trying to get my head around the structure of domain objects, data mappers and services, I am however struggling to grasp exactly what goes where.
This question is very similar, but does not have an answer that helps.
Should methods that require properties from several objects go into;
I am concerned creating a heavy Service class, but this approach seems simpler than editing both the DO and the DataMapper I would otherwise need.
final class UserService extends ServiceAbstract
{
public function user_is_admin($id)
{
// Build the user object
$userMapper = $this->dataMapperFactory->build('user');
$user = $this->domainObjectFactory->build('user');
$user->id = $id;
$userMapper->fetch($user);
// Build the admin usergroup object
$usergroup = $this->domainObjectFactory->build('usergroup');
$usergroupMapper = $this->dataMapperFactory->build('usergroup');
$usergroup->id = ADMIN_USERGROUP_ID;
$usergroupMapper->fetch($usergroup);
// Perform the actual check
if(in_array($user->id, $usergroup->aMembers))
{
return true;
}
}
}
Upvotes: 0
Views: 187
Reputation: 58444
First of all, IMHO, you are performing the authorization check at the wrong level (read this post for more details). And the other thing is - you seem to be returning data to the controllers (or your regional equivalent) from the model layer. Such a boolean
response would indicate, that you have application logic bleeding in your controllers.
If you want to stick you your current structure, then something like this would make more sense:
class UserService
{
// .. snip
public function someMethod( $id )
{
$userMapper = $this->dataMapperFactory->build('user');
$groupMapper = $this->dataMapperFactory->build('user');
$user = $this->domainObjectFactory->build('user');
$user->setId($id);
$group = $this->domainObjectFactory->build('usergroup');
$group->setId( UserGroup::ADMIN_GROUP );
$userMapper->fetch($user);
$groupMapper->fetch($group);
return $group->hasUser( $user );
}
}
my 2 cents
Upvotes: 1
Reputation: 7283
User.isAdmin() struck to my mind at first. But in your case, it seems that User and UserGroup together determine whether a User is admin. So we cannot put the responsibility in either the User or UserGroup.
I usually introduce a Specification object in this situation(Sorry, the example is written in Java).
public class AdminSpec {
private SomeComponetToRetrieveUserGroup userGroup;
public AdminSpec(SomeComponetToRetrieveUserGroup userGroup) {
this.userGroup = userGroup;
}
public boolean isSatisfiedBy(User user) {
// Perform the actual check
}
}
Therefore, the domain objects are not corrupted by undesired responsiblities, and the domain logic still remains in the Domain layer (not in application services).
You can find more details about Specification Pattern in DDD book or http://en.wikipedia.org/wiki/Specification_pattern.
Hope this helps.
Upvotes: 1