<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Taverna do Kiko]]></title><description><![CDATA[Sr Software Developer]]></description><link>https://blog.kaiquegarcia.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 12:08:06 GMT</lastBuildDate><atom:link href="https://blog.kaiquegarcia.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Eu disse que não era um adeus]]></title><description><![CDATA[Mas também não quero dizer que estou de volta, infelizmente.
Olá, leitores do meu blog! Talvez não seja tão necessário mas devo dizer, que saudade de falar de PHP. Faz muito tempo que sequer encosto num código escrito nessa linguagem. Até cheguei a e...]]></description><link>https://blog.kaiquegarcia.dev/eu-disse-que-nao-era-um-adeus</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/eu-disse-que-nao-era-um-adeus</guid><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Wed, 23 Jul 2025 16:19:46 GMT</pubDate><content:encoded><![CDATA[<p>Mas também não quero dizer que estou de volta, infelizmente.</p>
<p>Olá, leitores do meu blog! Talvez não seja tão necessário mas devo dizer, que saudade de falar de PHP. Faz muito tempo que sequer encosto num código escrito nessa linguagem. Até cheguei a escrever alguns programas para tratar de uns freelances, mas nada perto do que costumava ser o dia-a-dia. O que não quer dizer que meu trabalho ficou mais fácil - e obviamente não seria o motivo de se tornar mais difícil, rs - apenas que deixei de ser 100% focado em desenvolver projetos em PHP para ser mais criterioso em resolver problemas da melhor forma que estiver disponível.</p>
<p>De qualquer forma, sinto que o blog ficou totalmente abandonado e pensei que chegaria por aqui e não encontraria ninguém. Para minha surpresa: o blog ainda recebe visitas diariamente, desde pessoas que estão começando no PHP (que era o propósito da série “PHP para Iniciantes”) quanto pessoas que estão revisitando tópicos que esqueceram por quaisquer motivos. Até eu já me peguei procurando um artigo no meu blog para lembrar de alguma coisa, haha. Já usei até para buscar documentações para assimilar alguma coisa de uma linguagem que desconheço. Eis a importância de se ter alguém na comunidade escrevendo releituras de documentações de forma didática: criar um conteúdo adicional para <strong>facilitar a compreensão de alguma coisa</strong>.</p>
<p>Caso não se lembrem (ou seja sua primeira vez por aqui, rs), eu criei, anos atrás, um servidor no Discord chamado “Code Aspiras”, com o objetivo de distribuir conhecimentos em reuniões que chamamos de “refinamento”, onde faríamos uma votação prévia para definir um assunto e depois apresentaríamos para quem estivesse interessado. Nesse servidor, incentivei a escrita de artigos como os que fiz nesse blog e até abri um blog para que os aspiras pudessem escrever seus artigos: <a target="_blank" href="https://blog.codeaspiras.dev/">https://blog.codeaspiras.dev/</a> . Assim como meu blog, o do Code Aspiras é gerenciado pelo HashNode.com, onde cada artigo publicado pode ser associado ao perfil de um autor. Portanto, quem escrevesse teria sua marcação de autoria, embora, ainda assim, estivesse promovendo o blog do grupo em conjunto. A ideia era poder promover meus mentorados e, simultaneamente, escalar a releitura das documentações.</p>
<p>Uma pena que, assim como os refinamentos, o blog do Code Aspiras não vingou. Não foi por falta de interesse. Acredito fortemente que meus mentorados queriam muito fazer essa roda girar, mas o principal objetivo do grupo era fazer todos os novatos conseguirem um emprego na área e crescerem: coisa que aconteceu e me dá muito orgulho. Estão todos empregados, sempre com notícias corriqueiras e cheio de tarefas, rs. Consequentemente, estamos todos sem tempo para escrever, hahah. Eu até conseguiria dedicar algumas horas do dia para escrever uma vez ou outra, mas me distanciei demais do PHP e já não consigo tirar a mesma quantidade de certezas que eu conseguia anteriormente. Aliás, já mudaram tanta coisa nas versões mais recentes do PHP que imagino que os problemas que eu conhecia dessa linguagem já não existam mais.</p>
<p>Enfim, a quem quer que ainda esteja por aqui, um muitíssimo obrigado por sempre visitar. Deixa um comentário, eu faço questão de responder! E, caso precise de ajuda sobre algo que não está no blog, fica a vontade de entrar no nosso Discord para perguntar, ok? O link é esse: <a target="_blank" href="https://discord.com/invite/V9crjS9jft">https://discord.com/invite/V9crjS9jft</a> .</p>
<p>PS.: isso segue não sendo um adeus. Mas com esse post, eu deixo claro que meu blog é meu e o conteúdo nem sempre vai ser sobre PHP, rs. Abs!</p>
<p>Inté!</p>
]]></content:encoded></item><item><title><![CDATA[GO: Desafio do Quiz (simplificado)]]></title><description><![CDATA[Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.
Olá, leitores do CodeAspiras!
Quem participa do nosso canal no Discord sabe que, de tempos em tempos,...]]></description><link>https://blog.kaiquegarcia.dev/go-desafio-do-quiz-simplificado</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/go-desafio-do-quiz-simplificado</guid><category><![CDATA[challenge]]></category><category><![CDATA[golang]]></category><category><![CDATA[Quiz]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Wed, 28 Feb 2024 13:12:37 GMT</pubDate><content:encoded><![CDATA[<p><em>Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.</em></p>
<p>Olá, leitores do CodeAspiras!</p>
<p>Quem participa do nosso canal no Discord sabe que, de tempos em tempos, nós lançamos alguns desafios de programação no canal #desafios. Alguns são bem simples, outros meio complexos. Eu vou destrinchar o que foi mais famoso até então por aqui pra disseminar conhecimento. <s>Se você gostar e quiser buscar mais desafios, é só chegar junto no Discord e ir fazendo o que estiver por lá</s>.</p>
<p>Ah, um detalhe antes de começar: esse é o desafio <strong>simplificado</strong>. O original exige um pouco mais de conhecimento, como leitura/escrita em arquivo, decodificar/encodar JSON, etc. Como ainda tem muito estudante no começo ainda, decidi retirar esses obstáculos e deixar o desafio mais simples, gerando o que verá a seguir.</p>
<center><img src="https://media.giphy.com/media/75yYfqYy5tmHm/giphy.gif?cid=790b7611o0l9w2k7ecqlo50a7f1q6fr228v9sdf4gigaijhj&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" /></center>

<h2 id="heading-o-desafio">O desafio</h2>
<blockquote>
<p>Faça um programa que inicializa algumas variáveis de um quiz, faz as perguntas para colher as respostas e imprime o resultado.</p>
</blockquote>
<p>Obs.: não está sendo determinado como seu programa deve funcionar!</p>
<h3 id="heading-impressao-esperada-no-terminal">Impressão esperada no terminal</h3>
<pre><code class="lang-bash">Pergunta 1: Essa seria a primeira pergunta...?
Opção 1: Sim...?
Opção 2: Não....?
Resposta: 1
--
Pergunta 2: Essa seria a terceira pergunta...?
Opção 1: Sim...?
Opção 2: Não....?
Resposta: 1
--
Resultado: você acertou 1 de 2 perguntas!!
</code></pre>
<p>E é isso, não tem mais nenhuma descrição. A ideia é que seu programa inicie já imprimindo:</p>
<pre><code class="lang-bash">Pergunta 1: Essa seria a primeira pergunta...?
Opção 1: Sim...?
Opção 2: Não....?
Resposta:
</code></pre>
<p>E aguarde o usuário responder. Daí o usuário responde <code>1</code>, que é a resposta correta.</p>
<p>Então seu programa continuará o processo, imprimindo uma separação e a próxima pergunta:</p>
<pre><code class="lang-bash">--
Pergunta 2: Essa seria a terceira pergunta...?
Opção 1: Sim...?
Opção 2: Não....?
Resposta:
</code></pre>
<p>E aí, mais uma vez, irá aguardar o usuário responder. Respondendo <code>1</code>, que é a resposta errada, o programa deverá então finalizar e imprimir uma separação e o resultado, informando que acertei apenas uma das duas perguntas:</p>
<pre><code class="lang-bash">--
Resultado: você acertou 1 de 2 perguntas!!
</code></pre>
<p>As únicas entradas do usuário são as respostas, que são números.</p>
<p>Sacou? Quer tentar desenvolver uma solução aí antes de continuar lendo?</p>
<p>Se for tentar, aprecie esse gif e só role a tela quando terminar!</p>
<center><img src="https://media.giphy.com/media/MZiuuEnG0KOvdu2Grw/giphy.gif?cid=ecf05e47rt7g50bibf5xejrd1z2o2yilnttkc2lsnkytl0ek&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" /></center>

<h2 id="heading-a-solucao-em-golang">A solução (em Golang)</h2>
<p>A maior dificuldade que as pessoas tem ao tentar solucionar desafios como esse é dar o primeiro passo. É como se você estivesse dirigindo um carro bem velho, dando partida no meio de uma ladeira. Se você tentou pensar em alguma coisa e não conseguiu, espero que possa absorver um pouco da técnica que vou te passar agora, que é infalível para construção de linhas de raciocínio.</p>
<p>Essa técnica se chama <strong>Baby Steps</strong>, que significa <strong>Passos de Bebê,</strong> em inglês. A ideia é que, ao invés de tentar montar, na sua cabeça, toda uma história de "começo, meio e fim", você deveria dar um passo de cada vez. Conforme você se torna experiente, será capaz de montar a história inteira na mente antes de colocar a mão na massa, mas enquanto não chega lá, não faz mal algum dar pequenos passos de bebê.</p>
<p>Nesse caso, eu já dei uma ajudinha ali em cima descrevendo que o desafio não está determinando como deve ficar seu código e exibindo, passo-a-passo, como as coisas devem aparecer no terminal.</p>
<blockquote>
<p>Nesse caso, você pode simplemente copiar tudo o que foi impresso no exemplo e... imprimir, Kiko?</p>
</blockquote>
<p>Sim! Exatamente! Supondo que você ainda está aprendendo a fazer códigos em Golang, vamos por parte:</p>
<h3 id="heading-1-imprimindo-todos-os-textos">1 - Imprimindo todos os textos</h3>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Pergunta 1</span>
    fmt.Println(<span class="hljs-string">"Pergunta 1: Essa seria a primeira pergunta...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 1: Sim...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 2: Não....?"</span>)
    fmt.Print(<span class="hljs-string">"Resposta: "</span>)
    <span class="hljs-comment">// ler resposta</span>
    fmt.Println(<span class="hljs-string">""</span>) <span class="hljs-comment">// retirar essa quebra de linha temporaria</span>
    fmt.Println(<span class="hljs-string">"--"</span>)

    <span class="hljs-comment">// Pergunta 2</span>
    fmt.Println(<span class="hljs-string">"Pergunta 2: Essa seria a terceira pergunta...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 1: Sim...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 2: Não....?"</span>)
    fmt.Print(<span class="hljs-string">"Resposta: "</span>)
    <span class="hljs-comment">// ler resposta</span>
    fmt.Println(<span class="hljs-string">""</span>) <span class="hljs-comment">// retirar essa quebra de linha temporaria</span>
    fmt.Println(<span class="hljs-string">"--"</span>)

    <span class="hljs-comment">// Conclusão</span>
    fmt.Println(<span class="hljs-string">"Resultado: você acertou 1 de 2 perguntas!!"</span>)
}
</code></pre>
<p>Veja o código no Playground: <a target="_blank" href="https://go.dev/play/p/HBrbJPnV_SY">https://go.dev/play/p/HBrbJPnV_SY</a></p>
<p>O código acima irá imprimir:</p>
<pre><code class="lang-bash">Pergunta 1: Essa seria a primeira pergunta...?
Opção 1: Sim...?
Opção 2: Não....?
Resposta: 
--
Pergunta 2: Essa seria a terceira pergunta...?
Opção 1: Sim...?
Opção 2: Não....?
Resposta: 
--
Resultado: você acertou 1 de 2 perguntas!!
</code></pre>
<p>Nesse momento, nós já estamos fazendo 90% do que foi pedido no desafio, concorda? Falta, literalmente, ler dois números. Caso não saiba como ler a entrada do terminal, basta pesquisar <code>&lt;linguagem&gt; scanf</code> e você vai achar alguns bons artigos explicando como fazer. Note que é importante ler mais do que um site pra tirar alguma conclusão, hein?</p>
<h3 id="heading-2-lendo-respostas">2 - Lendo respostas</h3>
<p>No caso do nosso desafio, eu poderia usar o pacote <code>bufio</code>, que nos permite ter mais controle sobre qual stream de entrada estamos utilizando e tal, mas, para simplificar, quero utilizar a função <code>Scanln</code> do pacote <code>fmt</code>. É similar ao <code>scanf</code> de algumas outras linguagens por aí. Quer ver?</p>
<p><em>PS.:<strong><strong>daqui para baixo</strong></strong>\</em>, para rodar o programa, precisará criar o arquivo localmente e rodando na mão. Pra fazer isso,*<em> [</em>baixe o Golang<em>](https://go.dev/doc/install)</em>, instale, depois crie uma pasta em qualquer lugar, abra essa pasta pelo terminal e digite<em><code>go mod init quizsimp</code></em>. Daí crie o arquivo<em><code>main.go</code></em>e cole o código nesse arquivo. Para executar, rode:*<code>go run .</code></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> resposta <span class="hljs-keyword">string</span>

    <span class="hljs-comment">// Pergunta 1</span>
    fmt.Println(<span class="hljs-string">"Pergunta 1: Essa seria a primeira pergunta...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 1: Sim...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 2: Não....?"</span>)

    <span class="hljs-comment">// Resposta 1</span>
    fmt.Print(<span class="hljs-string">"Resposta: "</span>)
    <span class="hljs-keyword">if</span> _, err := fmt.Scanln(&amp;resposta); err != <span class="hljs-literal">nil</span> {
        fmt.Printf(<span class="hljs-string">"Um erro aconteceu ao ler a resposta: %s\n"</span>, err)
        <span class="hljs-keyword">return</span>
    }

    fmt.Println(<span class="hljs-string">"--"</span>)

    <span class="hljs-comment">// Pergunta 2</span>
    fmt.Println(<span class="hljs-string">"Pergunta 2: Essa seria a terceira pergunta...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 1: Sim...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 2: Não....?"</span>)

    <span class="hljs-comment">// Resposta 2</span>
    fmt.Print(<span class="hljs-string">"Resposta: "</span>)
    <span class="hljs-keyword">if</span> _, err := fmt.Scanln(&amp;resposta); err != <span class="hljs-literal">nil</span> {
        fmt.Printf(<span class="hljs-string">"Um erro aconteceu ao ler a resposta: %s\n"</span>, err)
        <span class="hljs-keyword">return</span>
    }

    fmt.Println(<span class="hljs-string">"--"</span>)

    <span class="hljs-comment">// Conclusão</span>
    fmt.Println(<span class="hljs-string">"Resultado: você acertou 1 de 2 perguntas!!"</span>)
}
</code></pre>
<h3 id="heading-3-contabilizando-acertos">3 - Contabilizando acertos</h3>
<p>Agora você está armazenando a resposta do usuário na nova variável <code>resposta</code>, certo? Só que não estamos fazendo nada com isso!! Que tal adicionarmos uma outra variável <code>acertos</code> que contabiliza quantas respostas foram certas?</p>
<p>Além disso, podemos mudar a impressão de resultados de <code>Println</code> para <code>Printf</code> e formatar o texto, injetando o número de acertos:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> resposta <span class="hljs-keyword">string</span>
    acertos := <span class="hljs-number">0</span>

    <span class="hljs-comment">// Pergunta 1</span>
    fmt.Println(<span class="hljs-string">"Pergunta 1: Essa seria a primeira pergunta...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 1: Sim...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 2: Não....?"</span>)

    <span class="hljs-comment">// Resposta 1</span>
    fmt.Print(<span class="hljs-string">"Resposta: "</span>)
    <span class="hljs-keyword">if</span> _, err := fmt.Scanln(&amp;resposta); err != <span class="hljs-literal">nil</span> {
        fmt.Printf(<span class="hljs-string">"Um erro aconteceu ao ler a resposta: %s\n"</span>, err)
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-keyword">if</span> resposta == <span class="hljs-string">"1"</span> {
        acertos++
    }

    fmt.Println(<span class="hljs-string">"--"</span>)

    <span class="hljs-comment">// Pergunta 2</span>
    fmt.Println(<span class="hljs-string">"Pergunta 2: Essa seria a terceira pergunta...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 1: Sim...?"</span>)
    fmt.Println(<span class="hljs-string">"Opção 2: Não....?"</span>)

    <span class="hljs-comment">// Resposta 2</span>
    fmt.Print(<span class="hljs-string">"Resposta: "</span>)
    <span class="hljs-keyword">if</span> _, err := fmt.Scanln(&amp;resposta); err != <span class="hljs-literal">nil</span> {
        fmt.Printf(<span class="hljs-string">"Um erro aconteceu ao ler a resposta: %s\n"</span>, err)
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-keyword">if</span> resposta == <span class="hljs-string">"2"</span> {
        acertos++
    }

    fmt.Println(<span class="hljs-string">"--"</span>)

    <span class="hljs-comment">// Conclusão</span>
    fmt.Printf(<span class="hljs-string">"Resultado: você acertou %d de 2 perguntas!!\n"</span>, acertos)
}
</code></pre>
<p>E pronto! Solucionamos o desafio............... Certo?</p>
<center><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExbWZqc2FoNDh5cjRzaDByZmtob29nb25xdGpodjZlZjJyMTh4MGswbCZlcD12MV9naWZzX3NlYXJjaCZjdD1n/406ZMCwmTzYfo4E9cS/giphy.gif" /></center>

<p>A verdade é que estamos gerando a mesma saída esperada que coloquei no começo desse desafio. Então, <strong>sim, solucionamos</strong>, porém não está nada elegante. Se quisermos fazer um Quiz com 100 perguntas, esse código ficaria gigantesco!</p>
<p>Nós podemos separar um pouco as responsabilidades aqui: que tal agruparmos todos os dados de cada pergunta em uma estrutura, deixando, então, o trecho de impressão/leitura fica responsável apenas por isso mesmo, simplificando os deveres?</p>
<h3 id="heading-4-organizando-dados-em-estruturas">4 - Organizando dados em estruturas</h3>
<blockquote>
<p>E o que teria nessa estrutura de pergunta, Kiko?</p>
</blockquote>
<p>Bem... A pergunta em si, as opções e a resposta esperada (vulgo gabarito). Seria algo assim:</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> QuizItem <span class="hljs-keyword">struct</span> {
    Question <span class="hljs-keyword">string</span>
    Options <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>
    RightOptionIndex <span class="hljs-keyword">string</span>
}
</code></pre>
<p>E poderíamos organizar a primeira pergunta assim:</p>
<pre><code class="lang-go">QuizItem{
    Question: <span class="hljs-string">"Essa seria a primeira pergunta...?"</span>,
    Options: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>{
        <span class="hljs-string">"1"</span>: <span class="hljs-string">"Sim...?"</span>,
        <span class="hljs-string">"2"</span>: <span class="hljs-string">"Não....?"</span>,
    },
    RightOptionIndex: <span class="hljs-string">"1"</span>,
}
</code></pre>
<p>E, com isso, teríamos quase todas as informações para imprimir tudo, concorda?</p>
<blockquote>
<p>Como assim, quase todas, Kiko?</p>
</blockquote>
<p>É que falta sabermos qual é o número dessa pergunta. Como a ideia é termos uma lista de perguntas, teremos essa informação de outro lugar. Enfim, vamos transformar o código:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> QuizItem <span class="hljs-keyword">struct</span> {
    Question         <span class="hljs-keyword">string</span>
    Options          <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>
    RightOptionIndex <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// prepara o quiz</span>
    quiz := []QuizItem{
        {
            Question: <span class="hljs-string">"Essa seria a primeira pergunta...?"</span>,
            Options: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>{
                <span class="hljs-string">"1"</span>: <span class="hljs-string">"Sim...?"</span>,
                <span class="hljs-string">"2"</span>: <span class="hljs-string">"Não....?"</span>,
            },
            RightOptionIndex: <span class="hljs-string">"1"</span>,
        },
        {
            Question: <span class="hljs-string">"Essa seria a terceira pergunta...?"</span>,
            Options: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>{
                <span class="hljs-string">"1"</span>: <span class="hljs-string">"Sim...?"</span>,
                <span class="hljs-string">"2"</span>: <span class="hljs-string">"Não....?"</span>,
            },
            RightOptionIndex: <span class="hljs-string">"2"</span>,
        },
    }

    <span class="hljs-comment">// executa o quiz</span>
    acertos := <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> index, item := <span class="hljs-keyword">range</span> quiz {
        <span class="hljs-comment">// número da pergunta vem do index+1 !</span>
        fmt.Printf(<span class="hljs-string">"Pergunta %d: %s\n"</span>, index+<span class="hljs-number">1</span>, item.Question)

        <span class="hljs-keyword">for</span> num, opt := <span class="hljs-keyword">range</span> item.Options {
            fmt.Printf(<span class="hljs-string">"Opção %s: %s\n"</span>, num, opt)
        }

        fmt.Print(<span class="hljs-string">"Resposta: "</span>)
        <span class="hljs-keyword">var</span> resposta <span class="hljs-keyword">string</span>
        <span class="hljs-keyword">if</span> _, err := fmt.Scanln(&amp;resposta); err != <span class="hljs-literal">nil</span> {
            fmt.Printf(<span class="hljs-string">"Um erro aconteceu ao ler a resposta: %s\n"</span>, err)
            <span class="hljs-keyword">return</span>
        }

        <span class="hljs-keyword">if</span> resposta == item.RightOptionIndex {
            acertos++
        }

        fmt.Println(<span class="hljs-string">"--"</span>)
    }

    <span class="hljs-comment">// Conclusão</span>
    fmt.Printf(<span class="hljs-string">"Resultado: você acertou %d de 2 perguntas!!\n"</span>, acertos)
}
</code></pre>
<center><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYjdqcGhuMG53Y2FzcXIyMXA5aXRyNmF2ZG1rMnl5bGt0cG1xZ2s2MiZlcD12MV9naWZzX3NlYXJjaCZjdD1n/LoIsP3fz02IjOUTc6t/giphy.gif" /></center>

<p>E podemos ir ainda além!! E se quisermos exibir o resultado em forma de gabarito? Bem, só faz sentido se você puder distinguir as opções corretas das erradas, concorda? E pra isso você pode usar símbolos e tal, mas eu prefiro <strong>COLORIR</strong>.</p>
<h3 id="heading-5-exibindo-gabarito-apos-resultado">5 - Exibindo gabarito após resultado</h3>
<blockquote>
<p>Oi?! Dá pra colorir texto no terminal, Kiko?</p>
</blockquote>
<p>Sim, dá! E para isso é só usarmos um comando que altera as propriedades de texto do terminal. Eu não sei exatamente qual é o nome disso, até tentei pesquisar mas parece que cada pessoa chama do jeito que quer, então não me ajudou muito, rs. Então vamos chamar do nosso jeito também! E deixo isso aberto para que alguém me corrija publicamente a vontade, hehe.</p>
<p>Eu chamo esse comando de <strong>Editor de Fonte</strong>. Ele funciona como uma tag HTML, tendo um comando no início de onde você quer trocar a fonte e outro no final. Em algumas linguagens, você pode acessar esse escape pela inicial <code>\e</code>, mas em Golang nós acessamos pela inicial <code>\033</code>:</p>
<ul>
<li><p>Começa com: <code>\033[&lt;nums&gt;m</code></p>
</li>
<li><p>Termina com: <code>\033[0m</code></p>
</li>
</ul>
<p>Nesse caso, a ideia é que, no lugar de <code>&lt;nums&gt;</code>, você coloque os números que vão definir o estilo de fonte a utilizar no trecho seguinte. Depois que acabar de imprimir o texto no estilo desejado, você reseta o estilo novamente com <code>\033[0m</code>. Sim, <code>0</code> é um dos possíveis códigos a se colocar no lugar de <code>&lt;nums&gt;</code>. E quando utilizamos mais de um código, nós separamos eles com ponto-e-vírgula (;).</p>
<p>Eu não vou colocar nenhuma tabela dos possíveis estilos aqui, mas o que nos interessa no momento:</p>
<ul>
<li><p>cor vermelha: <code>31</code>;</p>
</li>
<li><p>cor verde: <code>32</code>.</p>
</li>
</ul>
<p>Então, se você quiser imprimir uma linha vermelha, é só imprimir:</p>
<pre><code class="lang-go">fmt.Println(<span class="hljs-string">"\033[31mEsse é o estilo com a cor vermelha\033[0m"</span>)
</code></pre>
<p>Dito isso, podemos fazer três constantes com as cores e uma função para fazer essa impressão formatada, o que acha?</p>
<pre><code class="lang-go"><span class="hljs-keyword">const</span> (
    COLOR_RED = <span class="hljs-string">"31"</span>
    COLOR_GREEN = <span class="hljs-string">"32"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">printStyled</span><span class="hljs-params">(text <span class="hljs-keyword">string</span>, styles ...<span class="hljs-keyword">string</span>)</span></span> {
    fmt.Println(<span class="hljs-string">"\033["</span> + strings.Join(styles, <span class="hljs-string">";"</span>) + <span class="hljs-string">"m"</span> + text + <span class="hljs-string">"\033[0m"</span>)
}
</code></pre>
<p>Assim, é só chamar:</p>
<pre><code class="lang-go">printStyled(<span class="hljs-string">"Opção 1: ..."</span>, COLOR_GREEN) <span class="hljs-comment">// para opções corretas</span>
printStyled(<span class="hljs-string">"Opção 2: ..."</span>, COLOR_RED) <span class="hljs-comment">// para opções marcadas incorretamente</span>
</code></pre>
<p>Mas ainda não estamos prontos, pois... Não salvamos nenhuma resposta do usuário.</p>
<p>Então vamos adicionar uma nova informação no <code>QuizItem</code>: <code>Answer string</code>, além de mudar o slice <code>[]QuizItem</code> para <code>[]*QuizItem</code> para usarmos sempre as mesmas referências, alterando e salvando as respostas na própria estrutura:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> QuizItem <span class="hljs-keyword">struct</span> {
    Question         <span class="hljs-keyword">string</span>
    Options          <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>
    RightOptionIndex <span class="hljs-keyword">string</span>
    Answer           <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// prepara o quiz</span>
    quiz := []*QuizItem{
        {
            Question: <span class="hljs-string">"Essa seria a primeira pergunta...?"</span>,
            Options: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>{
                <span class="hljs-string">"1"</span>: <span class="hljs-string">"Sim...?"</span>,
                <span class="hljs-string">"2"</span>: <span class="hljs-string">"Não....?"</span>,
            },
            RightOptionIndex: <span class="hljs-string">"1"</span>,
        },
        {
            Question: <span class="hljs-string">"Essa seria a terceira pergunta...?"</span>,
            Options: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>{
                <span class="hljs-string">"1"</span>: <span class="hljs-string">"Sim...?"</span>,
                <span class="hljs-string">"2"</span>: <span class="hljs-string">"Não....?"</span>,
            },
            RightOptionIndex: <span class="hljs-string">"2"</span>,
        },
    }

    <span class="hljs-comment">// executa o quiz</span>
    acertos := <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> index, item := <span class="hljs-keyword">range</span> quiz {
        fmt.Printf(<span class="hljs-string">"Pergunta %d: %s\n"</span>, index+<span class="hljs-number">1</span>, item.Question)

        <span class="hljs-keyword">for</span> num, opt := <span class="hljs-keyword">range</span> item.Options {
            fmt.Printf(<span class="hljs-string">"Opção %s: %s\n"</span>, num, opt)
        }

        fmt.Print(<span class="hljs-string">"Resposta: "</span>)
        <span class="hljs-keyword">if</span> _, err := fmt.Scanln(&amp;item.Answer); err != <span class="hljs-literal">nil</span> {
            fmt.Printf(<span class="hljs-string">"Um erro aconteceu ao ler a resposta: %s\n"</span>, err)
            <span class="hljs-keyword">return</span>
        }

        <span class="hljs-keyword">if</span> item.Answer == item.RightOptionIndex {
            acertos++
        }

        fmt.Println(<span class="hljs-string">"--"</span>)
    }

    <span class="hljs-comment">// Conclusão</span>
    fmt.Printf(<span class="hljs-string">"Resultado: você acertou %d de 2 perguntas!!\n"</span>, acertos)
}
</code></pre>
<p>E agora, podemos fazer um novo loop nas perguntas, colorindo as respostas corretas e erradas!!</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"strings"</span>
)

<span class="hljs-keyword">const</span> (
    COLOR_RED    = <span class="hljs-string">"31"</span>
    COLOR_GREEN  = <span class="hljs-string">"32"</span>
)

<span class="hljs-keyword">type</span> QuizItem <span class="hljs-keyword">struct</span> {
    Question         <span class="hljs-keyword">string</span>
    Options          <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>
    RightOptionIndex <span class="hljs-keyword">string</span>
    Answer           <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">printStyled</span><span class="hljs-params">(text <span class="hljs-keyword">string</span>, styles ...<span class="hljs-keyword">string</span>)</span></span> {
    fmt.Print(<span class="hljs-string">"\033["</span> + strings.Join(styles, <span class="hljs-string">";"</span>) + <span class="hljs-string">"m"</span> + text + <span class="hljs-string">"\033[0m"</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// prepara o quiz</span>
    quiz := []*QuizItem{
        {
            Question: <span class="hljs-string">"Essa seria a primeira pergunta...?"</span>,
            Options: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>{
                <span class="hljs-string">"1"</span>: <span class="hljs-string">"Sim...?"</span>,
                <span class="hljs-string">"2"</span>: <span class="hljs-string">"Não....?"</span>,
            },
            RightOptionIndex: <span class="hljs-string">"1"</span>,
        },
        {
            Question: <span class="hljs-string">"Essa seria a terceira pergunta...?"</span>,
            Options: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>{
                <span class="hljs-string">"1"</span>: <span class="hljs-string">"Sim...?"</span>,
                <span class="hljs-string">"2"</span>: <span class="hljs-string">"Não....?"</span>,
            },
            RightOptionIndex: <span class="hljs-string">"2"</span>,
        },
    }

    <span class="hljs-comment">// executa o quiz</span>
    acertos := <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> index, item := <span class="hljs-keyword">range</span> quiz {
        fmt.Printf(<span class="hljs-string">"Pergunta %d: %s\n"</span>, index+<span class="hljs-number">1</span>, item.Question)

        <span class="hljs-keyword">for</span> num, opt := <span class="hljs-keyword">range</span> item.Options {
            fmt.Printf(<span class="hljs-string">"Opção %s: %s\n"</span>, num, opt)
        }

        fmt.Print(<span class="hljs-string">"Resposta: "</span>)
        <span class="hljs-keyword">if</span> _, err := fmt.Scanln(&amp;item.Answer); err != <span class="hljs-literal">nil</span> {
            fmt.Printf(<span class="hljs-string">"Um erro aconteceu ao ler a resposta: %s\n"</span>, err)
            <span class="hljs-keyword">return</span>
        }

        <span class="hljs-keyword">if</span> item.Answer == item.RightOptionIndex {
            acertos++
        }

        fmt.Println(<span class="hljs-string">"--"</span>)
    }

    <span class="hljs-comment">// gabarito</span>
    fmt.Println(<span class="hljs-string">"Gabarito:"</span>)
    <span class="hljs-keyword">for</span> index, item := <span class="hljs-keyword">range</span> quiz {
        fmt.Printf(<span class="hljs-string">"Pergunta %d: %s\n"</span>, index+<span class="hljs-number">1</span>, item.Question)

        <span class="hljs-keyword">for</span> num, opt := <span class="hljs-keyword">range</span> item.Options {
            label := fmt.Sprintf(<span class="hljs-string">"Opção %s: %s"</span>, num, opt)
            <span class="hljs-keyword">if</span> num == item.RightOptionIndex {
                printStyled(label, COLOR_GREEN)
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> num == item.Answer {
                printStyled(label, COLOR_RED)
            } <span class="hljs-keyword">else</span> {
                fmt.Print(label)
            }

            fmt.Println(<span class="hljs-string">""</span>)
        }

        fmt.Println(<span class="hljs-string">"--"</span>)
    }

    <span class="hljs-comment">// Conclusão</span>
    fmt.Printf(<span class="hljs-string">"Resultado: você acertou %d de 2 perguntas!!\n"</span>, acertos)
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709125073516/e28e1356-1cec-4c08-88d7-bdea768b3806.png" alt="Print do resultado final do código final" class="image--center mx-auto" /></p>
<h2 id="heading-conclusao">Conclusão</h2>
<p>Nesse desafio, nós fizemos um código estritamente imperativo, mas poderíamos evoluir ainda mais. Por exemplo, eu fiz <a target="_blank" href="https://github.com/codeaspiras/goquiz">minha versão do desafio com Bubbletea, sendo o desafio completo (lendo arquivos)</a>. Enfim, essa é uma excelente atividade para iniciantes! Vocês aprendem a colocar em prática várias coisas de uma vez só. Além disso, você pode brincar com seus colegas fazendo perguntas reais nos programas finais! E se puder aceitar múltiplas respostas? E se for um Quiz de <code>scoring</code> ao invés de gabarito? No <code>scoring</code>, não existe opção errada, apenas pontuações. No final, o total de pontuação do usuário varia pelas opções marcadas, encaixando ele em algum grupo de pontuações esperadas. O que acha de desenrolar esse desafio?</p>
<hr />
<p>E por hoje é só! Curtiu? Comenta e compartilha!! <s>Como falei no início, temos outros desafios lá no canal do Discord. Pode chegar que a casa é aberta, rs</s>. Qualquer coisa, é só falar aí nos comentários!</p>
<p>Abraços...</p>
<p>Inté!</p>
]]></content:encoded></item><item><title><![CDATA[Recapitulação: Data-Transfer Object]]></title><description><![CDATA[Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.
Olá, leitores do CodeAspiras!
Estava aqui revisando os vídeos do nosso canal no YouTube e me deparei ...]]></description><link>https://blog.kaiquegarcia.dev/recapitulacao-data-transfer-object</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/recapitulacao-data-transfer-object</guid><category><![CDATA[data-transfer object]]></category><category><![CDATA[refinamento]]></category><category><![CDATA[dto]]></category><category><![CDATA[discord]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Wed, 07 Feb 2024 11:34:48 GMT</pubDate><content:encoded><![CDATA[<p><em>Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.</em></p>
<p>Olá, leitores do CodeAspiras!</p>
<p>Estava aqui revisando os vídeos do nosso canal no YouTube e me deparei com o refinamento onde falamos sobre DTOs, estrutura que mencionei em um artigo de Golang anteriormente nesse blog. Esse vídeo traz outros exemplos sobre como usar DTO e quais suas limitações. Por isso, vou indicar o vídeo por aqui, beleza?!</p>
<p>A curtida no vídeo é opcional (não está público mesmo), mas no blog é lei, hein?!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=0j3AoTUE7vE">https://www.youtube.com/watch?v=0j3AoTUE7vE</a></div>
<p> </p>
<p>Assim como esse, temos outros refinamentos ocultos em nosso canal no YouTube. <s>Você pode acessar todos eles pelo nosso Discord! No canal </s> <strong><s>#log</s></strong><s>, fica o registro de todos os refinamentos que fizemos, materiais trabalhados, link do vídeo, etc. Fique a vontade para explorar lá ;)</s></p>
<hr />
<p>Curtiu?! Comenta e compartilha! O que acha de divulgarmos mais vídeos dos refinamentos que fazíamos pelo Discord? E se voltássemos a fazer os refinamentos? Deixa aí sua opinião... Abraço!</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[GO: Como tratar erros?]]></title><description><![CDATA[Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.
Olá, leitores do CodeAspiras! Tudo bem por aí?
Estamos de volta com mais um artigo sobre Golang, dess...]]></description><link>https://blog.kaiquegarcia.dev/go-como-tratar-erros</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/go-como-tratar-erros</guid><category><![CDATA[golang]]></category><category><![CDATA[error handling]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Fri, 02 Feb 2024 16:29:13 GMT</pubDate><content:encoded><![CDATA[<p><em>Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.</em></p>
<p>Olá, leitores do <strong>CodeAspiras</strong>! Tudo bem por aí?</p>
<p>Estamos de volta com mais um artigo sobre Golang, dessa vez falando sobre tratativa de erros e explicando mais um conceito relevante pra quem está começando a trabalhar nessa linguagem.</p>
<p>Primeiramente, gostaria de destacar o fato de que muitas pessoas odeiam os fluxos de erro do Golang, porque ficam com a sensação de que somos obrigados a criar diversas operações de condição para tratativas de erro.</p>
<p>É comum ficar puto por isso aqui, oh:</p>
<pre><code class="lang-go">_, err := algumacoisa()
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, err
}
</code></pre>
<p><img src="https://media.giphy.com/media/BbJdwrOsM7nTa/giphy.gif?cid=ecf05e47jv27utzodqm5eo09qrmls4aevwsrzldisxptsgi6&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="Um GIF de uma cena do filme &quot;The Smile Man&quot;, mostrando o ator Willem Dafoe com uma expressão que todos podem associar a uma crise absurda de ansiedade." class="image--center mx-auto" /></p>
<p>Esse é um padrão que se repete bastante em todo o fluxo do seu código. É praticamente certo dizer que, quanto mais funções você desenvolve, mais checagens de erro você precisará injetar.</p>
<h2 id="heading-o-jeito-errado">O jeito errado</h2>
<blockquote>
<p>Ah, Kiko, eu burlei isso. Eu decidi lançar <code>panic</code> e tratar com <code>recover()</code>.</p>
</blockquote>
<p><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNTM1bG5pcXMwd2dzbnU3MDR6NDl1a3N1dW8xNWE2YmVtNnl3NDNvcyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/1EghTrigJJhq8/giphy.gif" alt="GIF do fantoche de Kermit Muppet desesperado, em pânico." class="image--center mx-auto" /></p>
<p>Por favor, <strong>NÃO FAÇA ISSO</strong>. Você só deve lançar <code>panic</code> em cenários que deveriam ser impossíveis de acontecer. Além disso, assumir que todos os trechos de código que chamarem sua função vão estar preparados para tratar <code>panic</code> como fluxo de erros comuns, definitivamente, não é uma boa forma de manter a qualidade do seu código em dia.</p>
<p>Infelizmente, o certo é <strong><mark>aprender a lidar com os erros</mark></strong>. É até filosófico colocar a frase desse jeito, né? A ideia é que você se acostume com o fato de que, sim, <strong>seu código vai falhar</strong>. Algumas falhas serão esperadas na regra de negócio, outras não.</p>
<p>Por exemplo, erros de validação são sempre falhas esperadas, se não você nem validaria, sabe? Erros de conexão ao banco de dados também são esperados, afinal, <strong><mark>toda e qualquer transmissão de dados está exposta à falhas temporárias</mark></strong>. Isso não é motivo para gerar um <code>panic</code>. Falhas de <code>parsing</code> também são esperadas - isso é, inclusive, uma forma de validação de dados. No geral, é pouco provável que você precise declarar qualquer sentença explícita de <code>panic</code>.</p>
<p>Ainda assim, é uma boa prática ter tratativas de <code>panic</code> com <code>recover()</code> na camada mais "alta" da aplicação. Por exemplo, em caso de servidores web, você pode fazer com que todas as suas rotas usem um middleware de recuperação de <code>panic</code>. E é um middleware bem simples:</p>
<pre><code class="lang-go">
<span class="hljs-keyword">defer</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
    panicError := <span class="hljs-built_in">recover</span>()
    <span class="hljs-keyword">if</span> panicError == <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-comment">// trata o panicError, enviando algum log ou sei lá o quê, mas impedindo o servidor de parar de funcionar</span>
    <span class="hljs-comment">// também deve encerrar a conexão da requisição, mandando algum status do que aconteceu para quem a enviou</span>
}()
<span class="hljs-comment">// suponha que a variável "next" segue a implementação de http.HandlerFunc: https://pkg.go.dev/net/http#HandlerFunc</span>
<span class="hljs-comment">// w é http.ResponseWriter</span>
<span class="hljs-comment">// r é *http.Request</span>
next.ServeHTTP(w, r)
</code></pre>
<p>Se acontecer um <code>panic</code> durante a execução do handler, o código acionado no <code>defer</code> irá impedir que o processo do servidor seja encerrado, garantindo que falhas inesperadas <strong>não</strong> matem o serviço.</p>
<p>Já no caso de comandos CLI, que você roda no terminal e só executa uma tarefa, não faz sentido colocar tratativa de <code>panic</code>. Deixa o problema estourar e veja o que aparece no terminal... A menos, é claro, que seu terminal esteja programado para fechar automaticamente. Aí sim, você pode fazer uma tratativa de <code>recover()</code> pedindo para o usuário digitar algo para continuar antes de encerrar o código.</p>
<p><img src="https://media.giphy.com/media/nrXif9YExO9EI/giphy.gif?cid=790b7611535lniqs0wgsnu704z49uksuuo15a6bem6yw43os&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="Bob Esponja tentando apagar um incêndio embaixo d'água... assoprando o fogo." class="image--center mx-auto" /></p>
<h2 id="heading-o-jeito-certo">O jeito certo</h2>
<p>Voltando aos erros, o certo é sempre transferir os erros até a camada "mais alta", <strong>sempre</strong>. Claro, se sua intenção não for interromper o fluxo, você pode só enviar um log de erro e continuar o fluxo normalmente sem nenhum <code>return</code>. A ideia é que você jamais ignore um cenário de erro. E aí, quando esse bendito erro respingar no handler da requisição ou no fluxo principal da aplicação, você pode verificar qual erro que aconteceu e tomar uma decisão adequada para tal.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"errors"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">vaiDarRuim</span><span class="hljs-params">()</span> <span class="hljs-title">error</span></span> {
    <span class="hljs-keyword">return</span> errors.New(<span class="hljs-string">"deu ruim"</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">vouTentar</span><span class="hljs-params">()</span> <span class="hljs-title">error</span></span> {
    <span class="hljs-comment">// isso aqui é meramente ilustrativo</span>
    <span class="hljs-comment">// na prática, eu teria colocado um "return vaiDarRuim()" direto</span>
    err := vaiDarRuim()
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span> err
    }

    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    err := vouTentar()
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        <span class="hljs-comment">// deu ruim, faz alguma coisa, loga, sei lá, reaja</span>
        <span class="hljs-keyword">return</span>
    }

    <span class="hljs-comment">// deu bom, uhu</span>
}
</code></pre>
<p>Mas se você cria um erro durante o fluxo do código, como você faz para detectar qual foi o erro? Bem, uma forma é verificar o texto:</p>
<pre><code class="lang-go"><span class="hljs-keyword">switch</span>(err.Error()) {
<span class="hljs-keyword">case</span> <span class="hljs-string">"deu ruim"</span>:
     <span class="hljs-comment">// trata o cenário "deu ruim"</span>
<span class="hljs-keyword">default</span>:
     <span class="hljs-comment">// trata um cenário imprevisto</span>
}
</code></pre>
<p>Porém isso não é recomendado, pois nada impede que dois erros de contextos diferentes tenham exatamente o mesmo texto, correto? Então não faz sentido analisar a mensagem de erro em si, mas a instância.</p>
<p>E nesse caso, para comparar instâncias significa que você precisa ter isso centralizado em um lugar: um pacote de erros. Independente se você prefere definir structs distintas de erro, inicializar erros com <code>errors.New()</code> ou <code>fmt.Errorf()</code>, o fato é que seus erros precisam ficar em um pacote sem referências a outras partes do projeto. Isso é sério, se você referenciar qualquer outro pacote da aplicação, você pode gerar um problema de importação cíclica.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> errs

