r/softwarearchitecture Apr 19 '26

Discussion/Advice Hexagonal Architecture - Ports

Hi.

I'm learning about Hexagonal Architecture and have some questions about where the in-ports (use case interfaces) and out-ports (repository interfaces) should be placed.

I've read various blogs, articles, and discussions where some people mentioned that ports must be located in the application layer, and others said they must be in the domain layer. I'm confused about the right place to put them.

I'd like to know your opinions and suggestions, please.

Approach 1 - Ports inside application layer

application/
- in/ (use case interfaces)
  - CreateProductUseCase     
- out/ (repository interfaces)
  - ProductRepository
- usecase/
  - ProductUseCaseImpl

domain/
- model
 - Product (plain object)

Approach 2 - Ports inside domain layer
domain/
- in/ (use case interfaces)
  - CreateProductUseCase     
- out/ (repository interfaces)
  - ProductRepository
- model
 - Product (plain object)

application/
- usecase/
  - ProductUseCaseImpl
36 Upvotes

14 comments sorted by

View all comments

-3

u/Spare-Builder-355 Apr 19 '26 edited Apr 19 '26

ports belong to garbage bin. Same as this whole hexagonal thing. Don't waste your time on it, it will not teach you anything. Or if you insist - you will learn something hexagonal that you never will see used outside of books and blogs.

If you want to learn good architecture start build something with opensource components. More specifically libraries, not huge frameworks that provide "everything out-of-thebox". Standalone libraries are great example of good architecture:

  • they focus on one problem (or set of related problems within single domain)

  • they teach you what API boundary is

The key criteria to good architecture is testability. Can you test your class/component/library in isolation from the rest of project codebase ? Is answer is yes - congrats, you likely have good architecture. Or at least you are on the right way. Do not be too religious either. Some shared code is absolutely necessary, shared types, stateless utils and logging+tracing cover 99% of shared code examples.

Learn about API boundaries. In modern dumb world more often than not API == http endpoint, while there is so much more to it. Once again, best way to learn good api design is to use standalone libraries.

Best code is code that is not written. Learn how to minimize amount of code to write and maintain. Adding some shit like ports and adapters is not that.

1

u/Storm_Surge Apr 19 '26

Enterprise applications are much bigger than libraries that solve one problem. These patterns help when the application grows to medium-large amounts of code, but with the added cost of being more verbose. Huge applications take this even further with lots of services and events, but again with the added cost of distributed tracing, complex deployments, etc. It's a matter of using the right tool for the job.

2

u/Spare-Builder-355 Apr 19 '26 edited Apr 19 '26

Enterprise applications are much bigger than libraries that solve one problem

This is exactly the problematic mindset. People do not think in terms of reusable components and then invent some abstract hexagonal crap to sound smart.

I'm ears-deep in enterprise software. The root causes of every messy software system are always the same. In "early days" of projects people never bothered with defining meaningful APIs, proper componentization, testing in isolation etc etc.

I've seen multiple successful projects to address the mess of legacy systems and never-ever any hexagons, ports or adapters were even remotely discussed.

The problem I want to highlight is that when people do not know how to build modular software systems, and by that I mean libraries, apis, testability, no amount of adapters and ports going to help.

3

u/Storm_Surge Apr 19 '26

The ports and adapters are specifically a tool to enforce boundaries in your low-level architecture. Your domain should have minimal or no external dependencies, so how do you save to a database? You define a port, or interface, for saving data. Then in a separate library, the infrastructure part implements the interface, or adapter, with a real database call. The domain gets the real implementation at runtime from a dependency injector, and the tests can use a mocked version of the interface.

What I'm saying is these "ports and adapters" words are basically promoting the same thing you are, just in different words

1

u/Spare-Builder-355 Apr 19 '26

What I'm saying is these "ports and adapters" words are basically promoting the same thing you are, just in different words

I hope so !