-
Notifications
You must be signed in to change notification settings - Fork 3.5k
"Using application configuration for libraries" added (Anti-patterns documentation) #12944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Co-authored-by: Paulo F. Oliveira <paulo.ferraz.oliveira@gmail.com>
Co-authored-by: Andrea Leopardi <an.leopardi@gmail.com>
Co-authored-by: Andrea Leopardi <an.leopardi@gmail.com>
Co-authored-by: Andrea Leopardi <an.leopardi@gmail.com>
Co-authored-by: Eksperimental <eksperimental@autistici.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One suggestion I have is to simulate a slightly more complex example that however can be significantly more realistic.
My go to is once again something where the antipattern is configuring for example a base URL through app config
config :api_client,
base_url: "..."and the refactoring would be to pass it as an option:
APIClient.request(..., base_url: "...")|
@whatyouhide What do you think of this example? If it's cool I'll adapt the text with a new commit import Config
config :api_client,
base_url: "https://api.github.com"
import_config "#{config_env()}.exs"defmodule APIClient do
def request(endpoint) when is_binary(endpoint) do
HTTPoison.start
base_url = Application.fetch_env!(:api_client, :base_url) # <= retrieve parameterized value
HTTPoison.get(base_url <> endpoint) # <= base_url: "https://api.github.com"
end
end#...Use examples with anti-pattern
iex> APIClient.request("/users/lucasvegi") #<== OK!
{:ok,
%HTTPoison.Response{
status_code: 200,
body: "...",
headers: [ ... ],
request_url: "https://api.github.com/users/lucasvegi",
...
}}
iex> APIClient.request("/persons?_quantity=1") #<== Failed attempt to access a different API!
{:ok,
%HTTPoison.Response{
status_code: 404,
body: "{\"message\":\"Not Found\",\"documentation_url\":\"https://docs.github.com/rest\"}",
headers: [ ... ],
request_url: "https://api.github.com/persons?_quantity=1", # <== base_url never changes!
...
}}Refactoring: defmodule APIClient do
def request(endpoint, options \\ []) when is_binary(endpoint) and is_list(options) do
HTTPoison.start
base_url = Keyword.get(options, :base_url, "https://api.github.com") # <= default config of base_url == "https://api.github.com"
HTTPoison.get(base_url <> endpoint)
end
end#...Use examples of the refactored code
iex> APIClient.request("/users/lucasvegi") #<== OK with default config!
{:ok,
%HTTPoison.Response{
status_code: 200,
body: "...",
headers: [ ... ],
request_url: "https://api.github.com/users/lucasvegi",
...
}}
iex> APIClient.request("/persons?_quantity=1", [base_url: "https://fakerapi.it/api/v1"]) #<== OK with another API!
{:ok,
%HTTPoison.Response{
status_code: 200,
body: "{...\"data\":[{\"id\":1,\"firstname\":\"Taryn\",\"lastname\":\"Price\",...}",
headers: [ ... ],
request_url: "https://fakerapi.it/api/v1/persons?_quantity=1",
...
}} |
|
@lucasvegi yes that's exactly what I had in mind. Few notes:
Does that make sense? |
So the definition of the request function would look something like this? def request(endpoint ...) do
base_url = ...
MyApp.HTTPClient.get(base_url <> endpoint)
end |
|
@lucasvegi yep! |
Great! I'll make some adjustments and commit |
|
💚 💙 💜 💛 ❤️ |
No description provided.