Let me know if this sounds familiar:
You start working on a project. You add a schema (let’s say User). You create a User context module around functionality for a User. Everything is going well.
Three months later, that User now has several schemas associated with it (Roles, Settings, etc.) and the User context is now 500 lines long. But all the functions seem to make sense here.
Hit to close to home?
Code without defdelegate
defmodule Example.Users do
def get_user(id), do: #...
def get_user_by_email(email), do: #...
# 500 lines later
def get_roles_for_user(user_id), do #...
def get_settings_for_user(user_id), do #...
#....
end
Other languages have techniques to handle this, but Elixir has a secret weapon we can wield to tame our context. That weapon is known as defdelegate
. By definition defdelegate “defines a function that delegates to another module.”
Now that we have our sword, let us go to war!
We will start by making two new modules and move the get_roles_for_user
and get_settings_for_user
to each one respectively.
defmodule Example.Users.Roles do
def get_roles_for_user(user_id), do #...
end
defmodule Example.Users.Settings do
def get_settings_for_user(user_id), do #...
end
Finally, we update our Users module, delegating the functions we moved using defdelegate
.
defmodule Example.Users do
def get_user(id), do: #...
def get_user_by_email(email), do: #...
defdelegate get_roles_for_user(user_id), to: Example.Users.Roles
defdelegate get_settings_for_user(user_id), to: Example.Users.Settings
#....
end
We have now cleaned up our Example.Users
module while keeping our API the same. No upstream changes to code are needed!
Using defdelegate to Refactor
defdelegate
can be a great refactoring tool. But don’t overuse it. Focus its use on keeping your API consistent for you and your users. Sometimes it’s better to create a new module instead.
defdelegate
responsibly!
We're building an AI-powered Product Operations Cloud, leveraging AI in almost every aspect of the software delivery lifecycle. Want to test drive it with us? Join the ProdOps party at ProdOps.ai.