1

I am looking into using the ports and adapters pattern with layered architecture.

So I'll have the following layers:

  • framework/Infrastructure - i.e. ASP.NET MVC, Entity Framework, SMTP Client
  • application - logic that pulls your application together and performs actions on your domain.
  • domain - Defines how the actions in your domain work. Defines relationships between domain objects

After reading https://softwarecampament.wordpress.com/portsadapters/#tc2-3, https://fideloper.com/hexagonal-architecture and several other articles along with multiple youtube talks, I am still struggling with how to implement driver ports and adapters. I understand the idea of driven ports and adapters as it's something I've done with plain layered architecture.

But I still don't understand how driver ports and adapters would be implemented.

From my understanding, A driver port defines the way a layer outside of it should use the layer in which it is housed. An adapter is the implementation of that port on the layer that's using that port.

But there's something I'm wrestling with... How does the application layer implement an interface to the domain layer? Wouldn't that require the application layer to know the inter-workings of the domain layer? That completely ruins the point of using an interface in the first place. If the domain layer provides an interface that something outside of it should use, and the adapter for that interface is implemented by the layer using the interface, that would mean the user of the interface is also implementing the interface itself. It's like the outside layer is telling the inside layer how to work... which goes against the very nature of de-coupling or even just interfaces in general.

It sounds like the business layer is telling the application layer, "Here's an interface that I'm providing you... IDK how it's gonna work so you tell me." But then why even have the interface in the first place?

Here's some code to demonstrate what I'm picturing:

applicationLayer.UserRegisteringUseCasePort

public interface UserRegisteringUseCasePort
{
    void Register(string username, string password, string passwordConfirm, string name);
}

frameworkLayer.UserRegisteringUseCaseAdapter

public class UserRegisteringUseCaseAdapter : UserRegisteringUseCasePort
{
    private IUserRepository _userRepo;

    public class UserRegisteringUseCaseAdapter(IUserRepository userRepo)
    {
        _userRepo = userRepo;
    }

    public void Register(string username, string password, string passwordConfirm, string name)
    {
        // validation logic
        //... such as:
        if (password != passwordConfirm) {
            throw new Exception("password no match password confirm!");
        }
        userRepo.Add(new User(username, password, name));
    }
}

To me, this seems terrible because now you've forced the framework layer to do validation which should be part of the domain logic (which didn't even get a chance to do it since we stopped at the application layer). This also means that the application layer doesn't actually pull business logic together... It just says what actions it wants to be done but leaves the caller to decide how to do it. It should be the other way around, right?

Summary

I know I said a lot so let me sumarize... How do driver ports and adapters work? How should they be used/implemented in real world scenarios?

Ian Kirkpatrick
  • 1,553
  • 7
  • 23

1 Answers1

1

How do driver ports and adapters work? How should they be used/implemented in real world scenarios?

Driver Ports are the API of the "application" (in HexArch terminolgy, application is the whole hexagon, not to be confused with the application layer). They offer the functionality (use cases, user stories or whatever you call it) of the application to the outside world.

A driver adapter DOESN'T implement a driver port. This is a mistake lot of people does. A driver adapter is a software component outside the application that uses a driver port. The driver port is a dependency of the driver adapter. Examples of driver adapters: a MVC web controller, a REST controller, an automated test framework, etc

The implementation of a driver port is the business logic of the application itself. It is the use case implementation. In your case, you split the hexagon in 2 layers: application layer, and domain. Then the implementation of a driver port would be an application service implementation, that orchestrate the domain objects in order to perform the use case functionality.

Hope my explanation helps.

choquero70
  • 3,332
  • 2
  • 24
  • 40
  • Thank you! The clarification of not implementing interfaces for driver adapters cleared everything up. Now that that's cleared up it's funny cause I've been been doing this all along on personal projects lol – Ian Kirkpatrick Jun 24 '19 at 13:51
  • You are not the only one, there ate many people that misunderstand lot of hexagonal architecture concepts, I recommend to watch the talk Alistair in the Hexagone – choquero70 Jun 25 '19 at 13:29