Hexagonal Architecture isn’t new. The idea has been about for a long time, Alistair Cockburn talks about Ports and Adapters, however it hasn’t received widespread adoption. Kevin Rutherford brought Hexagonal Architecture to my attention and I’ve been a little bit enamored with it since.
I won’t repeat poorly what others have already written well, read their work for a more in-depth description of Hexagonal Architecture. Conceptually you can think of Hexagonal Architecture as two hexagons, one inside the other.
The inner hexagon contains Domain objects and has no references to the real world e.g. disk I/O, network, HTTP, XML or any other concept that is used to interface with the real world.
The outer hexagon contains Adapters that manage the interaction between the Domain objects and the real world. They do not have responsibility for any Domain logic.
Everything outside the outer Hexagon is the real world. In reality there would be other hexagonal systems arranged around the outer hexagon, hence why a shape that tessellates is important.
If the Domain objects are not allowed to have any reference to the real world, and the Adapters are part of the real world, then you might ask how do the two work together? The answer is that the Domain contains interfaces that represent what the Domain objects want to do. The Adapters then implement these interfaces.
It is correct for the Adapters to depend on the Domain, but the Domain should not depend on the Adapters. This gives you the power to replace a specific Adapter at any point without changing the Domain objects. Say you want to change from saving something in an XML file to saving it in a database. Just write a new Adapter that stores stuff in the database and plug it in place of the XML file Adapter. The Domain doesn’t change because as far as it knows it’s just interacting with the ‘save this stuff for later’ interface. How it goes about saving it is up to the Adapter objects.
Secondly testing becomes much easier. Duncan Nisbet has looked at hexagonal from the viewpoint of a tester in greater depth. I’ve found the tests for the Domain objects become much easier as they’re all just pure Java. There are no complex integration points to fake for the tests and because they don’t hit the real world in any way they run fast, really fast.
The Adapters become easier to test as well, because they are doing just the adaption between the Domain and the real world without having to include any Domain logic. I’ve found that getting the adapters as thin as possible can be turned into a bit of a sport, unfortunately not one that might qualify for the Olympics. Also the thinner they are, the faster the adapter tests run.
This is all good, but doesn’t explain why I’ve been enjoying Hexagonal Architecture as much as I have. It took me a while to realise exactly what it is. It takes your daily programming life back to that fun stage when you were learning a language.
Writing Domain objects involves a lot of tasks similar to those used when learning to program. Such as: “Here is a list of objects, sort them and return the top three”. You don’t know or care where the list came from. Just that it’s here now and it needs sorting. You don’t care where the result is going, only that it’s the top three from the list you were given. The vulgarities of the real world don’t come and slow you down by having to open up the Java Network API or figure out how to read in an XML file and parse it’s contents.
The reverse is true of writing the Adapters. Much like when you first realised you could open any socket you liked and flood the network with rubbish, writing Adapters allows you to not care about the business logic. You can just hack about with the API you’re using until you have something working, smarten it up a bit and then you’re done. The requirements of the Domain logic are not imposed upon you, only the interface the Domain objects want to use, which is typically a lesser restriction.
Much like Ruby puts the fun back into programing, I would suggest that Hexagonal Architecture puts the fun back into software architecture.