<span class="hljs-keyword">import</span> <span class="hljs-string">"errors"</span>

<span class="hljs-keyword">var</span> (
    ErrDeuRuim = errors.New(<span class="hljs-string">"deu ruim"</span>)
)
</code></pre>
<p>Com essa variável, agora poderíamos mudar a função <code>vaiDarRuim</code> para:</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">vaiDarRuim</span><span class="hljs-params">()</span> <span class="hljs-title">error</span></span> {
    <span class="hljs-keyword">return</span> errs.ErrDeuRuim
}
</code></pre>
<p>E a tratativa de erros para:</p>
<pre><code class="lang-go"><span class="hljs-keyword">switch</span>(err) {
<span class="hljs-keyword">case</span> errs.ErrDeuRuim:
    <span class="hljs-comment">// agora sim, deu ruim mesmo</span>
<span class="hljs-keyword">default</span>:
    <span class="hljs-comment">//...</span>
}
</code></pre>
<p><img src="https://media.giphy.com/media/9J7tdYltWyXIY/giphy.gif?cid=790b7611c9wy2xoc75znhh0ahbgo1ychv0uxoibqhj0f8bod&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="GIF do meme do John Travolta perdido, tendo como fundo uma foto do erro do Google Chrome sem conexão com internet." class="image--center mx-auto" /></p>
<h2 id="heading-conclusao">Conclusão</h2>
<p>Depois de passar um tempo implementando esse pacote em vários projetos, comecei a sentir uma maior facilidade em várias coisas. Por exemplo, se alguém pergunta "<strong>qual a lista de possíveis erros da aplicação?</strong>", eu consigo rapidamente checar tudo em um pacote só. Obviamente, o erro daqui não demonstra muita coisa, afinal, a frase era uma string fixa, então não é muito difícil de migrar casos como esse. Os erros mais complexos de se transferir para o pacote foram os que tinham alguma injeção de valor no texto. E aí, ao invés de ter uma variável fixa de erro, eu tive de fazer uma <code>struct</code> implementando a interface <code>error</code>. Logo, na hora de analisar se o erro era o mesmo dessa <code>struct</code>, eu tinha de fazer a validação por casting:</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> errCast, castable := err.(errs.ErrViaStruct); castable {
    <span class="hljs-comment">// é o erro da struct errs.ErrViaStruct{}</span>
}
</code></pre>
<p>O pacote <code>errors</code> até provê algumas funções como <code>errors.Is()</code> e <code>errors.As()</code>, mas não sinto muita segurança em utilizá-las, pois cada pacote que importo trata seus erros de forma diferente e essas funções não funcionam para todas as maneiras de lidar com erros.</p>
<p>E o mais importante é apenas criar tratativas especiais, não necessariamente identificar todos os erros possíveis em um <code>switch-case</code> só. Então a grande maioria dos erros que preciso tratar são de variáveis fixas. Vale a pena a implementação.</p>
<p>Indicação de leitura</p>
<ul>
<li><p><a target="_blank" href="https://www.digitalocean.com/community/tutorials/creating-custom-errors-in-go">Creating Custom Errors in Go (Digital Ocean)</a>;</p>
</li>
<li><p><a target="_blank" href="https://blog.logrocket.com/error-handling-golang-best-practices/">Error handling in Go: Best practices</a> (<a target="_blank" href="https://blog.logrocket.com/author/raphaelugwu/">Raphael Ugwu</a> via <a target="_blank" href="https://logrocket.com/">LogRocket</a>).</p>
</li>
</ul>
<hr />
<p>E é isso aí! Curtiu? Comenta e compartilha! <s>Está sentindo falta de algum artigo de uma linguagem específica? É só pedir que, se eu souber, eu escrevo alguma coisa, rs. Quero ver, hein?</s> Abraço!</p>
<p><strong>Inté</strong>!</p>
]]></content:encoded></item><item><title><![CDATA[Arquitetura: Dá pra usar uma planilha do Google como banco de dados de um front-end?]]></title><description><![CDATA[TL;DR: Sim, mas, por segurança, faça um back-end puxar os dados para o seu projeto de front-end, pelo menos.
Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se pe...]]></description><link>https://blog.kaiquegarcia.dev/arquitetura-da-pra-usar-uma-planilha-do-google-como-banco-de-dados-de-um-front-end</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/arquitetura-da-pra-usar-uma-planilha-do-google-como-banco-de-dados-de-um-front-end</guid><category><![CDATA[spreadsheets]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Thu, 01 Feb 2024 17:48:51 GMT</pubDate><content:encoded><![CDATA[<p><strong><em>TL;DR</em></strong>: <em>Sim, mas, por segurança, faça um back-end puxar os dados para o seu projeto de front-end, pelo menos.</em></p>
<p><em>Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.</em></p>
<p>Olá, leitores do CodeAspiras! Tudo tranquilo por aí?</p>
<p>Conforme prometido, segue um artigo que não seja de <strong>Golang</strong>! Sinceramente, eu quase publiquei um, mas lembrei da nossa promessa e resolvi mantê-lo em rascunho, rs. Então refleti sobre possíveis assuntos que poderia trazer a tona aqui no blog e lembrei de uma discussão que tive recentemente com um amigo, Wendel, sobre um projeto que ele estava desenvolvendo baseado em uma planilha do Google. No geral, esse artigo <strong>não é uma resposta a ele</strong>, pois nós encerramos a conversa no mesmo dia. Ainda assim, é um conhecimento que acredito ser interessante para outros iniciantes, pois pode trazer boa noção sobre responsabilidades de projetos front-end versus back-end. Vamos começar?</p>
<p><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExZ3JlY2tiZG1pOHd5MHViNzRwMWR1Y2NwNnZzdHY3OXE0bXoyMDlyeSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/IPbS5R4fSUl5S/giphy.gif" alt="GIF do Homer Simpson virando a página de um livre, expressando grande preocupação." class="image--center mx-auto" /></p>
<h2 id="heading-premissa">Premissa</h2>
<p>Suponha que você tem uma planilha de gestão de custos de uma organização pública e quer prover mais transparência sobre essas informações para os interessados nesse assunto.</p>
<p>Você pode:</p>
<ul>
<li><p><strong>compartilhar a planilha</strong> com a permissão restrita de leitura;</p>
</li>
<li><p><strong>fazer um site</strong> para expor esses dados:</p>
<ul>
<li><p>migrando tudo para um banco de dados, ou;</p>
</li>
<li><p>fazendo o site ler o contéudo da própria planilha.</p>
</li>
</ul>
</li>
</ul>
<p>Prover acesso à planilha é, sem dúvida, a decisão <strong>mais rápida</strong>. Porém, pode ser que você coloque informações com nomenclaturas que os usuários comuns não compreendam. Por exemplo, dados com termos em inglês podem gerar barreiras de linguagem no entendimento da leitura da planilha.</p>
<p>Fazer um site e migrar todas as informações para um banco de dados seria a decisão <strong>mais demorada</strong>. E, aliás, pode ser até desnecessária caso não tenham a intenção de incluir mais "planilhas" ou "páginas de planilha" nesse site (banco de uma tabela só). Então, fica a pergunta: é possível usar a planilha do Google como banco de dados e importar os dados de lá?</p>
<p><strong>SIM, É POSSÍVEL</strong>. Mas não é recomendado que você faça isso diretamente do seu front-end. Tudo o que você coloca no código do projeto front-end acabará sendo exposto na rede, de alguma forma. Então, se você colocar suas credenciais (leia-se token) de Google APIs para acessar a planilha diretamente lá, não estranhe se coisas estranhas começarem a aparecer em sua conta. Isso é, basicamente, um prato cheio para hackers tentarem todo tipo de malícia com suas credenciais, rs. O ideal é que, sempre que quiser acessar algum conteúdo com credenciais, crie uma rota em um servidor back-end para fazer essa requisição por você.</p>
<h2 id="heading-jamais-exponha-credenciais-no-front-end">Jamais exponha credenciais no front-end</h2>
<p>Salvo algumas raríssimas exceções, como, por exemplo, credenciais que servem para identificar a build do seu front-end para usar como autenticação na comunicação com o back-end. Disso, não tem como fugir, não é mesmo? E, mesmo assim, você não usará um token fixo. Vai ser a combinação de alguns fatores e recursos, como Cookies, Local Storage, SQLite, dados do navegador, etc.</p>
<p>E sobre esse projeto do exemplo, como são <strong>dados públicos</strong>, sinceramente, não acho que faz sentido criar uma barreira de credenciais entre o front-end e o back-end. O máximo que vai acontecer é que outros desenvolvedores vão poder enviar requisições diretamente ao seu back-end para acessar os dados da planilha. Se os dados são para dar transparência, então, qual o problema? Se não fosse esse cenário, aí sim seria um elemento obrigatório a se desenvolver também.</p>
<h2 id="heading-resultado">Resultado</h2>
<p><a target="_blank" href="https://www.websequencediagrams.com/?lz=dGl0bGUgUGxhbmlsaGEgZG8gR29vZ2xlIGNvbW8gQmFuY28gZGUgRGFkb3MKCmFjdG9yIFVzdcOhcmlvCgoAAggtPkZyb250OiBHRVQgL3AARwctZGUtY3VzdG8Kbm90ZSBvdmVyIAAhB3JlbmRlcml6YSBvIEhUTUwgZXN0w6F0aWNvCgBFBS0-AF0IOiBtb3N0cmEgcMOhZ2luYSBwYWRyw6NvIGNvbVxuIGVmZWl0AIEeBSJjYXJyZWdhbmRvLi4uIgBiEnByZXBhcmEgdW1hIHJlcXVpc2nDp8OjbyBwYXJhXG4gb2J0ZXIgb3MgZGFkAAEFIACBQQgAgQwIQmFjawCBXQdhcGkvdjEvc3ByZWFkc2hlZXQAgVoLACIGAGgIYXMgY3JlZGVuY2lhaXMgZGUAglsIQVBJcwpCYWNrLT4Agm8GQVBJcwCCPgZodHRwczovLwBVBXMuZwCDDwVhcGlzLmNvbS92NABtDHMve1NQUkVBRFNIRUVUX0lEfS92YWx1ZXMve3BhZ2V9IXtyYW5nZX0AgnsLAGMMcHJvY2Vzc2EgAIIIDgoAgQkKAIFxCHJldG9ybmEAghoJAIE1BwCDSgkAEA4gb2J0aQCCRAUAhEwIAIFrBQCDbxwAgnIJZSBhY29yZACDYAUgbyBww7pibGljby1hbHYAhAcaAIQZCmZpbmFs&amp;s=default"><img src="https://www.websequencediagrams.com/cgi-bin/cdraw?lz=dGl0bGUgUGxhbmlsaGEgZG8gR29vZ2xlIGNvbW8gQmFuY28gZGUgRGFkb3MKCmFjdG9yIFVzdcOhcmlvCgoAAggtPkZyb250OiBHRVQgL3AARwctZGUtY3VzdG8Kbm90ZSBvdmVyIAAhB3JlbmRlcml6YSBvIEhUTUwgZXN0w6F0aWNvCgBFBS0-AF0IOiBtb3N0cmEgcMOhZ2luYSBwYWRyw6NvIGNvbVxuIGVmZWl0AIEeBSJjYXJyZWdhbmRvLi4uIgBiEnByZXBhcmEgdW1hIHJlcXVpc2nDp8OjbyBwYXJhXG4gb2J0ZXIgb3MgZGFkAAEFIACBQQgAgQwIQmFjawCBXQdhcGkvdjEvc3ByZWFkc2hlZXQAgVoLACIGAGgIYXMgY3JlZGVuY2lhaXMgZGUAglsIQVBJcwpCYWNrLT4Agm8GQVBJcwCCPgZodHRwczovLwBVBXMuZwCDDwVhcGlzLmNvbS92NABtDHMve1NQUkVBRFNIRUVUX0lEfS92YWx1ZXMve3BhZ2V9IXtyYW5nZX0AgnsLAGMMcHJvY2Vzc2EgAIIIDgoAgQkKAIFxCHJldG9ybmEAghoJAIE1BwCDSgkAEA4gb2J0aQCCRAUAhEwIAIFrBQCDbxwAgnIJZSBhY29yZACDYAUgbyBww7pibGljby1hbHYAhAcaAIQZCmZpbmFs&amp;s=default" alt="Diagrama sequencial mostrando como funcionaria a comunicação desde a ação do usuário até a conexão com GoogleAPIs." class="image--center mx-auto" /></a></p>
<details>
<summary>Código-Fonte do diagrama sequencial (caso fique fora do ar)</summary>
<pre>title Planilha do Google como Banco de Dados<br />
<br />
actor Usuário<br />
<br />
Usuário-&gt;Front: GET /planilha-de-custo<br />
note over Front: renderiza o HTML estático<br />
Front-&gt;Usuário: mostra página padrão com\n efeito de "carregando..."<br />
note over Front: prepara uma requisição para\n obter os dados da planilha<br />
Front-&gt;Back: GET /api/v1/spreadsheet<br />
note over Back: prepara as credenciais de Google APIs<br />
Back-&gt;GoogleAPIs: GET https://sheets.googleapis.com/v4/spreadsheets/{SPREADSHEET_ID}/values/{page}!{range}<br />
note over GoogleAPIs: processa a requisição<br />
GoogleAPIs-&gt;Back: retorna os dados<br />
Back-&gt;Front: retorna os dados obtidos do GoogleAPIs<br />
note over Front: renderiza os dados de acordo com o público-alvo<br />
Front-&gt;Usuário: mostra a página final
</pre>
</details>

<p>A depender da linguagem que você vai utilizar no back-end, você pode ter uma biblioteca do Google APIs para facilitar a construção da requisição. Dá uma olhada na documentação:</p>
<ul>
<li><p>usando <strong>Google Client</strong>: <a target="_blank" href="https://developers.google.com/sheets/api/guides/values?hl=pt-br#read">https://developers.google.com/sheets/api/guides/values?hl=pt-br#read</a></p>
</li>
<li><p>implementando a requisição manualmente: <a target="_blank" href="https://developers.google.com/sheets/api/samples/reading?hl=pt-br#single-range">https://developers.google.com/sheets/api/samples/reading?hl=pt-br#single-range</a></p>
</li>
</ul>
<p>E é isso. Você pode até melhorar essa arquitetura implementando algum esquema de cache para evitar excesso de requisições para os servidores da Google (eles não gostam nada disso). E o melhor de tudo: se o projeto evoluir e precisar armazenar mais recursos, você já teria meio caminho andado para migrar para banco de dados.</p>
<h3 id="heading-edit">EDIT:</h3>
<p>Recebi de um amigo de longa data, <a target="_blank" href="https://www.linkedin.com/in/nahumsa/">Nahum Sá</a>, uma informação que complementa essa postagem com um caso de uso real que fizeram no projeto <a target="_blank" href="https://www.levels.fyi">levels.fyi</a> usando uma planilha do Google como banco de dados, provendo dados para milhões de usuários usando essa logística. No artigo do blog deles, mencionam que não desenvolveram back-end pois utilizaram um recurso serverless da Amazon, o <a target="_blank" href="https://aws.amazon.com/pt/lambda/">AWS Lambda</a>. Na arquitetura deles, o Lambda faz o mesmíssimo papel que descrevi no diagrama sequencial desse artigo, com o objetivo de não expor credenciais do Google APIs. Além disso, por ser um recurso da AWS, provavelmente trouxe já outros critérios de segurança, como a identificação de build de front-end que mencionei anteriormente também. Vale muito a pena a leitura para expandir seus horizontes e ver o que é possível de ser feito com muita performance como <a target="_blank" href="https://www.zendesk.com.br/blog/o-que-e-mvp/">Menor Produto Viável (MVP)</a>, onde vocês podem fazer experimentos a baixo custo.</p>
<p>É claro que "baixo custo" é algo relativo. Para eles, sustentar invocações de Lambdas é baixo custo. Para desenvolvedores solitários que querem só rodar alguns experimentos com uma quantidade menor de usuários, pode ser caro. Tudo é relativo na hora de analisar quantos recursos você tem a sua disposição na construção da arquitetura, mas sempre haverá uma forma de montar alguma coisa. Enfim, é isso, um conteúdo extremamente relevante para o tópico deste artigo, espero que dê tempo de alguém ler, rs. E mais uma vez, obrigado, Nahum!!</p>
<p>Fonte do artigo: <a target="_blank" href="https://www.levels.fyi/blog/scaling-to-millions-with-google-sheets.html">https://www.levels.fyi/blog/scaling-to-millions-with-google-sheets.html</a> (em inglês)</p>
<hr />
<p>Curtiu?! Comenta e compartilha!! Você já tinha parado pra pensar na arquitetura dos projetos on-line como agora? Acha que devo enviar mais artigos como esse, discutindo e refinando ideias e abordando assuntos como cybersec? Deixa seus pensamentos aí nos comentários e até a próxima!</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[GO: Pacotes adaptáveis]]></title><description><![CDATA[Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.
Olá, leitores do CodeAspiras! Prometo que depois desse artigo eu vou escrever qualquer outra coisa qu...]]></description><link>https://blog.kaiquegarcia.dev/go-pacotes-adaptaveis</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/go-pacotes-adaptaveis</guid><category><![CDATA[golang]]></category><category><![CDATA[interface]]></category><category><![CDATA[implements]]></category><category><![CDATA[package]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Wed, 31 Jan 2024 04:22:01 GMT</pubDate><content:encoded><![CDATA[<p><em>Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.</em></p>
<p>Olá, leitores do <strong>CodeAspiras</strong>! Prometo que depois desse artigo eu vou escrever qualquer outra coisa que não seja Golang, beleza? É que, no momento, todo o meu foco está nessa linguagem de programação e, por isso, está mais fácil escrever sobre ela.</p>
<p>Dessa vez, trago mais um assunto bem relevante pra quem está começando a desenvolver nessa linguagem, principalmente se você ainda não criou o hábito de escrever interfaces. Vamos começar?</p>
<h2 id="heading-interfaces">Interfaces</h2>
<p>Antes de mais nada, é preciso entender que interfaces são contratos. Elas não tem nenhum código atrelado a elas diretamente, apenas dizem: "<strong>o que quer que esteja implementando isso aqui, está de acordo com as assinaturas desta interface</strong>".</p>
<p>Diferente de outras linguagens, Golang não tem o conceito de classe da Orientação a Objeto. Isso por si só já foi motivo de ódio de muitos, mas calma. Na realidade, isso expandiu as possibilidades do que você pode fazer. Ao invés de ser obrigado a anunciar quais interfaces suas structs implementam, basta que as structs implementem as funções da assinatura das interfaces que, automaticamente, já será interpretada como implementação.</p>
<p><img src="https://media.giphy.com/media/lkdH8FmImcGoylv3t3/giphy.gif?cid=790b7611w0oyfwlwkc6q9e96v5xlxg9r60isan16fb7rh0gc&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="Meme: o quê?" class="image--center mx-auto" /></p>
<blockquote>
<p>QUÊ?!</p>
</blockquote>
<p>Calma, calma, calma... Vamos comparar para entender melhor.</p>
<h3 id="heading-interfaces-em-php">Interfaces em PHP</h3>
<p>Se você cria, no PHP, uma interface cuja assinatura declara que suas implementações possuem uma função chamada <code>Ping()</code> que retorna uma <code>string</code>, toda classe que implementar essa interface deverá ter essa função:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PingableInterface</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Ping</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pingable</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PingableInterface</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Ping</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"pong"</span>;
    }
}
</code></pre>
<p>Porém, se você fizer uma classe com a mesma função sem declarar na hierarquia que a mesma está implementado a interface, o interpretador entenderá que não implementa a assinatura:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PingableInterface</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Ping</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pingable</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PingableInterface</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Ping</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"pong"</span>;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pingable2</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Ping</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"pong"</span>;
    }
}

var_dump(is_a(<span class="hljs-keyword">new</span> Pingable(), <span class="hljs-string">'PingableInterface'</span>)); <span class="hljs-comment">// true</span>
var_dump(is_a(<span class="hljs-keyword">new</span> Pingable2(), <span class="hljs-string">'PingableInterface'</span>)); <span class="hljs-comment">// false - é exatamente o mesmo código do Pingable, só que sem a declaração "implements PingableInterface"</span>
</code></pre>
<p>Experimente o código: <a target="_blank" href="https://onlinephp.io/c/38b0a">https://onlinephp.io/c/38b0a</a></p>
<h3 id="heading-interfaces-em-golang">Interfaces em Golang</h3>
<p>Aqui, isso não acontece, dado que nem existe opção para você declarar que uma "struct implementa uma interface". As implementações são dinâmicas, então basta que sua struct esteja de acordo com a assinatura das interfaces para que o interpretador aceite-a como implementação.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> PingableInterface <span class="hljs-keyword">interface</span> {
    Ping() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Pingable <span class="hljs-keyword">struct</span>{} <span class="hljs-comment">// não tem nada como "implements PingableInterface"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p Pingable)</span> <span class="hljs-title">Ping</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"pong"</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> pingable <span class="hljs-keyword">interface</span>{} = Pingable{}
    <span class="hljs-keyword">if</span> _, is := pingable.(PingableInterface); is { <span class="hljs-comment">// equivalente ao is_a() do PHP</span>
        fmt.Println(<span class="hljs-string">"implements PingableInterface"</span>)
    } <span class="hljs-keyword">else</span> {
        fmt.Println(<span class="hljs-string">"does not implement PingableInterface"</span>)
    }
}
</code></pre>
<p>Experimente o código: <a target="_blank" href="https://go.dev/play/p/GKHEC6bd-CT">https://go.dev/play/p/GKHEC6bd-CT</a></p>
<p>E com isso, você consegue criar structs que implementam interfaces de terceiros e vice-versa. Mesmo se a interface for algo interno de alguma biblioteca importada, basta que os pacotes se comuniquem por interfaces ao invés de implementações. É isso que é um "<em>pacote adaptável</em>": é um pacote onde todas as chamadas públicas são tratadas por interfaces. Eu usei o termo "adaptável" aqui derivando do <a target="_blank" href="https://refactoring.guru/design-patterns/adapter">Design Pattern "Adapter"</a>. Recomendo a leitura!</p>
<h2 id="heading-escrevendo-um-pacote-regido-por-interfaces">Escrevendo um pacote regido por interfaces</h2>
<p>Uma forma simples de atingir esse objetivo é seguir as seguintes regrinhas:</p>
<ol>
<li><p>Se vai expor alguma coisa, tem de estar em uma interface;</p>
</li>
<li><p>Toda implementação real tem de ser privada, restrita ao pacote.</p>
</li>
</ol>
<p>No Golang, tudo que começa com letra maiúscula é <strong>público</strong>, ou seja, toda nomenclatura que você escreve é <em>case sensitive</em> (a caixa alta/baixa importa). Então é considerado uma boa prática escrever a interface com letra inicial maiúscula e a sua implementação usando o mesmo nome, mas com letra inicial minúscula.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> exping

