<?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: Martin Sch</title>
    <description>The latest articles on Forem by Martin Sch (@nitramchips).</description>
    <link>https://forem.com/nitramchips</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F331038%2Fe5fbf51e-214b-4c10-822f-b11c2cc92734.jpeg</url>
      <title>Forem: Martin Sch</title>
      <link>https://forem.com/nitramchips</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nitramchips"/>
    <language>en</language>
    <item>
      <title>Guia Passo-a-Passo: Corrigindo Problemas com o uiautomatorviewer</title>
      <dc:creator>Martin Sch</dc:creator>
      <pubDate>Wed, 25 Oct 2023 13:07:50 +0000</pubDate>
      <link>https://forem.com/nitramchips/como-resolver-problemas-com-o-uiautomatorviewer-ao-desenvolver-testes-de-ui-para-android-46da</link>
      <guid>https://forem.com/nitramchips/como-resolver-problemas-com-o-uiautomatorviewer-ao-desenvolver-testes-de-ui-para-android-46da</guid>
      <description>&lt;p&gt;Olá, Devs Android! Se você já tentou automatizar testes de UI para seus aplicativos usando Espresso e UIAutomator, provavelmente já se deparou com a ferramenta &lt;code&gt;uiautomatorviewer&lt;/code&gt;. Esta ferramenta é inestimável para entender e encontrar elementos da tela do app. No entanto, enfrentei um problema onde ela parou de funcionar. Neste artigo, vou guiá-los através dos passos que segui para resolver esse problema.&lt;/p&gt;

&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;Ao tentar executar o &lt;code&gt;uiautomatorviewer&lt;/code&gt;, me deparei com o seguinte erro:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ghDka6Be--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7imqdn7qau7a225gty1t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ghDka6Be--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7imqdn7qau7a225gty1t.png" alt="Mensagem no terminal informando:Error: Could not create the Java Virtual Machine.&amp;lt;br&amp;gt;
Error: A fatal exception has occurred. Program will exit." width="800" height="46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após muita pesquisa e tentativa e erro, descobri que a solução se resume a dois passos principais.&lt;/p&gt;
&lt;h2&gt;
  
  
  Passo 1: Alterar a versão do Java para 1.8
&lt;/h2&gt;

&lt;p&gt;O primeiro passo é garantir que você esteja usando a versão 1.8 do Java. Mas, se você é como eu e trabalha em vários projetos com diferentes versões do Java, alternar entre elas pode ser uma dor de cabeça. Aqui é onde o &lt;code&gt;jenv&lt;/code&gt; se torna útil.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configurando o &lt;code&gt;jenv&lt;/code&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Instale o &lt;code&gt;jenv&lt;/code&gt; usando o Homebrew:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;jenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Adicione o caminho &lt;code&gt;jenv&lt;/code&gt; e inicialize-o em seu shell (estou assumindo que você está usando zsh):
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="$HOME/.jenv/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'eval "$(jenv init -)"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Recarregue o shell para aplicar as alterações:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Instalando e Definindo Java 8 com &lt;code&gt;jenv&lt;/code&gt;:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Instale o Java 8:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;openjdk@8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Verifique as JVMs disponíveis no seu sistema:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/usr/libexec/java_home &lt;span class="nt"&gt;-V&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Isto deverá mostrar as JVMs disponíveis, e você deverá encontrar uma linha semelhante a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.8.0_212, x86_64: "AdoptOpenJDK 8" /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Adicione o Java 8 ao &lt;code&gt;jenv&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ele deve confirmar com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openjdk64-1.8.0.212 adicionado
1.8.0.212 adicionado
1.8 adicionado
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Defina a versão do Java no sistema para Java 8:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jenv global 1.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Verifique a versão do Java:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;p&gt;Agora, isso deve indicar que você está usando o Java 8.&lt;/p&gt;

&lt;p&gt;E pronto! Você instalou e definiu o Java 8 como a versão padrão usando &lt;code&gt;jenv&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passo 2: Baixando o novo arquivo SWT
&lt;/h2&gt;

&lt;p&gt;Após fazer a alteração na versão do Java, me deparei com um segundo erro:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yVubkTa4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hm9i883q67pyx8pmzc8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yVubkTa4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hm9i883q67pyx8pmzc8e.png" alt="Segunda mensagem de erro, dessa vez é um erro de interface do uiautomator" width="629" height="330"&gt;&lt;/a&gt;&lt;br&gt;
O próximo passo é baixar uma versão específica de um arquivo SWT que reside em um diretório específico do Android SDK.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Baixar a versão 4.20 do &lt;code&gt;swt.jar&lt;/code&gt;&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Acesse: &lt;a href="https://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops4/R-4.20-202106111600/swt-4.20-cocoa-macosx-x86_64.zip"&gt;Eclipse Downloads - swt-4.20-cocoa-macosx-x86_64.zip&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extraia o swt.jar do arquivo baixado&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Dentro do arquivo zip existe um swt.jar.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Renomear o arquivo extraído&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Mude o nome do &lt;code&gt;swt.jar&lt;/code&gt; baixado para &lt;code&gt;swt2.jar&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copiar o arquivo renomeado&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Mova o &lt;code&gt;swt2.jar&lt;/code&gt; para o diretório &lt;code&gt;Android/sdk/tools/lib/x86_64/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Importante&lt;/strong&gt;: Não substitua ou delete o arquivo original.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teste&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Inicie o uiautomatorviewer para verificar se a atualização foi bem-sucedida.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dica ao Iniciar o &lt;code&gt;uiautomatorviewer&lt;/code&gt;&lt;/strong&gt;: Ao lançar o &lt;code&gt;uiautomatorviewer&lt;/code&gt;, redimensione a janela.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d_JGSoS4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zihq3i6uf0alarrif5jh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d_JGSoS4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zihq3i6uf0alarrif5jh.png" alt="Image description" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Com essas duas alterações, consegui fazer o &lt;code&gt;uiautomatorviewer&lt;/code&gt; funcionar perfeitamente novamente. Espero que este guia ajude outros desenvolvedores que enfrentam o mesmo problema. Se você tiver dúvidas ou sugestões, sinta-se à vontade para deixar um comentário abaixo!&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/android/android-test/issues/911#issuecomment-849389068"&gt;Issue no Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/gramcha/81dcec3f1e4ce8cffd7f248d3e2a42a7#fromHistory"&gt;Gist de gramcha&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



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

