<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: OpenDevUFCG</title>
    <description>The latest articles on Forem by OpenDevUFCG (@opendevufcg).</description>
    <link>https://forem.com/opendevufcg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F726%2F786a8f6e-b488-4e18-a2e3-4f9188f718aa.png</url>
      <title>Forem: OpenDevUFCG</title>
      <link>https://forem.com/opendevufcg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/opendevufcg"/>
    <language>en</language>
    <item>
      <title>Não tenha medo de mudar de rota</title>
      <dc:creator>Robson Junior</dc:creator>
      <pubDate>Mon, 26 Jul 2021 17:31:49 +0000</pubDate>
      <link>https://forem.com/opendevufcg/nao-tenha-medo-de-mudar-de-rota-270e</link>
      <guid>https://forem.com/opendevufcg/nao-tenha-medo-de-mudar-de-rota-270e</guid>
      <description>&lt;p&gt;Escolhas... Não importa o quanto nós treinemos durante toda a vida a ter que fazê-las, tomar decisões não parece se tornar uma tarefa mais simples com o tempo. Vamos usar a sua potencial área de atuação como exemplo. Mesmo já sabendo que você gostaria de tentar Ciência da Computação (e mesmo se não for o caso, não desista desta postagem!), esse termo abarca uma infinidade de possibilidades. Como ter certeza de que o que você escolher vai possibilitar sua satisfação por tempo suficiente até você descobrir a próxima grande coisa?&lt;/p&gt;

&lt;p&gt;Resposta rápida, ou melhor, a única resposta: é impossível garantir isso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4oh4nnnzty9jymzrxsb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4oh4nnnzty9jymzrxsb.gif" alt="Ocupando muito espaço do cérebro..." width="168" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Não se preocupe: não vou te atacar com mais perguntas difíceis, nem usar termos de coach para mudar o seu &lt;em&gt;#mindset&lt;/em&gt;. Também não tenho nenhuma solução para oferecer, infelizmente. No lugar disso tudo, quero compartilhar uma história sobre o lado bom de criar coragem para tomar decisões difíceis, mesmo quando as suas escolhas anteriores não anteviam esse futuro.&lt;/p&gt;

&lt;p&gt;Cursos de graduação geralmente culminam em um Trabalho de Conclusão de Curso, certo? Aquela última disciplina que quase ninguém quer, mas vai ter que cursar, sendo geralmente o último obstáculo entre você e o tão sonhado diploma. Nesse caso em específico, o TCC se deu em duas etapas: um Projeto de TCC, consistindo basicamente no esboço e planejamento do trabalho, e o TCC propriamente dito, cada um em um semestre.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fimxxsrhuirc6g04v36bg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fimxxsrhuirc6g04v36bg.gif" alt="Muito trabalho..." width="298" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O primeiro passo foi, naturalmente, escolher qual professor(a) eu abordaria quanto à orientação, o que felizmente não foi uma decisão muito difícil. Embora eu tenha estudado com vários professores e professoras sensacionais, levei em consideração principalmente com quem eu ainda não tinha (até o momento) tido a chance de trabalhar, quem poderia me ajudar a encontrar mais possibilidades para o TCC e, principalmente, com quem eu realmente me sentia confortável.&lt;/p&gt;

&lt;p&gt;Em seguida, surgiu uma dúvida bem mais complicada: qual tema escolher? Eu sabia que queria fazer sobre um tema que realmente me despertasse interesse, mas, mesmo com as opções sendo teoricamente infinitas, nem todas se sustentam como uma temática de TCC. Depois de contatar a minha orientadora para definirmos isso, eu pensava que não fazia ideia do que queria trabalhar. Depois dela dar umas dez (sério mesmo) sugestões de temas super interessantes, eu... Propus o meu próprio. Pensei rapidamente que o que me traria satisfação seria construir algo com algum impacto social, e então dei uma ideia de um sistema que atuaria nesse sentido.&lt;/p&gt;

&lt;p&gt;Vieram mais dúvidas: como se daria esse trabalho? Focaríamos o TCC no desenvolvimento desse sistema, ou utilizaríamos os aprendizados obtidos ao longo do curso para viabilizar uma pesquisa? Como encaixar isso no contexto de Computação? Como encontrar os contatos das pessoas que poderiam nos ajudar a ceder as informações necessárias?&lt;/p&gt;

&lt;p&gt;Depois de uma série de ameaças à validade do tema e inseguranças quanto ao que poderíamos fazer, conseguimos chegar em uma proposta sólida ao fim de Projeto de TCC. Caramba, já tínhamos bastante coisa: uma introdução que poderia muito bem ser aproveitada, um cronograma otimista, referências a artigos multidisciplinares que poderiam nos guiar…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4lynoon7o4ijxyaz0yek.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4lynoon7o4ijxyaz0yek.gif" alt="Planejamento do TCC." width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mesmo assim, quando começamos TCC, comecei a enxergar mais furos naquilo tudo. Como íamos conseguir contatar todas aquelas pessoas? Como íamos abraçar o mundo com aquele projeto, estando no meio de uma pandemia que cada vez mais minava a minha vontade de interagir com outros virtualmente? Ainda assim, planejamos uma redução de escopo, fizemos mais pesquisas e estava tudo bem, talvez.&lt;/p&gt;

&lt;p&gt;Mas não estava. Eu já sabia que, apesar de já ter sido apaixonado por aquele tema, nenhum caminho que eu via naquele momento me levaria a um resultado satisfatório. E isso, a cada reunião, estava me deixando cada vez mais ansioso e incerto. Aquela sensação de saber o que precisa ser feito agora, mas perder todo o ânimo de continuar só por imaginar que no fim das contas não vai haver tempo o suficiente para fazer o melhor possível.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Facr0661hf2lbjubi2fjw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Facr0661hf2lbjubi2fjw.gif" alt="Trabalhando no TCC." width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Junto a isso, havia uma impotência ainda maior na insatisfação com aquele tema. Afinal, que direito eu tinha de não querer trabalhá-lo? Eu me agarrei com unhas e dentes a uma ideia que eu mesmo havia sugerido, fiz com que a lapidássemos de diversas formas e tinha uma proposta que, de diversos ângulos, parecia factível. Desistir de algo que você insistiu não é nada fácil. Mas eu não estava nada feliz.&lt;/p&gt;

&lt;p&gt;Foi nesse momento que uma ideia antiga, que eu não havia sugerido anteriormente por não ter domínio do tema, voltou à minha mente. Ao comentá-lo com alguns amigos que estavam acompanhando o andamento do meu trabalho, eles perceberam que essa nova proposta realmente me deixava empolgado e me incentivaram a sugeri-la. Com um novo ânimo, criei coragem e conversei com a minha orientadora: "não quero decepcioná-la, mas podemos mudar de tema?"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhjdekee369vd9pqrh0b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhjdekee369vd9pqrh0b.gif" alt="Implorando..." width="498" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E mais uma vez, provavelmente por eu ter muito privilégio de estar rodeado de gente incrivelmente acolhedora, eu não fui contrariado. Estávamos lá, com menos de três meses para desenvolver todo o TCC, com uma nova proposta em uma área totalmente diferente, com um propósito totalmente diferente. A diferença era: agora eu sentia que era o tema certo.&lt;/p&gt;

&lt;p&gt;Escrevi uma nova proposta, comecei a fazer os experimentos, digitei incansavelmente aquele trabalho e, o melhor de tudo, eu me vi apaixonado mais uma vez por um projeto. Depois de muitas linhas de código, muitas horas ouvindo "Te Amo Lá Fora" da DUDA BEAT, muitas revisões e muito apoio, consegui terminar o trabalho de que mais me orgulho até hoje. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/B6vfi_i2RnA"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;em&gt;Eu‌ ‌esqueci‌ ‌dessa‌ ‌lição‌ ‌de‌ ‌me‌ ‌tratar‌ ‌com‌ ‌mais‌ ‌amor‌ ‌&lt;br&gt;
Restou‌ ‌um‌ ‌pouco‌ ‌de‌ ‌esperança,‌ ‌dеcidi‌ ‌que‌ ‌é‌ ‌pra‌ ‌lá‌ ‌que‌ ‌eu‌ ‌vou&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Espero que essa história ~de superação~ seja um incentivo para você acreditar que não deve ter medo de mudar de rota. É claro: seja racional, considere bem todas as suas opções. Se, no fim das contas, você sente que há algo que poderia te levar por um caminho em que você se sinta uma pessoa mais realizada, não tema.&lt;/p&gt;

&lt;p&gt;Como diria Lady Gaga em sua fala icônica, pode haver 100 pessoas em uma sala e 99 não acreditam em você, mas basta que uma acredite. E essa primeira pessoa, por mais clichê que seja dizer isso, &lt;strong&gt;precisa&lt;/strong&gt; ser você. Espero que, como eu tive e tenho, você tenha a chance de estar rodeado por uma comunidade de pessoas que te levam para frente, mas acreditar em si é o primeiro e mais importante passo!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqmgsako7777k3x5ynaq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqmgsako7777k3x5ynaq.gif" alt="Pode haver 100 pessoas em uma sala e 99 não acreditam, mas você só precisa de 1 para acreditar." width="550" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obrigado pela leitura! Meu nome é Robson e normalmente você pode me encontrar no &lt;a href="https://twitter.com/JRosboJr" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, no &lt;a href="https://instagram.com/jrobsonjr" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; ou no &lt;a href="https://www.linkedin.com/in/jrobsonjr/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>motivation</category>
    </item>
    <item>
      <title>Script para abrir webcam com Python utilizando OpenCV</title>
      <dc:creator>Maria Eduarda de Azevedo Silva</dc:creator>
      <pubDate>Mon, 19 Jul 2021 17:07:49 +0000</pubDate>
      <link>https://forem.com/opendevufcg/script-para-abrir-webcam-com-python-utilizando-opencv-f26</link>
      <guid>https://forem.com/opendevufcg/script-para-abrir-webcam-com-python-utilizando-opencv-f26</guid>
      <description>&lt;p&gt;Já pensou em desenvolver algum projetinho que precisa de uma captura de imagem em tempo real, mas não sabe por onde começar? Nesse post vamos trazer uma solução simples de como fazer um script utilizando &lt;strong&gt;Python3&lt;/strong&gt; e &lt;strong&gt;OpenCV&lt;/strong&gt; para abrir a sua webcam!&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F5ee541edd1960466e4f30bd90a3d0590%2Ftenor.gif%3Fitemid%3D3780800" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F5ee541edd1960466e4f30bd90a3d0590%2Ftenor.gif%3Fitemid%3D3780800"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Um pouco sobre a biblioteca OpenCV
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://opencv.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenCV&lt;/strong&gt;&lt;/a&gt; é uma biblioteca de código aberto desenvolvida pela Intel nos anos 2000, inicialmente nas linguagens C e C++, com o objetivo de melhorar o aparato disponível para o desenvolvimento de aplicações, assim como nos estudos e pesquisas na área de &lt;a href="https://pt.wikipedia.org/wiki/Vis%C3%A3o_computacional" rel="noopener noreferrer"&gt;&lt;strong&gt;Visão Computacional&lt;/strong&gt;&lt;/a&gt;. Hoje em dia ela ainda é referência e se tornou multiplataforma e multilinguagem, isto é, podemos utilizá-la em aplicações nos mais diversos sistemas operacionais e linguagens de programação.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenCV + Python == "PERFEIÇÃO"
&lt;/h2&gt;

&lt;p&gt;O OpenCV não foi apenas desenvolvido para melhorar a experiência em questão de otimização das técnicas e dos algoritmos de processamento de imagem, mas também para fácil utilização da biblioteca pelos interessados. &lt;br&gt;
Quando unimos isso ao Python temos um ambiente perfeito para explorar a criatividade utilizando imagens: biblioteca simples e linguagem de sintaxe simples!&lt;br&gt;
Quer provas? Continua lendo este post!&lt;/p&gt;
&lt;h2&gt;
  
  
  Instalando o OpenCV na sua máquina
&lt;/h2&gt;

&lt;p&gt;Para iniciar, precisaremos instalar o OpenCV na nossa máquina. Para isso, você pode instalar o pacote via pip com o comando abaixo:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

pip install opencv-python


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

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

pip3 install opencv-python


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

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Lembrando que é sempre bom considerar a criação de um &lt;strong&gt;ambiente virtual&lt;/strong&gt; para seus projetos! Assim, caso você queira compartilhar e receber contribuições, irá ajudar bastante na configuração local do projeto na máquina do contribuidor, além de evitar que alguns erros se tornem incapazes de serem resolvidos. Caso não saiba como fazê-lo, consulte este &lt;a href="https://docs.python.org/pt-br/3/library/venv.html" rel="noopener noreferrer"&gt;link&lt;/a&gt; da documentação do Python para saber mais. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Mão na massa!
&lt;/h2&gt;

&lt;p&gt;Com o OpenCV instalado na máquina podemos partir para o código! Crie um arquivo .py, abra o editor de sua preferência e vamos começar!&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F3ccc0e15cbf9bee22c30701649065643%2Ftenor.gif%3Fitemid%3D3393582" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F3ccc0e15cbf9bee22c30701649065643%2Ftenor.gif%3Fitemid%3D3393582"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Antes de tudo, vamos importar a nossa biblioteca:&lt;/p&gt;

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

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Com o pacote devidamente importado, poderemos partir para a captura da imagem pela webcam do seu computador!&lt;/p&gt;

&lt;h3&gt;
  
  
  Abrindo a webcam com código!
&lt;/h3&gt;

&lt;p&gt;Abrir a webcam com um script Python é mais fácil do que você imagina! Vamos utilizar OpenCV para capturar imagens em tempo real.&lt;/p&gt;

&lt;h4&gt;
  
  
  Passo 1:
&lt;/h4&gt;

&lt;p&gt;O primeiro passo é instanciar um objeto &lt;a href="https://docs.opencv.org/master/dd/d43/tutorial_py_video_display.html" rel="noopener noreferrer"&gt;&lt;strong&gt;VideoCapture&lt;/strong&gt;&lt;/a&gt;. Essa classe do OpenCV é responsável por realizar a captura de frames em um vídeo, o qual passamos o caminho como parâmetro na criação do objeto. No caso da leitura da webcam, precisamos passar o seu ID de referência (se você usa um laptop, o ID da sua câmera primária é 0):&lt;/p&gt;

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

&lt;span class="n"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VideoCapture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  Passo 2:
&lt;/h4&gt;

&lt;p&gt;Para iniciar o segundo passo, é importante que você entenda &lt;strong&gt;o que é um vídeo&lt;/strong&gt;. De uma forma bem genérica, &lt;strong&gt;um vídeo é uma sucessão de imagens que imprimem uma sensação de movimento&lt;/strong&gt;. A cada uma dessas imagens damos o nome de &lt;strong&gt;quadros (ou frames)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Fazendo o paralelo disso com lógica de programação, &lt;strong&gt;qual a estrututa que utilizamos para fazer uma repetição sucessiva de alguma coisa?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F7ffd2774603c1aac0d09704ec29d1255%2Ftenor.gif%3Fitemid%3D11731609" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F7ffd2774603c1aac0d09704ec29d1255%2Ftenor.gif%3Fitemid%3D11731609"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Se você respondeu &lt;strong&gt;laço&lt;/strong&gt;, está mais que correto! Mas, qual laço escolher, &lt;strong&gt;for&lt;/strong&gt; ou &lt;strong&gt;while&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2Fd727553135e15b67eaee12ad00b4e213%2Ftenor.gif%3Fitemid%3D7528656" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2Fd727553135e15b67eaee12ad00b4e213%2Ftenor.gif%3Fitemid%3D7528656"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Vamos pensar: estamos fazendo uma captura de vídeo em &lt;strong&gt;tempo real&lt;/strong&gt; com a nossa webcam, então &lt;strong&gt;não sabemos quando a captura irá parar&lt;/strong&gt;, desse modo &lt;strong&gt;enquanto estiver rodando nosso script eu capturo um frame novo&lt;/strong&gt;. Matamos a charada e vamos de &lt;strong&gt;loop while&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Passando essa ideia para Python, temos algo do tipo:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;rodando&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;rodando&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Captura um frame
&lt;/span&gt;    &lt;span class="k"&gt;pass&lt;/span&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  Passo 3:
&lt;/h4&gt;

&lt;p&gt;Agora podemos partir para todo o código dentro do loop!&lt;/p&gt;

&lt;p&gt;Para fazer a captura do frame da vez, usaremos o método &lt;strong&gt;read()&lt;/strong&gt; no nosso objeto &lt;strong&gt;VideoCapture&lt;/strong&gt;. Esse método retorna uma tupla com dois valores: um booleano referente ao &lt;strong&gt;status de captura&lt;/strong&gt; e o próprio &lt;strong&gt;frame no formato de um array NumPy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O valor do &lt;strong&gt;status&lt;/strong&gt; é muito útil para quando estamos &lt;strong&gt;lendo um vídeo passado por um caminho&lt;/strong&gt;, visto que, quando chegamos no último frame do mesmo, o próximo não poderá ser capturado, o retorno desse valor será False e poderemos parar a execução do loop sem o lançamento de uma exceção. Além disso, pode haver algum problema na captura da webcam e isso ser indicado por esse retorno, por isso, vamos utilizá-lo. &lt;/p&gt;

&lt;p&gt;Já o &lt;strong&gt;frame&lt;/strong&gt; é essencial, já que é o que mais nos interessa! A &lt;strong&gt;imagem retornada&lt;/strong&gt; será o alvo dos &lt;strong&gt;processamentos&lt;/strong&gt; feitos durante a iteração do loop e também será jogada na saída.&lt;/p&gt;

&lt;p&gt;Faremos isso da seguinte forma, dissociando os valores retornados em duas variáveis:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="c1"&gt;#...
&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;rodando&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  Passo 4:
&lt;/h4&gt;

&lt;p&gt;Chegou o momento de falarmos das &lt;strong&gt;condições de parada&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F4e765a33c88071c8c321f3ce5e12ff8d%2Ftenor.gif%3Fitemid%3D14191522" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F4e765a33c88071c8c321f3ce5e12ff8d%2Ftenor.gif%3Fitemid%3D14191522"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Queremos parar a captura em &lt;strong&gt;dois casos&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Em casos de erro &lt;/li&gt;
&lt;li&gt;Caso eu apenas queira parar de executar o script&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vamos unir essas duas condições de parada em apenas uma condição:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="c1"&gt;#...
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;rodando&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F86f3b65249fbaca12e142281558c06ac%2Ftenor.gif%3Fitemid%3D4486363" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F86f3b65249fbaca12e142281558c06ac%2Ftenor.gif%3Fitemid%3D4486363"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Parece estranho, mas não é difícil de entender. O que estamos querendo dizer é basicamente "&lt;strong&gt;se deu algo errado na captura da imagem ou o usuário apertou a tecla 'q', então pare o script!&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;A função &lt;a href="https://docs.opencv.org/master/d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7" rel="noopener noreferrer"&gt;&lt;strong&gt;cv.waitKey(1)&lt;/strong&gt;&lt;/a&gt; espera que um evento de tecla acionada aconteça e, caso ocorra, ela retorna o valor da tecla pressionada segundo o padrão UTF-8. Para comparar se a tecla pressionada foi a 'q', combinamos o retorno dessa função com a constante hexadecimal &lt;strong&gt;0xff&lt;/strong&gt; e utilizamos a função padrão de python &lt;strong&gt;ord('q')&lt;/strong&gt;, que retorna o valor de uma string passada como parâmetro em UTF-8.&lt;/p&gt;

&lt;p&gt;Caso &lt;strong&gt;ao menos uma dessas condições seja satisfeita&lt;/strong&gt;, a nossa variável &lt;strong&gt;rodando&lt;/strong&gt; passa a receber &lt;strong&gt;False&lt;/strong&gt; e na próxima iteração há a &lt;strong&gt;parada do loop&lt;/strong&gt;. &lt;/p&gt;

&lt;h4&gt;
  
  
  Passo 5:
&lt;/h4&gt;

&lt;p&gt;Nesse estágio já temos o objeto que captura nossa imagem da webcam, a imagem capturada devidamente lida e também uma condição de parada do nosso loop. Só nos resta uma coisa: &lt;strong&gt;jogar essa imagem na saída&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2Fimages%2F55bf09e811c9fb48f27afcdb5dfe295b%2Ftenor.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2Fimages%2F55bf09e811c9fb48f27afcdb5dfe295b%2Ftenor.gif"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Para isso utilizaremos a função &lt;strong&gt;cv.imshow()&lt;/strong&gt; do OpenCV. Essa função cria recebe dois parâmetros: uma string referente ao &lt;strong&gt;nome da janela&lt;/strong&gt; e o array que se refere a &lt;strong&gt;imagem&lt;/strong&gt; que queremos mostrar. Temos tudo que precisamos!&lt;/p&gt;

&lt;p&gt;Para finalmente enxergarmos a captura em tempo real, escrevemos a seguinte linha dentro do loop:&lt;/p&gt;

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

&lt;span class="c1"&gt;#...
&lt;/span&gt;    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Camera&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Finalmente, o script!
&lt;/h2&gt;

&lt;p&gt;Tudo isso resulta em um script de &lt;strong&gt;apenas 8 linhas&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2Fimages%2F774f034a3348256ebc3032b8c166d15f%2Ftenor.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2Fimages%2F774f034a3348256ebc3032b8c166d15f%2Ftenor.gif"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt; 

&lt;span class="n"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VideoCapture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;rodando&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;rodando&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;rodando&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="n"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Camera&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Com isso temos tudo que você precisa para capturar imagens em tempo real utilizando um &lt;strong&gt;script simples em Python junto com OpenCV&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;E o que fazer com esse script?&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2Fb200fc13a785faf7d8589748b1794b27%2Ftenor.gif%3Fitemid%3D13895777" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2Fb200fc13a785faf7d8589748b1794b27%2Ftenor.gif%3Fitemid%3D13895777"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Existem várias possibilidades de aproveitar essa base, que vão desde &lt;strong&gt;detectores&lt;/strong&gt; até registros de imagens para alguma &lt;strong&gt;aplicação ou sistema feito em Python&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Muito obrigada por ter lido até o fim! Se esse post te inspirou a criar alguma coisa, não se esquece de postar nas tuas redes e me marcar, que eu quero ver ~e quem sabe eu volte aqui com mais coisas legais para fazer com OpenCV~!&lt;/p&gt;

&lt;p&gt;Minhas redes:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/MariaEduardaDeAzevedo/" rel="noopener noreferrer"&gt;LinkedIn: Maria Eduarda de Azevedo Silva&lt;/a&gt;&lt;br&gt;
&lt;a href="https://twitter.com/ddt_azevedo" rel="noopener noreferrer"&gt;Twitter: @ddt_azevedo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/MariaEduardaDeAzevedo" rel="noopener noreferrer"&gt;GitHub: MariaEduardaDeAzevedo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>opencv</category>
      <category>python</category>
      <category>visaocomputacional</category>
    </item>
    <item>
      <title>Não corra. Pode doer.</title>
      <dc:creator>Júlio Guedes</dc:creator>
      <pubDate>Mon, 12 Jul 2021 17:02:58 +0000</pubDate>
      <link>https://forem.com/opendevufcg/nao-corra-pode-doer-1165</link>
      <guid>https://forem.com/opendevufcg/nao-corra-pode-doer-1165</guid>
      <description>&lt;p&gt;Nós temos um grande potencial dentro de cada um de nós, e muitas vezes escolhemos o curso superior tentando atingir o máximo que somos capazes, e também provar que somos. Experimentamos novas áreas, aprendemos coisas novas, nos dispomos como voluntários, pesquisamos, desenvolvemos e analisamos coisas.&lt;/p&gt;

&lt;p&gt;É engraçado perceber que tudo isso acontece naquele minúsculo espaço, entre nós e o computador. Nós lemos, tentamos, assistimos aulas, perguntamos e, acima de tudo, nos esforçamos. Até conseguirmos. Quantas vezes não repetimos esse ciclo num único dia?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2FSTroE7bTBLTzxQUrZc%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2FSTroE7bTBLTzxQUrZc%2Fgiphy.gif" alt="Gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Durante a jornada da graduação, enfrentamos problemas, e começamos a buscar liberdades e alívios. Problemas financeiros, com a família, com amigos, de saúde, entre tantos outros. Alguns veem no estudo e no trabalho uma fuga, já que essa realidade não é confrontada no ambiente profissional ou universitário. Urge a necessidade de se formar, como primeiro passo pra libertação. &lt;/p&gt;

&lt;p&gt;Mas para se formar bem, é preciso experiência, afinal, que empresa legal e que pode pagar um salário bacana iria contratar um recém-formado com currículo em branco? Ainda nos primeiros períodos do curso, surge a necessidade de preencher o currículo com monitorias, pesquisas, projetos e estágios. Mesmo que, a princípio, sejam voluntários. Tudo isso sem baixar as notas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.incubadoraliberato.com.br%2Fwp-content%2Fuploads%2F2017%2F05%2Fwriting-in-notebook.jpg%3Fssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fwww.incubadoraliberato.com.br%2Fwp-content%2Fuploads%2F2017%2F05%2Fwriting-in-notebook.jpg%3Fssl%3D1" alt="Estudando"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A cada dia que passa, enxergamos o quanto é difícil. Aos poucos se vai abdicando pequenas coisas: assistir um filme com a família, fazer as refeições no mesmo horário, encontrar com os amigos, conversar com eles sobre coisas além da universidade. Seus hobbies se transformam em estudos, já que você ainda não conseguiu o tão sonhado estágio que vai garantir algumas portas abertas depois. A cada mês ou semestre, novas coisas começam a deixadas de lado: dormir bem, praticar exercícios ou esportes, a relação com seus amigos, e até um relacionamento.&lt;/p&gt;

&lt;p&gt;É claro que nessa jornada você conseguiu muita coisa, afinal, nenhum esforço grande assim passa despercebido pelo mundo, principalmente quando você quer ser notado. Você consegue oportunidades em estágios, projetos ou pesquisas, e é exemplar em cada um deles. Então, começa a se questionar porquê não é notado por aqueles que você queria. E aposta mais coisas nessa busca.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn2.hubspot.net%2Fhubfs%2F419889%2Fblue%2520light%2520computer%2520night%2520negative%2520effects.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn2.hubspot.net%2Fhubfs%2F419889%2Fblue%2520light%2520computer%2520night%2520negative%2520effects.jpg" alt="Computador de noite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Não é mais um problema trabalhar e estudar à noite, nos finais de semana e feriados. É o que precisa ser feito. A carga é grande demais pra não fazê-lo. E, diminuindo a carga, você sabe que não chegará onde quer.&lt;/p&gt;

&lt;p&gt;Cada vez é um fator a mais, um estresse a mais, que surge de uma oportunidade boa demais pra negar. E aceitamos a vida assim. Por um ou dois anos, vai valer a pena esse sacrifício. É um investimento no futuro.&lt;/p&gt;

&lt;p&gt;As decepções começam a aparecer, suas expectativas de ser notado continuam não se cumprindo a cada dia, e essa carga de trabalho tão pesada se transforma no seu dia. Você acorda e dorme para cumprir o que acha que os outros esperam de você, adiando a esperança de que vai dar certo. Cada vez mais você acumula rejeições nos estágios dos sonhos. Não desiste de lutar. E meses se passam.&lt;/p&gt;

&lt;p&gt;Até que você quebra.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phocuswire.com%2FuploadedImages%2FArticles%2FOpinion%2F2019%2FSeptember%2Fbroken-marketing-funnel.jpg%3Forigwidth%3D800%26origheight%3D400%26origmode%3Dcrop%26Anchor%3DMiddleCenter%26width%3D640%26height%3D480%26scale%3Dboth%26mode%3Dcrop" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phocuswire.com%2FuploadedImages%2FArticles%2FOpinion%2F2019%2FSeptember%2Fbroken-marketing-funnel.jpg%3Forigwidth%3D800%26origheight%3D400%26origmode%3Dcrop%26Anchor%3DMiddleCenter%26width%3D640%26height%3D480%26scale%3Dboth%26mode%3Dcrop" alt="Quebrado"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você está cansado. Olha para o lado e seus amigos, que antes se divertiam tanto juntos, não estão diariamente ao seu lado. Não estão ao seu lado há algum tempo, e você sequer tinha notado. Você não está satisfeito com seu corpo, sua aparência. Pensa em fazer outra coisa pra desestressar, mas o que fazer? Você deixou seus hobbies pra trás há muito tempo.&lt;/p&gt;

&lt;p&gt;Estar no computador começa a causar dor, e aos poucos você começa a abdicar de algumas das obrigações. Mesmo sem ter alcançado nada do que imaginava ser possível. Sair de um projeto, não se inscrever em mais uma monitoria. Surge o medo de se formar e estar desempregado, seu pior pesadelo.&lt;/p&gt;

&lt;p&gt;Mas existe a possibilidade de continuar na universidade, numa pós graduação, e extender esse tempo de se decidir. Com suas notas e seus esforços, deve ser possível. Mas foi pra isso que você lutou tanto? Pra continuar no mesmo lugar que você está? Sabendo que uma vez ouviu que "a pós-graduação é onde ficam aqueles que não conseguem um emprego"?&lt;/p&gt;

&lt;p&gt;Você sabe que isso não é verdade. Mas você correu demais. Esqueceu de aproveitar a graduação. Viver o dia a dia de um projeto, de uma monitoria. Divertir-se com seus amigos, ao invés de tentar agarrar o mundo com seus braços. Esqueceu de cursar uma disciplina e conversar com o professor após a aula, sobre como aquele conteúdo se aplica num problema, mesmo que você não fosse fazê-lo. Sua curiosidade e seu interesse sumiram, pois não havia mais tempo para novas coisas. &lt;/p&gt;

&lt;p&gt;Aos poucos, você foi murchando. E, só agora, percebeu que estava murcho.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flive.staticflickr.com%2F4683%2F39355517851_0353a16705_b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flive.staticflickr.com%2F4683%2F39355517851_0353a16705_b.jpg" alt="Flor murcha"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Não é possível voltar no tempo e reparar tudo, você sabe muito bem. Mas sempre é possível reconsiderar o que está fazendo agora, ponderar melhor e entender suas prioridades. Saúde, tempo, amigos, rir, sorrir, brincar. Assistir um filme ruim só pra dizer que é ruim mesmo, e então rir com seus amigos por vocês terem escolhido passar por isso. Se reaproximar daqueles que importam, das coisas que te faziam sorrir.&lt;/p&gt;

&lt;p&gt;A relação com o seu trabalho e seus estudos precisa ser saudável pra dar certo, afinal, você escolheu tudo isso por gostar. Mas sua vida não se resume a um emprego, um título, um trabalho. Escolher esse caminho pode te isolar. Pode doer.&lt;/p&gt;

&lt;p&gt;Pare, pense, reflita.&lt;br&gt;
Sempre.&lt;br&gt;
Para só então saber como continuar.&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>motivation</category>
      <category>career</category>
    </item>
    <item>
      <title>Descomplicando a protoboard</title>
      <dc:creator>Ricardo Adley da Silva Sena</dc:creator>
      <pubDate>Mon, 05 Jul 2021 16:57:56 +0000</pubDate>
      <link>https://forem.com/opendevufcg/descomplicando-a-protoboard-31oo</link>
      <guid>https://forem.com/opendevufcg/descomplicando-a-protoboard-31oo</guid>
      <description>&lt;p&gt;Um bom cientista da computação não vive só de código, então que tal dominar o mundo dos componentes eletrônicos também? Nessa postagem eu vou te ajudar a entender como funciona a &lt;strong&gt;protoboard&lt;/strong&gt; e como montar o seu primeiro circuito &lt;del&gt;simples&lt;/del&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Afinal o que é uma protoboard?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.pinimg.com%2Foriginals%2Fd2%2F68%2Fee%2Fd268eee34bdf25ae0a1df31041393e26.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.pinimg.com%2Foriginals%2Fd2%2F68%2Fee%2Fd268eee34bdf25ae0a1df31041393e26.gif" alt="essa gente inventa cada coisa"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A protoboard nada mais é do que uma placa de ensaio, cheia de furos para conexões elétricas e de componentes, onde é possível testar os seus protótipos ou projetos em estado inicial.&lt;/p&gt;

&lt;h2&gt;
  
  
  O básico do básico
&lt;/h2&gt;

&lt;p&gt;Vamos entender agora como funciona cada pedacinho da protoboard, essa linda que vocês podem ver na imagem abaixo.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo5rllzlb01jkl00p2pm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo5rllzlb01jkl00p2pm.jpg" alt="protoboard pequeno"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na imagem podemos ver duas seções em destaque: alimentação e área para conexão dos &lt;del&gt;todo o resto&lt;/del&gt; componentes. Essas seções funcionam da seguinte forma:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alimentação: Dividida entre positivo e negativo, ao conectar o fio em um dos pontos toda a linha &lt;strong&gt;horizontalmente&lt;/strong&gt; vai possuir a mesma carga. Você pode notar o símbolo de - ou + e a pintura referente a linha que será ativada.&lt;/li&gt;
&lt;li&gt;Área para conexão dos componentes: Aqui você está mais livre nas conexões &lt;del&gt;mas nem tanto&lt;/del&gt;, ao conectar o fio em um dos pontos toda a linha &lt;strong&gt;verticalmente&lt;/strong&gt; vai funcionar como a mesma conexão &lt;strong&gt;então tenha cuidado para não conectar componentes no mesmo lugar&lt;/strong&gt; afinal ninguém quer &lt;del&gt;queimar&lt;/del&gt; ter problemas com nada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.uncyc.org%2Fpt%2Fthumb%2F4%2F47%2FBombaatomica.gif%2F230px-Bombaatomica.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.uncyc.org%2Fpt%2Fthumb%2F4%2F47%2FBombaatomica.gif%2F230px-Bombaatomica.gif" alt="3..2..1..BOOOOM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nos exemplos deste artigo estou utilizando a protoboard pequena, mas não se preocupe, ela funciona da mesma forma em todos os tamanhos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acendendo um LED!
&lt;/h2&gt;

&lt;p&gt;Chega de pipipipopopo e vamos direto a prática pois nada melhor do que aprender fazendo!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fimages.uncyc.org%2Fpt%2F9%2F9b%2FIdeia.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fimages.uncyc.org%2Fpt%2F9%2F9b%2FIdeia.gif" alt="pensando"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um dos melhores lugares para montar seus circuitos de testes usando uma protoboard é sem dúvidas o &lt;a href="https://www.tinkercad.com/dashboard?type=circuits&amp;amp;collection=designs" rel="noopener noreferrer"&gt;Tinkercad&lt;/a&gt; (é grátis), com ele você pode praticar sem medo de &lt;del&gt;queimar componentes&lt;/del&gt; erros. Para facilitar a sua vida, abaixo você pode encontrar um exemplo de como seu circuito deve ficar, lembre-se de quando usar um &lt;a href="https://www.mundodaeletrica.com.br/o-que-e-um-led/" rel="noopener noreferrer"&gt;LED&lt;/a&gt; também usar um &lt;a href="https://www.mundodaeletrica.com.br/o-que-e-um-resistor/" rel="noopener noreferrer"&gt;resistor&lt;/a&gt; para o bixinho não explodir.&lt;/p&gt;

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

&lt;p&gt;Se você olhou para esse circuito e não entendeu nada, tenha calma, abaixo eu &lt;del&gt;tento&lt;/del&gt; explico o que está acontecendo.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F8552e2d285149629e2862dbeeb6fd8cd%2Ftenor.gif%3Fitemid%3D14756520" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F8552e2d285149629e2862dbeeb6fd8cd%2Ftenor.gif%3Fitemid%3D14756520" alt="picapau biruta"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como você pode ver na imagem, cada linha (que possui conexão) da protoboard assume um valor! Como expliquei na seção &lt;em&gt;o básico do básico&lt;/em&gt;. Com isso, é possível montar o "caminho" da corrente até o LED e montar o circuito com sucesso!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzk71p8fq4nsmv74zp6tr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzk71p8fq4nsmv74zp6tr.jpg" alt="Explicação circuito com LED"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com essa pequena introdução espero que você já consiga começar a se aventurar com a protoboard, pratique o circuito mostrado aqui, e outros também, usando o &lt;a href="https://www.tinkercad.com/dashboard?type=circuits&amp;amp;collection=designs" rel="noopener noreferrer"&gt;Tinkercad&lt;/a&gt;. &lt;/p&gt;




&lt;p&gt;Obrigado por ter lido até aqui! Não se esqueça de dar uma olhada nos outros artigos de contribuidores da &lt;a href="//dev.to/opendevufcg"&gt;OpenDevUFCG no dev.to&lt;/a&gt;. Espero te ver mais vezes!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F6d4ebb1873a044d18987507fc09184ef%2Ftenor.gif%3Fitemid%3D14291762" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2F6d4ebb1873a044d18987507fc09184ef%2Ftenor.gif%3Fitemid%3D14291762" alt="Obrigado amigo você é um amigo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você pode me encontrar falando &lt;del&gt;ou reclamando&lt;/del&gt; de outros assuntos nas minhas redes: &lt;br&gt;
&lt;a href="https://twitter.com/ricardoadley" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/ricardoadley/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt; e &lt;a href="https://github.com/ricardoadley" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>eletronica</category>
      <category>ptbr</category>
      <category>protoboard</category>
    </item>
    <item>
      <title>Um olhar sobre a Computação</title>
      <dc:creator>Íris Almeida</dc:creator>
      <pubDate>Mon, 28 Jun 2021 17:00:06 +0000</pubDate>
      <link>https://forem.com/opendevufcg/um-olhar-sobre-a-computacao-2mel</link>
      <guid>https://forem.com/opendevufcg/um-olhar-sobre-a-computacao-2mel</guid>
      <description>&lt;p&gt;Olá, assim como você, estou iniciando na área de tecnologia.&lt;/p&gt;

&lt;p&gt;Antecipo que tenho mais perguntas do que respostas, e, na minha perspectiva, essa é exatamente a beleza da nossa área. Estamos em formação para nos tornarmos Cientistas da Computação, certo?&lt;/p&gt;

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

&lt;p&gt;Creio que a primeira coisa que associamos ao pensar em Computação é um computador. Todavia, &lt;em&gt;nossa área não se resume a uma máquina&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;”Ciência da Computação tem tanto a ver com o computador como a Astronomia com o telescópio, a Biologia com o microscópio, ou a Química com os tubos de ensaio. A Ciência não estuda ferramentas, mas o que fazemos e o que descobrimos com elas.”&lt;br&gt;
– Edsger Dijkstra&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Na realidade, &lt;em&gt;o Computador é apenas um instrumento para o estudo de processos de informação(naturais e artificiais)&lt;/em&gt;. Ou seja, é por meio dessa ferramenta que nós, Cientistas da Computação, iremos atuar.&lt;/p&gt;




&lt;p&gt;Sob essa perspectiva, o que de fato nós aprendemos ao longo da graduação que nos destaca?&lt;/p&gt;

&lt;p&gt;A priori, é lícito referenciar o conceito "Pensamento Computacional", em que a Cientista da Computação &lt;a href="https://datascience.columbia.edu/people/jeannette-m-wing/" rel="noopener noreferrer"&gt;Jeannette Wing&lt;/a&gt; disserta acerca de técnicas da Ciência da Computação que podem ser aplicadas para a resolução de problemas (em diversas áreas do conhecimento). &lt;/p&gt;

&lt;p&gt;Assim, ao longo do curso, aprendemos e desenvolvemos cada vez mais a capacidade de pensar estrategicamente, ou seja, interpretar problemas de maneira adequada, e, a partir disso, descobrir soluções algorítmicas viáveis.&lt;/p&gt;

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




&lt;p&gt;Há inúmeras habilidades que são desenvolvidas por meio do  Pensamento Computacional. Confira 4 delas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Decomposição&lt;/strong&gt;: Capacidade de dividir um problema em partes menores, com o fito de facilitar na elaboração da solução;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Abstração&lt;/strong&gt;: Capacidade de planejar, identificando quais fatores tem maior relevância;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reconhecimento de padrões&lt;/strong&gt;: Capacidade de perceber itens em comum nos processos, baseados em eventos anteriores;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Algoritmos&lt;/strong&gt;: Capacidade de elaborar passos lógicos finitos (como um conjunto de "regras" que serão seguidas para elucidar um problema);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E ai, quais fatores contribuíram para desenvolver as habilidades acima? &lt;/p&gt;




&lt;p&gt;Ps:Recomendo essas três leituras, caso queira compreender mais acerca desse tema:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.931.7480&amp;amp;rep=rep1&amp;amp;type=pdf" rel="noopener noreferrer"&gt;Is Computer Science Science?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.americanscientist.org/article/the-great-principles-of-computing" rel="noopener noreferrer"&gt;The Great Principles of Computing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://periodicos.utfpr.edu.br/rbect/article/view/4711" rel="noopener noreferrer"&gt;Computational thinking (Jeannette Wing)&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Muito obrigada pela leitura!&lt;/p&gt;

&lt;p&gt;Sou Íris Almeida, e, se quiser entrar em contato comigo, você pode me adicionar no &lt;a href="https://www.linkedin.com/in/%C3%ADrisalmeida" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; ou enviar uma mensagem no Discord(Siri#1217).&lt;/p&gt;

&lt;p&gt;Convido todes a seguirem o &lt;a href="https://www.linkedin.com/company/mulheres-de-voz-na-tecnologia" rel="noopener noreferrer"&gt;Mulheres de Voz na Tecnologia&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mulheres de Voz na Tecnologia é um movimento que tem por missão promover maior visibilidade para inúmeras mulheres (cis ou trans) na área de Exatas, de forma que, cada vez mais, as pessoas associem Tecnologia também ao rosto de uma mulher.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Acompanhe a OpenDevUFCG no &lt;a href="https://github.com/OpenDevUFCG/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://twitter.com/OpenDevUFCG/" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; e no &lt;a href="https://www.instagram.com/OpenDevUFCG/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>Estamos de volta!</title>
      <dc:creator>Iele Passos</dc:creator>
      <pubDate>Mon, 21 Jun 2021 17:00:02 +0000</pubDate>
      <link>https://forem.com/opendevufcg/estamos-de-volta-2ndk</link>
      <guid>https://forem.com/opendevufcg/estamos-de-volta-2ndk</guid>
      <description>&lt;p&gt;
&lt;a href="https://i.giphy.com/media/3oEjI99ZdyZRE9Dw5O/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3oEjI99ZdyZRE9Dw5O/giphy.gif"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;É isso mesmo! Sentiram a nossa falta?&lt;/p&gt;

&lt;p&gt;Não há nada melhor do que poder tirar um tempo para descansar e refletir a respeito do rumo que queremos tomar, né?&lt;br&gt;
Como resultado dessa nossa "hibernação", definimos que teremos postagens constantes (1x por semana) com os mais variados temas feitas por membros e convidados da nossa comunidade.&lt;/p&gt;
&lt;h1&gt;
  
  
  Durante esse tempo que o blog esteve parado, nós não estávamos:
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  - Criamos o Andromedev!!🚀🚀🚀
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsvgshare.com%2Fi%2FQTp.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsvgshare.com%2Fi%2FQTp.svg"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Pensando em fortalecer a comunidade nesse período de pandemia, criamos o primeiro evento de mentoria organizado pela OpenDevUFCG  com o intuito de incentivar a participação de estudantes em projetos open source!&lt;/p&gt;

&lt;p&gt;O evento ocorreu em um período de nove semanas, onde estudantes colaboraram com projetos open source através de um sistema de mentoria. Cada projeto teve uma pessoa responsável, que tinha a missão de orientar a pessoa aprendiz durante o evento, ajudando a realizar as contribuições open source.&lt;/p&gt;

&lt;p&gt;Na inscrição, foram disponibilizados diversos projetos que conseguimos através de parcerias com laboratórios da universidade, organizações e empresas que estejam dispostas a ensinar alunos. Dentre elas, contamos com empresas de renome internacional, como a &lt;a href="https://www.redhat.com/pt-br" rel="noopener noreferrer"&gt;RedHat&lt;/a&gt; e a &lt;a href="https://vtex.com/br-pt/" rel="noopener noreferrer"&gt;VTEX&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ao fim do evento, foi realizada uma apresentação dos resultados dos projetos participantes do evento, que está disponível em nosso &lt;a href="https://www.youtube.com/c/OpenDevUFCG/videos" rel="noopener noreferrer"&gt;canal do YouTube&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Ao todo, na edição de 2020, foram &lt;strong&gt;49&lt;/strong&gt; projetos, &lt;strong&gt;145&lt;/strong&gt; inscritos para aprendiz e &lt;strong&gt;22&lt;/strong&gt; organizações!&lt;/p&gt;

&lt;p&gt;Amasse? &lt;a href="https://andromedev.opendevufcg.org/" rel="noopener noreferrer"&gt;https://andromedev.opendevufcg.org/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  - Teve Hacktoberfest online!
&lt;/h3&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fopendevufcg.org%2Fhacktoberfest%2Fassets%2Fimg%2Flogo.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fopendevufcg.org%2Fhacktoberfest%2Fassets%2Fimg%2Flogo.svg"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;O Hacktoberfest é um evento realizado ao longo de todo o mês de outubro, engajando estudantes e desenvolvedores em atividades e iniciativas voltadas ao open source ao redor do mundo todo.&lt;/p&gt;

&lt;p&gt;Com toda a situação causada pelo COVID-19, tivemos que repensar totalmente a estrutura do evento para conseguirmos engajar e passar conhecimentos sobre programação e cultura open source ao mesmo tempo que respeitamos às recomendações de isolamento social.&lt;/p&gt;

&lt;p&gt;Assim, fizemos o Hacktoberfest Home Edition!!&lt;br&gt;
O evento durou o MÊS INTEIRO!! É isso mesmo que você leu, foram 4 semanas abordando vários temas distintos através de Palestras e Workshops com vários convidados e membros da OpenDevUFCG. Falamos de conceitos iniciais, open source, análise de dados, frontend, design e muito mais, e o melhor, TUDO DE GRAÇA!&lt;/p&gt;

&lt;p&gt;Na edição online de 2020, tivemos o &lt;strong&gt;mês inteiro&lt;/strong&gt; de programação, &lt;strong&gt;10&lt;/strong&gt; palestras/minicursos, &lt;strong&gt;mais de 2.000&lt;/strong&gt; visualizações, &lt;strong&gt;mais de 900&lt;/strong&gt; minutos de conteúdo e parceria com a &lt;a href="https://vtex.com/br-pt/" rel="noopener noreferrer"&gt;VTEX&lt;/a&gt; e a &lt;a href="https://www.behance.net/ovnidesign" rel="noopener noreferrer"&gt;Ovni Design&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Quer saber mais? &lt;a href="https://opendevufcg.org/hacktoberfest/#about" rel="noopener noreferrer"&gt;https://opendevufcg.org/hacktoberfest/#about&lt;/a&gt;  &lt;/p&gt;
&lt;h3&gt;
  
  
  - Nossa comunidade cresceu!!
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;No nosso discord, temos mais de &lt;strong&gt;370&lt;/strong&gt; membros, onde &lt;strong&gt;mais 14&lt;/strong&gt; pessoas entraram no CoreTeam;&lt;/li&gt;
&lt;li&gt;No nosso &lt;a href="https://www.instagram.com/opendevufcg/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, temos mais de &lt;strong&gt;600&lt;/strong&gt; seguidores;&lt;/li&gt;
&lt;li&gt;E em nosso &lt;a href="https://twitter.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; temos mais de &lt;strong&gt;300&lt;/strong&gt; seguidores!!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  - Agora temos um perfil na Open Collective!!
&lt;/h3&gt;

&lt;p&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fopensource.org%2Ffiles%2Fopencollective.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fopensource.org%2Ffiles%2Fopencollective.png"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://opencollective.com/" rel="noopener noreferrer"&gt;Open Collective&lt;/a&gt; é uma ferramenta open source que permite que você gerencie suas finanças para que todos possam ver de onde vem o dinheiro e aonde ele vai. &lt;/p&gt;

&lt;p&gt;Ou seja, agora fica mais fácil patrocinar/apoiar/doar para a nossa comunidade e ver onde e como o dinheiro foi gasto!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://opencollective.com/opendevufcg" rel="noopener noreferrer"&gt;&lt;strong&gt;Confira nosso perfil!&lt;/strong&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  Mas o que será que vem ai??
&lt;/h2&gt;

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

&lt;p&gt;Além dos posts semanais por aqui, teremos eventos, minicursos, novos projetos...boatos que vai ser tuudo!&lt;br&gt;
E para saber quando o quê vai acontecer é facinho facinho: Nos acompanhem em nossas redes!!&lt;br&gt;
&lt;a href="https://twitter.com/opendevufcg" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.instagram.com/opendevufcg" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; e, claro, no &lt;a href="https://github.com/OpenDevUFCG" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Muito obrigada pela leitura!&lt;br&gt;
Meu nome é Iele Passos e sou contribuidora e membro do Core Team da OpenDevUFCG. Se desejar entrar em contato comigo, é só me mandar uma mensagem no Discord (iele#7381) ou no &lt;a href="https://www.linkedin.com/in/ielepassos/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; e, se quiser ver um pouco do meu trabalho, dá uma olhada no meu &lt;a href="https://github.com/ielepassos" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fiquem atentos: em breve, teremos novos artigos de contribuidores do OpenDevUFCG aqui no dev.to (inclusive meus hehehe)&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Bem-vindos e bem-vindas, feras de Computação@UFCG!</title>
      <dc:creator>Robson Junior</dc:creator>
      <pubDate>Thu, 12 Mar 2020 16:51:09 +0000</pubDate>
      <link>https://forem.com/opendevufcg/bem-vindos-e-bem-vindas-feras-de-computacao-ufcg-6c6</link>
      <guid>https://forem.com/opendevufcg/bem-vindos-e-bem-vindas-feras-de-computacao-ufcg-6c6</guid>
      <description>&lt;h2&gt;
  
  
  Oi, feras!
&lt;/h2&gt;

&lt;p&gt;Primeiramente, bem-vindos ao curso de Ciência da Computação! Esperamos que todos se sintam acolhidos com esse contato inicial da Semana do Fera. O PET organiza tudo com muito carinho e ficamos felizes em fazer parte de um pouquinho disso. ✨&lt;/p&gt;

&lt;p&gt;Tivemos a apresentação de algumas organizações estudantis do nosso curso, incluindo o OpenDevUFCG. Como prometido, vamos repassar algumas informações para quem ainda ficou meio perdido/orientações iniciais para quem não esteve presente ficar por dentro da nossa comunidade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quais são os links mais importantes?
&lt;/h3&gt;

&lt;p&gt;O link mágico que centraliza tudo é o nosso &lt;a href="https://opendevufcg.org" rel="noopener noreferrer"&gt;portal&lt;/a&gt;. Lá tem descrição da nossa visão (basicamente o motivo de nós existirmos), alguns dos nossos projetos e os integrantes do nosso core team. Outros projetos que devem ser de principal interesse para vocês nesse momento inicial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="//tamburetei.opendevufcg.org"&gt;Tamburetei&lt;/a&gt;, o nosso repositório de leites e dicas das disciplinas;&lt;/li&gt;
&lt;li&gt;
&lt;a href="//glossario.opendevufcg.org"&gt;Glossário&lt;/a&gt;, o guia para entender e se localizar melhor no curso;&lt;/li&gt;
&lt;li&gt;o &lt;a href="//dev.to/opendevufcg"&gt;blog OpenDevUFCG&lt;/a&gt;, que você deve estar lendo nesse momento. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O código fonte de todos esses projetos está hospedado no nosso &lt;a href="//github.com/OpenDevUFCG"&gt;GitHub&lt;/a&gt;:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/OpenDevUFCG" rel="noopener noreferrer"&gt;
        OpenDevUFCG
      &lt;/a&gt; / &lt;a href="https://github.com/OpenDevUFCG/opendevufcg.org" rel="noopener noreferrer"&gt;
        opendevufcg.org
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Portal da OpenDevUFCG
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;OpenDevUFCG &lt;a href="https://discord.gg/UgR5WrY" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d75071dbb402797f29b81c5833bfeac6aa622252654a618780f7ee88349bd3a6/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3535383239333537333439343131323235372e7376673f6c6f676f3d646973636f7264" alt="chat on Discord"&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Este repositório contém o código que faz o &lt;a href="https://opendevufcg.org/" rel="nofollow noopener noreferrer"&gt;portal da OpenDevUFCG&lt;/a&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Objetivo&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Objetivo do &lt;a href="https://opendevufcg.org/" rel="nofollow noopener noreferrer"&gt;opendevufcg.org&lt;/a&gt; é ser um site de apresentação para qualquer um que queria saber quem é a OpenDevUFCG, contendo informações sobre o que fazemos, nossos valores, e também uma listagem de projetos e maintainers atuais.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A filosofia desse projeto é ser simples sempre!&lt;/strong&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Como funciona&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;O site é feito utilizando apenas o essencial, &lt;strong&gt;Javascript&lt;/strong&gt;, &lt;strong&gt;HTML&lt;/strong&gt; e &lt;strong&gt;CSS&lt;/strong&gt;. Caso não conheça essas linguagens e como elas se comunicam, &lt;a href="http://apexensino.com.br/html-css-e-javascript-entendendo-melhor-base-da-programacao-front-end/" rel="nofollow noopener noreferrer"&gt;veja aqui&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Você pode encontrar o código na pasta &lt;a href="https://github.com/OpenDevUFCG/opendevufcg.orgdocs" rel="noopener noreferrer"&gt;&lt;code&gt;docs/&lt;/code&gt;&lt;/a&gt;. Caso queira entender melhor do código, veja nosso &lt;a href="https://github.com/OpenDevUFCG/opendevufcg.org/CONTRIBUTING.md" rel="noopener noreferrer"&gt;Contributing&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Desenvolvimento&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Caso deseje fazer alterações no código, você pode rodar o site na sua máquina, basta apenas que você tenha algum browser. Recomendamos que você faça um &lt;a href="https://github.com/UNIVALI-LITE/Portugol-Studio/wiki/Fazendo-um-Fork-do-reposit%C3%B3rio" rel="noopener noreferrer"&gt;&lt;strong&gt;Fork&lt;/strong&gt;&lt;/a&gt; do repositório e o &lt;em&gt;Clone&lt;/em&gt; para sua máquina:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/&lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;seu_usuario&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt;/opendevufcg.org&lt;/pre&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Substitua &amp;lt;seu_usuario&amp;amp;gt…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/OpenDevUFCG/opendevufcg.org" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Mas eu ainda não entendi nada de open source e GitHub, o que eu faço?
&lt;/h3&gt;

&lt;p&gt;Falando mais especificamente do blog, ressaltamos a publicação que faz uma introdução do zero a alguns conceitos de open source e GitHub que foi pensada especialmente para quem está chegando agora:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/opendevufcg" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F726%2F786a8f6e-b488-4e18-a2e3-4f9188f718aa.png" alt="OpenDevUFCG" width="500" height="500"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F158995%2F5b74a725-ccd2-4cfd-9297-fc02d6cbbeeb.jpeg" alt="" width="460" height="460"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/opendevufcg/contribuindo-para-projetos-open-source-com-github-3i76" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Contribuindo para projetos open source com GitHub&lt;/h2&gt;
      &lt;h3&gt;Lucas de Medeiros for OpenDevUFCG ・ Aug 3 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#community&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#github&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ptbr&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;E é claro, estamos disponíveis para esclarecer eventuais dúvidas. ;)&lt;/p&gt;

&lt;h3&gt;
  
  
  E o que eu tenho a ganhar contribuindo com open source?
&lt;/h3&gt;

&lt;p&gt;Fanny, integrante do nosso Core Team, conta um pouco de como o open source e o OpenDevUFCG contribuíram para que ela chegasse até uma vaga de estágio no Facebook. Tem que respeitar, viu?&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Como entro em contato com o OpenDevUFCG?
&lt;/h3&gt;

&lt;p&gt;O principal meio de comunicação com a comunidade OpenDevUFCG é o nosso &lt;a href="https://discordapp.com/invite/vFFGGEE" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;. Também é possível ficar por dentro das nossas atividades através das redes sociais: &lt;a href="//instagram.com/OpenDevUFCG"&gt;Instagram&lt;/a&gt; e &lt;a href="//twitter.com/OpenDevUFCG"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyy4tfbjork2asuuuy8l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyy4tfbjork2asuuuy8l.gif" alt="Cachorro digitando" width="480" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No mais, lembrem-se que estamos aqui para ajudá-los. Não fiquem com vergonha de falar conosco caso tenham dúvidas de como começar e como contribuir. Desejamos a todos um ótimo período! &amp;lt;3&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Retrospectiva OpenDevUFCG 2019 com visualizações analógicas</title>
      <dc:creator>Ivyna Santino</dc:creator>
      <pubDate>Tue, 31 Dec 2019 12:54:28 +0000</pubDate>
      <link>https://forem.com/opendevufcg/retrospectiva-opendevufcg-2019-com-visualizacoes-analogicas-46dl</link>
      <guid>https://forem.com/opendevufcg/retrospectiva-opendevufcg-2019-com-visualizacoes-analogicas-46dl</guid>
      <description>&lt;p&gt;Olá! Chegou o final do ano, para muitos é tempo de férias, de se reunir com a família e de relembrar momentos do ano que está chegando ao fim. A &lt;a href="https://opendevufcg.org"&gt;OpenDevUFCG&lt;/a&gt; também não ia deixar passar em branco isso, então, que tal recapitular alguns acontecimentos de 2019 através de visualizações analógicas?&lt;/p&gt;

&lt;h3&gt;
  
  
  Antes de mostrar as visus, um questionamento: o que são visualizações analógicas?
&lt;/h3&gt;

&lt;p&gt;São desenhos ou ilustrações, feitas à mão mesmo, sobre algum dado. A referência dessas visus é o trabalho &lt;a href="http://www.dear-data.com/theproject"&gt;Dear Data&lt;/a&gt; das designers Giorgia Lupi e Stefanie Posavec originado em 2015, quando decidiram criar visualizações sobre dados do dia a dia e enviá-las através de cartões postais como forma de comunicar uma à outra o que estava acontecendo em suas rotinas. Por exemplo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6hYtIEXx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e6soc2j62svs4xmzx8id.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6hYtIEXx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e6soc2j62svs4xmzx8id.jpeg" alt="Exemplo 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TzXxv9ME--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fvh56hxw83setj9828ip.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TzXxv9ME--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fvh56hxw83setj9828ip.jpg" alt="Exemplo 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As imagens acima foram tiradas do livro &lt;em&gt;Dear Data&lt;/em&gt; e, ao final do post, indicarei algumas referências do trabalho delas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Então, sabendo um pouco sobre visus analógicas, bora ver como os dados da OpenDevUFCG se comportaram ao longo do ano de 2019?
&lt;/h3&gt;

&lt;p&gt;Em 2019, a OpenDevUFCG completou um ano e, como resultado, tivemos o crescimento da equipe e do número de projetos, como podemos observar na imagem a seguir.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integrantes do &lt;em&gt;Core&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KEhFHttO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i7gekvfk1uh8u1a1qmda.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KEhFHttO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i7gekvfk1uh8u1a1qmda.jpeg" alt="Integrantes"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Tendo em vista que o time &lt;em&gt;Core&lt;/em&gt; cresceu, também tivemos mais ideias de projetos surgindo. É o que você vai ver na próxima imagem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dados dos nossos &lt;a href="https://github.com/OpenDevUFCG/"&gt;projetos&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8sTcZa7R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s69p68sabq47onmwc4ji.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8sTcZa7R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s69p68sabq47onmwc4ji.jpeg" alt="Projetos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É de grande satisfação ver o crescimento de nossos projetos e que nosso espírito de comunidade está impactando muitas pessoas, e como resultado, ver que nossa ideia está influenciando as pessoas a querer saber mais e participar de projetos &lt;em&gt;open source&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Então, movidos por isso, pensamos em organizar o &lt;strong&gt;Hacktoberfest OpenDevUFCG&lt;/strong&gt;, um evento para reunir boas ideias e pessoas legais para ajudar a comunidade através de atividades como palestras, minicursos, HackTime e abertura para sugestões. Agradecemos muito pelo apoio de todos, doadores e patrocinadores que compraram a ideia e deram apoio para o evento acontecer! Mas, deixando um pouco as palavras de lado, que tal ver os dados disso tudo?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5L5MkJtf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/irk9d9e5jedlamja2a21.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5L5MkJtf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/irk9d9e5jedlamja2a21.jpeg" alt="Hacktoberfest"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bem, tentei destacar os principais pontos da nossa organização esse ano. E, como prometido, links com mais detalhes sobre o projeto Dear Data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.dear-data.com/theproject"&gt;O projeto&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ted.com/talks/giorgia_lupi_how_we_can_find_ourselves_in_data"&gt;Vídeo TED&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.dear-data.com/thebook"&gt;Livro&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/@giorgialupi"&gt;Medium @Giorgia Lupi&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Então, gente, é isto, de novo gostaria de agradecer a cada um que acredita em nossos projetos e na nossa comunidade! Foi um ano muito legal para nossa organização, de bastante crescimento e de aprendizado, e sempre saibam, estamos dispostos para ajudar. Obrigada pela leitura, até ano que vem!&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>data</category>
      <category>design</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Projetos open source que apoiamos no Hacktoberfest 2019</title>
      <dc:creator>Robson Junior</dc:creator>
      <pubDate>Sat, 05 Oct 2019 23:46:06 +0000</pubDate>
      <link>https://forem.com/opendevufcg/projetos-open-source-que-apoiamos-no-hacktoberfest-2019-34be</link>
      <guid>https://forem.com/opendevufcg/projetos-open-source-que-apoiamos-no-hacktoberfest-2019-34be</guid>
      <description>&lt;p&gt;Já estamos no quinto dia do &lt;strong&gt;Hacktoberfest 2019&lt;/strong&gt; e amando ver tanta gente engajada com a causa! &lt;a href="https://twitter.com/OpenDevUFCG/status/1178114564132618240" rel="noopener noreferrer"&gt;Pedimos aos alunos de Computação@UFCG&lt;/a&gt; que compartilhassem conosco seus projetos open source e agora nós os compartilhamos com todo mundo. Confira alguns dos repositórios criados e mantidos por alunos do nosso curso!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Guardians-DSC" rel="noopener noreferrer"&gt;
        Guardians-DSC
      &lt;/a&gt; / &lt;a href="https://github.com/Guardians-DSC/horarios-ufcg" rel="noopener noreferrer"&gt;
        horarios-ufcg
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Visualização dos horários das disciplinas do curso de Ciência da Computação da UFCG
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Frontend, design&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; JavaScript, HTML, CSS, Vue&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Guardians-DSC" rel="noopener noreferrer"&gt;
        Guardians-DSC
      &lt;/a&gt; / &lt;a href="https://github.com/Guardians-DSC/horarios-ufcg-api" rel="noopener noreferrer"&gt;
        horarios-ufcg-api
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Api dos horários das disciplinas do curso de Ciência da Computação da UFCG
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Backend&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; JavaScript, Node.js, Docker&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Guardians-DSC" rel="noopener noreferrer"&gt;
        Guardians-DSC
      &lt;/a&gt; / &lt;a href="https://github.com/Guardians-DSC/iarl-vue" rel="noopener noreferrer"&gt;
        iarl-vue
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Aplicação da Interface de Acesso Remoto aos Laboratórios em VueJS
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Frontend, design&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; JavaScript, Vue, Docker&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/dadosjusbr" rel="noopener noreferrer"&gt;
        dadosjusbr
      &lt;/a&gt; / &lt;a href="https://github.com/dadosjusbr/api" rel="noopener noreferrer"&gt;
        api
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Site que publica as informações libertadas pelo DadosJusBR
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Data science, recuperação da informação, frontend&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; Go, HTML&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/joseims" rel="noopener noreferrer"&gt;
        joseims
      &lt;/a&gt; / &lt;a href="https://github.com/joseims/doqueru-kun" rel="noopener noreferrer"&gt;
        doqueru-kun
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🐌
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Sistemas operacionais&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; Perl, Shell, Python&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/richecr" rel="noopener noreferrer"&gt;
        richecr
      &lt;/a&gt; / &lt;a href="https://github.com/richecr/CamaraDosDeputados" rel="noopener noreferrer"&gt;
        CamaraDosDeputados
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Aplicativo web da câmara dos deputados usando ReactJS.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Frontend, design&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; JavaScript, HTML, CSS, React&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/richecr" rel="noopener noreferrer"&gt;
        richecr
      &lt;/a&gt; / &lt;a href="https://github.com/richecr/PyGraph" rel="noopener noreferrer"&gt;
        PyGraph
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Biblioteca com intuito de implementar os tipos de grafos e os algoritmos de Teoria dos Grafos.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Backend, educação, biblioteca&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; Python&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/richecr" rel="noopener noreferrer"&gt;
        richecr
      &lt;/a&gt; / &lt;a href="https://github.com/richecr/PyTwitterSDK" rel="noopener noreferrer"&gt;
        PyTwitterSDK
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A Python SDK for the API Twitter.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Backend&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; Python&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/felipemarinho97" rel="noopener noreferrer"&gt;
        felipemarinho97
      &lt;/a&gt; / &lt;a href="https://github.com/felipemarinho97/pipeline-previewer" rel="noopener noreferrer"&gt;
        pipeline-previewer
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Application that allows you to view and manage multiple deploys on a single static server through a graphical interface.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Frontend, backend, dev tools&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; JavaScript, HTML, CSS, Vue, Node.js&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/dados-congresso" rel="noopener noreferrer"&gt;
        dados-congresso
      &lt;/a&gt; / &lt;a href="https://github.com/dados-congresso/raspador-discursos-camara" rel="noopener noreferrer"&gt;
        raspador-discursos-camara
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      scripts para baixar discursos dos deputados em sessões políticas
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Data science, scraping&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; Python&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/0xHericles" rel="noopener noreferrer"&gt;
        0xHericles
      &lt;/a&gt; / &lt;a href="https://github.com/0xHericles/cast-sh" rel="noopener noreferrer"&gt;
        cast-sh
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      📟 An instance of your terminal in your browser
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Frontend, backend&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; Python, HTML, JavaScript, Docker&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Benardi" rel="noopener noreferrer"&gt;
        Benardi
      &lt;/a&gt; / &lt;a href="https://github.com/Benardi/touvlo" rel="noopener noreferrer"&gt;
        touvlo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🤖 ML algorithms implemented  from scratch and provided block by block 
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Machine learning, data science&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; Python&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/calluswhatyouwant" rel="noopener noreferrer"&gt;
        calluswhatyouwant
      &lt;/a&gt; / &lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk" rel="noopener noreferrer"&gt;
        spotify-web-sdk
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A JS SDK for the Spotify Web API.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Backend, biblioteca&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; TypeScript, mocha, chai, nock&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/calluswhatyouwant" rel="noopener noreferrer"&gt;
        calluswhatyouwant
      &lt;/a&gt; / &lt;a href="https://github.com/calluswhatyouwant/musicritic" rel="noopener noreferrer"&gt;
        musicritic
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Your personal music-specific Metacritic.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Frontend, design&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; JavaScript, HTML, CSS, React&lt;/p&gt;




&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/calluswhatyouwant" rel="noopener noreferrer"&gt;
        calluswhatyouwant
      &lt;/a&gt; / &lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor" rel="noopener noreferrer"&gt;
        spotify-playlist-editor
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Sort your Spotify playlists any way you want.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tópicos:&lt;/strong&gt; Frontend, design&lt;br&gt;
&lt;strong&gt;Principais linguagens e tecnologias:&lt;/strong&gt; JavaScript, HTML, CSS, React&lt;/p&gt;
&lt;h2&gt;
  
  
  Repositórios do OpenDevUFCG
&lt;/h2&gt;

&lt;p&gt;Não vamos esquecer dos nossos próprios repositórios, né? ❤️ Temos várias issues abertas, especialmente no Tamburetei, que é super fácil de contribuir. Corre lá!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/OpenDevUFCG" rel="noopener noreferrer"&gt;
        OpenDevUFCG
      &lt;/a&gt; / &lt;a href="https://github.com/OpenDevUFCG/Tamburetei" rel="noopener noreferrer"&gt;
        Tamburetei
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Fazendo de tamburete as cadeiras de CC@UFCG.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Ainda mais repositórios
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/jtemporal"&gt;Jessica Temporal&lt;/a&gt; publicou no blog dela uma lista enorme de projetos brasileiros para contribuir nesse Hacktoberfest. Não deixe de conferir o montão de ideias que são mantidas por pessoas do nosso país!&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;div class="ltag__link__content"&gt;
    &lt;div class="missing"&gt;
      &lt;h2&gt;Article No Longer Available&lt;/h2&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Mais por vir!
&lt;/h2&gt;

&lt;p&gt;Estamos preparando bastante coisa para esse mês tão lindo para o open source. Continuem nos acompanhando nas redes sociais (&lt;a href="https://twitter.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; e &lt;a href="https://instagram.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;)!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1179961889675235329-130" src="https://platform.twitter.com/embed/Tweet.html?id=1179961889675235329"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1179961889675235329-130');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1179961889675235329&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>contributorswanted</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>Cloud e OpenStack: Uma breve introdução</title>
      <dc:creator>Marta Laís </dc:creator>
      <pubDate>Sun, 22 Sep 2019 00:53:27 +0000</pubDate>
      <link>https://forem.com/opendevufcg/cloud-e-openstack-uma-breve-introducao-49cb</link>
      <guid>https://forem.com/opendevufcg/cloud-e-openstack-uma-breve-introducao-49cb</guid>
      <description>&lt;h1&gt;
  
  
  Cloud Computing
&lt;/h1&gt;

&lt;p&gt;Computação em Nuvem, ou &lt;strong&gt;Cloud Computing&lt;/strong&gt;, é uma tecnologia desenvolvida para flexibilizar os recursos que uma aplicação/sistema tem disponível. Nesse caso, quando falamos de recursos, estamos nos referindo a memória RAM, armazenamento, CPU e afins. Através da Cloud, é possível criar uma &lt;strong&gt;infraestrutura elástica e dinâmica&lt;/strong&gt;, ou seja, o sistema pode crescer ou diminuir mais facilmente, uma vez que é possível utilizar os recursos &lt;strong&gt;sob demanda&lt;/strong&gt;. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2p1nw7s7280cb08ut0rl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2p1nw7s7280cb08ut0rl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Por que Cloud Computing é tão importante para o futuro da computação?&lt;/strong&gt; Vamos dar um exemplo prático: uma aplicação. O crescimento de uma aplicação, por exemplo, é algo &lt;strong&gt;inconstante&lt;/strong&gt;. Podemos tentar estimar, com base em dados, o quanto uma aplicação tende a crescer ou diminuir, mas, mesmo assim, é uma previsão complexa. Teremos períodos onde usaremos uma demanda de recursos maior, pois o número de usuários será maior, assim como o contrário, períodos em que esses recursos (comprados pelos desenvolvedores da aplicação, por exemplo), &lt;strong&gt;ficarão ociosos&lt;/strong&gt;. Isso não é nada bom, uma vez que queremos aproveitar todo o dinheiro aplicado na ideia. Com o uso da Cloud, o usuário &lt;strong&gt;controla seus recursos de forma dinâmica&lt;/strong&gt;, levando em consideração a demanda do momento. Isso torna o &lt;strong&gt;sistema elástico&lt;/strong&gt;, o que, consequentemente, economiza recursos e investimentos. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2dp8do1nhi21x8bhr45i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2dp8do1nhi21x8bhr45i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Existe um conceito importante dentro disso tudo, e que também é crucial para entender como essa administração de recursos funciona: &lt;strong&gt;provisão de recursos&lt;/strong&gt;. Uma das definições de provisionamento é: &lt;em&gt;“fornecer os recursos necessários para que o sistema de gestão possa funcionar adequadamente”&lt;/em&gt;. Distribuição dos recursos por demanda.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx276oqgxosc546nnvjw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fx276oqgxosc546nnvjw1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para administrar os recursos da Cloud, existem diversas tecnologias, sendo uma das mais utilizadas o &lt;a href="https://www.openstack.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Openstack&lt;/strong&gt;&lt;/a&gt;.&lt;br&gt;
OpenStack pode ser definido como um &lt;strong&gt;gerenciador para componentes de múltiplas infraestruturas virtualizadas&lt;/strong&gt;. Imagine o OpenStack como uma plataforma de componentes, uma espécie de sistema operacional para a Cloud. OpenStack utiliza recursos virtuais para executar uma combinação de ferramentas, seus componentes. Os componentes servem para criar um ambiente de cloud que atende aos cinco critérios do &lt;em&gt;National Institute of Standards and Technology&lt;/em&gt; para a Cloud: &lt;strong&gt;rede, recursos agrupados, interface de usuário, provisionamento de funcionalidades e alocação/controle automático de recursos.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Openstack: Conceitos
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn58izzmom8bp808rmeyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn58izzmom8bp808rmeyq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora que você já tem uma ideia do que é Cloud Computing, da sua importância para a computação e foi introduzido ao OpenStack e seus componentes, existem alguns conceitos que são importantes entender ao lidar com esse tipo de sistema:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instância&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A instância nada mais é do que uma máquina virtual, já com sua imagem, grupos de seguranças e outras configurações, administrada pelo OpenStack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Imagens&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A imagem de uma instância é o sistema operacional utilizado pela mesma. Assim como temos o famoso formato .iso para imagens que usamos normalmente, o formato padrão mais utilizado para Cloud no OpenStack é o qcow2. Imagens com esse formato podem ser encontradas tanto nos sites da maioria das distribuições, quanto no próprio site do OpenStack.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A função de Network do OpenStack é bastante completa. Como o próprio nome já antecipa, essa área é focada nas conexões de redes, permitindo a criação de redes virtuais para as instâncias. Essas redes podem ser tanto públicas, quanto privadas. Ainda na parte de Network, é possível criar roteadores virtuais para conexão de redes entre si, o que possibilita a criação de redes públicas, isto é, conectadas à internet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grupos de Segurança&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Os grupos de segurança podem ser definidos como um conjunto de regras de firewall aplicadas a uma instância. Essas regras são definidas pelos usuários de acordo com as necessidades da instância. Caso o usuário não crie um grupo de segurança, o OpenStack define um grupo default que, por padrão, bloqueia tudo. Essa estratégia de bloquear tudo e, através dos grupos de segurança, ir liberando aos poucos o acesso, é de extrema importância para a segurança da instância e o controle de acesso total da mesma.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Volumes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Os volumes são discos virtuais que persistem os dados da instância. Imagine o volume como um HD instalado na sua máquina. É lá onde os dados ficam, mesmo que a instância seja reiniciada. Caso sua instância não seja inicializada com um volume, os dados não ficarão salvos.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Essa parte diz respeito ao controle de acesso ao seu OpenStack. Na interface do Horizon, é possível criar projetos, usuários, definir senhas e, assim, controlar o acesso e poderes de usuários. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Par de Chaves&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Por padrão, para acesso via SSH na sua instância, normalmente é necessário cadastrar uma senha pública gerada pelo usuário no OpenStack. Depois de cadastrada, basta aplicá-la ao criar uma instância. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flavors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Os flavors são um conjunto de configurações pré-determinadas que definem características da instância, como a memória e a capacidade de armazenamento. Podem ser entendidos também como “configurações de hardware” disponíveis para um servidor. Vários flavors podem ser criados e aplicados para diferentes instâncias. &lt;/p&gt;




&lt;h1&gt;
  
  
  OpenStack: Componentes
&lt;/h1&gt;

&lt;p&gt;Uma vez que o OpenStack atua como um gerenciador de componentes, é importante entender um pouco da atuação de cada um deles: cada um com sua responsabilidade na gerência da infraestrutura da Cloud. Como existem muitos, não precisamos nos apegar aos detalhes cada componente, então, vamos dar uma visão geral sobre os utilizados com maior frequência:&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenStack Compute (Nova)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkxnbyrceret9m5km22zg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkxnbyrceret9m5km22zg.png" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Responsável pela estrutura de virtualização. É uma ferramenta de acesso e gerenciamento total para os recursos computacionais do OpenStack, incluindo programações, criações e exclusões. &lt;/p&gt;

&lt;p&gt;É agnóstico ao hypervisor (camada de software entre o hardware e o sistema operacional), tendo compatibilidade com a maioria deles.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenStack Block Storage Cinder (Cinder)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcju49zb8kk1sbhe7nyqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcju49zb8kk1sbhe7nyqt.png" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Responsável pelo serviço de storage do OpenStack Nova. &lt;br&gt;
Com o Cinder é possível gerenciar volumes através da interface do Horizon ou via CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenStack Object Storage (Swift)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd8o495zf1kvbaztwd4kl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd8o495zf1kvbaztwd4kl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É um serviço altamente tolerante a falhas que armazena e recupera objetos de dados não estruturados. Enquanto o Cinder é responsável pelo volume, o Swift é responsável pelos objetos. &lt;/p&gt;

&lt;h2&gt;
  
  
  OpenStack Image Service (Glance)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ft8r73kudrehh7fdwswlu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ft8r73kudrehh7fdwswlu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Responsável pelos recursos de imagens de máquinas virtuais. Ele armazena e recupera imagens de disco de máquinas virtuais de uma variedade de locais.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenStack Networking (Neutron)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6fynnrvuni20iy2dc32y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6fynnrvuni20iy2dc32y.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Responsável pelos recursos do serviço de rede para o OpenStack.  Conecta redes a outros serviços do OpenStack.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenStack Identity (KeyStone)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkxnbyrceret9m5km22zg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkxnbyrceret9m5km22zg.png" alt="Alt Text"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Responsável pela autenticação e autorização, definindo regras para acesso aos recursos do OpenStack. Ele também é o catálogo de endpoints para todos os serviços.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenStack Dashboard (Horizon)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9rkdqe3hu46uw345v7a1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9rkdqe3hu46uw345v7a1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Provê uma interface web para acesso aos serviços do OpenStack.&lt;/p&gt;

&lt;p&gt;Dependendo da necessidade do serviço de Cloud, o administrador da infraestrutura pode inserir outros componentes, a exemplo do OpenStack Monasca, que tem como função ser um sistema de monitoramento para as máquinas (para saber mais, acesse a página de &lt;a href="https://www.openstack.org/openstack-components/" rel="noopener noreferrer"&gt;componentes&lt;/a&gt; do OpenStack).&lt;/p&gt;




&lt;h2&gt;
  
  
  OpenStack: Primeiros Passos
&lt;/h2&gt;

&lt;p&gt;É possível dar seus primeiros passos com OpenStack sem precisar ter uma infraestrutura de Cloud com diversos computadores, para isso existe uma solução: o &lt;a href="https://docs.openstack.org/openstack-ansible/latest/user/aio/quickstart.html" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenStack AIO&lt;/strong&gt;&lt;/a&gt; (All-In-One). &lt;/p&gt;

&lt;p&gt;Nele, é possível criar imagens, subir instâncias, definir grupos de segurança, integrar chaves públicas e outras funções, assim como no OpenStack; a diferença é que tudo funciona em uma máquina só, podendo ser utilizada uma máquina virtual, por exemplo. Por isso é considerado um laboratório para OpenStack. No site do OpenStack tem uma área dedicada para essa solução, com todo o passo a passo para sua instalação e configuração. &lt;/p&gt;

&lt;p&gt;É importante dizer também que o OpenStack AIO é integrado ao &lt;a href="https://pt.wikiversity.org/wiki/Ansible" rel="noopener noreferrer"&gt;&lt;strong&gt;Ansible&lt;/strong&gt;&lt;/a&gt;, uma ferramenta de automatização criada para gerenciar múltiplas máquinas de uma vez. A parte mais importante para se entender agora sobre Ansible são os seus Playbooks. Os Playbooks são um conjunto de Plays (instruções) através das quais o Ansible consegue configurar o passo a passo de um processo de configuração — uma estrutura bem parecida com um shell script. São basicamente instruções de fácil leitura de como serão feitas as configurações que possibilitam a realização de atividades em máquinas remotas ou diferentes hosts.&lt;/p&gt;

&lt;p&gt;Para administração e gerência do OpenStack, temos duas opções: a interface web já citada anteriormente, Horizon, ou o &lt;a href="https://docs.openstack.org/cli/command-list.html" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenStack-CLI&lt;/strong&gt;&lt;/a&gt; (Client Line Interface). Na dashboard do Horizon existem diversas abas relacionadas aos conceitos já abordados neste material.  &lt;/p&gt;

&lt;p&gt;Para finalizar, quando pensamos no futuro da computação, é impossível não pensar em Cloud. Um dos fatores mais limitantes para nossa área são os recursos, por isso precisamos aproveitá-los da maneira mais inteligente e consciente. Ferramentas como OpenStack, em conjunto com toda a comunidade open source que move o projeto, nos dão uma visão que, no futuro, os limites serão apenas termos usados em cálculo. &lt;/p&gt;




&lt;p&gt;Muito obrigada pela leitura! Fique atento: em breve, teremos novos artigos de contribuidores do OpenDevUFCG aqui no &lt;strong&gt;dev.to&lt;/strong&gt;. Acompanhe o OpenDevUFCG no &lt;a href="https://twitter.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, no &lt;a href="https://instagram.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; e, claro, no &lt;a href="https://github.com/OpenDevUFCG" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>openstack</category>
      <category>distributedsystems</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>Usando o spotify-web-sdk para gerenciar requisições à API Web do Spotify</title>
      <dc:creator>Robson Junior</dc:creator>
      <pubDate>Sun, 15 Sep 2019 00:45:18 +0000</pubDate>
      <link>https://forem.com/opendevufcg/usando-o-spotify-web-sdk-para-gerenciar-requisicoes-a-api-web-do-spotify-3j3i</link>
      <guid>https://forem.com/opendevufcg/usando-o-spotify-web-sdk-para-gerenciar-requisicoes-a-api-web-do-spotify-3j3i</guid>
      <description>&lt;p&gt;Eu e &lt;a href="https://dev.to/joserenan"&gt;Renan&lt;/a&gt; temos uma organização open source chamada &lt;a href="https://github.com/calluswhatyouwant" rel="noopener noreferrer"&gt;Call Us What You Want&lt;/a&gt;, na qual desenvolvemos aplicações com foco em música. Um de nossos projetos é um SDK para a API Web do Spotify, que criamos para servir de apoio para outras aplicações que fazem uso desses dados.&lt;/p&gt;

&lt;p&gt;Nessa postagem (que é tradução de &lt;a href="https://dev.to/calluswhatyouwant/using-spotify-web-sdk-to-handle-requests-to-the-spotify-web-api-2oj6"&gt;uma feita originalmente no dev.to da nossa organização&lt;/a&gt;), vou mostrar como o &lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk" rel="noopener noreferrer"&gt;spotify-web-sdk&lt;/a&gt; pode facilitar a recuperação e a gerência de dados de usuários do Spotify. Farei isso descrevendo o processo de desenvolvimento de uma aplicação inspirada por um problema &lt;em&gt;muito sério&lt;/em&gt; que eu enfrentava como usuário dessa plataforma de streaming. &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/calluswhatyouwant" rel="noopener noreferrer"&gt;
        calluswhatyouwant
      &lt;/a&gt; / &lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk" rel="noopener noreferrer"&gt;
        spotify-web-sdk
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A JS SDK for the Spotify Web API.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Spotify Web SDK&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A JavaScript SDK for the &lt;a href="https://developer.spotify.com/documentation/web-api/" rel="nofollow noopener noreferrer"&gt;Spotify Web API&lt;/a&gt;
Note that this project is still a BETA version.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Table of Contents&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#features" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#installation" rel="noopener noreferrer"&gt;Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#usage" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#community" rel="noopener noreferrer"&gt;Community&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#suggest-a-new-feature-or-report-a-bug" rel="noopener noreferrer"&gt;Suggest a new feature or report a bug&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#do-it-yourself" rel="noopener noreferrer"&gt;Do it yourself&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#maintainers" rel="noopener noreferrer"&gt;Maintainers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#hall-of-fame" rel="noopener noreferrer"&gt;Hall of Fame&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-web-sdk#license" rel="noopener noreferrer"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;"Why should I use this?"&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;We want to handle the hard work for you.
Even to make simple requests, such as to get information on a track, you'd need to make a bunch of setups.
Here is how you could do the same thing with our aid:&lt;/p&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-c1"&gt;*&lt;/span&gt; &lt;span class="pl-k"&gt;as&lt;/span&gt; &lt;span class="pl-s1"&gt;spotify&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'spotify-web-sdk'&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-s1"&gt;spotify&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;init&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-c1"&gt;token&lt;/span&gt;: &lt;span class="pl-s"&gt;'YOUR SPOTIFY TOKEN HERE!'&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt; &lt;span class="pl-c"&gt;// You should only need to run this once.&lt;/span&gt;
&lt;span class="pl-s1"&gt;spotify&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;getTrack&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'3LOpHuEpjkL4T1Zcjhko8w'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt; &lt;span class="pl-c"&gt;// Or any other track id.&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Yes, it's as simple as that!&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;"I still think it's no hard work at all.&lt;/h3&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/calluswhatyouwant/spotify-web-sdk" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  Um problema do mundo real (&lt;em&gt;A little motivation&lt;/em&gt;)
&lt;/h1&gt;

&lt;p&gt;A seção de álbuns da minha biblioteca do Spotify é bem desorganizada, mas não exatamente por culpa minha — na implementação do aplicativo, sempre que um single é adicionado às músicas, o mesmo também acaba aparecendo como álbum. Isso acaba sendo um problema na hora de localizar algo para ouvir, já que eu prefiro consumir álbuns do início ao fim no lugar de entrar no modo aleatório das playlists.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsb4asmtt5d5ztpo5hoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsb4asmtt5d5ztpo5hoo.png" alt="Screenshot de álbuns no Spotify" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;Comfort Crowd&lt;/b&gt; and &lt;b&gt;People&lt;/b&gt; são singles, mas também aparecem na minha biblioteca como álbuns.



&lt;p&gt;Pensei em uma solução simples: criei uma &lt;a href="https://open.spotify.com/user/jrobsonjr/playlist/7lWSJamQptWauCMIEDXgYC?si=HZZTKAY8RWObSGEdYm-4uA" rel="noopener noreferrer"&gt;playlist&lt;/a&gt; contendo a primeira faixa de cada álbum que eu já ouvi. Ter essa playlist é muito útil para que eu também mantenha o registro do dia em que ouvi os trabalhos inteiros pela primeira vez (pelo menos quando eu lembro de adicioná-los assim que termino de escutá-los). Problema resolvido... ao menos parcialmente. Bem, para manter as coisas ainda mais organizadas, eu ainda queria poder ordenar as referências aos álbuns pelas suas datas de lançamento, algo que o Spotify ainda não dá suporte (mesmo com usuários pedindo por essa feature &lt;a href="https://community.spotify.com/t5/Live-Ideas/Your-Music-Sort-Music-in-quot-Your-Music-quot-by-Year/idi-p/744893" rel="noopener noreferrer"&gt;há mais de cinco anos&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Procurei por ferramentas que pudessem gerenciar esse método de ordenação para mim e descobri uma aplicação web chamada &lt;a href="http://sortyourmusic.playlistmachinery.com/" rel="noopener noreferrer"&gt;Sort Your Music&lt;/a&gt;. Apesar de ser super simples e eficiente de usar, a abordagem de ordenação deles sobrescreve a data de adição das faixas. Sei que por agora você já deve estar revirando os olhos com a minha insatisfação, mas, sabendo que é possível conseguir o resultado que eu desejo, decidi implementar a minha própria ferramenta. Nada como um pequeno "faça você mesmo", certo?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35plebrwy8zvouqiiu5m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35plebrwy8zvouqiiu5m.gif" alt="Taylor Swift com ódio" width="500" height="281"&gt;&lt;/a&gt;&lt;/p&gt;
Perdoe-me caso você não enfrente esse problema no seu dia a dia.



&lt;h1&gt;
  
  
  Devagar e sempre
&lt;/h1&gt;

&lt;p&gt;A API Web do Spotify disponibiliza dois endpoints para gerência de playlists: &lt;a href="https://developer.spotify.com/documentation/web-api/reference/playlists/replace-playlists-tracks" rel="noopener noreferrer"&gt;um&lt;/a&gt; que permite sobrescrever todas as faixas e &lt;a href="https://developer.spotify.com/documentation/web-api/reference/playlists/reorder-playlists-tracks/" rel="noopener noreferrer"&gt;outro&lt;/a&gt; que pode ser usado para mover uma faixa ou um bloco de faixas. Ao contrário do primeiro, este não modifica o &lt;em&gt;timestamp&lt;/em&gt; que indica quando as faixas foram adicionadas à playlist e o identificador de quem as adicionou (para playlists colaborativas).  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk763yquv20q848pdvuhe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk763yquv20q848pdvuhe.png" alt="Visualização da reordenação de faixas" width="506" height="262"&gt;&lt;/a&gt;&lt;/p&gt;
Visualização de como funciona o endpoint "reordenação de faixas de uma playlist". &lt;br&gt; Fonte: &lt;a href="https://developer.spotify.com/documentation/web-api/reference/playlists/reorder-playlists-tracks/" rel="noopener noreferrer"&gt;Spotify for Developers&lt;/a&gt;



&lt;p&gt;Como visto acima, esse endpoint funciona de forma que ordenar uma playlist requer várias requisições consecutivas (basicamente uma requisição por faixa na playlist), o que também significa que leva muito mais tempo do que simplesmente sobrescrever tudo. Sacrifícios tiveram que ser feitos, mas o resultado é exatamente o esperado: aqui está o &lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor" rel="noopener noreferrer"&gt;Spotify Playlist Editor&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mhaxmvbqepdmocpclq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mhaxmvbqepdmocpclq3.png" alt="Spotify Playlist Editor" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;
Quando você tiver feito login, algo assim deve aparecer na tela inicial da aplicação.



&lt;h1&gt;
  
  
  Detalhando o processo (mas não demais)
&lt;/h1&gt;

&lt;p&gt;Eu queria prototipar uma aplicação React o mais rápido possível, então usei o &lt;a href="https://facebook.github.io/create-react-app/" rel="noopener noreferrer"&gt;create-react-app&lt;/a&gt;, que me poupou muito tempo de configurações iniciais. Em geral, encorajo que você tente entender como criar uma aplicação React do zero, mas isso é com certeza é uma mão na roda quando se tem pressa. Para manter tudo simples, o &lt;strong&gt;Spotify Playlist Editor&lt;/strong&gt; é &lt;em&gt;serverless&lt;/em&gt;, mas permite que todos acessem seus dados do Spotify através de uma implementação do &lt;a href="https://developer.spotify.com/documentation/general/guides/authorization-guide/" rel="noopener noreferrer"&gt;fluxo de concessão implícita&lt;/a&gt;, uma abordagem simples para conseguir token de acesso à API.&lt;/p&gt;

&lt;p&gt;Incluí alguns pacotes e ferramentas para simplificar o processo de codificação (por exemplo, &lt;a href="https://getbootstrap.com" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt; para que eu me preocupasse menos com estilos e &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;prettier&lt;/a&gt; para ajudar a manter o código padronizadinho). Também considero interessante mencionar que uso &lt;a href="https://flow.org" rel="noopener noreferrer"&gt;Flow&lt;/a&gt; para checagem estática de tipos. Eu amo que JavaScript tem tipagem dinâmica, mas como o SDK lida com muitos modelos que têm, por sua vez, muitos atributos, Flow se torna um ótimo aliado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cc5wozmf3c7qxhovub8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cc5wozmf3c7qxhovub8.png" alt="IntelliSense" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;
Você pode até odiar o Flow, mas o fato é que React + Flow + &lt;a href="https://code.visualstudio.com/docs/editor/intellisense" rel="noopener noreferrer"&gt;IntelliSense&lt;/a&gt; é um verdadeiro dream team.



&lt;h2&gt;
  
  
  Conheça o melhor amigo &lt;del&gt;autoproclamado&lt;/del&gt; da API Web do Spotify, o spotify-web-sdk!
&lt;/h2&gt;

&lt;p&gt;Aqui está um trecho de código tirado do componente &lt;em&gt;UserPage&lt;/em&gt;. Você pode ver que alguns imports são feitos diretamente ao SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* @flow */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* Funções que encapsulam endpoints da API do Spotify */&lt;/span&gt;
    &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;getCurrentUserPlaylists&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;getCurrentUserProfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="cm"&gt;/* Modelos */&lt;/span&gt;
    &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;PlaylistSimplified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;PrivateUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spotify-web-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PlaylistSimplified&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;playlists&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PlaylistSimplified&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PrivateUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Uma vez que o usuário esteja conectado ao Spotify, &lt;em&gt;UserPage&lt;/em&gt; é a página principal da aplicação. Seu principal propósito é exibir uma lista de playlists do usuário, com um botão que permite selecionar uma playlist de interesse. Inicialmente, cinco playlists são recuperadas:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;componentDidMount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getCurrentUserPlaylists&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;playlists&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ao manter o objeto &lt;em&gt;page&lt;/em&gt; no state do componente, requisitar mais playlists é tão simples quanto poderia ser. Isso é graças à lógica de recuperar os próximos dados já estar implementada lá na declaração da classe &lt;em&gt;Page&lt;/em&gt; no &lt;em&gt;spotify-web-sdk&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getNextPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasNext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;There are no more pages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAxiosPageInstance&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Dessa forma, lidar com toda essa lógica no editor de playlists se resume a uma simples chamada de função, dispensando a necessidade de manter-se a par de valores como limite e offset:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;loadMorePlaylists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getNextPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
    &lt;span class="c1"&gt;// Relaxa e deixa o spotify-web-sdk lidar com o trabalho duro!&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevState&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playlists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prevState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playlists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;playlists&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nextPage&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;O propósito principal da aplicação é permitir que os usuários ordenem suas playlists, então vamos focar nisso agora. Do componente &lt;em&gt;PlaylistPage&lt;/em&gt;, o usuário pode selecionar um método de ordenação (incluindo por data de lançamento!). Por baixo, minha implementação determina primeiro a ordem final esperada das faixas e então faz uso de chamadas sequenciais para reordená-las. É assim que funciona mais ou menos em código:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reorderPlaylistTracks&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spotify-web-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortPlaylistTracksByAttribute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;playlistId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;insertionOrder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getInsertionOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;playlistId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;insertionOrder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;previousPromise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;moveTrackToTop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;playlistId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getInsertionOrder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;playlistId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Determina a ordem de inserção baseada no atributo escolhido. */&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moveTrackToTop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;reorderPlaylistTracks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rangeLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;insertBefore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A propósito, se você não está familizarizado com essa abordagem de resolver Promises sequencialmente usando &lt;em&gt;Array.prototype.reduce()&lt;/em&gt;, tem um excelente artigo explicando como e, mais importantemente, a &lt;strong&gt;razão&lt;/strong&gt; disso funcionar. Dá uma olhada lá no &lt;a href="https://css-tricks.com/why-using-reduce-to-sequentially-resolve-promises-works/" rel="noopener noreferrer"&gt;CSS Tricks&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Como mostrado acima, o objetivo principal do spotify-web-sdk é poupar tempo dos desenvolvedores que desejam fazer acesso à API Web do Spotify. No lugar de fazer chamadas diretas à API e se preocupar com detalhes, a maior parte do seu trabalho deve ser importar uma função e invocá-la no código. &lt;/p&gt;

&lt;p&gt;Caso você tenha interesse em construir sua própria aplicação usando dados do Spotify, a versão atual do &lt;em&gt;spotify-web-sdk&lt;/em&gt; está &lt;a href="https://npmjs.com/package/spotify-web-sdk" rel="noopener noreferrer"&gt;hospedada no NPM&lt;/a&gt; e pode ser adicionada rapidamente em um projeto com package.json rodando &lt;code&gt;npm add spotify-web-sdk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;Spotify Playlist Editor&lt;/strong&gt; também está no ar &lt;a href="https://calluswhatyouwant.github.io/spotify-playlist-editor/" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; se você quiser brincar um pouco. Caso você experiencie qualquer coisa inesperada ao usar a aplicação, é apenas um treino para estimular o espírito open source: crie uma issue no repositório do GitHub! PRs também são sempre bem-vindas (tem umas issues abertas e o Hacktoberfest está logo aí...). &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/calluswhatyouwant" rel="noopener noreferrer"&gt;
        calluswhatyouwant
      &lt;/a&gt; / &lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor" rel="noopener noreferrer"&gt;
        spotify-playlist-editor
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Sort your Spotify playlists any way you want.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Spotify Playlist Editor&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Sort your Spotify playlists anyway you want! 🛠&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/calluswhatyouwant/spotify-playlist-editor./main-page.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcalluswhatyouwant%2Fspotify-playlist-editor.%2Fmain-page.png" alt="Initial page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Table of Contents&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor#features" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor#community" rel="noopener noreferrer"&gt;Community&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor#installation-and-usage" rel="noopener noreferrer"&gt;Installation and Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor#deployment" rel="noopener noreferrer"&gt;Deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor#suggest-a-new-feature-or-report-a-bug" rel="noopener noreferrer"&gt;Suggest a new feature or report a bug&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/calluswhatyouwant/spotify-playlist-editor#maintainers" rel="noopener noreferrer"&gt;Maintainers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Create new playlists out of your recent Spotify tracks or your all-time top tracks;&lt;/li&gt;
&lt;li&gt;Sort playlists based on:
&lt;ul&gt;
&lt;li&gt;playlist track attributes (addition date);&lt;/li&gt;
&lt;li&gt;track attributes (name, length, popularity);&lt;/li&gt;
&lt;li&gt;album attributes (name, release date);&lt;/li&gt;
&lt;li&gt;artist attributes (name).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Current limitations&lt;/h3&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;It's highly recommended to create a copy of the playlists you want to edit or to use one of the playlist creation options. (play around, but do it safely!);&lt;/li&gt;
&lt;li&gt;You can only sort playlists with 100 tracks or less;&lt;/li&gt;
&lt;li&gt;Sorting might take a while (a playlist with 100 tracks can take between 30 seconds and 1 minute). Do NOT reload or close the playlist page until sorting is over.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Community&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Installation and Usage&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Simply run &lt;code&gt;yarn install&lt;/code&gt; to install the project's dependencies…&lt;/p&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/calluswhatyouwant/spotify-playlist-editor" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Se quiser ficar por dentro das novidades dos projetos do Call Us What You Want, acompanhe o nosso &lt;a href="https://twitter.com/CallUsWhat" rel="noopener noreferrer"&gt;perfil no Twitter&lt;/a&gt;!&lt;/p&gt;




&lt;p&gt;Muito obrigado pela leitura! Fique atento: em breve, teremos novos artigos de contribuidores do OpenDevUFCG aqui no &lt;strong&gt;dev.to&lt;/strong&gt;. Acompanhe o OpenDevUFCG no &lt;a href="https://twitter.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, no &lt;a href="https://instagram.com/OpenDevUFCG" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; e, claro, no &lt;a href="https://github.com/OpenDevUFCG" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>music</category>
      <category>webdev</category>
      <category>showdev</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>Testes em JavaScript: Conceitos iniciais</title>
      <dc:creator>Júlio Guedes</dc:creator>
      <pubDate>Sat, 07 Sep 2019 21:51:15 +0000</pubDate>
      <link>https://forem.com/opendevufcg/testes-em-javascript-conceitos-iniciais-1okj</link>
      <guid>https://forem.com/opendevufcg/testes-em-javascript-conceitos-iniciais-1okj</guid>
      <description>&lt;p&gt;Diferentemente do que muitos pensam, o desenvolvimento de uma aplicação Web ou Mobile necessita de testes, seja para assegurar a qualidade do produto, o funcionamento, e até mesmo a aparência, durante a evolução do código.&lt;br&gt;
Quando nosso software está bem consolidado em termos de testes, podemos estabelecer estratégias de integração e deploy contínuos (CI/CD). Esses métodos atuam para garantir que nossa aplicação não tenha sofrido efeitos colaterais com as adições, modificações e correções que estarão sendo enviadas à branch principal para deploy. Nesse post, serão introduzidos os conceitos de &lt;strong&gt;Spies&lt;/strong&gt; e &lt;strong&gt;Stubs&lt;/strong&gt;, e como eles são úteis durante o desenvolvimento de um conjunto de testes de unidade.&lt;/p&gt;
&lt;h1&gt;
  
  
  Teste de Unidade
&lt;/h1&gt;

&lt;p&gt;Vamos supor o seguinte cenário: temos uma aplicação que requer o cadastro dos seus usuários com um &lt;em&gt;username&lt;/em&gt;, que deve ter tamanho de pelo menos 3 caracteres. Para tal, podemos adicionar no código de cadastro uma verificação para o tamanho do username:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cadastrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;senha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;O username necessita de pelo menos 3 caracteres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Continua o cadastro&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando escrevemos testes para a função de cadastro, nossa intenção seria testar diferentes casos, escolhendo &lt;strong&gt;valores limite&lt;/strong&gt;, para podermos testar a qualidade da nossa verificação e se estamos deixando passar algum cenário indesejado. Por enquanto, não vamos nos importar tanto com a sintaxe, mas na semântica:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testes da função de cadastro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testa um username válido&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cadastrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;teste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;teste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="cm"&gt;/* Nesse caso, espera-se que não seja lançado um erro,
     * visto que o username tem três ou mais caracteres
     */&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testa um username invalido&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cadastrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;te&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;teste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;O username necessita de pelo menos 3 caracteres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* Nesse outro caso, como o username tem menos de 3 caracteres,
     * espera-se que seja lançado um erro com a mensagem descrita
     */&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// testes de senha, e outros fluxos do cadastro&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso, estamos testando apenas a função de cadastro, ou seja, um teste unitário que testa apenas uma "unidade básica" do sistema (entenda unidade básica como aquela unidade que não chama outras funções internamente). De agora em diante, a ideia é termos funções mais complicadas que isso, ou seja, funções que precisam chamar outras funções na sua execução, por envolverem lógicas mais complexas.&lt;/p&gt;

&lt;h1&gt;
  
  
  Spies
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fprofile_images%2F951185073402994688%2FpKyQmqYh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fprofile_images%2F951185073402994688%2FpKyQmqYh.jpg" alt="Spies"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine agora que, uma vez cadastrado, também seja possível alterar esse &lt;em&gt;username&lt;/em&gt;. Temos, então, duas situações possíveis em que desejamos verificar se o que o usuário inseriu é válido. Para isso, podemos refatorar nosso código atual de maneira a reutilizar as linhas que verificam se o &lt;em&gt;username&lt;/em&gt; está no padrão correto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verificaUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;O username necessita de pelo menos 3 caracteres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cadastrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;senha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;verificaUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Continua o cadastro&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com o código refatorado, é também preciso refatorar os testes, para que se adequem ao contexto real do código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testes da função de cadastro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testa um username válido&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verificaUsername&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cadastrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;teste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;teste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;been&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;called&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testa um username invalido&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verificaUsername&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cadastrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;te&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;teste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;O username necessita de pelo menos 3 caracteres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;been&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;called&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// testes de senha, e outros fluxos do cadastro&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que já vimos como os spies são declarados e verificados, é mais fácil entender seu significado: um spy serve para verificar se uma função foi chamada ou não durante a execução de outra função. No nosso exemplo, pedimos para que o sinon (a biblioteca de testes que estamos usando) "espie" o método &lt;code&gt;verificaUsername&lt;/code&gt; e, após a chamada para a execução de &lt;code&gt;cadastrar&lt;/code&gt;, verificamos se &lt;code&gt;verificaUsername&lt;/code&gt; foi chamada. &lt;/p&gt;

&lt;p&gt;Entretanto, existe uma particularidade importante a se notar no nosso código: quando testamos um username inválido, a exceção ainda é lançada. Isso nos faz notar que nosso spy não modifica nada no código em execução, apenas verifica se as chamadas internas a uma função são realmente chamadas.&lt;/p&gt;

&lt;h1&gt;
  
  
  Stubs
&lt;/h1&gt;

&lt;p&gt;Mudando um pouco a perspectiva dentro do sistema que estamos construindo, podemos pensar num sistema mais complexo e que funciona numa certa sequência de operações e, para executar a operação seguinte, a anterior precisa ter sido executada corretamente. Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;operacaoComplexa&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;operacaoMenor&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resposta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resposta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;erro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;erro&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A função acima não parece ter uma lógica nem um motivo bem definidos, como é o caso da função de cadastro. Entretanto, não é esse o ponto em que precisamos focar: podemos ver que o retorno da &lt;code&gt;operacaoMenor&lt;/code&gt; é importante para entendermos o que será retornado nessa função, seja em caso de sucesso ou em caso de erro. Consideremos então que, por exemplo, essa função menor faz uma requisição a um serviço externo, uma API por exemplo.&lt;/p&gt;

&lt;p&gt;Na execução do nosso código, o código dessa função executará normalmente, fazendo a requisição necessária. Durante os testes, entretanto, não se deve fazer uma chamada à API, já que a API pode alterar dados reais da aplicação, deixar o banco de dados inconsistente e causar muitos outros problemas. Precisamos então de uma forma para testar a operação complexa sem realmente executar o código de &lt;code&gt;operacaoMenor&lt;/code&gt;, e para isso servem os &lt;strong&gt;stubs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fyukaichou.com%2Fwp-content%2Fuploads%2F2014%2F10%2FGamification-vs-Manipulation-image.jpg%3Fresize%3D600%252C375%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fyukaichou.com%2Fwp-content%2Fuploads%2F2014%2F10%2FGamification-vs-Manipulation-image.jpg%3Fresize%3D600%252C375%26ssl%3D1" alt="Stubs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Então, o que exatamente um Stub faz? Durante a execução dos nossos testes, um stub substitui uma função existente no código por uma função representativa, na qual é possível controlar o seu retorno. Através desse controle, o restante do código pode executar normalmente e é possível percorrer todos os cenários da execução do programa durante os testes, manipulando o retorno do stub conforme adequado. Vejamos como seria a aplicação de um stub no código dessa função:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testa operacaoComplexa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testa cenario 1 do then&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operacaoMenor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolves&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;param&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;retornoComplexo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;operacaoComplexa&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;retornoComplexo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* retorno no caso 1 */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;been&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;called&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testa cenario 2 do then&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operacaoMenor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolves&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;param&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;retornoComplexo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;operacaoComplexa&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;retornoComplexo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* retorno no caso 2 */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;been&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;called&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testa cenario catch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operacaoMenor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rejects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mensagem de erro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;operacaoComplexa&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Operação não deveria ter dado certo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;erro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;erro&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mensagem de erro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;been&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;called&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O teste acima verifica os três cenários que colocamos no código da nossa função. O teste parece ser grande, mas cobre apenas os três fluxos básicos na execução da &lt;code&gt;operacaoComplexa&lt;/code&gt;. Explicando em alto nível a sintaxe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no caso 1, estamos dizendo que a &lt;code&gt;operacaoMenor&lt;/code&gt; deve ser um stub que resolve, no retorno da Promise, um objeto &lt;code&gt;{ param: true }&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;no caso 2, estamos dizendo que a &lt;code&gt;operacaoMenor&lt;/code&gt; deve ser um stub que resolve, no retorno da Promise, um objeto &lt;code&gt;{ param: false }&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;no caso 3, de erro, estamos dizendo que a &lt;code&gt;operacaoMenor&lt;/code&gt; deve ser um stub que rejeita, no retorno da Promise, sendo &lt;code&gt;'mensagem de erro'&lt;/code&gt; a string retornada no erro.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nesse caso específico, nossa função complexa tinha uma chamada assíncrona (uma Promise) e, por isso, utilizamos &lt;code&gt;resolves&lt;/code&gt; e &lt;code&gt;rejects&lt;/code&gt; no nosso stub; caso fosse uma função síncrona, poderíamos ter utilizado &lt;code&gt;returns&lt;/code&gt; normalmente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plus!
&lt;/h2&gt;

&lt;p&gt;Existem diversas bibliotecas que podem ser utilizadas para testes em JavaScript. Algumas das mais famosas são &lt;a href="https://mochajs.org/#getting-started" rel="noopener noreferrer"&gt;Mocha&lt;/a&gt;, &lt;a href="https://sinonjs.org" rel="noopener noreferrer"&gt;Sinon&lt;/a&gt; e &lt;a href="https://chaijs.com" rel="noopener noreferrer"&gt;Chai&lt;/a&gt;, que geralmente são utilizados em conjunto. Atualmente, uma das bibliotecas que está sendo bastante visada é o &lt;a href="https://jestjs.io" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;. Se você está pensando em como começar a aplicar o que aprendeu aqui, te sugiro fazer alguns testes simples num dos sites que você hospeda no GitHub Pages — um portfolio, um pequeno projeto de disciplina, quem sabe? Qualquer um desses vai te dar um bom contato inicial :).&lt;/p&gt;

&lt;h2&gt;
  
  
  Chegamos ao fim desse post... :(
&lt;/h2&gt;

&lt;p&gt;Mas não se preocupe, há muito mais conteúdo do OpenDevUFCG para ler aqui no dev.to, e em breve ainda mais posts saindo do forno.&lt;/p&gt;

&lt;p&gt;Agradeço bastante pela leitura, e se quiser entrar em contato comigo, só mandar um &lt;a href="https://twitter.com/juliobguedes" rel="noopener noreferrer"&gt;Tweet&lt;/a&gt;! Se quiser ler mais textos meus, confere meu &lt;a href="https://medium.com/@Juliobguedes/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; que em breve mais posts vão sair.&lt;/p&gt;

&lt;p&gt;Fique atento: em breve, teremos novos artigos de contribuidores do OpenDevUFCG aqui no dev.to. Acompanhe o OpenDevUFCG no &lt;a href="https://www.twitter.com/OpenDevUFCG/" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, no &lt;a href="https://www.instagram.com/OpenDevUFCG/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; e, claro, no &lt;a href="https://www.github.com/OpenDevUFCG/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>ptbr</category>
    </item>
  </channel>
</rss>
