Jekyll2019-11-22T14:21:42+00:00http://www.fabriciorissetto.com/feed.xmlFabrício RissettoDevaneios sobre desenvolvimento e arquitetura de softwareA base da pirâmide de testes é um bom compilador2019-07-19T02:58:56+00:002019-07-19T02:58:56+00:00http://www.fabriciorissetto.com/blog/base-piramide-testes<p><strong>Fail Early & Fail Fast</strong>: um princípio que está constantemente presente, de uma forma ou de outra, em praticamente todas áreas profissionais. Em desenvolvimento de software ele se manifesta constantemente mesmo que muitas vezes o abracemos sem conscientemente notar que está ali. Quando adotamos práticas de Agile (como alternativa ao Waterfall) estamos abraçando esse princípio. Quando construímos um MVP, quando aplicamos práticas de Lean UX, quando escrevemos testes de unidade, estamos seguindo, mesmo sem saber ou notar, o fundamental princípio de falhar cedo (e aprender com os erros - eu espero).</p>
<h2 id="a-famosa-pirâmide-de-testes">A famosa pirâmide de testes</h2>
<div style="text-align:center">
<img style="text-align: center;" src="http://www.fabriciorissetto.com/images/2019-07-11-base-piramide-testes/teste-piramide.png" />
</div>
<p>Essa pirâmide é amplamente conhecida e é uma boa abstração para transmitir a ideia de que: quanto mais tarde você testa determinada peça do seu software, maior será o custo da correção.</p>
<p>Mas e se eu te disser que quando escolhemos a linguagem de programação de um software, dependendo da escolha, podemos nos presentear com mais uma sólida camada sob a base dessa pirâmide? Uma camada que pode prevenir que alguns tipos de erros atinjam as de cima…</p>
<p>Não sou bom em desenhos, mas me permita tentar:</p>
<div style="text-align:center">
<img style="text-align: center;" src="http://www.fabriciorissetto.com/images/2019-07-11-base-piramide-testes/teste-piramide-compilador.png" />
</div>
<p>Isso mesmo, estou falando do COMPILADOR. Mais precisamente, dos compiladores das <a href="https://stackoverflow.com/q/1517582/890890">linguagens estaticamente tipadas</a>.</p>
<p>Ter um bom compilador é a maior vantagem de se utilizar uma linguagem estaticamente tipada. Entretanto, tenho impressão de desenvolvedores nem sempre enxergam esse valor. Sem fazer julgamento, apenas uma constatação baseada em minha observação empírica: isso normalmente ocorre com desenvolvedores de linguagens dinamicamente tipadas. Principalmente com aqueles que jamais trabalharam numa linguagem estática, ou que trabalharam em linguagens estáticas mais “idosas” e verbosas, como o Java.</p>
<h2 id="mais-compilador-menos-testes">Mais compilador, menos testes</h2>
<blockquote>
<p>NOTA: Nesse post estou usando o termo “compilador” como uma generalização para: validação <a href="https://johnidm.gitbooks.io/compiladores-para-humanos/content/part1/structure-of-a-compiler.html">léxica, sintática e semântica</a> do código em tempo de desenvolvimento (não runtime), seja ela feita por um compiler, transpiler ou qualquer outro termo similar que atenda a esse fim (em tempo de desenvolvimento!).</p>
</blockquote>
<p>Ter um bom compilador no seu arsenal de ferramentas faz com que você precise escrever menos testes. Vou além: ter uma boa <strong>linguagem de programação</strong>, aliada a um forte <strong>compilador</strong> (se possível bem integrados através de uma <strong>IDE ou editor de texto empoderado</strong>), faz você escrever MUITO menos testes e passar MUITO menos trabalho.</p>
<p>Para fazer um rápido exercício dessa sinergia do compilador com a linguagem de programação, basta dar uma olhada <a href="http://www.fabriciorissetto.com/blog/kotlin-introducao/">nesse post onde apresento algumas features de Kotlin</a>. Veja quantas facilidades a linguagem nos dá que nos livra de escrever código boilerplate. Lembre-se: quanto mais boilerplate você escreve, mais brechas para bugs você abre, mais código você tem para testar, mais código você tem para ser lido e mantido (por você e pelos seus colegas). Como já dizia Jeff Atwood: “<a href="https://blog.codinghorror.com/the-best-code-is-no-code-at-all/">The best code is no code at all</a>”.</p>
<p>Apesar disso, sabemos que por mais avançada e alto nível que a linguagem seja, em alguma esfera, nós vamos ter que codar. Acontece que quando programamos sem um compilador, por maior que seja o esforço e engajamento em testar a aplicação, é comum acabar descobrindo em tempo de execução erros básicos como: um typo do desenvolvedor ao chamar um método ou variável, ocasionando erros como <a href="https://stackoverflow.com/questions/21072355/undefined-method-nomethoderror-ruby">undefined method</a> e <a href="https://stackoverflow.com/questions/9671259/ruby-local-variable-is-undefined">undefined local variable</a>.</p>
<p>Já trabalhei em um ambiente com diversos desenvolvedores Ruby experientes mantendo uma mesma aplicação. E mesmo sendo a comunidade de Ruby, de longe, a mais forte e qualificada em testes e grande adepta do TDD (essa aplicação tinha mais de 8 mil testes de unidade), ainda assim lá acontecia em produção erros básicos como os que acabei de citar. Não adianta, <em>shit happens</em>! Na verdade, com ou sem um compilador. Meu ponto é que quando a linguagem e a ausência de um compilador permite esse tipo de coisa, <em>“shit happens mais ainda”</em>.</p>
<p>Sim, é difícil separar o compilador da linguagem. Pelo simples fato de que o design de um é impactado pelo outro. Se um código pode ou não gerar bugs é uma mistura entre a permissividade que a linguagem oferece aliado ao trabalho que o compilador faz durante sua interpretação e compilação. Por exemplo, Kotlin não permite que você passe <code class="language-plaintext highlighter-rouge">null</code> para uma variável a não ser que ela explicitamente, em sua definição, aceite receber <code class="language-plaintext highlighter-rouge">null</code>.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">nome</span> <span class="o">=</span> <span class="s">"foo"</span> <span class="c1">//OK, variável definida como String e inicializada com "foo"</span>
<span class="n">nome</span> <span class="o">=</span> <span class="s">"bar"</span> <span class="c1">//OK, valor sobrescrito para "bar"</span>
<span class="n">nome</span> <span class="o">=</span> <span class="kc">null</span> <span class="c1">//BAAAM! NÃO COMPILA</span>
</code></pre></div></div>
<p>Estamos falando basicamente da prevenção de bugs, não é mesmo? No exemplo acima, o compilador está nos ajudando a evitar um dos mais famosos de todos, o tal <code class="language-plaintext highlighter-rouge">Null Reference Exception</code>, também conhecido como <a href="http://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions">o erro de um Bilhão de Dólares</a>, dado uma estimativa (obviamente chute, e do próprio criador) do prejuízo que isso já deve ter causado em produção pras empresas ao longo dos anos.</p>
<p>Enfim, os exemplos são os mais variados, mas tenho certeza de que você entendeu a ideia. Quis trazer aqui uma provocação quanto aos benefícios de se utilizar o compilador como um dos pilares para a descoberta de falhas cedo, a cada linha escrita, a cada caracter.</p>
<p><strong>Um disclaimer pra finalizar</strong>: Deve ter ficado claro no texto, dado algumas citações à linguagens dinâmicas, que eu tenho forte preferência pelas estáticas. Isso é verdade. Tive em minha carreira a oportunidade de trabalhar e aprender bastante com ambos os estilos e quis deixar aqui, documentado, uma parte dos porquês de tal preferência. Pretendo dar seguimento e aprofundar mais na comparação dos estilos em outro post.</p>Bizarrices de números reais na JVM2018-09-17T02:58:56+00:002018-09-17T02:58:56+00:00http://www.fabriciorissetto.com/blog/bizarrices-bigdecimal<p>O propósito desse post é ser rápido, portanto não pretendo entrar em muitos detalhes teóricos por trás das características dos valores de ponto flutuante na JVM, pois é bem simples de achar em respostas como <a href="https://stackoverflow.com/a/1661313/890890">essa</a> no StackOverflow que dão um ótimo “deep dive” na explicação científica por trás de pontos flutuantes na representação binária em geral.</p>
<h3 id="e-lá-vamos-nós">E lá vamos nós</h3>
<p>Veja o resultado da operação abaixo:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span>
<span class="c1">//0.30000000000000004</span>
</code></pre></div></div>
<p>Isso é o comum na maioria das linguagens devido a incapacidade de representar <a href="http://cs.furman.edu/digitaldomain/more/ch6/dec_frac_to_bin.htm">alguns números decimais em binário</a>.</p>
<p>Em Java, ou melhor, no munto JVM (Kotlin, Scala, etc), é muito comum achar em <a href="https://stackoverflow.com/a/3413493/890890">respostas</a> do StackOverflow a recomendação de se utilizar o <code class="language-plaintext highlighter-rouge">BigDecimal</code>
para esse tipo de operação. No entanto ao passar um <code class="language-plaintext highlighter-rouge">double</code> como parâmetro para um BigDecimal você continua com o mesmo problema:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">0.1</span><span class="o">)</span> <span class="o">+</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">0.2</span><span class="o">)</span>
<span class="c1">//0.3000000000000000166533453693773481063544750213623046875</span>
</code></pre></div></div>
<p>Isso acontece porque o <code class="language-plaintext highlighter-rouge">double</code> já perdeu a precisão exata antes mesmo do <code class="language-plaintext highlighter-rouge">BigDecimal</code> ter sido construído. E aí as coisas começam a ficar estranhas pra quem nunca trabalhou com <code class="language-plaintext highlighter-rouge">BigDecimal</code>, pois logo você descobre que utilizando o construtor que recebe uma <code class="language-plaintext highlighter-rouge">String</code> tudo funciona como o esperado:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0.1"</span><span class="o">)</span> <span class="o">+</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0.2"</span><span class="o">)</span>
<span class="c1">//0.3</span>
</code></pre></div></div>
<p><strong><em>Aeeee! Finalmente. Agora o BigDecimal funciona com suas completas capacidades e com precisão exata (sem a treta dos pontos flutuantes reprentados em binário).</em></strong></p>
<p>Mas algumas outras coisas podem intrigar você logo em seguida:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0"</span><span class="o">)</span> <span class="n">shouldEqual</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"0.0"</span><span class="o">)</span>
<span class="c1">//false</span>
</code></pre></div></div>
<p>Opa, falso!? Vamos tirar as aspas de novo e vamos ver o que dá…</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span><span class="o">(</span><span class="mi">0</span><span class="o">)</span> <span class="o">==</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">0.0</span><span class="o">)</span>
<span class="c1">// true</span>
</code></pre></div></div>
<p>Agora foi. Eita…</p>
<h2 id="precisão-interna-do-bigdecimal">Precisão interna do BigDecimal</h2>
<p>Isso acontece porque o BigDecimal possui internamente uma informação de <strong>precisão</strong>. BigDecimals inciados com o construtor Double contendo os valores <code class="language-plaintext highlighter-rouge">0</code> e <code class="language-plaintext highlighter-rouge">0.0</code> possuem ambos unidade <strong>0</strong> e escala <strong>0</strong>. Já BigDecimals inciados com o cosntrutor String contendo os valores <code class="language-plaintext highlighter-rouge">"0"</code> e <code class="language-plaintext highlighter-rouge">"0.0"</code> possuem a unidade <strong>0</strong> mas o segundo possui escala <strong>1</strong>! Por isso a igualdade resulta em falso.</p>
<p>Se você utilizar, ao invés do <code class="language-plaintext highlighter-rouge">equals()</code>, o <code class="language-plaintext highlighter-rouge">compareTo()</code>, a comparação ignora a diferença de precisão.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0"</span><span class="o">).</span><span class="na">compareTo</span><span class="o">(</span><span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0.0"</span><span class="o">))</span>
<span class="c1">//0</span>
</code></pre></div></div>
<h2 id="a-importância-da-precisão-para-as-operações">A importância da precisão para as operações</h2>
<p>O cálculo <code class="language-plaintext highlighter-rouge">1 / 3</code> resulta em uma <a href="https://pt.wikipedia.org/wiki/D%C3%ADzima_peri%C3%B3dica">dízima periodica</a>. Com double o resultado é limitado pela sua precisão pré-definida:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mf">1.0</span> <span class="o">/</span> <span class="mf">3.0</span>
<span class="c1">//0.3333333333333333</span>
</code></pre></div></div>
<p>Já com BigDecimal, se você não definir a precisão que deseja, a expressão <code class="language-plaintext highlighter-rouge">1 / 3</code> dá erro (o que faz todo sentido):</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">1.0</span><span class="o">).</span><span class="na">divide</span><span class="o">(</span><span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">3.0</span><span class="o">))</span>
<span class="c1">//Error: ArithmeticException</span>
</code></pre></div></div>
<p>Portanto defina o tamanho da escala e o tipo de arredondamento:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">1.0</span><span class="o">).</span><span class="na">divide</span><span class="o">(</span><span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">3.0</span><span class="o">),</span> <span class="mi">80</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_EVEN</span><span class="o">))</span>
<span class="c1">//0.33333333333333333333333333333333333333333333333333333333333333333333333333333333</span>
</code></pre></div></div>
<p>Note que aqui utilizei o método <code class="language-plaintext highlighter-rouge">divide</code> quando no exemplo anterior utilizei o <strong>operador</strong> <code class="language-plaintext highlighter-rouge">+</code> para a soma (ao invés do método <code class="language-plaintext highlighter-rouge">add()</code>). No Java o BigDecimal não possui overload de operador pois lá não são permitidos overloads de tipos complexos (apenas primitivos). Portanto o <code class="language-plaintext highlighter-rouge">/</code> é uma extensão de Kotlin sobre o BigDecimal, que por baixo dos panos utiliza uma o método <code class="language-plaintext highlighter-rouge">divide</code> porém com alguns parâmetros padrões que podem causar efeitos inesperados. Exemplo:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1"</span><span class="o">)</span> <span class="o">/</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"3.0"</span><span class="o">)</span> <span class="c1">//Utiliza a escala 0 inferida através do primeiro BigDecimal</span>
<span class="c1">//0</span>
<span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1.0"</span><span class="o">)</span> <span class="o">/</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"3"</span><span class="o">)</span> <span class="c1">//Utiliza a escala 1 inferida através do primeiro BigDecimal</span>
<span class="c1">//0.3</span>
</code></pre></div></div>
<p>Portanto eu aconselho a sempre utilizar os <strong>métodos</strong> originais do BigDecimal ao invés dos <strong>operadores</strong> criados no Kotlin, para manter um padrão no código e fazer você pensar na quantidade de precisão que espera para seus cálculos.</p>
<blockquote>
<p>Por hoje foi isso, mas as bizarrices de cálculos com números reais na JVM me surpreendem a cada dia, talvez eu complemente esse post no futuro :)</p>
</blockquote>Kotlin: Introdução a algumas das principais features da linguagem2018-09-14T02:58:56+00:002018-09-14T02:58:56+00:00http://www.fabriciorissetto.com/blog/kotlin-introducao<p>Na <a href="https://www.creditas.com.br/">Creditas</a> estamos começando a utilizar Kotlin para modelar nossas aplicações que são <em>Core Business</em> e que exigem padrões de projeto mais complexos como o DDD. Até então estávamos utilizando majoritariamente Ruby para esse fim. Porém, dado a inúmeras insatisfações com a stack Ruby para esse caso de uso em específico, resovemos testar Kotlin e o resultado tem sido muito bom. Talvez no futuro eu faça algum post falando mais detalhes por trás das motivações dessa migração. Neste aqui pretendo focar em algumas simples features da linguagem que inicialmente nos chamaram atenção e nos fizeram avaliar com seriedade essa linguagem que hoje estamos utilizando.</p>
<p>Uma das coisas que tem vindo bem forte no movimento de linguagens funcionais é a <strong>imutabilidade</strong>. Kotlin, diferente de algumas linguagens como C#, Java, Ruby e Python, tem uma série de facilidades para lidar com imutabilidade de forma simples e sem verbosidade. Um exemplo são os <code class="language-plaintext highlighter-rouge">data classes</code>:</p>
<h2 id="criando-value-objectsdtos">Criando Value Objects/DTOs</h2>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">data</span> <span class="kd">class</span> <span class="nf">Endereco</span><span class="o">(</span><span class="n">val</span> <span class="nl">rua:</span> <span class="nc">String</span><span class="o">,</span> <span class="n">val</span> <span class="nl">numero:</span> <span class="nc">Int</span><span class="o">)</span>
</code></pre></div></div>
<p>Ao usar a keyword <code class="language-plaintext highlighter-rouge">data class</code> você ganha diversas coisas como, por exemplo, um construtor padrão, um lindo método <code class="language-plaintext highlighter-rouge">equals()</code> <strong>que compara os valores dos atributos ao invés da referência da instância</strong>, além de outros métodos como <code class="language-plaintext highlighter-rouge">copy()</code>, <code class="language-plaintext highlighter-rouge">toString()</code>.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">val</span> <span class="n">instancia1</span> <span class="o">=</span> <span class="nc">Endereco</span><span class="o">(</span><span class="s">"foo"</span><span class="o">,</span> <span class="mi">1</span><span class="o">)</span>
<span class="n">val</span> <span class="n">instancia2</span> <span class="o">=</span> <span class="nc">Endereco</span><span class="o">(</span><span class="s">"foo"</span><span class="o">,</span> <span class="mi">1</span><span class="o">)</span>
<span class="n">instancia1</span> <span class="o">==</span> <span class="n">instancia2</span>
<span class="c1">// true!</span>
</code></pre></div></div>
<p>São funcionalidades perfeitas para atender implementações de <a href="https://imasters.com.br/back-end/aprendendo-sobre-objetos-de-valor">Value Objects do DDD</a> e <a href="https://pt.wikipedia.org/wiki/Objeto_de_Transfer%C3%AAncia_de_Dados">DTOs</a>.</p>
<h2 id="criando-uma-classe">Criando uma classe</h2>
<p>Uma classe comum contendo um atributo <code class="language-plaintext highlighter-rouge">nome</code> imutável (val) e <code class="language-plaintext highlighter-rouge">endereco</code> mutável (var):</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nf">Pessoa</span><span class="o">(</span><span class="n">val</span> <span class="nl">nome:</span> <span class="nc">String</span><span class="o">,</span> <span class="kt">var</span> <span class="nl">endereco:</span> <span class="nc">Endereco</span><span class="o">)</span> <span class="o">{</span>
<span class="n">fun</span> <span class="nf">tamanhoDoNome</span><span class="o">()</span> <span class="o">{</span>
<span class="n">println</span><span class="o">(</span><span class="s">"Olá, meu nome tem ${nome.length} letras!"</span><span class="o">)</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="diferença-entre-val-e-var">Diferença entre <code class="language-plaintext highlighter-rouge">val</code> e <code class="language-plaintext highlighter-rouge">var</code></h2>
<p>Eles na verdade são açucares sintáticos para criação de métodos getters e setters. O <code class="language-plaintext highlighter-rouge">val</code> equivale a uma propriedade com apenas getter, o <code class="language-plaintext highlighter-rouge">var</code> equivale a uma propriedade com getter e setter.</p>
<p>A seguinte classe:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nf">Animal</span><span class="o">(</span><span class="kt">var</span> <span class="nl">nome:</span> <span class="nc">String</span><span class="o">)</span>
</code></pre></div></div>
<p>É equivalente a isso em Java:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Animal</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">nome</span>
<span class="kd">public</span> <span class="nf">Animal</span><span class="o">(</span><span class="nc">String</span> <span class="n">nome</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">nome</span> <span class="o">=</span> <span class="n">nome</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">getNome</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">nome</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setNome</span><span class="o">(</span><span class="n">string</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">nome</span> <span class="o">=</span> <span class="n">value</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Muito menos verboso, não é mesmo? Durante a migração de um dos nossos projetos de Ruby para Kotlin conseguimos diminuir quase pela metade a quantidade de linhas de código. Nunca se esqueça: quanto mais boilerplate você escreve, mais brechas para bugs você abre, mais código você tem para testar, mais código você tem para ser lido (por você e pelos seus colegas) e mantido. Complexidade, seja lá de qual forma se manifeste, <a href="https://www.elemarjr.com/pt/2018/02/complexidade-e-custo/">é custo</a>.</p>
<p><strong>Observação</strong>: Ambos <code class="language-plaintext highlighter-rouge">val</code> e <code class="language-plaintext highlighter-rouge">var</code> podem ser utilizados tanto em classes normais <code class="language-plaintext highlighter-rouge">class</code> quanto em classes de dados <code class="language-plaintext highlighter-rouge">data class</code>. As pessoas normalmente entendem o <code class="language-plaintext highlighter-rouge">data class</code> como sendo por si só uma classe imutável, quando na verdade o que garante que seus campos não sejam modificados é o uso de atributos do tipo <code class="language-plaintext highlighter-rouge">val</code>. O <code class="language-plaintext highlighter-rouge">data class</code> por si só apenas facilita a criação do construtor, método <code class="language-plaintext highlighter-rouge">equals()</code> e etc (como citado anteriormente).</p>
<h2 id="fechado-por-padrão">Fechado por padrão</h2>
<p>Note o <code class="language-plaintext highlighter-rouge">final</code> na tradução para Java no código anterior. Isso mesmo, em Kotlin todas as classes são seladas por padrão (<strong><em>“Design and document for inheritance or else prohibit it”</em></strong>). Caso vocẽ queria estender uma classe você terá que marcá-la como <code class="language-plaintext highlighter-rouge">open</code>. Gosto desse comportamento pois se formos analisar em nossos projetos a esmagadora maioria das classes não possuem herança e não foram projetadas para isso.</p>
<h2 id="interoperabilidade">Interoperabilidade</h2>
<p>Outra coisa legal, em relação a interoperabilidade, é que se você consumir em Java um arquivo <code class="language-plaintext highlighter-rouge">.jar</code> que foi gerado a partir de Kotlin, você vai poder chamar os métodos setters e getters normalmente sem perceber nada de diferente do que está acostumado.</p>
<h2 id="variáveis-locais-imutáveis">Variáveis locais imutáveis</h2>
<p>Não apenas um açucar sintático para criação dos getters, setters e parâmetros de construtor, o <code class="language-plaintext highlighter-rouge">val</code> é uma keyworkd que também pode ser utilizada no escopo de funções para definir “variáveis” imutáveis (que nesse caso não deveriam ser chamadas de variáveis, já que não variam, anyway… é assim que a propria <a href="https://kotlinlang.org/docs/reference/basic-syntax.html#using-type-checks-and-automatic-casts">documentação</a> chama):</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">val</span> <span class="n">animal</span> <span class="o">=</span> <span class="nc">Animal</span><span class="o">(</span><span class="s">"Scooby"</span><span class="o">)</span>
<span class="n">animal</span> <span class="o">=</span> <span class="nc">Animal</span><span class="o">(</span><span class="s">"Marley"</span><span class="o">)</span> <span class="c1">//Error: Val cannot be reassigned!</span>
</code></pre></div></div>
<p>Das linguagens que citei anteriormente C#, Ruby e Python simplesmente não possuem essa feature (possuem apenas para tipos primitivos, através do uso de constantes hardcoded). Java possui através da junção das keyworkds <code class="language-plaintext highlighter-rouge">final</code> e <code class="language-plaintext highlighter-rouge">var</code>, exemplo: <code class="language-plaintext highlighter-rouge">final var animal = new Animal("Scooby")</code>.</p>
<p><strong>Observação 2</strong>: Na verdade o <code class="language-plaintext highlighter-rouge">val</code> não garante a imutabilidade de fato. [MIND BLOW] O <code class="language-plaintext highlighter-rouge">val</code> apenas garante que aquela variável vai ser <em>atribuída uma única vez</em>. Ou seja, a instância para qual aquela variável está apontando pode sofrer mudanças internas e isso está além do escopo do val.</p>
<p>Por exemplo, imaginando que a classe <code class="language-plaintext highlighter-rouge">Animal</code> tenha um método que altera estado do objeto, adicionando uma coleira no animal:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">val</span> <span class="n">animal</span> <span class="o">=</span> <span class="nc">Animal</span><span class="o">(</span><span class="s">"Scooby"</span><span class="o">)</span>
<span class="n">animal</span><span class="o">.</span><span class="na">adicionarColeira</span><span class="o">(</span><span class="n">coleira</span><span class="o">)</span>
<span class="c1">//A instância do objeto foi modificada, porém a variável não foi reatribuida, então Sucesso!</span>
</code></pre></div></div>
<h2 id="null-safety">Null safety</h2>
<p>A proteçao contra nulos é a feature que eu mais gosto em Kotlin e não está presente em nenhuma das linguagens citadas anteriormente.</p>
<blockquote>
<p>O sistema de tipos de Kotlin foi desenhado visando eliminar o perigo de exceções de <code class="language-plaintext highlighter-rouge">NullReference</code> no código, também conhecido como o <a href="http://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions">Erro de um Bilhão de Dólares</a>.</p>
</blockquote>
<p>Em Kotlin os tipos nulos e não nulos são tratados como coisas distintas. O default é ser <strong>não nulo</strong>. Caso você queira que seja nulo você precisa dizer isso explicitamente, e o compilador vai te <strong>OBRIGAR</strong> a tratar essa variável em todo lugar. Isso acaba por desencorajar o uso de tipos nulos e nos obriga a refletir onde eles realmente são necessários, o que é ótimo.</p>
<p>Por exemplo, se no código anterior alterarmos o atributo <code class="language-plaintext highlighter-rouge">nome</code> para ser nullable, o seguinte código <strong>não compila</strong>:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nf">Pessoa</span><span class="o">(</span><span class="n">val</span> <span class="nl">nome:</span> <span class="nc">String</span><span class="o">?,</span> <span class="kt">var</span> <span class="nl">endereco:</span> <span class="nc">Endereco</span><span class="o">)</span> <span class="o">{</span>
<span class="n">fun</span> <span class="nf">tamanhoDoNome</span><span class="o">()</span> <span class="o">{</span>
<span class="n">println</span><span class="o">(</span><span class="s">"Olá, meu nome tem ${nome.length} letras!"</span><span class="o">)</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>É preciso fazer o tratamento da possibilidade de null reference no trecho <code class="language-plaintext highlighter-rouge">${nome.lenght}</code>! Uma das formas de tratar isso seria utilizando o operador <code class="language-plaintext highlighter-rouge">?</code>, também conhecido como safe call operator, exemplo:<code class="language-plaintext highlighter-rouge">${nome?.length}</code>. Entretanto nem sempre é necessário, pois o compilador é inteligente e consegue identificar se você já tratou a variável em determinado escopo, veja o exemplo abaixo:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="o">(</span><span class="n">nome</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// Aqui dentro a variável nome é automaticamente convertida para 'não nula'</span>
<span class="c1">// Portanto não é necessário tratar o null reference, o compilador sabe que não vai acontecer!</span>
<span class="n">println</span><span class="o">(</span><span class="s">"Olá, meu nome tem ${nome.length} letras!"</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div></div>
<p>O nome dessa feature é <strong>smart cast</strong> e não serve apenas para tipos nullables.</p>
<h2 id="smart-cast">Smart Cast</h2>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fun</span> <span class="nf">funcaoQualquer</span><span class="o">(</span><span class="nl">x:</span> <span class="nc">Any</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">x</span> <span class="n">is</span> <span class="nc">String</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// x automaticamente convertido para String nesse escopo!</span>
<span class="n">print</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="na">length</span><span class="o">)</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>E funciona com o pattern matching do <code class="language-plaintext highlighter-rouge">when</code> também:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">when</span> <span class="o">(</span><span class="n">x</span><span class="o">)</span> <span class="o">{</span>
<span class="n">is</span> <span class="nc">Int</span> <span class="o">-></span> <span class="n">print</span><span class="o">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="o">)</span>
<span class="n">is</span> <span class="nc">String</span> <span class="o">-></span> <span class="n">print</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="na">length</span> <span class="o">+</span> <span class="mi">1</span><span class="o">)</span>
<span class="n">is</span> <span class="nc">IntArray</span> <span class="o">-></span> <span class="n">print</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="na">sum</span><span class="o">())</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="lidando-com-coleções">Lidando com coleções</h2>
<p>Esse <a href="https://medium.freecodecamp.org/my-favorite-examples-of-functional-programming-in-kotlin-e69217b39112">post</a> mostra ótimos exemplos ao se trabalhar com coleções em Kotlin. Vou reproduzir um bem simples aqui:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nf">Student</span><span class="o">(</span>
<span class="n">val</span> <span class="nl">name:</span> <span class="nc">String</span><span class="o">,</span>
<span class="n">val</span> <span class="nl">surname:</span> <span class="nc">String</span><span class="o">,</span>
<span class="n">val</span> <span class="nl">passing:</span> <span class="nc">Boolean</span><span class="o">,</span>
<span class="n">val</span> <span class="nl">averageGrade:</span> <span class="nc">Double</span>
<span class="o">)</span>
</code></pre></div></div>
<p>Considerando uma lista que contem vários estudantes (classe definida acima), é possível fazer operações nessa lista utilizando as funções da standard library do Kotlin:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">students</span><span class="o">.</span><span class="na">filter</span> <span class="o">{</span> <span class="n">it</span><span class="o">.</span><span class="na">passing</span> <span class="o">&&</span> <span class="n">it</span><span class="o">.</span><span class="na">averageGrade</span> <span class="o">></span> <span class="mf">4.0</span> <span class="o">}</span>
<span class="o">.</span><span class="na">sortedBy</span> <span class="o">{</span> <span class="n">it</span><span class="o">.</span><span class="na">averageGrade</span> <span class="o">}</span>
<span class="o">.</span><span class="na">take</span><span class="o">(</span><span class="mi">10</span><span class="o">)</span>
<span class="o">.</span><span class="na">sortedWith</span><span class="o">(</span><span class="n">compareBy</span><span class="o">({</span> <span class="n">it</span><span class="o">.</span><span class="na">surname</span> <span class="o">},</span> <span class="o">{</span> <span class="n">it</span><span class="o">.</span><span class="na">name</span> <span class="o">}))</span>
</code></pre></div></div>
<p>O código é auto explicativo pra maioria das pessoas que vem de outras linguagens, já que quase todas dão suporte pra esses tipos de operações. C# dá suporte pra isso há 10 anos, Java introduziu as Streams no Java 8 há 4 anos (porém com uma sintaxe muito mais suja do que o exemplo acima), Ruby, Python, Javascript e praticamente todas as linguagens mainstreams de mercado dão suporte, umas de forma mais clean e completa do que outras, mas todas possuem suporte em algum nível.</p>
<h2 id="monads-e-outras-abstrações-funcionais">Monads e outras abstrações funcionais</h2>
<p>Kotlin não possui na sua standard library um grande acervo para abstrações e estruturas de dados comuns em linguagens funcionais. Entretanto, é possível utilizar esse tipo de feature com o auxílio de libs de extensão como o <a href="https://arrow-kt.io/">Arrow</a>. Esse tipo de lib é bem comum mesmo em linguagens que possuem certo suporte para estruturas de dados funcionais. Scala, por exemplo, apesar de possuir algumas estruturas já implementadas na sua standard library, possui libs fortes que complementam essas funcionalidades como a <a href="https://github.com/scalaz/scalaz">Scalaz</a> e <a href="https://github.com/typelevel/cats">ScalaCats</a>.</p>
<h2 id="outras-features-não-mencionadas">Outras features não mencionadas</h2>
<p>Nesse post citei apenas algumas features para não estender tanto, mas tem muito mais coisas interessantes do que mostrei aqui. Aqui vai mais algumas:</p>
<ul>
<li>Funções soltas em nível de package (fora de classes)</li>
<li>Tipos de dados algébricos</li>
<li>Pattern matching <strong>exaustivos</strong> com <code class="language-plaintext highlighter-rouge">when</code></li>
<li>Ótimo suporte para criação de <a href="https://kotlinlang.org/docs/reference/type-safe-builders.html#a-type-safe-builder-example">DSLs</a> poderosas</li>
<li>Delegated properties</li>
<li>Extension functions</li>
</ul>
<p>A <a href="http://kotlinlang.org/docs/reference/">documentação oficial da linguagem</a> é muito boa e considero um ótimo começo de estudo pra quem tiver interesse em se aprofundar mais!</p>FP vs OOP2018-09-06T02:58:56+00:002018-09-06T02:58:56+00:00http://www.fabriciorissetto.com/blog/fp-vs-oop<p>Programação funcional está finalmente chegando ao “mainstream” dos desenvolvedores, já não é mais algo hipster. Se você está começando a se interessar por funcional é provável que já tenha recebido indicação para estudar <strong>Haskell</strong>, <em>aquela linguagem na qual você provavelmente não vai conseguir um trabalho</em>.</p>
<div style="text-align:center">
<img style="text-align: center;" src="http://www.fabriciorissetto.com/images/2018-09-06-fp-vs-oop/unemployed.png" />
</div>
<p><strong>Haskell</strong> é uma linguagem puramente funcional e por isso normalmente se indica ela para aprendizado do paradigma. Acho que faz todo sentido aprender um novo paradigma numa linguagem que não te dê espaço para fugir dele. Para programar em Haskell você é obrigado a pensar “funcionalmente”. Isso é uma escolha da linguagem. Haskell se sai bem como uma linguagem puramente funcional e não tem um grande espaço no mercado corporativo justamente por não ser <em>“general purpose”</em> como as linguagens mainstreams da atualidade, que estão absorvendo features de programação funcional, inspiradas em linguagens como Haskell.</p>
<p><strong>Smalltalk</strong> teve um papel parecido na história. É uma linguagem puramente orientada à objetos e foi a grande responsável por popularizar o paradigma, que posteriormente foi incorporado por outras linguagens que até então eram basicamente imperativas.</p>
<p>Em resumo, o que a curta história da programação nos mostra é que as linguagens multiparadigmas (funcional, imperativo, orientado à objetos) possuem maior escala de adoção e longevidade no mercado do que aquelas que são “puristas” (como Haskell e Smalltalk). Portanto, quando estamos falando de uma linguagem “functional-first” (ao invés de “functional only”) geralmente estamos falando de algo que é multiparadigma, ou seja, na prática estamos falando de algo não binário e sim de uma espécie de “slider” do quão OOP ou FP a linguagem é:</p>
<div style="text-align:center">
<img style="text-align: center;" src="http://www.fabriciorissetto.com/images/2018-09-06-fp-vs-oop/fp-oop-slider.png" />
</div>
<p>C#, por exemplo, é uma linguagem que possui muitos aspectos de programação funcional mas que está mais voltada para a esquerda nesse slider (se movendo mais pra direita a cada release). Já F# está claramente mais para a direita e por isso é considerada uma linguagem <em>functional-first</em>. Entretanto, ainda assim é possível escrever um código orientado à objetos conciso e legível em F#.</p>
<blockquote>
<p>Meu palpite para F# não ser tão popular mesmo entre os desenvolvedores .NET se dá ao fato de C# ser uma linguagem razoavelmente boa e que segue em rápido avanço. Olhando pro lado da stack JVM, acredito que um fator que influencou a popularização e criação de diversas linguagens alternativas seja a inconformação às restrições do Java, que por ser uma linguagem com mais de 20 anos de mercado (e que até então mantia retrocompatibilidade com as versões anteriores) acabou por ter uma evolução lenta em comparação as linguagens mais recentes.</p>
</blockquote>
<p>Esses são os meus 2 centavos sobre o assunto. Ultimamente tenho trabalhado com Kotlin, que é uma linguagem híbrida muito familiar para programadores que vem de linguagens tradicionais como Java, C# e até mesmo Ruby (apensar de ser uma linguagem dinâmica, o que por si só é outro universo). É uma linguagem bem moderna para se utilizar em códigos orientados à objetos e também atende bem ao approach funcional. Tenho utilizado diversas features de programação funcional em Kotlin, através de sua standard library e também com a ajuda de libs de extensão como o <a href="https://arrow-kt.io">Arrow</a>. Logo terão posts aqui no blog falando mais sobre esses assuntos…</p>Microservices (parte 2): Dificuldades2018-05-10T02:58:56+00:002018-05-10T02:58:56+00:00http://www.fabriciorissetto.com/blog/microservices-parte-2<p><img src="http://www.fabriciorissetto.com/images/2018-02-13-microservices-parte-2/blue-red-pills.jpg" alt="take your pills" /></p>
<p>Toda decisão arquitetural possui tradeoffs e com microserviços não é diferente. Sair do paradigma de uma arquitetura SOA voltada a serviços “encorpados” ou até mesmo migrar de uma estrutura monolítica para microserviços é um caminho complexo e cheio de desafios. Ao mesmo tempo que aconselho desenvolvedores a seguirem esse caminho em passos curtos, saliento que é exigido uma preparação não trivial que implica em investimento da empresa na maturidade de sua arquitetura e também de suas equipes técnicas.</p>
<p>Nesse post listo algumas das dificuldades mais comuns que vejo times enfrentarem ao optar pela abordagem de microserviços e também alguns pontos de atenção. Vamos lá.</p>
<h1 id="devops">DevOps</h1>
<p>Ter uma alta granularidade de microserviços heterogêneos numa mesma arquitetura traz diversos desafios não funcionais, tais como logs, segurança, monitoramento, conversão de protocolos (REST/SOAP). Todos esses requisitos normalmente vinham juntos no pacotão do ESB na arquitetura SOA clássica, mas dado os pontos negativos da abordagem (detalhados nos posts anteriores) talvez você esteja querendo evitá-los. Entretanto, não ter esse tipo de ferramenta central faz com que tenhamos que nos preocupar com todo esse tooling de forma descentralizada. Isso vem com um custo, e ele não é barato.</p>
<h4 id="monitoramento-e-logs">Monitoramento e logs</h4>
<p>Já pensou em como documentar seus microserviços?</p>
<ul>
<li>Quantos existem?</li>
<li>Onde eles estão?</li>
<li>Qual a topologia de comunicação entre eles?</li>
</ul>
<p>E os logs…</p>
<ul>
<li>Quantas requests por hora no serviço X?</li>
<li>Quantos erros no serviço Y?</li>
<li>Os logs estão centralizados num lugar só?</li>
<li>Eles são padronizados e fáceis de entender?</li>
</ul>
<p>Resolver esses problemas em uma arquitetura monolítica normalmente é simples. Existem diversas ferramentas de APM que você acopla na sua aplicação e que num passe de mágica disponibilizam esse tipo de visão. Algumas delas: <a href="https://www.appdynamics.com/">AppDynamics</a>, <a href="https://newrelic.com/">New Relic</a>, <a href="https://www.dynatrace.com/">DynaTrace</a>, <a href="https://www.datadoghq.com">Data Dog</a>.</p>
<p>O problema é que muitas dessas ferramentas, aos menos as melhores, são pagas e possuem planos que não são nada atrativos para quem possui um grande espectro de aplicações e serviços (acredito que isso irá mudar). Por esse e outros motivos muitas equipes utilizam libs descentralizadas em conjunto com algumas ferramentas para prover esse tipo de visão. Algumas dessas ferramentas: <a href="http://graphite.readthedocs.org/en/latest/">Graphite</a>, <a href="https://github.com/logstash/logstash-logback-encoder">Logstash</a>, <a href="https://www.elastic.co/guide/en/kibana/current/xpack-monitoring.html">Kibana</a>, <a href="https://grafana.com">Grafana</a>, <a href="https://prometheus.io/">Prometheus</a>, <a href="https://zipkin.io/">Zipkin</a>.</p>
<p>Quando utilizando essas ferramentas temos o desafio de como nos integrar com elas. Seria diretamente no código? Algumas delas requerem isso e o que muitas empresas fazem é criar uma “lib interna” ou um “template de arquitetura de microserviço” no qual já tenha esse tipo de coisa configurada. O problema desse approach é que “mudar” coisas nessa lib ou nesse template requer mudanças em microserviços que já existem. Além do mais, ao criar isso normalmente as empresas acabam se amarrando em uma stack de tecnologia “X”, fazendo com que (ou ao menos encorajando) todos os novos microserviços sigam aquele template que já foi criado.</p>
<p>Um approach que tende a facilitar nossa vida nesse quesito é o conceito de <strong>Service Mash</strong> no qual o <a href="https://istio.io/">Istio</a> implementa. O Istio é um projeto recente criado pela Google em parceria com a IBM e a Lyft e que parece ser muito promissor. Com ele não é necessário nenhuma modificação no código da sua aplicação e nem mesmo no container no qual ela está hospedado. Além do Istio existem outras iniciativas parecidas voltadas a container, como o <a href="https://linkerd.io/">Linkerd</a>.</p>
<h4 id="automação-de-infraestrutura">Automação de infraestrutura</h4>
<p>Suas ferramentas de integração e deploy contínuo devem ser preparadas para essa maior gama de aplicações/serviços. Não só preparadas para suportar mas também prover a adição de novas aplicações com facilidade. Se a configuração de sua infraestrutura automatizada é muito “manual”, isso será um slowdown na criação de novos microserviços e a longo prazo a soma desse setup todo pode ser demasiado custoso.</p>
<p>Além da integração contínua, não se esqueça que o setup do ambiente de desenvolvimento também deve ser ágil. Porque configurar um monolito na máquina de cada desenvolvedor pode até não ser tão custoso. Mas configurar múltiplas aplicações na qual o time depende para desenvolver e testar uma funcionalidade não é nada divertido, muito menos barato. Containers em conjunto com ferramentas como o <a href="https://github.com/docker/swarm">Docker Swarm</a> ou <a href="https://docs.docker.com/compose/">Docker Compose</a> ajudam muito nesse quesito.</p>
<h4 id="segurança-e-autenticação">Segurança e autenticação</h4>
<p>Um monolito normalmente sabe se autenticar sozinho, ou seja, a autenticação está lá, foi construída nele e é apenas ele quem a utiliza. Porém, se você começa a migrar para uma estrutura de microserviços é fortemente recomendado que você construa um serviço especialista nisso (normalmente autenticação + autorização) e que esse serviço seja bem resiliente, pois diversas outras aplicações vão depender dele.</p>
<p>Outra dica válida aqui é: não construa isso do zero! Utilize algum framework de mercado que possua uma forte comunidade em volta, existem vários desse tipo que são open source e gratuítos como o <a href="http://identityserver.io/">Identity Server</a>, por exemplo. Não reinvente a roda, principalmente quando envolve segurança.</p>
<h4 id="service-registry-e-service-discovery">Service registry e service discovery</h4>
<p>Service Registry é uma espécie de database que contém informações sobre a localidade dos serviços na rede, onde toda vez que um serviço sobe, ele ativamente (ou de maneira dinâmcia) informa o servicy registry. Com isso, quando um serviço <code class="language-plaintext highlighter-rouge">A</code> quer chamar um serviço <code class="language-plaintext highlighter-rouge">B</code> ele não precisa saber diretamente seu IP ou DNS exato. Ele pode fazer o “discovery” do endereço de <code class="language-plaintext highlighter-rouge">B</code> através de uma query no service registry.</p>
<p>Com isso você adquire diversos benefícios: O endereço físico (e até mesmo DNS) do seu serviço pode variar sem afetar o código de quem depende dele. Você também ganha um healthcheck dos seus serviços, pois uma vez desconectados do service registry você saberá e terá o log disso, além de que os serviços dependentes também podem ser informados. Outro benefício é a facilidade de balanceamento de carga, já que o service registry pode assumir essa role, utilizando uma estratégia de, por exemplo, Round Robin pra escolher qual instância do serviço <code class="language-plaintext highlighter-rouge">B</code> (contando que existam várias) ele irá disponibilizar para o solicitante.</p>
<p>Alguns exemplos desse tipo de ferramenta são: <a href="https://consul.io/">Consul</a>, <a href="https://github.com/coreos/etcd">etcd</a>, <a href="http://zookeeper.apache.org/">Zookeeper</a> e <a href="https://github.com/Netflix/eureka">Eureka</a>. Além disso, há outras formas de se resolver esse problema com: load palancers, reverse proxy e com soluções nativas de nuvem. Esse <a href="https://docs.aws.amazon.com/aws-technical-content/latest/microservices-on-aws/service-discovery.html">link</a> da AWS mostra diversas abordagens que você pode seguir utilizando serviços da AWS e no final ainda indica algumas soluções third party como os citados acima (Consul, Eureka, etc).</p>
<h1 id="alguns-outros-pontos-de-atenção">Alguns outros pontos de atenção</h1>
<h2 id="síncrono-vs-assíncrono">Síncrono vs Assíncrono</h2>
<p>Tome MUITO cuidado com chamadas síncronas entre serviços, elas não escalam. Prefira a abordagem <a href="https://www.reactivemanifesto.org/pt-BR">reativa</a>. Quanto mais assíncrona e reativa sua arquitetura mais dinâmica e escalável ela é. Eu sou um grande fã da abordagem “Event Driven”, que aplicada a microserviços significa a comunicação assíncrona entre eles utilizando eventos. Nessa abordagem, além da facilidade de escalabilidade, é menos doloroso e arriscado modelar incertezas do domínio como, dependência entre <a href="http://www.fabriciorissetto.com/blog/ddd-bounded-context/">bounded contexts</a> e em relação a ordem de processo/fluxo desses contextos. Ferramentas como RabbitMQ, Apache Kafka ou serviços gerenciados como Amazon SQS/SNS são tecnologias muito utilizadas para realizar essa comunicação assíncrona entre serviços utilizando eventos como forma de mensagem.</p>
<h2 id="consistência-eventual">Consistência Eventual</h2>
<p>Ao utilizar uma abordagem de comunicação assíncrona nos serviços você passa a ter que tratar do que é chamado de “consistência eventual”. Em um monolito você pode fazer uma série de alterações e encapsular tudo dentro de uma transaction para garantir a consistência, afinal, tudo está no mesmo banco de dados e no mesmo processo. Com microserviços isso geralmente não é possível, apesar de que existir padrões como o <a href="https://en.wikipedia.org/wiki/WS-Atomic_Transaction">WS Atomic Transaction</a> que possibilita criar transações ACID em microserviços, implementar isso não é trivial. Sendo assim, temos que tratar a consistência de outras maneiras, como <a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/compensating-transaction">compensating transactions</a>. Esse tipo de abordagem impacta não só a maneira como você escreve suas aplicações mas também a interação dela com os usuários.</p>
<h2 id="versionamento-de-api">Versionamento de API</h2>
<p>Fica dificil evoluir os serviços sem um versionamento de API. Um bom versionamento de API permite uma maior liberdade de evolução dos serviços e diminui as dores do acoplamento. Apesar de eu não ser um grande fã, uma abordagem que vem ganhando espaço para desacoplar APIs de seus consumidores é o uso do padrão HATEOAS implementado por ferramentas como <a href="http://stateless.co/hal_specification.html">HAL</a>, <a href="https://github.com/kevinswiber/siren">Siren</a> e <a href="http://jsonapi.org/">JSON API</a>. Caso sua API tenha diversos consumidores, que se interessam em diferentes dados da sua aplicação e que se beneficiariam em poder compor suas queries, o <a href="https://graphql.org/">GrapQL</a> pode ser uma boa opção também.</p>
<h1 id="monolito-não-é-ruim">Monolito não é ruim</h1>
<p>Por último, mas não menos importante, a dica que quero dar é: monolítico (ou monolito) nem sempre é ruim, apesar da conotação negativa no senso comum do termo. O Martin Fowler tem um ótimo post falando da estratégia <a href="https://martinfowler.com/bliki/MonolithFirst.html">“Monilith First”</a>, no qual ele cita que os exemplos de sucesso de microservices na experiência dele começaram por monolitos antes de evoluirem para microserviços.</p>
<blockquote>
<p>Any refactoring of functionality between services is much harder than it is in a monolith. But even experienced architects working in familiar domains have great difficulty getting boundaries right at the beginning. By building a monolith first, you can figure out what the right boundaries are, before a microservices design brushes a layer of treacle over them. It also gives you time to develop the Microservice Prerequisites you need for finer-grained services.</p>
</blockquote>
<p>Isso está fortemente atrelado ao conceito de <a href="www.fabriciorissetto.com/blog/ddd-bounded-context/">bounded contexts</a> aplicado a microserviços. Você sabe exatamente quais são as boundaries e responsabilidades do microservice que você está criando? Não ter isso bem definido é um risco. E esse risco é menor quando você está trabalhando dentro de um monolito (quando construído com design desacoplado) pois mover uma funcionalidade de um contexto para outro dentro de uma mesma aplicação é mais simples do que mover conteúdo de um serviço <code class="language-plaintext highlighter-rouge">A</code> para um <code class="language-plaintext highlighter-rouge">B</code>. Em serviços isso impacta até mesmo sua API, que pode já estar sendo consumida por alguém. E se o microserviço <code class="language-plaintext highlighter-rouge">A</code> foi escrito numa linguagem diferente do <code class="language-plaintext highlighter-rouge">B</code>? Isso torna o refactoring ainda mais custoso, sem falar da migração de database… Enfim, é sensato começar por um monolito caso haja dúvidas quanto as boundaries dos seus componentes. Iniciar nessa abordagem te permite ir migrando as partes que fizerem sentido para microserviços conforme a necessidade, isso pode ser feito com planejamento e menos dor. O caso contrário geralmente é mais custoso.</p>
<h2 id="conclusão">Conclusão</h2>
<p>Toda escolha de design e arquitetura possui seus tradeoffs e com microserviços não é diferente. São muitas as complexidades que você irá introduzir na sua arquitetura ao optar pelo approach de ter uma alta granularidade de serviços. É preciso avaliar os tradeoffs com cautela.</p>Microservices (parte 1): Benefícios2017-07-28T02:58:56+00:002017-07-28T02:58:56+00:00http://www.fabriciorissetto.com/blog/microservices-parte-1<p><em>Esse post é continuação de uma série sobre arquitetura SOA. Aqui você pode conferior o anterior, no qual falei de <a href="www.fabriciorissetto.com/blog/ESBs/">ESBs</a> e contextualizei o cenário SOA antes da hype de microservices.</em></p>
<ul>
<li><strong>Edit:</strong> Como o post ficou muito grande dividi ele em dois. Nessa primeira parte vou focar nos benefícios da abordagem e na segunda focarei nas dificuldades.</li>
</ul>
<h2 id="mais-hype-que-game-of-thrones">Mais hype que Game of Thrones…</h2>
<div style="text-align:center">
<img style="text-align: center;" src="http://www.fabriciorissetto.com/images/2017-07-28-microservices/one-does-not-microservice.jpg" />
</div>
<p>Antes de tudo, quero começar esclarecendo uma coisa: <strong>O padrão de microservices não é um substituto de SOA</strong>. Pra falar a verdade a afirmação nem faz tanto sentido. Vejo microservices como um subset de SOA, uma das N maneiras de se fazer SOA.</p>
<h2 id="afinal-o-que-é">Afinal, o que é?</h2>
<p>O termo ganhou popularidade depois desse <a href="http://martinfowler.com/articles/microservices.html">post</a> feito pelo Martin Fowler e James Lewis onde eles descrevem as 9 principais características do padrão de microserviços. Mas como aquele post é meio chato, e você está aqui ao invés de estar lá, me permito descrever pra você uma definição resumida utilizando minhas palavras, lá vai:</p>
<blockquote>
<p>É um monte de serviço se comunicando pra todo lado, em que cada serviço tem uma responsabilidade única e normalmente focada em uma parte específica do negócio (ou até mesmo em um aspecto não funcional) que juntos compõem um objetivo maior do “todo”. É separar aquele monolítico de Ecommerce em serviços menores como “Carrinho de compras”, “Pagamento”, “Catalogo de Produtos”, “Autenticação” (microserviço não funcional), etc.</p>
</blockquote>
<p>Bonito de falar, difícil de fazer…</p>
<p>Pra mim, não tem maneira melhor de entender um padrão do que descrevendo as vantagens e desvantagens de se usá-lo. No final das contas a decisão de utilizar qualquer padrão passa por essa balança. Então vamos lá.</p>
<div style="text-align:center">
<img style="text-align: center;" src="http://www.fabriciorissetto.com/images/2017-07-28-microservices/pros-cons.png" />
</div>
<h2 id="algumas-vantagens">Algumas vantagens</h2>
<h4 id="smart-endpoints-dumb-pipes">Smart endpoints, dumb pipes</h4>
<p>Os serviços conhecem e consomem uns aos outros. Por isso dizemos que os endpoints são “inteligentes” pois os serviços se comunicam entre si diretamente, sem um “ESB tomador de decisão” no meio. Com ESBs os desenvolvedores são encorajados a botar cada vez mais lógica e inteligência dentro dele. Ele é a única e central entidade nas quais as aplicações e serviços enxergam.</p>
<p>O resultado de termos serviços que se comunicam diretamente é que eles sabem da existência dos demais e por isso eles fazem parte da sau regra de negócio, bem como a comunicação entre eles.</p>
<h4 id="organized-around-business-capabilities">Organized around Business Capabilities</h4>
<p>Esse é um dos tópicos que eu mais gosto. Fazendo um gancho com DDD isso seria o conceito de <a href="http://www.fabriciorissetto.com/blog/ddd-bounded-context/">bounded contexts</a> implementado num sentido mais amplo, no de um serviço. Isso mesmo, cada bounded context poderia ser implementado como sendo um microserviço. Normalmente a motivação de separar um bounded context num microserviço seria isolar ele do restante, por diversos motivos como:</p>
<h5 id="independência-de-linguagem">Independência de linguagem</h5>
<p>Poder desenvolver os microserviços em diferentes linguagens. Por exemplo, na <a href="www.creditas.com.br">Creditas</a> existe um microserviço que utiliza uma série de conceitos de machine learning para elencar a prioridade de atendimento de um cliente (clientes com maiores chances de assinarem o contrato são atendidos primeiro). Apesar da stack da empresa estar em grande parte construída em Ruby, para esse microservice em específico foi utilizado Python devido ao fato de que haviam diversas libs prontas com implementação dos conceitos que eram necessários, além de libs de integração com ferramentas que utilizamos na área de data science. E como reinventar a roda, apesar de ser divertido, tem um custo, escolhemos utilizar a linguagem que mais nos favorecia naquela implementação.</p>
<h5 id="flexibilidade-de-arquitetura">Flexibilidade de arquitetura</h5>
<p>Seguir modelos e possuir padrões dentro de sua empresa é legal. Mas ditar que todas aplicações vão possuir o mesmo padrão de arquitetura não é. Por exmeplo, existem aplicações que vão ser favorecidas pelo uso do padrão de DDD por possuírem complexidade de negócio. Mas nem todas aplicações possuem complexidade de negócio e nem todas as áreas do seu negócio são complexas. Uma aplicação ou área de negócio que é mais voltada a dados, ou seja, “CRUD intensive”, poderia ser desenvolvida num estilo arquitetural como o <a href="http://www.markewer.com/2015/10/21/smartui-architecture-pattern/">Smart UI</a>, um padrão muito simples e fácil de se manter para casos como esse.</p>
<h5 id="independência-de-protocolo-rest-soap-etc">Independência de protocolo (REST, SOAP, etc)</h5>
<p>Seu serviço vai se expor para outros serviços/aplicações de alguma maneira e porvavelmente você vai utilizar algum padrão/protocolo para isso. Se ele vai ser consumido por um código javascript em uma página web talvez seja interessante você utilizar REST e retornar um JSON para o frontend. Se seu serviço vai ser consumido por uma aplicação escrita em Java ou C#, que são linguagens estaticamente tipadas, talvez você queira utilizar o protocolo SOAP para aproveitar o boilerplate de classes criadas automaticamente ao mapear o WSDL no seu projeto.</p>
<h5 id="independência-de-deploy">Independência de deploy</h5>
<p>A independência de deploy pode ter diversas vantagens quanto a simplicidade. Como a simplicidade de poder republicar um serviço de forma isolada sem ter que derrubar uma aplicação core da empresa. Sim, isso pode ser feito utilizando algum método de deploy <a href="https://stackoverflow.com/questions/23746038/canary-release-strategy-vs-blue-green">mais inteligente</a>, porém dependendo da arquitetura da sua estrutura de microserviços (reativa por exemplo) isso nem é necessário. E também simplicidade nos processos de automação de deploy na integração contínua, já que um microserviço normalmente tem menos complexidade de configuração que um monolítico que atende a várias necessidades.</p>
<h5 id="escalabilidade-do-serviço">Escalabilidade do serviço</h5>
<p>Esse aqui talvez nem precise explicar. É a primeira coisa que se acha no google quando se pesquisa por microserviços. Se uma professora da terceira série do fundamental aplicasse em uma prova a pergunta “qual é o principal benefício de microserviços?” <em>e algum aluno respondessse</em> provavelmente a resposta seria “escalabilidade do serviço”. E de fato o padrão se popularizou pelo uso em empresas com alta demanda de escalabilidade como Netflix, Amazon, Ebay. Entretanto essa é apenas uma das vantagens, que para empresas como as citadas anteriormente talvez realmente seja a principal, mas que para outras pode ser completamente irrelevante. Digo isso pois vejo muitas pessoas utilizando essa caracteríscica como o <a href="http://www.dictionary.com/browse/litmus-test">litmus test</a> para implementação de microserviços, o que é um equívoco. Talvez sua empresa não precise de escalabilidade mas ainda assim precise de microserviços. Veja o motivo abaixo.</p>
<h5 id="escalabilidade-de-equipe">Escalabilidade de equipe</h5>
<p>Complemento ao tópico anterior. Escalabilidade não se resume apenas a instâncias de sua aplicação subindo na AWS ou Azure. Escalabildiadde de <strong>equipe</strong> também é importante.</p>
<p>Isso daqui é a lei de Conway em ação!</p>
<blockquote>
<p>Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.
– Melvyn Conway, 1967</p>
</blockquote>
<p>Times completamente diferentes trabalhando na mesma base de código (mesmo repositório) podem enfrentar maiores dificuldades de trabalho conforme suas equipes crescem. Dificuldades de source control, como número excessivo de merges e resolução de conflitos, podem tomar um tempo precioso de desenvolvimento e aumentar o lead time do processo de code review. E não podemos esquecer também de alguns dos pontos que foram citados anteriormente como a dificuldade de deploy. Tudo isso pode afetar a <strong>escalabilidade da equipe</strong> e ao mesmo tempo não afetar em nada a <strong>escalabilidade aplicação</strong>.</p>
<h4 id="mas-nem-tudo-são-flores">Mas nem tudo são flores</h4>
<p>E por isso separei um post só pros “downsides” de microserviços. Muitos deles tive o prazer de sentir na pele e confesso que não foi uma experiência muito divertida. Confira o post <a href="/blog/microservices-parte-2">aqui</a>.</p>Proxy Pattern e Proxies dinâmicos em .NET com DynamicObject2017-07-21T02:58:56+00:002017-07-21T02:58:56+00:00http://www.fabriciorissetto.com/blog/dynamic-object<p>O Proxy é um padrão de uso relativamente específico, mas que quando bem aplicado resolve problemas de maneira muito sexy.</p>
<p>A imagem abaixo, retirada do site <a href="http://www.dofactory.com/net/proxy-design-pattern">dofactory.com</a>, exemplifica de uma maneira <del>que não dá pra entender</del> como o padrão funciona:</p>
<div style="text-align:center">
<img style="text-align: center;" src="http://www.fabriciorissetto.com/images/2017-07-21-dynamic-object/proxy-pattern.gif" />
</div>
<p>Mas não esquenta em entender a imagem, eu coloquei ela aqui só pra citar o site dofactory, que é uma ótima referência pro aprendizado de patterns.</p>
<p>Portanto, vou explicar o padrão com um exemplo real em que pude aplicá-lo recentemente. Vamos lá.</p>
<h2 id="o-problema-parte-1">O Problema: Parte 1</h2>
<p>Imagine um <strong>job</strong>, que em .NET poderia ser até mesmo uma Console Application, no qual é executado de forma recorrente para fazer determinadas tarefas no banco de dados durante a madrugada. Porque na madrugada? Poruqe essas tarefas são pesadas e causariam uma lentidão nos sistemas que dependem desse banco de dados. Esse job possui algumas <strong>configurações</strong> como, o horário que deve iniciar a execução, horário de parada, intervalo de tempo em que deve ficar parado (Idle) entre uma execução e outra, etc.</p>
<p>Um trecho de código bem escrito vale mais que mil palavras, então vamos fazer o esboço disso.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">Job</span>
<span class="p">{</span>
<span class="k">public</span> <span class="n">Config</span> <span class="n">Config</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Execute</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//...</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><em>Detalhe: Esses exeplos de código seguem uma versão simplificada por questões didáticas. A classe acima poderia ser abstrata bem como os modificadores de acesso de suas propriedades serem mais restritivos, o Config por exemplo, poderia ter o set privado e ser atribuído durante a construção da classe.</em></p>
<p>Os dados de configuração do job estão na classe <strong>Config</strong>:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">Config</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">Config</span><span class="p">(</span><span class="cm">/* ... */</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* ... */</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">DateTime</span><span class="p">?</span> <span class="n">StartTime</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">DateTime</span><span class="p">?</span> <span class="n">EndTime</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">IdleInterval</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">ExecutionInterval</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">bool</span> <span class="n">Enabled</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Esse código poderia ser consumida por uma console application da seguinte forma:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">job</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">JobImportacaoExcel</span><span class="p">();</span> <span class="c1">//Suposta classe que herda de Job</span>
<span class="k">if</span> <span class="p">(</span><span class="n">job</span><span class="p">.</span><span class="n">Config</span><span class="p">.</span><span class="n">Enabled</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="n">job</span><span class="p">.</span><span class="n">Config</span><span class="p">.</span><span class="n">StartTime</span> <span class="p">>=</span> <span class="cm">/* ... */</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">job</span><span class="p">.</span><span class="nf">Execute</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="o-problema-parte-2">O Problema: Parte 2</h2>
<p>Até aí tudo bem. Agora imagine que temos diversos Jobs como esse executando, todos eles dependendo dessa classe Config, e o cliente pede a seguinte modificação:</p>
<blockquote>
<p>No fim de semana os jobs deverão rodar durante o dia também (e não somente de madrugada), além disso o intervalo entre uma parada e outra deverá ser menor. Para atender isso gostaríamos que os jobs obedecessem um config diferente durante os finais de semana. Ou seja, os valores de StartTime, EndTime, IdleInterval, e qualquer outro, poderiam ser diferentes no sábado e domingo.</p>
</blockquote>
<p>Existem diversas maneiras de atender isso, uma das mais elegantes é utilizando um Proxy. Enfim chegamos a ele!</p>
<h2 id="solução-1-proxy-pattern">Solução 1: Proxy Pattern</h2>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">ConfigProxy</span>
<span class="p">{</span>
<span class="k">private</span> <span class="n">Config</span> <span class="n">ConfigWeekdays</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">private</span> <span class="n">Config</span> <span class="n">ConfigWeekend</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="nf">ConfigProxy</span><span class="p">(</span><span class="n">Config</span> <span class="n">configWeekdays</span><span class="p">,</span> <span class="n">Config</span> <span class="n">configWeekend</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* */</span> <span class="p">}</span>
<span class="k">private</span> <span class="n">Config</span> <span class="n">CurrentConfig</span>
<span class="p">{</span>
<span class="k">get</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">today</span> <span class="p">=</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">.</span><span class="n">DayOfWeek</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">todayIsWeekend</span> <span class="p">=</span> <span class="n">today</span> <span class="p">==</span> <span class="n">DayOfWeek</span><span class="p">.</span><span class="n">Saturday</span> <span class="p">||</span> <span class="n">today</span> <span class="p">==</span> <span class="n">DayOfWeek</span><span class="p">.</span><span class="n">Sunday</span><span class="p">;</span>
<span class="k">return</span> <span class="n">todayIsWeekend</span> <span class="p">?</span> <span class="n">ConfigWeekend</span> <span class="p">:</span> <span class="n">ConfigWeekdays</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">DateTime</span><span class="p">?</span> <span class="n">StartTime</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">CurrentConfig</span><span class="p">.</span><span class="n">StartTime</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">DateTime</span><span class="p">?</span> <span class="n">EndTime</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">CurrentConfig</span><span class="p">.</span><span class="n">EndTime</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">IdleInterval</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">CurrentConfig</span><span class="p">.</span><span class="n">IdleInterval</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">ExecutionInterval</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">CurrentConfig</span><span class="p">.</span><span class="n">ExecutionInterval</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">bool</span> <span class="n">Enabled</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">CurrentConfig</span><span class="p">.</span><span class="n">Enabled</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Note que ele possui dentro dele os dois configs, um pra ser utilizado durante a semana e outro no fim de semana. O mais interessante é que ele expõe as mesmas propriedades da classe Config. Ele imita a classe config, porém internamente modifica o comportamento de cada propriedade ou método.</p>
<blockquote>
<p><em>OBS: Se a classe Config implementasse uma interface a solução seria ainda mais interessante, pois o proxy poderia implementar essa mesma interface e, aí sim, a imitação de ser um config real seria ainda mais transparente.</em></p>
</blockquote>
<p>O legal dessa solução é que com uma mudança simples na classe Job, apenas mudando o tipo da propriedade <code class="language-plaintext highlighter-rouge">Config</code> para <code class="language-plaintext highlighter-rouge">ConfigProxy</code>:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">Job</span>
<span class="p">{</span>
<span class="k">public</span> <span class="n">ConfigProxy</span> <span class="n">Config</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Execute</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//...</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>A nosso “consumidor”, a console application, não seria impactado em absolutamente nada. Nenhum caracter alterado:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">job</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">JobImportacaoExcel</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">job</span><span class="p">.</span><span class="n">Config</span><span class="p">.</span><span class="n">Enabled</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="n">job</span><span class="p">.</span><span class="n">Config</span><span class="p">.</span><span class="n">StartTime</span> <span class="p">>=</span> <span class="cm">/* ... */</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">job</span><span class="p">.</span><span class="nf">Execute</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<blockquote>
<p>Um outro exemplo de uso do Proxy Pattern, talvez até mais interessante do que o demonstrado acima, é esse <a href="https://github.com/fabriciorissetto/design-patterns-examples/blob/master/2.%20Structural%20Patterns/Proxy%20Pattern/ConsoleApplication1/SerasaProxy.cs">daqui</a> onde eu crio um proxy pra otimizar e restringir chamadas a um serviço pago do Serasa.</p>
</blockquote>
<h2 id="solução-2-proxy-dinâmico-utilizando-dynamicobject">Solução 2: Proxy dinâmico utilizando DynamicObject</h2>
<p>Apesar da solução apresentada ser bacana e simples de entender (isso é imporantíssimo), o que aconteceria se uma nova propriedade ou método fosse criado dentro da classe real <code class="language-plaintext highlighter-rouge">Config</code>?</p>
<p>O resultado é que esses membros não seriam refletidos no nosso proxy (<code class="language-plaintext highlighter-rouge">ConfigProxy</code>) até que alguém fosse lá e manualmente tratasse esses novos campos.</p>
<p>Para evitar essa reescrita dentro do <code class="language-plaintext highlighter-rouge">ConfigProxy</code> poderíamos utilizar um recurso do framework chamado <a href="https://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx">DynamicObject</a>.</p>
<p>Vejam só que bacana:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">DynamicConfigProxy</span> <span class="p">:</span> <span class="n">DynamicObject</span>
<span class="p">{</span>
<span class="k">private</span> <span class="n">Config</span> <span class="n">ConfigWeekdays</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">private</span> <span class="n">Config</span> <span class="n">ConfigWeekend</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="nf">ConfigProxy</span><span class="p">(</span><span class="n">Config</span> <span class="n">configWeekdays</span><span class="p">,</span> <span class="n">Config</span> <span class="n">configWeekend</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* */</span> <span class="p">}</span>
<span class="k">private</span> <span class="n">Config</span> <span class="n">CurrentConfig</span>
<span class="p">{</span>
<span class="k">get</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">today</span> <span class="p">=</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">.</span><span class="n">DayOfWeek</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">todayIsWeekend</span> <span class="p">=</span> <span class="n">today</span> <span class="p">==</span> <span class="n">DayOfWeek</span><span class="p">.</span><span class="n">Saturday</span> <span class="p">||</span> <span class="n">today</span> <span class="p">==</span> <span class="n">DayOfWeek</span><span class="p">.</span><span class="n">Sunday</span><span class="p">;</span>
<span class="k">return</span> <span class="n">todayIsWeekend</span> <span class="p">?</span> <span class="n">ConfigWeekend</span> <span class="p">:</span> <span class="n">ConfigWeekdays</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="kt">bool</span> <span class="nf">TryGetMember</span><span class="p">(</span><span class="n">GetMemberBinder</span> <span class="n">propertyCalledByUser</span><span class="p">,</span> <span class="k">out</span> <span class="kt">object</span> <span class="n">result</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">result</span> <span class="p">=</span> <span class="k">typeof</span><span class="p">(</span><span class="n">Config</span><span class="p">)</span>
<span class="p">.</span><span class="nf">GetProperty</span><span class="p">(</span><span class="n">propertyCalledByUser</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span>
<span class="p">.</span><span class="nf">GetValue</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">CurrentConfig</span><span class="p">);</span>
<span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>O método <code class="language-plaintext highlighter-rouge">TryGetMember</code> é acionado toda vez que o objeto recebe uma chamada pra um membro que não existe. E ali dentro chamamos a propriedade do respectivo config através de reflection.</p>
<p>Feito isso, apenas teríamos que modificar a classe Job para tratar a propriedade como dynamic.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">Job</span>
<span class="p">{</span>
<span class="c1">//A instância seria do tipo DynamicConfigProxy (sendo setada via contrutor - que foi omitido dos exemplos por questão de legibilidade)</span>
<span class="k">public</span> <span class="kt">dynamic</span> <span class="n">Config</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Execute</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//...</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>O interessante dessa solução é que, novamente, nenhuma mudança seria necessária no nosso consumidor:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">job</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">JobImportacaoExcel</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">job</span><span class="p">.</span><span class="n">Config</span><span class="p">.</span><span class="n">Enabled</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="n">job</span><span class="p">.</span><span class="n">Config</span><span class="p">.</span><span class="n">StartTime</span> <span class="p">>=</span> <span class="cm">/* ... */</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">job</span><span class="p">.</span><span class="nf">Execute</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><em>O lado ruim é que pelo campo ser um “dynamic” não teríamos autocomplete :(</em></p>
<h3 id="dynamicobject-no-framework-signalr">DynamicObject no framework: SignalR</h3>
<p>Se você já utilizou o SignalR provavelmente passou pelo DynamicObject e nem se deu conta. O código está <a href="https://github.com/aspnet/SignalR/blob/8ba29b578da537af40d3e4942da6580963d7812c/src/Microsoft.AspNetCore.SignalR/DynamicClientProxy.cs">aqui</a>, e você o utiliza quando faz isso:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">ChatHub</span> <span class="p">:</span> <span class="n">Hub</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Send</span><span class="p">(</span><span class="kt">string</span> <span class="n">name</span><span class="p">,</span> <span class="kt">string</span> <span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Clients</span><span class="p">.</span><span class="n">All</span><span class="p">.</span><span class="nf">addNewMessageToPage</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Aquela propriedade <code class="language-plaintext highlighter-rouge">All</code> é um DynamicObject e o <code class="language-plaintext highlighter-rouge">addNewMessageToPage()</code> é a função que você quer que seja chamada no JavaScript de seus clients conectados no Hub.</p>
<h2 id="outras-maneiras-de-criar-proxies-dinâmicos-solução-3">Outras maneiras de criar Proxies Dinâmicos (Solução 3)</h2>
<p>Embora a classe DynamicObject seja uma das formas mais simples de implementar proxies dinâmicos em .NET, existem diversas outras maneiras. Se você estiver procurando algo mais robusto, não pode deixar de dar uma olhada no projeto <a href="http://www.castleproject.org/projects/dynamicproxy/">Castle Dynamic Proxy</a>. Um dos únicos pré-requisitos de utilizá-lo é que os membros que você quer “interceptar” devem possuir o modificador de acesso como <code class="language-plaintext highlighter-rouge">virutal</code>, o que pode não ser um problema.</p>Usos equivocados do Specification Pattern2017-06-30T02:58:56+00:002017-06-30T02:58:56+00:00http://www.fabriciorissetto.com/blog/specification-pattern<p>Imagine essa classe:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">Livro</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Titulo</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">Genero</span> <span class="n">Genero</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">Autor</span> <span class="n">Autor</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">DateTime</span><span class="p">?</span> <span class="n">DataPublicacao</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="nf">Livro</span><span class="p">(</span><span class="kt">string</span> <span class="n">titulo</span><span class="p">,</span> <span class="n">Genero</span> <span class="n">genero</span><span class="p">,</span> <span class="n">Autor</span> <span class="n">autor</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Titulo</span> <span class="p">=</span> <span class="n">titulo</span><span class="p">;</span>
<span class="n">Genero</span> <span class="p">=</span> <span class="n">genero</span><span class="p">;</span>
<span class="n">Autor</span> <span class="p">=</span> <span class="n">genero</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Publicar</span><span class="p">(</span><span class="n">Revisor</span> <span class="n">revisor</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">DataPublicacao</span> <span class="p">=</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">;</span>
<span class="n">Revisor</span> <span class="p">=</span> <span class="n">revisor</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>E esse specification:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">LivroEstaPublicadoSpecification</span> <span class="p">:</span> <span class="n">Specification</span><span class="p"><</span><span class="n">Livro</span><span class="p">></span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">override</span> <span class="kt">bool</span> <span class="nf">IsSatisfiedBy</span><span class="p">(</span><span class="n">Livro</span> <span class="n">livro</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">livro</span><span class="p">.</span><span class="n">DataPublicacao</span> <span class="p">!=</span> <span class="k">null</span> <span class="p">&&</span> <span class="n">livro</span><span class="p">.</span><span class="n">Revisor</span> <span class="p">!=</span> <span class="k">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Algum problema nisso? Pode ser que não. Na verdade a resposta está na seguinte pergunta: “É responsabilidade do livro informar se ele está publicado?”. Se a resposta for sim, então há um problema em usar especificação para isso.</p>
<p>Portanto,</p>
<h2 id="não-retire-da-entidade-regras-que-pertencem-a-ela">Não retire da entidade regras que pertencem a ela</h2>
<blockquote>
<p>Não é objetivo da especificação <strong>absorver regras que pertencem à entidade</strong>. E sim <strong>absorver regras que NÃO pertencem à entidade</strong> (explico melhor isso logo em seguida).</p>
</blockquote>
<p>Ou seja, se é responsabilidade do Livro informar seu status de publicação então é lá que essa regra deve estar (dentro de uma propriedade get ou método).</p>
<p>Tenho visto em muitos projetos a utilização equivocada do Specification Pattern e esse exemplo acima é um desses casos.</p>
<h2 id="cuidado-ao-utilizar-specification-para-validação">Cuidado ao utilizar specification para “validação”</h2>
<p>Outro caso que tenho visto também é esse:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">ContratoEstaValidoSpecification</span> <span class="p">:</span> <span class="n">Specification</span><span class="p"><</span><span class="n">Contrato</span><span class="p">></span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">override</span> <span class="kt">bool</span> <span class="nf">IsSatisfiedBy</span><span class="p">(</span><span class="n">Contrato</span> <span class="n">contrato</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">contrato</span><span class="p">.</span><span class="n">Cliente</span> <span class="p">!=</span> <span class="k">null</span> <span class="p">&&</span>
<span class="n">contrato</span><span class="p">.</span><span class="n">PrimeiraParcelaQuitada</span> <span class="p">==</span> <span class="k">true</span> <span class="p">&&</span>
<span class="n">contrato</span><span class="p">.</span><span class="n">Valor</span> <span class="p">></span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Isso dá pano pra manga…</p>
<p>Eu recomendo bastante a leitura desse <a href="https://www.martinfowler.com/apsupp/spec.pdf">paper</a> de apenas 19 páginas escrito de forma colaborativa pelo Eric Evans e Martin Fowler (e não precisa tentar entender aqueles códigos Smalltalk, só entender o conceito e visualizar os diagramas é o suficiente). Nesse paper eles descrevem 3 principais problemas que podem ser solucionados com Specification:</p>
<ul>
<li>
<p><strong>Selection</strong>: You need to select a subset of objects based on some criteria, and to refresh the selection at various times</p>
</li>
<li>
<p><strong>Validation</strong>: You need to check that only suitable objects are used for a certain purpose</p>
</li>
<li>
<p><strong>Construction-to-order</strong>: You need to describe what an object might do, without explaining the details of how the object does it, but in such a way that a candidate might be built to fulfill the requirement.</p>
</li>
</ul>
<p>Note que esse segundo item, o de <strong>validação</strong>, não trata sobre o tipo de validação que acabei de expor ali em cima. Naquele meu exemplo estamos verificando se a entidade está em um estado válido, e existem alguns problemas em relação a isso. Lá vai.</p>
<h5 id="primeiro">Primeiro:</h5>
<p>As entidades de domínio devem estar sempre em estado válido. Se para um <code class="language-plaintext highlighter-rouge">Contrato</code> ser construído é necessário que ele tenha o campo X, isso deve ser validado no seu construtor, de maneira a impedir que a entidade seja criada caso o campo X não seja informado ou esteja incorreto.</p>
<p>Voltando ao exemplo do contrato onde a regra de validação, ao invés de ficar no construtor, foi parar numa Specification. Isso quer dizer que durante um breve momento, após a classe ter sido instanciada e antes do Specification ser utilizado para validá-la, nesse breve momento, alguém pode fazer a seguinte chamada:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">contrato</span><span class="p">.</span><span class="nf">Aprovar</span><span class="p">();</span>
</code></pre></div></div>
<p><strong>Resultado</strong>: um contrato que estava num estado inválido foi aprovado.</p>
<p><strong><em>Ah Fabrício, mas eu poderia ter validado aqueles campos dentro do método Aprovar né?</em></strong> Sim, poderia. Mas imagine que essa validação poderia, além de estar dentro do método <code class="language-plaintext highlighter-rouge">Aprovar()</code>, estar no método <code class="language-plaintext highlighter-rouge">EnviarParaAnalise()</code>, no método <code class="language-plaintext highlighter-rouge">CalcularJuros()</code>, e dentro dos próximos N métodos que possam vir a existir e que dependam que esses campos estejam com dados válidos. Não é bacana ter essa validação espalhada em todos os cantos, correto? A não ser que faça parte de um fluxo de negócio que essas informações estejam em algum momento vazias ou com alguma inconsistência, devemos implementar o modelo de forma a isso não ocorrer.</p>
<p>Ainda fugindo um pouco do tópico de Specifications, outro exemplo é quando buscamos uma entidade do banco de dados. Se eu obtive um objeto <code class="language-plaintext highlighter-rouge">Contrato</code> do banco de dados e ele tem um campo <code class="language-plaintext highlighter-rouge">Cliente</code> vazio, isso me dá a enteder de que faz parte da regra de negócio que um contrato possa ser criado sem possuir um cliente associado a ele. <em>As vezes o desenvolvedor, por alguma questão de performance ou outros motivos, não traz a informação do banco de dados, o que se tratando de desenvolvimento orientado a domínio, não é correto. Existem diversas formas elegantes de driblar dificuldades como essa sem ferir o modelo (CQRS, Bounded Contexts, etc).</em></p>
<h5 id="segundo">Segundo:</h5>
<p>Ufa, demorei mais do que eu gostaria no primeiro.</p>
<p>Se o propósito é fazer validações de input do usuário, existem outras formas, que não o specification, que tratam isso de maneira mais adequada, uma das que estou gostando muito é o <a href="https://github.com/andrebaltieri/FluentValidator/blob/master/FluentValidator.Tests/FluentValidatorTests.cs">Notification Pattern</a>. Mas anteção, esse tipo de validação não deve ficar no domínio. Validar se o nome que o usuário digitou tem menos de 200 caracteres normalmente não é uma regra de negócio…</p>
<h1 id="bons-exemplos-de-specification">Bons exemplos de Specification</h1>
<p>Bom, já citei alguns exemplos em que considero equivocado o uso de Specification, agora vamos citar alguns exemplos legais. Na verdade, o exemplo que mais gosto é o que está no paper que citei, <strong>sobre a responsabiliade de definir se uma carga está apta a ser transportada por determinado container</strong>.</p>
<p>O exemplo é o seguinte: Estamos desenvolvendo um sistema de administração de cargas para uma transportadora. Essa transportadora tem diversos tipos de containers, com tamanhos e caracteríscas bem distintas. Nesses containers ela transporta cargas dos mais variados tipos.</p>
<p>Nessa breve descrição podemos visualizar duas entidades claras no nosso modelo: <code class="language-plaintext highlighter-rouge">Carga</code> e <code class="language-plaintext highlighter-rouge">Container</code>.</p>
<p>Agora algumas regras de negócio pra temperar ele:</p>
<p>Existem cargas que possuem restrição de temperatura, como: Frango Congelado, Pizza Congelada, Iogurte, Queijo, Ovo de Páscoa. E existem containers resfriados que são específicos para esse tipo de carga e que são higienizados. Mesmo entre os containers resfriados existe uma distinção devido a capacidade de temperaturas mínimas que cada um tem (alguns conseguem atingir a temperatura mínima para transportar iogurte, mas não frango congelado), além de que nem todos esses containers resfriados são higienizados e apropriados para acomodar alimentos.</p>
<p>Existem containers estofados para carregar cargas frágeis, como: vasos de cêramica, taças de cristal, etc.</p>
<p>Existem containers com blindagem e medidas de segurança específicas para transportar cargas perigosas como gazes, explosivos, produtos inflamáveis, etc.</p>
<p>Agora a pergunta:</p>
<p><strong>Container</strong>: É responsabilidade do container saber quais cargas ele pode carregar? É responsabilidadde dele saber que existe um iogurte e que no futuro talvez poderá existir uma carga de um novo tipo no qual ele ainda não conhece? Imagine um container quadradão xingando um funcionário: <em>“Eeeepa!! Pera aí… requeijão eu não posso transportar não fiii! Sai sai sai sai, tira isso daqui.”</em></p>
<p><strong>Carga</strong>: E o contrário? É responsabilidade da carga saber em quais containers ela pode ou não ser transportada? Uma carga tem um peso, uma validade, uma temperatura mínima para conservação, agora, a responsabilidade de saber se ela pode ou não ser transportada no <em>“Container Tabajara X 9800 Plus”</em> deveria ser dela?</p>
<p>Nesses casos o uso de Specification é um golaço, pois não estamos retirando das entidades reponsabilidades que pertencem a elas, e ao mesmo tempo estamos definindo regras dentro do nosso domínio de uma maneira clara, encapsulada, testável e reutilizável. Além de evitar um acoplamento desnecessário entre aquelas duas entidades.</p>
<p>Então, que tal então Specifications como esses:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CargaNecessitaContainerResfriadoSpecification()
CargaNecessitaContainerLimpoSpecification()
CargaNecessitaContainerLimpoEResfriadoSpecification()
CargaNecessitaContainerEstofadoSpecification
CargaNecessitaContainerBlindadoSpecification()
</code></pre></div></div>
<p>A implementação simplificada do <code class="language-plaintext highlighter-rouge">CargaNecessitaContainerResfriadoSpecification</code> poderia algo assim:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public class ContainerPodeLevarCargaResfriadaSpec : Specification<Carga>
{
public Container Container { get; set; }
public ContainerPodeLevarCargaResfriadaSpec(Container container)
{
this.Container = container;
}
public bool IsSatisfiedBy(Carga carga)
{
return Container.Caracterisiticas.CapacidadeTemperaturaMinima <= carga.TemperaturaDeConservacao;
}
}
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public class ContainerPodeLevarCargaResfriadaEHigienizadaSpec : Specification<Carga>
{
public Container Container { get; set; }
public ContainerPodeLevarCargaResfriadaEHigienizadaSpec(Container container)
{
this.Container = container;
}
public bool IsSatisfiedBy(Carga carga)
{
return
new ContainerPodeLevarCargaResfriadaSpec(Container).IsSatisfiedBy(carga) &&
new ContainerPodeLevarCargaHigienizadaSpec(Container).IsSatisfiedBy(carga);
}
}
</code></pre></div></div>
<p>No final das contas o uso de specifications, pelo menos nos projetos em que eu tenho atuado, não se faz algo assim “tão comum”. Com perdão da cacofonia, o uso de specifications é bem específico e você provavelmente não irá construir um sistema que já na concepção tem uma arquitetura que envolva isso. Ele é algo que irá surgir durante a modelagem, em casos específicos e que provavelmente será claro para todos de que ele é “o pettern” que vai resolver aquele problema. Assim como funciona para todos outros patterns.</p>
<p>Afinal, não começamos o projeto dizendo “Bom, essa pastinha aqui é onde vamos colocar os Strategies, aqui os Builders, nessa os Proxies, e naquela outra os Decorators”, não é mesmo? Os patterns se aplicam e se adequam aos projetos e não o contrário.</p>ESBs, o que são, do que se alimentam2017-02-18T02:58:56+00:002017-02-18T02:58:56+00:00http://www.fabriciorissetto.com/blog/ESBs<p><em>Esse post é a parte 1 de 3 tratando sobre arquitetura SOA. Nas próximas partes irei discutir sobre o padrão de microserviços e depois API Gateways, exemplificando até mesmo a possibilidade de coexistência de tudo isso numa mesma arquitetura.</em></p>
<h2 id="esb---enterprise-service-bus">ESB - Enterprise Service Bus</h2>
<p>ESB é algo que, assim como calça boca de sino, já esteve na moda. O termo (e as ferramentas que o implementam) tem perdido consideravelmente seu glamour, principalmente pelo avanço do paradigma de microserviços, que no momento é a nova modinha. Mas ESBs ainda tem seu espaço em ambientes enterprises complexos e certamente lá permanecerão por muito tempo, talvez sempre.</p>
<h3 id="soa">SOA</h3>
<p>Para entender o que é um ESB é necessário entender a motivação que levou a sua criação. Tudo começou com o avanço da arquitetura “SOA” (Service Oriented Architecture). O que é isso?</p>
<blockquote>
<p>SOA é uma abordagem arquitetural corporativa que permite a criação de serviços de negócio interoperáveis que podem facilmente ser reutilizados e compartilhados entre aplicações e empresas. (Gartner Group)</p>
</blockquote>
<p>Tradução:</p>
<blockquote>
<p>Uma porrada de aplicações se conversando através de padrões (REST, SOAP, AMQP, etc).</p>
</blockquote>
<p>Conforme as empresas foram criando e mantendo cada vez mais serviços a galera começou a notar que estava ficando difícil de manter a parafernalha toda funcionando. Algumas das principais dificuldades que estavam surgindo:</p>
<ul>
<li>Log de comunicação entre os serviços (logs de erros, qual serviço chama qual)</li>
<li>Lidar com protocolos diferentes (REST, SOAP)</li>
<li>Segurança (qual aplicação tem permissão pra chamar o serviço X)</li>
</ul>
<h3 id="esbs-for-the-rescue">ESBs for the rescue!</h3>
<p>Com nisso começaram a surgir diversas ferramentas de mercado, os tais ESBs, se propondo a suprir essas e outras necessidades.</p>
<p><img src="http://www.fabriciorissetto.com/images/2017-02-18-esbs/esb.png" alt="esb" /></p>
<h5 id="vantagens-adquiridas-por-utilizar-um-esb">Vantagens adquiridas por utilizar um ESB</h5>
<ul>
<li>Monitoramento</li>
<li>Conversão de protocolos</li>
<li>Segurança</li>
<li>Roteamento e mediação</li>
</ul>
<p>Bacana não? Se as chamadas entre os nossos serviços passarem pelo ESB teremos todos esses pontos citados acima de vantagens e isso é ótimo! Porém, voltando ao tópico de arquitetura SOA, os ESBs normalmente nos levam a uma prática que chamamos de <em>orquestração</em>.</p>
<h4 id="orquestração-e-coreografia-de-serviços">Orquestração e Coreografia de serviços</h4>
<p><img src="http://www.fabriciorissetto.com/images/2017-02-18-esbs/orquestracao-coreografia.png" alt="Orquestração e Coreografia" /></p>
<p>Esses dois simples conceitos são as principais abordagens utilizadas em arquiteturas SOA. Num deles, a <strong>orquestração</strong>, temos um serviço ou ferramenta que conhece as regras de negócio e as centraliza em si, coordenando de forma abstraída as chamadas aos demais serviços necessários pra concluir a operação desejada. Na outra abordagem, a <strong>coreografia</strong>, temos os serviços se conhecendo e conversando diretamente sem um intermediador no meio.</p>
<h5 id="desvantagens">Desvantagens</h5>
<p>Uma das críticas em relação aos ESBs é que eles podem se tornar um <em>“single point of failure”</em>, pois sendo ele o centro da comunicação entre os serviços, caso ele deixe de funcionar a comunicação simplesmente para. Entretanto, praticamente todos os ESBs modernos possuem uma estrutura distribuída e já não mais correm esse risco.</p>
<p>Pra mim, o principal problema termos um ESB como sendo o “orquestrador” é que isso influencia diretamente na composição interna dos nossos serviços. Ele faz muitas vezes com que nossos serviços sejam “burros”!</p>
<p><strong><em>Serviço inteligente</em></strong></p>
<p>Exemplo de um serviço inteligente de um <strong>Ecommerce</strong> ao realizar a conclusão de uma compra:</p>
<p><img src="http://www.fabriciorissetto.com/images/2017-02-18-esbs/microservice-example.png" alt="Serviço inteligente" /></p>
<p>Ele sabe exatamente quais outros serviços e em que ordem deve chamar pra cumprir seu processo.</p>
<p><strong><em>Serviço burro</em></strong></p>
<p>Agora um exemplo de como poderia ser essa comunicação com um ESB:</p>
<p><img src="http://www.fabriciorissetto.com/images/2017-02-18-esbs/esb-example.png" alt="Serviço inteligente" /></p>
<p>Em qual das duas imagens fica mais fácil de entender o fluxo completo da criação de um pedido?</p>
<p>Olhando pra essa segunda imagem, será que o serviço do Ecommerce é realmente inteligente em relação a sua regra de negócio? Se fosse adicionado um novo passo no processo como, por exemplo, uma chamada ao serviço do Serasa, teríamos que adicionar essa nova chamada no serviço que cria o pedido (Ecommerce) ou teríamos que adicionar essa chamada no ESB? Quem é que sabe a regra de negócio da criação de pedido afinal? É o ESB!</p>
<p>Isso viola uma das características mais interessantes de Microservices chamada de <em>“Smart endpoints and dumb pipes”</em> (mas isso fica pro próximo post).</p>
<p>Outro problema dessa abordagem é que ela causa uma fricção desnecessária no desenvolvimento pois, se tudo tem que passar pelo ESB, meu serviço não é autônomo o suficiente para a qualquer momento passar a fazer uma nova chamada que não esteja previamente configurada no ESB, dependemos da equipe que o mantém durante todas as fases do desenvolvimento (dev, homol, prod).</p>
<p>Então, que tal tentarmos criar serviços mais inteligentes e independentes? Serviços que saibam o que devem fazer, com quem devem se comunicar e que sejam especialistas em fazer uma coisa, e fazê-la bem feita. Essa á uma das propostas da abordagem de Microserviços na qual explicarei no próximo post…</p>Threads, Tasks e o tal do ThreadPool2017-02-05T02:58:56+00:002017-02-05T02:58:56+00:00http://www.fabriciorissetto.com/blog/threadsetasks<p>Certa vez em um projeto precisei desenvolver uma espécie de “worker” distribuído que tinha como função realizar duas simples tarefas:</p>
<ul>
<li>Obter um número X (1000, por exemplo) de eventos através de uma queue</li>
<li>Sincronizar esses eventos com um Web Service remoto (cada uma dessas sincronizações podia demorar até 1 minuto).</li>
</ul>
<p>Para isso eu primeiramente pensei em utilizar o método <code class="language-plaintext highlighter-rouge">Parallel.Foreach</code> que havia lido ser uma implementação do framework para facilitar tarefas de processamento paralelo. Ora, fazia sentido, não? Eu tinha 1000 eventos em que tudo o que eu precisava fazer era chamar um Web Service e ficar esperando o retorno.</p>
<p>O código, de uma maneira simplificada, era próximo desse (<a href="https://gist.github.com/fabriciorissetto/69cfb8188cbab6c61eed30b6f814cdbf">gist completo aqui</a>):</p>
<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">listaEventos</span> <span class="p">=</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">1000</span><span class="p">);</span>
<span class="n">Parallel</span><span class="p">.</span><span class="nf">ForEach</span><span class="p">(</span><span class="n">listaEventos</span><span class="p">,</span>
<span class="p">(</span><span class="n">idEvento</span><span class="p">)</span> <span class="p">=></span>
<span class="p">{</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">Write</span><span class="p">(</span><span class="s">"."</span><span class="p">);</span>
<span class="n">Thread</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="n">DoisSegundos</span><span class="p">);</span> <span class="c1">//Chamada para um Web Service</span>
<span class="p">});</span>
</code></pre></div></div>
<p>Entretanto ao executar o código descobri que as coisas não estavam saindo exatamente como eu esperava:</p>
<div style="text-align:center">
<img src="http://www.fabriciorissetto.com/images/2017-02-03-threadsetasks/parallel.gif" />
</div>
<p>Porque diabos ele está executando as tarefas num paralelismo tão baixo!? Algo como de 4 em 4… Eu queria que ele executasse todas ao mesmo tempo!</p>
<p>Então tive a magnífica ideia de abrir manualmente 1000 daquelas tal de tasks (<a href="https://gist.github.com/fabriciorissetto/ca78913af7cadc5abb6550e7aad34bee">gist completo aqui</a>):</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">listaEventos</span><span class="p">.</span><span class="nf">ToList</span><span class="p">().</span><span class="nf">ForEach</span><span class="p">((</span><span class="n">idEvento</span><span class="p">)</span> <span class="p">=></span>
<span class="p">{</span>
<span class="n">Task</span><span class="p">.</span><span class="nf">Run</span><span class="p">(()</span> <span class="p">=></span>
<span class="p">{</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">Write</span><span class="p">(</span><span class="s">"."</span><span class="p">);</span>
<span class="n">Thread</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="n">DoisSegundos</span><span class="p">);</span> <span class="c1">//Chamada para um Web Service</span>
<span class="p">});</span>
<span class="p">});</span>
</code></pre></div></div>
<p>E…</p>
<div style="text-align:center">
<img src="http://www.fabriciorissetto.com/images/2017-02-03-threadsetasks/parallel.gif" />
</div>
<p>Powww! O resultado foi exatamente o mesmo. Mas por que!?</p>
<h2 id="thread-pool">Thread Pool</h2>
<p>Os dois exemplos de código acima têm algo em comum: <strong>eles utilizam o thread pool</strong>.</p>
<p>O Thread Pool é uma implementação do framework que visa evitar o overhead da criação excessiva de threads. Ele resolve isso através da utilização de um “pool”. Nesse pool de threads ele administra quais delas irão executar em paralelo (normalmente esse número reflete a quantidade de núcleos do processador) e também faz um reaproveitamento delas pois quando uma tarefa conclui ele não elimina a thread, apenas marca ela como “livre e pronta para ser utilizada novamente”.</p>
<h2 id="thread">Thread</h2>
<p>Ele faz isso porque o processo de criação e destruição de threads é extremamente custoso, envolvendo tarefas como: chamadas de sistema operacional, alocação de um bloco de memória grande, desalocação desse bloco de memória (no momento de matar a thread), etc.</p>
<p>Além disso há um outro problema relacionado a threads: o conceito de <strong>processamento paralelo na maioria das vezes é uma mentira</strong>. Isso mesmo. Ele existe desde antes de termos processadores multicores. Como? O SO na esmagadora maioria das vezes (em TODAS para processadores single core) não executa as tarefas em paralelo de fato, ele executa um pouco de uma tarefa, para, executa outra, para, executa outra, para, e assim por diante. O nome dado a esse “para e vai pra outra” é <a href="https://en.wikipedia.org/wiki/Context_switch">context switch</a>, algo extremamente custoso para a CPU. Quanto mais threads, mais context switches.</p>
<p>Mas veja bem, isso não quer dizer que threads são ruins. Na verdade há casos em que é melhor utilizar elas do que a engine do thread pool.</p>
<h4 id="em-resumo-e-já-adiantando-a-regra-básica-é">Em resumo, e já adiantando, a regra básica é:</h4>
<ul>
<li>Utilize o <strong>Thread Pool</strong> para tarefas <strong><em>“CPU Bound”</em></strong>. Exemplos: cálculos hash, operações em matrizes, algoritmos recursivos, loops que utilizam grandes quantidades de variáveis locais, operações de reflection, etc).</li>
<li>Utilize <strong>Threads</strong> para tarefas <strong><em>“I/O Bound”</em></strong>. Exemplos: Leituras ou escritas em arquivos no disco, chamadas para Web Services ou APIs, escritas em banco de dados, testes de carga simulando requisições a uma aplicação Web, etc).</li>
</ul>
<p>Veja bem, a regra é simples de entender: se a tarefa é CPU bound, ou seja, a maior carga de trabalho dela está em processamento de instruções no processador, não faz muito sentido eu abrir 5 threads diferentes para fazer esses processamentos sendo que eu tenho apenas 4 núcleos no meu CPU. A thread que sobrou está sedenta por um CPU inteirinho só pra ela.</p>
<p>Já para o outro caso, onde minha tarefa é resource bound, não faz muito sentido também eu abrir apenas 4 threads devido a preocupação de não atolar meu CPU, sendo que minha tarefa é apenas chamar um Web Service e deixar minhas threads assim:</p>
<div style="text-align:center">
<img src="http://www.fabriciorissetto.com/images/2017-02-03-threadsetasks/bored.png" />
</div>
<h2 id="back-to-the-problem">Back to the problem</h2>
<p>Sabendo disso, ficou claro para mim que o que eu precisava eram threads. No final das contas acabei com um código muito próximo desse (<a href="https://gist.github.com/fabriciorissetto/96b9db06f17bd10f4fdd0ab969a83845">gist completo aqui</a>):</p>
<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">quantidadeThreads</span> <span class="p">=</span> <span class="m">100</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="p"><</span> <span class="n">quantidadeThreads</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
<span class="p">{</span>
<span class="k">new</span> <span class="nf">Thread</span><span class="p">(</span><span class="k">new</span> <span class="nf">ThreadStart</span><span class="p">(()</span> <span class="p">=></span>
<span class="p">{</span>
<span class="c1">//Infinitamente aberta, sempre sincronizando eventos...</span>
<span class="k">while</span> <span class="p">(</span><span class="k">true</span><span class="p">)</span>
<span class="p">{</span>
<span class="nf">ObtemEventoDaFilaESincronizaComWebService</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">})).</span><span class="nf">Start</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Agora sim o negócio tava funcionando como eu queria:</p>
<div style="text-align:center">
<img src="http://www.fabriciorissetto.com/images/2017-02-03-threadsetasks/threads.gif" />
</div>
<p>Observem que também modifiquei a lógica do algoritmo. Ao invés de obter 1000 eventos da fila, criar 1000 threads pra sincronizá-los e em seguida destruí-las, eu optei por criar uma quantidade menor de threads (aproximadamente 100) e deixá-las abertas durante toda a execução do programa. <del>Poderia chamar essas 100 threads de “Pool” só pra confundir o post.</del> O conteúdo dessas threads é que era responsável por: obter o último evento da fila, sincronizá-lo.</p>
<p>Como cheguei nessa quantidade ideal de threads? Testes. Testando os limites da máquina descobri que com 1500 threads dava OutOfMemoryException, e que aproximadamente 500 já era suficiente pra deixar o CPU no talo (context switches).</p>
<h2 id="tasks">Tasks</h2>
<p>O segundo código que exemplifiquei no início do post utilizava tasks, mais especificamente o método <code class="language-plaintext highlighter-rouge">Task.Run()</code>. Conforme comentei, tasks por baixo dos panos utilizam o thread pool, por isso é indicado que sejam utilizadas para tarefas <em>CPU Bound</em>. Entretanto, há uma opção que nos permite informar que aquela task será “demorada”, isso faz com que a engine (na implementação atual) crie uma nova thread ao invés de utilizar uma do pool:</p>
<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">Task</span><span class="p">.</span><span class="n">Factory</span><span class="p">.</span><span class="nf">StartNew</span><span class="p">(()</span> <span class="p">=></span>
<span class="p">{</span>
<span class="c1">//Chamada do Web Service</span>
<span class="p">},</span> <span class="n">TaskCreationOptions</span><span class="p">.</span><span class="n">LongRunning</span><span class="p">);</span>
</code></pre></div></div>
<p>O código acima tem o mesmo efeito prático deste daqui:</p>
<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">new</span> <span class="nf">Thread</span><span class="p">(</span><span class="k">new</span> <span class="nf">ThreadStart</span><span class="p">(()</span> <span class="p">=></span>
<span class="p">{</span>
<span class="c1">//Chamada do Web Service</span>
<span class="p">})).</span><span class="nf">Start</span><span class="p">();</span>
</code></pre></div></div>
<p>Entretanto utilizar tasks (mesmo as long running) traz algumas facilidades para o desenvolvimento, tais como:</p>
<ol>
<li>Tasks podem retornar resultados. Threads não possuem um mecanismo direto pra isso.</li>
<li>Com o Wait é possível esperar por várias tasks sem precisar construir um mecanismo de sinais.</li>
<li>Tasks podem ter sua execução encadeada com facilidade.</li>
<li>Exceptions em tasks filhas propagam para tasks pais.</li>
<li>Tasks suportam cancelamento de maneira simples via token de cancelamento.</li>
</ol>
<p>Sendo assim, é possível utilizar tasks tanto para tarefas CPU bound quanto Resource bound <strong>contanto que se configure corretamente a opção “LongRunning” para esse segundo caso</strong>.</p>
<p>Mas não se esqueça, quando se fala em paralelismo normalmente estamos visando performance. Quando se trata de performance não podemos trabalhar com suposições. Nada melhor do que fazer testes, comparações e análises de comportamento do código para tirar conclusões se a solução está atendendo devidamente ao problema.</p>