Hayden: Sasa, it’s a pleasure to discuss all things Elixir with you, I really appreciate you taking the time to work on this with me. We’ve been working hard to produce helpful content so that Beamrec.com can act as a useful resource for Elixir enthusiasts.
Your name & work has been mentioned to me on so many occasions by Elixir devs, Elixir in Action seems to be essential reading for anyone that is interested in learning the language.
To make you aware, I’m a ‘non-techie’ but have spent the past 7 years recruiting in the BEAM market so I’ve picked up some knowledge along the way, enough to get by at least :)
I have some questions that I’ve gathered from research & some contacts in the community, it would be great to hear your thoughts & opinions on some of these topics.
Hayden: I generally ask this to everyone I speak to, how did you first hear about Elixir? What immediately attracted you to it?
Sasa: It happened after using Erlang for about a year. At the time I really enjoyed the concurrency model, but I also found the language to be too simple, which led to quite a lot of boilerplate and noise in the code. So I started looking for a language which would give me similar concurrency features, but with more expressiveness and better supporting tools. Outside of BEAM, I looked at Scala and Go, while in the BEAM space I found two interesting languages: Reia and Elixir. I wasn't quite happy with what non-BEAM languages offered, while the BEAM languages seemed more promising, but also too immature at the time.
About a year later I started blogging at theerlangelist.com, with the purpose of sharing the things I liked about Erlang. I was worried that a more involved Erlang code would seem to scary to non-Erlangers, so I took another look at Elixir, hoping it would help me write more concise code, and therefore better illustrate some points. The language exceeded my expectations, and I was absolutely blown away. It was all I wanted from Erlang and more, and at the same time it was essentially Erlang, rather than some complex machinery on top of it. I was also impressed with the maturity of the project. I found the documentation extensive and informative, while mix already seemed way better than anything available in Erlang at the time. Despite still being at the early stage (version 0.7 at the time), I found the language to be mature enough for production, and quickly started using it in the existing Erlang project. The integration between the two languages was seamless, and Elixir quickly became my favourite language, offering the powerful BEAM support for highly-available systems in a developer-friendly language that draws inspiration from other languages such as Clojure and Ruby, while in its heart being quite close to Erlang.
Hayden: As one of the most popular mentors in the Elixir community, what would your advice be to someone just starting out in Elixir?
Sasa: Even as an author I don't suggest starting with a book. Instead, I advise going through the official guides at https://elixir-lang.org/, followed optionally with the Phoenix tutorial at https://hexdocs.pm/phoenix/. This will allow you to quickly get a feeling of the language and the Phoenix framework. Obviously it won't make you an expert, and you'll likely have a lot of questions and many things will seem magical, but you'll still be able to be productive to some extent, and at this point you can start to refine your knowledge.
The most important thing here is to write some code. Reading books and tutorials alone won't make you an expert. That can happen primarily through practice. If your company is using Elixir you have the perfect playground. Otherwise, you can consider doing a toy project, or solving programming challenges at e.g. Exercism (https://exercism.org/) or Advent of Code (https://adventofcode.com/). While you're practicing, consider reading more in-depth material, such as books and blog posts. Spending time at forums, such as elixirforum.com can also be helpful. Such resources will certainly help you expand your knowledge. But in my opinion, the two most important techniques for learning anything are practice and reflection.
Hayden: I understand that you’re doing some freelance mentoring now, how are you finding that? Are there any common problems that Elixir newbies are encountering?
Sasa: So far I've mostly worked with teams that had some Elixir knowledge and used it in production. In such cases, my impression was that often teams were not sure how to efficiently organize their codebase to support mid- to long-term maintenance. This is not an Elixir specific challenge, although obviously the language of choice determines the concrete approaches. In general, I've found that too often the code is either too fragmented or too coarse, with distinct responsibilities not properly separated. Another frequent issue I've seen is the lack of focus in tests. I've discussed some of the solutions to those problems in my recent talk called Clarity (https://www.youtube.com/watch?v=6sNmJtoKDCo).
When it comes to Elixir newcomers, my impression is that the main challenge lies in the amount of the material that has to be studied. None of that material is particularly difficult to learn, but there's just a lot of stuff to grasp, which can seem overwhelming. For example, if you want to write a CRUD web-backend, you need to learn Elixir, Ecto, Phoenix, and possibly also LiveView. If you choose one book for each topic, that can easily add up to about 1000 pages. Reading so much material without writing any code is going to be very demoralizing. By the time you finish reading the last page, you'll likely forget most of what you've previously studied.
That's why I'd like to reiterate my earlier advice about learning. Start by establishing some basic knowledge, then start producing the code. Rinse and repeat. Learn a bit about Elixir, write some code. Learn a bit about Ecto, and write some more code. Refine your knowledge as you go along. In addition, try to focus on the things you need immediately. For example, if you need to write GraphQL backends with Absinthe, you don't have to learn much about Phoenix. Just because you need to use Ecto, doesn't mean that you need to understand all of its advanced features. Such a line of thinking can significantly reduce the amount of material that must be studied upfront.
Hayden: Elixir has consistently grown in popularity year on year since 2014, to the extent that many no longer consider it a niche language choice, what do you envisage for the future? What do you predict for Elixir across the next 10 years?
Sasa: I don't like to predict the future, so instead I'll offer my personal wishes :-) I'd like to see the ecosystem further evolve to the point where building a small-to-medium fault-tolerant distributed backend (e.g. a web-facing CRUD) is possible using nothing but Elixir (i.e. without external database, reverse proxy, orchestration, etc.). This is in some ways already possible today. For example, with LiveView we can in some cases completely avoid JavaScript in our stack. Another interesting example is Phoenix Presence which gives us distributed statefulness without an external database. I'd like to see more such examples, where external products can be replaced with embedded libraries that we can control from our code, rather than through a combination of CLI arguments and yaml/json/ini configuration files. I believe that this style of building software, with less custom DSLs, less moving pieces, less OS processes to orchestrate, is much simpler, yet at the same time more flexible and powerful. Owing to its concurrency/distributed model, BEAM languages can support that, but it's up to us to make it happen. Hayden: Elixir has recently inspired some enthusiasts to create their own new languages, what are your thoughts on the likes of Gleam & Caramel that plan to introduce static typing? In what kind of scenario would you consider using them for a project?
Sasa: After working extensively with both dynamic and static typed languages, my position is that in most production cases static typing is better. I personally consider types to be first and foremost about documentation. Types describe the nature of the data coming into the function and out of it. This can significantly improve the reading experience, and simplify reasoning about the code. Therefore, when it comes to a codebase which is developed as a team effort over a long period of time, type specifications are not an option. We need them as a tool of communication and clarification between team members, the current and the future ones. But how can we be sure that specifications conform to the actual code? This can only be done reliably by a tool that can find and report all mismatches between type specifications and the actual code. And that to me is the role of static typing and type checking. It is the verification of the code against the accompanying formal documentation.
Therefore, I'm happy to see any exploration of static typing on BEAM. I'd be the happiest if something could be added to Elixir. But if that's not possible, then I definitely could see myself making a switch to some typed BEAM language, assuming it reaches the similar level of maturity as Elixir. I didn't yet look at Gleam or Caramel more closely to be able to make more concrete comments, but I'll definitely be looking at their further development, and I plan to give them a try at some point.
Hayden: In your talks you seem to have some strong opinions about code patterns, do you have any advice on how you could come to a consensus on a larger project with say 20-40 people? (many of whom come & go over time) How can teams of that scale successfully discuss, debate, decide, enforce & revisit Elixir code patterns across a larger project?
Sasa: The key thing is to develop a culture of teamwork where everyone understands that we should cooperate rather than compete with each other. The main driver for such a mindset is the idea of collective code ownership. Once the code is merged into some main branch, it becomes our code, not exclusively yours or mine. As a developer I want to be able to work on any part of the code, even the one I didn't write myself. Likewise, I want for other team members to be able work on the code I originally wrote. This improves the progress of the team, but also of individual people. As an individual, I can be more relaxed when I'm not working (e.g. on vacation), knowing that my teammates are able to deal with any possible issues. I also feel it's easier to make a switch to a different project, or even a different role. As a result I'm less anxious or stressed out. Collective code ownership can improve the happiness and productivity of people on the team, and therefore also of the entire team.
If this idea is properly communicated, it becomes easier to reach the consensus. Understanding that we need to find some common ground if we want to be a successful team, we can more easily distinguish relevant design concerns from unimportant nitpicks. Like many people in our profession, I have various personal preferences developed over time and influenced by my own experience. But if I understand the importance of teamwork and collective code ownership, I'm going to be more open-minded and more likely to accept different ideas and approaches.
It's also important to have a person on the team who can cut the debate and make a decision when the team becomes paralyzed. Without such a role there will be chaos, as I've witnessed first hand in a couple of teams. The code becomes a collection of individual contributions, with different parts using different styles and ideas, which is a nightmare to maintain. As a result, the level of stress is increased, people become more unhappy, they're more likely to leave the team. They are replaced with new people, but with a complete lack of a clear code design, that will just amplify the problem.
Therefore, no matter the team size, make sure to have a lead of some sort who makes the ultimate decision on the code design. Of course, such person should gather the feedback from everyone on the team, regardless of the expertise level, and try to leave as much of the decisions as possible to the team, exerting their own authority only when needed, for example when the team can't reach a consensus, or when they strongly feel that the team is heading into a wrong direction.
Finally, use the tools as much as possible to deal with low-level mechanical decisions, such as code layout and formatting. I wasn't a fan of code formatters, and I still believe that a human can do a better job of producing a human-friendly code layout, but I realize that formatters mostly do a good enough job while requiring a fraction of the effort. Most importantly formatters vastly reduce the amount of nitpicky debates, and the less we have of those, the more the time and the energy we'll have to focus on the important things.
Hayden: As a successful author, what advice would you give to a budding writer in the Elixir community?
Sasa: If I could single out one piece of advice, then it would be to find good reviewers. Elixir in Action wouldn't be half as good without them. Make sure to have both experts and non-experts in the review team. The former will check the content for correctness, but the latter represent your target audience and they are the only ones who can check the clarity of the prose. And without clarity, the book won't be much useful to the wider audience.
Hayden: Do you have any new publications or new versions in the works?
Sasa: I'm hoping to work on the 3rd edition of Elixir in Action at some point. The book is mostly up to date, save for the last chapter on OTP releases which requires some significant update, since in the meantime the support for OTP releases was added to Elixir.
Hayden: On behalf of myself & those that submitted questions, thank you so much for taking the time to speak with me, it's great to hear your insight on the Elixir ecosystem & how it's progressing.
I look forward to seeing the updated edition soon!