DEV Community

Cover image for My Top 5 Elixir Likes Today
Declan McGrath
Declan McGrath

Posted on

My Top 5 Elixir Likes Today

As it's coming up to my 6 month Elixir anniversary :-) I thought I'd post a snapshot of the top 5 things I've liked about starting to work day-to-day with Elixir...

1. Concrete Immutability

In many other languages to date, that have offer some functional programming, I'd find that I would be going well in my functional experiments - until I realised I'd accidentally mutated something. It's great to have the language enforce immutability so that you don't need to be worried if you are doing the right thing or not. Additionally, you can be confident that the performance characteristics of working with immutable data are optimised by the language.

2. Pattern Matching

If writing elegant code is, in part at least, the art of eliminating IF statements then pattern matching is surely one of the elegant coder's best friends. (Perhaps it is better to phrase "eliminating" as "making implicit" - as the IF statements are still there in principle, but they sit beautifully within the structure of your codebase rather than sticking out like sore thumbs.) Pattern matching seemed like one of the weirdest things to me before coming to Elixir. But we humans are natural pattern matching creatures and it doesn't take long for the idea to catch on. Soon, the thought of having one function - that frantically pivots around a series of IF statements - starts to look like the weird approach. Which is easier to reason about - one function which has 8 code paths through it via a network of IF statements? Or 8 functions with clearly defined pattern-matched entry points (perhaps plus one catch-all function for unhappy/unconsidered code paths)?

If the latter sounds worse then remember you can read the 8 code paths, like a table of contents, upfront. In the former case, you have to walk through the network of IF statements and reason about them. And the latter approach just sits nicely with human minds that lap up all those patterns!

3. The Ease of Selectively Reusing Code

Because you are only dealing with functions, it's surprisingly easy to move or use just the pieces of code you want. Want to use a single function from an otherwise complex module? You can. Just call it! The reason this is possible is that any complexity/state will likely be in a variable that you already have and want to act upon - and it is this variable that you will be passing into that function you want to leverage. In contrast, imagine trying to arbitrarily reuse 5%, 10% or 20% of the functionality of an object in a traditional OO paradigm. In such cases, you usually can't just use this over there because that would require a significant amount of work to set up the object/context. (Note: Just because you can selectively reuse functions doesn't mean you always should of course!)

4. Code Readability and Understanding

Because, at pretty much every point in an Elixir program, you are dealing with an input, followed by a calculation, followed by an output, it is usually straightforward to reason about causality. Coming from an OO style, it feels somewhat like moving from a combustion engine to an electric vehicle. There are less moving parts - but, instead of "parts", think "opportunities for indirection".

5. Ecto

I bowed out of the .NET world a long time ago, when LINQ was about to be the next big thing. Missing out on that was a slight regret at the time because I could sense a better world was possible when it came to querying data. Since then, I've typically either written SQL or used a framework's ORM functionality. But, the former is too hard to reuse and the latter is too rigid. Surely, there is a way that can retain the programmatic and algebraic advantages simultaneously. Yes there is! Enter Ecto and its powerful programmatic querying. Ecto is probably one of the best reasons to consider the Elixir/Phoenix stack. Querying is so flexible and Ecto has a host of other stellar ideas like changesets. Its similarities to the good parts of LINQ has also banished those nagging regrets!

So that's a braindump of my top 5 as it stands today. There's probably a glaring omission or some points that could be arguable. But all in all, it's been a very exciting journey and learning experience. Anything I have missed? Or is there one burning thing in Elixir that you couldn't live without?

I'll do another top 5 in future that covers some Elixir ecosystem surprises or even dislikes. But for now, let's stay positive :- ) If working with Elixir - even some of the time... perhaps mixed in with a little Ruby - sounds interesting to you then consider joining me on this exciting adventure at GreyScout, where there's open positions for Ruby-ish & Elixir-y types as well as pattern-match lovin' humans!

Top comments (3)

Collapse
 
theirishpenguin profile image
Declan McGrath

