<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Kris Lagerström - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Aprenda a codificar - de graça. Tutoriais de programação em Python, JavaScript, Linux e muito mais. ]]>
        </description>
        <link>https://www.freecodecamp.org/portuguese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Kris Lagerström - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/portuguese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 28 May 2026 16:39:25 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/portuguese/news/author/krislagerstrom/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Uma introdução aos testes unitários com o Jasmine ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Ahmed Bouchefra O Jasmine é a biblioteca do JS mais popular para testes unitários de aplicações para a web. Neste tutorial, projetado para iniciantes, apresentaremos um guia rápido e completo para testes com o Jasmine. Você será apresentado ao Jasmine, um framework de testes popular orientado a comportamentos ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/uma-introducao-aos-testes-unitarios-com-o-jasmine/</link>
                <guid isPermaLink="false">66a30c2f28ded7044a1fe1f2</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Sun, 22 Sep 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/5f9ca766740569d1a4ca76f2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/jasmine-unit-testing-tutorial-4e757c2cbf42/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">An Introduction to Jasmine Unit Testing</a>
      </p><p>Escrito por: Ahmed Bouchefra</p><p>O Jasmine é a biblioteca do JS mais popular para testes unitários de aplicações para a web. Neste tutorial, projetado para iniciantes, apresentaremos um guia rápido e completo para testes com o Jasmine.</p><p>Você será apresentado ao Jasmine, um <em>framework</em> de testes popular orientado a comportamentos para o JavaScript. Também veremos um exemplo prático simples de como escrever testes unitários com o Jasmine, que pode ajudá-lo a verificar facilmente se há <em>bugs</em> em seu código.</p><p>Em resumo, veremos como escrever suítes de teste, especificações e expectativas, além de como aplicar <em>matchers</em> (comparadores) integrados do Jasmine ou criar seus próprios <em>matchers</em> personalizados.</p><p>Também veremos como você pode agrupar suítes para organizar seus testes para bases de código mais complexas.</p><h3 id="apresentando-o-jasmine">Apresentando o Jasmine</h3><p>O <a href="http://jasmine.github.io/">Jasmine</a> é um <em>framework</em> de desenvolvimento orientado a comportamentos (em inglês, BDD ou <em>behavior-driven development)</em>. Com ele, você escreve testes antes de escrever o código real. Ele é muito popular para testes unitários de aplicações em JavaScript. Ele fornece utilitários que podem ser usados para executar testes automatizados para código síncrono e assíncrono.</p><p>O Jasmine tem muitos recursos:</p><ul><li>Ele é rápido, tem baixa sobrecarga e nenhuma dependência externa.</li><li>É uma biblioteca completa e oferece tudo o que você precisa para testar seu código.</li><li>Está disponível para Node e para o navegador.</li><li>Pode ser usado com outras linguagens, como Python e Ruby.</li><li>Não requer o DOM.</li><li>Fornece uma sintaxe limpa e fácil de entender e também uma API rica e direta.</li><li>Podemos usar linguagem natural para descrever os testes e os resultados esperados.</li></ul><p>O Jasmine é uma ferramenta de código aberto disponível sob a licença permissiva do MIT. No momento da redação deste artigo, a versão principal mais recente é a <em>Jasmine 3.0</em>, que fornece novos recursos e algumas mudanças significativas. A versão <em>2.99</em> do Jasmine fornecerá diferentes avisos de descontinuação para suítes que têm comportamento diferente na versão <em>3.0</em>, o que facilitará a migração dos desenvolvedores para a nova versão.</p><p>Você pode ler sobre os novos recursos e mudanças significativas <a href="https://github.com/jasmine/jasmine/blob/v3.0.0/release_notes/3.0.md">neste </a><a href="https://github.com/jasmine/jasmine/blob/v3.0.0/release_notes/3.0.md">documento</a>.</p><h3 id="usando-o-jasmine">Usando o Jasmine</h3><p>Você pode usar o Jasmine de várias maneiras diferentes:</p><ul><li>da maneira antiga, incluindo o núcleo do Jasmine e seus arquivos de teste usando uma tag <code>&lt;script&gt;</code>,</li><li>como uma ferramenta da CLI usando o Node.js,</li><li>como uma biblioteca no Node.js,</li><li>como parte de um sistema de <em>build</em>, como Gulp.js ou Grunt.js via <a href="https://github.com/gruntjs/grunt-contrib-jasmine">grunt-contrib-jasmine</a> e <a href="https://github.com/jasmine/gulp-jasmine-browser">gulp-jasmine-browser</a></li></ul><p>Você também pode usar o Jasmine para testar seu código em Python com <a href="https://github.com/jasmine/jasmine-py">jasmine-py</a>, que pode ser instalado a partir do PyPI usando o comando <code>pip install jasmine</code>. Este pacote contém um servidor para a web que serve e executa uma suíte do Jasmine para seu projeto e um script da CLI para executar testes e integrações contínuas.</p><p>O Jasmine também está disponível para projetos Ruby via <a href="https://github.com/jasmine/jasmine-gem">jasmine-gem</a>, que pode ser instalado adicionando <code>gem 'jasmine'</code> ao seu Gemfile e executando <code>bundle install</code>. Ele inclui um servidor para servir e executar testes, um script da CLI e também geradores para projetos Ruby on Rails.</p><p>Agora, vamos nos concentrar em como usar o Jasmine com JavaScript:</p><h3 id="usando-o-jasmine-standalone">Usando o Jasmine Standalone</h3><p>Comece baixando a versão mais recente do Jasmine na página de <a href="https://github.com/jasmine/jasmine/releases"><em>releases</em></a> (lançamentos).</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/c1Ieo1kBD-F8mAKy1ZKYbc2IayEoMWHDL1eH.png" class="kg-image" alt="c1Ieo1kBD-F8mAKy1ZKYbc2IayEoMWHDL1eH" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/c1Ieo1kBD-F8mAKy1ZKYbc2IayEoMWHDL1eH.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/c1Ieo1kBD-F8mAKy1ZKYbc2IayEoMWHDL1eH.png 635w" width="635" height="253" loading="lazy"></figure><p>Em seguida, basta extrair o arquivo zip, de preferência dentro de uma pasta no projeto que você deseja testar.</p><p>A pasta conterá diversos arquivos e pastas padrão:</p><p><code>/src</code>: contém os arquivos de código-fonte que você deseja testar. Essa pasta pode ser excluída se você já tiver a pasta do seu projeto configurada. Ela também pode ser usada quando for apropriado para hospedar seu código-fonte.</p><p><code>/lib</code>: contém os arquivos principais do Jasmine.</p><p><code>/spec</code>: contém os testes que você vai escrever.</p><p><code>SpecRunner.html</code>: é um arquivo usado como um executor de testes. Você executa suas especificações simplesmente iniciando esse arquivo.</p><p>Este é o conteúdo de um arquivo <code>SpecRunner.html</code> padrão:</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;title&gt;Jasmine Spec Runner v3.2.1&lt;/title&gt;

  &lt;link rel="shortcut icon" type="image/png" href="lib/jasmine-3.2.1/jasmine_favicon.png"&gt;
  &lt;link rel="stylesheet" href="lib/jasmine-3.2.1/jasmine.css"&gt;

  &lt;script src="lib/jasmine-3.2.1/jasmine.js"&gt;&lt;/script&gt;
  &lt;script src="lib/jasmine-3.2.1/jasmine-html.js"&gt;&lt;/script&gt;
  &lt;script src="lib/jasmine-3.2.1/boot.js"&gt;&lt;/script&gt;

  &lt;!-- include source files here... --&gt;
  &lt;script src="src/Player.js"&gt;&lt;/script&gt;
  &lt;script src="src/Song.js"&gt;&lt;/script&gt;

  &lt;!-- include spec files here... --&gt;
  &lt;script src="spec/SpecHelper.js"&gt;&lt;/script&gt;
  &lt;script src="spec/PlayerSpec.js"&gt;&lt;/script&gt;

&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>Lembre-se de que você precisa alterar os arquivos incluídos das pastas <code>/src</code> e <code>/spec</code> para conter seus arquivos de código-fonte e de teste reais.</p><h3 id="usando-o-jasmine-como-uma-biblioteca">Usando o Jasmine como uma biblioteca</h3><p>Você também pode usar o Jasmine como uma biblioteca em seu projeto. Por exemplo, o código a seguir importa e executa o Jasmine:</p><pre><code class="language-javascript">var Jasmine = require('jasmine');
var jasmine = new Jasmine();

jasmine.loadConfigFile('spec/support/jasmine.json');

jasmine.execute();
</code></pre><p>Primeiro, solicitamos/importamos o Jasmine e usamos o método <code>loadConfigFile()</code> para carregar o arquivo de configuração disponível no caminho <code>spec/support/jasmine.json</code> e, finalmente, executamos o Jasmine.</p><h3 id="usando-o-jasmine-via-cli">Usando o Jasmine via CLI</h3><p>Você também pode usar o Jasmine a partir da CLI (interface de linha de comando), o que permite executar facilmente os testes do Jasmine e, por padrão, gerar os resultados no terminal.</p><p>Seguiremos essa abordagem para executar nossos testes de exemplo neste guia, então, primeiro, execute o seguinte comando para instalar o Jasmine globalmente:</p><pre><code class="language-bash">npm install -g jasmine
</code></pre><blockquote><em>Você pode precisar executar <strong>sudo</strong> para instalar pacotes npm globalmente, dependendo da sua <a href="https://docs.npmjs.com/getting-started/fixing-npm-permissions">configuração do npm</a>.</em></blockquote><p>Agora, crie uma pasta para seu projeto e navegue para dentro dela:</p><pre><code class="language-bash">$ mkdir jasmine-project $ cd jasmine-project
</code></pre><p>Em seguida, execute o seguinte comando para inicializar seu projeto para o Jasmine:</p><p>O comando simplesmente cria uma pasta <code>spec</code> e um arquivo de configuração JSON. Esta é a saída do comando <code>dir</code>:</p><pre><code class="language-bash">.
└── spec
    └── support
        └── jasmine.json

