<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: André Santos Meireles</title>
    <description>The latest articles on DEV Community by André Santos Meireles (@andresmeireles).</description>
    <link>https://dev.to/andresmeireles</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F187574%2F0d563826-f915-4cda-a3f4-e70954988916.jpg</url>
      <title>DEV Community: André Santos Meireles</title>
      <link>https://dev.to/andresmeireles</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andresmeireles"/>
    <language>en</language>
    <item>
      <title>A importancia de fazer testes</title>
      <dc:creator>André Santos Meireles</dc:creator>
      <pubDate>Tue, 12 Mar 2024 00:57:55 +0000</pubDate>
      <link>https://dev.to/andresmeireles/a-importancia-de-fazer-testes-3m1p</link>
      <guid>https://dev.to/andresmeireles/a-importancia-de-fazer-testes-3m1p</guid>
      <description>&lt;p&gt;Em um sistema que estava desenvolvendo me deparei com a seguinte demanda, ler um arquivo csv e devolver seu primeiro resultado para analise, um arquivo csv podem vir com a primeira linha sendo um cabeçalho, logo essa linha deve ser ignorada e a segunda linha deve ser retornada ao invés da primeira.&lt;/p&gt;

&lt;p&gt;O codigo para essa tarefa é simples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getFirstContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;UploadedFile&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nv"&gt;$hasHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$openFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;openFile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$openFile&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$hasHeader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nv"&gt;$csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_getcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nv"&gt;$openFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;storeAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SAVE_DIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$csv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você pode ter notado o erro desta implementação, eu não. Após terminar de fazer esse código fui fazer os testes desta função. Escrevi testes com um caso onde o csv não teria um cabeçalho e o outro teria um cabeçalho, um teste deveria chamar a função &lt;code&gt;fgets&lt;/code&gt; uma vez e outro duas, eis o codigo do teste&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
     * @dataProvider cases
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testGetFistContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nv"&gt;$hasHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$fgets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$expected&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// arrange&lt;/span&gt;
        &lt;span class="nv"&gt;$splFileMock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMockBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SplFileObject&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setConstructorArgs&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'php://memory'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$splFileMock&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;exactly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fgets&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'fgets'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;willReturnOnConsecutiveCalls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$fgets&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UploadedFile&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;once&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'openFile'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;willReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$splFileMock&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;once&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'storeAs'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/tmp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'file.csv'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// act&lt;/span&gt;
        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getFirstContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$hasHeader&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// assert&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertIsArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertSame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;cases&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a,b,c'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a,b,c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c,b,a'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O primeiro teste rodou de forma correta e passou, o segundo caso, onde o cabeçalho existe e deve ser pulada não estava passando, justamente porque &lt;code&gt;$hasHeader&lt;/code&gt; nunca muda seu estado, logo quando for &lt;code&gt;true&lt;/code&gt;, sempre irá pular a linha e nunca lerá o csv, um erro simples, fácil de ser corrigido, porém com um alto potencial de quebrar sistemas, imagine o quando de processamento desnecessário um loop infinito irá gerar?&lt;/p&gt;

&lt;p&gt;Ao notar isso adicionei a uma linha de correção, um simples &lt;code&gt;$hasHeader = false&lt;/code&gt; e pronto, o teste passou.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$openFile&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$hasHeader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$hasHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nv"&gt;$csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_getcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testes são importantes para prevenir erros de falta de atenção, que podem ocorrer quando estamos com um prazo apertado ou no dia em que não estamos muito inspirados.&lt;/p&gt;

&lt;p&gt;Sempre teste seu código, até mais!&lt;/p&gt;

