By: Christoph Wagner, Coding Team (former), Break Diving, Inc.
I’ve been spending some time recently learning a bit of Elixir and Phoenix.
If you’ve never heard of it, Elixir is a new-ish programming language that borrows a lot of syntax from Ruby. However, even though it looks quite similar on the surface, it’s really a very different language.
Ruby is an object oriented, multi-paradigm language (meaning it supports imperative and functional programming styles). It’s also interpreted, meaning that there is no compilation step.
This is what makes many of the advanced features in Ruby work, but it’s also the reason why it is rather slow compared to languages like Java or C, which involve a compilation step.
Elixir is similar to Java, in the sense that there is a compiler, but instead of machine code, it produces byte code that runs on a virtual machine. In the case of Elixir, this is Erlang, a language invented by Ericsson about 20 years ago for use in telecommunications equipment.
It turns out that Erlang has many features that are very desirable for building web applications, such as high performance, fault tolerance, and the ability to support many millions on simultaneous connections. It also has very good support for multi-core CPUs, something that is more and more important (even your smartphone has multiple CPUs these days).
However, Erlang’s syntax is apparently quite dated (it was invented in the 90s). Elixir aims to fix that.
Phoenix is the web framework for Elixir. It’s heavily inspired by Ruby on Rails and has many of the same features. However, it’s an order of magnitude faster. Instead of taking several milliseconds, it can answer most requests in a matter of microseconds.
There is a cost, however, and that’s learning a new programming paradigm. Elixir is a *functional* language, meaning that there are no objects, only functions. Furthermore, functions have to be “pure” in the mathematical sense, that is, they can have no side effects.
All data in Elixir is *immutable* by default, meaning it cannot be changed. If you want to make changes to a variable, you need to return a new copy that includes the changes.
Of course, making copies of things is heavily optimized, so it’s faster that you’d think.
The advantage of having immutable data is that it allows for easy parallelization. The biggest problem that languages like Ruby have with parallelization is when data needs to be shared between two threads
If two separate threads want to access the same data (say, one wants to read and another wants to write), it creates a conflict. They have to synchronize somehow, so that one thread has to wait until the other is done before accessing the shared data. This can lead to many difficult-to-resolve bugs.
In Elixir, everything is immutable, so there is no problem sharing data between threads. If one thread wants to make changes, it automatically gets its own copy of the data.
It takes a bit of practice, but after a while it’s not that difficult thinking only in functions. A web server is really just a collection of functions (AWS lambda makes that pretty clear). Each function has as its input the user’s request (HTTP method and URL), and the current state of the database. It returns an HTML page.
That’s exactly how Phoenix treats it.
Requests go in, HTML comes out. Phoenix just gives you the tools to compose your functions out of many smaller functions, and a way to organize them in a sensible way.
Similar to Rails, it uses the MVC (Model, View, Controller) pattern, but it introduces a few more layers to keep things clean.
In Phoenix, every controller has a single view module, which then can have several templates. Any helper functions that are used in the view (which go into a helper module in Rails) go into the view model.
It also adds another layer (called a “context”) between controllers and models, which absorbs all the database queries. That means in Phoenix, models can focus on business logic. This fixes a big problem with Rails, where models often grow tremendously large because they have to deal with both business logic and database logic.
All in all, it makes for quite an interesting framework.
Another interesting aspect of Phoenix is the idea of pipelines, which fixes another big problem of Rails: middleware. If you’ve ever worked on a large Rails app, it can be quite difficult figuring out exactly what filters are run for a request and in what order. Even more so if you have an application that has both an HTML frontend and an API. In this case, you often want a different set of filters to apply for API requests than you have for HTML requests.
Phoenix solves this by letting you combine all the filters (called “plugs” here) in a pipeline and then giving you a way to decide which pipeline a request should use.
So if it’s a browser request, you send it through the “browser” pipeline. If it’s an API request, you send it through the “api” pipeline. Neat.
All of that said, I have to say it’s a clever framework, but the learning curve is quite steep. I wouldn’t recommend it to new coders, because there are so many concepts to learn. It’s rather something for experienced coders. If you’ve used Rails for a few years, it’s easy to pick up Elixir and Phoenix, but as a first language/framework, it might be a bit too complex. Rails, in my experience, has a much easier learning curve, and I’d recommend that to someone just getting started with web applications.
Break Diving, Inc. is a tax-exempt 501(c)(3)
Read all about our amazing mission at www.BreakDiving.org
Join our free community at www.breakdiving.io
Like what we do? Please make a feel-good donation!
Remember to tell your friends about this www.BreakDiving.blog