Hexagonal Architecture - Hands On
In my previous post about architectures, I gave an short view about the hexagonal architecture. However, it's difficult to identify the base structure of this architecture, mainly if you work in a legacy code. This post is to show a suggestion of a skeleton to guide you to create the first version of your project.
Sources: Tom Hombergs - reflectoring.io
Bringing back some concepts, this architecture has three parts:
- Left side: communication with actors (GUI, API, etc)
- Core: Isolated business logic
- Right Side: communication with back service (database, external service, etc)
To ensure the isolation, the approach use more three concepts:
- Adapters: point to intermediate the communication between different technologies from front to the core.
- Port: Interface to define the contract to access core, front and back service.
- usecase: it should be implemented inner hexagonon and specify functions and events from application. The ports should be mapped to usecases.
Now, with that in your mind let's go to the code.
Skeleton
Here is an option how it can be structured. The image show a structure with three main packages: backservice, core and frontend.
The backservice has the implementation using specific characteristics of an technology. The repository implementation could be a communication with oracle or some external service, for example.
The core package has all the business logic. The example has three functionalities: client, contract and investment. Inside each functionality there are more two packages: business and adapter.
The business has the (1) domain, the main part of the business; (2) the port, with the interface to communicate with back service (the example has a communication with repository); and (3) the usecase, which communicate with frontend.
Note that the interface to communicate with backservice is inside the core, but the implementation is out side the core. It is in the backservice package. It happens to keep the core Isolated.
The same way, usecase has the interface to communicate with frontend, but has an implementation. The detail of technology should be inside the frontend.
The adapter has the implementation to make the communication possible. The example implement an adapter to be the database mock. When the project start, maybe the database is not defined. It is an option to not let the development team waiting for implementation. In this case, you are using the mock and not the repository implementation.
The frontend has a package with adapters and implementations. The adapter can be a way to simulate the calls to the system. The example show an adapter simulate an user interface or even integration tests. The hexagonal architecture has the origin in Agile mind and has a strong idea to use TDD. Then integration test is a weapon to start project when you don't have the interfaces to call the system.
Run
So, let's start to run the example. If you are in the first step you are develop using integration test. The example show the integration test from investment. This test call the adapter from frontend to start the process.
The adapter will do what is necessary to test the application. That will abstract technical issues to test the business.
PS: In a real app you will use framework to instantiate by @Inject. Here, I just want a simple code.
The sequence of calls happen as show bellow.
The same idea happens if you start by AdapterUI. It will use the same sequence. The difference is how to start because will be specific by technology. By the example, the solutions are similar because the idea is to be simple.
Conclusion
This post suggests a structure to the hexagonal architecture but is not 100% right. It will depend on each project. The post wants only to give an overview of how the skeleton can be created.
All the code you can see in my github here.