2 directories, 1 file
</code></pre><p>Este é o conteúdo de um arquivo <code>jasmine.json</code> padrão:</p><pre><code class="language-js">{
  "spec_dir": "spec",
  "spec_files": [
    "**/*[sS]pec.js"
  ],
  "helpers": [
    "helpers/**/*.js"
  ],
  "stopSpecOnExpectationFailure": false,
  "random": true
}
</code></pre><ul><li><code>spec_dir</code>: especifica onde o Jasmine procura arquivos de teste.</li><li><code>spec_files</code>: especifica os padrões de arquivos de teste. Por padrão, todos os arquivos JS que terminam com as strings <strong>Spec</strong> ou <strong>spec</strong>.</li><li><code>helpers</code>: especifica onde o Jasmine procura arquivos auxiliares. Os arquivos auxiliares são executados antes das especificações e podem ser usados para definir <em>matchers</em> personalizados.</li><li><code>stopSpecOnExpectationFailure</code>: quando definido como <code>true</code>, interromperá imediatamente uma especificação na primeira falha de uma expectativa (pode ser usado como uma opção CLI via <code>--stop-on-failure</code>).</li><li><code>random</code>: quando definido como <code>true</code>, o Jasmine executará os casos de teste de modo pseudoaleatório (pode ser usado como uma opção da CLI via <code>--random</code>).</li></ul><p>Os arrays <code>spec_files</code> e <code>helpers</code> também podem conter padrões <a href="https://pt.wikipedia.org/wiki/Glob">Glob</a> (graças ao pacote <a href="https://github.com/isaacs/node-glob">node-glob</a>) para especificar caminhos de arquivo que são padrões que você normalmente usa para especificar um conjunto de arquivos ao trabalhar no Bash (por exemplo, <code>ls *.js</code>).</p><p>Se você não usar o local padrão para o arquivo de configuração <code>jasmine.json</code>, basta especificar o local personalizado por meio da opção <code>jasmine --config</code>.</p><p>Você pode encontrar mais opções da CLI na <a href="https://jasmine.github.io/setup/nodejs.html">documentação oficial</a>.</p><h3 id="entendendo-o-jasmine">Entendendo o Jasmine</h3><p>Nesta seção, aprenderemos sobre os elementos básicos dos testes do Jasmine, como suítes, especificações, expectativas, <em>matchers</em> e <em>spies</em> etc.</p><p>Na pasta do projeto, ao executar o comando para inicializar um novo módulo do Node, <code>npm init -y</code>, você criará um arquivo <code>package.json</code> com informações padrão:</p><pre><code class="language-js">{
  "name": "jasmine-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;&amp; exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
</code></pre><p>Em seguida, crie um arquivo <code>index.js</code> e adicione o seguinte código:</p><pre><code class="language-js">function fibonacci(n){

    if (n === 1) {
        return [0, 1];
    }
    else {
        var s = fibonacci(n - 1);
        s.push(s[s.length - 1] + s[s.length - 2]);
        return s;
    }
}
function isPrime(num){
    for (let i = 2; i &lt; num; i++)
        if (num % i === 0) return false;
    return num !== 1 &amp;&amp; num !== 0;
}
function isEven(n) {
    return n % 2 == 0;
}
function isOdd(n) {
    return Math.abs(n % 2) == 1;
}

function toLowerCase(str){
    return str.toLowerCase();
}
function toUpperCase(str){
    return str.toUpperCase();
}
function contains(str, substring, fromIndex){
    return str.indexOf(substring, fromIndex) !== -1;
}
function repeat(str, n){
    return (new Array(n + 1)).join(str);
}

module.exports = {
    fibonacci: fibonacci,
    isPrime: isPrime,
    isEven: isEven,
    isOdd: isOdd,
    toLowerCase: toLowerCase,
    toUpperCase: toUpperCase,   
    contains: contains,
    repeat: repeat
};
</code></pre><h3 id="su-tes">Suítes</h3><p>Uma suíte agrupa um conjunto de especificações ou casos de teste. É usada para testar um comportamento específico do código em JavaScript que geralmente é encapsulado por um objeto/classe ou uma função. Ela é criada usando a função global do Jasmine <code>describe()</code>, que recebe dois parâmetros, o título da suíte de teste e uma função que implementa o código real da suíte de teste.</p><p>Vamos começar criando nossa primeira suíte de teste. Dentro da pasta <code>spec</code>, crie um arquivo <code>MyJSUtilitiesSpec.js</code> e adicione:</p><pre><code class="language-js">describe("MyJSUtilities", function() { /* ... */ });
</code></pre><p><em>MyJSUtilities</em> é o nome da suíte de teste de nível superior.</p><h4 id="como-agrupar-e-aninhar-su-tes">Como agrupar e aninhar suítes</h4><p>Para melhor organização e descrição precisa do nosso conjunto de testes, podemos aninhar suítes dentro da suíte de nível superior. Por exemplo, vamos adicionar duas suítes à suíte <em>MyJSUtilities</em>:</p><pre><code class="language-js">describe("String Utils", function() { /*...*/});describe("Math Utils", function() { /*...*/});
</code></pre><p>Dentro da suíte <em>Math Utils</em>, vamos também adicionar duas suítes aninhadas:</p><pre><code class="language-js">describe("Basic Math Utils", function() {   /* ... */ }); describe("Advanced Math Utils", function() {   /* ... */ });
</code></pre><p>Estamos agrupando testes relacionados em testes para <em>String Utils</em>, <em>Basic Math Utils</em> e <em>Advanced Math Utils</em> e aninhando-os dentro da suíte de nível superior <em>MyJSUtilities</em>. Isso comporá suas especificações como árvores semelhantes a uma estrutura de pastas.</p><p>A estrutura de aninhamento será mostrada no relatório, o que facilita a localização de testes com falha.</p><h4 id="como-excluir-su-tes">Como excluir suítes</h4><p>Você pode desabilitar temporariamente uma suíte usando a função <code>xdescribe()</code>. Ela tem a mesma assinatura (parâmetros) de uma função <code>describe()</code>, o que significa que você pode desabilitar rapidamente suas suítes existentes simplesmente adicionando um <code>x</code> à função.</p><p>As especificações dentro de uma função <code>xdescribe()</code> serão marcadas como pendentes e não serão executadas no relatório.</p><h3 id="especifica-es">Especificações</h3><p>Uma especificação declara um caso de teste que pertence a uma suíte de teste. Isso é feito chamando a função global do Jasmine <code>it()</code>, que recebe dois parâmetros: o título da especificação (que descreve a lógica que queremos testar) e uma função que implementa o caso de teste real.</p><p>Uma especificação pode conter uma ou mais expectativas. Cada expectativa é simplesmente uma asserção que pode retornar <code>true</code> ou <code>false</code>. Para que a especificação seja aprovada, todas as expectativas pertencentes à especificação devem ser <code>true</code>. Caso contrário, a especificação falha.</p><p>Dentro da nossa suíte <em>String Utils</em>, adicione estas especificações:</p><pre><code class="language-js">describe("String Utils", function() {  it("should be able to lower case a string",function() {    /*...*/  });  it("should be able to upper case a string",function() {    /*...*/  });  it("should be able to confirm if a string contains a substring",function() {    /*...*/  });  it("should be able repeat a string multiple times",function() {    /*...*/  });});
</code></pre><p>Dentro da nossa suíte <em>Basic Math Utils</em>, vamos adicionar algumas especificações:</p><pre><code class="language-js">describe("Basic Math Utils", function() {  it("should be able to tell if a number is even",function() {    /*...*/  });     it("should be able to tell if a number is odd",function() {    /*...*/  });     });
</code></pre><p>Para <em>Advanced Math Utils</em>, vamos adicionar as especificações:</p><pre><code class="language-js">describe("Advanced Math Utils", function() {  it("should be able to tell if a number is prime",function() {    /*...*/  });   it("should be able to calculate the fibonacci of a number",function() {    /*...*/  }); });
</code></pre><h4 id="como-excluir-especifica-es">Como excluir especificações</h4><p>Assim como as suítes, você também pode excluir especificações individuais usando a função <code>xit()</code>, que desabilita temporariamente a especificação <code>it()</code> e a marca como pendente.</p><h3 id="expectativas">Expectativas</h3><p>As expectativas são criadas usando a função <code>expect()</code> que recebe um valor chamado <strong>real</strong> (que pode ser valores, expressões, variáveis, funções, objetos etc.). As expectativas compõem a especificação e são usadas junto com funções <em>matcher</em> (via encadeamento) para definir o que o desenvolvedor espera que uma unidade específica de código execute.</p><p>Uma função <em>matcher</em> compara um valor <strong>real</strong> (passado para a função <code>expect()</code> com a qual está encadeada) e um valor <strong>esperado</strong> (passado diretamente como um parâmetro para o <em>matcher</em>) e retorna <strong>true</strong> ou <strong>false</strong>, o que <strong>passa</strong> ou <strong>falha</strong> a especificação.</p><p>Você pode encadear a função <code>expect()</code> com vários <em>matchers</em>. Para negar/inverter o resultado booleano de qualquer <em>matcher</em>, você pode usar a palavra-chave <code>not</code> antes de chamar o <em>matcher</em>.</p><p>Vamos implementar as especificações do nosso exemplo. Por enquanto, usaremos <code>expect()</code> com o <em>matcher </em><code>nothing()</code>, que faz parte dos <em>matchers</em> integrados que veremos um pouco mais tarde. Isso passará em todas as especificações, pois não esperamos nada neste momento.</p><pre><code class="language-js">describe("MyJSUtilities", function() {describe("&gt;String Utils", function() {  it("should be able to lower case a string",function() {    expect().nothing();  });  it("should be able to upper case a string",function() {    expect().nothing();  });  it("should be able to confirm if a string contains a substring",function() {    expect().nothing();  });  it("should be able repeat a string multiple times",function() {    expect().nothing();  });     });describe("Math Utils", function() { describe("Basic Math Utils", function() {  it("should be able to tell if a number is even",function() {    expect().nothing();  });     it("should be able to tell if a number is odd",function() {    expect().nothing();  });    }); describe("Advanced Math Utils", function() {  it("should be able to tell if a number is prime",function() {    expect().nothing();  });   it("should be able to calculate the fibonacci of a number",function() {    expect().nothing();  });     }); });});
</code></pre><p>Esta é uma captura de tela dos resultados neste ponto:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/jvFGz7IVrci3GpsfT520cJg1T9lK3puc8Fca.png" class="kg-image" alt="jvFGz7IVrci3GpsfT520cJg1T9lK3puc8Fca" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/jvFGz7IVrci3GpsfT520cJg1T9lK3puc8Fca.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/jvFGz7IVrci3GpsfT520cJg1T9lK3puc8Fca.png 652w" width="652" height="387" loading="lazy"><figcaption>Temos oito especificações aprovadas e zero falhas.</figcaption></figure><p>Você pode usar <em>matchers</em> integrados ou também criar seus próprios <em>matchers</em> personalizados para suas necessidades específicas.</p><h3 id="matchers-integrados"><em>Matchers</em> integrados</h3><p>O Jasmine fornece um rico conjunto de <em>matchers</em> integrados. Vamos ver alguns dos mais importantes:</p><ul><li><code>toBe()</code> para testar identidade,</li><li><code>toBeNull()</code> para testar <code>null</code>,</li><li><code>toBeUndefined()/toBeDefined()</code> para testar <code>undefined</code>/não <code>undefined</code>,</li><li><code>toBeNaN()</code> para testar NaN (Not A Number)</li><li><code>toEqual()</code> para testar igualdade,</li><li><code>toBeFalsy()/toBeTruthy()</code> para testar falsidade/veracidade etc.</li></ul><p>Você pode encontrar a lista completa de <em>matchers </em>na <a href="https://jasmine.github.io/api/edge/matchers.html">documentação</a>.</p><p>Vamos agora implementar nossas especificações com alguns desses <em>matchers</em> quando apropriado. Primeiro, importe as funções que estamos testando em nosso arquivo <code>MyJSUtilitiesSpec.js</code>:</p><pre><code>const utils = require("../index.js");
</code></pre><p>Em seguida, comece com a suíte <em>String Utils</em> e altere <code>expect().nothing()</code> com as expectativas apropriadas.</p><p>Por exemplo, para a primeira especificação, esperamos que o método <code>toLowerCase()</code> seja primeiro definido e, em segundo lugar, retorne uma string em minúsculas, ou seja:</p><pre><code class="language-js">it("should be able to lower case a string",function() {        expect(utils.toLowerCase).toBeDefined();        expect(utils.toLowerCase("HELLO WORLD")).toEqual("hello world");  });
</code></pre><p>Este é o código completo para a suíte:</p><pre><code class="language-js">describe("&gt;String Utils", function() {  it("should be able to lower case a string",function() {    expect(utils.toLowerCase).toBeDefined();    expect(utils.toLowerCase("HELLO WORLD")).toEqual("hello world");  });  it("should be able to upper case a string",function() {    expect(utils.toUpperCase).toBeDefined();    expect(utils.toUpperCase("hello world")).toEqual("HELLO WORLD");  });  it("should be able to confirm if a string contains a substring",function() {    expect(utils.contains).toBeDefined();    expect(utils.contains("hello world","hello",0)).toBeTruthy();  });  it("should be able repeat a string multiple times",function() {    expect(utils.repeat).toBeDefined();    expect(utils.repeat("hello", 3)).toEqual("hellohellohello");  });     });
</code></pre><h3 id="matchers-personalizados">Matchers personalizados</h3><p>O Jasmine fornece a capacidade de escrever <a href="https://jasmine.github.io/tutorials/custom_matcher.html"><em>matchers personalizados</em></a> para implementar asserções não cobertas pelos <em>matchers </em>integrados ou apenas para tornar os testes mais descritivos e legíveis.</p><p>Por exemplo, vamos pegar a seguinte especificação:</p><pre><code class="language-js">it("should be able to tell if a number is even",function() {    expect(utils.isEven).toBeDefined();    expect(utils.isEven(2)).toBeTruthy();    expect(utils.isEven(1)).toBeFalsy();  });
</code></pre><p>Vamos supor que o método <code>isEven()</code> não esteja implementado. Se executarmos os testes, receberemos mensagens como a seguinte captura de tela:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/dHjK8DH8lMJRdUzXj23GiUMTPJ75zOg9rtbe.png" class="kg-image" alt="dHjK8DH8lMJRdUzXj23GiUMTPJ75zOg9rtbe" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/dHjK8DH8lMJRdUzXj23GiUMTPJ75zOg9rtbe.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/dHjK8DH8lMJRdUzXj23GiUMTPJ75zOg9rtbe.png 637w" width="637" height="182" loading="lazy"></figure><p>A mensagem de falha que recebemos diz <em>Expected undefined to be defined</em>, o que não nos dá nenhuma pista do que está acontecendo. Então, vamos tornar essa mensagem mais significativa no contexto do nosso domínio de código (isso será mais útil para bases de código complexas). Para isso, vamos criar um <em>matcher</em> personalizado.</p><p>Criamos <em>matchers</em> personalizados usando o método <code>addMatchers()</code>, que recebe um objeto composto por uma ou várias propriedades que serão adicionadas como <em>matchers</em>. Cada propriedade deve fornecer uma função <em>factory</em> que recebe dois parâmetros: <code>util</code>, que possui um conjunto de funções utilitárias para os <em>matchers</em> usarem (consulte: <code><a href="https://github.com/pivotal/jasmine/blob/master/src/core/matchers/matchersUtil.js">MatchersUtil.js</a></code>) e <code>customEqualityTesters</code>, que precisa ser passado se <code>util.equals</code> for chamado, devendo retornar um objeto com uma função <code>compare</code>, que será chamada para verificar a expectativa.</p><p>Precisamos registrar o <em>matcher</em> personalizado antes de executar cada especificação usando o método <code>beforeEach()</code>:</p><pre><code class="language-js">describe("/Basic Math Utils", function () {beforeEach(function () {jasmine.addMatchers({hasEvenMethod:  function (util, customEqualityTesters) {return {compare:  function (actual, expected) {var  result  = { pass:  utils.isEven  !==  undefined };if (result.pass) {result.message  =  "Expected isEven() to be not defined."}else {result.message  =  "Expected isEven() to be defined."}return  result;}}}});});/*...*/});
</code></pre><p>Podemos então usar o <em>matcher </em>personalizado em vez de <code>expect(utils.isEven).toBeDefined()</code>:</p><pre><code class="language-js">expect().hasEvenMethod();
</code></pre><p>Isso nos dará uma mensagem de falha melhor:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/OulftEemEqJoqGYNoPhHY4v3ok1VE5LE0K05.png" class="kg-image" alt="OulftEemEqJoqGYNoPhHY4v3ok1VE5LE0K05" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/OulftEemEqJoqGYNoPhHY4v3ok1VE5LE0K05.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/OulftEemEqJoqGYNoPhHY4v3ok1VE5LE0K05.png 646w" width="646" height="169" loading="lazy"></figure><h3 id="usando-beforeeach-e-aftereach-">Usando beforeEach() e afterEach()</h3><p>Para inicializar e limpar suas especificações, o Jasmine fornece duas funções globais, <code>beforeEach()</code> e <code>afterEach()</code>:</p><ul><li>A função <code>beforeEach</code> é chamada uma vez antes de cada especificação na suíte onde é chamada.</li><li>A função <code>afterEach</code> é chamada uma vez após cada especificação na suíte onde é chamada.</li></ul><p>Por exemplo, se você precisar usar quaisquer variáveis em sua suíte de teste, pode simplesmente declará-las no início da função <code>describe()</code> e colocar qualquer código de inicialização ou instanciação dentro de uma função <code>beforeEach()</code>. Finalmente, você pode usar a função <code>afterEach()</code> para redefinir as variáveis após cada especificação, para que você possa ter testes unitários puros sem a necessidade de repetir o código de inicialização e limpeza para cada especificação.</p><p>A função <code>beforeEach()</code> também é perfeitamente combinada com muitas APIs do Jasmine, como o método <code>addMatchers()</code> para criar <em>matchers</em> personalizados ou também com a função <code>done()</code> para aguardar operações assíncronas antes de continuar o teste.</p><h3 id="falhando-um-teste">Falhando um teste</h3><p>Você pode forçar um teste a falhar usando o método global <code>fail()</code> disponível no Jasmine. Por exemplo:</p><pre><code class="language-js">it("should explicitly fail", function () { fail('Forced to fail'); });
</code></pre><p>Você deve receber o seguinte erro:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/A0qZ0VRL7KrP2Xu0cCsRUq6vW4SRcMwov6Mn.png" class="kg-image" alt="A0qZ0VRL7KrP2Xu0cCsRUq6vW4SRcMwov6Mn" width="347" height="63" loading="lazy"></figure><h3 id="testando-exce-es">Testando exceções</h3><p>Quando você está testando seu código unitariamente, erros e exceções podem ser lançados, então você pode precisar testar esses cenários. O Jasmine fornece os <em>matchers</em> <code>toThrow()</code> e <code>toThrowError()</code> para testar quando uma exceção é lançada ou para testar uma exceção específica, respectivamente.</p><p>Por exemplo, se tivermos uma função que lança uma exceção <code>TypeError</code>:</p><pre><code class="language-js">function throwsError() { throw new TypeError("A type error"); }
</code></pre><p>Você pode escrever uma especificação para testar se uma exceção é lançada:</p><pre><code>it('it should throw an exception', function () { expect(throwsError).toThrow(); });
</code></pre><p>Ou você também pode usar o teste para a exceção <code>TypeError</code> específica:</p><pre><code class="language-js">it('it should throw a TypeError', function () { expect(throwsError).toThrowError(TypeError); });
</code></pre><h3 id="entendendo-spies">Entendendo <em>spies</em></h3><p>Muitas vezes, os métodos dependem de outros métodos. Isso significa que, ao testar um método, você pode acabar testando suas dependências também. Isso não é recomendado em testes, ou seja, você precisa garantir que está testando a função pura, isolando o método e vendo como ele se comporta, dado um conjunto de entradas.</p><p>O Jasmine fornece <a href="http://jasmine.github.io/2.0/introduction.html#section-Spies"><em>spies</em></a> que podem ser usados para "espionar"/ouvir chamadas de método em objetos e relatar se um método é chamado e em qual contexto e argumentos.</p><p>O Jasmine fornece duas maneiras de espionar chamadas de método: usando os métodos <code>spyOn()</code> ou <code>createSpy()</code>.</p><p>Você pode usar <code>spyOn()</code> quando o método já existe no objeto. Caso contrário, você precisa usar <code>jasmine.createSpy()</code>, que retorna uma nova função.</p><p>Por padrão, um <em>spy</em> apenas relatará se uma chamada foi feita sem chamar a função espionada (ou seja, a função parará de ser executada), mas você pode alterar o comportamento padrão usando estes métodos:</p><ul><li><code>and.callThrough()</code>: chama a função original,</li><li><code>and.returnValue(value)</code>: retorna o valor especificado,</li><li><code>and.callFake(fn)</code>: chama a função falsa em vez da original,</li><li><code>and.throwError(err)</code>: lança um erro,</li><li><code>and.stub()</code>: redefine o comportamento de <em>stub </em>padrão.</li></ul><p>Você pode usar um <em>spy</em> para coletar estatísticas de tempo de execução na função espionada, por exemplo, se você quiser saber quantas vezes sua função foi chamada.</p><p>Digamos que queremos garantir que nosso método <code>toUpperCase()</code> esteja usando o método <code>String.toUpperCase()</code> integrado. Precisamos, simplesmente, espionar <code>String.toUpperCase()</code> usando:</p><pre><code class="language-js">it("should be able to upper case a string", function () { 
</code></pre><pre><code>var spytoUpperCase = spyOn(String.prototype, 'toUpperCase') 
</code></pre><pre><code>expect(utils.toUpperCase).toBeDefined(); expect(utils.toUpperCase("hello world")).toEqual("HELLO WORLD"); expect(String.prototype.toUpperCase).toHaveBeenCalled(); expect(spytoUpperCase.calls.count()).toEqual(1); });
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/k-BN6V3GrUluGjMy3gtCMOAeae6wvu4CVu52.png" class="kg-image" alt="k-BN6V3GrUluGjMy3gtCMOAeae6wvu4CVu52" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/k-BN6V3GrUluGjMy3gtCMOAeae6wvu4CVu52.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/k-BN6V3GrUluGjMy3gtCMOAeae6wvu4CVu52.png 648w" width="648" height="217" loading="lazy"></figure><p>O teste falhou devido à segunda expectativa, pois <code>utils.toUpperCase("hello world")</code> retornou <code>undefined</code> em vez do <em>HELLO WORLD</em> esperado. Isso ocorre porque, como mencionamos, anteriormente, após criar o <em>spy</em> em <code>toUpperCase()</code>, o método não é executado. Precisamos mudar esse comportamento padrão chamando <code>callThrough()</code>:</p><blockquote><em>Observe que uma função <code>spy</code> substitui a função espionada por um stub por padrão. Se você precisar chamar a função original, pode adicionar <code>.and.callThrough()</code> ao seu objeto <code>spy</code>.</em></blockquote><pre><code>var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.callThrough();
</code></pre><p>Agora, todas as expectativas passam.</p><p>Você também pode usar <code>and.callFake()</code> ou <code>and.returnValue()</code> para falsificar a função espionada ou apenas o valor de retorno se você não quiser chamar a função real:</p><pre><code>var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.returnValue("HELLO WORLD"); 
</code></pre><pre><code class="language-js">var spytoUpperCase = spyOn(String.prototype, 'toUpperCase').and.callFake(function(){ return "HELLO WORLD"; });
</code></pre><p>Agora, se acabarmos não usando o <code>String.toUpperCase()</code> integrado em nossa própria implementação de <code>utils.toUpperCase()</code>, obteremos estas falhas:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/z43QKVly7yBHOnKndLsZ6Id4roK-G0ut9ufK.png" class="kg-image" alt="z43QKVly7yBHOnKndLsZ6Id4roK-G0ut9ufK" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/z43QKVly7yBHOnKndLsZ6Id4roK-G0ut9ufK.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/z43QKVly7yBHOnKndLsZ6Id4roK-G0ut9ufK.png 644w" width="644" height="305" loading="lazy"></figure><p>As duas expectativas <code>expect(String.prototype.toUpperCase).toHaveBeenCalled()</code> <code>expect(spytoUpperCase.calls.count()).toEqual(1)</code> falharam.</p><h3 id="como-lidar-com-assincronia-no-jasmine">Como lidar com assincronia no Jasmine</h3><p>Se o código que você está testando contém operações assíncronas, você precisa de uma maneira de informar ao Jasmine quando as operações assíncronas forem concluídas.</p><p>Por padrão, o Jasmine espera que qualquer operação assíncrona, definida por uma <em>callback</em>, uma <em>promise</em> ou a palavra-chave <code>async</code>, seja concluída. Se o Jasmine encontrar uma <em>callback</em>, <em>promise</em> ou palavra-chave async em uma dessas funções: <code>beforeEach</code>, <code>afterEach</code>, <code>beforeAll</code>, <code>afterAll</code> e <code>it</code>, ele aguardará a conclusão da operação assíncrona antes de prosseguir para a próxima operação.</p><h3 id="usando-done-com-beforeeach-it-">Usando <code>done()</code> com <code>beforeEach()</code>/<code>it()</code> ..</h3><p>Vamos pegar nosso exemplo <code>simulateAsyncOp()</code>, que simula uma operação assíncrona usando <code>setTimeout()</code>. Em um cenário do mundo real, pode ser uma solicitação Ajax ou qualquer coisa semelhante que aconteça de maneira assíncrona:</p><pre><code class="language-js">function simulateAsyncOp(callback){ 
</code></pre><pre><code>setTimeout(function () { callback(); }, 2000); }
</code></pre><p>Para testar esta função, podemos usar a função <code>beforeEach()</code> com a <em>callback</em> especial <code>done()</code>. Nosso código precisa invocar <code>done()</code> para informar ao Jasmine que a operação assíncrona foi concluída:</p><pre><code class="language-js">describe("/Async Op", function () {var  asyncOpCompleted  =  false;beforeEach(function (done) {utils.simulateAsyncOp(function(){  asyncOpCompleted  =  true;  done();});});it("should be able to tell if the async call has completed", function () {  expect(asyncOpCompleted).toEqual(true);});});
</code></pre><p>Podemos notar rapidamente uma desvantagem desse método, então precisamos escrever nosso código para aceitar a <em>callback</em> <code>done()</code>. No nosso caso, não codificamos o método <code>done()</code> em nosso <code>simulateAsyncOp(fn)</code>, mas fornecemos um parâmetro de <em>callback</em> apenas para poder chamar <code>done()</code>.</p><h3 id="usando-as-promises">Usando as <em>promises</em></h3><p>Se você não quiser criar código que dependa de como você escreve seu teste, pode usar uma <em>promise</em> e chamar a <em>callback</em> <code>done()</code> quando a <em>promise</em> for resolvida. Ou melhor ainda, a partir do Jasmine 2.7+, se seu código retornar uma <code>Promise</code>, o Jasmine aguardará até que ela seja resolvida ou rejeitada antes de executar o próximo código.</p><h3 id="usando-async-await">Usando async/await</h3><p>O Jasmine 2.7+ suporta chamadas a <code>async</code> e <code>await</code> em especificações. Isso o libera de colocar asserções em um bloco <code>.then()</code> ou <code>.catch()</code>.</p><pre><code class="language-js">it("should work with async/await", async () =&gt; { let completed = false; completed = await utils.simulateAsyncOp(); expect(completed).toEqual(true); });
</code></pre><p>Esta é a implementação de <code>simulateAsyncOp</code>:</p><pre><code class="language-js">function simulateAsyncOp() { 
</code></pre><pre><code class="language-js">return new Promise(resolve =&gt; { setTimeout(() =&gt; { resolve(true); }, 1000); }); }
</code></pre><h3 id="usando-o-jasmine-clock">Usando o Jasmine Clock</h3><p>O Jasmine Clock é usado para testar código assíncrono que depende de funções de tempo, como <code>setTimeout()</code>, da mesma maneira que testamos código síncrono, simulando APIs baseadas em tempo com métodos personalizados. Desse modo, você pode executar as funções testadas sincronicamente controlando ou avançando manualmente o relógio.</p><p>Você pode instalar o Jasmine Clock chamando a função <code>jasmine.clock().install</code> em sua especificação ou suíte.</p><p>Depois de usar o relógio, você precisa desinstalá-lo para restaurar as funções originais.</p><p>Com o Jasmine Clock, você pode controlar as funções <code>setTimeout</code> ou <code>setInterval</code> do JavaScript avançando o relógio para avançar no tempo usando a função <code>jasmine.clock().tick</code>, que recebe o número de milissegundos que você pode mover.</p><p>Você também pode usar o Jasmine Clock para simular a data atual.</p><pre><code class="language-js">beforeEach(function () {jasmine.clock().install();});afterEach(function() {jasmine.clock().uninstall();});it("should call the asynchronous operation synchronously", function() {var  completed  =  false;utils.simulateAsyncOp(function(){completed  =  true;});expect(completed).toEqual(false);jasmine.clock().tick(1001);expect(completed).toEqual(true);});
</code></pre><p>Esta é a função <code>simulateAsyncOp</code>:</p><pre><code>function simulateAsyncOp(callback){ 
</code></pre><pre><code class="language-js">setTimeout(function () { callback(); }, 1000); }
</code></pre><blockquote><em>Caso você não tenha especificado um horário para a função <code>mockDate</code>, ela usará a data atual.</em></blockquote><h3 id="lidando-com-erros">Lidando com erros</h3><p>Se o seu código assíncrono falhar devido a algum erro, você vai querer que suas especificações falhem da maneira certa. A partir do Jasmine 2.6+, quaisquer erros não tratados são enviados para a especificação atualmente executada.</p><p>O Jasmine também fornece uma maneira que você pode usar se precisar falhar explicitamente em suas especificações:</p><ul><li>usando a callback <code>done()</code> com <code>beforeEach()</code> chamando o método <code>done.fail(err)</code>,</li><li>simplesmente passando um erro para a <em>callback </em><code>done(err)</code> (Jasmine 3+),</li><li>chamando o método <code>reject()</code> de uma <code>Promise</code>.</li></ul><h3 id="conclus-o">Conclusão</h3><p>Neste guia, apresentamos o Jasmine e vimos como começar a usá-lo para fazer testes unitários de seu código em JavaScript. Agradecemos pela leitura!</p><p>Este <a href="https://www.techiediaries.com/angular/jasmine-unit-testing/">artigo</a> foi publicado originalmente em <a href="https://www.techiediaries.com/">techiediaries</a>.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como realizar testes de integração usando JUnit 5 e TestContainers com SpringBoot ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Sameer Shukla TestContainers é uma biblioteca que ajuda você a executar contêineres Docker específicos do módulo para simplificar o teste de integração. Esses contêineres do Docker são leves e, uma vez que os testes são concluídos, os contêineres são destruídos. Neste artigo, vamos entender o que é o ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-realizar-testes-de-integracao-usando-junit-5-e-testcontainers-com-springboot/</link>
                <guid isPermaLink="false">66a7076397bcd504087699de</guid>
                
                    <category>
                        <![CDATA[ Testes ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Thu, 05 Sep 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/testcontainers-logo.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/integration-testing-using-junit-5-testcontainers-with-springboot-example/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Perform Integration Testing using JUnit 5 and TestContainers with SpringBoot</a>
      </p><p>Escrito por: Sameer Shukla</p><p>TestContainers é uma biblioteca que ajuda você a executar contêineres Docker específicos do módulo para simplificar o teste de integração.</p><p>Esses contêineres do Docker são leves e, uma vez que os testes são concluídos, os contêineres são destruídos.</p><p>Neste artigo, vamos entender o que é o TestContainers e como ele ajuda você a escrever testes mais confiáveis.</p><p>Também vamos entender os componentes importantes (anotações e métodos) da biblioteca que ajudam você a escrever os testes.</p><p>Finalmente, aprenderemos a escrever um teste de integração adequado no SpringBoot usando a biblioteca TestContainers e seus componentes.</p><h2 id="limita-es-do-teste-com-um-banco-de-dados-h2-na-mem-ria">Limitações do teste com um banco de dados H2 na memória</h2><p>A abordagem mais comum para o teste de integração hoje é usar um banco de dados H2 na memória. Existem, no entanto, certas limitações para esse método.</p><p>Em primeiro lugar, digamos que estamos usando a versão 8.0 do MySQL em produção, mas que nossos testes de integração estão usando H2. Nunca poderemos executar nossos testes para a versão do banco de dados em execução em produção.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-303.png" class="kg-image" alt="image-303" width="480" height="517" loading="lazy"><figcaption>Aplicação do SpringBoot com banco de dados MySQL e H2</figcaption></figure><p>‌Em segundo lugar, os casos de teste são menos confiáveis porque, em produção, estamos usando um banco de dados totalmente diferente – e os testes estão apontando para o H2. A aplicação pode ter problemas em produção, mas os testes de integração podem ser bem-sucedidos.</p><p>Eu estava tentando acessar meu serviço RESTful localmente e me deparei com este erro:</p><p><strong>"Caused by: org.postgresql.util.PSQLException: FATAL: database "example_db" does not exist"</strong>.</p><p>Ele aconteceu por causa de um problema de permissão, mas os testes locais funcionaram bem.</p><p>Por fim, conforme documentado <a href="https://h2database-com.translate.goog/html/features.html?_x_tr_sch=http&amp;_x_tr_sl=en&amp;_x_tr_tl=pt&amp;_x_tr_hl=en&amp;_x_tr_pto=wapp#compatibility">aqui, na seção Compatibility</a> (documentação em inglês), o H2 é compatível com outros bancos de dados apenas até certo ponto. Existem algumas áreas onde o H2 é incompatível. Se você precisar usar "nativeQueries" em uma aplicação do SpringBoot, por exemplo, usar o H2 pode causar problemas.</p><h2 id="apresentando-a-biblioteca-testcontainers">Apresentando a biblioteca TestContainers</h2><p>Ao usar TestContainers, podemos superar as limitações do H2.</p><ul><li>Os testes de integração apontarão para a mesma versão do banco de dados que está em produção. Assim, podemos vincular nossa imagem de banco de dados do TestContainer à mesma versão em execução na produção.</li><li>Os testes de integração são muito mais confiáveis porque a aplicação e os testes estarão usando o mesmo tipo e versão de banco de dados, não havendo problemas de compatibilidade, portanto, nos casos de teste.</li></ul><h2 id="o-que-s-o-os-testcontainers">O que são os TestContainers?</h2><p>A biblioteca TestContainers é uma API <em>wrapper</em> sobre o Docker. Quando escrevemos código para criar um contêiner nos bastidores, ele pode ser traduzido para algum comando do Docker como, por exemplo‌:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-283.png" class="kg-image" alt="image-283" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-283.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-283.png 932w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Criação do MySQLContainer</figcaption></figure><p>Este código pode ser traduzido para algo como o seguinte:</p><pre><code class="language-docker">docker run -d --env MYSQL_DATABASE=example_db --env MYSQL_USER=test --env MYSQL_PASSWORD=test ‘mysql:latest’ 
</code></pre><p>O TestContainers tem um nome de método "<em>withCommand</em>". Você o usa para definir o comando que deve ser executado dentro do contêiner do Docker, o que confirma que o TestContainers é uma API <em>wrapper </em>sobre o Docker.</p><p>O TestContainers baixa as imagens MySQL, Postgres, Kafka, Redis e as executa em um contêiner. O MySQLContainer executará um banco de dados do MySQL em um contêiner e os casos de teste podem se conectar a ele na máquina local. Uma vez que a execução termina, o banco de dados desaparecerá – ele simplesmente é excluído da máquina. Nos casos de teste, podemos iniciar quantas imagens de contêiner quisermos.</p><p>O TestContainers suporta JUnit 4, JUnit 5 e Spock. Se você for ao site TestContainers.org, basta visitar a seção <em>QuickStart</em> que explica como usá-lo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-284.png" class="kg-image" alt="image-284" width="600" height="400" loading="lazy"><figcaption>TestContainers.org: como começar com o Test Framework</figcaption></figure><p>O TestContainers tem suporte a quase todos os bancos de dados, do MySQL e Postgres ao CockroachDB. Você pode encontrar mais informações sobre isso no site TestContainers.org, na seção <em>Modules</em>:‌</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-285.png" class="kg-image" alt="image-285" width="600" height="400" loading="lazy"><figcaption>Suporte do TestContainers para módulos de bancos de dados</figcaption></figure><p>‌O TestContainers também suporta módulos de nuvem como o módulo da GCloud e o módulo do Azure. Se sua aplicação estiver sendo executada no Google Cloud, o TestContainers terá suporte para Cloud Spanner, Firestore, Datastore e assim por diante.‌</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-286.png" class="kg-image" alt="image-286" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-286.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-286.png 975w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Suporte do TestContainers para o módulo da GCloud</figcaption></figure><p>Até agora, no artigo, falamos apenas sobre bancos de dados, mas o TestContainers suporta vários outros componentes, como Kafka, SOLR, Redis e muito mais.</p><h2 id="como-usar-a-biblioteca-testcontainers">Como usar a biblioteca TestContainers</h2><p>Neste artigo, vamos explorar o TestContainers com o JUnit 5. Para implementar o TestContainers, precisamos entender algumas anotações, métodos e bibliotecas importantes do TestContainers que precisamos implementar em nosso projeto.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-288.png" class="kg-image" alt="image-288" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-288.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-288.png 924w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Bibliotecas TestContainers</figcaption></figure><h3 id="anota-es-em-testcontainers">Anotações em TestContainers</h3><p>Duas anotações importantes são necessárias em nossos testes para que o TestContainers funcione: @TestContainers e @Container.</p><p>@TestContainer é uma extensão do JUnit-Jupiter que inicia e interrompe automaticamente os contêineres usados nos testes. Essa anotação encontra os campos que são marcados com @Container e chama os métodos específicos do ciclo de vida do contêiner. Aqui, os métodos do ciclo de vida do MySQLContainer serão invocados.‌</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-289.png" class="kg-image" alt="image-289" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-289.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-289.png 932w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>MySQLContainer</figcaption></figure><p>O MySQLContainer é declarado como estático, pois, se declararmos o contêiner como estático, um único contêiner será iniciado e será compartilhado entre todos os métodos de teste.</p><p>Se for uma variável de instância, um contêiner será criado para cada método de teste.</p><h2 id="m-todos-da-biblioteca-testcontainers">Métodos da biblioteca TestContainers</h2><p>Existem alguns métodos importantes na biblioteca TestContainers que você usará nos testes. É bom conhecê-los antes de usar a biblioteca.</p><ul><li><strong>withInitScript</strong>: usando 'withInitScript', podemos executar o .SQL para definir o esquema, tabelas e também adicionar os dados ao banco de dados. Resumindo, esse método é usado para executar o .SQL para popular o banco de dados.</li><li><strong>withReuse</strong> (true): usando o método 'withReuse', podemos habilitar a reutilização de contêineres. Esse método funciona bem em conjunto com a habilitação da propriedade "testcontainers.reuse.enable:true" no arquivo ".testcontainers.properties".</li><li><strong>start</strong>: usamos isso para iniciar o contêiner.</li><li><strong>withClasspathResourceMapping</strong>: usamos para mapear um recurso (arquivo ou diretório) no <em>classpath</em> para um caminho dentro do contêiner. Isso só funcionará se você estiver executando seus testes fora de um contêiner do Docker.</li><li><strong>withCommand</strong>: define o comando que deve ser executado dentro do contêiner do Docker.</li><li><strong>withExposedPorts</strong>: usado para definir a porta na qual o contêiner escuta.</li><li><strong>withFileSystemBind</strong>: usado para mapear um arquivo/diretório do sistema de arquivos local para o contêiner.</li></ul><h2 id="caso-de-uso-do-testcontainers">Caso de uso do TestContainers</h2><p>No exemplo que veremos agora, a aplicação se comunicará apenas com o banco de dados e escreverá os testes de integração para ele usando o TestContainers. Em seguida, estenderemos o caso de uso implementando o Redis no meio.</p><p>Se os dados existirem no cache do Redis, eles serão retornados; caso contrário, ele mergulhará no banco de dados para salvar e recuperar com base na chave.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-308.png" class="kg-image" alt="image-308" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-308.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/09/image-308.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-308.png 1047w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Caso de uso - a solicitação acessa o cache do Redis e retorna, caso a informação esteja lá. Do contrário, é feito o acesso ao BD do MySQL</figcaption></figure><p>O serviço é simples. Ele tem 2 endpoints – o primeiro é para criar um usuário e o segundo é para encontrar um usuário por e-mail. Se o usuário for encontrado, ele será retornado; caso contrário, obteremos um 404. O código da classe de serviço tem esta aparência:‌</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-291.png" class="kg-image" alt="image-291" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-291.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-291.png 975w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Componente de serviço</figcaption></figure><p>Vamos escrever os testes para essa classe. Você pode encontrar toda a base de código <a href="https://github.com/kslagerstrom/testcontainers-examples">aqui</a>:‌</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-292.png" class="kg-image" alt="image-292" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-292.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-292.png 975w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Classe de teste</figcaption></figure><p>A classe de teste é marcada com a anotação @TestContainers, que inicia/para o contêiner. Usamos a anotação @Container para chamar os métodos específicos do ciclo de vida do contêiner.</p><p>Além disso, o "MySQLContainer" é declarado como estático porque, então, um único contêiner é iniciado. Em seguida, ele é compartilhado entre todos os métodos de teste (já discutimos a importância dessas anotações).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-293.png" class="kg-image" alt="image-293" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-293.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-293.png 975w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>BeforeAll</figcaption></figure><p>Em seguida, precisamos escrever um método de configuração marcado com @BeforeAll, onde habilitamos o método "withReuse". Isso nos ajuda a reutilizar os contêineres existentes. Estamos usando o método "withInitScript" para executar o arquivo ".sql" e, em seguida, iniciar o contêiner.‌</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-294.png" class="kg-image" alt="image-294" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-294.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-294.png 975w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Sobrescrevendo as Properties</figcaption></figure><p>‌@DynamicPropertySource nos ajuda a sobrescrever as propriedades declaradas no arquivo <em>properties</em>. Escrevemos esse método para permitir que o TestContainers crie o URL, o nome de usuário e a senha por conta própria – caso contrário, podemos enfrentar erros.</p><p>Por exemplo, ao remover o nome de usuário e a senha, podemos enfrentar um erro 'Access denied' (acesso negado, em português), que pode nos confundir. Portanto, é melhor permitir que o TestContainer atribua essas propriedades dinamicamente por conta própria.</p><p>É isso – estamos prontos para executar os casos de teste:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-295.png" class="kg-image" alt="image-295" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-295.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-295.png 695w" width="600" height="400" loading="lazy"><figcaption>Casos de teste</figcaption></figure><p>Execute @AfterAll para parar o contêiner. Caso contrário, ele poderá continuar sendo executado em sua máquina local se você não o parar explicitamente.‌</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-296.png" class="kg-image" alt="image-296" width="600" height="400" loading="lazy"></figure><h2 id="como-usar-o-genericcontainer">Como usar o GenericContainer</h2><p>‌‌GenericContainer é o contêiner mais flexível. Ele facilita a execução de quaisquer imagens de contêiner dentro do GenericContainer.</p><p>Agora que temos o Redis em seu devido lugar, tudo o que precisamos fazer em nosso caso de teste é ativar um GenericContainer com a imagem do Redis.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-297.png" class="kg-image" alt="image-297" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-297.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-297.png 975w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>GenericContainer para o Redis</figcaption></figure><p>Em seguida, iniciamos o contêiner genérico do Redis em @BeforeAll e o paramos com o método de desmontagem @AfterAll.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-298.png" class="kg-image" alt="image-298" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-298.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-298.png 859w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"><figcaption>Iniciando os contêineres</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-299.png" class="kg-image" alt="image-299" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/image-299.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/image-299.png 667w" width="600" height="400" loading="lazy"><figcaption>Parando os contêineres</figcaption></figure><h2 id="conclus-o">Conclusão</h2><p>É extremamente fácil usar o TestContainers em nossa aplicação para escrever testes melhores. A curva de aprendizado não é muito íngreme e tem suporte para vários módulos diferentes de uma variedade de bancos de dados, como Kafka, Redis e outros.</p><p>Escrever testes usando o TestContainers torna nossos testes muito mais confiáveis. O único lado negativo é que os testes são lentos em comparação aos do H2. Isso ocorre porque o H2 está na memória e o TestContainers leva tempo para baixar a imagem, executar o contêiner e executar toda a configuração que discutimos neste artigo.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Teste do JUnit com o Maven no VSCode ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Clark Jason Ngo Instalar o VSCode Configuração aqui: Configurando o Visual Studio Code [https://code-visualstudio-com.translate.goog/docs/setup/setup-overview?_x_tr_sl=en&_x_tr_tl=pt] Instalar e criar um projeto do Maven Guia de instalação completo aqui: Maven – Maven em 5 minutos [https://maven-apache-org.translate.goog/guides/getting-started/maven-in-five-minutes.html?_x_tr_sl=en&_x_tr_tl=pt]  (em inglês) Se você tem o Maven instalado, siga estas etapas: Gerar o projeto ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/teste-do-junit-com-o-maven-no-vscode/</link>
                <guid isPermaLink="false">66a6d6e997bcd504087699d4</guid>
                
                    <category>
                        <![CDATA[ Testes ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Wed, 04 Sep 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_8zPHl_wSifWv_DBOkYGEzQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/cjn-junit-test-with-maven-in-vscode/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">JUnit Test with Maven in VSCode</a>
      </p><p>Escrito por: Clark Jason Ngo</p><h3 id="instalar-o-vscode">Instalar o VSCode</h3><p>Configuração aqui: <a href="https://code-visualstudio-com.translate.goog/docs/setup/setup-overview?_x_tr_sl=en&amp;_x_tr_tl=pt">Configurando o Visual Studio Code</a></p><h3 id="instalar-e-criar-um-projeto-do-maven">Instalar e criar um projeto do Maven</h3><p>Guia de instalação completo aqui: <a href="https://maven-apache-org.translate.goog/guides/getting-started/maven-in-five-minutes.html?_x_tr_sl=en&amp;_x_tr_tl=pt">Maven – Maven em 5 minutos</a> (em inglês)</p><p>Se você tem o Maven instalado, siga estas etapas:</p><p><strong><strong>Gerar o projeto</strong></strong></p><pre><code>mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
</code></pre><p><strong><strong>Mudar para o diretório do projeto</strong></strong></p><pre><code>cd my-app
</code></pre><p><strong><strong>Construir o projeto</strong></strong></p><pre><code>mvn package
</code></pre><p><strong><strong>Testar e compilar o projeto</strong></strong></p><pre><code>java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App
</code></pre><p><strong>Você deve obter uma saída com:</strong> Hello World!</p><h3 id="modificar-nosso-projeto">Modificar nosso projeto</h3><p>Vamos começar criando funções matemáticas simples</p><p>Procure o arquivo <code>App.java</code> e substitua o conteúdo por este código:</p><pre><code class="language-java">package com.mycompany.app;

public class App 
{
  public static int add(int firstNumber, int secondNumber) {
    return firstNumber + secondNumber;
  }

  public static int multiply(int multiplicand, int multiplier) {
    return multiplicand * multiplier;
  }

  public static int divide(int dividend, int divisor) {
    if (divisor == 0)
      throw new IllegalArgumentException("Cannot divide by zero (0)."); // Não pode dividir por zero (0).

    return dividend / divisor;
  }
  public static void main( String[] args )
  {
    System.out.println(App.add(3, 3)); 
  }
}
</code></pre><p>Procure por <code>AppTest.java</code> e substitua o conteúdo por este código:</p><pre><code class="language-java">package com.mycompany.app;

import static org.junit.Assert.assertTrue;

import org.junit.Assert;
import org.junit.Test;

/**
* Teste unitário para App simples. 
*/ 
public class AppTest 
{
    /**
    *Teste Rigoroso :-)
    */
    @Test
    public void shouldAnswerWithTrue() // deveResponderComVerdadeiro
    {
        assertTrue( true );
    }
    @Test
    public void add_TwoPlusTwo_ReturnsFour() { // adicionar_DoisMaisDois_RetornaQuatro
      // Organizar
      final int expected = 4;

      // Agir
      final int actual = App.add(2, 2);

      // Afirmar
      Assert.assertEquals(expected, actual);
    }    
    @Test
    public void multiply_FourTimesTwo_ReturnsEight() { // multiplicar_QuatroVezesDois_RetornaOito
      // Organizar
      final int expected = 8;

      // Agir
      final int actual = App.multiply(4, 2);

      // Afirmar
      Assert.assertEquals(expected, actual);
    }        

    @Test
    public void divide_TenDividedTwo_ReturnsFive() { // dividir_DezDivididoPorDois_RetornaCinco
      // Organizar
      final int expected = 5;

      // Agir
      final int actual = App.divide(10, 2);

      // Afirmar
      Assert.assertEquals(expected, actual);
    }           
}
</code></pre><p>Você pode continuar criando testes como, por exemplo:</p><pre><code class="language-java">@Test    
public void multiply_FiftyTimesTwo_ReturnsOneHundred()  // multiplicar_CinquentaVezesDois_RetornaCem
{      
  // // Organizar
  final int expected = 100;        
  // // Agir
  final int actual = App.multiply(50, 2);        
  // // Afirmar
  Assert.assertEquals(actual, expected);    
}
</code></pre><p><strong><strong>Construir o projeto</strong></strong></p><pre><code>mvn package
</code></pre><p>Saída:</p><pre><code>[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.026 s - in com.mycompany.app.AppTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
</code></pre><p><strong><strong>Testar e compilar o projeto</strong></strong></p><pre><code class="language-java">java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App
</code></pre><p>Saída:</p><pre><code>6
Hello World!
</code></pre><p>Uma maneira alternativa de executar os testes é clicar em <em>Run Test</em> dentro de <code>AppTest.java</code></p><p>No exemplo abaixo, <em>Run Test</em> está localizado logo abaixo da linha de código 44.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_TFBgactTWvK7ColY1YgxEw.png" class="kg-image" alt="1_TFBgactTWvK7ColY1YgxEw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/1_TFBgactTWvK7ColY1YgxEw.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/09/1_TFBgactTWvK7ColY1YgxEw.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_TFBgactTWvK7ColY1YgxEw.png 1240w" sizes="(min-width: 720px) 720px" width="1240" height="680" loading="lazy"><figcaption>Nos comentários, "Arrange" (organizar), "Act" (agir) e Assert (afirmar)</figcaption></figure><p><strong><strong>Visualizar </strong>t<strong>estes e </strong>r<strong>elatório de </strong>t<strong>este</strong></strong></p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_uNAouJG881s3iP0rX2zeVw.png" class="kg-image" alt="1_uNAouJG881s3iP0rX2zeVw" width="468" height="296" loading="lazy"></figure><h3 id="migrando-do-junit-4-para-o-junit-5">Migrando do JUnit 4 para o JUnit 5</h3><p>Altere as dependências do seu <code>pom.xml</code> para:</p><pre><code class="language-xml">  &lt;dependencies&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.junit.jupiter&lt;/groupId&gt;
          &lt;artifactId&gt;junit-jupiter-api&lt;/artifactId&gt;
          &lt;version&gt;5.4.2&lt;/version&gt;
          &lt;scope&gt;test&lt;/scope&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.junit.jupiter&lt;/groupId&gt;
          &lt;artifactId&gt;junit-jupiter-engine&lt;/artifactId&gt;
          &lt;version&gt;5.4.2&lt;/version&gt;
          &lt;scope&gt;test&lt;/scope&gt;
      &lt;/dependency&gt;
  &lt;/dependencies&gt;
</code></pre><p>Altere seu <code>AppTest.java</code> para:</p><pre><code class="language-java">package com.mycompany.app;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

/** 
* Teste unitário para App simples. 
*/
public class AppTest 
{
    /**
    * Teste Rigoroso :-)
    */ 
    @Test
    public void shouldAnswerWithTrue() // deveResponderComVerdadeiro
    {
        assertTrue( true );
    }
    @Test
    public void add_TwoPlusTwo_ReturnsFour() { // adicionar_DoisMaisDois_RetornaQuatro
      // Organizar
      final int expected = 4;

      // Agir
      final int actual = App.add(2, 2);

      // Afirmar
      assertEquals(expected, actual);
    }    
    @Test
    public void multiply_FourTimesTwo_ReturnsEight() { // multiplicar_QuatroVezesDois_RetornaOito
      // Organizar
      final int expected = 8;

      // Agir
      final int actual = App.multiply(4, 2);

      // Afirmar
      assertEquals(expected, actual);
    }        

    @Test
    public void divide_TenDividedTwo_ReturnsFive() { // dividir_DezDivididoPorDois_RetornaCinco
      // Organizar
      final int expected = 5;

      // Agir
      final int actual = App.divide(10, 2);

      // Afirmar
      assertEquals(expected, actual);
    }           
}
</code></pre><p><strong><strong>Adicionando cobertura de teste</strong></strong></p><p><strong><strong>Verifique o relatório de cobertura de teste</strong></strong></p><p>No VSCode, abra o Extension MarketPlace e pesquise Coverage Gutters</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_OjkwUa9oX9s8MNgTMG6WdQ.png" class="kg-image" alt="1_OjkwUa9oX9s8MNgTMG6WdQ" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/1_OjkwUa9oX9s8MNgTMG6WdQ.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_OjkwUa9oX9s8MNgTMG6WdQ.png 718w" width="718" height="304" loading="lazy"></figure><p>Clique no botão Instalar (ou <em>Install</em>)</p><p>Abra o arquivo <code>pom.xml</code> na sua pasta raiz e substitua o conteúdo pelo <a href="http://bit.ly/2Df1Oj2">pom.xml no GitHub</a> para adicionar suporte a um <em>plug-in</em>.</p><pre><code class="language-xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;

&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

  &lt;groupId&gt;com.mycompany.app&lt;/groupId&gt;
  &lt;artifactId&gt;my-app&lt;/artifactId&gt;
  &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;

  &lt;name&gt;my-app&lt;/name&gt;
  &lt;!-- IMPORTANTE troque este endereço pelo do site do projeto --&gt;
  &lt;url&gt;http://www.exemplo.com&lt;/url&gt;

  &lt;properties&gt;
    &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
    &lt;maven.compiler.source&gt;1.7&lt;/maven.compiler.source&gt;
    &lt;maven.compiler.target&gt;1.7&lt;/maven.compiler.target&gt;
  &lt;/properties&gt;

  &lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.junit.jupiter&lt;/groupId&gt;
        &lt;artifactId&gt;junit-jupiter-api&lt;/artifactId&gt;
        &lt;version&gt;5.4.2&lt;/version&gt;
        &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.junit.jupiter&lt;/groupId&gt;
        &lt;artifactId&gt;junit-jupiter-engine&lt;/artifactId&gt;
        &lt;version&gt;5.4.2&lt;/version&gt;
        &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;


  &lt;build&gt;
    &lt;pluginManagement&gt;&lt;!-- faça o lockdown das versões dos plug-ins para evitar o uso dos padrões do Maven (pode ser movido para o pom pai) --&gt;
      &lt;plugins&gt;
        &lt;plugin&gt;
          &lt;groupId&gt;org.jacoco&lt;/groupId&gt;
          &lt;artifactId&gt;jacoco-maven-plugin&lt;/artifactId&gt;
          &lt;version&gt;0.8.2&lt;/version&gt;
          &lt;executions&gt;
              &lt;execution&gt;
                  &lt;goals&gt;
                      &lt;goal&gt;prepare-agent&lt;/goal&gt;
                  &lt;/goals&gt;
              &lt;/execution&gt;
              &lt;execution&gt;
                  &lt;id&gt;report&lt;/id&gt;
                  &lt;phase&gt;prepare-package&lt;/phase&gt;
                  &lt;goals&gt;
                      &lt;goal&gt;report&lt;/goal&gt;
                  &lt;/goals&gt;
              &lt;/execution&gt;
          &lt;/executions&gt;
        &lt;/plugin&gt;
        &lt;!-- Ciclo de vida limpo; consulte https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle (em inglês) --&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-clean-plugin&lt;/artifactId&gt;
          &lt;version&gt;3.1.0&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;!-- Ciclo de vida padrão, empacotamento em jar; consulte https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging (em inglês) --&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-resources-plugin&lt;/artifactId&gt;
          &lt;version&gt;3.0.2&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
          &lt;version&gt;3.8.0&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
          &lt;version&gt;2.22.1&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;
          &lt;version&gt;3.0.2&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-install-plugin&lt;/artifactId&gt;
          &lt;version&gt;2.5.2&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-deploy-plugin&lt;/artifactId&gt;
          &lt;version&gt;2.8.2&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;!-- Ciclo de vida do site; consulte https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle (em inglês) --&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-site-plugin&lt;/artifactId&gt;
          &lt;version&gt;3.7.1&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-project-info-reports-plugin&lt;/artifactId&gt;
          &lt;version&gt;3.0.0&lt;/version&gt;
        &lt;/plugin&gt;
      &lt;/plugins&gt;
    &lt;/pluginManagement&gt;
  &lt;/build&gt;
&lt;/project&gt;
</code></pre><p>Abra o terminal no VSCode e execute</p><pre><code>mvn install
mvn clean jacoco:prepare-agent install jacoco:report
</code></pre><p>Abra seu arquivo <code>App.java</code> na pasta <code>main/java/com/mycompany/app</code> e clique no botão <em>Watch</em> para verificar o relatório</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_eRmrtwQ23Gp6IGXRwphLvA.png" class="kg-image" alt="1_eRmrtwQ23Gp6IGXRwphLvA" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/1_eRmrtwQ23Gp6IGXRwphLvA.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_eRmrtwQ23Gp6IGXRwphLvA.png 974w" sizes="(min-width: 720px) 720px" width="974" height="677" loading="lazy"></figure><p>Barra vermelha: código de teste não coberto</p><p>Barra amarela: condição não coberta</p><p>Barra verde: código coberto</p><p>Abra o arquivo <code>index.html</code> na sua pasta <code>root/target/site/jacoco</code>.</p><p>Para abrir:</p><p>Eme seguida, cole (Ctrl + V para Windows e Command + V para MacOS) o caminho no seu navegador.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_jj1o8eqXMZ27xK9crCng9w.png" class="kg-image" alt="1_jj1o8eqXMZ27xK9crCng9w" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/1_jj1o8eqXMZ27xK9crCng9w.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_jj1o8eqXMZ27xK9crCng9w.png 787w" sizes="(min-width: 720px) 720px" width="787" height="387" loading="lazy"></figure><p>Você pode ver um relatório de cobertura de teste muito detalhado:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_LIgnn-CgO6vR9hBhZZGvug.png" class="kg-image" alt="1_LIgnn-CgO6vR9hBhZZGvug" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/09/1_LIgnn-CgO6vR9hBhZZGvug.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/09/1_LIgnn-CgO6vR9hBhZZGvug.png 974w" sizes="(min-width: 720px) 720px" width="974" height="214" loading="lazy"></figure><p>Obrigado pela leitura! 😉</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Construindo uma aplicação de CRUD simples com Express e MongoDB ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Zell Liew Por muito tempo, não ousei me aventurar no desenvolvimento de back-end. Me sentia intimidado por causa da minha falta de formação acadêmica em programação. Lembro-me de quando finalmente criei coragem para tentar o desenvolvimento de  back-end. Tive tanta dificuldade em entender a documentação do Express, ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/construindo-uma-aplicacao-de-crud-simples-com-express-e-mongodb/</link>
                <guid isPermaLink="false">6687425423266d03fc8b83da</guid>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Sun, 04 Aug 2024 23:29:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/1_umzW9eAqELBCuo458Rzdcw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/building-a-simple-crud-application-with-express-and-mongodb-63f80f3eb1cd/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Building a Simple CRUD Application with Express and MongoDB</a>
      </p><p>Escrito por: Zell Liew</p><p>Por muito tempo, não ousei me aventurar no desenvolvimento de <em>back-end</em>. Me sentia intimidado por causa da minha falta de formação acadêmica em programação.</p><p>Lembro-me de quando finalmente criei coragem para tentar o desenvolvimento de <em>back-end</em>. Tive tanta dificuldade em entender a documentação do Express, MongoDB e Node.js que desisti.</p><p>No fim, voltei e trabalhei para esclarecer minha confusão. Agora, um ano depois, entendi como trabalhar com essas ferramentas. Então, decidi escrever este tutorial abrangente para que você não precise passar pela mesma dor de cabeça que eu passei.</p><h3 id="crud-express-e-mongodb">CRUD, Express e MongoDB</h3><p>CRUD, Express e MongoDB são palavras grandes para uma pessoa que nunca tocou em programação do lado do servidor em sua vida. Vamos apresentar rapidamente o que elas são antes de mergulharmos no tutorial.</p><p><a href="https://pt.wikipedia.org/wiki/Express.js"><strong>Express</strong></a> é um <em>framework </em>para construir aplicações para a web com base no Node.js. Ele simplifica o processo de criação do servidor que já está disponível no Node. Caso você esteja se perguntando: o Node permite que você use JavaScript como sua linguagem do lado do servidor.</p><p><a href="https://pt.wikipedia.org/wiki/MongoDB"><strong>MongoDB</strong></a> é um banco de dados. É no banco de dados que você armazena informações para seus sites (ou aplicações) para a web.</p><p><a href="https://pt.wikipedia.org/wiki/CRUD"><strong>CRUD</strong></a> é uma abreviação em inglês para Criar, Ler, Atualizar e Excluir. É um conjunto de operações que fazemos para que os servidores as executem (POST, GET, PUT e DELETE, respectivamente). Isso é o que cada operação faz:</p><ul><li><strong>Criar (POST)</strong> — Criar algo</li><li><strong>Ler (GET)</strong> — Obter algo</li><li><strong>Atualizar (PUT)</strong> — Alterar algo</li><li><strong>Excluir (DELETE)</strong>– Remover algo</li></ul><p>Se colocarmos CRUD, Express e MongoDB juntos em um único diagrama, seria assim:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_UKwrPtpRSGFiDomm.png" class="kg-image" alt="0_UKwrPtpRSGFiDomm" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_UKwrPtpRSGFiDomm.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_UKwrPtpRSGFiDomm.png 800w" sizes="(min-width: 720px) 720px" width="800" height="294" loading="lazy"><figcaption>À direita, o navegador. Entre ele e o servidor, as operações de CRUD.</figcaption></figure><p>CRUD, Express e MongoDB fazem mais sentido para você agora?</p><p>Ótimo. Vamos em frente.</p><h3 id="o-que-vamos-construir">O que vamos construir</h3><p>Vamos construir uma aplicação de lista simples que permite que você acompanhe as coisas dentro de uma lista (como uma Lista de Tarefas, por exemplo).</p><p>Bem, uma lista de tarefas é meio chata. Que tal fazermos uma lista de citações de personagens de Star Wars? Incrível, não é? Além disso, <a href="https://github.com/zellwk/crud-express-mongo">aqui é onde</a> você pode encontrar o código finalizado para a aplicação.</p><p>A propósito, o que estamos construindo não é uma aplicação de página única atraente. Estamos focando principalmente em como usar o CRUD, o Express e Mongo DB neste tutorial. Serão, portanto, mais orientações de como criar o lado do servidor. Não vou enfatizar o estilo.</p><p>Você precisará de duas coisas para começar com este tutorial:</p><ol><li>Você não deve ter medo de digitar comandos em um shell. Confira <a href="https://zellwk.com/blog/fear-of-command-line/">este artigo</a> (em inglês) se estiver com medo.</li><li>Você precisa ter o <a href="https://nodejs.org/">Node</a> instalado.</li></ol><p>Para verificar se você tem o Node instalado, abra sua linha de comando e execute o seguinte código:</p><pre><code>$ node -v</code></pre><p>Você deve obter um número de versão se tiver o Node instalado. Se não tiver, você pode instalar o Node baixando o instalador do <a href="https://nodejs.org/">site do Node</a> ou baixando-o por meio de gerenciadores de pacotes como <a href="http://brew.sh/">Homebrew</a> (Mac) e <a href="https://chocolatey.org/">Chocolatey</a> (Windows).</p><h3 id="come-ando">Começando</h3><p>Comece criando uma pasta para este projeto. Sinta-se à vontade para chamá-la do que quiser. Depois de navegar até ela, execute o comando <code>npm init</code>.</p><p>Esse comando cria um arquivo <code>package.json</code>, que ajuda você a gerenciar as dependências que instalaremos mais tarde no tutorial.</p><pre><code>$ npm init</code></pre><p>Basta pressionar Enter em tudo o que aparecer. Falarei sobre o que você precisa saber à medida que avançamos.</p><h3 id="executando-o-node-pela-primeira-vez-em-sua-vida">Executando o Node pela primeira vez em sua vida</h3><p>A maneira mais simples de usar o node é executar o comando node e especificar um caminho para um arquivo. Vamos criar um arquivo chamado <code>server.js</code> para executar o node.</p><pre><code>$ touch server.js</code></pre><p>Quando executarmos o arquivo <code>server.js</code>, queremos ter certeza de que ele está sendo executado corretamente. Para fazer isso, basta escrever uma instrução <code>console.log</code> no server.js:</p><pre><code>console.log('Que o Node esteja com você')</code></pre><p>Agora, execute node server.js em sua linha de comando e você deverá ver a instrução que você registrou:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_82cfsJUuV4b0Mmn2.png" class="kg-image" alt="0_82cfsJUuV4b0Mmn2" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_82cfsJUuV4b0Mmn2.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_82cfsJUuV4b0Mmn2.png 769w" sizes="(min-width: 720px) 720px" width="769" height="53" loading="lazy"><figcaption>Se você enxergar <em>May Node be with you</em> (Que o Node esteja com você), é sinal de que deu certo.</figcaption></figure><p>Ótimo. Vamos em frente e aprender como usar o Express agora.</p><h3 id="usando-o-express">Usando o Express</h3><p>Primeiro, temos que instalar o Express antes de podermos usá-lo em nossa aplicação. Instalar o Express é muito fácil. Tudo o que temos que fazer é executar um comando de instalação com o gerenciador de pacotes do Node (npm), que vem junto com o Node.</p><p>Execute o comando <code>npm install express --save</code> em sua linha de comando:</p><pre><code>$ npm install express --save</code></pre><p>Depois de terminar, você deverá ver que o npm salvou o Express como uma dependência no <code>package.json</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_WQ2iauA--9SEqja3.png" class="kg-image" alt="0_WQ2iauA--9SEqja3" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_WQ2iauA--9SEqja3.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_WQ2iauA--9SEqja3.png 617w" width="617" height="174" loading="lazy"><figcaption>A versão da dependência será diferente, dependendo de quando você estiver lendo este artigo.</figcaption></figure><p>Em seguida, usamos o express em server.js exigindo-o.</p><pre><code>const express = require('express');
const app = express();</code></pre><p>A primeira coisa que queremos fazer é criar um servidor ao qual os navegadores possam se conectar. Podemos fazer isso com a ajuda de um método <code>listen</code> fornecido pelo Express:</p><pre><code>app.listen(3000, function() {
	console.log('Escutando na porta 3000')
})</code></pre><p>Agora, execute <code>node server.js</code> e navegue até <code>localhost:3000</code> em seu navegador. Você deverá ver uma mensagem que diz <code>Cannot get /</code>.</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/0*HuIZ1G3D7TMPjbdU.png" class="kg-image" alt="0HuIZ1G3D7TMPjbdU" width="800" height="141" loading="lazy"></figure><p>Isso é um bom sinal. Significa que <strong>agora podemos nos comunicar com nosso servidor do Express através do navegador</strong>. É aqui que começamos as operações CRUD.</p><h3 id="crud-ler">CRUD — LER</h3><p>A operação <strong>LER</strong> é realizada pelos navegadores sempre que você visita uma página da web. Nos bastidores, os navegadores enviam uma solicitação <strong>GET</strong> ao servidor para realizar uma operação de LEITURA. O motivo pelo qual vemos o erro "Cannot get /" é porque ainda não enviamos nada de volta ao navegador do nosso servidor.</p><p>No Express, lidamos com uma solicitação <strong>GET</strong> com o método get:</p><pre><code>app.get(caminho, callback)</code></pre><p><strong>O primeiro argumento, caminho</strong>, é o caminho da solicitação GET. É qualquer coisa que vem depois do nome de domínio.</p><p>Quando estamos visitando <code>localhost:3000</code>, nossos navegadores estão, na verdade, procurando por <code>localhost:3000/</code>. O argumento caminho, neste caso, é <code>/</code>.</p><p><strong>O segundo argumento é uma função de <em>callback</em></strong> que informa ao servidor o que fazer quando o caminho é correspondido. Ele recebe dois argumentos, um objeto de solicitação e um objeto de resposta:</p><pre><code>app.get('/', function (request, response) {
  // faça algo aqui
})</code></pre><p>Por enquanto, vamos escrever "Olá Mundo" de volta para o navegador. Fazemos isso usando um método <em>send</em> que vem com o objeto de resposta:</p><pre><code>app.get('/', function(req, res) {
  res.send('Olá Mundo')
}) // Observação: solicitação e resposta são geralmente escritas como req e res, respectivamente.</code></pre><p>Vou começar a escrever em código ES6 e mostrar como converter para ES6 ao longo do caminho também. Primeiro, estou substituindo o function() pela <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Functions/Arrow_functions"><em>arrow function</em>, da ES6</a>. O código abaixo é o mesmo que o código acima:</p><pre><code>app.get('/', (req, res) =&gt; {
  res.send('Olá mundo')
})</code></pre><p>Agora, reinicie seu servidor fazendo o seguinte:</p><ol><li>Pare o servidor atual pressionando <code>CTRL + C</code> na linha de comando.</li><li>Execute <code>node server.js</code> novamente.</li></ol><p>Em seguida, navegue até <code>localhost:3000</code> em seu navegador. Você deverá ver uma <em>string</em> que diz "Hello World" (Olá Mundo).</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/0*jBDbdhi2v2N82RvP.png" class="kg-image" alt="0jBDbdhi2v2N82RvP" width="800" height="130" loading="lazy"></figure><p>Ótimo. Vamos mudar nossa aplicação para que sirva uma página <code>index.html</code> de volta para o navegador. Para fazer isso, usamos o método <em>sendFile</em> que é fornecido pelo objeto <code>res</code>.</p><pre><code>app.get('/', (req, res) =&gt; {
  res.sendFile(__dirname + '/index.html')
}) // Observação: __dirname é o caminho para o seu diretório de trabalho atual. Tente registrá-lo e veja o que você obtém! O meu era '/Users/zellwk/Projects/demo-repos/crud-express-mongo' para esta aplicação.</code></pre><p>No método <code>sendFile()</code> acima, dissemos ao Express para servir um arquivo index.html que pode ser encontrado na raiz da pasta do seu projeto. Ainda não temos esse arquivo. Vamos criá-lo agora.</p><pre><code>touch index.html</code></pre><p>Vamos colocar algum texto em nosso arquivo <code>index.html</code> também:</p><pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
	&lt;head&gt;
	  &lt;meta charset="UTF-8"&gt;
	  &lt;title&gt;MEU APP&lt;/title&gt;&lt;/head&gt;
	&lt;/head&gt;
	&lt;body&gt;
		Que o Node e o Express estejam com você.
	&lt;/body&gt;