</description>
      <category>php</category>
      <category>testing</category>
      <category>tip</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Aprendizados após um projeto pessoal</title>
      <dc:creator>André Santos Meireles</dc:creator>
      <pubDate>Fri, 09 Feb 2024 09:34:34 +0000</pubDate>
      <link>https://dev.to/andresmeireles/aprendizados-apos-um-projeto-pessoal-4bnf</link>
      <guid>https://dev.to/andresmeireles/aprendizados-apos-um-projeto-pessoal-4bnf</guid>
      <description>&lt;p&gt;Recentemente, fiz como projeto pessoal, um clone do chatgpt, o &lt;a href="https://github.com/andresmeireles/dgpt" rel="noopener noreferrer"&gt;dgpt&lt;/a&gt;, foi um projeto bem divertido onde testei várias tecnologias emergentes e tive diversos tipos de satisfação usando essas tecnologias. Quero compartilhar alguns aprendizados e duvidas que tive.&lt;/p&gt;

&lt;h2&gt;
  
  
  IA
&lt;/h2&gt;

&lt;p&gt;Após mexer um pouco com IA entendi o buzz ao redor, é muito divertido testar modelos, treina-los, ve-los delirando entre outros. O ferramental delas é bom, dependendo da linguagem de programação escolhida haverá mais ou menos recursos, por exemplo javascript e go tem a biblioteca &lt;a href="https://www.langchain.com" rel="noopener noreferrer"&gt;langchain&lt;/a&gt;, em PHP, que foi a linguagem que escolhi existe um porte do langchain, que voce pode conferir &lt;a href="https://github.com/kambo-1st/langchain-php" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;, porém ele ainda é muito embrionário, quando comecei a brincar com ia com go usei bastante o langchain em conjunto com llama.cpp, mas como não consegui fazer funcionar no php busquei alternativas e encontrei o &lt;a href="https://ollama.ai" rel="noopener noreferrer"&gt;ollama&lt;/a&gt;, um serviço web onde vários tipos de modelos podem ser adicionados, esse serviço é escrito em go e é muito util para testar modelos, como no caso do meu projeto.&lt;/p&gt;

&lt;p&gt;Ao usa-lo vi a grande barreira para usar IA de modo "caseiro", elas necessitam de muitos recursos da maquina, os modelos tem cada vez mais parâmetros, logo são muito maiores, necessitam de bastante processamento e memória. Existem modelos menores, mas eles tendem a ser menos eficazes e mesmo modelos pequenos exigem bastante da maquina.&lt;/p&gt;

&lt;h1&gt;
  
  
  HTMX
&lt;/h1&gt;

&lt;p&gt;Num primeiro momento pensei em usar uma lib ou framework js como solid ou svelte ao outro para aprender, mas resolvi experimentar o "hyper" do htmx. O htmx é uma lib muito competente, pequena, performática, com conceitos muito interessantes, com ele fiz algumas tarefas que exigiram algumas linhas de JS em uma linha com alguns atributos em tags html, parecido em como fazia quando estava aprendendo e tudo que sabia usar era o &lt;strong&gt;GRANDIOSO&lt;/strong&gt; jqeury.&lt;/p&gt;

&lt;p&gt;Contudo no decorrer da experiencia percebi alguns engasgos que nao teria usando um lib ou framework js, como na parte do chat onde precisava adicionar vários dinamicamente alguns campos e me vi lutando contra o htmx ao invés de ser ajudado, coisa que quando lembro de ter aprendido svelte, react ou outro framework não lembro de ter acontecido, claro que com mais estudo e pratica esses pontos podem ser mitigados e eu perceba que o htmx é a panacea para o frontend, porem minha impressão atual é: ele é bom para coisas que exigem pouca interação, mas da feita que sua pagina precisa de mais interações ele começa a mostrar sua limitações.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mercure
&lt;/h1&gt;

&lt;p&gt;Quando fiz o projeto queria usar websockets para quando a mensagem fosse escrita, ele mandar a resposta de acordo com o que fosse recebendo ao invés de esperar a resposta ficar pronta e mandar tudo, ate porque por causa da limitação da minha maquina o processo terminava em timeout. Não queria usar nenhum serviço externo, então busquei alternativas em php, não achei nenhuma boa para rodar localmente, neste projeto usei o frankenphp e em sua documentação comenta que ele ja vem com um servidor Mercure &lt;a href="https://frankenphp.dev/docs/mercure/" rel="noopener noreferrer"&gt;embutido&lt;/a&gt; então fui ver do que se tratava.&lt;/p&gt;

