DEV Community

Dependency inversion on Elixir using Ports and Adapters design pattern

Diogo Dourado on January 10, 2023

Introduction Dependency Inversion is a well-known software development principle, described by Robert C. Martin as the responsible of sy...
Collapse
 
brunoribeiro147 profile image
Bruno Ribeiro •

Hey man, great article!! I always try to implement this pattern on my code. One thing that a make different, is that I use defdelegate on the port, I think that make the code more easy to understand. But thanks for the excellent article

defmodule MySystem.SmsNotificationPort do
  @moduledoc """
  Sends SMS to users using configured SMS adapter.
  """

  @callback notify(user :: User.t(), message :: String.t()) :: :ok | :error

  @adapter Application.get_env(:my_system, __MODULE__)

  defdelegate notify(user, message), to @adapter
end
Enter fullscreen mode Exit fullscreen mode
Collapse
 
03juan profile image
Juan Barrios •

Doesn't assigning it to @adapter make it a compiled variable, breaking the Application.put_env trick?

Collapse
 
dcdourado profile image
Diogo Dourado •

Yes @03juan, didn't notice that

Collapse
 
hackvan profile image
Diego Camacho •

I think you're right, in this case we need to move to a private function instead

defp adapter, do: Application.get_env(:my_system, __MODULE__)

Doesn't it?

Collapse
 
brunoribeiro147 profile image
Bruno Ribeiro •

Yep! You right! I already change this implementation, and now I use Application.get_env instead

Collapse
 
dcdourado profile image
Diogo Dourado •

Great tip, Bruno! Thanks for the feedback

Collapse
 
lcezermf profile image
Luiz Cezer •

Awesome content!

Collapse
 
rakshans1 profile image
Rakshan Shetty •

Paring this with mox for testing makes testing so much simpler

Collapse
 
brunoribeiro147 profile image
Bruno Ribeiro • • Edited

Yep! I like to use with Hammox! It's a really good abstraction for the mox