Layered Architecture vs. Hexagonal Architecture
In the article's introduction, I discussed the commonly utilized layered architecture and outlined its drawbacks, including transitive dependencies to the database, blurred layer boundaries, inadequate component isolation, poor testability, and maintainability, as well as limited interchangeability of infrastructure components.
Below, you'll find a comparison between the two architectural patterns. Unlike the hexagonal architecture (here presented in its original form by Alistair Cockburn without explicit ports), the layered architecture prioritizes the database over the business logic:
We often adopt a "database-driven design," focusing initially on devising storage solutions for our model in tables rather than considering the behavioral aspects of our model.
Many developers, including myself, have grown accustomed to the layered model over time, viewing it as the conventional approach to structuring applications around a database.
Doesn't it make more sense to prioritize planning and developing the business logic of an application first? Then, only when necessary, consider the persistence of data. Shouldn't changes in the business logic dictate changes to the persistence, rather than the other way around? I believe so.
As applications grow in complexity, additional dependencies inevitably arise. The subsequent illustration depicts an extended architecture featuring a REST API and integration with a third-party service:
领英推荐
With the hexagonal architecture, the placement of additional components is clearly delineated.
In a layered architecture, it's common for a REST API to be linked directly to the business logic, potentially leading to duplication of business logic already implemented in the presentation layer if not refactored beforehand. Consequently, the business logic acquires an additional dependency on the external service.
I've depicted the "third-party client" as a dashed line since this component is often overlooked, and the interface of the external application is accessed directly from the business layer (or sometimes from the presentation layer).
While the hexagonal architecture introduces a port and two adapters with explicit source code dependencies towards the core, the inter-layer dependency complexity grows: now, we have transitive dependencies extending from the REST API to the data access layer, from the REST API to the third-party API, from the user interface to the data access layer, and from the user interface to the third-party API:
These dependencies expose not just the lower-layer code within the REST API, presentation layer, and business layer, but also all the libraries utilized within them. Consequently, the architectural boundaries become increasingly indistinct.