&lt;/div&gt;

</description>
      <category>android</category>
      <category>testing</category>
      <category>kotlin</category>
      <category>ui</category>
    </item>
    <item>
      <title>Garantindo a Usabilidade para Todos: Testando a Acessibilidade em Aplicações Android com MockK</title>
      <dc:creator>Martin Sch</dc:creator>
      <pubDate>Tue, 21 Feb 2023 18:07:43 +0000</pubDate>
      <link>https://forem.com/nitramchips/garantindo-a-usabilidade-para-todos-testando-a-acessibilidade-em-aplicacoes-android-com-mockk-4bfh</link>
      <guid>https://forem.com/nitramchips/garantindo-a-usabilidade-para-todos-testando-a-acessibilidade-em-aplicacoes-android-com-mockk-4bfh</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;A acessibilidade é uma preocupação cada vez mais importante no desenvolvimento de sistemas e aplicativos para celular. Com a crescente conscientização sobre a importância da acessibilidade, é essencial garantir que todos os usuários, independentemente de suas necessidades, possam utilizar os produtos digitais de forma eficaz. Para isso, o Android disponibiliza recursos que o desenvolvedor pode utilizar para tornar as suas aplicações mais acessíveis e inclusivas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objetivo
&lt;/h2&gt;

&lt;p&gt;Mas quando se trata em criar testes automatizados para aplicações Android, geralmente não é uma tarefa fácil. Aqui vai um exemplo simples que baseado no guia de acessibilidade do Firebox Android e adaptado utilizando MockK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fundamentos
&lt;/h2&gt;

&lt;p&gt;As aplicações que ajudam na acessibilidade do Android são denominadas &lt;strong&gt;AccessibilityService&lt;/strong&gt;. Isso significa que, se você quiser desenvolver um leitor de tela como o &lt;strong&gt;Talkback&lt;/strong&gt;, ele precisa ser um &lt;strong&gt;AccessibilityService&lt;/strong&gt;. Para que o &lt;strong&gt;Talkback&lt;/strong&gt; possa ler o conteúdo exibido por um aplicativo de terceiros, ele precisa receber uma árvore hierárquica que seja basicamente uma cópia da estrutura de layout do aplicativo em questão. Em outras palavras, cada nó da árvore representa um botão ou um TextView da aplicação que será lida. Essa árvore é conhecida como &lt;strong&gt;AccessibilityNodeProvider&lt;/strong&gt;, e os nós da árvore são denominados &lt;strong&gt;AccessibilityNodeInfo&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftvgciw31xrpm1cdjszhr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftvgciw31xrpm1cdjszhr.gif" alt="Imagem que representa uma árvore de view do layout que é utilizada pelo leitor de tela. Na animação, cada nó da árvore representa uma view que dispara um evento de acessibilidade, repassa para o nó pai." width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cenário
&lt;/h2&gt;

&lt;p&gt;Para exemplificar, imagine uma situação onde vc tem um modal que aparece para o usuário para exibir uma mensagem. Nós queremos ter algum tipo de interação quando o usuário mudar o foco de um elemento do modal para o outro. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fo10u05bpko6vqhhfho2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fo10u05bpko6vqhhfho2z.png" alt="Exemplo de modal onde existem 3 itens selecionáveis e um botão para fechar o modal." width="503" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AccessibilityDelegate
&lt;/h2&gt;

&lt;p&gt;Com &lt;strong&gt;AccessibilityDelegate&lt;/strong&gt;, é possível utilizar algumas funções para escutar determinados eventos de acessibilidade ou adicionar novas informações para a view para que sejam lidas pelo leitor de tela. O exemplo a seguir, a função &lt;strong&gt;onRequestSendAccessibilityEvent&lt;/strong&gt; é chamada sempre que um evento de acessibilidade é disparado por uma view e com o parâmetro “event” posso verificar que tipo de evento é esse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;vModal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accessibilityDelegate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AccessibilityDelegate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onRequestSendAccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ViewGroup&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
        &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;View&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="nc"&gt;AccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;==&lt;/span&gt;&lt;span class="nc"&gt;TYPE_VIEW_ACCESSIBILITY_FOCUSED&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                    &lt;span class="nf"&gt;fazerAlgumaCoisa&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onRequestSendAccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;child&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código a seguir, um exemplo de como podemos implementar um cenário de teste automatizado para o onRequestSendAccessibilityEvent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Mockar uma view pai&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;root&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mockk&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ViewParent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

