
Ready for changes with Hexagonal Architecture - WalterSobchak
https://netflixtechblog.com/ready-for-changes-with-hexagonal-architecture-b315ec967749?gi=d802b8fc4fc0
======
adamkl
I came across an article a few weeks ago [1] that distils the idea of this
architecture into a very simple pattern, stratified design, or the
“Integration Operation Segregation Principal”:

“A function either integrates or operates, it either only calls other
functions or it does not call other functions but contains only logic.”

Basically, you have code that interacts with the outside world, and you have
logic (read: conditionals and branching). Don’t mix the two.

It’s such a simple concept that it seems obvious in hind-sight (so maybe
that’s why nobody ever talks about it, because it is obvious), but I don’t see
code written this way all that often.

If there’s one thing I could teach every new developer it would be this. It’s
such a little thing, but it would make a lot of code much easier to work with.

[1] [https://medium.com/clean-code-development/stratified-
design-...](https://medium.com/clean-code-development/stratified-design-over-
layered-design-125727c7e15)

~~~
tsimionescu
To me this article looks a lot like the kind of principle that looks very nice
in articles but immediately breaks down in practice with even slight
complexity.

First of all, the difference between operations and integrations makes no
sense, even in his examples. All of his functions are calling other functions.
All of his integrations are doing some logic (passing results between
functions in particular ways). There is no fundamental difference between 'if
a then b else c' and 'other_function(a, quote(b), quote(c))'.

Second of all, this idea that you don't have dependencies between Presentation
and Business only looks like that because he's passing very simplistic data
between them. But in real code you have complex data structures and complex
interactions and complex invariants and they almost unavoidably introduce
dependencies between 'strata'. Even if you force yourself to use maps and
strings and lists so you don't have explicit type dependencies, you still get
implicit structure dependencies.

~~~
adamkl
The premise is not that there are no dependencies of any sort, or that you
aren't allowed to pass complex structures from one to the other. Its more
about splitting logic (and by logic, he is referring to code with multiple,
branching paths) from side-effects.

When you mix effectful code (rendering to the UI, accessing a database) with
conditional logic, you need to resort to mocking (potentially complex) objects
just to perform basic unit testing. He's simply stating that if you split
those out into different functions (operations in his case) and use a simple
function to integrate them together, it will make life easier, and I agree.

Its a very functional approach; get data, perform calculation, return data.

Like I said, I thought article did a good job of distilling an important idea
into a simple pattern. It doesn't have to be an overarching architectural
design; even just using it locally in a larger code base can make life easier.

*As an aside, I'd say there is a fundamental difference between:

'if a then b else c'

and

'other_function(a, quote(b), quote(c))`

The first, when tested inside the scope of its parent function needs multiple
unit tests for full coverage, the second only needs one.

~~~
tsimionescu
I think the last point is the most important - if there really is a difference
between those two pieces of code, then the article does make some sense. If
there isn't, the the article's pout is weakened.

The reason why I think they are equivalent is that other_function may well be
really reusable and have many different use cases, of which only one is right
in my current use case. For example, it could be the 'if' special form in
Lisp. That means, I can know for sure that other_function is itself perfectly
correct, but still be calling it badly, so I still need to test whether my
function does the right thing for any possible value of a, b and c.

~~~
adamkl
True.

I actually thought about the same 'if' special form when formulating my
response (I've been playing a lot with Clojure lately, and your other_function
looks a lot like a functional conditional when compared to an if/else), but
figured that most people would be viewing this stuff through a more typical
imperative lens, in which case, those constructs (if/else vs other_function)
would likely be different.

