<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Diogo Dourado</title>
    <description>The latest articles on DEV Community by Diogo Dourado (@dcdourado).</description>
    <link>https://dev.to/dcdourado</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F913689%2F62e7a51b-a4dd-4d85-bd54-0c9da692ff7c.jpeg</url>
      <title>DEV Community: Diogo Dourado</title>
      <link>https://dev.to/dcdourado</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dcdourado"/>
    <language>en</language>
    <item>
      <title>Dependency inversion on Elixir using Ports and Adapters design pattern</title>
      <dc:creator>Diogo Dourado</dc:creator>
      <pubDate>Tue, 10 Jan 2023 12:32:10 +0000</pubDate>
      <link>https://dev.to/dcdourado/dependency-inversion-on-elixir-using-ports-and-adapters-design-pattern-4k3f</link>
      <guid>https://dev.to/dcdourado/dependency-inversion-on-elixir-using-ports-and-adapters-design-pattern-4k3f</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Dependency Inversion is a well-known software development principle, described by Robert C. Martin as the responsible of systems to become flexible by making source code dependencies refer only to abstractions and not to concrete items.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexvk6d3gddlcparbb5vq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexvk6d3gddlcparbb5vq.jpeg" alt="Dependency Inversion demonstrations taken from Clean Architecture book"&gt;&lt;/a&gt;&lt;br&gt;
Dependency Inversion demonstration taken from Clean Architecture book.&lt;/p&gt;

&lt;p&gt;Deciding which implementation will be used in a given piece of code can be very useful and is commonly used to develop mocks on tests that involves external dependencies, such as HTTP calls or event publications.&lt;/p&gt;
&lt;h2&gt;
  
  
  How it is used
&lt;/h2&gt;

&lt;p&gt;On Java and other object oriented programming languages the principle can be achieved using an Interface to expose desired functions and then develop a Class to implement these signatures. On the other hand, Elixir makes it possible to apply this principle by defining a set of callbacks on a Behavior and implement them on another module following the defined specification.&lt;/p&gt;

&lt;p&gt;We can see this pattern replicated on different open source libraries of Elixir community on many use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/adapter.ex" rel="noopener noreferrer"&gt;Ecto database driver use-case&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/swoosh/swoosh/blob/main/lib/swoosh/adapter.ex" rel="noopener noreferrer"&gt;Swoosh mailing service use-case&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/elixir-tesla/tesla/blob/master/lib/tesla.ex#L125" rel="noopener noreferrer"&gt;Tesla HTTP adapter use-case&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Implementation example
&lt;/h2&gt;

&lt;p&gt;By deriving the Dependency Inversion principle on Elixir it is possible to implement Ports and Adapters design pattern. It consists of having a Port defining the Behaviour callbacks and the functions calling the configured Adapter implementation.&lt;/p&gt;

&lt;p&gt;Check out this quick demonstration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MySystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;SmsNotificationPort&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Sends SMS to users using configured SMS adapter.
  """&lt;/span&gt;

  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="ss"&gt;:error&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:my_system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MySystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;TwillioSmsAdapter&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Twillio SMS adapter implementation.
  """&lt;/span&gt;

  &lt;span class="nv"&gt;@behaviour&lt;/span&gt; &lt;span class="no"&gt;MySystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;SmsNotificationPort&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;MySystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="ss"&gt;http:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;twillio&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="s2"&gt;" &amp;lt;&amp;gt; user.phone, %{message: message}) do
      {:ok, _} -&amp;gt; :ok
      _ -&amp;gt; :error
    end
  end