&lt;/html&gt;</code></pre><p>Reinicie seu servidor e atualize seu navegador. Você deverá ver os resultados do seu arquivo HTML agora.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_oisDzT819Ex3FtDs.png" class="kg-image" alt="0_oisDzT819Ex3FtDs" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_oisDzT819Ex3FtDs.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_oisDzT819Ex3FtDs.png 696w" width="696" height="159" loading="lazy"><figcaption>Você deve ver <em>May Node and Express be with you</em>/Que o Node e o Express estejam com você!</figcaption></figure><p>É assim que o Express lida com uma solicitação <strong>GET</strong> (operação <strong>LER</strong>) em poucas palavras.</p><p>Neste ponto, você provavelmente percebeu que precisa reiniciar seu servidor sempre que fizer uma alteração em <code>server.js</code>. Esse processo é incrivelmente tedioso. Por isso, vamos fazer um pequeno desvio e otimizá-lo usando um pacote chamado <a href="http://nodemon.io/">nodemon</a>.</p><h3 id="apresentando-o-nodemon">Apresentando o Nodemon</h3><p><strong>O Nodemon reinicia o servidor automaticamente</strong> sempre que você salva um arquivo que o servidor usa. Podemos instalar o Nodemon usando o seguinte comando:</p><pre><code>$ npm install nodemon --save-dev</code></pre><p>Observação: o motivo pelo qual estamos usando uma <em>flag</em> <code>--save-dev</code> aqui é porque estamos usando o Nodemon apenas quando estamos desenvolvendo. Essa <em>flag </em>salvaria o Nodemon como uma devDependency em seu arquivo <code>package.json</code>.</p><p>Continuando, o Nodemon se comporta exatamente da mesma maneira que o node, o que significa que podemos executar nosso servidor chamando <code>nodemon server.js</code>. No entanto, não podemos fazer isso na linha de comando agora porque o Nodemon não está instalado com uma <em>flag</em> <code>-g</code>.</p><p>Há outra maneira de executar o Nodemon — podemos executá-lo a partir da pasta node_modules. O código se parece com isto:</p><pre><code>$ ./node_modules/.bin/nodemon server.js</code></pre><p>Isso é muito para digitar. Uma maneira de simplificar é criar uma chave de script em <code>package.json</code>.</p><pre><code>{  
	// ...
   "scripts": {
		"dev": "nodemon server.js"
	}
    // ...
}</code></pre><p>Agora, você pode executar <code>npm run dev</code> para acionar <code>nodemon server.js</code>.</p><p>De volta ao tópico principal. Vamos cobrir a operação <strong>CRIAR</strong> em seguida.</p><h3 id="crud-criar">CRUD — CRIAR</h3><p>A operação <strong>CRIAR</strong> é realizada apenas pelo navegador se uma solicitação <strong>POST</strong> for enviada ao servidor. Essa solicitação POST pode ser acionada com JavaScript ou por meio de um elemento <code>&lt;form&gt;</code>.</p><p>Vamos descobrir como usar um elemento <code>&lt;form&gt;</code> para criar entradas para nossa aplicação de citações de Star Wars para esta parte do tutorial.</p><p>Para fazer isso, você primeiro precisa criar um elemento <code>&lt;form&gt;</code> e adicioná-lo ao seu arquivo <code>index.html</code>. Você precisa ter três coisas nesse elemento de formulário:</p><ol><li>Um atributo <code>action</code></li><li>Um atributo <code>method</code></li><li>Atributos <code>name</code> em todos os elementos <code>&lt;input&gt;</code> dentro do formulário</li></ol><pre><code>&lt;form action="/quotes" method="POST"&gt;
	&lt;input type="text" placeholder="nome" name="nome"&gt;
	&lt;input type="text" placeholder="citação" name="citação"&gt;
	&lt;button type="submit"&gt;Enviar&lt;/button&gt;
&lt;/form&gt;</code></pre><p>O atributo <code>action</code> informa ao navegador para onde navegar em nossa aplicação Express. Neste caso, estamos navegando para <code>/quotes</code>. O atributo <code>method</code> informa ao navegador qual solicitação enviar. Neste caso, é uma solicitação POST.</p><p>Em nosso servidor, podemos lidar com essa solicitação POST com um método post que o Express fornece. Ele recebe os mesmos argumentos que o método GET:</p><pre><code>app.post('/quotes', (req, res) =&gt; {  console.log('Oláááááááááááááá!')})</code></pre><p>Reinicie seu servidor (espero que você tenha configurado o Nodemon para que ele reinicie automaticamente) e atualize seu navegador. Em seguida, insira algo em seu elemento de formulário. Você deverá ver Oláááááááááááááá! em sua linha de comando.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_qsLmf8vEhBlhIfJj.png" class="kg-image" alt="0_qsLmf8vEhBlhIfJj" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_qsLmf8vEhBlhIfJj.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_qsLmf8vEhBlhIfJj.png 712w" width="712" height="76" loading="lazy"><figcaption>Você deverá ver <em>Helloooooooooooooooo!</em> ou Oláááááááááá</figcaption></figure><p>Ótimo, sabemos que o Express está lidando com o formulário para nós agora. A próxima pergunta é: como obtemos os valores de entrada com o Express?</p><p>Acontece que o Express não lida com a leitura de dados do elemento <code>&lt;form&gt;</code> por conta própria. Temos que adicionar outro pacote chamado <code>body-parser</code> para obter essa funcionalidade.</p><pre><code>$ npm install body-parser --save</code></pre><p>O Express nos permite adicionar <em>middlewares </em>como <code>body-parser</code> à nossa aplicação com o método <code>use</code>. Você ouvirá muito o termo <em>middleware</em> ao lidar com o Express. Essas coisas são basicamente <em>plug-ins</em> que alteram o objeto de solicitação ou resposta antes que eles sejam tratados por nossa aplicação. <strong>Certifique-se de colocar o <em>body-parser</em> antes de seus manipuladores CRUD!</strong></p><pre><code>const express = require('express')
const bodyParser= require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({extended: true}))
// Todos os outros manipuladores aqui...</code></pre><p>O método <code>urlencoded</code> dentro do <code>body-parser</code> informa ao <code>body-parser</code> para extrair dados do elemento <code>&lt;form&gt;</code> e adicioná-los à propriedade <code>body</code> no objeto de solicitação.</p><blockquote>Nota da tradução: nas versões mais recentes, é possível usar <code>express.json</code> no lugar de <code>body-parser</code> para fazer o <em>parsing</em> do documento, tornando desnecessária a requisição deste último. </blockquote><p>Agora, você deverá ver tudo no campo do formulário dentro do objeto <code>req.body</code>. Tente fazer um <code>console.log</code> e veja o que é!</p><pre><code>app.post('/quotes', (req, res) =&gt; {
  console.log(req.body)
})</code></pre><p>Você deverá obter um objeto semelhante ao seguinte em sua linha de comando:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_cmNU6GQhNS7BYsLT.png" class="kg-image" alt="0_cmNU6GQhNS7BYsLT" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_cmNU6GQhNS7BYsLT.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_cmNU6GQhNS7BYsLT.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Hmmm. Mestre Yoda falou! Vamos garantir que nos lembremos das palavras de Yoda. É importante. Queremos poder recuperá-las na próxima vez que carregarmos nossa página inicial.</p><p>É aqui que entra o banco de dados, o MongoDB.</p><h3 id="mongodb">MongoDB</h3><p>Primeiro, temos que instalar o MongoDB através do <code>npm</code> se quisermos usá-lo como nosso banco de dados.</p><pre><code>npm install mongodb --save</code></pre><p>Depois de instalado, podemos nos conectar ao MongoDB através do método connect do Mongo.Client, conforme mostrado no código abaixo:</p><pre><code>const MongoClient = require('mongodb').MongoClient</code></pre><pre><code>MongoClient.connect('link-para-o-mongodb', (err, database) =&gt; {
  // ... inicie o servidor
})</code></pre><p>A próxima parte é obter o link correto para nosso banco de dados. A maioria das pessoas armazenam seus bancos de dados em serviços em nuvem como o <a href="https://mongolab.com/">MongoLab</a>. Faremos o mesmo também.</p><p>Então, vá em frente e crie uma conta no MongoLab. (É grátis). Depois de terminar, crie uma nova implantação do MongoDB e defina o plano como <em>sandbox</em>.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_YujCEhVovfSgPH_j.png" class="kg-image" alt="0_YujCEhVovfSgPH_j" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_YujCEhVovfSgPH_j.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_YujCEhVovfSgPH_j.png 777w" sizes="(min-width: 720px) 720px" width="777" height="1266" loading="lazy"></figure><p>Depois de terminar de criar a implantação, vá até ela e crie um usuário de banco de dados e uma senha de banco de dados. <strong>Lembre-se do usuário e da senha do banco de dados</strong> porque você os usará para conectar o banco de dados que acabou de criar.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_pPeHMc1EqlQRAqKU.png" class="kg-image" alt="0_pPeHMc1EqlQRAqKU" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_pPeHMc1EqlQRAqKU.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_pPeHMc1EqlQRAqKU.png 800w" sizes="(min-width: 720px) 720px" width="800" height="162" loading="lazy"></figure><p>Finalmente, pegue o URL do MongoDB e adicione-a ao seu método <code>MongoClient.connect</code>. Certifique-se de usar seu usuário e senha do banco de dados!</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_x5a1AplcCRyq712P.png" class="kg-image" alt="0_x5a1AplcCRyq712P" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_x5a1AplcCRyq712P.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_x5a1AplcCRyq712P.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><pre><code>MongoClient.connect('seu-url-do-mongodb', (err, database) =&gt; {
  // ... faça algo aqui
})</code></pre><p>Em seguida, queremos iniciar nossos servidores apenas quando o banco de dados estiver conectado. Portanto, vamos mover <code>app.listen</code> para dentro do método <code>connect()</code>. Também vamos criar uma variável <code>db</code> para nos permitir usar o banco de dados quando lidarmos com solicitações do navegador.</p><pre><code>var db</code></pre><pre><code>MongoClient.connect('sua-url-do-mongodb', (err, database) =&gt; {
  if (err) return console.log(err)
  db = database  
  app.listen(3000, () =&gt; {
    console.log('escutando na porta 3000')
  })
})</code></pre><p>Terminamos de configurar o MongoDB. Agora, vamos criar uma coleção de citações para armazenar citações para nossa aplicação.</p><p>A propósito, <strong>uma coleção é um local nomeado para armazenar coisas</strong>. Você pode criar quantas coleções quiser. Podem ser coisas como "produtos", "citações", "mantimentos" ou quaisquer outros rótulos que você escolher.</p><p>Podemos criar a coleção de citações usando a <em>string </em><code>quotes</code> ao chamar o método <code>db.collection()</code> do MongoDB. Ao criar a coleção de citações, também podemos salvar nossa primeira entrada no MongoDB com o método save simultaneamente.</p><p><strong>Depois de terminarmos de salvar, temos que redirecionar o usuário para algum lugar</strong> (ou ele ficará preso esperando para sempre que nosso servidor se mova). Nesse caso, vamos redirecioná-los de volta para <code>/</code>, o que faz com que seus navegadores recarreguem.</p><pre><code>app.post('/quotes', (req, res) =&gt; {
  db.collection('quotes').save(req.body, (err, result) =&gt; {
    if (err) return console.log(err)
    console.log('salvo no banco de dados')
    res.redirect('/')
    })
})</code></pre><p>Agora, se você inserir algo no elemento, poderá ver uma entrada em sua coleção do MongoDB.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_XEGKefxWJP6SlQpM.png" class="kg-image" alt="0_XEGKefxWJP6SlQpM" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_XEGKefxWJP6SlQpM.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_XEGKefxWJP6SlQpM.png 792w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Uhuuu! Já que já temos algumas citações na coleção, por que não tentar mostrá-las ao nosso usuário quando ele acessar nossa página?</p><h3 id="mostrando-cita-es-aos-usu-rios">Mostrando citações aos usuários</h3><p>Temos que fazer duas coisas para mostrar as citações armazenadas no MongoLab aos nossos usuários.</p><ol><li>Obter citações do MongoLab</li><li>Usar um mecanismo de template para exibir as citações</li></ol><p>Vamos passo a passo.</p><p>Podemos obter as citações do MongoLab usando o método find que está disponível no método <code>collection</code>.</p><pre><code>app.get('/', (req, res) =&gt; {
	var cursor = db.collection('quotes').find()
})</code></pre><p>O método <code>find</code><em> </em>retorna um cursor (um objeto do Mongo) que provavelmente não faz sentido se você fizer console.log dele.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_IQHvKZ7Bd5mIlxT0.png" class="kg-image" alt="0_IQHvKZ7Bd5mIlxT0" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_IQHvKZ7Bd5mIlxT0.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_IQHvKZ7Bd5mIlxT0.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>A boa notícia é que esse objeto cursor contém todas as citações do nosso banco de dados. Ele também contém várias outras propriedades e métodos que nos permitem trabalhar com dados facilmente. Um desses métodos é o método <code>toArray()</code>.</p><p><strong>O método toArray</strong> recebe uma função de <em>callback</em> que nos permite fazer coisas com as citações que recuperamos do MongoLab. Vamos tentar fazer um <code>console.log()</code> para os resultados e ver o que obtemos!</p><pre><code>db.collection('quotes').find().toArray(function(err, results) {
	console.log(results)  // enviar arquivo HTML preenchido com citações aqui
})</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_6McLqpFyG1xA5of1.png" class="kg-image" alt="0_6McLqpFyG1xA5of1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_6McLqpFyG1xA5of1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_6McLqpFyG1xA5of1.png 782w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Ótimo! Agora, você vê um <em>array</em> de citações (eu só tenho uma agora). Concluímos a primeira parte — obter dados do MongoLab. A próxima parte é gerar um HTML que contenha todas as nossas citações.</p><p>Não podemos servir nosso arquivo <code>index.html</code> e esperar que as citações apareçam magicamente porque não há como adicionar conteúdo dinâmico a um arquivo HTML. O que podemos fazer em vez disso é usar mecanismos de template para nos ajudar. Alguns mecanismos de <em>template</em> populares incluem Jade, Embedded JavaScript e Nunjucks.</p><p>Escrevi extensivamente sobre o como e o porquê dos mecanismos de <em>template </em>em uma <a href="https://zellwk.com/blog/nunjucks-with-gulp/">artigo separado</a> (em inglês). Você pode querer dar uma olhada se não tiver ideia do que são mecanismos de <em>template</em>. Eu pessoalmente uso (e recomendo) Nunjucks como meu mecanismo de <em>template </em>de escolha. Sinta-se à vontade para conferir o artigo para descobrir o porquê.</p><p>Para este tutorial, vamos usar <a href="https://ejs.co/">Embedded JavaScript - ejs</a> como nosso mecanismo de <em>template </em>porque é o mais fácil para começar. Você o achará familiar desde o início, pois já conhece HTML e JavaScript.</p><p>Podemos usar o EJS primeiro instalando-o e, em seguida, definindo o mecanismo de visualização no Express como ejs.</p><pre><code>$ npm install ejs --save</code></pre><pre><code>app.set('view engine', 'ejs')</code></pre><p>Depois que o mecanismo de visualização for definido, podemos começar a gerar o HTML com nossas citações. Esse processo também é chamado de <strong>renderização</strong>. Podemos usar o objeto render integrado ao objeto de resposta render para fazer isso. Ele tem a seguinte sintaxe:</p><pre><code>res.render(view, locals)</code></pre><p><strong>O primeiro parâmetro, views</strong>, é o nome do arquivo que estamos renderizando. Esse arquivo deve ser colocado dentro de uma pasta views.</p><p><strong>O segundo parâmetro, locals</strong>, é um objeto que passa dados para a visualização.</p><p>Vamos primeiro criar um arquivo <code>index.ejs</code> dentro da pasta views para que possamos começar a preencher os dados.</p><pre><code>$ mkdir views$ touch views/index.ejs</code></pre><p>Agora, coloque o seguinte código dentro de <code>index.ejs</code>.</p><pre><code>&lt;ul class="quotes"&gt;
	&lt;% for(var i=0; i&lt;quotes.length; i++) {%&gt;
		&lt;li class="quote"&gt;
      		&lt;span&gt;&lt;%= quotes[i].name %&gt;&lt;/span&gt;
      		&lt;span&gt;&lt;%= quotes[i].quote %&gt;&lt;/span&gt;
    	&lt;/li&gt;
	&lt;% } %&gt;
&lt;/ul&gt;</code></pre><p>Viu o que eu quis dizer quando disse que você o acharia familiar? No EJS, você pode escrever JavaScript dentro de tags <code>&lt;% e %&gt;</code>. Você também pode gerar JavaScript como strings se usar as tags <code>&lt;%= e %&gt;</code>.</p><p>Aqui, você pode ver que estamos basicamente percorrendo o array <em>quotes</em> e criando strings com <code>quotes[i].name</code> e <code>quotes[i].quote</code>.</p><p>Mais uma coisa a fazer antes de prosseguirmos com o arquivo <code>index.ejs</code>. Lembre-se de copiar o elemento <code>&lt;form&gt;</code> do arquivo <code>index.html</code> para esse arquivo também. O arquivo <code>index.ejs</code> completo até agora deve ser:</p><pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
	&lt;head&gt;
    	&lt;meta charset="UTF-8"&gt;
        &lt;title&gt;MEU APP&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
    	Que o Node e o Express estejam com você.
        &lt;ul class="quotes"&gt;
        	&lt;% for(var i=0; i&lt;quotes.length; i++) {%&gt;
            	&lt;li class="quote"&gt;
                	&lt;span&gt;&lt;%= quotes[i].name %&gt;&lt;/span&gt;
                    &lt;span&gt;&lt;%= quotes[i].quote %&gt;&lt;/span&gt;
                &lt;/li&gt;
            &lt;% } %&gt;
        &lt;/ul&gt;
        &lt;form action="/quotes" method="POST"&gt;
        	&lt;input type="text" placeholder="nome" name="nome"&gt;
            &lt;input type="text" placeholder="citação" name="citação"&gt;
            &lt;button type="submit"&gt;Enviar&lt;/button&gt;
        &lt;/form&gt;
     &lt;/body&gt;
