You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Define "nutrition facts" for "use SomeModule" (#12613)
One common concern about using Elixir libraries
is that "use SomeModule" does not make clear how
it impacts the caller. Most of the time those
changes are minor but it is impossible to know
without traversing the source code.
This pull request suggests defining a summary
alongside each module that succintly explains
the impact of using it.
This is documented as best practice in our guides
and we added the note to all of Elixir modules.
Copy file name to clipboardExpand all lines: lib/elixir/pages/library-guidelines.md
+26-2Lines changed: 26 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -65,7 +65,7 @@ you should prefer:
65
65
```elixir
66
66
caseFile.read("some_path_that_may_or_may_not_exist") do
67
67
{:ok, contents} -> {:it_worked, contents}
68
-
{:error, _} ->:it_failed
68
+
{:error, _} ->:it_failed
69
69
end
70
70
```
71
71
@@ -200,7 +200,31 @@ The code above says we are only bringing in the functions from `MyLib` so we can
200
200
201
201
If the module you want to invoke a function on has a long name, such as `SomeLibrary.Namespace.MyLib`, and you find it verbose, you can leverage the `alias/2` special form and still refer to the module as `MyLib`.
202
202
203
-
While there are situations where `use SomeModule` is necessary, `use` should be skipped when all it does is to `import` or `alias` other modules. In a nutshell, `alias` should be preferred, as it is simpler and clearer than `import`, while `import` is simpler and clearer than `use`.
203
+
### Avoid undocumented `use SomeModule`
204
+
205
+
In some situations, where you need to do more than importing and aliasing modules, allowing a developer to `use SomeModule` may be necessary. The benefit of `use SomeModule` is that it provides a common extension point for the Elixir ecosystem. However, given `use SomeModule` can execute any code, it may not be easy for developers to understand the impact of `use SomeModule`.
206
+
207
+
For this reason, to provide guidance and clarity, we recommend library authors to include an admonition block in their `@moduledoc` that explains how `use SomeModule` impacts the developer's code. As an example, the `GenServer` documentation outlines:
208
+
209
+
> #### `use GenServer` {: .info}
210
+
>
211
+
> When you `use GenServer`, the `GenServer` module will
212
+
> set `@behaviour GenServer` and define a `child_spec/1`
213
+
> function, so your module can be used as a child
214
+
> in a supervision tree.
215
+
216
+
Think of this summary as a ["Nutrition facts"](https://en.wikipedia.org/wiki/Nutrition_facts_label) for code generation. Keep in mind to only list changes made to the public API of the module. For example, if `use SomeModule` sets an internal attribute called `@_some_module_info` and this attribute is never meant to be public, it must not be listed.
217
+
218
+
For convenience, the markup notation to generate the admonition block above is:
219
+
220
+
```
221
+
> #### `use GenServer` {: .info}
222
+
>
223
+
> When you `use GenServer`, the `GenServer` module will
224
+
> set `@behaviour GenServer` and define a `child_spec/1`
0 commit comments