TW: controversial statements ahead ![]()
In languages like Elixir, where you don’t get truly private modules (another example of that would be Ruby), private functions don’t matter as much as people give them meaning. Say, you write a code like this:
defmodule Note do
def normalize_title(title)
title
|> normalize_case()
|> replace_illegal_characters()
end
def normalize_case(string), do: [something]
def replace_illegal_characters(string), do: [something]
end
In my experience there is a 95% chance someone will call that out during the code review, because normalize_case and replace_illegal_charecters should be private. But do it like that, and nobody will bat an eye ![]()
defmodule Note do
def normalize_title(title)
title
|> StringHelper.normalize_case()
|> StringHelper.replace_illegal_characters()
end
end
Now it’s okay. You can test the StringHelper in isolation, because its functions are “legally” public. This is encountered in codebases more often than people think.
This matters if you are writing a library, i.e. you don’t control how and by whom your code is used. In this scenario it makes sense to try to keep public API surface as small as possible. Make the function public and you never know if someone uses it, so even renaming it is a breaking change.
But in a classic “work project” it’s pretty much a cargo cult. You control the “supply” and “demand” side, both definition and usage. You can simply grep a project for usages before making a change - and it will be safe. Private vs public remains mostly a guideline.
And if someone needs your private function outside of the module, they will simply make it public. Another things I’ve witnessed dozens of times.
The only thing maybe keeping the sense of having private functions id adhering to another cargo cult - that every public function needs to be unit testing. Then having some function private serves the purpose of avoiding too many, too brittle tests.


















