mudasobwa

mudasobwa

Creator of Cure

I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to it, like, look, here is the ruleset.

No, there is not. Until there is an iron proof attached, it’s just an opinion (or even rant.) Here is my debrief of some piece of Elixir documentation, bringing mere bits of advice on how to better write an average library, into “Anti-patterns” with my explanation of why all of those are not dogmas.

Showing Posts 1 to 10

krasenyp

krasenyp

Thank you for writing this article. My main gripe with the dogma is that spawning processes is wrong. People are afraid of spawning processes but there are so much interesting patterns which involve spawning, even unsupervised, processes. Don’t get me started on monitoring. It’s so powerful yet most of the people I’ve worked with before don’t know about it at all, or at least don’t know how to use it effectively.

josevalim

josevalim

Creator of Elixir

If anyone thinks that anti-patterns are rules that should not be violated, you should point them to the second paragraph of their introduction: :smiley:

The goal of these guides is to document potential anti-patterns found in Elixir software and teach developers how to identify them and their pitfalls. If an existing piece of code matches an anti-pattern, it does not mean your code must be rewritten. Sometimes, even if a snippet matches a potential anti-pattern and its limitations, it may be the best approach to the problem at hand. No codebase is free of anti-patterns and one should not aim to remove all of them.


Some comments on your remarks below:

In complex recursive operations, using throw/1 and catch (or raising a dedicated structural exception rescued at the top-level boundary) acts as a clean, non-local exit.

Aye, throw/catch is exactly what should be used, but throw/catch is not an exception and you must always catch what you throw. I will clarify the current docs, thanks!

While putting arithmetic in a GenServer is obviously silly, using processes as fault-isolation boundaries for computation is a battle-tested OTP pattern. […] If you run that code directly inside the caller’s process and it triggers an out-of-memory error, segfaults, or enters an infinite loop, it takes down the caller.

Processes are not going to protect you from segfaults or out-of-memory errors. Plus the current patterns do support using processes for fault-tolerance and isolation anyway.

Take non-critical background operations: sending an asynchronous telemetry event, flushing an audit log, or dispatching a best-effort metric. If you start these tasks under the main caller’s supervision tree, a failure in the telemetry reporter can crash the supervisor or block the shutdown sequence of the primary application.

Starting an unsupervised process is not a solution to this problem. You can set the tasks to temporary, their default, which means a crash doesn’t count towards the supervisor restart. Worse, by not supervising them, you make much harder to introspect them and guarantee proper shutdown (if ever desired). Those are exactly the type of assumptions the anti-patterns are meant to correct!

mudasobwa

mudasobwa OP

Creator of Cure

The wording “anti-patterns” is so strong, that I believe people think “ok, they put it for a reason, and yet I know Chris wrote this book about macros and whatnot, but quod licet Iovi, non licet bovi.”

Yes, but again, I never said it’s a silver bullet. I said under many circumstances you are good to fire-and-forget unlinked task to send some telemetry and just didn’t do any defensive programming. Like, log("#{Repo.get!(a)} / String.to_integer(b)"). Assuming the meaningful error is handled somewhere else and logged properly.

And that was actually fighting the goal to challenge all the items there, what was most likely the wrong idea.

thiagomajesk

thiagomajesk

Consider a library executing third-party NIFs, parsing untrusted image files, or running heavy memory-intensive computations. If you run that code directly inside the caller’s process and it triggers an out-of-memory error, segfaults, or enters an infinite loop, it takes down the caller.

Well, isn’t that exactly what using processes to model runtime properties is all about though!? I might have misunderstood your point, but this has always been my understanding of what fault tolerance/ isolation is.

Besides that, totally agree with the post’s premise; thanks for sharing! :flexed_biceps:

sodapopcan

sodapopcan

The problem is always wording. For example, in your article (which I like and am generally in agreement with) you’ve taken the term “avoid” to mean “must never.” Many people, myself included, don’t tend to think of “avoid” as “never” but as something we generally try not to do with some exceptions.

The other word like this that shows up quite a bit in documentation, outside of the anti-patterns even (and I’ve just used twice above) is “generally.” While this should unambiguously be taken to mean “usually but not always,” so many people treat it as just meaning “always,” at least in my experience.

EDIT: Ha my logic for my “generally” definition flipped.

derek-zhou

derek-zhou

Man, I have to look up all the Latin quotes you used. I hope you are not trying to one-up the people who quoted the official guidelines. Joke aside, I agree with everything you said in the post; however, I still think a personal journey through 1, learn the rules, 2 break the rules, 3 come back and appreciate the rules, can be skipped.

Schultzer

Schultzer

I think its important to understand that declarations of anti-patterns is an anti pattern in itself, as most of them are opinionated and not based on hard science. There is nothing wrong with opinions as long as they are always questions and never taken as gospel unfortunately history has shown again and again that we humans tend to leverage these kind of declarations politically. It would have been better for our community to stick with hard science regardless of how hard some people find “readability” to be. This is even more true in this day and age with AI.

dimitarvp

dimitarvp

Readability will be important as long as there are people who want to work on the code, with or without AI.

And with the sad fact happy LLM agents are to forever generate code and never tidying it up, unless you very strongly insist on that with them (which still fails, part of the time, maddeningly), readability as a requirement, as annoyingly non-deterministic a concept it might be, is not going anywhere. Its important is even going up in the age of LLMs, at least if one hopes to be able to understand the codebases they are working on.

mudasobwa

mudasobwa OP

Creator of Cure

Yes, absolutely. Also when this “avoid” or “generally” or like happens to appear at the official documentation site, it rocket-jumps to a commandment :slight_smile:

mudasobwa

mudasobwa OP

Creator of Cure

Wise men learn by other men’s mistakes; fools by their own. (See? I didn’t use a dead-language proverb here :-P)

On the other hand, I am pretty sure that while failing miserably breaking the rules, the wise man gains a ton of great experience, which is not verbally shareable, specifically taking into account that mileages do always vary.

That said, this journey makes a person wiser. The cost of this training is out of scope though.

Where Next? Top

Trending in Blog Posts Top

pckrishnadas88
Hey everyone! :waving_hand: I’ve published Part 7 of the Building Distributed Systems in Elixir series, where we build core distributed ...
New
mudasobwa
So, instead of wasting my afternoon arguing with anonymous handles on X, I turned to my trusty, soulless assistant and said: “Listen, ple...
New
abreujp
New article: Elixir Project Structure — From mix new to a Growing Codebase I’ve published a new article in my Elixir learning series on d...
New
zorn
An educational side project in Elixir, Phoenix, and Tauri. I share what I learned while wiring Automerge into the BEAM, including how I s...
New
jola
Wrote about how to safely run a globally unique process in an Elixir cluster, and a scary story from the past! Learn about :global for r...
New
jola
The way Phoenix is set up adding a CDN sub-domain for serving static assets, without worrying about the main dynamic content, is incredib...
New
UlfAnger
What happens when an AI agent reaches its limit because the required tool isn’t in its catalog? Normally, you get a polite refusal. I wa...
New

Other Trending Topics Top

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
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
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
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews