<?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; Ruby</title>
	<atom:link href="http://blog.lucashungaro.com/category/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.lucashungaro.com</link>
	<description>Conhecimento nunca é o bastante</description>
	<lastBuildDate>Sat, 03 Sep 2011 19:36:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Gems &#8220;locais&#8221;, irb e Bundler</title>
		<link>http://blog.lucashungaro.com/2011/07/23/gems-locais-irb-e-bundler/</link>
		<comments>http://blog.lucashungaro.com/2011/07/23/gems-locais-irb-e-bundler/#comments</comments>
		<pubDate>Sat, 23 Jul 2011 18:40:56 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Dicas]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=419</guid>
		<description><![CDATA[Gosto de algumas gems como o wirble, que adicionam algumas funcionalidades ao irb (e, por consequência, ao console do Rails). O problema é que, em projetos que utilizam o Bundler, fica complicado adicionar esse tipo de gem ao Gemfile, pois elas não são realmente dependências do projeto e nem todos gostariam de utilizá-las. Como programadores [...]]]></description>
			<content:encoded><![CDATA[<p>Gosto de algumas gems como o <a href="https://rubygems.org/gems/wirble">wirble</a>, que adicionam algumas funcionalidades ao irb (e, por consequência, ao console do Rails). O problema é que, em projetos que utilizam o Bundler, fica complicado adicionar esse tipo de gem ao Gemfile, pois elas não são realmente dependências do projeto e nem todos gostariam de utilizá-las.</p>
<p>Como programadores costumam ser bem radicais (ainda mais com essa mania de ser &#8220;opinionado&#8221;), isso sempre gera discussões e atritos. Eu já penso que é mais fácil simplesmente buscar uma solução, e eis aqui uma: <a href="https://gist.github.com/1096494">https://gist.github.com/1096494</a>.</p>
<p>Colocando esse snippet no seu arquivo .irbrc, ao abrir o irb (ou console do Rails), todas as gems do gemset global do RVM serão colocadas no load path, podendo assim serem requeridas na sequência. Eu não costumo usar gemsets por projeto (uso apenas o Bundler, da maneira explicada <a href="http://ryan.mcgeary.org/2011/02/09/vendor-everything-still-applies/">nesse post</a>), mas deixo o gemset global com algumas gems para esse fim. Meu arquivo .irbrc <a href="https://github.com/lucashungaro/dotfiles/blob/master/irbrc">está disponível no GitHub</a>.</p>
<p>Essa solução não é lá muito elegante, mas funciona muito bem para gems utilizadas no irb. Há algum tempo propus uma solução na lista do Bundler e recebi algumas sugestões, porém nenhuma me agradou (como, por exemplo, obrigar todo mundo que não quer as gems a usar a flag &#8211;without a cada bundle install). A discussão <a href="http://groups.google.com/group/ruby-bundler/browse_thread/thread/f05d8613fc434c37">pode ser vista aqui</a>. Até cheguei a fazer um fork do Bundler para implementar algum tipo de metadado para controlar isso, mas o código é bem complicado e acoplado, então deixei pra lá. <img src='http://blog.lucashungaro.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2011/07/23/gems-locais-irb-e-bundler/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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: Open-Closed Principle</title>
		<link>http://blog.lucashungaro.com/2011/05/11/solid-ruby-open-closed-principle/</link>
		<comments>http://blog.lucashungaro.com/2011/05/11/solid-ruby-open-closed-principle/#comments</comments>
		<pubDate>Wed, 11 May 2011 17:43:22 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=413</guid>
		<description><![CDATA[Muitos dos princípios da programação orientada a objetos foram criados com linguagens estáticas em mente. Esse é o caso do Open-Closed Principle, enunciado da seguinte maneira: Software entities (classes, modules, functions, etc) should be open for extension, but closed for modification. Originalmente, a ideia é que, uma fez finalizada, uma entidade só poderia ser modificada [...]]]></description>
			<content:encoded><![CDATA[<p>Muitos dos princípios da programação orientada a objetos foram criados com linguagens estáticas em mente. Esse é o caso do <a href="http://en.wikipedia.org/wiki/Open/closed_principle">Open-Closed Principle</a>, enunciado da seguinte maneira:</p>
<blockquote><p>Software entities (classes, modules, functions, etc) should be open for extension, but closed for modification.</p></blockquote>
<p>Originalmente, a ideia é que, uma fez finalizada, uma entidade só poderia ser modificada para correções. Qualquer nova &#8220;feature&#8221; deveria ser implementada em uma nova entidade, que aproveitaria o código da primeira principalmente através de herança. Isso resulta em reaproveitamento da implementação, mas não garante a consistência da interface.</p>
<p>Um pouco depois, com a introdução e popularização de classes abstratas e recursos de linguagem como Interfaces, o princípio evoluiu e passou a ser aplicado em conjunto com o DIP, fazendo com que o código sempre dependesse de interfaces ao invés de implementações. Com isso, era possível reaproveitar uma interface (closed) e modificar a implementação (open).</p>
<p>Mas e nas linguagens como Ruby, em que abrir uma classe é tão simples como definí-la e pode ser feito a qualquer momento? Será que esse princípio se aplica? Isso sempre é tema de muita discussão e aqui vai minha visão sobre isso.</p>
<p>Bem, com Ruby temos algumas formas de modificar uma classe, como herança, mixins, reabrir a classe ou usar metaprogramação. Perceba que, exceto pela herança, as outras maneiras infringem a ideia original do princípio. Mas, como já vimos, o próprio princípio evoluiu para abraçar mudanças nas linguagens e paradigmas. </p>
<p>O importante, principalmente em linguagens com Duck Typing (que, como já vimos, não dão a mínima para tipos), é que a interface seja fechada. Não importa o modo que você escolher para fazer as modificações, desde que a &#8220;superfície de contato&#8221; entre as entidades permaneça estável.</p>
<p>No exemplo do post anterior poderíamos modificar as classes que passamos como dependências via parâmetro e utilizá-las sem problemas, desde que a interface permanecesse a mesma. Uma vantagem adicional da tipagem dinâmica é que nesse caso podemos utilizar também herança (modificando o &#8220;tipo&#8221;) sem precisar modificar o código cliente, que só se importa com a interface.</p>
<p>Dessa forma, podemos modificar um pouco o enunciado do OCP para adaptá-lo à nossa linguagem preferida:</p>
<blockquote><p>Software entities (classes, modules, functions, etc) should be open for extension, but closed for interface modification.</p></blockquote>
<p>Recomendo esse vídeo-podcast sobre o assunto: <a href="http://www.heartmindcode.com/blog/2011/03/monkeypatching-and-the-open-closed-principle/">Monkeypatching and the Open-Closed Principle</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2011/05/11/solid-ruby-open-closed-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>SOLID Ruby: Single Responsibility Principle</title>
		<link>http://blog.lucashungaro.com/2011/05/04/solid-ruby-single-responsibility-principle/</link>
		<comments>http://blog.lucashungaro.com/2011/05/04/solid-ruby-single-responsibility-principle/#comments</comments>
		<pubDate>Wed, 04 May 2011 05:34:38 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=409</guid>
		<description><![CDATA[Utilizamos BDD e técnicas do programação orientada a objetos não apenas para obter código mais limpo e bonito. Na verdade, essas são consequências do principal objetivo: criar código que tenha baixo custo de manutenção, isto é, não demande muito tempo e pessoas para correções e melhorias. Um conjunto de técnicas que podemos utilizar para atingir [...]]]></description>
			<content:encoded><![CDATA[<p>Utilizamos BDD e técnicas do programação orientada a objetos não apenas para obter código mais limpo e bonito. Na verdade, essas são consequências do principal objetivo: criar código que tenha baixo custo de manutenção, isto é, não demande muito tempo e pessoas para correções e melhorias.</p>
<p>Um conjunto de técnicas que podemos utilizar para atingir esse objetivo é chamada de <a href="http://en.wikipedia.org/wiki/Solid_(object-oriented_design)">SOLID</a>, um acrônimo que representa cinco técnicas:</p>
<ul>
<li>Single Responsibility Principle</li>
<li>Open-Closed Principle</li>
<li>Liskov Substitution Principle</li>
<li>Interface Segregation Principle</li>
<li>Dependency Inversion Principle</li>
</ul>
<p>O objetivo desses princípios é fazer com que alterações necessárias sejam feitas no menor número possível de locais no código. Em outras palavras, é diminuir o custo dessas mudanças através de um design que reduz os efeitos colaterais das modificações.</p>
<p>Nesse artigo vou mostrar um pouco sobre a aplicação do <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">Single Responsibility Principle</a> em Ruby.</p>
<p>Esse princípio nos diz que uma classe deve ter apenas uma responsabilidade e deve executá-la por completo (não devem haver outras classes que executem partes dela). É uma forma de conseguir alta <a href="http://en.wikipedia.org/wiki/Cohesion_(computer_science)">coesão</a>, uma qualidade desejável em código orientado a objetos. Uma classe coesa executa completamente uma responsabilidade, ou seja, essa responsabilidade não fica fragmentada e espalhada entre diferentes entidades no domínio.</p>
<p>Uma forma de pensar sobre o que é uma responsabilidade para facilitar a absorção do conceito é que esta representa <em>uma razão para mudar</em>. Então podemos definir o princípio como: uma classe tem uma e apenas uma razão para mudar.</p>
<p>Vamos a um exemplo de um modelo ActiveRecord que viola esse princípio (alerta para pseudo-código que nem deve funcionar, é apenas um exemplo):</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>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> get_official_price
    <span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;http://thegamedatabase.com/api/game/#{name}/price?api_key=ek2o1je&quot;</span><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:#CC0066; font-weight:bold;">print</span>
    <span style="color:#006600; font-weight:bold;">&lt;&lt;-</span>EOF
      <span style="color:#008000; font-style:italic;">#{name}, #{platform}, #{year} </span>
      current value is <span style="color:#008000; font-style:italic;">#{get_official_price}</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 modelo tem como sua responsabilidade principal cuidar da lógica de negócio ligada à entidade Game. Porém, como podemos ver aqui, ele também está responsável por consultar um webservice para obter a cotação do jogo e por formatar sua exibição. Essa implementação possui baixa coesão pois essa classe possui mais de um motivo para mudar. Ela será alterada se os requisitos de validação de dados mudarem, se algum detalhe da chamada do webservice mudar ou se precisarmos exibir seus dados numa formatação diferente.</p>
<p>Uma forma de resolver isso seria desmembrar essa classe tendo esse resultado:</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>Assim aumentamos bastante a coesão de nosso sofware. Cada classe possui apenas uma razão para mudar e atende ao SRP.</p>
<p>Um exemplo mais real pode ser visto no modelo <a href="https://github.com/spree/spree/blob/master/core/app/models/creditcard.rb">Creditcard</a> do <a href="http://spreecommerce.com/">Spree</a>. Note que, entre outras coisas, o modelo também é responsável pelos processos de compra e autorização do cartão (métodos purchase e authorize). Note como esse métodos implementam parte do processo e delegam outras partes para outros componentes quando a responsabilidade deveria ser 100% realizada em outra parte. Isso cria baixa coesão (múltiplas responsabilidades por classe) e alto acoplamento (uma responsabilidade dividida por várias classes interdependentes).</p>
<p>Como um exercício a parte podemos pensar sobre até que ponto modelos do ActiveRecord quebram o SRP por serem responsáveis por persistência e lógica de negócios (que inclui validação de dados). Há muitos desenvolvedores dos dois lados nessa questão. Acredito que há pequenas violações mas de uma forma não prejudicial, já que a persistência é implementada por uma classe especializada e apenas herdada em nossos modelos, de forma que essa é delegada ao framework (que cuida de possíveis modificações necessárias à persistência).</p>
<p>É preciso ter em mente que ser muito extremista com esses princípios também pode levar à problemas e a um excesso de preciosismo que torna-se prejudicial.</p>
<p>Bom, a partir daqui vamos para outros artigos onde serão explorados os outros princípios. O pseudo-código utilizado no exemplo acima ainda tem algumas coisas a ganhar através da aplicação de outros princípios.</p>
<p>Leitura recomendada:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Cohesion_(computer_science)">Cohesion</a></li>
<li><a href="http://en.wikipedia.org/wiki/Coupling_(computer_science)">Coupling</a></li>
<li><a href="http://en.wikipedia.org/wiki/Separation_of_concerns">Separation of concerns</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2011/05/04/solid-ruby-single-responsibility-principle/feed/</wfw:commentRss>
		<slash:comments>3</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>Back-end caching com Ruby, parte 1 &#8211; Introdução</title>
		<link>http://blog.lucashungaro.com/2010/11/30/back-end-caching-com-ruby-parte-1-introducao/</link>
		<comments>http://blog.lucashungaro.com/2010/11/30/back-end-caching-com-ruby-parte-1-introducao/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 17:33:13 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tutoriais]]></category>

		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=378</guid>
		<description><![CDATA[Depois de pesquisar muito código e dar duas palestras em que falei um pouco sobre o tema, posso afirmar com convicção que caching é um dos aspectos mais negligenciados pelos desenvolvedores em nossa comunidade &#8211; não por preguiça ou algo do tipo, mas por falta de prática e exposição ao assunto. Resolvi contribuir para que [...]]]></description>
			<content:encoded><![CDATA[<p>Depois de pesquisar muito código e dar duas palestras em que falei um pouco sobre o tema, posso afirmar com convicção que caching é um dos aspectos mais negligenciados pelos desenvolvedores em nossa comunidade &#8211; não por preguiça ou algo do tipo, mas por falta de prática e exposição ao assunto.</p>
<p>Resolvi contribuir para que o assunto seja mais discutido escrevendo alguns posts. Como a parte de cache em front-end já é mais difundida, vou focar no back-end.</p>
<p>Para começar, precisamos clarificar essa distinção importante: front-end cache e back-end cache. O primeiro tipo é o mais comum de encontrar em tutoriais e posts em blogs. Trata-se do cache de camadas relacionadas à interface da aplicação. No Rails, por exemplo, engloba: page, action e fragment cache. Já o segundo tipo, em geral, envolve fazer cache de resultados de operações pesadas (como queries complexas a banco de dados) utlizando algum storage como memcached. É desse tipo que vamos falar.</p>
<p>Sabemos que, quanto mais cedo no ciclo do request for feito o cache, mais eficiente ele é. Daí o cache no front-end ser o que traz mais retorno. No entanto, há momentos em que não é possível utilizar cache no front-end. Além disso, há situações em que outros tipos de cache são necessários, por exemplo quando utilizamos um back-end comum para a aplicação web e API (com clientes mobile e desktop, por exemplo) e queremos ter o benefício de desempenho do cache nessa parte também.</p>
<p>De modo geral, o que precisamos para o caching no back-end é um storage e um cliente para ele. Um dos storages mais comuns (em diversas plataformas) é o <a href="http://memcached.org/">memcached</a> &#8211; tão comum e consistente que vários frameworks o suportam <em>out of the box</em>, como é o caso do Rails.</p>
<p>Vamos a um simples exemplo utilizando a gem <a href="https://github.com/fauna/memcached">memcached</a> para o caching de um cálculo feito em cima do resultado de uma hipotética query a um banco de dados.</p>
<p>Primeiro, vamos iniciar um servidor do memcached localmente:</p>
<pre>
$ memcached -vv -l 127.0.0.1 -p 11211
</pre>
<p>Isso vai iniciar o servidor localmente na porta 11211 em modo <em>very verbose</em> para que possamos acompanhar o que está acontecendo.</p>
<p>Agora, vamos ao código:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;mysql&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;memcached&quot;</span>
&nbsp;
connection = Mysql.<span style="color:#9900CC;">real_connect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;127.0.0.1&quot;</span>, <span style="color:#996600;">&quot;root&quot;</span>, <span style="color:#996600;">&quot;pass&quot;</span>, <span style="color:#996600;">&quot;my_database&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
results = connection.<span style="color:#9900CC;">query</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;select * from amazingly_big_table where non_indexed_column = 'some_value'&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
some_calc = <span style="color:#006666;">0</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># no inject on Mysql::Result :(</span>
results.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>row<span style="color:#006600; font-weight:bold;">|</span>
   <span style="color:#008000; font-style:italic;"># do some processing using some_calc</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">puts</span> some_calc</pre></div></div>

<p>Toda vez que esse código for executado, a query irá ser feita no banco de dados e o resultado será calculado novamente. Nesse exemplo, vamos adicionar cache para evitar que isso ocorra tantas vezes:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;mysql&quot;</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;memcached&quot;</span>
&nbsp;
connection = Mysql.<span style="color:#9900CC;">real_connect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;127.0.0.1&quot;</span>, <span style="color:#996600;">&quot;root&quot;</span>, <span style="color:#996600;">&quot;pass&quot;</span>, <span style="color:#996600;">&quot;my_database&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
cache = Memcached.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;localhost:11211&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
some_calc = cache.<span style="color:#9900CC;">get</span> <span style="color:#996600;">&quot;some_calc&quot;</span> <span style="color:#008000; font-style:italic;">#busca o valor no cache</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">unless</span> some_calc <span style="color:#008000; font-style:italic;">#caso não esteja em cache</span>
  results = connection.<span style="color:#9900CC;">query</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;select * from amazingly_big_table where non_indexed_column = 'some_value'&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  some_calc = <span style="color:#006666;">0</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># no inject on Mysql::Result :(</span>
  results.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>row<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#008000; font-style:italic;"># do some processing using some_calc</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  cache.<span style="color:#9900CC;">set</span> <span style="color:#996600;">&quot;some_calc&quot;</span>, some_calc, <span style="color:#006666;">3600</span> <span style="color:#008000; font-style:italic;"># coloca o valor no cache por 3600 segundos</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">puts</span> some_calc</pre></div></div>

<p>As linhas importantes aqui são as que manipulam o cache. No caso do memcached (e na grande maioria dos outros storages para cache) utilizamos o esquema de chave-valor. Armazenamos um valor em uma determinada chave, que deve ser conhecida para que possamos recuperar os dados. O memcached também suporta um <em>time to live</em>, que é um tempo em que o dado deve ser mantido no cache. Após esse tempo, ele é considerado expirado e não será encontrado quando tentarmos um <em>get</em>.</p>
<p>Dessa forma, nosso resultado permanecerá em cache por 3600 segundos. Durante esse tempo, toda vez que o código for executado, o valor será trazido do memcached e mostrado ao final, sem execução da query e do cálculo novamente.</p>
<p>No terminal podemos ver a saída do memcached, mostrando quando armazenamos e buscamos o valor:</p>
<p><a href="http://blog.lucashungaro.com/wp-content/uploads/2010/11/memcached.png"><img src="http://blog.lucashungaro.com/wp-content/uploads/2010/11/memcached.png" alt="memcached" title="memcached" width="276" height="108" class="aligncenter size-full wp-image-382" /></a></p>
<p>Bom, para começar é só isso. Bem simples e não lá muito útil, mas precisamos começar do mais básico, certo? <img src='http://blog.lucashungaro.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>No próximo artigo vou mostrar alguns exemplos mais práticos, utilizando frameworks como Rails e Sinatra. Após isso vamos explorar áreas como: expiração de dados e coleções interdependentes, <em>dog pile effect</em> e outras coisas interessantes.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2010/11/30/back-end-caching-com-ruby-parte-1-introducao/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Slides (com algumas anotações) da minha palestra na RubyConf Brasil</title>
		<link>http://blog.lucashungaro.com/2010/10/29/slides-com-algumas-anotacoes-da-minha-palestra-na-rubyconf-brasil/</link>
		<comments>http://blog.lucashungaro.com/2010/10/29/slides-com-algumas-anotacoes-da-minha-palestra-na-rubyconf-brasil/#comments</comments>
		<pubDate>Fri, 29 Oct 2010 14:01:05 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Apresentações]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=376</guid>
		<description><![CDATA[No último dia 26 palestrei na RubyConf Brasil, em São Paulo, falando sobre uma miscelânea de dicas e técnicas para otimização de aplicações Rails e formas de tornar o código de uma aplicação mais flexível e mais fácil de manter. Os slides (em pdf) podem ser baixados aqui: Coisas que aprendi e quero passar adiante [...]]]></description>
			<content:encoded><![CDATA[<p>No último dia 26 palestrei na RubyConf Brasil, em São Paulo, falando sobre uma miscelânea de dicas e técnicas para otimização de aplicações Rails e formas de tornar o código de uma aplicação mais flexível e mais fácil de manter.</p>
<p>Os slides (em pdf) podem ser baixados aqui: <a href="http://lucashungaro.com/files/RubyConfBR.pdf">Coisas que aprendi e quero passar adiante</a></p>
<p>Obrigado a todos que estiveram presentes e fizeram críticas e elogios.</p>
<p>Sinta-se à vontade para comentar a apresentação.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2010/10/29/slides-com-algumas-anotacoes-da-minha-palestra-na-rubyconf-brasil/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Duas dicas rápidas sobre RSpec</title>
		<link>http://blog.lucashungaro.com/2010/09/26/duas-dicas-rapidas-sobre-rspec/</link>
		<comments>http://blog.lucashungaro.com/2010/09/26/duas-dicas-rapidas-sobre-rspec/#comments</comments>
		<pubDate>Sun, 26 Sep 2010 17:27:33 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[RSpec]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=354</guid>
		<description><![CDATA[Não utilize a sintaxe abaixo: something.should != value A razão para isso é que != é uma expressão, enquanto ==, >=,]]></description>
			<content:encoded><![CDATA[<ol>
<li>Não utilize a sintaxe abaixo:</li>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">something.<span style="color:#9900CC;">should</span> != value</pre></div></div>

<p>A razão para isso é que != é uma expressão, enquanto ==, >=, <= e outros são métodos (podermos utilizá-los sem o "." é açúcar sintático da linguagem). Dessa forma, por mais que na maioria dos casos isso não incorra em efeitos indesejados (a expressão retorna um booleano, o que, em geral, basta) mas a equipe que desenvolve o RSpec recomenda evitar o uso, preferindo a sintaxe abaixo:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">something.<span style="color:#9900CC;">should_not</span> == value</pre></div></div>

<p>E para verificar essa diferença, veja abaixo:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">ree<span style="color:#006600; font-weight:bold;">-</span>1.8.7<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">2010.02</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">1</span>.== <span style="color:#006666;">1</span>
 <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span> 
ree<span style="color:#006600; font-weight:bold;">-</span>1.8.7<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">2010.02</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">2</span>.<span style="color:#006600; font-weight:bold;">&gt;</span>= <span style="color:#006666;">1</span>
 <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span> 
ree<span style="color:#006600; font-weight:bold;">-</span>1.8.7<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">2010.02</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">2</span>.!= <span style="color:#006666;">1</span>
<span style="color:#CC00FF; font-weight:bold;">SyntaxError</span>: compile error
<span style="color:#006600; font-weight:bold;">&#40;</span>irb<span style="color:#006600; font-weight:bold;">&#41;</span>:<span style="color:#006666;">3</span>: syntax error, unexpected tNEQ
<span style="color:#006666;">2</span>.!= <span style="color:#006666;">1</span>
    ^
	from <span style="color:#006600; font-weight:bold;">&#40;</span>irb<span style="color:#006600; font-weight:bold;">&#41;</span>:<span style="color:#006666;">3</span></pre></div></div>

<li>Essa é até bem conhecida, mas vejo um número considerável de pessoas fazendo outra coisa tentando fazer isso: ao configurar callbacks para executar código de setup/teardown antes ou depois de toda a suíte, no bloco de configuração, podemos controlar a ordem com os métodos prepend_before e append_after:</li>
</ol>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">Spec::Runner</span>.<span style="color:#9900CC;">configure</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>config<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#008000; font-style:italic;"># antes da suite</span>
  config.<span style="color:#9900CC;">before</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:suite</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#008000; font-style:italic;">#alias para append_before (ou seja, depois de outros blocos &quot;before&quot;)</span>
    <span style="color:#008000; font-style:italic;"># fazer alguma coisa, provavelmente setup</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
 <span style="color:#008000; font-style:italic;"># depois da suite</span>
  config.<span style="color:#9900CC;">after</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:suite</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#008000; font-style:italic;">#alias para prepend_after (ou seja, antes de outros blocos &quot;after&quot;)</span>
    <span style="color:#008000; font-style:italic;"># fazer alguma coisa, provavelmente cleanup</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Podemos ter um controle mais fino da ordem de execução dos callbacks</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># antes de tudo, inclusive do bloco &quot;config.before&quot; um pouco acima</span>
  config.<span style="color:#9900CC;">prepend_before</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:suite</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#008000; font-style:italic;"># setup do setup ;)</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># após tudo, inclusive do bloco &quot;config.after&quot; um pouco acima</span>
  config.<span style="color:#9900CC;">append_after</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:suite</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#008000; font-style:italic;"># teardown do teardown ;)</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2010/09/26/duas-dicas-rapidas-sobre-rspec/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sentinel: agora, mais transparente do que nunca</title>
		<link>http://blog.lucashungaro.com/2010/03/02/sentinel-agora-mais-transparente-do-que-nunca/</link>
		<comments>http://blog.lucashungaro.com/2010/03/02/sentinel-agora-mais-transparente-do-que-nunca/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 18:17:06 +0000</pubDate>
		<dc:creator>Lucas Húngaro</dc:creator>
				<category><![CDATA[Gem]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.makemesimple.com/blog/?p=344</guid>
		<description><![CDATA[Em Janeiro criei a gem Sentinel, que provê a funcionalidade do padrão Observer de forma transparente para código Ruby. Bom, olhando os exemplos de uso da primeira versão, é possível perceber que a biblioteca não é tão transparente assim: apesar de não alterar os métodos observados, a classe subject tem conhecimento do observer, o que [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.makemesimple.com/blog/2010/01/07/sentinel-observers-transparentes-para-seu-codigo-ruby/">Em Janeiro criei a gem Sentinel</a>, que provê a funcionalidade do padrão Observer de forma transparente para código Ruby. Bom, olhando os exemplos de uso da primeira versão, é possível perceber que a biblioteca não é tão transparente assim: apesar de não alterar os métodos observados, a classe subject tem conhecimento do observer, o que não é bom (nos comentários do post <em>linkado</em> acima falo sobre um &#8220;hack&#8221; para contornar isso, mas não é uma solução elegante).</p>
<p>Com o amadurecimento da ideia e algumas alterações no código, foi possível tornar a biblioteca totalmente transparente do ponto de vista do <em>subject</em><a href="http://github.com/lucashungaro/sentinel"> a partir da versão 0.2.0</a>. Segue um exemplo (ignore a &#8220;inocência&#8221; do código):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> User
  <span style="color:#9966CC; font-weight:bold;">def</span> save
    ...
  <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> UserObserver
  <span style="color:#9966CC; font-weight:bold;">include</span> Sentinel
&nbsp;
  observe User, <span style="color:#ff3333; font-weight:bold;">:save</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">notify</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#008000; font-style:italic;">#método chamado antes de user.save</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Uma atual limitação é que a interceptação é sempre feita pelo método de classe <em>notify</em> do Observer. O plano é que isso seja flexibilizado em breve.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lucashungaro.com/2010/03/02/sentinel-agora-mais-transparente-do-que-nunca/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