end
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And on config.exs we would setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# …&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:my_system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MySystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;SmsNotificationPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="no"&gt;MySystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;TwillioSmsAdapter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The same principle is used on Dependency Injection design pattern, given that you can use different implementations on a piece of your software. The difference is that Dependency Injection implementation is given on compile-time whilst Ports and Adapters is on &lt;strong&gt;run-time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means you could execute the command below on a running application and change the SMS API used on your system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:my_system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MySystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;SmsNotificationPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MySystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ZenviaSmsAdapter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg72u8rh2ibdal95mh4nf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg72u8rh2ibdal95mh4nf.png" alt="SMS Port implementation swap"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is very powerful because now we are able to switch running implementations on the fly. For instance, if Twillio went through an outage we could change the SMS implementation Adapter to Zenvia resulting in our users having zero impact on their SMS messages. In the future, we could automatically detect outage events on a specific SMS adapter and switch to the other one, a pattern known as Circuit Breaker.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding GenStage back-pressure mechanism</title>
      <dc:creator>Diogo Dourado</dc:creator>
      <pubDate>Tue, 23 Aug 2022 01:37:00 +0000</pubDate>
      <link>https://dev.to/dcdourado/understanding-genstage-back-pressure-mechanism-1b0i</link>
      <guid>https://dev.to/dcdourado/understanding-genstage-back-pressure-mechanism-1b0i</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Back-pressure is a technique utilized to prevent an application or a piece of software of using more resources than there are available on a given infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hexdocs.pm/gen_stage/GenStage.html" rel="noopener noreferrer"&gt;GenStage&lt;/a&gt; is an Elixir library to build complex processes divided by steps (or stages) that share data between them. This is the core behaviour used on &lt;a href="https://hexdocs.pm/broadway/introduction.html" rel="noopener noreferrer"&gt;Broadway&lt;/a&gt;, a multi-stage data ingestion backed on message queue systems such as Kafka, RabbitMQ and others.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Suppose you've built a news sharing system which is composed of three main components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data ingestor (A):&lt;/strong&gt; constantly searches and downloads tweets that contains hashtags of interest, such as #computerscience, #architecture and #programming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Republisher (B):&lt;/strong&gt; takes a tweet content, renders it on several different formats (HTML, Markdown, PDF and so on) and then publishes on different platforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reporter (C):&lt;/strong&gt; writes to database the timestamps of each publishing and also exports metrics to be analyzed on the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkezoyjiyhsq0bigpq88q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkezoyjiyhsq0bigpq88q.png" alt="System configuration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process being executed on component A is simple and takes only a single request to be done: a GET on Twitter's API. For this action we will account an imaginary measurement of &lt;strong&gt;1N&lt;/strong&gt; amount of energy to get done.&lt;/p&gt;

&lt;p&gt;Now that a tweet content is retrieved and delivered to component B, a more complex process starts: it is required to transform the data acquired on several different formats and then make several other requests to external services (which may or not fail, timeout or take several more amount of time than usual). For this step then we will account &lt;strong&gt;10N&lt;/strong&gt; amount of energy taken.&lt;/p&gt;

&lt;p&gt;Component C executes a simpler process as well since it only does a write operation on database and then create telemetry data that will be polled later. That's &lt;strong&gt;2N&lt;/strong&gt; amount of energy on our example.&lt;/p&gt;

&lt;p&gt;As you can imagine, this scenario is problematic because component A generates input for component B on a speed ratio that it can't absorb, and that generates a overflow on B's execution queue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm65fd4xz2bis7yht4xz2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm65fd4xz2bis7yht4xz2.png" alt="System overflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;GenStage strategy to apply back-pressure is to invert the flow direction from the producer to the consumer and so consumers now control the velocity and amount of data transmitted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91fu1mipwq3nq5282ng1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91fu1mipwq3nq5282ng1.png" alt="Back-pressured system"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Component C starts with its execution queue empty and then asks Component B (which is a consumer-producer) to produce a piece of data.&lt;/p&gt;

&lt;p&gt;Component B which also has it's execution queue empty now asks Component A to produce a piece of data and only then the Tweeter API is called!&lt;/p&gt;

&lt;p&gt;The amount of data produced is back-pressured so no queues gets overflowed and that's how you have a healthy workflow on Elixir using GenStages.&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>architecture</category>
      <category>programming</category>
      <category>elixir</category>
    </item>
  </channel>
</rss>
