Created
May 25, 2025 15:05
-
-
Save thmsmlr/498d3613bfa7426b095b44dfeaaf951b to your computer and use it in GitHub Desktop.
My cursorrules for elixir coding styles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
When writing Elixir code, perfer the following style guidlines: | |
1. Elixir developers tend to create many small functions in their modules. I DO NOT LIKE THIS. Instead create functions that fully capture a conceptual task, even if it makes that function longer. A good rule of thumb is, if a private function is only called once within a module, it should've been inlined. | |
For example: | |
DON'T DO THIS: | |
```elixir | |
defmodule SomeModule do | |
def some_public_function do | |
x = some_private_function | |
x + 1 | |
end | |
defp some_private_function do | |
72 / 2 | |
end | |
end | |
``` | |
Instead, perfer to inline single use private functions: | |
```elixir | |
defmodule SomeModule do | |
def some_public_function do | |
x = 72 / 2 | |
x + 1 | |
end | |
end | |
``` | |
2. DO NOT ADD UNNECESSARY CODE COMMENTS. Code should generally be self evident. I am a senior developer, I assure you I can understand the code you produce. Only add comments if it's not obvious what's going on, or if it's because of some edge case that isn't obvious. | |
3. Question Intermediate Layers, Ensure every layer of abstraction (like services) provides tangible value by hiding significant complexity. Wrapper modules just add unnecessary indirection and make the code more confusing to read. | |
Good Implementation: | |
```elixir | |
# Controller calls context directly | |
defmodule MyAppWeb.UserController do | |
use MyAppWeb, :controller | |
alias MyApp.Accounts | |
def show(conn, %{"id" => id}) do | |
user = Accounts.get_user!(id) | |
render(conn, :show, user: user) | |
end | |
end | |
# Context handles DB interaction | |
defmodule MyApp.Accounts do | |
alias MyApp.Repo | |
alias MyApp.Accounts.User | |
def get_user!(id), do: Repo.get!(User, id) | |
end | |
``` | |
Bad Implementation: | |
```elixir | |
# Controller calls a 'service' | |
defmodule MyAppWeb.UserController do | |
use MyAppWeb, :controller | |
alias MyApp.Users.UserService | |
def show(conn, %{"id" => id}) do | |
user = UserService.find_user_by_id(id) | |
render(conn, :show, user: user) | |
end | |
end | |
# Service just calls the context (Adds little value) | |
defmodule MyApp.Users.UserService do | |
alias MyApp.Accounts | |
def find_user_by_id(id) do | |
Accounts.get_user!(id) # Just a pass-through | |
end | |
end | |
# Context (Same as above) | |
defmodule MyApp.Accounts do | |
alias MyApp.Repo | |
alias MyApp.Accounts.User | |
def get_user!(id), do: Repo.get!(User, id) | |
end | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment