<?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: Vinicius Dias</title>
    <description>The latest articles on DEV Community by Vinicius Dias (@cviniciussdias).</description>
    <link>https://dev.to/cviniciussdias</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%2F364363%2F662e513c-cd0f-4c7b-98d1-bd52d9a7550f.jpeg</url>
      <title>DEV Community: Vinicius Dias</title>
      <link>https://dev.to/cviniciussdias</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cviniciussdias"/>
    <language>en</language>
    <item>
      <title>PHP assíncrono de forma nativa</title>
      <dc:creator>Vinicius Dias</dc:creator>
      <pubDate>Wed, 16 Sep 2020 12:42:21 +0000</pubDate>
      <link>https://dev.to/phpbrasil/php-assincrono-de-forma-nativa-1db1</link>
      <guid>https://dev.to/phpbrasil/php-assincrono-de-forma-nativa-1db1</guid>
      <description>&lt;p&gt;Realizar acesso a streams é uma tarefa relativamente comum para devs PHP. Seja lendo e escrevendo em arquivos, fazendo requisições HTTP, etc.&lt;/p&gt;

&lt;p&gt;Operações de I/O são custosas e levam algum tempo para executar. Quando temos diversas operações desse tipo, uma técnica que pode ajudar (e muito) na performance da aplicação é realizá-las de forma assíncrona.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acesso a streams
&lt;/h2&gt;

&lt;p&gt;Antes de falar sobre técnicas e funções que permitem a programação assíncrona, é importante saber como normalmente nós trabalhamos com I/O.&lt;/p&gt;

&lt;p&gt;Acesso a arquivos, requisições HTTP, sockets e muito mais pode ser feito através de &lt;a href="https://php.net/streams"&gt;streams&lt;/a&gt;. Um stream é basicamente um fluxo de dados, sendo que a origem desse fluxo pode variar (vide o início desse parágrafo). Quando utilizamos funções como &lt;code&gt;file_get_contents&lt;/code&gt;, &lt;code&gt;fopen&lt;/code&gt;, &lt;code&gt;fgets&lt;/code&gt;, e as demais, estamos trabalhando com streams do PHP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programação assíncrona
&lt;/h2&gt;

&lt;p&gt;Se você não está familiarizado com o termo "programação assíncrona", recomendo assistir este vídeo antes de continuar o artigo:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/zLfXPSeCkB8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Entendido o que é programação assíncrona, como podemos fazer acesso a streams de forma assíncrona utilizando PHP sem nenhuma extensão ou biblioteca externa? Será possível?&lt;/p&gt;

&lt;h2&gt;
  
  
  Eventos
&lt;/h2&gt;

&lt;p&gt;Programação orientada a eventos não é novidade e nós utilizamos muito na web. Para agir quando um botão for clicado, ou quando um texto for digitado em um &lt;code&gt;input&lt;/code&gt; nós utilizamos eventos no JavaScript. Eventos podem acontecer a qualquer momento então sua natureza é assíncrona. Mas será possível fazer algo parecido do lado do PHP?&lt;/p&gt;

&lt;p&gt;Antes de falar do PHP em si, acho válido citar que o sistema operacional já trabalha com chamadas assíncronas. Diversos eventos acontecem durante a execução do seu sistema, e há código reagindo a estes eventos o tempo todo. Utilizando PHP nós podemos acessar algumas dessas funcionalidades do sistema operacional&lt;/p&gt;

&lt;h3&gt;
  
  
  Função stream_select
&lt;/h3&gt;

&lt;p&gt;Uma função não muito comum para nós que trabalhamos com PHP é a &lt;a href="https://php.net/stream_select"&gt;stream_select&lt;/a&gt;. Essa função nos permite "observar" modificações que possam acontecer em streams. O probelma é que ela não é nada fácil de se entender, então vou tentar tornar este processo menos doloroso para você.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cenário
&lt;/h2&gt;

&lt;p&gt;Imagine que para executar uma tarefa nós precisemos ler 5 arquivos distintos e depois realizar algum processamento. Normalmente utilizando PHP nós poderíamos fazer algo como:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nv"&gt;$conteudoDoArquivo1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo1.txt'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$conteudoDoArquivo2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo2.txt'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$conteudoDoArquivo3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo3.txt'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$conteudoDoArquivo4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo4.txt'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$conteudoDoArquivo5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo5.txt'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Processar os 5 arquivos&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O problema nessa abordagem é óbvio: Antes de ler o &lt;code&gt;arquivo2.txt&lt;/code&gt; precisamos terminar de ler todo o conteúdo de &lt;code&gt;arquivo1.txt&lt;/code&gt;. Enquanto o computador espera, nós já poderíamos estar sendo os demais arquivos e os processando de forma individual.&lt;/p&gt;

&lt;p&gt;Quando temos uma operação de I/O (acesso a arquivos, rede, etc) sendo realizada de forma síncrona, o processador fica ocioso enquanto a operação não é executada. Ou seja, enquanto o arquivo estiver sendo carregado, o processador fica esperando, sem fazer nada. É exatamente isso que queremos evitar. Queremos garantir que ele continue trabalhando enquanto o arquivo não estiver pronto para leitura.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solução com assincronicidade
&lt;/h2&gt;

&lt;p&gt;Para resolver essa situação, podemos utilizar a função &lt;code&gt;stream_select&lt;/code&gt; que observa alterações no status de uma lista de streams, ou seja, quando algum dos arquivos estiver pronto para leitura, essa função nos avisará. E é interessante citar que a leitura não necessariamente vai acontecer em ordem. O sistema operacional pode abrir o &lt;code&gt;arquivo3.txt&lt;/code&gt; mais rápido do que o &lt;code&gt;arquivo1.txt&lt;/code&gt;, por exemplo. Neste cenário, vamos processá-lo logo, sem ficar esperando os arquivos anteriores.&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nv"&gt;$listaDeStreamsDeArquivos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo1.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo2.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo3.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo4.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo5.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$listaDeStreamsDeArquivos&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$streamDeArquivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;stream_set_blocking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$streamDeArquivo&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="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$streamsParaLer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$listaDeStreamsDeArquivos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$streamsComNovidades&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;stream_select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$streamsParaLer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$write&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$except&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$streamsComNovidades&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;echo&lt;/span&gt; &lt;span class="s1"&gt;'Erro inesperado'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;$streamsComNovidades&lt;/span&gt; &lt;span class="o"&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;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$streamsParaLer&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$indice&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$streamDeArquivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$conteudo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;stream_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$streamDeArquivo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// processa o conteúdo do arquivo&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;feof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$streamDeArquivo&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$streamDeArquivo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nb"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$listaDeStreamsDeArquivos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$indice&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;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;$listaDeStreamsDeArquivos&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explicação
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Preparação
&lt;/h4&gt;

