At least, that’s what I feel like when writing Elixir code .. Like an Alchemist… Constructing a bunch of flasks and burners, interconnected with a series of glass tubes, working seamlessly together to produce meth- erm.. I mean, Magic!
You High, Bro?
I can’t deny the high feeling I get when working on Elixir. It’s just such a foreign language when compared to the crappy language I learned programming through (C++!). Without the static typing, without the generics, without the classes, without the inheritance … Functional programming at it’s best, coupled with process-oriented architecture. Let me just spit out a few nice Elixir encounters I’ve had.
.. On second thought, you should probably get an idea what the project itself is! Well, it’s a game backend! Yup, a game backend, with user profiles, matchmaking, rooms, leaderboards, game sessions, .. The whole 9-yards, basically. For a one developer, with absolutely no prior experience in shipping Elixir nor a game backend to do that would be considered insanity .. But here I am, 5 months into this project, with the most stable backend code I’ve ever written.
Built on top of Erlang, this robust, mature, and fully-featured beast, Elixir is usually the only technology you’ll need to run the show. Within the Erlang ecosystem, you can take care of logging, background jobs, routing, … etc. This cuts down the complexity tremendously!
Functional programming is by definition simple. The fact that no data is mutable just takes one more thing off your head, “Will an object change under my feet?” .. NEVER.
The fact that it’s concurrent causes lots of misconception that such a feature results in complexity and overhead … NO! That can’t be any further from the truth.
The fact that it’s concurrent means you are safe from race conditions. It means you can isolate your code with minimal effort, and safely contain any error from causing the whole system to go down. It means .. profit.
Am I Truthly?
Ok, how can I convince anyone with all that rant above without some stories, eh? Sore-wa, dame desu.
First, let’s take a quick look at a very quirky problem that usually takes a ton of work to sort out .. Player state.
You have player states everywhere! A game session contains the game state along with the connected players. A game room contains the players that joined, and could be chatting with one another. A matchmaking state tracks if the players accept the challenge or decline … and so on.
I am not even interested in exploring the solution in a traditional OOP language, since it would involve some sort of central crappy thing, OS threads, and stuff like that which just makes the system ever so error prone.
What about Elixir?
It’s literally as simple as spawning an Elixir process (Actor) that would manage the session. That’s it! The process would also monitor the player state, and make sure if the user disconnects, it processes the state accordingly. Let’s take an example.
A player opens a game room by sending a “join” request with a certain ID format. Once the backend detects that the player is trying to join with an ID and room meta data, it will spawn a new “room state” process, assign it the room meta data, register the process globally using the room id, then add the host player.
Once the room is added, we broadcast its availability to all players. Once another player decides to join, the player sends the same “join” request, with that room id (but no room meta this time). Once the backend processes that request, it can easily fetch the room process using the ID provided, since remember! We did register the process globally using the room id! So, fetch it, add the user, and you are done!
Well, at that point, the room state process will notice that it has 2 players, which means the room is filled! It will signal both players to proceed to the game, and broadcast an updated to the other players that the room is no longer available … la fin!
I can never cover my journey with Elixir in one post, nor ten, but hopefully this will give you some urge to unravel this mighty beast, and look beyond the primitive tools education casts on us!