When I started reading the post, I though the author would talk about pattern matching to get rid of the switch block.
In that case, creating a user can be expressed in Elixir as follows:
def createUser(attributes, "admin") do
create(attributes) |> setupAdmin |> setupNotifications
end
def createUser(attributes, "customer") do
create(attributes) |> setupCustomer |> setupNotifications
end
# example
User.createUser(%{name: "laura", age: 30}, "admin")
Here, we chain functions using a pipe, |>, assuming that each function returns a user-like variable, like %User{}I also liked the idea of using a callback for decoupling code (although that approach was discouraged by many users in this post). It could be done in Elixir as follows:
def createUserCallback(attributes, callback) do
create(attributes) |> callback.() |> setupNotifications
end
# example
User.createUserCallback(%{name: "laura", age: 30}, &User.setupCustomer/1)
User.createUserCallback(%{name: "laura", age: 30}, &User.setupAdmin/1)
Since callback can be any kind of function, we can use pattern matching to enforce that the return type of each function is a user, ie %User{}: def createUserCallback(attributes, callback) do
user = %User{} = create(attributes)
user = %User{} = callback.(user)
user = %User{} = setupNotifications(user)
user
end
Another approach is using a @spec annotation to define the signature of the callback.Full code:
defmodule User do
defstruct name: nil, age: nil, type: nil
defp create(_attributes = %{name: name, age: age}) do
%User{name: name, age: age}
end
defp setupNotifications(user = %User{}) do
IO.puts("User created #{user.type}: #{user.name}")
user
end
def setupAdmin(user = %User{}) do
%User{ user | type: "admin" }
end
def setupCustomer(user = %User{}) do
%User{ user | type: "customer" }
end
def createUser(attributes, "admin") do
create(attributes) |> setupAdmin |> setupNotifications
end
def createUser(attributes, "customer") do
create(attributes) |> setupCustomer |> setupNotifications
end
def createUserCallback(attributes, callback) do
user = %User{} = create(attributes)
user = %User{} = callback.(user)
user = %User{} = setupNotifications(user)
user
end
end