&lt;p&gt;Como eu disse, não é muito fácil, então vamos por partes. Primeiro abrimos todos os arquivos que queremos ler com o &lt;code&gt;fopen&lt;/code&gt;. Até aí sem segredo. Depois, informamos com a função &lt;code&gt;stream_set_blocking&lt;/code&gt; que o recurso deve ser aberto em modo não-bloqueante - assim, o processo que acessa o arquivo não bloqueará a CPU por causar um estado de espera ao tentar acessar os arquivos.&lt;/p&gt;

&lt;p&gt;Nesse ponto, temos um array com 5 recursos abertos para podermos trabalhar com estes streams. Então analisando o este pedaço de código:&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="nv"&gt;$listaDeStreamsDeArquivos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo1.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo2.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo3.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo4.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'arquivo5.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$listaDeStreamsDeArquivos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Teríamos a seguinte saída:&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;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;span class="mi"&gt;0&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&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;Depois disso que começa a parte difícil. A chamada para a função &lt;code&gt;stream_select&lt;/code&gt; deve estar em um loop, porque pode acontecer de nem todos os streams estarem prontos para leitura logo de cara.&lt;/p&gt;

&lt;h4&gt;
  
  
  Parâmetros
&lt;/h4&gt;

&lt;p&gt;Segundo detalhe importante: os parâmetros. O 3 primeiros parâmetros dessa função são passados por referência. Por isso o segundo e terceiro são variáveis que nós nem tínhamos definido ainda. O primeiro parâmetro é a lista de streams que queremos observar para ler. O segundo é para escrita. Já o terceiro, menos comum, é para dados excepcionais que possuem maior prioridade. Os 2 últimos parâmetros são sobre timeout.&lt;/p&gt;

&lt;p&gt;O parâmetro passado como 1 indica o número de segundos que essa função deve esperar receber uma notificação de novidade nos streams até "desistir", ou seja, o timeout. Esse é o motivo pelo qual ela deve estar em um loop. Se esse tempo passar e nós não tivermos novidade, devemos tentar de novo depois. Caso algum (não necessariamente todos) stream esteja pronto antes desse 1 segundo, a função retornará. O último parâmetro, que informamos como 0, indica o tempo em microsegundos para timeout.&lt;/p&gt;

&lt;h4&gt;
  
  
  Retorno e leitura
&lt;/h4&gt;

&lt;p&gt;Agora vamos falar do retorno. Essa função retorna o número de streams que contém modificações. No nosso caso, vai informar quantos arquivos estão prontos para leitura. Porém em caso de erro essa função nos retorna o valor &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Além disso, os parâmetros que nós passamos podem ter sido modificados. Por isso eu realizo uma cópia da lista original de streams em &lt;code&gt;$arquivosParaLer = $listaDeArquivos;&lt;/code&gt;. Após o retorno da função, o parâmetro passado vai conter apenas os streams que possuem novidades, ou seja, no nosso caso, os arquivos que estão prontos para leitura.&lt;/p&gt;

&lt;p&gt;Para exemplificar, vamos supor que na primeira execução do loop todos os arquivos já estejam disponíveis. Nesse caso, analisando os valores das variáveis, podemos entender o que está acontecendo. Analisando então o valor de &lt;code&gt;$streamsComNovidades&lt;/code&gt;, teríamos &lt;code&gt;int(5)&lt;/code&gt; como resultado deste cenário.&lt;/p&gt;

&lt;p&gt;Já analisando ambos arrays de streams (&lt;code&gt;$listaDeStreamsDeArquivos&lt;/code&gt; e &lt;code&gt;$streamsParaLer&lt;/code&gt;), teríamos exatamente o mesmo resultado:&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;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;span class="mi"&gt;0&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;span class="mi"&gt;0&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&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;Agora caso na primeira execução tivéssemos apenas 3 dos 5 arquivos prontos, e analisássemos os 3 valores anteriores, teríamos ter algo como:&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="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$streamsComNovidades&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$listaDeStreamsDeArquivos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$streamsParaLer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;span class="mi"&gt;0&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&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;span class="mi"&gt;0&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&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;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&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;Onde, nesse caso, o segundo array exibido é o de &lt;code&gt;$streamsParaLer&lt;/code&gt;, e possui apenas os 3 arquivos prontos para leitura.&lt;/p&gt;

&lt;p&gt;Sendo assim, posso percorrer este array tendo a certeza de que há dados para ler e processar. Mas não há garantia de que todo o conteúdo do arquivo estará lá, por isso verifico se cheguei ao fim do arquivo com &lt;code&gt;feof&lt;/code&gt;. Para arquivos pequenos, via de regra, todo o conteúdo virá de uma vez só, mas não conte com isso e prepare seu código para ler até mesmo um único byte por vez.&lt;/p&gt;

&lt;p&gt;Após ler todo o arquivo, devemos fechá-lo. Mas um outro detalhe importante é que eu também o removo da lista original de streams que queremos ler. Faço isso para que caso seja necessária uma nova iteração no loop, ou seja, caso nem todos os arquivos tenham sido lidos, eu não tente ler novamente os arquivos que já foram lidos e fechados.&lt;/p&gt;

&lt;p&gt;Com isso temos nossa condição de saída do loop. Quando todos os arquivos tiverem sido removidos e minha lista estiver vazia, sei que processei todos os arquivos.&lt;/p&gt;

&lt;p&gt;PS.: A função &lt;code&gt;stream_set_blocking&lt;/code&gt; só surte efeito com arquivos e sockets. Os outros wrappers, com esta técnica, não podem ser lidos de forma assíncrona e não bloqueante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conceitos
&lt;/h2&gt;

&lt;p&gt;Esse código obviamente pode ser refatorado para torná-lo um pouco mais legível, mas acredito que a lógica por trás dele tenha ficado clara. Caso contrário, você pode usar a sessão de comentários dessa página para fazer perguntas.&lt;/p&gt;

&lt;p&gt;O que nós escrevemos de forma rudimentar aqui pode ser visto como uma implementação do que é conhecido como &lt;em&gt;Event Loop&lt;/em&gt;, ou loop de eventos. Você provavelmente já ouviu esse termo se estuda sobre a runtime Node.js.&lt;/p&gt;

&lt;p&gt;Claro que essa implementação não é completa ou otimizada, mas atende nosso propósito: ler arquivos conforme eles fiquem prontos para leitura. Dessa forma nós vamos pedir para que o sistema operacional prepare todos os arquivos para leitura de uma só vez.&lt;/p&gt;

&lt;p&gt;As vantagens nessa abordagem assíncrona são mais perceptíveis quando temos operações mais lentas como chamadas HTTP, por exemplo. Mas isso aumentaria a complexidade do código para este artigo.&lt;/p&gt;

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

&lt;p&gt;Claro que o PHP já possui ferramentas que realizam este trabalho de forma muito mais simples. ReactPHP com seu pacote de Streams é um ótimo exemplo.&lt;/p&gt;

&lt;p&gt;Mas seguindo o que citei no post sobre aprendizado, eu penso como &lt;a href="https://pt.wikipedia.org/wiki/Richard_Feynman"&gt;Richard Feynman&lt;/a&gt; (Nobel de física): "O que eu não consigo criar, eu não entendo". Então antes de utilizar uma ferramenta que realiza o trabalho para mim, eu gosto de saber como realizar este trabalho sem ela. Com isso, se algum problema acontecer com a biblioteca, por exemplo, eu vou estar mais preparado para resolvê-lo já que eu entendo um pouco melhor como as coisas funcionam.&lt;/p&gt;

&lt;p&gt;Além disso, se chamadas HTTP assíncronas com essa técnica é um assunto que te interessa, interaja com essa publicação para que eu produza um conteúdo sobre isso.&lt;/p&gt;

</description>
      <category>php</category>
      <category>async</category>
      <category>performance</category>
    </item>
    <item>
      <title>Princípios ou Ferramentas - O que estudar</title>
      <dc:creator>Vinicius Dias</dc:creator>
      <pubDate>Thu, 23 Apr 2020 20:44:23 +0000</pubDate>
      <link>https://dev.to/phprio/principios-ou-ferramentas-o-que-estudar-1364</link>
      <guid>https://dev.to/phprio/principios-ou-ferramentas-o-que-estudar-1364</guid>
      <description>&lt;h2&gt;
  
  
  O mundo de desenvolvimento
&lt;/h2&gt;

&lt;p&gt;Quando decidimos entrar para o mundo de desenvolvimento, sofremos um bombardeio de informações e novos termos.&lt;/p&gt;

&lt;p&gt;Linguagens, frameworks, bibliotecas, paradigmas, princípios, etc. Não é fácil saber que caminho seguir e o que estudar primeiro.&lt;/p&gt;

&lt;p&gt;Obviamente não existe alternativa certa ou errada, então nesse post eu vou somente expor minha opinião. Não tome o que for dito aqui como verdade, mas sim reflita e analise se faz sentido para você.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mercado de trabalho
&lt;/h2&gt;

&lt;p&gt;É inegável que para atuar no mercado de trabalho nós precisamos de muito mais conhecimento do que nos é passado inicialmente em qualquer livro, curso ou post de blog. Somente a experiência e vivência vai nos dar a bagagem necessária para resolver os problemas e gerar valor para os clientes.&lt;/p&gt;

&lt;p&gt;Mas isso não quer dizer que nós só devamos estudar o que o emprego atual nos pede. Pelo contrário. Se nós estudamos além do que nos é pedido, ou no caso do primeiro emprego, estudamos antes de algo nos ser cobrado, quando uma oportunidade ou problema surgir, as chances serão muito maiores de estarmos prontos.&lt;/p&gt;

&lt;p&gt;Além de solucionar os problemas ou aproveitar as oportunidades, estudar nos faz conhecer melhores formas de atingir estes objetos, nos dando vantagens competitivas sobre quem simplesmente "resolve o problema".&lt;/p&gt;

&lt;p&gt;Ok, até aqui só usei o termo "estudo", mas devemos estudar o que? Ferramentas específicas ou princípios genéricos que podem ser aplicados a várias ferramentas?&lt;/p&gt;

&lt;h2&gt;
  
  
  Linguagens, bibliotecas e frameworks
&lt;/h2&gt;

&lt;p&gt;Se você quer entrar para a área de desenvolvimento e acredita que seu trabalho vai ser escrever código, você está enganado(a). O nosso trabalho é solucionar problemas. Código é uma ferramenta, um meio para o fim. Linguagens de programação são apenas ferramentas para nós resolvermos determinados problemas. Frameworks e bibliotecas nada mais são do que ferramentas de "alto nível", que nós trazem alguma facilidades e alguns problemas genéricos já resolvidos.&lt;/p&gt;

&lt;p&gt;Ah, Vinicius, quer dizer que a escolha da linguagem de programação não é importante? Longe disso! A linguagem de programação é uma ferramenta muito importante para a solução do problema e existem linguagens diferentes para solucionar problemas diferentes. O ponto é: elas são ferramentas.&lt;/p&gt;

&lt;p&gt;Se nós tivermos isso em mente, acabamos deixando de lado aquele tipo de briga de "minha linguagem é melhor que a sua" ou "meu framework é melhor do que o seu". Discussões desse tipo são interessantes e até emocionantes (eu mesmo adoro falar mal de Laravel ;-p), mas nós não podemos nos cegar achando que realmente há uma ferramenta melhor do que outra e ponto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Não existe bala de prata&lt;/strong&gt; (solução pra qualquer problema)!&lt;/p&gt;

&lt;p&gt;Assim como cada linguagem resolve um problema, cada framework tem um propósito, uma identidade. Você vai acabar se identificando mais com um ou outro, mas não faça com que isso seja o foco de todo o seu estudo e trabalho. Conhecer muito bem a linguagem e o framework que você utiliza para trabalhar é importante, mas é o primeiro passo?&lt;/p&gt;

&lt;h2&gt;
  
  
  Paradigmas
&lt;/h2&gt;

&lt;p&gt;Como eu citei no último parágrafo, "cada linguagem resolve um problema", e cada linguagem faz isso de um jeito. Existem diversos paradigmas de programação, dentre eles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declarativos

&lt;ul&gt;
&lt;li&gt;Programação funcional&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Imperativos

