One Flew Over the Phoenix's Nest
Phoenix is a Web Framework inspired by Ruby On Rails, the father of all modern Web Frameworks. It’s written on Elixir, which is a functional dynamic language that runs on the Erlang Virtual Machine.
The ErlangVM, also known as BEAM, is an incredible piece of engineering. It has been around for about 30 years but for some reason, it didn’t get mainstream. Its reliability is contrasted: around 50% of the worlds telephone switches work on top of BEAM. Another example is WhatsApp (link, link), which is able to handle more than 900 million users thanks to the ErlangVM.
We also owe the Actor Model to the Erlang community, which is being more and more used over time. A few months ago I wrote a post about using it with F# . When you program in Elixir you feel that the BEAM interop is quite natural. That's because it was built with a functional programming language in mind, Erlang. In languages like F# when you have to deal with the standard libraries of .NET you will end up doing workarounds because .NET was built with C# in mind. For me this is a selling point, we don’t have drawbacks because of the main language of the VM being imperative.
Elixir is a functional, dynamic programming language with a syntax inspired by Ruby, but it’s just the syntax. As with all functional languages the concept of objects doesn’t exist in Elxir.The data doesn’t mutate, it’s transformed. Elixir has a macro system for extending the language and also has Erlang interop. It has a REPL, IEx and a build tool called Mix. It even has a gradual type system. If you have followed me on Twitter for long enough, you know that I really like typed functional langs. Unfortunately for me, there is no typed production-ready language on top of BEAM. If you want to be updated about the langs that run on the ErlangVM, this repo is great.
Standing on BEAM’s shoulders, Phoenix makes it easy to build Webs, APIs and Channels (aka real time communication through sockets) without interfering too much in the design of our application. This gives us applications that are easy to maintain or at least more maintainable than the average Web Framework. This is because, if we don’t include Ecto here, a lot of times you will have the impression that you are working with a light library. That’s possible because Phoenix is built with the concept of Referencial Transparency, in mind, which basically says: for the same input we will always obtain the same output or in other words: we have guarantee that our functions don’t modify the state out of its scope. With that level of isolation, it’s super simple to test or to open a REPL and start building the application by pieces. Plug was created with this concept in mind, and it’s in the heart of Phoenix.
According to its documentation. Plug is:
1. A specification for composable modules between web applications
2. Connection adapters for different web servers in the Erlang VM
Plug can be seen as a function* with the following signature:
conn -> conn
A function that receives a connection and returns a connection. The connection is just a dictionary. This means, the plug receives a connection and returns a transformation of the given connection. In Phoenix plugs are everywhere: controllers, router (it’s also a pipeline), authentication, logs.. There are a lot of third party apps that follow the plug’s specification. So they can be *plugged* to Phoenix without additional work.
*To be precise a plug is composed by two functions, init and call.
Let’s write a Hello World. I wanted to create an Evernote-like app but to keep this post as short as possible I will skip that for the next one.
The first thing that we have to do is to setup our environment.
Then we can open a terminal and type:
mix phoenix.new hello_world
Mix will ask us to download the dependency, obviously we will want to do that. Then we will have to move to the hello_world directory and type
This will create our database. To start a server we can type:
If we go to http://localhost:4000 we will see our brand new app. If we go to web/pages/index.html.eex and replace the content of the file with “Hello World!”, when we save it, we will see how the app is automatically updated.
How awesome is that? Yes, the view (which is written in Elixir) was recompiled (yes, Elixir supports hot compilation) when we saved the file, and thanks to that there is a socket, the page will be automatically updated. This is implemented at framework level, which means that it will work with any editor without needing external tools!
The project structure in Phoenix is the following:
config: it will contain all the configuration files of the project. By default there is a configuration file for each environment: Dev, Prod and Test.
deps: this folder contains the dependencies of our application.
lib: inside lib lives the entry point of our app.
priv: usually it’s used for things related to the data layer. E.g. location files, database migrations or the database repository.
test: as its name indicates, here is where the test lives.
mix.exs: it’s the mix’s entry point. It defines the project’s dependencies among other things.
web: here is where our application lives. And this is its structure:
│ └── page_controller.ex
│ ├── layout
│ │ └── app.html.eex
│ └── page
│ └── index.html.eex
| ├── error_view.ex
| ├── layout_view.ex
| └── page_view.ex
channels: we will have a file for each channel. Remember that a channel is an entry point of our server that allows us to have stateful real time communication with a client through a socket.
controllers: as pretty much all modern web frameworks here is the folder where our controllers will be.
models: in this folder we will define the database’s scheme and all the transformation functions (behaviours). Remember that there are no objects in Elixir. The ActiveRecord pattern was also replaced by the Repository pattern.
router.ex: routes definition file.
templates: Phoenix distinguishes between Views and Templates. Templates are basically an Elixir DSL for generating HTML. The same as Asp.NET does with Razor. By convention there will be a directory for each controller and a file for every action.
views: here will be the necessary transformation functions to get our templates as passive as possible. It’s convenient to distinguish between them because a lot of transformation can be applied not only to the templates but also to APIs and Channels as well.
web.ex: here we can include the definition of our modules. By default it includes definitions for routes, models, controllers, views and channels.
Chances are that Phoenix will be the very first mainstream functional web framework. I really think that the following year apps and webs will consume channels and Phoenix will include them out of the box. There are things that don’t convince me like how Ecto is coupled in pretty much all layers of our app or the fact that Elixir is a dynamic language. Besides that, I think that the ErlangVM will get noticed in the following years.