<span class="hljs-keyword">type</span> Pingable <span class="hljs-keyword">interface</span> {
    Ping() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> pingable <span class="hljs-keyword">struct</span> {}
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p *pingable)</span> <span class="hljs-title">Ping</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"pong"</span>
}
</code></pre>
<p>Assim, quando você fizer uma função de inicialização, essa função deverá declarar que retorna a interface. Mas, na prática, retorna sua implementação privada:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> exping

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NewPingable</span><span class="hljs-params">()</span> <span class="hljs-title">Pingable</span></span> {
    <span class="hljs-keyword">return</span> &amp;pingable{}
}
</code></pre>
<p>E em todo lugar que você precisar dessa implementação, você sempre irá referenciar pela interface, nunca pela struct:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> expong

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">HandlePing</span><span class="hljs-params">(p exping.Pingable)</span></span> {
    <span class="hljs-comment">// ...</span>
    p.Ping()
}
</code></pre>
<blockquote>
<p>O que eu ganho com isso, Kiko?</p>
</blockquote>
<p>Bem... Quando você for escrever testes unitários, você poderá <strong>mockar a interface</strong> (usando mockery ou qualquer outra coisa, você pode até escrever a implementação de mock na mão, se quiser). Se o que estiver desenvolvendo for uma biblioteca, você estará permitindo que seus consumidores possam injetar implementações próprias ao invés de usar o que você fez... Por ser interface, você também pode passar dados nulos e criar um fluxo mais flexível, coisa que não seria possível ao passar uma struct sem referência. Isso também permite que você faça <em>cast</em> para outras interfaces.</p>
<p>Enfim, tem muitos usos para isso. No geral, eu gosto de pensar que isso torna o código um pouco mais seguro e dá mais possibilidades do que podemos fazer posteriormente. E é por isso que eu acredito que esse seja um conhecimento relevante para novatos da linguagem.</p>
<blockquote>
<p>Ah, Kiko, então só vale a pena fazer interfaces em Golang?</p>
</blockquote>
<p>De jeito nenhum! <strong>Interfaces são contratos</strong>. Ao anunciar qual estrutura sua implementação irá seguir, fica mais fácil para todos de entender como o código irá se comportar. Então, sempre que uma linguagem der suporte para interfaces, dê um jeito de aprender a usar!</p>
<hr />
<p>E por hoje é só! Curtiu? Comenta e compartilha! <s>Lembrando que ainda temos muitas vagas para colaboradores do blog. Sinta-se a vontade para entrar em contato e começar a mandar suas publicações. Sua conta irá aparecer como autor(a) e você aparecerá na página de membros do blog. Isso é um incentivo para que cada um possa fazer sua parte de girar a roda da comunidade, ok?</s></p>
<p>E eu vou indo nessa. Abraço!</p>
<p><strong>Inté!</strong></p>
]]></content:encoded></item><item><title><![CDATA[GO: O que raios é "config pattern"?]]></title><description><![CDATA[Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.
Olá, leitores do CodeAspiras! Estou aqui novamente com mais um artigo de Golang para disseminar conhe...]]></description><link>https://blog.kaiquegarcia.dev/go-config-pattern</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/go-config-pattern</guid><category><![CDATA[golang]]></category><category><![CDATA[dto]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Tue, 30 Jan 2024 02:53:28 GMT</pubDate><content:encoded><![CDATA[<p><em>Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.</em></p>
<p>Olá, leitores do CodeAspiras! Estou aqui novamente com mais um artigo de <strong>Golang</strong> para disseminar conhecimentos relevantes para a área. Dessa vez, venho com mais um conceito de desenvolvimento que é bom conhecer mas que não deve ser tão utilizado assim, que é o Config Pattern ou "padrão de configuração".</p>
<p>Como o próprio nome diz, trata-se de uma estratégia de estrutura de argumentos e/ou configurações de qualquer coisa. Você consegue até aplicar em outras linguagens, pois o conceito é abrangente o suficiente para produzir em quaisquer linguagens que fornecem alguma ferramenta de captura de argumentos dinâmicos. No caso do Golang, nós usamos o <code>pack operator</code>.</p>
<blockquote>
<p>O que raios é isso, Kiko?!</p>
</blockquote>
<p>É o oposto de <code>unpack</code> ou <code>spread</code>. Em outras linguagens, em situações onde você quer quebrar um <code>array</code> em uma lista de valores, geralmente você "desempacota" o array com a assinatura <code>array...</code>, onde os três pontos no final significam que você vai pegar todos os valores e distribuir na linha onde a sentença está escrita.</p>
<p>No caso do <code>pack</code>, é justamente o oposto. Você vai ter uma lista de valores e quer "empacotar" tudo em um único <code>array</code>. No caso do Golang, é em um <code>slice</code>, ficando assim:</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">MyFunc</span><span class="hljs-params">(arguments ...<span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-comment">// nesse caso, a assinatura final do argumento 'arguments' é []string</span>
}
</code></pre>
<p>Se a linguagem que você usa fornece algum recurso para capturar uma lista indefinida de argumentos, então você consegue aplicar o <code>Config Pattern</code>.</p>
<h2 id="heading-ok-mas-o-que-e-isso">OK, mas o que é isso?</h2>
<p><code>Config Pattern</code> nada mais é que um DTO gerenciado por pequenas funções.</p>
<p><em>Não sabe o que é DTO? Dá uma lida</em><a target="_blank" href="https://telegra.ph/Data-Transfer-Object---DTO-02-15"><em>nesse outro artigo que expliquei direitinho</em></a><em>(escrevi via Telegraph, numa época obscura que eu publicava coisas para só uma pessoa ler... Eu deveria republicar aqui no CodeAspiras? Comenta aí).</em></p>
<p>A principal diferença seria sobre qual lado da função retém a responsabilidade de alimentar os dados do objeto que carrega informação. O DTO é alimentado por quem chama a função, antes de chamá-la. Já o Config Pattern, é alimentado dentro da função. Por isso você cria funções que servem para injetar valores no objeto de configuração.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706582282826/3aa887fa-7a6f-4a0e-860f-df1b780856c5.png" alt="Exemplo visual descrevendo os cenários DTO versus Config Pattern, onde a função em DTO recebe um objeto construído e a função em Config Pattern recebe vários valores para construir um objeto." class="image--center mx-auto" /></p>
<blockquote>
<p>E pra que serve isso tudo, Kiko?!</p>
</blockquote>
<p>Para ter um controle rígido do que pode e não pode ser inserido. Por exemplo, no Golang, você pode desenvolver uma configuração 100% privada, expondo somente algumas possibilidades pra quem vai chamar sua função.</p>
<p>Digamos que estamos desenvolvendo um <code>Logger</code> e queremos que o desenvolvedor que irá usá-lo possa configurar somente prefixo ou sufixo. Se você implementar em DTO, você teria algo mais ou menos assim:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> mylog <span class="hljs-comment">// logger.go</span>

<span class="hljs-keyword">type</span> LoggerConfigDTO <span class="hljs-keyword">struct</span> {
    Prefix <span class="hljs-keyword">string</span>
    Suffix <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Logger <span class="hljs-keyword">struct</span> {
    config LoggerConfigDTO
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">New</span><span class="hljs-params">(config LoggerConfigDTO)</span> *<span class="hljs-title">Logger</span></span> {
    <span class="hljs-keyword">return</span> &amp;Logger{config: config}
}
</code></pre>
<p>E aí, quem fosse inicializar seu <code>Logger</code> poderia fazer algo assim:</p>
<pre><code class="lang-go">mylog.New(mylog.LoggerConfigDTO{
    Prefix: <span class="hljs-string">"$timestamp [$level]"</span>,
    Suffix: <span class="hljs-string">"/n"</span>,
})
</code></pre>
<p>Só tem um problema nisso. Lá no enunciado, eu disse que era para ter somente prefixo <strong>ou</strong> sufixo, <strong>não ambos simultaneamente</strong>, correto? Então essa implementação não está adequada.</p>
<p>Uma possível solução seria somente aplicar o prefixo se o sufixo estiver vazio e/ou vice-versa, porém isso iria impactar o tempo de escrita de logs, adicionando uma condição para o momento de execução. Outra solução seria, já na hora de inicializar a struct, verificar se os dois estão preenchidos e apagar um arbitrariamente.</p>
<p>Em ambas as soluções, nós estamos decidindo algo e gerando um <strong>comportamento obscuro</strong> na nossa aplicação. O desenvolvedor que usasse seu <code>Logger</code> só iria perceber esse comportamento quando já estivesse vendo os logs em produção com alguma informação faltando. Claro, você também pode deixar um aviso gigante na documentação... Enfim...</p>
<h2 id="heading-em-busca-do-config-pattern">Em busca do Config Pattern</h2>
<p><img src="https://media.giphy.com/media/HVr4gFHYIqeti/giphy.gif?cid=790b76111pdkaz7v01fjry0zolodromomr76xbclrrjttci6&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="Personagem de O Hobbit correndo com a legenda em inglês &quot;I'm going on an adventure!&quot; (Estou indo em uma aventura!)" class="image--center mx-auto" /></p>
<p>Antes de prosseguir, deixe-me alertá-lo(a) novamente: só use isso se você precisar de controle rígido sobre configurações, pois a implementação pode deixar o código bem massante. Outro ponto: embora você possa implementar a configuração de forma privada, sempre que possível, faça-a pública. Assim você facilita a escrita de testes de outros desenvolvedores, beleza? Tendo uma interface de configuração pública, eles conseguem mockar o setup e fazer seu código ter um comportamento específico nos testes. Mas chega de papo e vamos lá.</p>
<p>O primeiro passo que você precisa para transformar seu <code>DTO</code> em um <code>Config Pattern</code> é criar uma assinatura para funções de manipulação dos dados. No caso, eu vou chamar de <code>LoggerOption</code>:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> mylog <span class="hljs-comment">// logger_config.go</span>

<span class="hljs-keyword">type</span> LoggerOption <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *LoggerConfigDTO)</span></span>
</code></pre>
<p>Nessa assinatura, estou dizendo que um <code>LoggerOption</code> é uma função que recebe uma referência/ponteiro de <code>LoggerConfigDTO</code> e não retorna nada. Basicamente, essa função deve alterar a referência que recebe no argumento e nada mais.</p>
<p>Tendo essa definição, você pode criar as funções que manipulam os dados do DTO. Essas funções recebem como argumento o dado a ser inserido na configuração e retornam um <code>LoggerOption</code>, ou seja, retornam a função de injeção do dado no DTO:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> mylog <span class="hljs-comment">// logger_config.go</span>

<span class="hljs-keyword">type</span> LoggerOption <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *LoggerConfigDTO)</span></span>

<span class="hljs-comment">// WithPrefix defines the prefix to be injected in all logs. It erases the suffix, if it's filled.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">WithPrefix</span><span class="hljs-params">(prefix <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">LoggerOption</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *LoggerConfigDTO)</span></span> {
        c.Prefix = prefix <span class="hljs-comment">// aqui aplicamos o prefixo na configuração</span>
        c.Suffix = <span class="hljs-string">""</span> <span class="hljs-comment">// aqui limpamos o sufixo para não ter coexistência</span>
    }
}

<span class="hljs-comment">// WithSuffix defines the suffix to be injected in all logs. It erases the prefix, if it's filled.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">WithSuffix</span><span class="hljs-params">(suffix <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">LoggerOption</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *LoggerConfigDTO)</span></span> {
        c.Suffix = suffix <span class="hljs-comment">// aqui aplicamos o sufixo na configuração</span>
        c.Prefix = <span class="hljs-string">""</span> <span class="hljs-comment">// aqui limpamos o prefixo para não ter coexistência</span>
    }
}
</code></pre>
<p>Note que adicionei dois comentários indicando o comportamento de cada configuração. Esses comentários são chamados de <code>godoc</code> e são suportados por quase toda IDE que podemos usar para desenvolver Golang. Dito isso, ao invocar a função, o desenvolvedor já vai saber dos efeitos obscuros - se ele ler, claro. E isso não é exclusivo de Config Pattern. Por favor, use <code>godoc</code> em tudo, até em propriedades, rs.</p>
<p>E por último mas não menos importante, agora podemos modificar a função de inicialização para receber um pack de <code>LoggerOption</code> ao invés de um DTO preenchido, <strong>migrando a responsabilidade de construção do DTO</strong> para dentro da função:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> mylog <span class="hljs-comment">// logger.go</span>

<span class="hljs-keyword">type</span> LoggerConfigDTO <span class="hljs-keyword">struct</span> { <span class="hljs-comment">// isso pode permanecer assim</span>
    Prefix <span class="hljs-keyword">string</span>
    Suffix <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Logger <span class="hljs-keyword">struct</span> {
    config LoggerConfigDTO <span class="hljs-comment">// aqui também</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">New</span><span class="hljs-params">(options ...LoggerOption)</span> *<span class="hljs-title">Logger</span></span> {
    config := LoggerConfigDTO{} <span class="hljs-comment">// construimos o DTO</span>
    <span class="hljs-keyword">for</span> index := <span class="hljs-number">0</span>; index &lt; <span class="hljs-built_in">len</span>(options); index++ {
        options[index](&amp;config) <span class="hljs-comment">// executamos cada LoggerOption na referência do DTO</span>
    }

    <span class="hljs-keyword">return</span> &amp;Logger{config: config}
}
</code></pre>
<p>E com isso, ao invés de inicializar um DTO, agora o desenvolvedor poderá inicializar o <code>Logger</code> com várias chamadas de <code>LoggerOption</code>:</p>
<pre><code class="lang-go">mylog.New(
    mylog.WithPrefix(<span class="hljs-string">"$timestamp [$level]"</span>),
    <span class="hljs-comment">// mylog.WithSuffix("\n"),</span>
)
</code></pre>
<p>Fim. Você rapidamente migrou o padrão do seu projeto de DTO para Config Pattern. Caso mantenha a assinatura das opções e do DTO como públicas, você dará ao desenvolvedor a possibilidade de criar novos controles de configuração, mas ele só vai poder manipular o que for público.</p>
<p>Então você realmente vai ter muito mais domínio sobre o código e a escrita vai ficar mais semântica. Às vezes temos de lidar com campos com nomes esquisitos e, com Config Pattern, temos a possibilidade de escrever funções com nomenclaturas mais claras sobre o que estamos configurando.</p>
<p>A documentação em <code>godoc</code> está disponível tanto para DTO quanto para Config Pattern, então isso não é exatamente vantagem pra ninguém. Porém, quando se trata de sobreescrever configurações padrões, o Config Pattern é a melhor escolha.</p>
<blockquote>
<p>Como assim, Kiko?</p>
</blockquote>
<p>Digamos que, por padrão, eu que o prefixo seja sempre <code>"$timestamp [$level]"</code>. Com o pattern, é bem simples:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> mylog <span class="hljs-comment">// logger.go</span>

<span class="hljs-keyword">type</span> LoggerConfigDTO <span class="hljs-keyword">struct</span> {
    Prefix <span class="hljs-keyword">string</span>
    Suffix <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Logger <span class="hljs-keyword">struct</span> {
    config LoggerConfigDTO
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">New</span><span class="hljs-params">(options ...LoggerOption)</span> *<span class="hljs-title">Logger</span></span> {
    config := LoggerConfigDTO{
        Prefix: <span class="hljs-string">"$timestamp [$level]"</span>, <span class="hljs-comment">// valor padrão</span>
    }
    <span class="hljs-keyword">for</span> index := <span class="hljs-number">0</span>; index &lt; <span class="hljs-built_in">len</span>(options); index++ {
        options[index](&amp;config)
    }

    <span class="hljs-keyword">return</span> &amp;Logger{config: config}
}
</code></pre>
<p>Basta instanciar o DTO com o valor inicial de cada opção, certo? Mas se você não é responsável pela inicialização dele, como você vai garantir esse valor padrão? Você teria de partir para solução de mesclagem de structs e isso não é exatamente necessário se você usa Config Pattern, dado que você é quem inicializa o DTO.</p>
<p>É nesses casos que esse padrão ganha força e se torna prático.</p>
<p><img src="https://media.giphy.com/media/l0Ex4MZdAVJPHxjvG/giphy.gif?cid=790b7611aoiesw8pkr3y58ndl8l1vn2jm0xh9qf18yltq9f9&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="Body builder feminina exibindo seus bíceps definidos, como analogia à &quot;força&quot; do Config Pattern." class="image--center mx-auto" /></p>
<blockquote>
<p>Alguém já usou isso antes, Kiko?</p>
</blockquote>
<p>Com certeza! Eu já cheguei a dar palpite num Config Pattern do <a target="_blank" href="https://github.com/DataDog/dd-trace-go/blob/d7ed3ea75ae8cc691d34f405debe585874778df1/ddtrace/tracer/tracer.go#L135">Tracer do Datadog</a>. Eles fizeram as configurações privadas e eu queria modificar o logger deles em outro pacote. Você pode ver a issue que abri aqui: <a target="_blank" href="https://github.com/DataDog/dd-trace-go/issues/1331">https://github.com/DataDog/dd-trace-go/issues/1331</a> . No final das contas, eles perceberam que centralizaram a configuração de logger de todos os produtos no Tracer e resolveram refatorar essa lógica.</p>
<p>Outra biblioteca bem famosa que usa o Config Pattern é o <a target="_blank" href="https://github.com/go-gorm/gorm/blob/418ee3fc1939d87a05bbb8ac6d7c7223e2c4571f/gorm.go#L121">GORM</a>.</p>
<p>Se você procurar direitinho, você vai perceber que muitas bibliotecas usam essa estratégia para estabelecer um controle mais rígido sobre os argumentos. Então sim, muita gente usa.</p>
<hr />
<p>Curtiu? Comenta e compartilha! <s>E lembrando: esse blog é nosso! Se tiver algo que queira publicar por aqui, fala comigo que te convido como colaborador do blog. Pode ser sobre qualquer coisa da área de tecnologia! Algo que acabou de estudar e tal. Antes de publicar, nós revisamos o conteúdo, assim podemos te corrigir se tiver aprendido algo errado e reforçamos nossos conhecimentos juntos</s>. Bora?</p>
<p>E por hoje é só!</p>
<p>Inté.</p>
]]></content:encoded></item><item><title><![CDATA[GO: Como organizar meu código?]]></title><description><![CDATA[Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.
Muito se fala sobre designs de projeto mas pouco se aplica na realidade. Por exemplo, seguir o Domain...]]></description><link>https://blog.kaiquegarcia.dev/go-como-organizar-meu-codigo</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/go-como-organizar-meu-codigo</guid><category><![CDATA[golang]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Sun, 28 Jan 2024 00:10:07 GMT</pubDate><content:encoded><![CDATA[<p><em>Nota: esse artigo foi publicado primeiramente no blog.codeaspiras.dev, que foi encerrado. Transferi para esse blog para que o mesmo não se perdesse.</em></p>
<p>Muito se fala sobre designs de projeto mas pouco se aplica na realidade. Por exemplo, seguir o <strong>Domain-Driven Design</strong> à risca não é uma tarefa fácil. Sua ideia até foi moldada de forma abstrata, mas, quando uma linguagem traz limitações estruturais, isso aumenta a dificuldade de aprendizado.</p>
<p><strong>Golang</strong> é esse tipo de linguagem: toda vez que você pensa que está fazendo algo prático, alguma hora depois irá descobrir que algo ficou redundante a ponto de prejudicar a legibilidade do código ou deixar o esquema de importações bastante confuso. Eu passei muito por isso, rs.</p>
<p>Eu fui aprendendo muita coisa com o tempo, absorvendo conteúdos de muitas pessoas. Dito isso, eu não sei a quem dar créditos por cada pequeno conhecimento que me trouxe ao ponto que cheguei. Vou evitar atribuir nomes aos bois, ok? Mas prometo colocar alguns artigos ao final deste, pode ser?!</p>
<p>Vamos começar pelo começo.</p>
<h2 id="heading-iniciando-um-projeto-em-go">Iniciando um projeto em Go</h2>
<p>Se você pesquisar um pouco, vai ver que nem precisa de pastas para fazer um projeto Golang. Você pode simplesmente despejar quantos arquivos <code>.go</code> quiser na raiz e <strong>deixar a desorganização tomar conta</strong>.</p>
<p>OK, pera, tem projetos que isso até faz sentido. São bibliotecas (libs), projetos menores, que não costumam ter mais de 2 arquivos (o principal e o de teste). Você não vai criar todo um sistema de pastas pra colocar dois arquivos, certo??</p>
<p>Todavia, se o seu projeto é um pouquinho maior que isso, faz sentido repensar sobre a estrutura utilizada.</p>
<blockquote>
<p>Como você organiza seus projetos, Kiko?</p>
</blockquote>
<p>Primeiramente, gosto de pensar que toda aplicação Go é um recurso CLI, <strong>mesmo se o objetivo for rodar um servidor web</strong>. Dito isso, a primeira pasta que me vem em mente tem como função "<em>organizar os comandos que irei disponibilizar para o CLI</em>", ou seja, a pasta "<strong>cmd</strong>" (abreviação de <em>command</em>).</p>
<p>A ideia dessa pasta é expor, por exemplo, a execução principal do código (vulgo <code>main.go</code>) e, quando aplicável, os comandos abaixo dele, como nos exemplos abaixo:</p>
<ul>
<li><p><code>myapp serve -p 80</code> =&gt; chama o arquivo <code>cmd/main.go</code>, que inicializa o servidor na porta 80, importando alguma execução em <code>cmd/serve.go</code>;</p>
</li>
<li><p><code>myapp cron:reset-quotas</code> =&gt; chama o arquivo <code>cmd/main.go</code>, que inicializa o fluxo de Cronjobs, importando alguma execução em <code>cmd/cron.go</code>;</p>
</li>
<li><p><code>myapp db:migrate</code> =&gt; chama o arquivo <code>cmd/main.go</code>, que inicializa o arquivo de migrations do banco em <code>cmd/migrate.go</code>;</p>
</li>
<li><p><code>myapp db:revert</code> (...);</p>
</li>
<li><p><code>myapp db:seed</code> (...);</p>
</li>
<li><p>e por aí vai.</p>
</li>
</ul>
<p>É muito importante refletir quantos comandos você quer expor no terminal e quais opções de controle você quer fornecer antes de começar o projeto, pra validar a real necessidade da pasta. De repente, ter só um comando desfaz a necessidade de criar isso e você pode deixar o <code>main.go</code> na raiz da aplicação. É algo a se pensar, certo?</p>
<p>Após isso, a próxima pasta que me vem em mente e que é obrigatória a quase todos os projetos é a pasta <code>internal</code>.</p>
<blockquote>
<p>Que pasta é essa, Kiko?</p>
</blockquote>
<p>A ideia dessa pasta é <strong>separar o código público do código <mark>interno</mark> do projeto</strong> (daí o nome). Isso não significa que o código será secreto nem nada do tipo, só que outros projetos <strong>não conseguirão importar nada que estiver dentro dessa pasta</strong>. O compilador do Golang não permite a importação de pastas dentro de alguma pasta com o nome <code>internal</code>.</p>
<p><em>Não é sobre guardar segredos</em>, mas de impedir que alguém use sua biblioteca <strong><mark>da forma errada</mark></strong>.</p>
<p><strong><mark>É qualidade de código!</mark></strong></p>
<p>E igualmente serve para centralizar a sua camada de domínio. Gosto de dizer que "<strong>o que é exclusivo do projeto, fica na pasta internal</strong>". Implicitamente, isso também significa que "<strong>o que não é exclusivo do projeto, fica fora</strong>".</p>
<blockquote>
<p>Se não for comando e não for exclusivo do projeto, fica onde então, Kiko?</p>
</blockquote>
<p>Re: na pasta <code>pkg</code>!</p>
<p>"pkg" é uma abreviação para "package" e é lá que você vai colocar a parte pública da sua aplicação que não está em fluxo de execuções. Tem algumas pastas que vejo ter quase como um padrão em todos os projetos que já trabalhei:</p>
<ul>
<li><p><code>pkg/platform</code>: todas as lógicas de plataforma usadas pela aplicação. Clients, Middlewares, Autenticação, etc. Sinceramente, isso poderia estar em um kit-repository e ter as "configurações" (ou divergências) importadas por variáveis de ambiente, mas isso é outro assunto;</p>
</li>
<li><p><code>pkg/util</code>: são funções "auxiliares" que podem ser facilmente confundidas com "serializers". A grande maioria apenas transforma dados e são importadas tanto pelos pacotes internos quanto os de comando;</p>
</li>
<li><p><code>pkg/services</code>: quando você precisa desenvolver um serviço de terceiros, quando não há um SDK ou algo do gênero para usar, você acaba colocando aqui, focando em criar apenas o serviço, sem embutir regra de negócio da sua aplicação;</p>
</li>
<li><p>etc.</p>
</li>
</ul>
<p>Só com isso você já consegue organizar um projeto tranquilo, mas preciso te alertar sobre outras pastas:</p>
<ul>
<li><p><code>docs</code>: se você está fazendo uma aplicação HTTP, é comum usar gerador de documentações que extraem informação de <code>godoc</code> para criar uma OpenAPI (vulgo Swagger). A documentação compilada geralmente é exportada na pasta <code>docs</code> nos projetos em Golang. É tipo um padrão que foi instalado silenciosamente;</p>
</li>
<li><p><code>mocks</code>: outra pasta bastante comum pra quem usa <code>mockery</code>. Basicamente, se você faz interface pra tudo, você consegue compilar todas as interfaces em mocks para fazer testes unitários bem refinados. Na minha humilde opinião, Golang foi a linguagem que achei estupidamente mais fácil de mockar qualquer coisa... E olha que eu já fiz todo tipo de teste automatizado aqui, hein?</p>
</li>
<li><p><code>vendor</code>: se você usa o comando <code>go mod vendor</code>, o Golang irá baixar todas as suas dependências e colocar na pasta <code>vendor</code>. Quase toda linguagem provê esse tipo de pasta (no Node, seria a <code>node_modules</code>. No PHP com Composer, é <code>vendor</code> também, etc), então já é de senso comum não mexer em nada que estiver nela. É importado automaticamente, então não é SEU.</p>
</li>
</ul>
<p>E agora sim, tendo noção dessas pastas, você pode começar a investigar melhor os códigos que encontrar por aí. Ainda pode haver outras pastas mas, sinceramente, isso pra mim é o necessário. Você pode ler mais sobre isso em um dos links no final desse artigo.</p>
<h2 id="heading-desenvolvendo">Desenvolvendo</h2>
<p>Um detalhe que os iniciantes se batem em Golang é sobre como nomear e importar projetos. Eventualmente, percebe-se que há uma certa simplicidade nisso: tudo é baseado no que está definido no <code>go.mod</code>. Quando você batiza o nome de uma aplicação, você deve ter em mente que, se ela for ser importada em outros projetos, toda a navegação de diretórios será inciada a partir da raiz, onde fica o <code>go.mod</code>.</p>
<p>Por exemplo, se eu crio uma pasta vazia e rodo o comando no terminal <code>go mod init myproject</code>, o compilador da linguagem vai criar os arquivos <code>go.mod</code> e <code>go.sum</code> na raiz do projeto chamando-o <code>myproject</code>. Assim, quando você importar alguma função <code>myproject.Blablabla</code>, ele vai procurar nesse diretório-raiz.</p>
<p>Já os pacotes, que são outras pastas, não mencionam o nome do projeto mais. Portanto, se você repetir nomes de pastas, eventualmente você vai ter de gerar apelidos (traduzindo <code>alias</code>) pra não dar conflitos nas importações.</p>
<p>O ideal é que você jamais repita nomes de pacotes, interfaces, nada. Evite repetir qualquer coisa. Outro ponto é que todas as pastas devem ser escritas em letras minúsculas e somente letras. Nada de underline, etc. É pra dar nomes pequenos mesmo, sabe?</p>
<p>Explorando um pouco da estrutura de pastas que discutimos, alguns dos pacotes que vejo em comum nos projetos são:</p>
<ul>
<li><p><code>internal/entity</code>: fica a implementação de entidades de domínio, assim como algumas regras de negócio (as que forem independentes). Evite ao máximo importar outros pacotes dentro desse;</p>
</li>
<li><p><code>internal/db/model</code>: fica a implementação de modelagem de banco de dados referente as entidades criadas anteriormente, deixando claro que o pacote <code>entity</code> deve evitar ao máximo mencionar qualquer coisa de banco salvo algumas exceções como dados anuláveis (ex: <code>sql.NullTime</code>). Na Model você geralmente descreve o nome da tabela de cada entidade e campos adicionais que só importam para o banco (ex: <code>DeletedAt</code> é um campo geralmente utilizado para <em>soft-deleting</em> ~ não é consumido pela sua aplicação, apenas pro banco, e raramente há necessidade de expor essa informação. Nesse cenário, você não coloca esse campo na entidade, somente no modelo do banco). Outro detalhe é que cada Model implementa suas funções de conversão aqui, como <code>NewBlablablaModel()</code> recebendo entidade e retornando model e <code>model.ToEntity()</code>, convertendo a modelagem para entidade;</p>
</li>
<li><p><code>internal/db/repository</code>: aqui fica a implementação de comunicação com banco, encapsulando o que quer que use para se comunicar com banco em funções mais simplificadas pra sua aplicação. Note que há variações gigantescas de como implementar esse pacote. Algumas pessoas preferem centralizar tudo em uma interface de Repository e uma implementação que serve para todas as entidades e outras preferem ter um repository pra cada entidade. No geral, o objetivo aqui é dar aos demais pacotes algo que possa receber ou prover entidades sem expor as modelagens do banco;</p>
</li>
<li><p><code>internal/usecases/&lt;fluxo&gt;</code>: como diz o nome, nesses pacotes implementamos os casos de uso da aplicação, independente de qual protocolo esteja sendo usado. A ideia é que todos os fluxos nesse pacote não saibam o que é uma requisição web ou comando CLI. Eles vão ter seus argumentos completamente restritos para somente executar o caso de uso e retornar o que precisar retornar ou erro. Um exemplo simples seria casos de uso de uma loja online, onde poderia ter os pacotes de CRUD <code>product</code>, <code>category</code>, <code>customer</code>, etc, e pacotes de fluxo de compra como <code>shopping</code>, <code>publishing</code>, etc. A forma como você vai separar os fluxos só depende de você. O importante é não receber <code>*http.Request</code> aqui dentro, muito menos <code>http.ResponseWriter</code>;</p>
</li>
<li><p><code>internal/http</code>: essa pasta aqui é um verdadeiro dilema. Na minha opinião, isso poderia ser uma pasta lá no pacote <code>cmd</code>. Porém também é uma configuração interna da aplicação, então faz total sentido estar na <code>internal</code>. Então minha conclusão é mais simples: siga seu coração.</p>
</li>
</ul>
<p><img src="https://media.giphy.com/media/XDp1CMTpLg60KrfXfB/giphy.gif?cid=ecf05e476mard22mz8vtl3oci58hhhz4w9uo6u2i609oafn9&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="Um rapaz loiro imitando o personagem de Yu-Gi-OH, puxando uma carta invisível, de mentira, de um dos seus braços, simulando a confiança no coração das cartas." class="image--center mx-auto" /></p>
<center>Entendedores entenderão (Yu-Gi-OH).</center>

<details><summary>Mais detalhes sobre o pacote http</summary><div data-type="detailsContent">No pacote http, nós colocamos tudo relacionado a inicialização da API. Por exemplo, geralmente temos um arquivo router.go com toda a definição de URLs da aplicação, incluindo path, middlewares e handlers. Não se preocupe se não entender esses termos, porém não vai dar pra explicar aqui nesse artigo. Mas, resumindo, esse pacote é o que diz pra aplicação "toda requisição GET /admin/nao-manda-em-mim deve ser tratada pela função adminHandler.Playground()". A depender do framework, essa função pode estar em um subpacote ou atrelada a uma struct. Nesse caso aqui, realmente depende de como o servidor está sendo inicializado, pois alguns frameworks criaram umas limitações bem bizarras.</div></details>

