<?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>Forem: Trybe</title>
    <description>The latest articles on Forem by Trybe (@trybe).</description>
    <link>https://forem.com/trybe</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%2Forganization%2Fprofile_image%2F5302%2F26258239-4ac6-4d28-b94c-ba6d3f9eabc2.png</url>
      <title>Forem: Trybe</title>
      <link>https://forem.com/trybe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/trybe"/>
    <language>en</language>
    <item>
      <title>Funções Built In no Elixir</title>
      <dc:creator>Igor Giamoniano</dc:creator>
      <pubDate>Fri, 28 Oct 2022 23:36:34 +0000</pubDate>
      <link>https://forem.com/trybe/funcoes-built-in-no-elixir-2d9o</link>
      <guid>https://forem.com/trybe/funcoes-built-in-no-elixir-2d9o</guid>
      <description>&lt;p&gt;Também conhecidas como &lt;strong&gt;funções internas,&lt;/strong&gt; as funções &lt;em&gt;built in&lt;/em&gt; são recursos muito uteis encontrados na maioria das linguagens de programação.&lt;/p&gt;

&lt;p&gt;Nesse capítulo exploraremos algumas que são bastante uteis para diversas situações.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/MqyWCZbMMFFL2/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/MqyWCZbMMFFL2/giphy.gif" alt="ready" width="270" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  String
&lt;/h2&gt;

&lt;p&gt;Comecemos com algumas bem simples para trabalharmos com string.&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;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Trybe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# "ebyrT"&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Trybe escola de programação"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# ["Trybe", "escola", "de", "programação"]&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;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"meen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"o"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# "moon"&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;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Vamos usar Javascript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Javascript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Elixir"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# "Vamos usar Elixir"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enum
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/5zbj7HTomGwJa37pWO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/5zbj7HTomGwJa37pWO/giphy.gif" alt="couting" width="318" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora que já deu pra sentir um gostinho, falaremos do módulo &lt;strong&gt;Enum&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;Enum&lt;/strong&gt; é o módulo que utilizamos no Elixir para trabalhar com dados “enumeráveis”, como &lt;em&gt;Lists&lt;/em&gt;, &lt;em&gt;Maps&lt;/em&gt; e &lt;em&gt;Ranges&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;Enum.map()&lt;/code&gt;, por exemplo, é muito parecido com o &lt;code&gt;.map&lt;/code&gt; do Python ou do Javascript, o primeiro argumento é uma coleção e o segundo argumento é uma função, que pode ser anônima, que lida com os valores passados e retorna uma nova coleção.&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;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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&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;num&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# [20, 40, 60]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;Enum.reduce()&lt;/code&gt; pega uma coleção de elementos e reduz eles a um único resultado, segundo os critérios que passarmos.&lt;/p&gt;

&lt;p&gt;Observe o exemplo abaixo:&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;students&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Paracelso"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;media_final:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Rasputin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;media_final:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Eliphas Levi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;media_final:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&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;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;media_final:&lt;/span&gt; &lt;span class="n"&gt;media_final&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;media_final&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 27&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma maneira muito útil de acessarmos uma determinada posição em uma lista é usando &lt;code&gt;Enum.at()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Observe o exemplo:&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# %{name: "Eliphas Levi", media_final: 9}&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;at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# %{name: "Rasputin", media_final: 8}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É importante ressaltar que estamos utilizando listas nos exemplos, mas também podemos realizar as operações diretamente nos maps.&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;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="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Eliphas Levi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;media_final:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# ["Eliphas Levi", 9]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/TcdpZwYDPlWXC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/TcdpZwYDPlWXC/giphy.gif" alt="borat" width="400" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stream
&lt;/h2&gt;

&lt;p&gt;Agora para fechar a seção de funções &lt;em&gt;Built In&lt;/em&gt; é importante falarmos sobre &lt;strong&gt;Stream!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Muitas vezes precisaremos lidar com uma enorme quantidade de dados e a função &lt;em&gt;Enum&lt;/em&gt; armazena seu resultado direto, na memória, o que pode trazer problemas de desempenho.&lt;/p&gt;

&lt;p&gt;Com o &lt;em&gt;Stream&lt;/em&gt; armazenamos o resultado na memória somente quando ele é &lt;strong&gt;implicitamente invocado,&lt;/strong&gt; ou seja, “&lt;strong&gt;Lazy method”.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Observe o exemplo:&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;Stream&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;students&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#Stream&amp;lt;[&lt;/span&gt;
  &lt;span class="ss"&gt;enum:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;media_final:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Paracelso"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;media_final:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Rasputin"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;media_final:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Eliphas Levi"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;funs:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="c1"&gt;#Function&amp;lt;47.58486609/1 in Stream.map/2&amp;gt;]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo anterior vemos que o &lt;em&gt;map&lt;/em&gt; não foi feito ainda e somente sera efetuado quando invocarmos o resultado, assim otimizamos o nosso fluxo:&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;Stream&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;students&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;end&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# ["Paracelso", "Rasputin", "Eliphas Levi"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Nesse artigo aplicamos algumas funções &lt;em&gt;Built in&lt;/em&gt; uteis para o nosso dia a dia.&lt;/p&gt;

&lt;p&gt;O próximo artigo encerra a série &lt;a href="https://dev.to/trybe/meus-primeiro-passos-no-elixir-1n1j"&gt;“Meus primeiros passos no Elixir”&lt;/a&gt; e falarei sobre a &lt;strong&gt;Phoenix&lt;/strong&gt; uma poderosa framework Elixir para desenvolvimento web.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/NpXecaHPKbdVm/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/NpXecaHPKbdVm/giphy.gif" alt="phoenix" width="302" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>erlang</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Como automatizamos a avaliação de projetos com Github Actions e o Broadway do Elixir</title>
      <dc:creator>Renan</dc:creator>
      <pubDate>Thu, 08 Sep 2022 19:17:54 +0000</pubDate>
      <link>https://forem.com/trybe/como-automatizamos-a-avaliacao-de-projetos-com-github-actions-e-o-broadway-do-elixir-2pjf</link>
      <guid>https://forem.com/trybe/como-automatizamos-a-avaliacao-de-projetos-com-github-actions-e-o-broadway-do-elixir-2pjf</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Aqui na Trybe, ao final de cada seção de conteúdos, as pessoas estudantes precisam desenvolver um projeto para avaliarmos seu aprendizado. O repositório do projeto é disponibilizado no Github e elas fazem clone para iniciar o desenvolvimento em suas máquinas. A cada commit da pessoa no repositório nós disparamos a execução de uma avaliação através das &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;Github Actions&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Processamento de uma delivery (commit)
&lt;/h2&gt;

&lt;p&gt;Após abrir um pull request com o código desenvolvido, cada commit dispara uma github action que irá avaliar o código da pessoa estudante e guardará no nosso banco de dados informações sobre a avaliação do código dessa pessoa.&lt;/p&gt;

&lt;p&gt;Os commits são enfileirados e assim conseguimos controlar o status do seu processamento, para garantir que todos os commits tenham suas avaliações devidamente calculadas. Em caso de falhas, reprocessamos automaticamente a cada 5 minutos.&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%2F3c11n6vhe633al02ub3v.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%2F3c11n6vhe633al02ub3v.png" alt="Fluxo de processamento da delivery"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O processamento do commit no backend foi implementado em cima do conceito de processamento de dados em multi-etapas com a biblioteca &lt;a href="https://github.com/dashbitco/broadway" rel="noopener noreferrer"&gt;Broadway&lt;/a&gt;. Consistindo em um módulo produtor que é responsável por buscar no banco todas as deliveries que estão aguardando processamento para repassar ao consumidor. Já o consumidor é o módulo Broadway que é responsável por demandar as avaliações ao produtor, processar a nota e criar o comentário de feedback no Github.&lt;/p&gt;

&lt;p&gt;Como temos uma grande quantidade de commits sendo feitos nos projetos, a primeira coisa que tentamos fazer é utilizar os recursos da programação concorrente disponível na linguagem Elixir  para processar várias deliveries ao mesmo tempo, com o objetivo de evitar um atraso no feedback para as pessoas estudantes. &lt;/p&gt;

&lt;p&gt;No código abaixo, observe nas configurações do Broadway que na linha 10 foi definido qual é o módulo produtor e nas linhas 16 e 17 foi definido a quantidade de processos concorrentes e a quantidade de demanda que cada processo irá solicitar ao produtor.&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;Trybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Consumer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Broadway&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Broadway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Message&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_opts&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;Broadway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&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="ss"&gt;name:&lt;/span&gt; &lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;producer:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="ss"&gt;module:&lt;/span&gt; &lt;span class="no"&gt;Trybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Producer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;transformer:&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="ss"&gt;:transform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
        &lt;span class="ss"&gt;concurrency:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;processors:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="ss"&gt;concurrency:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;max_demand:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;]&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;def&lt;/span&gt; &lt;span class="n"&gt;handle_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_processor&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="n"&gt;_context&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;Message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_data&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;process_data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_opts&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="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;data:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;acknowledger:&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="ss"&gt;:ack_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:ack_data&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;ack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ack_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_successful&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_failed&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;:ok&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;process_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delivery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# =&amp;gt; 1- Calcula a nota e salva no banco&lt;/span&gt;
    &lt;span class="c1"&gt;# =&amp;gt; 2- Faz request no Github criando o comentário de feedback.&lt;/span&gt;
    &lt;span class="c1"&gt;# =&amp;gt; 3- Atualiza o status da avaliação para `finished`.&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;p&gt;Já no produtor, com base na demanda definida nas configurações do Broadway, seu papel é buscar no banco de dados as deliveries que estão aguardando o processamento e repassar para o consumidor. Caso o produtor não encontre mais deliveries, é feito um agendamento de um novo processo para buscar novas deliveries nos próximos 10 segundos.&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;Trybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Producer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;GenStage&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Trybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Deliveries&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="p"&gt;\\&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;GenStage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&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="n"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&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;def&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deliveries&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;:producer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Função que irá enviar as deliveries para o consumidor&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_demand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;demand&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;send_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Função que é chamada quando um processo é agendado &lt;/span&gt;
  &lt;span class="c1"&gt;# solicitando mais deliveries.&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_info&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:get_deliveries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;state&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;send_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&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;defp&lt;/span&gt; &lt;span class="n"&gt;send_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&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;deliveries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;maybe_schedule_next_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Função responsável por buscar novas deliveries &lt;/span&gt;
  &lt;span class="c1"&gt;# nos próximos 10 segundos caso a quantidade de deliveries &lt;/span&gt;
  &lt;span class="c1"&gt;# no estado seja menor do que o solicitado.&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;maybe_schedule_next_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;demand&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;nil&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;maybe_schedule_next_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_deliveries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;demand&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;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:get_deliveries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Função responsável por buscar as deliveries no banco &lt;/span&gt;
  &lt;span class="c1"&gt;# e mudar o status delas para `processing`.&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;list_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;demand&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;with&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;Deliveries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_deliveries_waiting_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;Deliveries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_processing_status_to_deliveries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deliveries&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;deliveries&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;p&gt;Logo abaixo um exemplo de como o Broadway se comporta com as configurações definidas.&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%2Fk0gbgrkcq3njhi3d3pmc.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%2Fk0gbgrkcq3njhi3d3pmc.png" alt="Fluxo de processamento da nota no backend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problemas ao fazer requests simultâneas na API do Github
&lt;/h2&gt;

&lt;p&gt;No primeiro momento tudo parecia perfeito, mas infelizmente não funcionou da maneira esperada por causa do &lt;a href="https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting" rel="noopener noreferrer"&gt;rate limit do Github&lt;/a&gt;, que acabou gerando um grande atraso na entrega dos feedbacks para as pessoas estudantes.&lt;/p&gt;

&lt;p&gt;Na API do Github existem dois tipos de rate limit para garantir a disponibilidade da API para todos. Aqui no post iremos focar apenas no &lt;a href="https://docs.github.com/en/rest/overview/resources-in-the-rest-api#secondary-rate-limits" rel="noopener noreferrer"&gt;secondary rate limit&lt;/a&gt; que é nosso principal vilão, mas saiba que também existe o primary rate limit.&lt;/p&gt;

&lt;p&gt;Na documentação do Github existem algumas &lt;a href="https://docs.github.com/en/rest/guides/best-practices-for-integrators" rel="noopener noreferrer"&gt;práticas recomendadas&lt;/a&gt; para evitar o rate limit secundário, e os nossos maiores vilões são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não faça solicitações simultâneas para um mesmo token.&lt;/li&gt;
&lt;li&gt;Solicitações que criam conteúdo que acionam notificações, tais como issues, comentários e pull requests, podem ser ainda mais limitadas.Crie este conteúdo em um ritmo razoável para evitar maiores limitações.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Requisições moderadas ao Github
&lt;/h2&gt;

&lt;p&gt;Sorte a nossa que o Broadway já estava preparado para esse tipo de problema e implementou uma feature que nos possibilita botar o pé no freio do nosso produtor. A configuração é a &lt;code&gt;rate_limiting&lt;/code&gt;, com ela é possível definir a quantidade de deliveries que podemos processar em um intervalo de tempo.&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;Trybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Consumer&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Broadway&lt;/span&gt;

  &lt;span class="o"&gt;......&lt;/span&gt;
  &lt;span class="o"&gt;......&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_opts&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;Broadway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&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="ss"&gt;name:&lt;/span&gt; &lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;producer:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="ss"&gt;module:&lt;/span&gt; &lt;span class="no"&gt;Trybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Producer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;transformer:&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="ss"&gt;:transform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]},&lt;/span&gt;
        &lt;span class="ss"&gt;concurrency:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;rate_limiting:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="ss"&gt;allowed_messages:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;interval:&lt;/span&gt; &lt;span class="mi"&gt;30_000&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;processors:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="ss"&gt;default:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="ss"&gt;concurrency:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;max_demand:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;]&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;p&gt;Mas só essa configuração ainda não foi o suficiente, ela apenas desacelera a quantidade de requisições que fazemos no serviço em um intervalo de tempo, mas o problema de requests simultâneas ainda permanece. Dito isso, tivemos que também mudar as configurações dos processors, definindo o campo &lt;code&gt;concurrency: 1&lt;/code&gt; para que exista apenas um único processo recebendo deliveries do produtor evitando requisições concorrentes.&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%2Fs5v6j5gen7yh66zz9j83.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%2Fs5v6j5gen7yh66zz9j83.png" alt="Fluxo de processamento da nota evitando rate limit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dessa forma, conseguimos fazer requisições moderadas e sequenciais no serviço do Github sem comprometer o tempo de retorno do feedback para as pessoas estudantes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;A solução implementada nos possibilitou controlar o secondary rate limit e assim conseguimos processar os feedbacks para as pessoas estudantes de forma eficiente, ou seja, com poucas linhas de código podemos reajustar as configurações do Broadway novamente para que o processamento de deliveries  possa ser feita de maneira concorrente em grande escala.&lt;/p&gt;

&lt;p&gt;Se você tiver curiosidade de saber como é a infraestrutura que permite a Trybe corrigir mais de 20mil avaliações por semana,  recomendo também a leitura do &lt;a href="https://dev.to/trybe/como-a-trybe-corrige-mais-de-20-mil-avaliacoes-por-semana-1i6f"&gt;post publicado pelo Biasi&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>backend</category>
      <category>github</category>
      <category>phoenix</category>
    </item>
    <item>
      <title>Como utilizamos design tokens na Trybe</title>
      <dc:creator>Claudio Furini Jr.</dc:creator>
      <pubDate>Wed, 31 Aug 2022 17:42:23 +0000</pubDate>
      <link>https://forem.com/trybe/como-utilizamos-design-tokens-na-trybe-1o38</link>
      <guid>https://forem.com/trybe/como-utilizamos-design-tokens-na-trybe-1o38</guid>
      <description>&lt;p&gt;Em uma &lt;a href="https://dev.to/trybe/criando-consistencia-de-design-com-tokens-1j2"&gt;publicação anterior&lt;/a&gt;, apontamos a importância da consistência no design de uma aplicação e como isso pode ser alcançado com o uso de design tokens.&lt;/p&gt;

&lt;p&gt;Neste post, vamos mostrar como a Trybe utiliza os tokens de design no dia a dia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nossos tokens
&lt;/h2&gt;

&lt;p&gt;Nosso time de design definiu 6 categorias de tokens que são usados nos nossos produtos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cor&lt;/li&gt;
&lt;li&gt;Tipografia&lt;/li&gt;
&lt;li&gt;Sombra&lt;/li&gt;
&lt;li&gt;Borda&lt;/li&gt;
&lt;li&gt;Espaçamentos&lt;/li&gt;
&lt;li&gt;Z-index&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Não cabe a este post entrar em detalhes de cada valor dos nossos tokens e como foram definidos. A definição dos valores dos tokens de um produto deve partir de uma análise feita pelo time de design para encontrar padrões que irão representar a marca/produto em questão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fonte da verdade
&lt;/h2&gt;

&lt;p&gt;Um ponto muito importante para sucesso e adoção dos tokens é ter uma maneira simples onde design e desenvolvimento possam &lt;strong&gt;&lt;em&gt;consumir os mesmos valores&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Como fonte da verdade dos nossos tokens, adotamos um arquivo JSON.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O_UuPY75--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6ocperfk38pp7pstrbt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O_UuPY75--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6ocperfk38pp7pstrbt.png" alt="Visualização do JSON" width="880" height="1368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Como design constrói e utiliza o JSON?
&lt;/h3&gt;

&lt;p&gt;Sabemos que não é uma experiencia muito boa definir manualmente valores em um JSON. Pensando nisso, buscamos uma ferramenta que nos auxiliasse no processo e encontramos o &lt;a href="https://www.figma.com/community/plugin/843461159747178978/Figma-Tokens"&gt;Figma Tokens&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;O Figma Tokens é um plugin disponível na comunidade do Figma, que possibilita a administração de tokens que podem ser aplicados durante a construção de um layout, dessa forma o próprio plugin gera e consome o arquivo JSON.&lt;/p&gt;

&lt;p&gt;No caso da Trybe, demos um passo a mais e conectamos o plugin à nossa conta do Github e o JSON oficial fica armazenado no repositório do nosso Design System.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O631Vc8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4qk04sizjmouzhwbwj1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O631Vc8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4qk04sizjmouzhwbwj1.png" alt="Imagem representação do figma tokens" width="880" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O Figma Tokens também  possibilita a adição de temas relacionados aos tokens, como por exemplo um tema escuro. Mas vamos falar sobre &lt;em&gt;dark mode&lt;/em&gt; em um outro post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como desenvolvimento constrói e utiliza o JSON?
&lt;/h3&gt;

&lt;p&gt;Outro ponto importante da adoção dos tokens de design é o uso deles no nosso código. Mas como podemos usar valores de um JSON no nosso CSS?&lt;/p&gt;

&lt;p&gt;O primeiro passo é converter esse JSON em um padrão que possa ser usado pela nossa linguagem de programação. Para isso nós usamos o &lt;a href="https://amzn.github.io/style-dictionary/#/"&gt;Style Dictionary&lt;/a&gt;. Essa ferramenta nos possibilita converter o JSON em muitos outros formatos, como por exemplo, variáveis de CSS puras.&lt;/p&gt;

&lt;p&gt;No caso da Trybe, estamos utilizando uma biblioteca de estilização no JavaScript chamada &lt;a href="https://stitches.dev/"&gt;Stitches&lt;/a&gt;. Essa biblioteca já tem suporte a variáveis e nos da uma ótima experiência de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Para utilizarmos as variáveis do &lt;em&gt;Stitches&lt;/em&gt;, usamos o &lt;em&gt;Styled Dictionary&lt;/em&gt; para converter os valores do JSON para variáveis JavaScript e passamos esses valores para a &lt;a href="https://stitches.dev/docs/tokens"&gt;configuração do Stitches&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Assim utilizamos nossos tokens de maneira direta no momento de estilização de um componente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sxiez7b9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bajvp5rmqdewo0vxyc23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sxiez7b9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bajvp5rmqdewo0vxyc23.png" alt="Exemplo de código com Stitches" width="880" height="851"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Utilizando as ferramentas &lt;em&gt;Figma Tokens&lt;/em&gt;, &lt;em&gt;Style Dictionary&lt;/em&gt; e &lt;em&gt;Stitches&lt;/em&gt; a Trybe garante que tanto o time de design quanto o time de desenvolvimento falem a mesma linguagem e utilizem os mesmos valores durante o desenvolvimento. &lt;/p&gt;

&lt;p&gt;Esse padrão garante não só um bom alinhamento entre os times, mas diminui a carga cognitiva que nosso time precisa durante a execução de uma tarefa, pois todos esses valores já estão definidos e são usados de maneira semântica. &lt;/p&gt;

&lt;p&gt;E assim estamos cada vez mais perto de alcançar a consistência de design no nosso produto.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Data migrations para Phoenix</title>
      <dc:creator>José Camelo de Freitas</dc:creator>
      <pubDate>Mon, 29 Aug 2022 18:55:00 +0000</pubDate>
      <link>https://forem.com/trybe/data-migrations-para-phoenix-4mh9</link>
      <guid>https://forem.com/trybe/data-migrations-para-phoenix-4mh9</guid>
      <description>&lt;h2&gt;
  
  
  O que são?
&lt;/h2&gt;

&lt;p&gt;Migrations estão geralmente relacionadas a alterações na estrutura do banco de dados, mas é recorrente em ambientes de produção termos também a necessidade de efetuar operações em nossos dados. Chamaremos isso de data migrations. Nessas situações, é comum fazer essas data migrations através do mecanismo das migrations normais, as estruturais, ou até mesmo se conectar diretamente ao banco de dados e executar um SQL com as operações desejadas.&lt;/p&gt;

&lt;p&gt;Mas…&lt;/p&gt;

&lt;p&gt;Executar a SQL direto no banco não é a melhor das ideias, pois incentiva a falta de code review nessas operações, e é bastante propenso a erro humano, como esquecer uma transação aberta ou fazer um update sem where. Já fazer essas migrações junto das tradicionais migrações de estrutura, é um &lt;a href="https://github.com/lucasvegi/Elixir-Code-Smells#data-manipulation-by-migration"&gt;code smell conhecido&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A solução
&lt;/h2&gt;

&lt;p&gt;Uma solução recomendada é criar Mix Scripts para essas operações em dados, mas com &lt;a href="https://hexdocs.pm/mix/1.13/Mix.Tasks.Release.html"&gt;Mix Releases&lt;/a&gt; não temos o Mix disponível, pois o Mix é uma ferramenta de desenvolvimento e build, e no binário gerado de uma release o objetivo é não incluir nada que não seja estritamente necessário para que o projeto seja executado. Aqui na Trybe, em vários serviços não temos nem Elixir nem Erlang instalados dentro dos containers — tudo é executado a partir do binário gerado pela release. &lt;/p&gt;

&lt;p&gt;Para contornar isso, dentro do nosso serviço responsável por projetos, adotamos uma solução levemente customizada para nossas data migrations.&lt;/p&gt;

&lt;p&gt;Nosso serviço de projetos é uma aplicação Phoenix, e nela já tínhamos um módulo chamado Release, responsável por executar as migrações tradicionais, e como a própria &lt;a href="https://hexdocs.pm/phoenix/releases.html"&gt;documentação&lt;/a&gt; diz, esse é o local perfeito para adicionar qualquer tipo de comando customizado que venha precisar ser executado em produção!&lt;/p&gt;

&lt;p&gt;No módulo &lt;code&gt;Release&lt;/code&gt;, e seguindo o esqueleto da função &lt;code&gt;migrate/0&lt;/code&gt; que já temos por padrão, podemos ter uma função que ficará responsável por executar data migrations no nosso serviço.&lt;/p&gt;

&lt;h3&gt;
  
  
  Primeiro, vamos definir como serão nossas data migrations!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Elas devem estar em um diretório separado.
Podemos colocar essas data migrations em um diretório chamado &lt;code&gt;data_migrations&lt;/code&gt;, ao lado do nosso diretório &lt;code&gt;migrations&lt;/code&gt; tradicional.&lt;/li&gt;
&lt;li&gt;Elas vão receber um Repo para fazer suas operações no banco de dados.
Significa que não precisaremos acessar diretamente o módulo Repo da nossa aplicação, receberemos ele como parâmetro de uma função. Já podemos definir que essa função deverá ser chamada &lt;code&gt;run/1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Elas podem ser executadas “n” vezes, individualmente, e não possuem uma ordem específica.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Com essas premissas já podemos começar nossa implementação:
&lt;/h3&gt;

&lt;p&gt;Essa é a função &lt;code&gt;migrate/0&lt;/code&gt; do nosso módulo Release:&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;def&lt;/span&gt; &lt;span class="n"&gt;migrate&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;load_app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;repos&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;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Migrator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with_repo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Migrator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:up&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;all:&lt;/span&gt; &lt;span class="no"&gt;true&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;p&gt;A função &lt;code&gt;migrate/0&lt;/code&gt; é responsável por:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Garantir o carregamento da aplicação;&lt;/li&gt;
&lt;li&gt;Pegar uma lista de todos os repos disponível através da &lt;code&gt;repos/0&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Pedir para que o ecto execute as migrações pendentes para cada repo disponível;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bem simples, nossa função customizada para migrações de dados reaproveitará os passos 1 e 2, só se diferenciando no 3, que irá executar uma data migration a partir de seu nome de arquivo.&lt;/p&gt;

&lt;p&gt;Nossa implementação fica 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="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;migrate_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&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;load_app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;repos&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;with&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;migration&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;eval_data_migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_name&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Migrator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with_repo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;migration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&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;Logger&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="s2"&gt;"A migração de dados foi executada."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;else&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="n"&gt;message&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;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&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;message&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;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;eval_data_migration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_name&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;with&lt;/span&gt; &lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;get_data_migration_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
         &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;regular?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;),&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="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&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;eval_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&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;: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="k"&gt;else&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="s2"&gt;"Não foi possível encontrar a migração de dados."&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="s2"&gt;"A migração de dados aparenta ser inválida."&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;defp&lt;/span&gt; &lt;span class="n"&gt;get_data_migration_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_name&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;repo&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Migrator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;migrations_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"data_migrations"&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;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temos 2 funções auxiliares aqui:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;get_data_migrations_path/2&lt;/code&gt;: será responsável retornar o path do arquivo de migração que será executado.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eval_data_migration/2&lt;/code&gt;: irá fazer um eval da migração, retornando uma tupla de sucesso/erro, e o módulo da migração em caso de sucesso&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A nossa função &lt;code&gt;migrate_data/1&lt;/code&gt; irá:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Garantir o carregamento da aplicação;&lt;/li&gt;
&lt;li&gt;Iterar numa lista de repos;&lt;/li&gt;
&lt;li&gt;Para cada repo pegar o path completo do arquivo de data migration;&lt;/li&gt;
&lt;li&gt;Fazer o eval da &lt;code&gt;data_migration&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Passar a função &lt;code&gt;run/1&lt;/code&gt; da data migration para o Ecto.Migrator, que irá executar a migração;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Criando uma data migration
&lt;/h3&gt;

&lt;p&gt;Para criar uma data migration basta criar um arquivo no diretório &lt;code&gt;/priv/repo/data_migrations/&lt;/code&gt;. Devemos dar um nome descritivo para o arquivo, como &lt;code&gt;fix_trybetunes_module.exs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nossa migração só irá precisar ser um módulo simples com nossa função &lt;code&gt;run/1&lt;/code&gt;:&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;MyProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DataMigrations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;FixTrybetunesModule&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;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&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;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;where:&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"trybetunes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;update:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;set:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;module:&lt;/span&gt; &lt;span class="s2"&gt;"frontend"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; 
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;[]&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;h3&gt;
  
  
  Usando as data migrations
&lt;/h3&gt;

&lt;p&gt;Com a nossa nova função &lt;code&gt;Release.migrate_data/1&lt;/code&gt;, executar nossas data migrations é tão simples quanto… chamar uma função 😀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Utilizando o IEx:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;iex -S mix&lt;/code&gt; em ambiente de desenvolvimento;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;./release_bin remote&lt;/code&gt; em ambiente de produção ou staging, onde um deploy já foi feito, a aplicação já está sendo executada, e só temos o binário dela disponível;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; Release.migrate_data&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fix_trybetunes_module.exs"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;info] A migração de dados foi executada.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Chamando a função diretamente através do binário de release:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./release_bin &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"Release.migrate_data('fix_trybetunes_module.exs')"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;info] A migração de dados foi executada.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Vantagens
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Separação das responsabilidades;&lt;/li&gt;
&lt;li&gt;Versionamento e revisão de operações que em outro momento seriam feitas diretamente no banco de dados;&lt;/li&gt;
&lt;li&gt;Controle de quando será executado, e a possibilidade de executar a mesma operação quantas vezes se fizer necessário;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E é isso, implementadas as migrações de dados!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>ecto</category>
      <category>backend</category>
      <category>phoenix</category>
    </item>
    <item>
      <title>Uma introdução ao Pattern Matching</title>
      <dc:creator>Igor Giamoniano</dc:creator>
      <pubDate>Fri, 19 Aug 2022 20:42:06 +0000</pubDate>
      <link>https://forem.com/trybe/uma-introducao-ao-pattern-matching-2hl4</link>
      <guid>https://forem.com/trybe/uma-introducao-ao-pattern-matching-2hl4</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Ufa, nós aprendemos bastante coisa sobre a linguagem de programação Elixir!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/trybe/meus-primeiro-passos-no-elixir-1n1j"&gt;Configuramos o nosso Setup&lt;/a&gt;, &lt;a href="https://dev.to/trybe/elixir-conceitos-iniciais-4m8k"&gt;iniciamos um projeto no Mix, falamos sobre programação funcional e Aridade&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Agora falemos de um assunto, considerado um dos ‘cores’ do Elixir, falemos de &lt;strong&gt;Pattern Matching&lt;/strong&gt; então prepara o café e vamos lá!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/LG1ZZP1Go0D8j7YsWy/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/LG1ZZP1Go0D8j7YsWy/giphy.gif" alt="the office" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern Matching
&lt;/h2&gt;

&lt;p&gt;Começaremos do início ok? Na maior parte das linguagens de programação o sinal de igual (=) é usado como um operador de atribuição, ou seja, eu atribuo um valor a uma determinada variável, &lt;strong&gt;no Elixir isso não se aplica!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No elixir o sinal de igual é um operador de correspondência (’Match operator’). &lt;br&gt;
Vamos dar uma olhada no exemplo abaixo:&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;    &lt;span class="c1"&gt;# 1&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;    &lt;span class="c1"&gt;# 1&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;    &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MatchError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="n"&gt;hand&lt;/span&gt; &lt;span class="n"&gt;side&lt;/span&gt; &lt;span class="ss"&gt;value:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos entender o que esta acontecendo, na linha 1 estamos correspondendo o valor 1 a uma variável x, dando um match!&lt;/p&gt;

&lt;p&gt;Na linha 2 estamos correspondendo o valor 1 a uma variável que possui valor 1, deu match com certeza!&lt;/p&gt;

&lt;p&gt;Na linha 3 estamos correspondendo o valor 2 a variável x que possui valor 1, e isso nitidamente não da match, é exatamente isso que o log esta nos informando!&lt;/p&gt;

&lt;p&gt;No Pattern Matching o lado direito deve ser correspondente ao lado esquerdo. Se você veio do JavaScript, deve estar pensando que o Pattern Matching é muito parecido com &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment"&gt;Destrutcing&lt;/a&gt;. Na verdade, são coisas diferentes, mas através do Pattern Matching conseguimos fazer destruct no Elixir, vamos dar uma olhada neste outro exemplo:&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# [1, x, 3] = [1, 2, 3]&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="c1"&gt;# 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo anterior estamos correspondendo a variável x o segundo valor da lista a direita, também poderíamos fazer o seguinte:&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="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# [y, x, 3] = [1, 2, 3]&lt;/span&gt;

&lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="c1"&gt;# 1&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="c1"&gt;# 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lembrando que os dois lados devem ser correspondentes, nos exemplos abaixo temos o mesmo erro que vimos la atrás:&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="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MatchError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="n"&gt;hand&lt;/span&gt; &lt;span class="n"&gt;side&lt;/span&gt; &lt;span class="ss"&gt;value:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MatchError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="n"&gt;hand&lt;/span&gt; &lt;span class="n"&gt;side&lt;/span&gt; &lt;span class="ss"&gt;value:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mais alguns exemplos de Pattern Matching
&lt;/h2&gt;

&lt;p&gt;No caso do &lt;em&gt;map&lt;/em&gt; não precisamos referenciar todos os valores dos dois lados justamente porque no &lt;em&gt;map&lt;/em&gt; não importa a ordem dos elementos, portanto podemos corresponder somente a chave que precisamos do valor.&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;school:&lt;/span&gt; &lt;span class="n"&gt;school_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;school:&lt;/span&gt; &lt;span class="s2"&gt;"Trybe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;country:&lt;/span&gt; &lt;span class="s2"&gt;"BR"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;# %{school: "Trybe", country: "BR"}&lt;/span&gt;

&lt;span class="n"&gt;school_name&lt;/span&gt;
&lt;span class="c1"&gt;# "Trybe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para concluir veja no próximo exemplo como usamos Pattern Matching para controle de fluxo em uma função de cláusula múltipla.&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;control_function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&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;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Great: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response&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;:error&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;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Error: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="n"&gt;control_function&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"register concluded"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;# "Great: register concluded"&lt;/span&gt;

&lt;span class="n"&gt;control_function&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"Disconnected"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;# "Error: Disconnected"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao receber o argumento da função o Elixir faz a comparação com a cláusula, caso “dê match” ele envia o retorno esperado, senão envia uma exceção, por exemplo:&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;control_function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;FunctionClauseError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;clause&lt;/span&gt; &lt;span class="n"&gt;matching&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="ss"&gt;:erl_eval&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"-inside-an-interpreted-fun-"&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Vimos então como o Pattern Matching é poderoso e, porque ele faz parte do core do Elixir, no próximo artigo falaremos sobre funções built in e como usamos no nosso dia a dia, até lá!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/k3YNVBrbn2KqbXEgDJ/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/k3YNVBrbn2KqbXEgDJ/giphy.gif" alt="bye - the office" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>beginners</category>
      <category>erlang</category>
      <category>functional</category>
    </item>
    <item>
      <title>Criando consistência de design com tokens</title>
      <dc:creator>Claudio Furini Jr.</dc:creator>
      <pubDate>Wed, 06 Apr 2022 20:10:21 +0000</pubDate>
      <link>https://forem.com/trybe/criando-consistencia-de-design-com-tokens-1j2</link>
      <guid>https://forem.com/trybe/criando-consistencia-de-design-com-tokens-1j2</guid>
      <description>&lt;p&gt;Imagine você entrar em um site e cada elemento da página possui um estilo diferente. Múltiplos tipos de fonte, cada texto com um tamanho, uso de diversos tipos e tons de cores sem nenhuma lógica aparente, espaçamentos entre componentes que nunca se alinham... é um pesadelo tentar entender qualquer coisa nesse cenário.&lt;/p&gt;

&lt;p&gt;Para diminuir a carga cognitiva, usuários buscam padrões e modelos que tornem as interações simples e fáceis. No design da experiência do usuário, um dos fatores que contribui para esse objetivo é a &lt;strong&gt;consistência&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que significa consistência em design?
&lt;/h2&gt;

&lt;p&gt;A consistência no design une os elementos, facilita o entendimento da conexão entre os componentes e garante que o seu usuário sinta-se seguro para aprender e a explorar seu produto.&lt;/p&gt;

&lt;p&gt;Ao garantir que a consistência seja prioridade, seu produto terá ótima usabilidade e acessibilidade. Os usuários poderão navegar facilmente pelo seu produto sem parar para questionar se estão fazendo algo errado.&lt;/p&gt;

&lt;p&gt;Existem diversas maneiras de buscar e garantir consistência no design de um produto. Principalmente no momento de concepção das ideias e protótipos. &lt;/p&gt;

&lt;p&gt;O propósito deste artigo não é detalhar todos os métodos. Mas sim falar de um em específico: &lt;strong&gt;design tokens&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que são design tokens?
&lt;/h2&gt;

&lt;p&gt;De maneira resumida, Design Tokens são variáveis semânticas que carregam determinadas informações. Como cores, espaçamentos e tamanhos, que quando sozinhos parecem não ter muita importância, mas que em conjunto são muito relevantes para determinar a consistência de um produto.&lt;/p&gt;

&lt;p&gt;Cada token tem um nome exclusivo que faz referência a um valor específico. Por exemplo, quando a pessoa designer precisa definir uma cor de fundo, ao invés de usar o valor &lt;code&gt;#ffffff&lt;/code&gt; no elemento, passaria a usar &lt;code&gt;background-primary&lt;/code&gt;.&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%2Fx4yav3ovj94yl09ionhq.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%2Fx4yav3ovj94yl09ionhq.png" alt="Exemplo de token"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pode parecer desnecessário, em primeiro momento, utilizar &lt;code&gt;background-primary&lt;/code&gt; sendo que essa variável tem o valor &lt;code&gt;#ffffff&lt;/code&gt;. Mas imagine que no futuro queremos alterar a cor de fundo do nosso produto para um tom mais cinza, como &lt;code&gt;#fafafa&lt;/code&gt;. Como isso seria feito sem tokens?&lt;/p&gt;

&lt;p&gt;Teríamos que localizar todos os lugares do nosso produto que estão usando o valor &lt;code&gt;#ffffff&lt;/code&gt;, garantir que estão sendo usado para cor de fundo e ai substituir todos para &lt;code&gt;#fafafa&lt;/code&gt;. Já com o uso do token &lt;code&gt;background-primary&lt;/code&gt;, nós já garantimos que todos os usos são referentes a cor de fundo (o nome semântico nos ajuda a garantir isso) e caso necessitamos alterar o valor, basta alterar em um único lugar para que todo o seu produto reflita essa mudança.&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%2F1h3od88g31es7uywmyc8.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%2F1h3od88g31es7uywmyc8.png" alt="Imagem representando a alteração de valores"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Como design tokens garantem consistência?
&lt;/h2&gt;

&lt;p&gt;Definindo uma lista semântica de variáveis, faz com que a pessoa responsável pela implementação (seja no Figma ou o código CSS) selecione apenas valores existentes ao invés de usar valores e variações específicas.&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%2Fg49d3mtkhfez4k3wirzl.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%2Fg49d3mtkhfez4k3wirzl.png" alt="Uso dos tokens em um elemento"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Introduzir um novo valor, como por exemplo tamanho de fonte, se torna mais difícil. Pois o fluxo de trabalho, das pessoas designers e desenvolvedoras, passa a ser de utilizar valores pré-existentes. Qualquer valor que não tenha uma variável estabelecida, é facilmente identificado como variante. &lt;/p&gt;

&lt;p&gt;A utilização do tokens torna o processo saudável, evitando atritos e inconsistências, tornando o processo flexível e dinâmico para todos os envolvidos.&lt;/p&gt;

&lt;p&gt;Nos próximos artigos, vamos mostrar a implementação dos design tokens da Trybe e como garantimos que pessoas designers e desenvolvedoras utilizem o mesmo valor tendo uma única fonte da verdade. Aguarde!&lt;/p&gt;

</description>
      <category>figma</category>
      <category>design</category>
      <category>token</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Um guia sobre estruturação de pastas para projetos em Next.js</title>
      <dc:creator>Gabriel Nunes</dc:creator>
      <pubDate>Fri, 01 Apr 2022 18:23:11 +0000</pubDate>
      <link>https://forem.com/trybe/um-guia-sobre-estruturacao-de-pastas-para-projetos-em-nextjs-5b6j</link>
      <guid>https://forem.com/trybe/um-guia-sobre-estruturacao-de-pastas-para-projetos-em-nextjs-5b6j</guid>
      <description>&lt;p&gt;Sempre que vou iniciar um novo projeto usando Next.js a primeira coisa que vem na cabeça é: como eu mantenho as coisas organizadas em um padrão de Developer Experience semelhante ao que o time do Next já criou?&lt;/p&gt;

&lt;p&gt;É realmente impressionante a forma como é simples, fácil de entender e prático. Toda nova atualização mais facilidades são adicionadas ao framework e ele fica cada vez mais maravilhoso (ok, sou fã, como descobriu?).&lt;/p&gt;

&lt;p&gt;Aqui na Trybe, começamos recentemente o trabalho de migração do site institucional para Next.js, e tivemos que pesquisar um bocado para entender a melhor forma de organizar as pastas do projeto. Não existe uma unanimidade, algumas pessoas gostam de usar um padrão semelhante ao que usam em projetos em React, outras criam seus próprios padrões. Que foi o nosso caso.&lt;/p&gt;

&lt;p&gt;Decidimos primeiro entender qual seria a estrutura de um site, para depois pensarmos na estrutura das pastas, sempre tentando entender o que seria mais fácil de compreender somente olhando para o projeto... e ficou assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;- site-trybe
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; __tests__
        index.test.tsx
        primeiros-passos.test.tsx
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; components
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; _ui
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Button
                Button.tsx
                Button.module.scss
                Button.test.tsx
                index.tsx
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Navbar
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; home
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Hero
                constants.ts
                Hero.tsx
                Hero.module.scss
                Hero.test.tsx
                index.tsx
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; first-steps
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Video
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Form
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hooks
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; pages
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; primeiros-passos
            confirmacao.tsx
            index.tsx
        _app.tsx
        index.tsx
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; public
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; images
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; fonts
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; icons
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; styles
        theme.scss
        global.scss
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; utils
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; constants
            navigation.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos entender melhor o que temos em cada pasta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testes de snapshot para cada página
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; __tests__
        index.test.tsx
        primeiros-passos.test.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para manter a consistência do site, e evitar, ou melhor, avisar, quando alterações sejam feitas em conteúdos ou ordem de componentes, decidimos criar testes simples para cada página do site, apenas para manter o snapshot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pasta de componentes separados por páginas
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; components
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; _ui
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Button
                Button.tsx
                Button.module.scss
                Button.test.tsx
                index.tsx
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Navbar
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; home
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Hero
                constants.ts
                Hero.tsx
                Hero.module.scss
                Hero.test.tsx
                index.tsx
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; first-steps
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Video
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Form
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A pasta &lt;code&gt;_ui&lt;/code&gt; é onde ficam todos os componentes em comum entre várias páginas do site, quase que como se fosse o nosso Design System.&lt;/p&gt;

&lt;p&gt;Além disso, cada página do site possui uma pasta dentro da pasta de componentes. Dentro dessa pasta, então, são adicionados todos os componentes, com seus arquivos de estilo, constantes que são usadas apenas ali e seu arquivo de teste (caso seja necessário).&lt;/p&gt;

&lt;p&gt;Dessa forma, podemos ter dois componentes &lt;code&gt;&amp;lt;Hero /&amp;gt;&lt;/code&gt;, porém, eles estarão em suas pastas relacionadas a cada página/contexto. Nós também focamos em manter os textos e organização do layout em cada componente, dessa forma, uma página apenas importa os componentes que formam ela.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* /pages/empresas-parceiras/index.tsx */&lt;/span&gt;

&lt;span class="cm"&gt;/* ... aqui vão todos os imports */&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ParnerCompanies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextPage&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Page&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contrate programadores e desenvolvedores pela Trybe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Empresas inovadoras contratam talentos de tecnologia na Trybe. E o melhor: elas não pagam nada por isso. Contrate agora!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Hero&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CompleteTraining&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WhyHireTrybers&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WhatCompaniesSays&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OurTraining&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WorldOfPossibility&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Benefits&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HowItWorks&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NoCosts&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Page&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ParnerCompanies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Outras pastas complementares
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hooks
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; public
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; images
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; fonts
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; icons
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; styles
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; utils
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; constants
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fora a pasta &lt;code&gt;pages&lt;/code&gt; que é padrão dos projetos Next.js, também criamos pastas para deixar organizados os estilos, os hooks e os utils, como as constantes globais do projeto.&lt;/p&gt;

&lt;p&gt;Também separamos a pasta &lt;code&gt;public&lt;/code&gt; em outras três: images, fonts e icons.&lt;/p&gt;

&lt;h1&gt;
  
  
  Organização é tudo para uma pessoa desenvolvedora feliz
&lt;/h1&gt;

&lt;p&gt;Sim, meu amigo e minha amiga. Ter um projeto organizado é o que nos dá vontade de trabalhar todo dia.&lt;/p&gt;

&lt;p&gt;Acredito que este artigo pode ajudar você, que estava perdido em qual arquitetura utilizar na hora de deixar o seu projeto Next.js mais arrumadinho.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Como a Trybe corrige mais de 20 mil avaliações por semana!</title>
      <dc:creator>Gabriel de Biasi</dc:creator>
      <pubDate>Tue, 29 Mar 2022 18:06:46 +0000</pubDate>
      <link>https://forem.com/trybe/como-a-trybe-corrige-mais-de-20-mil-avaliacoes-por-semana-1i6f</link>
      <guid>https://forem.com/trybe/como-a-trybe-corrige-mais-de-20-mil-avaliacoes-por-semana-1i6f</guid>
      <description>&lt;p&gt;Para quem não conhece a &lt;a href="https://www.betrybe.com/" rel="noopener noreferrer"&gt;Trybe&lt;/a&gt;, é uma escola de desenvolvimento web que tem comprometimento genuíno com o sucesso profissional de quem estuda conosco. Com o Modelo de Sucesso Compartilhado (MSC) ofertado pela Trybe Fintech, a pessoa estudante tem a opção de pagar apenas quando já estiver trabalhando, você acredita nesse nível de confiança?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/PudZiAbQDUEik/giphy-downsized.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/PudZiAbQDUEik/giphy-downsized.gif" alt="gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E para isso precisamos ter um infraestrutura para avaliar todos os projetos enviados pelas pessoas estudantes! Hoje utilizamos GitHub Actions, entretanto, usar os executores oferecidos pelo próprio GitHub Cloud não é o suficiente, pois esgotaríamos os minutos oferecidos pelo plano rapidamente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l4FGjq205dsq8mcw0/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l4FGjq205dsq8mcw0/giphy.gif" alt="Simulação de uma pessoa estudante esperando pela sua avaliação"&gt;&lt;/a&gt;&lt;/p&gt;
Simulação de uma pessoa estudante esperando pela sua avaliação



&lt;p&gt;Logo, optamos por manter nossa própria infraestrutura de self-hosted runners, e melhor ainda, tudo orquestrado usando &lt;a href="https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Veja na imagem abaixo como é o esquema de funcionamento. Após isso, temos o passo-a-passo explicando o fluxo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 1:&lt;/strong&gt; A pessoa estudante envia seu projeto como um &lt;em&gt;pull request&lt;/em&gt; no repositório.&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%2Fjhe3yiz1rb2lgyf5ey0a.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%2Fjhe3yiz1rb2lgyf5ey0a.png" alt="Passo 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 2:&lt;/strong&gt; De acordo com a configuração do workflow, o trigger é acionado e uma nova avaliação é inserida na fila de workflows do repositório;&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%2Fzfdmg2eql07kx6csonn0.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%2Fzfdmg2eql07kx6csonn0.png" alt="Passo 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 3:&lt;/strong&gt; Os self-hosted runners funcionam como &lt;strong&gt;pull-based&lt;/strong&gt;, ou seja, eles fazem &lt;strong&gt;pulling&lt;/strong&gt; no GitHub API aguardando por jobs à serem executados.&lt;/p&gt;

&lt;p&gt;É possível que não haja runners disponíveis no momento. Então, nós temos um &lt;em&gt;controller&lt;/em&gt; que se comunica com o GitHub API sobre a condição atual dos runners. Se não houver runners disponíveis no momento, o controler aciona o &lt;strong&gt;Horizontal Runner Autoscaler&lt;/strong&gt; para escalar para cima o número de runners em nossa infraestrutura.&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%2Fjy2hmnc69inijp3isr49.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%2Fjy2hmnc69inijp3isr49.png" alt="Passo 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ao mesmo tempo, nosso &lt;em&gt;controler&lt;/em&gt; também verifica se não temos "runners demais": Se mais de 50% dos runners atuais estão em &lt;em&gt;idle&lt;/em&gt;, isso significa que podemos diminuir o número de runners para melhorarmos nossos custos com infraestrutura. O controler aciona o &lt;strong&gt;Horizontal Runner Autoscaler&lt;/strong&gt; para escalar para baixo o número de runners em nossa infraestrutura.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 4:&lt;/strong&gt; A avaliação é feita utilizando uma série de actions implementados pelo time da Trybe. Essas actions envolvem &lt;em&gt;linters&lt;/em&gt; de arquivos, execução do &lt;em&gt;cypress&lt;/em&gt;, testes unitários, etc.&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%2Fb9vhn3an2httespgiwb3.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%2Fb9vhn3an2httespgiwb3.png" alt="Passo 4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 5:&lt;/strong&gt; Após executar a avaliação, a última action do workflow envia o resultado obtido para o nosso backend de avaliações, para ser armazenado em nosso banco de dados.&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%2F2j4xcbvhezd5afdp7uz0.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%2F2j4xcbvhezd5afdp7uz0.png" alt="Passo 5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 6:&lt;/strong&gt; Como muitas pessoas estudantes enviam suas avaliações ao mesmo tempo, foi implementado uma solução utilizando &lt;strong&gt;Amazon MQ&lt;/strong&gt;, para enfilieirar o processo de avaliação e também evitar um possível &lt;em&gt;rate limit&lt;/em&gt; na API do GitHub.&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%2Fnrbck64fswqm00bd92l9.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%2Fnrbck64fswqm00bd92l9.png" alt="Passo 6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passo 7-8:&lt;/strong&gt; Após processar a avaliação que estava na fila de mensageria, o backend de avaliação faz um comentário no PR da pessoa estudante, informando o resultado!&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%2Fcqt7yhrkapdnf0l2us5r.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%2Fcqt7yhrkapdnf0l2us5r.png" alt="Passo 7-8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bem simples, né&lt;/strong&gt;? O processo parece ser complicado, mas é necessário pelo tamanho da demanda que temos em corrigir mais de 20 mil avaliações por semana. Agora veja todo o processo em apenas uma figura:&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%2Frybftr82dy0loaim0fa2.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%2Frybftr82dy0loaim0fa2.png" alt="Processo Completo"&gt;&lt;/a&gt;Processo de correção&lt;/p&gt;

&lt;p&gt;Gostou do que viu? Quer ajudar a Trybe a manter esta infraestrutura? Venha pois temos várias &lt;a href="https://www.betrybe.com/trabalhe-conosco" rel="noopener noreferrer"&gt;vagas abertas&lt;/a&gt;!!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>github</category>
      <category>githubactions</category>
      <category>devops</category>
    </item>
    <item>
      <title>Automatizando tarefas com Go</title>
      <dc:creator>Matheus Mina</dc:creator>
      <pubDate>Fri, 11 Mar 2022 17:43:48 +0000</pubDate>
      <link>https://forem.com/trybe/automatizando-tarefas-com-go-1cje</link>
      <guid>https://forem.com/trybe/automatizando-tarefas-com-go-1cje</guid>
      <description>&lt;p&gt;Na vida de uma pessoa desenvolvedora, nos deparamos diversas vezes com tarefas monótonas, repetitivas e sempre nos vem a ideia na cabeça de como podemos automatizar isso. Aqui na Trybe, temos dois cenários bem legais de como Go nos ajudou a automatizar algumas dessas tarefas.&lt;/p&gt;

&lt;p&gt;O primeiro cenário é o nosso &lt;strong&gt;trybe-cli&lt;/strong&gt;. Isso mesmo, escrevemos um client em Go, para ajudar nossas pessoas desenvolvedoras e executar tarefas repetitivas com alguns comandos. Neste momento, nosso cli nos permite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;criar todos os arquivos da esteira de deploy;&lt;/li&gt;
&lt;li&gt;criar flags e segmentos no nosso serviço de feature flags;&lt;/li&gt;
&lt;li&gt;gerenciar as tarefas no Jira: mover a tarefa pra doing, mover a tarefa pra review e até mesmo ter algumas estatísticas de tempo do ticket aberto e etc;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para escrever esse cli, duas ferramentas nos ajudaram muito. A primeira delas é a lib &lt;a href="https://github.com/spf13/cobra" rel="noopener noreferrer"&gt;cobra&lt;/a&gt; e ela auxilia na criação de CLIs e é utilizada por diversos lugares como Kubernetes, Hugo, GitHub cli, Docker e mais todas os lugares apontados &lt;a href="https://github.com/spf13/cobra/blob/master/projects_using_cobra.md" rel="noopener noreferrer"&gt;nessa lista&lt;/a&gt;. Das diversas funcionalidades, as mais legais são: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sugestões inteligentes: (&lt;code&gt;app srver&lt;/code&gt;... did you mean &lt;code&gt;app server&lt;/code&gt;?);&lt;/li&gt;
&lt;li&gt;criação automática de um help para seu cli;&lt;/li&gt;
&lt;li&gt;criação automática de auto-complete para &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;zsh&lt;/code&gt; e etc;&lt;/li&gt;
&lt;li&gt;reconhece flags de forma automática e inteligente, por exemplo &lt;code&gt;-h&lt;/code&gt; e &lt;code&gt;--help&lt;/code&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A segunda ferramenta é a &lt;a href="https://github.com/goreleaser/goreleaser" rel="noopener noreferrer"&gt;goreleaser&lt;/a&gt;, responsável por buildar e gerar os binários em todas as plataformas: MacOS, Linux e Windows. Para nós, isso é extremamente útil, já que não precisamos nos preocupar com as particularidades de cada sistema operacional e nossas pessoas desenvolvedoras não ficam travadas em um sistema ou outro. Isso só é possível porque Go é uma linguagem cross-plataform.&lt;/p&gt;

&lt;p&gt;O segundo cenário, é um &lt;strong&gt;micro-serviço&lt;/strong&gt; responsável somente por receber requisições do GitHub.  Para explicar o porque fazemos isso, vale a pena explicar um pouco sobre nosso ambiente de desenvolvimento. Hoje temos os seguintes ambientes, que podem ser traduzidos em clusters kubernetes: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;produção&lt;/em&gt;: ambiente que as pessoas estudantes, candidatas e empregadas utilizam;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;staging&lt;/em&gt;: ambiente que simula o ambiente produtivo. Utilizado para testar funcionalidades maiores;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;preview-app&lt;/em&gt;: ambiente de teste para funcionalidades especificas. Cada pull request aberto, em cada repositório nosso, gera um pod neste cluster;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;homologação&lt;/em&gt;: ambiente de testes utilizados por nossos QAs;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Como podem ver, o cluster das preview-apps cresce exponencialmente, já que pra cada pull request aberto, um pod lá é criado. Para consumir menos recursos, nossos SREs criaram uma tarefa em background para limpar os pods que eram mais velhos que 5 dias. Contudo, ainda era possível melhorar este gerenciamento.&lt;/p&gt;

&lt;p&gt;Ao fechar um pull request, seja ao fazer um merge ou ao recusar, aquele pod se torna automaticamente obsoleto e dispensável. Com isso, um pequeno micro-serviço foi criado com a única responsabilidade de escutar estes eventos do GitHub e apagar o pod. Assim nosso cluster só mantem os pods que estão de fato sendo utilizados. &lt;/p&gt;

&lt;p&gt;Como podemos ver, Go é bem versátil e que pode nos ajudar em diversos cenários de automação, criando desde clis multi-plataformas até micro-serviços pequenos e robustos. É definitivamente uma linguagem a se avaliar neste cenário.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>productivity</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Elixir - Conceitos Iniciais</title>
      <dc:creator>Igor Giamoniano</dc:creator>
      <pubDate>Thu, 10 Mar 2022 22:41:35 +0000</pubDate>
      <link>https://forem.com/trybe/elixir-conceitos-iniciais-4m8k</link>
      <guid>https://forem.com/trybe/elixir-conceitos-iniciais-4m8k</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;No &lt;a href="https://dev.to/trybe/meus-primeiro-passos-no-elixir-1n1j"&gt;último artigo&lt;/a&gt;, ensinei a configurar a máquina para começarmos a usar o Elixir, agora falaremos um pouco sobre a linguagem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elixir x Erlang
&lt;/h3&gt;

&lt;p&gt;Você deve ter notado no último artigo, que tivemos que instalar o Elixir e o Erlang, mas o que é Erlang?&lt;br&gt;
&lt;a href="https://i.giphy.com/media/pPhyAv5t9V8djyRFJH/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/pPhyAv5t9V8djyRFJH/giphy.gif" alt="Obama" width="480" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O Erlang é uma linguagem de programação criada muitos anos antes do Elixir para solucionar demandas relacionadas a rede de telefonia, é uma linguagem muito poderosa porem com uma sintaxe bastante complexa e é aí que entra o Elixir.&lt;/p&gt;

&lt;p&gt;O Elixir traz uma sintaxe mais amigável porem sua estrutura é idêntica a do Erlang sendo assim nosso código pode ser escrito em Elixir e depois transpilado para Erlang e por último compilado pela BEAM.&lt;/p&gt;
&lt;h3&gt;
  
  
  BEAM?
&lt;/h3&gt;

&lt;p&gt;BEAM é um acrônimo para &lt;em&gt;"Bogdan/Björn's Erlang Abstract Machine”&lt;/em&gt; (Sendo &lt;em&gt;Bogdan&lt;/em&gt; e &lt;em&gt;Björn's&lt;/em&gt; o nome original dos criadores) e é simplesmente o nome da Virtual Machine (VM) como a Java Virtual Machine (JVM) para quem conhece Java. &lt;/p&gt;

&lt;p&gt;Agora que já falamos bastante, vamos pro código!&lt;/p&gt;


&lt;h2&gt;
  
  
  Iniciando um Projeto com Mix
&lt;/h2&gt;

&lt;p&gt;Acredito que a melhor forma de se aprender uma linguagem de programação é criando um projeto, então por mais que leiamos a documentação ou vejamos vários vídeos tutoriais, o  aprendizado só é consolidado quando realmente aplicamos a linguagem.&lt;/p&gt;

&lt;p&gt;Então vamos aplicar alguns conceitos de Elixir, na prática, para isso iniciaremos um projeto com o Mix!&lt;/p&gt;
&lt;h2&gt;
  
  
  Mix o quê?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/JoxvmZFZ224I4kD8qN/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/JoxvmZFZ224I4kD8qN/giphy.gif" alt="Mix it up" width="480" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chegamos naquele momento em que parece que o sentido foi deixado para trás, acreditem isso é muito comum principalmente se você veio de outra linguagem de programação e está aprendendo Elixir agora, mas calma que as coisas vão começar a se encaixar.&lt;/p&gt;

&lt;p&gt;Mix é uma ferramenta de linha de comando que integra o ecossistema Elixir e a utilizamos para gerenciar uma porção de coisas diferentes no nosso código (ex: Gerar e compilar projetos, rodar ‘Tasks’, gerenciar dependências).&lt;/p&gt;

&lt;p&gt;Portanto, iniciaremos um projeto usando Mix! &lt;/p&gt;

&lt;p&gt;No seu terminal digite o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix new basics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você vera algo parecido com isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/projetos 
❯ mix new basics
&lt;span class="k"&gt;*&lt;/span&gt; creating README.md
&lt;span class="k"&gt;*&lt;/span&gt; creating .formatter.exs
&lt;span class="k"&gt;*&lt;/span&gt; creating .gitignore
&lt;span class="k"&gt;*&lt;/span&gt; creating mix.exs
&lt;span class="k"&gt;*&lt;/span&gt; creating lib
&lt;span class="k"&gt;*&lt;/span&gt; creating lib/basics.ex
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;/test_helper.exs
&lt;span class="k"&gt;*&lt;/span&gt; creating &lt;span class="nb"&gt;test&lt;/span&gt;/basics_test.exs

Your Mix project was created successfully.
You can use &lt;span class="s2"&gt;"mix"&lt;/span&gt; to compile it, &lt;span class="nb"&gt;test &lt;/span&gt;it, and more:

    &lt;span class="nb"&gt;cd &lt;/span&gt;basics
    mix &lt;span class="nb"&gt;test

&lt;/span&gt;Run &lt;span class="s2"&gt;"mix help"&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more commands.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que ele pede para você entrar no diretório criado para começar, vamos lá:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;basics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Módulos e Funções
&lt;/h2&gt;

&lt;p&gt;A primeira coisa que devemos notar é como as funções se comportam, como falamos lá atrás o Elixir usa o paradigma funcional, falaremos disso mais tarde, antes disso quero que você preste atenção na sintaxe.&lt;/p&gt;

&lt;p&gt;Lá no diretório &lt;em&gt;lib&lt;/em&gt;, perceba que foi gerado um arquivo &lt;em&gt;basics.ex&lt;/em&gt; e dentro dele um módulo &lt;em&gt;Basics&lt;/em&gt;:&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;Basics&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para definir um módulo no elixir usamos a sintaxe &lt;strong&gt;defmodule&lt;/strong&gt; você perceberá que basicamente, 100% dos códigos escritos em Elixir estão dentro de algum módulo.&lt;/p&gt;

&lt;p&gt;Um &lt;strong&gt;módulo&lt;/strong&gt; é uma coleção de diferentes &lt;strong&gt;métodos&lt;/strong&gt; ou &lt;strong&gt;funções.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Então deixaremos de ser tediosos e escreveremos um pouco de código aqui!&lt;/p&gt;

&lt;p&gt;Vamos criar uma função &lt;strong&gt;create_list&lt;/strong&gt; que retornara uma lista.&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;Basics&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;create_list&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"little indians"&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;p&gt;Perceba que usamos a sintaxe &lt;strong&gt;def&lt;/strong&gt; para definir uma função &lt;strong&gt;create_list&lt;/strong&gt; dentro do nosso método &lt;strong&gt;Basics.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Rodando nosso projeto
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/4LWEwOMfbVeYU/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/4LWEwOMfbVeYU/giphy.gif" alt="rolling simpson" width="380" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para rodar nosso projeto, utilizaremos o &lt;strong&gt;IEx&lt;/strong&gt; (Interactive Elixir Shell). O IEx é como o Shell do Python ou o IRB do Ruby, podemos escrever qualquer código Elixir dentro dele e executar em Real Time.&lt;/p&gt;

&lt;p&gt;Na pasta do projeto em seu terminal digite:&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;iex&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;S&lt;/span&gt; &lt;span class="n"&gt;mix&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso você devera abrir o IEx com seu projeto compilado, para testar digite:&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;Basics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você devera receber a seguinte resposta:&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"little indians"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um ponto importante que devemos notar é que nossa lista foi retornada automaticamente, isso é chamado &lt;strong&gt;retorno implícito&lt;/strong&gt; onde o último valor da função chamada é retornado.&lt;/p&gt;

&lt;h3&gt;
  
  
  POO x Programação Funcional
&lt;/h3&gt;

&lt;p&gt;Se você já usou Javascript ou Ruby provavelmente já escreveu algo do tipo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;little indians&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como observamos na sessão anterior não precisamos fazer isso no Elixir, o valor simplesmente foi retornado chamando a função que estava dentro do nosso módulo. Isso é extremamente importante quando estamos falando de &lt;strong&gt;Programação Funcional x&lt;/strong&gt; &lt;strong&gt;Programação Orientada a Objeto&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Na prática na POO você cria classes e estancia essas classes em variáveis sempre que precisa utilizar os seus métodos, na PF você atribui um valor primitivo a um método que retornara algo.&lt;/p&gt;

&lt;p&gt;Não é possível na programação funcional criar ou estanciar classes, lembre-se: &lt;strong&gt;um módulo no Elixir é apenas uma coleção de métodos e nada mais&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Para se aprofundar no assunto, estou colocando aqui um link para um curso de&lt;/em&gt; &lt;a href="https://www.udemy.com/course/programacao-funcional-com-elixir/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Webindex_Catchall_la.PT_cc.BR&amp;amp;utm_term=_._ag_114148736799_._ad_485704569539_._de_c_._dm__._pl__._ti_dsa-525138004927_._li_1001773_._pd__._&amp;amp;gclid=CjwKCAiAjoeRBhAJEiwAYY3nDCBWUhc4qrIKjNm0aOH2A6X8t9z7dIMQK2WNSnlKJTEiQ00zV5YqOhoCWu8QAvD_BwE"&gt;Programação Funcional com Elixir&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Aridade
&lt;/h3&gt;

&lt;p&gt;Veja bem eu disse ARIDADE (do inglês, &lt;em&gt;Arity&lt;/em&gt;) e não RARIDADE ou PARIDADE, mas o que raios é Aridade &lt;strong&gt;&lt;a href="https://emojipedia.org/thinking-face/"&gt;🤔&lt;/a&gt;&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Vamos criar uma nova função abaixo da que criamos anteriormente chamada &lt;strong&gt;shuffle:&lt;/strong&gt;&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;def&lt;/span&gt; &lt;span class="n"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&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;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora com no IEx usaremos a palavra reservada &lt;strong&gt;recompile&lt;/strong&gt; para recompilar nossa aplicação, basta escrever:&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;recompile&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois vamos testar a função que acabamos de criar:&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;Basics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shuffle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você verá um erro parecido com esse:&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="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UndefinedFunctionError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="no"&gt;Basics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shuffle&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="no"&gt;Did&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="ss"&gt;mean:&lt;/span&gt;
      &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;shuffle&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;basics&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;Basics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba o que este log esta nos falando, ele diz que a função &lt;em&gt;Basics.shuffle&lt;/em&gt; precisa de um argumento &lt;em&gt;shuffle/1, ou seja&lt;/em&gt;, a função Basics.shuffle possui aridade 1.&lt;/p&gt;

&lt;p&gt;Veja esse exemplo:&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;Basics&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;hello&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="s2"&gt;"Hello World"&lt;/span&gt;                              &lt;span class="c1"&gt;# hello/0&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;                        &lt;span class="c1"&gt;# hello/1&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name2&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="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;name1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;name2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# hello/2&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Basics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="s2"&gt;"Hello World"&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Basics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"Hello, John"&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Basics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Nicole"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"Hello John and Nicole"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Elixir aridade é um cidadão de &lt;a href="https://en.wikipedia.org/wiki/First-class_citizen#:~:text=In%20programming%20language%20design%2C%20a,generally%20available%20to%20other%20entities."&gt;primeira classe&lt;/a&gt;, ou seja, podemos invocar funções sem necessariamente informar os parâmetros.&lt;/p&gt;

&lt;p&gt;Com base no nosso exemplo podemos perceber como o Elixir percebe cada função como diferente uma da outra devido a sua aridade, ou seja, &lt;strong&gt;através da aridade sabemos qual função deve ser chamada.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Isso será muito importante no futuro quando falarmos de Pattern Matching.&lt;/p&gt;

&lt;p&gt;Para resumir, &lt;strong&gt;aridade se refere a quantidade de argumentos que uma função deve receber conforme a sua implementação&lt;/strong&gt; e por padrão referimos-lhe com / e o número de argumentos do lado direito.&lt;/p&gt;

&lt;p&gt;Para se aprofundar no assunto estou colocando &lt;a href="https://elixirschool.com/en/lessons/basics/functions/#named-functions-2"&gt;um artigo da Elixir School&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Nesse artigo falamos um pouco sobre Elixir, Erlang e Beam, iniciamos nossa primeira aplicação com MIX, falamos um pouco sobre programação funcional e Aridade.&lt;/p&gt;

&lt;p&gt;No próximo artigo vamos dar mais funcionalidades para a nossa aplicação.&lt;/p&gt;

&lt;p&gt;Te vejo em breve! ;)&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>erlang</category>
      <category>aridade</category>
      <category>mix</category>
    </item>
    <item>
      <title>Evite configuration drift no seu estado de terraform ao usar aws_security_group</title>
      <dc:creator>Gabriel de Biasi</dc:creator>
      <pubDate>Tue, 08 Mar 2022 11:02:37 +0000</pubDate>
      <link>https://forem.com/trybe/evite-configuration-drift-no-seu-estado-de-terraform-ao-usar-awssecuritygroup-2ndp</link>
      <guid>https://forem.com/trybe/evite-configuration-drift-no-seu-estado-de-terraform-ao-usar-awssecuritygroup-2ndp</guid>
      <description>&lt;p&gt;O &lt;a href="https://www.terraform.io/intro"&gt;terraform&lt;/a&gt; é uma ferramenta fantástica para provisionar e manter o estado de uma infraestrutura, tanto on-premises quanto nos ambientes de cloud. Entretanto, algumas vezes passamos por algumas situações que nós temos uma expectativa de que o terraform funcione de uma maneira, porém o terraform acaba funcionando de outra forma.&lt;/p&gt;

&lt;p&gt;Foi o que aconteceu comigo ao utilizar o recurso &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group"&gt;aws_security_group&lt;/a&gt;. Este recurso permite criar um &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html"&gt;Security Group&lt;/a&gt; dentro de uma VPC, que na prática pode ser aplicado a outros recursos, como instâncias EC2, banco de dados, clusters Kubernetes, para fechar portas de conexão e liberar apenas algumas portas específicas (ou nenhuma).&lt;/p&gt;

&lt;p&gt;Meu caso de uso foi criar um Security Group para uma instância EC2 que iria trabalhar como um &lt;em&gt;worker&lt;/em&gt;, ou seja, essa instância iria obter os jobs através de uma fonte externa, realizar o processamento e enviar o resultado. Em resumo, por trabalhar em &lt;strong&gt;pull-based&lt;/strong&gt;, essa instância não precisaria ter nenhuma regra de ingresso (entrada), apenas uma regra de egresso (saída) para qualquer IP.&lt;/p&gt;

&lt;p&gt;Logo, fiz o recurso da seguinte maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_security_group" "sg" {
  name   = "my-amazing-security-group"
  vpc_id = aws_vpc.main.id

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao executar o comando &lt;strong&gt;terraform apply&lt;/strong&gt;, obtive a seguinte saída:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gabriel@machine:~/terraform$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_security_group.sg will be created
  + resource "aws_security_group" "sg" {
      + arn                    = (known after apply)
      + description            = "Managed by Terraform"
      + egress                 = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = ""
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = false
              + to_port          = 0
            },
        ]
      + id                     = (known after apply)
      + ingress                = (known after apply)
      + name                   = "my-amazing-security-group"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags_all               = (known after apply)
      + vpc_id                 = "vpc-0101010101"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

aws_security_group.sg: Creating...
aws_security_group.sg: Creation complete after 2s [id=sg-0101010101010101]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ótimo! O terraform criou o security group e eu pude utilizar na instância EC2 que criei. Entretanto, percebi que tinha cometido um erro ao provisionar a instância EC2 e eu precisava me conectar nessa instância usando &lt;strong&gt;ssh&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/QBpnlzndcEeIS57v15/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/QBpnlzndcEeIS57v15/giphy.gif" alt="made a mistake" width="600" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para possibilitar o acesso, eu precisava criar a regra de ingresso no security group. Logo, fui diretamente no dashboard da AWS, editei o security group manualmente liberando a porta 22 para apenas o meu IP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/xThtaxbIPLT9XqWcDK/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/xThtaxbIPLT9XqWcDK/giphy.gif" alt="hehehe" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após me conectar na instância e resolver o problema, pensei: “&lt;em&gt;Vou simplesmente executar terraform apply, pois o terraform irá perceber a regra extra no security group e criar um plano para remover esta regra&lt;/em&gt;”. Então, ao executar o comando, obtive a seguinte saída:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gabriel@machine:~/terraform$ terraform apply
aws_security_group.sg: Refreshing state... [id=sg-0101010101010101]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/nTfdeBvfgzV26zjoFP/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/nTfdeBvfgzV26zjoFP/giphy.gif" alt="confuso" width="400" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na hora fiquei confuso. O terraform não percebeu a regra nova no security group? Fui no dashboard da AWS e vi que a regra de ingresso ainda estava presente! E agora?&lt;/p&gt;

&lt;p&gt;Pesquisando melhor, entendi que o recurso aws_security_group não mantém o estado das regras, se isso não for &lt;strong&gt;explícito&lt;/strong&gt;. Ou seja, precisamos deixar explícito na definição do recurso que não queremos nenhuma regra de ingresso. Corrigindo nosso código, ficaria assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_security_group" "sg" {
  name   = "my-amazing-security-group"
  vpc_id = data.aws_vpc.main.id

  ingress = []    # explicitamente nenhuma regra de ingresso

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que o atributo &lt;strong&gt;ingress&lt;/strong&gt; recebe uma lista vazia. Isto deixa explícito que não queremos nenhuma regra de ingresso para este security group. Logo, executando o comando terraform apply novamente, finalmente podemos ter o estado garantido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gabriel@machine:~/terraform$ terraform apply
aws_security_group.sg: Refreshing state... [id=sg-0110522c7ec4870d0]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_security_group.sg will be updated in-place
  ~ resource "aws_security_group" "sg" {
        id                     = "sg-0110522c7ec4870d0"
      ~ ingress                = [
          - {
              - cidr_blocks      = [
                  - "169.169.169.169/32",
                ]
              - description      = "My IP"
              - from_port        = 22
              - ipv6_cidr_blocks = []
              - prefix_list_ids  = []
              - protocol         = "tcp"
              - security_groups  = []
              - self             = false
              - to_port          = 22
            },
        ]
        name                   = "my-amazing-security-group"
        tags                   = {}
        # (7 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

aws_security_group.sg: Modifying... [id=sg-0110522c7ec4870d0]
aws_security_group.sg: Modifications complete after 0s [id=sg-0110522c7ec4870d0]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/nXxOjZrbnbRxS/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/nXxOjZrbnbRxS/giphy.gif" alt="ufa" width="200" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ufa! Agora sim o terraform nos garante que este security group não ganhe novas regras através do dashboard da AWS e mantenha este estado pra gente. &lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>sre</category>
      <category>devops</category>
    </item>
    <item>
      <title>Elixir - Configurando o Setup</title>
      <dc:creator>Igor Giamoniano</dc:creator>
      <pubDate>Thu, 03 Mar 2022 17:47:52 +0000</pubDate>
      <link>https://forem.com/trybe/meus-primeiro-passos-no-elixir-1n1j</link>
      <guid>https://forem.com/trybe/meus-primeiro-passos-no-elixir-1n1j</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Antes de começarmos é importante trazer que esse artigo faz parte de uma série de outros artigos, nos quais documentarei a minha experiência pessoal com Elixir e meus primeiros passos.&lt;/p&gt;

&lt;p&gt;Vim recentemente do Node.js e todo mundo sabe como é simples configurar o seu setup, baixar o NPM, Snippets no VSCode, etc.&lt;/p&gt;

&lt;p&gt;No Elixir não é tão difícil porem tive muita dificuldade de encontrar um passo a passo e acabei pulando etapas o que me deu muita dor de cabeça depois para consertar.&lt;/p&gt;

&lt;p&gt;Dito isto, resolvi trazer um passo a passo para você configurar seu setup do zero, bora lá!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S. Utilizarei o &lt;a href="https://linuxmint.com/" rel="noopener noreferrer"&gt;Linux Mint&lt;/a&gt; e você pode adaptar para o seu SO ok?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/4Zgy9QqzWU8C3ugvCa/giphy-downsized.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/4Zgy9QqzWU8C3ugvCa/giphy-downsized.gif" alt="code pinguim"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ASDF (What?)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/yoJC2qZ23Pb8HQI08g/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/yoJC2qZ23Pb8HQI08g/giphy.gif" alt="ASDF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A primeira coisa que nos vamos instalar na nossa maquina é esse bichinho chamado &lt;a href="https://asdf-vm.com/" rel="noopener noreferrer"&gt;ASDF&lt;/a&gt; e se você nunca ouviu falar nele faço questão de te apresentar.&lt;/p&gt;

&lt;p&gt;ASDF e um gerenciador de máquina virtual que nós vamos utilizar para instalar o Elixir e o Erlang.&lt;/p&gt;

&lt;p&gt;Então de um gole no café ☕ e vamos começar!&lt;/p&gt;




&lt;h3&gt;
  
  
  Instalando ASDF-Vm.
&lt;/h3&gt;

&lt;p&gt;Primeiro acesse o &lt;a href="https://asdf-vm.com/" rel="noopener noreferrer"&gt;site oficial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Clique em &lt;em&gt;'Get Started'&lt;/em&gt;&lt;br&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%2F471m8at7561g5p7vlz3q.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%2F471m8at7561g5p7vlz3q.png" alt="ASDF Homepage"&gt;&lt;/a&gt;&lt;br&gt;
Procure o gerenciador de pacotes para o seu SO, no meu caso como estou usando o Mint vou usar &lt;a href="https://wiki.debian.org/Aptitude" rel="noopener noreferrer"&gt;o Aptitude&lt;/a&gt; (o famoso APT).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;curl git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois disso vamos clonar o repositório do ASDF na nossa maquina.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/asdf-vm/asdf.git ~/.asdf &lt;span class="nt"&gt;--branch&lt;/span&gt; v0.9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ &lt;strong&gt;Esse passo é muito importante&lt;/strong&gt; ⚠️ Vamos combinar a instalação com o Shell, no meu caso como estou usando &lt;a href="https://ohmyz.sh/" rel="noopener noreferrer"&gt;Oh-My-ZSH&lt;/a&gt; vou nessa opção:&lt;br&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%2Fuvqhta22skwepm28rnwu.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%2Fuvqhta22skwepm28rnwu.png" alt="ZSH&amp;amp;Git Option"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você estiver utilizando Oh-My-ZSH basta seguir o passo-a-passo do &lt;a href="https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/asdf" rel="noopener noreferrer"&gt;repositório do plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Que é basicamente adicionar essa linha de código ao arquivo ./zshrc fechar o terminal e abri-lo novamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;git asdf&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso você esteja utilizando o terminal puro vá à opção &lt;em&gt;Bash &amp;amp; Git&lt;/em&gt;.&lt;br&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%2Fqanlqp9l1c000f456esa.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%2Fqanlqp9l1c000f456esa.png" alt="Bash &amp;amp; Git Option"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basta adicionar essas duas linhas de código no arquivo ~/.bashrc fechar o terminal e abri-lo novamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.asdf/asdf.sh
&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.asdf/completions/asdf.bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rode o seguinte comando para testar se deu tudo certo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você devera ver algo parecido com isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;asdf &lt;span class="nt"&gt;--version&lt;/span&gt;
v0.9.0-9ee24a3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Instalando Plugin Erlang na ASDF.
&lt;/h4&gt;

&lt;p&gt;Beleza 👍, com a ASDF instalada chegou a hora de instalar os plugins, vamos começar pelo Erlang.&lt;/p&gt;

&lt;p&gt;Vamos começar rodando o seguinte comando no terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf plugin-add erlang
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso, precisaremos instalar algumas dependências que estão aqui &lt;a href="https://github.com/asdf-vm/asdf-erlang" rel="noopener noreferrer"&gt;nesse repositório&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No meu caso, como estou rodando no Mint vou buscar para Ubuntu 20:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;build-essential autoconf m4 libncurses5-dev libwxgtk3.0-gtk3-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop libxml2-utils libncurses-dev openjdk-11-jdk
&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%2Fbyt9yi662dtruhz6c9en.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%2Fbyt9yi662dtruhz6c9en.png" alt="Ubuntu 20 Erlang Plugin Dependencies"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Instalando Erlang
&lt;/h4&gt;

&lt;p&gt;Com as dependências baixadas vamos procurar as versões do Erlang com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf list-all erlang
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seu terminal deve ter uma lista parecida com essa:&lt;br&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%2Fr4pt98y2q585rle2c0ce.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%2Fr4pt98y2q585rle2c0ce.png" alt="Erlang versions list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos instalar a última versão estável que até o momento desse artigo é a 24.2.1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf &lt;span class="nb"&gt;install &lt;/span&gt;erlang 24.2.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você vera a instalação do Erlang e não se preocupe, ela demora &lt;strong&gt;e realmente parece que seu computador travou, tenha calma!&lt;/strong&gt;&lt;br&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%2F41t4yczfhg2qjw5q5smp.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%2F41t4yczfhg2qjw5q5smp.png" alt="Erlang Install Screen on Terminal"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Iniciando o Erlang
&lt;/h4&gt;

&lt;p&gt;Agora com o Erlang instalado vamos rodar o comando para iniciar globalmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf global erlang 24.2.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E vamos testar abrindo o Shell do Erlang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;erl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você devera ver algo parecido com isso, basta sair dando CTRL + C duas vezes.&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%2F37tckk8va018abh6r61e.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%2F37tckk8va018abh6r61e.png" alt="Erlang Shell"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Instalando Plugin Elixir na ASDF.
&lt;/h4&gt;

&lt;p&gt;Ufa! Cansou? Estamos acabando dá mais um gole no café e roda esse comando no terminal.&lt;/p&gt;

&lt;p&gt;Vamos rodar o seguinte comando no terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf plugin-add elixir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos ver todas as versões do Elixir assim como fizemos com Erlang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf list-all elixir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Instalando Elixir
&lt;/h4&gt;

&lt;p&gt;Como instalamos o Erlang 24 temos que instalar o Elixir OTP para versão 24, a versão mais recente até o momento desse artigo é a 1.13.3-otp-24.&lt;/p&gt;

&lt;p&gt;Vamos rodar o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf &lt;span class="nb"&gt;install &lt;/span&gt;elixir 1.13.3-otp-24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos configurar o Elixir globalmente, assim como fizemos com o Erlang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf global elixir 1.13.3-otp-24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Iniciando o Elixir
&lt;/h4&gt;

&lt;p&gt;Vamos testar se deu tudo certo rodando o IEX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você deverá ver algo parecido com isso:&lt;br&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%2Fel4s1wudkvgpflb8hvla.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%2Fel4s1wudkvgpflb8hvla.png" alt="Elixir Shell Screen"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Hello World!
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/PnUatAYWMEMvmiwsyx/giphy-downsized.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/PnUatAYWMEMvmiwsyx/giphy-downsized.gif" alt="Hello World Keanu Reves"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E para começar do jeito certo, não se esqueça de não cair na maldição do Hello World, rodando o seguinte comando no IEX:&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;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Be Cool with Livebook
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/hOzfvZynn9AK4/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/hOzfvZynn9AK4/giphy.gif" alt="coding gif"&gt;&lt;/a&gt;&lt;br&gt;
O Livebook é parecido com o &lt;a href="https://jupyter.org/" rel="noopener noreferrer"&gt;Jupyter Notebook&lt;/a&gt; do Python, é uma forma de você aplicar, documentar e testar códigos Elixir e salvar seus arquivos MD.&lt;/p&gt;
&lt;h3&gt;
  
  
  Instalando Livebook
&lt;/h3&gt;

&lt;p&gt;A primeira coisa que vamos fazer é ir até o &lt;a href="https://github.com/livebook-dev/livebook" rel="noopener noreferrer"&gt;repositório do Livebook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Como já estamos com o Elixir instalado globalmente vamos rodar o seguinte comando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix escript.install hex livebook &lt;span class="c"&gt;# mix é um comando global do Elixir&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A instalação pode demorar um pouco e pedira algumas confirmações no processo, no final ele perguntara se você quer realmente instalar o livebook, vamos responder Y.&lt;/p&gt;

&lt;p&gt;Feito isso, como estamos rodando o ASDF precisamos usar o RESHIM para reconhecer os novos comandos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asdf reshim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por fim podemos iniciar o Livebook com o seguinte comando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;livebook server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ele rodara na porta 8080 na sua localhost.&lt;br&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%2Fmnppwc34w31d6s68m8zv.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%2Fmnppwc34w31d6s68m8zv.png" alt="Livebook local homepage"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Nesse artigo aprendemos a instalar e configurar a ASDF-VM para rodar o Erlang e o Elixir e instalar o Livebook local.&lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/NpXecaHPKbdVm/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/NpXecaHPKbdVm/giphy.gif" alt="Phoenix GIF"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>beginners</category>
      <category>asdf</category>
      <category>erlang</category>
    </item>
  </channel>
</rss>
