Software Development

Hexagonal Architecture in Practice: Ports, Adapters, and Real Use Cases

Structuring Applications for Testability and Longevity

As software systems grow in complexity, maintaining a clean separation of concerns becomes essential—not just for testability but also for adaptability and longevity. One architectural pattern that addresses this challenge elegantly is Hexagonal Architecture, also known as the Ports and Adapters architecture.

In this article, we’ll break down Hexagonal Architecture, explore how it enables loosely coupled design, and walk through real-world use cases to show how it can future-proof your applications.

What Is Hexagonal Architecture?

Coined by Alistair Cockburn, Hexagonal Architecture promotes the idea that the core business logic should be independent of external concerns such as databases, web frameworks, or messaging systems.

The pattern visualizes the system as a hexagon with:

  • Inside: The application core (domain and use cases).
  • Outside: The infrastructure and interfaces (e.g., UI, DB, APIs).
  • Ports: Abstractions that define how the core communicates with the outside world.
  • Adapters: Implementations of those ports (e.g., JDBC adapter, REST controller).

This separation allows the core logic to remain untouched when infrastructure details change.

Core Components

1. Ports

  • Primary Ports: Define the entry points into your application (e.g., use case interfaces).
  • Secondary Ports: Define how your application interacts with external systems (e.g., repository interfaces).

2. Adapters

  • Driving Adapters: Drive the application by calling primary ports (e.g., controllers, CLI).
  • Driven Adapters: Implement secondary ports to handle infrastructure (e.g., DAOs, API clients).

3. Application Core

This is where your business rules, entities, and use cases live. It has no dependencies on frameworks or infrastructure.

Benefits of Hexagonal Architecture

Testability: Core logic can be tested in isolation without mocking web servers or databases.
Maintainability: Easy to swap out adapters without affecting the core logic.
Scalability: Decouple the app from infrastructure—great for evolving or distributed systems.
Flexibility: Clean separation of concerns leads to better modularity and clearer code boundaries.
Longevity: Adapters may change (e.g., migrating from MySQL to PostgreSQL), but the core remains stable.

A Real-World Example: Bank Account Management System

Let’s walk through a simplified system that manages bank accounts.

Application Core

Domain Model: BankAccount.java

public class BankAccount {
    private final String accountId;
    private BigDecimal balance;

    public void deposit(BigDecimal amount) { ... }
    public void withdraw(BigDecimal amount) { ... }
}

Use Case Port: AccountService.java

public interface AccountService {
    void deposit(String accountId, BigDecimal amount);
    void withdraw(String accountId, BigDecimal amount);
}

Secondary Port: AccountRepository.java

public interface AccountRepository {
    Optional<BankAccount> findById(String accountId);
    void save(BankAccount account);
}

Adapters

Driving Adapter: AccountController.java

@RestController
public class AccountController {
    private final AccountService service;

    @PostMapping("/deposit")
    public ResponseEntity<?> deposit(@RequestBody DepositRequest request) {
        service.deposit(request.getAccountId(), request.getAmount());
        return ResponseEntity.ok().build();
    }
}

Driven Adapter: JpaAccountRepository.java

@Repository
public class JpaAccountRepository implements AccountRepository {
    // Maps domain model to JPA entity and persists
}

Now, if you want to replace your database or switch from REST to gRPC, you only touch the adapters—not the business logic.

Real Use Cases

1. Legacy Modernization

Legacy systems often entangle business logic with infrastructure. By refactoring toward Hexagonal Architecture, teams can extract and protect domain logic before gradually modernizing interfaces (e.g., moving from SOAP to REST or REST to gRPC).

2. Test-Driven Development (TDD)

With clearly defined ports, you can mock dependencies and focus tests on domain logic, leading to faster, more reliable unit testing and CI/CD pipelines.

3. Multiple Interfaces

Want your application to support both REST and CLI? Implement two driving adapters targeting the same ports—no changes to your core logic.

4. Plug-and-Play Adapters

In enterprise applications, business logic often remains stable while integrations evolve (e.g., from in-house databases to cloud-managed services). Adapters make it easy to “plug” new infrastructure with minimal disruption.

Drawbacks and Considerations

🟡 Initial Complexity: For small projects, this separation may feel like overengineering.
🟡 Learning Curve: Developers unfamiliar with the pattern may struggle without training or conventions.
🟡 More Interfaces: You’ll write more interfaces and boilerplate, though this can be reduced with modern frameworks and tools.

Best Practices

  • Treat the domain model as sacred—avoid leaking framework-specific annotations into core classes.
  • Inversion of control is key—application core should never know about adapters.
  • Use dependency injection to wire adapters to ports cleanly.
  • Name clearly—use suffixes like Port, Adapter, and Service for clarity.

Conclusion

Hexagonal Architecture isn’t just a fancy diagram—it’s a practical, battle-tested approach to building maintainable and resilient software. Whether you’re building a microservice or a monolith, it helps you think in terms of core responsibilities vs. infrastructure concerns.

By enforcing boundaries and favoring abstraction, Hexagonal Architecture helps your applications remain testable, adaptable, and ready for change—long after the frameworks and databases have moved on.

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button