kostonstyle
How to use dependency injection pattern in Elixir?
Hi all
I want to make my codes scalable and decide to use dependency injection pattern.
How to use the concept of dependency injection in elixir?
THanks
Most Liked
michalmuskala
Just to follow up, I’ll give here the same example for this I gave in Slack.
We can define a protocol for our use case - e.g. a repository of users:
defprotocol UserRepository do
def get(database, id)
end
And then we can define two implementations - one based on a real database and one based on a simple in-memory ETS store:
defmodule Database do
defstruct [:ecto_repo]
def new(repo), do: %__MODULE__{ecto_repo: repo}
end
defmodule EtsDatabse do
defstruct [:table]
def new(), do: %__MODULE__{table: :ets.new(__MODULE__, [:set, :public])}
end
We can then implement the protocol for those data structures
defimpl UserRepository, for: Database do
def get(%{ecto_repo: repo}, id) do
repo.get(User, id)
end
end
defimpl UserRepository, for; EtsDatabase do
def get(%{table: table}, id) do
# assuming {{User, id}, struct} tuples in ets table
:ets.lookup_element(table, {User, id}, 2)
end
end
That’s a simple sketch of a protocol-based dependency injection.
mkunikow
Dependency injection is bad pattern used in OO languages to overcome weakness of these languages.
DI frameworks are very dangerous (they do many things under which you don’t have control of)
For this reason I will never use Angular ![]()
In Java the example of DI is Spring Framework
Dependencies are not good, they are bad! They should be things that we try to avoid wherever possible.
https://dzone.com/articles/dependency-injection-makes
Functional languages don’t need DI.
In functional languages you just compose functions.
For testing you just mock function like GitHub - jjh42/mock: Mocking library for Elixir language · GitHub
Korbin73
Generally speaking, this question comes up a lot when people are coming from OO languages. @mkunikow makes a valid point that you don’t need it. The solution is fairly simple especially when it comes to testing. If you take the following steps, you won’t need to mock your functions that are touching the outside world.
-
Keep your impure functions separate from your pure functions. If you have a function that touches a database, calls a webservice, gets the date, etc. Or anything that touches the outside world it should be put in a separate module/function and there should be only one place in your program where it’s called and that data gets passed to your pure functions.
-
Your unit test will only need the stubbed data that would have come from an impure function like the data that would come from a webservice or a database.
The only time mocking is necessary is when you are calling impure functions from pure functions and they are intertwined (this is true even in OO languages). However, if you keep your impure functions separate from your pure functions then there is no need to have DI or a mocking framework when unit testing.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








