Skipping Incoming Ports

Learn why you should skip incoming ports.

While the outgoing ports are necessary to invert the dependency between the application layer and the outgoing adapters (to make the dependencies point inward), we don’t need the incoming ports for dependency inversion. We could decide to let the incoming adapters access our application services directly, without incoming ports in between, as shown in the figure below.

Skipping incoming ports

By removing the incoming ports, we have reduced a layer of abstraction between incoming adapters and the application layer. Removing layers of abstraction usually feels rather good.

The entry points

The incoming ports, however, define the entry points into our application core. Once we remove them, we must know more about the internals of our application to find out which service method we can call to implement a certain use case. By maintaining dedicated incoming ports, we can identify the entry points to the application at a glance. This makes it especially easy for new developers to get their bearings in the codebase.

Enforcing architecture

Another reason to keep the incoming ports is that they allow us to easily enforce architecture. Using the enforcement options from the chapter “Enforcing Architecture Boundaries”, we can make certain that incoming adapters only call incoming ports and not application services. This makes every entry point into the application layer a very conscious decision. We can no longer accidentally call a service method that was not meant to be called from an incoming adapter.

Small applications

If an application is small enough or only has a single incoming adapter so that we can grasp the whole control flow without the help of incoming ports, we might want to do without incoming ports. However, how often can we say that we know that an application stays small or will only ever have a single incoming adapter over its whole lifetime?