Skip to content

Instantly share code, notes, and snippets.

@zoedsoupe
Last active September 3, 2024 01:44
Show Gist options
  • Save zoedsoupe/8563f8e16a7c4a65d64066a42be02919 to your computer and use it in GitHub Desktop.
Save zoedsoupe/8563f8e16a7c4a65d64066a42be02919 to your computer and use it in GitHub Desktop.
bad example of usage of with expression and the else clause in elixir and other examples
defmodule UserRegistration do
def register_user(params) do
with {:ok, user_data} <- validate_params(params),
{:ok, user} <- create_user(user_data),
{:ok, _email} <- send_welcome_email(user) do
{:ok, "User registration successful!"}
else
{:error, reason} -> {:error, reason}
end
end
defp validate_params(%{"email" => email, "password" => password}) when is_binary(email) and is_binary(password) do
{:ok, %{email: email, password: password}}
end
defp validate_params(_params), do: {:error, :invalid_params}
defp create_user(user_data) do
with {:ok, user} <- insert_user_to_db(user_data),
{:ok, _} <- log_user_creation(user) do
{:ok, user}
else
{:error, reason} -> {:error, reason}
end
end
defp send_welcome_email(user) do
case send_email(user) do
:ok -> {:ok, :email_sent}
{:error, reason} -> {:error, reason}
end
end
# Simulated helper functions
defp insert_user_to_db(_user_data) do
# Simulating success
{:ok, %{id: 1, email: "user@example.com"}}
# To simulate failure, return {:error, :db_error}
end
defp log_user_creation(_user) do
# Simulating logging success
{:ok, :logged}
# To simulate failure, return {:error, :log_failed}
end
defp send_email(_user) do
# Simulating email sending success
:ok
# To simulate failure, return {:error, :email_failed}
end
end
def handle_user_registration(params) do
with {:error, :invalid_params} <- validate_params(params),
{:error, :user_creation_failed} <- create_user(params),
{:error, :email_failed} <- send_welcome_email(params) do
{:error, "Failed to register user due to multiple errors."}
else
# Handle the success case as the "else"
_ -> {:ok, "User registration succeeded with all steps."}
end
end
defp validate_params(%{"email" => email, "password" => password}) when is_binary(email) and is_binary(password) do
# Simulating an error in validation
{:error, :invalid_params}
end
defp validate_params(_params), do: {:ok, %{email: "valid@example.com", password: "secret"}}
defp create_user(_user_data) do
# Simulating an error in user creation
{:error, :user_creation_failed}
end
defp send_welcome_email(_user_data) do
# Simulating an error in sending email
{:error, :email_failed}
end
def worse_example(params) do
with {:ok, user} <- fetch_user(params),
{:ok, account} <- fetch_account(user),
{:ok, balance} <- fetch_balance(account) do
IO.puts("All good! Balance: #{balance}")
else
{:error, :user_not_found} ->
{:error, "User not found."}
{:error, :account_not_found} ->
{:error, "Account not found."}
{:error, :balance_not_found} ->
{:error, "Balance not found."}
# Now it gets worse with mixed formats
:user_not_found ->
{:error, "User not found (atom)."}
{:user_not_found, reason} ->
{:error, "User not found with reason: #{reason}"}
"user_not_found" ->
{:error, "User not found (string)."}
# More mixed return types
{:error, account_error} when is_atom(account_error) ->
{:error, "Account error: #{account_error}"}
{:error, balance_error} when is_binary(balance_error) ->
{:error, "Balance error: #{balance_error}"}
{:ok, _} ->
{:error, "Unexpected success? Should this be an error?"}
_ ->
{:error, "Unknown error. Who knows what's happening?"}
end
end
defp fetch_user(_params), do: {:ok, %{id: 1, name: "Alice"}}
defp fetch_account(_user), do: {:ok, %{id: 123, balance: 500}}
defp fetch_balance(_account), do: {:ok, 500}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment