I posted a full article on this at http://alistair.cockburn.us/index.php/Hexagonal_architecture
Finally, after many years, I understood better what this architecture is about, and have shifted to calling it PortsAndAdaptersArchitecture
, because each facet of the hexagon represents a port (a technology-independent protocol capturing a reason for a discussion), and the things in the outer layer are GoF-style Adapters mapping that protocol to different external technologies. I guess the next step is to get better at defining what constitutes a 'port'. -- AlistairCockburn
This is my response to the standard discussions on layered architecture. It was the line in FourLayerArchitecture
that triggered this writing, "The Infrastructure layer. This is where the objects that represent connections to entities outside the application (specifically those outside the object world) reside." No offense intended about choosing that line, Kyle, it is an accurate description of a standard way of looking at the world. I wish to offer an alternate way of looking at the world and see where the discussion takes us.
I view the standard layered model as a special case of a more generic and more applicable model. By "the standard layered model" I mean: UI -> application -> domain -> network and database. If you mean something else, see how your meaning changes the discussion. Maybe I'll change my views.
To me, there is nothing awfully different about the network and database compared to the person sitting at the screen working at the UI. In fact, I deliberately wish for there to be little difference. I specifically want to replace the person sitting at the screen with a flat file full of test cases, with an EDI link to another company's computer, with a developer typing at the transcript window, with a hot link to another local program. Also, I wish to replace the network and database with a canned script or demo database locally, with a GUI and a developer inventing data on the fly, with a satellite link.
I am a symmetrist at heart. I wish everything to be symmetric at some moment, and work the differences from there. So I create a symmetric version of the layered model, in which the UI is not the front and the DB the back, but both are simply OUTSIDE. Now the layered architecture looks like this < pretend you are looking at a colored drawing in Corel :-) >
OUTSIDE <-> transformer <--> ( application <-> domain )
I draw this as concentric hexagons. I put the person on the upper left and the network/DB on the upper right, with a printer outside one of the faces, a satellite, and anything else I can think of. Inside the outer hexagon is a smaller hexagon. Between the two are the transformer objects in the transformer layer. Inside the inner hexagon are the application objects and domain objects, which some people like to layer and some people like not to layer.
(Finally posted a picture of the thing the way I visualize it. -- AlistairCockburn
Applications work like this: Events arrive from the outside world. The transformer converts it into a usable procedure call or message and passes it to the application. The application is blissfully ignorant of the nature of the input device (see also Ward's CHECKS pattern language, http://c2.com/ppr/checks.html
). Do this and regression testing of the application finally becomes available. On the "back end" (hexagons don't have back ends), the network layer is really another transformer layer transforming out to a particular output form, the particular network and database you are using. When the application has something to report to the person sitting at the screen, it passes out to the transformers a semantically meaningful message, which the transformer converts to a suitable output form. The application has a semantically sound interaction with the transformers on all sides of it, without actually knowing the nature of the actor.
Each face of the hexagon represents some "reason" the application is trying to talk with the outside world. This is why it is concentric hexagons and not concentric circles. Input control things on the upper left, storage and secondary input on the right, as I draw it. In some more detailed formal rendition of the architecture I would probably call them ports.
It is very often I need to start the day with a canned piece of data, instead of a link to a live database. In basic electronics design, they call this a "LoopBack
" (what I erroneously called the ShuntPattern
for a long time) - a little wire that goes out the out port and into the in port, so the machine talks to itself instead of to another machine. That shunt puts the whole communicating system on the desk of the developer, where (s)he can poke at it. How I wish our 18-month project with constantly changing persistence layer and relational database had a shunt, so we could write our own test data locally!
The point is, stuff goes in and stuff comes out, and we are regularly having to plug different technologies into the in and the out. If I could redirect database output to myself sitting at the screen and enter my own data, if I could put my own answers into a file and the that file play fast typist to the application, then I would be a much happier camper while developing, testing and deploying.
I find I can clean up my own designs a bit by asking whether they fit the HexagonalArchitecture
. Where they don't, I find I have unstable assumptions about some piece of technology.
Some of you may also recognize this as an extension of the pattern UserInterfaceOutside
, a principle that showed up originally in my PLOP paper "Prioritizing Forces in Software Architecture" (PLOP2 book) and later in the CACM paper "Social Issues and Software Architecture".
Whoo!!! Excellent, Alistair, Excellent! I can't agree more that there is an axis of symmetry around the domain classes, and that "Control" objects and "Infrastructure" objects look and act a lot alike. This reminds me of a similar discussion DonFiresmith?
and I had a few years ago where we discussed another axis of symmetry in control software - there you have a hardware representation of something (like a valve or a switch) and a software representation of the same thing. The axis of symmetry runs between the two so that everything on one side is reflected on the other. Very astute observation! -- KyleBrown
documented the pattern about the axis of symmetry in control software in the paper "Patterns for Generating a Layered Architecture", which you can find in the first PatternLanguagesOfProgramDesign
. It is one of my favorite patterns, and I always present it when I talk to a group that builds real-time systems. So far, they always connect with it, which is pretty good considering that I have no experience with real-time.
Are there other axes of symmetries in software? I bet there are.
This would seem to be quite similar to the structure of essential, infrastructure and interaction domains described in the SyntropyMethodology
Similar observations are coming out of our current efforts (in parallel) to convert to a three-tier architecture and to develop a more powerful intranet. There's at least one place where we find a browser used as a data source/store to through a Web server to an Oracle database, for example.
It's become more complicated recently: MatthewFuchs?
presents a compelling argument that documents will (could) merge with transactions: Web documents will provide a user interface definition to the browser for use by applets, and the browser, in turn, will validate and record the transactions initiated by the applet.
Outside <-> Middle <-> Outside seems clearer than contorting a three-tier model to fit. But how am I going to explain it to executive management?
(References TK -- sorry...)
I just went and read Barry Rubel's article in PLOP 1- very good presentation. You have a good eye to see the resemblance. I would not have seen that they were similar if you hadn't mentioned it (in fact I wouldn't have read it at all if you hadn't mentioned it, since it talks about electromechanical devices and stuff I don't deal with). I like his use of Pedestals and the way he shows layering as connecting pedestals. I found that the easiest description of when to go vertical and when to go horizontal I have seen. -- AlistairCockburn
The main thing they have in common is the axis of symmetry, though his symmetry is between the software objects and the real world objects being controlled, while yours is between various software objects. But the use of symmetry is striking. -- RalphJohnson
This sounds like a great idea, but I find it slightly difficult in practice. Here is one example that seems like it would fit into HexagonalArchitecture
, but didn't (at least not to the best of my ability):
An application wants to reserve money from the bank accounts (outside 1) of the business' customers. The information about the reservation should be stored in a database (outside 2). The user interface (outside 3) presents a list of customers and gives the choice of "Reserve money on this customer's bank account
". Since there should be potentially several interfaces to different banks, HexagonalArchitecture
Problem 1, choice of outside is part of the domain model
: There is more than one bank/interface that can be used for reservation. Which one is use depends upon (say) an attribute in the customer object. This means that the choice of which of, say, Outside 1a or Outside 1b to use is part of the domain logic.
Problem 2, UI too thick
: The user interface wants the method reserve(Amount)
presented on the Customer domain object. However, this method accesses the bank (outside 1) and the database (outside 2). These accesses should, of course, be atomic (don't reserve money without writing the reservation in the database, or vice-versa).
Have I totally misunderstood the applicability of HexagonalArchitecture
, or is my problem just different from what HexagonalArchitecture
addresses? Does anyone have any examples of HexagonalArchitecture
in action? PatternForm
? Anyone? -- JohannesBrodwall
I have some comments on Alistair's hexagon model here (Alistair, I've emailed you to get a copy of the picture - describing pictures in text doesn't work for me).
One fundamental asymmetry between a database (for example) and a user (or for that matter, textual input file from another system) is the dependency structure of the software.
The user-interface or file-parsing code is dependent upon the application code. Conversely, the application/domain code is dependent upon the database code.
One reason to use a layering model is to assist you in thinking about dependency management - what relies on what, etc.
A more philosophical question back to Alistair - we can come up with lots of ways of "visualizing" systems, but in the end the merits of one visualization against another have to be judged by whether the particular visualization proposal assists in achieving some overall objective. What are your objectives in the case of the Hexagonal architecture? Symmetry is not an end in itself (IMHO).
For more on my perspective on this stuff see "An Architectural Reference Model for Component Based Development" (http://www.ratio.co.uk/techlibrary.html
Mark Collins-Cope (Mail: email@example.com).
Mark, How about I choose to disagree with you? - those asymmetries you name are not significant, and the purpose of the hex model is to get people to see a symmetry that is otherwise not obvious. I recently visited an otherwise excellent group with an asymmetric architecture... as a result they couldn't run without the database, and they couldn't self-test the system. They agreed to implement a LoopBack
mechanism so they can run decoupled from the back end database, and also implement a from-disk test interface. Now, as a result, they have the disk operating as a person, and code operating as a disk (they don't want a person to operate as a disk, the typing is too slow). -- AlistairCockburn
I read this piece and had a EurekaMoment
, because it finally articulates something that I've been doing with varying degrees of success (and with varying degrees of zealousness) over my whole career without realizing that I'm doing it. I've caught a lot of flak for it, too, as early in a project it seems like a lot of effort to some folks to try to treat all EventSources?
in the same fashion (as much as is practical and possible). I had stumbled around trying to articulate this in terms of a fuzzy pseudopattern (Model-View-Controller-Serializer-Deserializer, perhaps?), but had not gotten all the way there. I'll throw out what I had come up with in case there's anything extra of value in it, although I think it's pretty well subsumed under this topic.
Basically, whether the system is truly hexagonal or not :-), most business-oriented systems have models that need to be viewed, and controllers that react to events and typically change views to keep pace with changes in models (this is standard MVC stuff). But then there are other categories of things: the spaghetti pile (usually) that serializes and deserializes things to the PersistenceMechanism
s, the spaghetti pile that converts this system's frobnicator to that system's caturgiator, the spaghetti pile that screen-scrapes the view of the other system thus making its view behave like a model, and so on.
Reduced quite a bit, I think this works out to something like this: there are methods/functions in a system that can only do their job when they are called in a meaningful context (controllers), and there are methods/functions/objects in a system that do their job whenever they are called, more or less regardless of context (models, views to some degree, and serializers/transformers). That is, it really only makes sense for a controller to update its view when its associated model has changed. But a model can change its state pretty much whenever it wants, and a serializer should serialize its payload whenever it's called (certainly assuming that the place it's serializing to is alive and well and kicking).
Looked at in this way, the dependencies that exist in a system like this are controller-oriented. A model and a view end up being somewhat similar. A view, after all, can often serve as a model to some other controller that is depending on it. And a serializer is effectively (depending on how you look at it) either:
- 1. A view that cannot ever cause further events to be generated
- 2. A model that cannot ever have a controller monitoring it for changes
OK, enough rambling; hope this made some sense. Thanks, Alistair, for putting this to virtual paper. -- LairdNelson
I have to say this is a great idea and could reduce the amount of code I'm writing substantially.
I was just wondering what people think of the access rights issue.
(The persistence 'outside' would probably need to have access to methods that I would rather the 'UI 'outside' doesn't.
How would the UI tell the object to save itself to a database? Since the objects would have no idea of a persistent data store, never mind a database. It might also need to broker between several different persistent stores to provide it's interface to the UI.
A crack on an implementation of this is NakedObjects.
Aha! The object graph is implemented using behaviourally complete objects, as per recommended on the naked object page. This allows a user interface to derive itself from that object graph. The same behaviourally complete operations that would allow a UI to display changes in realtime could be used to implement a PersistenceMechanism
, or a distribution system, or anything really.
I've been calling this the Island-on-a-Lake Architecture. I find the image more evocative and memorable.
The Island on a Lake: There is an island (the domain model), separated from the outside world by the lake on which it sits. We need to build bridges (application models) to the island in order to reach it. Once a bridge is built, it's fairly easy for anyone outside to interface with the island; all he needs is a suitable vehicle (transform). He will see the island from a different perspective, depending on which bridge he comes by.
Today, I began playing with yet another metaphor: The Brain in the Box.
In my hands I hold a brain. It can think. It's a brilliant thinker. But it can't communicate with the outside world. So I put it in a box, and I wire it up to connectors on the outside of the box. On one side of the box, maybe I have a connector through which I can send commands to the brain. On another side, the brain can send and receive data. On another, a connector that is designed to interface to large-scale secondary storage, in case the brain wants to offload massive amounts of data and then retrieve them later.
Any device I have I can interface to any connector on the box, as long as I build the appropriate adapter cable. Let's say I have an old-style VT100 terminal. With the appropriate adapter, I could hook my terminal to the command port and type commands on the keyboard to be issued to the brain. Or with a different adapter, I could hook the terminal to the data port and see data the brain was sending and type data to be sent to the brain. I could even hook the terminal to the secondary-storage port; and if the brain offloaded data, it would appear on the display; and if the brain requested that data be retrieved, I'd have to type it on the keyboard. That's not much good as a secondary-storage solution, but it would be great for testing quickly that the brain is working. Better yet, I'll record a complete session with the brain on a magnetic tape, and then with an appropriate adapter module, I can hook the tape deck to all the connectors on the box. Instant automated subsystem test. And all I had to do was build a few simple adapter cables.
"Hexapodia is the key." -- TwirlipOfTheMists?
for an interesting implication of this architecture...
Thanks - I just read it (July 2005) ... indeed, I agree that they are better named 'Adapters' than 'Transformers'. I cam to that realization while reading RebeccaWirfsBrock's great book ObjectDesign, and seeing that she calls that stereotype 'Interfacers', but shows examples of them using the GoF patter 'Adapter'; and then had my own little Eureka! moment when I finally saw what to call this thing besides HexagonalArchitecture (which only names the shape of the drawing): PortsAndAdaptersArchitecture. I can now semi-articulate what a port is and refer to standard literature on adapters, so I feel this is making progress. -- AlistairCockburn
Taking the hexagon concept a little further, I would propose a HoneyComb?
architecture. Essentially each edge of the hexagon represents a contract (interface) with the outside world. In order for two models to interact with each other, they need to agree on this contract. Visually, this represents two hexagons sharing an edge. Extending this concept results in the HoneyComb?
architecture. Adjacency represents an interface, but does not dictate what is in the honeycomb. (Hence the person becoming a disk and the disk becoming a person. :-) The hexagon next door may be a test harness or a LoopBack
interface or the real thing.
When talking to executives, I find that this can clarify what you are getting when you purchase an application server. It is a bunch of hexagons arranged in a circle with a hole in the middle. This is the container and your put slot your custom model in the available hole.
Ok. I will stop before this degenerates into the "the birds and the bees"... ;-)
Ferit Albukrek - firstname.lastname@example.org
This seems to be orthogonal to FunctionalProgramming
. This sort of program structure is almost necessary in the HaskellLanguage
, because input and output is the transformer, and all the inner code is the domain. More details if anyone is interested. -- ShaeErisson
It is interesting how architectures always have a center. The center is the core thing that the group of engineers sees the system being.
For example, if the system is viewed as a database application, then the database is at the center of the drawing, there is a domain ring around it, and then services, then applications.
If the system is viewed as a Service Oriented Architecture, the service bus is a big bar across the middle with all the services hanging off of the Message Bus.
If the system is user story driven then the application is at the center (the hexagon above) and every thing else is around that.
If the system is viewed as a software representation of some aspect or reality, then it has a Domain at the center and is Domain driven design.
Thus all these architectures are really a drawing of the world from the view of the group designing the system. When the actual coding begins, then in system memory there is no center. It is just lots of Object Oriented Code trying to get the job done.
Thus architecture block drawings are always misleading. They show in unbalanced view of the system, with a false center of attention. If taken too far then the center becomes the catchall and meaning is lost.
Far better is to talk about the roles and responsibilities of packages of code and not even do a drawing. Instead use a good text editor to list roles and responsibilities that get translated into directory structure and packages. Then fill in the details with actual classes.
The only measure of the success of an architecture is a working implementation that is maintainable over time.
We are witnessing the independent confirmation of the EleventhGreenspunLaw?
: Every (web) application is an object.
A comparison with the Unix pipes is quite interesting; we are trying to preserve composability while removing the untyped nature of data exchange and the unidirectionality of communication.
Now for a practical question: Can we think of some incremental refactoring process that could be employed to move from a dirty mixture of layers to a clean hexagonal architecture? The upfront cost of a full refactoring may, unfortunately, be unacceptable for an existing product.