------
Communitivity
I was disappointed that the article didn't mention Alistair Cockburn, who came
up with this architecture style, which is also sometimes called ports and
adapters. I like hexagonal architecture a lot, but I change one aspect.
Instead of Interactors I use composable Functors and Pipes. A Functor is an
Interactor that takes in one Entity and produces an Entity. A Pipe is software
that implements one of the different Router patterns from Enterprise
Integration Patterns
([https://www.enterpriseintegrationpatterns.com/patterns/messa...](https://www.enterpriseintegrationpatterns.com/patterns/messaging/MessageRoutingIntro.html)).
I guess you'd call what I use a hybrid of the EIP style and the Hexagonal
style.

~~~
BoiledCabbage
This sounds really interesting, and reminds me of "Domain Modeling Made
Functional". But could you describe the pipes a bit more? EIP from the link
your provided says that any interactor/filter in a pipe is interchangeable
with another. Based on the model you described you say you'd have each
interactor take in an entity and output a possibly different entity (which
seems reasonable). But if you did that and had a chain of interactions, then
removed one from the middle wouldn't you now have a type mismatch where you
try to connect the remaining interactions?

~~~
Communitivity
Good question. You're right in that the Interactors can only be chained
according to their types. Let's say I had an A->B, C->D, B->C, and C->E. I
could form a chain (A->B)->(B->C)->(C->D), but I couldn't do (A->B)->(C->D).
The Pipes come into play for routing, splitting, and combining. I can use []
as syntax for a splitter and => for a combiner. The combiner is used in
conjunction with {} to represent an input that's a combination of the inputs
inside of it. I can then represent textually a pipeline to produce F from A
with functors (the 1-1 Interactors), a combiner pipe and a splitter pipe.
(A->B)->(B->C)->[(C->E), (C->D)]=>({E,D}->F). As a side note, you can tell I
like to make sure I can have a textual syntax for describing things..let's you
process it with sw and I am horrible at graphics.

Regarding interchanging the different, I think it means you can swap a router
for an interactor, or vice versa, as long as the types match. It's basically
enterprise architecture level functional programming, kind of.

~~~
BoiledCabbage
I like your approach to problem solving - it's very similar to mine and in
domains I also think about.

Your syntax is very convenient thanks for sharing.

And finally, I assume you're familiar with Scott Wlashin (of F# for fun and
profit & "Domain Modeling Made Functional")[1][2]. If not you _100%_ should
read it as it is right up your alley. It's the intersection of Functional
Programing and DDD/EIP. (I have no affiliation).

[1]
[https://fsharpforfunandprofit.com/ddd/](https://fsharpforfunandprofit.com/ddd/)

[2] [https://www.amazon.com/Domain-Modeling-Made-Functional-
Domai...](https://www.amazon.com/Domain-Modeling-Made-Functional-Domain-
Driven/dp/1680502549)

[3]
[https://fsharpforfunandprofit.com/rop/](https://fsharpforfunandprofit.com/rop/)
(Railway oriented programming)

~~~
Communitivity
Thanks, for the compliment and for the links. I wasn't aware of him until now.
I've little experience with the X# family, other than some Mono hacking on an
OpenSim clone. Sounds interesting and will definitely read at least the Domain
Modeling one, possibly the F#s too (never too late to add a piece of kit to
your toolbox).

------
SmooL
I love the idea, and maybe this works well for them in a position of
relatively lax performance.

The truth is that all abstractions around data fetching are inherently leaky;
making an API call does _not_ have the same runtime characteristics as reading
from a file. Different access patterns have different performance implications
across different data sources.

I would love if somehow we could put runtime performance characteristics in
the type systems. Implementing readFile<T extends Readable, S extends
SomeRuntimeCharacteristic> would go a long way towards sealing those leaks.

~~~
adamkl
It’s all about the right tool for the job.

I always push this approach when developing applications, but I work in large
enterprise where performance often isn’t critical, but applications can live
on for _decades_.

Should you use this approach when developing something like nginx? Probably
not. But if you are developing a line-of-business application that has to
interact with an ever-evolving mish-mash of other systems over an
embarrassingly long time frame, it’s a great approach.

------
UK-Al05
People have been using this for years. One of things I recommend is not using
the repository pattern. You end up with a repo with lots of methods on and
overly generic.

For each of the use cases/interactors, any database action should be wrapped
up in a specific interface for that database action. Then implement those
database interaction by implementing that interface. Query and command objects
instead of repos.

Much finer grained then repos. Also allows for finer grained control over
which data source you use for each interaction.

~~~
HelloNurse
It depends. Sometimes a repository can cover all needs with relatively few and
relatively generic methods, sometimes specialized database interactions can be
application logic layered on top of a much less specialized repository,
sometimes a repository becomes unpleasant because it should be split up, etc.

------
sischoel
Some thing I was wondering about this kind of architecture, how would you
express some constrains, like foreign key constraints or unique key
constraint? Would they still be in the database, or would you put them into
some inner layer?

~~~
kgwxd
My understanding is that only the storage layer should care about that, and
only if it's a relational store. The concept of looking things up by "id" will
obviously make it to the application layer but the application layer "id"
isn't directly linked to the PK column of a particular SQL table, even if it's
going to be the most common use case.

------
saagarjha
I guess I’ve been staring at LLVM CMake output for too long, because I thought
this had something to do with
[https://en.wikipedia.org/wiki/Qualcomm_Hexagon](https://en.wikipedia.org/wiki/Qualcomm_Hexagon)

------
jmartrican
This architecture might bring back monoliths. Or at least it'll bring back
monolith first.

------
aprdm
Wonder if they have some source code examples, this also seems very similar to
DDD.

~~~
m2mdas2
I have been following hexagonal architecture recently, found some good
references,

* This article [https://herbertograca.com/2017/11/16/explicit-architecture-0...](https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/) have detailed explanation on the components of hexagonal architecture.

* There is COLA framework [https://github.com/alibaba/COLA](https://github.com/alibaba/COLA) based on spring boot from Alibaba. Description is in Chinese but google translate does good enough translation. There is some pretty interesting things happening in Chinese universe that are hidden for language barrier.

* Another sample application in .NET [https://github.com/kgrzybek/modular-monolith-with-ddd](https://github.com/kgrzybek/modular-monolith-with-ddd) which gives good overview of code architecture.

~~~
vosper
> There is some pretty interesting things happening in Chinese universe that
> are hidden for language barrier.

Are there any other things you can point to that you think are overlooked?

~~~
m2mdas2
I occasionally check trending repositories of chinse language in github
[https://github.com/trending?spoken_language_code=zh](https://github.com/trending?spoken_language_code=zh)
and github repositories of Alibaba, tencent etc. From the look of it they are
very focused on tooling/tutorials on highly salable distributed systems
architecture. Java is very popular and spring cloud is their preferred choice.
One thing I found interesting is that hibernate ORM is not used anywhere,
instead they prefer MyBatis data mapper framework. Some of those projects are
moved to apache foundation.

On top of my head I found these projects interesting,

* Dolphin Scheduler [https://github.com/apache/incubator-dolphinscheduler](https://github.com/apache/incubator-dolphinscheduler)

* Echarts [https://github.com/apache/incubator-echarts](https://github.com/apache/incubator-echarts)

* Ant Design [https://ant.design/](https://ant.design/)

* Sky walking APM [https://github.com/apache/skywalking](https://github.com/apache/skywalking)

* Seata distributed transaction system [https://github.com/seata/seata](https://github.com/seata/seata)

* EasyTransaction distributed transaction system [https://github.com/QNJR-GROUP/EasyTransaction](https://github.com/QNJR-GROUP/EasyTransaction)

* EShop-SOA [https://github.com/songxinjianqwe/EShop-SOA](https://github.com/songxinjianqwe/EShop-SOA)

* RocketMQ [https://github.com/apache/rocketmq](https://github.com/apache/rocketmq)

* Sharding Sphere [https://github.com/apache/incubator-shardingsphere](https://github.com/apache/incubator-shardingsphere)

* Jeecg-Boot [https://github.com/zhangdaiscott/jeecg-boot](https://github.com/zhangdaiscott/jeecg-boot)

* SOFA Stack [https://github.com/sofastack](https://github.com/sofastack)

* Dubbo RPC framework [https://dubbo.apache.org/en-us/](https://dubbo.apache.org/en-us/) . Also it seems that every big companies in China have their own RPC framework.

------
michael_j_ward
If someone has some good, open source examples- please share!

------
cheez
This sounds like something a politically astute developer came up with and
built short-term career growth on it at Netflix while the rest of the
developers at Netflix look on and say "yeah ok but that's just <FOO METHOD>
drawn like a hexagaon. AM I THE ONLY ONE WHO SEES THIS ISNT SPECIAL????"

(Because of course, I created something like this more than a decade ago that
is still in use)

~~~
wpietri
The term was invented something like 15 years ago by Alistair Cockburn.
[https://en.wikipedia.org/wiki/Hexagonal_architecture_(softwa...](https://en.wikipedia.org/wiki/Hexagonal_architecture_\(software\))

~~~
cheez
The originality is not really relevant. I've seen this type of thing take
place before.

~~~
wpietri
It is in fact relevant to your claim that it sounds like somebody came up with
it as a career advancement technique. Rather than it being part of a decades-
long dialog about how to build software.

~~~
cheez
Ah, I seem to have have met the politically astute developer on HN.

You might like this version better

[https://news.ycombinator.com/item?id=22566315](https://news.ycombinator.com/item?id=22566315)

~~~
wpietri
Anything can be used for politics. But I've met Cockburn a few times. Ditto
Fowler and Evans, all of whom have related work in software architecture. They
are all people sincerely trying to figure out better ways to build software.

By the way, making spurious accusations is very much a political technique. So
bravo you.

~~~
cheez
Jesus Christ, you are the reason I decided against working for FANG companies.

~~~
wpietri
Me personally? Great! I'm always glad to help people stay away from large
companies.

~~~
cheez
On the off chance that you are genuinely seeking truth, perhaps you would like
to venture an opinion on one of the following rephrasing:

[https://news.ycombinator.com/item?id=22566315](https://news.ycombinator.com/item?id=22566315)

[https://news.ycombinator.com/item?id=22569847](https://news.ycombinator.com/item?id=22569847)

~~~
wpietri
Sorry, what truth do you think I should be seeking here? My point was that you
were needlessly (and apparently ignorantly) trash-talking a serious
contribution to the long, ongoing discussion of software architecture. If
you've decided to stop doing that, great.

~~~
cheez
Point proven. Your political astuteness is well honed man, well done. But no
one who works with you likes you, guaranteed.

------
duke360
cool... but it is not hexagonal, it is almost quadrilateral :D :D

