It's been a while since I started to build my DDD/Hexagonal architecture application, and I got quite overwhelmed with the amount of concepts related to both of them.
Though I started to go slightly and trying to apply concepts when I found them necessary. I find that there's still many of them that I cannot or even I do not think about applying into my application, some of them are: Adapters, Commands (CQRS?), Events..
Apart from this, I got a little bit stuck with something that has to do with Hexagonal Architecture. I'm trying to apply the definition of external behavior should depend inwards, so Infrastructure Layer -> Application Layer -> Domain Layer
In my case, I defined Services in my Application Layer as this example of a LoginService:
class LoginUserService implements ApplicationServiceInterface
{
private $userRepository;
private $session;
public function __construct(UserRepositoryInterface $userRepository, Session $session)
{
$this->userRepository = $userRepository;
$this->session = $session;
}
public function execute($request = null)
{
// TODO: Implement execute() method.
$userName = $request->get('user');
$password = $request->get('password');
$user = $this->userRepository->findByUsername($userName);
if (!empty($user) && $user->validate($password)) {
$this->session->start();
$this->session->set('user', array('id' => $user->getUserId(), 'username' => $user->getName(), 'email' => $user->getEmail()));
return true;
} else {
return false;
}
}
}
But, I'm quite sure I'm blowing the dependency statement hexagonal architecture stands for. As my Application Layer is depending on Infrastructure Layer. (In this case, $this->userRepository->findByUsername($userName);
is part of the DoctrineUserRepository injected in the serviceContainer of the application)
My repo is completely available in github: Malendar Repository
How to deal with this Service case which depends on the Database Output? Also, Which concepts do am I skipping that would be pretty nice to use?
Thank you beforehand =D
The UserRepositoryInterface
should be defined in the Domain Layer. If it's in the Infrastructure Layer, you should move it to the Domain Layer.
When you created UserRepositoryInterface
, you created a contract that all Infrastructure Layer implementations must fulfill. It's a textbook example of Dependency Inversion principle.
You can safely assume that the implementations fulfill the contract. This assumption does not create a dependency on Infrastructure Layer.
So, LoginUserService
only depends on UserRepositoryInterface
(which should be a part of Domain Layer) and Session
.
I would be more worried about the Session
dependency and the $request
parameter. I don't know PHP and the framework you use, but in an MVC pattern I'd rather keep both in the controller, delegating the logic to the Application Layer. The rule of thumb is that the Application Layer should not be responsible for dealing with any HTTP-specific issues. I would make the LoginUserService.execute
method accept $userName
and $password
parameters and return the logged-in user details.
It will of course break the implements ApplicationServiceInterface
part, but this interface should be removed anyway. The Application Layer methods will have different parameters and return types.