Skip to content
Merged
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
aa7b40c
"Complex extractions in clauses" (Anti-pattern documentation)
lucasvegi Jul 14, 2023
efa35af
"Dynamic map fields access" (Anti-pattern documentation)
lucasvegi Jul 14, 2023
e8f5a76
Fixing blanks-around-fences problem (Anti-patterns documentation)
lucasvegi Jul 14, 2023
38f3036
Apply suggestions from code review
josevalim Jul 16, 2023
a81d7ad
Apply suggestions from code review
josevalim Jul 16, 2023
b7ce804
Update lib/elixir/pages/anti-patterns/code-anti-patterns.md
josevalim Jul 16, 2023
ddd113b
Merge branch 'elixir-lang:main' into main
lucasvegi Jul 17, 2023
edf23e1
"Dynamic atom creation" added (Documentation)
lucasvegi Jul 17, 2023
9ef5eb4
Fixing backquotes usage (Dynamic atom creation - anti-pattern)
lucasvegi Jul 17, 2023
add1f7e
"Dynamic atom creation" documentation adjustments
lucasvegi Aug 10, 2023
f3bf95a
"Dynamic atom creation" - static_atom_creation() added
lucasvegi Aug 10, 2023
d0ecb3c
Update lib/elixir/pages/anti-patterns/code-anti-patterns.md
josevalim Aug 16, 2023
1004a49
Update code-anti-patterns.md
josevalim Aug 16, 2023
eaba20b
Update lib/elixir/pages/anti-patterns/code-anti-patterns.md
josevalim Aug 16, 2023
505d892
Merge branch 'elixir-lang:main' into main
lucasvegi Aug 17, 2023
fad00d7
"Speculative assumptions" added (Anti-patterns documentation)
lucasvegi Aug 17, 2023
8888097
Update lib/elixir/pages/anti-patterns/code-anti-patterns.md
josevalim Aug 18, 2023
e4b24f9
Apply suggestions from code review
josevalim Aug 18, 2023
20213d7
Merge branch 'elixir-lang:main' into main
lucasvegi Aug 18, 2023
3f165fa
"Long parameter list" added (Anti-patterns documentation)
lucasvegi Aug 18, 2023
b889bc3
Fixing typo ("Long Parameter List" documentation)
lucasvegi Aug 18, 2023
cfd552c
Update code-anti-patterns.md
josevalim Aug 20, 2023
991dccb
Merge branch 'elixir-lang:main' into main
lucasvegi Sep 1, 2023
098d665
"Alternative return types" added (Anti-patterns documentation)
lucasvegi Sep 1, 2023
8efb189
Apply suggestions from code review
whatyouhide Sep 1, 2023
d64185e
Apply suggestions from code review
josevalim Sep 11, 2023
60a1282
Apply suggestions from code review
josevalim Sep 11, 2023
4e2be8c
Apply suggestions from code review
josevalim Sep 11, 2023
159fe84
Update lib/elixir/pages/anti-patterns/design-anti-patterns.md
josevalim Sep 11, 2023
304fde0
Apply suggestions from code review
josevalim Sep 11, 2023
9103a18
Merge branch 'elixir-lang:main' into main
lucasvegi Sep 11, 2023
ca5ac56
"Using exceptions for control-flow" added (Anti-patterns documentation)
lucasvegi Sep 11, 2023
6b32731
Apply suggestions from code review
whatyouhide Sep 11, 2023
f683618
Update lib/elixir/pages/anti-patterns/design-anti-patterns.md
whatyouhide Sep 11, 2023
6bf7f08
Update design-anti-patterns.md
josevalim Sep 13, 2023
9dcba18
Merge branch 'elixir-lang:main' into main
lucasvegi Sep 14, 2023
580b345
"Unrelated multi-clause function" added (Anti-patterns documentation)
lucasvegi Sep 14, 2023
336a553
Apply suggestions from code review
whatyouhide Sep 14, 2023
8e4f6e7
Update design-anti-patterns.md
josevalim Sep 16, 2023
2d44257
Merge branch 'elixir-lang:main' into main
lucasvegi Sep 18, 2023
9c2728c
"Using application configuration for libraries" added (Anti-patterns …
lucasvegi Sep 18, 2023
4e70b0b
Update lib/elixir/pages/anti-patterns/design-anti-patterns.md
whatyouhide Sep 18, 2023
0648c47
application environment format changes
lucasvegi Sep 18, 2023
4aaa1e4
application environment format changes
lucasvegi Sep 18, 2023
a178d6c
Update lib/elixir/pages/anti-patterns/design-anti-patterns.md
josevalim Sep 21, 2023
37be217
Update lib/elixir/pages/anti-patterns/design-anti-patterns.md
josevalim Sep 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion lib/elixir/pages/anti-patterns/design-anti-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,59 @@ A common practice followed by the community is to make the non-raising version t

## Using application configuration for libraries

TODO
#### Problem

The [*application environment*](https://hexdocs.pm/elixir/Application.html#module-the-application-environment) can be used to parameterize global values that can be used in an Elixir system. This mechanism can be very useful and therefore is not considered an anti-pattern by itself. However, library authors should avoid using the application environment to configure their library. The reason is exactly that the application environment is a **global** state, so there can only be a single value for each key in the environment for an application. This makes it impossible for multiple applications depending on the same library to configure the same aspect of the library in different ways.

#### Example

The `DashSplitter` module represents a library that configures the behavior of its functions through the global application environment. These configurations are concentrated in the *config/config.exs* file, shown below:

```elixir
import Config

config :app_config,
parts: 3

import_config "#{config_env()}.exs"
```

One of the functions implemented by the `DashSplitter` library is `split/1`. This function aims to separate a string received via a parameter into a certain number of parts. The character used as a separator in `split/1` is always `"-"` and the number of parts the string is split into is defined globally by the application environment. This value is retrieved by the `split/1` function by calling `Application.fetch_env!/2`, as shown next:

```elixir
defmodule DashSplitter do
def split(string) when is_binary(string) do
parts = Application.fetch_env!(:app_config, :parts) # <= retrieve parameterized value
String.split(string, "-", parts: parts) # <= parts: 3
end
end
```

Due to this parameterized value used by the `DashSplitter` library, all applications dependent on it can only use the `split/1` function with identical behavior about the number of parts generated by string separation. Currently, this value is equal to 3, as we can see in the use examples shown below:

```elixir
iex> DashSplitter.split("Lucas-Francisco-Vegi")
["Lucas", "Francisco", "Vegi"]
iex> DashSplitter.split("Lucas-Francisco-da-Matta-Vegi")
["Lucas", "Francisco", "da-Matta-Vegi"]
```

#### Refactoring

To remove this anti-pattern and make the library more adaptable and flexible, this type of configuration must be performed via parameters in function calls. The code shown below performs the refactoring of the `split/1` function by accepting [keyword lists](`Keyword`) as a new optional parameter. With this new parameter, it is possible to modify the default behavior of the function at the time of its call, allowing multiple different ways of using `split/2` within the same application:

```elixir
defmodule DashSplitter do
def split(string, opts \\ []) when is_binary(string) and is_list(opts) do
parts = Keyword.get(opts, :parts, 2) # <= default config of parts == 2
String.split(string, "-", parts: parts)
end
end
```

```elixir
iex> DashSplitter.split("Lucas-Francisco-da-Matta-Vegi", [parts: 5])
["Lucas", "Francisco", "da", "Matta", "Vegi"]
iex> DashSplitter.split("Lucas-Francisco-da-Matta-Vegi") #<= default config is used!
["Lucas", "Francisco-da-Matta-Vegi"]
```