anthonator

anthonator

I’m curious to hear people’s opinions on implementing the Onion Architecture in an Elixir application.

Jeffrey Palermo, the originator of the Onion Architecture, states that it is “unashamedly biased toward object-oriented programming, and it puts objects before all others”. However, there has been some discussion on implementing the Onion Architecture in Functional Programming.

The diagram depicts the Onion Architecture. The main premise is that it controls coupling. The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core. In other words, all coupling is toward the center. This architecture is unashamedly biased toward object-oriented programming, and it puts objects before all others.

Has anybody in the Elixir community implemented the Onion Architecture in Elixir or another functional language? Has anybody implemented the Onion Architecture in an OOP language? If you have, what are your thoughts on implementing this architecture?

Do you think this architecture could be useful to the Elixir community? Is using this architecture a bad idea? A good idea? A waste of time? Do Elixir apps tend to exhibit this architecture anyway?

I’m looking forward to hearing people’s thoughts!

Showing Posts 1 to 7

Crowdhailer

Crowdhailer

Creator of Raxx

This might be a slightly controversial point but I don’t think Elixir code needs to be very different from OO code. A user struct is not very different from an immutable user object. The domain core being functionally pure is I link a good idea because it makes units very easy to test.

By the time you step out to application services and infrastructure, your code will no longer be pure. However at this level a Elixir program will probably be coordinating multiple process and they encapsulate state so again many of the OO lessons are still relevant.

So in summary I think that the onion architecture in Elixir is a good idea.

DianaOlympos

DianaOlympos

I would say that my main problems with that architecture are that it is badly defined

  1. If it is about code and use dependency injection, then… it is deeply single threaded. Which… urgh
  2. if it is about higher level stuff… Why not but it is highly specific. Why even need something that complex that limits you that much ? And why talk about Objects or DI ?

All in all.. I still do not understand all these talks about architecture. Think about your system as a whole, build from there, rewrite regularly, decouple stuff and please make it works safely before diving in complex architecture.

StefanHoutzager

StefanHoutzager

I did not dive into the onion thing. My time is limited, and I just read that tip of mr. Kunikow: [Functional Programming] Domain Modeling Made Functional (Pragprog) (F#). The writer of that book is also a nice humoristic and clear presenter. I can recommend
https://www.youtube.com/watch?v=AG3KuqDbmhM on the subject of a comparison of oo and fp dependency injection (it comes a bit later in the presentation).

peerreynders

peerreynders

I thought that looked familiar as it’s basically Alistair Cockburn’s Hexagonal Architecture.

I’m not even sure why it claims that its “unashamedly biased toward object-oriented programming, and it puts objects before all others” because it basically just takes the general notion of “separation of concerns” and transforms that into pleasingly shaped boundaries - manifesting themselves as “objects” at the lowest level of granularity and bending a layered architecture into an out-in-out circular shape on the highest level of granularity.

And it also seems that somehow the Onion Architecture got associated with DDD (Domain-Driven Design with Onion Architecture). Which is interesting because I suspect that similar criticism (Jim Coplien — Symmetry in Design) can be levelled against it - it relies heavily on symmetry (and hierarchy) which may not be inherent in the problem domain which can ultimately lead to accidental complexity.

From that viewpoint Coplien’s DCI (Data, Context and Interaction) may actually be a more profitable place to pilfer ideas from. While he’s still an object-oriented guy, he eshews class-orientation and his “network of objects” seem reminiscent of communicating BEAM processes.

anthonator

anthonator OP

If someone were to implement this in Elixir it may not make sense to bring over all aspects from the original article. I agree that dependency injection is one of my least favorite aspects.

However, I am intrigued by the clear separation between domain, application, and infrastructure code. Most apps that I encounter in the wild are “database first” and place the infrastructure layer in the middle. This tends to set the stage for a “Traditional Layered Architecture” which leads to a hopeless amount of coupling.

A lot of this may be obvious to others but judging from the projects I’ve worked on it doesn’t seem obvious to a good number of smart people I’ve worked with.

Qqwy

Qqwy

TypeCheck Core Team

In the end, the reason that many applications in the wild are extremely tightly coupled is possibly because it takes a conscious effort to not introduce coupling.

That for some reason the term ‘model’ started becoming confounded (moving from ‘conceptual model’, also known as ‘business logic’, to take on the extra meaning: ‘database model’, resulting in programmers only being able to think about both concepts simultaneously) did not help in this regard, as this resulted in very tight coupling of the database with the application logic.

In your application, the main piece that should dictate how everything else works, should be your business domain logic: The abstract representation of the part of real world your application attempts to help with (to ‘model’).

What database you use is an implementation detail.
What user-interface the business logic can be manipulated through is an implementation detail.

Yes, there can be multiple different kinds of databases in a single application, or none at all. Yes, you might both have a web interface, a command-line interface and an Application Programming Interface.

These decisions do not have impact on your business logic, but the inverse is true: Your business logic strongly impacts in what ways it make sense to store certain pieces of data, and in what ways it makes sense to interact with it.


I believe that above realization is the core of all these different kinds of architecture ideas. Whether you call the result Domain Driven Design, Onion Architecture, Hexagonal Architecture, Data Context and Interaction, SOLID, etc. does not really matter. Their goals are the same: To decouple the multiple pieces of your application, making sure that your code remains structured (understandable, maintainable and adaptable) over time.

Rather, I have somewhat the feeling that all these different names steal the wind out of each other’s sails a little bit, making all of them less valuable as a result (in a way similar to this).

peerreynders

peerreynders

However, I am intrigued by the clear separation between domain, application, and infrastructure code.

I’m not against being organized (i.e. observing separation of concerns) - in fact most of the success stories are probably based on the fact that projects went from not managing boundaries and dependencies appropriately to starting to having to think about them - but that doesn’t give the onion architecture “special powers”.

Most apps that I encounter in the wild are “database first” and place the infrastructure layer in the middle.

To certain degree that is simply an matter of perspective - and typically there are multiple perspectives. The onion architecture’s primary claim to fame is the direction of the interfaces - something that can’t even be discerned in the primary graphic. The domain logic gets to dictate the interfaces and types and the infrastructure has to implement everything based on those constraints.

So for example in Java-land that would mean that none of the classes in Java.sql would be allowed in the domain code, even something as convenient as ResultSet because that would ultimately couple the domain logic with the notion of a relational database. From the perspective of the Dependency Inversion Principle this has always been the right thing to do:

  • High-level modules should not depend on low-level modules. Both should depend on abstractions.
  • Abstractions should not depend on details. Details should depend on abstractions.

By extension Ecto.Changeset has no business appearing anywhere in your domain logic because Ecto is ultimately only part of your infrastructure - not your domain. So according to DDD you would have to build a repository around Ecto’s repo and transform all inbound and outbound data to basic and domain datatypes - no leaking of changesets and schemas allowed.

it doesn’t seem obvious to a good number of smart people I’ve worked with.

Loose coupling adds effort upfront. So a lot of those “smart people” will accept tight coupling either of their own accord (laziness) or because of pressure by management to produce something (we need this yesterday).

— All posts loaded —

Where Next? Top

Trending in Discussions Top

cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
achempion
I’ve been using Emacs as my main code editor for more than a two years. It’s a custom build version although I’ve tried doom emacs and sp...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews