home

Elixir: A Case for Less /case/

In Elixir one has a wonderful `case` statement to use:

@spec check_calendar(date()) :: {[date_slot()], [info_atom()]}

def check_calendar(date) do
  case Calendar.check(date) do # Reads from database adds some more logic
    :free -> Calendar.show_day(date)
    :off  -> {[], [:day_off]}
    {:available, slots} when slots < 3 -> {Calendar.grab_slots(date), [:busy]}
    {:available, slots} when slots > 10 -> {Calendar.grab_slots(date), [:recommended]}
    {:available, slots} -> {Calendar.grab_slots(date), []}
  end
end

It’s a perfectly good function, but I have few issues with it.

From looking at it, I don’t know what happens when Database adapter error happens. Do I need to catch it? Of course, I could assume it won’t due to lack of “!” but unfortunatelly I cannot have any guarantees for that.

Second is, that if I’d like to test the logic (I would like to question - what happens when I receive {:available, -1} which is an obvious error, but hey, could happen - I can’t.

This function relies on side effect.

But I’d like to propose a simple change:

def check_calendar(date), do: check_calendar_result(date, Calendar.check(date))

def check_calendar_result(date, :free), do: {Calendar.build_slots(date), []}

def check_calendar_result(_, :off), do: {[], [:day_off]}

def check_calendar_result(date, {:available, slots}) when slots < 3,
     do: { Calendar.grab_slots(date), [:busy] }

def check_calendar_result(date, {:available, slots}) when slots > 10,
     do: { Calendar.grab_slots(date), [:busy] }

def check_calendar_result(date, {:available, _}),
     { do: Calendar.grab_slots(date), [] }

Logic remains the same, few benefits:

  • I can unit test logic function easier
  • Dialyzer can pick up function headers and catch potential errors
  • It’s very easy to separate behavior that can even further ease testing, e.g
# ...
def check_calendar_result(date, {:available, _}),
     { do: calendar_impl().grab_slots(date), [] }

def calendar_impl do
  Application.fetch_env(:my_application, :calendar_impl, Calendar)
end

Przemysław Alexander Kamiński
vel xlii vel exlee

cb | gl | gh | li | rss

Powered by hugo and hugo-theme-nostyleplease.