📅 Join me: Clean Architecture for Backend Developers on Wed 26th Aug, 5:00 - 6:30 PM (CEST)
The first time you see Hexagonal Architecture, it can feel like a lot.
Schedule a shipment.
You're used to something like: ShipmentHttpController, talking straight to the ORM and the FedEx API. One class, two integrations.
Then you look at the Hexagonal Architecture version of the same feature:
driving adapter (
ShipmentHttpController)driving port (
ScheduleShipmentUseCase)the hexagon itself (
Shipment,Address,PackageDetails,ShipmentRepository,CourierGateway)driven adapters (
SqlShipmentRepository,FedExCourierGateway).
And here’s where things can get out of hand.
You start creating all of these classes before you actually need them.
The Starting Point
🚫 Problem: No pain yet
One feature, one caller, one integration on each side.
✅ Solution: Ship it as a single class
There’s nothing to abstract until something actually hurts.
One class handles the HTTP request, runs the validation, talks to Postgres through JPA, and calls the FedEx SDK directly. No ports, no adapters, no domain model.
This isn't the design we'd want to keep forever: it’s slow to test and it’s going to get worse as more logic lands in it — but it hasn’t gotten worse yet.
Step 1 — Driven Ports Keep I/O Out of the Way
🚫 Problem: Tests are slow
Every test hits a real Postgres instance and the real FedEx test instance, so they’re slow, and the test instance goes down more often than the code changes.
✅ Solution: Use driven ports for I/O