&lt;p&gt;Mercure é um protocolo pensando em comunicação em tempo real, de alto nível, funciona por padrão nos browsers modernos. É fácil e simples de usar, tem uma performance incrível, com certeza é algo que utilizarei sempre que uma solução exija comunicação em tempo real. A única ressalva e que estudarei melhor como levantar um servidor mercure em um ambiente onde ele não é embutido pro padrão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frankenphp
&lt;/h2&gt;

&lt;p&gt;Em novembro foi lançado para produção um novo runtime php, o frankenphp, ele vem com um conceito muito legal que é o worker mode, onde após a inicialização o projeto php todo fica em memória, fazendo com que as requisições subsequentes nao tenham o overhead de carregar todas as libs e subir todos os processos, como aplicativos usando o php-fpm fazem, como 25 a 50% do response time do php é composto apenas do boot da aplicação isso de cara ja faz o php ficar bem mais rápido. Neste &lt;a href="https://www.youtube.com/watch?v=_IpouO-pVmc" rel="noopener noreferrer"&gt;video&lt;/a&gt; do Dias de dev a um benchmark que mostra bem o potencial do frankenphp em comparação com libs estabelecidas como o Swoole, no video fica claro que o benchmark não foi feito para comprar ambas, porem os números são bastante reveladores.&lt;/p&gt;

&lt;p&gt;Integrar o slim framework com o frankenphp foi simples, durante todo o desenvolvimento não usei o woker mode, pois quando em memória a aplicação so é alterada quando ela é terminada e levantada novamente. Mesmo sem usar o worker mode a aplicação ja é bastante responsivo por usar o caddy server, em worker mode ela também fica mais rápida, porem como a minha aplicação não exige muito processamento, por delegar o processamento para o olham, não da para notar aumentos dramáticos de performance, mas ha um perceptível aumento de performance.&lt;/p&gt;

&lt;p&gt;O PHP é sempre ótimo de trabalhar, é uma linguagem que sou apaixonado e ver seu progresso ano após ano é fantástico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Estudar novas tecnologias sempre é bom, mas as vezes pode ser algo tao distante da realidade do trabalho ou do que as vagas pedem que desanima as pessoas de fazerem. Tendo essa experiência aprimorei algumas habilidades e descobri coisas que podem se aplicar em projetos atuais como o ollama e o mercure. Recomendo a todos que tenham seus projetos de duas ou tres semanas para testar tecnologias novas e aprender novos conceitos.&lt;/p&gt;

