<?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: lipe</title>
    <description>The latest articles on DEV Community by lipe (@lipejose).</description>
    <link>https://dev.to/lipejose</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%2F806235%2Fb8775fe2-13dc-47a2-a3d1-8b4e9b2d7601.png</url>
      <title>DEV Community: lipe</title>
      <link>https://dev.to/lipejose</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lipejose"/>
    <language>en</language>
    <item>
      <title>plugin architecture no elixir</title>
      <dc:creator>lipe</dc:creator>
      <pubDate>Sun, 30 Jan 2022 14:33:06 +0000</pubDate>
      <link>https://dev.to/lipejose/plugin-architecture-no-elixir-da0</link>
      <guid>https://dev.to/lipejose/plugin-architecture-no-elixir-da0</guid>
      <description>&lt;p&gt;&lt;strong&gt;OBS: esse artigo foi originalmente escrito no livebook, toda a saída de código do livebook foi colocada abaixo de seu respectivo bloco de código.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine se você pudesse ter um sistema tão flexível onde precisasse apenas criar plugins para adicionar novas integrações? Aqui quis passar um pouco do que aprendi sobre a arquitetura de plugins e como eu consegui aplicar esses conceitos usando o elixir, qualquer dúvida, critica e sugestão, sinta-se a vontade em me contatar.&lt;/p&gt;

&lt;h3&gt;
  
  
  O Projeto
&lt;/h3&gt;

&lt;p&gt;O carriershub é um projeto de integração com transportadoras, a intenção é criar um projeto onde quando for necessário realizar uma nova integração com alguma transportadora, seja necessária a criação de apenas mais um plugin sem a necessidade de alterar qualquer outra parte do código.&lt;/p&gt;

&lt;p&gt;A ideia aqui apresentada pode ser reaproveitada em inúmeras situações e até mesmo em outras linguagens de programação.&lt;/p&gt;

&lt;p&gt;Um plugin de transportadora pode ter N métodos diferente como solicitação de etiquetas, cancelamento de postagem/coleta mas vamos nos limitar apenas ao método de tracking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mão na massa (ou no código ;D)
&lt;/h3&gt;

&lt;p&gt;Primeiramente criamos um mock (&lt;a href="https://61be22a12a1dd4001708a255.mockapi.io/mock/correios/"&gt;https://61be22a12a1dd4001708a255.mockapi.io/mock/correios/&lt;/a&gt;) para retornar um tracking fake nas nossas chamadas. E para fazer as chamadas também precisamos instalar a lib tesla para fazer as requisições http.&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;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;&lt;span class="ss"&gt;:tesla&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.4"&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Resolving Hex dependencies...
Dependency resolution completed:
New:
  mime 2.0.2
  tesla 1.4.4
* Getting tesla (Hex package)
* Getting mime (Hex package)
==&amp;gt; mime
Compiling 1 file (.ex)
Generated mime app
==&amp;gt; tesla
Compiling 29 files (.ex)
Generated tesla app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:ok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com a lib instalada, vamos definir os nossos primeiros 2 plugins conforme abaixo, vamos usar o nosso mock apenas no primeiro plugin definido que no caso, chamei de correios, para isso definimos um atributo chamado de &lt;code&gt;@base_url&lt;/code&gt;, seguido de uma função chamada tracking que recebe data com os codes e fields que por se tratar de um exemplo não iremos utilizar, mas seria os dados de integração que ficariam salvos no banco de dados.&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;Plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Correios&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@base_url&lt;/span&gt; &lt;span class="s2"&gt;"https://61be22a12a1dd4001708a255.mockapi.io/mock/correios/"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;codes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Tesla&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@base_url&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;
    &lt;span class="k"&gt;end&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;end&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Braspress&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codes&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;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:module, Plugins.Braspress, &amp;lt;&amp;lt;70, 79, 82, 49, 0, 0, 5, ...&amp;gt;&amp;gt;, {:tracking, 2}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que temos dois plugins definidos como módulos elixir precisamos saber como carregar esses plugins. Para isso vamos definir um módulo chamado Loader, ele tem como alias todos os plugins e uma função chamada &lt;code&gt;can_loader&lt;/code&gt; que recebe apenas o nome da transportadora que ali chamamos de &lt;strong&gt;integrations&lt;/strong&gt; e verifica a existência do plugin.&lt;br&gt;
Dentro da função a primeira coisa que precisamos fazer é se certificar em transformar tudo para downcase e depois para capitalize para dar match correto com o nome do módulo da transportadora. Em seguida usamos a função &lt;code&gt;ensure_loader&lt;/code&gt; do próprio Elixir para verificar se o módulo consegue ser carregado e caso sim, retornamos ele para ser utilizado.&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;Loader&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Plugins&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;can_loader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;integration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="n"&gt;integration&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;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;downcase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;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;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ensure_loaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Plugins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plugin&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="ss"&gt;:module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;result:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;integration&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; plugin was not implemeted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status:&lt;/span&gt; &lt;span class="ss"&gt;:bad_request&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;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:module, Loader, &amp;lt;&amp;lt;70, 79, 82, 49, 0, 0, 7, ...&amp;gt;&amp;gt;, {:can_loader, 1}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos tentar carregar um plugin que existe e um que não e ver nas saídas que o primeiro é carregado com sucesso e o segundo retorna um erro de que não foi implementado.&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;Loader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_loader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"correios"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:ok, Plugins.Correios}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Loader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_loader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"kangu"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:error, %{result: "kangu plugin was not implemeted", status: :bad_request}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Show! Agora já conseguimos carregar os plugins existentes.&lt;/p&gt;