&lt;/html&gt;</code></pre><p>Finalmente, temos que renderizar esse arquivo index.ejs ao lidar com a solicitação <strong>GET</strong>. Aqui, estamos definindo os resultados (um array) como o array <em>quotes</em> que usamos em index.ejs acima.</p><pre><code>app.get('/', (req, res) =&gt; {
	db.collection('quotes').find().toArray((err, result) =&gt; {
    	if (err) return console.log(err)    // renderiza index.ejs
        res.render('index.ejs', {quotes: result})
    })
})</code></pre><p>Agora, atualize seu navegador e você deverá ver as citações do Mestre Yoda.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_Wy8S2Yag15rpIOlt.png" class="kg-image" alt="0_Wy8S2Yag15rpIOlt" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/08/0_Wy8S2Yag15rpIOlt.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/08/0_Wy8S2Yag15rpIOlt.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Ah, você pode ter apenas uma citação se seguiu o tutorial passo a passo até esse ponto. O motivo pelo qual tenho várias citações é porque adicionei mais silenciosamente enquanto trabalhava na aplicação.</p><h3 id="conclus-o">Conclusão</h3><p>Cobrimos muito terreno em apenas 3 mil palavras! Aqui estão alguns marcadores para resumir tudo. Você...</p><ul><li>Criou um servidor Express</li><li>Aprendeu a executar operações CRIAR (CREATE) e LER (READ)</li><li>Aprendeu a salvar e ler no MongoDB</li><li>Aprendeu a usar um mecanismo de <em>template</em> como o Embedded JS.</li></ul><p>Este artigo apareceu pela primeira vez no <a href="https://zellwk.com/blog/1/">blog do autor</a> (em inglês). Confira o blog se quiser ver mais artigos como este.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ O que é uma API e como ela funciona? APIs para iniciantes ]]>
                </title>
                <description>
                    <![CDATA[ Quando comecei a aprender a programar, o termo API sempre me assombrava. Eu não conseguia entender o que realmente significava porque ouvia as pessoas falando sobre APIs em diferentes contextos. O maior desafio era que eu não conseguia encontrar recursos para aprender sobre APIs em termos simples. Agora que sei ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/o-que-e-uma-api-e-como-ela-funciona-apis-para-iniciantes/</link>
                <guid isPermaLink="false">66872e9223266d03fc8b83ba</guid>
                
                    <category>
                        <![CDATA[ API ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Mon, 29 Jul 2024 12:49:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/api-article.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-apis-work/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">What is an API and How Does it Work? APIs for Beginners</a>
      </p><p>Quando comecei a aprender a programar, o termo API sempre me assombrava. Eu não conseguia entender o que realmente significava porque ouvia as pessoas falando sobre APIs em diferentes contextos.</p><p>O maior desafio era que eu não conseguia encontrar recursos para aprender sobre APIs em termos simples.</p><p>Agora que sei como as APIs funcionam, decidi escrever este guia para qualquer iniciante que tenha dificuldade para entender esse tópico que não é tão complicado, mas que ainda é confuso, em desenvolvimento para a web e em engenharia de software.</p><h2 id="o-que-uma-api">O que é uma API?</h2><p>API significa Interface de Programação de Aplicações. A aplicação pode ser qualquer software que execute uma tarefa específica e a interface é um ponto onde duas aplicações se comunicam.</p><p>Uma aplicação atua como <em>client</em> e o outro atua como servidor. Um <em>client</em> solicita algum recurso (por exemplo, uma foto) e o servidor envia essa foto para o <em>client</em>.</p><p>O <em>client</em>, aqui, pode ser seu celular, computador <em>desktop</em> ou <em>laptop</em> ou qualquer dispositivo que você usa para navegar na internet. O servidor é um computador maior, que armazena os dados que você deseja (uma foto, no nosso caso).</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/unsplash-1.png" class="kg-image" alt="unsplash-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/unsplash-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/unsplash-1.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/unsplash-1.png 1353w" sizes="(min-width: 720px) 720px" width="1353" height="626" loading="lazy"></figure><p>Suponha que eu queira uma fotografia da natureza para enviar para meu blog de viagens. Eu posso ir ao site do Unsplash, digitar "natureza" na barra de pesquisa e ele retornará um grande número de fotografias da natureza.</p><p>Essa é uma API trabalhando nos bastidores para fazer a conversa entre o Unsplash e eu acontecer.</p><h2 id="como-as-apis-funcionam">Como as APIs funcionam?</h2><p>Os computadores seguem um protocolo para se comunicar uns com os outros. Um protocolo nada mais é do que um conjunto de regras que os computadores seguem para se comunicar. Qualquer computador que não siga o protocolo quebra o fio da comunicação.</p><p>Você pode ter usado Bluetooth para compartilhar dados no passado. Bluetooth nada mais é do que um protocolo para dispositivos móveis se comunicarem entre eles a uma distância menor.</p><p>Quando você pede ao seu amigo para enviar fotos de sua última viagem, seu dispositivo atua como <em>client</em> e o dispositivo do seu amigo (aquele que envia as fotos) é o servidor.</p><p>Esse é apenas um exemplo de protocolo. Temos um grande número de protocolos no mundo da ciência da computação – um para quase tudo.</p><p>Na web, usamos o protocolo HTTP (em inglês, <em>Hyper Text Transfer Protocol</em>). As APIs disponíveis na web usam o protocolo HTTP por vários motivos – é fácil de usar e é popular, por exemplo.</p><p>As comunicações que ocorrem pelo <strong>protocolo HTTP</strong> também são conhecidas como ciclo de solicitação-resposta porque é exatamente assim que o protocolo funciona. O <em>client</em> envia uma solicitação ao servidor e o servidor responde ao <em>client</em> em relação a essa solicitação.</p><p>Ao contrário dos humanos, os computadores precisam ser rígidos para se comunicarem uns com os outros ou eles quebram a comunicação. Por esse motivo, um <em>client</em> (computador/dispositivo solicitante) precisa de um conjunto de informações para enviar com a solicitação para que o servidor responda de acordo. Essas informações incluem:</p><ol><li>URL – um endereço da web onde você deseja fazer uma solicitação</li><li>Método – se você deseja dados já armazenados em algum lugar ou deseja salvar novos dados em um banco de dados</li><li>Cabeçalho – todas as informações relevantes sobre sua solicitação, incluindo em qual formato o dispositivo <em>client</em> espera receber os dados</li><li>Corpo – os dados reais da solicitação</li></ol><p>No nosso exemplo do Unsplash, o URL é <a href="https://unsplash.com/s/photos/nature">https://unsplash.com/s/photos/nature</a>. O método é GET, porque queremos que o servidor recupere imagens da natureza. O cabeçalho inclui informações como o formato que nosso computador espera obter e aceitar – como o idioma, o idioma do dispositivo, nosso sistema operacional e assim por diante. O corpo inclui os dados que precisamos enviar ao servidor (a palavra-chave natureza, por exemplo).</p><p>Existem quatro tipos de métodos para solicitações HTTP que abordaremos em breve. Por enquanto, saiba apenas que um método indica o que você deseja fazer com os dados disponíveis no servidor. Por exemplo, se você deseja esses dados como documentos ou se deseja salvar uma nova entrada em dados salvos em algum lugar.</p><p>Quando um <em>client</em> faz uma solicitação, o servidor responde a essa solicitação. A resposta pode ser os dados que o <em>client</em> solicitou ou um erro.</p><p>Assim como uma resposta, uma solicitação tem uma estrutura que inclui URL, código de status, cabeçalho e corpo. Em uma solicitação, temos um método, que possui quatro tipos. Na resposta, temos um código de status, que indica se uma solicitação foi aceita ou recusada.</p><h3 id="m-todos-http">Métodos HTTP</h3><p>Existem quatro métodos HTTP disponíveis e cada um tem sua funcionalidade exclusiva.</p><ol><li>GET: como já discutido, indica que o <em>client</em> está solicitando que os dados sejam enviados do servidor.</li><li>POST: esse método informa ao servidor que o <em>client</em> deseja criar uma entrada em um banco de dados. Por exemplo, salvar uma nova postagem em um blog em um banco de dados de todos os blogs anteriores.</li><li>DELETE: como o nome em inglês sugere, o <em>client</em> deseja excluir um registro de dados de um banco de dados.</li><li>PUT: esse método é usado quando um <em>client</em> deseja atualizar ou editar um registro de dados. Por exemplo, alterar sua senha do Facebook.</li></ol><h3 id="c-digos-de-status-http">Códigos de status HTTP</h3><p>Existe uma lista enorme de códigos de status HTTP, mas vamos dar uma olhada em alguns dos mais comuns:</p><ol><li>200 OK: indica que a solicitação foi atendida com sucesso pelo servidor</li><li>201 CREATED: a entrada de dados cuja criação você solicitou foi criada</li><li>404 NOT FOUND: indica que o recurso que você solicitou não foi encontrado pelo servidor</li><li>500 INTERNAL SERVER ERROR: significa que ocorreu um erro no lado do servidor e que ele não pôde atender à sua solicitação</li></ol><p>Não há necessidade de memorizar esses códigos de status, pois a lista é enorme e você os aprenderá inconscientemente à medida que os encontrar em sua jornada de desenvolvimento.</p><p>Ainda assim, existem vários códigos de status que indicam uma resposta genérica, como você pode ver aqui:</p><ol><li>100s: respostas informativas, indicando o progresso da solicitação</li><li>200s: sucesso, indicando o sucesso da solicitação</li><li>300s: redirecionamento, indicando que a solicitação teve que ser redirecionada para outro lugar</li><li>400s: erros do <em>client</em>, indicando erros que ocorreram no lado do <em>client</em></li><li>500s: erros do servidor, quando o servidor falha ao responder a uma solicitação válida do <em>client</em></li></ol><h2 id="tipos-de-apis">Tipos de APIs</h2><p>Você se lembra quando eu disse que ficava confusa quando as pessoas falavam sobre APIs em diferentes contextos? Isso ocorre porque também temos diferentes tipos de APIs disponíveis.</p><p>As que falamos neste artigo são APIs da web que usam o protocolo HTTP. Os desenvolvedores podem usá-las para criar uma melhor experiência do usuário para seus usuários.</p><p>Outros tipos incluem as APIs internas, que estão ocultas de usuários externos e que são usadas apenas dentro de uma empresa.</p><p>Existem também APIs abertas, que estão disponíveis para serem usadas por qualquer pessoa gratuitamente (como a <a href="https://openweathermap.org/api">OpenWeatherMap API</a>, a API de mapa meteorológico aberto). Você pode ter APIs de parceiros, que são compartilhadas apenas entre parceiros de negócios para realizar suas tarefas de negócios e APIs compostas, que combinam sequencialmente várias solicitações de API em uma única chamada de API para reduzir a carga do servidor e criar uma experiência mais rápida.</p><h3 id="recursos-para-aprender-mais-sobre-apis-">Recursos para aprender mais sobre APIs:</h3><p>Se você quiser aprender mais sobre a criação de APIs, <a href="https://www.freecodecamp.org/news/rest-api-design-best-practices-build-a-rest-api/">aqui há um texto para começar</a> (em inglês).</p><p>Aqui está um tutorial sobre <a href="https://www.freecodecamp.org/news/what-is-an-api-and-how-to-test-it/">tipos de APIs, ferramentas de testes e documentação</a> (em inglês).</p><p>Aqui está uma <a href="https://www.freecodecamp.org/news/fetch-api-cheatsheet/">ficha informativa sobre a Fetch API</a> (em inglês), para você começar a aprender mais sobre ela.</p><h2 id="conclus-o">Conclusão</h2><p>Uma API é uma interface para dois computadores se comunicarem para realizar tarefas na internet.</p><p>As APIs da web seguem o protocolo HTTP para se comunicarem. Esse protocolo possui uma estrutura específica de solicitação e resposta.</p><p>Existem diferentes métodos para realizar diferentes tarefas e vários códigos de status estão disponíveis. Eles indicam se a solicitação foi bem-sucedida, recusada ou está em estado pendente.</p><p>Interessado em se conectar pelo LinkedIn? <a href="https://www.linkedin.com/in/tooba-jamal/">Fale com a autora por lá</a>.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A grande competição entre os termos usados em programação ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Preethi Kasireddy Imperativo x Declarativo, Puro x Impuro, Estático x Dinâmico. Terminologias como essas são salpicadas por várias publicações em blogs de programação, palestras em conferências, artigos e livros didáticos. Porém, você não deve se deixar intimidar por esse vocabulário. Vamos examinar e desvendar alguns desses conceitos para ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/a-grande-competicao-entre-os-termos-usados-em-programacao/</link>
                <guid isPermaLink="false">668de2da23266d03fc8b8675</guid>
                
                    <category>
                        <![CDATA[ Programação ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Sun, 28 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/1_d55K-aHn7CPPe-M83e_n5g.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/programming-mental-models-47ccc65eb334/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">The Great Programming Jargon Bake-off</a>
      </p><p>Escrito por: Preethi Kasireddy</p><p>Imperativo x Declarativo, Puro x Impuro, Estático x Dinâmico.</p><p>Terminologias como essas são salpicadas por várias publicações em blogs de programação, palestras em conferências, artigos e livros didáticos.</p><p>Porém, você não deve se deixar intimidar por esse vocabulário. Vamos examinar e desvendar alguns desses conceitos para que você possa entender sobre o que todos esses desenvolvedores ao seu redor estão falando.</p><h3 id="tipagem-est-tica-x-din-mica">Tipagem estática x dinâmica</h3><p>Isso se trata de quando a informação de <em>tipo </em>é adquirida — seja no momento da compilação ou em tempo de execução.</p><p>Você pode usar essa informação de tipo para detectar erros de tipo. Um erro de tipo ocorre quando um valor não é do tipo esperado.</p><h4 id="verifica-o-de-tipo-est-tica">Verificação de tipo estática</h4><p>É o processo de verificar a segurança de tipo de um programa com base na análise do código-fonte do programa. Em outras palavras, a verificação de tipo ocorre no momento da compilação, permitindo que erros de tipo sejam detectados mais cedo.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/GD1KhgaCFzdaiATtb-MnKj3L-ZXUiIoydrc8.png" class="kg-image" alt="GD1KhgaCFzdaiATtb-MnKj3L-ZXUiIoydrc8" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/GD1KhgaCFzdaiATtb-MnKj3L-ZXUiIoydrc8.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/GD1KhgaCFzdaiATtb-MnKj3L-ZXUiIoydrc8.png 800w" sizes="(min-width: 720px) 720px" width="800" height="522" loading="lazy"><figcaption>À direita: os tipos de x e y são verificados no momento da compilação para garantir que as duas variáveis são do tipo <em>int</em>/Abaixo: quando você instancia a classe <em>Point</em>, os tipos de x e de y são verificados no momento da compilação para garantir que são do tipo <em>int</em></figcaption></figure><h4 id="verifica-o-de-tipo-din-mica">Verificação de tipo dinâmica</h4><p>O processo de verificar a segurança de tipo de um programa em tempo de execução. Com a verificação de tipo dinâmica, os erros de tipo ocorrem em tempo de execução.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/r0NYTBqJGSc8XLHqK8Et-rMW0tkOd3VI7I5u.png" class="kg-image" alt="r0NYTBqJGSc8XLHqK8Et-rMW0tkOd3VI7I5u" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/r0NYTBqJGSc8XLHqK8Et-rMW0tkOd3VI7I5u.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/r0NYTBqJGSc8XLHqK8Et-rMW0tkOd3VI7I5u.png 800w" sizes="(min-width: 720px) 720px" width="800" height="600" loading="lazy"><figcaption>À direita: os tipos de x e y são determinados no momento da execução/Abaixo: quando você instancia a classe <em>Point</em>, os tipos de x e de y não são verificados. Se você passar um valor de <em>string</em> para y, o programa o aceitará (e pode lançar um erro de tempo de execução se y for usado indevidamente)</figcaption></figure><h3 id="tipagem-forte-x-fraca">Tipagem forte x fraca</h3><p>É importante observar que forte x fraca não tem um significado técnico sobre o qual todos universalmente concordam. Por exemplo, mesmo que Java seja tipado estaticamente, toda vez que você usa reflexão ou <em>cast</em>, você está adiando a verificação de tipo para a execução.</p><p>Da mesma maneira, a maioria das linguagens fortemente tipadas ainda converterá automaticamente entre inteiros e ponto flutuante. Portanto, você deve evitar usar esses termos porque chamar um sistema de tipagem "forte" ou "fraca", por si só, não diz muito.</p><h4 id="tipagem-forte">Tipagem forte</h4><p>Em uma linguagem fortemente tipada, o tipo de uma construção não muda — um <code>int</code> é sempre um <code>int</code> e tentar usá-lo como uma <code>string</code> resultará em um erro.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/qQuFtQHI0nVeCYYPFiwmtPXD0I0VtUfQS3VH.png" class="kg-image" alt="qQuFtQHI0nVeCYYPFiwmtPXD0I0VtUfQS3VH" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/qQuFtQHI0nVeCYYPFiwmtPXD0I0VtUfQS3VH.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/qQuFtQHI0nVeCYYPFiwmtPXD0I0VtUfQS3VH.png 800w" sizes="(min-width: 720px) 720px" width="800" height="460" loading="lazy"></figure><h4 id="tipagem-fraca">Tipagem fraca</h4><p>Tipagem fraco significa que o tipo de uma construção pode mudar dependendo do contexto. Por exemplo, em uma linguagem de tipagem fraca, a string "123" pode ser tratada como o número 123 se você adicionar outro número a ela.</p><p>Isso geralmente significa que o sistema de tipos pode ser subvertido (invalidando quaisquer garantias) porque você pode converter um valor de um tipo para outro.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/iKBgNAycyEVpLytn2tivoY3U0wN-osYulEJr.png" class="kg-image" alt="iKBgNAycyEVpLytn2tivoY3U0wN-osYulEJr" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/iKBgNAycyEVpLytn2tivoY3U0wN-osYulEJr.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/iKBgNAycyEVpLytn2tivoY3U0wN-osYulEJr.png 800w" sizes="(min-width: 720px) 720px" width="800" height="577" loading="lazy"><figcaption>Adicionar a <em>string</em> "4" à soma de 4 + 4 = 8 resulta na <em>string</em> "8" + "4" = "84". Assim, adicionar a <em>string </em>a um número causou o <em>casting </em>(a conversão) do número 8 para uma <em>string</em>.</figcaption></figure><h3 id="dados-mut-veis-x-imut-veis">Dados mutáveis x imutáveis</h3><h4 id="dados-imut-veis">Dados imutáveis</h4><p>Quando um objeto não pode ser modificado após sua criação, você pode dizer que ele é "imutável", que é outro modo de dizer "inalterável". Isso significa que você alocará um novo valor para cada alteração.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/D3tF-qLMqDUXzFdHRRXy9jZm5ZrZ-DJVxi-p.png" class="kg-image" alt="D3tF-qLMqDUXzFdHRRXy9jZm5ZrZ-DJVxi-p" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/D3tF-qLMqDUXzFdHRRXy9jZm5ZrZ-DJVxi-p.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/D3tF-qLMqDUXzFdHRRXy9jZm5ZrZ-DJVxi-p.png 800w" sizes="(min-width: 720px) 720px" width="800" height="397" loading="lazy"></figure><h4 id="dados-mut-veis">Dados mutáveis</h4><p>Quando você pode modificar um objeto após sua criação, ele é "mutável". Quando você tem uma referência a um objeto mutável, por exemplo, o conteúdo do objeto pode mudar.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/lKF181TAlPPvUz0ln8VLksubyCYCbs8ocB73.png" class="kg-image" alt="lKF181TAlPPvUz0ln8VLksubyCYCbs8ocB73" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/lKF181TAlPPvUz0ln8VLksubyCYCbs8ocB73.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/lKF181TAlPPvUz0ln8VLksubyCYCbs8ocB73.png 800w" sizes="(min-width: 720px) 720px" width="800" height="456" loading="lazy"><figcaption>A variável <em>person</em> é mutável. Assim, podemos atualizar a propriedade <em>age</em> (idade)</figcaption></figure><h3 id="fun-es-puras-x-impuras">Funções puras x impuras</h3><h4 id="fun-es-puras">Funções puras</h4><p>Uma função pura tem duas qualidades:</p><ol><li>Ela depende apenas da entrada fornecida — e não de nenhum estado externo que possa mudar durante sua avaliação ou entre chamadas.</li><li>Ela não causa nenhum efeito colateral semanticamente observável, como modificar um objeto global ou um parâmetro passado por referência.</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ir5sDGMoxckbC-wpR8JikApucz6DLkkPzGZx.png" class="kg-image" alt="ir5sDGMoxckbC-wpR8JikApucz6DLkkPzGZx" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ir5sDGMoxckbC-wpR8JikApucz6DLkkPzGZx.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ir5sDGMoxckbC-wpR8JikApucz6DLkkPzGZx.png 800w" sizes="(min-width: 720px) 720px" width="800" height="530" loading="lazy"><figcaption>A função depende somente das variáveis passadas explicitamente a ela, não alterando estados externos nem os argumentos passados a ela</figcaption></figure><h4 id="fun-es-impuras">Funções impuras</h4><p>Qualquer função que não atenda a esses dois requisitos para uma função pura é "impura".</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/J02vTF9q3BE9lIYoi2jV1QbJAqjRcMZJBw8L-1.png" class="kg-image" alt="J02vTF9q3BE9lIYoi2jV1QbJAqjRcMZJBw8L-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/J02vTF9q3BE9lIYoi2jV1QbJAqjRcMZJBw8L-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/J02vTF9q3BE9lIYoi2jV1QbJAqjRcMZJBw8L-1.png 800w" sizes="(min-width: 720px) 720px" width="800" height="534" loading="lazy"><figcaption>A função depende da variável global PI e altera o argumento de entrada <em>radii</em></figcaption></figure><h3 id="avalia-o-lenta-x-avalia-o-r-pida">Avaliação lenta x avaliação rápida</h3><h4 id="avalia-o-lenta">Avaliação lenta</h4><p>A avaliação lenta não avalia os argumentos da função a menos que seus valores sejam necessários para avaliar a própria chamada da função.</p><p>Em outras palavras, as expressões são avaliadas apenas quando ocorre a avaliação de outra expressão que depende da expressão atual.</p><p>A versão lenta das avaliações permite que os programas calculem estruturas de dados que são potencialmente <em>infinitas</em> sem travar.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/uxczq1DSf-SYP34fDk02eeBqbbEFaqwsUwP0.png" class="kg-image" alt="uxczq1DSf-SYP34fDk02eeBqbbEFaqwsUwP0" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/uxczq1DSf-SYP34fDk02eeBqbbEFaqwsUwP0.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/uxczq1DSf-SYP34fDk02eeBqbbEFaqwsUwP0.png 800w" sizes="(min-width: 720px) 720px" width="800" height="557" loading="lazy"><figcaption>Acima: vamos supor que temos uma função que filtra todos os números ímpares de 1 até o infinito e recebe os dez primeiros elementos/Abaixo: com a avaliação lenta, isso não é executado até que a operação que depende disso, <em>take</em>, é chamada.</figcaption></figure><h4 id="avalia-o-r-pida">Avaliação rápida</h4><p>A avaliação ávida — também conhecida como avaliação estrita — sempre avalia completamente os argumentos da função antes de invocar a função. Em outras palavras, uma expressão é avaliada assim que é vinculada a uma variável.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/SHUGZI2HS4n8mSPAWoUfWySxt8D4X0N5CXu-.png" class="kg-image" alt="SHUGZI2HS4n8mSPAWoUfWySxt8D4X0N5CXu-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/SHUGZI2HS4n8mSPAWoUfWySxt8D4X0N5CXu-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/SHUGZI2HS4n8mSPAWoUfWySxt8D4X0N5CXu-.png 800w" sizes="(min-width: 720px) 720px" width="800" height="258" loading="lazy"><figcaption>Com a avaliação rápida, a função <em>range </em>tentará executar por inteiro antes de enviar seu resultado a <em>take</em>, o que leva a um <em>loop </em>infinito.</figcaption></figure><h3 id="declarativo-x-imperativo">Declarativo x imperativo</h3><h4 id="programa-o-declarativa">Programação declarativa</h4><p>Programas declarativos expressam um conjunto de operações sem revelar como são implementadas ou como os dados fluem através delas. Eles se concentram em "o que" o programa deve realizar (usando expressões para descrever a lógica) em vez de "como" o programa deve alcançar o resultado.</p><p>Um exemplo de programação declarativa é o SQL. As consultas SQL são compostas por instruções que descrevem como deve ser o resultado de uma consulta, enquanto abstraem o processo interno de como os dados são recuperados:</p><pre><code class="language-sql">SELECT EMP_ID, FIRST_NAME, LAST_NAMEFROM EMPLOYEES WHERE CITY = ‘SAN FRANCISCO’ ORDER BY EMP_ID;</code></pre><p>Aqui está um exemplo de código declarativo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/KJkzhjbfo5EYE2flsvDS9gT0JqAIcKcfklcA.png" class="kg-image" alt="KJkzhjbfo5EYE2flsvDS9gT0JqAIcKcfklcA" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/KJkzhjbfo5EYE2flsvDS9gT0JqAIcKcfklcA.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/KJkzhjbfo5EYE2flsvDS9gT0JqAIcKcfklcA.png 761w" sizes="(min-width: 720px) 720px" width="761" height="655" loading="lazy"><figcaption>Usa <em>funções de ordem superior</em> para expressar <em>o que</em> o programa faz, não <em>como</em> o faz.</figcaption></figure><h4 id="programa-o-imperativa">Programação imperativa</h4><p>A programação imperativa concentra-se em descrever como um programa deve alcançar um resultado usando instruções que especificam o fluxo de controle ou alterações de estado. Ela usa uma sequência de instruções para calcular um resultado.</p><p>Aqui está um exemplo de código imperativo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/nWC5LzuByaWllxXsVXJS1pcYokOWlKxkZor2.png" class="kg-image" alt="nWC5LzuByaWllxXsVXJS1pcYokOWlKxkZor2" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/nWC5LzuByaWllxXsVXJS1pcYokOWlKxkZor2.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/nWC5LzuByaWllxXsVXJS1pcYokOWlKxkZor2.png 800w" sizes="(min-width: 720px) 720px" width="800" height="544" loading="lazy"><figcaption>Informa ao programa como executar a tareda usando <em>loops</em> e instruções <em>if-else</em></figcaption></figure><h3 id="com-estado-x-sem-estado">Com estado x sem estado</h3><p>Um estado (em inglês, <em>state</em>) é uma sequência de valores calculados progressivamente, que contém os resultados intermediários de um cálculo.</p><h4 id="com-estado">Com estado</h4><p>Programas com estado (do inglês., <em>stateful</em>) têm algum mecanismo para acompanhar e atualizar o estado. Eles têm alguma memória do passado e lembram transações anteriores que podem afetar a transação atual.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/2MCDlKSDdS9imKRxHECiksWO2jjxjeV1ndVB.png" class="kg-image" alt="2MCDlKSDdS9imKRxHECiksWO2jjxjeV1ndVB" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/2MCDlKSDdS9imKRxHECiksWO2jjxjeV1ndVB.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/2MCDlKSDdS9imKRxHECiksWO2jjxjeV1ndVB.png 782w" sizes="(min-width: 720px) 720px" width="782" height="646" loading="lazy"><figcaption>Essa função tem conhecimento do passado. Ela sabe o valor da variável <em>count</em>.</figcaption></figure><h4 id="sem-estado">Sem estado</h4><p>Programas sem estado (do inglês, <em>stateless</em>), por outro lado, não acompanham o estado. Não há memória do passado. Cada transação é realizada como se estivesse sendo feita pela primeira vez. Programas <em>stateless</em> darão a mesma resposta para o mesmo pedido, função ou chamada de método — todas as vezes.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/O4aqQxCiZF-tsYmo4yl34wrLs8wGOsWODvy3.png" class="kg-image" alt="O4aqQxCiZF-tsYmo4yl34wrLs8wGOsWODvy3" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/O4aqQxCiZF-tsYmo4yl34wrLs8wGOsWODvy3.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/O4aqQxCiZF-tsYmo4yl34wrLs8wGOsWODvy3.png 800w" sizes="(min-width: 720px) 720px" width="800" height="534" loading="lazy"><figcaption>Essa função não tem conhecimento do passado. A variável <em>count</em> é passada como um parâmetro e a função simplesmente retorna um resultado a partir daquilo que é passado para ela.</figcaption></figure><h3 id="funcional-x-orientada-a-objetos">Funcional x orientada a objetos</h3><h4 id="funcional">Funcional</h4><p>A programação funcional é um paradigma que enfatiza o uso de funções. O objetivo da programação funcional é usar funções para abstrair fluxos de controle e operações em dados, evitando efeitos colaterais.</p><p>Então, a programação funcional usa funções puras e evita dados mutáveis, o que, por sua vez, fornece <em>transparência referencial</em>.</p><p>Uma função tem transparência referencial quando você pode substituir livremente uma expressão por seu valor e não mudar o comportamento do programa. Dito de um modo um pouco diferente: para uma determinada entrada, ele sempre retorna os mesmos resultados.</p><p>Alguns exemplos de linguagens que enfatizam a programação funcional incluem Haskell, Lisp, Clojure e Elm. Você pode, contudo, usar conceitos de programação funcional na maioria das linguagens, incluindo em JavaScript.</p><h4 id="orientada-a-objetos">Orientada a objetos</h4><p>O paradigma de programação orientada a objetos enfatiza o uso de objetos. Isso resulta em programas que são feitos de objetos que interagem entre si. Esses objetos podem conter dados (na forma de campos ou atributos) e comportamento (na forma de métodos).</p><p>É um estilo de particionamento (ou encapsulamento) do estado de um programa através de objetos para tornar a análise do efeito das mudanças tratável [1].</p><p>Além disso, programas orientados a objetos usam herança e/ou composição como seus principais mecanismos para reutilização de código. Herança significa que uma nova classe pode ser definida em termos de classes existentes especificando apenas como a nova classe é diferente. Representa um relacionamento "é um" (por exemplo, uma classe <code>Pássaro</code> que estende uma classe <code>Animal</code>). A composição, por outro lado, é quando as classes contêm instâncias de outras classes que implementam a funcionalidade desejada. Representa um relacionamento "tem um" (por exemplo, uma classe <code>Pássaro</code> tem uma instância de uma classe <code>Asa</code> como membro).</p><p>O polimorfismo também é um mecanismo importante para a reutilização de código na programação orientada a objetos. É quando uma linguagem pode processar objetos de maneira diferente dependendo de seu tipo de dados ou classe.</p><p>Alguns exemplos de linguagens que enfatizam a programação orientada a objetos incluem Java, C++, Ruby. Novamente, você pode aplicar esses conceitos na maioria das linguagens, incluindo em JavaScript.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/N8MHF9tH7WY137DollJShA9icCiaduLFJS9O.png" class="kg-image" alt="N8MHF9tH7WY137DollJShA9icCiaduLFJS9O" width="578" height="655" loading="lazy"><figcaption>Comentários em ordem (de cima para baixo): Métodos de instâncias usam "this" para acessar os dados do objeto/Herança/Dados mutáveis</figcaption></figure><h3 id="determin-stico-x-n-o-determin-stico">Determinístico x não determinístico</h3><h4 id="determin-stico">Determinístico</h4><p>Programas determinísticos sempre retornam o mesmo resultado sempre que são chamados com um conjunto específico de valores de entrada e o mesmo estado fornecido.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/QZcUv8Ergv0DU4N3SSrR6SFbajhNRXzagcTr.png" class="kg-image" alt="QZcUv8Ergv0DU4N3SSrR6SFbajhNRXzagcTr" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/QZcUv8Ergv0DU4N3SSrR6SFbajhNRXzagcTr.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/QZcUv8Ergv0DU4N3SSrR6SFbajhNRXzagcTr.png 800w" sizes="(min-width: 720px) 720px" width="800" height="416" loading="lazy"><figcaption>Não importa o número de vezes que invocarmos a função <em>add</em>, os resultados sempre serão os mesmos.</figcaption></figure><h4 id="n-o-determin-stico">Não determinístico</h4><p>Programas não determinísticos podem retornar resultados diferentes cada vez que são chamados, mesmo com o mesmo conjunto específico de valores de entrada e estado inicial.</p><p>O não determinismo é uma propriedade de qualquer sistema concorrente — ou seja, qualquer sistema em que várias tarefas podem acontecer ao mesmo tempo, executando em diferentes <em>threads</em>. Um algoritmo concorrente que está alterando o estado pode se comportar de maneira diferente a cada vez, dependendo de qual <em>thread </em>o agendador decidir executar.</p><p>Por exemplo:</p><pre><code>declare Xthread X=1 endthread X=2 end</code></pre><p>A ordem de execução das duas <em>threads </em>não é fixa. Não sabemos se X será vinculado a 1 ou 2. O sistema escolherá durante a execução do programa, sendo livre para escolher qual <em>thread </em>executar primeiro.</p><p>Outro exemplo de não determinismo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/V0yGj2uPPh5HUKf25kTgQiGZwLG8eAsRjkXM.png" class="kg-image" alt="V0yGj2uPPh5HUKf25kTgQiGZwLG8eAsRjkXM" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/V0yGj2uPPh5HUKf25kTgQiGZwLG8eAsRjkXM.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/V0yGj2uPPh5HUKf25kTgQiGZwLG8eAsRjkXM.png 800w" sizes="(min-width: 720px) 720px" width="800" height="569" loading="lazy"><figcaption>Temos dois resultados possíveis para os valores resultantes de <em>a</em> e de <em>b</em>, dependendo de qual chamada de API é retornada primeiro./Se a primeira chamada de API retorna antes da segunda, foo será invocada antes de bar, <em>a</em> será 15 e <em>b</em> será 3. Caso contrário, <em>a</em> será 13 e <em>b</em> será 2.</figcaption></figure><h3 id="conclus-o">Conclusão</h3><p>Como sempre, seu <em>feedback </em>e sua contribuição são realmente importantes para mim. Você também pode conferir a <a href="https://prezi.com/fftgbgltl-6u/programming-models/?utm_campaign=share&amp;utm_medium=copy">apresentação do Prezi</a> que criei para este artigo.</p><p>[1] Um agradecimento especial a <a href="https://twitter.com/kentbeck">Kent Beck</a> por sua contribuição para este artigo.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Já programamos há milhares de anos ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Tautvilas Mečinskas Programas de computador estão por toda parte. Interagimos com eles todos os dias. Parece que os softwares estão se tornando cada vez mais importantes para a nossa sociedade. Por que, no entanto, achamos os programas tão necessários? Por que e quando começamos a programar? Qual é ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/ja-programamos-ha-milhares-de-anos/</link>
                <guid isPermaLink="false">668dda5023266d03fc8b866e</guid>
                
                    <category>
                        <![CDATA[ Programação ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Fri, 26 Jul 2024 00:59:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/1_baG6RijcVa8LysywkCpN8g.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/what-is-programming-22a72ef4fd02/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">We have been programming for thousands of years</a>
      </p><p>Escrito por: Tautvilas Mečinskas</p><p>Programas de computador estão por toda parte. Interagimos com eles todos os dias. Parece que os softwares estão se tornando cada vez mais importantes para a nossa sociedade. Por que, no entanto, achamos os programas tão necessários? Por que e quando começamos a programar? Qual é a essência da programação? Essas perguntas podem parecer triviais, mas sinto que hoje ainda não temos uma boa definição do que é programação. Talvez este artigo possa ajudar a mudar isso.</p><p>É bastante difícil definir programação porque ela é muito diversa. Pode-se programar jogos, aplicações para dispositivos móveis, sites, compiladores, simulações e muito mais. Nesse caso, pode ser útil começar eliminando algumas ideias preconcebidas e esclarecer o que a programação não é.</p><p><strong>Programação não é ciência.</strong> A ciência é a arte de examinar o mundo e descobrir padrões repetitivos nele. O método científico consiste em fazer uma hipótese e, em seguida, realizar experimentos para provar ou rejeitá-la. Não usamos esse método na programação – portanto, não é ciência. A programação não se trata de descoberta, mas de criatividade.</p><p><strong>Programação não é matemática.</strong> Sim, há um aspecto matemático na programação. Algumas partes dos programas podem ser expressas como funções matemáticas. Escrever um gerador de números de Fibonacci é divertido, mas completamente inútil sem uma aplicação no mundo real. A matemática na programação é um meio para um fim, não uma parte central do processo.</p><p><strong>Programação não se trata de computadores eletrônicos.</strong> Computadores são muito úteis, mas não são necessários. Os programas podem ser entendidos e interpretados por seres humanos também. Portanto, os computadores são apenas ferramentas que usamos na programação.</p><p>Então, do que se trata a programação? O que se encontra dentro de todo programa, seja ele ou pequeno?</p><p>Abstrações.</p><p>O que é abstração? É uma imagem reduzida do mundo. Ao abstrair, estamos convertendo a realidade em símbolos que podem ser transmitidos como informação. A palavra <em>abstração</em> origina-se de duas palavras latinas, que são <em>abs</em>, que significa <em>longe de</em> e <em>trahere</em>, que significa <em>desenhar</em>. A tradução latina sugere que abstrair implica separar algo do todo.</p><p>O processo de abstração é único da programação? De fato, não. É algo que os humanos fazem há bastante tempo. Nossas ferramentas de abstração mais básicas são o mapa e o relógio.</p><p>Arqueólogos descobriram mapas de pedra que os humanos fizeram há mais de 14 mil anos. Isso mostra que a cartografia é fundamental para os humanos. É um processo de transformar território em símbolos abstratos. Um mapa é um modo de abstrair o espaço. É uma ferramenta que nos ajuda a fazer sentido do território ao nosso redor para que a navegação seja mais fácil.</p><p>Um relógio, por outro lado, é um modo de abstrair o tempo. Achamos a natureza contínua do tempo confusa. Por isso, a abstraímos. Os humanos dividem o tempo em intervalos discretos: anos, meses, dias, horas, minutos, segundos. Enquanto um mapa nos ajuda a navegar no espaço, um relógio nos ajuda a navegar no tempo. O predecessor do relógio - o calendário - surgiu há mais de 10 mil anos.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/K2-yzsletJjBjTnKwA7kvn4sz4Ynu1UOC3ou.jpg" class="kg-image" alt="K2-yzsletJjBjTnKwA7kvn4sz4Ynu1UOC3ou" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/K2-yzsletJjBjTnKwA7kvn4sz4Ynu1UOC3ou.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/K2-yzsletJjBjTnKwA7kvn4sz4Ynu1UOC3ou.jpg 800w" sizes="(min-width: 720px) 720px" width="800" height="587" loading="lazy"><figcaption>O gigante calendário solar de <a href="https://en.wikipedia.org/wiki/Chankillo">Chankillo</a> foi construído há 2.300 anos.</figcaption></figure><p>Já aos computadores são ferramentas que também lidam com abstrações. Há 3 partes fundamentais em todo computador:</p><ol><li>Relógio interno – a maneira de o computador abstrair o tempo</li><li>Memória – a maneira de o computador abstrair o espaço</li><li>Unidade de processamento – a maneira de o computador executar operações lógicas</li></ol><p>Esses recursos dão aos computadores uma maneira de entender abstrações espaciais e suas interações no tempo abstrato. Isso significa que os programas são abstrações do espaço e do tempo. A programação é a arte de criar abstrações do espaço e do tempo. Essas abstrações nos ajudam a navegar na realidade, sendo, por isso, tão importantes para nós.</p><p>Existe um método de abstração que é muito semelhante à programação, mas que é ainda mais antigo que mapas, relógios e calendários: a linguagem.</p><p>Se você olhar de perto para nossa linguagem natural, verá que ela possui todas as características necessárias para abstrair o espaço e o tempo.</p><p>Vamos analisar um exemplo de frase:</p><blockquote>Vá para o jardim e colha algumas flores esta noite.</blockquote><p><strong>O jardim</strong> e as <strong>flores</strong> referem-se a espaço abstrato. <strong>Esta noite</strong> é um modo de abstrair o tempo. <strong>E</strong> adiciona lógica à frase. <strong>Vá para</strong> e <strong>colha</strong> são sub-rotinas.</p><p>Podemos facilmente transformar a frase acima em JavaScript:</p><pre><code class="language-js">quandoNoite.then(()=&gt;voce.irPara(jardim)).then(()=&gt;voce.pegar(flor))
</code></pre><p>Essa frase pode ser entendida por um computador que tenha definições de <strong>noite</strong>, <strong>você</strong>, <strong>flores</strong> e as sub-rotinas necessárias definidas.</p><p>O problema da linguagem natural é que ela tem aplicações muito amplas. A linguagem pode ser usada não apenas para comunicar informações, mas também para expressar sentimentos e emoções. Os melhores exemplos de programas de linguagem natural pura são leis, regras de jogos de tabuleiro e manuais de instruções.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/xQoLcFFm2PL69Hv3LpF1saAtoAn86lGejQ99.jpg" class="kg-image" alt="xQoLcFFm2PL69Hv3LpF1saAtoAn86lGejQ99" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/xQoLcFFm2PL69Hv3LpF1saAtoAn86lGejQ99.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/xQoLcFFm2PL69Hv3LpF1saAtoAn86lGejQ99.jpg 640w" width="640" height="423" loading="lazy"><figcaption>O <a href="https://pt.wikipedia.org/wiki/C%C3%B3digo_de_Hamurabi">Código de Hamurabi</a> é um dos mais antigos programas de linguagem natural (foto de <a href="https://www.flickr.com/photos/prof_richard/">Richard</a> / <a href="https://creativecommons.org/licenses/by-nc-sa/2.0/">CC BY-NC-SA</a>)</figcaption></figure><p>As linguagens de programação, por outro lado, são rigorosas e só podem criar abstrações. Os computadores são projetados para interpretar essas abstrações de uma maneira muito específica e determinística.</p><p>Para escrever programas de computador, você precisa aprender a programar a linguagem natural em símbolos que o computador possa entender. Isso geralmente requer conhecimento intrincado da arquitetura do computador e da sintaxe da linguagem de computador escolhida. Portanto, se você quiser que um computador entenda suas abstrações de realidade, você precisa aprender a programar.</p><p>Os computadores são ferramentas que podem executar regras definidas em programas com velocidade e precisão sobre-humanas. Eles nos capacitam a construir abstrações complexas e multicamadas e a transformar nossos programas em mapas da realidade verdadeiramente dinâmicos e interativos.</p><p>De muitas maneiras, programar é algo que todos nós já sabemos fazer. O processo de abstração da realidade é fundamental para os seres humanos. A programação de computadores é apenas a maneira mais eficaz de se fazer isso.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Clean Code explicado: um guia prático para iniciantes ]]>
                </title>
                <description>
                    <![CDATA[ > "Qualquer um consegue escrever código que um computador entende. Bons programadores escrevem código que humanos entendem."                                       – Martin Fowler Escrever código limpo, fácil de entender e que não dê dor ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/clean-code-explicado-um-guia-pratico-para-iniciantes/</link>
                <guid isPermaLink="false">668b41b223266d03fc8b846f</guid>
                
                    <category>
                        <![CDATA[ Código limpo ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Wed, 24 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/clean-code-image.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/clean-coding-for-beginners/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Clean Code Explained – A Practical Introduction to Clean Coding for Beginners</a>
      </p><blockquote>"Qualquer um consegue escrever código que um computador entende. Bons programadores escrevem código que humanos entendem." &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; – Martin Fowler</blockquote><p>Escrever código limpo, fácil de entender e que não dê dor de cabeça para mexer depois é essencial para qualquer programador.</p><p>Neste guia prático, vamos desvendar os segredos do código elegante e mostrar como deixar seu código tinindo!</p><h2 id="dando-nome-aos-bois-ou-melhor-s-vari-veis-">Dando nome aos bois (ou melhor, às variáveis)</h2><blockquote>"Só existem duas coisas difíceis em Ciência da Computação: invalidar o cache e dar nomes às coisas." &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;– Phil Karlton</blockquote><p>Já imaginou ter que decorar um monte de números sem sentido para usar um programa? É por isso que damos nomes às variáveis: para facilitar a nossa vida!</p><p>Um bom nome já diz tudo sobre a variável, sem precisar de gambiarras.</p><h3 id="nomes-que-contam-uma-hist-ria">Nomes que contam uma história</h3><p>Evite usar comentários para explicar o óbvio. Se o nome precisa de legenda, é hora de repensar a vida (e o código!).</p><blockquote>"Um bom nome já diz para que ele serve, o que faz e como usar. Se precisa de comentário, é porque está faltando informação." &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; – Clean Code</blockquote><p><strong>Jeito tosco:</strong></p><pre><code class="language-js">var d; // tempo decorrido em dias
</code></pre><p>Não caia na armadilha de esconder o problema com comentários! Letras soltas, como x, y, a ou b só servem para confundir.</p><p><strong>Jeito elegante:</strong></p><pre><code>var tempoDecorridoEmDias;
var diasDesdeACriacao;
var diasDesdeAModificacao;
</code></pre><p>Veja a diferença! Agora, sabemos exatamente o que cada variável guarda.</p><h3 id="informa-o-clara-e-direta">Informação clara e direta</h3><p>Cuidado com nomes que induzem ao erro! Não chame um grupo de contas de <em>listaDeContas</em> se não for uma lista de verdade.</p><p>Seja específico e use nomes simples e diretos.</p><p><strong>Jeito tosco:</strong></p><pre><code class="language-js">var listaDeContas = [];
</code></pre><p><strong>Jeito elegante:</strong></p><pre><code class="language-js">var contas = []
</code></pre><h3 id="sem-enrola-o">Sem enrolação</h3><p>Nomes longos e repetitivos só servem para ocupar espaço. Corte o excesso!</p><ul><li>O ou A (como prefixo)</li><li>Informacoes</li><li>Dados</li><li>Variavel</li><li>Objeto</li><li>Gerenciador</li></ul><p><strong>Jeito tosco:</strong></p><pre><code class="language-java">class InformacoesDoUsuario {
  // ...
}
</code></pre><p><strong>Jeito elegante:</strong></p><pre><code class="language-java">class Usuario {
  // ...
}
</code></pre><h3 id="falando-a-l-ngua-dos-humanos">Falando a língua dos humanos</h3><p>Escolha nomes fáceis de ler e pronunciar, para não ter que soletrar código em voz alta.</p><p><strong>Jeito tosco:</strong></p><pre><code class="language-js">const yyyymmdstr = moment().format("YYYY/MM/DD");
</code></pre><p><strong>Jeito elegante:</strong></p><pre><code class="language-js">const dataAtual = moment().format("YYYY/MM/DD");
</code></pre><h3 id="f-cil-de-encontrar">Fácil de encontrar</h3><p>Evite usar números mágicos no código. Dê nomes descritivos às constantes para facilitar a busca.</p><p><strong>Jeito tosco:</strong></p><pre><code class="language-java">if (aluno.aulas.length &lt; 7) {
   // Fazer alguma coisa
}
</code></pre><p><strong>Jeito elegante:</strong></p><pre><code class="language-java">if (aluno.aulas.length &lt; MAXIMO_AULAS_POR_ALUNO) {
    // Fazer alguma coisa
}
</code></pre><p>Agora, se precisarmos mudar o limite de aulas, é só ajustar a constante.</p><h3 id="consist-ncia-a-alma-do-neg-cio">Consistência é a alma do negócio</h3><p>Use o mesmo nome para o mesmo conceito em todo o código. Nada de usar <em>buscar</em>, <em>recuperar</em> e <em>obter</em> para a mesma operação!</p><h2 id="fun-es-espertas-e-enxutas">Funções espertas e enxutas</h2><h3 id="tamanho-documento">Tamanho é documento</h3><p>Funções curtas e diretas são mais fáceis de entender e manter. Evite escrever códigos gigantes!</p><h3 id="uma-fun-o-uma-responsabilidade">Uma função, uma responsabilidade</h3><blockquote>Funções devem fazer apenas uma coisa, devem fazê-la bem e ponto final. – Clean Code</blockquote><p>Se sua função está fazendo malabarismos, é hora de dividi-la em partes menores.</p><h3 id="escondendo-a-complexidade">Escondendo a complexidade</h3><p>Use funções para encapsular condições complexas e deixar o código principal mais limpo.</p><p><strong>Exemplo:</strong></p><pre><code class="language-java">public void inserirPeca(int coluna) throws Exception {
        if (jogadaValida(coluna)) {
            // Lógica para inserir a peça
        } else {
            // Lógica para lidar com jogadas inválidas
        }
    }

    private boolean jogadaValida(int coluna) {
        // Verificar se a coluna é válida e se a jogada é possível
    }
</code></pre><h3 id="argumentos-contidos">Argumentos contidos</h3><p>Funções com muitos argumentos são confusas e difíceis de testar. Limite-se a dois, no máximo.</p><h3 id="evite-as-flags">Evite as <em>flags</em></h3><p>Argumentos booleanos que controlam o fluxo da função são sinais de problemas. Divida a função em funções menores!</p><h3 id="efeitos-colaterais-evite-os-">Efeitos colaterais: evite-os!</h3><p>Efeitos colaterais são como surpresas desagradáveis no código. Evite modificar variáveis globais ou parâmetros passados por referência sem necessidade.</p><h3 id="repeti-o-nem-pensar-">Repetição? Nem pensar!</h3><p>Código duplicado é sinônimo de dor de cabeça. Use as ferramentas da sua IDE para extrair métodos e evitar repetições.</p><h2 id="dicas-extras">Dicas extras</h2><h3 id="coment-rios-n-o-s-o-lixeiras">Comentários não são lixeiras</h3><p>Evite comentar código desnecessário. Se não for mais útil, exclua-o! Use o controle de versão para recuperar o código antigo, se precisar.</p><h3 id="conhe-a-as-regras-do-jogo">Conheça as regras do jogo</h3><p>Cada linguagem tem suas próprias convenções de estilo. Use e abuse das boas práticas! Confira os guias de estilo abaixo (em inglês):</p><ul><li><a href="https://www.python.org/dev/peps/pep-0008/">Guia de estilo do Python</a></li><li><a href="https://google.github.io/styleguide/jsguide.html">Guia de estilo do JavaScript do Google</a></li><li><a href="https://google.github.io/styleguide/javaguide.html">Guia de estilo do Java do Google</a></li></ul><h1 id="conclus-o">Conclusão</h1><p>Código limpo é um hábito que se constrói com o tempo. Aplique esses princípios no seu dia a dia e veja a mágica acontecer!</p><p>Gostou do guia? Compartilhe-o com seus amigos programadores! 😉</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como (e por que) incorporar conceitos de domínio no código ]]>
                </title>
                <description>
                    <![CDATA[ Imagine que o código é como uma receita de bolo: ele precisa ser fácil de entender para que qualquer um possa seguir os passos e ter o resultado esperado. Para isso, é fundamental que ele reflita claramente o problema que está resolvendo, como se estivesse falando a língua do problema. ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-e-por-que-incorporar-conceitos-de-dominio-no-codigo/</link>
                <guid isPermaLink="false">668ad46823266d03fc8b8468</guid>
                
                    <category>
                        <![CDATA[ Qualidade do código ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Tue, 23 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/2015-Gran-Paradiso-007.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/embedding-domain-concepts-in-code/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How (and why) to embed domain concepts in code</a>
      </p><p>Imagine que o código é como uma receita de bolo: ele precisa ser fácil de entender para que qualquer um possa seguir os passos e ter o resultado esperado. Para isso, é fundamental que ele reflita claramente o problema que está resolvendo, como se estivesse falando a língua do problema.</p><p>Incorporar os conceitos do problema no código exige atenção e habilidade. Isso não acontece automaticamente só porque você está usando TDD (Desenvolvimento Orientado a Testes). Acredite, porém, que esse esforço extra vale a pena, pois resulta em um código muito mais fácil de entender e manter.</p><p>Para ilustrar, vou usar um exemplo que vivenciei em um encontro de programadores. O desafio era criar um Relógio de Berlim simplificado, que mostra as horas através de luzes que piscam em um padrão específico (veja a imagem abaixo). No nosso caso, a saída era em formato de texto, mas a ideia é a mesma.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/berlin-clock-2.gif" class="kg-image" alt="berlin-clock-2" width="600" height="400" loading="lazy"></figure><h2 id="solu-o-inicial-com-tdd">Solução Inicial com TDD</h2><p>Muitas duplas usaram a técnica de TDD "de dentro para fora" e chegaram a soluções parecidas com esta (o <a href="https://github.com/ceddlyburge/berlin-clock-initial-tdd-solution/blob/master/BerlinClock.py">código completo está no GitHub</a>).</p><pre><code class="language-python">def berlin_clock_time(julian_time):
    hours, minutes, seconds = list(map(int, julian_time.split(":")))

    return [
        seconds_row_lights(seconds % 2)
        , five_hours_row_lights(hours)
        , single_hours_row_lights(hours % 5)
        , five_minutes_row_lights(minutes)
        , single_minutes_row_lights(minutes % 5)
    ]

def five_hours_row_lights(hours):
    lights_on = hours // 5
    lights_in_row = 4
    return lights_for_row("R", lights_on, lights_in_row)

# ...</code></pre><p>Essa solução surge naturalmente ao aplicar o TDD, mas observe que alguns detalhes importantes sobre como o relógio funciona ficam escondidos nas funções auxiliares, como a <code>get_five_hours</code>.</p><h2 id="elevando-os-conceitos">Elevando os conceitos</h2><p>Para melhorar a clareza, podemos trazer alguns desses detalhes para o topo do código, mesmo que isso quebre alguns testes (o <a href="https://github.com/ceddlyburge/berlin-clock-elevated-concepts/blob/master/BerlinClock.py">código completo está no GitHub</a>).</p><pre><code class="language-python">def berlin_clock_time(julian_time):
    hours, minutes, seconds = list(map(int, julian_time.split(":")))

    single_seconds = seconds_row_lights(seconds % 2)
    five_hours = row_lights(
        light_colour="R",
        lights_on=hours // 5,
        lights_in_row=4)
    single_hours = row_lights(
        light_colour="R",
        lights_on=hours % 5,
        lights_in_row=4)
    five_minutes = row_lights(
        light_colour="Y",
        lights_on=minutes // 5,
        lights_in_row=11)
    single_minutes = row_lights(
        light_colour="Y",
        lights_on=minutes % 5,
        lights_in_row=4)

    return [
        single_seconds,
        five_hours,
        single_hours,
        five_minutes,
        single_minutes
    ]

# ...</code></pre><p>Agora, fica mais evidente que:</p><ul><li>Existem 5 linhas no relógio.</li><li>A linha dos segundos é um caso especial.</li><li>Há 2 linhas para as horas e 2 para os minutos.</li><li>As linhas usam cores diferentes (vermelho e amarelo).</li><li>Cada linha tem um número diferente de luzes.</li></ul><h2 id="nomeando-conceitos-impl-citos">Nomeando conceitos implícitos</h2><p>Apesar da melhoria, ainda não está claro como as linhas se relacionam entre si e o que cada luz representa em termos de tempo. Para resolver isso, precisamos tornar esses conceitos implícitos explícitos, dando nomes a eles.</p><p>Por exemplo, podemos passar um valor <code>time_per_light</code> para a função <code>row_lights</code>. Isso nos leva a perceber que existem dois tipos de linhas:</p><ul><li>Linhas que representam a divisão inteira do tempo (<code>//</code>).</li><li>Linhas que representam o resto da divisão (<code>%</code>).</li></ul><p>Ao analisarmos o primeiro caso, notamos que o segundo parâmetro é sempre 5 (5 horas ou 5 minutos). Já no segundo caso, o <code>time_per_light</code> (tempo por luz) é sempre 1 (1 hora ou 1 minuto), complementando o primeiro caso.</p><p>Com essa percepção, podemos reescrever as linhas da seguinte maneira:</p><pre><code class="language-python">five_hour_row = row_lights(
    time_per_light=5,
    value=hours, 
    light_colour="R",
    lights_in_row=4)</code></pre><p>Essa mudança deixa claro que existe uma relação de pai e filho entre as linhas, onde a linha do resto depende da linha da divisão inteira.</p><p>Com base nisso, podemos criar uma função específica para as linhas "filhas" e o código fica assim (o <a href="https://github.com/ceddlyburge/berlin-clock">código completo está no GitHub</a>):</p><pre><code class="language-python">def berlin_clock_time(julian_time):
    hours, minutes, seconds = list(map(int, julian_time.split(":")))

    return [
        seconds_row_lights(
            seconds % 2),
        parent_row_lights(
            time_per_light=5,
            value=hours, 
            light_colour="R",
            lights_in_row=4),
        child_remainder_row_lights(
            parent_time_per_light=5,
            value=hours,
            light_colour="R"),
        parent_row_lights(
            time_per_light=5,
            value=minutes, 
            light_colour="Y",
            lights_in_row=11),
        child_remainder_row_lights(
            parent_time_per_light=5,
            light_colour="Y",
            value=minutes)
    ]

# ...</code></pre><p>Agora, com uma rápida olhada no código, podemos entender quase todos os conceitos do domínio do problema:</p><ul><li>A primeira linha representa os segundos e é um caso especial.</li><li>Na segunda linha, cada luz "R" representa 5 horas.</li><li>A terceira linha mostra o resto da divisão das horas por 5.</li><li>Na quarta linha, cada luz "Y" representa 5 minutos.</li><li>A quinta linha mostra o resto da divisão dos minutos por 5.</li></ul><h2 id="conclus-es">Conclusões</h2><p>Incorporar os conceitos de domínio no código exige tempo e esforço – e o TDD não faz isso para você, necessariamente. No entanto, esses conceitos tornam o código muito mais fácil de entender e manter, o que economiza tempo e dinheiro a longo prazo. Lembre-se de que, como em uma receita de bolo, um código claro e organizado é essencial para que todos possam "colaborar na cozinha" sem dificuldades.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Notação pé de galinha (ERD) – símbolos de relacionamento e como ler diagramas ]]>
                </title>
                <description>
                    <![CDATA[ Diagramas de entidade-relacionamento (ERD - do inglês, Entity-Relationship Diagram) são como mapas que mostram a relação entre diferentes "coisas" dentro de um sistema. Pense em um banco de dados, por exemplo. Ele é como um armário gigante com várias gavetas (tabelas) para guardar informações sobre clientes, produtos, pedidos etc. O ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/notacao-pe-de-galinha-erd-simbolos-de-relacionamento-e-como-ler-diagramas/</link>
                <guid isPermaLink="false">668aaa3523266d03fc8b8463</guid>
                
                    <category>
                        <![CDATA[ Bancos de dados ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Mon, 22 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/hanna-morris-_XXNjSziZuA-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/crows-foot-notation-relationship-symbols-and-how-to-read-diagrams/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Crow's Foot Notation – Relationship Symbols And How to Read Diagrams</a>
      </p><p>Diagramas de entidade-relacionamento (ERD - do inglês, <em>Entity-Relationship Diagram</em>) são como mapas que mostram a relação entre diferentes "coisas" dentro de um sistema.</p><p>Pense em um banco de dados, por exemplo. Ele é como um armário gigante com várias gavetas (tabelas) para guardar informações sobre clientes, produtos, pedidos etc. O ERD serve para visualizarmos como essas gavetas se conectam.</p><p>Para entender a relação entre as entidades em um ERD, usamos símbolos e notações. Uma das mais populares é a <strong>notação pé de galinha </strong>(em inglês, <em>crow's foot</em>), que vamos desvendar neste tutorial.</p><p>Ao final, você será capaz de:</p><ul><li>Entender o que são entidades e atributos em um ERD.</li><li>Decifrar os símbolos da notação pé de galinha.</li><li>Ler e interpretar diagramas como um profissional.</li><li>Criar seus próprios ERDs!</li></ul><p>Vamos usar os termos "notação", "indicadores" e "símbolos" como sinônimos, ok?</p><h2 id="o-que-uma-entidade-em-um-erd">O que é uma entidade em um ERD?</h2><p>Entidade é cada "coisa" importante no nosso banco de dados, como clientes, produtos ou pedidos.</p><p><strong>Dica:</strong> use nomes no singular (cliente, produto) e não no plural (clientes, produtos).</p><p>Olha um exemplo:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/entity.png" class="kg-image" alt="entity" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/entity.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/entity.png 696w" width="696" height="580" loading="lazy"></figure><p>Aí, temos a entidade "Cliente". É nela que guardaremos as informações sobre cada cliente cadastrado.</p><h2 id="o-que-s-o-os-atributos">O que são os atributos?</h2><p>Atributos são as características de uma entidade, como nome, endereço e telefone do cliente.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/attributes-2.png" class="kg-image" alt="attributes-2" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/attributes-2.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/attributes-2.png 696w" width="696" height="580" loading="lazy"></figure><p>Nesse exemplo, a entidade "Cliente" tem 3 atributos: nome de usuário, idade e e-mail.</p><h2 id="relacionamento-entre-entidades-conectando-as-pe-as-do-quebra-cabe-as">Relacionamento entre Entidades: conectando as peças do quebra-cabeças</h2><p>Na maioria dos casos, um banco de dados tem várias entidades interligadas. Para mostrar essas relações, usamos linhas com símbolos que indicam o tipo de relação entre elas.</p><h3 id="s-mbolos-da-nota-o-p-de-galinha-e-seus-significados">Símbolos da notação pé de galinha e seus significados</h3><p>Antes de mostrar os símbolos, precisamos entender o conceito de <strong>cardinalidade</strong>.</p><p>A cardinalidade define quantos "elementos" de uma entidade se relacionam com quantos "elementos" de outra entidade. Parece complicado, mas você vai entender rapidinho!</p><h4 id="zero">Zero</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/zero-crow.png" class="kg-image" alt="zero-crow" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/zero-crow.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/zero-crow.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/zero-crow.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/zero-crow.png 1607w" sizes="(min-width: 720px) 720px" width="1607" height="209" loading="lazy"></figure><p>A bolinha na ponta da linha indica "zero" ou "nenhum".</p><h4 id="um">Um</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/one-crow.png" class="kg-image" alt="one-crow" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/one-crow.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/one-crow.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/one-crow.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/one-crow.png 1607w" sizes="(min-width: 720px) 720px" width="1607" height="209" loading="lazy"></figure><p>A perninha reta indica "um" e somente um.</p><h4 id="muitos">Muitos</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/crows-crows-foot.png" class="kg-image" alt="crows-crows-foot" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/crows-crows-foot.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/crows-crows-foot.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/crows-crows-foot.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/crows-crows-foot.png 1607w" sizes="(min-width: 720px) 720px" width="1607" height="209" loading="lazy"></figure><p>O "pé de galinha" indica "muitos".</p><p>Combinando esses símbolos básicos, podemos representar diferentes tipos de relações:</p><h4 id="zero-ou-muitos">Zero ou Muitos</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/zero-and-many-crow.png" class="kg-image" alt="zero-and-many-crow" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/zero-and-many-crow.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/zero-and-many-crow.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/zero-and-many-crow.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/zero-and-many-crow.png 1607w" sizes="(min-width: 720px) 720px" width="1607" height="209" loading="lazy"></figure><h4 id="um-ou-muitos">Um ou Muitos</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/one-and-many-crow.png" class="kg-image" alt="one-and-many-crow" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/one-and-many-crow.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/one-and-many-crow.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/one-and-many-crow.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/one-and-many-crow.png 1607w" sizes="(min-width: 720px) 720px" width="1607" height="209" loading="lazy"></figure><h4 id="um-e-somente-um">Um e Somente Um</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/one-and-one-crow.png" class="kg-image" alt="one-and-one-crow" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/one-and-one-crow.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/one-and-one-crow.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/one-and-one-crow.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/one-and-one-crow.png 1607w" sizes="(min-width: 720px) 720px" width="1607" height="209" loading="lazy"></figure><h2 id="hora-da-pr-tica-exemplos-de-erd-com-nota-o-p-de-galinha">Hora da prática: exemplos de ERD com notação pé de galinha</h2><p>Vamos usar a notação para modelar um banco de dados simples.</p><h3 id="exemplo-n-1-professores-e-cursos">Exemplo nº 1: professores e cursos</h3><h5 id="passo-1-entidades">Passo 1: entidades</h5><p>Imagine um sistema de cursos <em>on-line</em> com duas entidades: "Professor" e "Curso".</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/teacher-course-crow.png" class="kg-image" alt="teacher-course-crow" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/teacher-course-crow.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/teacher-course-crow.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/teacher-course-crow.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/teacher-course-crow.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="780" loading="lazy"></figure><h5 id="passo-2-rela-o-professor-curso">Passo 2: relação professor-curso</h5><p>Regra: cada professor só pode ministrar <strong>um</strong> curso por vez.</p><p>Usamos o indicador "um e somente um" do lado do "Curso".</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/teacher-course-crow2.png" class="kg-image" alt="teacher-course-crow2" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/teacher-course-crow2.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/teacher-course-crow2.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/teacher-course-crow2.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/teacher-course-crow2.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="780" loading="lazy"></figure><p>A cardinalidade do lado do "Professor" é <strong>1:1</strong> (mínimo 1, máximo 1).</p><h5 id="passo-3-rela-o-curso-professor">Passo 3: relação curso-professor</h5><p>Regra: cada curso pode ter <strong>um ou vários</strong> professores.</p><p>Usamos o indicador "um ou muitos" do lado do "Professor".</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/teacher-course-crow3.png" class="kg-image" alt="teacher-course-crow3" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/teacher-course-crow3.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/teacher-course-crow3.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/teacher-course-crow3.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/teacher-course-crow3.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="780" loading="lazy"></figure><p>A cardinalidade do lado do "Curso" é <strong>1:N</strong> (mínimo 1, máximo N, ou seja, vários).</p><h3 id="exemplo-n-2-clientes-e-pizzas">Exemplo nº 2: clientes e pizzas</h3><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/crows-foot-example.png" class="kg-image" alt="crows-foot-example" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/crows-foot-example.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/crows-foot-example.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/crows-foot-example.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/crows-foot-example.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="780" loading="lazy"></figure><p>Aqui, uma pizza pode ser pedida por <strong>zero ou muitos</strong> clientes (quem nunca dividiu uma pizza com a galera?).</p><p>Da mesma maneira, um cliente pode pedir <strong>zero ou muitas</strong> pizzas (a fome bate, certo?).</p><p>A cardinalidade em ambos os lados é <strong>0:N</strong> (mínimo 0, máximo N).</p><h2 id="conclus-o">Conclusão</h2><p>A notação pé de galinha facilita a vida na hora de modelar bancos de dados. Com ela, você consegue visualizar as entidades e seus relacionamentos de maneira clara e organizada.</p><p>Os exemplos que vimos são simples, mas a lógica se aplica a sistemas complexos. Agora, é só praticar e se aventurar no mundo da modelagem de dados!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como usar o Git e o GitHub – controle de versão para iniciantes ]]>
                </title>
                <description>
                    <![CDATA[ Já pensou em como programadores guardam as diferentes versões do código que escrevem? É aí que entra o "controle de versão", uma ferramenta que salva o histórico do seu código, como se fosse um "control + z" turbinado. Com ele, você e sua equipe podem voltar atrás em qualquer mudança, ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-usar-o-git-e-o-github-controle-de-versao-para-iniciantes/</link>
                <guid isPermaLink="false">6689d63f23266d03fc8b845d</guid>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Sun, 21 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/git-github.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/git-and-github-the-basics/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Use Git and GitHub – Version Control Basics for Beginners</a>
      </p><p>Já pensou em como programadores guardam as diferentes versões do código que escrevem? É aí que entra o "controle de versão", uma ferramenta que salva o histórico do seu código, como se fosse um "control + z" turbinado.</p><p>Com ele, você e sua equipe podem voltar atrás em qualquer mudança, como se fosse uma máquina do tempo para o seu código!</p><p>Existem três tipos principais de sistemas de controle de versão:</p><ul><li><strong>Sistemas locais:</strong> salvam as versões do código na sua própria máquina. É simples, mas se o computador der problema, já era!</li><li><strong>Sistemas centralizados:</strong> guardam tudo em um servidor central. É bom para colaboração, mas, se o servidor cair, ninguém trabalha!</li><li><strong>Sistemas distribuídos:</strong> cada desenvolvedor tem uma cópia completa do código. É o mais seguro e moderno.</li></ul><h2 id="certo-e-o-que-isso-tem-a-ver-com-o-git">Certo, e o que isso tem a ver com o Git?</h2><p>O Git é um sistema de controle de versão <strong>distribuído</strong>, gratuito e muito popular. Com ele, você salva "instantâneos" do seu código (chamados de <strong><em>commits</em></strong>) e pode voltar para qualquer um deles quando quiser.</p><p>Pense no Git como um álbum de figurinhas do seu código, onde cada figurinha representa uma mudança.</p><h2 id="o-que-o-github">O que é o GitHub?</h2><p>O GitHub é como se fosse uma rede social para o seu código do Git. É lá que você guarda seus projetos (chamados de <strong>repositórios</strong>) e mostra para o mundo (ou não, você escolhe!).</p><p>No GitHub, você pode:</p><ul><li>Trabalhar em equipe em um projeto, cada um com sua cópia, sem confusões.</li><li>"Clonar" o código de outros projetos e aprender com eles.</li><li>Mostrar seus projetos para futuros empregadores.</li></ul><h2 id="por-que-usar-o-github">Por que usar o GitHub?</h2><ul><li><strong>Organização:</strong> chega de pastas com nomes "projeto_final_versao_5_final_mesmo.zip"!</li><li><strong>Trabalho em equipe:</strong> programe junto com seus amigos sem dor de cabeça.</li><li><strong>Portfólio:</strong> mostre seus projetos para o mundo e impressione os recrutadores.</li></ul><h2 id="m-os-obra-configurando-o-git">Mãos à obra: configurando o Git</h2><ol><li><strong>Baixe o Git:</strong> vá no site oficial <a href="https://git-scm.com/">https://git-scm.com/</a> e baixe a versão para o seu sistema operacional (Windows, Mac ou Linux).</li><li><strong>Instale o Git:</strong> é só seguir as instruções do instalador.</li><li><strong>Configure o Git:</strong> abra o terminal (ou o Git Bash) e digite:</li></ol><pre><code class="language-bash">git config --global user.name "Seu Nome"
git config --global user.email "seu_e-mail@exemplo.com"
</code></pre><p>Substitua "Seu Nome" e "<a>seu_e-mail@exemplo.com</a>" por suas informações.</p><h2 id="criando-sua-conta-no-github">Criando sua conta no GitHub</h2><ol><li>Acesse o site <a href="https://github.com/">https://github.com/</a>.</li><li>Clique em "Sign up" (inscrever-se) no canto superior direito.</li><li>Preencha o formulário com seu e-mail, senha e nome de usuário.</li><li>Pronto! Você já faz parte da comunidade GitHub!</li></ol><h2 id="comandos-b-sicos-do-git">Comandos básicos do Git</h2><ul><li><code>git init</code>: cria um novo repositório Git na pasta atual.</li><li><code>git add</code>: adiciona suas mudanças na "área de preparação" (em inglês, <em>staging area</em>).</li><li><code>git commit -m "mensagem"</code>: salva suas mudanças com uma mensagem descrevendo o que você fez.</li><li><code>git clone [link do repositório]</code>: copia um repositório do GitHub para sua máquina.</li><li><code>git push</code>: envia suas mudanças para o GitHub.</li></ul><h2 id="conclus-o">Conclusão</h2><p>Este guia é uma introdução ao mundo do Git e GitHub. Agora, é hora de você colocar a mão na massa e começar a fazer o versionamento de seus projetos!</p><p>Lembre-se: errar faz parte do aprendizado. Não tenha medo de experimentar e explorar as funcionalidades do Git e do GitHub.</p><p>Boa programação para você!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Clear Code – como escrever código fácil de ler ]]>
                </title>
                <description>
                    <![CDATA[ Este artigo é uma continuação de um tweet que fiz sobre como lido com minha péssima capacidade de lembrar código. Pode parecer engraçado para você, mas eu realmente tendo a esquecer o que escrevo logo depois de escrever. > If you have a bad memory for code like I do, ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/clear-code-como-escrever-codigo-facil-de-ler/</link>
                <guid isPermaLink="false">6689d0c023266d03fc8b8457</guid>
                
                    <category>
                        <![CDATA[ Código limpo ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Thu, 18 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/cafe-gc5d844b68_1280.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/clear-code-how-to-write-code-that-is-easy-to-read/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">https://www.freecodecamp.org/news/clear-code-how-to-write-code-that-is-easy-to-read/</a>
      </p><p>Este artigo é uma continuação de um tweet que fiz sobre como lido com minha péssima capacidade de lembrar código. Pode parecer engraçado para você, mas eu realmente tendo a esquecer o que escrevo logo depois de escrever.</p><figure class="kg-card kg-embed-card"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">If you have a bad memory for code like I do, then I suggest you make your code read like a book. <br><br>That way you don't need to remember what you wrote yesterday, or a month ago; the code will tell you as you read it.</p>— Ryan Kay (@wiseAss301) <a href="https://twitter.com/wiseAss301/status/1591181678051229696?ref_src=twsrc%5Etfw">November 11, 2022</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

</figure><p>Primeiro, discutiremos por que você pode querer escrever um código mais legível em vez de um código curto e conciso. Depois, veremos as seguintes estratégias sobre como fazer isso com:</p><ul><li>Nomenclatura de variáveis, valores, referências, classes, objetos e funções</li><li>Funções auxiliares</li><li>Comentários de código</li><li>Enums/dicionários/classes seladas etc.</li><li>Organização e nomenclatura de pacotes</li></ul><p>Conhecimento básico de código é recomendado para aproveitar ao máximo este artigo. No entanto, tentei torná-lo acessível para iniciantes, sempre que possível.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1535930891776-0c2dfb7fda1a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE1Mnx8cmVhZGluZ3xlbnwwfHx8fDE2Njg4MTYyMjQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" class="kg-image" alt="photo-1535930891776-0c2dfb7fda1a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE1Mnx8cmVhZGluZ3xlbnwwfHx8fDE2Njg4MTYyMjQ&amp;ixlib=rb-4.0" width="600" height="400" loading="lazy"><figcaption>Foto por: <a href="https://unsplash.com/@jamie452?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Jamie Street</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></figcaption></figure><h2 id="a-efici-ncia-vem-de-escrever-menos-c-digo">A eficiência vem de escrever menos código?</h2><p>Lembro-me de quando era um desenvolvedor júnior, pensando que nomes curtos ou abreviados para identificadores – basicamente, qualquer código que nós, desenvolvedores, podemos nomear – eram mais eficientes.</p><p>Minha lógica era simples: se eu levo menos tempo para escrever, posso terminar o trabalho mais rápido.</p><p>Essa lógica faria sentido se as seguintes coisas fossem verdadeiras:</p><ul><li>Eu, ou outra pessoa, nunca teria que ler ou corrigir o que escrevi no passado</li><li>Eu não esqueceria com frequência o que era uma variável, ou várias variáveis, enquanto lia uma função</li><li>Eu não teria que escrever ocasionalmente algum código que fosse realmente complexo e obscuro</li><li>Eu poderia renomear funções, classes ou propriedades de bibliotecas externas ridículas ou obscuras para algo mais sensato</li></ul><p>O ponto é que, para mim, <strong><strong>encontro poucas situações em que ser conciso realmente economiza tempo</strong></strong>. Além disso, os IDEs modernos têm esse recurso útil chamado preenchimento automático de código que economiza a maior parte da digitação de qualquer maneira.</p><p>Você pode não se sentir da mesma maneira – e tudo bem! Pegue o que funcionar para você neste artigo e descarte o resto.</p><h2 id="como-nomear-classes-vari-veis-e-fun-es">Como nomear classes, variáveis e funções</h2><p>Agora, compartilharei o que faço para tornar meu código mais fácil de ler para mim e para os outros. Os exemplos de código que usarei serão em Kotlin, mas os pontos que levantarei devem ser aplicáveis à maioria das plataformas e linguagens.</p><p>Existem duas coisas importantes para saber ao aprender, como nomear entidades de software. Antes de chegar a isso, o termo entidades de software se refere a qualquer um dos seguintes:</p><ul><li>Classes, structs, objetos</li><li>Variáveis, valores, referências, ponteiros</li><li>Funções, métodos, algoritmos, comandos</li><li>Interfaces, protocolos, abstrações</li></ul><p>Essencialmente, qualquer coisa que um programador precisa nomear ao escrever um programa.</p><h3 id="que-n-vel-de-descri-o-devemos-usar-para-os-nomes">Que nível de descrição devemos usar para os nomes</h3><p>Meu objetivo para nomear entidades de software é este: o nome deve <strong><strong>reduzir qualquer confusão sobre o que uma entidade de software faz ou é</strong></strong>.</p><p>Os detalhes de <em>como </em>ela faz algo geralmente não são necessários.</p><p>O contexto, ou tudo ao redor, de uma entidade de software é importante ao decidir sobre um nome. Algo pode exigir mais ou menos detalhes dependendo do seu contexto.</p><p>Vamos considerar três exemplos:</p><ol><li><code>obterDataFormatada(data: String) : String</code></li><li><code>obterDataFormatadaAAAAMMDD(data: String) : String</code></li><li><code>obterDataFormatadaAAAAMMDDdeFormatoISO8601(data: String) : String</code></li></ol><p>A aplicação em produção na qual estou trabalhando atualmente exige frequentemente a transformação de datas de e para diferentes formatos.</p><p>Nesse contexto, eu simplesmente uso nomes como o do exemplo 3, que é muito mais claro do que o do exemplo 1.</p><p>Outra opção pode ser alterar o nome do parâmetro no exemplo 2 para algo como <code>dataISO8601</code>.</p><p>Embora eu sugira que você seja consistente em sua abordagem em uma determinada base de código, sinta-se à vontade para experimentar o que funciona para você. O ponto é adicionar o máximo de informações necessárias para esclarecer qualquer ambiguidade.</p><p>Se eu estivesse escrevendo um programa único que apenas converte um formato para outro, o exemplo 1 seria bom. <strong><strong>Adicionar mais informações do que o necessário não é o que estou defendendo aqui</strong></strong>.</p><h3 id="quanto-mais-algo-faz-mais-dif-cil-nome-lo">Quanto mais algo faz, mais difícil é nomeá-lo</h3><p>Se você está tendo problemas para nomear algo, geralmente (embora nem sempre) é porque ele faz muitas coisas que não estão conceitualmente relacionadas.</p><p>O grau em que as entidades de software estão conceitualmente relacionadas é conhecido como <a href="https://en.wikipedia.org/wiki/Cohesion_(computer_science)">coesão</a> (texto em inglês).</p><p><strong>Ao observar quais partes de um programa são coesas ou não, você pode começar a entender o que deve ser separado ou agrupado</strong>.</p><p>Esse processo pode ser feito de várias perspectivas, que tentarei explicar por meio de exemplos.</p><p>Suponha que você tenha quatro entidades de software:</p><ol><li><code>ArmazenarUsuárioNaNuvem</code></li><li><code>ArmazenarUsuárioEmDisco</code></li><li><code>ArmazenarMensagem</code></li><li><code>EditarIUDoUsuário</code></li></ol><p>A primeira perspectiva que podemos considerar é a informação do mundo real com a qual essas entidades estão preocupadas. Dessa perspectiva, podemos ver que <code>ArmazenarUsuárioNaNuvem</code>, <code>ArmazenarUsuárioEmDisco</code> e <code>EditarIUDoUsuário</code> usam o mesmo modelo de informação: um <em>usuário</em>.</p><p>No entanto, há outra perspectiva que devemos ter em mente, particularmente ao projetar programas de interface gráfica do usuário (GUI).</p><p>Todo programa de GUI pode ser dividido em três camadas principais:</p><ul><li>Interface do usuário (comumente chamada de "View" – em português, visão ou visualização)</li><li>Lógica (comumente se refere a coisas como controladores e apresentadores)</li><li>Modelo (armazenamento e acesso a dados, ou o próprio estado, dependendo da sua definição)</li></ul><p>Isso não significa que você deva sempre olhar para um programa como tendo apenas essas três camadas! A abordagem de três camadas é uma generalização que <strong>frequentemente é insuficiente</strong>.</p><p>De qualquer modo, a partir dessa perspectiva, <code>ArmazenarMensagem</code> tem mais em comum com as outras entidades de armazenamento do que <code>EditarIUDoUsuário</code>.</p><p>Ser capaz de olhar para seus programas de várias perspectivas é algo que virá à medida que você construir programas mais complexos.</p><p>A principal lição é que separar sua base de código em partes coesas e relacionadas geralmente tornará as entidades de software mais fáceis de nomear.</p><h2 id="como-usar-fun-es-auxiliares">Como usar funções auxiliares</h2><p>Funções auxiliares, particularmente, quando combinadas com boas práticas de nomenclatura de funções, podem melhorar muito a legibilidade do seu código.</p><p>As funções auxiliares também são uma oportunidade para aplicar um princípio fundamental da arquitetura de software: a separação de responsabilidades.</p><h3 id="como-criar-quebra-cabe-as-de-sudoku-com-fun-es-auxiliares">Como criar quebra-cabeças de Sudoku com funções auxiliares</h3><p>Agora, veremos um exemplo prático para demonstrar o uso extensivo de funções auxiliares. Tente imaginar a dificuldade que seria seguir este código se tudo estivesse em uma única função gigante!</p><p>No passado, trabalhei em uma parte grande, mas coesa, de um programa: um construtor de <a href="https://pt.wikipedia.org/wiki/Sudoku">Sudoku</a> que usa estruturas de dados e algoritmos de grafos. Mesmo que você não esteja familiarizado com Sudoku ou grafos, acredito que ainda seja capaz de acompanhar o ponto principal.</p><p>Você pode encontrar o <a href="https://github.com/BracketCove/GraphSudokuOpen/tree/master/app/src/main/java/com/bracketcove/graphsudoku/computationlogic">código-fonte completo aqui</a>.</p><p>Podemos dividir o processo de geração de um quebra-cabeça de Sudoku jogável em cinco etapas:</p><ul><li>Criar os nós do quebra-cabeça (representando as peças)</li><li>Criar as arestas do quebra-cabeça (arestas, neste caso, é outra palavra para relacionamentos/referências entre as peças: linha, coluna ou subgrade)</li><li>Semear (adicionar) alguns valores à estrutura de dados para tornar a resolução mais rápida</li><li>Resolver o quebra-cabeça</li><li>Desfazer um certo número de peças para que o jogo seja realmente jogável por um usuário</li></ul><p>Usei algo semelhante ao padrão <em>construtor</em> para representar essas etapas na função que chamo para criar o quebra-cabeça:</p><pre><code class="language-kotlin">internal fun construirNovoSudoku(
    limite: Int,
    dificuldade: Dificuldade
): QuebraCabecaSudoku = construirNos(limite, dificuldade)
        .construirArestas()
        .semearCores()
        .resolver()
        .desfazer()
</code></pre><p>Embora a ideia de "nós" e "arestas" seja a de definições técnicas dentro da <a href="https://pt.wikipedia.org/wiki/Teoria_dos_grafos">teoria dos grafos</a>, esse código reflete claramente as cinco etapas que decidi.</p><p>Não veremos toda a base de código, mas quero destacar como as funções auxiliares continuam a decompor a lógica e promover a legibilidade:</p><pre><code class="language-kotlin">internal fun QuebraCabecaSudoku.construirArestas(): QuebraCabecaSudoku {
    this.grafo.forEach {
        val x = it.value.first.x
        val y = it.value.first.y

        it.value.mesclarSemRepeticoes(
                obterNosPorColuna(this.grafo, x)
        )

        it.value.mesclarSemRepeticoes(
                obterNosPorLinha(this.grafo, y)
        )

        it.value.mesclarSemRepeticoes(
                obterNosPorSubgrade(this.grafo, x, y, limite)
        )

    }
    return this
}

internal fun LinkedList&lt;NoSudoku&gt;.mesclarSemRepeticoes(novo: List&lt;NoSudoku&gt;) {
    val hashes: MutableList&lt;Int&gt; = this.map { it.hashCode() }.toMutableList()
    novo.forEach {
        if (!hashes.contains(it.hashCode())) {
            this.add(it)
            hashes.add(it.hashCode())
        }
    }
}

internal fun obterNosPorColuna(grafo: LinkedHashMap&lt;Int,
        LinkedList&lt;NoSudoku&gt;&gt;, x: Int): List&lt;NoSudoku&gt; {
    val listaDeArestas = mutableListOf&lt;NoSudoku&gt;()
    grafo.values.filter {
        it.first.x == x
    }.forEach {
        listaDeArestas.add(it.first)
    }
    return listaDeArestas
}
//...
</code></pre><p>Para resumir esse processo, as funções auxiliares fornecem dois benefícios:</p><ul><li>Elas são um substituto para um bloco de código que faz algo</li><li>Esse bloco de código pode receber um nome descritivo</li></ul><p>Ambos os benefícios podem levar a uma maior legibilidade, pois o código se torna menos confuso e mais descritivo.</p><p>Se você está se perguntando o que deve e o que não deve ser uma função auxiliar, sugiro que pratique diferentes abordagens para ver o que funciona para você.</p><h2 id="como-usar-coment-rios-de-c-digo">Como usar comentários de código</h2><p>Minha preferência pessoal em comentários de código é que eles tenham dois usos principais: primeiro, os comentários ajudam a descrever funções complexas em detalhes.</p><p>Segundo, para esclarecer qualquer confusão sobre uma linha ou bloco de código.</p><h3 id="como-usar-coment-rios-para-projetar-novas-fun-es">Como usar comentários para projetar novas funções</h3><p>Quando encontro funções que espero que sejam difíceis de escrever, descrevo o que a função faz usando linguagem simples ou pseudocódigo.</p><p>A forma como faço isso mudou ao longo dos anos, então encorajo você a tentar diferentes abordagens.</p><p>Nos exemplos da seção anterior, omiti os comentários de código:</p><pre><code class="language-kotlin">/** * 1. Gere um Mapa que contém n*n nós. * 2. para cada nó adjacente (conforme as regras do Sudoku), adicione uma Aresta ao conjunto hash *  - Por coluna *  - Por linha *  - Por subgrade de tamanho n * *  LinkedHashMap: Escolhi usar um LinkedHashMap porque ele preserva a ordem dos *  elementos colocados dentro do Mapa, mas também permite pesquisas por código hash, que são *  gerados por valores x e y. * *  Quanto ao LinkedList em cada bucket (elemento) do mapa, assuma que o primeiro elemento *  é o nó em hashCode(x, y), e os elementos subsequentes são arestas desse elemento. *  Além da ordenação do primeiro elemento como Cabeça do LinkedList, o resto dos *  elementos não precisa ser ordenado de nenhuma maneira específica. * * *  */
internal fun construirNos(n: Int, dificuldade: Dificuldade): QuebraCabecaSudoku {
    val novoMapa = LinkedHashMap&lt;Int, LinkedList&lt;NoSudoku&gt;&gt;()

    (1..n).forEach { indiceX -&gt;
        (1..n).forEach { indiceY -&gt;
            val novoNo = NoSudoku(
                    indiceX,
                    indiceY,
                    0
            )

            val novaLista = LinkedList&lt;NoSudoku&gt;()
            novaLista.add(novoNo)
            novoMapa.put(
                    novoNo.hashCode(),
                    novaLista
            )
        }
    }
    return QuebraCabecaSudoku(n, dificuldade, novoMapa)
}
</code></pre><p>A quantidade de detalhes que adiciono a esses comentários depende do contexto. Se estou trabalhando em equipe, geralmente tento mantê-los muito mais curtos do que o que você vê acima e incluo apenas informações que considero necessárias.</p><p>O exemplo acima foi um projeto de aprendizado pessoal que eu esperava compartilhar com outras pessoas. É por isso que até incluí meu processo de tomada de decisão sobre os tipos usados para representar um quebra-cabeça de Sudoku.</p><p>Para os fãs de desenvolvimento orientado a testes, você pode tentar escrever as etapas de pseudocódigo de um algoritmo antes de escrever o teste:</p><pre><code class="language-kotlin">/**     * No processo de vinculação, chamado pela visualização em onCreate. Verifique o estado atual do usuário, grave esse resultado em     * vModel, mostre o gráfico de carregamento, execute alguma inicialização     *     * a. Usuário é Anônimo     * b. Usuário é Registrado     *     * a:     * 1. Exibir Visualização de Carregamento     * 2. Verificar se há um usuário conectado da autenticação: nulo     * 3. gravar nulo no estado do usuário vModel     * 4. chamar o processo On start     */
    @Test
    fun `On bind Usuário anônimo`() = runBlocking {

        //...
    } 
</code></pre><p>Isso permite que você projete a unidade em um <strong><strong>nível mais alto de abstração</strong></strong> antes de escrever a implementação. O tempo que você gasta projetando em níveis mais altos de abstração pode economizar tempo a longo prazo.</p><h3 id="como-usar-coment-rios-de-c-digo-em-linha-de-modo-eficaz">Como usar comentários de código em linha de modo eficaz</h3><p>Existem duas situações principais em que escreverei um comentário de código em linha:</p><ul><li>Quando sinto que o propósito de uma linha ou bloco de código não ficará claro para mim ou para qualquer outra pessoa que o leia mais tarde</li><li>Quando tenho que chamar alguma função de biblioteca mal nomeada que tem um nome confuso ou enganoso</li></ul><p>De longe, o algoritmo de Sudoku mais complexo no meu programa é o <a href="https://github.com/BracketCove/GraphSudokuOpen/blob/master/app/src/main/java/com/bracketcove/graphsudoku/computationlogic/SolveSudoku.kt">algoritmo de resolução</a>. Na verdade, é tão longo que postarei apenas um trecho dele aqui:</p><pre><code class="language-kotlin">internal fun QuebraCabecaSudoku.resolver()
        : QuebraCabecaSudoku {
    //nós que foram atribuídos (não incluindo nós semeados de semearCores())
    val atribuicoes = LinkedList&lt;NoSudoku&gt;()

    //acompanhe as tentativas de atribuição com falha para observar loops infinitos
    var tentativasDeAtribuicao = 0
    //Duas etapas de retrocesso, parcial é metade do conjunto de dados, completo é uma reinicialização completa
    var retrocessoParcial = false

    var contadorDeRetrocessoCompleto = 0

    //de 0 - limite, representa o quão "exigente" o algoritmo é sobre atribuir novos valores
    var valorLegal: Int = (limite / 2)

    //para evitar ser muito legal muito cedo
    var contadorLegal = 0

    //trabalhe com uma cópia
    var novoGrafo = LinkedHashMap(this.grafo)
    //todos os nós que são de valor 0 (não coloridos)
    val nosNaoColoridos = LinkedList&lt;NoSudoku&gt;()
    novoGrafo.values.filter { it.first.cor == 0 }.forEach { nosNaoColoridos.add(it.first) }

    while (nosNaoColoridos.size &gt; 0) {
    //...
    }
//...
}
</code></pre><p>Neste caso, os comentários em linha eram necessários, pois eu frequentemente esquecia o que algumas dessas variáveis eram enquanto lia este algoritmo gigante.</p><p>Outro caso em que adicionarei um comentário em linha é quando tenho que explicar ou me lembrar sobre o código sobre o qual não tenho controle.</p><p>Por exemplo, a infame <a href="https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#MONTH">API Java Calendar</a> usa indexação baseada em zero para meses. Isso é indiscutivelmente muito estúpido, pois não estou ciente de nenhum padrão que represente janeiro com 0, nem me importo se existe um!</p><p>Não posso compartilhar o código com você, pois é proprietário, mas basta dizer que tenho comentários na base de código da minha equipe atual que explicam instruções aleatórias <code>- 1</code> para se conformar com a API Calendar.</p><h2 id="como-usar-enums-e-dicion-rios">Como usar enums e dicionários</h2><p>Existem outros nomes para esses tipos de construções de código, mas esses são os dois com os quais estou familiarizado. Suponha que você tenha um conjunto restrito ou limitado de valores que você usa para representar algo.</p><p>Por exemplo, eu precisava de uma maneira de limitar o número de peças que são incluídas em um novo quebra-cabeça de Sudoku, com base:</p><ul><li>No tamanho do quebra-cabeça (4, 9 ou 16 peças por coluna/linha/subgrade)</li><li>Na dificuldade do quebra-cabeça (fácil, médio ou difícil)</li></ul><p>Por meio de testes extensivos, cheguei aos seguintes valores como modificadores:</p><pre><code class="language-kotlin">enum class Dificuldade(val modificador:Double) {
    FACIL(0.50),
    MEDIO(0.44),
    DIFICIL(0.38)
}

data class QuebraCabecaSudoku(
        val limite: Int,
        val dificuldade: Dificuldade,
        val grafo: LinkedHashMap&lt;Int, LinkedList&lt;NoSudoku&gt;&gt;
        = construirNovoSudoku(limite, dificuldade).grafo,
        var tempoDecorrido: Long = 0L
)//...
</code></pre><p>Esses valores são usados em vários lugares onde a lógica deve mudar com base na dificuldade.</p><p>Às vezes, você nem precisa ter valores associados a nomes legíveis por humanos. Usei um enum diferente para representar diferentes estratégias de resolução para garantir que um quebra-cabeça seja jogável em relação à dificuldade selecionada:</p><pre><code class="language-kotlin">enum class EstrategiaDeResolucao {
    BASICA,
    AVANCADA,
    INSOLUVEL
}

internal fun determinarDificuldade(
    quebraCabeca: QuebraCabecaSudoku
): EstrategiaDeResolucao {
    val resolucaoBasica = ehBasica(
        quebraCabeca
    )
    val resolucaoAvancada = ehAvancada(
        quebraCabeca
    )

    //se o quebra-cabeça não for mais solucionável, retornamos a estratégia atual
    if (resolucaoBasica) return EstrategiaDeResolucao.BASICA
    else if (resolucaoAvancada) return EstrategiaDeResolucao.AVANCADA
    else {
        quebraCabeca.imprimir()
        return EstrategiaDeResolucao.INSOLUVEL
    }
}
</code></pre><p>Um bom princípio no projeto de qualquer sistema é este: <strong>m<strong>enos partes móveis geralmente têm menos coisas que podem dar errado</strong></strong>.</p><p>Colocar restrições em valores e tipos e dar a eles bons nomes não apenas torna seu código mais fácil de ler, <strong><strong>mas também pode protegê-lo de erros</strong></strong>.</p><h2 id="como-organizar-e-nomear-pacotes-pastas-e-diret-rios">Como organizar e nomear pacotes, pastas e diretórios</h2><p>Nenhum guia sobre legibilidade de código estaria completo sem alguma discussão sobre pacotes. Se a plataforma e a linguagem de sua preferência não usam esse termo, assuma que quero dizer pasta ou diretório.</p><p>Já mudei de opinião sobre isso várias vezes. Isso se reflete em meus projetos mais antigos.</p><p>Duas abordagens comuns para a organização de pacotes são:</p><ul><li>Pacote por camada arquitetônica</li><li>Pacote por recurso</li></ul><h3 id="como-fazer-pacote-por-camada">Como fazer pacote por camada</h3><p>Pacote por camada é o primeiro e pior sistema que já usei. A ideia geralmente é construir sua estrutura de pacotes em torno de algum padrão arquitetônico como MVC, MVP, MVVM e assim por diante.</p><p>Para tomar o MVC como exemplo, sua estrutura de pacotes de nível superior seria assim:</p><ul><li>modelo</li><li>visão</li><li>controlador</li></ul><p>O primeiro problema com essa abordagem é que ela assume que toda classe ou função se encaixa confortavelmente em uma dessas camadas. Isso raramente é o caso na prática.</p><p>Também acho essa abordagem a menos legível, pois o nível superior informa apenas os detalhes mais gerais sobre o que esperar dentro de cada pacote.</p><p>Essa abordagem geralmente pode ser aprimorada adicionando mais "camadas" para ser mais específica:</p><ul><li>ui</li><li>modelo</li><li>api</li><li>logicaDeConstrucao/di</li><li>repositorio</li><li>dominio</li><li>comum</li></ul><p>Isso pode funcionar razoavelmente bem em bases de código menores, onde todos os desenvolvedores estão familiarizados com o padrão geral e o estilo usado.</p><h3 id="como-fazer-pacote-por-recurso">Como fazer pacote por recurso</h3><p>Pacote por recurso tem suas próprias falhas, mas geralmente é mais fácil de ler e navegar. Isso supondo que você dê bons nomes aos pacotes.</p><p>O termo recurso é difícil de descrever, mas eu geralmente o definiria assim: uma tela/página ou conjunto de telas/páginas que definem uma <strong><strong>parte principal da funcionalidade</strong></strong> para usuários ou clientes.</p><p>Para uma aplicação de mídia social, podemos ver uma estrutura como:</p><ul><li>linhaDoTempo</li><li>amigos</li><li>perfilDoUsuario</li><li>mensagens</li><li>detalheDaMensagem</li></ul><p>O problema principal com o pacote por recurso é o oposto do pacote por camada: quase sempre haverá entidades de software que são usadas em vários recursos.</p><p>Existem duas soluções para esse problema. A primeira seria ter código duplicado em cada recurso.</p><p>Acredite ou não, duplicar entidades de software <strong><strong>pode ser incrivelmente útil em ambientes corporativos</strong></strong> em situações específicas.</p><p>No entanto, não é algo que eu recomendaria como regra geral.</p><h3 id="como-fazer-uma-estrutura-de-pacote-h-brida">Como fazer uma estrutura de pacote híbrida</h3><p>A solução que geralmente recomendo aos desenvolvedores é o que gosto de chamar de abordagem híbrida. É muito simples, flexível e deve cobrir a maioria dos seus requisitos:</p><ul><li>linhaDoTempo</li><li>amigos</li><li>mensagens</li><li>todasAsMensagens</li><li>conversa</li><li>detalheDaMensagem</li><li>api</li><li>linhaDoTempo</li><li>usuario</li><li>mensagem</li><li>componentesDeIU</li></ul><p>Não leve esse exemplo muito a sério; estou tentando transmitir a ideia geral: qualquer coisa que seja específica do recurso vai para o pacote desse recurso. Qualquer coisa que seja compartilhada entre os recursos vai para um pacote separado aninhado no mesmo nível ou em um nível superior.</p><p>Novamente, o que define uma camada é um conceito vago para começar. Então, não siga uma convenção cegamente. <strong><strong>Pense criticamente sobre o que é claro, particularmente para alguém que não está familiarizado com o projeto</strong></strong>.</p><h2 id="considera-es-finais">Considerações finais</h2><p>A maioria das minhas preferências em legibilidade e estilo de código veio de muitas tentativas de diferentes abordagens. Às vezes, essas eram abordagens que eu vi outras pessoas usarem e algumas delas surgiram naturalmente.</p><p>Se você for capaz de se colocar na posição de alguém menos familiarizado com o código ou programa que está olhando, terá mais facilidade em fazer seu código ser lido como se fosse um livro.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Comandos da linha de comando – tutorial de CLI ]]>
                </title>
                <description>
                    <![CDATA[ A linha de comando do Windows é uma das ferramentas mais poderosas em um PC com Windows. Com ela, você pode interagir diretamente com o sistema operacional e fazer muitas coisas que não estão disponíveis na interface gráfica do usuário (GUI – do inglês, Graphical User Interface). Neste artigo, mostrarei ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/comandos-da-linha-de-comando-tutorial-de-cli/</link>
                <guid isPermaLink="false">6689bbaa23266d03fc8b8452</guid>
                
                    <category>
                        <![CDATA[ Linha de comando ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Wed, 17 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/cli.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/command-line-commands-cli-tutorial/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Command Line Commands – CLI Tutorial</a>
      </p><p>A linha de comando do Windows é uma das ferramentas mais poderosas em um PC com Windows. Com ela, você pode interagir diretamente com o sistema operacional e fazer muitas coisas que não estão disponíveis na interface gráfica do usuário (GUI – do inglês, <em>Graphical User Interface</em>).</p><p>Neste artigo, mostrarei 40 comandos que você pode usar na linha de comando do Windows e que podem aumentar sua confiança como usuário do Windows.</p><p><strong>Observação:</strong> você precisa ter cuidado ao usar os comandos que mostrarei. Isso ocorre porque alguns comandos podem ter um efeito negativo ou positivo duradouro em seu PC com Windows até que você o reinicie.</p><p>Além disso, alguns desses comandos exigem que você abra o prompt de comando como administrador.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss5-1.png" class="kg-image" alt="ss5-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss5-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/ss5-1.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss5-1.png 1185w" sizes="(min-width: 720px) 720px" width="1185" height="968" loading="lazy"></figure><h3 id="comandos-da-linha-de-comando-do-windows">Comandos da linha de comando do Windows</h3><h4 id="powershell-start-cmd-v-runas-executar-o-prompt-de-comando-como-administrador"><code>powershell start cmd -v runAs</code> – executar o prompt de comando como administrador</h4><p>Inserir esse comando abre outra janela do prompt de comando como administrador:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss1-1.png" class="kg-image" alt="ss1-1" width="507" height="208" loading="lazy"></figure><h4 id="driverquery-lista-todos-os-drivers-instalados"><code>driverquery</code> – lista todos os drivers instalados</h4><p>É importante ter acesso a todos os drivers porque eles costumam causar problemas.</p><p>É isso que este comando faz – ele mostra até mesmo os drivers que você não encontrará no gerenciador de dispositivos.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss2-1.png" class="kg-image" alt="ss2-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss2-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss2-1.png 845w" sizes="(min-width: 720px) 720px" width="845" height="478" loading="lazy"></figure><h4 id="chdir-ou-cd-muda-o-diret-rio-de-trabalho-atual-para-o-diret-rio-especificado"><code>chdir</code> ou <code>cd</code> – muda o diretório de trabalho atual para o diretório especificado</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss3-1.png" class="kg-image" alt="ss3-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss3-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss3-1.png 694w" width="694" height="382" loading="lazy"></figure><h4 id="systeminfo-mostra-os-detalhes-do-seu-pc"><code>systeminfo</code> – mostra os detalhes do seu PC</h4><p>Se você quiser ver informações mais detalhadas sobre o seu sistema que você não vê na GUI, esse é o comando para você.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss4-1.png" class="kg-image" alt="ss4-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss4-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss4-1.png 825w" sizes="(min-width: 720px) 720px" width="825" height="473" loading="lazy"></figure><h4 id="set-mostra-as-vari-veis-de-ambiente-do-seu-pc"><code>set</code> – mostra as variáveis de ambiente do seu PC</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss5-2.png" class="kg-image" alt="ss5-2" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss5-2.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss5-2.png 844w" sizes="(min-width: 720px) 720px" width="844" height="611" loading="lazy"></figure><h4 id="prompt-altera-o-texto-padr-o-exibido-antes-de-inserir-comandos"><code>prompt</code> – altera o texto padrão exibido antes de inserir comandos</h4><p>Por padrão, o prompt de comando mostra o caminho da unidade C para sua conta de usuário.</p><p>Você pode usar o comando <code>prompt</code> para alterar esse texto padrão com a sintaxe <code>prompt nome_do_prompt $G</code>:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss6-1.png" class="kg-image" alt="ss6-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss6-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss6-1.png 774w" sizes="(min-width: 720px) 720px" width="774" height="380" loading="lazy"></figure><p><strong>Observação:</strong> se você não anexar <code>$G</code> ao comando, não obterá o símbolo de maior que (<code>&gt;</code>) na frente do texto.</p><h4 id="clip-copia-um-item-para-a-rea-de-transfer-ncia"><code>clip</code> – copia um item para a área de transferência</h4><p>Por exemplo, <code>dir | clip</code> copia todo o conteúdo do diretório de trabalho atual para a área de transferência.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss7.png" class="kg-image" alt="ss7" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss7.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss7.png 734w" sizes="(min-width: 720px) 720px" width="734" height="423" loading="lazy"></figure><p>Você pode digitar <code>clip /?</code> e pressionar <code>ENTER</code> para ver como usá-lo.</p><h4 id="assoc-lista-os-programas-e-as-extens-es-com-as-quais-eles-est-o-associados"><code>assoc</code> – lista os programas e as extensões com as quais eles estão associados</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss8.png" class="kg-image" alt="ss8" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss8.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss8.png 674w" width="674" height="478" loading="lazy"></figure><h4 id="title-altera-o-t-tulo-da-janela-do-prompt-de-comando-usando-o-formato-title-nome-do-t-tulo-da-janela"><code>title</code> – altera o título da janela do prompt de comando usando o formato <code>title nome-do-título-da-janela</code></h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss9.png" class="kg-image" alt="ss9" width="445" height="190" loading="lazy"></figure><h4 id="fc-compara-dois-arquivos-semelhantes"><code>fc</code> – compara dois arquivos semelhantes</h4><p>Se você é um programador ou escritor e deseja ver rapidamente a diferença entre dois arquivos, pode inserir esse comando e, em seguida, o caminho completo para os dois arquivos. Por exemplo, <code>fc "caminho-do-arquivo-1" "caminho-do-arquivo-2"</code>.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss10.png" class="kg-image" alt="ss10" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss10.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/ss10.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss10.png 1298w" sizes="(min-width: 720px) 720px" width="1298" height="600" loading="lazy"></figure><h4 id="cipher-limpa-o-espa-o-livre-e-criptografa-dados"><code>cipher</code> – limpa o espaço livre e criptografa dados</h4><p>Em um PC, os arquivos excluídos permanecem acessíveis para você e outros usuários. Então, tecnicamente, eles não são excluídos nos bastidores.</p><p>Você pode usar o comando <code>cipher</code> para limpar a unidade e criptografar esses arquivos.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss11.png" class="kg-image" alt="ss11" width="585" height="344" loading="lazy"></figure><h4 id="netstat-an-mostra-as-portas-abertas-seus-endere-os-ip-e-estados"><code>netstat -an</code> – mostra as portas abertas, seus endereços IP e estados</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss12.png" class="kg-image" alt="ss12" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss12.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss12.png 802w" sizes="(min-width: 720px) 720px" width="802" height="397" loading="lazy"></figure><h4 id="ping-mostra-o-endere-o-ip-de-um-site-permite-saber-quanto-tempo-leva-para-transmitir-dados-e-obter-uma-resposta"><code>ping</code> – mostra o endereço IP de um site, permite saber quanto tempo leva para transmitir dados e obter uma resposta</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss13.png" class="kg-image" alt="ss13" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss13.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss13.png 602w" width="602" height="311" loading="lazy"></figure><h4 id="color-altera-a-cor-do-texto-do-prompt-de-comando"><code>color</code> – altera a cor do texto do prompt de comando</h4><p>Digite <code>color attr</code> para ver as cores para as quais você pode mudar:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss14.png" class="kg-image" alt="ss14" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss14.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/ss14.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss14.png 1309w" sizes="(min-width: 720px) 720px" width="1309" height="912" loading="lazy"></figure><p>Digitar <code>color 2</code> muda a cor do terminal para verde:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss15.png" class="kg-image" alt="ss15" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss15.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss15.png 896w" sizes="(min-width: 720px) 720px" width="896" height="399" loading="lazy"></figure><h4 id="for-f-skip-9-tokens-1-2-delims-i-in-netsh-wlan-show-profiles-do-echo-j-findstr-i-v-echo-netsh-wlan-show-profiles-j-key-clear-mostra-todas-as-senhas-de-wi-fi"><code>for /f "skip=9 tokens=1,2 delims=:" %i in ('netsh wlan show profiles') do @echo %j | findstr -i -v echo | netsh wlan show profiles %j key=clear</code> – mostra todas as senhas de Wi-Fi</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss16.png" class="kg-image" alt="ss16" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss16.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/ss16.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss16.png 1370w" sizes="(min-width: 720px) 720px" width="1370" height="732" loading="lazy"></figure><h4 id="ipconfig-mostra-informa-es-sobre-endere-os-ip-e-conex-es-do-pc"><code>ipconfig</code> – mostra informações sobre endereços IP e conexões do PC</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss17-1.png" class="kg-image" alt="ss17-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss17-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss17-1.png 604w" width="604" height="401" loading="lazy"></figure><p>Esse comando também possui extensões como <code>ipconfig /release</code>, <code>ipconfig /renew</code> e <code>ipconfig /flushdns</code>, que você pode usar para solucionar problemas com conexões de internet.</p><h4 id="sfc-verificador-de-arquivos-do-sistema"><code>sfc</code> – verificador de arquivos do sistema</h4><p>Esse comando verifica seu computador em busca de arquivos corrompidos e os repara. A extensão do comando que você pode usar para executar uma verificação é <code>/scannow</code>.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss18.png" class="kg-image" alt="ss18" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss18.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss18.png 990w" sizes="(min-width: 720px) 720px" width="990" height="560" loading="lazy"></figure><h4 id="powercfg-controla-as-configura-es-de-energia-configur-veis"><code>powercfg</code> – controla as configurações de energia configuráveis</h4><p>Você pode usar esse comando com suas várias extensões para mostrar informações sobre o estado de energia do seu PC.</p><p>Você pode digitar <code>powercfg help</code> para mostrar essas extensões.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss19.png" class="kg-image" alt="ss19" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss19.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss19.png 651w" width="651" height="412" loading="lazy"></figure><p>Por exemplo, você pode usar <code>powercfg /energy</code> para gerar um relatório de integridade da bateria.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss20.png" class="kg-image" alt="ss20" width="552" height="295" loading="lazy"></figure><p>O comando <code>powercfg /energy</code> gerará um arquivo HTML contendo o relatório. Você pode encontrar o arquivo HTML em <code>C:\Windows\system32\energy-report.html</code>.</p><h4 id="dir-lista-itens-em-um-diret-rio"><code>dir</code> – lista itens em um diretório</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss21.png" class="kg-image" alt="ss21" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss21.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss21.png 676w" width="676" height="377" loading="lazy"></figure><h4 id="del-exclui-um-arquivo"><code>del</code> – exclui um arquivo</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss22.png" class="kg-image" alt="ss22" width="491" height="235" loading="lazy"></figure><h4 id="attrib-h-s-r-nome_da_pasta-oculta-uma-pasta"><code>attrib +h +s +r nome_da_pasta</code> – oculta uma pasta</h4><p>Você pode ocultar uma pasta diretamente da linha de comando digitando <code>attrib +h +s +r nome_da_pasta</code> e pressionando <code>ENTER</code>.</p><p>Para mostrar a pasta novamente, execute o comando <code>attrib -h -s -r nome_da_pasta</code>.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss23.png" class="kg-image" alt="ss23" width="577" height="147" loading="lazy"></figure><h4 id="start-endere-o-do-site-abre-um-site-a-partir-da-linha-de-comando"><code>start endereço-do-site</code> – abre um site a partir da linha de comando</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss24.png" class="kg-image" alt="ss24" width="527" height="174" loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss25.png" class="kg-image" alt="ss25" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss25.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/ss25.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss25.png 1600w" sizes="(min-width: 720px) 720px" width="1600" height="704" loading="lazy"></figure><h4 id="tree-mostra-a-rvore-do-diret-rio-atual-ou-da-unidade-especificada"><code>tree</code> – mostra a árvore do diretório atual ou da unidade especificada</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss26.png" class="kg-image" alt="ss26" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss26.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss26.png 714w" width="714" height="720" loading="lazy"></figure><h4 id="ver-mostra-a-vers-o-do-sistema-operacional"><code>ver</code> – mostra a versão do sistema operacional</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss27.png" class="kg-image" alt="ss27" width="527" height="307" loading="lazy"></figure><h4 id="tasklist-mostra-os-programas-abertos"><code>tasklist</code> – mostra os programas abertos</h4><p>Você pode fazer a mesma coisa que faz com o gerenciador de tarefas com esse comando:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss28.png" class="kg-image" alt="ss28" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss28.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss28.png 722w" sizes="(min-width: 720px) 720px" width="722" height="408" loading="lazy"></figure><p>O próximo comando mostra como fechar uma tarefa aberta.</p><h4 id="taskkill-encerra-uma-tarefa-em-execu-o"><code>taskkill</code> – encerra uma tarefa em execução</h4><p>Para encerrar uma tarefa, execute <code>taskkill /IM "tarefa.exe" /F</code>. Por exemplo, <code>taskkill /IM "chrome.exe" /F</code>:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss29.png" class="kg-image" alt="ss29" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss29.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss29.png 828w" sizes="(min-width: 720px) 720px" width="828" height="308" loading="lazy"></figure><h4 id="date-mostra-e-altera-a-data-atual"><code>date</code> – mostra e altera a data atual</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss30.png" class="kg-image" alt="ss30" width="510" height="286" loading="lazy"></figure><h4 id="time-mostra-e-altera-a-hora-atual"><code>time</code> – mostra e altera a hora atual</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss31.png" class="kg-image" alt="ss31" width="555" height="283" loading="lazy"></figure><h4 id="vol-mostra-o-n-mero-de-s-rie-e-as-informa-es-de-r-tulo-da-unidade-atual"><code>vol</code> – mostra o número de série e as informações de rótulo da unidade atual</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss32.png" class="kg-image" alt="ss32" width="489" height="297" loading="lazy"></figure><h4 id="dism-executa-a-ferramenta-de-gerenciamento-e-manuten-o-de-imagens-de-implanta-o"><code>dism</code> – executa a ferramenta de gerenciamento e manutenção de imagens de implantação</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/08/ss33.png" class="kg-image" alt="ss33" width="600" height="400" loading="lazy"></figure><h4 id="ctrl-c-interrompe-a-execu-o-de-um-comando"><code>CTRL + C</code> – interrompe a execução de um comando</h4><h4 id="-help-fornece-um-guia-para-outros-comandos"><code>-help</code> – fornece um guia para outros comandos</h4><p>Por exemplo, <code>powercfg -help</code> mostra como usar o comando <code>powercfg</code></p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss34.png" class="kg-image" alt="ss34" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss34.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss34.png 639w" width="639" height="379" loading="lazy"></figure><h4 id="echo-mostra-mensagens-personalizadas-ou-mensagens-de-um-script-ou-arquivo"><code>echo</code> – mostra mensagens personalizadas ou mensagens de um script ou arquivo</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss35.png" class="kg-image" alt="ss35" width="491" height="282" loading="lazy"></figure><p>Você também pode usar o comando <code>echo</code> para criar um arquivo com esta sintaxe: <code>echo conteúdo-do-arquivo &gt; nome-do-arquivo.extensão</code>.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss36.png" class="kg-image" alt="ss36" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss36.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss36.png 609w" width="609" height="266" loading="lazy"></figure><h4 id="mkdir-cria-uma-pasta"><code>mkdir</code> – cria uma pasta</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss37.png" class="kg-image" alt="ss37" width="443" height="235" loading="lazy"></figure><h4 id="rmdir-exclui-uma-pasta"><code>rmdir</code> – exclui uma pasta</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss38.png" class="kg-image" alt="ss38" width="502" height="299" loading="lazy"></figure><p><strong>Observação:</strong> a pasta deve estar vazia para que esse comando funcione.</p><h4 id="more-mostra-mais-informa-es-ou-o-conte-do-de-um-arquivo"><code>more</code> – mostra mais informações ou o conteúdo de um arquivo</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss39.png" class="kg-image" alt="ss39" width="521" height="270" loading="lazy"></figure><h4 id="move-move-um-arquivo-ou-pasta-para-uma-pasta-especificada"><code>move</code> – move um arquivo ou pasta para uma pasta especificada</h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss40.png" class="kg-image" alt="ss40" width="553" height="268" loading="lazy"></figure><h4 id="ren-renomeia-um-arquivo-com-a-sintaxe-ren-nome-do-arquivo-extens-o-novo-nome-extens-o"><code>ren</code> – renomeia um arquivo com a sintaxe <code>ren nome-do-arquivo.extensão novo-nome.extensão</code></h4><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss41-1.png" class="kg-image" alt="ss41-1" width="555" height="296" loading="lazy"></figure><h4 id="cls-limpa-a-linha-de-comando"><code>cls</code> – limpa a linha de comando</h4><p>Caso você insira vários comandos e a linha de comando fique congestionada, você pode usar <code>cls</code> para limpar todas as entradas e suas saídas.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/cls.gif" class="kg-image" alt="cls" width="600" height="338" loading="lazy"></figure><h4 id="exit-fecha-a-linha-de-comando"><code>exit</code> – fecha a linha de comando</h4><h4 id="shutdown-desliga-reinicia-hiberna-suspende-o-computador"><code>shutdown</code> – desliga, reinicia, hiberna, suspende o computador</h4><p>Você pode desligar, reiniciar, hibernar e suspender seu PC a partir da linha de comando.</p><p>Digite <code>shutdown</code> na linha de comando para ver as extensões que você pode usar para executar as ações. Por exemplo, <code>shutdown /r</code>0 reiniciará seu computador.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss42.png" class="kg-image" alt="ss42" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ss42.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ss42.png 858w" sizes="(min-width: 720px) 720px" width="858" height="504" loading="lazy"></figure><h3 id="conclus-o">Conclusão</h3><p>Este artigo mostrou vários comandos "desconhecidos para muitos" que você pode usar para obter acesso a funcionalidades ocultas em seu PC com Windows.</p><p>Novamente, você deve ter cuidado ao trabalhar com esses comandos porque eles podem ter um efeito duradouro em seu sistema operacional.</p><p>Se você achar os comandos úteis, compartilhe o artigo com seus amigos e familiares.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ O que é CI/CD? Aprenda integração contínua/entrega contínua criando um projeto ]]>
                </title>
                <description>
                    <![CDATA[ Olá! Neste artigo, você aprenderá sobre CI/CD (integração contínua e implantação contínua). Vamos revisar o que essa prática significa, como ela se compara à abordagem anterior na indústria de desenvolvimento de software e, finalmente, ver um exemplo prático de como podemos implementá-la em nossos projetos. Vamos lá! Índice  * ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/</link>
                <guid isPermaLink="false">6687189223266d03fc8b83b3</guid>
                
                    <category>
                        <![CDATA[ Integração contínua ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Tue, 16 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/jj-ying-4XvAZN8_WHo-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/what-is-ci-cd/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">What is CI/CD? Learn Continuous Integration/Continuous Deployment by Building a Project</a>
      </p><p>Olá! Neste artigo, você aprenderá sobre CI/CD (integração contínua e implantação contínua).</p><p>Vamos revisar o que essa prática significa, como ela se compara à abordagem anterior na indústria de desenvolvimento de software e, finalmente, ver um exemplo prático de como podemos implementá-la em nossos projetos.</p><p>Vamos lá!</p><h1 id="-ndice">Índice</h1><ul><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#introdu-o">Introdução</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#como-o-ci-cd-funciona">Como o CI/CD funciona</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#os-principais-benef-cios-do-ci-cd">Os principais benefícios do CI/CD</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#ferramentas-para-ci-cd">Ferramentas para CI/CD</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#como-configurar-um-pipeline-de-ci-cd-com-github-actions">Como configurar um pipeline de CI/CD com GitHub Actions</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#inicializando-o-projeto">Inicializando o projeto</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#o-que-s-o-github-actions-e-como-funcionam">O que são GitHub Actions e como funcionam?</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#configurando-nosso-fluxo-de-trabalho">Configurando nosso fluxo de trabalho</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#a-m-gica">A mágica</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/o-que-e-ci-cd-aprenda-integracao-continua-entrega-continua-criando-um-projeto/#conclus-o">Conclusão</a></li></ul><h1 id="introdu-o">Introdução</h1><p>Integração Contínua e Entrega Contínua (CI/CD, do inglês <em>Continuous Integration/Continuous Delivery</em>) é uma abordagem de desenvolvimento de software que visa melhorar a velocidade, eficiência e confiabilidade da entrega de software. Ela envolve integração frequente de código, testes automatizados e entrega contínua de alterações de software em produção.</p><p>Antes da adoção do CI/CD na indústria de desenvolvimento de software, a abordagem comum era um modelo tradicional em <strong>cascata</strong> de desenvolvimento de software.</p><p>Nessa abordagem, os desenvolvedores trabalhavam em silos, com cada etapa do ciclo de vida do desenvolvimento de software sendo concluída após a anterior. O processo normalmente envolvia a coleta de requisitos, o design do software, a programação, os testes e a implantação.</p><p><strong>As desvantagens dessa abordagem tradicional incluem:</strong></p><ol><li><strong>Ciclos de lançamento lentos:</strong> como cada etapa do ciclo de vida do desenvolvimento de software era concluída em sequência, o ciclo de lançamento era lento, o que dificultava a resposta rápida às mudanças nas necessidades do cliente.</li><li><strong>Altas taxas de falha:</strong> os projetos de software eram propensos a falhas devido à falta de testes automatizados, o que significava que os desenvolvedores tinham que confiar em testes manuais, levando a erros e <em>bugs </em>no código.</li><li><strong>Colaboração limitada:</strong> a abordagem tradicional não incentivava a colaboração entre desenvolvedores, testadores e outras partes interessadas, o que dificultava a identificação e correção de problemas.</li><li><strong>Alto custo:</strong> a natureza manual do desenvolvimento de software significava que era caro, com altos custos associados a testes, depuração e correção de erros.</li><li><strong>Agilidade limitada:</strong> como a abordagem tradicional era linear, não era possível fazer alterações no software rapidamente ou responder às necessidades do cliente em tempo real.</li></ol><p>O CI/CD surgiu como uma solução para essas desvantagens, introduzindo uma abordagem mais ágil e colaborativa para o desenvolvimento de software. O CI/CD permite que as equipes trabalhem juntas, integrando suas alterações de código com frequência e automatizando o processo de teste e implantação.</p><h1 id="como-o-ci-cd-funciona">Como o CI/CD funciona</h1><p>O CI/CD é um processo automatizado que envolve integração frequente de código, testes automatizados e implantação contínua de alterações de software em produção.</p><p>Vamos explicar cada etapa com um pouco mais de detalhes:</p><h3 id="integra-o-de-c-digo">Integração de código</h3><p>A primeira etapa no <em>pipeline</em> de CI/CD é a integração de código. Nessa etapa, os desenvolvedores confirmam suas alterações de código em um repositório remoto (como <a href="https://github.com/">GitHub</a>, <a href="https://about.gitlab.com/">GitLab</a> ou <a href="https://bitbucket.org/product/">BitBucket</a>), onde o código é integrado à base de código principal.</p><p>Essa etapa visa garantir que as alterações de código sejam compatíveis com o restante da base de código e não interrompam a compilação.</p><h3 id="testes-automatizados">Testes automatizados</h3><p>Uma vez que o código é integrado, a próxima etapa é o teste automatizado. O teste automatizado envolve a execução de um conjunto de testes para garantir que as alterações de código sejam funcionais, atendam aos padrões de qualidade esperados e estejam livres de defeitos.</p><p>Essa etapa ajuda a identificar problemas no início do processo de desenvolvimento, permitindo que os desenvolvedores os corrijam de maneira rápida e eficiente.</p><p>Se você não está familiarizado com o tópico de testes, consulte <a href="https://www.freecodecamp.org/portuguese/news/como-escrever-testes-unitarios-em-java/">este artigo</a>.</p><h3 id="entrega-cont-nua">Entrega contínua</h3><p>Depois que as alterações de código passam na etapa de teste automatizado, a próxima etapa é a entrega contínua. Nessa etapa, as alterações de código são implantadas automaticamente em um ambiente de teste para testes adicionais.</p><p>Essa etapa visa garantir que o software seja atualizado continuamente com as alterações de código mais recentes, entregando novos recursos e funcionalidades aos usuários de maneira rápida e eficiente.</p><h3 id="implanta-o-em-produ-o">Implantação em produção</h3><p>A etapa final no <em>pipeline </em>de CI/CD é a implantação em produção. Nessa etapa, as alterações de software são lançadas para os usuários finais. Essa etapa envolve o monitoramento do ambiente de produção, garantindo que o software esteja funcionando sem problemas e identificando e corrigindo quaisquer problemas que surjam.</p><p>As quatro etapas de um <em>pipeline </em>de CI/CD trabalhem juntas para garantir que as alterações de software sejam testadas, integradas e implantadas em produção automaticamente. Essa automação ajuda a reduzir erros, aumentar a eficiência e melhorar a qualidade geral do software.</p><p>Ao adotar um <em>pipeline</em> de CI/CD, as equipes de desenvolvimento podem alcançar ciclos de lançamento mais rápidos, reduzir o risco de defeitos de software e melhorar a experiência do usuário.</p><p>Lembre-se de que as etapas do <em>pipeline </em>podem parecer diferentes, dado o projeto ou empresa específica sobre a qual estamos falando. Ou seja, algumas equipes podem ou não usar testes automatizados, algumas equipes podem ou não ter um ambiente de "teste" e assim por diante.</p><p>As partes principais que compõem a prática de CI/CD são a integração e a implantação (entrega). Isso significa que o código deve ser continuamente integrado em um repositório remoto e que esse código deve ser continuamente implantado em um determinado ambiente após cada integração.</p><h1 id="os-principais-benef-cios-do-ci-cd">Os principais benefícios do CI/CD</h1><p>Os principais benefícios do CI/CD incluem:</p><ol><li><strong>Ciclos de lançamento mais rápidos:</strong> ao automatizar o processo de teste e implantação, o CI/CD permite que as equipes lancem software com mais frequência, respondendo rapidamente às necessidades do cliente.</li><li><strong>Qualidade aprimorada:</strong> o teste automatizado garante que as alterações de software não introduzam novos <em>bugs </em>ou problemas, melhorando a qualidade geral do software.</li><li><strong>Maior colaboração:</strong> a integração e o teste frequentes de código exigem que os desenvolvedores trabalhem em estreita colaboração, levando a uma melhor colaboração e comunicação.</li><li><strong>Risco reduzido:</strong> a implantação contínua permite que os desenvolvedores identifiquem e corrijam problemas rapidamente, reduzindo o risco de falhas graves e tempo de inatividade.</li><li><strong>Custo-benefício:</strong> o CI/CD reduz a quantidade de trabalho manual necessária para implantar alterações de software, economizando tempo e reduzindo custos.</li></ol><p>Em resumo, o CI/CD surgiu como uma solução para as limitações da abordagem tradicional e linear para o desenvolvimento de software. Ao introduzir uma abordagem mais ágil e colaborativa para o desenvolvimento de software, o CI/CD permite que as equipes trabalhem juntas, lancem software com mais frequência e respondam rapidamente às necessidades do cliente.</p><h1 id="ferramentas-para-ci-cd">Ferramentas para CI/CD</h1><p>Existem várias ferramentas disponíveis para implementar <em>pipelines</em> de CI/CD no desenvolvimento de software. Cada ferramenta tem seus recursos, prós e contras exclusivos. Aqui estão algumas das ferramentas mais usadas em pipelines de CI/CD hoje:</p><h3 id="jenkins">Jenkins</h3><p>O <a href="https://www.jenkins.io/">Jenkins</a> é um servidor de automação de código aberto amplamente utilizado em <em>pipelines</em> de CI/CD. É altamente personalizável e suporta uma grande variedade de <em>plug-ins</em>, tornando-o adequado para vários ambientes de desenvolvimento. Alguns de seus principais recursos incluem:</p><p><strong>Prós:</strong></p><ul><li>Altamente personalizável com uma grande quantidade de <em>plug-ins</em></li><li>Suporta integração com várias ferramentas e tecnologias</li><li>Fornece relatórios e análises detalhados</li></ul><p><strong>Contras:</strong></p><ul><li>Requer alguma experiência técnica para configurar e manter</li><li>Pode consumir muitos recursos, especialmente para grandes projetos</li><li>Falta de um painel centralizado para gerenciar vários projetos</li></ul><p>Se você quiser saber mais sobre o Jenkins, <a href="https://en.wikipedia.org/wiki/Jenkins_(software)">clique aqui</a> (em inglês).</p><h3 id="travis-ci">Travis CI</h3><p>O <a href="https://www.travis-ci.com/">Travis CI</a> é uma plataforma de CI/CD baseada em nuvem que fornece testes e implantação automatizados para projetos de software. Ele suporta várias linguagens de programação e <em>frameworks</em>, tornando-o adequado para vários ambientes de desenvolvimento. Alguns de seus principais recursos incluem:</p><p><strong>Prós:</strong></p><ul><li>Fácil de configurar e usar</li><li>Baseado em nuvem, não havendo a necessidade de configurar e manter a infraestrutura</li><li>Suporta uma grande variedade de linguagens de programação e <em>frameworks</em></li><li>Fornece relatórios e análises detalhados</li></ul><p><strong>Contras:</strong></p><ul><li>Opções de personalização limitadas</li><li>Não é adequado para grandes projetos com requisitos complexos</li><li>Suporte limitado para instalações locais</li></ul><p>Para saber mais sobre o Travis CI, <a href="https://en.wikipedia.org/wiki/Travis_CI">clique aqui</a> (em inglês).</p><h3 id="github-actions">GitHub Actions</h3><p><a href="https://github.com/features/actions">GitHub Actions</a> é uma ferramenta poderosa de CI/CD, que permite que os desenvolvedores automatizem fluxos de trabalho, executem testes e implantem código diretamente de seus repositórios no GitHub.</p><p><strong>Prós:</strong></p><ul><li>Integrado ao GitHub</li><li>Fácil de usar</li><li>Fornece um grande ecossistema e boa documentação</li></ul><p><strong>Contras:</strong></p><ul><li>Minutos de compilação limitados</li><li>Sintaxe YAML complexa</li></ul><blockquote>Nota: menciono GitHub Actions aqui porque é uma ferramenta popular – mas lembre-se de que outros provedores de repositórios online, como GitLab e BitBucket, também oferecem opções muito semelhantes às GitHub Actions.</blockquote><h3 id="recursos-de-ci-cd-integrados-por-hosts">Recursos de CI/CD integrados por <em>hosts</em></h3><p><em>Hosts </em>populares, como <a href="https://vercel.com/">Vercel</a> ou <a href="https://www.netlify.com/">Netlify</a>, têm recursos de CI/CD integrados que permitem vincular um repositório <em>on-line</em> a um determinado site e implantar nesse site após um determinado evento ocorrer nesse repositório.</p><p><strong>Prós:</strong></p><ul><li>Muito simples de configurar e usar</li></ul><p><strong>Contras:</strong></p><ul><li>Opções de personalização limitadas</li></ul><p>Cada uma dessas ferramentas tem seus recursos, prós e contras exclusivos. A escolha da ferramenta dependerá dos requisitos específicos do seu projeto, da experiência técnica da sua equipe e do seu orçamento.</p><h1 id="como-configurar-um-pipeline-de-ci-cd-com-github-actions">Como configurar um <em>pipeline</em> de CI/CD com GitHub Actions</h1><p>Agora que temos uma ideia clara do que é CI/CD, vamos ver como podemos implementar um exemplo simples com um projeto real usando <a href="https://github.com/features/actions">GitHub Actions</a>.</p><h2 id="inicializando-o-projeto">Inicializando o projeto</h2><p>Começaremos com uma aplicação do React muito básica construída com <a href="https://en.wikipedia.org/wiki/Vite_(software)">Vite</a>. Você pode fazer isso executando <code>yarn create vite</code> no seu console.</p><p>Vamos nos concentrar no <em>pipeline </em>de CI/CD aqui. Então, não haverá complexidade no código real da aplicação. Para se ter uma ideia, porém, o componente <code>app.jsx</code> terá este código:</p><pre><code class="language-javascript">import './App.css';

function App() {

    return (
        &lt;div className='App'&gt;
            &lt;h1&gt;Vite + Reactooooo&lt;/h1&gt;
        &lt;/div&gt;
    );
}

export default App;</code></pre><p>Então, teremos um arquivo de teste que verificará se esse texto é renderizado:</p><pre><code class="language-javascript">import { describe, expect, it } from 'vitest';
import { render, screen } from './utils/test-utils/test-utils.jsx';

import App from 'src/App.jsx';

describe('App', async () =&gt; {
    it('deve renderizar durante a autenticação', () =&gt; {
        render(&lt;App /&gt;);

        expect(screen.getByText('Vite + Reactooooo')).toBeInTheDocument();
    });
});</code></pre><p>Esse teste será executado cada vez que executarmos o comando <code>yarn test</code>.</p><p>O próximo passo deve ser enviar nosso código para um repositório no GitHub. Vamos falar um pouco mais sobre o que são GitHub Actions e sobre como funcionam.</p><h2 id="o-que-s-o-github-actions-e-como-funcionam">O que são GitHub Actions e como funcionam?</h2><p>GitHub Actions é um serviço de CI/CD (Integração Contínua/Entrega Contínua) fornecido pelo GitHub. Ele permite que os desenvolvedores automatizem fluxos de trabalho definindo <em>scripts</em> personalizados, conhecidos como "ações", que podem ser acionados por eventos como <em>pushes </em>para um repositório, <em>pull requests </em>ou <em>issues</em>.</p><p>As ações são definidas em um arquivo YAML, também conhecido como "fluxo de trabalho", que especifica as etapas necessárias para concluir uma tarefa. Os fluxos de trabalho das GitHub Actions podem ser executados em ambientes Linux, Windows e macOS e suportam uma grande variedade de linguagens de programação e <em>frameworks</em>.</p><p>Quando um evento aciona um fluxo de trabalho das GitHub Actions, o serviço cria um novo ambiente, instala dependências e executa as etapas definidas na ordem especificada. Isso pode incluir tarefas como compilar, testar, empacotar e implantar código.</p><p>As GitHub Actions também fornecem várias ações integradas, que podem ser usadas para simplificar tarefas comuns, como verificar código, compilar e testar aplicações, publicar lançamentos e implantar em provedores de nuvem populares como AWS, Azure e Google Cloud.</p><p>Os fluxos de trabalho das GitHub Actions podem ser executados em um cronograma, manualmente ou automaticamente, quando um evento específico ocorre, como um <em>pull request</em> sendo aberto ou um novo <em>commit </em>sendo enviado para uma <em>branch</em>.</p><h2 id="configurando-nosso-fluxo-de-trabalho">Configurando nosso fluxo de trabalho</h2><p>Como vimos, basicamente, as GitHub Actions são um recurso que nos permite definir fluxos de trabalho para nossos projetos. Esses fluxos de trabalho nada mais são do que uma série de tarefas ou etapas que serão executadas na nuvem do GitHub após um determinado evento que declaramos.</p><p>A maneira como o GitHub lê e executa esses fluxos de trabalho é lendo automaticamente os arquivos dentro do diretório <code>.github/workflows</code> na raiz do nosso projeto. Esses arquivos de fluxo de trabalho devem ter a extensão <code>.yaml</code> e usar a sintaxe <a href="https://www.redhat.com/en/topics/automation/what-is-yaml">YAML</a>.</p><p>Para criar um fluxo de trabalho, basta criar um arquivo YAML dentro desse diretório. Chamaremos o nosso de <code>prod.yaml</code>, pois o usaremos para implantar a <em>branch </em>de produção do nosso projeto.</p><p>Lembre-se de que um único projeto pode ter muitos fluxos de trabalho diferentes que executam tarefas diferentes em ocasiões diferentes. Por exemplo, poderíamos ter um fluxo de trabalho para <em>branches </em>de desenvolvimento e teste também, pois esses ambientes podem exigir tarefas diferentes para executar e provavelmente serão implantados em sites diferentes.</p><p>Depois de criar esse arquivo, vamos colocar o seguinte código nele:</p><pre><code class="language-yaml"># Nome do nosso fluxo de trabalho
name: Implantação de Produção

# Aciona o fluxo de trabalho no push para o branch principal
on:
  push:
    branches:
      - main

# Lista de trabalhos
# Um "trabalho" é um conjunto de etapas que são executadas no mesmo executor
jobs:
  # Nome do trabalho
  testar-e-implantar-no-netlify:
    # Sistema operacional para executar
    runs-on: ubuntu-latest

    # Lista de etapas que compõem o trabalho
    steps:
    # Faz checkout do seu repositório em $GITHUB_WORKSPACE, para que seu trabalho possa acessá-lo
    - name: Checkout do código
      uses: actions/checkout@v2

    # Configurar ambiente Node.js
    - name: Usar Node.js 16.x
      uses: actions/setup-node@v2
      with:
        node-version: '16.x'

    # Instalar dependências
    - name: Instalar dependências
      run: yarn install

    # Executar testes
    - name: Executar testes
      run: yarn test

    # Implantar no Netlify
    - name: Implantação Netlify
      uses: jsmrcaga/action-netlify-deploy@v2.0.0
      with:
        # Token de autenticação para usar com o Netlify
        NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
        # ID do seu site Netlify
        NETLIFY_SITE_ID:  ${{ secrets.NETLIFY_SITE_ID }}
        # Diretório onde os arquivos compilados são armazenados
        build_directory: './dist'
        # Comando para instalar dependências
        install_command: yarn install
        # Comando para compilar o site estático
        build_command: yarn build   </code></pre><p>Então, nosso fluxo de trabalho tem as seguintes tarefas declaradas:</p><ol><li>Etapa "Checkout do código", que faz <em>checkout</em> do último <em>commit</em> na <em>branch</em> atual.</li><li>Etapa "Usar Node.js 16.x", que configura o ambiente Node.js para a versão 16.x.</li><li>Etapa "Instalar dependências", que instala as dependências do projeto usando o gerenciador de pacotes Yarn.</li><li>Etapa "Executar testes", que executa os testes do projeto usando o gerenciador de pacotes Yarn.</li><li>Etapa "Implantação no Netlify", que implanta o projeto no Netlify usando a ação <code>jsmrcaga/action-netlify-deploy</code>. Essa etapa usa o <em>token </em>de autenticação do Netlify e os segredos de ID do site armazenados nos segredos do repositório GitHub. O diretório de compilação, o comando de instalação e o comando de compilação também são especificados.</li></ol><p>Você provavelmente notou que a primeira e a última etapas têm a palavra-chave <code>uses</code>. Essa palavra-chave permite que você use ações ou fluxos de trabalho desenvolvidos por outros usuários do GitHub e é um dos melhores recursos das GitHub Actions.</p><p>Algo fantástico é o fato de que, ao usar essas ações de terceiros, podemos executar tarefas complexas, como implantar em um <em>host </em>externo ou construir infraestrutura de nuvem complexa, sem a necessidade de escrever cada linha de código necessária.</p><p>Como essas tarefas tendem a ser repetitivas e frequentemente executadas em muitos projetos, podemos simplesmente usar um fluxo de trabalho desenvolvido por uma conta oficial da empresa (como Azure ou AWS, por exemplo) ou um desenvolvedor independente de código aberto. Pense nisso como usar uma biblioteca de terceiros. É a mesma ideia, mas aplicada aos fluxos de trabalho de CI/CD. É muito conveniente.</p><p>Outra coisa importante a mencionar aqui é que, nos fluxos de trabalho das GitHub Actions, as tarefas são executadas <strong>sequencialmente</strong>, uma após a outra. Se uma determinada tarefa falhar ou lançar um erro, <strong>a próxima não será executada</strong>. Isso é importante porque, se tivermos um problema ao instalar nossas dependências ou se um teste falhar, não queremos que esse código seja implantado.</p><p>Antes de enviarmos esse código e vermos como a mágica funciona, primeiro, precisamos criar um site no Netlify e obter o <strong>NETLIFY_AUTH_TOKEN</strong> e o <strong>NETLIFY_SITE_ID</strong>. Isso é bastante direto. Mesmo quee você não tenha experiência anterior com o Netlify, experimente e pesquise um pouco no Google se não conseguir descobrir. 😉</p><p>Depois de ter esses dois tokens, você precisa declará-los como segredos do repositório no seu repositório do GitHub. Você pode fazer isso na guia &nbsp;de configurações (<em>Settings</em>):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/image-32.png" class="kg-image" alt="image-32" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/image-32.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/image-32.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/image-32.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/image-32.png 1892w" sizes="(min-width: 720px) 720px" width="1892" height="889" loading="lazy"><figcaption>Configure os dois tokens secretos do Netlify no seu repositório</figcaption></figure><p>Com isso em vigor, agora nosso arquivo <code>prod.yaml</code> poderá ler esses dois tokens e executar a ação de implantação do Netlify.</p><h2 id="a-m-gica">A mágica</h2><p>Agora, que temos tudo no lugar, vamos enviar nosso código e ver como vai.</p><p>Após o <em>push</em>, se formos para a guia "<em>Actions</em>" do nosso repositório, à esquerda veremos uma lista de todos os fluxos de trabalho que temos em nosso repositório. À direita, veremos uma lista de cada execução do fluxo de trabalho selecionado. Como nosso fluxo de trabalho é executado após cada <em>push</em>, devemos ver uma nova execução cada vez que enviarmos.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/image-33.png" class="kg-image" alt="image-33" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/image-33.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/image-33.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/image-33.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/image-33.png 1874w" sizes="(min-width: 720px) 720px" width="1874" height="343" loading="lazy"><figcaption>Uma execução de fluxo de trabalho</figcaption></figure><p>Quando a execução tem uma luz amarela à esquerda, significa que ainda está em execução (executando tarefas). Se tiver uma luz verde, significa que terminou de executar com sucesso. Se a luz estiver vermelha, você sabe que algo deu errado.</p><p>Depois de clicar na execução, podemos ver uma lista dos trabalhos do fluxo de trabalho (tínhamos apenas um).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/image-34.png" class="kg-image" alt="image-34" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/image-34.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/image-34.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/image-34.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/image-34.png 1861w" sizes="(min-width: 720px) 720px" width="1861" height="539" loading="lazy"><figcaption>Os trabalhos do fluxo de trabalho</figcaption></figure><p>Depois de clicar no trabalho, podemos ver uma lista das tarefas do trabalho.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/image-35.png" class="kg-image" alt="image-35" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/image-35.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/image-35.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2024/07/image-35.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/image-35.png 1886w" sizes="(min-width: 720px) 720px" width="1886" height="908" loading="lazy"><figcaption>As tarefas do trabalho</figcaption></figure><p>Cada tarefa é expansível e, dentro dela, podemos ver os <em>logs </em>correspondentes à execução dessa tarefa. Isso é muito útil para fins de depuração. 😉</p><p>Agora, se formos para o nosso site do Netlify configurado anteriormente, devemos ver nossa aplicação funcionando!</p><p>Como temos nosso <em>pipeline </em>de CI/CD em funcionamento, podemos implantar nossa aplicação após cada <em>push </em>para a <em>branch </em>principal, tudo sem precisar de mais esforços. 😀</p><h1 id="conclus-o"><strong>Conclusão</strong></h1><p>CI/CD é uma abordagem de desenvolvimento de software que oferece vários benefícios às equipes de desenvolvimento de software, incluindo tempo mais rápido de lançamento no mercado, qualidade aprimorada, maior colaboração, risco reduzido e custo-benefício.</p><p>Ao automatizar o <em>pipeline </em>de entrega de software, as equipes podem implantar rapidamente novos recursos e correções de <em>bugs</em>, ao mesmo tempo em que reduzem o risco de falhas graves e tempo de inatividade.</p><p>Com a disponibilidade de várias ferramentas de CI/CD, tornou-se mais fácil para as equipes implementarem essa abordagem e melhorarem seu processo de entrega de software.</p><p>Como sempre, espero que tenham gostado do artigo e aprendido algo novo.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Bancos de dados ACID – atomicidade, consistência, isolamento e durabilidade explicados ]]>
                </title>
                <description>
                    <![CDATA[ ACID é a sigla para Atomicidade, Consistência, Isolamento e Durabilidade. Essas são quatro propriedades essenciais que a maioria dos sistemas de gerenciamento de bancos de dados (DBMS, do inglês DataBase Management Systems) oferece como garantia ao lidar com transações. A maioria dos DBMS populares, como MySQL [https://dev.mysql.com/doc/refman/9.0/en/mysql-acid.html], PostgresSQL [https://www.postgresql.org/about/] e ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/bancos-de-dados-acid-atomicidade-consistencia-isolamento-e-durabilidade-explicados/</link>
                <guid isPermaLink="false">6686464e23266d03fc8b81d2</guid>
                
                    <category>
                        <![CDATA[ Bancos de dados ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kris Lagerström ]]>
                </dc:creator>
                <pubDate>Mon, 15 Jul 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/cover-fcc.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/acid-databases-explained/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">ACID Databases –&nbsp;Atomicity, Consistency, Isolation &amp; Durability Explained</a>
      </p><p>ACID é a sigla para Atomicidade, Consistência, Isolamento e Durabilidade. Essas são quatro propriedades essenciais que a maioria dos sistemas de gerenciamento de bancos de dados (DBMS, do inglês <em>DataBase Management Systems</em>) oferece como garantia ao lidar com transações.</p><p>A maioria dos DBMS populares, como <a href="https://dev.mysql.com/doc/refman/9.0/en/mysql-acid.html">MySQL</a>, <a href="https://www.postgresql.org/about/">PostgresSQL</a> e <a href="https://docs.oracle.com/cd/F51125_01/docs.85/SDS%20PI/acid-compliant-transactions.html#GUID-ECB79D66-46DE-4F48-93DC-8677E7BB44EF">Oracle</a>, possui garantias ACID prontas para uso. Outros têm garantias ACID parciais, como <a href="https://www.oreilly.com/library/view/redis-cookbook/9781449311353/ch01.html#:~:text=Redis%20provides%20partial%20ACID%20compliance,also%20be%20a%20key%20factor.">Redis</a>, DynamoDB e Cassandra. A tendência, no entanto, parece ser que mais e mais DBMS ofereçam conformidade com ACID.</p><p>É importante observar que, embora muitos DBMS possam afirmar ser compatíveis com ACID, a implementação dessa conformidade pode variar.</p><p>Assim, por exemplo, se o isolamento é uma propriedade fundamental de que você precisa para uma aplicação que está criando, é necessário entender como exatamente o DBMS escolhido implementa o isolamento.</p><p>Este artigo explicará o que são transações e analisará em detalhes o que significam atomicidade, consistência, isolamento e durabilidade, usando analogias e exemplos do mundo real.</p><h3 id="-ndice-">Índice:</h3><ol><li><a href="https://www.freecodecamp.org/portuguese/news/bancos-de-dados-acid-atomicidade-consistencia-isolamento-e-durabilidade-explicados/#o-que-s-o-transa-es">O que são transações?</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/bancos-de-dados-acid-atomicidade-consistencia-isolamento-e-durabilidade-explicados/#o-que-significa-atomicidade">O que significa atomicidade?</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/bancos-de-dados-acid-atomicidade-consistencia-isolamento-e-durabilidade-explicados/#o-que-significa-consist-ncia">O que significa consistência?</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/bancos-de-dados-acid-atomicidade-consistencia-isolamento-e-durabilidade-explicados/#o-que-significa-isolamento">O que significa isolamento?</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/bancos-de-dados-acid-atomicidade-consistencia-isolamento-e-durabilidade-explicados/#o-que-significa-durabilidade">O que significa durabilidade?</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/bancos-de-dados-acid-atomicidade-consistencia-isolamento-e-durabilidade-explicados/#juntando-tudo">Juntando tudo</a></li></ol><h2 id="o-que-s-o-transa-es">O que são transações?</h2><p>Muitas coisas podem dar errado ao usar um banco de dados:</p><ul><li>o hardware ou software do banco de dados pode falhar</li><li>a aplicação que chama o banco de dados pode falhar no meio da operação</li><li>a rede pode ficar congestionada com mais tráfego do que ela pode lidar (tornando-a inoperante)</li><li>vários <em>clients</em> podem fazer gravações ao mesmo tempo que sobrescrevem as alterações uns dos outros</li><li>os <em>clients</em> podem ler dados fantasmas, que não deveriam estar no banco de dados</li></ul><p>Várias outras coisas podem dar errado - esta não é, de modo algum, uma lista completa.</p><p>Como algo pode dar errado de mais maneiras do que podemos prever, tentar evitar todas as falhas possíveis pode se tornar desnecessariamente caro e complicado. Em vez disso, é melhor projetar um sistema que possa continuar a operar apesar de uma falha. As transações nos permitem fazer isso.</p><p>As transações têm um único propósito: garantir que um sistema seja <strong><a href="https://pt.wikipedia.org/wiki/Toler%C3%A2ncia_a_falhas">tolerante a falhas</a>.</strong> Se ocorrer uma falha em um sistema, o sistema pode continuar a operar sem uma catástrofe completa? Dito de outro modo, o sistema consegue tolerar falhas? Uma resposta "sim" a essa pergunta significa que tal sistema é tolerante a falhas.</p><p>Então, o que é exatamente uma transação?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/718d52b8-c016-4746-a1eb-73b6aac6d5fa_636x960.png" class="kg-image" alt="718d52b8-c016-4746-a1eb-73b6aac6d5fa_636x960" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/718d52b8-c016-4746-a1eb-73b6aac6d5fa_636x960.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/718d52b8-c016-4746-a1eb-73b6aac6d5fa_636x960.png 636w" width="636" height="960" loading="lazy"><figcaption>Não, não estamos falando DESTE tipo de transação</figcaption></figure><p>Uma transação é uma <a href="https://pt.wikipedia.org/wiki/Abstra%C3%A7%C3%A3o">abstração</a>. É um conjunto de operações (leituras e gravações) que são tratadas como uma única operação lógica.</p><p>Imagine que você deseja comprar um único livro em uma loja on-line, como a amazon.com.br, por exemplo. As etapas abaixo mostram uma visão simplificada do que precisa acontecer:</p><ol><li>Primeiro, você seleciona o livro, adicionando o item à sua cesta.</li><li>A quantidade em estoque do livro é verificada para garantir que seja válida (ou seja, o valor do estoque para o título que você está comprando precisa ser maior que zero).</li><li>Você clica em "comprar", o que atualiza o estoque da Amazon para o livro e o diminui em 1 (já que você está comprando um único livro).</li><li>Além disso, o saldo da sua conta bancária é atualizado para contabilizar o custo do livro.</li></ol><p>Uma transação garante que todas as operações relacionadas à compra sejam tratadas como uma única operação. Se qualquer parte da transação falhar, toda a transação é revertida, deixando o banco de dados em um estado como se o cliente nunca tivesse tentado a compra, mantendo assim a integridade dos dados.</p><p>A transação é confirmada quando todas as operações dentro da transação são concluídas com sucesso e seus resultados são registrados permanentemente. Essa permanência é normalmente alcançada gravando as alterações no armazenamento do banco de dados, que pode ser em disco para bancos de dados tradicionais ou na memória para bancos de dados na memória, como o Redis.</p><p>Ao tratar todas essas diferentes operações como uma única operação lógica, o banco de dados pode oferecer algumas garantias sobre como ele pode ser tolerante a falhas. Essas garantias são <strong>atomicidade</strong>, <strong>consistência</strong>, <strong>isolamento</strong> e <strong>durabilidade</strong>.</p><h2 id="o-que-significa-atomicidade">O que significa atomicidade?</h2><p>Atomicidade significa simplesmente que todas as consultas em uma transação devem ser bem-sucedidas para que a transação seja bem-sucedida. Se uma consulta falhar, toda a transação falhará.</p><h3 id="um-restaurante-at-mico">Um restaurante atômico</h3><p>Imagine usar uma máquina de autoatendimento em um restaurante de fast-food. A transação, neste caso, é pedir comida e consiste em duas operações separadas:</p><ol><li>Selecionar comida</li><li>Fazer o pagamento</li></ol><p>Ambas devem ser bem-sucedidas para que a transação seja bem-sucedida. Se alguma falhar, a transação falhará.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/b52901d6-a9e0-43a7-a198-d56ca2a82219_544x886.png" class="kg-image" alt="b52901d6-a9e0-43a7-a198-d56ca2a82219_544x886" width="544" height="886" loading="lazy"><figcaption>Cliente fazendo um pedido em um restaurante "atômico"</figcaption></figure><p>Você seleciona seu hambúrguer, batata frita e uma bebida no menu da tela sensível ao toque. A máquina solicita que você pague e, somente depois de seu pagamento ser processado com sucesso, ela enviará seu pedido para a cozinha. Momentos depois, seu pedido completo está pronto e você o retira no balcão.</p><p>Essa é uma operação atômica: a transação (pedir comida) é totalmente concluída (se você selecionar seu item de comida e fizer um pagamento) ou não é concluída.</p><p>Se qualquer parte da transação falhar, toda a transação falhará. Se o seu pagamento falhar, a máquina não processará nenhuma parte do pedido, então a transação falhará. Se você fizer um pagamento sem selecionar um item de comida, a transação também falhará, pois não há nada para a cozinha preparar.</p><h3 id="um-restaurante-n-o-at-mico">Um restaurante não atômico</h3><p>Agora, considere a alternativa – um restaurante tradicional com serviço de mesa onde você pede vários pratos. À medida que cada prato é preparado, ele é trazido à sua mesa.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/045c9ec7-dbb9-45b7-ad4d-357f7b7cc37c_888x1026.png" class="kg-image" alt="045c9ec7-dbb9-45b7-ad4d-357f7b7cc37c_888x1026" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/045c9ec7-dbb9-45b7-ad4d-357f7b7cc37c_888x1026.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/045c9ec7-dbb9-45b7-ad4d-357f7b7cc37c_888x1026.png 888w" sizes="(min-width: 720px) 720px" width="888" height="1026" loading="lazy"><figcaption>Cliente fazendo um pedido em um restaurante "não atômico"</figcaption></figure><p>Novamente, a transação é pedir comida e consiste em duas operações separadas:</p><ol><li>Selecionar comida</li><li>Fazer o pagamento</li></ol><p>Nesse restaurante não atômico, a falha em fazer um pagamento não impede que a transação seja concluída, pois você paga depois de terminar sua refeição. Falhas parciais não fazem com que uma transação falhe.</p><p>Isso cria um risco para o restaurante. Os clientes que optam por comer e sair correndo podem pedir comida à vontade e simplesmente ir embora sem pagar, causando prejuízo financeiro para o restaurante.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/4136ceee-82b9-4cf0-b0de-5a0af3f1aa71_2218x1278.jpg" class="kg-image" alt="4136ceee-82b9-4cf0-b0de-5a0af3f1aa71_2218x1278" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/4136ceee-82b9-4cf0-b0de-5a0af3f1aa71_2218x1278.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/4136ceee-82b9-4cf0-b0de-5a0af3f1aa71_2218x1278.jpg 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/4136ceee-82b9-4cf0-b0de-5a0af3f1aa71_2218x1278.jpg 1456w" sizes="(min-width: 720px) 720px" width="1456" height="839" loading="lazy"><figcaption>Restaurantes não atômicos correm o risco de clientes darem o golpe da "saidinha"</figcaption></figure><h3 id="transa-es-at-micas">Transações atômicas</h3><p>Se várias consultas SQL são agrupadas em uma transação, a atomicidade é uma garantia de que, se alguma das consultas falhar por qualquer motivo (problemas de <em>hardware</em>, da aplicação ou da rede), a transação será interrompida e o banco de dados retornará ao seu estado anterior, como se nada tivesse acontecido.</p><p>Sem atomicidade, se ocorrer uma falha enquanto algumas consultas estão sendo executadas, é difícil saber quais consultas foram confirmadas (ou seja, concluídas) e quais não foram. Executar as consultas novamente após uma falha pode agravar o problema, pois você corre o risco de introduzir dados incorretos no banco de dados ao executar novamente consultas que foram bem-sucedidas anteriormente.</p><p>As transações atômicas evitam essa incerteza, pois você sabe que, se a transação anterior falhou, ela falhou em sua totalidade e você pode simplesmente tentar novamente sem se preocupar em introduzir dados inconsistentes.</p><h2 id="o-que-significa-consist-ncia">O que significa consistência?</h2><p>Consistência pode significar coisas diferentes em engenharia de nuvem/software, dependendo do contexto. No caso de ACID, o "C" provavelmente foi adicionado para fazer a abreviação funcionar.</p><p>Consistência no contexto de ACID significa <em>consistência nos dados</em>, que é definida pelo criador do banco de dados. O termo técnico para consistência de dados é <strong>integridade referencial</strong>. A integridade referencial é um método para garantir que os relacionamentos entre as tabelas permaneçam consistentes. Geralmente, é aplicada por meio do uso de chaves estrangeiras.</p><p>Para entender a integridade referencial, considere o seguinte.</p><p>Imagine um sistema de biblioteca com dois tipos de cartões: um cartão de livro e um cartão de usuário.</p><ul><li>O cartão de livro lista todos os livros disponíveis na biblioteca.</li><li>O cartão de usuário rastreia quais livros estão emprestados para quais membros.</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/82ea7c95-f55f-4cb6-86ea-47c11399b5c7_2324x1316.jpg" class="kg-image" alt="82ea7c95-f55f-4cb6-86ea-47c11399b5c7_2324x1316" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/82ea7c95-f55f-4cb6-86ea-47c11399b5c7_2324x1316.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/82ea7c95-f55f-4cb6-86ea-47c11399b5c7_2324x1316.jpg 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/82ea7c95-f55f-4cb6-86ea-47c11399b5c7_2324x1316.jpg 1456w" sizes="(min-width: 720px) 720px" width="1456" height="824" loading="lazy"><figcaption>Um cartão de livro e um cartão de usuário para uma biblioteca</figcaption></figure><p>A regra da biblioteca é que um livro só pode ser listado no cartão de um usuário se ele existir no cartão de livro. Isso é integridade referencial. Se alguém tentar listar um livro no cartão de um usuário que não está no cartão de livro (ou seja, um livro que não existe na biblioteca), o sistema não permitirá.</p><p>Embora a atomicidade, o isolamento e a durabilidade sejam propriedades intrínsecas ao próprio banco de dados, a consistência dos dados, ou integridade referencial, não é uma propriedade intrínseca ao banco de dados.</p><p>A consistência é definida pelo criador do banco de dados. A aplicação que chama o banco de dados depende das propriedades de atomicidade e isolamento do banco de dados para manter essa consistência.</p><h2 id="o-que-significa-isolamento">O que significa isolamento?</h2><p>Isolamento é uma garantia de que transações executadas simultaneamente não devam interferir umas nas outras. Concorrência aqui se refere a duas ou mais transações tentando modificar ou ler os mesmos registros do banco de dados ao mesmo tempo.</p><p>Existem três níveis de isolamento de transação. Vou apenas explicar os dois principais abaixo, organizados do menos rígido para o mais rígido.</p><h3 id="leitura-confirmada-read-committed-">Leitura confirmada (<em>read committed</em>)</h3><p>Isso oferece duas garantias. Impede leituras sujas e gravações sujas.</p><p><strong>Sem leituras sujas (<em>no dirty reads</em>)</strong>: ler dados de outra transação que ainda não foi confirmada é chamado de "leitura suja". Com o nível de isolamento de leitura confirmada, você verá apenas os dados que foram confirmados por outra transação.</p><p><strong>Sem gravações sujas (<em>no dirty writes</em>)</strong>: sobrescrever dados que já foram gravados por outra transação, mas que ainda não foram confirmados, é chamado de "gravação suja".</p><p>Para entender como funciona o isolamento de leitura confirmada, considere o seguinte exemplo.</p><p>Imagine um restaurante de fast-food com apenas um último hambúrguer especial disponível e dois clientes famintos, Marie e Marko, tentando comprá-lo simultaneamente.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ec0fd185-63c9-4821-bcac-b0140f2f4183_2360x1322.jpg" class="kg-image" alt="ec0fd185-63c9-4821-bcac-b0140f2f4183_2360x1322" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/07/ec0fd185-63c9-4821-bcac-b0140f2f4183_2360x1322.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2024/07/ec0fd185-63c9-4821-bcac-b0140f2f4183_2360x1322.jpg 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2024/07/ec0fd185-63c9-4821-bcac-b0140f2f4183_2360x1322.jpg 1456w" sizes="(min-width: 720px) 720px" width="1456" height="816" loading="lazy"><figcaption>Dois clientes pedindo um hambúrguer ao mesmo tempo</figcaption></figure><ol><li>Marie verifica a disponibilidade de hambúrgueres e vê o último disponível. Sem que ela saiba, o pedido de Marko está sendo processado, mas ainda não foi finalizado no sistema, pois ele não pagou. Como seu pedido ainda não foi finalizado, Marie não sabe que seu pedido está em conflito com o dela. Isso é semelhante a uma transação lendo os dados confirmados mais recentemente, onde ela não vê as alterações não confirmadas (como o pedido pendente de Marko).</li><li>Marie faz um pedido com base nessas informações incompletas, pensando que um hambúrguer está disponível.</li><li>Assim que Marko paga, o sistema é atualizado para mostrar que não há mais hambúrgueres restantes. Isso é semelhante a uma transação sendo confirmada.</li><li>O pedido de Marie terá que ser negado, pois não há mais hambúrgueres restantes.</li></ol><p>O ponto principal aqui é a etapa nº 3. Se o pagamento de Marko falhar nesta fase, a transação não será confirmada e ainda haverá um hambúrguer disponível para Marie.</p><p>Nesse exemplo, o isolamento de leitura confirmada garante que Marie não tenha a compra do hambúrguer prematuramente negada apenas porque outra pessoa disse que o queria. Somente transações confirmadas podem ser lidas. Portanto, o hambúrguer está disponível para ser pedido, desde que ninguém o tenha pago.</p><h3 id="leitura-repetitiva-repeatable-read-">Leitura repetitiva (<em>repeatable read</em>)</h3><p>A leitura repetitiva é um nível de isolamento mais rígido, pois oferece as mesmas garantias que o isolamento de leitura confirmada – além de garantir que as leituras sejam repetitivas.</p><p>Uma leitura repetitiva garante que, se uma transação ler uma linha de dados, quaisquer leituras subsequentes dessa mesma linha de dados dentro da mesma transação produzirão o mesmo resultado, independentemente das alterações feitas por outras transações. Essa consistência é mantida durante toda a duração da transação.</p><p>Quando uma transação lê os mesmos dados duas vezes, mas vê um valor diferente em cada leitura porque uma transação confirmada atualizou o valor entre as duas leituras, isso é chamado de leitura difusa. O nível de isolamento de leitura repetitiva impede leituras difusas.</p><p>Leituras difusas não são inerentemente boas nem ruins. Tudo depende do que você está tentando alcançar.</p><p>Leituras difusas são ruins para transações de longa duração somente leitura, pois novas gravações podem ocorrer durante a transação e isso pode causar inconsistências nos dados. Exemplos de transações de longa duração somente leitura são um <em>back-up</em> de banco de dados e consultas analíticas normalmente usadas em um <em>data warehouse</em>.</p><p>Leituras repetitivas são geralmente implementadas pelo DBMS lendo de um instantâneo do banco de dados que permanece inalterado durante a transação, ignorando assim quaisquer novas gravações confirmadas nesse período.</p><h2 id="o-que-significa-durabilidade">O que significa durabilidade?</h2><p>Durabilidade é uma garantia de que as alterações feitas por uma transação confirmada não devem ser perdidas. Todas as transações confirmadas devem ser persistidas em armazenamento durável e não volátil, ou seja, em disco. Isso garante que quaisquer transações confirmadas sejam protegidas, mesmo se o banco de dados travar.</p><p>Naturalmente, a durabilidade não pode proteger contra a destruição do disco que armazena os dados. Redundância adicional pode ser adicionada, tendo <em>back-ups</em> do seu banco de dados armazenados separadamente do original.</p><h2 id="juntando-tudo">Juntando tudo</h2><p>O ACID (Atomicidade, Consistência, Isolamento e Durabilidade) fornece um conjunto de garantias ao trabalhar com um DBMS. Embora a maioria dos DBMS relacionais sejam compatíveis com ACID, a implementação dessa conformidade pode variar.</p><p>A atomicidade garante que todas ou nenhuma das partes de uma transação sejam concluídas. Falhas parciais não são permitidas.</p><p>A consistência, ou integridade referencial, garante que os dados permaneçam precisos e confiáveis, aderindo a regras predefinidas. Ao contrário das outras prioridades, a consistência não é intrínseca ao próprio DBMS. Em vez disso, a aplicação que chama o banco de dados depende das propriedades de atomicidade e isolamento do banco de dados para manter a consistência.</p><p>O isolamento é uma garantia de que transações executadas simultaneamente não devem interferir umas nas outras. Essa é, indiscutivelmente, a propriedade mais importante, porque um DBMS pode frequentemente ter diferentes níveis de isolamento padrão, que podem precisar ser alterados com base no que é necessário para a sua aplicação.</p><p>Por fim, a durabilidade é uma garantia de que as alterações feitas por uma transação confirmada não devem ser perdidas.</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
