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
 
hackvan profile image
Diego Camacho • Edited

Hi Bruno,

I don't quite understand why the delegate or function call of the behavior should be made in the port, what's the porpuse?

It's because all the application use the MySystem.SmsNotificationPort.notify/2 function?

Collapse
 
brunoribeiro147 profile image
Bruno Ribeiro

Hey Diego!! How are you?

Well, I use the delegate on the port, because the port's idea is to be an interface. The only responsibility of the port is to call the correct adapter.

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