<p>Implementando esses pacotes, teu serviço estará praticamente pronto, restando somente configurar as coisas no pacote <code>cmd</code> e rodar.</p>
<blockquote>
<p>Ah, Kiko, não vai dar nenhum exemplo de código??</p>
</blockquote>
<p>Quem disse que não? Toma aí: <a target="_blank" href="https://github.com/kaiquegarcia/gomarket/">https://github.com/kaiquegarcia/gomarket/</a></p>
<p>Eu fiz esse projeto para explorar alguns conceitos na minha mente. Por exemplo, o armazenamento em disco, gerenciado de forma abstrata por uma <code>collection</code>. Funcionou perfeitamente nos primeiros experimentos e deu até pra escrever testes de ponta.</p>
<p>Como pode ver no git, praticamente toda <code>struct</code> implementa uma <code>interface</code>. Isso serve para que o <code>mockery</code> consiga mockar absolutamente qualquer coisa da minha aplicação, facilitando a escrita de quaisquer testes.</p>
<p>Além disso, a clara separação de responsabilidades por pacotes deixa claro onde poderia estar alguma coisa. Nesse projeto, eu coloquei a pasta <code>http</code> dentro da <code>cmd</code>. Como falei: <strong>siga seu coração</strong>! E dessa vez eu quis jogar lá mesmo. Mas também tenho projetos com a presença do pacote dentro da <code>internal</code>. É meio louco isso, né?</p>
<hr />
<p>Enfim, por hoje é só! Diferentemente do meu blog pessoal, aqui, no Code Aspiras, não pretendo dar continuidade de um artigo pro outro. Nesse escrevi sobre Golang, no próximo pode ser um Typescript, Angular, Javascript, PHP, Java, sei lá. Não estou com um foco em mente e ultimamente não sobra muito tempo pra fazer um trabalho mais prolongado nas escritas.</p>
<p>Então vou escrever o que percebo que poderia ser relevante pra quem fosse trabalhar comigo, por exemplo. Esse artigo é extremamente relevante pra qualquer iniciante de Golang que for se aventurar nos meus projetos.</p>
<p>Outro detalhe é que Go é uma linguagem muito nova. Não existe nada como regras absolutas. O que eu disse aqui é apenas uma das milhares de formas de se fazer um projeto bem limpo, legível e fácil de manter. Ainda há muitos assuntos que não foram discutidos, como conceitos de redução de código (DRY, AHA, etc) e técnicas para enxugar complexidades lógicas. Pretendo escrever artigos sobre eles, voltados a Golang, assim como redigir alguns aprendizados importantes que tive com outros colegas de equipe.</p>
<h3 id="heading-artigos-interessantes">Artigos interessantes</h3>
<ul>
<li><p><a target="_blank" href="https://dev.to/odilonjk/socorro-como-posso-organizar-os-pacotes-em-go-km0">Socorro! Como posso organizar os pacotes em Go? (Odilon Jonathan Kröger)</a>;</p>
</li>
<li><p><a target="_blank" href="https://medium.com/deliveryherotechhub/mocking-an-interface-using-mockery-in-go-afbcb83cc773">Mocking an Interface using Mockery in Go (Mert Kimyonşen)</a>;</p>
</li>
<li><p><a target="_blank" href="https://dev.to/booscaaa/documentanto-uma-api-go-com-swagger-2k05">Documentanto uma api Go com Swagger (Vinícius Boscardin)</a>.</p>
</li>
</ul>
<p>E agora eu vou indo nessa. Abraço!</p>
<p><img src="https://media.giphy.com/media/VduFvPwm3gfGO8duNN/giphy.gif?cid=790b7611o7vndc16am9f9afr7fuum1lm9se2mn4wt1xvojzm&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="Crianças correndo para se abraçar." class="image--center mx-auto" /></p>
<p>Inté!</p>
]]></content:encoded></item><item><title><![CDATA[Uma partida, não um adeus]]></title><description><![CDATA[Olá, leitores do meu blog. Tudo bem com vocês? Preciso falar o óbvio: faz MUITO TEMPO que fiquei sem escrever absolutamente uma palavra por aqui. Realmente acreditei na ilusão de que conseguiria conciliar certas atividades, mas minha vida tá uma bagu...]]></description><link>https://blog.kaiquegarcia.dev/uma-partida-nao-um-adeus</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/uma-partida-nao-um-adeus</guid><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Thu, 29 Sep 2022 22:22:28 GMT</pubDate><content:encoded><![CDATA[<p>Olá, leitores do meu blog. Tudo bem com vocês? Preciso falar o óbvio: faz <strong>MUITO TEMPO</strong> que fiquei sem escrever absolutamente uma palavra por aqui. Realmente acreditei na ilusão de que conseguiria conciliar certas atividades, mas minha vida tá uma bagunça.</p>
<p>Eu não vou enrolar muito nas desculpas, mas quero abrir um espaço para nos comunicarmos caso alguém queira um mentor pra tirar dúvidas no tempo livre. O que acha? Enfim, se você quiser me contactar, tem algumas redes onde sou sempre bem receptivo pra galera de TI (mesmo se você AINDA não for da área, mas tem intenção de migrar):</p>
<ul>
<li><p><s>Twitter</s> (\EDIT: vazei do Twitter);</p>
</li>
<li><p><a target="_blank" href="https://bsky.app/profile/kaiquegarcia.dev">Blue Sky</a>;</p>
</li>
<li><p><a target="_blank" href="https://kaiquegarcia.dev/telegram">Telegram</a>.</p>
</li>
</ul>
<p>É, só essas duas mesmo. Tenho um WhatsApp mas prefiro não expor meu telefone (embora acreditando fortemente que <em>Telegram &gt;&gt;&gt; WhatsApp</em>).</p>
<p>Então deixo essa mensagem como uma despedida temporária. Não consegui concluir a missão de pregar a palavra do PHP, hahaha.</p>
<p>PS.: lembre-se que além de trabalhar em empresa multilíngue, eu sou pai de gêmeas. Então eu tô SEMPRE mentalmente esgotado. Na grande maioria das vezes eu costumo não responder desconhecidos automaticamente, mas depois que começamos a conversar (e eu passe a acreditar que não é um bot), a conversa vai fluir mais rápido, rs.</p>
<p>Assuntos que consigo mentorar:</p>
<ul>
<li><p>PDI (plano de desenvolvimento individual ou plano de carreira);</p>
</li>
<li><p>Indicação de cursos de front-end / back-end;</p>
</li>
<li><p>Avaliar soluções JS (incluindo frameworks como Node.js, React.js, Angular, Vue.js, etc), PHP (Laravel, Lumen e me arrisco um pouco sobre Swoole), Golang (aqui é onde estou mais forte no momento), etc (também consigo direcionar a pesquisas quando não sei sobre o assunto);</p>
</li>
<li><p>Enfim, coisas relacionadas ao técnico, eu geralmente sou bem prestativo, mas só oriento! Não faço trabalho nenhum por você.</p>
</li>
</ul>
<p>Se for do teu interesse, só vem!</p>
<p>E até a próxima, pessoal...</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP para Iniciantes - Classes e Objetos - Operador de Resolução de Escopo]]></title><description><![CDATA[Olá, leitores da taverna, tudo belezinha? Antes de irmos direto ao assunto desse artigo, gostaria de quebrar um pouco esse costume de deixar a escrita pessoal pro final, pode ser?

Ah, não, Kiko... Que que você quer dessa vez?!

Hahaha, só conhecer q...]]></description><link>https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-operador-de-resolucao-de-escopo</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-operador-de-resolucao-de-escopo</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Sat, 11 Jun 2022 19:31:43 GMT</pubDate><content:encoded><![CDATA[<p>Olá, leitores da taverna, tudo belezinha? Antes de irmos direto ao assunto desse artigo, gostaria de quebrar um pouco esse costume de deixar a escrita pessoal pro final, pode ser?</p>
<blockquote>
<p>Ah, não, Kiko... Que que você quer dessa vez?!</p>
</blockquote>
<p>Hahaha, só conhecer quem está lendo! Eu tenho dois grandes objetivos para esse ano de 2022:</p>
<ol>
<li>ajudar <strong>100 aspirantes a dev</strong> a, de fato, conseguir um emprego como dev: pelo andar da carruagem, acho que não vou conseguir... Mas já ajudei quase 30, hein?! e não, eu não mexo pauzinhos para alguém pular uma catraca e entrar... A única coisa que faço é guiar as pessoas a seguir uma direção de forma lógica e explorar os conhecimentos para ver com o que se identifica. Bora?</li>
<li>criar um evento cíclico de coding dojo para devs Golang, nem que seja só na empresa onde estou: percebi que a correria da vida está sendo um verdadeiro problema pra tocar isso. Nem eu tenho energia pra fazer no horário livre, nem os devs demonstram querer, de fato, que isso aconteça. Será que é porque nunca foram a um coding dojo ou só não acham isso tão relevante assim? Talvez o problema seja <strong>eu</strong>?</li>
</ol>
<p>Enfim... Se você se encaixa de alguma forma em um dos meus objetivos, seja por querer participar de um coding dojo ou por querer trabalhar como dev, não hesite em me procurar, fechado?! Eu também ajudo empresas a organizar coding dojos para seus colaboradores, mas geralmente eu não participo dos eventos, por serem fechados. Eu só digo o que fazer, opino se o desafio tá bem interessante, etc. Eu nem cobro por essas paradas! Aiai...</p>
<p>Agora chega, vamos falar de PHP!</p>
<h2 id="heading-operador-de-resolucao-de-escopo">Operador de Resolução de Escopo <em>(<code>::</code>)</em></h2>
<p>Esse nome pode nos confundir bastante, mas eu já mostrei esse operador diversas vezes ao longo dos artigos sobre classes, será que você reparou? Em algum momento até aqui, eu te ensinei, de forma explícita, como acessar propriedades e métodos de um objeto, usando o operador <code>-&gt;</code>. Esse operador é específico para dados <strong>não-estáticos</strong>, ou seja, que precisam de uma instância para existir.</p>
<p>E da mesma forma que esse tipo de estrutura existe, também temos os dados <strong>estáticos</strong>, que não precisam de uma instância. São eles:</p>
<ul>
<li><strong>constantes</strong>: se o valor é fixo, por que raios eu precisaria instanciar a classe para acessá-lo?;</li>
<li><strong>propriedades estáticas</strong>: ok, não é fixo, mas tem um valor que transita entre instâncias, ou seja, compartilhado... Não necessariamente precisa de uma instância para existir;</li>
<li><strong>métodos estáticos</strong>: são funções quase desacopladas de uma classe, presente por apenas dois motivos - ou para tornar a legibilidade de um código mais semântico, ou para poder acessar outros dados estáticos da própria classe que tem visibilidade protegida ou restrita. Temos apenas uma exceção para <a target="_blank" href="https://refactoring.guru/pt-br/design-patterns/factory-method"><strong>fábricas</strong>, que é um <em>design pattern</em> que usa função estática como gerador de instâncias</a>... Isso não vai ser abordado aqui, mas achei relevante mencionar.</li>
</ul>
<p>Para exemplificar os cenários acima, escrevi o código a seguir:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sirene</span> </span>{
    <span class="hljs-comment">// Constantes</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">const</span> SOM = <span class="hljs-string">"UEEENNNNNNNNNN"</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> REPETICOES = <span class="hljs-number">20</span>;

    <span class="hljs-comment">// Propriedades estáticas</span>
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $RESPONSAVEL = <span class="hljs-string">""</span>;

    <span class="hljs-comment">// Métodos estáticos</span>
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tocar</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $autor</span>): <span class="hljs-title">void</span> </span>{
        Sirene::$RESPONSAVEL = $autor;
        <span class="hljs-keyword">for</span> ($contador = <span class="hljs-number">0</span>; $contador &lt; Sirene::REPETICOES; $contador++) {
            <span class="hljs-keyword">echo</span> Sirene::SOM . PHP_EOL;
        }
    }
}

<span class="hljs-comment">// 1. Qual é o som da sirene?</span>
<span class="hljs-keyword">echo</span> <span class="hljs-string">"O som da sirene é: "</span> . Sirene::SOM . PHP_EOL;

<span class="hljs-comment">// 2. Ligue a sirene!</span>
Sirene::tocar(<span class="hljs-string">"Fulano"</span>);

<span class="hljs-comment">// 3. Quem ligou a sirene?!</span>
<span class="hljs-keyword">echo</span> <span class="hljs-string">"Quem ligou a sirene foi "</span> . Sirene::$RESPONSAVEL;
</code></pre>
<p>Veja o código em ação: <a target="_blank" href="https://onlinephp.io/c/900c7">https://onlinephp.io/c/900c7</a></p>
<blockquote>
<p>Tá, Kiko, se o objetivo desse operador é acessar dados de uma classe, por que se chama <strong>Operador de Resolução de Escopo</strong>?</p>
</blockquote>
<p>Porque ele pode ser aplicado de diversas formas. Eu te disse que ele acessa dados estáticos, certo? Mas jamais falei que só poderia ser usado em classes, pois também é possível aplicarmos em um objeto ou em palavras-chave como <code>self</code>, <code>static</code> e <code>parent</code>. Ele irá funcionar em qualquer uma, desde que o dado que está tentando acessar exista para aquela referência.</p>
<p>Ou seja: você diz o escopo e a referência do dado que você quer acessar e o operador <strong>resolve</strong> isso pra você. Faz mais sentido agora?</p>
<p>Nós podemos reescrever o código acima para mostrar a aplicação em objeto e nas palavras-chave <code>self</code> e <code>static</code>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sirene</span> </span>{
    <span class="hljs-comment">// Constantes</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">const</span> SOM = <span class="hljs-string">"UEEENNNNNNNNNN"</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> REPETICOES = <span class="hljs-number">20</span>;

    <span class="hljs-comment">// Propriedades estáticas</span>
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $RESPONSAVEL = <span class="hljs-string">""</span>;

    <span class="hljs-comment">// Métodos estáticos</span>
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tocar</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $autor</span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-built_in">self</span>::$RESPONSAVEL = $autor;
        <span class="hljs-comment">// "self" equivale a Sirene, pois está dentro dessa classe</span>
        <span class="hljs-comment">// e nesse caso, poderíamos usar também a palavra "static"</span>
        <span class="hljs-comment">// "self" representa a classe que implementa o método acionado</span>
        <span class="hljs-comment">// "static" representa a classe acionada</span>
        <span class="hljs-comment">// vou mostrar mais exemplos, não se preocupe... mas vamos de static:</span>
        <span class="hljs-keyword">for</span> ($contador = <span class="hljs-number">0</span>; $contador &lt; <span class="hljs-built_in">static</span>::REPETICOES; $contador++) {
            <span class="hljs-keyword">echo</span> <span class="hljs-built_in">static</span>::SOM . PHP_EOL;
        }
    }
}

<span class="hljs-comment">// Digamos que, ao invés de acessar a classe, por algum motivo nós temos um objeto Sirene</span>
$sirene = <span class="hljs-keyword">new</span> Sirene();

<span class="hljs-comment">// Então, ao invés de usar Sirene::, podemos usar $sirene::</span>

<span class="hljs-comment">// 1. Qual é o som da sirene?</span>
<span class="hljs-keyword">echo</span> <span class="hljs-string">"O som da sirene é: "</span> . $sirene::SOM . PHP_EOL;

<span class="hljs-comment">// 2. Ligue a sirene!</span>
$sirene::tocar(<span class="hljs-string">"Fulano"</span>);

<span class="hljs-comment">// 3. Quem ligou a sirene?!</span>
<span class="hljs-keyword">echo</span> <span class="hljs-string">"Quem ligou a sirene foi "</span> . $sirene::$RESPONSAVEL;
</code></pre>
<p>Veja o código na prática: <a target="_blank" href="https://onlinephp.io/c/0653b">https://onlinephp.io/c/0653b</a></p>
<blockquote>
<p>Mas Kiko, se eu posso escrever o nome da classe, por que que eu usaria as outras formas? Onde que isso faz sentido?</p>
</blockquote>
<p>Concordo que, em cenários onde é possível escrever o nome da classe, é muito mais legível deixar a classe por extenso. Ainda assim, nem sempre isso é possível de se fazer, principalmente se você está desenvolvendo um código utilizando <strong>interfaces</strong>, como mencionei no artigo anterior, que pode obrigar a desenvolver métodos estáticos e você não faz ideia de qual implementação está recebendo na função.</p>
<p>Por exemplo, veja a função <code>calcularDano</code> a seguir:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Arma</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gerarDano</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $defesa</span>): <span class="hljs-title">float</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bazuca</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Arma</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gerarDano</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $defesa</span>): <span class="hljs-title">float</span> </span>{
        <span class="hljs-keyword">return</span> rand(<span class="hljs-number">500</span>, <span class="hljs-number">2000</span>) - $defesa;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Metralhadora</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Arma</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gerarDano</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $defesa</span>): <span class="hljs-title">float</span> </span>{
        <span class="hljs-keyword">return</span> rand(<span class="hljs-number">50</span>, <span class="hljs-number">350</span>) - $defesa;
    }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calcularDano</span>(<span class="hljs-params">Arma $arma, <span class="hljs-keyword">float</span> $defesa</span>): <span class="hljs-title">float</span> </span>{
    <span class="hljs-comment">// não sabemos com qual implementação da interface Arma estamos lidando</span>
    <span class="hljs-comment">// a única coisa que sabemos é que, o que quer que seja, implementa o método estático "gerarDano"</span>
    <span class="hljs-comment">// nesse caso, podemos usar o operador de resolução de escopo para nos dar acesso a esse mé<span class="hljs-doctag">todo:</span></span>
    $dano = $arma::gerarDano($defesa);
    <span class="hljs-keyword">if</span> ($dano &lt; <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0.0</span>;
    }
    <span class="hljs-keyword">return</span> $dano;
}

$defesa = rand(<span class="hljs-number">0</span>,<span class="hljs-number">200</span>);
$bazuca = calcularDano(<span class="hljs-keyword">new</span> Bazuca(), $defesa);
$metralhadora = calcularDano(<span class="hljs-keyword">new</span> Metralhadora(), $defesa);
<span class="hljs-keyword">echo</span> <span class="hljs-string">"Defesa: <span class="hljs-subst">$defesa</span>"</span> . PHP_EOL;
<span class="hljs-keyword">echo</span> <span class="hljs-string">"Dano aleatório da Bazuca: <span class="hljs-subst">$bazuca</span>"</span> . PHP_EOL;
<span class="hljs-keyword">if</span> ($bazuca &gt; <span class="hljs-number">2</span>*$defesa) {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"Foi crítico!"</span> . PHP_EOL;
}
<span class="hljs-keyword">echo</span> <span class="hljs-string">"Dano aleatório da Metralhadora: <span class="hljs-subst">$metralhadora</span>"</span> . PHP_EOL;
<span class="hljs-keyword">if</span> ($metralhadora &gt; <span class="hljs-number">2</span>*$defesa) {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"Foi crítico!"</span> . PHP_EOL;
}
</code></pre>
<p>Veja o código na prática: <a target="_blank" href="https://onlinephp.io/c/e46e8">https://onlinephp.io/c/e46e8</a></p>
<blockquote>
<p>Ok, acho que entendi o uso desse operador com objetos... Mas e as palavras-chave? Quando faz sentido usar?</p>
</blockquote>
<p>Em cenários onde há o uso de <strong>Herança</strong>. Vamos revisar cada palavra-chave:</p>
<h2 id="heading-self"><code>self</code></h2>
<p>Trata-se de uma referência para a <strong>classe onde o método</strong> acionado <strong>está registrado</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654993502303/Tq853JutF.png" alt="Representação: self" class="image--center mx-auto" /></p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mae</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $EXPERIMENTO = <span class="hljs-string">"MÃE"</span>;
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">teste</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{ <span class="hljs-comment">// método registrado na classe Mae</span>
        <span class="hljs-keyword">echo</span> <span class="hljs-built_in">self</span>::$EXPERIMENTO; <span class="hljs-comment">// self = Mae, sempre</span>
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Filha</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mae</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $EXPERIMENTO = <span class="hljs-string">"FILHA"</span>;
}

Filha::teste(); <span class="hljs-comment">// imprimirá "MÃE"</span>
</code></pre>
<p>Veja o código em ação: <a target="_blank" href="https://onlinephp.io/c/81e90">https://onlinephp.io/c/81e90</a></p>
<h2 id="heading-static"><code>static</code></h2>
<p>Trata-se de uma referência para a <strong>classe acionada</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654993588584/2pznkMqlq.png" alt="Representação: static" class="image--center mx-auto" /></p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mae</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $EXPERIMENTO = <span class="hljs-string">"MÃE"</span>;
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">teste</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-built_in">static</span>::$EXPERIMENTO; <span class="hljs-comment">// static = depende</span>
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Filha</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mae</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $EXPERIMENTO = <span class="hljs-string">"FILHA"</span>;
}

Filha::teste(); <span class="hljs-comment">// imprimirá "FILHA", pois o "static" aqui é a classe "Filha"</span>
</code></pre>
<p>Veja o código em ação: <a target="_blank" href="https://onlinephp.io/c/d7fcc">https://onlinephp.io/c/d7fcc</a></p>
<p>Observações:</p>
<ul>
<li>eu apenas troquei <code>self::$EXPERIMENTO</code> por <code>static::$EXPERIMENTO</code>;</li>
<li>se a classe <code>Filha</code> não sobreescrevesse a propriedade <code>$EXPERIMENTO</code>, herdaria o valor da classe <code>Mae</code>. Não significa que está acessando a classe <code>Mae</code>, apenas usando o valor que foi herdado, beleza? Faz o teste aí: <a target="_blank" href="https://onlinephp.io/c/271ce">https://onlinephp.io/c/271ce</a>.</li>
</ul>
<h2 id="heading-parent"><code>parent</code></h2>
<p>Trata-se de uma referência a <strong>classe que vem antes da classe onde o método</strong> acionado <strong>está registrado</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654993678433/bYh3FZI7E.png" alt="Representação: static" class="image--center mx-auto" /></p>
<p>Que descrição complexa, né?! Você pode pensar dessa forma: ele funciona como o <code>self</code>, só que busca a classe que foi extendida pela classe presente em <code>self</code>. Para isso, vamos fazer mais uma classe:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mae</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $EXPERIMENTO = <span class="hljs-string">"MÃE"</span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Filha</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mae</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $EXPERIMENTO = <span class="hljs-string">"FILHA"</span>;
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">teste</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-built_in">parent</span>::$EXPERIMENTO; <span class="hljs-comment">// parent = Mae, sempre</span>
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Neta</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Filha</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> $EXPERIMENTO = <span class="hljs-string">"NETA"</span>;
}

Neta::teste(); <span class="hljs-comment">// imprimirá "MÃE"</span>
</code></pre>
<p>Veja o código em ação: <a target="_blank" href="https://onlinephp.io/c/ece">https://onlinephp.io/c/ece</a></p>
<center><h1>. . .</h1></center>

<p>E por hoje é só! Curtiu?? <strong>Comenta e compartilha</strong>!! Uma curiosidade bacana sobre esse operador é que o nome oficial que deram a ele é <strong>Paamayim Nekudotayim</strong>, que é a fonética para <strong>פעעמיים נקודותיים</strong>, que significa <a target="_blank" href="https://translate.google.com/?sl=iw&amp;tl=pt&amp;text=%D7%A4%D7%A2%D7%A2%D7%9E%D7%99%D7%99%D7%9D%20%D7%A0%D7%A7%D7%95%D7%93%D7%95%D7%AA%D7%99%D7%99%D7%9D&amp;op=translate"><strong>dois pontos duplos</strong> em Hebreu</a>!</p>
<p>Então, se por algum motivo você encontrar um erro com essas palavras no PHP, já vai ficar ligado que se trata de algum uso errado do operador de resolução de escopo! Hehehehe. Espero que tenham curtido, hein?! No próximo artigo, falaremos um pouco mais sobre <a target="_blank" href="https://www.php.net/manual/pt_BR/language.oop5.static.php">a palavra-chave <code>static</code></a>. Hoje só falamos a ponta do iceberg, usando <code>static</code> como referência. No próximo, vamos falar sobre dados estáticos. Não perca, hein?</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP para Iniciantes - Classes e Objetos - Herança]]></title><description><![CDATA[Olá, devs incríveis e maravilhoses. Tudo certinho com vocês?! Eu consegui um tempinho para escrever esse artigo, então acho que estou bem, haha.
O assunto de hoje vai ser mais um pequeno salto no fluxo atual da documentação oficial do PHP, pois ao in...]]></description><link>https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-heranca</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-heranca</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><category><![CDATA[PHPparaIniciantes]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Thu, 09 Jun 2022 12:22:22 GMT</pubDate><content:encoded><![CDATA[<p>Olá, devs incríveis e maravilhoses. Tudo certinho com vocês?! Eu consegui um tempinho para escrever esse artigo, então acho que estou bem, haha.</p>
<p>O assunto de hoje vai ser mais um pequeno salto no fluxo atual da documentação oficial do PHP, pois ao invés de falarmos somente sobre <strong><a target="_blank" href="https://www.php.net/manual/pt_BR/language.oop5.visibility.php">Visibilidade</a></strong>, falaremos de <strong><a target="_blank" href="https://www.php.net/manual/pt_BR/language.oop5.inheritance.php">Herança</a></strong>.</p>
<blockquote>
<p>Ué, Kiko... Por que pularemos esse assunto?</p>
</blockquote>
<p>Pelo simples fato de que eu já falei sobre ele. Lembra das palavras <code>public</code>, <code>private</code> e <code>protected</code>? Eu expliquei nos artigos onde esse tópico estava relevante:</p>
<ol>
<li><a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-o-objetos-propriedades">Visibilidade de Propriedades</a> (procura por <strong>1.1.1</strong>);</li>
<li><a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-o-basico">Visibilidade de Métodos</a> (procura por <strong>3. O que é e como declarar métodos</strong>).</li>
</ol>
<p>Ainda assim, há um pequeno detalhe que não falei a respeito: <strong><a target="_blank" href="https://www.php.net/manual/pt_BR/language.oop5.visibility.php#language.oop5.visibility-other-objects">visibilidade em outros objetos</a></strong>. Vou dedicar essa introdução para isso, ok? Afinal, está relacionado com <strong>herança</strong>.</p>
<h2 id="heading-visibilidade-entre-objetos">Visibilidade entre objetos</h2>
<p>A visibilidade que damos às propriedades e métodos pertence à assinatura da classe que estamos desenvolvendo. Isso significa que mesmo que você escreva uma propriedade privada, instâncias diferentes da mesma classe poderão acessar esse valor. Basta injetar a outra instância em algum método:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $codigo
    </span>) </span>{ }

    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">imprime</span>(<span class="hljs-params">$ex Exemplo</span>) </span>{
        <span class="hljs-keyword">echo</span> $ex-&gt;codigo;
        <span class="hljs-comment">// $ex-&gt;codigo é uma propriedade privada da instância $ex</span>
        <span class="hljs-comment">// mas eu consigo acessar seu valor, pois estamos dentro da classe que conhece toda a assinatura dele</span>
    }
}

$ex = <span class="hljs-keyword">new</span> Exemplo(<span class="hljs-number">123</span>);
Exemplo::imprime($ex);
</code></pre>
<p>Notou que o método estático <code>imprime</code> está recebendo um objeto da classe <code>Exemplo</code>? E que esse método também pertence à classe <code>Exemplo</code>? Dessa forma, é possível trabalhar com todas as propriedades e métodos privados de <code>$ex</code>.</p>
<blockquote>
<p>E o que isso tem a ver com herança, Kiko?</p>
</blockquote>
<p><strong>Tudo</strong>. Nós podemos acessar propriedades protegidas de outra classe, se estiver herdada na classe atual. É por isso que digo que a visibilidade entre objetos faz parte de herança.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">protected</span> <span class="hljs-keyword">string</span> $name
    </span>) </span>{ }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pilot</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">criticize</span>(<span class="hljs-params">Person $person</span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-keyword">echo</span> $person-&gt;name . <span class="hljs-string">" ainda tem muito o que aprender..."</span> . PHP_EOL;
    }
}

$john = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"John Doe"</span>);


$pilot = <span class="hljs-keyword">new</span> Pilot(<span class="hljs-string">"José"</span>);
$pilot-&gt;criticize($john);
</code></pre>
<p>Veja o código funcionando: <a target="_blank" href="https://onlinephp.io/c/b7bb0">https://onlinephp.io/c/b7bb0</a></p>
<ol>
<li><code>$person-&gt;name</code> é uma propriedade protegida de <code>Person</code>;</li>
<li><code>Pilot</code> extende <code>Person</code>, logo ele herda todos os métodos e propriedades protegidos e públicos de <code>Person</code>, incluindo <code>$person-&gt;name</code>;</li>
<li>Quando <code>Pilot</code> recebe um objeto <code>Person</code>, ele pode acessar tudo aquilo que herdou dele.</li>
</ol>
<p>É por isso que vemos por aí o pessoal divulgando herança sempre como uma relação Pai e Filho. Hoje vou quebrar um pouco esse ciclo vicioso:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mae</span> </span>{
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">array</span> $imoveis;
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">array</span> $contasBancarias;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Filho</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mae</span> </span>{ }
</code></pre>
<p>Esse exemplo faz sentido e, ao mesmo tempo, não faz.</p>
<center>
<img src="https://media.giphy.com/media/xTiTnDAP0RiCo9k85W/giphy.gif" alt="MEME: é o que, véi?" />
</center>

<blockquote>
<p>Como é, Kiko?</p>
</blockquote>
<p>Olhando somente pela herança entre as classes, nós entendemos que a classe <code>Filho</code> herda as propriedades <code>imoveis</code> e <code>contasBancarias</code> da classe <code>Mae</code>. Porém, da forma como está, <code>Filho</code> herda tudo, não somente bens e dinheiro. Se a gente cria uma propriedade que define o emprego da mãe, o filho estaria herdando isso também... E na vida real, a gente sabe que isso não faz sentido algum, não é mesmo?</p>
<p>Se fossemos replicar a herança da vida real, esse relacionamento seria limitado aos objetos e não às classes. O que poderíamos fazer é criar uma abstração, definindo o que é uma pessoa e criando relacionamento entre pessoas, sem herança:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pessoa</span> </span>{
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">array</span> $imoveis;
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">array</span> $contasBancarias;
    <span class="hljs-keyword">protected</span> Pessoa|<span class="hljs-literal">null</span> $pai; <span class="hljs-comment">// sutilidade triste aqui, mas é realidade. Se você se identificou, força! Eu te respeito muito.</span>
    <span class="hljs-keyword">protected</span> Pessoa $mae;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">herancaMaternal</span>(<span class="hljs-params"></span>) </span>{
        array_push(<span class="hljs-keyword">$this</span>-&gt;imoveis, <span class="hljs-keyword">$this</span>-&gt;mae-&gt;imoveis...);
        <span class="hljs-comment">// na real, aqui a gente precisa dividir com os irmãos ainda, né? mas vamos deixar assim só pra explicar o que eu tava falando</span>
        array_push(<span class="hljs-keyword">$this</span>-&gt;contasBancarias, <span class="hljs-keyword">$this</span>-&gt;mae-&gt;contasBancarias...);
    }
}
</code></pre>
<p>Com isso, a pessoa que acionar <code>$pessoa-&gt;herancaMaternal()</code> só vai receber o que de fato herdou, quando for a hora. Percebeu que eu acessei os atributos protegidos <code>imoveis</code> e <code>contasBancarias</code> de <code>$this-&gt;mae</code>? Só foi possível pois a visibilidade de qualquer instância de <code>Pessoa</code> nos permite "ver" esses dados naquele bloco.</p>
<p>E com isso, temos uma boa introdução para o artigo...</p>
<h2 id="heading-heranca">Herança</h2>
<blockquote>
<p>Oloko, Kiko, isso foi só uma introdução?!</p>
</blockquote>
<p>Eu queria que fosse, mas eu já escrevi bastante, né? Hahaha. Pelo menos agora eu vou poder ser um pouco mais direto...</p>
<p><strong>Resusmo</strong>: herança, em orientação a objeto, é o compartilhamento de recursos entre classes. Se a classe <code>A</code> <strong>extende</strong> a classe <code>B</code>, ela herda todos os métodos e propriedades públicos e privados dela. Esses métodos e propriedades passam a coexistir tanto em <code>B</code> quanto em <code>A</code>.</p>
<p>A forma de escrita é na declaração da classe. Até aqui, você me viu declarando classes como <code>class AlgumaCoisa</code>, certo? Em herança, a declaração inclui a palavra <code>extends</code> que indica de qual classe você está herdando:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span> </span>{ }
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">A</span> </span>{ } 
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">C</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">B</span> </span>{ }
</code></pre>
<p>Sim, é possível fazer heranças contínuas.</p>
<p>Um tópico interessante sobre herança é o <code>override</code>, ou seja, <code>sobreescrever</code> alguma coisa. Uma amostra bem simples disso seria uma classe <code>A</code> implementar o método <code>vibrar()</code> de um jeito e a classe que a herda reimplementar de outra forma:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">vibrar</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-string">"zzz"</span> . PHP_EOL;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">A</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">vibrar</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-string">"BZZZZ"</span> . PHP_EOL;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">C</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">A</span> </span>{ }
</code></pre>
<p>Se você chamar:</p>
<ul>
<li><code>A::vibrar()</code>: irá imprimir <code>zzz</code>;</li>
<li><code>B::vibrar()</code>: irá imprimir <code>BZZZZ</code>;</li>
<li><code>C::vibrar()</code>: irá imprimir <code>zzz</code>.</li>
</ul>
<p>Veja o código rodando aqui: <a target="_blank" href="https://onlinephp.io/c/98c0e">https://onlinephp.io/c/98c0e</a></p>
<blockquote>
<p>Ué, por que só <code>B::vibrar()</code> está diferente?</p>
</blockquote>
<p>Porque ele sobreescreveu o comportamento de <code>A</code> ao reimplementar o método <code>vibrar()</code>.</p>
<p>Override é um recurso comumente utilizado quando encontramos alguma particularidade no meio das heranças, por isso podemos fazer isso. Mas é preciso tomar cuidado com um pequeno detalhe: antes do PHP 8, nós não tínhamos a capacidade de informar o tipo de dado que cada função e/ou método poderia retornar, por isso sempre foi possível sobreescrever os métodos herdados retornando um tipo de dado completamente diferente.</p>
<p>A partir do PHP 8.1, esse tipo de comportamento gera um aviso de depreciação, o que significa que, muito em breve, essa prática não irá mais funcionar nas novas versões.</p>
<p>Ou seja: precisou reimplementar um método e mudou a assinatura dele? É melhor refatorar enquanto ainda pode... Veja o alerta de depreciação aqui: <a target="_blank" href="https://onlinephp.io/c/c6e6d">https://onlinephp.io/c/c6e6d</a>.</p>
<p>Na documentação, consta a possibilidade de omitir esse alerta ao aplicar o atributo <code>#[ReturnTypeWillChange]</code> acima da assinatura do método ou função, porém não recomendo e nem vou explorar isso... Até porque, se há esse risco nas suas heranças, isso só mostra que você está quebrando o seu código.</p>
<p>O que nos leva à seguinte polêmica...</p>
<h2 id="heading-heranca-e-anti-pattern">Herança é <strong>anti-pattern</strong></h2>
<p>A herança entre classes, apesar de ser bem aceito na programação com abstrações, também pode ser considerado um <strong>anti-pattern</strong> ou <strong>anti-padrão</strong>. O exemplo que dei ali de pessoas, mãe, filho e tal evidencia isso: muitas vezes aplicamos uma lógica de herança porque queremos reduzir código, mas quase sempre estamos enxergando a abstração da forma errada.</p>
<p>Como esse artigo é pra quem nunca viu a parada, eu preciso mostrar o erro acontecendo, não é mesmo? Então vamos lá...</p>
<p>Digamos que nós queremos criar uma classe que represente um fusca e que tenha uma função de buzinar, sendo o som da buzina <code>"bibii"</code>.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Fusca</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">buzinar</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-string">"bibii"</span>;
    }
}

$fusca = <span class="hljs-keyword">new</span> Fusca();
$fusca-&gt;buzinar();
</code></pre>
<p>E agora, além do fusca, queremos uma lamborghini, sendo a buzina <code>"pompom"</code>.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Lamborghini</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">buzinar</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-string">"pompom"</span>;
    }
}

$lamborghini = <span class="hljs-keyword">new</span> Lamborghini();
$lamborghini-&gt;buzinar();
</code></pre>
<blockquote>
<p>Ué, Kiko... Repetiu tudo?!</p>
</blockquote>
<p>Sim, criamos uma repetição de código, onde a única diferença é o som da buzina. Se eu quiser criar uma função que chama essa buzina independente do modelo de carro, nós teremos um problema, pois as classes não tem relação entre si.</p>
<p>Geralmente, a primeira coisa que as pessoas pensam quando querem resolver esse tipo de problema é em herança, pois é a saída mais fácil: ah, pega o que tem em comum, cria uma classe abstrata com isso e pronto.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Carro</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">buzinar</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-built_in">static</span>::BUZINA . PHP_EOL;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Fusca</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Carro</span> </span>{
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">const</span> BUZINA = <span class="hljs-string">"bibii"</span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Lamborghini</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Carro</span> </span>{
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">const</span> BUZINA = <span class="hljs-string">"pompom"</span>;
}

<span class="hljs-comment">// Função genérica para todos os carros</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">apertarBuzina</span>(<span class="hljs-params">Carro $carro</span>) </span>{
    $carro-&gt;buzinar();
}

<span class="hljs-comment">// Aplicando a função</span>
$fusca = <span class="hljs-keyword">new</span> Fusca();
$lamborghini = <span class="hljs-keyword">new</span> Lamborghini();

apertarBuzina($fusca);
apertarBuzina($lamborghini);
</code></pre>
<p>Veja o código em ação: <a target="_blank" href="https://onlinephp.io/c/cb978">https://onlinephp.io/c/cb978</a></p>
<blockquote>
<p>Pô, Kiko, para mim ficou muito legível... Por que isso seria considerado um <strong>anti-pattern</strong>??</p>
</blockquote>
<p>Sim, herança pode até deixar tudo mais organizado, porém a manutenabilidade disso é péssima pois criamos <strong>perigos invisíveis</strong>. Por exemplo, para indicar o som da buzina de cada carro, eu preciso declarar a constante <code>BUZINA</code>. Se eu escrever um carro sem declarar isso, nós teremos um erro:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CarroQuebrado</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Carro</span> </span>{ }

$carro = <span class="hljs-keyword">new</span> CarroQuebrado();
$carro-&gt;buzinar();
</code></pre>
<p>Veja o que acontece: <a target="_blank" href="https://onlinephp.io/c/2e033">https://onlinephp.io/c/2e033</a></p>
<p>Toda vez que precisarmos abstrair alguma coisa no nosso código, o ideal é criarmos uma estrutura rígida que nos force a criar tudo o  que for obrigatório. Essa estrutura rígida é chamada de <code>interface</code> e é amplamente utilizada em várias linguagens de programação.</p>
<p>Quando você define uma interface <code>Carro</code>, você está dizendo ao interpretador: <em>olha aqui, cara... Toda vez que alguma classe implementar essa estrutura, obrigue o desenvolvedor a escrever todos esses métodos do mesmo jeitinho que eu estou assinando aqui, ok?!</em></p>
<p>E o dev que se vire pra respeitar isso:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ICarro</span> </span>{ <span class="hljs-comment">// colocamos o I na frente pra deixar claro que é uma interface</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">obterBuzina</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span>
}</span>
</code></pre>
<p>Diferente de herança, a declaração de uma interface é precedido pela palavra-chave <code>interface</code>. Em herança, nós declaramos classes mesmo... Da mesma forma, para declarar que uma classe está seguindo as regras de uma interface, nós usamos a palavra-chave <code>implements</code>, diferente do <code>extends</code> da herança.</p>
<p>Toda classe que implementar a interface <code>ICarro</code> precisará ter um método <code>obterBuzina()</code> que retorna uma <code>string</code>. Com isso, a gente pode recriar aquelas classes <code>Fusca</code> e <code>Lamborghini</code> para parar de usar herança e passar a assinar a nova interface:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Fusca</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ICarro</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">obterBuzina</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"bibii"</span>;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Lamborghini</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ICarro</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">obterBuzina</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"pompom"</span>;
    }
}
</code></pre>
<p>Ficou um pouco mais verboso? Ficou, duas linhas... Ainda assim, as próximas classes de carro que forem criadas não terão o risco de alguém esquecer de escrever o que é obrigatório.</p>
<blockquote>
<p>Mas Kiko, cadê o método <code>buzinar</code>?</p>
</blockquote>
<p>É aqui que fica o pulo do gato: apesar de fazer total sentido colocar um método <code>buzinar</code> nos carros, nós podemos criar uma função que faça a buzina em si... Afinal, na outra implementação, nós teríamos de criar essa função do mesmo jeito, lembra? Tínhamos <code>carro-&gt;buzinar</code> dentro de <code>apertarBuzina($carro)</code>.</p>
<p>Agora só precisamos do <code>apertarBuzina($carro)</code>:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">apertarBuzina</span>(<span class="hljs-params">ICarro $carro</span>): <span class="hljs-title">void</span> </span>{
    <span class="hljs-keyword">echo</span> $carro-&gt;obterBuzina() . PHP_EOL;
}

