Quick & Easy Elixir Refactorings — Part 1

Over the next few blog posts I’ll be covering some quick easy refactorings that could help you tidy up your Elixir codebase.

We’ll go over some patterns you might find in your code and look at simple techniques you can use to hopefully make your code neater, easier to work with in the future and more readable.

In this first post I’ll cover functions that start with a conditional. In following posts we’ll cover functions that start with similar code but with different ends and functions that have something slightly different in the middle among others.


Functions starting with a conditional

This is a pattern I see a lot with people new to Elixir or pattern matching, especially with a good Ruby background where they already have a great practise of writing small functions.

The first thing to happen in these functions is we check something that was passed in.

defmodule Example do
  def is_zero?(number) do
if number == 0 do
true
else
false
end
end
end

Contrived example for sure and first thing you could do is get rid of the useless if structure like this

defmodule Example do
  def is_zero?(number) do
number == 0
end
end

But lets imagine this was little more complicated. What we can do instead is do the conditional branching using pattern matching in the function signature

defmodule Example do
  def is_zero?(0), do: true
def is_zero?(_), do: false
end

This is particularly nice if you started with a 8–9 line function where both branches had 3 or so lines of code.

This is also handy for case statements

defmodule Example do
  def send(message) do
case message.type do
:sms ->
# some SMS send code
:email ->
# email send code
:slack ->
# Slack code
_ ->
# Bad type catch
end
end
end

becomes something like

defmodule Example do
  def send(%{type: :sms}) do
# some SMS send code
end
  def send(%{type: :email}) do
# some email send code
end
  def send(%{type: :slack}) do
# Slack code
end
  def send(_) do
# Bad type catch
end
end

or even

defmodule Example do
  def send(%{type: :sms}), do: # some SMS send code
def send(%{type: :email}), do: # some email send code
def send(%{type: :slack}), do: # Slack code
def send(_), do: # Bad type catch
end

If your functions start by inspecting the values passed in and branching from there there’s a good chance you can use pattern matching to tidy things up.

Please click the high fives icon below if you liked this post and follow me here and on Twitter @efexen for the next post where we’ll look at more simple tricks for leveling up your Elixir code 👍

Next: Quick & Easy Elixir Refactorings — Part 2