<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Keep Learning &#187; Test-Driven Development</title>
	<atom:link href="http://blog.lucashungaro.com/category/test-driven-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.lucashungaro.com</link>
	<description>Conhecimento nunca é o bastante</description>
	<lastBuildDate>Tue, 10 Apr 2012 17:18:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>SOLID Ruby: Liskov Substitution Principle e Interface Segregation Principle</title>
		<link>http://blog.lucashungaro.com/2011/05/18/solid-ruby-liskov-substitution-principle-e-interface-segregation-principle/</link>
		<comments>http://blog.lucashungaro.com/2011/05/18/solid-ruby-liskov-substitution-principle-e-interface-segregation-principle/#comments</comments>
		<pubDate>Wed, 18 May 2011 22:38:49 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=416</guid>
		<description><![CDATA[Para fechar os cinco princípios do SOLID, vamos falar sobre os dois princípios restantes: Liskov Substitution Principle (LSP) e Interface Segregation Principle (ISP). Como já foi falado anteriormente, esses princípios foram formulados com linguagens estáticas em mente e, por essa razão, precisam ser &#8220;adaptados&#8221; para que sejam aplicados em linguagens dinâmicas. Note que, em suas [...]]]></description>
			<content:encoded><![CDATA[<p>Para fechar os cinco princípios do SOLID, vamos falar sobre os dois princípios restantes: <a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle">Liskov Substitution Principle</a> (LSP) e <a href="http://en.wikipedia.org/wiki/Interface_segregation_principle">Interface Segregation Principle</a> (ISP).</p>
<p>Como já foi falado anteriormente, esses princípios foram formulados com linguagens estáticas em mente e, por essa razão, precisam ser &#8220;adaptados&#8221; para que sejam aplicados em linguagens dinâmicas. Note que, em suas formas originais, esses princípios em geral recorrem a técnicas como herança para contornar as &#8220;amarras&#8221; do sistema estático de tipos.</p>
<p>No caso do LSP temos mais um exemplo disso. Em sua forma original ele é definido da seguinte forma:</p>
<blockquote><p>If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2, then S is a subtype of T.</p></blockquote>
<p>O que foi &#8220;traduzido&#8221; para o OOP da seguinte forma:</p>
<blockquote><p>Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.</p></blockquote>
<p>Em Ruby isso não é muito problemático pois, como sabemos, não estamos presos à tipos. O importante, como já vimos com o OCP, é manter a mesma interface, de forma que se precisarmos modificar alguma entidade, as demais entidades que dela dependem não precisem ser modificadas.</p>
<p>Além da interface, também precisamos prestar atenção ao comportamento. Modificações no comportamento podem fazer com que clientes da entidade sofram consequências inesperadas.</p>
<p>Já o ISP é definido da seguinte forma:</p>
<blockquote><p>Clients should not be forced to depend upon interfaces that they do not use.</p></blockquote>
<p>Isso quer dizer que um cliente (entidade que depende de alguma outra) não deve depender de interfaces não utilizadas por ele pois, em caso de modificação nessa interface, mesmo que o cliente em questão não a utilize, também terá que ser modificado.</p>
<p>Em linguagens estáticas há uma série de técnicas e artifícios para atingir isso. Em Ruby, o Duck Typing nos entrega esse princípio &#8220;de graça&#8221;, já que cada entidade depende apenas da interface que utiliza, independente do restante (e de tipos). Apesar disso, devemos sempre buscar entidades com interfaces coesas e bem delimitadas, evitando que sejam muito extensas e genéricas (o SRP se aplica aqui também). Aplicar o design pattern <a href="http://en.wikipedia.org/wiki/Adapter_pattern">Adapter</a> é uma boa forma de respeitar isso.</p>
<p>Bem, é fácil perceber que os últimos três princípios discutidos (OCP, LSP e ISP) lidam diretamente com formas de garantir interfaces estáveis para atingirmos o nosso objetivo de evitar que mudanças no código gerem um &#8220;efeito dominó&#8221; e façam com que tenhamos que alterar várias partes do software.</p>
<p>Mas, já que não temos estruturas como Interfaces e classes abstratas para garantir que estamos respeitando a interface definida, como garantir a aplicação desses princípios? Bom, há algumas formas para fazer isso. Você pode &#8220;emular&#8221; uma interface da seguinte forma:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> MyInterface
  <span style="color:#9966CC; font-weight:bold;">def</span> method_1
    <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;abstract method called&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> method_2
    <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;abstract method called&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># and so on...</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> MyClass <span style="color:#006600; font-weight:bold;">&lt;</span> MyInterface
  <span style="color:#9966CC; font-weight:bold;">def</span> method_1
    <span style="color:#008000; font-style:italic;"># do something</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> method_2
    <span style="color:#008000; font-style:italic;"># do something</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Obs: também pode ser feito através de módulos e mixins ao invés de herança.</p>
<p>Isso funciona, mas não é muito o estilo Ruby, certo? A maneira que prefiro fazer é através de specs. Sempre que vou criar um wrapper/adapter ou qualquer estrutura que precise de uma interface estável mesmo quando o código encapsulado for modificado, crio um grupo de &#8220;specs de interface&#8221; e uso ela para toda estrutura que precise implementar a mesma.</p>
<p>Por exemplo, poderíamos escrever um cliente para o Twitter e escrever nosso código de modo que a gem que consome a API do serviço possa ser trocada sem maiores consequências:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">&nbsp;
<span style="color:#008000; font-style:italic;"># app/adapters/twitter_gem_adapter.rb</span>
<span style="color:#9966CC; font-weight:bold;">class</span> TwitterGemAdapter
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">timeline</span><span style="color:#006600; font-weight:bold;">&#40;</span>page=<span style="color:#006666;">1</span>, per_page=<span style="color:#006666;">5</span>, since_id = <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    options = <span style="color:#006600; font-weight:bold;">&#123;</span>:page <span style="color:#006600; font-weight:bold;">=&gt;</span> page, <span style="color:#ff3333; font-weight:bold;">:count</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> per_page<span style="color:#006600; font-weight:bold;">&#125;</span>
    options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:since_id</span><span style="color:#006600; font-weight:bold;">&#93;</span> = since_id <span style="color:#9966CC; font-weight:bold;">if</span> since_id
&nbsp;
    Twitter.<span style="color:#9900CC;">home_timeline</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">update</span><span style="color:#006600; font-weight:bold;">&#40;</span>text<span style="color:#006600; font-weight:bold;">&#41;</span>
    Twitter.<span style="color:#9900CC;">update</span><span style="color:#006600; font-weight:bold;">&#40;</span>text<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">reply</span><span style="color:#006600; font-weight:bold;">&#40;</span>in_reply_to_status_id, text<span style="color:#006600; font-weight:bold;">&#41;</span>
    Twitter.<span style="color:#9900CC;">update</span><span style="color:#006600; font-weight:bold;">&#40;</span>text, <span style="color:#ff3333; font-weight:bold;">:in_reply_to_status_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> in_reply_to_status_id<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">retweet</span><span style="color:#006600; font-weight:bold;">&#40;</span>tweet_id<span style="color:#006600; font-weight:bold;">&#41;</span>
    Twitter.<span style="color:#9900CC;">retweet</span><span style="color:#006600; font-weight:bold;">&#40;</span>tweet_id<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">favorite</span><span style="color:#006600; font-weight:bold;">&#40;</span>tweet_id<span style="color:#006600; font-weight:bold;">&#41;</span>
    Twitter.<span style="color:#9900CC;">favorite_create</span><span style="color:#006600; font-weight:bold;">&#40;</span>tweet_id<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># spec/support/shared_examples/twitter_adapter_examples.rb</span>
<span style="color:#9966CC; font-weight:bold;">module</span> TwitterAdapterExamples
  shared_examples_for <span style="color:#996600;">&quot;any adapter for a twitter api gem&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    it <span style="color:#006600; font-weight:bold;">&#123;</span> should respond_to<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:timeline</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
    it <span style="color:#006600; font-weight:bold;">&#123;</span> should respond_to<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:update</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
    it <span style="color:#006600; font-weight:bold;">&#123;</span> should respond_to<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:reply</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
    it <span style="color:#006600; font-weight:bold;">&#123;</span> should respond_to<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:retweet</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
    it <span style="color:#006600; font-weight:bold;">&#123;</span> should respond_to<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:favorite</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># spec/adapters/twitter_gem_adapter_spec.rb</span>
describe TwitterGemAdapter <span style="color:#9966CC; font-weight:bold;">do</span>
  context <span style="color:#996600;">&quot;API contract&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    subject <span style="color:#006600; font-weight:bold;">&#123;</span> TwitterGemAdapter <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
    it_behaves_like <span style="color:#996600;">&quot;any adapter for a twitter api gem&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># other specs ...</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Aqui utilizamos a feature de &#8220;exemplos compartilhados&#8221; do RSpec, mas isso pode ser feito facilmente em outros frameworks. O importante é que, através dessas specs, garantimos que qualquer adapter implemente a mesma interface. Nesse caso cuidamos apenas disso, mas qualquer comportamento comum também pode ser especificado da mesma forma.</p>
<p>Material recomendado:</p>
<ul>
<li><a href="http://blog.objectmentor.com/articles/2008/09/06/the-liskov-substitution-principle-for-duck-typed-languages">The Liskov Substitution Principle for &#8220;Duck-Typed&#8221; Languages</a></li>
<li><a href="http://confreaks.net/videos/185-rubyconf2009-solid-ruby">SOLID Ruby, by Jim Weirich &#8211; RubyConf 2009</a></li>
<li><a href="http://confreaks.net/videos/240-goruco2009-solid-object-oriented-design">SOLID Object-Oriented Design, by Sandi Metz, GoRuCo 2009</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2011/05/18/solid-ruby-liskov-substitution-principle-e-interface-segregation-principle/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SOLID Ruby: Dependency Inversion Principle</title>
		<link>http://blog.lucashungaro.com/2011/05/09/solid-ruby-dependency-inversion-principle/</link>
		<comments>http://blog.lucashungaro.com/2011/05/09/solid-ruby-dependency-inversion-principle/#comments</comments>
		<pubDate>Tue, 10 May 2011 02:57:16 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=410</guid>
		<description><![CDATA[Continuando os artigos sobre SOLID, vamos falar um pouco sobre o Dependency Inversion Principle. Em resumo, esse princípio diz que os componentes devem depender de abstrações ao invés de implementações. Bom, isso faz muito sentido em linguagens estáticas como Java, onde há estruturas como Interfaces, classes abstratas e outras parafernalhas. No final, na minha modesta [...]]]></description>
			<content:encoded><![CDATA[<p>Continuando os artigos sobre SOLID, vamos falar um pouco sobre o <a href="http://en.wikipedia.org/wiki/Dependency_inversion_principle">Dependency Inversion Principle</a>. Em resumo, esse princípio diz que os componentes devem depender de abstrações ao invés de implementações.</p>
<p>Bom, isso faz muito sentido em linguagens estáticas como Java, onde há estruturas como Interfaces, classes abstratas e outras parafernalhas. No final, na minha modesta opinião, o código torna-se um espetáculo bizarro de indireção e pode mais confundir do que ajudar se você não for cuidadoso. Mas e nas linguagens dinâmicas?</p>
<p>É comum ouvir que, quando você utiliza uma linguagem que contém Duck Typing (a característica que mais gosto no Ruby), você obtém os benefícios do DIP &#8220;de graça&#8221;. Isso não é bem verdade. Você os obtém de graça somente se <em>pedir com jeitinho</em>. <img src='http://blog.lucashungaro.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>O que quero dizer com isso?</p>
<p>Vamos ao exemplo do artigo anterior em sua última versão:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Game <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:category</span>
  validates_presence_of <span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#ff3333; font-weight:bold;">:category_id</span>, <span style="color:#ff3333; font-weight:bold;">:description</span>,
                        <span style="color:#ff3333; font-weight:bold;">:price</span>, <span style="color:#ff3333; font-weight:bold;">:platform</span>, <span style="color:#ff3333; font-weight:bold;">:year</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GamePriceService
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:game</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># we could use a config file</span>
  BASE_URL = <span style="color:#996600;">&quot;http://thegamedatabase.com/api/game&quot;</span>
  API_KEY = <span style="color:#996600;">&quot;ek2o1je&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">game</span> = game
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> get_price
    data = <span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{BASE_URL}/#{game.name}/price?api_key=#{API_KEY}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    JsonParserLib.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>data<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GamePrinter
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:game</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">game</span> = game
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#CC0066; font-weight:bold;">print</span>
    price_service = GamePriceService.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&lt;&lt;-</span>EOF
      <span style="color:#008000; font-style:italic;">#{game.name}, #{game.platform}, #{game.year} </span>
      current value is <span style="color:#008000; font-style:italic;">#{price_service.get_price[:value]}</span>
    EOF
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Esse código possui algumas <strong>dependências rígidas</strong>. Chamamos as classes GamePriceService e JsonParserLib explicitamente dentro de GamePrinter#print e GamePriceService#get_price, respectivamente. Note que, apesar do Duck Typing nos permitir utilizar componentes com uma determinada interface independente de tipo, fizemos com que nossas classes fiquem amarradas à alguns tipos através dessas dependências.</p>
<p>Uma forma de se aproveitar dos benefícios do Duck Typing e, assim, conseguir &#8220;de graça&#8221; as vantagens do DIP, é tornar nossas dependências transparentes. Enquanto linguagens estáticas costumam se utilizar (embora isso não seja obrigatório) de complexas bibliotecas de injeção de dependência para fazer isso (ah, meus tempos de Java e Spring <img src='http://blog.lucashungaro.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ), em Ruby isso é tão simples quanto passar um parâmetro:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Game <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:category</span>
  validates_presence_of <span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#ff3333; font-weight:bold;">:category_id</span>, <span style="color:#ff3333; font-weight:bold;">:description</span>,
                        <span style="color:#ff3333; font-weight:bold;">:price</span>, <span style="color:#ff3333; font-weight:bold;">:platform</span>, <span style="color:#ff3333; font-weight:bold;">:year</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GamePriceService
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:game</span>, <span style="color:#ff3333; font-weight:bold;">:json_parser</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># we could use a config file</span>
  BASE_URL = <span style="color:#996600;">&quot;http://thegamedatabase.com/api/game&quot;</span>
  API_KEY = <span style="color:#996600;">&quot;ek2o1je&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>game, json_parser = JsonParserLib<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">game</span> = game
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">json_parser</span> = json_parser
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> get_price
    data = <span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{BASE_URL}/#{game.name}/price?api_key=#{API_KEY}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    json_parser.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>data<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GamePrinter
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:game</span>, <span style="color:#ff3333; font-weight:bold;">:game_webservice</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>game, game_webservice = GamePriceService<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">game</span> = game
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">game_webservice</span> = game_webservice
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#CC0066; font-weight:bold;">print</span>
    price_service = game_webservice.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&lt;&lt;-</span>EOF
      <span style="color:#008000; font-style:italic;">#{game.name}, #{game.platform}, #{game.year} </span>
      current value is <span style="color:#008000; font-style:italic;">#{price_service.get_price[:value]}</span>
    EOF
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Usage example:</span>
game = Game.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>some_game_data<span style="color:#006600; font-weight:bold;">&#41;</span>
webservice = GamePriceService.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
game.<span style="color:#9900CC;">price</span> = webservice.<span style="color:#9900CC;">get_price</span>
&nbsp;
GamePrinter.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#CC0066; font-weight:bold;">print</span></pre></div></div>

<p>Aqui escolhemos passar essas dependências através dos construtores das classes. Dessa forma, ficamos livres da dependência de tipo e passamos a depender apenas de uma interface. Basta que a classe passada no construtor responda aos métodos que utilizamos e não teremos problema. Outra forma seria passar as dependências apenas para os métodos que as utilizam:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Game <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  belongs_to <span style="color:#ff3333; font-weight:bold;">:category</span>
  validates_presence_of <span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#ff3333; font-weight:bold;">:category_id</span>, <span style="color:#ff3333; font-weight:bold;">:description</span>,
                        <span style="color:#ff3333; font-weight:bold;">:price</span>, <span style="color:#ff3333; font-weight:bold;">:platform</span>, <span style="color:#ff3333; font-weight:bold;">:year</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GamePriceService
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:game</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># we could use a config file</span>
  BASE_URL = <span style="color:#996600;">&quot;http://thegamedatabase.com/api/game&quot;</span>
  API_KEY = <span style="color:#996600;">&quot;ek2o1je&quot;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">game</span> = game
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> get_price<span style="color:#006600; font-weight:bold;">&#40;</span>json_parser = JsonParserLib<span style="color:#006600; font-weight:bold;">&#41;</span>
    data = <span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{BASE_URL}/#{game.name}/price?api_key=#{API_KEY}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    json_parser.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>data<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GamePrinter
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:game</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">game</span> = game
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#CC0066; font-weight:bold;">print</span><span style="color:#006600; font-weight:bold;">&#40;</span>game_webservice = GamePriceService<span style="color:#006600; font-weight:bold;">&#41;</span>
    price_service = game_webservice.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&lt;&lt;-</span>EOF
      <span style="color:#008000; font-style:italic;">#{game.name}, #{game.platform}, #{game.year} </span>
      current value is <span style="color:#008000; font-style:italic;">#{price_service.get_price[:value]}</span>
    EOF
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Usage example:</span>
game = Game.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>some_game_data<span style="color:#006600; font-weight:bold;">&#41;</span>
webservice = GamePriceService.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>
game.<span style="color:#9900CC;">price</span> = webservice.<span style="color:#9900CC;">get_price</span>
&nbsp;
GamePrinter.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>game<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#CC0066; font-weight:bold;">print</span></pre></div></div>

<p>É uma maneira melhor para evitarmos construtores muito complexos quando esse for o caso. Uma vantagem adicional é obtida através da utilização de valores padrão para os parâmetros. Desta forma, a não ser que queiramos utilizar alguma dependência não-padrão, as dependências ficam totalmente transparentes.</p>
<p>Mais uma vantagem é no momento de escrever testes. Passando dependências dessa maneira, é muito fácil criar objetos dublês e utilizá-los para facilitar o processo (tornar a execução mais rápida, evitar o uso de webservices reais etc). Um exemplos simples e eficiente pode ser <a href="http://www.slideshare.net/lucashungaro/ruby-confbr">visto aqui</a>. (slides 34, 35 e 36)</p>
<p>Em geral, se você não conseguir substituir uma dependência por um dublê em suas especificações, seu código está muito rígido e pode se beneficiar da aplicação desse princípio.</p>
<p>Leitura adicional:</p>
<p>  <a href="http://patmaddox.com/blog/2008/1/27/make-your-dependencies-translucent-with-default-parameters.html">Make Your Dependencies Translucent with Default Parameters</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2011/05/09/solid-ruby-dependency-inversion-principle/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Dica rápida: formatação da saída do Test::Unit com a gem turn</title>
		<link>http://blog.lucashungaro.com/2011/01/26/dica-rapida-formatacao-da-saida-do-test-unit-com-a-gem-turn/</link>
		<comments>http://blog.lucashungaro.com/2011/01/26/dica-rapida-formatacao-da-saida-do-test-unit-com-a-gem-turn/#comments</comments>
		<pubDate>Wed, 26 Jan 2011 20:06:23 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Gem]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=402</guid>
		<description><![CDATA[Recentemente voltei a brincar com um pet project para atualizá-lo do Rails 2.3 para o Rails 3. A suíte de testes do projeto foi escrita com Test::Unit e Shoulda e, quando a executei sob Ruby 1.9.2, vi que a saída não estava formatada, isto é, não havia alinhamento, as falhas não ficavam em vermelho e [...]]]></description>
			<content:encoded><![CDATA[<p>Recentemente voltei a brincar com um pet project para atualizá-lo do Rails 2.3 para o Rails 3. A suíte de testes do projeto foi escrita com Test::Unit e Shoulda e, quando a executei sob Ruby 1.9.2, vi que a saída não estava formatada, isto é, não havia alinhamento, as falhas não ficavam em vermelho e os sucessos em verde. Pelo que me lembro, quando rodava esses testes no Ruby 1.8, a saída era formatada e com cores. Provavelmente algo que foi retirado do Ruby 1.9, talvez na mudança de Test::Unit para MiniTest.</p>
<p>Bem, não me preocupei muito com o motivo disso. Busquei algumas maneiras de formatar essa saída e, entre outras, encontrei a gem <a href="https://github.com/TwP/turn">turn</a>. Configurei-a no Gemfile do projeto e tudo funcionou perfeitamente de primeira, sem nenhum incômodo. Além da formatação, uma feature interessante é que, ao invés de mostrar pontinhos e letras (ex: …..F…F.), o turn vai mostrando as descrições dos testes e seu status (passou/falhou) à medida que a suite é executada. Feedback bem mais útil.</p>
<p>Veja um exemplo de como fica a formatação através desse link: <a href="http://d.pr/mWPe">http://d.pr/mWPe</a> (assim não quebro todo o layout do blog). <img src='http://blog.lucashungaro.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2011/01/26/dica-rapida-formatacao-da-saida-do-test-unit-com-a-gem-turn/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cuidado com o DRY nos seus testes</title>
		<link>http://blog.lucashungaro.com/2009/09/02/cuidado-com-o-dry-nos-seus-testes/</link>
		<comments>http://blog.lucashungaro.com/2009/09/02/cuidado-com-o-dry-nos-seus-testes/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 17:31:21 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=283</guid>
		<description><![CDATA[Don&#8217;t Repeat Yourself é um dos princípios de desenvolvimento de software mais &#8220;badalados&#8221; nos últimos tempos. O problema é que, como tudo que se torna popular, isso acaba sendo abusado. Numa tentativa de criar código limpo é comum criar código difícil de entender. Isso afeta principalmente os testes. Testes devem ser extremamente legíveis. Não deve [...]]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">Don&#8217;t Repeat Yourself</a> é um dos princípios de desenvolvimento de software mais &#8220;badalados&#8221; nos últimos tempos. O problema é que, como tudo que se torna popular, isso acaba sendo abusado. Numa tentativa de criar código limpo é comum criar código difícil de entender. Isso afeta principalmente os testes.</p>
<p>Testes devem ser extremamente legíveis. Não deve existir sobrecarga cognitiva, isto é, não deve ser necessário entender o código do teste para então entender o comportamento que ele especifica &#8211; isso deve ficar claro rapidamente. Exemplos de sobrecarga são a necessidade de &#8220;ficar pulando&#8221; entre vários arquivos ou &#8220;descriptografando&#8221; lógica mágica para entender o código do teste.</p>
<p>É fácil, então, identificar dois tipos de recursos que podem causar problemas no entendimento dos testes &#8211; há uma tênue linha separando o bom e o mal uso deles: macros e &#8220;magia negra&#8221; em forma de código Ruby.</p>
<p>Macros devem ser utilizadas com muito cuidado. É interessante utilizar macros que encapsulam código simples para economizar tempo na criação dos testes, como essa macro para especificar ações autenticadas com o Authlogic:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> login_as<span style="color:#006600; font-weight:bold;">&#40;</span>user<span style="color:#006600; font-weight:bold;">&#41;</span>
  activate_authlogic   <span style="color:#008000; font-style:italic;">#this is from Authlogic::TestCase</span>
  UserSession.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span>:email <span style="color:#006600; font-weight:bold;">=&gt;</span> user.<span style="color:#9900CC;">email</span>, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> user.<span style="color:#9900CC;">password</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Macros com muito código ou que utilizam outras macros devem ser evitadas.</p>
<p>Um problema provavelmente mais grave é a utlização de algumas técnicas de &#8220;magia negra&#8221; no código. Aquela técnica super obscura e bacana envolvendo o Enumerable que você viu num blog esses dias não deve ser usada nos testes (nem na lógica de negócios, na minha opinião): foque sempre nos idiomas comuns da linguagem. Por simples falha da minha memória agora, segue um exemplo bobo, mas válido:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># truque menos conhecido</span>
<span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#40;</span>this is a test<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">*</span> <span style="color:#996600;">&quot;, &quot;</span>    <span style="color:#008000; font-style:italic;">#=&gt; &quot;this, is, a, test&quot;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># idioma comum</span>
<span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#40;</span>this is a test<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;, &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>    <span style="color:#008000; font-style:italic;">#=&gt; &quot;this, is, a, test&quot;</span></pre></div></div>

<p>Os testes, quando usados corretamente, também são a porta de entrada de novos desenvolvedores ao código já existente na aplicação. Pode ser que sua equipe seja formada por Rubistas experientes que conheçam todos os truques envolvidos, mas a adaptação de um profissional com menos experiência na linguagem pode ser muito facilitada por testes com código simples e altamente legível, mesmo que isso &#8220;custe&#8221; alguma repetição ou uso de construções mais comuns.</p>
<p>A conclusão é: em todo seu código e principalmente nos testes, evite o uso de macros que escondem muito código ou lógica relevante ao comportamento especificado e também prefira idiomas comuns, mesmo que você saiba técnicas &#8220;ninja&#8221; da linguagem.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2009/09/02/cuidado-com-o-dry-nos-seus-testes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Você confia em métricas?</title>
		<link>http://blog.lucashungaro.com/2009/08/31/voce-confia-em-metricas/</link>
		<comments>http://blog.lucashungaro.com/2009/08/31/voce-confia-em-metricas/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 17:29:23 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Opinião]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=154</guid>
		<description><![CDATA[Usar métricas no seu código é uma boa prática. Existem várias ferramentas que provém métricas muito interessantes e ferramentas, como o metric_fu, que integram várias delas. No entanto, é preciso ter bastante cuidado. Métricas são como muletas: muito úteis quando você não consegue andar sem a ajuda delas mas, se você utilizá-las sem necessidade, vai [...]]]></description>
			<content:encoded><![CDATA[<p>Usar métricas no seu código é uma boa prática. Existem várias ferramentas que provém métricas muito interessantes e ferramentas, como o metric_fu, que integram várias delas.</p>
<p>No entanto, é preciso ter bastante cuidado. Métricas são como muletas: muito úteis quando você não consegue andar sem a ajuda delas mas, se você utilizá-las sem necessidade, vai enfraquecer suas pernas.</p>
<p>Um bom exemplo disso é uma métrica muito utilizada por quem escreve testes: a cobertura de código. É uma ferramenta muito útil quando é preciso &#8220;correr atrás&#8221; do prejuízo, isto é, adicionar testes a código sem cobertura. Nesse caso, é prática comum estabelecer uma porcentagem de cobertura a ser atingida dentro de um prazo limitado. Mas, se você pratica BDD/TDD consistentemente e não deixa código importante sem cobertura, é realmente necessário confirmar isso com um gráfico ou uma porcentagem?</p>
<p>O uso e confiança cega em métricas mesmo sem necessidade de um amparo como esse pode levar à má aplicação da técnica do desenvolvimento guiado por testes, já que ela passa a ser baseada em um número artificial &#8211; é muito fácil ter 100% de cobertura de código com uma suíte de testes ruim. Antes uma suite boa mas que, conscientemente, não passa por cada linha de código do que uma suite que execute cada linha, mas seja um lixo como especificação e ferramenta de refactoring.</p>
<p>Mais um exemplo de fragilidade fica claro no famoso e cantado aos quatro ventos <em>code to test ratio</em>: ao utilizar um framework de testes verboso, é fácil obter uma razão de linhas de teste por linhas de código muito maior do que utilizando um framework mais compacto ou macros. Me desculpe quem utiliza e divulga esse número como algum indicativo de qualidade, mas essa medida é simplesmente ridícula, além de totalmente ilusória.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2009/08/31/voce-confia-em-metricas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testes envolvendo tempo: usando a gem time-warp</title>
		<link>http://blog.lucashungaro.com/2009/08/28/testes-envolvendo-tempo-usando-a-gem-time-warp/</link>
		<comments>http://blog.lucashungaro.com/2009/08/28/testes-envolvendo-tempo-usando-a-gem-time-warp/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 16:46:23 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=269</guid>
		<description><![CDATA[É comum que precisemos &#8220;manipular o tempo&#8221; quando escrevendo testes para código cujo comportamento depende do momento no tempo. Uma técnica comum é utilizar um mock ou stub na classe Time do Ruby para manipular o horário de acordo com o desejado. Isso vai contra um princípio importante do uso de fake objects em testes: [...]]]></description>
			<content:encoded><![CDATA[<p>É comum que precisemos &#8220;manipular o tempo&#8221; quando escrevendo testes para código cujo comportamento depende do momento no tempo.</p>
<p>Uma técnica comum é utilizar um mock ou stub na classe Time do Ruby para manipular o horário de acordo com o desejado. Isso vai contra um princípio importante do uso de fake objects em testes: &#8220;<a target="_blank" href="http://www.infoq.com/news/2008/08/Mock-Roles-Pryce-and-Freeman">Não use fakes em objetos que não são seus</a>&#8220;. Na maioria do tempo isso pode não causar problemas, mas alterar o comportamento de uma classe usada internamente pela linguagem não soa bem e pode causar bugs difíceis de rastrear.</p>
<p>Aí entra a gem <a target="_blank" href="http://github.com/iridesco/time-warp/tree/master">time-warp</a>. Ela ainda trabalha sobre as classes do Ruby, mas provê uma camada específica para testes para todo código executado em um bloco definido pelo programador. Um exemplo de uso (da <a target="_blank" href="http://twtapp.info/">nossa aplicação feita para o Rails Rumble</a>):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">it <span style="color:#996600;">&quot;should only silence tweets with the desired word inside the configured time interval&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  pretend_now_is<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>.<span style="color:#9900CC;">utc</span>.<span style="color:#9900CC;">beginning_of_day</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span>.<span style="color:#9900CC;">hour</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    tweet1.<span style="color:#9900CC;">sent_at</span> = <span style="color:#006666;">2</span>.<span style="color:#9900CC;">minutes</span>.<span style="color:#9900CC;">ago</span>
    tweet2.<span style="color:#9900CC;">sent_at</span> = <span style="color:#006666;">32</span>.<span style="color:#9900CC;">minutes</span>.<span style="color:#9900CC;">from_now</span>
    tweet3.<span style="color:#9900CC;">sent_at</span> = <span style="color:#006666;">1</span>.<span style="color:#9900CC;">hour</span>.<span style="color:#9900CC;">from_now</span>
&nbsp;
    collection = <span style="color:#006600; font-weight:bold;">&#91;</span>tweet1, tweet2, tweet3<span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
    Silencer.<span style="color:#9900CC;">apply</span><span style="color:#006600; font-weight:bold;">&#40;</span>collection, <span style="color:#006600; font-weight:bold;">&#123;</span>:word <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;soccer&quot;</span>, :<span style="color:#9966CC; font-weight:bold;">until</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">30</span>.<span style="color:#9900CC;">minutes</span>.<span style="color:#9900CC;">from_now</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  tweet1.<span style="color:#9900CC;">should</span> be_filtered
  tweet2.<span style="color:#9900CC;">should</span> be_filtered
  tweet3.<span style="color:#9900CC;">should_not</span> be_filtered
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>A gem adiciona o método &#8220;pretend_now_is&#8221;, que recebe um parâmetro com o horário desejado e um bloco. Dentro desse bloco, todo código executado é &#8220;transportado no tempo&#8221; para o horário definido. Além de tornar a manipulação das classes de tempo mais segura, o código fica muito mais elegante.</p>
<p>Veja mais detalhes no <a target="_blank" href="http://github.com/iridesco/time-warp/blob/884623fec90687c7f3c28b8e8074a39c96946cbb/README.md">README da gem</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2009/08/28/testes-envolvendo-tempo-usando-a-gem-time-warp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Slides e notas da minha sessão no FISL10</title>
		<link>http://blog.lucashungaro.com/2009/06/25/slides-e-notas-da-minha-sessao-no-fisl10/</link>
		<comments>http://blog.lucashungaro.com/2009/06/25/slides-e-notas-da-minha-sessao-no-fisl10/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 16:52:25 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Apresentações]]></category>
		<category><![CDATA[Eventos]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=228</guid>
		<description><![CDATA[Pessoal, abaixo está o link para download, em formato PDF, dos slides com notas que eu utilizei na minha sessão ontem no FISL10, entitulada &#8220;TDD e Rails: Mais rápido, mais forte e melhor&#8221;. Download. Obrigado a todos que apareceram por lá! Qualquer feedback é muito bem-vindo.]]></description>
			<content:encoded><![CDATA[<p>Pessoal, abaixo está o link para download, em formato PDF, dos slides com notas que eu utilizei na minha sessão ontem no FISL10, entitulada &#8220;TDD e Rails: Mais rápido, mais forte e melhor&#8221;.</p>
<p><a href="http://makemesimple.com/files/fisl10.pdf" target="_blank">Download</a>.</p>
<p>Obrigado a todos que apareceram por lá! Qualquer feedback é muito bem-vindo. <img src='http://blog.lucashungaro.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2009/06/25/slides-e-notas-da-minha-sessao-no-fisl10/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Testes devem revelar a intenção do código</title>
		<link>http://blog.lucashungaro.com/2009/05/08/testes-devem-revelar-a-intencao-do-codigo/</link>
		<comments>http://blog.lucashungaro.com/2009/05/08/testes-devem-revelar-a-intencao-do-codigo/#comments</comments>
		<pubDate>Fri, 08 May 2009 22:04:13 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Extreme Programming]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=138</guid>
		<description><![CDATA[Essa frase não é novidade para ninguém &#8211; ou, pelo menos, não deveria ser. No entanto, é muito mais difícil fazer isso acontecer do que falar sobre o assunto. É muito bom que a mentalidade de testes esteja sendo cada vez mais difundida. Com isso, desenvolvem-se as abordagens às práticas de desenvolvimento orientado por testes [...]]]></description>
			<content:encoded><![CDATA[<p>Essa frase não é novidade para ninguém &#8211; ou, pelo menos, não deveria ser. No entanto, é muito mais difícil fazer isso acontecer do que falar sobre o assunto.</p>
<p>É muito bom que a mentalidade de testes esteja sendo cada vez mais difundida. Com isso, desenvolvem-se as abordagens às práticas de desenvolvimento orientado por testes como, por exemplo, os frameworks. Enquanto eles se tornam cada vez mais extensíveis, eficientes e com DSLs mais limpas e bonitas, muitas pessoas esquecem que, independentemente da ferramenta, da sintaxe e da abordagem técnica a ser utilizada, a intenção do código desenvolvido é que deve ficar explícita.</p>
<p><strong>Observação</strong>: ao longo desse texto, utilizarei a expressão &#8220;desenvolvimento orientado por testes&#8221;, mas você pode substituir por &#8220;desenvolvimento orientado por comportamento&#8221; ou qualquer abordagem similar.</p>
<h4>O que é a intenção do código?</h4>
<p>A intenção do código tem tudo a ver com algo que vem sendo muito discutido: o comportamento do software. Uma definição de comportamento é &#8220;<em>a resposta observável de um sistema a um estímulo</em>&#8220;. Logo, em última análise, podemos dizer que o que importa é verificar se a resposta observável de um componente de software é a esperada, dado um ou mais estímulos pré-definidos.</p>
<p>Em alguns casos isso significa apenas definir um estado, chamar algum método e verificar o resultado. Em outros, significa verificar também a propagação dos efeitos em outros objetos (caso onde os mocks são muito úteis). Isso vai depender do componente em desenvolvimento e da abordagem utilizada.</p>
<h4>Como?</h4>
<p>A pergunta é: como testes ajudam a revelar a intenção do código?</p>
<p>Se você escrever um monte de código confuso e, após isso, resolver escrever alguns testes para validar esse trabalho, esses testes não vão ajudar em nada. Mas, se utilizar testes para orientar seu processo de desenvolvimento, descobrirá o papel fundamental que eles terão para criar código claro, fácil de entender, utilizar e modificar. Ao especificar um cenário (o estado pré-definido onde ocorrerá o estímulo), fica muito mais simples projetar e verificar o comportamento necessário.</p>
<p>Geralmente, ao escrever testes antes da implementação, obtêm-se outros benefícios, tais como: uso de boa nomenclatura, simplicidade e facilidade no refactoring. Tudo isso deve-se ao fato de que, ao praticar o desenvolvimento orientado por testes, você efetivamente <strong>pensa</strong> mais sobre o que vai escrever, antes de o fazer.</p>
<h4>Exemplo</h4>
<p>Vou tentar exemplificar os passos de criação de um componente simples com e sem testes para orientar a implementação. Assim, ao final, teremos uma perspectiva melhor dos efeitos do processo.</p>
<p>Quero escrever uma aplicação para cadastrar minha coleção de filmes. Preciso de uma classe que representará o filme:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Movie
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:title</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Isso é o suficiente para o exemplo.</p>
<p>Agora vamos iniciar o processo de implementação da classe responsável pelo gerenciamento da coleção. Primeiro, sem teste algum.</p>
<p>Sei que preciso de uma classe que possua uma lista de filmes e permita que eu posso adicionar, remover, procurar e listar todos os filmes. Vamos lá:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> MovieShelf
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:movies</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize
    <span style="color:#0066ff; font-weight:bold;">@movies</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> lookup<span style="color:#006600; font-weight:bold;">&#40;</span>movie<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@movies</span>.<span style="color:#9900CC;">detect</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>m<span style="color:#006600; font-weight:bold;">|</span> m == movie<span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> list
    <span style="color:#0066ff; font-weight:bold;">@movies</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>movie<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#CC0066; font-weight:bold;">puts</span> movie.<span style="color:#9900CC;">title</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Ok, muito simples. Em dois minutos está pronto. Um exemplo de uso (no irb):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&gt;&gt;</span> shelf = MovieShelf.<span style="color:#9900CC;">new</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#008000; font-style:italic;">#&lt;movieShelf:0x36eb88 @movies=[]&gt;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> m = Movie.<span style="color:#9900CC;">new</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#008000; font-style:italic;">#&lt;movie:0x33b328&gt;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> m.<span style="color:#9900CC;">title</span> = <span style="color:#996600;">&quot;Juno&quot;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Juno&quot;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> m2 = Movie.<span style="color:#9900CC;">new</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#008000; font-style:italic;">#&lt;movie:0x39968&gt;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> m2.<span style="color:#9900CC;">title</span> = <span style="color:#996600;">&quot;Transformers&quot;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Transformers&quot;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> shelf.<span style="color:#9900CC;">movies</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> m
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#008000; font-style:italic;">#&lt;movie:0x33b328 @title=&quot;Juno&quot;&gt;]</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> shelf.<span style="color:#9900CC;">movies</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> m2
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#008000; font-style:italic;">#&lt;movie:0x33b328 @title=&quot;Juno&quot;&gt;, #&lt;movie:0x39968 @title=&quot;Transformers&quot;&gt;]</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> shelf.<span style="color:#9900CC;">list</span>
Juno
Transformers
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#008000; font-style:italic;">#&lt;movie:0x33b328 @title=&quot;Juno&quot;&gt;, #&lt;movie:0x39968 @title=&quot;Transformers&quot;&gt;]</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> shelf.<span style="color:#9900CC;">lookup</span> m2
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#008000; font-style:italic;">#&lt;movie:0x39968 @title=&quot;Transformers&quot;&gt;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> shelf.<span style="color:#9900CC;">movies</span>.<span style="color:#9900CC;">delete</span> m2
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#008000; font-style:italic;">#&lt;movie:0x39968 @title=&quot;Transformers&quot;&gt;</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> shelf.<span style="color:#9900CC;">list</span>
Juno
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#008000; font-style:italic;">#&lt;movie:0x33b328 @title=&quot;Juno&quot;&gt;]</span></pre></div></div>

<p>Tudo bem, funciona e parece estar de acordo com os requisitos. Mas o código não está muito consistente. A coleção de filmes, que na prática é um objeto da classe Array, está exposta e pode ser manipulada diretamente. Isso pode ser muito ruim caso algum método da classe MovieShelf faça ações adicionais ao operar sobre a coleção. A nomenclatura também não é muito clara, entre outros pequenos problemas. Também não gostei da forma como estou criando os objetos que representam os filmes.</p>
<p>Agora, vamos começar com uma pequena especificação do que é preciso. Com isso, vou ter mais tempo para pensar em bons nomes e numa forma de uso limpa e direta.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">context <span style="color:#996600;">&quot;a movie shelf&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  setup <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#0066ff; font-weight:bold;">@shelf</span> = MovieShelf.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  should <span style="color:#996600;">&quot;let the user store a movie&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    juno = Movie.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Juno&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    shelf.<span style="color:#9900CC;">store</span> juno
    assert shelf.<span style="color:#9900CC;">contains</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>juno<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Somente estabelecendo essa primeira expectativa quanto ao comportamento do componente, já temos idéia de um início de implementação:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Movie
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:title</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>title<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">title</span> = title
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> MovieShelf
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize
    <span style="color:#0066ff; font-weight:bold;">@movies</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> store<span style="color:#006600; font-weight:bold;">&#40;</span>movie<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@movies</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> movie
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> contains?<span style="color:#006600; font-weight:bold;">&#40;</span>movie<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@movies</span>.<span style="color:#9966CC; font-weight:bold;">include</span>? movie
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Continuando:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">context <span style="color:#996600;">&quot;a movie shelf&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  setup <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#0066ff; font-weight:bold;">@shelf</span> = MovieShelf.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  should <span style="color:#996600;">&quot;show how many movies are stored&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    juno = Movie.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Juno&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    transformers = Movie.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Transformers&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    shelf.<span style="color:#9900CC;">store</span> juno
    shelf.<span style="color:#9900CC;">store</span> transformers
    assert_equal <span style="color:#006666;">2</span>, shelf.<span style="color:#9900CC;">movies_count</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Implementando:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> MovieShelf
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize
    <span style="color:#0066ff; font-weight:bold;">@movies</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> store<span style="color:#006600; font-weight:bold;">&#40;</span>movie<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@movies</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> movie
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> contains?<span style="color:#006600; font-weight:bold;">&#40;</span>movie<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@movies</span>.<span style="color:#9966CC; font-weight:bold;">include</span>? movie
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> movies_count
    <span style="color:#0066ff; font-weight:bold;">@movies</span>.<span style="color:#9900CC;">size</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>É claro que o exemplo é bem bobo, mas perceba como a interface fica melhor e também como vamos descobrindo novas funcionalidades ao longo do processo de especificação. Este é um dos principais benefícios do desenvolvimento orientado por testes: interfaces ricas através de código modular, flexível e de intenção clara.</p>
<p>Não vou continuar o exemplo com as demais funcionalidades para não alongar ainda mais o artigo. Acredito que consegui expor aqui a importância da intenção do código e como deixá-la clara e fácil de entender.</p>
<p>O que você pensa sobre isso? Deixe sua opinião, comentário, exemplo, crítica ou sugestão. <img src='http://blog.lucashungaro.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Leia também:</p>
<ul>
<li><a href="http://www.informit.com/articles/article.aspx?p=357688" target="_blank">Test Driven Development: Programming by Intention</a></li>
<li><a href="http://blog.aslakhellesoy.com/2006/12/11/the-bdd-cargo-cult" target="_blank">The BDD cargo culting</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2009/05/08/testes-devem-revelar-a-intencao-do-codigo/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Evitando over-stubbing com Mocha</title>
		<link>http://blog.lucashungaro.com/2009/03/18/evitando-over-stubbing-com-mocha/</link>
		<comments>http://blog.lucashungaro.com/2009/03/18/evitando-over-stubbing-com-mocha/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 16:45:29 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Anúncios]]></category>
		<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=191</guid>
		<description><![CDATA[Não é segredo que não sou &#8220;fã&#8221; da maneira como a comunidade de desenvolvedores utiliza mocks e stubs. A meu ver, trata-se de mal uso de uma ferramenta muito útil. Com esse tipo de uso surgem alguns problemas, tais como over-mocking e over-stubbing, ou seja, o uso abusivo de mocks e stubs. O abuso de [...]]]></description>
			<content:encoded><![CDATA[<p>Não é segredo que não sou &#8220;fã&#8221; da maneira como a comunidade de desenvolvedores utiliza mocks e stubs. A meu ver, trata-se de mal uso de uma ferramenta muito útil.</p>
<p>Com esse tipo de uso surgem alguns problemas, tais como over-mocking e over-stubbing, ou seja, o uso abusivo de mocks e stubs. O abuso de mocks torna seus testes quebradiços, isto é, testes que falham sem que haja alteração de comportamento do componente sob verificação. O abuso de stubs torna seus testes fracos, isto é, testes que saem de sincronia com o código, verificando comportamento que já não é real, mas continuam passando.</p>
<p>Um exemplo de abuso de mocks:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">it <span style="color:#996600;">&quot;should be successful&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  Account.<span style="color:#9900CC;">expects</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:new</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:current_user</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@user</span>, <span style="color:#ff3333; font-weight:bold;">:first_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Test&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:last_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Test&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">returns</span><span style="color:#006600; font-weight:bold;">&#40;</span>@account<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@account</span>.<span style="color:#9900CC;">expects</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:login_method</span>=<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">CONFIG::LOGIN::OpenID</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#0066ff; font-weight:bold;">@account</span>.<span style="color:#9900CC;">expects</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:has_email_and_password</span>=<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">at_least_once</span>
  <span style="color:#0066ff; font-weight:bold;">@account</span>.<span style="color:#9900CC;">expects</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:has_openid</span>=<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">twice</span>
  do_edit
  response.<span style="color:#9900CC;">should</span> be_success
  response.<span style="color:#9900CC;">should</span> render_template<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;edit&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Note que até métodos de atribuição são colocados sob expectativas. Se a implementação sofrer uma alteração simples, fazendo, por exemplo, com que algum desses métodos não seja mais chamado, mesmo que não haja qualquer modificação no comportamento, o teste falhará.</p>
<p>Um exemplo do abuso de stubs:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">it <span style="color:#996600;">&quot;has been modified a lot of times&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  Dependency.<span style="color:#9900CC;">stubs</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:a_method</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  NoLongerADependency.<span style="color:#9900CC;">stubs</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:something</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">returns</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  AnotherDependency.<span style="color:#9900CC;">stubs</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nonexistent_method</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">returns</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">10</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  MyClass.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">do_something</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Com esse tipo de abordagem, você pode acabar com problemas como fazer stubs de métodos que não existem mais ou até mesmo de objetos que já não são mais uma dependência.</p>
<p>Uma forma de evitar isso com o Mocha (além, é claro, de estudar o uso correto das ferramentas) é utilizar algumas configurações providas pelo framework através de sua classe Configuration:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">Mocha::Configuration</span>.<span style="color:#9900CC;">prevent</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:stubbing_non_existent_method</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;">#impede stubbing de métodos inexistentes</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">Mocha::Configuration</span>.<span style="color:#9900CC;">prevent</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:stubbing_method_unnecessarily</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;">#impede stubbing de métodos não utilizados</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">Mocha::Configuration</span>.<span style="color:#9900CC;">prevent</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:stubbing_non_public_method</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;">#impede stubbing de métodos não-públicos</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">Mocha::Configuration</span>.<span style="color:#9900CC;">prevent</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:stubbing_method_on_non_mock_object</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;">#impede stubbing em objetos &quot;reais&quot;</span></pre></div></div>

<p>Nos exemplos acima, caso encontre um dos usos &#8220;indevidos&#8221;, o Mocha lançará uma exceção do tipo Mocha::StubbingError. Isso ocorre por termos utilizado o método prevent. Há outras configurações possíveis, sendo providos três nívels de configuração:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># padrão - permite a condição</span>
<span style="color:#6666ff; font-weight:bold;">Mocha::Configuration</span>.<span style="color:#9900CC;">allow</span><span style="color:#006600; font-weight:bold;">&#40;</span>condition<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># apenas emite um aviso quando ocorre a condição</span>
<span style="color:#6666ff; font-weight:bold;">Mocha::Configuration</span>.<span style="color:#9900CC;">warn_when</span><span style="color:#006600; font-weight:bold;">&#40;</span>condition<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># lança um erro quando ocorre a condição</span>
<span style="color:#6666ff; font-weight:bold;">Mocha::Configuration</span>.<span style="color:#9900CC;">prevent</span><span style="color:#006600; font-weight:bold;">&#40;</span>condition<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Essas configurações podem ser um auxílio para o aprendizado do uso correto e equilibrado da ferramenta.</p>
<p>Leia mais:<br />
<a href="http://mocha.rubyforge.org/classes/Mocha/Configuration.html" target="_blank">Mocha::Configuration RDoc</a><br />
<a href="http://blog.floehopper.org/articles/2009/02/09/mocha-configuration" target="_blank">Mocha Configuration &#8211; James Mead</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2009/03/18/evitando-over-stubbing-com-mocha/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Seu framework não faz BDD</title>
		<link>http://blog.lucashungaro.com/2009/01/08/seu-framework-nao-faz-bdd/</link>
		<comments>http://blog.lucashungaro.com/2009/01/08/seu-framework-nao-faz-bdd/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 03:49:51 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Opinião]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Test-Driven Development]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=142</guid>
		<description><![CDATA[Eu sinto uma &#8220;pontada&#8221; no cérebro quando ouço ou leio coisas como &#8220;o RSpec (ou Shoulda, test/spec etc) é um framework BDD&#8221;. Não existe algo como um &#8220;framework BDD&#8221;. Tenha em mente que quem pratica ou não o BDD é o desenvolvedor. O que existe são frameworks ou bibliotecas que adicionam uma boa dose de [...]]]></description>
			<content:encoded><![CDATA[<p>Eu sinto uma &#8220;pontada&#8221; no cérebro quando ouço ou leio coisas como &#8220;o RSpec (ou Shoulda, test/spec etc) é um framework BDD&#8221;.</p>
<p>Não existe algo como um &#8220;framework BDD&#8221;. Tenha em mente que quem pratica ou não o BDD é o desenvolvedor. O que existe são frameworks ou bibliotecas que adicionam uma boa dose de açúcar sintático para facilitar o estilo de escrita para quem deseja praticar essa técnica de testes.</p>
<p>Os <a href="http://dannorth.net/introducing-bdd" target="_blank">maiores</a> <a href="http://blog.daveastels.com/files/BDD_Intro.pdf" target="_blank">proponentes</a> do BDD enfatizam que a maior mudança em relação às técnicas tradicionais é mesmo a sintaxe. Porém, isso não quer dizer que basta utilizar uma sintaxe &#8220;mais legível&#8221; (o que é discutível também) para pular no vagão do BDD. A sintaxe bonitinha é um auxílio, uma ferramenta com o objetivo de diminuir as dificuldades na transição de um <strong>modo de pensar</strong>, que é onde a verdadeira diferença reside. Muitas dessas dificuldades são, inclusive, ditas de origem &#8220;psicológica&#8221;, como a abolição da palavra &#8220;test&#8221; nos nomes dos métodos para forçar o pensamento no sentido de uma verificação de comportamento ao invés de um teste de estado (medida defendida através da <a href="http://pt.wikipedia.org/wiki/Hip%C3%B3tese_de_Sapir-Whorf" target="_blank">hipótese de Sapir-Whorf</a>).</p>
<p>De fato, posso afirmar que a maior parte das suítes de testes escritas em RSpec, Shoulda ou test/spec que já tive a oportunidade de examinar (seja trabalhando, seja &#8220;navegando&#8221; por projetos open source &#8211; uma grande fonte de aprendizado), falha miseravelmente na tentativa de adotar o BDD, tropeçando feio em erros como verificar estado ao invés de comportamento, testar funcionalidades da linguagem ou framework e, principalmente, overmocking &#8211; chegando ao ponto em que um teste não verifica mais nada, apenas mocks e stubs &#8211; o que nos leva a testes quebradiços ou testes que não falham mesmo que você apague o código que eles deveriam verificar.</p>
<p>Esse último item leva a um outro ponto importante (e, aqui, uma visão muito pessoal &#8211; acredito ser compartilhada por poucos): acredita-se que o uso de mocks configura o uso do BDD, pois estabelecer expectativas em relação à interfaces e, consequentemente, isolar horizontalmente os componentes testados, passa a ser, &#8220;automaticamente&#8221;, verificação de comportamento. O uso de mocks não estabelece nada além de uma expectativa de interação &#8211; uma interface.</p>
<p>Como um <a href="http://martinfowler.com/articles/mocksArentStubs.html#ClassicalAndMockistTesting" target="_blank">classicista</a> evito o uso de mocks (e dublês em geral), reservando-os para onde realmente é difícil ou pouco prático o uso de um objeto real ou, como deveria ser seu principal uso, uma ferramenta de design de código através da qual modelamos interfaces ainda não existentes à medida em que praticamos o TDD (ou seja, escrevemos testes antes da implementação do código real) &#8211; e os substituo assim que a classe real é implementada, quando aplicável.</p>
<p>Então, não acredite que por utilizar alguma ferramenta facilitadora, você, instantâneamente, estará praticando BDD. Estude a técnica e a filosofia envolvida e você poderá utilizá-la com qualquer ferramenta para testes.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2009/01/08/seu-framework-nao-faz-bdd/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