$fusca = <span class="hljs-keyword">new</span> Fusca();
$lamborghini = <span class="hljs-keyword">new</span> Lamborghini();

apertarBuzina($fusca);
apertarBuzina($lamborghini);
</code></pre>
<p>Veja o código funcionando aqui: <a target="_blank" href="https://onlinephp.io/c/cd215">https://onlinephp.io/c/cd215</a></p>
<p>Então mesmo herança sendo muito legal, tente pensar um pouco além, tudo bem? Você precisa fazer um código com o menor risco possível de erros acidentais. Pense sempre que outro desenvolvedor vai precisar mexer: é melhor força-lo a seguir um padrão do que criar padrões invisíveis, concorda?</p>
<p>E por hoje é só!! Curtiu? <strong>Comenta e compartilha</strong>! Acho que, com esse artigo, consegui deixar bem claro o motivo de herança ser considerado um <strong>anti-pattern</strong>... Ou você ainda discorda? Você teria feito esse exercício dos carros diferente? Pode mandar aí nos comentários, hehe.</p>
<p>No próximo artigo, falaremos sobre <strong><a target="_blank" href="https://www.php.net/manual/pt_BR/language.oop5.paamayim-nekudotayim.php">Operador de Resolução de Escopo (::)</a></strong>, que é o que usamos para acessar propriedades e métodos estáticos das classes. Tá preparade?</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP para Iniciantes - Classes e Objetos - Construtores e Destrutores]]></title><description><![CDATA[Olá, quanto tempo! Não sei o que rolou, mas meu último artigo fugiu totalmente da ordenação original dos assuntos. Se você voltar lá para a Introdução da série PHP para Iniciantes, verá que eu listei todos os assuntos que irei abordar. Namespace está...]]></description><link>https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-construtores-e-destrutores</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-construtores-e-destrutores</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Sat, 04 Jun 2022 21:33:25 GMT</pubDate><content:encoded><![CDATA[<p>Olá, quanto tempo! Não sei o que rolou, mas meu último artigo fugiu totalmente da ordenação original dos assuntos. Se você voltar lá para a <a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-introducao">Introdução da série PHP para Iniciantes</a>, verá que eu listei todos os assuntos que irei abordar. <strong>Namespace</strong> está  citado fora do conceito de <strong>Classes e Objetos</strong>, e mesmo assim escrevi sobre isso no último artigo, rs.</p>
<p>E não, não foi uma falha no manual oficial do PHP, pois lá também está separado dessa forma. Eu que pulei algum conteúdo mesmo. Ainda assim, se prestarmos atenção sobre a temática daquele tópico, faz muito sentido mencioná-lo enquanto falamos sobre classes, concorda? Talvez meio cedo demais, mas com certeza tem muito a ver.</p>
<p>Nesse artigo, voltaremos ao fluxo natural das coisas e vamos abordar o que estava agendado como "próximo tópico" no final do penúltimo artigo (Autoloading):</p>
<h2 id="heading-construtores-andamp-destrutores">Construtores &amp; Destrutores</h2>
<p>Como de costume, antes de irmos direto para o código eu gostaria de abrir um espaço para reflexão semântica, que é um espaço para pensarmos no significado das coisas. Por exemplo: o que raios é um <strong>construtor</strong>?? E o que é um <strong>destrutor</strong>?! São opostos?</p>
<p>De acordo com o dicionário, <strong>construtor</strong> é:</p>
<blockquote>
<ol>
<li>que ou aquele que constrói; construidor.<br /><em>"indústria c. de navios"</em></li>
<li>que ou aquele que possui empresa dedicada à construção de imóveis.</li>
</ol>
</blockquote>
<p>E <strong>destrutor</strong> é:</p>
<blockquote>
<p>m.q. DESTRUIDOR.</p>
</blockquote>
<p>Ou seja:</p>
<blockquote>
<p>que ou quem destrói; destrutor.</p>
</blockquote>
<hr />
<blockquote>
<p>Pô, Kiko, essa seção foi uma perda de tempo, não é mesmo? Como isso poderia ajudar a entender o que isso deveria ser no código?</p>
</blockquote>
<p>Se você pensou assim, calma, jovem! Na realidade, entender o significado das coisas antes de ir atrás delas ajuda a compreender 10000% melhor na hora de ver a prática, ok?! Vamos avançando...</p>
<p>Falando de classes e objetos, eu tentei deixar evidente que "Classe" é apenas uma definição de alguma coisa e nada mais que isso. O que deve representar algo "mais consolidado" é o "Objeto".</p>
<p>Esse sim, pode ter todo um ciclo de vida. Por exemplo: se temos uma classe "Pessoa", você seria um objeto dessa classe, uma instância dela. Depois de ler isso, o que você imagina que é um construtor e um destrutor? Sobre o que está relacionado?</p>
<blockquote>
<p>Pô, Kiko, para de mistério e fala de uma vez...</p>
</blockquote>
<p>Hahaha, ok! É simples: construtor é a função que <strong>inicializa</strong> um objeto. Ou seja, quando você está criando um objeto a partir de uma classe, o construtor é acionado.</p>
<p>Enquanto isso, destrutor é a função que <strong>finaliza</strong> o objeto. Quando ele está prestes a ser eliminado no ciclo de vida do sistema, o destrutor é acionado.</p>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654374109391/AMBAF-m3V.png" alt="Diagrama do Ciclo de Vida de um Objeto" />
</center>

<h2 id="heading-construtores">Construtores</h2>
<p>Quando você chama o operador <code>new</code> junto do nome de uma classe, o que você está acionando, na verdade, é uma função <code>__construct</code> dentro dela. Os argumentos que você insere no nome são injetados diretamente dentro dela, portanto, precisa respeitar a assinatura do que quer que tenha criado ali dentro.</p>
<p>Exemplificando:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Example</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $a;
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> $a</span>) </span>{
        <span class="hljs-keyword">$this</span>-&gt;a = $a;
    }
}
</code></pre>
<p>No construtor da classe <code>Example</code> acima, eu espero como argumento obrigatório <code>int $a</code>. Se você chamar <code>new Example(1)</code>, tudo vai funcionar perfeitamente. Mas se chamar <code>new Example()</code> (sem argumentos), teremos um grande erro acontecendo ao executar esse código.</p>
<p>Como você percebeu, a única coisa que meu construtor faz é pegar o argumento que você injetou na construção do objeto e definí-lo como valor de uma propriedade com mesmo nome dentro. Essa propriedade poderia ter qualquer outro nome:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Example</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $a;
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> $b</span>) </span>{
        <span class="hljs-keyword">$this</span>-&gt;a = $b;
    }
}
</code></pre>
<p>O importante aqui é perceber que <code>$a</code> é diferente de <code>$this-&gt;a</code>. <code>$a</code> no exemplo anterior era apenas a variável criada dentro do construtor, recebida como argumento. <code>$this-&gt;a</code> era uma propriedade interna do objeto que estamos instanciando. No exemplo atual, agora ficou bem mais claro pois nomeei de forma diferente.</p>
<blockquote>
<p>Ah, Kiko, eu preciso declarar a propriedade fora e dentro do construtor?</p>
</blockquote>
<p><strong>Depende</strong>. Se você usa PHP antes do 8.1: sim, você precisa. O PHP até consegue criar propriedades dinâmicas mas isso é horrível! Principalmente se você usa alguma ferramenta de análise estática do seu código. Então sempre declare essas propriedades direitinho.</p>
<p>Agora se você já está mais atualizado, é possível declarar as propriedades na assinatura do construtor! Veja o exemplo a seguir:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Example</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $a
    </span>) </span>{ }
}
</code></pre>
<p>Sim, isso é o equivalente ao primeiro exemplo, mas não preciso nem declarar a propriedade fora do construtor, nem atribuir o valor de uma variável do argumento. O PHP já faz isso pra mim nessa assinatura aí!</p>
<center>
<img src="https://media.giphy.com/media/DyvyiFFXF1Yli/giphy.gif" alt="MEME: quê?!" />
</center>

<p>Tirando esse detalhe, outro fator muito importante para as versões mais recentes da linguagem é sobre os campos <code>readonly</code>, ou seja, <strong>somente leitura</strong>. Quando você cria uma propriedade que não pode ser alterada, significa que o único momento de todo o ciclo de vida do objeto em que podemos atribuir algum valor à propriedade é no construtor. Dá pra fazer um monte de coisa bacana, hein?</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cents</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> readonly <span class="hljs-keyword">int</span> $value
    </span>) </span>{ }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">Cents $cents</span>): <span class="hljs-title">Cents</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">static</span>(<span class="hljs-keyword">$this</span>-&gt;value + $cents-&gt;value);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sub</span>(<span class="hljs-params">Cents $cents</span>): <span class="hljs-title">Cents</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">static</span>(<span class="hljs-keyword">$this</span>-&gt;value - $cents-&gt;value);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toString</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $symbol = <span class="hljs-string">"R$ "</span></span>): <span class="hljs-title">string</span> </span>{
        $str = <span class="hljs-string">"<span class="hljs-subst">{$this-&gt;value}</span>"</span>; <span class="hljs-comment">// só dá pra fazer isso aqui com inteiros pequenos, OK???</span>
        <span class="hljs-keyword">return</span> $symbol . preg_replace(<span class="hljs-string">"/(\d{2})$/"</span>, <span class="hljs-string">",<span class="hljs-subst">$1</span>"</span>, $str);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fromFloat</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $num</span>): <span class="hljs-title">Cents</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">static</span>(intval($num*<span class="hljs-number">100</span>));
    }
}
</code></pre>
<p>Com uma classe como essa, podemos fazer a seguinte brincadeira:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">include_once</span>( <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/Cents.php"</span>); <span class="hljs-comment">// ou substitua isso aqui pela classe criada anteriormente</span>

$venda = <span class="hljs-keyword">new</span> Cents(<span class="hljs-number">0</span>);
$venda = $venda-&gt;add(Cents::fromFloat(<span class="hljs-number">1.20</span>));
$venda = $venda-&gt;add(Cents::fromFloat(<span class="hljs-number">3.99</span>));
$venda = $venda-&gt;add(Cents::fromFloat(<span class="hljs-number">5.32</span>));
<span class="hljs-keyword">echo</span> $venda-&gt;toString(); <span class="hljs-comment">// R$ 10,51</span>

<span class="hljs-comment">// também é possível acessar a variável somente leitura</span>
var_dump($venda-&gt;value); <span class="hljs-comment">// int(1051)</span>
</code></pre>
<h2 id="heading-destrutores">Destrutores</h2>
<p>Diferentemente do construtor, nós não temos a liberdade de injetarmos argumentos nos destrutores. Isso porque não somos nós que o acionamos, mas o interpretador do PHP. Para escrever um destrutor, basta adicionar um método <code>__destruct</code> na classe. Por exemplo:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Example</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__destruct</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-string">"Adeus mundo!"</span>;
    }
}
</code></pre>
<p>Os destrutores são acionados somente em duas situações:</p>
<ol>
<li>quando um objeto perde todas as referências ligadas a ele (isso seria o limbo absoluto para uma instância - felizmente o PHP consegue eliminar isso sozinho);</li>
<li>quando nós solicitamos propositalmente que o PHP o elimine.</li>
</ol>
<p>Em ambos os casos, se trata do fim do ciclo de vida do objeto, então podemos sempre resumir dessa forma.</p>
<blockquote>
<p>Pra que eu usaria isso, Kiko?</p>
</blockquote>
<p>Olha, tirando <strong>Graceful Shutdown</strong>, eu nunca vi nenhuma outra aplicação que não fosse algum tipo de gambiarra. Isso que mencionei é basicamente uma garantia de que os recursos do seu sistema serão encerrados da melhor forma possível quando o servidor estiver prestes a ser desligado.</p>
<p>Um exemplo disso é quando o servidor recebe um comando de <strong>shutdown</strong> no meio de um processo onde coisas estão sendo armazenadas no banco de dados... Nesse cenário, faz sentido ter uma tratativa no objeto onde essas coisas estão acontecendo para evitar que os dados se percam, seja salvando todo o estado atual em algum lugar temporário para continuar quando o servidor iniciar novamente ou só direcionando para que outra máquina continue o trabalho.</p>
<p>O <strong>Graceful Shutdown</strong> não é a parte de controlar a máquina de estado do seu produto, somente a parte de garantir que, ao desligar, nada será brutalmente interrompido. Sacou?</p>
<p>Aí sim, faz sentido ter um destrutor.</p>
<p>Você também pode usar isso para centralizar o disparo de logs, mas isso pode dar muito errado. Vou dar um exemplo básico:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Logger</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $logs = <span class="hljs-string">""</span>
    </span>) </span>{ }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">log</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $message</span>): <span class="hljs-title">void</span> </span>{
        $timestamp = date(<span class="hljs-string">'Y-m-d H:i:s'</span>);
        <span class="hljs-keyword">$this</span>-&gt;logs .= PHP_EOL . <span class="hljs-string">"[<span class="hljs-subst">$timestamp</span>] <span class="hljs-subst">$message</span>"</span>;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__destruct</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">echo</span> <span class="hljs-keyword">$this</span>-&gt;logs;
        <span class="hljs-comment">// imagine que, no lugar de echo, estaríamos registrando os logs onde quer seja</span>
        <span class="hljs-comment">// desse modo, os logs só seriam enviados quando o objeto responsável por acumular os logs fosse destruído</span>
        <span class="hljs-comment">// mas isso pode dar muito errado!</span>
        <span class="hljs-comment">// se você for armazenar num banco, por exemplo, o tempo de conexão pode não ser tão rápido quanto o comando de desligamento do servidor e aí você perderia esses logs todinhos :)</span>
    }
}
</code></pre>
<p>O uso da classe acima seria:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">include_once</span>( <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/Logger.php"</span>); <span class="hljs-comment">// ou só trocar pela classe declarada acima</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">exemplo</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
    $logger = <span class="hljs-keyword">new</span> Logger();
    $logger-&gt;log(<span class="hljs-string">"testando"</span>); <span class="hljs-comment">// nada acontece</span>
    $logger-&gt;log(<span class="hljs-string">"ue"</span>); <span class="hljs-comment">// nada acontece</span>
} <span class="hljs-comment">// quando a função morre, é que os logs vão parar no echo!</span>

exemplo();
</code></pre>
<h3 id="heading-observacoes-importantes">Observações importantes</h3>
<ol>
<li>Os destrutores são acionados mesmo se você tentar matar a execução do script com um <code>exit()</code>;</li>
<li>Entretanto, se você acionar o <code>exit()</code> dentro de um destrutor, outros destrutores de outros objetos não serão executados;</li>
<li>Lançar exceções (<code>Exception</code>) dentro de um destrutor resultará em um erro fatal no PHP - não faz sentido acontecer isso num ciclo de destruição, não é mesmo? Se houver a mínima possibilidade de algo disparar uma exceção, encapsule com um try-catch e faça um tratamento, beleza?</li>
</ol>
<p>E por hoje é só! Curtiu?? <strong>Comenta e compartilha</strong>!! Comecei a escrever esse artigo para testar meu novo teclado mecânico, o qual estou amando MUITO. Não sei porque não tinha aderido a isso ainda, é gostoso demais de digitar, hahaha. Dá uma saudade enorme de datilografar (sim, eu peguei o final do final dessa fase com a máquina de datilografar da minha mãe). De qualquer forma, estou tentando voltar, pessoal!</p>
<p>Vocês já conheciam o destrutor? Já fizeram alguma solução com ele que não foi uma gambiarra? Comenta aí! Confesso que me falta experiência com ele, por isso nem pude mostrar algo muito relevante sobre isso. Deixa sua marca, hein?</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP para Iniciantes - Classes e Objetos - Namespace]]></title><description><![CDATA[Sei que já dei algum spoiler sobre esse assunto nos artigos anteriores, mas vamos falar sobre ele mesmo assim, até pra reforçar se o que você absorveu é, de fato, o real propósito desse recurso.
Antes de mais nada, qual seria a tradução da  palavra "...]]></description><link>https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-namespace</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-namespace</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Sat, 07 May 2022 17:28:21 GMT</pubDate><content:encoded><![CDATA[<p>Sei que já dei algum spoiler sobre esse assunto nos artigos anteriores, mas vamos falar sobre ele mesmo assim, até pra reforçar se o que você absorveu é, de fato, o real propósito desse recurso.</p>
<p>Antes de mais nada, qual seria a tradução da  palavra "Namespace"?</p>
<p>"Espaço de nomes"? Bom, não tem uma tradução no dicionário e levar a composição da palavra ao pé da letra também não parece uma boa solução. Logo, o que você quer saber aqui não é sobre a escrita disso em português (que seria <strong>namespace</strong> mesmo) e sim o que ele significa, certo?</p>
<p>No contexto de <em>Classes e Objetos</em>, <strong>namespace</strong> tem o mesmo significado de <strong>grupo</strong>, na mesmíssima intenção da palavra <strong>workspace</strong>. Deram esse nome porque, no geral, a única coisa que muda quando se relaciona a um <em>namespace</em> é o seu <strong>nome absoluto</strong>.</p>
<blockquote>
<p>Como assim, Kiko?</p>
</blockquote>
<p>No artigo anterior, sobre autoloading, eu citei uma proposta sobre colocar a classe <code>Evento</code> dentro do namespace <code>Entidades</code>. Isso faz com que o <em>nome</em> que devemos utilizar para chamar essa classe mude para <code>Entidades/Evento</code>.</p>
<blockquote>
<p>E como faz isso, Kiko?</p>
</blockquote>
<p>Temos duas formas. Se você trabalha da forma recomendada pela maioria dos desenvolvedores PHP, você provavelmente fragmenta todo o seu projeto em vários arquivos <code>.php</code>, onde cada classe tem seu próprio arquivo.</p>
<p>A ideia de <strong>Namespace</strong> é possibilitar abstrairmos ainda mais as coisas, organizando cada arquivo em uma estrutura de pastas que deixe tudo mais organizado. Não que você não consiga fazer isso sem namespaces, mas certamente ele facilita na hora de criar um esquema de autoloading, como apresentei no artigo passado.</p>
<p>Então esse recurso tem como principal finalidade unir o poder de autoloading com organização, tirando a dificuldade de ficar usando <code>include</code> e <code>require</code> ou varrendo pastas inteiras para mapear classes e fornecendo a facilidade de mapear somente um namespace.</p>
<blockquote>
<p>Ainda não entendi, Kiko...</p>
</blockquote>
<p>Supomos que, na sua aplicação, todas as suas classes de domínio começam no namespace <code>\Domain</code>, enquanto as de infraestrutura começam no namespace <code>\Infraestructure</code>. O primeiro fica na pasta <code>domain/</code> e o segundo na pasta <code>infra/</code> (já é bem diferente do que está escrito no namespace).</p>
<h3 id="heading-como-voce-faria-para-incluir-todos-os-dominios-precedidos-dele-automaticamente-via-autoloading">Como você faria para incluir todos os domínios precedidos dele automaticamente via autoloading?</h3>
<p>Reflita um pouquinho, tente exercitar se quiser ou pula direto pra resposta mais abaixo.</p>
<center>
<h1>. . .</h1>
<h1>.</h1>
<h1>.</h1>
<h1>.</h1>
<h1>.</h1>
<h1>. . .</h1>
</center>

<p>Conseguiu? Se sim, você já manja de namespace. Se não, vamos estudar um pouco mais. Se nem tentou, tudo bem também! Mas uma dica que te dou sobre programação é que só aprendemos de verdade quando colocamos em prática, beleza? Enfim, vamos lá.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span> <span class="hljs-comment">// autoload.php</span>

<span class="hljs-comment">// primeiramente, nós precisamos configurar nosso autoload</span>
<span class="hljs-comment">// de alguma forma, ele precisa saber que nomes de classes precedidos por "\Domain" serão convertidos para "/domain" e por "\Infraestructure" para "/infra"</span>
<span class="hljs-comment">// lembrem que a barra "/" do sistema de arquivos do sistema operacional pode ser diferente (alguns usam "/", outros "\"). nesse caso, sempre use a constante pré-definida DIRECTORY_SEPARATOR para evitar bugs desnecessários na sua vida</span>
$autoloadNamespaces = [
    <span class="hljs-string">"\\Domain"</span> =&gt; DIRECTORY_SEPARATOR . <span class="hljs-string">"domain"</span>,
    <span class="hljs-string">"\\Infraestructure"</span> =&gt; DIRECTORY_SEPARATOR . <span class="hljs-string">"infra"</span>,
];

<span class="hljs-comment">// agora que temos um dicionário indicando que todo namespace "\\Domain" vira "/domain" e "\\Infraestructure" vira "/infra", podemos registrar uma função de autoload</span>

spl_autoload_register(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$className</span>) <span class="hljs-title">use</span> (<span class="hljs-params">$autoloadNamespaces</span>) </span>{

    <span class="hljs-comment">// para usar a função str_replace, nós precisamos separar tudo o que estamos buscando ($replaceFrom) de tudo o que queremos aplicar ($replaceTo)</span>
    <span class="hljs-comment">// quando essas duas entradas são arrays de comprimento igual, o PHP faz a substituição 1 para 1, de índice para índice</span>
    <span class="hljs-comment">// essa é uma dica legal hein? ;)</span>
    $replaceFrom = array_keys($autoloadNamespaces); <span class="hljs-comment">// array_keys pega todas as chaves do dicionário, ficando array("\\Domain", "\\Infraestructure")</span>
    $replaceTo = array_values($autoloadNamespaces); <span class="hljs-comment">// array_values pega todos os valores do dicionário, ficando array("/domain", "/infra")</span>

    <span class="hljs-comment">// Além dos namespaces, para usar o include_once corretamente, precisamos trocar todas as barras invertidas do namespace para a barra do sistema operacional (DIRECTORY_SEPARATOR)</span>
    $replaceFrom[] = <span class="hljs-string">"\\"</span>;
    $replaceTo[] = DIRECTORY_SEPARATOR;

    <span class="hljs-comment">// Então, acionamos o str_replace</span>
    $className = str_replace($replaceFrom, $replaceTo, $className);

    <span class="hljs-comment">// Daí incluímos o endereço, considerando que está no mesmo caminho desse arquivo</span>
    <span class="hljs-keyword">include_once</span> <span class="hljs-keyword">__DIR__</span> . DIRECTORY_SEPARATOR . <span class="hljs-string">"<span class="hljs-subst">{$className}</span>.php"</span>;
});
</code></pre>
<p>Se quiser testar na prática aí na sua máquina, cria uma <code>index.php</code> assim:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . DIRECTORY_SEPARATOR . <span class="hljs-string">"autoload.php"</span>;
</code></pre>
<p>Depois cria algumas classes. Você pode explorar tanto só as pastas raízes (<code>/domain</code> e <code>/infra</code>) quanto subpastas para explorar mais namespaces. Exemplo: <code>/domain/Entities</code> e <code>/infra/Database</code>.</p>
<p>Daí chama essas classes na index e veja o autoload mágico acontecer!</p>
<center>
<h1>. . .</h1>
</center>

<p>E por hoje é só! Curtiu? Comenta e compartilha! Enquanto escrevia esse artigo, aproveitei para revisar o anterior. Acabei descobrindo que digitei duas funções erroneamente, a <code>spl_autoload_register</code> estava <code>spl_register_autoload</code> e <code>str_replace</code> estava <code>replace</code>. Peço desculpas caso alguém tenha se frustrado tentando executar os ensinamentos e tenha enfrentado alguma dificuldade com esses erros. Já corrigi lá.</p>
<p>Aiaiai se eu pudesse ter um code review nesse blog... Hahaha</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP para Iniciantes - Classes e Objetos - Autoloading]]></title><description><![CDATA[Se eu pudesse resumir esse artigo em poucas palavras, diria: uma das melhores coisas já desenvolvidas no PHP. Isso para quem segue as boas práticas de programação orientada a objeto.

Como assim, Kiko?

Se você programa seguindo a POO, você certament...]]></description><link>https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-autoloading</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-autoloading</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Mon, 18 Apr 2022 16:35:53 GMT</pubDate><content:encoded><![CDATA[<p>Se eu pudesse resumir esse artigo em poucas palavras, diria: uma das melhores coisas já desenvolvidas no PHP. Isso para quem segue as boas práticas de programação orientada a objeto.</p>
<blockquote>
<p>Como assim, Kiko?</p>
</blockquote>
<p>Se você programa seguindo a POO, você certamente vai transcrever várias abstrações de domínio da sua aplicação em classes. Por exemplo:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Evento</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> $idEvento,
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> $titulo,
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> $detalhes,
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> $dataInicio,
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> $dataFim,
    </span>) </span>{ }
}
</code></pre>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Ingresso</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> $idIngresso,
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> $idEvento,
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> $idUsuario,
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> $valorCentavos,
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> $foiPago,
    </span>) </span>{ }
}
</code></pre>
<p>Considerando essas duas classes hipotéticas, não faz sentido escrever as duas no mesmo arquivo, certo? E até aqui, nós chamamos as duas em um terceiro arquivo usando as operações de inclusão via <code>include()</code>, <code>include_once()</code>, <code>require()</code> ou <code>require_once()</code>, confere?</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">include_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/Evento.php"</span>;
<span class="hljs-keyword">include_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/Ingresso.php"</span>;

<span class="hljs-comment">// faz o que quiser</span>
</code></pre>
<p>Não tem nenhum problema em construir um sistema inteiro dessa forma. Você só vai precisar criar um arquivo exclusivo para inicialização, comumente chamado de bootstrap, onde você centralizaria toda essa chamada de includes e requires.</p>
<p>Isso só tem um grande problema: <strong>performance</strong>.</p>
<p>Você estará incluindo em todas as requisições do seu servidor, por exemplo, todas as classes que você já desenvolveu, incluindo aquelas que não irá utilizar. Isso faz sentido pra você?</p>
<blockquote>
<p>Ah, Kiko, então ao invés de centralizar os includes e requires no bootstrap, eu tenho de fazer onde for precisar?</p>
</blockquote>
<p>Também poderia fazer isso, mas é bem mais difícil de controlar as dependências de cada fluxo. Começar estruturando o projeto dessa forma é o jeito ideal de destruir esperanças de refatoração. Hahahah</p>
<blockquote>
<p>Ah, Kiko, e se eu fizesse uma classe para tratar importações dinâmicas?</p>
</blockquote>
<p>Até poderia dar certo. Eu cheguei a fazer isso no framework da primeira agência onde trabalhei. A ideia inicial era de modularizar a aplicação (que nem classes tinha antes) de forma a reduzir as importações. Assim, você usava a classe para importar módulos inteiros, não somente classes.</p>
<p>Funcionou bem, mas o problema resolvido não era exatamente o mesmo do proposto por aqui. Naquela época eu não conhecia o <strong>autoloading</strong> do PHP, caso contrário, não teria perdido meu tempo fazendo isso, hahaha.</p>
<blockquote>
<p>Tá bom, Kiko, aceitei o fato de que tem alguma coisa melhor. Mostra isso logo!</p>
</blockquote>
<p>OK, ok! O que você precisa é de apenas uma função!!</p>
<h2 id="heading-splautoloadregisterhttpswwwphpnetmanualptbrfunctionspl-autoload-registerphp"><a target="_blank" href="https://www.php.net/manual/pt_BR/function.spl-autoload-register.php"><code>spl_autoload_register()</code></a></h2>
<p>Com essa função, é possível ensinar ao PHP "<em>o que fazer quando uma <strong>classe ou interface</strong> não-definida for acionada?</em>". E é basicamente isso. Então você pode centralizar as suas classes em uma pasta e simplesmente ensinar o PHP a importar as classes a partir daquele diretório.</p>
<p>Por exemplo, digamos que você tenha um sistema de arquivos assim:</p>
<ul>
<li><code>/index.php</code>: seu arquivo que é sempre executado em todas as rotas (seja via <code>.htaccess</code>, configuração no NGINX, no Apache, sei lá, mas você manda tudo passar por lá);</li>
<li><code>/bootstrap.php</code>: seu arquivo de inicialização, para centralizar coisas obrigatórias e onde iremos colocar o <code>spl_autoload_register()</code>;</li>
<li><code>/classes/Evento.php</code>: aquela classe de evento que mencionei lá em cima;</li>
<li><code>/classes/Ingresso.php</code>: aquela outra classe (...);</li>
<li>etc (outros arquivos irrelevantes no momento).</li>
</ul>
<p>Note que já temos duas classes dentro da pasta <code>/classes</code> e que o arquivo de inicialização (que chama o <code>spl_autoload_register</code>) está logo acima dela. Portanto, a chamada pode ficar assim:</p>
<pre><code class="lang-php">spl_autoload_register(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"><span class="hljs-keyword">string</span> $className</span>) </span>{
    $slash = DIRECTORY_SEPARATOR; <span class="hljs-comment">// isso aqui é a barra "/" de forma amigável para todos os sistemas operacionais</span>
    $basePath = <span class="hljs-string">"<span class="hljs-subst">{$slash}</span>classes<span class="hljs-subst">{$slash}</span>"</span>;
    <span class="hljs-keyword">include_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"<span class="hljs-subst">{$basePath}</span><span class="hljs-subst">{$className}</span>.php"</span>;
});
</code></pre>
<p>Assim, quando o você chamar <code>new Evento()</code> em alguma parte do fluxo, o interpretador vai:</p>
<ol>
<li>verificar se <code>Evento</code> é uma classe ou interface definida;</li>
<li>não sendo, irá verificar se nós definimos alguma instrução para tentar incluir uma classe indefinida;</li>
<li>como nós definimos, irá acionar a função que passamos como instrução, introduzindo nos argumentos o nome do que estamos tentando acionar: <code>"Evento"</code>;</li>
<li>dentro da função, irá chamar <code>include_once __DIR__ "/classes/Evento.php"</code>, que irá importar aquele arquivo que define a classe <code>Evento</code>;</li>
<li>por fim, irá tentar executar o <code>new Evento()</code>, com sucesso.</li>
</ol>
<p>Nas próximas vezes que alguma coisa chamar a classe no mesmo fluxo, não precisará importar novamente pois a classe já está definida (saltando do passo 1 ao 5).</p>
<center>
<img src="https://media.giphy.com/media/sEms56zTGDx96/giphy.gif" alt="Uaaaauuuuuu" />
</center>

<p>E isso não é tudo!</p>
<p>Se você usar namespaces, poderá deixar tudo ainda mais organizado, colocando o caminho do namespace em forma de pastas. Tudo o que precisaria mudar é colocar uma tratativa de barras, pois o namespace vem todo bugado para dentro da instrução.</p>
<p>No caso, ficaria algo assim:</p>
<pre><code class="lang-php">spl_autoload_register(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"><span class="hljs-keyword">string</span> $className</span>) </span>{
    $slash = DIRECTORY_SEPARATOR; <span class="hljs-comment">// isso aqui é a barra "/" de forma amigável para todos os sistemas operacionais</span>
    $basePath = <span class="hljs-string">"<span class="hljs-subst">{$slash}</span>classes<span class="hljs-subst">{$slash}</span>"</span>;
    $className = str_replace(<span class="hljs-string">"\\"</span>, $slash, $className);
    <span class="hljs-keyword">include_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"<span class="hljs-subst">{$basePath}</span><span class="hljs-subst">{$className}</span>.php"</span>;
});
</code></pre>
<p>Então, se você armazena a classe <code>Evento</code> na pasta <code>classes/Entidades</code> e atribuindo o devido namespace (<code>namespace Entidades;</code>) antes da declaração da classe, ao chamar <code>new Entidades\Evento()</code>, o PHP iria rodar a instrução <code>include_once __DIR__ . "/classes/Entidades/Evento.php"</code> no passo 4.</p>
<blockquote>
<p>Ok, Kiko, e qual é o real benefício disso?</p>
</blockquote>
<p>Primeiramente, você ensina ao PHP sistematicamente onde encontrar classes indefinidas no seu sistema de arquivos. Isso automaticamente retirará a obrigação de sair importando todas as classes, mesmo onde não precisa. Deixa que o PHP encontre-as!</p>
<p>E, consequentemente, seus fluxos só importarão as classes que precisam. Maravilhoso, não é mesmo? E você pode ir muito além, criando uma função mais complexa para estruturar tudo o que for necessário.</p>
<p>É desse jeito que funciona o <a target="_blank" href="https://getcomposer.org/"><strong>Composer</strong></a>. Exceto que você, como desenvolvedor, só precisa configurar o <code>composer.json</code> para mapear namespaces fictícios.</p>
<p>Por exemplo, no <strong>Laravel</strong>, todas as classes que são colocadas dentro da pasta <code>app/</code> são acionáveis pelo namespace <code>App</code>. Se você olhar no <code>composer.json</code> do Laravel, vai encontrar isso aqui:</p>
<pre><code class="lang-json">    <span class="hljs-comment">// ...</span>
    <span class="hljs-string">"autoload"</span>: {
        <span class="hljs-attr">"psr-4"</span>: {
            <span class="hljs-attr">"App\\"</span>: <span class="hljs-string">"app/"</span>,
            <span class="hljs-attr">"Database\\Factories\\"</span>: <span class="hljs-string">"database/factories/"</span>,
            <span class="hljs-attr">"Database\\Seeders\\"</span>: <span class="hljs-string">"database/seeders/"</span>
        }
    },
    <span class="hljs-comment">// ...</span>
