Ports and Adapters: The Hexagonal Core

Hexagonal Architecture (also known as Ports and Adapters) is an architectural pattern that moves from a layered model to a "centered" model. The goal is to isolate the application's core logic (the Domain) from external concerns—UI, databases, and third-party APIs—by using explicit interfaces (Ports) and implementations (Adapters).

I. The Core Philosophy: Dependency Inversion

In a traditional layered architecture, the Business layer depends on the Data Access layer. Hexagonal Architecture flips this:

II. Anatomy of the Hexagon

1. The Inside: Domain and Ports

The core contains only business logic. It has zero dependencies on frameworks (like Spring) or drivers.

2. The Outside: Adapters

Adapters bridge the gap between the Port and the external technology.

III. Concrete Example: Decoupling Page Storage

In Wikantik, the PageManager interface is a Driven Port. The engine doesn't care if pages are stored in a Git repo, a database, or a cloud bucket.

The Port (wikantik-api)

public interface PageRepository {
    void persist(WikiPage page);
    Optional<WikiPage> fetch(String id);
}

The Adapter (wikantik-main)

public class JdbcPageRepository implements PageRepository {
    private final JdbcTemplate jdbc; // Implementation detail

    @Override
    public void persist(WikiPage page) {
        jdbc.update("INSERT INTO pages...", page.getId(), page.getContent());
    }
}

IV. Technical Integrity: Preventing Leakage

A common failure in "Hexagonal" systems is Framework Leakage. If your WikiPage entity in the core hexagon contains JPA annotations (@Entity, @Table), you have leaked infrastructure into the domain.

The Wikantik Standard:

  1. Pure Entities: Entities in wikantik-api are POJOs or Records with zero annotations.
  2. Mapping Layers: The Adapter is responsible for mapping Domain Entities to Persistence Entities (e.g., mapping a WikiPage to a PageDbo).
  3. No Persistence in Domain: Domain logic never calls save() or commit(). It returns events or updated state; the Application Service (the driving port implementation) handles the persistence orchestration.

See Also: