<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Pedro Henrique on Medium]]></title>
        <description><![CDATA[Stories by Pedro Henrique on Medium]]></description>
        <link>https://medium.com/@pedrofullstack?source=rss-fd9e7a69f5d1------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*07wFhFklcFXHJi8d.jpeg</url>
            <title>Stories by Pedro Henrique on Medium</title>
            <link>https://medium.com/@pedrofullstack?source=rss-fd9e7a69f5d1------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 09:08:28 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@pedrofullstack/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Um Guia Para Design Patterns em JavaScript]]></title>
            <link>https://medium.com/@pedrofullstack/um-guia-para-design-patterns-em-javascript-171ca3c24dd6?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/171ca3c24dd6</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[padrões-de-projeto]]></category>
            <category><![CDATA[código]]></category>
            <category><![CDATA[programação]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Mon, 03 Aug 2020 21:32:23 GMT</pubDate>
            <atom:updated>2020-08-03T21:32:23.744Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hFZMjg0KRB-48cupnLoH5w.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@arianismmm?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Arian Darvishi</a> on <a href="https://unsplash.com/s/photos/software?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Design Patterns são soluções reutilizáveis para problemas comuns no desenvolvimento de software. Todo programador já encontrou várias vezes problemas semelhantes que pediam soluções parecidas, essas soluções são os Padrões de Projetos (Design Patterns).</p><p>Toda linguagem tem várias dessas soluções reutilizáveis criadas pela sua comunidade. É por causa dessa experiência combinada de vários desenvolvedores que os padrões de projetos são tão úteis, eles nos ajudam a produzir um código otimizado ao mesmo tempo que resolvem nosso problema. Outra grande vantagem é que por serem comuns desenvolvedores diferentes conseguem entender com facilidade os códigos uns dos outros.</p><p>Os maiores benefícios dos padrões de projetos são os seguintes:</p><ul><li><strong>São soluções que funcionam</strong>: Como são usados por vários programadores, você pode ter certeza de que funcionam. E não é só isso, como foram usados muitas vezes, várias otimizações foram sendo feitas ao longo do tempo.</li><li><strong>Facilmente reutilizáveis</strong>: Padrões de projeto são soluções reutilizáveis que podem ser facilmente adaptadas a problemas particulares, elas não se limitam a um único problema.</li><li><strong>São expressivas</strong>: Padrões de projeto conseguem explicar uma solução grande de forma elegante.</li><li><strong>Elas facilitam a comunicação</strong>: Programadores familiares com padrões de projeto conseguem conversar de forma mais fácil a respeito das soluções.</li><li><strong>Diminuem a necessidade de refatoração</strong>: Quando você escreve uma aplicação tendo padrões de projeto em mente, fica mais fácil de ter um código limpo mais rápido. Assim, acabamos fazendo menos refatorações.</li><li><strong>Eles diminuem o tamanho da código</strong>: Porque padrões de projeto normalmente são soluções otimizadas, elas costumam precisar de menos código para serem implementadas.</li></ul><p>Com tudo isso você já deve estar com vontade de começar a usar os padrões de projeto, mas acho importante revermos alguns conceitos de JavaScript primeiro.</p><h3>Uma Breve História do JavaScript</h3><p>Hoje em dia JavaScript é a linguagem de programação mais popular para web. No começo ela era só uma “cola” entre vários elementos HTML, uma linguagem de scripts para rodar no cliente para um dos primeiros navegadores, o Netscape. Naquela época os navegadores só conseguiam renderizar páginas HTML estáticas, o surgimento do JavaScript levou a uma guerra entre os grandes da época, Netscape e Microsoft.</p><p>Cada uma das grandes empresas do início dos anos 90 queria usar sua própria implementação para uma linguagem de scripts, Netscape com JavaScript (criado por Brendan Eich em 1995) e a Microsoft com o JScript. Essa foi a primeira Browser’s War.</p><p>Como você pode imaginar, as diferenças entre elas eram enormes e cada site precisava ser feito para um navegador específico, sempre com um sinal de “melhor visto em…”. Logo ficou claro que era preciso de um standard, uma linguagem cross-browser que unificaria o processo de desenvolvimento e simplificaria a criação das páginas web. O resultado disso tudo foi a criação do <a href="https://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript</a>.</p><p>ECMAScript é uma especificação para uma linguagem de script que todos os navegadores tentam suportar, e existem várias implementações do ECMAScript. A implementação mais popular de todas é o JavaScript. Desde seu lançamento o ECMAScript padronizou várias coisas importantes - para os curiosos existe uma lista de todos os detalhes na <a href="https://en.wikipedia.org/wiki/ECMAScript">Wikipedia em inglês</a>. O suporte para a versão 6 do ECMAScript (ES6) e as mais novas ainda está incompleto, por isso precisam ser transpiladas para ES5 antes de funcionarem em (quase) todos os navegadores.</p><p>O Que Então é JavaScript?</p><p>Para entendermos completamente os padrões de projeto deste post, vamos ver uma introdução a alguns aspectos importantes da linguagem que precisamos estar cientes antes de nos aprofundarmos nos padrões de projeto. Podemos definir JavaScript mais ou menos assim:</p><blockquote>JavaScript é uma linguagem leve, interpretada, orientada a objetos com funções de primeira classe mais conhecida como uma linguagem para páginas da web</blockquote><p>Essa definição serve para dizer que JavaScript tem uma pegada pequena na memoria, é de fácil uso, fácil de aprender e tem uma sintaxe similar a linguagens mais populares como C++ e Java. É uma linguagem de scripts, o que significa que seu código é interpretado e não compilado. Tem suporte a programação procedural, orientada a objeto e funcional, o que a torna muito flexível (e também é a causa de vários problemas).</p><p>Até agora, nós só vimos características semelhantes a várias outras linguagens de programação. Vamos dar uma olhada no que tem de específico no JavaScript e a destaca no meio das outras. Eu vou listar algumas características e dar o meu melhor para explicar o porque delas merecerem uma atenção especial.</p><p>JavaScript Suporta Funções de Primeira Classe</p><p>Essa é uma característica que pode ser difícil de compreender para quem vem de linguagens como C e C++. Dizer que JavaScript trata funções como cidadãos de primeira classe significa que você pode passar funções como parâmetros a outras funções como uma variável qualquer. Quase como se funções fossem objetos.</p><pre>// Mandamos uma função para ser executada<br>// dentro da função que faz a chamada<br>function performOperation(a, b, cd) {<br>    var c = a + b;<br>    cd(c);<br>}</pre><pre>performOperation(2, 3, function(result) {<br>    // result vai ser 5<br>    console.log(&quot;O resultado da operação é &quot; + result);<br>});</pre><h4>JavaScript é Baseada em Protótipos</h4><p>Como qualquer outra linguagem orientada a objetos, JavaScript suporta objetos (ó…), e umas das primeiras coisas que nos vem a mente quando falamos em objetos são classe e herança. E é aqui que a porca torce o rabo, JavaScript não suporta classes na sua linguagem mais básica, mas usa uma herança baseada em protótipos (também conhecida como instancia).</p><p>Só no ES6 que classes formais foram introduzidas, o que significa que muitos navegadores ainda não suportam essa feature (a última versão do ECMAScript completamente suportada pelos principais navegadores é a 5.1). Mas é importante lembrar que embora a palavra <em>class</em> tenha sido introduzida ela é só maquiagem, por baixo dos panos, JavaScript ainda usa sua herança baseada em protótipos.</p><p>A programação baseada em protótipos é um estilo de programação que constrói sua reutilização de comportamentos (a herança) através de um processo de reuso de objetos já existentes que funcionam como protótipos. Nós vamos rever a herança baseada em protótipos na seção sobre padrões de projeto, essa é uma característica muito usada nos design patterns.</p><h4>Loops de Eventos em JavaScript</h4><p>Se você já programou em JavaScript, com certeza é familiar com o termo <strong>callback</strong>. Para quem não está familiarizado, um callback é uma função passada como parâmetro que será executada quando um dado evento for disparado. Eles são geralmente usados para inscrição em eventos como click do mouse ou quando um botão é apertado.</p><p>Cada vez que um evento que tenha um listener (ouvinte?) é disparado, uma mensagem é enviada para uma fila (queue) que é processada de forma síncrona, do tipo FIFO (first-in-first-out). Isso é chamado de loop de eventos (event loop).</p><p>Cada mensagem na queue tem uma função relacionada a ela. Sempre que uma mensagem sai da fila, a função é executada por completo antes de qualquer outra mensagem ser processada. Ou seja, se a função contem outras chamadas a outras funções, eles são todas feitos antes de uma nova mensagem da fila ser processada. Isso é chamado run-to-completion.</p><pre>while (queue.waitForMessage()) {<br>    queue.processNextMessage();<br>}</pre><p>A <em>queue.processNextMessage()</em> espera por novas mensagens de forma síncrona. Cada uma das mensagens sendo processada tem o seu próprio stack e é processada até que o stack esteja vazio. Uma vez encerrado o processamento, uma nova mensagem é lida da fila, enquanto houverem mensagens na fila.</p><p>Também é comum ouvir dizer que JavaScript é não bloqueante, o que significa que quando uma operação asíncrona está sendo realizada o programa pode continuar processando outras coisas, como receber novos inputs, sem bloquear a thread principal. Essa é uma propriedade muito útil do JavaScript e de fato muitas pessoas optam por usar a linguagem fora do navegador justamente por isso. Esse é um tópico muito amplo e merece um artigo só para ele, acabei deixando de fora desse post.</p><h3>O Que São Design Patterns?</h3><p>De novo, padrões de projeto são soluções reutilizáveis para problemas comuns do desenvolvimento de software. Vamos ver as categorias de padrões de projetos.</p><h4>Proto-padrão</h4><p>Como se cria um padrão? Digamos que tu reconheceu um problema recorrente e tem uma solução única para esse problema, que ainda não foi globalmente reconhecida e documentada. Você usa essa solução sempre que encontra o mesmo problema e acredita que é uma solução reutilizavel e que toda a comunidade de desenvolvimento se beneficiária disso.</p><p>Tua solução vira imediatamente um padrão? Por sorte, não. É comum que uma pessoa com boas práticas de desenvolvimento apenas confunda algo que parece um padrão com o que , de fato, não é.</p><p>Como você pode saber se o que encontrou é realmente um padrão de projeto?</p><p>Descobrindo a opinião de outros desenvolvedores a respeito, sabendo o processo de criar o padrão e se familiarizando com os padrões já existentes. Existe uma fase pela qual o padrão precisa passar antes de ser reconhecido, a chamada proto-padrão.</p><p>Um proto-padrão precisa ser usado e testado por vários desenvolvedores antes de ser tornar um padrão de verdade. Tem um grande trabalho de documentação a ser feito para tornar um padrão reconhecido e usado pela comunidade.</p><h4>Anti-padrão</h4><p>Assim como um padrão de projeto representa uma boa prática, um anti-padrão (anti-pattern) representa uma má prática.</p><p>Um bom exemplo de anti-padrão é modificar o protótipo <em>Object</em>. Praticamente todos os objetos do JavaScript herdam de <em>Object </em>(lembre-se que JavaScript usa herança baseada em protótipos) então imagine que você tenha alterado esse protótipo. As mudanças em Object seriam vistas em todos os objetos que herdam desse protótipo — <strong>o que seria quase todos os objetos do JavaScript</strong>. Um desastre esperando para acontecer!</p><p>Outro exemplo é modificar objetos que você não conhece. Uma modificação em um método de um objeto usado em vários pontos da aplicação poderia causar uma grande confusão, em um time grande seria pior ainda. Você rapidamente teria colisões de nomenclatura, implementações compatíveis e um pesadelo na manutenção. Com sorte os testes te salvariam a tempo.</p><p>Da mesma forma que é importante conhecer boas práticas, também é legal conhecer as más. Essa é a única forma de perceber os erros e evitá-los antes que seja tarde demais.</p><h3>Categorias de Padrões de Projeto</h3><p>Padrões de projeto podem ser categorizado de várias maneiras, mas as mais populares são as seguintes:</p><ul><li>Padrões de projeto <strong>criacionais</strong></li><li>Padrões de projeto <strong>estruturais</strong></li><li>Padrões de projeto <strong>comportamentais</strong></li><li>Padrões de projeto de <strong>concorrência</strong></li><li>Padrões de projeto <strong>arquiteturais</strong></li></ul><h4>Padrões de Projeto Criacionais</h4><p>Esses padrões lidam com a geração de objetos de uma forma que otimize a criação quando comparado com a forma mais básica. Quando a forma padrão de criação de objetos poderia adicionar complexidade ou problemas ao código os padrões criacionais podem resolver o problema. Alguns padrões populares dessa categoria são (em inglês para facilitar as buscas no Google):</p><ul><li>Factory method</li><li>Abstract factory</li><li>Builder</li><li>Prototype</li><li>Singleton</li></ul><h4>Padrões de Projeto Estruturais</h4><p>Esses padrões trabalham com os relacionamentos entre objetos. Ele garantem que se uma parte do sistema muda, mais nada precisa mudar com ela. Os padrões mais populares dessa categoria são:</p><ul><li>Adapter</li><li>Bridge</li><li>Composite</li><li>Decorator</li><li>Facade</li><li>Flyweight</li><li>Proxy</li></ul><h4>Padrões de Projeto Comportamentais</h4><p>Esse tipo de padrões reconhecem, implementam e melhoram a comunicação entre objetos do sistema. Eles ajudam a garantir que partes desconexas da aplicação tenham a informação sincronizada. Exemplos populares são:</p><ul><li>Chain of Responsibility</li><li>Command</li><li>Iterator</li><li>Mediator</li><li>Memento</li><li>Observer</li><li>State</li><li>Strategy</li><li>Visitor</li></ul><h4>Padrões de Projeto de Concorrência</h4><p>Esse tipo de padrões de projeto lida com programação em várias threads (multi-threaded programming). Alguns mais populares são:</p><ul><li>Active object</li><li>Nuclear reaction</li><li>Scheduler</li></ul><h4>Padrões de Projeto Arquiteturais</h4><p>Padrões de projeto que são usados na arquitetura do sistema. Alguns mais famosos são:</p><ul><li>MVC (Model View Controller)</li><li>MVP (Model View Presenter)</li><li>MVVM (Model View ViewModel)</li></ul><p>Na próxima seção iremos dar uma olhada em alguns desses padrões, com exemplos para melhor entendimento.</p><h3>Exemplos de Padrões de Projeto</h3><p>Cada padrão de projeto representa uma solução para um tipo de problema. Não existe um conjunto universal de padrões que vai solucionar todos os problemas que você ira encontrar. Precisamos entender quando um dado padrão vai ser útil e quando ele vai entregar valor de fato. Uma vez que estejamos familiarizados com os padrões de projetos e os cenários nos quais eles se encaixam, seremos capazes de determinar qual padrão podemos usar e se ele serve para resolver o problema em questão.</p><p>Lembre-se, aplicar o padrão errado pode levar a efeitos indesejados, como complexidade desnecessária, perda de performance até criar um anti-padrão.</p><p>Essas são todas coisas importantes a serem consideradas quando estamos pensando em aplicar um padrão de projeto em nosso código. Vamos olhar alguns padrões de projetos que eu acho mais úteis para JavaScript e todo desenvolvedor JavaScript sênior deveria conhecer.</p><h4>Constructor Pattern</h4><p>Quando pensamos na implementação clássica de linguagens orientada a objetos, um construtor é uma função especial de uma classe que inicializa uma série de valores default e/ou valores recebidos.</p><p>Três formas comuns de criar objetos em JavaScript são:</p><pre>// Qualquer uma dessas maneiras pode ser usada<br>// para criar um objeto em JavaScript<br>var instance = {};<br>// ou<br>var instance = Object.create(Object.prototype);<br>// ou<br>var instance = new Object();</pre><p>Depois de criarmos um objeto, temos quatro maneiras de adicionar propriedades a eles. Elas são as seguintes:</p><pre>// A partir do ES3<br>// a notação .<br>instance.key = &quot;valor&quot;;</pre><pre>// A notação de colchetes<br>instance[&quot;key&quot;] = &quot;valor&quot;;</pre><pre>// A partir do ES5<br>// Definindo uma propriedade com Object.defineProperty<br>Object.defineProperty(instance, &quot;key&quot;, {<br>    value: &quot;valor&quot;,<br>    writable: true,<br>    enumerable: true,<br>    configurable: true<br>});</pre><pre>// Definindo multiplas propriedades com Object.defineProperties<br>Object.defineProperties(instance, {<br>    &quot;firstKey&quot;: {<br>        value: &quot;valor da primeira chave&quot;,<br>        writable: true<br>    },<br>    &quot;secondKey&quot;: {<br>        value: &quot;valor da segunda chave&quot;,<br>        writable: false<br>    }<br>});</pre><p>A forma mais comum de criação de um objeto é usando chaves e para adicionar propriedades a notação ponto ou colchetes. Por isso recomendo que esses sejam os métodos usados, vai facilitar o entendimento por outros programadores e teu eu do futuro.</p><p>Nós mencionamos antes que JavaScript não suporta classes nativas, mas suporta construtores através da palavra chave <em>new</em> prefixada a uma chamada de função. Dessa forma podemos usar uma função como construtor e inicializar as propriedades da mesma maneira que faríamos em uma linguagem tradicional.</p><pre>// Definimos um construtor para os objetos do tipo Person<br>function Person (name, age, isDeveloper) {<br>    this.name = name;<br>    this.age = age;<br>    this.isDeveloper = isDeveloper || false;</pre><pre>    this.writesCode = function() {<br>        console.log(this.isDeveloper ? &quot;Essa pessoa escreve código&quot; : &quot;Essa pessoa não escreve código&quot;);<br>    }<br>}</pre><pre>// Cria uma Person com as propriedades name: Bob, age: 38,<br>// isDeveloper: true e um método writesCode<br>var person1 = new Person(&quot;Bob&quot;, 38, true);</pre><pre>// Cria uma Person com as propriedades name: Ana, age: 32,<br>// isDeveloper: false e um método writesCode<br>var person1 = new Person(&quot;Ana&quot;, 32);</pre><pre>// Escreve: Essa pessoa escreve código<br>person1.writesCode();<br>// Escreve: Essa pessoa não escreve código<br>person2.writesCode();</pre><p>Porém, ainda podemos melhorar esse código. Se você lembrar, eu falei antes que JavaScript usa uma herança baseada em protótipos. O problema com o exemplo anterior é que o método <em>writesCode</em> é redefinido para cada instancia do construtor <em>Person</em>. Podemos evitar isso adicionando o método no protótipo.</p><pre>// Definimos um construtor para o objeto Person<br>function Person(name, age, isDeveloper) {<br>    this.name = name;<br>    this.age = age;<br>    this.isDeveloper = isDeveloper || false;<br>}</pre><pre>// Extendemos o prtótipo da função<br>Person.prototype.writesCode = function() {<br>    console.log(this.isDeveloper ? &quot;Essa pessoa escreve código&quot; : &quot;Essa pessoa não escreve código&quot;);<br>    }<br>}</pre><pre>// Cria uma Person com as propriedades name: Bob, age: 38,<br>// isDeveloper: true e um método writesCode<br>var person1 = new Person(&quot;Bob&quot;, 38, true);</pre><pre>// Cria uma Person com as propriedades name: Ana, age: 32,<br>// isDeveloper: false e um método writesCode<br>var person1 = new Person(&quot;Ana&quot;, 32);</pre><pre>// Escreve: Essa pessoa escreve código<br>person1.writesCode();<br>// Escreve: Essa pessoa não escreve código<br>person2.writesCode();</pre><p>Agora ambas as instancias de Person podem acessar uma instancia compartilhada de <em>writesCode().</em></p><p>É como se no primeiro exemplo a gente tivesse uma função diferente para cada Person, ou seja, cada Person aponta para sua função. No segundo exemplo não, todas as Persons vão apontar para a mesma função, o mesmo pedaço de código com a função.</p><h4>Module Pattern</h4><p>Apesar de ser orientada a objetos, JavaScript faz isso do seu próprio jeito peculiar. Como não possui propriamente classes ela também não tem limitadores de acesso aos componentes da classe. Em uma linguagem como Java ou C++ você pode definir os direitos de acesso para os membros de uma classe (private, protected, public, etc.), por isso, JavaScript tem uma maneira de emular esse comportamento.</p><p>Antes de entrar nos detalhes do module pattern, vamos ver melhor o que são <strong>closures</strong>. Uma closure é uma função com acesso ao scope do pai, mesmo depois que a função pai já foi encerrada. Ela nos ajuda a emular o comportamento dos limitadores de acesso. Vejamos um exemplo:</p><pre>// Nós usamos uma função invocada imediatamente<br>// para criar uma variada privada counter<br>var counterIncrementer = (function() {<br>    var counter = 0;</pre><pre>    return function() {<br>        return ++counter;<br>    };<br>})();</pre><pre>// Imprime 1<br>console.log(counterIncrementer());</pre><pre>// Imprime 2<br>console.log(counterIncrementer());</pre><pre>// Imprime 3<br>console.log(counterIncrementer());</pre><p>Como você pode ver, nós amarramos a variável <em>counter </em>a uma função que foi chamada e encerrada mas ainda pode ser acessada pela função filha que faz o incremento. Como não podemos acessar a variável <em>counter </em>de fora da função, na pratica nós a tornamos privada através da manipulação do escopo.</p><p>Usando closures podemos criar objetos com partes públicas e privadas. A isso damos o nome de <strong>modulos</strong> e são muito úteis quando queremos esconder partes de um objeto e expor somente uma interface para o usuário do módulo. Vamos ver um exemplo:</p><pre>// Através de uma closure vamos expor um objeto<br>// como uma API pública que faz a gestão de suas<br>// partes privadas<br>var collection = (function() {<br>    // private<br>    var objects = [];</pre><pre>    // public<br>    return {<br>        addObject: function(object) {<br>            objects.push(object);<br>        },<br>        removeObject: function(object) {<br>            var index = objects.indexOf(object);<br>            if (index &gt;= 0) {<br>                objects.splice(index, 1);<br>            }<br>        },<br>        getObjects: function() {<br>            return JSON.parse(JSON.stringify(objects));<br>        }<br>    };<br>})();</pre><pre>collection.addObject(&quot;Bob&quot;);<br>collection.addObject(&quot;Alice&quot;);<br>collection.addObject(&quot;Franck&quot;);</pre><pre><em>// imprime [&quot;Bob&quot;, &quot;Alice&quot;, &quot;Franck&quot;]</em><br>console.log(collection.getObjects());<br>collection.removeObject(&quot;Alice&quot;);</pre><pre><em>// imprime [&quot;Bob&quot;, &quot;Franck&quot;]</em><br>console.log(collection.getObjects());</pre><p>A maior utilidade desse padrão é ter uma separação clara entre partes publicas e privadas de um objeto.</p><p>Como nem tudo são flores, esse padrão tem alguns problemas. Quando queremos mudar a visibilidade de um membro, precisamos alterar todo o código em que ele é usado, porque a forma de acesso é diferente para partes publicas e privadas. Outro problema é que métodos adicionados depois do objeto ser criado não podem acessar os membros privados.</p><h4>Revealing Module Pattern</h4><p>Esse padrão é uma evolução do module pattern descrito acima. A principal diferença é que escrevemos toda a lógica do objeto no escopo privado e então expomos as partes que queremos através de um objeto anônimo. Também podemos trocar o nome de membros privados do objeto quando os mapeamos aos membros públicos.</p><pre>// Escrevemos toda a lógica do objeto como membros privados<br>// e expomos um objeto anônimo que mapeia os métodos que queremos<br>// expor aos seus membros públicos correspondentes<br><strong>var</strong> namesCollection = (<strong>function</strong>() {<br>    <em>// membros privados</em><br>    <strong>var</strong> objects = [];<br><br>    <strong>function</strong> <strong>addObject</strong>(object) {<br>        objects.push(object);<br>    }<br><br>    <strong>function</strong> <strong>removeObject</strong>(object) {<br>        <strong>var</strong> index = objects.indexOf(object);<br>        <strong>if</strong> (index &gt;= 0) {<br>            objects.splice(index, 1);<br>        }<br>    }<br><br>    <strong>function</strong> <strong>getObjects</strong>() {<br>        <strong>return</strong> JSON.parse(JSON.stringify(objects));<br>    }<br><br>    <em>// membros públicos</em><br>    <strong>return</strong> {<br>        addName: addObject,<br>        removeName: removeObject,<br>        getNames: getObjects<br>    };<br>})();<br><br>namesCollection.addName(&quot;Bob&quot;);<br>namesCollection.addName(&quot;Alice&quot;);<br>namesCollection.addName(&quot;Franck&quot;);</pre><pre><em>// imprime [&quot;Bob&quot;, &quot;Alice&quot;, &quot;Franck&quot;]</em><br>console.log(namesCollection.getNames());<br>namesCollection.removeName(&quot;Alice&quot;);</pre><pre><em>// imprime [&quot;Bob&quot;, &quot;Franck&quot;]</em><br>console.log(namesCollection.getNames());</pre><p>O revealing module pattern é uma das maneiras pelas quais podemos implementar um module pattern. As diferenças entre o revealing module pattern e as outras variantes é principalmente a maneira como os métodos públicos são referenciados. Como resultado, o revealing module pattern é muito mais fácil de ser usado e modificado, mas pode se provar frágil em certos cenários, como quando usamos os objetos em uma cadeia de heranças. As situações mais problemáticas são as seguintes:</p><ol><li>Se nós temos uma função privada que faz referência a uma função pública, não podemos sobrescrever a função pública. A função privada vai continuar a referenciar a implementação privada da função e isso pode levar a bugs.</li><li>Quando temos um membro público apontando para um membro privado e tentamos sobrescrever o membro público de fora do módulo, as outras funções ainda vão fazer referência ao valor privado da variável, introduzindo bugs.</li></ol><h4>Singleton Pattern</h4><p>Quando precisamos que exista uma única instância de uma classe, usamos o padrão singleton. Por exemplo, quando temos um objeto de configurações, não queremos criar um novo objeto cada vez que ele é chamado, mas que retorne sempre o mesmo.</p><pre>var singleton = (function() {<br>    // valor privado do singleton inicializado uma vez</pre><pre>   var config;</pre><pre>    function initializeConfiguration(values){<br>        this.randomNumber = Math.random();<br>        values = values || {};<br>        this.number = values.number || 5;<br>        this.size = values.size || 10;<br>    }</pre><pre>    // Exportamos o método centralizado para retornar<br>    // o valor do singleton<br>    return {<br>        getConfig: <strong>function</strong>(values) {<br>            <em>// inicializamos o singleton uma única vez</em><br>            <strong>if</strong> (config === undefined) {<br>                config = <strong>new</strong> initializeConfiguration(values);<br>            }<br><br>            <em>// e retornamos sempre o mesmo valor</em><br>            <strong>return</strong> config;<br>        }<br>    };<br>})();<br><br><strong>var</strong> configObject = singleton.getConfig({ &quot;size&quot;: 8 });</pre><pre><em>// imprime number: 5, size: 8, randomNumber: someRandomDecimalValue</em><br>console.log(configObject);</pre><pre><strong>var</strong> configObject1 = singleton.getConfig({ &quot;number&quot;: 8 });</pre><pre><em>// imprime number: 5, size: 8, randomNumber: same randomDecimalValue // como no primeiro config</em><br>console.log(configObject1);</pre><p>Como fica claro no exemplo, o número aleatório gerado é sempre o mesmo, assim como os valores de config recebidos.</p><p>É importante notar que o ponto de acesso para retornar os valores do singleton é único e precisa ser bem conhecido.</p><h4>Observer Pattern</h4><p>O Observer Pattern é muito útil quando queremos otimizar a comunicação entre partes separadas do sistema. Ela promove uma integração entre as partes sem que elas fiquem acopladas.</p><p>Você vai encontrar várias maneiras de implementar esse padrão, mas a mais simples é onde temos um emissor e vários observadores (observers, saca?).</p><p>O emissor vai executar todas as operações a que os observadores estão inscritos. Essas operações podem ser, inscrever um observador a um tópico, desinscrever um observador de um tópico e notificar os observadores sempre que algo é publicado em um tópico.</p><p>Uma das variantes desse padrão é o <strong>publisher/subscriber pattern</strong>, que é o que nós vamos ver nesse texto.</p><p>No padrão Observer, o emissor fica com todas as referências aos observadores e chama os métodos diretamente nesses objetos. No formato publisher/subscriber, nós temos canais que servem de comunicação entre o publisher (publicador) e os subscribers (assinantes). O publisher dispara um evento e simplesmente executa o callback enviado para esse evento.</p><p>Esse é um pequeno exemplo do padrão publisher/subscriber.</p><pre>var publisherSubscriber = {}</pre><pre>// Nós passamos um objeto container para gerenciar inscrições<br>(function(container) {<br>    // o id representa uma inscrição única ao tópico<br>    var id = 0;</pre><pre>    // os objetos se inscrevem em um tópico ao<br>    // enviar um callback a ser executado quando<br>    // o evento é disparado<br>    container.subscribe = function(topic, f) {<br>        if (!(topic in container)) {<br>            container[topic] = [];<br>        }</pre><pre>        container[topic].push({<br>            &quot;id&quot;: ++id,<br>            &quot;callback&quot;: f<br>        });</pre><pre>        return id;<br>    }</pre><pre>    // cada inscrição tem seu próprio ID, nós vamos<br>    // usá-lo para remover a inscrição<br>    constainer.unsubscribe = function(topic, id) {<br>        var subscribers = [];<br>        for (car subscriber of container[topic]) {<br>            if (subscriber.id !== id) {<br>                subscribers.push(subscriber);<br>            }<br>        }<br>        container[topic] = subscribers;<br>    }</pre><pre>    container.publish = function(topic, data) {<br>        for (var subscriber of container[topic]) {<br>            // quando executamos um callback é sempre bom<br>            // ler a documentação para saber quais argumentos<br>            // são passados pelo objeto que dispara o evento<br>            subscriber.callback(data);<br>        }<br>    }<br>})(publisherSubscriber);</pre><pre>var subscriptionID1 = publisherSubscriber.subscribe(&quot;mouseClicked&quot;, <strong>function</strong>(data) {<br>    console.log(&quot;Eu sou o callback de um evento mouseClicked e esses são meus dados: &quot; + JSON.stringify(data));<br>});</pre><pre>var subscriptionID2 = publisherSubscriber.subscribe(&quot;mouseHovered&quot;, <strong>function</strong>(data) {<br>    console.log(&quot;Eu sou o callback de um evento mouseHovered e esses são meus dados: &quot; + JSON.stringify(data));<br>});</pre><pre>var subscriptionID1 = publisherSubscriber.subscribe(&quot;mouseClicked&quot;, <strong>function</strong>(data) {<br>    console.log(&quot;Eu sou outro callback de um evento mouseClicked e esses são meus dados: &quot; + JSON.stringify(data));<br>});</pre><pre>// Quando publicamos um evento, todos os callbacks<br>// devem ser chamados e você verá três logs<br>publisherSubscriber.publish(&quot;mouseClicked&quot;, {&quot;data&quot;: &quot;data1&quot;});<br>publisherSubscriber.publish(&quot;mouseHovered&quot;, {&quot;data&quot;: &quot;data2&quot;});</pre><pre>// Nos desincrevemos de um evento<br>publisherSubscriber.unsubscribe(&quot;mouseClicked&quot;, subscriptionID3);</pre><pre><em>// agora só teremos 2 logs</em><br>publisherSubscriber.publish(&quot;mouseClicked&quot;, {&quot;data&quot;: &quot;data1&quot;});<br>publisherSubscriber.publish(&quot;mouseHovered&quot;, {&quot;data&quot;: &quot;data2&quot;});</pre><p>Esse padrão de projeto é especialmente útil quando queremos responder a um único evento em vários lugares diferentes. Imagine que você precisa fazer vários requests a uma API e dependendo das respostas fazer outras chamadas. Você teria que aninhar vários callbacks o que te levaria ao callback hell. Usando o publisher/subscriber você resolve a situação de uma maneira muito mais simples.</p><p>O problema deste padrão são os testes. Acaba sendo difícil testar o comportamento do publisher e das listeners.</p><h4>Mediator Pattern</h4><p>Um padrão muito útil para sistemas desacoplados é o mediator. Quando temos várias partes diferentes de um sistema que precisam se comunicar de forma coordenada um mediador pode ser a melhor opção.</p><p>Da mesma forma que na vida real, o mediador é um objeto que vai ser o ponto central de comunicação entre os objetos.</p><p>A primeira vista os padrões mediator e publisher/subscriber parecem muito parecidos. E, de fato, os dois servem para gerenciar a comunicação entre elementos. A diferença é que o publisher/subscriber joga os eventos ao vento e esquece, enquanto o mediador vai cuidar para que cada inscrito lide com a mensagem.</p><p>Um bom exemplo de uso do mediator é um wizard. Digamos que você tenha longo processo de cadastro no seu sistema. Normalmente é uma boa ideia quebrar em passos um processo que requer muitos dados do usuário.</p><p>É uma forma de facilitar a manutenção do código ao mesmo tempo que o usuário não fica soterrado em um formulário gigantesco. Um mediador poderia gerenciar todo o wizard mostrando para o usuário passos diferentes de acordo com o que é imformado em cada etapa do processo de inscrição.</p><p>O benefício óbvio desse padrão de projeto é a melhoria na comunicação entre as diferentes partes do sistema. Da mesma forma que em um debate o mediador garante que cada um tenha sua vez de falar e o faça na hora certa.</p><p>Por outro lado, o mediador é um ponto crítico de falha, se ele parar, todo o sistema para.</p><h4>Prototype Pattern</h4><p>Como já falamos várias vezes, JavaScript não suporta classes na sua forma nativa. A herança é feita através de protótipos.</p><p>Nós podemos criar objetos que serão usados como protótipos dos objetos a serem gerados. O protótipo é um projeto para os objetos que o construtor cria. Quase da maneira como diferenciamos classes e objetos em Java.</p><p>Vejamos um exemplo simples desse padrão.</p><pre>var personPrototype = {<br>    sayHi: function() {<br>        console.log(&quot;Oi, meu nome é &quot; + this.name + &quot;, e eu tenho &quot; + this.age);<br>    },<br>    sayBye: function() {<br>        console.log(&quot;Tchau!&quot;);<br>    }<br>};</pre><pre>function Person(name, age) {<br>    name = name || &quot;Fulano&quot;;<br>    age = age || 26;</pre><pre>function constructorFunction(name, age) {<br>        this.name = name;<br>        this.age = age;<br>    };<br><br>    constructorFunction.prototype = personPrototype;<br><br>    var instance = new constructorFunction(name, age);<br>    return instance;<br>}<br><br>var person1 = Person();<br>var person2 = Person(&quot;Beltrano&quot;, 38);<br><br><em>// imprime Oi, meu nome é Fulano, e eu tenho 26</em><br>person1.sayHi();</pre><pre><em>// imprime Oi, meu nome é </em>Beltrano<em>, e eu tenho 38</em><br>person2.sayHi();</pre><p>Note que a herança por protótipos acaba trazendo uma melhoria em performance também, porque os dois objetos tem uma referência ao mesmo método que é implementado no protótipo, ao invés de ser implementado em cada um deles.</p><h4>Command Pattern</h4><p>O Command Pattern é usado quando queremos encapsular uma chamada como um objeto. É uma maneira de manter separados os contexto de quem chama e de quem é chamado.</p><p>Digamos que tua aplicação tenha várias chamadas para uma API. Imagine agora que a API mude. Teríamos que mexer em todos os pontos que interagem com a API.</p><p>É aqui que entra uma camada de abstração separando os objetos que chamam a API dos objetos que dizem <strong>quando</strong> chamar. Dessa maneira não precisamos fazer uma alteração tão grande na aplicação, porque só precisamos mudar a chamada para a API que vai ser um lugar só.</p><p>Um problema desse padrão é que como ele cria uma camada de abstração adicional, pode impactar a performance da aplicação. É preciso saber balancear performance e facilidade de edição do código.</p><pre>// O objeto que sabe executar o comando<br>var invoker = {<br>    add: function(x, y) {<br>        return x + y;<br>    },<br>    subtract: function(x, y) {<br>        return x - y;<br>    }<br>}</pre><pre>// o objeto usado como camada de abstração quand executamos<br>// comandos; ele representa uma interface para o objeto<br>// invocador<br>var manager = {<br>    execute: function(name, args) {<br>        if (name in invoker) {<br>            return invoker[name].apply(invoker, [].slice.call(arguments, 1));<br>        }<br>        return false;<br>    }<br>}</pre><pre>// imprime 8<br>console.log(manager.execute(&quot;add&quot;, 3, 5));</pre><pre>// imprime 2<br>console.log(manager.execute(&quot;subtract&quot;, 5, 3));</pre><h4>Facade Pattern</h4><p>o padrão Facade é usado quando queremos criar uma camada de abstração entre o que é mostrado publicamente e a implementação interna. Ele é usado quando desejamos ter uma interface mais simples.</p><p>Um bom exemplo desse padrão são os seletores para manipulação do DOM em frameworks como JQuery, Dojo e D3. Essas bibliotecas tem seletores muito poderosos, que permitem a escrita de queries complexas de forma bem simples.</p><pre>jQuery(“.parent .child div.span”)</pre><p>Esse tipo de funcionalidade parece bem simples, mas esconde uma complexa lógica de seleção por baixo dos panos.</p><p>Aqui de novo, sempre que temos uma abstração acima do código, acabamos tendo uma perda de performance. Na maioria dos casos essa perda é irrelevante, mas é sempre bom considerar.</p><h3>Conclusão</h3><p>Padrões de projeto são ferramentas primordiais de qualquer desenvolvedor JavaScript. Elas colaboram muito na hora de dar manutenção ao código, por deixarem tudo mais simples e fácil de entender.</p><p>Esse post já está bem longo, se você quiser saber mais sobre os padrões de projeto eu recomendo o clássico <a href="https://amzn.to/2XoLBSA"><em>Design Patterns: Elements of Reusable Object-Oriented Software</em></a><em> </em>da Gang of Four e também o mais moderno <a href="https://amzn.to/30nG1BF"><em>Learning JavaScript Design Patterns</em></a><em> </em>de Addy Osmani. Os dois livros são muito bons e valem a leitura.</p><p><em>Me segue no </em><a href="https://twitter.com/pedrofullstack"><em>twitter</em></a><em>, para saber quando vai sair o próximo post</em> 😀</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=171ca3c24dd6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Entendo os Geradores do Python]]></title>
            <link>https://medium.com/@pedrofullstack/entendo-os-geradores-do-python-4a028556239d?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/4a028556239d</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[programação]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[python-programming]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Sat, 04 Jul 2020 14:56:00 GMT</pubDate>
            <atom:updated>2020-07-06T16:57:02.470Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qkykZ6fJCS3TpOQPumC6IA.jpeg" /><figcaption>Meu loop diário, ou quase…</figcaption></figure><p>Vamos supor que tu esteja no mercado com uma lista de compras. Para cada item da lista, tu coloca ele no carrinho e risca da lista. Tu consegue colocar a lista em uma folha até um dado tamanho, mas e se a lista tiver 10000 itens? E se ela for infinita?</p><p>A memória do computador é limitada, ali vão caber listas de alguns megas ou alguns gigas, mas listas muito grandes ou que você não sabe o tamanho podem quebrar a memória. Estruturas como arrays, listas e dicionários ficam armazenadas na memória, e por isso são limitadas pelo espaço disponível. Um gerador fica armazenado em outro lugar (em disco ou em banco, por exemplo) e por isso só coloca na memória o elemento que está sendo trabalhado no momento.</p><h3>Geradores</h3><p>Vamos análisar um problema que vai nos ajudar a entender os geradores.</p><pre>i = 0<br>while True:<br>    print(i)<br>    i+=1</pre><p>Temos um loop infinito que a cada iteração vai incrementar i em 1.</p><pre>def run_till_end():<br>    i = 0<br>    while True:<br>        return i<br>        i+=1</pre><p>Agora, temos uma função. Quando rodarmos run_till_end() ela vai retornar 0 e encerrar. Mesmo com o loop infinito ela encerra com o return , mas nós queremos todos os valores!</p><pre>def run_till_end():<br>    i = 0<br>    while True:<br>        yield i<br>        i+=1</pre><p>Usando o yield para retornar os valores, cada vez que chamarmos a função ele vai andar um passo. A cada chamada ela inicia a execução do ponto onde parou na chamada anterior. A grosso modo, funções com yield são chamadas de geradores.</p><pre>run = run_till_end()<br>print(type(run))<br>print(next(run))  # 0<br>print(next(run))  # 1</pre><p>Se rodarmos esse código, o tipo da função será generator. O primeiro print vai retornar 0 e o segundo vai retornar 1.</p><p>O mesmo pode ser feito com listas.</p><pre>def run_list():<br>    lst = [&#39;foo&#39;, &#39;baz&#39;, &#39;bar&#39;]<br>    for i in lst:<br>        yield i</pre><pre>run = run_list()<br>print(next(run))  # foo<br>print(next(run))  # baz</pre><p>Mas e se chamarmos next 4 vezes na run_list ?</p><p>Na quarta chamada vamos ter o erro StopIteration . Essa exeção é jogada sempre que o gerador tiver iterado por todos os itens.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SKHSb7JHNBEu9tcMVB8vUw.png" /><figcaption>Exeção StopIteration quando termina a lista</figcaption></figure><p>Existe outra maneira de criar geradores, quase como um list comprehension, o generator comprehension.</p><pre>quadrados_list = [n**2 for n in range(5)]  # cria uma lista<br>quadrados_gene = (n**2 for n in range(5))  # cria um gerador</pre><p>Quando você roda esse código, quadrados_list será uma lista e quadrados_gene será um gerador.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vXUBqMN2L-zF41YgA-64Mw.png" /><figcaption>Criando list e gerador</figcaption></figure><p>Lembrando:</p><ul><li>List comprehension usam colchetes [ ]</li><li>Generator comprehension usam parenteses ( )</li></ul><h3>Análisando a memória e velocidade</h3><p>Vamos análisar o uso de memória e o desempenho de listas e geradores. Para isso vamos criar os quadrados de 1 milhão de números.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TQIxwbZJ2_5MvfuZFCEaVQ.png" /><figcaption>Criando as variáveis e testando o tamanho</figcaption></figure><p>No quesito memória os geradores ganham com tranquilidade, a lista ocupou 8697472 bytes enquanto o gerador apenas 128.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pMg-O1zyDt33Mn0_WxjgPA.png" /><figcaption>Testando o desempenho de list e generator</figcaption></figure><p>Como você pode ver, em termos de desempenho as coisas se invertem. Como a lista já está armazenada em memória, ela acaba sendo mais rápida (0,009 segundos) do que o gerador (0,347 segundos).</p><h3>Concluindo</h3><p>Demos uma olhada nos geradores (ou generators) do Python. Vimos como eles se comportam e com podem ser usados para iterar sobre listas muito grandes ou que não sabemos o tamanho total.</p><p>Além dos exemplos que usamos aqui, os generators podem ser usados também para iterarmos sobre arquivos e bancos de dados.</p><p>Eu coloquei um Jupyter Notebook no Github com os exemplos para quem quiser rodar eles online, <a href="https://github.com/pedrozan/python-generators-blog">acesse aqui</a>.</p><p><a href="https://twitter.com/pedrofullstack"><em>Me segue no Twitter!</em></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4a028556239d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introdução ao Jupyter Notebook Para Python]]></title>
            <link>https://medium.com/@pedrofullstack/introdu%C3%A7%C3%A3o-ao-jupyter-notebook-para-python-b2cf79cea31d?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/b2cf79cea31d</guid>
            <category><![CDATA[jupyter-notebook]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[programação]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Mon, 29 Jun 2020 04:15:06 GMT</pubDate>
            <atom:updated>2020-06-29T04:15:06.150Z</atom:updated>
            <content:encoded><![CDATA[<p>Jupyter Notebook é uma aplicação web que permite a você criar e compartilhar documentos que contem ao mesmo tempo código interativo e textos explicativos.</p><p>Ele usa uma linguagem simples de markdown para formatação de texto e permite o uso de várias linguagens de programação além do Python. Ele é muito bom se você quer executar código de maneira interativa, por isso é muito usado no processamento exploratório de dados, simulações numéricas, modelagens estatisticas e até machine learning.</p><p>Como o Jupyter Notebook permite essa facilidade de rodar código e tomar notas, é uma baita ferramenta para quem está aprendendo a programar em Python.</p><p>Vamos ver então como você pode usar o Jupyter Notebook com o Python na sua máquina local.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wOWI-9WQ2ntWq_4mwa6C9Q.jpeg" /></figure><h3>Instalando o Jupyter Notebook</h3><p>Comece acessando o site do projeto <a href="https://jupyter.org/">jupyter.org</a> e encontrando o botão <em>Install the Notebook </em>(a Jupyter oferece também o Jupyter Lab, mas não é ele o nosso foco no momento). No site você encontra a opção de acessar o Jupyter Notebook online, sem precisar instalar nada, mas com menos controle tambem.</p><p>É possível fazer a instalação de duas maneiras, via pip ou com o Anaconda.</p><p>Pip é o package manager oficial do Python, através dele você pode instalar vários outros pacotes e dependencias que vão ser necessárias nos teus projetos. Se você jpa tem o Python instalado e configurado na sua máquina, basta usar o comando pip install notebook que já vai estar funcionando.</p><p>Anaconda é um kit de ferramentas para data science que já te entrega o Python junto com várias outras ferramentas comumente usadas nessa área. Se você é novo no Python e ainda não tem um ambiente funcional, essa é uma forma fácil de ter acesso a muitas das coisas que você vai acabar usando. Acesse o <a href="https://www.anaconda.com/products/individual">site de download da Anaconda</a> e siga as instruções lá.</p><h3>Rodando o Notebook</h3><p>Depois de instalado, para rodar o Jupyter Notebook apenas digite o seguinte no seu terminal</p><pre>$ jupyter notebook</pre><p>Você vai ver uma resposta semelhante a essa</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*WR8gbNHtsK1cDdj_eR7SEw.png" /></figure><p>O servidor do Jupyter Notebook vai ser iniciado e no seu navegador default você deve estar vendo uma tela como a abaixo. Se não abrir o seu navegador, tente navegar para <a href="http://localhost:8889/tree">http://localhost:8889/tree</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*ObD4fHYTFQKxQzo9mTIIXQ.png" /></figure><p>Essa é a página inicial do seu notebook, ela é separada em 3 abas: Files, Running e Clusters. A aba default é a Files, é nela que você vai visualizar, abrir e criar notebooks.</p><h3>Criando um Notebook</h3><p>Criar um Jupyter Notebook é bem fácil, basta clicar em <em>New</em> no canto direito e selecionar Python 3 do menu. O notebook vai ser criado e abrir em uma nova aba, você deve ver algo similar a:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*HA3FkiMKmc2GFavS38Iatw.png" /></figure><p>Seu notebook está criado, mas ainda sem título. Clicando em Untitled, no topo da página, você pode mudar o título do notebook. Quando trocar o nome dele seu notebook será salvo e será criado um novo arquivo com o mesmo nome do notebook e a extensão <em>.ipynb</em>. Na tela inicial do Jupyter Notebook você poderá ver o seu novo notebook com o status running.</p><p>Selecionando o notebook na aba Files aparecem algumas opções no topo, como Duplicate, Shutdown e Delete. Duplicate vai criar uma cópia do seu notebook, Shutdown para de rodar o notebook e delete apaga.</p><h3>Trabalhando com o Jupyter Notebook</h3><p>O Notebook é composto por diferentes células, elas ficam uma sobre a outra e podem ser de dois tipos, código e markdown.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/558/1*3cd1OzXq_a3sR8nFzQl7BA.png" /><figcaption>Célula de código</figcaption></figure><p>Essa é uma célula do tipo código e você pode começar a codar diretamente em Python 3 nela. Por exemplo, escrevendo 1 + 2 e apertando ctrl + enter você vai ver aparecer o resultado logo abaixo.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/619/1*FZoWE6y6WbxmPHHJW_Q3aA.png" /></figure><p>Se ao invés de ctrl + enter você usar shift + enter além de mostrar o resultado, o notebook vai posicionar o teu cursor em uma nova célula do tipo código e é só continuar programando.</p><p>Para trocar de código para markdown, basta usar o menu do topo ou usar a tecla de atalho: m para mudar para markdown e y volta para código.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*33rKmFbaymcoktmiqrqSyA.png" /></figure><p>Uma vez em modo markdown você pode começar a digitar os textos explicativos usando código de markdown semelhante ao que usaria em um README do Github por exemplo. <a href="https://www.ibm.com/support/knowledgecenter/SSHGWL_1.2.3/analyze-data/markd-jupyter.html">Aqui</a> a IBM fez uma ótima referência com a marcação que você pode usar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9CPiW3l_7Jo9Wc8vBJgnhw.png" /></figure><p>Dando o comando para executar o texto ele troca para o formato compilado. Um duplo-clique no texto e ele volta ser editável.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NdvyxOIPNgrFeWi7X-EwEQ.png" /></figure><h3>Modos de Edição e de Comando</h3><p>A célula que você seleciona pode estar em dois modos, edição e comando. Quando você clica em uma célula, ela entra automaticamente no modo de comando e isso fica evidente pela borda azul no lado esquerdo da célula. Se você clicar na área de código a célula muda para o modo de edição e a borda esquerda fica verde.</p><p>Apertando esc no mode de edição te leva para o mode comando.</p><p>Se você quiser ver todas as teclas de atalho disponíveis no Jupyter Notebook, pode navegar pelo menu em <em>Help</em> <em>→ Keyboard Shortcuts.</em></p><h3>Checkpoints</h3><p>Além de salvar o notebook na última versão, você pode criar checkpoints com o estado atual do notebook e depois voltar para esses pontos quando necessário. Os checkpoints são muito úteis para testar coisas novas sem medo de estragar o que está fazendo.</p><p>Para criar um checkpoint vá em <em>Save and Checkpoint </em>no menu <em>File. </em>Para reverter para um checkpoint salvo, clique em<em> Revert to Checkpoint </em>no mesmo menu.</p><h3>Concluindo</h3><p>Agora tu já aprendeu a usar os Jupyter Notebooks e pode usar eles para rodar teus códigos Python. Muito usados em projetos de análise de dados com bibliotecas como <em>numpy</em>, <em>pandas </em>e <em>matplotlib, </em>os notebooks também são muito úteis para testar e validar vários outros projetos. Um uso bem interessante pode ser válidar os endpoints de uma API chamdo as funções internas direto pelo notebook.</p><p>Espero que esse tutorial te ajudado a entrar no mundo dos notebooks. Se ficou com alguma dúvida pode colocar nos comentários que eu respondo o mais rápido possível.</p><p><em>Me segue no twitter </em><a href="http://twitter.com;pedrofullstack/"><em>@pedrofullstack</em></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b2cf79cea31d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Magia do Timeboxing]]></title>
            <link>https://medium.com/@pedrofullstack/a-magia-do-timeboxing-bb1472099e2b?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/bb1472099e2b</guid>
            <category><![CDATA[timebox]]></category>
            <category><![CDATA[procrastinação]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[scrum]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Tue, 16 Jul 2019 14:36:02 GMT</pubDate>
            <atom:updated>2019-07-16T14:36:02.368Z</atom:updated>
            <content:encoded><![CDATA[<p>Uma das peças chaves do Scrum é o Timeboxing, a técnica de definir um limite de tempo para uma entrega. De fato, o Scrum usa timeboxing para tudo, limite de tempo no sprint, na planning, na retro, etc.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s_-8ONLputm2ExC3PF0_sQ.jpeg" /><figcaption>Meça seus minutos parça</figcaption></figure><h3>Porque o Timeboxing Funciona</h3><p>Existe uma coisa chamada temporal motivation theory, criada por Piers Steel e Cornelius J. König ela tenta explicar como a motivação de alguém para fazer alguma coisa muda ao longo do tempo. Por exemplo, se você tem que limpar a casa para uma festa no final de semana, segunda-feira é muito mais interessante ficar no Netflix, mas conforme a sexta se aproxima a sua motivação para começar a faxina vai aumentando até superar a vontade de ver mais um episódio de Stranger Things e te tirar do sofá.</p><p>Existe até uma formula que explica o funcionamento da motivação (e da procrastinação também):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/292/1*9QjTMZeoAZvOfFdxAEnKYQ.png" /><figcaption>Fórmula da motivação no tempo</figcaption></figure><p>Onde <em>Motivation</em> é o desejo de se atingir um resultado, <em>Expectancy</em> é a probabilidade de sucesso, <em>Value</em> é a recompensa pelo resultado, <em>Impulsiviness</em> é a sensibilidade do individuo ao atraso e <em>Delay</em> é o tempo até a realização.</p><p>No timeboxing a busca é otimizar essa equação para alcançar o objetivo de forma rápida e eficiente. Para isso é preciso adicionar um passo a mais que é a definição exata do resultado esperado, a famosa definição de pronto, DOD do inglês. Então definimos o que fazer, em quanto tempo e o que é a entrega.</p><h3>Timeboxing nos eventos do Scrum</h3><p>Como parte do Scrum todos os eventos geram um ou mais artefatos, essas são as definições de pronto. Eles também têm um tempo específico para acontecerem conforme a duração da sprint, veja:</p><h3>Sprint</h3><p>Por definição o sprint é um timebox de um mês ou menos em que o time deve entregar as tarefas definidas na planning. O tamanho do sprint vai servir de base para definir a duração dos outros eventos.</p><h3>Sprint Planning</h3><p>Durante a planning o time vai definir o que será entregue no final da sprint. Para sprints de 1 mês a Scrum Guide define que a planning deve durar no máximo 8 horas, para sprints menores podemos definir tempos proporcionais. Essa regra não é definitiva, o time em que trabalho usa sprints de duas semanas com plannings de duas horas, pela regra deveríamos ter plannings de 4 horas.</p><h3>Daily</h3><p>Independentemente do tamanho da sprint, a daily é um timebox de 15 minutos para cada período de 24 horas. Dentro da daily, os membros do time vão ter a oportunidade de acompanhar o desempenho do time e o quanto do planejado na planning vai ser realmente entregue.</p><h3>Sprint Review</h3><p>Um encontro para apresentar o que foi realizado na sprint, essa é uma oportunidade para reavaliar o backlog com base no feedback recebido dos stakeholders. Para sprints de um mês o tempo padrão é de 4 horas.</p><h3>Sprint Retrospective</h3><p>Fundamental para o aprimoramento do time a retrospectiva é um timebox de 3 horas para um sprint de um mês. No final da retro devem ser definidas ações para melhorar a qualidade do produto e do time.</p><h3>Timebox Para Tarefas de Final Aberto</h3><p>Uma tarefa com um final aberto pode bagunçar todo o andamento de uma sprint. Uma spike para entender um novo sistema de pagamento, por exemplo, pode ser rápida ou pode exigir o contato com outros times e até empresas terceiras para entender como tudo funciona.</p><p>Para manter esse tipo de tarefa sob controle, podemos definir um prazo para sua realização e um artefato a ser entregue no fim. Seguindo nosso exemplo do sistema de pagamento, podemos definir que a spike deve durar no máximo 6 horas e no final deveremos ter uma POC da integração.</p><p>Se ao final das 6 horas não tivermos a POC funcionando, teremos pelo menos uma indicação forte de onde conseguir as informações que ainda faltam. A sprint atual não será afetada, mas teremos novas tarefas no backlog para serem executadas na próxima sprint.</p><h3>Conclusão</h3><p>Entendo melhor como funciona nossa motivação em relação ao tempo e como o timebox funciona no Scrum, podemos criar usos para a ferramenta. De uma forma geral, o timebox vai te ajudar a realizar mais em menos tempo.</p><p>Não tenha medo de testar para coisas que você precisa fazer na vida. Desde limpar a casa até trabalhos para a faculdade, no Master Chef os pratos são feitos dentro um timebox e alguns ficam maravilhosos.</p><p><em>Quer mais conteúdo? </em><a href="http://twitter.com/pedrofullstack"><em>Me segue no Twitter também</em></a><em> :D</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bb1472099e2b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Montando um ambiente de desenvolvimento Angular no Windows com WSL e VS Code]]></title>
            <link>https://medium.com/@pedrofullstack/montando-um-ambiente-de-desenvolvimento-angular-no-windows-com-wsl-e-vs-code-817995e23d01?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/817995e23d01</guid>
            <category><![CDATA[windows-subsystem-linux]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[windows-10]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[wsl]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Fri, 05 Jul 2019 02:21:01 GMT</pubDate>
            <atom:updated>2019-07-05T02:21:01.084Z</atom:updated>
            <content:encoded><![CDATA[<p>Começando com a Windows 10 Fall Creators Update a Microsoft lançou o Windows Subsystem For Linux (WSL) que permite o uso de um sistema Linux dentro do próprio Windows. Eu já vinha há um tempo curioso para experimentar esse ambiente e quando entrei em uma nova empresa e ganhei um notebook com Windows 10, pareceu uma ótima oportunidade.</p><p>Eu poderia ter montado o ambiente todo em Windows, mas como todo o time já usava o Linux para o desenvolvimento iam ser necessárias muitas adaptações para tudo rodar de forma lisa. O WSL funciona muito bem no lugar de uma VM ou do Docker nesses casos, porque é mais nativo e fácil de acessar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BKLG2rlY2s2wVU00fIk2SA.jpeg" /><figcaption>Foto bonita de código</figcaption></figure><h4>Instalando o Ubuntu dentro do Windows com WSL</h4><p>O primeiro passo para criarmos nosso ambiente é a instalação do Ubuntu via WSL. Como o Windows Subsystem for Linux é uma feature opcional do Windows 10, vamos ter que habilita-la em nosso sistema.</p><p>Abra o Powershell como administrador (de um clique direito em cima do ícone e escolha rodar como administrador, ou algo do tipo) e rode o seguinte comando:</p><pre>Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux</pre><p>Seu sistema vai reiniciar, tenha paciência e depois volte para cá.</p><p>Com o WSL habilitado basta acessar a própria Windows Store e no campo de busca procurar por Linux, você vai ver todas as opções de distros disponíveis na loja.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/793/1*cVwfuxWcRZ8DiJoQ4GfZHg.png" /><figcaption>Opções de distros na Windows Store</figcaption></figure><p>Escolha a distro de sua preferência, Ubuntu no nosso caso, e faça a instalação. Depois de instalado é preciso abrir o terminal do Ubuntu para que ele conclua a instalação criando seu usuário e senha para o Linux, <strong>ele pode ser diferente do que você usa no Windows</strong>.</p><h4>Instalação do Node.js</h4><p>Para o Angular funcionar ele precisa do Node.js e eu acho que a melhor forma de instalar ele no WSL é usando o <a href="https://github.com/nvm-sh/nvm">nvm</a>. Para instalar o nvm basta rodar o comando:</p><pre>curl -o- <a href="https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh">https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh</a> | bash</pre><p>Depois disso feche e abra de novo o terminal do WSL e o nvm estara instalado, para confirmar rode</p><pre>command -v nvm</pre><p>E se o output for <em>nvm </em>ele foi instalado com sucesso.</p><p>Instale o GIT</p><pre>apt-get install git</pre><p>Depois de instalar o GIT, rodar <em>nvm ls-remote</em> vai mostrar todas as opções de versões para o npm, escolha a mais recente (hoje é 10.16.0) ou a que o seu projeto usa:</p><pre>nvm install 10.16.0</pre><p>Rodar <em>node -version</em> vai confirmar que a versão escolhida foi instalada com sucesso.</p><h4>Enfim, o Angular</h4><p>Agora estamos prontos para instalar o Angular. Nada é melhor do que seguir o próprio <a href="https://angular.io/guide/setup-local">tutorial do Angular,</a> como fazemos a seguir.</p><p>Instale o <em>Angular cli</em> rodando</p><pre>npm install -g @angular/cli</pre><p>A rigor o Angular já está instalado e pronto para ser usado. Para testar podemos criar uma aplicação básica e ver se tudo funciona como esperado.</p><p>Use o cli para criar o app rodando o comando</p><pre>ng new my-app</pre><p>O <em>ng new</em> vai te pedir varias informações a respeito do seu app, basta aceitar o default apertando enter.</p><p>Para rodar a aplicação e ver tudo operando como deve, entre na pasta do app e peça para o Angular servir a aplicação</p><pre>cd my-app<br>ng serve -open</pre><p>Se tudo correu bem o <em>-open</em> vai fazer o seu navegador abrir uma página no <a href="http://localhost:4200/">http://localhost:4200</a> com a aplicação padrão do Angular aberta.</p><h4>VS Code Para Editar seu Código</h4><p>Meu editor favorito para o Windows é o <a href="https://code.visualstudio.com/">VS Code</a> e como você vai precisar de algum editor mesmo, aqui vai o passo a passo para a instalação.</p><p>1- Comece <a href="https://code.visualstudio.com/">baixando e instalando o VS Code</a> no próprio Windows. <strong>Importante, mantenha ativa a opção de adicionar o VS Code ao PATH</strong>.</p><p>2- Depois baixe e instale o pack de <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack">Remote Development</a></p><p>3- No WSL rode o seguinte comando para evitar problemas com CLRF/RF no finais das linhas</p><pre>git config — global core.autocrlf input</pre><p>Agora se você for na pasta de sua aplicação de teste do Angular e escrever</p><pre>code .</pre><p>ele vai abrir o VS Code com a pasta do app aberta e pronta para suas edições.</p><p><strong>Concluindo</strong></p><p>Espero que você tenha conseguido acompanhar até o fim esse tutorial, em caso de dúvidas deixe sua pergunta nos comentários ou me <a href="https://twitter.com/pedrofullstack">procura no Twitter</a>, prometo que respondo!</p><p>Abraço!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=817995e23d01" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[O que aprendi usando User Story Mapping]]></title>
            <link>https://medium.com/@pedrofullstack/o-que-aprendi-usando-user-story-mapping-2db73b6aeabb?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/2db73b6aeabb</guid>
            <category><![CDATA[ágil]]></category>
            <category><![CDATA[user-story-mapping]]></category>
            <category><![CDATA[user-stories]]></category>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[development]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Thu, 27 Jun 2019 16:07:17 GMT</pubDate>
            <atom:updated>2019-06-27T16:07:17.793Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4aiAll5VNxl59HYww0Xirw.jpeg" /><figcaption>Pessoas felizes usam post its</figcaption></figure><p>Recentemente o time em que eu trabalho foi incumbido de desenvolvo toda uma parte Novo para o sistema da empresa. Essa foi uma oportunidade muito massa de trabalhar em uma coisa do zero, envolvendo back, front, banco e serviços. A coisa ainda mais interessante que fizemos de diferente foi o user story mapping.</p><p>A maioria do povo que trabalha com desenvolvimento com certeza já ouviu falar de história do usuário, ou user Story, em inglês, mas o conceito se expande muito quando pensamos no processo de mapeamento da aplicação (ou feature) como um todo.</p><p>A ideia é a seguinte, quando queremos explicar alguma coisa para alguém, fica muito mais fácil da pessoa entender através de uma história. Então se falarmos sobre um sistema como uma sequência de acontecimentos podemos pensar em cada um desses acontecimentos como uma história separada.</p><p>Por exemplo, uma visão simplificada do Spotify nos dá o seguinte cenário, o sujeito entra no app, escolhe a música que quer ouvir e ela começa a tocar. Podemos quebrar isso em três partes:</p><ol><li>Entrar no app</li><li>Escolher a música</li><li>Ouvir a música</li></ol><p>Claro que o Spotify é bem mais complexo que isso, mas nosso exemplo fica só nessa parte.</p><p>Se fôssemos montar um mapa disso, colocaríamos em post its cada uma dessa etapas e as colamos na parede da esquerda para direita. Depois de concordar sobre a sequência das três, em baixo de cada uma podemos colocar mais detalhes, na primeira vamos ter que preencher um login e senha, etc.</p><p>No final do processo teríamos uma visão geral do comportamento do app. Em cima a histórias gerais e na segunda linha as etapas um pouco mais aprofundadas.</p><p>Nesse ponto podemos começar a pensar em caminhos alternativos, se eu não tenho cadastro, a música que eu gosto não está disponível, e outras possibilidades. Cada uma dessas alternativas precisa ir para o mapa, vamos colocando esses novos post its em baixo do “caminho feliz” que definimos no começo.</p><p>Por fim, vamos definir o que é mais importante. Traçando linhas horizontais que servirão de corte para o que será feito primeiro (não são ainda as sprints, mas uma indicação de prioridade). O resultado vai ser mais ou menos assim:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/792/1*87i0vxh4O_KgT0FNjp9Kvg.png" /><figcaption>Exemplo de user story map</figcaption></figure><h4>Pra que serve isso afinal?</h4><p>O primeiro motivo para o uso do user story mapping parece ser o de visualizar toda a aplicação, e ele ajuda muito nisso, mas o principal é a construção de consenso. Uma das coisas mais difíceis de se ter em um projeto é consenso a respeito do que está sendo construído, cada pessoa tem uma ideia de como vai ficar no fim.</p><p>Na hora que a gente pega um post It, cola na parede e começa a debater, a ideia que cada um tem do resultado vai encontrar a dos outros e aí elas vão se unir na solução final. Quando os caras inventaram as histórias de usuário foi justamente para gerar conversas dentro do time e aparecer esse consenso, por isso elas vão num espaço tão pequeno.</p><p>O mapa de história do usuário, vai levar o time a ter, ao mesmo tempo, uma visão do todo e do resultado esperado. Isso vai dar trabalho, mas o resultado compensa.</p><h4>O que vai numa história de usuário?</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/737/1*X63XYj_KBRt2ZiPC8ArnxQ.png" /><figcaption>Exemplo de história de usuário</figcaption></figure><p>As histórias de usuário têm uma estrutura clássica: Eu como &lt;pessoa que vai usar&gt; Quero &lt;o que quer fazer&gt; Para &lt;o objetivo&gt;</p><p>A ideia dessa estrutura é mostrar de maneira simples quem é o usuário final do que vai ser desenvolvido, o que precisa ser desenvolvido e qual o objetivo final de quem vai usar aquilo. Ela pode ser adaptada de diferentes formas, mas é importante que o foco no usuário se mantenha, porque no fim das contas é ele quem vai usar o software.</p><p>Problemas nessa estrutura aparecem quando pensamos em funcionalidades que atendem partes do sistema e não um usuário, ou quando a história serve um membro da equipe como um teste de carga ou algo do tipo.</p><p>No primeiro caso, basta pensar nas partes do sistema como usuários, você pode ter um banco de dados “usando” um de-para.</p><p>O segundo caso é mais complicado, porque ele vai realmente exigir uma quebra do script. Mas ainda podemos pensar em termos de quem, o que e para que.</p><p>Não esqueça de adicionar critérios de aceitação da tarefa. São eles que vão definir se a história esta entregue ou não.</p><h4>Como foi nossa experiência</h4><p>Para ser sincero tivemos duas mudanças no nosso processo. No mesmo Sprint em que fizemos o user story mapping para as novas features também paramos de definir quem faria as tarefas durante a planning, deixando para fazer isso durante as dailys.</p><p>O resultado foi excelente, o mapa ajudou a espalhar o conhecimento pela equipe. A necessidade de alguém mais sênior explicando as tarefas diminuiu. Realmente floresceu a auto organização do time.</p><p>Não sei se posso falar aqui, mas esse foi o primeiro Sprint desde que eu entrei no projeto em que fechamos todas as tarefas. E muito do tempo que economizamos foi justamente com explicações que já ficaram claras para todo mundo durante a construção do mapa de histórias do usuário. E tudo fica mais legal se consideramos que teve um feriado e um dia inteiro de mapping nessa sprint.</p><h4>Experimente que não vai se arrepender</h4><p>Vale muito a pena testar está ferramenta. Se seu time está dependendo de algumas pessoas que detém o conhecimento, se não tem um consenso sobre o que exatamente está sendo feito ou precisa otimizar a ordem de entregas o user story mapping ajuda muito.</p><p>Nós usamos para um novo desdobramento do sistema, mas isso pode ser usado para coisas pequenas, como uma feature, e grandes, como um app inteiro. Não tem desculpa para não usar!</p><p><strong><em>Se você já usou ou usa essa o User Story Mapping deixa tua experiência nos comentários, vamos conversar um pouco mais sobre isso.</em></strong></p><p><a href="http://twitter.com/pedrofullstack">Me segue no Twitter também</a>, eu posto mais coisas de Agile lá, quando não estou reclamando da vida.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2db73b6aeabb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Micro Serviços como opção para um ecommerce]]></title>
            <link>https://medium.com/@pedrofullstack/micro-servi%C3%A7os-como-op%C3%A7%C3%A3o-para-um-ecommerce-e6b9f58a43e4?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/e6b9f58a43e4</guid>
            <category><![CDATA[ecommerce-web-development]]></category>
            <category><![CDATA[ecommerce]]></category>
            <category><![CDATA[arquitetura-de-software]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[desenvolvimento]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Tue, 18 Sep 2018 20:10:35 GMT</pubDate>
            <atom:updated>2018-09-18T20:32:11.636Z</atom:updated>
            <content:encoded><![CDATA[<h3>Microsserviços como opção para um ecommerce</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XFS-bDPsBiz9VjVsgYScFw.jpeg" /><figcaption>fotinho obrigatoria</figcaption></figure><p>A maioria dos sites de ecommerce que conheço e em que trabalhei são construídos em cima de um arquitetura do tipo monolito. Isso significa que todo o código é construído em uma estrutura única com componentes interdependentes e interligados, é a arquitetura tradicional de frameworks como Laravel e WordPress.</p><p>Microsserviços, por outro lado é uma arquitetura de código que segue a ideia de ter as diferentes partes da aplicação funcionando como unidades independentes. Dando um passo adiante das arquiteturas modulares, aqui cada serviço pode funcionar como uma aplicação separada.</p><p>As duas opções são radicalmente diferentes, mas os micro serviços vem ganhando cada vez mais espaço junto a CTOs e gestores de produto. Isso se deve às vantagens de ter uma arquitetura que funciona com sistemas distribuídos, como escalabilidade e facilidade de colocar novos programadores no time.</p><h4>Porque usar Microsserviços</h4><p>É importante frisar que micro serviços não são uma tecnologia, mas um padrão de projeto. Nele cada serviço é uma unidade de lógica de negócios completamente independente, podendo inclusive ser implementada em uma linguagem diferente do resto do código. Todos os serviços são unidos por APIs versionadas e (esperasse) documentadas.</p><p>Como cada serviço é uma aplicação separada, muitos dos problemas enfrentados por ecommerces são resolvidos. Você pode, por exemplo, aumentar o número de cópias de um serviço que estão rodando para atender a demandas maiores em determinadas épocas. Outro exemplo é adicionar um novo membro à equipe de desenvolvimento, essa nova pessoa só precisa entender um pequeno serviço, e não todo o sistema, para começar a ser produtiva.</p><h4>Mas nem tudo são flores</h4><p>Microsserviços são como um iceberg, no topo temos os serviços bonitinhos funcionando como queremos, mas por baixo d’água existe uma infraestrutura robusta para manter tudo rodando. Coisas como, testes de integração, versionamento de código e API, autenticação, falhas na rede, logs, etc. precisam ser feitas para garantir que o sistema como um todo vai funcionar como esperado.</p><p>Por esse trabalho e custo adicionais que é preciso pensar bem se esta é a arquitetura mais indicada para o seu site. Veja que ecommerce pequenos podem ser muito bem atendidos por um monolito e conforme crescem migrar para microsserviços.</p><h4>É melhor ou não é?</h4><p>Lógico que eu não posso responder essa pergunta, cada caso é um caso e nenhum ecommerce é igual ao outro. Existem sites que se beneficiam muito dessa arquitetura (Amazon, por exemplo) já outros preferem manter seus monólitos.</p><p><strong>O que você acha que funciona melhor no seu caso? Qual sua experiência com cada um?</strong></p><p><em>Para mais conteúdo sobre arquitetura e desenvolvimento de software, </em><a href="http://twitter.com/pedrohmkt"><em>me segue no Twitter</em></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e6b9f58a43e4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cinco Dicas Para Crescer no Instagram]]></title>
            <link>https://medium.com/@pedrofullstack/cinco-dicas-para-crescer-no-instagram-e230960b0dc9?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/e230960b0dc9</guid>
            <category><![CDATA[dicas-de-marketing]]></category>
            <category><![CDATA[social-media]]></category>
            <category><![CDATA[dicas]]></category>
            <category><![CDATA[instagram]]></category>
            <category><![CDATA[marketing]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Tue, 05 Jun 2018 15:21:01 GMT</pubDate>
            <atom:updated>2018-06-05T15:21:01.079Z</atom:updated>
            <content:encoded><![CDATA[<p>O Instagram é um ótimo canal para conversar com seu público, a rede conta com 300 milhões de usuários diários e só tende a crescer. A questão é, o que você pode fazer para ser encontrado no meio de toda essa gente?</p><p>São diversas estratégias que levam as pessoas até você, aqui está um compilado de algumas. São cinco atitudes que você precisa tomar para começar a crescer no Instagram. Muito mais pode ser feito, mas fazer essas cinco já te coloca na vantagem.</p><h4>1. Transforme seu Perfil em Comercial</h4><p>Todo perfil no Instagram tem a opção de ser pessoal ou comercial. O perfil pessoal tem a vantagem de que as postagens tendem a ter um alcance maior, mas só isso. O perfil comercial, por outro lado, te da acesso a ferramentas de análise, permite colocar botões para contato e você pode impulsionar publicações para alcançar ainda mais pessoas.</p><p>O acesso aos dados da análise é crucial para montar sua estratégia. Ali você pode ver os melhores horários para postar, quais conteúdos tiveram melhor desempenho, o que o público mais gostou. A partir dessa informação você vai aprimorar o seu comportamento na rede, otimizando seu crescimento.</p><h4>2. Conhece o teu Público</h4><p>Isso serve para tudo, conhecer o público é chave para o sucesso. Quem é a pessoa que compra da sua marca? Quem consome seu conteúdo? Qual a idade deles? Quais são os interesses? Falam biscoito ou bolacha?</p><p>Quanto mais informação você tiver a respeito do seu público alvo melhor você vai conseguir engajar com ele. Não só nas redes sociais mas em todo o contato que a pessoa tem com a sua marca.</p><h4>3. Siga os seguidores dos teus concorrentes</h4><p>Uma experiência interessante é buscar pelos perfis da sua concorrência e entrar no perfil das pessoas que estão seguindo eles. Você pode seguir estas pessoas e interagir com elas para que elas eventualmente visitem o seu perfil e acabem te seguindo também.</p><p>É importante ter o cuidado de ter um perfil atrativo, porque quando as pessoas forem visitar o teu Instagram elas precisam se interessar pelo conteúdo.</p><p>Uma maneira comum de fazer isso é utilizando bots para automatizar o processo. Eu escrevi sobre isso <a href="https://pedrohenrique.net/como-funcionam-os-bots-do-instagram/">neste post</a> e explico os prós e contras dessa abordagem.</p><h4>4. Não se esqueça das hashtags!</h4><p>As hashtags do Instagram são uma das melhores maneiras de atrair novos seguidores. Uma boa seleção de hashtags ajuda seu conteúdo a se destacar e aparecer em buscas na rede.</p><p>Quanto ao número de hashtags, tente manter entre 5 e 10 por postagem. Muitas hashtags e o Instagram vai penalizar seu alcance por considerar spam e muito poucas vai limitar o teu alcance.</p><p>Que hashtags usar? Aqui, de novo, o principal é conhecer o seu público. Veja o que eles mais gostam, quem seguem, quais hashtags eles usam.</p><h4>5. Parcerias com Influencers</h4><p>Durante suas pesquisas de público você vai encontrar perfis que muitos dos seus clientes seguem. Fazer parcerias com esses perfis pode alavancar o seu sucesso no Instagram.</p><p>Comece por identificar perfis que tem grande abrangência entre as pessoas que você quer atingir. Siga esses perfis e comece a interagir com as publicações deles, se apresente no privado como marca para iniciar uma relação.</p><p>Você pode, por exemplo, pedir para que eles escolham um item que você vende e mandar para eles. Eles vão receber o item e fazer uma postagem a respeito, levando os seguidores deles a conhecer sua marca (lembre-se de compartilhar a postagem deles).</p><p>Outro ponto importante com o marketing de <em>influencers </em>é que a sua marca vai ficar associada com aquela pessoa. Por isso você tem que escolher com sabedoria com quem fazer a parceria.</p><h4>Conclusão</h4><p>Essas foram as cinco dicas para que você comece com o pé direito a crescer sua base de seguidores. O Instagram oferece um mundo grande de possibilidades para atingir o teu público alvo, mas é importante conhecer o público e ir atrás dele.</p><p>Uma dica bônus é seguir meu perfil no Instagram <a href="https://www.instagram.com/pedrohenriquemkt/">@pedrohenriquemkt</a></p><p><strong>Eu também escrevo sobre marketing digital </strong><a href="https://pedrohenrique.net/my-blog/"><strong>aqui</strong></a><strong> :D</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e230960b0dc9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Inevitabilidade dos ChatBots]]></title>
            <link>https://medium.com/pedro-henrique/a-inevitabilidade-dos-chatbots-24cc48ab1e75?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/24cc48ab1e75</guid>
            <category><![CDATA[futuro]]></category>
            <category><![CDATA[mercado]]></category>
            <category><![CDATA[chatbots]]></category>
            <category><![CDATA[ux]]></category>
            <category><![CDATA[bots]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Fri, 27 Apr 2018 18:56:00 GMT</pubDate>
            <atom:updated>2018-04-27T18:56:00.855Z</atom:updated>
            <content:encoded><![CDATA[<p>Estamos vivendo em tempos estranhos, os computadores estão em todos os lugares e é só questão de tempo até eles estarem no seu lugar. As interfaces que usamos para interagir com as máquinas estão mudando, passamos da manivela para o teclado e agora chegamos na voz. É essa transição para voz que vai fazer a mágica de transformar um computador em uma pessoa.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zsiBd0l_BUP2sjqtdIlp2g.jpeg" /><figcaption>Eles estão vindo!</figcaption></figure><p>Durante muito tempo as pessoas que se preocupavam com a automação da força de trabalho eram os trabalhadores manuais. É muito mais fácil imaginar uma máquina substituindo uma pessoa em uma linha de montagem do que um advogado, mas hoje temos algoritmos fazendo a análise de documentos de forma infinitamente mais eficiente que advogados.</p><h4>O que falta para os ChatBots fazerem mágica?</h4><p>Falar que a maioria das tarefas podem ser automatizadas já é trivial o que vai ser o pulo do gato é poder <strong>falar</strong> para o computador fazer essas tarefas. Imagine simplesmente pedir para o computador fazer coisas e ele fazer exatamente o que você quer. “Computador, envie um email para o fulano dizendo …”, pode ser algo comum em um futuro muito próximo.</p><p>Na verdade, a tecnologia para que isso aconteça já esta disponível o que falta é a visão de como fazer isso da melhor maneira. Por isso que começar a pensar em termos de conversas ao invés de apps é muito importante, o número de downloads de aplicativos vem caindo, mas o uso de ferramentas de chat só cresce (olha o WhatsApp).</p><blockquote>Combinar essas duas tendências é o passo que falta para termos bots trabalhando ao nosso lado da mesma maneira que Tony Stark trabalha com J.A.R.V.I.S.</blockquote><p>A mudança de paradigma é muito interessante, ao invés de pensarmos o que o usuário vai fazer e como o sistema vai responder precisamos pensar na história que o usuário vai experimentar. A interação através da fala pede um nível mais refinado de UX do que estamos acostumados, mas aproxima mais os participantes.</p><h4>Nosso colega o ChatBot</h4><p>Estão começando a aparecer em diversas frentes iniciativas de trazer assistentes robôs para o local de trabalho. A primeira vista parece só mais um passo no sentido de automatizar os processos, mas a diferença é que agora tudo acontece de forma assíncrona.</p><p>A pessoa não fica interagindo com o bot, ela da a ordem e vai fazer outra tarefa enquanto o robô faz o que foi pedido (<a href="https://pedrohenrique.net/como-funcionam-os-bots-do-instagram/">veja os bots de redes sociais</a>, por exemplo). Não estamos criando ferramentas para fazer o que já fazemos mais rápido, são ferramentas para fazer mais coisas ao mesmo tempo.</p><h4>Conclusão</h4><p>Ainda não chegamos no momento que o bot é capaz de substituir o ser humano por completo, somos os únicos capazes de fazer o “algo a mais”. Por mais avançada que esteja nossa tecnologia ela ainda se restringe ao que está programada para fazer e segundo alguns teóricos essa vai ser sempre uma restrição.</p><p>Se queremos nos manter trabalhando em um mundo cada vez mais dominado pelas máquinas precisamos aprender a colocar esse fator humano no que fazemos. Não basta desempenharmos nossas funções como robozinhos, temos que dar o próximo passo, enquanto o bot fica fazendo o trabalho chato e automatizável temos tempo de olhar para as pessoas ao nosso redor e estender a mão.</p><p><strong>O que você acha disso tudo? Comenta aí em baixo que nosso bot te responde (brincadeira, isso eu faço questão de fazer).</strong></p><p><a href="https://pedrohenrique.net/my-blog/">públicado primeiro no blog ;)</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=24cc48ab1e75" width="1" height="1" alt=""><hr><p><a href="https://medium.com/pedro-henrique/a-inevitabilidade-dos-chatbots-24cc48ab1e75">A Inevitabilidade dos ChatBots</a> was originally published in <a href="https://medium.com/pedro-henrique">Pedro Henrique</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Feito é Melhor que Perfeito]]></title>
            <link>https://medium.com/pedro-henrique/feito-%C3%A9-melhor-que-perfeito-4433be92cbe5?source=rss-fd9e7a69f5d1------2</link>
            <guid isPermaLink="false">https://medium.com/p/4433be92cbe5</guid>
            <category><![CDATA[marketing]]></category>
            <category><![CDATA[social-media-marketing]]></category>
            <category><![CDATA[empreendedorismo]]></category>
            <category><![CDATA[social-media]]></category>
            <category><![CDATA[motivacional]]></category>
            <dc:creator><![CDATA[Pedro Henrique]]></dc:creator>
            <pubDate>Wed, 07 Mar 2018 13:31:01 GMT</pubDate>
            <atom:updated>2018-03-07T13:31:01.175Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fehOWVshxIMk4A0HoRKE6Q.jpeg" /><figcaption>O negócio é alongar e começar a fazer</figcaption></figure><p>Outro dia eu estava conversando com um amigo no WhatsApp e ele me contava que queria começar a fazer lives no Facebook. Lives são uma maneira ótima de gerar engajamento e ter mais pessoas olhando teu conteúdo, tanto no Facebook quanto no Instagram.</p><p>Perguntei para ele o que estava faltando para começar e ele disse que estava se preparando para comprar uma GoPro por R$2.000,00. Minha resposta foi: “Tu tá bebendo!? Como tu vai pagar 2 mil em uma câmera para fazer lives que tu ainda nem sabe são vão dar resultados de verdade?”</p><p>O que ele queria era fazer uma live com “qualidade profissional”, atingir um padrão arbitrário que ele mesmo definiu com o equipamento que ele acha que precisa. O pior é que como ele não pode comprar a GoPro agora, o projeto vai ficar engavetado e talvez nunca saia do papel.</p><h4>Vai lá e Faz!</h4><p>Me incomoda muito esse tipo de pensamento porque muita gente esbarra nesses padrões de qualidade e acabam nunca fazendo nada. Não faz sentido ficar buscando a perfeição em um mundo em que as coisas duram no máximo 24h.</p><blockquote>Tu está fazendo um post não um filme de milhões de dólares!</blockquote><p>Imagina a quantidade de boas ideias que não são executadas porque as pessoas ficam esperando o momento ideal, a maneira ideal, que tudo esteja perfeito para colocar em prática.</p><p>Não estou dizendo que é tudo bem fazer de qualquer jeito. A qualidade do conteúdo ainda é importante.</p><p>Fazer uma live com o celular funciona perfeitamente, mas o que tu vai dizer nessa live tem que valer a pena. As pessoas não assistem porque foi bem filmado, mas porque tem conteúdo.</p><h4>O Conteúdo é rei</h4><p>O que vai ser dito ou mostrado tem que ser importante para tua audiência. É o conteúdo que vai manter as pessoas engajadas e consumindo o que tu produz.</p><p>Essa parece ser a parte mais difícil, pensar no que vai falar, mas na verdade não é. Tu ja conheces teu negócio, sabe como as coisas funcionam porque tu estás fazendo. Se tu é corretor de imóveis, por exemplo, já conhece o mercado e alguns imóveis, então pode falar com facilidade a respeito.</p><p>Mesmo quem está começando, essa é a oportunidade de estudar um pouco mais o mercado em que está iniciando e conhecer mais os detalhes para poder passar adiante. Inclusive mostrar que está começando e convidar a audiência para aprender junto pode ser uma coisa poderosa.</p><h4>Conclusão</h4><p>Tu não precisa ir atrás do equipamento perfeito para fazer teus vídeos, tirar fotos, etc… O que importa é ter conteúdo que valha a pena ser consumido. Pensa nos teus clientes e pensa no que eles gostariam de ouvir, depois vai lá e enrtega isso para eles.</p><p>Sempre mantém a tua própria voz, tem que ser autentico. Pensa na audiência, eles que precisam gostar. O resto é dale!</p><p>Meu amigo da história acabou desistindo da GoPro e comprou uma webcam full HD por R$100 para começar com as lives. Ele ainda não colocou em prática, mas com certeza está bem mais perto que antes.</p><p><a href="https://pedrohenrique.net/feito-e-melhor-que-perfeito/">Este artigo saiu primeiro em nosso site, dá uma conferida lá para ver outras públicações :)</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4433be92cbe5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/pedro-henrique/feito-%C3%A9-melhor-que-perfeito-4433be92cbe5">Feito é Melhor que Perfeito</a> was originally published in <a href="https://medium.com/pedro-henrique">Pedro Henrique</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>