2017-06-20
My notes from Alistair in the 'hexagone', a cross-over meetup event mixing:
With @TotherAlistair and @tpierrain.
See also the videos of the event:
- https://www.youtube.com/watch?v=th4AgBcrEHA
- https://www.youtube.com/watch?v=iALcE8BPs94
- https://www.youtube.com/watch?v=DAe0Bmcyt-4
Note: you can find the paper board drawings made during this presentation here, thanks to @PatrickGIRY. It helps to vizualize "things on the left" and "things on the right" :)
"More hits on my 2004 Hexagonal Architecture article than in all my use case articles, it happened over the last two years."
"Early 1990's Kent Beck style programming."
"A Port is just an interface. OK, you can go home."
What is a pattern? "Patterns of X" = "Common characteristics of good examples of X."
Configurable dependency (Gerard Meszaros): general name to replace "Dependency Injection" and Inversion of Control, the former a specific implementation, the latter a double negative.
The hexagon is at the center. The business code is inside the hexagon. Then, outside of the hexagon, there is a left-hand side and a right-hand side.
The things on the left we call drivers, that drives the system around. On the left, I don't care if it's a person or a computer (draws a stick figure with a square head to illustrate).
The things on the right are of two kinds, repositories or recipients.
Hexagon has configurable dependencies on the right-hand side and the left-hand side.
A Port is the intention of the dialog, no notion of technology. You say what it's for. "This is for ...ing".
"This interface is for adding events". "This is for showing images".
"For Selecting a drink" "For Obtaining prices & recipes" "For dispensing"
The primary actor : the one who does the triggering (on the left-hand side)
The secondary actor : the one triggered (on the right-hand side).
Why is it a hexagon? I didn't want a square because people focus on top, bottom, left, right. Then pentagon was too complicated to draw. The hexagon was the smallest polygon that was not taken that I could draw.
Code a program that give some poems.
Plan:
- One port "for requesting poems" (left side).
- One port "for obtaining poems" (right side).
- First adapter: the test case. The test case is a legitimate driver with a legitimate adapter. The test case is the first user!
- The first repository is a stub. At that moment, the hexagon is complete. The hexagonal architecture is in place, with very few lines of code. See how simple it is!
- Then a console adapter on the left working with the stub
- Then a file adapter on the right.
Implement only one verb, "GiveMeSomePoetry()".
In TDD.
To enter the hexagon, we need a left-hand side port:
// IRequestVerses: left-hand side port
// PoetryReader: the hexagon
IRequestVerses poetryReader = new PoetryReader();
var verses = poetryReader.GiveMeSomePoetry();
Note: for an interface, you can have multiple verbs that will be part of the interface.
Then add a right-hand side port:
// IObtainPoems: right-hand side port
IObtainPoems poetryLibrary = Substitute.For<IObtainPoems>();
poetryLibrary.GetMeAPoem().Returns("If you could read a leaf or tree..."); // don't use the same poem to easily tell if something is broken
var poetryReader = new PoetryReader(poetryLibrary);
var verse = poetryReader.GiveMeSomePoetry()
Note: after that, we can refactor the first test (that tests left-hand side) to use a HardCodedLibrary
(that implements the IObtainPoems
interface).
var hardCodedLibrary = new HardCodedLibrary();
IRequestVerses poetryReader = new PoetryReader(hardCodedLibrary);
var verses = poetryReader.GiveMeSomePoetry();
The hexagon is complete. We have something really small that has the shape we want. Now we can make it grow keeping the shape.
Note: then see 3 steps initialization in the slides (pdf). Instantiate the right-side adapters, then the hexagon, then the left-side adapters.
For the rest of the kata, see:
When you implement adapters, map from infra to domain, use domain, then map back from domain to infra.
Note: the ports are inside the hexagon. The adapters are outside (in the infrastructure
directory, that can be structured if there are many adapters).
There's only inside and outside.
Hexagonal architecture + CQRS? Example by Pat Maddox. Different, the read / write split: no more a single hexagon, or a hexagon only on the write side. The business logic is on the write side.
Out of the tar pit (pdf) - Tar pit architecture?
Bonus from Twitter discussions in the following days after the event.
@totheralistair
https://twitter.com/TotherAlistair/status/877831204376113152.
- most ppl focus on left side. I got hurt more by right side absence (I talk about HA for pain from previous experiences more than futures)
1a. microservices is a left-side conversation, CQRS is a right-side (not write-side gah) conversation
1b. in 1994, I had trouble getting ppl to see batch jobs are legit drivers (think use cases as project contract, 1e actors are batch jobs)
1c. 1997, CORBA ~~ micro services. The cost of sending requests out through CORBA was too expensive. I think on-chip vs off-chip signals
1d. 2000 SOA == same same, same ideas, same problems
1e. 2002 Mho's weather warning system needs hook 2 apps together. He doesn't say SOA or micro services, just names need To me, same as batch
1f. 2014 microservices: yawn, same same My only Q: has it become cheap enough to send signals out of the app to make it worth it? u tell me
1g. I'm getting ancient, seen this all 5 times now all only about putting an API on the left side how 1975 tell me what's new
https://twitter.com/TotherAlistair/status/877845075966935040
2a. CQRS is a right-side - recipient, not repository - conversation. The event store is a simple right-side recipient of the app @gregyoung
2b. That the event store is a hexagon is a bit of a yawn, but probably ppl violate that anyway as they tend to do
2c. the two um hexagons together do not look like just a bigger hexagon to me they look like two systems operating in tandem
2d. glued together at the relevant primary actor's terminal. wd need to see an implementation to be convinced it's 1 hexagon Greg?
Also: Mountain West Rubyconf 2010 - Alistair Cockburn - CQRS
@gregyoung
https://twitter.com/gregyoung/status/10288731558
@totheralistair I am thiking more that hexagonal applies to the write side but not the read... A good Sunday night beer conv
@tpierrain
Same thing applies to the domain logic
@mathiasverraes
https://twitter.com/mathiasverraes/status/877493260381548544
That's how I've been doing it
@totheralistair I am thiking more that hexagonal applies to the write side but not the read... A good Sunday night beer conv
@PatrickLouys
@mathiasverraes how do you architect the read side? Interface in application layer and implementation in infrastructure?
@mathiasverraes
Most of the time: a single class that listens to events, writes state changes directly to db, responds to queries. No need for domain model.
Design them around queries, answering those is the primary purpose. Events and state are simply means to answer queries.