&lt;ul&gt;
&lt;li&gt;Programação procedural&lt;/li&gt;
&lt;li&gt;Programação orientada a objetos&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Entender bem as vantagens e desvantagens de cada paradigma e as diferenças entre eles é crucial para aprender qualquer linguagem de programação. Diversas linguagens modernas são o que chamamos de "multi-paradigma", ou seja, nos permitem utilizar mais de um paradigma em nosso código, como procedural e Orientado a Objetos, funcional e Orientado a objetos, funcional e procedural, etc.&lt;/p&gt;

&lt;p&gt;Este post (em inglês) fala com bem mais de detalhes sobre os principais paradigmas de programação e alguns exemplos de linguagens:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/vplentinax" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F214333%2F2c277664-7e87-4565-bc6b-549c046cc14c.png" alt="vplentinax"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/vplentinax/classification-of-computer-languages-ii-2201" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Classification of computer languages (II)&lt;/h2&gt;
      &lt;h3&gt;Valentiina VP ・ Apr 13 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devlive&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Princípios
&lt;/h2&gt;

&lt;p&gt;Cada paradigma de programação (e suas respectivas linguagens suportadas) sugerem diversos princípios para que seu código seja de fácil manutenção, testável, legível, etc.&lt;/p&gt;

&lt;p&gt;Princípios muito comuns da programação orientada a objetos (paradigma que estudo mais a fundo) são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tell, don't ask;&lt;/li&gt;
&lt;li&gt;Least astonishment;&lt;/li&gt;
&lt;li&gt;*Fail fast;&lt;/li&gt;
&lt;li&gt;*Early return;&lt;/li&gt;
&lt;li&gt;SOLID (conjunto de princípios);&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;* Princípios também aplicáveis a outros paradigmas&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Estudar os princípios referentes ao paradigma que você escolher é fundamental para manter seu código saudável. Não aplicá-los pode dar a falsa impressão de que você está sendo mais produtivo(a), mas a longo prazo a verdade sempre surge e nós acabamos nos arrependendo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Padrões
&lt;/h2&gt;

&lt;p&gt;Tendo entendido o que são paradigmas e que cada um deles possui princípios, baseando-se nestes princípios surgem padrões. Os famosos &lt;em&gt;Padrões de Projeto&lt;/em&gt; são basicamente soluções padrões para problemas genéricos. São sugestões de como proceder em determinadas situações.&lt;/p&gt;

&lt;p&gt;Certos problemas são tão comuns de acontecer, que pessoas através dos anos já estudaram e discutiram muito sobre as melhores formas de resolvê-los.&lt;/p&gt;

&lt;p&gt;Alguns dos padrões mais famosos seguindos os princípios da programação orientada a objetos são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Padrões da "turma dos 4" (&lt;em&gt;Gang of Four "GoF"&lt;/em&gt;)

&lt;ul&gt;
&lt;li&gt;24 padrões (super famosos) separados em 3 categorias&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Object calisthenics

&lt;ul&gt;
&lt;li&gt;9 regras para exercitar em seus códigos&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Sugeridos pelo "desenvolvimento guiado a domínio" (&lt;em&gt;DDD&lt;/em&gt;)

&lt;ul&gt;
&lt;li&gt;Conhecidos como blocos de construção do &lt;em&gt;DDD&lt;/em&gt; como &lt;em&gt;Entity&lt;/em&gt;, &lt;em&gt;Value Object&lt;/em&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Como citado no início do capítulo, cada padrão visa resolver problemas bem comuns e genéricos, e devem ser aplicados quando fazem sentido. Os padrões exemplificados estão em níveis bem diferentes de sua aplicação e explicá-los individualmente é impossível através de um único post.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que estudar primeiro?
&lt;/h2&gt;

&lt;p&gt;Como foi dito lá no início, esse post é para que eu expressar &lt;strong&gt;minha opinião&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Na minha visão, devemos estudar o básico dos paradigmas de programação, entendendo qual problema cada um resolve e em que casos são usados. Após entendê-los, normalmente nos aprofundamos em 1 deles, mas existe um porém:&lt;br&gt;
Antes de aprender Orientação a Objetos, é importante conhecermos o paradigma procedural, visto que o primeiro surgiu para resolver determinados problemas do último.&lt;/p&gt;

&lt;p&gt;Para estudar um dos paradigmas, obviamente precisamos de uma linguagem de programação, então este estudo acontece em paralelo: Conhecemos uma linguagem enquanto conhecemos um paradigma.&lt;/p&gt;

&lt;p&gt;Após dominar razoavelmente bem os conceitos da linguagem e do paradigma em questão, podemos começar a estudar os princípios sugeridos, entendendo suas propostas, quais problemas resolvem, porque surgiram, etc.&lt;/p&gt;

&lt;p&gt;Estes princípios, normalmente nos levam naturalmente para o estudo de alguns padrões. O estudo de padrões já é um estudo mais avançado, porém muito recompensante.&lt;/p&gt;

&lt;p&gt;Se você tem um bom conhecimento de um paradigma (e consequentemente, uma linguagem), alguns de seus princípios e padrões, pode ser o momento de aprender a utilizar ferramentas que auxiliem no processo.&lt;/p&gt;

&lt;p&gt;Frameworks e bibliotecas são ferramentas que facilitam a resolução de problemas &lt;strong&gt;que você deveria saber resolver sem elas&lt;/strong&gt;. Richard Feynman, ganhador do Nobel de física, escreveu uma vez: “What I cannot create I do not understand”. Traduzindo: "O que eu não consigo criar eu não entendo".&lt;/p&gt;

&lt;p&gt;Então antes de utilizar um framework, sabia resolver o problema sem ele. Antes de utilizar uma biblioteca mais específica, saiba resolver o problema sem ela. Isso faz com que você consiga resolver um problema nas ferramentas, caso aconteça.&lt;/p&gt;

</description>
      <category>oop</category>
      <category>functional</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>Programação procedural orientada a classes - Parte 2</title>
      <dc:creator>Vinicius Dias</dc:creator>
      <pubDate>Thu, 16 Apr 2020 16:37:50 +0000</pubDate>
      <link>https://dev.to/phprio/programacao-procedural-orientada-a-classes-parte-2-ofg</link>
      <guid>https://dev.to/phprio/programacao-procedural-orientada-a-classes-parte-2-ofg</guid>
      <description>&lt;h2&gt;
  
  
  Design de código
&lt;/h2&gt;

&lt;p&gt;Uma vez eu ouvi uma frase mas não me lembro o autor: "Não existe código sem design. Existe código com design ruim". Inclusive adaptei esta frase para "arquitetura" na primeira parte desta publicação.&lt;/p&gt;

&lt;p&gt;Antes de falarmos sobre as péssimas decisões de design que tomamos, vamos falar sobre o que é design de código.&lt;/p&gt;

&lt;p&gt;Uma analogia interessante foi feita pelo &lt;a href="https://twitter.com/junior_grossi" rel="noopener noreferrer"&gt;Junior Grossi&lt;/a&gt; em um workshop maravilhoso de qualidade de código que fiz com ele. Foi mais ou menos assim (não com essas exatas palavras):&lt;/p&gt;

&lt;p&gt;"Podemos fazer uma analogia da arquitetura de software com a arquitetura de uma casa. Onde fica cada cômodo, como se encaixam juntos, etc. É uma visão de bem &lt;strong&gt;alto nível&lt;/strong&gt;. Já o design de código pode ser considerado análogo aos móveis de uma casa. É uma visão de mais &lt;strong&gt;baixo nível&lt;/strong&gt; sobre nossas decisões sobre o código".&lt;/p&gt;

&lt;p&gt;Então, basicamente (beem basicamente), arquitetura diz respeito a como você vai separar sua aplicação em camadas, por exemplo, onde cada camada pode ter sua responsabilidade bem definida. Já o design de código diz respeito a como você vai organizar suas classes e métodos em cada uma das camadas. Quais padrões você vai seguir, como cada classe vai se comportar sozinha ou em conjunto com suas respetivas dependências, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Escolhas corriqueiras
&lt;/h2&gt;

&lt;p&gt;Agora que já entendemos basicamente o que é Design de Código, vamos falar sobre escolhas que fazemos frequentemente e que talvez não sejam as mais interessantes sob a ótica da programação orientada a objetos, ou melhor, sob a ótica do design orientado a objetos.&lt;/p&gt;

&lt;p&gt;Como já foi discutido no post anterior, é muito comum termos um modelo anêmico: Classes que apenas possuem &lt;code&gt;getters&lt;/code&gt; e &lt;code&gt;setters&lt;/code&gt;, ou seja, meros sacos de dados. Para quem já estudou C sabe que no fundo isso não é uma classe, mas sim uma &lt;code&gt;struct&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O fato de termos modelos anêmicos onde classes que deveriam ser do nosso domínio na verdade acabam sem nenhuma regra de negócio, geralmente faz com que nós transfiramos essas regras para lugares "errados" (entre aspas porque quem sou eu pra dizer o que é certo ou errado?).&lt;/p&gt;

&lt;p&gt;Que lugares errados seriam esses?&lt;/p&gt;

&lt;h2&gt;
  
  
  Helpers ou Utils
&lt;/h2&gt;

&lt;p&gt;Quem nunca viu uma classe chamada &lt;code&gt;StringHelper&lt;/code&gt; ou &lt;code&gt;DateUtils&lt;/code&gt;? São classes que claramente estão perdidas em nosso sistema. O que seria, no mundo real, um(a) &lt;code&gt;StringHelper&lt;/code&gt;? Se não existe no mundo real, tem certeza que deveria existir no código?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Frc9OMWr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Frc9OMWr.jpg" alt="Reflitão"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse tipo de classe é uma herança clara da programação procedural em nosso código onde estamos separando o comportamento dos seus dados, quando a orientação a objetos tem todas as ferramentas necessárias para nós os juntarmos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Possível solução
&lt;/h3&gt;

&lt;p&gt;Se você possui uma classe &lt;code&gt;StringHelper&lt;/code&gt;, talvez ela esteja fazendo validações bem genéricas. Nesse caso, nada mais justo do que transformá-la em uma classe bem genérica, como &lt;code&gt;String&lt;/code&gt;. Nessa classe você pode ter comportamentos e verificações pertinentes a uma string em seu código.&lt;/p&gt;

&lt;p&gt;Mas na maioria das vezes as verificações nesse tipo de classe são específicas de regras de negócio. Ex.: Garantir que nome possua pelo menos 10 letras.&lt;/p&gt;

&lt;p&gt;Se é uma regra de negócio, deveria estar na classe de negócio. Talvez na classe &lt;code&gt;Pessoa&lt;/code&gt;. Talvez numa classe mais específica, como &lt;code&gt;Nome&lt;/code&gt;. Depende do seu sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Services inúteis
&lt;/h2&gt;

&lt;p&gt;O livro do Eric Evans sobre DDD é certamente uma obra que revolucionou o mundo do desenvolvimento. Eu particularmente ainda não o li, mas li obras inspiradas por este livro, então sei que: Neste livro foram definidos alguns conceitos sobre classes chamadas de &lt;code&gt;Services&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Uma das possíveis "categorias" desse tipo de classe é &lt;code&gt;Application Service&lt;/code&gt;. Este tipo de classe tem como propósito receber informações de fora do domínio do sistema (da web, linha de comando, etc) e orquestrar as chamadas a regras de domínio.&lt;/p&gt;

&lt;p&gt;Um exemplo clássico:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;UserRepository&lt;/span&gt; &lt;span class="nv"&gt;$repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;PasswordHasher&lt;/span&gt; &lt;span class="nv"&gt;$hasher&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;__cosntruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserRepository&lt;/span&gt; &lt;span class="nv"&gt;$repository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;PasswordHasher&lt;/span&gt; &lt;span class="nv"&gt;$hasher&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$repository&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="n"&gt;hasher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$hasher&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;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;AddUserDto&lt;/span&gt; &lt;span class="nv"&gt;$data&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="nv"&gt;$hashedPassword&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;hasher&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;password&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$dados&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nv"&gt;$hashedPassword&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="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&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;Há pontos de melhoria nesse código (sempre há), mas basicamente: Ele recebe os dados de algum mecanismo de entrega através de um DTO (objeto de transferência de dados, que serve basicamente para transferir dados entre camadas no sistema), e passa para o domínio que sabe cifrar a senha, armazenar o usuário no repositório, etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  Problema comum
&lt;/h3&gt;

&lt;p&gt;Essa definição de &lt;code&gt;Application Service&lt;/code&gt; em algum momento foi tomada por alguém como "Classe obrigatória para adicionar &lt;em&gt;indireção&lt;/em&gt; desnecessária no sistema".&lt;/p&gt;

&lt;p&gt;Na prática é muito comum vermos código onde um Controller chama um método de uma classe com &lt;code&gt;Service&lt;/code&gt; no nome, e esse método não faz nada além de chamar um método de outra classe. Essa chamada extra de um método é conhecida como indireção, de forma resumida.&lt;/p&gt;