</code></pre>
<p>Esse trecho das configurações diz, basicamente, o seguinte:</p>
<ol>
<li>Se a classe começar com o namespace <code>App\\</code>, retire esse namespace e procure o resto da instrução dentro da pasta <code>app/</code> (a partir da raiz do projeto);</li>
<li>Se a classe começar com o namespace <code>Database\\Factories\\</code> (...) dentro da pasta <code>database/factories/</code>;</li>
<li>Se a classe (...) <code>Database\\Seeders\\</code> (...) <code>database/seeders/</code>.</li>
</ol>
<p>E assim, ao compilar as dependências usando o composer, um arquivo grande de autoload será gerado dentro da pasta <code>vendor/</code>. Se você abrir, encontrará uma implementação bem genérica do <code>spl_autoload_register</code>, que é o que faz a mágica acontecer para gente.</p>
<center>
<img src="https://media.giphy.com/media/xT0xeJpnrWC4XWblEk/giphy.gif" alt="Mindblow" />
</center>

<p>Você sabia disso?? Hehehe, na época que descobri eu fiquei super fascinado por esse rolê, espero que tenha transmitido o mesmo sentimento pra você! E se curtiu, lembra de curtir e compartilhar, hein?! No próximo artigo voltaremos falando sobre <a target="_blank" href="https://www.php.net/manual/pt_BR/language.oop5.decon.php"><strong>Construtores e Destrutores</strong></a>, onde falaremos sobre o ciclo de vida dos objetos e é bem relacionado a outros assuntos como <strong>Graceful Shutdown</strong>. Não perca, hein?</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[Migrei de PHP para Golang, e agora?]]></title><description><![CDATA[Olá, quanto tempo, não é mesmo?! Já faz tanto que não escrevo por aqui que até me senti nostálgico quando vi o editor de texto da hashnode. E ao invés de chegar retomando a série de artigos de PHP para Iniciantes, resolvi falar um pouco do que anda r...]]></description><link>https://blog.kaiquegarcia.dev/migrei-de-php-para-golang-e-agora</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/migrei-de-php-para-golang-e-agora</guid><category><![CDATA[Go Language]]></category><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Thu, 14 Apr 2022 14:25:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649938631969/r8u7odX4r.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Olá, quanto tempo, não é mesmo?! Já faz tanto que não escrevo por aqui que até me senti nostálgico quando vi o editor de texto da hashnode. E ao invés de chegar retomando a série de artigos de PHP para Iniciantes, resolvi falar um pouco do que anda rolando na minha vida primeiro.</p>
<h1 id="heading-problemas-da-vida">Problemas da vida</h1>
<p>Primeiramente: não, eu não desisti do blog e tampouco vou deixar a galera do PHP com conteúdo incompleto. Eu apenas não estou conseguindo conciliar meus horários na vida, saca? A ponto de que está faltando horas no dia-a-dia pra fazer outras coisas também, que tem mais prioridades que o blog.</p>
<blockquote>
<p>Quê?! Como ousa priorizar outra coisa, Kiko?!</p>
</blockquote>
<p>Infelizmente, a idade chega para todos... E minhas filhas estão prestes a fazer 3 aninhos! HEHEHE Pensou que eu ia dar uma desculpa de idoso, né? Calma lá, eu ainda vou fazer 30, mas é lá pro Halloween. Porém minha saúde não anda tão bem assim. Eu precisei fazer uma super bateria de exames de cardio e... Deu tudo ok, não tenho problema algum fora obesidade e uma dor esquisita no calcanhar. Ainda preciso ir no ortopedista ver isso e só depois voltar a frequentar o oftalmologista para terminar as sessões de cirurgia a laser e concluir exames de glaucoma.</p>
<p><strong>RESUMINDO</strong>: tem muita coisa de saúde pra tratar. E não é só a minha saúde! Minhas filhas estão tendo crises asmáticas desde semana passada e eu sigo torrando grana com remédios, médicos, etc. Tratamento exaustivo é outro rolê, em duas crianças então... Nem se fala.</p>
<p>Se você julgava a minha falta de tempo, espero que tenha um bom julgamento agora, rs.</p>
<h1 id="heading-voltando-ao-blog">Voltando ao blog</h1>
<p>Mesmo faltando tempo pra tudo, eu não deixo de acompanhar a galera no BlueSky. Às vezes eu solto meus recados por lá e consigo interagir com quem lê meus artigos. Uma das coisas que mais me pediram pra comentar por lá foi sobre como está sendo minha experiência na <a target="_blank" href="https://www.kavak.com/br">KAVAK</a>, onde estou desenvolvendo em Golang ao invés de PHP.</p>
<p>As perguntas mais comuns são:</p>
<ol>
<li><p>É muito diferente?</p>
</li>
<li><p>Conseguiu se adaptar rápido?</p>
</li>
<li><p>Está curtindo?</p>
</li>
<li><p>Vai fazer um "GO para iniciantes"?</p>
</li>
</ol>
<p>Antes de sair respondendo cada uma, eu quero repassar o que aconteceu comigo desde o processo de contratação até onde cheguei, e aí voltamos a responder. Bora lá?!</p>
<h1 id="heading-go-do-nada-ao-pro">Go: do nada ao pro</h1>
<center>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649938631969/r8u7odX4r.png" alt="GOPRO" />
(copyright: Pocket-lint)
<em>(explicando a piada: go PRO)</em>
</center>

<p>Antes de entrar na KAVAK, eu estava trabalhando na Linx como desenvolvedor especialista. Mais especificamente falando, eu era especialista em PHP lá. Minhas ações mais relevantes foram destrinchar bugs antigaços e mapear tudo o que precisava ser corrigido para colocar o serviço onde atuei nas rédeas (leia-se atualizar a infraestrutura para acompanhar as atualizações de segurança). Não posso dar muitos detalhes, mas o bug mais antigo que ajudei a solucionar por lá tinha 3 anos e eu cheguei a mapear mais de 50 débitos técnicos.</p>
<p>Sinceramente, eu gosto muito de chegar investigando tudo o que já fizeram nos serviços onde atuo. É importante que você, futuro desenvolvedor de novas empresas, aprender a fazer isso por conta própria. E fazer por conta não significa fazer sozinho! Faz parte saber perguntar a outras pessoas. Descobrir quem tem mais domínio do que está precisando aprender é essencial para o trabalho funcionar. No pior caso, as pessoas que tinham domínio saíram e você vai precisar de mais tempo para investigar e entender o que tá rolando... Concorda? Enfim...</p>
<blockquote>
<p>Mas Kiko, se estava tão legal, por que você saiu da Linx?!</p>
</blockquote>
<p>Voltando mais um pouco, lembra que eu trabalhava na Picpay? Sem dar muitos detalhes e sendo bem curto: eu fiquei por lá por um ano e saí por questões financeiras. Eu conheci <strong>muita gente</strong> lá, sério. E essa galera que conheci é maravilhosa... Não tem ninguém que não seja incrível lá.</p>
<p>Porém, sou pai de gêmeas. Meu salário precisa, no mínimo, acompanhar o custo exponencial que cresce a cada ano. Falando disso agora, eu só vejo como eu fui certeiro nessa decisão... Se eu continuasse com o salário que recebia lá ou com a proposta que me deram, hoje eu teria gastado todas as minhas reservas...</p>
<p>De qualquer modo, eu entrei na Linx por dinheiro. Lá conheci muita gente foda, de verdade... Mas poucos meses depois que entrei lá, recebi o convite de alguns ídolos de carreira que conheci na Picpay para vir pra Kavak. Isso, por si só, já era um bom motivo para vir... O receio era o salário: se fosse menor, não daria pra ir.</p>
<p>Mas eles cobriram.</p>
<center>
<img src="https://media.giphy.com/media/Ld0P4AdeSDjoY/giphy.gif" alt="Ohh sim!! HEHEHEHE" />
</center>

<p>Então eu fui, mesmo não sendo PHP. O foco era trabalhar com quem eu sei que só gera desafio iradíssimo. Quando eu coloquei na balança as questões de cultura da empresa, outros benefícios foram aparecendo... Eu só não vou colocar essa lista aqui, pois é meio desrespeitoso comparar empresas onde trabalhei assim, em um artigo, sabe?</p>
<p>(não é nada errado falar disso boca a boca ou numa conversa particular, é só meio sem noção deixar isso registrado - agradeço a compreensão)</p>
<blockquote>
<p>Ué, Kiko, mas você já tinha trabalhado com Golang antes, certo?</p>
</blockquote>
<p><strong>Não!</strong></p>
<p>E isso que é foda. O pessoal que me chamou pra trabalhar lá sabia da minha expertise como desenvolvedor, independente da linguagem, e eles confiaram na minha capacidade de trabalhar com novas linguagens baseado no meu histórico: já fui back-end, front-end, fullstack... Por que não tentar?</p>
<p>Já do meu ponto de vista, eu estava muito nervoso porque já fui contratado como sênior para atuar com uma linguagem que sequer tinha visto. Minha primeira reação nesse cenário foi: eu preciso destrinchar Golang o quanto antes!</p>
<p>Então baixei alguns aplicativos com conteúdo sobre isso no celular e comecei a ler toda noite. Só pra dar um contexto: no dia 04/01 eu anunciei na Linx que ficaria somente até o dia 04/02 (aviso prévio). Nesse período, eu trabalhei normalmente sem deixar nada a desejar. Sempre dou o meu máximo. Mas fora do horário de trabalho, eu foquei em aprender Go só consumindo conteúdos, sem desenvolver nada ainda. Por isso que fiquei um tempão sem escrever nada naquela época. Cheguei a avisar no meu (falecido) Twitter, hehe.</p>
<p>No final de semana após minha saída da Linx, eu fiz um projetinho em Go pra testar os conhecimentos. Foi aí que notei que esqueci de estudar um detalhe muito importante: padrão de desenvolvimento em Go.</p>
<p>Logo de cara percebi que arquitetura hexagonal não é nada parecido entre Go e PHP. É possível?? É! Mas não é do mesmo jeito. Golang traz um recurso de importação nativa de módulos armazenados em repositórios externos. O próprio script nativo de uso de banco de dados já dá uma certa noção de Adapter, pois você só precisa importar o driver que vai usar na aplicação e usar o código dele na instância do banco. O que muda além disso? Possivelmente a sintaxe usada nas queries. Aí é que entra os kits que você pode desenvolver para suas aplicações.</p>
<p>A ideia de Go é que você consiga quebrar sua aplicação em pequenas aplicações independentes. E quando eu digo pequenas, é pequenas mesmo. Cada uma delas seria um pacote e é importantíssimo que a conexão entre os pacotes seja de mão única. Você não pode fazer um pacote A usar o B e vice-versa ao mesmo tempo. Se isso acontecer, então está errado (inclusive nem vai compilar).</p>
<p>Há quem prefira colocar todos os códigos na raiz, mas aí vai totalmente contra a arquitetura hexagonal, certo? A gente tem de trabalhar pensando na manutenção constante e não somente na entrega.</p>
<p>Voltando ao final de semana antes de começar na Kavak: fiz um projetinho todo fora dos padrões e pesquisei para entender como a comunidade estava desenvolvendo. Deixo aqui um forte abraço ao time da Uber, que fez um trabalho excepcional de colocar o Package Oriented Design em prática... E deixou muito evidente para mim que a comunidade ainda não acolheu um padrão definitivo.</p>
<p>O que eu senti com isso? Euforia, empolgação, tesão (não-sexual). Um cenário onde o padrão é "terra de ninguém" é o ambiente ideal para chegar participando das tomadas de decisão. E quando eu falo em chegar, não é somente dentro da empresa: isso é na comunidade como um todo. Mas antes de me tornar um porta-voz de qualquer coisa lá, eu preciso me tornar relevante para ser um dentro da empresa.</p>
<blockquote>
<p>E como fazer isso, Kiko?</p>
</blockquote>
<p>Fazendo bons projetos, bem feitos e desafiando as estruturas atuais com modelos mais ricos e eficientes. Se eu te der um projeto mais organizado que o seu e com desempenho melhor, você iria assistir uma palestra minha para entender qual bruxaria eu fiz? Pois é.</p>
<p>Isso era meu principal objetivo antes de entrar na empresa. Agora que estou dentro, vejo que só temos desenvolvedores fodas e que todos que conheci tem o mesmo sentimento. Já aceitei que não vou ter tanto espaço quanto eu estava almejando, mas eu já tenho um pouco dessa notoriedade. Já puxei discussões relevantes, tentei juntar a galera que manja de Golang para fazer o time geral de desenvolvedores Go, que até então não existia, etc.</p>
<p>Um dev muito foda que tem apresentado várias coisas é o Ricardo Manuel (Massa). Não sei se ele vai ler isso aqui algum dia, mas é, Ricardo, tu é muito brabo. Ele consegue transmitir o que você levaria uma semana para aprender em uma conversa de 30 minutos, sem faltar nada. Isso se você já souber o pré-requisito para acontecer, né? Geralmente já sabemos.</p>
<blockquote>
<p>Peraí, Kiko... Então sua maior dificuldade hoje é mais sobre padrões de desenvolvimento em Go e não a linguagem em si?</p>
</blockquote>
<p>Exatamente. É a dor de trabalhar com uma linguagem tão recente (ainda estamos na versão 1.18, enquanto outras já estão na 11+). Aprender a linguagem em um mês foi muito fácil, pois ela é bem parecida com C. Algumas mudanças de sintaxe a gente só aprende desenvolvendo, porém minha curva foi bem rápida, pra não dizer instantânea. Outro detalhe é que meus gestores deram um projeto de onboarding para minha squad, onde pudemos discutir, refletir e analisar o padrão que usaríamos, além de refatorar várias vezes até chegar numa estrutura aceitável.</p>
<p>Então devo dizer: esse aprendizado não dependeu só de mim. A empresa me deu todo o necessário para me desenvolver sem exigir praticamente nada. Esperavam o projeto de onboarding em dois meses, entregamos em um. Começamos o primeiro projeto que agrega valor ao produto logo em seguida e já estamos 10 vezes mais rápidos, pois já absorvemos a forma ideal de desenvolver projetos em Go.</p>
<p>Ou seja: leitore, a KAVAK é perfeita. Meus gestores são perfeitos. Meu time é maravilhoso. Tudo nessa p* é empolgante e eu ainda vou crescer bastante por aqui.</p>
<blockquote>
<p>Tá, Kiko, mas cadê a comparação entre PHP e Golang?</p>
</blockquote>
<p>É, eu quase esqueci desse detalhe. Então vamos fazer uma lista básica:</p>
<ol>
<li><p>É inviável ter super frameworks em Golang como temos no PHP (Laravel, Code Igniter, etc) pelo simples fato que qualquer "faz-tudo" em um pedacinho do projeto irá pesar MUITO na capacidade de processamento da aplicação. Por isso, faz-se importante definir, o quanto antes, o padrão de desenvolvimento dentro das empresas, no mínimo! Se os times não seguirem o mesmo padrão, vai ser um tiro no pé!</p>
</li>
<li><p>O conceito de construtor em Golang é bem diferente do PHP. Geralmente, cada pacote tem uma função <code>New()</code> (se há somente uma struct a ser instanciada do lado de fora do pacote), o que significa que você constrói PACOTES, não structs (que é o que confundimos com classes). Ao invés de ter <code>entities.NewPhone()</code> e <code>entities.NewEmail()</code> você pode ter um pacote <code>phone</code>, outro <code>email</code> e chamar <code>phone.New()</code> e <code>email.New()</code>. É isso.</p>
</li>
<li><p>Golang não tem herança como vemos no PHP. As visibilidades são privadas ou públicas, sendo que a visibilidade privada é visível para todo o pacote, não somente a struct, por exemplo. E o que define isso é se a primeira letra do que está definindo está minúscula ou maiúscula. Nada de <code>private</code> ou <code>public</code>.</p>
</li>
<li><p>Em Go, o conceito de ponteiros mágicos não existem dentro dos métodos. Eu falo principalmente do <code>$this</code>: não existe e não é recomendado criar o conceito lá.</p>
</li>
<li><p>Consequentemente, os métodos podem ou não ter um ponteiro da struct onde está sendo atrelado. Por exemplo, considere a seguinte struct (mesmo se não souber ler o código):</p>
<pre><code class="lang-go"> <span class="hljs-keyword">package</span> main

 <span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
     <span class="hljs-comment">// Criando a classe diretamente, sem referência</span>
     ex2 := (Exemplo{})
     ex2.MetodoSemPonteiro(<span class="hljs-number">30</span>)
     fmt.Println(ex2) <span class="hljs-comment">// {0}</span>
     ex2.MetodoComPonteiro(<span class="hljs-number">30</span>)
     fmt.Println(ex2) <span class="hljs-comment">// {30}</span>

     <span class="hljs-comment">// Usando construtor, retornando referência</span>
     ex := New(<span class="hljs-number">10</span>)
     ex.MetodoSemPonteiro(<span class="hljs-number">15</span>)
     fmt.Println(ex) <span class="hljs-comment">// &amp;{10}</span>
     ex.MetodoComPonteiro(<span class="hljs-number">20</span>)
     fmt.Println(ex) <span class="hljs-comment">// &amp;{20}</span>
 }

 <span class="hljs-keyword">type</span> Exemplo <span class="hljs-keyword">struct</span> {
     Valor <span class="hljs-keyword">int</span>
 }

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">New</span><span class="hljs-params">(valorInicial <span class="hljs-keyword">int</span>)</span> *<span class="hljs-title">Exemplo</span></span> {
     <span class="hljs-keyword">return</span> &amp;Exemplo{Valor: valorInicial}
 }

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(ex Exemplo)</span> <span class="hljs-title">MetodoSemPonteiro</span><span class="hljs-params">(novoValor <span class="hljs-keyword">int</span>)</span></span> {
     ex.Valor = novoValor
 }

 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(ex *Exemplo)</span> <span class="hljs-title">MetodoComPonteiro</span><span class="hljs-params">(novoValor <span class="hljs-keyword">int</span>)</span></span> {
     ex.Valor = novoValor
 }
</code></pre>
<p> Na declaração do método <code>MetodoSemPonteiro</code>, após o termo <code>func</code> temos a declaração da struct que recebe aquele método, no caso, <code>(ex Exemplo)</code>. No <code>MetodoComPonteiro</code>, essa declaração tem um asterisco. Esse caractere significa referência. Isso significa apenas uma coisa importantíssima que você precisa sacar em Golang: <strong>o primeiro método (</strong><code>MetodoSemPonteiro</code>) não salva o campo <code>novoValor</code> em lugar nenhum, pelo simples fato de que ele não tem a referência do objeto original.</p>
<p> Os métodos sem referência servem apenas para retornar algo, sem persistir mudanças na estrutura. O mais próximo disso em PHP são os métodos estáticos, que não precisam instanciar a classe para existir, exceto que em Go, é preciso instanciar, de certa forma.</p>
<p> Você pode rodar o código acima <a target="_blank" href="https://go.dev/play/p/6hTaHrY_gw7">aqui (Go Playground)</a>.</p>
</li>
<li><p>O código da sua aplicação não precisa ter separação de domínio e infra. Você pode desenvolver um projeto pra infra e outro pra aplicação! Ficando somente o domínio. Irado, né? Essa é uma das minhas favoritas.</p>
</li>
<li><p>Consequentemente, se suas aplicações tiverem configurações de infra parecidas, você pode criar um kit para todas as aplicações, instantaneamente centralizado alguns padrões, como:</p>
<ul>
<li><p>Servidor web (Fiber, Chi, Gin?);</p>
</li>
<li><p>Logs (estrutura padrão dos logs, integrações, etc);</p>
</li>
<li><p>Tracking de eventos (estrutura padrão dos eventos, integrações, etc);</p>
</li>
<li><p>Banco de dados (centralizar o padrão de instância da empresa, assim como uso das configurações corretas);</p>
</li>
<li><p>Mensageria (estrutura padrão das mensagens, integrações, etc);</p>
</li>
<li><p>Notificações (estrutura padrão das notificações, possíveis integrações, etc), sendo que essa você pode quebrar em pacotes específicos (sms, email, slack, discord, whatsapp, telegram, etc, o que você quiser fornecer de possibilidade de notificação);</p>
</li>
<li><p>etc!</p>
</li>
</ul>
</li>
</ol>
<p>    Sua aplicação só precisará importar os pacotes que vai utilizar e chamar. Fim! Sendo um kit da empresa, o padrão de inicialização de cada "componente" pode ficar no respectivo pacote, tendo o desenvolvedor a única obrigação de seguir a documentação dos pacotes para configurar as variáveis de ambiente corretamente.</p>
<p>    Enfim, isso também é possível de fazer em PHP, mas em Golang isso é praticamente obrigatório. As limitações da linguagem te induzem a fazer essa boa separação de responsabilidades, esse é o ponto.</p>
<p>E por enquanto eu vou parar por aqui, pois meu tempo para escrever acabou e não sei quando vou poder retornar. Dito isso, não quero deixar para continuar escrevendo depois (quando eu claramente já vou ter esquecido o que estava escrevendo).</p>
<p>Curtiu? Comenta e compartilha! Você já tinha visto um código em Golang antes desse post? Quer comentar suas experiências também ou o que achou do meu ponto de vista? Só descer aí e escrever, hahaha. Se não tiver uma conta e não quiser se cadastrar, aceito um <a target="_blank" href="https://twitter.com/kg_thebest">tweet me marcando</a>. O importante é se comunicar!</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP para Iniciantes: Classes e Objetos - Constantes]]></title><description><![CDATA[Se você leu meus artigos anteriores, já tens uma certa noção do que é uma constante em uma linguagem de programação, certo? Só por precaução, eu vou deixar esse link do artigo Constantes - O básico.
As constantes em classes são declaradas da mesmíssi...]]></description><link>https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-constantes</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-constantes</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Sat, 26 Feb 2022 22:16:26 GMT</pubDate><content:encoded><![CDATA[<p>Se você leu meus artigos anteriores, já tens uma certa noção do que é uma constante em uma linguagem de programação, certo? Só por precaução, eu vou deixar esse link do artigo <a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-constantes-o-basico">Constantes - O básico</a>.</p>
<p>As constantes em classes são <strong>declaradas</strong> da mesmíssima forma que as constantes do escopo global sem uso da função <code>define()</code>. Note que eu estou falando em <strong>declaração</strong>, não em uso e muito menos em escopo.</p>
<p>Ou seja, se para criar a constante <code>CARNAVAL</code> eu faço <code>const CARNAVAL = "vale-night"</code>, o mesmo se aplicaria dentro de uma classe:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span> </span>{
    <span class="hljs-keyword">const</span> CARNAVAL = <span class="hljs-string">"vale-night"</span>;
}
</code></pre>
<p>E temos aqui a mesma sintaxe e limitações que menciono no artigo <a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-constantes-sintaxe">Constantes - Sintaxe</a>, que são, em resumo:</p>
<ul>
<li>o primeiro caractere do nome da constante precisa ser uma letra ou <em>underline</em> (<code>_</code>);</li>
<li>os próximos caracteres podem ser letras, <em>underline</em> ou números;</li>
<li>o valor atribuído à constante só pode ser de tipos de dados primitivos escalares ou arrays contendo somente tipos (...) escalares.</li>
</ul>
<p>Se alguma linha desse resumo te confundiu, peço que releia o artigo, tudo bem? Lá está um pouco mais detalhado.</p>
<blockquote>
<p>Ok, Kiko, então o que muda?</p>
</blockquote>
<p>A forma de acionar essa constante. Como ela está sendo declarada dentro de uma classe, é óbvio que, para acessar seu valor, você vai precisar usar o nome da classe de alguma forma. É uma sintaxe bem simples: <code>NOME_DA_CLASSE::NOME_DA_CONSTANTE</code>.</p>
<blockquote>
<p>O que são esses quatro pontos (dois pontos duas vezes), Kiko?</p>
</blockquote>
<p>Lembra que, quando você quer acessar uma propriedade de um objeto, você usa o operator de objeto <code>-&gt;</code>? Assim como existe esse operador, temos um para acessar as propriedades de uma classe, que é os quatro pontos <code>::</code>.</p>
<p>Portanto, se formos acessar aquela constante da classe anterior, seria algo como:</p>
<pre><code class="lang-php"><span class="hljs-keyword">echo</span> Exemplo::CARNAVAL; <span class="hljs-comment">//vale-night</span>
</code></pre>
<blockquote>
<p>Hummm, interessante, Kiko! Então toda constante nas classes é pública?</p>
</blockquote>
<h2 id="heading-nao">NÃO</h2>
<p>Antigamente eram, mas hoje o PHP nos dá a possibilidade de controlar a visibilidade das constantes nas classes. No <a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-o-objetos-propriedades">artigo anterior, sobre propriedades</a>, eu mencionei detalhes sobre como funcionam as visibilidades <code>private</code>, <code>protected</code> e <code>public</code>, certo? Nas constantes funcionam da mesma forma! Então deixo o link para revisar caso não lembre, hehe.</p>
<p>Por isso, é seguro dizer que constantes em classe tem escopos totalmente diferentes das constantes globais. Se você pode fazer uma constante ser visível somente dentro da classe, não tem como outra parte do código acessar aquilo, sabe? Diferente de constantes globais que podem ser acessadas de qualquer parte depois que forem declaradas.</p>
<p>Dito isso, vamos falar sobre um ponto muito importante.</p>
<h2 id="heading-boas-praticas">Boas práticas</h2>
<p>Não, eu não vou dizer <strong>como você tem de escrever o seu código</strong>. Eu vou falar o que é considerado boas práticas <strong>pela comunidade de desenvolvimento</strong>. Na real, é errado chamar algo de bom ou mal, porque o sentido aqui é sobre criar um padrão sólido que deixe o código compreensível e de fácil manutenção. Toda vez que alguém mencionar "boas práticas", lembre-se disso, tá bom?</p>
<blockquote>
<p>Tá, Kiko, mas diz aí, o que que a comunidade diz sobre constantes em classes?</p>
</blockquote>
<p>Não somente sobre constantes em classes, mas constantes no geral. É dito que é uma boa prática escrever as constantes com todas as letras maiúsculas, por exemplo. Também é importantíssimo que você controle bem as visibilidades das constantes: não tem porque algo ser visível em escopos onde sua existência não importa, sabe? Porém, se você não tem certeza de onde vai usar, tudo bem deixar no escopo global.</p>
<p>E outro detalhe que, na minha opinião, foi a minha maior lição de vida e que posso confirmar por experiência que impacta diretamente na manutenabilidade de código é: nunca deixe <strong>números mágicos</strong> no seu código.</p>
<p>Quando falamos em números mágicos, não estamos falando somente de números. Qualquer valor <em>misterioso</em> que está aplicado diretamente no código deve ser substituído por uma constante com um nome que descreva o que é aquele valor.</p>
<p>Por exemplo, se eu faço:</p>
<pre><code class="lang-php"><span class="hljs-keyword">if</span> ($status == <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Exception</span>();
}
</code></pre>
<p>Você entende qual é o status validado?</p>
<center> <img src="https://media.giphy.com/media/WRQBXSCnEFJIuxktnw/giphy.gif" alt="Meme: Nazaré fazendo conta" /> </center>

<p>Não, né? Agora se eu faço:</p>
<pre><code class="lang-php"><span class="hljs-keyword">if</span> ($status == STATUS_INDEFINIDO) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Exception</span>();
}
</code></pre>
<p>Fica bem mais claro, concorda?</p>
<center> <img src="https://media.giphy.com/media/d3mlE7uhX8KFgEmY/giphy.gif" alt="Meme: pense nisso" /> </center>

<p>Nesse exemplo, a pessoa que está desenvolvendo <em>provavelmente</em> saberia que o status <code>0</code> é o status indefinido. Porém, parte do desenvolvimento é sobre escrever códigos para que OUTROS DESENVOLVEDORES façam manutenção no futuro. Então você deve pensar: <em>se um novato pegar esse código, ele vai entender rapidamente o que está acontecendo?</em></p>
<p>É isso. Constantes funcionam bem aqui.</p>
<blockquote>
<p>Legal, Kiko... Mas você usou uma constante global ali, não foi?</p>
</blockquote>
<p>Sim! E falando em <code>status</code>, aquela constante poderia ser o valor de um <strong>Enum</strong>.</p>
<blockquote>
<p>O que é isso, Kiko?</p>
</blockquote>
<p>Se jogar no Google "<em>o que é enum?</em>", irá encontrar a definição mais comum que é:</p>
<blockquote>
<p>(...) Enum(eração) é um tipo de dado abstrato, cujos valores são atribuídos a exatamente um elemento de um conjunto finito de identificadores escolhidos pelo programador (...)</p>
</blockquote>
<p>E é isso mesmo. Enums servem para definir os possíveis valores de alguma coisa, atribuindo um nome mais claro para cada um desses valores. Antes do PHP 8.1, não existia nenhuma implementação de enums nativamente, então nós criávamos classes com constantes públicas dentro delas para fazer esse mapa e evitar números mágicos no código. Por exemplo:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StatusEnum</span> </span>{
    <span class="hljs-keyword">const</span> INDEFINIDO = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">const</span> PUBLICADO = <span class="hljs-number">1</span>;
    <span class="hljs-keyword">const</span> RASCUNHO = <span class="hljs-number">2</span>;
}

<span class="hljs-comment">// (...)</span>

<span class="hljs-keyword">if</span> ($status == StatusEnum::INDEFINIDO) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Exception</span>();
}
</code></pre>
<p>Com uma Enum bem definida no código, você não teria a necessidade de decorar os possíveis valores que pode atribuir.</p>
<blockquote>
<p>Ah, Kiko, e como são os Enums no PHP 8.1?</p>
</blockquote>
<p><strong>MARAVILHOSOS</strong></p>
<pre><code class="lang-php">enum StatusEnum: <span class="hljs-keyword">int</span> {
    <span class="hljs-keyword">case</span> INDEFINIDO = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">case</span> PUBLICADO = <span class="hljs-number">1</span>;
    <span class="hljs-keyword">case</span> RASCNHO = <span class="hljs-number">2</span>;
}

<span class="hljs-comment">// (...)</span>

<span class="hljs-keyword">if</span> ($status == StatusEnum::INDEFINIDO) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Exception</span>();
}
</code></pre>
<blockquote>
<p>Ah, Kiko, a usabilidade não é a mesma?</p>
</blockquote>
<p>Absolutamente <strong>não</strong>. No caso dos Enums no PHP 8.1, nós temos as Enums e as <strong>backed values</strong> Enums. Atualmente só funciona com os tipos <code>int</code> e <code>string</code>.
Se você faz apenas uma Enum (sem informar tipagem e valores), o interpretador automaticamente implementa um método <code>cases</code> que retorna um array com todos os cases que você criou.</p>
<p>Já se você usa o <strong>backed values enums</strong>, informando uma tipagem e os valores de cada case, o interpretador adiciona dois métodos:</p>
<ul>
<li><strong>from</strong>, que serve até pra validar se um valor é um dos cases presente na Enum, disparando exception se não for;</li>
<li><strong>tryFrom</strong>, que é o mesmo que o <strong>from</strong> exceto que não dispara erro, apenas retorna nulo se não for um valor válido.</li>
</ul>
<p>São métodos que teríamos de implementar na mão, se fôssemos desenvolver com classes, sabe? E eles vem nativamente.</p>
<blockquote>
<p>Tá, Kiko, mas quando eu devo usar um <strong>backed value enum</strong> e quando não usar?</p>
</blockquote>
<p>Quando você estiver desenvolvendo uma Enum cujos valores não importam fora do código, tanto a nível de resposta de requisição quanto a enviar para o banco de dados, você não precisa usar o <strong>backed value enum</strong>. Já se você está criando algo que será armazenado no banco ou que irá preencher a resposta da aplicação, é interessante atribuir os valores.</p>
<p>Eu já não vou dar mais detalhes sobre Enum por agora porque vai ser conteúdo de outro artigo, tudo bem? Só escrevi o necessário para complementar a importância das constantes no seu código.</p>
<p>Enums são sempre globais, porque estão ali para deixar o seu código mais legível em qualquer parte dele. Mas é válido lembrar que teremos constantes que não precisam ser globais, podem ser um dado específico de uma classe, sabe? Tem de fazer sentido estar ali ou não. Fechado??</p>
<p>Por hoje é só! Curtiu? <strong>Comenta e compartilha!!</strong> Eu demorei bem mais do que o esperado para voltar a escrever, né?! Tanto que só consegui tempo agora no carnaval, hahahaha. Feliz carnaval pra você, se estiver lendo antes/durante. Se já passou, bem, que sua vida seja verdadeiramente feliz!</p>
<p>Não sei o quanto vou demorar para escrever a continuação, por isso solta aí nos comentários "faz ele escrever, Jéssica!" para eu mostrar para minha esposa, assim ela vai me instigar mais a escrever também! HUEHUEHUE</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP: Pra que mockar?]]></title><description><![CDATA[Se você já escreve testes, em algum momento, deve ter recebido orientações para mockar uma classe com o objetivo de fazer um teste mais simples. Se você nunca passou por isso ou se ainda não entendeu o motivo de usar, esse artigo é pra você.
E antes ...]]></description><link>https://blog.kaiquegarcia.dev/php-pra-que-mockar</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-pra-que-mockar</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[Learning Journey]]></category><category><![CDATA[learn]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Tue, 01 Feb 2022 15:55:48 GMT</pubDate><content:encoded><![CDATA[<p>Se você já escreve testes, em algum momento, deve ter recebido orientações para <strong>mockar</strong> uma classe com o objetivo de fazer um teste mais simples. Se você nunca passou por isso ou se ainda não entendeu o motivo de usar, esse artigo é pra você.</p>
<p>E antes de começar, quero destacar um fato importante: <strong>mock</strong> não é para ser usado em tudo. Em algumas situações, o que você vai precisar é de um <strong>spy</strong>, que é bem menos "agressivo" que um mock. Então eu não estou dizendo que você deve <strong>mockar tudo em todos os testes</strong>, por favor. Se seu teste pode ser escrito de forma simples e clara sem ele, escreva sem!</p>
<blockquote>
<p>Mas Kiko, o que é um mock?</p>
</blockquote>
<p>O <strong>mock</strong> é um clone de alguma classe ou objeto, que serve para substituir a classe original de modo a te dar o controle sobre o que é esperado de acontecer durante o fluxo de testes.</p>
<p>Por exemplo, se você tem uma classe <strong>Panela</strong> que tem um método <code>cozinhar()</code>, em testes onde é preciso chamar esse método sem se importar com o que acontece dentro, você pode mockar a classe e criar a expectativa de que o método deve ser acionado pelo menos uma vez. Assim, se após a checagem isso não acontecer, uma falha será detectada.</p>
<p>Além desse cenário, o mock também serve para retirar dependências desnecessárias para o seu teste. Isso fica claro em situações onde uma classe tem acúmulo de responsabilidade e você quer testar somente uma delas. Para ignorar todas as outras, você vai mockar algumas classes chamadas ali dentro para criar retornos falsos, de modo que o teste não dependa do sucesso delas.</p>
<blockquote>
<p>Interessante... Mas como funciona um mock, Kiko?</p>
</blockquote>
<p>Via <strong>injeção de dependência</strong>. Isso é uma estratégia que depende inteiramente de como o seu projeto foi desenvolvido. Por exemplo, se você usa um framework com gerenciamento de container como o Laravel, o mock pode ser atrelado diretamente a uma classe. Assim, quando você for instanciar essa classe usando o gerenciador, o Laravel instanciará o mock no lugar da classe.</p>
<p>Outra forma de injeção é quando você não instancia classe alguma no seu código, recebendo isso como entrada via construtor ou algum método em específico, que exemplifiquei no artigo anterior.</p>
<blockquote>
<p>Hum... Acho que entendi... Acho...</p>
</blockquote>
<p>Então vamos ver na prática, continuando o exemplo da classe <strong>Panela</strong>:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Panela</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">array</span> $ingredientes
    </span>) </span>{ }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cozinhar</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-keyword">foreach</span>(<span class="hljs-keyword">$this</span>-&gt;ingredientes <span class="hljs-keyword">as</span> $ingrediente) {
            $ingrediente-&gt;aumentarTemperatura();
        }
    }
}
</code></pre>
<p>Para complementar, farei uma classe <strong>Ingrediente</strong>:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Ingrediente</span>
</span>{
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">float</span> $congelado = <span class="hljs-number">10.0</span>;
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">float</span> $cru = <span class="hljs-number">30.0</span>;
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">float</span> $malCozido = <span class="hljs-number">55.0</span>;
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">float</span> $cozido = <span class="hljs-number">65.0</span>;
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">float</span> $bemCozido = <span class="hljs-number">75.0</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> readonly <span class="hljs-keyword">string</span> $nome,
        <span class="hljs-keyword">protected</span> <span class="hljs-keyword">float</span> $temperatura = <span class="hljs-number">25.0</span>
    </span>) </span>{
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">temperaturaAtual</span>(<span class="hljs-params"></span>): <span class="hljs-title">float</span>
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;temperatura;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">aumentarTemperatura</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
         <span class="hljs-keyword">$this</span>-&gt;temperatura += <span class="hljs-number">0.01</span>;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">estado</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;temperatura &lt;= <span class="hljs-keyword">$this</span>-&gt;congelado) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">"congelado"</span>;
        }

        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;temperatura &lt;= <span class="hljs-keyword">$this</span>-&gt;cru) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">"cru"</span>;
        }

        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;temperatura &lt;= <span class="hljs-keyword">$this</span>-&gt;malCozido) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">"mal cozido"</span>;
        }

        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;temperatura &lt;= <span class="hljs-keyword">$this</span>-&gt;cozido) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">"cozido"</span>;
        }

        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;temperatura &lt;= <span class="hljs-keyword">$this</span>-&gt;bemCozido) {
            <span class="hljs-keyword">return</span> <span class="hljs-string">"bem cozido"</span>;
        }

        <span class="hljs-keyword">return</span> <span class="hljs-string">"queimado"</span>;
    }
}
</code></pre>
<p>Nota: eu não manjo nada de cozinha, apenas chutei alguns valores.</p>
<blockquote>
<p>Ué, Kiko, como vai funcionar isso tudo?</p>
</blockquote>
<p>Eu vou explorar um pouco de <strong><em>Design Patterns</em></strong> aqui. Cada ingrediente será uma classe que herda essa base de ingredientes, precisando configurar somente o nome do ingrediente e sua temperatura inicial (vindo via construtor). Já a temperatura de cada estado, é uma configuração opcional da hierarquia.</p>
<p>Também podemos fazer um <em>override</em> no método <code>aumentarTemperatura</code>, já que cada ingrediente tem um tempo de cozimento diferente.</p>
<p>Isso nos permitirá configurar ingredientes completamente diferentes. Por exemplo:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PeitoDeFrango</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Ingrediente</span>
</span>{ 
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"></span>)
    </span>{
        <span class="hljs-built_in">parent</span>::__construct(
            nome: <span class="hljs-string">'Peito de frango'</span>,
            temperatura: <span class="hljs-number">20.0</span>
        );
    }
}
</code></pre>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CoxaoMole</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Ingrediente</span>
</span>{ 
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"></span>)
    </span>{
        <span class="hljs-built_in">parent</span>::__construct(
            nome: <span class="hljs-string">'Coxão Mole'</span>,
            temperatura: <span class="hljs-number">28.0</span>
        );
    }
}
</code></pre>
<p>Com isso, você pode ter a seguinte usabilidade:</p>
<pre><code class="lang-php">$coxaoMole = <span class="hljs-keyword">new</span> CoxaoMole();
$panela = <span class="hljs-keyword">new</span> Panela(ingredientes: [$coxaoMole]);

