2 min read

Hexagonal Architecture (Ports and Adapters)

Hexagonal Architecture, also known as Ports and Adapters, is an architectural pattern used in software design. It aims to create loosely coupled application components that can be easily connected to their software environment by means of ports and adapters.

1. The Core Concept

The main idea is to isolate the Application Core (business logic) from outside concerns (User Interface, Database, External APIs).

  • The Hexagon: Represents the core application. It contains the domain objects and the business rules. It knows nothing about the outside world (no SQL, no HTTP).

2. Ports

Ports are the interfaces that allow data to enter or leave the application core. They define what the application can do or what it needs, without defining how.

Primary Ports (Driving)

These are the entry points. They define the use cases of the application.

  • Example: IUserService interface with methods like registerUser().

Secondary Ports (Driven)

These are the exit points. They define what the application needs from the outside world to work.

  • Example: IUserRepository interface with methods like save() or findById().

3. Adapters

Adapters are the concrete implementations that plug into the ports. They translate data between the format required by the application and the format required by the external technology.

Primary Adapters (Driving)

They trigger the application logic.

  • REST Controller: Converts an HTTP request into a call to the IUserService.
  • CLI: Converts command line arguments into a call to the IUserService.
  • Test Suite: Calls IUserService directly to verify logic.

Secondary Adapters (Driven)

They are triggered by the application logic.

  • SQL Adapter: Implements IUserRepository to save data to a PostgreSQL database.
  • Email Adapter: Implements IEmailService to send emails via SMTP.
  • Mock Adapter: Implements IUserRepository using an in-memory array for testing.

4. Why "Hexagonal"?

The shape is arbitrary, but a hexagon was chosen to visually suggest that an application can have multiple distinct sides (ports) for different types of interactions, rather than just a simple "top-down" layer structure.

5. Benefits

  1. Testability: You can test the core logic in isolation by plugging in Mock Adapters for the database or external services.
  2. Flexibility: You can swap out a database (e.g., MySQL to MongoDB) just by writing a new Secondary Adapter, without touching the core logic.
  3. Independence: The business logic doesn't depend on frameworks or UI.

programming/clean-architecture programming/solid-principles programming/software-testing-basics