Documente Academic
Documente Profesional
Documente Cultură
Hexagonal Architecture divides work inside and outside of an app instead of into
layers. This overview covers the benefits and uses of the Hexagonal style in your
work.
Continuing our journey through various architectural styles, we�re now headed for
Hexagonal Architecture, also known as Ports and Adapters.
By separating the core, I mean making the use case and domain logic free of any
outside dependencies. We�re putting the application behavior and business rules in
terms of abstract ports, making our application logic agnostic to the delivery
model. Thanks to this, the most crucial logic of our application is pure and clean
and can be understood without the clutter of different technologies used to make it
work in the production environment. We can also test this �most crucial logic�
without spinning up all those technologies.
The second important concept is thinking in terms of ports and adapters. In Layered
Architecture, there is a significant distinction between the presentation part and
the infrastructure part. The latter is �so important� that we allow the application
and domain logic to depend directly on it. In Hexagonal Architecture this
distinction is non-existent � both presentation and the infrastructure are just the
outside. We simply provide abstract ports and implement adapters to them,
regardless of the type of actor the inside is communicating with. This means we can
swap out the UI, the same way we swap out the database. We can easily swap out both
for the testing purposes and there won�t be any significant implementation
differences.
We should also note here that Hexagonal Architecture does not make any assumptions
when it comes to code organization and, similarly to Layered Architecture, it does
not tell us much about system�s design itself.
Basic Example
Let�s start small. Imagine we�re implementing a console Tic-Tac-Toe game and we
want to ask the player for his next move. We could, of course, bash a Scanner
somewhere and read it directly, but that would not be very testable. We would also
have problems to swap out the human player with a computer � should we make the
computer write to standard input? The Hexagonal approach would be to create a port
for the communication with the player, as the input handling is the part of the
outside and should not be mixed with our Tic-Tac-Toe inside logic:
Then, we would create an adapter to this port that actually does the job:
Look at the current packages and classes and try to identify what�s the inside and
what�s the outside:
Image title
Obviously, the controllers and config classes are parts of the outside. Domain
classes like Owner or Pet will be parts of the inside. The repositories are
interfaces, which fits our idea of a port, but they can contain dependencies on
Spring and use a query language in @Query annotations. This leads to an interesting
question�
Image title
As you can see, we just had to create a presentation layer, same as we did in the
Layered Architecture article.
The second step towards more a Hexagonal Architecture would be to get the use case
logic out of the controllers. Let�s do it for one of the use cases � scheduling a
visit:
From this method, we can derive that the application presents the owner page if
Visit data is valid and prompts the user to correct the data otherwise. Let�s
create a port that handles the UI in these cases:
With this port in place, we can abstract specific view details out of our use case
logic:
The last step would be to create an adapter and use it in our controller:
It�s easy to see how powerful the application service is and how stupid the
controller is in the Hexagonal approach. We could literally implement that part of
Pet Clinic to work in the console while saving the visits to a text file � and the
service logic would remain untouched (as long as we keep using Spring). On the
other hand, it�s even easier to see that we replaced a single small method in a
single class with five methods in four classes.
Summary
To sum things up, Hexagonal Architecture is an approach that divides our software
into an inside and an outside part. The former contains use case and domain logic,
while the latter contains technical stuff like UI, databases and messaging. The two
parts are connected using ports, exposed by the inside, and adapters, implemented
by the outside. By applying this approach, we make our most important code free of
unnecessary technical details and we gain flexibility and testability. Since going
�full hexagonal� is not required to get the benefits it provides, I�d be skeptical
to do that and instead apply interfaces and patterns selectively.