&lt;span class="c1"&gt;//Inserir a view de teste dentro desse pai mockado&lt;/span&gt;
&lt;span class="nc"&gt;Shadows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shadowOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vModal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setMyParent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;//Precisa garantir que haja algum retorno para esse método de acessibilidade&lt;/span&gt;
&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestSendAccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;())}&lt;/span&gt;&lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;//Cria um shadow para simular a acessibilidade ativa&lt;/span&gt;
&lt;span class="nc"&gt;Shadows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shadowOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BaseObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;applicationContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSystemService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ACCESSIBILITY_SERVICE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;AccessibilityManager&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;//Pega um elemento do modal&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;closeButton&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getCloseButton&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;//Dispara um evento de foco de acessibilidade&lt;/span&gt;
&lt;span class="n"&gt;closeButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendAccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TYPE_VIEW_ACCESSIBILITY_FOCUSED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;//Cria um slot para capturar argumento&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;accessibilityEvent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

&lt;span class="c1"&gt;//Captura o argumento passado no método de acessibilidade&lt;/span&gt;
&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestSendAccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;

&lt;span class="c1"&gt;//Verifica se o argumento passado é o que era esperado&lt;/span&gt;
&lt;span class="nf"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AccessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TYPE_VIEW_ACCESSIBILITY_FOCUSED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accessibilityEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;captured&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este trecho de código apresenta um exemplo de como realizar um teste automatizado com foco em acessibilidade.&lt;/p&gt;

&lt;p&gt;Inicialmente, é feita uma simulação de uma view pai, utilizando o framework &lt;strong&gt;MockK&lt;/strong&gt;. Em seguida, a view de teste é inserida nessa view pai mockada.&lt;/p&gt;

&lt;p&gt;Para garantir que o teste está efetivamente verificando a acessibilidade da view, é necessário que haja algum retorno para o método de acessibilidade. Assim, utilizando o framework &lt;strong&gt;MockK&lt;/strong&gt; novamente, é definido que o retorno do método &lt;strong&gt;&lt;code&gt;requestSendAccessibilityEvent&lt;/code&gt;&lt;/strong&gt; seja falso.&lt;/p&gt;

&lt;p&gt;Em seguida, é criado um "&lt;strong&gt;shadow&lt;/strong&gt;" (simulação) para a acessibilidade ativa, utilizando o framework &lt;strong&gt;Robolectric&lt;/strong&gt;. Então, é capturado um elemento do modal (provavelmente algum botão ou elemento que possa ser acessado) e é disparado um evento de foco de acessibilidade.&lt;/p&gt;

&lt;p&gt;Com o framework &lt;strong&gt;MockK&lt;/strong&gt;, é criado um slot para capturar o argumento passado no método de acessibilidade, que é verificado posteriormente para verificar se o argumento passado é o esperado. Por fim, é utilizada a função &lt;strong&gt;&lt;code&gt;assertEquals&lt;/code&gt;&lt;/strong&gt; para verificar se o tipo do evento de acessibilidade capturado corresponde ao tipo de evento esperado.&lt;/p&gt;

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

&lt;p&gt;Com isso, esse trecho de código apresenta uma forma de simular e testar a acessibilidade de uma view em um ambiente controlado, a fim de garantir uma aplicação tenha um comportamento consistente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fontes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Guia de acessibilidade do Firebox Android
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/mozilla-mobile/shared-docs/blob/main/android/accessibility_guide.md" rel="noopener noreferrer"&gt;shared-docs/accessibility_guide.md at main · mozilla-mobile/shared-docs&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Para adaptar o exemplo de Moquito para MockK
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://notwoods.github.io/mockk-guidebook/docs/mockito-migrate/argument-captor/" rel="noopener noreferrer"&gt;&lt;code&gt;ArgumentCaptor&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>googlecloud</category>
      <category>ai</category>
      <category>promptengineering</category>
    </item>
    <item>
      <title>Como o ExoPlayer garante video streaming fluida e de alta performance</title>
      <dc:creator>Martin Sch</dc:creator>
      <pubDate>Mon, 16 Jan 2023 02:19:52 +0000</pubDate>
      <link>https://forem.com/nitramchips/como-o-exoplayer-lida-com-arquivos-de-video-17b</link>
      <guid>https://forem.com/nitramchips/como-o-exoplayer-lida-com-arquivos-de-video-17b</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2F55hh8i9agb8lnen3nz5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F55hh8i9agb8lnen3nz5g.png" alt="Image description" width="601" height="943"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O ExoPlayer é uma biblioteca de reprodução de mídia open-source desenvolvida pela Google. Ele é utilizado em aplicativos de mídia em dispositivos Android e permite aos desenvolvedores criar aplicativos de mídia personalizados, com recursos avançados e alta performance. Neste artigo, vamos explorar como o ExoPlayer lida com a reprodução de arquivos de vídeo, desde o momento em que um "chunk" de dados é recebido até o momento em que ele é renderizado na tela.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fonte de Dados
&lt;/h2&gt;

&lt;p&gt;O ciclo de reprodução de um arquivo de vídeo no ExoPlayer começa com a obtenção de dados, que é gerenciada pelo componente "fonte de mídia". Esse componente é responsável por lidar com a obtenção de dados, seja eles através de uma rede ou de um arquivo local. &lt;/p&gt;

&lt;h2&gt;
  
  
  Buffer de Input
&lt;/h2&gt;

&lt;p&gt;Os dados são então passados para o componente "buffer", que armazena esses dados temporariamente, garantindo que haja sempre dados suficientes para a reprodução contínua.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decodificador
&lt;/h2&gt;

&lt;p&gt;Em seguida, os dados do buffer são passados para o componente "decodificador", que é responsável por decodificar o chunk em formato de áudio ou vídeo. O decodificador também pode aplicar quaisquer transformações necessárias, como a mudança de taxa de quadros ou a aplicação de efeitos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Buffer de Output
&lt;/h2&gt;

&lt;p&gt;Após a decodificação, os dados são passados para o segundo buffer, que armazena esses dados decodificados temporariamente antes de serem passados para o componente de renderização. Isso garante que haja sempre dados suficientes para a reprodução contínua, mesmo em caso de variações na velocidade de rede ou outros problemas de transmissão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Renderizador
&lt;/h2&gt;

&lt;p&gt;Após a decodificação, os dados são enviados para o componente "renderizador", que é responsável por exibir os dados na tela. No caso do vídeo, isso pode incluir ajustes de tamanho, posição e transparência. O renderizador também pode aplicar efeitos adicionais, como o aumento de brilho ou contraste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Controle
&lt;/h2&gt;

&lt;p&gt;Por fim, o componente "controle" é responsável por garantir que o fluxo de dados esteja sincronizado e que a reprodução esteja ocorrendo na velocidade correta. Isso pode incluir ajustes de velocidade, pausa e retomada.&lt;/p&gt;

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

&lt;p&gt;Em resumo, o ExoPlayer é uma poderosa biblioteca de reprodução de mídia que permite aos desenvolvedores criar aplicativos de mídia personalizados com recursos avançados e alta performance. Ele é composto por 5 componentes principais: Fonte de mídia, Buffer de Entreda, Decodificador, Buffer de Saída, Decodificador, Renderizador e Controle, cada um deles com suas respectivas funções, que são necessárias para garantir a reprodução correta de arquivos de vídeo. Ao entender como esses componentes trabalham juntos, os desenvolvedores podem analisar o tempo de latência ou a perda de frames entre esses 5 componentes, melhorando a performance do serviço de streaming e tornando a experiência do usuário mas fluída e com mais qualidade.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>developer</category>
      <category>learning</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>O Cérebro do Programador</title>
      <dc:creator>Martin Sch</dc:creator>
      <pubDate>Wed, 22 Sep 2021 12:45:42 +0000</pubDate>
      <link>https://forem.com/nitramchips/o-cerebro-do-programador-2jne</link>
      <guid>https://forem.com/nitramchips/o-cerebro-do-programador-2jne</guid>
      <description>&lt;p&gt;Em setembro deste ano foi lançado o livro &lt;br&gt;
&lt;a href="https://www.amazon.com/Programmers-Brain-every-programmer-cognition/dp/1617298670" rel="noopener noreferrer"&gt;"&lt;strong&gt;&lt;em&gt;The Programmer's Brain: What every programmer needs to know about cognition&lt;/em&gt;&lt;/strong&gt;"&lt;/a&gt; da cientista &lt;a href="https://en.wikipedia.org/wiki/Felienne_Hermans" rel="noopener noreferrer"&gt;&lt;strong&gt;Felienne Hermans&lt;/strong&gt;&lt;/a&gt; onde ela ajuda programadores a entender como o cérebro funciona e como ele pode ser utilizado de forma mais efetiva para ler e escrever código. &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%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F6%2F61%2FFelienne.jpg%2F440px-Felienne.jpg" 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%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F6%2F61%2FFelienne.jpg%2F440px-Felienne.jpg" alt="Felienne Hermans"&gt;&lt;/a&gt;Felienne Hermans&lt;/p&gt;
&lt;h2&gt;
  
  
  Conteúdo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Processos Cognitivos&lt;/li&gt;
&lt;li&gt;Programador Iniciante e o Programador Expert&lt;/li&gt;
&lt;li&gt;Escrevendo cometários no código&lt;/li&gt;
&lt;li&gt;Beacons&lt;/li&gt;
&lt;li&gt;Memorizar a sintaxe&lt;/li&gt;
&lt;li&gt;Melhorando a memória&lt;/li&gt;
&lt;li&gt;Conclusão&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Processos Cognitivos &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Entender o código alheio pode ser umas das tarefas mais difíceis e de maior peso na lista de tarefas de um programador e existem alguns fatores que dificultam o entendimento. &lt;/p&gt;

&lt;p&gt;Como o código foi escrito e como o projeto foi arquitetado, são fatores que influenciam, mas de uma forma geral. A autora classifica em 3 processos cognitivos:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conhecimento &lt;/li&gt;
&lt;li&gt;Informação&lt;/li&gt;
&lt;li&gt;Poder de processamento&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tente imaginar a parte de conhecimento como tudo o que você já memorizou até hoje sobre sintaxe, estrutura de dados, Design Patterns e outros. É como se ele fosse o seu HD.&lt;/p&gt;

&lt;p&gt;Já o processo cognitivo da informação seria a sua memória RAM, ou seja, são informações que são guardadas a curto prazo, como valores das variáveis que estão sendo utilizadas, o contexto daquele código e o histórico de alterações recentes no bloco de código analisado.&lt;/p&gt;

&lt;p&gt;Se o processo cognitivo do conhecimento é o HD e o da informação é a sua memória RAM, então o poder de processamento é a CPU. É esse componente cognitivo que vai utilizar a memória de longo prazo e a de curto prazo para debugar o código mentalmente.&lt;/p&gt;

&lt;p&gt;Um ponto importante é que quando a memória a longo prazo não tem informação suficiente sobre o código analisado, a memória de curto prazo precisa ser utilizada com mais frequência, porém tem uma capacidade de armazenamento menor. &lt;/p&gt;

&lt;p&gt;Por não ter muita "informação armazenada" na memória de longo prazo, o programador acaba levando mais tempo para entender um código.&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%2Fw0687ttkfo3kfuwls25j.jpg" 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%2Fw0687ttkfo3kfuwls25j.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Programador Iniciante e o Programador Expert &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Um experimento feito pelo matemático Adrian de Groot que estava interessado em entender por qual motivo algumas pessoas se tornam ótimos jogadores de xadrez enquanto outras são jogadores medianos a vida inteira.&lt;/p&gt;

&lt;p&gt;No experimento, uma imagem de um tabuleiro com uma configuração específica de peças era mostrada para jogadores de xadrez iniciantes e experientes por um curto espaço de tempo. Os participantes tinham que tentar memorizar aquela configuração de peças e depois tenta reproduzir o mais fiel possível.&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%2Ffw64uojjh7k3jbp6xn2a.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffw64uojjh7k3jbp6xn2a.jpeg" alt="Abertura Ruy López"&gt;&lt;/a&gt;Abertura Ruy López&lt;/p&gt;

&lt;p&gt;Como você pode imaginar, os jogadores mais experientes foram os que conseguiram reproduzir com mais facilidade. Mas por qual motivo isso acontece? Eles tem uma memória mais afiada do que os iniciantes? Não exatamente. Com muito treino e experiência, um jogador é capaz de identificar padrões de jogada, prevendo o que o adversário provavelmente tentará fazer e como se livrar daquela jogada.&lt;/p&gt;

&lt;p&gt;Enquanto um iniciante apenas vê uma sequência de peças em um tabuleiro, o jogador experiente vê aquela configuração formando uma abertura Ruy López, por exemplo. Isso facilita bastante na memorização, pois não é necessário memorizar peça por peça. &lt;/p&gt;

&lt;p&gt;Quando o matemático começou a mostrar configurações de tabuleiro com peças em posições totalmente aleatórias, o jogadores experientes tiveram o mesmo desempenho que os iniciantes!&lt;/p&gt;

&lt;p&gt;A mesma coisa acontece quando lemos um código. Um programador experiente vai reconhecer algumas operações, estruturas de dados ou padrões de projeto que já são familiares por já fazerem parte da memória de longo prazo dele. Mas se o código estiver mal escrito, um expert terá a mesma dificuldade que um programador iniciante.&lt;/p&gt;

&lt;p&gt;Uma outra forma de entender esse processo é através da própria linguagem humana. A não ser que você tenha algum conhecimento em Marati, nada do que está escrito abaixo é familiar. Nem mesmo os símbolos utilizados são reconhecíveis:&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%2F7jrco8ewle7jfx9q4i9d.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%2F7jrco8ewle7jfx9q4i9d.png" alt="Alt Text"&gt;&lt;/a&gt;??? no idioma Marati&lt;/p&gt;

&lt;p&gt;Nesse outro exemplo, você pode não saber Polonês, mas pelo menos já pode reconhecer os signos utilizados, apenas não consegue saber o que eles estão formando:&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%2Fez3jml75h5hfck88ig9s.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%2Fez3jml75h5hfck88ig9s.png" alt="Alt Text"&gt;&lt;/a&gt;??? no idioma Polonês&lt;/p&gt;

&lt;p&gt;Aaaah agora sim!! Neste exemplo existem signos de um alfabeto que você conhece e eles formam um padrão que tem um significado pra você:&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%2Fo126ww48hi1z9d44bvh7.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%2Fo126ww48hi1z9d44bvh7.png" alt="Alt Text"&gt;&lt;/a&gt;Cachorro no idioma Português&lt;/p&gt;
&lt;h2&gt;
  
  
  Escrevendo comentários no código &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Esse pode ser um assunto um pouco polêmico, pois existem pessoas que acreditam que não é uma boa prática. Códigos que possuem comentário podem levar mais tempo para serem lidos, mas isso não é necessariamente um problema.&lt;/p&gt;

&lt;p&gt;Ter o código comentado, pode ser muito útil para programadores que acabaram de entrar no time e precisam entender o codebase.&lt;/p&gt;

&lt;p&gt;Segundo o trabalho de Martha Elizabeth Crosby da Universidade do Hawaii, programadores iniciantes focam em ler comentários com mais frequências do que os experientes. É claro que é importante não exagerar na detalhamento dos comentários, o ideal é coloca uma descrição mais alto nível do que comentar linha por linha, caso contrário, pode mais atrapalhar do que ajudar.&lt;br&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%2Ff3sutfhfbhpnvolvk2b7.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%2Ff3sutfhfbhpnvolvk2b7.png" alt="Alt Text"&gt;&lt;/a&gt;Exemplo de código com muitos cometários de baixo nível, explicando linha por linha do que está sendo feito&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%2Fcozu922l3o3i14ug2oji.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%2Fcozu922l3o3i14ug2oji.png" alt="Alt Text"&gt;&lt;/a&gt;Exemplo de código explicando em mais alto nível qual é o objetivo do código&lt;/p&gt;
&lt;h2&gt;
  
  
  Beacons &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Um outro elemento importante que o livro explica, é a idéia de beacons. São pequenas partes do código que pela própria nomenclatura do código, já dão pistas do que o algoritmo faz. Colocar palavras como root ou graph, já passam para o leitor, qual é a estrutura de dados utilizado. Por isso é importante ter cuidado ao definir o nome de funções, classes ou variáveis. Programadores experientes utilizam beacons com muita frequência.&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%2Fgelyodc2oefh1ze3z9r3.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgelyodc2oefh1ze3z9r3.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Beacons são conhecidos como luzes de navegação