$repeticoes = <span class="hljs-number">0</span>;
<span class="hljs-keyword">while</span> ($coxaoMole-&gt;temperaturaAtual() &lt; <span class="hljs-number">67.0</span>) {
    $panela-&gt;cozinhar();
    $repeticoes++;
}

<span class="hljs-keyword">echo</span> <span class="hljs-string">"Levou <span class="hljs-subst">$repeticoes</span> aumentos de temperatura para deixar o <span class="hljs-subst">{$coxaoMole-&gt;nome}</span> <span class="hljs-subst">{$coxaoMole-&gt;estado()}</span>!"</span>;
</code></pre>
<p>Brinque com o código: <a target="_blank" href="https://paiza.io/projects/MmMfRYUKATVnyER0NLw5oQ?language=php">https://paiza.io/projects/MmMfRYUKATVnyER0NLw5oQ?language=php</a></p>
<p>Agora que montamos o nosso projetinho, vamos refletir sobre como podemos mockar alguma das classes citadas a fim de comprovar alguma coisa. Dada que a principal classe é a <code>Panela</code> e ela é a única que recebe outra em algum trecho do código, faz muito sentido que ela <strong>não</strong> seja mockada, somente suas dependências. No nosso experimento, ela só tem dependência com a classe <strong>Ingrediente</strong>.</p>
<p>E se você pensou dessa forma, você está plenamente certo(a). <code>Ingrediente</code> é o nosso alvo aqui. Se eu quero testar se a panela funciona, eu não preciso colocar um ingrediente de verdade, concorda? É só cozinhar qualquer coisa.</p>
<p>Nesse caso, nós vamos cozinhar um ingrediente falso. Para isso, nós precisamos criar essa classe falsa, por exemplo:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IngredienteMock</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Ingrediente</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"></span>)
    </span>{
        <span class="hljs-built_in">parent</span>::__construct(
            name: <span class="hljs-string">"Mock"</span>,
            temperatura: <span class="hljs-number">-50.0</span>
        );
    }
}
</code></pre>
<p>Essa é uma classe falsa, que tem como único objetivo validar interações entre os ingredientes e a panela. Digamos que eu queira comprovar que a classe panela aciona o método <code>aumentarTemperatura</code> do ingrediente... Há várias formas de se fazer isso.</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IngredienteMock</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Ingrediente</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> $acionou = <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"></span>)
    </span>{
        <span class="hljs-built_in">parent</span>::__construct(
            nome: <span class="hljs-string">"Mock"</span>,
            temperatura: <span class="hljs-number">-50.0</span>
        );
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">aumentarTemperatura</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;acionou = <span class="hljs-literal">true</span>;
    }
}
</code></pre>
<p>E aí, no seu teste, você teria algo assim:</p>
<pre><code class="lang-php">$ingrediente = <span class="hljs-keyword">new</span> IngredienteMock();
$panela = <span class="hljs-keyword">new</span> Panela(ingredientes: [$ingrediente]);
$panela-&gt;cozinhar();
<span class="hljs-keyword">if</span> ($ingrediente-&gt;acionou) {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"Acionou o método aumentarTemperatura()"</span>;
} <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"Não acionou o método aumentarTemperatura()"</span>;
}
</code></pre>
<p>Veja essa brincadeira aqui: <a target="_blank" href="https://paiza.io/projects/ppWVYgKRKjOxztCMzGIFPQ?language=php">https://paiza.io/projects/ppWVYgKRKjOxztCMzGIFPQ?language=php</a></p>
<blockquote>
<p>Ah, então o Mock não necessariamente precisa fazer o que o código original faz, apenas <strong>registrar os métodos acionados</strong>, Kiko?</p>
</blockquote>
<p><strong>Exatamente</strong>. No geral, nós usamos o Mock para <strong>simular coisas</strong>. Então muitas vezes você vai ter um <strong>Mock</strong> que retorna algum resultado fictício para testar se esse resultado está influenciando no resto do código, etc.</p>
<p>A forma como montamos esse mock não é a ideal, na verdade, está bem longe! Afinal, nós temos diversas bibliotecas que nos fornecem várias classes auxiliadoras para clonar classes e tornar as verificações ainda mais assertivas.</p>
<p>Uma das bibliotecas mais usadas é a <a target="_blank" href="http://docs.mockery.io/en/latest/">Mockery.io</a>, que já vem integrada no PHPUnit e é bem simples de se usar. Por exemplo, aquele teste que fizemos poderia ser bem mais compacto:</p>
<pre><code class="lang-php">
$ingrediente = Mockery::mock(Ingrediente::class);
$ingrediente-&gt;shouldReceive(<span class="hljs-string">'aumentarTemperatura'</span>)-&gt;once();

$panela = <span class="hljs-keyword">new</span> Panela(ingredientes: [$ingrediente]);
$panela-&gt;cozinhar();
</code></pre>
<p>Se o método não for chamado, durante o processo de desconstrução do objeto, o Mockery lançará um erro. Seu teste não terá nenhum problema se for chamado conforme esperado (somente uma vez).</p>
<h2 id="heading-conclusao">Conclusão</h2>
<p>Embora o ato de <strong>mockar</strong> possa ser feito do zero, trabalhar com bibliotecas mais robustas e com um bom tempo de mercado pode ser uma escolha melhor. Até porque seu código fica mais legível e você perde menos tempo escrevendo os seus testes.</p>
<p>Outro detalhe é o fato de que <strong>Mocks</strong> estão aí para deixar seus testes mais focados, unitariamente falando. Se eu estou testando a panela, pouco importa o ingrediente, confere? Agora se eu estivesse testando o ingrediente, não teríamos o que mockar.</p>
<p>Se a classe que estiver mockando tiver algum método essencial para o teste (que faz parte do que está testando), não faça esse mock! No máximo, faça um <strong>spy</strong>, como mostra o <a target="_blank" href="https://adamwathan.me/2016/10/12/replacing-mocks-with-spies/"><strong>Adam Wathan</strong> nesse artigo sobre <strong>Mockery mock vs spy</strong></a>. Não deixe brechas no seu teste!</p>
<p>E por hoje é só! Curtiu?? Comenta e compartilha! Acabei ficando até tarde escrevendo esse artigo só pra dar mais uma variada no blog. Prometo que no próximo eu voltarei com a série de PHP para Iniciantes, hahaha. Não deixa de acompanhar!</p>
<p><strong>Inté!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP: Função auxiliar com contexto de objeto?!]]></title><description><![CDATA[Se você é iniciante no PHP, essa introdução pode ter te deixado com uma super incógnita na cabeça... E tudo bem! Eu vou explicar direitinho. Mas antes de começar eu quero destacar o que eu não vou me aprofundar tanto assim, beleza?
O ponto forte dest...]]></description><link>https://blog.kaiquegarcia.dev/php-funcao-auxiliar-com-contexto-de-objeto</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-funcao-auxiliar-com-contexto-de-objeto</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Sat, 29 Jan 2022 00:47:22 GMT</pubDate><content:encoded><![CDATA[<p>Se você é iniciante no PHP, essa introdução pode ter te deixado com uma super incógnita na cabeça... E tudo bem! Eu vou explicar direitinho. Mas antes de começar eu quero destacar o que eu não vou me aprofundar tanto assim, beleza?</p>
<p>O ponto forte deste artigo será sobre funções anônimas (closures). Se você não sabe nem o que é função, começa pelo meu <a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-funcoes-introducao">artigo introdutório</a>. Se já tem conhecimentos mas ainda se sente meio inseguro sobre o que é uma closure, lê meu artigo específico sobre <a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-funcoes-closures-funcoes-variaveis-e-arrow-functions">Closures, Funções variáveis e Arrow Functions</a>.</p>
<p>Há um outro pré-requisito que é <strong>estruturas de try-catch</strong>, que ainda não falei em nenhum artigo... Se só não souber isso, tenta ler assim mesmo. Ficando alguma dúvida, sinta-se a vontade para perguntar nos comentários ou mandando mensagem lá no <a target="_blank" href="https://bsky.app/profile/kaiquegarcia.dev">meu BlueSky</a>!</p>
<p>Agora que já estabeleci os pré-requisitos para nos aventurarmos na leitura de hoje, vamos nos jogar de cabeça!</p>
<blockquote>
<p>Mas Kiko, o que é uma função auxiliar?</p>
</blockquote>
<p>É um bom começo, não é mesmo? Quem programa com Orientação a Objeto há algum tempo pode ter a mesma sensação que eu tenho hoje, sobre parecer um tabu escrever qualquer função que não seja um método de uma classe. Porém isso não é tão errado assim, tem momentos que uma função deixa o código bem mais legível do que instanciar uma classe para chamar apenas um método, sabe?</p>
<p>Um exemplo bem legal sobre isso vem de um problema que investiguei no trabalho hoje sobre transações de banco de dados. Calma, você não precisa entender isso a fundo para sacar o que está acontecendo, apenas pega o resumo e você vai entender o problema geral.</p>
<p>Quando nós enviamos um comando para o banco de dados fora de uma transação, esse comando é persistido nos dados instantaneamente (leia-se, no momento que o banco processar o seu comando). Já dentro de uma transação, você pode efetuar vários comandos em sequência, mas eles só serão persistidos quando você fizer o <strong>commit</strong> dos comandos. Isso serve para, caso algo dê errado, você possa reverter todos os comandos de uma só vez.</p>
<p>Então você tem a seguinte situação:</p>
<ol>
<li><p>Vou fazer vários comandos complexos, então <strong>inicio uma transação com o banco de dados</strong>;</p>
</li>
<li><p>Faço um comando;</p>
</li>
<li><p>Faço outro comando;</p>
</li>
<li><p>... Faço vários comandos de banco de dados;</p>
</li>
<li><p>Se deu tudo certo, mando o sinal de <strong>commit</strong> e salto para o passo 7;</p>
</li>
<li><p>Se algo deu errado, reverto com o sinal de <strong>rollback</strong> e salto para o próximo passo;</p>
</li>
<li><p>Concluo transmitindo se deu certo ou não.</p>
</li>
</ol>
<p>Em vários frameworks você terá uma classe que fornece esses comandos de banco de dados. Hoje eu vou me basear no <a target="_blank" href="https://laravel.com/">Laravel</a>, usando como referência a classe <code>DB</code>, que, por sinal, já fornece um método auxiliar sobre o que iremos ver mais abaixo.</p>
<p>Enfim, então você pode fazer os passos acima da seguinte forma:</p>
<pre><code class="lang-php">DB::beginTransaction(); <span class="hljs-comment">// passo 1</span>
$success = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// passo 2</span>
    <span class="hljs-comment">// passo 3</span>
    <span class="hljs-comment">// ... passo 4</span>
    DB::commit(); <span class="hljs-comment">// passo 5</span>
    $success = <span class="hljs-literal">true</span>;
} <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> $throwable) {
    DB::rollback(); <span class="hljs-comment">// passo 6</span>
    <span class="hljs-comment">// eu colocaria um log aqui, mas não convém ao caso</span>
}
<span class="hljs-keyword">return</span> $success; <span class="hljs-comment">// passo 7</span>
</code></pre>
<p>O que é desagradável nessa situação, é ver essa estratégia repetida diversas vezes ao longo do código, sendo que temos pelo menos quatro passos iguais em todos os casos, concorda? Então por que não criar uma função que dá a possibilidade de executar um <code>callabe</code>?</p>
<h2 id="heading-criando-a-funcao-auxiliar-transaction">Criando a função auxiliar <code>transaction()</code></h2>
<p>Se você encapsular isso tudo em uma função, teremos o seguinte cenário:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transaction</span>(<span class="hljs-params"></span>): <span class="hljs-title">bool</span>
</span>{
    DB::beginTransaction(); <span class="hljs-comment">// passo 1</span>
    $success = <span class="hljs-literal">false</span>;
    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// passo 2</span>
        <span class="hljs-comment">// passo 3</span>
        <span class="hljs-comment">// ... passo 4</span>
        DB::commit(); <span class="hljs-comment">// passo 5</span>
        $success = <span class="hljs-literal">true</span>;
    } <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> $throwable) {
        DB::rollback(); <span class="hljs-comment">// passo 6</span>
    }
    <span class="hljs-keyword">return</span> $success; <span class="hljs-comment">// passo 7</span>
}
</code></pre>
<p>Porém, os passos 2, 3, 4 e 7 não são exatamente responsabilidades dela. Isso precisa ser algo que possa ser criado do lado de fora dela... É aí que entra as funções anônimas: <strong>você dá para quem usar a função auxiliar o poder de escrever outra função para executar dentro</strong>.</p>
<p>Isso nos leva a criar um argumento <code>callable $closure</code>, chamando-o dentro da estrutura de <code>try-catch</code>:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transaction</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure</span>): <span class="hljs-title">mixed</span>
</span>{
    DB::beginTransaction(); <span class="hljs-comment">// passo 1</span>
    $result = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">try</span> {
        $result = $closure();
        DB::commit(); <span class="hljs-comment">// passo 5</span>
    } <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> $throwable) {
        DB::rollback(); <span class="hljs-comment">// passo 6</span>
    }
    <span class="hljs-keyword">return</span> $result; <span class="hljs-comment">// passo 7</span>
}
</code></pre>
<p>Notou que mudei o <code>$sucess</code> para <code>$result</code>? Porque eu não quero forçar o desenvolvedor a só responder booleanos. Ele vai responder o que precisar e isso poderá ter a tipagem que precisar.</p>
<p>Se o PHP tivesse <strong>Generics</strong>, nós poderíamos forçar a criação de um tipo genérico, modificando a assinatura do argumento para algo como <code>callable&lt;Response&gt; $closure</code> e a assinatura da função para <code>: Response</code>. Assim poderíamos facilmente mapear a partir da criação das closures qual seria o tipo de resposta...</p>
<blockquote>
<p>QUÊ?!</p>
</blockquote>
<p>Ok, eu só estava pensando em como a linguagem ficaria ainda mais divertida se tivesse <strong>Generics</strong>, mas foi total fuga do tema: nota zero na redação. Mas, voltando ao assunto... Com o retorno <code>mixed</code>, o desenvolvedor já tem total controle para fazer algo assim:</p>
<pre><code class="lang-php">transaction(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// passo 2</span>
    <span class="hljs-comment">// passo 3</span>
    <span class="hljs-comment">// ... passo 4</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; <span class="hljs-comment">// sucesso</span>
});
</code></pre>
<p>Você pode até ajudá-lo, dando opção para definir o valor padrão do retorno negativo:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transaction</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure, $defaultResult = <span class="hljs-literal">null</span></span>): <span class="hljs-title">mixed</span>
</span>{
    DB::beginTransaction(); <span class="hljs-comment">// passo 1</span>
    $result = $defaultResult;
    <span class="hljs-keyword">try</span> {
        $result = $closure();
        DB::commit(); <span class="hljs-comment">// passo 5</span>
    } <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> $throwable) {
        DB::rollback(); <span class="hljs-comment">// passo 6</span>
    }
    <span class="hljs-keyword">return</span> $result; <span class="hljs-comment">// passo 7</span>
}
</code></pre>
<p>Deixando o uso dessa forma:</p>
<pre><code class="lang-php">transaction(
    <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-comment">// passo 2</span>
        <span class="hljs-comment">// passo 3</span>
        <span class="hljs-comment">// ... passo 4</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; <span class="hljs-comment">// sucesso</span>
    },
    <span class="hljs-literal">false</span> <span class="hljs-comment">// erro</span>
);
</code></pre>
<p>De todo modo, isso ainda não está tão legal assim. A função faz o que promete: transaciona baseado no sucesso de tudo o que for executado na sua closure... Mas não te dá o controle de poder enviar sinal de <strong>commit</strong> quando quiser... Além de fornecer outros controles que vamos ver mais embaixo.</p>
<p>Para melhorar esse controle, você terá de ter uma classe de gerenciamento de transações, a qual irei chamar de <strong>TransactionManager</strong>. Ela terá os métodos públicos para inicializar a transação, comitar ou reverter:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TransactionManager</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">beginTransaction</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::beginTransaction();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commit</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::commit();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rollback</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::rollback();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bind</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure</span>): <span class="hljs-title">callable</span>
    </span>{
        <span class="hljs-keyword">return</span> $closure-&gt;bindTo(<span class="hljs-keyword">$this</span>); <span class="hljs-comment">// vincula a instância à closure</span>
    }
}
</code></pre>
<p>Notou que coloquei um método <code>bind</code>? Esse método é o que vai tornar a execução de tudo bem mais legível... Você vai ver mais abaixo! Agora nós precisamos ajustar a função auxiliar para não chamar mais nada diretamente, apenas o gerenciador de transações:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transaction</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure, $defaultResult = <span class="hljs-literal">null</span></span>): <span class="hljs-title">mixed</span>
</span>{
    $transactionManager = <span class="hljs-keyword">new</span> TransactionManager();
    $transactionManager-&gt;beginTransaction();
    $result = $defaultResult;
    <span class="hljs-keyword">try</span> {
        $closure = $transactionManager-&gt;bind($closure);
        $result = $closure();
        $transactionManager-&gt;commit();
    } <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> $throwable) {
        $transactionManager-&gt;rollback();
    }
    <span class="hljs-keyword">return</span> $result;
}
</code></pre>
<blockquote>
<p>Ué, Kiko? O código ficou bem mais extenso de se ler... Não era pra ser simples?</p>
</blockquote>
<p>Funções auxiliares raramente são simples. Elas estão ali para centralizar o grosso do código de modo que o seu controle, do lado de fora, seja simples. Quer ver na prática?</p>
<p>Bem, agora você pode controlar o commit e rollback de dentro da sua função:</p>
<pre><code class="lang-php">transaction(
    <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-comment">// passo 2</span>
        <span class="hljs-keyword">$this</span>-&gt;commit();
        <span class="hljs-comment">// passo 3</span>
        <span class="hljs-comment">// ... passo 4</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; <span class="hljs-comment">// sucesso</span>
    },
    <span class="hljs-literal">false</span> <span class="hljs-comment">// erro</span>
);
</code></pre>
<p>Legal?! Percebeu que eu chamei <code>$this-&gt;commit()</code> dentro de uma closure que é chamada dentro de uma função? Em cenários comuns, isso resultaria em um belíssimo erro. O que nos possibilita chamar o <code>$this</code> aqui é aquele método <code>bind</code> que mencionei lá em cima.</p>
<p>Ele vincula a função anônima ao objeto <code>$transactionManager</code>, de modo que ela passa a ter praticamente o mesmo escopo dos outros métodos ali dentro. Eu acho isso iradíssimo! E esse é o ponto forte desse artigo, mas vamos além...</p>
<blockquote>
<p>Kiko, e se eu quiser que alguma coisa rode após todo o fluxo de sucesso?</p>
</blockquote>
<p>O céu é o limite! Você pode adicionar uma estrutura no gerenciador de transações para empilhar várias funções anônimas e chamar todas sequencialmente após qualquer <code>commit</code>. Para não deixar isso amarrado ao gerenciador de transações, vamos criar uma pilha de callbacks, pode ser? Chamarei de <strong>CallbackStackManager</strong>:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CallbackStackManager</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">array</span> $stack = [];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addCallback</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $callback</span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;stack[] = $callback;
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">popStack</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        $stack = <span class="hljs-keyword">$this</span>-&gt;stack;
        <span class="hljs-keyword">$this</span>-&gt;stack = [];
        <span class="hljs-keyword">return</span> $stack;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-keyword">foreach</span>(<span class="hljs-keyword">$this</span>-&gt;popStack() <span class="hljs-keyword">as</span> $callback) {
            $callback();
        }
    }
}
</code></pre>
<p>É um controle de pilha bem simples. Você vai adicionando suas funções anônimas com o método <code>addCallback</code>. Conforme o código for funcionando, em algum momento você irá rodar todos os callbacks chamando o método <code>run()</code>. Simples assim!</p>
<blockquote>
<p>E o que é aquele <code>popStack</code>, Kiko?</p>
</blockquote>
<p>É um método de segurança para evitar <strong>loops infinitos</strong>. Passei por um problema onde uma função desenvolvida por outra pessoa gerou um loop infinito por voltar ao ponto onde o código chamava o <code>run()</code> antes de resetar a <code>stack</code>. Com o método <code>pop</code>, você já reseta a <code>stack</code> antes mesmo de começar.</p>
<blockquote>
<p>Ok, Kiko, e como unimos essa classe ao resto da <em>obra de arte</em>?</p>
</blockquote>
<p>HEHEHE, primeiramente: <strong>nem pense em instanciar o</strong> <code>CallbackStackManager</code> dentro do <code>TransactionManager</code>. Se fizer isso, você estará gerando uma dependência interna... Essa classe precisa ser uma entrada no construtor do outro gerenciador, de modo a nos permitir <strong>mockar</strong> a dependência quando precisarmos escrever algum teste.</p>
<p>Na prática, já era pra termos escrito algum teste para validar nossa teoria... Mas aí iria ser mais um conhecimento de pré-requisito e eu quero tornar esse artigo mais acessível, ok? Se você não conhece o TDD (Test-Driven Development), recomendo a leitura.</p>
<blockquote>
<p>Tá, tá, e como faz a parada?</p>
</blockquote>
<p>Pra já:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TransactionManager</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> CallbackStackManager $callbackStackManager
    </span>) </span>{ }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">runAfterCommit</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure</span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;callbackStackManager-&gt;addCallback($closure);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">beginTransaction</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::beginTransaction();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commit</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::commit();
        <span class="hljs-keyword">$this</span>-&gt;callbackStackManager-&gt;run();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rollback</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::rollback();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bind</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure</span>): <span class="hljs-title">callable</span>
    </span>{
        <span class="hljs-keyword">return</span> $closure-&gt;bindTo(<span class="hljs-keyword">$this</span>); <span class="hljs-comment">// vincula a instância à closure</span>
    }
}
</code></pre>
<p><strong>O que alterei</strong>:</p>
<ul>
<li><p>incluí um construtor, recebendo uma instância da nova classe <code>CallbackStackManager</code>;</p>
</li>
<li><p>incluí um método <code>runAfterCommit</code> para facilitar o uso na closure do desenvolvedor;</p>
</li>
<li><p>incluí uma chamada ao <code>callbackStackManager-&gt;run()</code> dentro do método <code>commit</code>.</p>
</li>
</ul>
<p>Lembrando que, em cada <code>run()</code>, o gerenciador apaga todas as funções anônimas da pilha.</p>
<p>Além dessas alterações, precisaremos modificar a função auxiliar:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transaction</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure, $defaultResult = <span class="hljs-literal">null</span></span>): <span class="hljs-title">mixed</span>
</span>{
    $callbackStackManager = <span class="hljs-keyword">new</span> CallbackStackManager();
    $transactionManager = <span class="hljs-keyword">new</span> TransactionManager($callbackStackManager);
    $transactionManager-&gt;beginTransaction();
    $result = $defaultResult;
    <span class="hljs-keyword">try</span> {
        $closure = $transactionManager-&gt;bind($closure);
        $result = $closure();
        $transactionManager-&gt;commit();
    } <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> $throwable) {
        $transactionManager-&gt;rollback();
    }
    <span class="hljs-keyword">return</span> $result;
}
</code></pre>
<p><strong>O que modifiquei</strong>:</p>
<ul>
<li><p>instanciei a nova classe <code>CallbackStackManager</code>;</p>
</li>
<li><p>adicionei a nova instância no construtor da classe <code>TransactionManager</code>.</p>
</li>
</ul>
<blockquote>
<p>E como seria o uso disso na prática, Kiko?</p>
</blockquote>
<pre><code class="lang-php">transaction(
    <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-comment">// passo 2</span>
        <span class="hljs-comment">// passo 3</span>
        <span class="hljs-keyword">$this</span>-&gt;runAfterCommit(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
            event(<span class="hljs-keyword">new</span> Event(<span class="hljs-string">'bonequinho_criado'</span>));
        });
        <span class="hljs-comment">// ... passo 4</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; <span class="hljs-comment">// sucesso</span>
    },
    <span class="hljs-literal">false</span> <span class="hljs-comment">// erro</span>
);
</code></pre>
<h2 id="heading-resultado-final">Resultado final</h2>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CallbackStackManager</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">array</span> $stack = [];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addCallback</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $callback</span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;stack[] = $callback;
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">popStack</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        $stack = <span class="hljs-keyword">$this</span>-&gt;stack;
        <span class="hljs-keyword">$this</span>-&gt;stack = [];
        <span class="hljs-keyword">return</span> $stack;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-keyword">foreach</span>(<span class="hljs-keyword">$this</span>-&gt;popStack() <span class="hljs-keyword">as</span> $callback) {
            $callback();
        }
    }
}


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TransactionManager</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> CallbackStackManager $callbackStackManager
    </span>) </span>{ }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">runAfterCommit</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure</span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;callbackStackManager-&gt;addCallback($closure);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">beginTransaction</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::beginTransaction();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commit</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::commit();
        <span class="hljs-keyword">$this</span>-&gt;callbackStackManager-&gt;run();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rollback</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span>
    </span>{
        DB::rollback();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bind</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure</span>): <span class="hljs-title">callable</span>
    </span>{
        <span class="hljs-keyword">return</span> $closure-&gt;bindTo(<span class="hljs-keyword">$this</span>); <span class="hljs-comment">// vincula a instância à closure</span>
    }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transaction</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> $closure, $defaultResult = <span class="hljs-literal">null</span></span>): <span class="hljs-title">mixed</span>
</span>{
    $callbackStackManager = <span class="hljs-keyword">new</span> CallbackStackManager();
    $transactionManager = <span class="hljs-keyword">new</span> TransactionManager($callbackStackManager);
    $transactionManager-&gt;beginTransaction();
    $result = $defaultResult;
    <span class="hljs-keyword">try</span> {
        $closure = $transactionManager-&gt;bind($closure);
        $result = $closure();
        $transactionManager-&gt;commit();
    } <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> $throwable) {
        $transactionManager-&gt;rollback();
    }
    <span class="hljs-keyword">return</span> $result;
}
</code></pre>
<p><strong>OBS.: você não vai conseguir rodar esse código se só copiar e colar, pois falta importar a classe</strong> <code>DB</code> do Laravel/Lumen. Além disso, não está nada organizado... O ideal é que cada classe esteja em um arquivo separado, assim como a função auxiliar.</p>
<p>Se ainda assim, quiser ver isso funcionando para brincar um pouco, eu criei um projeto no site <a target="_blank" href="https://paiza.io/projects/Qrb2UOhRGHHH3hdEBDrMVg">paiza.io</a> para te fornecer o código pronto para brincadeira. Dá uma olhada: <a target="_blank" href="https://paiza.io/projects/Qrb2UOhRGHHH3hdEBDrMVg">https://paiza.io/projects/Qrb2UOhRGHHH3hdEBDrMVg</a>.</p>
<p>Como o objetivo era apenas mostrar um bom uso de funções auxiliares para simplificar a legibilidade do código, acredito que atingi o objetivo desse artigo. Só não sei se está tão claro assim pra quem nunca viu transações de banco de dados... Mas não era o foco, tá bom?</p>
<p>Curtiu?! Comenta e compartilha! E me conta o que mais gostou, o que mais odiou e se concorda que dá sim pra ter funções auxiliares legais nos projetos? Estou ansioso para saber sua opinião! Sei que esperava um artigo da série <a target="_blank" href="https://blog.kaiquegarcia.dev/series/php-para-iniciantes">PHP para Iniciantes</a>, mas hoje resolvi quebrar a rotina, hahahah.</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP para Iniciantes: Classes o Objetos - Propriedades]]></title><description><![CDATA[Quando vamos falar de propriedade de um objeto, nós normalmente pensamos em valores de uma instância... E é isso mesmo! Quando estiver estudando uma linguagem, o que você deve sempre se perguntar, em algum momento, é:

Como declarar uma propriedade?
...]]></description><link>https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-o-objetos-propriedades</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-o-objetos-propriedades</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Wed, 26 Jan 2022 22:37:36 GMT</pubDate><content:encoded><![CDATA[<p>Quando vamos falar de propriedade de um objeto, nós normalmente pensamos em valores de uma instância... E é isso mesmo! Quando estiver estudando uma linguagem, o que você deve sempre se perguntar, em algum momento, é:</p>
<ol>
<li><strong>Como declarar uma propriedade?</strong></li>
<li><strong>É possível determinar o tipo de uma propriedade nessa linguagem?</strong></li>
<li><strong>Essa linguagem possui controle de visibilidade?</strong></li>
<li><strong>Como acesso o valor de uma propriedade de um objeto?</strong></li>
<li><strong>Como altero o valor dessa propriedade?</strong></li>
</ol>
<p>São todas perguntas-chave que te farão entender mais rapidamente como a linguagem estudada funciona... Apesar de que nem todas tem o conceito literalmente chamado de "propriedade", você poderá encontrar a mesma intenção em nomes distintos.</p>
<p>Focando no PHP, você já sabe que a escrita de variáveis é precedida de <code>$</code>, certo? E que quando atribuímos um objeto a uma variável, na verdade, estamos apenas atribuindo uma referência ao objeto, o que significa que você nunca vai ter uma variável com um objeto irreferenciável.</p>
<blockquote>
<p>Onde você quer chegar, Kiko?</p>
</blockquote>
<center> <img src="https://media.giphy.com/media/xT0xeuOy2Fcl9vDGiA/giphy.gif" alt="Cachorrinho confuso" /> </center>

<p>Com uma particularidade tão agressiva, é lógico que a forma que interagimos com o que quer que esteja "<em>dentro</em>" do objeto é diferente das outras coisas que você viu até então. Por exemplo, em <code>array</code>, você poderia acessar um índice dele apenas encapsulando o índice desejado entre colchetes (<code>[</code> e <code>]</code>) logo após acessá-lo. A frase ficou confusa? Então deixa que eu mostro na prática:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

$matriz = [
    [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>],
];

<span class="hljs-comment">// acessando a primeira linha da matriz</span>
$primeiraLinha = $matriz[<span class="hljs-number">0</span>];

<span class="hljs-comment">// acessando a última coluna da primeira linha da matriz</span>
$ultimaColuna = $primeiraLinha[<span class="hljs-number">2</span>];
<span class="hljs-comment">// OU</span>
$ultimaColuna = $matriz[<span class="hljs-number">0</span>][<span class="hljs-number">2</span>]; <span class="hljs-comment">// acessei o array $matriz, peguei o índice 0 - acessando outro array, depois peguei o índice 2</span>
</code></pre>
<p>Quando eu quis acessar o array armazenado na variável <code>$matriz</code>, escrevi algo simples e fácil de entender, concorda? Mas a partir do momento que você precisa acessar <strong><em>um dado que está dentro de outro</em></strong>, o caos começa a crescer. <strong>Você deve evitar situações como essa sempre que possível</strong>. O código fica ilegível.</p>
<p>Agora voltando ao que estava falando sobre a particularidade de objetos... Para acessar um dado dentro de uma instância, você usa o <strong>operador de objetos</strong> (<code>-&gt;</code>, sinal de <strong>menos</strong> seguido do sinal de <strong>maior que</strong>), que é colocado imediatamente após um objeto. Ele irá te dar acesso ao que quer que exista na instância de acordo com a visibilidade atual. É literalmente <code>$objeto-&gt;&lt;alguma coisa aqui&gt;</code>.</p>
<p>Antes de te mostrar isso na prática, vamos responder aquelas perguntinhas pra seguir a ordem da evolução da minha linha de raciocínio?</p>
<center> <img src="https://media.giphy.com/media/l0HlRnAWXxn0MhKLK/giphy.gif" alt="Interrogações" /> </center>

<h2 id="heading-1-como-declarar-uma-propriedade">1. Como declarar uma propriedade?</h2>
<p>Quando falamos da declaração de propriedade, não estamos falando na <strong>criação de uma</strong> - sim, é possível criar uma propriedade não-declarada... <em>E assim como isso é crime pra Receita Federal (quando falamos de imóveis), deveria ser crime aqui também</em>.</p>
<center> <img src="https://media.giphy.com/media/LPZRL8ZsLnmPD7NzA2/giphy.gif" alt="Criminoso jogando tinta em câmera de vigilância" /> </center>

<p>Estamos falando, na verdade, no ato de definir suas características antes mesmo de utilizá-la, logo, isso só se aplica na escrita de classes. Concorda? A classe define as características de como seus objetos irão se comportar e é sobre isso que estamos falando.</p>
<p>Existe duas formas de declarar uma propriedade em uma classe:</p>
<ol>
<li>a boa: <code>{visibilidade} {opcional: tipo de dado primitivo} ${nome da propriedade}</code>;</li>
<li>a ruim: <code>var ${nome da propriedade}</code>.</li>
</ol>
<p>Você conhecia essa segunda forma? <strong>Cavernosíssima</strong>. Há muito tempo escrevíamos da segunda forma pois o entendimento comum era de que as propriedades são variáveis dentro de uma classe. Felizmente isso evoluiu, embora a linguagem aceite essa escrita até hoje.</p>
<p>Por favor, finja que só existe a primeira forma:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $propriedade;
}
</code></pre>
<h3 id="heading-11-destrinchando-a-declaracao-de-propriedade">1.1. Destrinchando a declaração de propriedade</h3>
<h4 id="heading-111-visibilidade">1.1.1. Visibilidade</h4>
<p>O primeiro texto, <code>private</code>, remete a privacidade, que podem ser as seguintes:</p>
<ul>
<li><code>private</code>: visibilidade privada, ou seja, somente métodos da classe onde estamos declarando podem acessar essa propriedade diretamente;</li>
<li><code>protected</code>: visibilidade protegida, ou seja, somente métodos da classe onde estamos declarando e das classes que herdarem as propriedades dela poderão acessar diretamente;</li>
<li><code>public</code>: visibilidade pública, todo mundo pode acessar diretamente.</li>
</ul>
<p>Exemplos:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $myPrivate = <span class="hljs-string">"ola"</span>;
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">string</span> $myProtected = <span class="hljs-string">"mundo"</span>;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> $myPublic= <span class="hljs-string">"louco"</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMyPrivate</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;myPrivate;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExemploHerdeiro</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exemplo</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMyProtected</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;myProtected;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMyPrivateWithError</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;myPrivate;
    }
}