&lt;p&gt;Algo parecido com isso:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;UserRepository&lt;/span&gt; &lt;span class="nv"&gt;$repository&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;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserRepository&lt;/span&gt; &lt;span class="nv"&gt;$repository&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$repository&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;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="nv"&gt;$user&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// todos os outros métodos públicos que também existem em UserRepository&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Agora me responda: O que ganhamos ao ter a classe &lt;code&gt;UserService&lt;/code&gt;? Ganhamos apenas mais indireções em nosso sistema. Mais um lugar que nossa IDE vai nos fazer passar até chegar no código que de fato executa algo.&lt;/p&gt;

&lt;p&gt;Além de parecerem ser classes conhecidas como &lt;em&gt;God classes&lt;/em&gt;, já que aparentam fazer tudo no sistema, são inúteis na prática.&lt;/p&gt;

&lt;p&gt;Esse é mais um exemplo de programação procedural sendo aplicada, onde temos apenas funções sem nenhum significado pro negócio agrupadas em uma classe que simplesmente chama outras funções.&lt;/p&gt;

&lt;p&gt;Outra característica de programação procedural nesse caso é que muito comumente temos métodos não tão relacionados na mesma classe &lt;code&gt;Service&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;É comum um &lt;code&gt;UserService&lt;/code&gt; ter um método com uma chamada para salvar um usuário e outro método para enviar um e-mail para ele. Responsabilidades que deveriam estar em classes separadas.&lt;/p&gt;

&lt;p&gt;No canal &lt;em&gt;Dev Eficiente&lt;/em&gt;, do Aberto Souza, tem um vídeo falando um pouco mais sobre o problema deste tipo de classe, mas sob uma outra ótica. Vale a pena conferir:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/szGb93_hXgI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;
&lt;h2&gt;
  
  
  Camada Model do MVC
&lt;/h2&gt;

&lt;p&gt;Um ponto que tem levantado bastante discussão em comunidades que participo é: O que é a camada &lt;em&gt;Model&lt;/em&gt; no MVC?&lt;/p&gt;

&lt;p&gt;Discutir sobre MVC é assunto pra outro post, mas o que tenho visto como consenso é: Camada que faz a persistência dos dados.&lt;/p&gt;

&lt;p&gt;E a regra de negócio? Uma galera tem colocado nos &lt;em&gt;Controllers&lt;/em&gt;. E aí? Se essa lógica precisar ser reaproveitada, como fazemos? Como chamamos um &lt;em&gt;Controller&lt;/em&gt; dentro de outro? Complicado, né?&lt;/p&gt;

&lt;p&gt;Em nossos &lt;em&gt;Controllers&lt;/em&gt; é muito comum ver aquele código super famoso da programação procedural cheio de IFs e verificações em tipos primitivos, sem nenhum significado para o negócio.&lt;/p&gt;
&lt;h3&gt;
  
  
  Padrões arquiteturais
&lt;/h3&gt;

&lt;p&gt;Para "resolver" esse problema, diversos padrões arquiteturais existem, e eu falei um pouquinho (bem pouquinho) sobre arquitetura nesse meu outro post: &lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/phprio" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F2161%2F6e8ee19b-64ab-461f-9517-0b9e26f93e0b.jpg" alt="PHP Rio"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F364363%2F662e513c-cd0f-4c7b-98d1-bd52d9a7550f.jpeg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/phprio/o-que-e-arquitetura-17ob" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;O que é arquitetura&lt;/h2&gt;
      &lt;h3&gt;Vinicius Dias for PHP Rio ・ Apr 10 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#php&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#architecture&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



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

&lt;p&gt;Por mais que a gente estude muito sobre ferramentas, frameworks, hypes e modinhas, os princípios da programação orientada a objetos mudam muito pouco e merecem MUITA atenção.&lt;/p&gt;

&lt;p&gt;Estude conceitos, princípios, padrões... Tudo isso vai poder ser aplicado naquele framework que foi lançado semana passada e você está doido pra usar pra fazer um CRUD. Acredite.&lt;/p&gt;

&lt;p&gt;Infelizmente eu ainda vejo muito código utilizando estas "técnicas" procedurais utilizando classes, e pessoas acreditando que isso é desenvolver utilizando a programação orientada a objetos.&lt;/p&gt;

&lt;p&gt;Você costuma ver código assim no seu dia a dia? Compartilha aqui nos comentários algum caso que você tenha visto recentemente.&lt;/p&gt;

</description>
      <category>php</category>
      <category>oop</category>
      <category>codequality</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Programação procedural orientada a classes</title>
      <dc:creator>Vinicius Dias</dc:creator>
      <pubDate>Mon, 13 Apr 2020 12:34:06 +0000</pubDate>
      <link>https://dev.to/phprio/programacao-procedural-orientada-a-classes-3i11</link>
      <guid>https://dev.to/phprio/programacao-procedural-orientada-a-classes-3i11</guid>
      <description>&lt;h2&gt;
  
  
  Farsa da programação Orientada a Objetos
&lt;/h2&gt;

&lt;p&gt;Acredito que todos concordamos que a programação Orientada a Objetos torna nosso código mais legível e permite arquiteturas mais interessantes do que a programação procedural, além de permitir recursos interessantes de reutilização de código.&lt;/p&gt;

&lt;p&gt;Partindo desse pressuposto, também acredito que seja intenção de qualquer pessoa que trabalhe com desenvolvimento aprender mais e mais as técnicas e boas práticas deste paradigma de programação.&lt;/p&gt;

&lt;p&gt;O problema acontece quando a gente vem de um aprendizado de programação procedural e tenta aplicar as mesmas técnicas fazendo uso de classes e objetos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo clássico
&lt;/h2&gt;

&lt;p&gt;Há um exemplo muito clássico de um código que claramente, embora utilize classes e objetos, é procedural:&lt;/p&gt;

&lt;h3&gt;
  
  
  Definição de uma classe
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pessoa&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$primeiroNome&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$ultimoNome&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nc"&gt;DateTimeInterface&lt;/span&gt; &lt;span class="nv"&gt;$dataNascimento&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;setPrimeiroNome&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;$primeiroNome&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;primeiroNome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$primeiroNome&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;getPrimeiroNome&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;primeiroNome&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;setUltimoNome&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;$ultimoNome&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ultimoNome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ultimoNome&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;getUltimoNome&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ultimoNome&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;setDataNascimento&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nc"&gt;DateTimeInterface&lt;/span&gt; &lt;span class="nv"&gt;$dataNascimento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;void&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="n"&gt;dataNascimento&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$dataNascimento&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;getDataNascimento&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nc"&gt;DateTimeInterface&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dataNascimento&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;h3&gt;
  
  
  Utilização dela
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$pessoa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pessoa&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$pessoa&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setPrimeiroNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Vinicius'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$pessoa&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setUltimoNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Dias'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$pessoa&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setDataNascimento&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nf"&gt;DateTimeImmutable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'1997-10-15'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// aceito presentes&lt;/span&gt;