&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%2Fyjwpx05qsix0u9ks4fps.jpg" 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%2Fyjwpx05qsix0u9ks4fps.jpg" alt="Alt Text"&gt;&lt;/a&gt;Exemplo de beacon utilizado para indicar para o leitor do código, que está sendo utilizado um tipo abstrato de dados chamado grafo.(Código tirado de: &lt;a href="https://github.com/ronami/minipack/blob/master/src/minipack.js" rel="noopener noreferrer"&gt;https://github.com/ronami/minipack/blob/master/src/minipack.js&lt;/a&gt;)&lt;/p&gt;
&lt;h2&gt;
  
  
  Memorizar a sintaxe &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Do mais iniciante ao expert, é muito comum dar aquela pesquisada no google para lembrar como faz a validação de um campo de e-mail utilizando expressão regular. Todo mundo dá aquela consultada no Stack Overflow como escrever uma função específica. &lt;/p&gt;

&lt;p&gt;O problema que esse hábito pode fazer a diferença na produtividade, pois o desenvolvedor precisa interromper a sua linha de raciocínio para pesquisar nas páginas de discussão e filtrar o que não é importante, para assim finalmente achar o que precisa e depois voltar para o contexto que estava trabalhando. &lt;/p&gt;

&lt;p&gt;Uma estudo do professor Chris Parnin da Universidade da Carolina do Sul, mostra que todas as vezes que o desenvolvedor é interrompido, apenas em 10% das vezes ele consegue retomar o raciocínio em menos de 1 minuto. &lt;/p&gt;

&lt;p&gt;Com a memória mais afiada, suas consultas ao Google diminuem e assim o número de interrupções também diminuem.&lt;/p&gt;
&lt;h2&gt;
  
  
  Melhorando a memória &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;O livro recomenda o utilização de Flashcards para a memorização. Basicamente a técnica consiste em criar vários cards onde na parte da frente do card você tem a descrição do que o código faz e no verso, o código. &lt;/p&gt;

&lt;p&gt;A idéia e sempre pegar um o card aleatório e após ler a descrição, tentar lembrar mentalmente como é o código. Existem vários aplicativos para criar o seu baralho, mas se quiser, pode criar a versão analógica no papel mesmo. 😄&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%2F5qrigqkliyy0eg192m4m.jpg" 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%2F5qrigqkliyy0eg192m4m.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É necessário fazer esse processo várias vezes por conta da curva de esquecimento citada pelo estudo feito por Ebbinghaus.&lt;/p&gt;

&lt;p&gt;Existem diversos artigos e vídeos que explicam sobre a Curva de Esquecimento de Ebbinghaus:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/twyUUQbmLQI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

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

&lt;p&gt;Esses foram só alguns dos pontos importantes do livro que ajudam a entender e a melhorar a forma que o cérebro lê e escreve código e o que pode ser feito para melhorar essas atividades.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>performance</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Criando mapas utilizando Leaflet via CDN em um projeto React</title>
      <dc:creator>Martin Sch</dc:creator>
      <pubDate>Wed, 15 Sep 2021 16:09:15 +0000</pubDate>
      <link>https://forem.com/nitramchips/criando-mapas-utilizando-leaflet-via-cdn-em-um-projeto-react-300h</link>
      <guid>https://forem.com/nitramchips/criando-mapas-utilizando-leaflet-via-cdn-em-um-projeto-react-300h</guid>
      <description>&lt;p&gt;Estava trabalhando em um projeto onde teria que ser exibido um mapa com pontos agrupados (marker clusters). O Leaflet é com certeza uma ótima solução para isso. Existem duas opções para adicionar o Leaflet, por npm (&lt;a rel="noreferrer noopener" href="https://react-leaflet.js.org/"&gt;react-leaft&lt;/a&gt;) ou via &lt;a rel="noreferrer noopener" href="https://pt.wikipedia.org/wiki/Rede_de_fornecimento_de_conte%C3%BAdo"&gt;CDN&lt;/a&gt;. A segunda opção é mais vantajosa já que o mapa só seria apresentado em uma página e adicionar-lo em npm faz o projeto aumentar de tamanho e o build ficar mais lento.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CHMvNZkQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/Leaflet/Leaflet.markercluster/raw/master/example/map.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CHMvNZkQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/Leaflet/Leaflet.markercluster/raw/master/example/map.png" alt="cluster map example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;strong&gt;Como importar o leaflet?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Segundo a &lt;a rel="noreferrer noopener" href="https://leafletjs.com/examples/quick-start/"&gt;documentação&lt;/a&gt;, você tem que importar o CSS e o JavaScript, exatamente nessa ordem:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mixsiL6L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://inventordigital.files.wordpress.com/2021/08/image-4.png%3Fw%3D1024" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mixsiL6L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://inventordigital.files.wordpress.com/2021/08/image-4.png%3Fw%3D1024" alt="Imagem mostrando um treco da documentação."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na hora que for carregar o componente, é possível fazer a mesma coisa "injetando"      o &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; e &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; utilizando:&lt;/p&gt;



&lt;pre&gt;&lt;code&gt;// função para adicionar a tag link
const insertLinkCSS = (cssUrl, key = '', id) =&amp;gt; {
      const link = document.createElement('link')
      link.rel = 'stylesheet'
      link.href = cssUrl
      if (id.length &amp;gt; 0) {
        link.id = id
      }
      if (key.length &amp;gt; 0) {
        link.integrity = key
      }
      link.crossOrigin = ''
      document.body.appendChild(link)
}

//função para adicionar a tag script
const insertScriptSrc = (scriptUrl, key = '', id) =&amp;gt; {
      const script = document.createElement('script')
      script.type = 'text/javascript'
      script.src = scriptUrl
      if (id.length &amp;gt; 0) {
        script.id = id
      }
      if (key.length &amp;gt; 0) {
        script.integrity = key
      }
      script.async = false
      script.crossOrigin = ''
      document.body.appendChild(script)
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Em seguida são chamadas as funções passando o import no inicio do componente:&lt;br&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;useEffect(() =&amp;gt; {
   insertLinkCSS(
      'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css',
      'sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==',
    )
    insertScriptSrc(
      'https://unpkg.com/leaflet@1.7.1/dist/leaflet.js',
      'sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==',
    )
  })

  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;header className="App-header"&amp;gt;
        &amp;lt;img src={logo} className="App-logo" alt="logo" /&amp;gt;
        &amp;lt;div id='mapid'&amp;gt; &amp;lt;/div&amp;gt;
      &amp;lt;/header&amp;gt;
    &amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Dessa forma as tags de import aparecem no html da página.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hatYD7Bq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://inventordigital.files.wordpress.com/2021/08/image-1.png%3Fw%3D1024" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hatYD7Bq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://inventordigital.files.wordpress.com/2021/08/image-1.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que estou adicionando um id para cada elemento e eu já vou mostrar o motivo disso.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Esperando os imports serem carregados&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Antes começar a utilizar, é necessário garantir que os elementos foram carregados antes de começar a configurar o mapa. Uma forma de resolver isso é criar uma forma de verificar quando o &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;  e o &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; aparecem no &lt;code&gt;document&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;//Define todos os ids que precisam ser verificados
const elementsIdConst = {
    LEAFTLET_CSS: 'leafletcss',
    LEAFTLET_JS: 'leafletjs',
    MAP_ID: 'mapid',
  }

function waitLoadElementsById(elementsId, callBack) {
    const formatedArray = elementsId.map(item =&amp;gt; `#${item}`)

    //cria um setInterval para verificar a cada 100 milissegundos
    var elementsExists = setInterval(function () {
      if (document.querySelectorAll(formatedArray).length === elementsId.length) {
        try {
          callBack()
        } catch (e) {
          throw e
        }

        //Se achou todos os elementos, para o setInterval e o setTimeout
        clearInterval(elementsExists)
        clearTimeout(timeout)
      }
    }, 100)

    //timeout para para de rodar o setInterval depois de um tempo
    const timeout = setTimeout(() =&amp;gt; {
      clearInterval(elementsExists)
    },5000)
  }


useEffect(() =&amp;gt; {

   //chama o import do CSS com o id
   insertLinkCSS(
      'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css',
      '',
      elementsIdConst.LEAFTLET_CSS,
    )

   //chama o import do script com o id
    insertScriptSrc(
      'https://unpkg.com/leaflet@1.7.1/dist/leaflet.js',
      '',
      elementsIdConst.LEAFTLET_JS,
    )

    //Com os elementos carregados, chama a função para iniciar o mapa
    waitLoadElementsById(Object.values(elementsIdConst), () =&amp;gt; renderMap())
  })&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Código completo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para ter mais detalhes sobre a implementação você pode ver o código com &lt;a href="https://github.com/NitramTasu/react-map"&gt;repositório&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Utilizando um lib JavaScript via CDN pode ser um pouco mais "complicado" mas pode trazer muitas vantagens para um projeto que pretende escalar, pois você tem muito mais controle dos recursos utilizados e garante que eles só serão carregados na sua aplicação nos momentos certos. Se a sua aplicação é mais simples, então vale a pena adicionar via npm uma lib como "&lt;a rel="noreferrer noopener" href="https://react-leaflet.js.org/"&gt;react-leaft&lt;/a&gt;" que utiliza leaftlet como componentes react. &lt;/p&gt;

</description>
      <category>webpack</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Entendendo o Webpack</title>
      <dc:creator>Martin Sch</dc:creator>
      <pubDate>Wed, 08 Sep 2021 14:55:59 +0000</pubDate>
      <link>https://forem.com/nitramchips/entendendo-o-webpack-107n</link>
      <guid>https://forem.com/nitramchips/entendendo-o-webpack-107n</guid>
      <description>&lt;p&gt;Quando comecei a pegar algumas tarefas de desenvolvimento para React, não entendia o que era o Webpack e qual era a sua utilidade. Após estudar sobre o assunto, achei que seria interessante fazer um artigo para compartilhar uma síntese do que aprendi.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o Webpack?
&lt;/h2&gt;

&lt;p&gt;A definição mais básica: Um empacotador de módulos Javascript de código aberto&lt;/p&gt;
&lt;div class="ltag__wikipedia--container"&gt;
  &lt;div class="ltag__wikipedia--header"&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%2Fassets%2Fwikipedia-logo-0a3e76624c7b1c3ccdeb9493ea4add6ef5bd82d7e88d102d5ddfd7c981efa2e7.svg" class="ltag__wikipedia--logo" alt="Wikipedia Logo"&gt;
    &lt;a href="https://en.wikipedia.org/wiki/Webpack" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt;
  &lt;/div&gt;
  &lt;div class="ltag__wikipedia--extract"&gt;&lt;p&gt;&lt;b&gt;Webpack&lt;/b&gt; is a free and open-source module bundler for JavaScript. It is made primarily for JavaScript, but it can transform front-end assets such as HTML, CSS, and images if the corresponding loaders are included. Webpack takes modules with dependencies and generates static assets representing those modules.&lt;/p&gt;&lt;/div&gt;
  &lt;div class="ltag__wikipedia--btn--container"&gt;
      &lt;a class="ltag__wikipedia--btn" href="https://en.wikipedia.org/wiki/Webpack" rel="noopener noreferrer"&gt;View on Wikipedia&lt;/a&gt;&amp;gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Mas o que é um módulo?
&lt;/h2&gt;

&lt;p&gt;Nos primórdios, o JS era utilizado para criar interações simples nas páginas web. Com a chegada do Node, foi possível criar aplicações inteiras em JS. Mas com ele também surgiu a necessidade de ter uma forma de quebrar o código em várias partes. Toda vez que se é utilizado o &lt;strong&gt;export&lt;/strong&gt; em um bloco de código, significa que está deixando aquele módulo disponível para ser utilizado com &lt;strong&gt;import&lt;/strong&gt;. &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Modules" rel="noopener noreferrer"&gt;Sobre módulos&lt;/a&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%2F4ii41pzzpv1saegm16tz.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%2F4ii41pzzpv1saegm16tz.png" alt="Captura de Tela 2021-09-07 às 21.07.02"&gt;&lt;/a&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%2F4bpqyyihr65lvnv5vuzp.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%2F4bpqyyihr65lvnv5vuzp.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Como funciona o Webpack?
&lt;/h2&gt;

&lt;p&gt;No arquivo de configurações dele, você vai informar qual é o arquivo onde começa a executar o seu projeto (&lt;strong&gt;Entry&lt;/strong&gt;) e em qual diretório você quer que ele salve o arquivo resultante (&lt;strong&gt;Output&lt;/strong&gt;). A partir desse arquivo inicial, empacotador irá mapear todos os módulos que serão utilizados, criando assim, um grafo de dependências.&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%2Ftj1q3bzkmtvei66uh10v.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%2Ftj1q3bzkmtvei66uh10v.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Como ele consegue navegar pela estrutura do código?
&lt;/h2&gt;

&lt;p&gt;Existe um recurso chamado AST (Abstract Structure Tree), uma representação estrutural em árvore do código, onde cada nó representa um elemento do script. Com ele é possível manipular os elementos do script adicionando e removendo os nós.&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%2F64iypkahze7sy5oa5l30.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%2F64iypkahze7sy5oa5l30.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Qual é a vantagem de se utilizar o Webpack?
&lt;/h2&gt;

&lt;p&gt;Imagina que você criou um aplicação de vacinação. Nela o usuário informa a data da ultima vacinação, o tipo de vacina que tomou e qual foi a dose. Nesse exemplo, cada campo é um componente separado que é injetado no html da página. Quando a tela é carregada, o index.html chama o app.js que por sua vez importa os componentes que serão exibidos. &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%2Fc4i8o93igj3k8ev3xlc2.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%2Fc4i8o93igj3k8ev3xlc2.png"&gt;&lt;/a&gt;&lt;br&gt;Um projeto simples utilizando lite-server para demonstrar quando os módulos são carregados
  &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%2Fpo0gowufegmqi4numz1h.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%2Fpo0gowufegmqi4numz1h.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para cada componente, o client precisa fazer um requisição pedindo o módulo para o servidor e isso não é nada bom para a latência e largura da banda.&lt;/p&gt;

&lt;p&gt;Com o Webpack, todas essas dependências estão em um único arquivo e tudo o que a aplicação precisa naquele momento já está pré-carregado.&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%2Fynaxqshmqih71agu0pmw.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%2Fynaxqshmqih71agu0pmw.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  É possível gerar mais de um bundler?
&lt;/h2&gt;

&lt;p&gt;Sim. Ter sempre um único bundler nem sempre é vantajoso pois dependendo do tamanho da aplicação, o arquivo final pode ficar muito grande e o carregamento ficará muito lento. Se  você tem módulos que só serão utilizados após o usuário executar uma ação, então é possível utilizar o lazy loading para que o Webpack crie um bundler separado para esses módulos.&lt;/p&gt;

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

&lt;p&gt;O objetivo desse post era dar uma explicação simplificada de como funciona o Webpack e a vantagem de utiliza-lo. React, Angular e Vuejs já utilizam por baixo dos panos, então a princípio você não precisa se preocupar. O conceito de AST é bem interessante e tem várias aplicações como automatizar a alteração do código. O compilador Babel.js utiliza o AST para transformar o código escrito para que seja compatível com navegadores que utilizam especificações mais antigas do JavaScript.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webpack</category>
      <category>javascript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
