0

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

1 Answers1

2

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.

Jakub Lortz
  • 13,858
  • 3
  • 20
  • 32
  • 1
    If you have a domain the `UserRepositoryInterface` should be created in the domain layer. – plalx Nov 07 '15 at 14:14
  • Thank for the response Jakub, although I think repository interfaces must be defined in the domain layer. The approach I've done in this, still gets coupled with the Infraestructure layer and HTTP specific issues as you mention, so I came across with Commands and CommandHandlers, I'm trying to take another way to make this properly well-built. – Marcos Segovia Nov 08 '15 at 14:23