Hexagonal Architecture: How Does It Work?

What is Hexagonal Architecture?

First of all, let’s talk about Software Architecture. Software architecture is a set of patterns that allow programmers and analysts a guide to develop applications following the same line of work. These patterns stablish the structure and interaction between the parts of the software.

Examples of Software Architecture are model-view-controller, layer programming, peer-to-peer, service oriented, etc.

Due to the increasing complexity of systems over the last few years, it is necessary to use a Clean Architecture. The concept of Clean Architecture consists of separate responsibilities using layers and defining dependency rules between these layers. This is the way to build decoupled software third party independent, more testable, reusable and maintainable.

If you want to know more about Clean Architecture and SOLID principles click here.

So Hexagonal Architecture.. What is Hexagonal Architecture? In brief, Hexagonal Architecture is a software architecture that is “clean”, and therefore has to allow an application to be interacted in the same way by real users, third party software, automated tests, or scripts. To achieve this, our application has to be isolated from devices, databases, and third party APIs in execution time.

Ports and Adapters pattern

The Hexagonal Architecture is also known as Ports and Adapters pattern. The main motivation of the ports and adapters pattern is to separate our application or platform into different layers which have their own responsibility. This way, our different layers can evolve in isolation, and we could reuse them individually.

If you want to know more about Design patterns click here.

Hexagonal Architecture - jokiruiz.com
Hexagonal Architecture – jokiruiz.com

Thanks to this decoupling, we also obtain the advantage of being able to test these layers without other external, avoiding double tests. This architecture is represented in the shape of a hexagon. Each side of the hexagon represents a port in or out of the application. 

All input and output interfaces that allow users to interact with the application are called ports:

  • Primary Ports: These ports trigger an event in the application through the User Interface, Testing Interface…
  • Secondary Ports: Ports that provide the necessary information required by the application to execute the business logic. For example, interfaces for repository, database, events, and notifications.

DDD

Domain-driven design (DDD) is a development approach that values the domain model and connects it to the implementation. DDD can lead to software abstractions called domain models. These models encapsulate complex business logic, closing the gap between business reality and code.

As explained before, the hexagonal architecture encourages our domain to be the core of all layers, and not to be coupled to anything external, this fits very well with the idea of DDD.

Example

To exemplify this architecture, let’s think we need a catalog of products module for an eCommerce website. We need to provide an API so an external service could get and create products, and a Database to store the products.

Hexagonal Architecture example - jokiruiz.com
Hexagonal Architecture example – jokiruiz.com

First of all, the main domain object would be the Product entity.

class Product {
    protected $id;
    protected $name;
    protected $description;
    protected $price;
}

The business logic would be the service interface implementation of ProductService, in this case the functionality we need is to retrieve and create products.

interface ProductService {
    public function createProduct();
    public function getProduct();
    public function getAllProducts();
}
  • As I said before, we use ports to communicate with the business logic for each layer. We create one for the API, ProductApiPort:
interface ProductApiPort extends ProductService {}

public class ProductController implements ProductApiPort {
    private $service; // autowired
    public function __construct (ProductService $service) {
        $this->service = $service;
    }
    public function createProduct($product) {
        $product = $this->service.createProduct($product);
        return Message(“200”, “product created”).toResponseAPI();
    }
    ...
}

And another for the database, ProductDatabasePort:

interface ProductDatabasePort extends ProductService {}

public class ProductRepositoryAdapter implements ProductDatabasePort {
    public function createProduct($product) {
        $productEntity = EntityManager.create(“product”, $product);
        return $productEntity;
    }
    ...
}

Conclusion

In conclusion, Hexagonal Architecture helps us to reuse and maintain code as the core logic is independent from the ports. We can change and modify the implementation of the ports without changing the functionality.

What do you think? Do you know another approach to Hexagonal architecture? Let me know in the comments below 🙂

In:

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x