<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://blog.augustopascutti.com/atom.xml" rel="self" type="application/atom+xml" /><link href="http://blog.augustopascutti.com/" rel="alternate" type="text/html" /><updated>2025-04-01T14:57:35-03:00</updated><id>http://blog.augustopascutti.com/atom.xml</id><title type="html">/dev/null</title><subtitle>Algumas coisas acabam aqui...</subtitle><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><entry><title type="html">AWK Your Way Parsing Logs</title><link href="http://blog.augustopascutti.com/2025/03/02/awk-your-way-parsing-logs/" rel="alternate" type="text/html" title="AWK Your Way Parsing Logs" /><published>2025-03-02T00:00:00-03:00</published><updated>2025-03-02T00:00:00-03:00</updated><id>http://blog.augustopascutti.com/2025/03/02/awk-your-way--parsing-logs</id><content type="html" xml:base="http://blog.augustopascutti.com/2025/03/02/awk-your-way-parsing-logs/"><![CDATA[<p>It is a <a href="https://gist.github.com/augustohp/029f20ec3dd97377666cf8ed1e5361e7">common</a> <a href="https://github.com/misaku/QuakeLogParser/blob/master/DOC/DESAFIO.md">challenge</a> for <em>technical interviews</em> to parse Quake 3 
server logs and display:</p>

<ol>
  <li>Players in a match</li>
  <li>Player score card, listing player names and kill count:
    <ol>
      <li>Ignore <code class="language-plaintext highlighter-rouge">&lt;world&gt;</code> as a <em>player</em></li>
      <li>If <code class="language-plaintext highlighter-rouge">&lt;world&gt;</code> kills a <em>player</em>, add <code class="language-plaintext highlighter-rouge">-1</code> to <em>player</em>’s kill count</li>
    </ol>
  </li>
  <li>(optional) Group <em>outputs</em> above by <em>match</em></li>
  <li>(optional) Death cause report by <em>match</em></li>
</ol>

<p>Working with files is a common practice for any developer. Using <a href="https://www.gnu.org/software/gawk/manual/gawk.html">awk</a> not so 
much, even though it is IMHO one of the best tools for doing so:</p>

<ul>
  <li>The language is built for (1) text matching and (2) manipulation.</li>
  <li>Working with small files is as easy as it is working with very large files.</li>
</ul>

<p>Intending to spread the knowledge of the <a href="https://www.gnu.org/software/gawk/manual/gawk.html">tool</a> to more people, let’s solve 
the challenge with <a href="https://www.gnu.org/software/gawk/manual/gawk.html">AWK</a> and get to know how you can effectively start using it 
today in your workflow. I assume you know well a programming language, your way 
around a (*nix) CLI and that we are using <a href="https://www.gnu.org/software/gawk/manual/gawk.html">GNU awk</a>.</p>

<h2 id="the-beginning-of-a-not-so-usual-program">The beginning of a not so usual program</h2>

<p>As it is common with other Unix tools, it is better to break the program into 
smaller pieces, <a href="https://www.gnu.org/software/gawk/manual/gawk.html">Awk</a> programs <a href="https://www.gnu.org/software/gawk/manual/html_node/When.html#:~:text=If%20you%20find%20yourself%20writing%20awk%20scripts%20of%20more%20than%2C%20say%2C%20a%20few%20hundred%20lines%2C%20you%20might%20consider%20using%20a%20different%20programming%20language.">bigger than ~150 lines are difficult to 
maintain</a>. 
Here are the different programs we are going to create:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">clean.awk</code> will read <em>input</em> files, which are the original <a href="https://gist.githubusercontent.com/cloudwalk-tests/be1b636e58abff14088c8b5309f575d8/raw/df6ef4a9c0b326ce3760233ef24ae8bfa8e33940/qgames.log">log</a> files, 
and <em>output</em> a cleaner version of their content. 
Containing just the data we need to manipulate and use.</li>
  <li><code class="language-plaintext highlighter-rouge">scoreboard.awk</code> will use the <em>output</em> from the previous <em>program</em> to produce 
the score boards for each game.</li>
</ol>

<p>Let’s create a <em>walking skeleton</em> to run and debug our progress while tackling 
the challenge:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">mkdir</span> /tmp/awk-quake
<span class="nv">$ </span><span class="nb">cd</span> <span class="o">!</span><span class="err">$</span>
<span class="nv">$ </span>curl <span class="nt">--remote-name</span> <span class="nt">-L</span> https://gist.githubusercontent.com/cloudwalk-tests/be1b636e58abff14088c8b5309f575d8/raw/df6ef4a9c0b326ce3760233ef24ae8bfa8e33940/qgames.log
<span class="nv">$ </span><span class="nb">tail </span>qgames.log
 13:55 Kill: 3 4 6: Oootsimo killed Dono da Bola by MOD_ROCKET
 13:55 Exit: Fraglimit hit.
 13:55 score: 20  ping: 8  client: 3 Oootsimo
 13:55 score: 19  ping: 14  client: 6 Zeh
 13:55 score: 17  ping: 1  client: 2 Isgalamido
 13:55 score: 13  ping: 0  client: 5 Assasinu Credi
 13:55 score: 10  ping: 8  client: 4 Dono da Bola
 13:55 score: 6  ping: 19  client: 7 Mal
 14:11 ShutdownGame:
 14:11 <span class="nt">------------------------------------------------------------</span>
<span class="nv">$ </span><span class="nb">cat </span>clean.awk
<span class="o">{</span> print <span class="o">}</span>
<span class="nv">$ </span>watch gawk <span class="nt">-f</span> parse.awk qgames.log
</code></pre></div></div>

<p>Above we:</p>

<ol>
  <li>Downloaded <code class="language-plaintext highlighter-rouge">qgames.log</code></li>
  <li>Created <code class="language-plaintext highlighter-rouge">clean.awk</code> that prints everything passed to it</li>
  <li>Executed the program every couple of seconds (with <code class="language-plaintext highlighter-rouge">watch</code>) to see its result 
while we change it in another session (to stop <code class="language-plaintext highlighter-rouge">watch</code>, use <kbd>CTRL-C</kbd>)</li>
</ol>

<p>Let’s change <code class="language-plaintext highlighter-rouge">clean.awk</code> to filter just the lines useful to us, and help us debug 
what to do with them:</p>

<div class="language-awk highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">BEGIN</span> <span class="p">{</span>
    <span class="kc">FS</span> <span class="o">=</span> <span class="s2">" "</span>
    <span class="nx">LFS</span> <span class="o">=</span> <span class="s2">"\n"</span>
<span class="p">}</span>
<span class="sr">/Init/</span> <span class="p">{</span> <span class="k">print</span> <span class="p">}</span>
<span class="sr">/kill/</span> <span class="p">{</span> <span class="nx">debug_fields</span><span class="p">()</span> <span class="p">}</span>

<span class="kd">function</span> <span class="nx">debug_fields</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;=</span> <span class="kc">NF</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">printf</span><span class="p">(</span><span class="s2">"%d: %s\n"</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nv">$i</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Don’t despair yet, it is pretty simple what we are doing:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">BEGIN</code> is a <em>special block</em>, that gets executed <strong>once</strong> at the start 
of the parsing:
    <ol>
      <li>We use it to (re-)define some <em>special variables</em>:
        <ol>
          <li><code class="language-plaintext highlighter-rouge">FS</code> defines the <strong>field separator</strong> (space). It is used to break 
a <em>matching line</em> into a smaller array of objects.</li>
          <li><code class="language-plaintext highlighter-rouge">LFS</code> defines the <strong>line separator</strong> (new line). Everything until 
that character will be treated as a <em>line</em>.</li>
        </ol>
      </li>
    </ol>
  </li>
  <li><code class="language-plaintext highlighter-rouge">/match/ { action }</code> blocks execute a set of <code class="language-plaintext highlighter-rouge">actions</code> when a <code class="language-plaintext highlighter-rouge">match</code> (regex supported) is found:
    <ol>
      <li><code class="language-plaintext highlighter-rouge">/Init/ { print }</code> prints every line that has <code class="language-plaintext highlighter-rouge">Init</code> on it, without doing anything more.</li>
      <li><code class="language-plaintext highlighter-rouge">/kill/ { debug_fields() }</code> executes the <code class="language-plaintext highlighter-rouge">debug_fields()</code> function for every line that has a matching <code class="language-plaintext highlighter-rouge">kill</code> string on it.</li>
      <li>Every line that doesn’t match the rules above is ignored.</li>
    </ol>
  </li>
  <li><code class="language-plaintext highlighter-rouge">function debug_fields()</code> prints all fields identified after breaking the <em>line</em> with <code class="language-plaintext highlighter-rouge">FS</code>:
    <ol>
      <li><code class="language-plaintext highlighter-rouge">NF</code> is a <em>special variable</em> containing the <em>number of fields</em> parsed for the current line.</li>
      <li>
        <p><code class="language-plaintext highlighter-rouge">$n</code> is the <em>field</em> <code class="language-plaintext highlighter-rouge">n</code> parsed. Inside the <em>loop</em> <code class="language-plaintext highlighter-rouge">$i</code> will become <code class="language-plaintext highlighter-rouge">$1</code>, 
<code class="language-plaintext highlighter-rouge">$2</code> and <code class="language-plaintext highlighter-rouge">$3</code> allowing us to retrieve the contents of every field on that 
line, displaying something like:</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 1: 20:54                                     
 2: Kill:
 3: 1022
 4: 2
 5: 22:
 6: &lt;world&gt;
 7: killed
 8: Isgalamido
 9: by
 10: MOD_TRIGGER_HURT
</code></pre></div>        </div>
      </li>
      <li>The <em>output</em> above is useful to debug the current line contents we can work with. 
Try changing <code class="language-plaintext highlighter-rouge">debug_fields()</code> <em>action</em> to <code class="language-plaintext highlighter-rouge">print $6 " killed " $8</code>.</li>
    </ol>
  </li>
</ol>

<p>With little changes, we can use <code class="language-plaintext highlighter-rouge">$6</code> (killer) and <code class="language-plaintext highlighter-rouge">$8</code> (killed) to display who 
killed who, which is pretty much everything we need.</p>

<p>🐛 If player names would not contain spaces we’d be ready. But <code class="language-plaintext highlighter-rouge">Assassinu Credi</code>, for example, 
breaks our algorithm because we use <em>spaces</em> to separate fields. 
When he kills someone <code class="language-plaintext highlighter-rouge">$8</code> will <code class="language-plaintext highlighter-rouge">killed</code> instead of the other player name.</p>

<p>Let’s see this happening:</p>

<div class="language-awk highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">BEGIN</span> <span class="p">{</span>
    <span class="kc">FS</span> <span class="o">=</span> <span class="s2">" "</span>
    <span class="nx">LFS</span> <span class="o">=</span> <span class="s2">"\n"</span>
<span class="p">}</span>
<span class="sr">/Init/</span> <span class="p">{</span> <span class="k">next</span> <span class="p">}</span>
<span class="sr">/Assas/</span> <span class="p">{</span> <span class="k">print</span> <span class="nv">$6</span> <span class="s2">" killed "</span> <span class="nv">$8</span> <span class="p">}</span>
</code></pre></div></div>

<p>The program above ignores (with <code class="language-plaintext highlighter-rouge">next</code> action) lines matching <code class="language-plaintext highlighter-rouge">Init</code> and prints 
just lines matching <code class="language-plaintext highlighter-rouge">Assas</code>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">awk</span> <span class="nt">-f</span> clean.awk qgames.log
Zeh killed Assasinu
&lt;world&gt; killed Assasinu
Isgalamido killed Assasinu
Zeh killed Assasinu
Assasinu killed killed
</code></pre></div></div>

<p>Note that <code class="language-plaintext highlighter-rouge">Assasinu killed killed</code> line is wrong. It doesn’t have the name of 
the <em>killed</em> player. Let’s fix this!</p>

<h2 id="making-things-more-reliable-with-regex">Making things more reliable with regex</h2>

<p>The end <code class="language-plaintext highlighter-rouge">clean.awk</code> program is below. It <em>substitutes</em> some strings by <code class="language-plaintext highlighter-rouge">nfs</code> 
(new file separator) variable and removes the prefix on lines that notifies 
of a kill:</p>

<div class="language-awk highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">BEGIN</span> <span class="p">{</span>
    <span class="kc">FS</span> <span class="o">=</span> <span class="s2">" "</span>
    <span class="nx">LFS</span> <span class="o">=</span> <span class="s2">"\n"</span>
    <span class="nx">nfs</span> <span class="o">=</span> <span class="s2">"|"</span>
    <span class="nx">current_game</span> <span class="o">=</span> <span class="mi">0</span>
<span class="p">}</span>
<span class="sr">/Init/</span> <span class="p">{</span> <span class="nx">current_game</span><span class="o">++</span> <span class="p">}</span>
<span class="sr">/kill/</span> <span class="p">{</span>
    <span class="nb">sub</span><span class="p">(</span><span class="sr">/^</span><span class="se">[</span><span class="sr"> 0-9:</span><span class="se">]</span><span class="sr">+ Kill: </span><span class="se">[</span><span class="sr">0-9: </span><span class="se">]</span><span class="sr">+/</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="nv">$0</span><span class="p">)</span>
    <span class="nb">sub</span><span class="p">(</span><span class="sr">/ killed /</span><span class="p">,</span> <span class="nx">nfs</span><span class="p">,</span> <span class="nv">$0</span><span class="p">)</span>
    <span class="nb">sub</span><span class="p">(</span><span class="sr">/ by /</span><span class="p">,</span> <span class="nx">nfs</span><span class="p">,</span> <span class="nv">$0</span><span class="p">)</span>
    <span class="k">print</span> <span class="nv">$0</span> <span class="nx">nfs</span> <span class="nx">current_game</span>
<span class="p">}</span>
</code></pre></div></div>