&lt;span class="nv"&gt;$idade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$pessoa&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getDataNascimento&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;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nf"&gt;DateImmutable&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$pessoa&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getPrimeiroNome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$pessoa&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUltimoNome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; tem &lt;/span&gt;&lt;span class="nv"&gt;$idade&lt;/span&gt;&lt;span class="s2"&gt; anos"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problema
&lt;/h3&gt;

&lt;p&gt;Olhando esse simples exemplo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Você nota algum problema?&lt;/li&gt;
&lt;li&gt;Identifica semelhança com algum pedaço de código que você tenha escrito recentemente?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Depois de você refletir um pouco, vamos continuar.&lt;/p&gt;

&lt;p&gt;O código exemplificado utiliza uma classe &lt;code&gt;Pessoa&lt;/code&gt; e a partir desta classe, cria um objeto. Logo, está utilizando do paradigma de programação orientada a objetos, certo? Errado!&lt;/p&gt;

&lt;p&gt;Esse exemplo é claramente um código procedural que usa uma classe. Nada além disso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proposta
&lt;/h2&gt;

&lt;p&gt;Se você possui uma classe, os objetos gerados através dela devem ter seus comportamentos descritos (através de métodos) e não apenas fornecer os dados para realizar essas ações.&lt;/p&gt;

&lt;p&gt;O código anterior poderia ser escrito da seguinte forma para usar o paradigma Orientado a Objetos:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pessoa&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$primeiroNome&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$ultimoNome&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nc"&gt;DateTimeInterface&lt;/span&gt; &lt;span class="nv"&gt;$dataNascimento&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;__construct&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;$primeiroNome&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;$segundoNome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nc"&gt;DateTimeInterface&lt;/span&gt; &lt;span class="nv"&gt;$dataNascimento&lt;/span&gt;
    &lt;span class="p"&gt;)&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="n"&gt;primeiroNome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$primeiroNome&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="n"&gt;ultimoNome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ultimoNome&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="n"&gt;dataNascimento&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$dataNascimento&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;nomeCompleto&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&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;primeiroNome&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&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;ultimoNome&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&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;idade&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$hoje&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DateTimeImmutable&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dataNascimento&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$hoje&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;y&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;E assim poderíamos utilizar esta classe:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nv"&gt;$pessoa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pessoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Vinicius'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Dias'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nf"&gt;DateTimeImmutable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'1997-10-15'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$pessoa&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;nomeCompleto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; tem &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$pessoa&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;idade&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; anos."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Motivação da mudança
&lt;/h3&gt;

&lt;p&gt;Com essa simples modificação nós não temos mais instâncias inválidas, já que agora toda &lt;code&gt;Pessoa&lt;/code&gt; tem seu primeiro e último nome e sua data de nascimento. Antes, primeiro nós estávamos criando uma &lt;code&gt;Pessoa&lt;/code&gt; em um estado inconsistente, sem seus dados, para depois defini-los.&lt;/p&gt;

&lt;p&gt;Além disso, agora qualquer método que receba uma &lt;code&gt;Pessoa&lt;/code&gt; por parâmetro não precisa saber se nesse objeto o nome completo está separado em primeiro e segundo nome ou não. Não precisa saber como o cálculo da idade é feito.&lt;/p&gt;

&lt;p&gt;Caso a forma de apresentar o nome precise ser modificado (de "Vinicius Dias" para "Dias, Vinicius", por exemplo), podemos ir direto no ponto correto: O método &lt;code&gt;nomeCompleto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Embora seja um exemplo muito simples, ele mostra com clareza como normalmente escrevemos código acreditando estar utilizando a programação orientada a objetos.&lt;/p&gt;

&lt;p&gt;Caso você tenha algum outro exemplo desse tipo em mente, já tenha visto algum código procedural com classes assim, ou tenha alguma outra sugestão de melhoria pra esse exemplo, que tal compartilhar com a gente aqui nos comentários?&lt;/p&gt;

&lt;h2&gt;
  
  
  Princípios e padrões
&lt;/h2&gt;

&lt;p&gt;Para nos ajudar a utilizar de forma mais "correta" a orientação a objetos, existem diversos padrões e princípios. Uns mais simples como o &lt;a href="https://youtu.be/6mfX6863SAk"&gt;Tell, Don't ask&lt;/a&gt;, outros mais completos e complexos como os princípios SOLID.&lt;/p&gt;

&lt;p&gt;Todos os princípios merecem uma atenção especial, porém isso foge do escopo deste artigo, mas uma rápida busca te mostra uma imensidão de conteúdo a respeito.&lt;/p&gt;

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

&lt;p&gt;Muito frequentemente nós utilizamos o paradigma procedural em nosso código e só pelo fato de termos classes definidas no código, achamos que estamos utilizando a Orientação a Objetos.&lt;/p&gt;

&lt;p&gt;Este paradigma é muito mais do que apenas definir classes, atributos e métodos, logo, precisa de muito mais estudo do que apenas a leitura da documentação da sua linguagem favorita para aprender a sintaxe.&lt;/p&gt;

</description>
      <category>php</category>
      <category>oop</category>
      <category>codequality</category>
      <category>architecture</category>
    </item>
    <item>
      <title>O que é arquitetura</title>
      <dc:creator>Vinicius Dias</dc:creator>
      <pubDate>Fri, 10 Apr 2020 18:45:05 +0000</pubDate>
      <link>https://dev.to/phprio/o-que-e-arquitetura-17ob</link>
      <guid>https://dev.to/phprio/o-que-e-arquitetura-17ob</guid>
      <description>&lt;h2&gt;
  
  
  Problema
&lt;/h2&gt;

&lt;p&gt;Imagine que no momento da escrita desse artigo (ano de 2020) você esteja criando um sistema para a empresa que te contratou como desenvolvedor(a). Nesse sistema você pode utilizar todas as novas tecnologias, pode decidir como vai organizar o código, enfim, o sonho de qualquer pessoa que trabalha na área.&lt;/p&gt;

