Exploring the Hexagonal Architecture
A Ports and Adapters architecture style, or a Hexagonal Architecture, makes a clear separation between the domain model and the devices used for inputs and outputs, Ian Cooper explains in a presentation about architecture styles, specifically the Hexagonal Architecture.
Layered systems are an architectural style used essentially to avoid coupling, which Ian, a software developer since 20 years and a Microsoft MVP, believes is the biggest enemy of software maintainability especially in large scale systems, the more things are coupled the harder it is to change anything without ripple effects, testing becomes harder, the ability to understand and reason about the impact of change becomes harder.
Ports and Adapters is an example of a layered architecture, it conforms to all the constraints and properties of a layered system. Ian prefers the name Ports and Adapters to Hexagonal Architecture in order to avoid questions if the number of sides in the hexagon is of any importance, which it is not.
A hexagonal architecture has three layers with the key part being the Domain model containing all the logic and rules of the application. No technology concerns, e.g. HTTP contexts or database calls, are referenced in the domain, allowing changes in technology to be made without affecting the domain.
Around the domain model is the Ports layer receiving all requests that corresponds to a use case that orchestrates the work in the domain model. The ports layer is a boundary with the domain on the inside and external entities on the outside.
Outside the ports is the Adapters layer, the technological stack that takes input in some format and produces output. With e.g. an HTTP request, the adapter transforms it into a call into the domain and marshals the response from the domain back to the client over HTTP. No domain logic is present in an adapter; its only responsibility is a technical transformation between the external world and the domain. Any adapter that adheres to the protocol of a port can use it and multiple adapters may use the same port. One use case Ian describes is switching to a new user interface with both the old and the new using the same ports.
Ian believes that tests should focus on behaviour and by testing directly against a port testing will be ignorant of any user interface in use. A mistake many developers do is testing the internal details of the domain model. This prevents refactoring since changing the implementation details will cause the test to fail. Instead unit testing should be done at the ports boundary which is the public interface that remains inviolate even after changing the implementation details.
Integration tests are only needed for testing of e.g. configuration, for instance testing ORM mapping to verify that the configuration is correct. In the same way system tests at the external boundary consists of just a few confidence tests to verify that everything is hooked together, e.g. that the REST API is working and similar tests.
Alistair Cockburn presented his Hexagonal Architecture 2005 as a solution to problems with e.g. traditional layering, coupling and entanglement.