$exemplo = <span class="hljs-keyword">new</span> Exemplo();
$exemploHerdeiro = <span class="hljs-keyword">new</span> ExemploHerdeiro();

<span class="hljs-comment">// se você descomentar a linha abaixo, receberá um erro:</span>
<span class="hljs-comment">// var_dump($exemplo-&gt;myPrivate);</span>
<span class="hljs-comment">// isso acontece porque, nesse escopo, fora da classe, essa propriedade não é visível</span>
<span class="hljs-comment">// então o interpretador dá um erro como se ela não existisse</span>

<span class="hljs-comment">// para acessar o valor de uma propriedade com visibilidade restringida, eu criei o</span>
<span class="hljs-comment">// método getMyPrivate, que retorna o valor dela:</span>
var_dump($exemplo-&gt;getMyPrivate()); <span class="hljs-comment">// string(ola)</span>

<span class="hljs-comment">// da mesma forma, se você descomentar a linha abaixo, também receberá um erro:</span>
<span class="hljs-comment">// var_dump($exemplo-&gt;myProtected);</span>
<span class="hljs-comment">// por ser protegida, é preciso expor seu valor em outro método</span>
<span class="hljs-comment">// como seu só escrevi esse método na classe herdeira (ExemploHerdeiro),</span>
<span class="hljs-comment">// então é preciso acessar por lá:</span>
var_dump($exemploHerdeiro-&gt;getMyProtected()); <span class="hljs-comment">// string(mundo)</span>

<span class="hljs-comment">// já a propriedade pública é acessível normalmente</span>
var_dump($exemplo-&gt;myPublic); <span class="hljs-comment">// string(louco)</span>

<span class="hljs-comment">// sendo pública, a classe herdeira também irá herdá-la de forma pública:</span>
var_dump($exemploHerdeiro-&gt;myPublic);

<span class="hljs-comment">// porém, a classe herdeira não consegue acessar nada que estiver privado na</span>
<span class="hljs-comment">// classe pai, como mostro no erro a seguir (descomente para ver):</span>
<span class="hljs-comment">// var_dump($exemploHerdeiro-&gt;getMyPrivateWithError());</span>
</code></pre>
<h4 id="heading-112-tipo-de-dado-primitivo">1.1.2. Tipo de dado primitivo</h4>
<p>Eu já te mostrei toda a seção sobre os tipos de dados primitivos existentes no PHP, certo? Você basicamente deve trabalhar com os tipos que sua propriedade irá aceitar.</p>
<p>Antes do PHP 8, você estava limitado a declarar somente um tipo por vez. Agora é possível declarar mais de um tipo aceito concatenando com o operador <strong>OU</strong> (<code>|</code>). Deixando isso mais flexível de modo a não precisar aceitar todos os tipos para aceitar mais de um. <em>Mas mesmo sendo possível...</em> Tente limitar sempre a um tipo, ok?!</p>
<h4 id="heading-113-nomenclatura-da-propriedade">1.1.3. Nomenclatura da propriedade</h4>
<p>As regras são as mesmas de quando vamos escrever uma variável. Como eu já mencionei isso no artigo anterior (e acho que já ficou bem claro), vou evitar essa repetição, rs.</p>
<h3 id="heading-12-outras-novidades-do-php-8">1.2. Outras novidades do PHP 8</h3>
<p>Além dessas formas que te apresentei, a partir do PHP 8, passamos a ter novas possibilidades no que diz respeito a declaração de propriedades. Por exemplo: uma das dores de cabeça de escrever uma propriedade não-pública, é que muitas vezes somos forçados a escrever comandos <code>get</code> para dar acesso ao dado armazenado. Quando um dado é exposto somente para leitura, nós não poderíamos torná-lo <code>public</code>, pois isso iria expor, também, para escrita.</p>
<p>Agora nós podemos declarar um tipo de somente leitura informando a palavra-chave <code>readonly</code>.</p>
<h4 id="heading-121-propriedade-readonly">1.2.1. Propriedade <code>readonly</code></h4>
<p>Essa definição deve ficar entre a visibilidade e o tipo de dado da propriedade, modificando aquela assinatura que escrevi mais cedo para <code>{visibilidade} readonly {tipo de dado primitivo} ${nome da propriedade}</code>. Simples, não? Com isso, você pode manter a propriedade pública, sem medo.</p>
<p>Quando declaramos uma propriedade <code>readonly</code>, o PHP irá limitar o escopo de alteração da mesma <strong>somente no processo de construção</strong>. Ou seja, se você tentar alterar o dado depois da instância estar construída, mesmo que executando dentro da própria classe, você terá um belo de um erro. Quer ver?</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span> <span class="hljs-comment">// PHP 8.1</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span>
</span>{
    <span class="hljs-keyword">public</span> readonly <span class="hljs-keyword">string</span> $text;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $text</span>)
    </span>{
        <span class="hljs-comment">// aqui podemos alterar</span>
        <span class="hljs-keyword">$this</span>-&gt;text = $text;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setText</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $newText</span>): <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-comment">// aqui não podemos</span>
        <span class="hljs-keyword">$this</span>-&gt;text = $newText;
    }
}

$exemplo = <span class="hljs-keyword">new</span> Exemplo(<span class="hljs-string">"Ola mundo"</span>);
var_dump($exemplo-&gt;text); <span class="hljs-comment">// string(Ola mundo)</span>

<span class="hljs-comment">// descomente para ver o erro</span>
<span class="hljs-comment">// $exemplo-&gt;setText("Adeus mundo");</span>

<span class="hljs-comment">// aqui também não podemos</span>
<span class="hljs-comment">// descomente para ver o erro</span>
<span class="hljs-comment">// $exemplo-&gt;text = "Adeus mundo";</span>
</code></pre>
<p>Você pode rodar os códigos do PHP 8.1 no site <a target="_blank" href="https://3v4l.org/U0K7c#v8.1.2">3v4l.org</a>.</p>
<p>Ah, e quando eu digo que essa propriedade só pode ser escrita no construtor, significa que ela também não pode ter nenhum valor padrão.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span>
</span>{
    <span class="hljs-keyword">public</span> readonly <span class="hljs-keyword">int</span> $vida = <span class="hljs-number">42</span>; <span class="hljs-comment">// erro</span>
}
</code></pre>
<p>Mesmo que não seja permitido <strong>alterar</strong> um dado, o <code>readonly</code> não impede <strong>mutação</strong>. Como você já sabe, <strong>objetos se tornam referências</strong> onde quer que você os atribua, seja em uma variável ou em uma propriedade.</p>
<p>Você não pode alterar de uma referência para outra, mas você pode alterar os valores dentro dessa referência:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> $vida = <span class="hljs-number">42</span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExemploReadonly</span>
</span>{
    <span class="hljs-keyword">public</span> readonly Exemplo $exemplo;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">Exemplo $exemplo</span>)
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;exemplo = $exemplo;
    }
}

$readonly = <span class="hljs-keyword">new</span> ExemploReadonly(<span class="hljs-keyword">new</span> Exemplo());
$readonly-&gt;exemplo-&gt;vida = <span class="hljs-number">43</span>; <span class="hljs-comment">// permitido</span>
var_dump($readonly-&gt;exemplo-&gt;vida);

<span class="hljs-comment">// não permitido:</span>
$readonly-&gt;exemplo = <span class="hljs-keyword">new</span> Exemplo();
</code></pre>
<p>Então muito cuidado com o que você deixa readonly... Se sua intenção era proteger o dado dentro do objeto de ser alterado, era para aquele dado ser <code>readonly</code> também.</p>
<h4 id="heading-122-declaracao-de-propriedades-via-construtor">1.2.2. Declaração de propriedades via construtor</h4>
<p>Se você já escreveu algumas classes em PHP, você já deve ter se deparado bastante com situações como essa:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $propriedade1 = <span class="hljs-string">"abc"</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $propriedade2 = <span class="hljs-number">123</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">array</span> $propriedade3 = [];
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">float</span> $propriedade4 = <span class="hljs-number">3.21</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> $propriedade1,
        <span class="hljs-keyword">int</span> $propriedade2,
        <span class="hljs-keyword">array</span> $propriedade3,
        <span class="hljs-keyword">float</span> $propriedade4
    </span>) </span>{
        <span class="hljs-keyword">$this</span>-&gt;propriedade1 = $propriedade1;
        <span class="hljs-keyword">$this</span>-&gt;propriedade2 = $propriedade2;
        <span class="hljs-keyword">$this</span>-&gt;propriedade3 = $propriedade3;
        <span class="hljs-keyword">$this</span>-&gt;propriedade4 = $propriedade4;
    }
}
</code></pre>
<p>Você não acha super redundante? Olha quantas vezes eu escrevi o mesmo nome só nesse trecho... E então, no PHP 8.0, trouxeram uma novidade que resolveu essa questão: declaração de propriedade em construtor.</p>
<p>Você só precisa incluir a visibilidade nos argumentos, então o interpretador sabe que precisa eleger aqueles argumentos como propriedades, ficando assim:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Exemplo</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $propriedade1 = <span class="hljs-string">"abc"</span>,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $propriedade2 = <span class="hljs-number">123</span>,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">array</span> $propriedade3 = [],
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">float</span> $propriedade4 = <span class="hljs-number">3.21</span>
    </span>) </span>{
    }
}
</code></pre>
<p>Bem mais simples, não?! Conseguiram unificar de uma vez só:</p>
<ol>
<li>necessidade de declarar propriedade;</li>
<li>necessidade de declarar argumento;</li>
<li>necessidade de atribuir o argumento à propriedade.</li>
</ol>
<p><strong>Magnífico</strong>.</p>
<center> <img src="https://media.giphy.com/media/l3q2XhfQ8oCkm1Ts4/giphy.gif" alt="Morgan Freeman batendo palmas" /> </center>

<p>E com isso, você já sabe tudo o que precisaria saber sobre declaração de propriedades, o que nos leva à próxima pergunta.</p>
<h2 id="heading-2-e-possivel-determinar-o-tipo-de-uma-propriedade-nessa-linguagem">2. É possível determinar o tipo de uma propriedade nessa linguagem?</h2>
<p>Eu já respondi isso ao explicar que, na declaração da propriedade, é possível informar qual tipo de dados primitivos é esperado. Isso é realmente opcional. Se por algum motivo você não sabe com qual tipo irá lidar, é possível não colocar nada.</p>
<p>Logo, a resposta para essa pergunta é <strong>sim, é possível</strong>.</p>
<h2 id="heading-3-essa-linguagem-possui-controle-de-visibilidade">3. Essa linguagem possui controle de visibilidade?</h2>
<p>Também respondi no momento em que mostrei em qual trecho da declaração nós determinamos a visibilidade da propriedade, confere? Nesse caso, <strong>informar a visibilidade</strong> também é opcional - exceto em declaração no construtor. Quando você não informa a visibilidade, o interpretador entende que é uma propriedade pública.</p>
<p>Mesmo que seja opcional, por favor, <strong>sempre determine qual a visibilidade desejada</strong>.</p>
<p>E a resposta para essa pergunta é <strong>sim, possui</strong>.</p>
<h2 id="heading-4-como-acesso-o-valor-de-uma-propriedade-de-um-objeto">4. Como acesso o valor de uma propriedade de um objeto?</h2>
<p>Lembra que mencionei o <strong>Operador de Objetos</strong>? Sinal de <strong>menos</strong> com sinal de <strong>maior que</strong>, <code>-&gt;</code>. Esse operador serve para requisitar qualquer coisa de um objeto, incluindo uma propriedade. Se você escrever <code>$objeto-&gt;nomeDaPropriedade</code>, irá <strong>ler</strong> o dado da propriedade <code>nomeDaPropriedade</code>, se ela existir.</p>
<p>Veja um exemplo mais claro:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span> <span class="hljs-comment">// PHP 8.1</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Tomada</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> readonly <span class="hljs-keyword">string</span> $corrente = <span class="hljs-string">'220v'</span>
    </span>) </span>{ }
}

$tomada220 = <span class="hljs-keyword">new</span> Tomada();
$tomada110 = <span class="hljs-keyword">new</span> Tomada(corrente: <span class="hljs-string">'110v'</span>); <span class="hljs-comment">// named arguments, do PHP 8.0</span>

<span class="hljs-comment">// quanto é a corrente da tomada 220?</span>
var_dump($tomada220-&gt;corrente); <span class="hljs-comment">// string(220v)</span>

<span class="hljs-comment">// quanto é a corrente da tomada 110v?</span>
var_dump($tomada110-&gt;corrente); <span class="hljs-comment">// string(110v)</span>
</code></pre>
<h2 id="heading-5-como-altero-o-valor-dessa-propriedade">5. Como altero o valor dessa propriedade?</h2>
<p>Usando o mesmo <strong>Operador de Objetos</strong> em conjunto com o <strong><a target="_blank" href="https://blog.kaiquegarcia.dev/php-para-iniciantes-operadores-de-atribuicao">Operador de Atribuição</a></strong>, é possível atribuir o valor a uma propriedade.</p>
<p>Basicamente, você só precisa acessar a propriedade que deseja atribuir um (novo) valor e colocar a atribuição que desejar. Por exemplo:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span> <span class="hljs-comment">// PHP 8.0</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Porta</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> $status
    </span>) </span>{ }
}

<span class="hljs-keyword">const</span> ABERTA = <span class="hljs-string">'aberta'</span>;
<span class="hljs-keyword">const</span> FECHADA = <span class="hljs-string">'fechada'</span>;

$porta = <span class="hljs-keyword">new</span> Porta(status: FECHADA);
<span class="hljs-comment">// acessando:</span>
var_dump($porta-&gt;status); <span class="hljs-comment">// string(fechada)</span>

<span class="hljs-comment">// atribuindo:</span>
$porta-&gt;status = ABERTA;

<span class="hljs-comment">// confirmando, acessando novamente:</span>
var_dump($porta-&gt;status); <span class="hljs-comment">// string(aberta)</span>
</code></pre>
<p>Você pode usar qualquer expressão de atribuição, até aquelas atribuições mescladas com outros operadores:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Moeda</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> $centavos
    </span>) </span>{ }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saldo</span>(<span class="hljs-params"></span>): <span class="hljs-title">float</span>
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;centavos / <span class="hljs-number">100</span>;
    }
}

$cinquenta = <span class="hljs-keyword">new</span> Moeda(<span class="hljs-number">50</span>);
$vinteECinco = <span class="hljs-keyword">new</span> Moeda(<span class="hljs-number">25</span>);
$dez = <span class="hljs-keyword">new</span> Moeda(<span class="hljs-number">10</span>);
$cinco = <span class="hljs-keyword">new</span> Moeda(<span class="hljs-number">5</span>);

$carteira = <span class="hljs-keyword">new</span> Moeda(<span class="hljs-number">0.0</span>);
$carteira-&gt;centavos += $cinquenta-&gt;centavos; <span class="hljs-comment">// 50 centavos</span>
$carteira-&gt;centavos *= <span class="hljs-number">2</span>; <span class="hljs-comment">// 1 real</span>
$carteira-&gt;centavos -= $dez-&gt;centavos; <span class="hljs-comment">// 90 centavos</span>
$carteira-&gt;centavos += $cinco-&gt;centavos * <span class="hljs-number">2</span>; <span class="hljs-comment">// 1 real</span>
$carteira-&gt;centavos /= $cinco-&gt;centavos; <span class="hljs-comment">// 20 centavos</span>
$carteira-&gt;centavos += $cinco-&gt;centavos; <span class="hljs-comment">// 25 centavos</span>

var_dump($carteira-&gt;saldo()); <span class="hljs-comment">// float(0.25)</span>
</code></pre>
<p>Legal, né? Hehe...</p>
<p>E então zeramos as perguntas, o que nos leva ao fim desse artigo. Curtiu?! Comenta e compartilha! Qual foi o melhor exemplo desse artigo? Quando eu estava escrevendo o código da tomada, estava pensando em criar um método tipo <code>colocarODedo</code> que responderia se você vive ou morre baseado na voltagem dela, hahaha. Mas acho que iria fugir <strong>muito</strong> do tema, então deixei pra lá.</p>
<center> <img src="https://media.giphy.com/media/GqfISYS3VqkELxfm7X/giphy.gif" alt="Homem jogando papel amassado no lixo" /> </center>

<p>E me conta aí: como tá sendo o aprendizado? Tem algum assunto que você tem muita dificuldade e quer ler em um artigo dedicado? Manda aí!</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[PHP para Iniciantes: Classes e Objetos - O básico]]></title><description><![CDATA[Agora que eu já te passei uma boa visão sobre a importância de aprender isso, vamos começar a falar sobre como funcionam as classes e objetos no PHP. Mesmo especializando na linguagem, esse é um assunto grande e, por isso, faz sentido apresentarmos e...]]></description><link>https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-o-basico</link><guid isPermaLink="true">https://blog.kaiquegarcia.dev/php-para-iniciantes-classes-e-objetos-o-basico</guid><category><![CDATA[PHP]]></category><category><![CDATA[learning]]></category><category><![CDATA[learn coding]]></category><category><![CDATA[learn]]></category><dc:creator><![CDATA[Kaique Garcia]]></dc:creator><pubDate>Wed, 19 Jan 2022 00:26:58 GMT</pubDate><content:encoded><![CDATA[<p>Agora que eu já te passei uma boa visão sobre a importância de aprender isso, vamos começar a falar sobre como funcionam as classes e objetos no PHP. Mesmo especializando na linguagem, esse é um assunto grande e, por isso, faz sentido apresentarmos em partes.</p>
<p>É de senso comum chamar a primeira de "básico", mas as próximas não são "intermediário" nem "avançado", pois aqui é tudo assunto pra iniciante, né?</p>
<p>E o que nós chamamos de básico é bem simples:</p>
<ol>
<li><p>Como declarar uma classe;</p>
</li>
<li><p>O que é e como declarar <strong>propriedades</strong> ;</p>
</li>
<li><p>O que é e como declarar <strong>métodos</strong>.</p>
</li>
</ol>
<p>E tem muitas outras coisas pra gente falar e que muita gente chama de básico, mas eu acho que não é bem assim.</p>
<p>Se você der uma espiada na <a target="_blank" href="https://www.php.net/manual/pt_BR/language.oop5.basic.php">documentação oficial do PHP</a>, também verá a menção de outros recursos que eu já falei em outros artigos e não são tão relevantes assim, logo não irei mencionar. Se você começou a ler meu blog a partir desse artigo, estou me referindo às constantes pré-definidas e métodos mágicos. Recomendo a leitura!</p>
<blockquote>
<p>Ok, Kiko, eu já vi alguma dessas coisas básicas em outro artigo?</p>
</blockquote>
<p>Sim, <strong>quase tudo</strong>. Mas eu vou repetir esses pontos para te ajudar a reforçar sua base de conhecimento. Repetição é importante nesse processo, então... Vamos recapitular!</p>
<h2 id="heading-1-como-declarar-uma-classe">1. Como declarar uma classe</h2>
<p>A declaração de classe é similar a qualquer estrutura de controle que agrupa conjuntos de instruções, onde precedimos tudo com a palavra reservada <code>class</code>, atribuímos um nome e depois encapsulamos sua estrutura entre chaves (<code>{</code> e <code>}</code>), ficando:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NossaClasse</span>
</span>{
    <span class="hljs-comment">// conteúdo da classe</span>
}
</code></pre>
<p>Notou que eu escrevi a primeira letra da classe com letra maiúscula? Isso não é uma regra da linguagem, mas uma boa prática. As regras de escrita são as mesmas da escrita de variáveis:</p>
<ul>
<li><p>só começa com uma letra ou underline;</p>
</li>
<li><p>pode ter números.</p>
</li>
</ul>
<p>E o mais importante de tudo é que esse nome precisa fazer sentido quando você for acionar seus recursos. Por exemplo, faz sentido nomear uma classe que gerencia banco de dados de <code>Gerente</code>? Primeiro que o termo correto para o papel seria <code>Gerenciador</code>, segundo que o que o diferencia dos demais é o fato de ser sobre banco de dados. Então não faria sentido algum dar somente esse nome para a classe.</p>
<blockquote>
<p>Kiko, eu vi na internet algumas pessoas discutindo se era melhor escrever em inglês ou português... O que você acha?</p>
</blockquote>
<p>Eu não acho é nada, rs. Eu defendo que o time tem de definir em conjunto. Se você vai trabalhar sozinho, então reflita bastante sobre quais profissionais poderão trabalhar no seu código no futuro e vise fornecer um código legível para a maioria. Colocando isso em pauta e falando do meu contexto, acho que o inglês deixa o código mais fácil de ler, pois as palavras reservadas são escritas nesse idioma e o PHP foi feito para ter legibilidade semântica. O único lugar onde a mistura de idiomas consegue fazer sentido de algum jeito é nas músicas asiáticas (pode discordar, mas eu gosto de algumas que todos os versos são no idioma da banda e, de repente, vem uma frase em inglês hahaha).</p>
<p>De todo modo, não feche sua mente pensando "só se programa desse jeito", porque isso é uma mentira.</p>
<p>Dito isso, vamos mudar nosso exemplo para:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OurClass</span>
</span>{
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<h2 id="heading-2-o-que-e-e-como-declarar-propriedades-de-uma-classe">2. O que é e como declarar propriedades de uma classe</h2>
<p><strong>Propriedades</strong>, além de imóveis, também é um termo utilizado para referenciar <strong>aquilo que se apropria</strong>. Eu acho estupidamente vago, e você?</p>
<p>Mas quando estamos falando de Orientação a Objeto, propriedade é qualquer <strong>informação</strong> que um objeto pode conter. E por informação, nós estamos falando de tipos de dados primitivos.</p>
<p>Portanto, propriedade aqui é qualquer informação que você desejar atrelar à sua classe. Por exemplo, digamos que você quer construir a classe <code>Caderno</code>. Para fazer isso, você deve refletir: o que um caderno tem que poderia ser diferente dos outros?</p>
<ul>
<li><p>a. Marca?</p>
</li>
<li><p>b. Quantidade de páginas?</p>
</li>
<li><p>c. Quantidade de seções?</p>
</li>
<li><p>d. Quantidade de páginas por seção?</p>
</li>
<li><p>e. Quantidade de figurinhas?</p>
</li>
<li><p>f. Tema?</p>
</li>
</ul>
<p>Cada um desses pontos <strong>pode</strong> ser uma propriedade dessa nova classe. Eu digo <strong>pode</strong> porque alguma dessas questões podem ser relacionamentos também, o que seria um pouco mais complexo de explicar. Por agora, vamos apenas criar uma classe tendo isso tudo como propriedades:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Caderno</span>
</span>{
    <span class="hljs-keyword">public</span> $marca;
    <span class="hljs-keyword">public</span> $page_quantity;
    <span class="hljs-keyword">public</span> $section_quantity;
    <span class="hljs-keyword">public</span> $pages_per_section;
    <span class="hljs-keyword">public</span> $sticker_quantity;
    <span class="hljs-keyword">public</span> $theme;
}
</code></pre>
<blockquote>
<p>Ué, Kiko... Você criou variáveis dentro da classe?</p>
</blockquote>
<p>Basicamente. Isso é uma propriedade. Porém, a forma que coloquei é a pior possível, pois não estou especificando nada além do nome da propriedade e deixando tudo completamente visível. A forma ideal é colocarmos:</p>
<ul>
<li><p>o tipo de dados primitivos que aceitamos;</p>
</li>
<li><p>a visibilidade que precisamos.</p>
</li>
</ul>
<p>Supondo que essas propriedades sejam acessíveis de forma pública, podemos manter cada uma das declarações precedidas pela palavra reservada <code>public</code>. Isso significa que você poderá acessar e alterar a informação a partir de qualquer parte do código. Se você quer que seja acessível somente pela própria clase e outras que herdarem algo dela, então use a visibilidade <code>protected</code>. Se não houver nenhuma necessidade de ter isso acessível de fora da classe, use o <code>private</code>.</p>
<p>Sobre a tipagem, o que for texto será <code>string</code> e o que for quantidade será <code>int</code>.</p>
<p>Vamos reescrever a classe agora?</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Caderno</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $marca;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $page_quantity;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $section_quantity;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $pages_per_section;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $sticker_quantity;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $theme;
}
</code></pre>
<blockquote>
<p>Kiko, por que você deixou tudo <code>private</code>?</p>
</blockquote>
<p>Como eu não tenho nenhum uso fora da classe, ainda, convém deixar tudo assim mesmo. A menos que apareça uma real necessidade de modificar a visibilidade, aí sim nós mudamos.</p>
<p>Com isso, nós conseguimos definir propriedades à classe que queremos criar. Porém, temos alguns problemas aqui:</p>
<ol>
<li><p>Qual é o valor padrão de cada propriedade?</p>
</li>
<li><p>Como definir um valor inicial quando instanciarmos a classe?</p>
</li>
</ol>
<p>Bem, para determinar um valor padrão na sintaxe que estamos usando, basta chamar o operador de atribuição e colocar o tal valor:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Caderno</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $marca;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $page_quantity = <span class="hljs-number">125</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $section_quantity = <span class="hljs-number">5</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $pages_per_section = <span class="hljs-number">25</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $sticker_quantity = <span class="hljs-number">20</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $theme = <span class="hljs-string">"Abstrato"</span>;
}
</code></pre>
<p>É desnecessário comentar, mas, lembre que o dado padrão precisa respeitar a tipagem que você definiu.</p>
<p>E sobre atribuir os valores iniciais, para isso precisaremos escrever um método mágico usado no processo de construção de um objeto.</p>
<h2 id="heading-3-o-que-e-e-como-declarar-metodos">3. O que é e como declarar <strong>métodos</strong></h2>
<p>O método que veremos a seguir é chamado de <strong>Construtor</strong> e é acionado toda vez que você usar o operador <code>new</code> na sua classe (ex: <code>new Caderno()</code>), mesmo se você não defini-lo.</p>
<p>O nome desse método deve ser escrito dessa forma: <code>__construct</code>, ficando assim:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Caderno</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $marca;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $page_quantity = <span class="hljs-number">125</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $section_quantity = <span class="hljs-number">5</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $pages_per_section = <span class="hljs-number">25</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $sticker_quantity = <span class="hljs-number">20</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $theme = <span class="hljs-string">"Abstrato"</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"></span>)
    </span>{
    }
}
</code></pre>
<p>Note que esse método precisa ter a visibilidade <code>public</code>, por isso já a escrevi por padrão. Outros métodos poderiam ter a visibilidade que <strong>você precisar</strong>. Lembre de nunca dar liberdade demais a um método ou propriedade, use somente o que precisa.</p>
<p>E assim como funções, você pode passar argumentos de entrada e usa-los com as propriedades do novo objeto. Por exemplo:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Caderno</span>
</span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $marca;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $page_quantity = <span class="hljs-number">125</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $section_quantity = <span class="hljs-number">5</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $pages_per_section = <span class="hljs-number">25</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $sticker_quantity = <span class="hljs-number">20</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $theme = <span class="hljs-string">"Abstrato"</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> $marca,
        <span class="hljs-keyword">int</span> $page_quantity = <span class="hljs-number">125</span>,
        <span class="hljs-keyword">int</span> $section_quantity = <span class="hljs-number">5</span>,
        <span class="hljs-keyword">int</span> $pages_per_section = <span class="hljs-number">25</span>,
        <span class="hljs-keyword">int</span> $sticker_quantity = <span class="hljs-number">20</span>,
        <span class="hljs-keyword">string</span> $theme = <span class="hljs-string">"Abstrato"</span>
    </span>)
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;marca = $marca;
        <span class="hljs-keyword">$this</span>-&gt;page_quantity = $page_quantity;
        <span class="hljs-keyword">$this</span>-&gt;section_quantity = $section_quantity;
        <span class="hljs-keyword">$this</span>-&gt;pages_per_section = $pages_per_section;
        <span class="hljs-keyword">$this</span>-&gt;sticker_quantity = $sticker_quantity;
        <span class="hljs-keyword">$this</span>-&gt;theme = $theme;
    }
}
</code></pre>
<p>Notou que eu praticamente repeti toda a assinatura da classe? Bem, no PHP 8 fizeram uma parada muito legal que é a <strong>Definição de Propriedade via Constructor</strong> (tradução não-literal para <strong>constructor property promotion</strong>). Tudo isso que eu escrevi pode ser reescrito da seguinte forma no PHP 8:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Caderno</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $marca,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $page_quantity = <span class="hljs-number">125</span>,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $section_quantity = <span class="hljs-number">5</span>,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $pages_per_section = <span class="hljs-number">25</span>,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> $sticker_quantity = <span class="hljs-number">20</span>,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $theme = <span class="hljs-string">"Abstrato"</span>
    </span>)
    </span>{
    }
}
</code></pre>
<p>Com o termo de visibilidade escrito antes do argumento, o interpretador sabe que você quer transformar aquele argumento em uma propriedade da classe. No PHP 8.1 ainda veio a opção de <strong>somente leitura</strong>, isto é, propriedades que funcionam como a visibilidade <code>public</code> mas somente para acessar o dado. Se você tentar sobreescrever, não funcionará.</p>
<p>Enfim, com essa definição toda, você pode, finalmente, instanciar um objeto:</p>
<pre><code class="lang-php"><span class="hljs-comment">// PHP 8: Argumentos nomeados</span>
$caderno = <span class="hljs-keyword">new</span> Caderno(
    marca: <span class="hljs-string">"KG"</span>,
    page_quantity: <span class="hljs-number">60</span>,
    section_quantity: <span class="hljs-number">2</span>,
    pages_per_section: <span class="hljs-number">30</span>,
    sticker_quantity: <span class="hljs-number">0</span>,
    theme: <span class="hljs-string">"PHP is the best"</span>
);
</code></pre>
<p>Em caso de versões anteriores ao PHP, você não poderá indicar o que está populando, apenas seguir a ordem da assinatura dos métodos.</p>
<p>Achou complexo? Foi muita coisa de uma vez?! Bem, isso foi apenas o básico, aquele choque de realidade que sou obrigado a te passar... Mas com certeza iremos ver todos esses tópicos bem mais mastigados nos próximos artigos. Espero não demorar tanto quanto demorei pra lançar esse, hehe.</p>
<p>Curtiu?! Comenta e compartilha! Ainda não segue meu BlueSky? <a target="_blank" href="https://bsky.app/profile/kaiquegarcia.dev">Corre lá!</a>! E não deixa de avisar os amigos que o pai de gêmeas está de volta! ;P</p>
<p><strong>Inté!!</strong></p>
]]></content:encoded></item></channel></rss>