I am in the process of expanding my Elixir application and wanted to sanity check some of the patterns which have emerged to see what others think.
I am attempting to layer the structure for composition and clarity, but have fallen into the habit of extracting things into a kind of command pattern.
For example, instead of:
defmodule App.Users do
def accept_invitation(invitation, user) do
end
end
I would have:
defmodule App.Users.AcceptInvitation do
def call(invitation, user) do
end
end
My folder structure would be:
users/
accept_invitation.ex
This has allowed me to build more complicated commands into separate modules/namespaces with just the relevant functions for that command instead of having lots of functions in the same module with mixed responsibilities.
I’m on a fence a little, but I can’t see any other way of keeping this clean as my application grows.
I have thought of a potential hybrid approach using defdelegate
:
defmodule App.Users do
defdelegate accept_invitation(invitation, user),
to: App.Users.AcceptInvitation, as: :call
def simple_function(user) do
end
end
Which would allow App.Users.accept_invitation(user)
, and allow me to bundle with small, related functions which don’t necessarily need their own module. I like this because it keeps the API simpler from the outside.
Or what about:
defmodule App.Users.Invitation do
def accept(invitation, user) do
end
end
However, I don’t particularly like this as I have quite a few Ecto models and would rather not dump too many functions in them and keep them responsible for schema and validation.
Just trying to figure some patterns which will serve me well going forward. The command modules and single call
functions are working well at the moment (especially having the file structure reflect the commands).
Thoughts?