<ol>
  <li>On the <code class="language-plaintext highlighter-rouge">BEGIN</code> section, declares 2 new variables:
    <ol>
      <li><code class="language-plaintext highlighter-rouge">nfs</code> to separate output by something other than spaces, so next programs 
 easily support player names with them.</li>
      <li><code class="language-plaintext highlighter-rouge">current_game</code> is a variable that gets incremented every time a new game starts.</li>
    </ol>
  </li>
  <li><code class="language-plaintext highlighter-rouge">/Init/</code> marks a new game:
    <ol>
      <li>Increments the variable <code class="language-plaintext highlighter-rouge">current_game</code> for the next time it gets used</li>
    </ol>
  </li>
  <li>For every <code class="language-plaintext highlighter-rouge">/kill/</code>:
    <ol>
      <li><code class="language-plaintext highlighter-rouge">sub(regex, replacement, target)</code> will put <code class="language-plaintext highlighter-rouge">replacement</code> into every matching 
<code class="language-plaintext highlighter-rouge">regex</code> on <code class="language-plaintext highlighter-rouge">target</code>, replacing <code class="language-plaintext highlighter-rouge">target</code>. <code class="language-plaintext highlighter-rouge">$0</code> is the whole current line.</li>
      <li><code class="language-plaintext highlighter-rouge">sub(/^[ ...</code> removes the prefix of the line until the player name.</li>
      <li><code class="language-plaintext highlighter-rouge">sub(/ by...</code> and <code class="language-plaintext highlighter-rouge">sub(/ killed...</code> replaces these matches by <code class="language-plaintext highlighter-rouge">nfs</code> (the 
 new field separator), allowing us to easily identify (<code class="language-plaintext highlighter-rouge">$1</code>) the killer, 
 (<code class="language-plaintext highlighter-rouge">$2</code>) who got killed and (<code class="language-plaintext highlighter-rouge">$3</code>) how he got killed.</li>
      <li><code class="language-plaintext highlighter-rouge">print</code> will print the current line (<code class="language-plaintext highlighter-rouge">$0</code>) with the <em>current game</em> as a suffix:
        <ul>
          <li>As every <code class="language-plaintext highlighter-rouge">sub()</code> replaces the current line (<code class="language-plaintext highlighter-rouge">$0</code>), we now have only 
what we needed.</li>
          <li>As <a href="https://www.gnu.org/software/gawk/manual/gawk.html">awk</a> programs operate on lines, it is easier to have everything 
we need on them. That is why we add <em>current game</em> to every line.</li>
        </ul>
      </li>
    </ol>
  </li>
</ol>

<p>Executing the program above, produces:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">awk</span> <span class="nt">-f</span> clean.awk qgames.log | <span class="nb">tee </span>qgames-clean.log
&lt;world&gt;|Isgalamido|MOD_TRIGGER_HURT|2
&lt;world&gt;|Isgalamido|MOD_TRIGGER_HURT|2
&lt;world&gt;|Isgalamido|MOD_TRIGGER_HURT|2
Isgalamido|Mocinha|MOD_ROCKET_SPLASH|2
Isgalamido|Isgalamido|MOD_ROCKET_SPLASH|2
Isgalamido|Isgalamido|MOD_ROCKET_SPLASH|2
&lt;world&gt;|Isgalamido|MOD_TRIGGER_HURT|2
&lt;world&gt;|Isgalamido|MOD_TRIGGER_HURT|2
&lt;world&gt;|Isgalamido|MOD_TRIGGER_HURT|2
&lt;world&gt;|Isgalamido|MOD_FALLING|2
&lt;world&gt;|Isgalamido|MOD_TRIGGER_HURT|2
Isgalamido|Mocinha|MOD_ROCKET|3
&lt;world&gt;|Zeh|MOD_TRIGGER_HURT|3
</code></pre></div></div>

<p>With the <code class="language-plaintext highlighter-rouge">qgames-clean.log</code> file we can now easily achieve every objective of 
the original challenge without having to deal with:</p>

<ul>
  <li>Unneeded context.</li>
  <li>Space separators. With <code class="language-plaintext highlighter-rouge">FS = "|"</code> we use <code class="language-plaintext highlighter-rouge">|</code> as <em>field separator</em> and have:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">$1</code> as the killer</li>
      <li><code class="language-plaintext highlighter-rouge">$2</code> who got killed</li>
      <li><code class="language-plaintext highlighter-rouge">$3</code> how <em>killer</em> killed <em>killed</em></li>
      <li><code class="language-plaintext highlighter-rouge">$4</code> in which game that happened</li>
    </ul>
  </li>
  <li>A “checkpoint”. If the log changes format, or we discover a bug, as long we 
produce an <em>output</em> conforming the current format we are good to use the next 
programs.</li>
</ul>

<h2 id="next-steps">Next steps</h2>

<p>How about you try to figure out the rest? I will post my solution and, if you 
learned something from this, I promise you will learn something else on the next 
one as well.</p>

<p>The <a href="https://www.gnu.org/software/gawk/manual/gawk.html">Gnu awk’s manual</a> is <strong>really</strong> good - from a time technical documents 
were worth reading. You don’t need to read everything, the <em>index</em> will take you 
where you need. Pinky promise!</p>

<p>I won’t leave you without anything though, here is a beginning for <code class="language-plaintext highlighter-rouge">scoreboard.awk</code>:</p>

<div class="language-awk highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">BEGIN</span> <span class="p">{</span>
    <span class="kc">FS</span> <span class="o">=</span> <span class="s2">"|"</span>   
<span class="p">}</span>
<span class="p">{</span>
    <span class="c1"># Sets a player as a key in the players array</span>
    <span class="nx">players</span><span class="p">[</span><span class="nv">$1</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$1</span>
    <span class="nx">players</span><span class="p">[</span><span class="nv">$2</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$2</span>
<span class="p">}</span>
<span class="kr">END</span> <span class="p">{</span>
    <span class="c1"># Removes &lt;world&gt; from players</span>
    <span class="k">for</span> <span class="p">(</span><span class="nx">name</span> <span class="o">in</span> <span class="nx">players</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">name</span> <span class="o">==</span> <span class="s2">"&lt;world&gt;"</span><span class="p">)</span>
            <span class="k">continue</span>
        <span class="k">print</span> <span class="nx">name</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Let me know of your solution, suggestions or doubts in the comments! ❤️</p>

<!--
vim: spell spelllang=pt
-->]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="[&quot;Shell&quot;, &quot;AWK&quot;]" /><summary type="html"><![CDATA[Learn how to use AWK in practice! Let's parse Quake 3 logs to display players in a match, player score card, and death cause report.]]></summary></entry><entry><title type="html">Automatizando testes de software</title><link href="http://blog.augustopascutti.com/palestra/php/2018/09/19/automatizando-testes-com-phpunit.html" rel="alternate" type="text/html" title="Automatizando testes de software" /><published>2018-09-19T00:00:00-03:00</published><updated>2018-09-19T00:00:00-03:00</updated><id>http://blog.augustopascutti.com/palestra/php/2018/09/19/automatizando-testes-com-phpunit</id><content type="html" xml:base="http://blog.augustopascutti.com/palestra/php/2018/09/19/automatizando-testes-com-phpunit.html"><![CDATA[<p>O <a href="https://phpunit.de/">PHPUnit</a> é a ferramenta <a href="https://packagist.org/search/?tags=testing">padrão de testes no PHP</a>, e após várias
tentativas anteriores de como explicar <em>testes automatizados em 50 minutos</em>
chegamos a essa iteração da tentativa, que:</p>

<ol>
  <li>Explica como criar sua própria ferramenta de testes</li>
  <li>Como testar uma aplicação existente</li>
  <li>Como transportar nossos testes para o PHPUnit</li>
</ol>

<p>Meu objetivo com essa estrutura é mostrar que você já sabe testar. Minha
hipótese é que mostrando como automatizar um teste sem nenhuma ferramenta fica
mais fácil entender como usar o PHPUnit.</p>

<h2 id="você-já-sabe-testar">Você já sabe testar</h2>

<p>Automatizar testes não é tão óbvio quando pode parecer e é bem difícil escrever
<em>bons testes</em> - justiça seja feita que é difícil até definir o que é um <em>bom
teste</em>. A receita pra isso é tentar, falhar e aprender com isso. Levei mais de 5
anos pra me sentir confortável com o conceito.</p>

<p>Você sempre checa se o que você fez funciona ou não, isso é testar. É normal
escutar pessoas dizendo que “não sabem testar” quando na verdade elas querem
dizer que não sabem fazer isso de forma automática. A exemplo o teste abaixo:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ echo "Hello World!"
Hello World!
</code></pre></div></div>

<p>O <em>output</em> é exatamente o esperado então o teste é um sucesso! Falhas podem
acontecer de diversas formas:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ echp "Hello World!"
-bash: echp: command not found
</code></pre></div></div>

<p>O <em>output</em> do comando acima é uma falha, por exemplo. Se você que automatizar
seus testes precisa aprender que eles possuem basicamente duas condições:
<strong>sucesso</strong> ou <strong>falha</strong>.</p>

<h3 id="automatizando-nossa-primeira-verificação">Automatizando nossa primeira verificação</h3>

<p><em>Automatizar</em> significa criar um programa que faça essa verificação sozinho pra
nós e nos diga se tudo deu certo ou não. Daí vem a primeira confusão:</p>

<ol>
  <li>Uma <strong>verificação</strong> (<em>assertion</em>) pode ter <em>sucesso</em> ou <em>falha</em></li>
  <li>Um <strong>teste</strong> pode ter <em>sucesso</em> ou <em>falha</em></li>
</ol>

<p>Um <em>teste</em> pode ser composto por várias <em>verificações</em> e se uma <em>verificação</em>
falha o teste falha como consequência. Para automatizar o um teste precisamos
saber quais verificações podemos ou iremos fazer, seguindo o exemplo anterior
podemos verificar:</p>

<ol>
  <li>O <em>output</em> é igual ao esperado?</li>
  <li>O comando sendo executado existe?</li>
  <li>O comando é executado com sucesso?</li>
</ol>

<p>A mim, a lista de <em>verificações</em> passíveis de automatização são uma das tarefas
mais difíceis e que nenhum <em>framework de teste unitário irá fazer por você</em>.
Implementar todas as <em>verificações</em> é uma excelente ideia mas com o tempo você
nota que existe um ideal e o ideal agora é só verificar se o <em>comando é
executado com sucesso</em>.</p>

<p>Toda <em>shell</em>, ao executar um comando, popula a variável <code class="language-plaintext highlighter-rouge">$?</code> com <code class="language-plaintext highlighter-rouge">0</code> (zero) caso
sucesso e é nesse comportamento que vamos verificar todo nosso comportamento:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ echo "a"
a
$ echo $?
0
$ echp "a"
-bash: echp: command not found
$ echo $?
127
</code></pre></div></div>

<p>Sabendo o que precisamos <em>verificar</em>, podemos escrever nosso <em>teste</em>. Ele será
um programa <em>shell</em> que terminará com <code class="language-plaintext highlighter-rouge">0</code> (zero) no caso de sucesso além de
imprimir “ok”.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env sh</span>

<span class="c"># 1. Executa o comando</span>
<span class="c"># O `&gt; /dev/null` faz com que o output do comando não seja exibido</span>
<span class="nb">echo</span> <span class="s2">"Hello World!"</span> <span class="o">&gt;</span> /dev/null
<span class="c"># 2. Verificamos a saida</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$?</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"0"</span> <span class="o">]</span>
<span class="k">then</span>
    <span class="c"># 3. Imprime sucesso</span>
    <span class="nb">echo</span> <span class="s2">"Ok"</span>
    <span class="c"># 4. Sai com status 0 (zero) de sucesso</span>
    <span class="nb">exit </span>0
<span class="k">else</span>
    <span class="c"># 3. Imprime erro</span>
    <span class="nb">echo</span> <span class="s2">"Error"</span>
    <span class="c"># 4. Sai com status 1 (um) de erro</span>
    <span class="nb">exit </span>1
<span class="k">fi</span>
</code></pre></div></div>

<p>Toda vez que executarmos o programa acima, ele fará a <em>verificação</em> de forma
automática. Apesar do programa acima não parecer muito útil, ele é a estratégia
que todas as ferramentas de <em>Integração Contínua</em> usam: verificar o <a href="https://en.wikipedia.org/wiki/Exit_status#POSIX"><em>exit code</em>
de um comando</a>. Apesar dele não parecer muito útil, você aprendeu uma lição
fundamental para fazer seu próprio sistema de <em>integração contínua</em>.</p>

<h3 id="automatizando-a-execução-das-verificações">Automatizando a execução das verificações</h3>

<p>É aqui que a maioria dos frameworks de teste entram. Apesar deles já possuírem
diversas ferramentas que auxiliam na <em>verificação</em>, o que eles inicialmente
provêm é uma <em>forma de organizar suas verificações</em> e de <em>executar elas</em>.</p>

<p>O <a href="https://phpunit.de/">PHPUnit</a>, por exemplo, trata todas as classes com sufixo <code class="language-plaintext highlighter-rouge">Test</code> e que
herdam <code class="language-plaintext highlighter-rouge">PHPUnit\Framework\TestCase</code> como uma suíte (conjunto) de testes e todo
método com o prefixo <code class="language-plaintext highlighter-rouge">test</code> como um teste. Se nós quisermos algo semelhante,
precisamos:</p>

<ol>
  <li>Definir uma <em>estrutura</em> padrão de teste</li>
  <li><em>Executar</em> todos os testes que seguem essa estrutura</li>
  <li>Produzir um <em>relatório</em> dos testes</li>
</ol>

<p>A <em>estrutura</em> que nossos testes terão é simples e eficiente, e não muito
diferente do que várias ferramentas oferecem:</p>

<ol>
  <li>Todo teste deve estar dentro do diretório <code class="language-plaintext highlighter-rouge">test</code></li>
  <li>Um teste por arquivo, o nome do arquivo é o nome do teste</li>
  <li>O teste não deve imprimir nada</li>
  <li>O <a href="https://en.wikipedia.org/wiki/Exit_status#POSIX">exit code</a> do teste é o resultado dele</li>
</ol>

<p>Agora precisamos de um programa para <em>executar todos os testes</em>. Esse programa,
assim como nossa <em>verificação automatizada</em> e nossos testes, irá terminar com
<a href="https://en.wikipedia.org/wiki/Exit_status#POSIX">exit code</a> 0 (zero) em caso de sucesso.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ls tests/*.sh
tests/hello.sh
</code></pre></div></div>

<p>O <code class="language-plaintext highlighter-rouge">ls</code> acima irá listar todos os arquivos <code class="language-plaintext highlighter-rouge">.sh</code> dentro do diretório <code class="language-plaintext highlighter-rouge">tests</code>,
podemos usar a saída desse comando em um <code class="language-plaintext highlighter-rouge">for</code> que será executado para cada item
encontrado:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env</span>

<span class="c"># 1. Busca todos os testes existentes</span>
<span class="k">for </span><span class="nb">test </span><span class="k">in</span> <span class="si">$(</span><span class="nb">ls </span>tests/<span class="k">*</span>.sh<span class="si">)</span>
<span class="k">do</span>
    <span class="c"># 2. Garante que o teste possa ser executado</span>
    <span class="nb">chmod </span>a+x <span class="s2">"</span><span class="k">${</span><span class="nv">test</span><span class="k">}</span><span class="s2">"</span>
    <span class="c"># 3. Executa o teste</span>
    <span class="nv">$test</span> <span class="o">&gt;</span> /dev/null
    <span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$?</span><span class="s2">"</span> <span class="o">!=</span> <span class="s2">"0"</span> <span class="o">]</span>
    <span class="k">then</span>
        <span class="c"># 4. Saída com status 1 (um) de erro</span>
        <span class="nb">exit </span>1
    <span class="k">fi
done</span>
<span class="c"># 4. Saída com status 0 (zero) de sucesso</span>
<span class="nb">exit </span>0
</code></pre></div></div>

<p>Agora não importa quantos testes tenhamos no diretório <code class="language-plaintext highlighter-rouge">tests</code>, sempre que
executarmos o programa acima vamos ter o resultado de sucesso caso todas as
nossas <em>verificações</em> passem.</p>

<p>Falta fazer a parte de <em>relatório</em>, mas acho que você já pegou as manhas do que
estamos fazendo. Existem padrões de relatório de testes automatizados:</p>

<ul>
  <li><a href="https://en.wikipedia.org/wiki/XUnit#Test_result_formatter">xUnit</a> é um formato em XML que costuma ser o padrão aceito</li>
  <li><a href="https://testanything.org/">TAP</a> é um formato mais verboso e mais apropriado para humanos</li>
  <li><a href="https://en.wikipedia.org/wiki/TestDox">TestDox</a> é um padrão para nome de testes que é usado como relatório também</li>
</ul>

<p>Esses formatos padrão de relatório de execução são importantes só para
integração com outras ferramentas, que normalmente são ferramentas de
<a href="https://www.martinfowler.com/articles/continuousIntegration.html">Integração Contínua</a>.</p>

<h2 id="para-onde-continuar">Para onde continuar?</h2>

<p>Existe <a href="https://www.eventials.com/locaweb/automatizando-testes-com-phpunit-com-augusto-pascutti/">um vídeo deu apresentando essa ideia e como usar o PHPUnit para
automatizar seus testes</a> que vai um pouco além do escrevi aqui.</p>

<p>Recomendo alguns livros também:</p>

<ul>
  <li><a href="https://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627">GOOS</a>: Cria um software usando TDD num passo-a-passo bem fácil de entender</li>
  <li><a href="https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530">TDD</a>: Descreve a técnica de criar testes automatizados antes da
implementação e como isso pode melhorar sua vida</li>
</ul>

<p>Se você quiser qualquer dica, ou tiver alguma crítica ou sugestão, dê um toque!
Se eu puder der uma dica a você que nunca fez um <em>teste automatizado</em> ela é a de
começar logo. Além da curva de aprendizado natural, leva um tempo aprender que
nem todo código é automaticamente testável e mais tempo ainda em como fazer isso
e os livros acima ajudam bastante a reduzir esse tempo.</p>

<h2 id="perguntas-frequentes">Perguntas frequentes</h2>

<blockquote>
  <p>Como eu convenço meu chefe de que isso é importante?</p>
</blockquote>

<p>No começo desse post eu tentei explicar que você faz isso de um jeito ou de
outro. Começar a fazer testes de maneira automática reduz o <strong>seu trabalho</strong> e
se tudo der certo você vai começar a entregar trabalho com mais qualidade.</p>

<p>Se você precisa aprender a fazer testes automáticos, daí a conversa com seu
gestor é outra.</p>

<blockquote>
  <p>Como eu testo algo que já existe e o código é ruim?</p>
</blockquote>

<p>Você pode usar <a href="https://en.wikipedia.org/wiki/Behavior-driven_development">testes de comportamento</a> para testar a aplicação inteira.
Eles são mais lentos e precisam de algumas condições anteriores (usuário
existir, produto, etc) mas vão entregar valor rápido e costumam ser mais simples
de entender e fazer no início.</p>

<!--
vim: spell spelllang=pt
-->]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="[&quot;Palestra&quot;, &quot;PHP&quot;]" /><summary type="html"><![CDATA[Uma breve descrição do que são testes automatizados, como fazer seu primeiro teste e o que buscar para continuar aprendendo.]]></summary></entry><entry><title type="html">Melhorando como desenvolvedor em 5min</title><link href="http://blog.augustopascutti.com/5min/2016/10/18/melhorando-como-desenvolvedor.html" rel="alternate" type="text/html" title="Melhorando como desenvolvedor em 5min" /><published>2016-10-18T00:00:00-02:00</published><updated>2016-10-18T00:00:00-02:00</updated><id>http://blog.augustopascutti.com/5min/2016/10/18/melhorando-como-desenvolvedor</id><content type="html" xml:base="http://blog.augustopascutti.com/5min/2016/10/18/melhorando-como-desenvolvedor.html"><![CDATA[<p>Ao desenvolver, escrever é uma parte bem pequena do trabalho. <strong>Ler</strong> é
a maior. Sua <a href="https://bit.ly/porque-vim" title="Palestra: Por que VIM? Uma palestra sobre limitações, não um editor.">IDE favorita impede você de melhorar</a>, com a navegação facilitada
pelo código é bem fácil ignorar código ruim. E bom. Não quero nenhuma guerra
santa contra IDEs mas, por favor, comece a tentar entender o código que você (e
outras pessoas) escreve(m).</p>

<p>Um código bom é como um livro do <a href="https://bit.ly/2ecTfdz" title="Wikipedia: Isaac Azimov. Não conhece? Leia 'O fim da eternidade'">Isaac Azimov</a>: curto, expressivo e
inspirador. Ele esconde camadas e mais camadas de decisões nos lugares onde
elas pertencem, através de uma interface clara e extensível.</p>

<p>Você precisa <a href="https://www.imdb.com/title/tt1772925" title="Documentário: Jiro Dreams of Sushi.">consumir código bom</a>, como o <a href="https://bit.ly/2dnHDjk" title="A filosofia Unix é sobre pequenos programas, que juntos fazem muito. Não o tamanho deles.">Unix</a>, e ser preguiçoso. Pegue
uma tarefa repetitiva no seu dia a dia e a automatize. Considere o <em>terminal</em>
<a href="https://bit.ly/2egr0Yx" title="Post: Unix as your IDE. O post é bem básico, mas é um excelente começo.">como sua IDE</a> e viva com ele:</p>

<ol>
  <li>Receba no seu e-mail os 5 posts mais votados no <a href="https://bit.ly/2ebFhaA" title="Agregação de notícias: Hacker News. 3 horas te ajudam a escapar dos hype-links. Acredite em mim, você não quer eles.">HN</a>, que estiveram lá
por mais de 3 horas.</li>
  <li>Atualize os projetos importantes pra você no começo do dia, com um resumo do
que aconteceu com eles enquanto você esteve fora.</li>
  <li>Garanta que sua suíte de testes automatizados seja exatamente isso. Se você
precisa navegar ou usar outras coisas pra testar, vá caçar o que aconteceu de
errado e arrume sua vida.</li>
</ol>

<p>Estude código de outras pessoas, pegue um projeto que você usa e vá
aprender como ele funciona. Pare de achar que <em>ignorância</em> e <em>economia de tempo</em>
são a mesma coisa, que esse conhecimento em nada vai agregar na sua vida. 
Você sabe como os Mocks do PHPUnit funcionam, por exemplo? Que
praticamente tudo que usa no ZSH é possível no BASH, sem todos os problemas?</p>

<p>Nada me ensinou, e me ensina, tanto quando o <a href="https://bit.ly/2dnHDjk" title="Será que alguém lê isso?">Unix</a>. Então leia. Se permita
ser mais preguiçoso e <strong>pare de reinventar a roda</strong>.</p>

<!--
vim: spell spelllang=pt
-->]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="5min" /><summary type="html"><![CDATA[Ao desenvolver, escrever é uma parte bem pequena do trabalho. Ler é a maior. Sua IDE favorita impede você de melhorar, com a navegação facilitada pelo código é bem fácil ignorar código ruim. E bom. Não quero nenhuma guerra santa contra IDEs mas, por favor, comece a tentar entender o código que você (e outras pessoas) escreve(m).]]></summary></entry><entry><title type="html">Orientação a Objetos - Tell Don’t Ask</title><link href="http://blog.augustopascutti.com/ood/2015/07/31/oo-tell-dont-ask.html" rel="alternate" type="text/html" title="Orientação a Objetos - Tell Don’t Ask" /><published>2015-07-31T00:00:00-03:00</published><updated>2015-07-31T00:00:00-03:00</updated><id>http://blog.augustopascutti.com/ood/2015/07/31/oo-tell-dont-ask</id><content type="html" xml:base="http://blog.augustopascutti.com/ood/2015/07/31/oo-tell-dont-ask.html"><![CDATA[<p>Num <a href="https://blog.augustopascutti.com/orientação%20a%20objetos/2015/06/25/oo-setters-getters.html">post anterior</a> vimos quanta informação do desenvolvedor os
métodos de acesso escondem, não dos objetos em si mas de como os desenvolvedores
podem usar esses objetos no dia a dia.</p>

<p>Continuando a mesma série de exemplos, vamos ver como unir dado e comportamento
para melhorar a comunicação com nossos usuários (desenvolvedores).</p>

<h2 id="dados-vs-comportamentos">Dados vs Comportamentos</h2>

<p>Nos examplos anteriores, tínhamos um valor de desconto em dinheiro. Um desconto
só é útil se aplicado à alguma coisa, certo? Como nossa empresa fictícia vende livros,
vamos ver como seria usar dar desconto em um livro:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">namespace</span> <span class="nn">MyApp\Promotion</span><span class="p">;</span>

<span class="nv">$book</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Product</span><span class="p">(</span><span class="s1">'Object Thinking (Developer Reference)'</span><span class="p">,</span> <span class="mf">60.00</span><span class="p">);</span>
<span class="nv">$blackFriday</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Discount\Money</span><span class="p">(</span><span class="mf">10.00</span><span class="p">);</span>

<span class="nv">$finalPrice</span> <span class="o">=</span> <span class="nv">$book</span><span class="o">-&gt;</span><span class="nf">getPrice</span><span class="p">()</span> <span class="o">-</span> <span class="nv">$blackFriday</span><span class="o">-&gt;</span><span class="nf">getValue</span><span class="p">();</span>
<span class="nv">$book</span><span class="o">-&gt;</span><span class="nf">setPrice</span><span class="p">(</span><span class="nv">$finalPrice</span><span class="p">);</span>
</code></pre></div></div>

<p>No exemplo acima temos duas classes representando dois dados diferentes: <code class="language-plaintext highlighter-rouge">desconto</code>
e <code class="language-plaintext highlighter-rouge">produto</code>. Veja que o comportamento de cálculo do desconto não esta encapsulado
em nada, vamos resolver isso:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">namespace</span> <span class="nn">MyApp\Promotion</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">DiscountCalculator</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">applyDiscountOnProduct</span><span class="p">(</span>
        <span class="kt">Discount</span><span class="err">\</span><span class="nc">Money</span> <span class="nv">$discount</span><span class="p">,</span>
        <span class="nc">Product</span> <span class="nv">$book</span>
    <span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="nv">$discount</span><span class="o">-&gt;</span><span class="nf">getValue</span><span class="p">()</span> <span class="o">&gt;=</span> <span class="nv">$book</span><span class="o">-&gt;</span><span class="nf">getPrice</span><span class="p">())</span> <span class="p">{</span>
            <span class="nv">$message</span> <span class="o">=</span> <span class="nb">sprintf</span><span class="p">(</span>
                <span class="s1">'Discount (%01.2f) is greater than book price (%01.2f).'</span><span class="p">,</span>
                <span class="nv">$discount</span><span class="o">-&gt;</span><span class="nf">getValue</span><span class="p">(),</span>
                <span class="nv">$book</span><span class="o">-&gt;</span><span class="nf">getPrice</span><span class="p">()</span>
            <span class="p">);</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="err">\</span><span class="nf">UnexpectedValueException</span><span class="p">(</span><span class="nv">$message</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="nv">$book</span><span class="o">-&gt;</span><span class="nf">getPrice</span><span class="p">()</span> <span class="o">-</span> <span class="nv">$discount</span><span class="o">-&gt;</span><span class="nf">getValue</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Agora temos nosso comportamento agindo em dois dados diferentes. Apesar de ser
um exemplo com classes, nada impede os seus dados de serem um array ou qualquer
outra estrutura de dados (apesar de saber que você prefere objetos 😉).</p>

<p>Vamos ver como fica o uso deles com nossa classe tilanga:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">namespace</span> <span class="nn">MyApp\Promotion</span><span class="p">;</span>

<span class="nv">$calculator</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DiscountCalculator</span><span class="p">;</span>
<span class="nv">$book</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Product</span><span class="p">(</span><span class="s1">'Object Thinking (Developer Reference)'</span><span class="p">,</span> <span class="mf">60.00</span><span class="p">);</span>
<span class="nv">$guguFriday</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Discount\Money</span><span class="p">(</span><span class="mf">50.00</span><span class="p">);</span>

<span class="nv">$customerCart</span> <span class="o">=</span> <span class="nv">$calculator</span><span class="o">-&gt;</span><span class="nf">applyDiscountOnProduct</span><span class="p">(</span><span class="nv">$guguFriday</span><span class="p">,</span> <span class="nv">$book</span><span class="p">);</span>
</code></pre></div></div>

<p>Repare como <em>a calculadora</em> depende sempre dos dois objetos mas principalmente
do desconto, que é quando ela é necessária. Separar dados de comportamento pode
ser útil em alguns casos mas existe um grande poder (de comunicação) em unir ambos,
além de ser um dos fundamentos da Orientação a Objetos:</p>

<blockquote>
  <p>Código procedural pega uma informação e toma uma decisão. Código orientado a
objetos pede que objetos façam coisas.</p>

  <p>Alec Sharp</p>
</blockquote>

<p>Separando <em>dado</em> de <em>comportamento</em> você cobra do usuário o conhecimento dos
comportamentos associados ao dado. Toda vez que alguém quiser saber o preço que
algum cliente pagou (ou vai pagar) por algo, ela precisa saber dos descontos e
aplicá-los. Você acha mesmo que elas vão sempre saber disso?!</p>

<p>Papai Noel não existe, nem o coelhinho da páscoa. #prontofalei</p>

<h2 id="tell-dont-ask">Tell, don’t ask</h2>

<p>O <a href="https://web.archive.org/web/20121227021359/pragprog.com:80/articles/tell-dont-ask">Tell, don’t ask</a> basicamente diz que juntando os dois (dado e
comportamento) em uma única classe, o desenvolvedor precisa saber menos e o
código tende a ficar mais conciso (e coeso, como  consequência).</p>

<p>Como ficaria nosso exemplo de desconto em dinheiro usando ele?</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">namespace</span> <span class="nn">Myapp\Promotion\Discount</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">Money</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="nv">$amount</span> <span class="o">=</span> <span class="mf">0.00</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$amountToDiscount</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">amount</span> <span class="o">=</span> <span class="nv">$amountToDiscount</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">calculateProductFinalPrice</span><span class="p">(</span><span class="kt">Product</span> <span class="nv">$product</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$newPrice</span> <span class="o">=</span> <span class="nv">$product</span><span class="o">-&gt;</span><span class="nf">getPrice</span><span class="p">()</span> <span class="o">-</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">amount</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="nv">$newPrice</span> <span class="o">&lt;=</span> <span class="mf">0.00</span><span class="p">)</span> <span class="p">{</span>
            <span class="nv">$message</span> <span class="o">=</span> <span class="nb">sprintf</span><span class="p">(</span>
                <span class="s1">'Discount (%01.2f) is greater than book price (%01.2f).'</span><span class="p">,</span>
                <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">amount</span><span class="p">(),</span>
                <span class="nv">$product</span><span class="o">-&gt;</span><span class="nf">getPrice</span><span class="p">()</span>
            <span class="p">);</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="err">\</span><span class="nf">UnexpectedValueException</span><span class="p">(</span><span class="nv">$message</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="nv">$newPrice</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Pronto. Jogamos a <em>calculadora</em> fora, tiramos o método de acesso pra retornar o
valor do desconto e colocamos o método da calculadora dentro do desconto.</p>

<p>Antes o desenvolvedor precisava saber o que fazer com aquele valor, agora ele
precisa decidir se o que ele precisa é o valor do produto com o desconto aplicado
ou não. É justamente desse fato que sai o nome <a href="https://web.archive.org/web/20121227021359/pragprog.com:80/articles/tell-dont-ask">do princípio</a>: antes de
permitir algum usuário de pedir alguma coisa (dado), diga/ofereça a ele as
ações (comportamentos) que ele pode usar naquele objeto (dado+comportamento).</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$book</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Product</span><span class="p">(</span><span class="s1">'Object Thinking (Developer Reference)'</span><span class="p">,</span> <span class="mf">60.00</span><span class="p">);</span>
<span class="nv">$blackFriday</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Discount\Money</span><span class="p">(</span><span class="mf">10.00</span><span class="p">);</span>

<span class="nv">$customerCartValue</span> <span class="o">=</span> <span class="nv">$blackFriday</span><span class="o">-&gt;</span><span class="nf">calculateProductFinalPrice</span><span class="p">(</span><span class="nv">$book</span><span class="p">);</span>
</code></pre></div></div>

<p>Pensando sempre em quem vai usar seu código, inclusive você, o código acima é
mais simples e menos propenso aos erros de interpretação no futuro.</p>

<p>Como todo comportamento de desconto está disponível e pronto pra usar, expor o
valor de desconto através de um método de acesso é desnecessário. Esse menor
nível de exposição torna o encapsulamento dos algoritmos melhor e portanto, mais
fáceis de evoluir.</p>

<p>É comum nas discussões de segregar (ou não) <em>dado</em> de <em>comportamento</em>, o pessoal
a favor da união de ambos citar o argumento <a href="https://en.wikipedia.org/wiki/Anemic_domain_model">dos modelos anêmicos</a>
em <a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">DDD</a> mas, acho que ninguém precisa ir tão longe pra defender os benefícios
desse princípio.</p>

<h2 id="agora-queremos-descontos-em-porcentagem">Agora queremos descontos em porcentagem!</h2>

<p>Agora precisamos aplicar um desconto em porcentagem. Refletindo sobre o
problema, não temos muito a fazer além de criar outra classe de desconto
e mudar ou pouco como o valor final do livro é calculado.</p>

<p>Acho sempre válido você pensar nas soluções por você, se possível envie
elas pra mim depois. Como agora não tenho muita opção, segue minha solução
pro problema:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">namespace</span> <span class="nn">MyApp\Promotion\Discount</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">Percentage</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="nv">$fraction</span> <span class="o">=</span> <span class="mf">0.00</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$percentageToDiscount</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$value</span> <span class="o">=</span> <span class="nv">$percentageToDiscount</span> <span class="o">/</span> <span class="mi">100</span><span class="p">;</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">fraction</span> <span class="o">=</span> <span class="p">(</span><span class="n">float</span><span class="p">)</span> <span class="nv">$value</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">calculateProductFinalPrice</span><span class="p">(</span><span class="kt">Product</span> <span class="nv">$product</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$discountValue</span> <span class="o">=</span> <span class="nv">$product</span><span class="o">-&gt;</span><span class="nf">getPrice</span><span class="p">()</span> <span class="o">*</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">fraction</span><span class="p">;</span>
        <span class="nv">$newPrice</span> <span class="o">=</span> <span class="nv">$product</span><span class="o">-&gt;</span><span class="nf">getPrice</span><span class="p">()</span> <span class="o">-</span> <span class="nv">$discountValue</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="nv">$newPrice</span> <span class="o">&lt;=</span> <span class="mf">0.00</span><span class="p">)</span> <span class="p">{</span>
            <span class="nv">$message</span> <span class="o">=</span> <span class="nb">sprintf</span><span class="p">(</span>
                <span class="s1">'Discount (%01.2f%%) makes product cost nothing!'</span><span class="p">,</span>
                <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">fraction</span> <span class="o">*</span> <span class="mi">100</span>
            <span class="p">);</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="err">\</span><span class="nf">UnexpectedValueException</span><span class="p">(</span><span class="nv">$message</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="nv">$newPrice</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Usar o <a href="https://web.archive.org/web/20121227021359/pragprog.com:80/articles/tell-dont-ask">princípio</a> força você a imaginar como um objeto vai ser usado
e nas informações que o usuário terá quando for consumir a funcionalidade
da sua classe. Pra resolver isso, eu costumo tentar fazer o <a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">código imitar
uma conversa entre duas pessoas</a>.</p>

<p>Quando você recebe um desconto, como a pessoa comunica esse desconto a você?</p>

<ol>
  <li>Você tem 25% de desconto em qualquer produto.</li>
  <li>Você só vai pagar 75% do produto.</li>
  <li>Você vai pagar o valor do produto menos o valor dele multiplicado por 0.25.</li>
</ol>

<p>Imaginando que as três conversas fossem um código de verdade, eu penso
imediatamente nos códigos abaixo:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">namespace</span> <span class="nn">MyApp\Promotion</span><span class="p">;</span>

<span class="c1">// 1. Você tem 25% de desconto em qualquer produto.</span>
<span class="nv">$blackFriday</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Discount\Percentage</span><span class="p">(</span><span class="mi">25</span><span class="p">);</span>

<span class="c1">// 2. Você só vai pagar 75% do produto.</span>
<span class="nv">$blackFriday</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Discount\Percentage</span><span class="p">(</span><span class="mi">75</span><span class="p">);</span>

<span class="c1">// 3. Você vai pagar o valor do produto menos o valor dele multiplicado por 0.25.</span>
<span class="nv">$blackFriday</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Discount\Percentage</span><span class="p">(</span><span class="mf">0.25</span><span class="p">);</span>
</code></pre></div></div>

<p>Qualquer um dos três códigos pode funcionar, mas qual é a real expectativa do
desenvolvedor quando for consumir o código existente?
<a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">Deixar implementação próxima da forma como vocês conversam sobre uma
funcionalidade dentro da empresa</a> evita diversos problemas. Como na nossa
empresa fictícia nos comunicamos usando o primeiro caso, implementamos ele.</p>

<p>Repare no nome do primeiro argumento: <code class="language-plaintext highlighter-rouge">$percentageToDiscount</code>. Ele tira toda a
ambiguidade do processo e elimina a necessidade do desenvolvedor precisar ler o
resto da classe. Através de um <a href="https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">código limpo</a> estamos sempre evitando a ambiguidade
e a dúvida onde pudermos.</p>

<p>As diferenças entre os casos 1 e 2 são a forma como vocês conversam sobre a
funcionalidade. Já no caso 3 a coisa se degringola um pouco: Você expõe a conta
de porcentagem pro cliente, o que pode ser prejudicial no futuro, como no <a href="https://blog.augustopascutti.com/orientação%20a%20objetos/2015/06/25/oo-setters-getters.html">caso
dos métodos de acesso</a>.</p>

<h2 id="defendendo-a-separação-de-comportamento-e-dados">Defendendo a separação de comportamento e dados</h2>

<p>Existem alguns vários argumentos a favor de manter os dois separados mas de forma alguma
vou esgotar essa discussão, nem que eu fosse presunçoso o suficiente pra achar
que tenho essa capacidade, então minha intenção é te dar opções (ou novos problemas)
pra ao menos facilitar sua escolha.</p>

<p>O primeiro argumento contra a separação costuma ser o da violação de <a href="https://drive.google.com/file/d/0ByOwmqah_nuGNHEtcU5OekdDMkk/view?pli=1" title="Uncle Bob: Single Responsability Principle">SRP</a>, o
que é ótimo se a pessoa se embasar na questão de responsabilidade. É ótimo porque
a questão de responsabilidade em nada viola a unidade de dado e comportamento.
“Um motivo pra mudar” é o que define “responsabilidade” no <a href="https://drive.google.com/file/d/0ByOwmqah_nuGNHEtcU5OekdDMkk/view?pli=1" title="Uncle Bob: Single Responsability Principle">SRP</a>, se você
fizer um bom trabalho de design você consegue ter ambos. Ninguém disse que ia
ser fácil.</p>

<p>O segundo argumento é chato e costuma tocar objetos que precisam ser mapeados ou
serializados. Nesse caso, você tem uma classe que possui informações além de um
método que retorna o mapamento daquele objeto pra outro. Você pode isolar o
mapeamento em outra classe e sempre que a estrutura de dados mudar, mudar essa
classe-mapa também - resumindo, uma bosta. Você pode usar <a href="https://php.net/ReflectionClass">Reflection</a> e fazer
esse mapeamento com <a href="https://en.wikipedia.org/wiki/Inflection">Inflexão</a>, é um jeito melhor de resolver esse
determinado problema e tenho certeza que não é o único. Aqui o argumento é chato
porque provavelmente você vai cair nos <em>trade-off</em>s: analisar diferentes soluções
e adotar a “menos pior” pro seu caso específico.</p>

<p>Em todos os casos, repare que a opinião pouco importa. Usar o “<a href="https://web.archive.org/web/20121227021359/pragprog.com:80/articles/tell-dont-ask">Tell, don’t ask</a>”
não precisa violar nenhum outro princípio independente da situação mas te convido
a antes de pensar nos princípios, pensar em quem utilizará o código e se todas
as implicações de negócio estarão tão claras pra eles quanto estão pra você. Esqueça
disso e use todos os princípios, você terá problemas. Não disse que os princípios
são ruins, só disse que eles por si só não resolverão todos os seus problemas.</p>

<p>PS: Se você pensou em usar alguns desses argumentos pra defender <a href="https://en.wikipedia.org/wiki/Active_record_pattern">Active Record</a>,
eu tenho um argumento contra você: <a href="https://drive.google.com/file/d/0ByOwmqah_nuGNHEtcU5OekdDMkk/view?pli=1" title="Uncle Bob: Single Responsability Principle">SRP</a> 😄. Eu sou um filho da puta, to ligado. 😘</p>

<h2 id="conclusões">Conclusões</h2>

<p>Assim como <a href="https://blog.augustopascutti.com/orientação%20a%20objetos/2015/06/25/oo-setters-getters.html">o uso inconsicente dos métodos de acesso pode ser ruim</a>, separar
<em>dado</em> dos seus <em>comportamentos</em> também é.</p>

<p>Dar aos usuários do seu código ações a serem feitas em cima de determinados dados,
junto com eles, vai melhorar a comunicação do seu código com eles. É essa melhora
de comunicação que impede os problemas de acontecerem.</p>

<p>Eu não falei quase nada sobre o <a href="https://web.archive.org/web/20121227021359/pragprog.com:80/articles/tell-dont-ask">TDA</a>, então vá ler mais a respeito:</p>

<ul>
  <li>O <a href="https://pragprog.com/about">Andy Hunt e o Dave Thomas</a> publicaram um <a href="https://media.pragprog.com/articles/jan_03_enbug.pdf">artigo no IEEE</a> além de
<a href="https://web.archive.org/web/20121227021359/pragprog.com:80/articles/tell-dont-ask">outro bem mais detalhado no blog deles</a>. Eu aconselho bastante a você
ler eles! Eu podia ter colocado esses links na introdução e não ter escrito
absolutamente mais nada, mas como eu <a href="https://twitter.com/augustohp/status/626032867798351872">peguei feijão e strogonoff hoje</a>,
considerem esses links o strogonoff.</li>
  <li>No <a href="https://c2.com/cgi/wiki?WelcomeVisitors">Cunningham &amp; Cunningham Wiki</a> existe <a href="https://c2.com/cgi/wiki?TellDontAsk">uma discussão</a> dos dois links
acima com algumas conclusões. Você já sacou que nenhum dos links que eu ponho
deveriam ser ignorados por vossa senhoria, certo?!</li>
  <li>O <a href="https://martinfowler.com">Martin Fowler</a> publicou <a href="https://martinfowler.com/bliki/TellDontAsk.html">no bliki dele</a> um artigo bem preguiçoso
a respeito do princípio. Se você gosta dele e está com tempo, vá lá ler, se não
vá procurar alguém errado pelas internets. Com esse link aqui é sério, você
não via perder nada se não ler.</li>
  <li>A <a href="https://thoughtbot.com/">ThoughtBot</a> fez <a href="https://robots.thoughtbot.com/tell-dont-ask">alguns exemplos em Ruby</a> que são bacanas. Sem bla bla
bla, só exemplos.</li>
</ul>

<p>PS: Meu obrigado pro <a href="https://github.com/netojoaobatista/">João</a>, <a href="https://twitter.com/nelson_senna">Nelson</a> e <a href="https://github.com/lcobucci">Cobucci</a> pelo review a mais um
post. Eles são uns 👼 !</p>]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="ood" /><summary type="html"><![CDATA[Num post anterior vimos quanta informação do desenvolvedor os métodos de acesso escondem, não dos objetos em si mas de como os desenvolvedores podem usar esses objetos no dia a dia.]]></summary></entry><entry><title type="html">Orientação a Objetos - Um caso contra os métodos de acesso</title><link href="http://blog.augustopascutti.com/orienta%C3%A7%C3%A3o%20a%20objetos/2015/06/25/oo-setters-getters.html" rel="alternate" type="text/html" title="Orientação a Objetos - Um caso contra os métodos de acesso" /><published>2015-06-25T00:00:00-03:00</published><updated>2015-06-25T00:00:00-03:00</updated><id>http://blog.augustopascutti.com/orienta%C3%A7%C3%A3o%20a%20objetos/2015/06/25/oo-setters-getters</id><content type="html" xml:base="http://blog.augustopascutti.com/orienta%C3%A7%C3%A3o%20a%20objetos/2015/06/25/oo-setters-getters.html"><![CDATA[<p>Quanto de suas classes são compostas por métodos para definir e retornar valores
guardados nela? Você já questionou o benefício da orientação a objetos enquanto
estava criando uma classe?</p>

<p>A ideia de um objeto é encapsular uma computação e isso envolve esconder algumas
coisas do usuário. Um método de acesso (ou setter/getter) é uma exposição:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php

namespace MyApp\Promotion;

class Discount
{
    private $value = 0.00;

    public function setValue($float)
    {
        $this-&gt;value = $float;
    }

    public function getValue()
    {
        return $this-&gt;value;
    }
}
</code></pre></div></div>

<p>A proposta de encapsular as coisas é permitir que elas evoluam (ou mudem) sem o
conhecimento do usuário, que no caso é o desenvolvedor. Todo método público
é como uma mensagem de um desenvolvedor pra outro, uma mensagem dizendo
“ei, me use”.</p>

<p>Cabe ao usuário decidir se ele quer usar ou não as ferramentas dadas a ele
e na orientação a objetos, para usar um método precisamos das instâncias:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php

namespace MyApp\Promotion;

$blackFriday = new Discount;
$askingToGetFired = new Discount;
</code></pre></div></div>

<p>Existem casos em que você quer <a href="https://sourcemaking.com/design_patterns/singleton">garantir só uma instância de determinada
classe</a> (o que não acho muito válido pro PHP), mas no caso do
nosso desconto queremos obviamente vários tipos de desconto.</p>

<p>No caso de várias instâncias, o que diferencia uma da outra como no exemplo
acima? Quais dos métodos um usuário pode ou não usar e em quais circunstâncias?</p>

<p>Qual a vantagem do código da classe usando os métodos de acesso (get/set)
ao invés de definir o atributo como público?</p>

<h2 id="objetos-sempre-válidos">Objetos sempre válidos</h2>

<p>Nosso trabalho é fazer com que as coisas funcionem 100% do tempo. Deixar
informações implícitas e quebrar promessas (um método é uma promessa) é
a receita para nunca atingir o 100% desejado.</p>

<p>A promessa a ser quebrada aí é a chamada pro <code class="language-plaintext highlighter-rouge">getValue</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php

$blackFriday = new Discount;
$blackFriday-&gt;getValue();
</code></pre></div></div>

<p>Sem valor nenhum de desconto como você poderia querer cumprir essa promessa?
Existem formas de melhorar a comunicação entre nossos objetos, impedindo que
coisas inesperadas aconteçam e que um desenvolvedor precise ler inúmeras linhas
de código pra descobrir como alguma coisa funciona.</p>

<p>A Orientação a Objetos oferece duas mecânicas que consigo pensar em usar nesse
momento. Uma é lançar uma exceção caso nenhum valor de desconto tenha sido definido
e a outra é obrigar um valor de desconto no construtor:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php

namespace MyApp\Promotion;

class Discount
{
    private $value = 0.00;

    public function __construct($value)
    {
        $this-&gt;value = (float) $value;
    }

    public function getValue()
    {
        return $this-&gt;value;
    }
}
</code></pre></div></div>

<p>Existem várias outras maneiras de resolver esse problema. Não usei a exceção
porque um valor de desconto sempre é necessário. Eu poderia criar um validador
de descontos também, mas por enquanto esse tipo de burocracia parece bastante
desnecessário. O melhor código é aquele que não existe.</p>

<p>Criar um código pensando no seu consumo implica em querer contar uma história.
A última coisa que queremos é suspense ou mistério, o melhor tipo de código
é aquele filme de ação tapa na cara, MacGyver:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php

namespace MyApp\Promotion;

$blackFriday = new Discount(10);
$guguSunday = new Discount(25);
</code></pre></div></div>

<p>Parece que nosso código está fazendo um pouco mais de sentido agora. Repare
que ao ler você sabe que o <code class="language-plaintext highlighter-rouge">Discount</code> é membro de <code class="language-plaintext highlighter-rouge">MyApp\Promotion</code> e que
temos dois descontos com valores diferentes. Pare por 1 minuto e pense o
quanto de informação você tem com o código acima que estava escondida por
causa dos métodos de acesso.</p>

<p>Faça o exercício mental de imaginar esse código num caso mirabolante de
checkout num e-commerce. Se você tem uma instância, você pressupõe que ela
faça tudo que ela promete, então se atente a criar uma classe que obriga
todas as instâncias dela a serem válidas. Se você quiser se gabar entre
seus amiguinhos, <a href="https://en.wikipedia.org/wiki/Principle_of_least_astonishment">você pode até dar um nome bacana pra esse princípio
de design</a>.</p>

<p>Repare também como o consumo da classe utilizando o construtor <a href="https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">conta uma
história</a>. Será que na história contada você tem todas as informações
que precisa pra colaborar ou mudar essa história?</p>

<p>Essa é a pergunta que você deve fazer ao escrever <strong>cada linha de código</strong>.</p>

<h2 id="contando-uma-história-completa">Contando uma história completa</h2>

<p>Se a nossa empresa agora quiser dar dois descontos: um de 25% e outro de R$15.
Como você vai instanciar as classes de desconto?</p>

<p>Afinal, nossos descontos até agora são em porcentagem ou são valores monetários?</p>

<p>Esse tipo de suspense ou informação que só é óbvia pra quem está criando o código
é o tipo de problema chato. Difícil resolver ele sozinho sem muita experiência e
sensibilidade. A melhor prática pra identificar esses problemas, na minha opinião,
é o <a href="https://en.wikipedia.org/wiki/Code_review">code review</a>. Além de alinhar as práticas do time, é imperativo que quem leia
o código entenda ele plenamente.</p>

<p>Outra forma de resolver isso é utilizar comentários. Eu aprendi que o destino de
um comentário é ser ignorado ou ficar desatualizado então, como a gente resolve
nosso problema sem comentários?</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php

namespace MyApp\Promotion\Discount;

class Money
{
    private $amount = 0.00;

    public function __construct($amountToDiscount)
    {
        $this-&gt;amount = $amountToDiscount;
    }

    public function getValue()
    {
        return $this-&gt;amount;
    }
}
</code></pre></div></div>

<p>Podíamos ter resolvido isso de várias formas, imediatamente penso em duas:</p>

<ul>
  <li>Mudar o atributo de <code class="language-plaintext highlighter-rouge">$value</code> para <code class="language-plaintext highlighter-rouge">$amountOfMoney</code>.</li>
  <li>Mudar o nome da classe de <code class="language-plaintext highlighter-rouge">Discount</code> pra <code class="language-plaintext highlighter-rouge">MoneyDiscount</code>.</li>
</ul>

<p>Eu poderia ter <a href="https://sourcemaking.com/refactoring/introduce-explaining-variable">usado as variáveis e atributos pra explicar o que eles devem
conter</a>, mas criei uma <em>namespace</em> intermediária além de
mudar o nome da classe pra deixar claro que iremos precisar de outros tipos
de desconto.</p>

<p>O <a href="https://github.com/netojoaobatista/">João Batista Neto</a> argumentou que obrigar os demais desenvolvedores a
olhar um atributo pra descobrir o que ele é quebra a regra de encapsulamento.
Por isso optei por expressar isso no nome da classe e no argumento do construtor.
Quebrando encapsulamento ou não, o argumento do construtor sempre irá tanger o
escopo de fora da classe e a interno, agradando tanto a mim e <a href="https://github.com/netojoaobatista/">ao João</a>.</p>

<blockquote>
  <p>Existem só duas coisas difíceis na Ciência da Computação: invalidação de cache
e dar nome à coisas.</p>

  <p>– Phil Karlton</p>
</blockquote>

<p>Tem <a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">uma galera</a> que vai muito além de querer <a href="https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">contar uma história</a> e
defende o estebecimento e uso de termos muito bem definidos no seu código, então</p>
<ul>
  <li>eu acho que - é uma boa ideia você começar a prestar mais atenção nisso.</li>
</ul>

<h2 id="pensamentos-do-fim-do-post">Pensamentos do fim do post</h2>

<p>Quero que você pense no seu código e veja quanto dos seus métodos de acesso
fazem alguma coisa de fato. Será que deixar todos os atributos de suas classes
públicos implica no mesmo comportamento do que ter os métodos de acesso? Se sim,
evite-os.</p>

<p>Seus métodos deveriam sempre expressar uma ação e um objeto deve sempre ser válido.
Pense nos métodos públicos como promessas e na responsabilidade de manter várias
promessas desnecessariamente.</p>

<p>Uma boa classe, além de sempre fornecer instâncias válidas, sempre cumpre o que
promete.</p>

<p>PS: Existe <a href="https://c2.com/cgi/wiki?AccessorsAreEvil">um post muito melhor</a> no sempre excelente
<a href="https://c2.com/cgi/wiki?WelcomeVisitors">Cunningham &amp; Cunningham Wiki</a> sobre isso. Sugiro que você ignore ele e
continue confiando somente em mim! Óbvio que não, vai lá ler essa porra agora!</p>

<p>PPS: Preciso agradecer imensamente a paciência e amizade dos amigos <a href="https://twitter.com/nelson_senna">Nelson</a>,
<a href="https://github.com/netojoaobatista/">João</a>, <a href="https://github.com/lcobucci">Cobucci</a> e <a href="https://twitter.com/ivonascimento">Ivo Nascimento</a> que me ajudaram muito revisando
e discutindo esse post (e provavelmente mais alguns que virão). Se você curtiu
esse post, por favor agradeça a elas por mim também! :)</p>]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="Orientação a Objetos" /><summary type="html"><![CDATA[Quanto de suas classes são compostas por métodos para definir e retornar valores guardados nela? Você já questionou o benefício da orientação a objetos enquanto estava criando uma classe?]]></summary></entry><entry><title type="html">Por que VIM?</title><link href="http://blog.augustopascutti.com/desenvolvimento/2015/04/30/porque-vim.html" rel="alternate" type="text/html" title="Por que VIM?" /><published>2015-04-30T00:00:00-03:00</published><updated>2015-04-30T00:00:00-03:00</updated><id>http://blog.augustopascutti.com/desenvolvimento/2015/04/30/porque-vim</id><content type="html" xml:base="http://blog.augustopascutti.com/desenvolvimento/2015/04/30/porque-vim.html"><![CDATA[<p>Já escrevi sobre <a href="https://blog.augustopascutti.com/desenvolvimento/2013/11/06/Meu_ambiente_de_trabalho.html">meu ambiente</a> de trabalho antes então o fato deu usar <a href="https://www.vim.org/">VIM</a> não deveria ser novidade. Adoro discutir e observar como cada desenvolvedor trabalha no dia a dia mas odeio o fato de ter que compartilhar o editor que várias pessoas usam só pra demonstrar alguma habilidade - ou a falta dela.</p>

<h2 id="eu-não-escolhi-usar-vim-escolhi-usar-o-terminal">Eu não escolhi usar VIM, escolhi usar o terminal</h2>

<blockquote>
  <p>Over 1 year, the average Vim user saves 11 minutes in productivity. However, they lose 27 hours through evangelising Vim to non-users.</p>

  <p>– I Am Devloper <a href="https://twitter.com/iamdevloper/status/588355053104267264">(@iamdevloper)</a> April 15, 2015.</p>
</blockquote>

<p>Acho que a maioria das pessoas que usam <a href="https://www.vim.org/">VIM</a> só querem exercer algum tipo de superioridade com relação às outras. Acredite em mim quando digo: Você <strong>não</strong> deveria usar <a href="https://www.vim.org/">vim</a>. Siga com as ferramentas que te fazem produtivo, que saem do seu caminho e que te fazem sentir confortável. Nunca esqueça que você é livre e que as ferramentas que você usa pra produzir software são só ferramentas.</p>

<blockquote>
  <p>vim é aquela ferramenta que todo programador quer bancar o fodão diz que usa <a href="https://twitter.com/hashtag/phpexperience">#phpexperience</a>.</p>

  <p>– Valdir Bruxel Junior <a href="https://twitter.com/hagnat/status/591981964686708737">(@hagnat)</a></p>
</blockquote>

<p>Eu escolhi <a href="https://www.vim.org/">VIM</a> ao <a href="https://www.gnu.org/software/emacs/">Emacs</a> por preguiça. Ele já estava instalado em todos os servidores e ambientes com que tenho contato. Assistir a animação após executar um <em>ALT/CMD+TAB</em> entre o terminal e o <a href="https://www.sublimetext.com/">Sublime Text</a> do <a href="https://www.apple.com/osx/">OSX</a> me matava (literalmente) de ansiedade e eu já passava a maior parte do tempo no terminal mesmo.</p>

<p>Não estou satisfeito com <a href="https://www.vim.org/">VIM</a> ainda, mas minhas frustrações são menores que as satisfações que ele me dá.</p>

<h2 id="comendo-boa-comida">Comendo boa comida</h2>

<blockquote>
  <p>“The heart of Unix philosophy is the idea that the power of a system comes more from the relationships among programs than from the programs themselves.”</p>

  <p>– Rob Pike</p>
</blockquote>

<p>Eu já tentei <a href="https://www.slideshare.net/augustopascutti/logs-36298518">várias vezes</a> mostrar o poder do terminal pra vários desenvolvedores. Acredito que pra desenvolver bom software é necessário consumir bom software, entender os problemas e as soluções dadas leva tempo e determinação. Quanto mais simples a solução, mais difícil de etendê-la.</p>

<p>Já pensou, por exemplo, em porque o <a href="https://en.wikipedia.org/wiki/LAMP_%28software_bundle%29">LAMP</a> é popular? Te garanto que os <a href="https://www.wampserver.com/en/">WAMP</a>s da vida vieram depois dessa popularização. Estou longe de entender completamente o porquê, mas consigo compartilhar um pouco da minha visão atual:</p>

<ul>
  <li><a href="https://kernel.org/">Linux</a> dispensa apresentações. Sério.</li>
  <li>O <a href="https://httpd.apache.org/">Apache HTTPD</a> é estável, robusto, eficiente e largamente utilizado. Além de ser extramemente flexível: um ótimo <a href="https://httpd.apache.org/docs/current/mod/mod_proxy.html">Proxy</a>, possui boas opções de <a href="https://httpd.apache.org/docs/current/howto/auth.html">segurança</a> e muitos outros plugins embutidos.</li>
  <li>O <a href="https://www.mysql.com/">MySQL</a> é simples e robusto. Você pode confiar nele pro seu blog pessoal, <a href="https://wordpress.com/">quase todos os outros blogs do planeta</a>, ou <a href="https://wikipedia.org/">quase todo o conhecimento</a>. A chance de você usar ele sem nem saber o arquivo de configuração dele é grande.</li>
  <li>A arquitetura <a href="https://en.wikipedia.org/wiki/Shared_nothing_architecture">shared nothing</a> do <a href="https://php.net/">PHP</a>: Uma requisição, um novo processo. Sem memória compartilhada. Torna ridiculamente simples o desenvolvimento, a escalabilidade e os hosts compartilhados.</li>
</ul>

<p>Todos esses caras são grandes softwares, em todos os sentidos. Possuem, no sentido de desenvolvimento, uma grande equipe de contribuidores e muitas linhas de código. Mas possuem outra característica em comum: Fazer uma coisa e fazer bem.</p>

<p>Passar bastante tempo no terminal pode parecer uma penitência, e é por muito tempo. Mas aprender como as pequenas ferramentas podem funcionar juntas é fascinante pra dizer o mínimo. Com o passar do tempo você se sente <a href="https://blog.augustopascutti.com/hacks/unix/2013/09/02/Crawler-de-json-com-mongo-em-5-min.html">com super poderes</a>: você gerencia seus <em>TODOs</em>, suas contas, stalkeia, conversa e derruba aquele site safado sem sair da shell.</p>

<p>Com o passar do tempo, você passa a identificar melhor o problema que cada algoritmo deve resolver. Quais soluções e problemas existem além de como usar elas e eles de forma melhor. Você não vai deixar de usar o Google, perguntar ou ler. Pelo contrário! Mas te garanto, você vai aproveitar <strong>muito mais</strong> as coisas se tornando um preguiçoso invejável - eu ainda chego lá.</p>

<p>Como desenvolvedor isso afeta diretamente o produto final de seu trabalho.</p>

<h2 id="você-deveria-usar-mais-a-shell">Você deveria usar mais a shell</h2>

<p>Esqueça aquele lance babaca de dividir seu terminal em várias partes e abrir 73 abas pra se sentir <a href="https://web.archive.org/jtnimoy.com/blogs/projects/14881671-tron-legacy">no Tron</a>. Comece a fazer tudo que você puder no seu dia a dia dentro de uma shell. Veja como melhoras seu fluxo de trabalho antes de fazer algo que você não precisa e procure entender o que cada ferramente oferece.</p>

<p>Escolha a ferramenta do mês, o <a href="https://en.wikipedia.org/wiki/Grep">grep</a> por exemplo. Aprenda tudo que puder dele, use-o em tudo que puder mesmo que sem necessidade. Quer ver um log? <a href="https://en.wikipedia.org/wiki/Grep">Grep</a>. Buscar ocorrências de uma classe/método? <a href="https://en.wikipedia.org/wiki/Grep">Grep</a>. Achar um commit? <a href="https://en.wikipedia.org/wiki/Grep">Grep</a>. Saber quantas vezes você usou um comando? <a href="https://en.wikipedia.org/wiki/Grep">Grep</a>. Buscar ajuda? <a href="https://en.wikipedia.org/wiki/Grep">Grep</a>. Continue até sua mulher/marido perguntar de manhã “Quem é essa tal de <a href="https://en.wikipedia.org/wiki/Grep">Grep</a>?”.</p>

<p>Você vai encontrar casos em que a ferramenta não é útil. Ótimo! Você sabe pra que não usá-la então só falta achar uma boa (ou um conjunto) que torne aquilo possível. Garanto que ela(s) já existem.</p>

<blockquote>
  <p>Mas minha IDE já faz tudo isso!</p>

  <p>– Você. Sendo um babaca.</p>
</blockquote>

<p>Sua IDE não vai transformar você num programador melhor, ela é uma ferramenta. Assim como o melhor pincel do mundo, com todas as cores do mundo, não faz de você o melhor pintor do mundo. Enquanto um pintor experiente, com um pincel bosta e poucas cores consegue provar por que ele é o melhor pintor do mundo.</p>

<p>Exerça seu direito de nascença e seja livre de todas as ferramentas. Aprenda a usar as mais básicas e a fazer tudo com elas. Imponha esse limite a você mesmo e ganhe continuamente com ele. O caminho <a href="https://web.archive.org/web/20170718104420/www.linuxcommand.org:80/learning_the_shell.php">esta</a> <a href="https://www.oreilly.com/openbook/debian/book/ch13_01.html">cheio</a> <a href="https://www.amazon.com/Power-Tools-Third-Shelley-Powers/dp/0596003307">de ajuda</a>.</p>

<p>PS: Fiz uma palestra sobre tudo isso, se você quiser <a href="//www.slideshare.net/augustopascutti/porque-vim">ver os slides, eles estão disponíveis</a>.</p>]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="Desenvolvimento" /><summary type="html"><![CDATA[Já escrevi sobre meu ambiente de trabalho antes então o fato deu usar VIM não deveria ser novidade. Adoro discutir e observar como cada desenvolvedor trabalha no dia a dia mas odeio o fato de ter que compartilhar o editor que várias pessoas usam só pra demonstrar alguma habilidade - ou a falta dela.]]></summary></entry><entry><title type="html">Meu ambiente de trabalho</title><link href="http://blog.augustopascutti.com/desenvolvimento/2013/11/06/Meu_ambiente_de_trabalho.html" rel="alternate" type="text/html" title="Meu ambiente de trabalho" /><published>2013-11-06T00:00:00-02:00</published><updated>2013-11-06T00:00:00-02:00</updated><id>http://blog.augustopascutti.com/desenvolvimento/2013/11/06/Meu_ambiente_de_trabalho</id><content type="html" xml:base="http://blog.augustopascutti.com/desenvolvimento/2013/11/06/Meu_ambiente_de_trabalho.html"><![CDATA[<p>Gosto de ter meu fluxo de trabalho otimizado: simples e extremamente produtivo. É uma questão de encontrar a melhor solução e ver se ela resiste ao teste do tempo. Talvez por isso me interesse <strong>bastante</strong> pelo ambiente de trabalho dos outros.</p>

<p>Há algum tempo houveram uma série de posts por parte da comunidade PHP em que cada desenvolvedor descrevia seu ambiente de trabalho em 7 itens. Minha idéia aqui é revisitar isso, sem regras dessa vez.</p>

<h2 id="um-anel-para-todos-governar">Um anel para todos governar</h2>

<p>Confesso que minha relação com o <a href="https://www.gnu.org/software/bash/">bash</a> já sofreu bastante. Pequei e usei o <a href="https://www.zsh.org/">zsh</a> durante um tempo mas no fim, o <code class="language-plaintext highlighter-rouge">bash-complete</code> funciona como deveria enquanto a experiência com o <a href="https://www.zsh.org/">zsh</a> completando comandos era embaraçosa mais vezes do que eu gostaria.</p>

<p>É o <a href="https://www.gnu.org/software/bash/">bash</a> que me faz sentir confortável em um sistema operacional. Ele foi o motivo deu ter comprado meu primeiro <em>MacBook</em>. Ele é o motivo de simplesmente não me importar se estou no Ubuntu, OSX pou qualquer outro Unix. Ele é o motivo deu esperar tão mais de um teclado que do mouse.</p>

<p>Aliás, se você se considera um programador e não usa ou sabe utilizar um *nix muito bem (no bom e velho terminal), faça um bem a humanidade e reconsidere o título. Sério.</p>

<h2 id="um-anel-para--aprisionar">Um anel para […] aprisionar</h2>

<p>Como já disse, uso o <em>OSX</em> e o <em>Ubuntu</em> diariamente. A “cola” que liga os dois e deixa tudo relativamente indiferente pra mim (junto com o <a href="https://www.gnu.org/software/bash/">bash</a>) é o <a href="https://github.com/technicalpickles/homesick">Homesick</a>. Mantenho meu <a href="https://github.com/augustohp/warwick">castle</a> com muito carinho, que é exatamente tudo que eu gostaria de ter na minha <em>home</em>.</p>

<h3 id="osx">OSX</h3>

<p>Este é um caso de amor <strong>e</strong> ódio.</p>

<p>Tento manter <a href="https://gist.github.com/augustohp/4000099">uma relação atualizada de amores e ódios com relação ao OSX num Gist</a>, contribua você também!</p>

<h3 id="ubuntu">Ubuntu</h3>

<p>Eu gosto de sistemas operacionais debian-like. A experiência de usar um sistema operacional que não tenta te impedir de fazer as coisas (<a href="https://wiki.debian.org/POSIX">e segue um padrão bem estabelecido</a>) é sempre estimulante. Tentar coisas novas é simples como deveria ser, voltar e não se arrepender é gratificante como “tentar” deveria ser em qualquer atividade.</p>

<p>Apesar de uma mania <strong>foda</strong> de foder com os pacotes e seus respectivos padrões (sim, o pleonasmo se faz necessário), compilar as depedências é algo que estou acostumado então nunca sofro mais que o suficiente.</p>

<p>Buscar informações funciona. Sem conexão com internet. Essas duas orações anteriores matam praticamente qualquer distribuição que você quiser comparar contra uma Debian-like.</p>

<h2 id="um-anel-para-todos-encontrar">Um anel para todos encontrar</h2>

<p>Navegadores. Pra mim é uma questão de se decepcionar o suficiente e trocar. Um loop infinito no qual a iteração atual está com o <del><a href="https://getfirefox.com"><strong>firefox</strong></a></del> <a href="http://google.com/crome">Google Chrome</a>.</p>

<p>Abrir mão de todas minhas informações pessoais pro Google em troca do genrenciamento de usuários do <a href="https://google.com/chrome">Chrome</a> é uma mão na roda. Eu só evito dar uma olhada no tráfego de rede da minha máquina, é assustador.</p>

<p>Uso também o <a href="https://vimperator.org">vimperator</a> mais por causa dos motions. Usar um teclado pode parecer coisa de <em>hipster</em>, mas é bem mais produtivo e confortável.</p>

<h2 id="minha-montanha-da-perdição">Minha montanha da perdição</h2>

<p>Já usei bastante coisa pra criar/editar/ler código, valem ser citados:</p>

<ul>
  <li>Zend Studio 5.5 (pré-eclipse)</li>
  <li>Netbeans</li>
  <li>Textmate</li>
</ul>

<p>O mínimo que eu espero de uma ferramenta do tipo:</p>

<ul>
  <li>Busca decente. (No arquivo, no diretório do projeto e regex <em>search</em>)</li>
  <li>Feedback imediato. Se eu digitar, eu quero ver.</li>
  <li>Respeite (facilmente) as diferentes configurações de cada projeto.</li>
  <li>Sintax highligh decente (é incrível como algumas simplesmente ignoram isso).</li>
  <li>Saia do meu caminho.</li>
</ul>

<p>Tendo isso em mente, hoje, fico alternando sem nenhuma regra entre dois: vim e sublime.</p>

<h3 id="sublime-text">Sublime Text</h3>

<p>Comecei a usar ele assim que saiu o Textmate 2, e foi uma grata surpresa.</p>

<ul>
  <li>Abas do chrome: de brinde, todo o gerenciamento de memória.</li>
  <li>CMD+T ou CTRL+P: Era a killer feature do <em>Textmate</em>, na minha opinião.</li>
  <li>Plugins: Package Installer, Git (não funciona no 3), Alignment, alguns de sintaxe e pronto.</li>
  <li>Snnipets e Temas compatíveis com os do Textmate.</li>
  <li>O comando <code class="language-plaintext highlighter-rouge">subl</code></li>
</ul>

<h3 id="vim">Vim</h3>

<p>Tirando toda idéia <a href="https://www.wikihow.com/Tell-if-You-Are-a-Metal-Poser">poser</a> de dizer que uso <a href="https://www.vim.org/">vim</a>, diria que ele é um vício bem vindo. Aprender é uma tarefa constante. Com o <a href="https://www.vim.org/">vim</a> aprendo muito mais do que eu gostaria, mas todos extremamente gratificantes!</p>

<ul>
  <li>Os <a href="https://vimdoc.sourceforge.net/htmldoc/usr_03.html">atalhos de movimentação</a> são <strong>um absurdo de práticos</strong>.</li>
  <li>Disponível em qualquer *nix.</li>
  <li>Ele <strong>realmente</strong> sai do seu caminho.</li>
  <li>Os <a href="https://vimdoc.sourceforge.net/htmldoc/intro.html#Normal">diferentes</a> <a href="http://vimdoc.sourceforge.net/htmldoc/insert.html#Insert">modos</a> são <a href="http://vimdoc.sourceforge.net/htmldoc/cmdline.html#Command-line">realmente</a> uma <a href="http://vimdoc.sourceforge.net/htmldoc/visual.html#Visual">ótima idéia</a>.</li>
  <li>Rápido que é o diabo.</li>
  <li><a href="https://github.com/tpope">Tim pope</a>.</li>
  <li><a href="https://vimdoc.sourceforge.net/htmldoc/diff.html">vim-diff</a>.</li>
</ul>

<h2 id="git">Git</h2>

<p>Depois de começar a usar controle de versões, você simplesmente espera que tudo seja versionado. Com o <code class="language-plaintext highlighter-rouge">git</code> você descobre que “<em>tudo</em>” é muita coisa e agora sim, você quer realmente versionar tudo.</p>

<p>Uso ele pra escrever posts nos blogs, como minha lista de tarefas em vários projetos e não canso de me surpreender com as oportunidades que ele oferece.</p>

<p>É uma das poucas ferramentas que realmente recompensa você pelo tempo que você investiu lendo documentações. Eu sempre me pego buscando na <code class="language-plaintext highlighter-rouge">manpage</code> de algum comando algo que preciso e acabo lendo um pouco mais do que deveria. Acaba que praticamente todo dia descubro algo novo nelas.</p>

<h1 id="vagrant-e-puppet">Vagrant (e Puppet)</h1>

<p>Eu não vou negar que levei anos pra me sentir confortável num ambiente em que eu conseguisse desenvolver usando várias versões do PHP. Passei por coleções de scripts shell, por diferentes instalações e configurações de servidores web, diferentes formas de organizar as mais bizarras dependências até chegar no php-bulid e phpenv.</p>

<p>A satisfação durou alguns meses até chegar o <a href="https://www.vagrantup.com/">Vagrant</a>. Ter uma pequena VM rodando em um ambiente extremamente controlado com baixo uso de memória e muito próximo do ambiente de produção da aplicação é simplesmente imbatível por enquanto. Usar essas VMs diretamente na Amazon? Fritas acompanha senhor?!</p>

<p>Usa o <a href="https://puppetlabs.com/">Puppet</a> e ter o mesmo conjunto de instruções gerando seu ambiente de desenvolvimento e o de produção é um brinde bem vindo. Ainda namoro a idéia de ter algumas dezenas de shell-scripts bem escritos, mas pra mim (o puppet, sua sintaxe bizarra e o mundo bizarro de orquestração dele) é tolerável simplesmente por causa das contribuições de módulos já existentes no <a href="https://forge.puppetlabs.com/">Puppet Forge</a>.</p>

<h1 id="conclusão">Conclusão</h1>

<p>Espero ter apresentado algo que você possa usar ou se identificar no dia a dia.</p>

<p>Já passei pelo sonho de acreditar em ferramentas mágicas. Hoje aprendi que nós fazemos a mágica com as ferramentas que já existem, como por exemplo as que descrevi acima. Eu realmente não preciso de mais nada (sem contar a <em>Internet</em>) além delas pra fazer qualquer coisa.</p>

<p>E você, o que tem usado?</p>

<p>PS: Comente, me manda um <a href="https://twitter.com/augustohp">tweet</a> com suas ferramentas.
PPS: Não tem onde postar? Use um <a href="https://gist.github.com">gist</a> e me passe o link. ;)</p>]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="Desenvolvimento" /><summary type="html"><![CDATA[Gosto de ter meu fluxo de trabalho otimizado: simples e extremamente produtivo. É uma questão de encontrar a melhor solução e ver se ela resiste ao teste do tempo. Talvez por isso me interesse bastante pelo ambiente de trabalho dos outros.]]></summary></entry><entry><title type="html">Exceptions nativas do PHP</title><link href="http://blog.augustopascutti.com/php/exceptions/oo/2013/10/22/PHP_Exceptions.html" rel="alternate" type="text/html" title="Exceptions nativas do PHP" /><published>2013-10-22T00:00:00-02:00</published><updated>2013-10-22T00:00:00-02:00</updated><id>http://blog.augustopascutti.com/php/exceptions/oo/2013/10/22/PHP_Exceptions</id><content type="html" xml:base="http://blog.augustopascutti.com/php/exceptions/oo/2013/10/22/PHP_Exceptions.html"><![CDATA[<p>O <a href="https://php.net" title="PHP: Hipertext Preprocessor">PHP</a> possui <a href="https://www.php.net/manual/en/spl.exceptions.php" title="PHP Manual: SPL Exceptions">algumas Exceptions</a> embutidas que você pode
(e deveria) usar no seu código. Vamos ver como elas se dividem e casos apropriados
pra algumas delas.</p>

<p>Julgo, antes de mais nada, que você sabe o que são e pra que servem as
<a href="https://php.net/exceptions" title="PHP Manual: Exceptions">Exceptions</a> e que elas só fazem sentido dentro de um código
<a href="https://en.wikipedia.org/wiki/Object-oriented_programming" title="Wikipedia: Object Oriented Programming">Orientado a Objetos</a>.</p>

<h1 id="as-exceptions-nativas-do-php">As Exceptions nativas do PHP</h1>

<p>Como você poderia esperar, o <a href="https://php.net" title="PHP: Hipertext Preprocessor">PHP</a> fornece <a href="https://php.net/exceptions" title="PHP Manual: Exceptions">exceptions</a> pras ocasiões mais
comuns, a hierarquia delas é a seguinte:</p>

<ul>
  <li><a href="https://www.php.net/manual/en/class.logicexception.php" title="PHP Manual: Logic Exception">LogicException</a>: <a href="https://www.php.net/manual/en/class.badfunctioncallexception.php" title="PHP Manual: Bad Function Call Exception">BadFunctionCallException</a>, <a href="https://www.php.net/manual/en/class.badmethodcallexception.php" title="PHP Manual: Bad Method Call Exception">BadMethodCallException</a>,
<a href="https://www.php.net/manual/en/class.domainexception.php" title="PHP Manual: Domain Exception">DomainException</a>, <a href="https://www.php.net/manual/en/class.invalidargumentexception.php" title="PHP Manual: Invalid Argument Exception">InvalidArgumentException</a>, <a href="https://www.php.net/manual/en/class.lengthexception.php" title="PHP Manual: Length Exception">LengthException</a>, <a href="https://www.php.net/manual/en/class.outofrangeexception.php" title="PHP Manual: Out of Range Exception">OutOfRangeException</a>.</li>
  <li><a href="https://www.php.net/manual/en/class.runtimeexception.php" title="PHP Manual: Runtime Exception">RuntimeException</a>: <a href="https://www.php.net/manual/en/class.outofboundsexception.php" title="PHP Manual: Out of Bounds Exception">OutOfBoundsException</a>, <a href="https://www.php.net/manual/en/class.overflowexception.php" title="PHP Manual: Overflow Exception">OverflowException</a>,
<a href="https://www.php.net/manual/en/class.rangeexception.php" title="PHP Manual: Range Exception">RangeException</a>, <a href="https://www.php.net/manual/en/class.underflowexception.php" title="PHP Manual: Underflow Exception">UnderflowException</a>, <a href="https://www.php.net/manual/en/class.unexpectedvalueexception.php" title="PHP Manual: Unexpected Value Exception">UnexpecedValueException</a>.</li>
</ul>

<h2 id="logic-exceptions">Logic Exceptions</h2>

<p><a href="https://www.php.net/manual/en/class.logicexception.php" title="PHP Manual: Logic Exception">Conforme o próprio manual do PHP</a>, devem se referir à erros que
poderiam ser identificados no momento de compilação do código. Como o <a href="https://php.net" title="PHP: Hipertext Preprocessor">PHP</a> é
interpretado temos que dar uma convertida nesse pensamento.</p>

<p>Vamos ver, por exemplo, duas <a href="https://www.php.net/manual/en/class.logicexception.php" title="PHP Manual: Logic Exception">LogicException</a>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php
namespace MyApp\DateTime;

class Weekday
{
    private $name;

    public function __construct($intDayOfTheWeek)
    {
        $this-&gt;name = $this-&gt;getNameByNumber($intDayOfTheWeek);
    }

    public function __toString()
    {
        return $this-&gt;name;
    }

    private function getNameByNumber($dayOfTheWeek)
    {
        if (false === is_int($dayOfTheWeek)) {
            $exceptionMessage = 'Integer expected.';
            throw new \InvalidArgumentException($exceptionMessage);
        }

        if ($dayOfTheWeek &lt; 0 || $dayOfTheWeek &gt; 6) {
            $exceptionMessage = 'Integer between 0 (zero) and 6 (six) expected.';
            throw new \OutOfRangeException($exceptionMessage);
        }

        return date('l', strtotime("Sunday + ${dayOfTheWeek} DAYS"));
    }
}
</code></pre></div></div>

<p>Como o <a href="https://php.net" title="PHP: Hipertext Preprocessor">PHP</a> é basicamente uma cola entre diferentes bibliotecas em <a href="https://en.wikipedia.org/wiki/C_language" title="Wikipedia: C Language">C</a>,
além de ser fracamente e dinamicamente tipado; algumas coisas jamais aconteceriam:
como o exemplo acima produzir um erro no momento de interpretação.</p>

<p>Ao passar alguma coisa diferente de um inteiro pra um método
(que só aceita inteiros), o compilador de uma linguagem tipada deria um erro
(assim como o [InvalidArgumentEception][]) acima.</p>

<p>As demais <a href="https://php.net/exceptions" title="PHP Manual: Exceptions">Exceptions</a> são um “brinde”, como a <a href="https://www.php.net/manual/en/class.outofrangeexception.php" title="PHP Manual: Out of Range Exception">OutOfRangeException</a>!
Sabemos qual o <em>range</em> (limite mínimo e máximo) de inteiros, logo podemos lançar
uma [Exception][] (como feito acima) nessas situações.</p>

<p>Um ponto interessante desse grupo de <a href="https://php.net/exceptions" title="PHP Manual: Exceptions">Exceptions</a> é que qualquer uma dentro deste
tipo deve gerar (diretamente) alguma correção no seu código,
<a href="https://www.php.net/manual/en/class.logicexception.php" title="PHP Manual: Logic Exception">como o próprio manual dita</a>.</p>

<h2 id="runtime-exceptions">Runtime Exceptions</h2>

<p>Existem erros e/ou situações que podem ser previstas mas que não deveriam acontecer.
Por definição isso é uma [Exception][]. Mas extrapolando a situação, existem casos
que não podemos controlar em momento de compilação ou na passagem de argumentos, já
que lidamos (na grande maioria dos casos) com informação dinâmica (gravamos e buscamos
informações em Bancos de dados, serviços, etc).</p>

<p>Esse grupo de <a href="https://php.net/exceptions" title="PHP Manual: Exceptions">Exceptions</a> serve pro caso descrito no parágrafo anterior, ou seja:
erros que ocorrem somente na nossa aplicação enquanto ela possui (consome/produz) dados
no ambiente real dela.</p>

<p>Como podemos extender, um caso viável de extensão e criação de uma nova [Exception][]
seria:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;?php
namespace MyApp\Exception;

class RecordNotFound extends \OutOfBoundsException
{
    // noop.
}
</code></pre></div></div>

<p>Sempre que buscarmos um registro, por uma coluna <code class="language-plaintext highlighter-rouge">id</code> por exemplo, e não encontrarmos;
podemos lançar essa [Exception][]. A <a href="https://www.php.net/manual/en/class.outofboundsexception.php" title="PHP Manual: Out of Bounds Exception">OutOfBoundsException</a> pode ser usada sempre que
formos consumir uma chave (de um array, por exemplo) que era deveria existir mas não
existe.</p>

<p>Um outro exemplo de uso pra outra [Exception][] deste grupo seria numa paginação:
sua aplicação (ou algum usuário) tentar acessar uma página que não existe. Lançar uma
<a href="https://www.php.net/manual/en/class.rangeexception.php" title="PHP Manual: Range Exception">RangeException</a> neste caso é viável.</p>

<p>Note que apesar do nome conter <em>range</em>, assim como no exemplo do <a href="https://www.php.net/manual/en/class.outofrangeexception.php" title="PHP Manual: Out of Range Exception">OutOfRangeException</a>,
note a diferença da natureza do erro: no caso do <a href="https://www.php.net/manual/en/class.outofrangeexception.php" title="PHP Manual: Out of Range Exception">OutOfRangeException</a> era possível saber
o que esperar e quais eram os únicos valores válidos. Pra <a href="https://www.php.net/manual/en/class.rangeexception.php" title="PHP Manual: Range Exception">RangeException</a> ocorrer, dependemos
das informações em alguma lugar e do usuário (ou nossa aplicação) utilizar uma página
que não pode ser acessada.</p>

<h2 id="perguntas-frequentes">Perguntas frequentes</h2>

<blockquote>
  <p>Qual a diferença entre a OutOfRangeException e a OutOfBoundException</p>
</blockquote>

<p>Elas são de naturezas (tipos) diferentes:</p>

<ul>
  <li>Uma depende das informações que sua aplicação consome e produz. ([OutOfBoundException][])</li>
  <li>Outra possui valores bem determinados de limite, que não dependem diretamente de informações produzidas. (<a href="https://www.php.net/manual/en/class.outofrangeexception.php" title="PHP Manual: Out of Range Exception">OutOfRangeException</a>)</li>
</ul>

<p>Note, porém que a origem da informação não tem relação direta com a [Exception][]
que você deve utilizar. Pensando nos exemplos dados, se ao querer pegar o dia da semana
a partir de um número que é gravado no banco de dados e no banco existe um 9 (nove)
você ainda deve lançar uma <a href="https://www.php.net/manual/en/class.outofrangeexception.php" title="PHP Manual: Out of Range Exception">OutOfRangeException</a>; mesmo que essa informação tenha sido
produzida e consumida.</p>

<p>Porquê? Porque seu problema foi um problema de validação, um valor inválido não
deveria ter sido produzido em primeira instância. Muito menos ser persistido no
banco de dados. Vá arrumar seu código!</p>

<p>PS: o que não quer dizer que <a href="https://www.php.net/manual/en/class.runtimeexception.php" title="PHP Manual: Runtime Exception">RuntimeException</a>s não devam produzir mudanças no
código.</p>]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="php" /><category term="exceptions" /><category term="oo" /><summary type="html"><![CDATA[O PHP possui algumas Exceptions embutidas que você pode (e deveria) usar no seu código. Vamos ver como elas se dividem e casos apropriados pra algumas delas.]]></summary></entry><entry><title type="html">Um crawler em 5 minutos</title><link href="http://blog.augustopascutti.com/hacks/unix/2013/09/02/Crawler-de-json-com-mongo-em-5-min.html" rel="alternate" type="text/html" title="Um crawler em 5 minutos" /><published>2013-09-02T00:00:00-03:00</published><updated>2013-09-02T00:00:00-03:00</updated><id>http://blog.augustopascutti.com/hacks/unix/2013/09/02/Crawler-de-json-com-mongo-em-5-min</id><content type="html" xml:base="http://blog.augustopascutti.com/hacks/unix/2013/09/02/Crawler-de-json-com-mongo-em-5-min.html"><![CDATA[<p>Eu não sei se é uma prática geral mas eu gosto de ter dados guardados pra quem sabe, algum dia, dominar o mundo?!
Há muito tempo não via uma API que me desse vontade de sugar, vou mostrar o que fiz pra baixar todo conteúdo JSON de uma API pública (que não me impediu de fazer isso).</p>

<h2 id="requisitos">Requisitos</h2>

<p>Já adianto que eu não fiz nenhum milagre, aqui está tudo o que precisa pra esse crawler:</p>

<ul>
  <li><a href="https://www.mongodb.org/">MongoDB</a></li>
  <li><a href="https://en.wikipedia.org/wiki/Bash_%28Unix_shell%29">Bash</a></li>
  <li><a href="https://curl.haxx.se/">cURL</a></li>
</ul>

<h2 id="o-crawler">O Crawler</h2>

<p>A <a href="https://mtgapi.com/">api</a> em questão tem informação de <a href="https://news.ycombinator.com/item?id=6300576">quase</a> todos os cards do <a href="http://www.wizards.com/Magic">Magic: The Gathering</a> em formato <a href="http://json.org">JSON</a> (por isso o MongoBD).</p>

<p>Um dos <em>endpoints</em> é <code class="language-plaintext highlighter-rouge">https://mtgapi.com/api/v1/fetch/id/{id}</code> onde o <code class="language-plaintext highlighter-rouge">{id}</code> pra mim foi um auto incremento até o infinito.</p>

<p>O crawler que usei consiste de uma linha, abaixo vai uma versão extendida (mais fácil de ler):</p>

<pre class="language-bash">
#!/bin/bash
URL="https://mtgapi.com/api/v1/fetch/id/"
for ID in {1..999}; do
    result=$(curl --get --silent -H "User-Agent: BadassBash 0.0.1 (Yep, another crawler)" "${URL}/${ID}" 2&gt; crawler.err)
    echo $result | mongoimport localhost -d magic -c cards
done;
</pre>]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="hacks" /><category term="unix" /><summary type="html"><![CDATA[Eu não sei se é uma prática geral mas eu gosto de ter dados guardados pra quem sabe, algum dia, dominar o mundo?! Há muito tempo não via uma API que me desse vontade de sugar, vou mostrar o que fiz pra baixar todo conteúdo JSON de uma API pública (que não me impediu de fazer isso).]]></summary></entry><entry><title type="html">Mensagens Commit</title><link href="http://blog.augustopascutti.com/desenvolvimento/2012/07/17/Commit-messages.html" rel="alternate" type="text/html" title="Mensagens Commit" /><published>2012-07-17T00:00:00-03:00</published><updated>2012-07-17T00:00:00-03:00</updated><id>http://blog.augustopascutti.com/desenvolvimento/2012/07/17/Commit-messages</id><content type="html" xml:base="http://blog.augustopascutti.com/desenvolvimento/2012/07/17/Commit-messages.html"><![CDATA[<p>Espero (sinceramente) que você use algum sistema de controle de versões. A idéia aqui
é (como o título sugere) expressar a importância das mensagens de commit em um
projeto.</p>

<h2 id="nossa-função">Nossa função</h2>

<p>Expressar nosso objetivo como profissionais é sempre algo delicado de se fazer,
ainda mais algo genérico. Provavelmente essa minha definição mude com o tempo, 
mas atualmente ela seria algo assim:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"Arquitetar um conjunto de necessidades com a finalidade de evoluir da maneira
mais simples e óbvia possível."
</code></pre></div></div>

<p>A <em>expressão</em> tem duas partes, a primeira convém a evolução lógica e inexorável
de um software que (assim como praticamente tudo) surge sempre de uma necessidade.
Não acho que exista nada de muito delicado nem questionável aí.</p>

<p>A segunda parte fala de simplicidade. O ponto delicado aqui é <em>entender</em> o que é
<em>simplicidade</em>.</p>

<h2 id="simplicidade">Simplicidade</h2>

<p>É bem natural pensar que qualquer coisa “<em>grande</em>” seja complexa, assim como é
natural ver algo simples e não esperar resultados magníficos.</p>

<p>Toda uma genialidade é necessária para abstrair algo complexo de maneira simples.
Exemplos disso são: a teoria da gravidade e consequentemente da relatividade e a
web.</p>

<p>A simplicidade é importante porque ela é extremamente acessível. Não é necessário
muito estudo nem habilidade pra entender algo simples, seja qual for esse entendimento.
Entender “<em>algo</em>” não é tão importante e essencial quanto consumir os benefícios
desse mesmo “<em>algo</em>”.</p>

<p>Simplicidade em software é importante por diversos motivos, o que nos interessa
aqui é o ponto específico de que o software precisa ser mantido. Tornar essa 
manutenção uma tarefa simples é uma obrigação e ferramentas pra isso existem várias:
comentários simples, PHPDoc, padrões de codificação, Testes Unitários, 
Testes de Comportamento e (porque não) <strong>mensagens de commit</strong>.</p>

<h2 id="mensagens-de-commit">Mensagens de commit</h2>

<p>Todo código que produzimos é fruto de algum pensamento lógico, por mais ilógico
que ele pareça. Tentamos deixar esse <em>fruto</em> o mais simples possível de se entender,
essa simplicidade é grande responsável pela evolução do software como produto final.</p>

<p>Porém o código tem um limite. Comentários no meio dele mais atrapalham do que ajudam
quando ele é simples o suficiente, eles só são necessários quando o código é
extremamente ineficiente em expressar à um humano seus objetivos.</p>

<p>Lembre-se que (se) você escreve códigos numa linguagem de alta abstração para 
humanos entenderem e não para máquinas. O problema de comunicação com a máquina
já esta resolvido em camadas abstratas mais baixas.</p>

<p>Porém comentários em códigos tem problemas, o mais crítico é a falta de ordem
cronológica neles. Algo que uma mensagem de commit faz naturalmente. E como saber
à que pedaço de código aquela mensagem de commit pertence? Procure por <strong>blame</strong>
no seu gerenciador de versão preferido.</p>

<p>A mensagem de commit deve expressar o objetivo que aquele conjunto de mudanças
têm de maneira clara e objetiva, ela é uma ferramenta fenomenal de discussão
muito pouco utilizada.</p>

<p>Uma mensagem de commit digna de entrar no controle de versões deve responder à
algumas perguntas:</p>

<ul>
  <li>Qual problema ele resolve</li>
  <li>Como o problema é resolvido</li>
  <li>Se necessário, o porquê determinada solução foi escolhida</li>
</ul>

<p>Ela é a melhor forma de comunicação para um desenvolvedor dentro de um projeto.
Esqueça os <em>bug trackers</em>, o GitHub, e-mail, ferramentas de review de código e
demais soluções. As mensagens de commit não substituem elas, mas são a melhor
ponte de comunicação entre os desenvolvedores e códigos já que além de tudo, estão
ligados à eles. Virtualmente (ou fisicamente se você encarar que o sistema de arquivos
é algo físico) e cronologicamente.</p>

<p>Quer saber o que se passava na cabeça de um desenvolvedor ao criar, alterar ou
remover linhas de código? O que você deve procurar como resultado no código e
como ele vai se comportar? As mensagens de commit são ótimas alternativas.
indubitavelmente superiores aos comentários dentro do código.</p>

<h2 id="exemplo">Exemplo</h2>

<p>O [debian][] recentemente (na <em>Jessie</em>) trocou o gerenciador de janelas padrão do
[gnome][] pro [xfce][]. O anúncio pode ser lido, juntamente com as mudanças na
distribuição diretamente <a href="https://salsa.debian.org/installer-team/tasksel/-/commit/dfca406eb694e0ac00ea04b12fc912237e01c9b5">na mensagem de commit</a>.</p>

<p>A mensagem de commit possui:</p>

<ul>
  <li>A motivação da mudança.</li>
  <li>Qual foi a mudança, além do <em>diff</em> de código deixar ela bem explícita.</li>
  <li>Quais os casos em que esse commit pode ser revertido.</li>
  <li>Qual o impacto do commit, para os usuários. (O valor entregue)</li>
</ul>

<p>Hoje, segundo meus julgamentos, ele já é um excelente commit mas daqui alguns 
anos ela pode muito bem ser usada (também em conjunto com as mensagens de commit
futuras relacionadas aos mesmos arquivos) pra contar a história do projeto: as decisões e 
o porquê delas. Evitando erros futuros ou estimulando decisões parecidas.</p>

<h2 id="conclusão">Conclusão</h2>

<p>Espero ter conseguido mostrar a importância que uma simples mensagem de commit
tem. O quão simples e vital é ter isso em qualquer projeto.</p>

<p>Se tudo for como eu espero, todas suas próximas mensagens de commit serão algo
que valha ser lido ao invés de ser algum pedaço de texto que alguma ferramenta
estúpida requer repetidamente a fim de fazer algo.</p>]]></content><author><name>Augusto Pascutti</name><email>augusto.hp@gmail.com</email></author><category term="Desenvolvimento" /><summary type="html"><![CDATA[Espero (sinceramente) que você use algum sistema de controle de versões. A idéia aqui é (como o título sugere) expressar a importância das mensagens de commit em um projeto.]]></summary></entry></feed>