#Dependency inversion with intellisense?

1 messages · Page 1 of 1 (latest)

covert jackal
#

In the aims of avoiding an X -> Y problem, here's the context:

I am working on a Phoenix application, and have a mailer module for sending (you guessed it!) emails.
The thing is, I would like my application code to not directly reference the mailer module, I would prefer it got injected into the application module instead so I can supply a different implementation based on the environment.

My current setup is:

defmodule App.Behaviour do
  @callback do_thing() :: :ok
end

defmodule AppWeb.Implementation do
  @behaviour App.Behaviour

  def do_thing(), do: :ok
end

defmodule App.Context do
  @service Application.compile_env!(:app, :service)

  def do_magic do
    @service.do_thing()
  end
end

and in config.exs:

config :app, :service, AppWeb.Implementation

And... it works... but I get zero intellisense/docs when using the module attribute in my code... is there a way to fix that?

I tried supplying a default value to compile_env in the hopes this would help the compiler know what to expect for that attribute... no success.

Isn't this being injected comp-time, why is the compiler not aware of the value? Is it a bug with my language server maybe? Am I overthinking it and I should instead just use the module directly in my app code and instead do the mocking as part of my implementation based on some config value?

Help a brotha out 😅 thanks in advance all!

graceful prism
#

Hey, you can use a similar implementation as mox docs suggest.

In your behaviour, you are going to create the same functions as your callbacks, but you are going to use the chosen implementation via a private funtion which is going to get the implementation.

Look for the mox library.