What’s your 80/20 technique for maintaining a healthy Elixir codebase?

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