&lt;p&gt;Mas agora como saberemos que um plugin consegue executar um método como o de tracking por exemplo?&lt;/p&gt;

&lt;p&gt;Para isso vamos definir mais um módulo, esse vai se chamar Manager e vai ter uma função chamada &lt;code&gt;can_perform_action&lt;/code&gt; que receber o plugin que já nos certificamos que existe e uma string com o nome do método que se quer executar nesse plugin, novamente nos certificamos em converter tudo para downcase e depois para atom, pois é o que a função &lt;code&gt;Keyword.has_key&lt;/code&gt; necessita para verifica a existência da função dentro do plugin e retornar um boleano. Com o resultado caso ele seja true, retornamos a função, caso não, um erro.&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;Manager&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;can_perform_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="n"&gt;action&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;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;downcase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;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;to_atom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Keyword&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__info__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:functions&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="no"&gt;false&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;result:&lt;/span&gt; &lt;span class="s2"&gt;"can't perform action: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status:&lt;/span&gt; &lt;span class="ss"&gt;:bad_request&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;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:module, Manager, &amp;lt;&amp;lt;70, 79, 82, 49, 0, 0, 8, ...&amp;gt;&amp;gt;, {:can_perform_action, 2}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui testamos o funcionamento da função em caso de sucesso e erro. Como esperado ele tem o método tracking definido mas não o solicitation.&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Loader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_loader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"correios"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_perform_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"tracking"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:ok, :tracking}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_perform_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"solicitation"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:error, %{result: "can't perform action: solicitation", status: :bad_request}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que já temos o nosso plugin loader e nosso manager prontos para executar nossa solicitação. Para isso vamos utilizar uma função do Elixir que chama &lt;code&gt;apply&lt;/code&gt;, ela recebe 3 parâmetros, o plugin, a função a ser executada e os parâmetros que quer passar para essa função. Para executar um tracking nos correios então, o código ficaria assim:&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="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;codes:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;token:&lt;/span&gt; &lt;span class="s2"&gt;"CORREIOSAUTHTOKEN"&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Loader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_loader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"correios"&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_perform_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"tracking"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;["{\"rastreio\":[{\"status\":\"Status: Objeto em trânsito - por favor aguarde\",\"data\":\"Data  : 04/10/2021 | Hora: 17:44\",\"origem\":\"Origem: País -  / \",\"destino\":\"Destino: País -  / BR\"},{\"status\":\"Status: Objeto recebido pelos Correios do Brasil\",\"data\":\"Data  : 08/10/2021 | Hora: 15:51\",\"local\":\"Local: Unidade Operacional - Curitiba / PR\"},{\"status\":\"Status: Fiscalização aduaneira finalizada\",\"data\":\"Data  : 08/10/2021 | Hora: 16:24\",\"local\":\"Local: Unidade Operacional - Curitiba / PR\"},{\"status\":\"Status: Objeto em trânsito - por favor aguarde\",\"data\":\"Data  : 08/10/2021 | Hora: 16:26\",\"origem\":\"Origem: Unidade Operacional - Curitiba / PR\",\"destino\":\"Destino: Unidade de Tratamento - Curitiba / PR\"},{\"status\":\"Status: Objeto em trânsito - por favor aguarde\",\"data\":\"Data  : 09/10/2021 | Hora: 09:31\",\"origem\":\"Origem: Unidade de Tratamento - Curitiba / PR\",\"destino\":\"Destino: Unidade de Distribuição - Curitiba / PR\"},{\"status\":\"Status: Objeto em trânsito - por favor aguarde\",\"data\":\"Data  : 11/10/2021 | Hora: 11:43\",\"origem\":\"Origem: Unidade de Distribuição - Curitiba / PR\",\"destino\":\"Destino: Unidade de Distribuição - Curitiba / PR\"},{\"status\":\"Status: Objeto saiu para entrega ao destinatário\",\"data\":\"Data  : 13/10/2021 | Hora: 09:51\",\"local\":\"Local: Unidade de Distribuição - Curitiba / PR\"},{\"status\":\"Status: Objeto entregue ao destinatário\",\"data\":\"Data  : 13/10/2021 | Hora: 17:00\",\"local\":\"Local: Unidade de Distribuição - Curitiba / PR\"},{\"status\":\"Status: Objeto entregue ao destinatário\",\"data\":\"Data  : 13/10/2021 | Hora: 17:00\",\"local\":\"Local: Unidade de Distribuição - Curitiba / PR\"}],\"status_code\":200,\"id\":\"1\"}",
 "{\"rastreio\":[{\"status\":\"Status: Objeto em trânsito - por favor aguarde\",\"data\":\"Data  : 04/10/2021 | Hora: 17:44\",\"origem\":\"Origem: País -  / \",\"destino\":\"Destino: País -  / BR\"},{\"status\":\"Status: Objeto recebido pelos Correios do Brasil\",\"data\":\"Data  : 08/10/2021 | Hora: 15:51\",\"local\":\"Local: Unidade Operacional - Curitiba / PR\"},{\"status\":\"Status: Fiscalização aduaneira finalizada\",\"data\":\"Data  : 08/10/2021 | Hora: 16:24\",\"local\":\"Local: Unidade Operacional - Curitiba / PR\"},{\"status\":\"Status: Objeto em trânsito - por favor aguarde\",\"data\":\"Data  : 08/10/2021 | Hora: 16:26\",\"origem\":\"Origem: Unidade Operacional - Curitiba / PR\",\"destino\":\"Destino: Unidade de Tratamento - Curitiba / PR\"},{\"status\":\"Status: Objeto em trânsito - por favor aguarde\",\"data\":\"Data  : 09/10/2021 | Hora: 09:31\",\"origem\":\"Origem: Unidade de Tratamento - Curitiba / PR\",\"destino\":\"Destino: Unidade de Distribuição - Curitiba / PR\"},{\"status\":\"Status: Objeto em trânsito - por favor aguarde\",\"data\":\"Data  : 11/10/2021 | Hora: 11:43\",\"origem\":\"Origem: Unidade de Distribuição - Curitiba / PR\",\"destino\":\"Destino: Unidade de Distribuição - Curitiba / PR\"},{\"status\":\"Status: Objeto saiu para entrega ao destinatário\",\"data\":\"Data  : 13/10/2021 | Hora: 09:51\",\"local\":\"Local: Unidade de Distribuição - Curitiba / PR\"},{\"status\":\"Status: Objeto entregue ao destinatário\",\"data\":\"Data  : 13/10/2021 | Hora: 17:00\",\"local\":\"Local: Unidade de Distribuição - Curitiba / PR\"},{\"status\":\"Status: Objeto entregue ao destinatário\",\"data\":\"Data  : 13/10/2021 | Hora: 17:00\",\"local\":\"Local: Unidade de Distribuição - Curitiba / PR\"}],\"status_code\":200,\"id\":\"2\"}"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto! Como pudemos ver na saída já estamos conseguindo consultar códigos nos correios. Nesse ponto já poderíamos implementar rotas específicas para cada método ou algo mais genérico onde quem está requisitando passaria o que deseja e caso não existisse seria retornado o erro de plugin ou método não implementado.&lt;/p&gt;

&lt;p&gt;O legal dessa implementação é a versatilidade dela e a facilidade em adicionar novos recursos, eu curti bastante a arquitetura de plugins, o que você achou?&lt;/p&gt;

&lt;h4&gt;
  
  
  Links úteis
&lt;/h4&gt;

&lt;p&gt;Toda a aplicação com cadastro de clientes e acesso ao banco de dados pose ser consultado &lt;a href="https://github.com/lipejose/carriershub"&gt;aqui nesse repositório&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Se você quiser saber mais sobre o poder da arquitetura de plugins recomendo &lt;a href="https://www.youtube.com/watch?v=iCE1bDoit9Q"&gt;esse vídeo no youtube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Obrigado e até o próximo! ;D&lt;/p&gt;

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