</description>
      <category>learning</category>
    </item>
    <item>
      <title>Um modo facil de usar code standards no php</title>
      <dc:creator>André Santos Meireles</dc:creator>
      <pubDate>Sat, 08 Jan 2022 20:19:42 +0000</pubDate>
      <link>https://dev.to/andresmeireles/um-modo-facil-de-usar-code-standards-no-php-2786</link>
      <guid>https://dev.to/andresmeireles/um-modo-facil-de-usar-code-standards-no-php-2786</guid>
      <description>&lt;p&gt;O php é uma linguagem maravilhosa e muito popular, ela possui padrões que ajudam a escrever códigos de fácil manutenção e legíveis, exemplos desses padrões são as &lt;a href="https://www.php-fig.org/psr/" rel="noopener noreferrer"&gt;PSR's&lt;/a&gt; 1 e 12, que indicam &lt;strong&gt;padrões de estilo de código&lt;/strong&gt; ou &lt;strong&gt;coding standards&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Um modo de aplicar esses padrões é com o pacote &lt;a href="https://github.com/squizlabs/PHP_CodeSniffer" rel="noopener noreferrer"&gt;PHP_CodeSniffer&lt;/a&gt; que, de forma simplificada, lê nosso código e analisa se segue os padrões indicados nas PSR's ou nos padrões que definimos, essa ferramenta pode ser instalada de forma global ou por projeto com o &lt;em&gt;composer&lt;/em&gt;. Assim que instalado podemos utilizar o comando &lt;code&gt;phpcs caminho/para/arquivo&lt;/code&gt; se instalado globalmente ou &lt;code&gt;vendor/bin/phpcs caminho/para/arquivo&lt;/code&gt; quando instalado por projeto, isso irá listar que pontos do nosso código podem ser ajustados para seguir os padrões. Por mais que esse método exista ele não é prático, normalmente usamos esse pacote em conjunto com o &lt;em&gt;linter&lt;/em&gt; da nossa IDE ou editor de texto, o &lt;em&gt;phpstorm&lt;/em&gt; já vem com um &lt;em&gt;linter&lt;/em&gt; de &lt;em&gt;code standards&lt;/em&gt; embutido que precisa ser apenas configurado, o &lt;em&gt;visual studio code&lt;/em&gt; tem plugins para implementar essa função de &lt;em&gt;linter&lt;/em&gt; e outras ferramentas também tem plugins ou extensões que integram essa função. Isso pode ser aliado com outras ferramentas como &lt;a href="https://github.com/FriendsOfPHP/PHP-CS-Fixer" rel="noopener noreferrer"&gt;PHP-cs-fixer&lt;/a&gt; que irão ajustar o código automaticamente com um comando no terminal, atalho nos editores ou quando o arquivo for salvo, as possibilidades e integrações são inúmeras.&lt;/p&gt;

&lt;p&gt;Desde que aprendi sobre isso usei os plugins do &lt;em&gt;visual studio code&lt;/em&gt; (vscode), até ler post do blog do &lt;a href="https://tomasvotruba.com/blog/2019/06/24/do-you-use-php-codesniffer-and-php-cs-fixer-phpstorm-plugin-you-are-slow-and-expensive/" rel="noopener noreferrer"&gt;Tomas Votruba&lt;/a&gt; onde ele dizia que olhar as sugestões de padrões de código e concertar manualmente, por mais que fosse algo rápido, quando somando todas as vezes que repetimos essa ação, consumia um tempo razoável, mesmo quando eram concertadas de forma automática por atalhos ainda consumiam um tempo que não seria necessário, então sugeriu o uso de um pacote do &lt;em&gt;composer&lt;/em&gt; chamado &lt;a href="https://github.com/symplify/easy-coding-standard" rel="noopener noreferrer"&gt;easy coding standard&lt;/a&gt; que automatiza a correção de "erros" padrões de estilo de código. Esse pacote usa os pacotes &lt;code&gt;php_codesniffer&lt;/code&gt; e o &lt;code&gt;php-cs-fixer&lt;/code&gt; para executar suas ações.&lt;/p&gt;

&lt;p&gt;O processo é simples, após instalar o pacote com o comando &lt;code&gt;composer require symplify/easy-coding-standard --dev&lt;/code&gt;, você cria um arquivo chamado &lt;code&gt;ecs.php&lt;/code&gt; na raiz do projeto, adicionando nele os padrões que deseja irá seguir, após isso execute o comando &lt;code&gt;vendor/bin/ecs check caminho/do/arquivo/ou/diretório&lt;/code&gt; para checar os "erros" (não são erros de fato, apenas pontos a melhorar) de padrões e &lt;code&gt;vendor/bin/ecs check caminho/do/arquivo/ou/diretório --fix&lt;/code&gt; para concertar os "erros".&lt;/p&gt;

&lt;p&gt;Ao aplicar o fluxo que ele sugeriu, achei bem interessante e prático, principalmente para dev's que ainda estão aprendendo sobre essa padrões de estilo de código e ainda não entendem o uso das ferramentas. Até porque todo o processo fica resumido a um comando, mas nem tudo são flores.&lt;/p&gt;

