dangdennis
What’s your 80/20 technique for maintaining a healthy Elixir codebase?
Hey, Elixir novice here coming from Typescript, Go, Ocaml.
What are your favorite techniques to get the most of your compile time checks, code readability and maintainability, and even testing strategies?
I just read this https://ulisses.dev/elixir/2020/02/19/elixir-style-for-maintanability.html, and I actually hadn’t thought to do more pattern matching on structs. Noteworthy to me because the code generated for Ecto’s CRUD functions often just pass along a generic map as the sole argument for parameters. Looking back at my project now, it would’ve served me better if I had used the specific struct as the argument.
Most Liked
zorn
I just posted a blog post on how I scope my use of typespecs, trying to find a a type safe balance while enjoying the dynamic nature of Elixir:
I also am really starting to fall into a groove with pattern matching and use it more and more – specifically I like making sure the variables I’m binding values into are the only ones required for a test or function. Trying not to make too many assumptions about the data (so it can hopefully evovle without breaking things).
Other final note, is I’m being much more mindful of how entities cross context boundaries. Still finding my way with LARGE code bases, but I feel like I’m starting to ask the right questions.
KristerV
my number one rule is to just go back tomorrow and read your code. Is there any doubt in your mind that you’ll enjoy reading this code in 2 years? Or worse yet - is there a remote possibility that this code is clear only because of memory?
Other than that this article has a few nice points: http://blog.cretaria.com/posts/erlang-beauty.html
my favs are:
- keep functions the size of 7 lines
- turn case statements into functions
- rename stuff after you’re done with the code
harmon25
Maybe something to do with this: The Magical Number Seven, Plus or Minus Two - Wikipedia
I would imagine they mean 7 operations/assignments and for example a list that is split over n lines (for formatting sake) would just count as 1. Also comments and line breaks would not count, those are just there for context/formatting.
If your function is doing more than 7 things/operations inside of it, it becomes harder to keep all that in your head at once, and thus more prone to bugs…
Exadra37
Elixir has guard clauses, that I like to use heavily in conjunction with pattern matching:
defp _todo_hash(%{
title: title, # pattern matching
user_uid: user_uid,
date: date,
} = _attrs,
action
)
when is_binary(title) # guard clauses
and byte_size(title) > 0
and is_binary(user_uid)
and byte_size(user_uid) === 64
and is_binary(date)
and byte_size(date) === 10
do
# your code here
end
Now that I discovered the Domo library I am using it to have typed structs and then pattern match on them:
defmodule Tasks.Todos.Types.Event do
# @link https://hexdocs.pm/domo/Domo.html
use Domo
typedstruct do
field :type, :todo | :backlog
field :target, :todo | :backlog | :all
field :action, :add | :update | :move | :duplicate | :delete
field :origin, atom()
field :broadcast_topics, list(), default: []
field :context, map(), default: %{}
end
end
that are then used like this:
def broadcast_change(
{:ok, data} = result,
%Tasks.Todos.Types.Event{} = event
) do
# your code here
do