&lt;p&gt;Como você trabalha com PHP, escolhe o framework que está "na boca do povo": Laravel. Começa o desenvolvimento e rapidamente entrega uma primeira versão do projeto. A equipe de negócios está feliz com toda a velocidade de entrega e a equipe técnica está feliz de utilizar um framework da moda.&lt;/p&gt;

&lt;p&gt;Os anos se passam. No futuro, você precisa dar manutenção em um sistema que usa uma versão mega desatualizada do framework já que eles decidiram trocar a ferramenta que fazia o acesso ao banco de dados, e toda a regra de negócios da aplicação está em "models" do Eloquent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mundo real
&lt;/h2&gt;

&lt;p&gt;Parece irreal, né!?&lt;/p&gt;

&lt;p&gt;"Ah, mas o Laravel não vai deixar de usar o Eloquent. Não faz sentido esse exemplo"&lt;/p&gt;

&lt;p&gt;Bom, hoje eu trabalho em uma empresa que tem um software funcionando desde o PHP 3.&lt;/p&gt;

&lt;p&gt;Em algum momento da vida desse software, acharam uma boa ideia atrelar as regras de negócio a um projeto conhecido como Pear DB. Esse projeto hoje não recebe atualizações (apenas correções de segurança), além de nos deixar "amarrados" a sua filosofia de código, que difere do que temos nos mundos atuais de PSRs, Composer, etc.&lt;/p&gt;

&lt;p&gt;Resultado: O sistema evolui. Novas funcionalidades são adicionadas todo dia. A equipe de negócios continua recebendo suas demandas, mas como a forma de desenvolver não evoluiu junto com o conhecimento e ferramentas atuais, o prazo já não é o mesmo.&lt;/p&gt;

&lt;p&gt;Além disso, novos integrantes da equipe sofrem para entender todo o espaguete que o código virou. Caos!&lt;/p&gt;

&lt;h2&gt;
  
  
  Como poderia ter sido?
&lt;/h2&gt;

&lt;p&gt;Se os arquitetos desse sistema pudessem voltar no tempo, o que fariam, você pode se perguntar. Minha ideia aqui é levantar algumas opções.&lt;/p&gt;

&lt;p&gt;Em termos de código, entidades poderiam ter sido criadas sem nenhum conhecimento da infraestrutura que cuida da persistência. Se é utilizado Pear DB, PDO, Doctrine, Eloquent, uma API, um arquivo com os dados, tanto faz. A lógica de negócios estaria intacta.&lt;/p&gt;

&lt;p&gt;E para salvar no banco? Classes especializadas nessa tarefa, também conhecidas como repositórios, poderiam ter sido utilizadas. Essas classes saberiam lidar com as entidades e fazerem a tradução necessária para o sistema de persistência (usando SQL, por exemplo).&lt;/p&gt;

&lt;p&gt;E se a ferramenta usada fosse descontinuada? Bom, simples: Poderíamos criar uma &lt;code&gt;interface&lt;/code&gt; que define o que um repositório deve saber fazer. Quando o Pear DB deixasse de receber suporte, nossa classe &lt;code&gt;PearDbQuestionRepository&lt;/code&gt; (repositório de perguntas) poderia ser fácilmente substituída por uma classe &lt;code&gt;PdoQuestionRepository&lt;/code&gt;, ou até mesmo &lt;code&gt;DoctrineQuestionRepository&lt;/code&gt;. Isso não faria diferença para as regras de negócio, que precisavam de qualquer implementação da interface &lt;code&gt;QuestionRepository&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que isso tem a ver com arquitetura?
&lt;/h2&gt;

&lt;p&gt;— Essa solução proposta é perfeita?&lt;br&gt;
— Longe disso! Tem suas vantagens e desvantagens&lt;/p&gt;

&lt;p&gt;Decisões de como organizar nosso código de forma que ele continue "utilizável" após determinado período é o propósito mais simples de uma arquitetura.&lt;/p&gt;

&lt;p&gt;Arquitetura, segundo nosso querido Google, é: "arte e técnica de organizar espaços e criar ambientes para abrigar os diversos tipos de atividades humanas, visando tb. a determinada intenção plástica."&lt;/p&gt;

&lt;p&gt;Se trazemos isso para o mundo do desenvolvimento temos uma definição semelhante à seguinte: "A arquitetura de software de um sistema consiste na definição dos componentes de software, suas propriedades externas, e seus relacionamentos com outros softwares."&lt;/p&gt;

&lt;p&gt;Você pode encontrar inúmeras definições para esse termo, mas em sua essência, arquitetura de software nos ajuda a definir como organizar nosso código, torná-lo mais compreensível, manutenível a longo prazo, e separar a responsabilidades de domínio (regras de negócio) da infraestrutura (banco de dados, log, envio de e-mails, etc).&lt;/p&gt;

&lt;h2&gt;
  
  
  Padrões arquiteturais
&lt;/h2&gt;

&lt;p&gt;O exemplo que eu dei é bem raso e cita apenas um pequeno problema que uma arquitetura bem feita visa resolver. Para resolver diversos outros problemas, padrões arquiteturais surgiram ao longo do tempo.&lt;/p&gt;

&lt;p&gt;Você muito provavelmente conhece pelo menos um (nem que seja de nome), e aqui cito nomes de padrões arquiteturais bem famosos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MVC (o famoso Model-View-Controller)&lt;/li&gt;
&lt;li&gt;ADR (Action-Domain-Response, uma espécie de evolução do MVC para web)&lt;/li&gt;
&lt;li&gt;SOA (Arquitetura orientada a serviços)&lt;/li&gt;
&lt;li&gt;Clean Architecture (em português, Arquitetura Limpa)&lt;/li&gt;
&lt;li&gt;Hexagonal Architecture (em português, Arquitetura Hexagonal)&lt;/li&gt;
&lt;li&gt;Onion Architecture (em português, Arquitetura em Camadas (cebola))&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Citar especificidades de cada padrão e suas semelhanças / diferenças fogem do escopo desse post, mas é interessante conhecer e se adaptar com alguns nomes.&lt;/p&gt;

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

&lt;p&gt;Não existe sistema sem arquitetura, só sistema com arquitetura ruim. &lt;/p&gt;

&lt;p&gt;Mesmo que no desenvolvimento de um sistema você não siga nenhum padrão arquitetural, há decisões de arquitetura no código, e se mal feitas, essas decisões podem te assombrar por muito (MUITO) tempo.&lt;/p&gt;

</description>
      <category>php</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