&lt;p&gt;Além do setup que pode ser trabalhoso a princípio, rodar um comando é mais um processo durante o desenvolvimento que pode ser facilmente esquecido quando queremos terminar algo ou apenas subir as alterações do código para o github, então pensei, como poderia automatizar a já automatizada verificação e correção de padrões de estilo de código? Após um pouco de pesquisa encontrei a resposta da minha dúvida, &lt;em&gt;git hooks&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;Hooks são ações que podem ser configuradas entre as ações do git, por exemplo, um &lt;em&gt;hook pre-commit&lt;/em&gt; vai executar algo antes da ação &lt;em&gt;git commit&lt;/em&gt; ser executada, assim podemos adicionar um hook para verificar nosso código e ajustar os padrões. Para fazer isso dentro da pasta &lt;code&gt;.git&lt;/code&gt; do seu repositório adicione o arquivo um arquivo chamado &lt;code&gt;pre-commit&lt;/code&gt; com o conteúdo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# hook to fix style errors using ecs (easy coding standard)
# this hook is a pre-commit
# when using this script copy as pre-commit on folder .git/hook
# after copy give execution permission with "chmod +x pre-commit"

echo "start scan to find cs errors with ecs"    

ECS_BIN="./vendor/bin/ecs"    
HAS_ECS=false    

if [ -x $ECS_BIN ]; then    
 HAS_ECS=true    
fi    

if $HAS_ECS; then    
 echo "fix cs errors"    
 git status --porcelain | grep -e '^[AM]\(.*\).php$' | cut -c 3- | while read line; do    
   $ECS_BIN check "$line" --fix --quiet;    
   git add "$line";    
 done    
 echo "finish fixers"    
else    
 echo ""    
 echo "cannot run ecs please install in project"    
 echo ""    
 echo "   composer require symplify/easy-coding-standard --dev    "    
 echo ""    
fi 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como isso feito toda vez que o comando &lt;em&gt;git commit&lt;/em&gt; for executado ajustes nos arquivos editados serão feitos. Essa é uma ótima abordagem, porém contem um problema, o arquivo &lt;code&gt;pre-commit&lt;/code&gt; estará salvo apenas no repositório local e não será compartilhado com todos os outros que usam ou clonarem seu repositório. Isso pode ser contornado usando um pacote do composer chamado &lt;a href="https://github.com/BrainMaestro/composer-git-hooks" rel="noopener noreferrer"&gt;composer-git-hooks&lt;/a&gt; que facilita do gerenciamento de &lt;em&gt;git hooks&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Instruções da instalação do pacote estão no repositório do pacote, após a sua instalação em &lt;code&gt;extra&lt;/code&gt; do arquivo &lt;code&gt;composer.json&lt;/code&gt; o seguinte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"hooks": { 
            "pre-commit": [
                "echo committing as $(git config user.name)",
                "git status --porcelain | grep -e '^[AM]\\(.*\\).php$' | cut -c 3- | while read line; do vendor/bin/ecs check \"$line\" --fix --quiet; git add \"$line\"; done"
            ]
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso esse hook será adicionado automaticamente no repositório, mesmo quando for clonado por outro desenvolvedor(a).&lt;/p&gt;

&lt;p&gt;Acho que é algo conveniente a ser feito, porque todos que forem interagir com o projeto, versados ou não com estilos de código, no final obedecerão o estilo de código que foi definido e se forem necessárias alterações no estilo de código do projeto elas serão feitas em um ponto central e serão refletidas para todos que trabalham no projeto.&lt;/p&gt;

&lt;p&gt;Obrigado por ter chegado até aqui, compartilhe como você lida com padrões de estilo de código. Se quiser, deixe as dúvidas nos comentários que farei meu melhor para responder, bem como sugestões ou criticas, estou linkedin como &lt;a href="https://www.linkedin.com/in/andresmeireles/" rel="noopener noreferrer"&gt;andresmeireles&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>php</category>
      <category>codequality</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
