liveBook · Manning

Port

As explained in AI-Powered Developer: Build software with ChatGPT and Copilot

A port is an interface defining a contract between an application’s domain model and an external system.

A port is an interface that defines a contract at the boundary between a domain model and an external system. In hexagonal architecture, ports keep business logic independent of implementation details such as databases, APIs, and user interfaces. Primary ports expose application use cases to outside callers; secondary ports state what the application requires from repositories or external services. section 3.3

Use a port when a controller or other external entry point would otherwise call application logic directly. The controller depends on the port; an adapter implements that port and translates the interaction to the application component. This extra boundary makes it possible to replace the adapter—for example, to support a command-line application instead of a REST API—without changing the core interaction contract. section 4.3.2

A practical port-and-adapter flow has three parts:

  • Define an interface containing the operations the caller needs, rather than exposing a concrete manager directly. section 4.3.2
  • Implement the interface in an adapter that wraps the application component and delegates each operation. section 4.3.2
  • Update the controller to invoke the adapter, removing its direct references to the application manager. section 4.3.2

REST port for asset operations

An AssetRestPort declares read, create, update, delete, and get_assets operations for Asset objects. AssetRestAdapter implements that interface, receives an AssetManager in its constructor, and forwards each call to it. A FastAPI controller can then call the adapter rather than AssetManager directly, making the REST-facing boundary explicit. section 4.3.2

Listing 4.23 Complete source code for AssetRestPort
from itam.domain.asset import Asset
from abc import abstractmethod
  
class AssetRestPort:
    @abstractmethod
    def read(self, asset_id: int) -> Asset:
        pass
  
    @abstractmethod
    def create(self, asset: Asset) -> None:
        pass
  
    @abstractmethod
    def update(self, asset: Asset) -> None:
        pass
   
    @abstractmethod
    def delete(self, asset_id: int) -> None:
        pass
  
    @abstractmethod
    def get_assets(self):
        pass

Inspect the abstract AssetRestPort contract before comparing it with its delegating adapter implementation. section 4.3.2

Ports add an abstraction layer, so apply them deliberately. Their value is separating the driving REST API from the driven business model and preserving the option to substitute external-facing adapters. Review generated interfaces and adapters to confirm that the contract exposes the intended operations and that delegation remains correct. section 4.3.2

How AI-Powered Developer: Build software with ChatGPT and Copilot covers it

How deep it goes
Defines port roles and works through an abstract CRUD interface, adapter implementation, and controller update.
Examples
Uses an IT asset-management REST controller, AssetRestPort, AssetRestAdapter, and CRUD asset operations.
What it assumes
Assumes familiarity with Python classes, abstract methods, REST controllers, and an AssetManager-style application component.
What you can do after
Build it from scratch by defining a port, implementing an adapter, and redirecting controller calls through it.
How it connects
Connects hexagonal architecture with adapters, domain models, REST APIs, AssetManager, and controllers.

Also explained in

Compare how 3 books explain port →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of AI-Powered Developer: Build software with ChatGPT and Copilot. The section links point to the parts of the book it draws on.