It is not about Elixir2021-07-30
That’s right. It never has been.
Before you read this post with your teeth clenched and ready for some hot takes, chill. This isn’t where I throw Elixir under the bus. Rather it is where I try to put my finger on the values that makes Elixir a good fit for me and a language I consistently recommend to people.
So to summarize the values:
- Software should be efficient
- Software should be maintainable
- Software should be suitable for continuous development
- Developers should not burn out from the work
- Teams should be able to deliver consistently without stress
- Technically conservative but extremely progressive
So some of my values are fairly specific to software though they apply in other contexts as well. Some other ones are much more focused on the people. We can start on the software side.
Software should be efficient
I find it immensely frustrating that we have incredibly powerful computers now and pretty much everything feels slower to me. I think back to the days of native desktop software that was snappy and fast. Our browsers are beastly software platforms and everything is now a browser.
Beyond that we have programming languages and paradigms that keep things simple by constraining it to single core operation and making processing that is both concurrent and parallel a second class citizen. In a time where clock-speed is no longer going up but core-count is, this is terrible for efficiently utilizing modern hardware.
Efficiency is not just about hardware utilization. It is also about the experience of using things. If you are crunching the numbers quickly but your software is unresponsive during the whole process that can be just as bad as processing slowly.
In some cases Python is perfectly performant enough and you’ll never see an issue. In others you might want Go, Rust or even Fortran, I don’t make the rules about what’s efficient for your use-case. With Elixir I have the BEAM virtual machine which provides low latency and which typically protects me from screwing up latency too badly. It models applications in primitives that map well to concurrent workloads and they make it much, much easier to not botch it. I find Elixir efficient at utilizing hardware while making it straight-forward to maintain a responsive experience.
Software should be long-term maintainable
I’ve built systems that have been hard to maintain. And then I’ve had to maintain them. I don’t recommend it.
There is some software that through a combination of persistent developers and maybe good design just keep going and stick with us. I’ll try to paint a wide picture here. I wish more software could be like VLC. A piece of software that just keeps working. Since I discovered it I have never had to think about what to use if I want to play media. It has persisted because someone has obviously been able to maintain it.
There is so much software we rely on that some person or group of people maintains for us. Postgres, ffmpeg, Linux, git, bash, vim, Ubuntu, Photoshop, Office. Some of these are maybe driven more by a headstrong business making sure they persist than good architectural choices. With proprietary things that’s hard to know. But if we could reduce the churn of software that launches and then dies from complexity I think that’d be great.
With my consulting work I’ve also dove head-first into other people’s code on a regular basis and I’ve seen approachable code bases and less approachable ones. Unwinding other people’s code to understand it is often challenging and also a big part of the job as a developer.
Some products die as the team decides it needs a full rewrite and the rewrite fails. Or because the only person who knew how it fit together left. Or the team burnt out because every update was a thankless slog of complex drudgery. These are typical costs of unmaintainable systems.
Being able to write parts of the code in isolation, mostly reason about code in isolation and know the scope of changes you make is incredibly important to maintainability. I have never had this experience as strongly as in Elixir. I think this is a combination of the high-level dynamic pragmatism and a general feature of functional programming meeting the Actor model. It is easier to reason about state while the dynamic nature of it keeps the threshold to actual coding low and unceremonious. In Elixir I have been able to contribute code in the first few days of a project in a way that hasn’t happened elsewhere.
Software should be well suited for continuous development
The development of software is commonly a continuous labor. Every week developers all around the world pick up issues and implement solutions to them. There are a number of ways in which this can work. But important parts are generally around delivering improvements and avoiding the introduction of defects. Usually there are also heavy incentives towards moving fast.
Good tool support, a strong testing story and all of the previously mentioned maintainability concerns feed into what a language is like to do continuous development with. There are also things like productivity, in the sense that Rails is known to be very productive, you can build new features quickly. Rails is not known for maintainability or efficiency. I think this is why a lot of people that have moved from Rails to Phoenix and Ruby to Elixir have done so.
Any later stage software project tends to achieve a certain level of complexity and at a certain point it matters a lot if your tools are good at managing complexity. If the paradigm you work in supports you in keeping things manageable that helps you to move forward. It is quite possible to move forward in something less structured but it places higher demand on each developer to make good choices at every turn.
So aside from software values I try to think in terms of individuals, teams and wider organizations.
No developer should be burning out due to the work
This happens all the time of course.
It is not primarily a tools issue. But as noted in discussing maintainability and continuous development there is pressure to proceed and complexity to manage and each individual developer is under this pressure. How you manage it is partly up to you. However, it also matters what you are dealing with in the work. Is it clear, is it well-constructed. Are there strong conventions to support you? Do the tools help or hinder you?
I’ve heard plenty of complaints from people working in stacks they hate and how the tools cause more problems than they solve or how frustrating it all is.
At the individual level I find developers have an easy time being enthusiastic about Elixir and often delighted by the power and clarity it provides. The practical tooling is very good. Documentation is great. I think this is a tool that supports individual developers in creating software without causing undue stress.
At the end of the day, therapy, experience and a few run-ins with how not to do it has probably done more for me in this area than working with Elixir. But I do feel like the language supports my work personally and that’s a good feeling that contributes to building a good stable self in this line of work.
Teams should be able to deliver consistently without stress
All teams can screw up. That’s not entirely avoidable. But consistency isn’t about never failing, it is about repeatably being able to succeed. Much like with individual devs I find this to be a people challenge more than a tools challenge. But a tool can provide benefit. Having strong conventions around the tools gives some stable expectations for a team.
I would describe the idioms and conventions of Elixir as a language, tool and community as pretty strong but not very strict. There is direction, there are core ideas, recommendations and writing to lean on for how you can do things. But you don’t have to do it that way. In other parts, the language and frameworks actually press you to work within certain constraints.
The Actor model is a particular way of solving particular problems and working with it forces you to think and work within that solution the absolute majority of the time. And those constraints can be very helpful. There are mistakes it simply won’t let you make or where it will make the wrong thing really hard to do.
I’ve found Elixir to enable and support what I want to do and be enjoyable to work with. When working fast on something that needs to be delivered quickly it lets me do that without ruining the future potential of the system. Reworking internals and refactoring code is very doable due to the limits on shared state and mutability. And when I’m working with complex, intricate things and need to slow down and move carefully there is good tooling for creating comprehensive tests. The language and frameworks allow you to build complex and intricate things that can be tested in isolation. It doesn’t force me to always prioritize one way.
Technically conservative but extremely progressive
I don’t think we should avoid making up new stuff. I do however think there is value in tempering what we invent with some of the wisdom in using what already exists. And I think that balance is very present in Elixir as a technical solution and as a community.
The BEAM it runs on is proven with Erlang since the 80’s and that has only improved with time. The Elixir language itself was sort of dubbed “done” in a keynote (re-iterated here) and it doesn’t change very much while still adding nice improvements consistently along with improvements to Erlang/OTP. That’s a fairly conservative stance and I think it has a good chance of preventing large breakages like Python 2/3 or enormous legacy to maintain in the standard library like what I’ve seen in PHP. Only time will tell.
Elixir as a project, community and going concern hasn’t nearly stopped moving though. There is an enthusiasm and ambition in this community that drives forward some remarkable progress on top of a VM that allows us to do things that simply would be unadvisable in other runtimes. Such as Phoenix LiveView. Which allows developers to build reactive HTML-over-the-wire applications with a minimum of frontend/backend ceremony.
The Nerves project, an IoT-ish embedded framework where the BEAM is most of your OS on a Linux kernel, is already sniffing some RISC-V boards. Dashbit and friends is bringing Machine Learning to Elixir with the Nx project and their ludicrously ambitious Livebook project lets us do some very cool things that I don’t think would be feasible outside of Elixir.
A big reservation I have about the JS ecosystem is the rate of change, churn and the breakages I’ve experienced in projects just from time passing. My experience with Elixir has been very stable, some libraries barely move at all, they are essentially done. Some move slowly, some move faster but I haven’t experienced any issues getting older projects going or handling dependencies. Progress, but not very much churn.
Elixir has taken documentation, tooling and developer experience seriously from early on and it shows. Phoenix and LiveView are both great examples of tools that are built to keep you happy and productive when doing the bulk of the work. This is not an ecosystem that is just reaching the baseline, it is pushing forward. You can see Livewire (Laravel) and Hotwire (Rails, etc) picking up what LiveView put forward. I’ve heard many devs from other langs speak well of Hex, the package manager and the hexdocs it provides.
I don’t need new things for no reason, that’s the realm of experiments. I do want new things, actually useful progress, powerful tools built on solid foundations.
Stability and progress.
It is not about Elixir.
Elixir just happens to be a language, ecosystem and community that suits my values and priorities. That is no small thing. It feels like home.