Elixir and Pragmatic Programming
In the run-up to delivering a talk about Elixir’s unique traits at the conference, I endeavored to link its use with the essence of pragmatic programming. It was a challenge to distill my raw insights into compelling arguments. However, I feel this connection is significant, particularly given that Dave Thomas, the co-author of Pragmatic Programmers and a vocal Elixir advocate, too shares this perspective. Though my presentation has concluded, I continue my effort to systematically present my musings through written words.
Pragmatic Programming
<Pragmatic Programmers, Dave Thomas & Andrew Hunt> is one of those must-read books for developers. What at first glance seems like just a collection of developer tips from a senior has remained relevant and instructive for developers for 20 years, and even more so in this new edition, which has been refined based on 20 years of feedbacks.
As it in the introduction to the first edition, this is not a theoretical book. It gives a lot of tips, but doesn’t try to prove them perfectly. It just gives you a subjectively better direction, like the advice of an experienced senior. For some, this may make the book feel less relatable and more dogmatic. It may even be more so because of the meaning of the term “Pragmatic” in the title of this book.
What is “Pragmatic”? The first thing that comes to mind is the opposite of “Idealistic”: fluid, situational, and dependent on reality, or by common English expression, “It Depends”. But if you take this to the extreme, the book ends up contradicting itself. How can you give any meaningful advice other than “just figure it out” when everyone’s situation is different, and even one person’s situation changes over time? Therefore, readers should take the book’s advice in their own way, but remain cautious and critical. In fact, the authors emphasize this several times in the book. There are several pieces of advice related to “be critical” and warnings like “beware of zealots”. After all, that could apply to this book as well.
Nevertheless, the content of the book has made strong impression on many people, so it’s worth reading repeatedly and I’m sure you can find something new each time. As with most good books, each time you read Pragmatic Programmers you will see different aspects of it depending on your own situation.
In my presentation, I underscored the book’s sections on “good-enough software,” “good design is easier to change,” and agile development processes, and maintainable code design. Additionally, I highlighted the importance of the developer experience, a theme not explicitly addressed in the book. I then linked these principles with Elixir as a tool for pragmatic programming.
Elixir and Pragmatic Programming
Pragmatic Programmers doesn’t tell you to use a particular tool. However, to be honest, the authors are often subtly indicating a particular focus. This is especially true when you consider the following context. One of the authors, Dave Thomas, seems to be obsessed with the Elixir language(at least in recent years). His enthusiastic praise of Elixir since its very first days made even Erlang creator Joe Armstrong curious enough to write an Elixir review. He eventually wrote a book of Elixir, <Programming Elixir>, and his publishing company, “The Pragmatic Programmers” has been a major contributor to the spread of Elixir, publishing almost all of the Elixir books on the market.
Of course, in 1999, when the author first wrote the book “Pragmatic Programmers”, Elixir didn’t even exist yet, so there was nothing in the book about it. However, in the new edition, much of the example code in the book is in Elixir, and some of the topics are very closely related to Elixir. In other words, the author was clearly impressed by Elixir and influenced by its development values.
I’m going to show more specific examples in the book that support this insist.
In Topic 24. Dead Programs Tell No Lies, the phrase “CRASH, DON’T TRASH” sums up the philosophy of erlang and elixir. erlang’s Let it Crash is distinctive concept that is unique to erlang, and even though it’s now over 30 years but it seems to be even stronger in the modern era of increasingly complex distributed processing environments.
The Topic 30. Transforming Programming is closely related to the functional programming. Although functional programming is not necessarily needed for this, a functional programming perspective inevitably leads to a data transformation perspective. In particular, most functional programming languages support a pipelining operator and it really clean up your code in those languages. So while functional programming languages are not required to transforming programming perspective, functional languages naturally lead you to think in terms of transforming programming. However, it’s important note that not “all” functional programming languages are designed around pipelines. In functional programming languages, it’s actually the combination of functions that matters, and languages like Elixir just make it easier to organize combinations of functions into pipelines, while languages like Haskell have multiple kinds of what can be called pipelines, which is not always easy to understand when you first encounter them. So while transforming programming is not a necessary concept for all functional programming languages, languages like Elixir with a simple pipeline syntax can maximize this strength.
Chapter 6 is a new chapter in the revised edition and talks about concurrency and parallelism. And one of the key topics here is Topic 35. Actors and Processes. It emphasizes that concurrency with actors is a simpler way of dealing with concurrency, without having to write extra code to control concurrency, since there is no shared state at all. And erlang is the best representation for this actor model. It’s interesting to note that creators of erlang didn’t read any papers on the actor model, yet it has become a popular representation of the actor model because several languages that implements actor model, including prolog, are ancestors of erlang. The creators of erlang created the language out of necessity for purely practical reasons, so there seems to have been no desire to create a theoretically precise implementation of the actor model. Therefore, while the actor model cannot be said to be erlang itself, it seems that erlang (and elixir) have made good use of the features of the actor model for practical purpose.
It is also worth noting that most of this erlang and elixir stuff is new in the revision, and I don’t think it negates what was there before the revision, it just makes it a little bit more advanced for the times. One more personal feeling is that both ‘transforming programming’ and ‘actors and processes’ make you think about complex things in a more simplified way. I think that both objected-oriented design, where state management is important, and thread-based concurrency design, where you have to consider shared state between threads, require complex thought flows. Even in functional programming, you may have to go through complex (though simple in code) thoughts to represent types mathematically (or algebraically), or in concurrent programming, you may need to know things like Software Transactional Memory (STM). Elixir uses a pipeline structure and an actor model to help you think more simply. I think the author wanted to emphasize this as pragmatism.
Programmers don’t need to be mathematicians, nor do they need to be obsessed with the theoretical aspects of functional programming. In fact, erlang has a great strength in concurrency, combined with the actor model, but it has moved away from being a purely functional language by making interprocess message communication a side-effect. In my opinion, erlang adopted functional programming to gain advantages in concurrency, just as immutable data structure simplify state management of isolated processes. In other words, erlang got its current features for very practical reasons, and elixir inherits the philosophy of erlang and adds things like pipelines, macros, and protocols for very practical reasons, and a truly pragmatic language is completed.
Conclusion
When I was preparing for a talk at the conference, I was actually planning to tell why Elixir is good through giving a modest explanation listing the benefits based on my 3 years maintainance experience. However, at some point, I realized that the pragmatic programming should be contained in my presentation. Despite that I cannot explain well why pragmatic programming is matter for this presentation until almost the last moment, and just talked about it in the same kind as developer productivity, but now I think I can explain a little bit about why elixir is a language that represents pragmatism well.
I will continue to introduce others to elixir as a pragmatic language and try to help them understand the pragmatism I feel.