Well, the questions is a little bit broader, so I'll assume that the basics is already defined:
Controller
- FrontController
- Controllers (plugin hooks, request/response object, view handler)
View
- View (template, scripts, partials, helpers)
Model
- Domain model objects
- Domain model repository
- Database abstraction layer
Let me know if I missed something.
Assuming that the above is correct. Now the big question:
Should controllers implement business logic?
// (an example in php)
class UsersController {
public function create() {
$user = new User();
$user->setName($this->getRequest()->getPost('name'));
// ...
}
}
The point is, the create action is deciding which information a user need to be created. Therefore, I'm assuming that it's business logic.
// (an example in php just delegating the job to the repository)
class UsersController {
public function create() {
$this->userRepository->create($this->getRequest->getPost());
}
}
If we delegate the job to the repository, then I'm assuming that now the controller is just doing its job, no business logic in there.
Now the second question. Should repositories deal with create, edit and delete operations?
Finally, it will be common for repositories to populate associations and aggregations. So the user repository
can also populate the user object
with its article
associations, for instance. In this case, should the repository call the article
repository to do so?
Now about the aspect oriented programming:
We need to deal with ACLs
. Whether a domain object or collection is accessible by the current user
is determined by the ACLs
.
Isn't it part of the model?
Should controller implement ACL's checks as a plugin hooked on the pre-dispatch or, since it's business logic, should our repositories know if its methods are accessible by the current user?
Now what I achieved so far
Well, I ended up with a service layer
with protected methods like:
class UsersService extends AbstractService {
protected function _create($data) {
$this->validate($data)
$this->userRepository->create($data);
}
}
and with a overloading (again in php, but in java for instance, we'd assume a proxy)
class AbstractService {
public function __call($method, $args) {
// ACLs checks
// then call the protected method
}
}
My service layer is responsible to hold validations and ACLs checks.
So in the end:
class UsersController {
public function create() {
$this->userService->create($this->getRequest->getPost());
}
}