Gary Bernhardt of Destroy all Software has been mentioned before.
The primary design idea is functional core, imperative shell - I’m more familiar with the phrase of pushing the impure aspects to the edge of the system.
Another version can be found here:
He also references J B Rainsberger Integrated Tests Are A Scam:
Again - take everything with a grain of salt - nevertheless worth listening to/watching.
Which version of the Boundaries talk do you like better?
The first one - but don’t ask me why; to figure that out I would have to watch them again. (though I do seem to remember that there was a good QA section at the end of the first one).
@peerreynders thanks for posting this! Just finished watching the first video (and there was an excellent 20 minute Q&A session at the end). I think the ideas presented in the talk are excellent and definitely a great fit for Elixir (moreso than Ruby because of all the functional/immutable constructs built into the language).
I might even checkout the screencast since it goes more in-depth, has anyone watched the screencast?
Loved the videos, but it does ring the bell of the hexagonal architecture I am still struggling with:
Specially the second talk, which directly states that this “Imperative Shell, Functional Core” is a subset of the Hexagonal architecture.
Basically what I still don’t get is why some people seem to love this kind of stuff while others ( in the Elixir community ) seem to just shrug it and downright don’t like it.
I still don’t get what are the cons to using such layered architectures ( be it onion, lasagna, hexagonal, etc ) and unfortunately none of the videos talk about them.
I get that defining boundaries does have overhead, if you define a boundary for everything your code will quickly fill up with mocks, but I still think that the benefits/cost ratio one inherits is still overall positive.
I will say however, this Ruby video was one of the best Erlang/Elixir videos I have seen!
The primary downside is that you get indirect code - you can’t just follow the call into the implementation to see what it does - you must either understand the interface and what it promises to do or try to dynamically at runtime discover what code is actually called. This adds mental overhead to understanding the code. It’s less so if you’re well disciplined in defining the interfaces and contracts, but being well disciplined is not easy to do.
That’s indeed the problem many people have with it. In fact they have this problem with what’s called polymorphism. Polymorphism is great but some people have a hard time working with code which hide all the nitty gritty details. They will prefer code that is explicitly coupled to a specific library/framework/IO/etc… They will realise later the cost of their mistake when all of these have to change (better solution out there, new incompatible version, change in the infrastructure, …).