Hi Oisín, from my day-to-day developer-focused perspective, it goes very smoothly - particularly on the deployment front. But, I'd like to dig out more concrete details and share a fuller answer with you. It's a topic that I'm sure that would be of general interest, so I'll try to put something solid together on this.

Collapse
 
oisin profile image
Oisín Hurley

Declan, what about the deployment angle, the runtime, telemetry and monitoring and all that, how does the elixir support system rate in those areas?

Collapse
 
theirishpenguin profile image
Declan McGrath • Edited

Following up on my last reply, here's some more detail on the deployment/etc question. Hopefully, there's something here of use for thinking beyond the language itself. Just so anyone reading this can get a sense of the full gamut of deployment options in the Elixir ecosystem, I'll try to lay this out from a broad perspective initially and zone in.

The best place to start for an up-to-date set of deployment options for Elixir/Phoenix is usually the official deployment guide which lists the following guides at the time of writing...

  • Elixir's releases
  • Gigalixir, an Elixir-centric Platform as a Service (PaaS)
  • Fly.io, a PaaS that deploys your servers close to your users with built-in distribution support
  • Heroku, one of the most popular PaaS.

If you are going the PasS route, just note the limitations cited for Heroku relative to the other PaaS platforms (in the Heroku guide above) which may not concern you but at least will allow you to make an informed choice.

Note: For deploying to things like AWS and Google Cloud Platform (GCP), you'll want to use the Elixir's releases guide above.

To narrow in a little on what route you may wish to take, we'll focus on a question that sounds like an ops version of a U2 song - "With or without docker?"

There is plenty of discussion on this question, such as here, but to short circuit some of that, here goes:

  • A strength of the BEAM is leveraged by using more stateful, non-disposable ways of serving applications. Servers that stay up on an ongoing basis can take advantage of BEAM features such as "hot code swapping", which means you can patch live code changes to production without downtime

  • This has a lot of obvious benefits in certain use cases (especially in the traditional telecoms domain that this kind of tech occupied). However, writing hot swappable code is non-trivial. And developers and ops folk are typically much more familiar with stateless disposable container technologies - as found in the Docker and Kubernetes approach to deployment

  • Hence, it is common to deploy using Docker/Kubernetes and forsake some of the benefits and simplifications that Elixir derives from being on the BEAM platform - such as hot code swapping - but gives the advantage of a familiar contemporary deployment strategy. Containers can then be deployed to AWS or GCP

But that is not to say there is one true right or wrong answer. So do check out the PaaS options as well, which may make for an easier and more flexible starting point for you and your team. For example, you may be swayed by what Gigalixir states it can do for you on its website, and play to some of the BEAMs strengths...

  • Distributed clustering is one of the coolest parts of Elixir. You can have distributed Phoenix channels without Redis. You can have global cron jobs without a separate scheduler. You can design your app the way you want to and keep one global process per game or chat room. You can distribute workload evenly across machines. The use cases are endless.
  • Hot upgrades let you deploy new code without restarting and you get true zero downtime deploys that don't drop websocket connections or lose in-memory state.
  • Remote console let's you debug your node and run one-off tasks.
  • Remote observer gives you a GUI to monitor and inspect your node.

So choose the best fit for your use case. As regards monitoring, there is the usual syslog integration that can work with any third party monitoring platform supporting syslog. For more advanced telemetry, Elixir's telemetry library integrates with Prometheus to give Dashboards in one's preferred monitoring system. Here's an example of doing that by the Fly.io team (one of the PaaS deployment options listed earlier) Monitoring Elixir Apps on Fly.io With Prometheus and PromEx.

So, you can have your monitoring dashboards appear in pretty much whichever platform you like. If you go the GCP route, it's worth noting that Prometheus is well integrated with GCP. Also, system level and application level metrics appear in GCP monitoring but can also be pushed to DataDog.

Hopefully, the above sheds some light on the different deploy options - irrespective of whether you are just trying to experiment with Elixir on a small scale or something more heavyweight. One way or another, you should be able to find something that suits your needs.