<?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</title>
	<atom:link href="http://blog.lucashungaro.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.lucashungaro.com</link>
	<description>Conhecimento nunca Ã© o bastante</description>
	<lastBuildDate>Tue, 17 Jul 2012 04:20:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.1</generator>
	<item>
		<title>Pair programming comigo!</title>
		<link>http://blog.lucashungaro.com/2012/07/17/pair-programming-comigo/</link>
					<comments>http://blog.lucashungaro.com/2012/07/17/pair-programming-comigo/#respond</comments>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Tue, 17 Jul 2012 04:19:11 +0000</pubDate>
				<category><![CDATA[AnÃºncios]]></category>
		<category><![CDATA[Desenvolvimento]]></category>
		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=440</guid>

					<description><![CDATA[Que tal aprender mais sobre tÃ©cnicas e prÃ¡ticas para tornar seu trabalho desenvolvendo software mais prazeroso e satisfatÃ³rio? Menos bugs, cÃ³digo limpo, bonito e flexÃ­vel, testes rÃ¡pidos e relevantes, entre outros benefÃ­cios, sÃ£o facilmente obtidos atravÃ©s do estudo e prÃ¡tica de alguns fundamentos. A partir desta semana estou disponÃ­vel para workshops/sessÃµes de pareamento presenciais focados [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Que tal aprender mais sobre tÃ©cnicas e prÃ¡ticas para tornar seu trabalho desenvolvendo software mais prazeroso e satisfatÃ³rio? Menos bugs, cÃ³digo limpo, bonito e flexÃ­vel, testes rÃ¡pidos e relevantes, entre outros benefÃ­cios, sÃ£o facilmente obtidos atravÃ©s do estudo e prÃ¡tica de alguns fundamentos.</p>
<p>A partir desta semana estou disponÃ­vel para workshops/sessÃµes de pareamento presenciais focados nessas tÃ©cnicas.</p>
<p><strong>O que Ã©?</strong></p>
<p>NÃ£o Ã© um curso. NÃ£o darei uma aula ou palestra. A ideia Ã© que eu sente com os integrantes da equipe e, trabalhando em projetos reais do time, ensine e pratique as tÃ©cnicas que aplico em meu cÃ³digo e sobre as quais falo em diversos eventos no Brasil.</p>
<p>O foco Ã© em aplicaÃ§Ãµes desenvolvidas com Ruby sob o paradigma de orientaÃ§Ã£o a objetos. AplicaÃ§Ã£o de BDD e princÃ­pios como SOLID e &#8220;Tell, don&#8217;t ask&#8221; serÃ£o os principais objetivos.</p>
<p>Apenas para deixar claro, nÃ£o tenho nada contra cursos. Apenas quero tentar uma nova abordagem que, enquanto mais &#8220;perigosa&#8221; para mim (o risco de dar de cara com situaÃ§Ãµes que nÃ£o conheÃ§o Ã© alto), proporciona mais aprendizado para ambos os lados. Acredito que o time que me contratar se beneficiarÃ¡ muito da possibilidade de aprender enquanto desenvolve dentro de um contexto real, que enfrenta diariamente.</p>
<p><strong>HorÃ¡rios</strong></p>
<p>NÃ£o estou deixando meu trabalho atual. Por isso, meus horÃ¡rios disponÃ­veis sÃ£o de Segunda Ã  Sexta das 19h Ã s 22h e durante os SÃ¡bados. Isso limita os lugares aos quais posso ir, mas Ã© o factÃ­vel no momento.</p>
<p><strong>PreÃ§os</strong></p>
<p>Os preÃ§os serÃ£o de acordo com duraÃ§Ã£o, tamanho das equipes e porte da empresa. Entre em contato comigo atravÃ©s do e-mail lucashungaro@gmail.com e vamos conversar. Tenho certeza que o custo ficarÃ¡ bem inferior ao de contratar uma consultoria de desenvolvimento e o benefÃ­cio serÃ¡ bem maior.</p>
<p><strong>Contato</strong>: lucashungaro@gmail.com</p>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.lucashungaro.com/2012/07/17/pair-programming-comigo/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Capistrano and whenever: updating the crontab of the runner user</title>
		<link>http://blog.lucashungaro.com/2012/04/10/capistrano-and-whenever-updating-the-crontab-of-the-runner-user/</link>
					<comments>http://blog.lucashungaro.com/2012/04/10/capistrano-and-whenever-updating-the-crontab-of-the-runner-user/#respond</comments>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Tue, 10 Apr 2012 17:15:06 +0000</pubDate>
				<category><![CDATA[Deploy]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=432</guid>

					<description><![CDATA[When deploying Rails applications with Capistrano it&#8217;s a common practice to use two separated users: a deployer (the user who actually does the deploy process, copying files and all that) and a runner (the user that runs the application on the server). If you need cronjobs you probably use the whenever gem. It&#8217;s an awesome [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>When deploying Rails applications with <a href="https://github.com/capistrano/capistrano" title="Capistrano">Capistrano</a> it&#8217;s a common practice to use two separated users: a deployer (the user who actually does the deploy process, copying files and all that) and a runner (the user that runs the application on the server).</p>
<p>If you need cronjobs you probably use the <a href="https://github.com/javan/whenever" title="whenever">whenever</a> gem. It&#8217;s an awesome tool to configure your scheduled jobs with a nice and easy DSL. It also has built-in integration with Capistrano, but there&#8217;s a caveat: it will update the crontab of the <strong>deployer</strong>, not the <strong>runner</strong>&#8216;s one.</p>
<p>To solve that issue, I&#8217;ve dropped the &#8220;automatic&#8221; integration (just a simple require &#8220;whenever/capistrano&#8221;) and used a hook to invoke whenever passing a user option to specify which user&#8217;s crontab to update. Here&#8217;s the relevant code:</p>
<pre lang="Ruby">
after "deploy:update_code" do
  run "cd #{release_path} && #{try_sudo} GEM_HOME=/opt/local/ruby/gems RAILS_ENV=production bundle exec whenever --clear-crontab #{application} --user #{runner}"
  run "cd #{release_path} && #{try_sudo} GEM_HOME=/opt/local/ruby/gems RAILS_ENV=production bundle exec whenever --update-crontab #{application} --user #{runner}"
end
</pre>
<p>The code above sets some env vars for sanity sake and runs whenever specifying the runner user as the crontab owner.</p>
<p>There&#8217;s another small tweak you&#8217;ll need. On your schedule.rb file, add the following code on the very first line:</p>
<pre lang="Ruby">
env "PATH", ENV["PATH"]
every 10.minutes do
  # ...
end
</pre>
<p>This will avoid nasty path-related errors (the cronjobs won&#8217;t find the gem&#8217;s bins and all that). Andâ€¦ that&#8217;s it! Have fun! <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.lucashungaro.com/2012/04/10/capistrano-and-whenever-updating-the-crontab-of-the-runner-user/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Compilando uma versÃ£o local do Rails Guides</title>
		<link>http://blog.lucashungaro.com/2012/03/06/compilando-uma-versao-local-do-rails-guides/</link>
					<comments>http://blog.lucashungaro.com/2012/03/06/compilando-uma-versao-local-do-rails-guides/#respond</comments>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Tue, 06 Mar 2012 03:48:41 +0000</pubDate>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=429</guid>

					<description><![CDATA[Para compilar uma versÃ£o local do Rails Guides, vocÃª pode fazer o seguinte processo: 1) Descubra qual o seu &#8220;gem path&#8221;, o local onde suas gems estÃ£o instaladas. No meu caso, o Rails estÃ¡ instalado diretamente no sistema e nÃ£o utilizo rvm ou rbenv. Para encontrar essa informaÃ§Ã£o, utilizei o comando &#8220;gem env&#8221; diretamente no [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Para compilar uma versÃ£o local do Rails Guides, vocÃª pode fazer o seguinte processo:</p>
<p>1) Descubra qual o seu &#8220;gem path&#8221;, o local onde suas gems estÃ£o instaladas. No meu caso, o Rails estÃ¡ instalado diretamente no sistema e nÃ£o utilizo rvm ou rbenv. Para encontrar essa informaÃ§Ã£o, utilizei o comando &#8220;gem env&#8221; diretamente no terminal. Meu path Ã© &#8220;/usr/local/lib/ruby/gems/1.9.1/gems/&#8221;.</p>
<p>2) Acesse o diretÃ³rio da gem railties. Essa gem Ã© como um &#8220;rails-core&#8221;, sendo o nÃºcleo e o &#8220;hub&#8221; em que todas as outras gems que compÃµe o framework (e tambÃ©m extensÃµes de terceiros) se registram para serem carregadas:</p>
<pre lang="bash">
lucashungaro@IronMan:/usr/local/lib/ruby/gems/1.9.1/gems
$ cd railties-3.2.2/guides

lucashungaro@IronMan:/usr/local/lib/ruby/gems/1.9.1/gems/railties-3.2.2/guides (master)
$ gem install RedCloth

lucashungaro@IronMan:/usr/local/lib/ruby/gems/1.9.1/gems/railties-3.2.2/guides (master)
$ ruby rails_guides.rb

lucashungaro@IronMan:/usr/local/lib/ruby/gems/1.9.1/gems/railties-3.2.2/guides (master)
$ mv output ~/projects/documentation/rails_guides_3.2.2
</pre>
<p>Isso irÃ¡ compilar os guias no diretÃ³rio local &#8220;output&#8221;, o qual movemos para uma localizaÃ§Ã£o mais familiar. NÃ£o encontrei uma forma de mudar o diretÃ³rio com argumentos na linha de comando. VocÃª pode fazer isso se chamar o gerador via cÃ³digo, no entanto. O script aceita outras opÃ§Ãµes via linha de comando, como a opÃ§Ã£o de gerar guias para o Edge Rails ou versÃ£o Kindle, entre outras.</p>
<p>3) Ao tÃ©rmino do processo, teremos os guias compilados em HTML no diretÃ³rio indicado. Para acessÃ¡-los vocÃª pode criar um bookmark em seu browser ou utilizar um SSB. Prefiro a segunda maneira e, para isso, utilizo o <a href="http://fluidapp.com/">Fluid</a> (para encontrar alguns Ã³timos Ã­cones visite <a href="http://www.flickr.com/groups/fluid_icons/">esse grupo no Flickr</a>. Basta criar uma nova aplicaÃ§Ã£o e apontar para o diretÃ³rio em que geramos os guias, iniciando pelo arquivo index.html.</p>
<div style="width: 500px" class="wp-caption aligncenter"><a href="http://blog.lucashungaro.com/wp-content/uploads/2012/03/guides.png"><img src="http://blog.lucashungaro.com/wp-content/uploads/2012/03/guides.png" title="Rails Guides com Fluid" width="490" height="328" class="size-full" /></a><p class="wp-caption-text">Rails Guides com Fluid</p></div>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.lucashungaro.com/2012/03/06/compilando-uma-versao-local-do-rails-guides/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>iPhone/iPad: minhas aplicaÃ§Ãµes favoritas</title>
		<link>http://blog.lucashungaro.com/2011/09/03/iphoneipad-minhas-aplicacoes-favoritas/</link>
					<comments>http://blog.lucashungaro.com/2011/09/03/iphoneipad-minhas-aplicacoes-favoritas/#respond</comments>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Sat, 03 Sep 2011 19:34:50 +0000</pubDate>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Dicas]]></category>
		<category><![CDATA[Entretenimento]]></category>
		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=421</guid>

					<description><![CDATA[Simples e rÃ¡pido, minhas aplicaÃ§Ãµes favoritas para iOS: Camera+: aplicativo para tirar fotos com opÃ§Ãµes adicionais (como controle de exposiÃ§Ã£o separado do foco) e efeitos de pÃ³s-processamento. Hipstamatic: provavelmente a app que lanÃ§ou a moda de efeitos vintage em fotos. A mais utilizada hoje Ã© o Instagram, mas ainda prefiro o Hipstamatic. 1Password: pra quem [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Simples e rÃ¡pido, minhas aplicaÃ§Ãµes favoritas para iOS:</p>
<ul>
<li><strong>Camera+</strong>: aplicativo para tirar fotos com opÃ§Ãµes adicionais (como controle de exposiÃ§Ã£o separado do foco) e efeitos de pÃ³s-processamento.</li>
<li><strong>Hipstamatic</strong>: provavelmente a app que lanÃ§ou a moda de efeitos vintage em fotos. A mais utilizada hoje Ã© o Instagram, mas ainda prefiro o Hipstamatic.</li>
<li><strong>1Password</strong>: pra quem utiliza a versÃ£o desktop, Ã© uma grande mÃ£o na roda pra lembrar senhas quando o celular Ã© tudo que temos Ã  mÃ£o.</li>
<li><strong>Dropbox</strong>: Ã³timo pra visualizar documentos e fotos.</li>
<li><strong>Convertbot</strong>: sou fanboy da Tapbots e uso todas as aplicaÃ§Ãµes dos caras. O Convertbot Ã© um conversor de unidades com muitas opÃ§Ãµes disponÃ­veis e uma UI fantÃ¡stica.</li>
<li><strong>Pastebot</strong>: mÃºltiplas Ã¡reas de transferÃªncia no iPhone, com direito Ã  operaÃ§Ãµes sobre o conteÃºdo copiado (como efeitos sobre imagens ou traduÃ§Ã£o de textos). AlÃ©m disso, com o Pastebot Sync, Ã© possÃ­vel copiar e colar conteÃºdos entre Mac e iPhone e vice-versa.</li>
<li><strong>Tweetbot</strong>: cliente de Twitter da Tapbots. UI sensacional, gestures, filtros, possibilidade de usar listas como timeline principal e vÃ¡rias outras opÃ§Ãµes.</li>
<li><strong>Weightbot</strong>: aplicaÃ§Ã£o para acompanhamento de peso, com estabelecimento de metas, cÃ¡lculo de IMC e grÃ¡ficos de projeÃ§Ãµes (pra vocÃª ver se estÃ¡ no ritmo certo pra chegar lÃ¡).</li>
<li><strong>Shazam</strong>: estÃ¡ num cafÃ© e comeÃ§a a tocar uma mÃºsica boa, mas vocÃª nÃ£o sabe o nome e/ou artista? Use o Shazam pra identificÃ¡-la. Uso bastante com trilhas sonoras de filmes tambÃ©m. <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>
<li><strong>Kindle</strong>: leitor de e-books, se integra muito bem com o Kindle for Mac.</li>
<li><strong>Reeder</strong>: Ã³timo leitor de feeds.</li>
</ul>
<p>Hora dos jogos:</p>
<ul>
<li><strong>Angry Birds e Angry Birds Seasons</strong>: clÃ¡ssico. Ã“timo passatempo pra longas esperas.</li>
<li><strong>Cut the Rope e Cut the Rope: experiments</strong>: Ã³timo jogo que combina elementos de fÃ­sica e habilidade de raciocÃ­nio pra resolver os problemas.</li>
<li><strong>Contre Jour</strong>: uma mistura de Angry Birds, Cut the Rope, Portal e outros jogos, com uma trilha sonora e visuais muito bons.</li>
<li><strong>Rage HD</strong>: prÃ©via do prÃ³ximo jogo para consoles da id Software, um shooter muito bem feito.</li>
<li><strong>Infinity Blade</strong>: provavelmente o jogo com grÃ¡ficos mais poderosos no iOS, leva o device (e a bateria) ao limite. O jogo em si nÃ£o Ã© uma obra-prima, mas vale pelos grÃ¡ficos.</li>
<li><strong>Death Rally</strong>: corrida + destruiÃ§Ã£o, power ups, jogo em estilo bem clÃ¡ssico com Ã³timos grÃ¡ficos e controles.</li>
<li><strong>Fruit Ninja</strong>: mais um jogo clÃ¡ssico e Ã³timo pra passar o tempo.</li>
<li><strong>Civilization Revolutions</strong>: pra quem Ã© fÃ£ da franquia, uma versÃ£o simplificada do Civ, dÃ¡ pra fazer um jogo completo em pouco mais de uma hora.</li>
</ul>
<p>Ã‰ isso! <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.lucashungaro.com/2011/09/03/iphoneipad-minhas-aplicacoes-favoritas/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<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/#respond</comments>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Sat, 23 Jul 2011 18:40:56 +0000</pubDate>
				<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 [&#8230;]]]></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="https://s.w.org/images/core/emoji/14.0.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></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>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Wed, 18 May 2011 22:38:49 +0000</pubDate>
				<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 [&#8230;]]]></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>
<pre lang="Ruby">
class MyInterface
  def method_1
    raise "abstract method called"
  end
  
  def method_2
    raise "abstract method called"
  end
  
  # and so on...
end

class MyClass < MyInterface
  def method_1
    # do something
  end
  
  def method_2
    # do something
  end
end
</pre>
<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 "specs de interface" 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>
<pre lang="Ruby">

# app/adapters/twitter_gem_adapter.rb
class TwitterGemAdapter
  def self.timeline(page=1, per_page=5, since_id = nil)
    options = {:page => page, :count => per_page}
    options[:since_id] = since_id if since_id

    Twitter.home_timeline(options)
  end

  def self.update(text)
    Twitter.update(text)
  end

  def self.reply(in_reply_to_status_id, text)
    Twitter.update(text, :in_reply_to_status_id => in_reply_to_status_id)
  end

  def self.retweet(tweet_id)
    Twitter.retweet(tweet_id)
  end

  def self.favorite(tweet_id)
    Twitter.favorite_create(tweet_id)
  end
end

# spec/support/shared_examples/twitter_adapter_examples.rb
module TwitterAdapterExamples
  shared_examples_for "any adapter for a twitter api gem" do
    it { should respond_to(:timeline)}
    it { should respond_to(:update)}
    it { should respond_to(:reply)}
    it { should respond_to(:retweet)}
    it { should respond_to(:favorite)}
  end
end

# spec/adapters/twitter_gem_adapter_spec.rb
describe TwitterGemAdapter do
  context "API contract" do
    subject { TwitterGemAdapter }

    it_behaves_like "any adapter for a twitter api gem"
  end
  
  # other specs ...
end
</pre>
<p>Aqui utilizamos a feature de "exemplos compartilhados" 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 "Duck-Typed" Languages</a></li>
<li><a href="http://confreaks.net/videos/185-rubyconf2009-solid-ruby">SOLID Ruby, by Jim Weirich - 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>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Wed, 11 May 2011 17:43:22 +0000</pubDate>
				<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 [&#8230;]]]></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>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Tue, 10 May 2011 02:57:16 +0000</pubDate>
				<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 [&#8230;]]]></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="https://s.w.org/images/core/emoji/14.0.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>O que quero dizer com isso?</p>
<p>Vamos ao exemplo do artigo anterior em sua Ãºltima versÃ£o:</p>
<pre lang="Ruby">
class Game < ActiveRecord::Base
  belongs_to :category
  validates_presence_of :title, :category_id, :description,
                        :price, :platform, :year
end
 
class GamePriceService
  attr_accessor :game
 
  # we could use a config file
  BASE_URL = "http://thegamedatabase.com/api/game"
  API_KEY = "ek2o1je"
 
  def initialize(game)
    self.game = game
  end
 
  def get_price
    data = open("#{BASE_URL}/#{game.name}/price?api_key=#{API_KEY}")
    JsonParserLib.parse(data)
  end
end
 
class GamePrinter
  attr_accessor :game
 
  def initialize(game)
    self.game = game
  end
 
  def print
    price_service = GamePriceService.new(game)
    <<-EOF
      #{game.name}, #{game.platform}, #{game.year}â€¨
      current value is #{price_service.get_price[:value]}
    EOF
  end
end
</pre>
<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 "de graÃ§a" 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 :D), em Ruby isso Ã© tÃ£o simples quanto passar um parÃ¢metro:</p>
<pre lang="Ruby">
class Game < ActiveRecord::Base
  belongs_to :category
  validates_presence_of :title, :category_id, :description,
                        :price, :platform, :year
end
 
class GamePriceService
  attr_accessor :game, :json_parser
 
  # we could use a config file
  BASE_URL = "http://thegamedatabase.com/api/game"
  API_KEY = "ek2o1je"
 
  def initialize(game, json_parser = JsonParserLib)
    self.game = game
    self.json_parser = json_parser
  end
 
  def get_price
    data = open("#{BASE_URL}/#{game.name}/price?api_key=#{API_KEY}")
    json_parser.parse(data)
  end
end
 
class GamePrinter
  attr_accessor :game, :game_webservice
 
  def initialize(game, game_webservice = GamePriceService)
    self.game = game
    self.game_webservice = game_webservice
  end
 
  def print
    price_service = game_webservice.new(game)
    <<-EOF
      #{game.name}, #{game.platform}, #{game.year}â€¨
      current value is #{price_service.get_price[:value]}
    EOF
  end
end

# Usage example:
game = Game.new(some_game_data)
webservice = GamePriceService.new(game)
game.price = webservice.get_price

GamePrinter.new(game).print
</pre>
<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>
<pre lang="Ruby">
class Game < ActiveRecord::Base
  belongs_to :category
  validates_presence_of :title, :category_id, :description,
                        :price, :platform, :year
end
 
class GamePriceService
  attr_accessor :game
 
  # we could use a config file
  BASE_URL = "http://thegamedatabase.com/api/game"
  API_KEY = "ek2o1je"
 
  def initialize(game)
    self.game = game
  end
 
  def get_price(json_parser = JsonParserLib)
    data = open("#{BASE_URL}/#{game.name}/price?api_key=#{API_KEY}")
    json_parser.parse(data)
  end
end
 
class GamePrinter
  attr_accessor :game
 
  def initialize(game)
    self.game = game
  end
 
  def print(game_webservice = GamePriceService)
    price_service = game_webservice.new(game)
    <<-EOF
      #{game.name}, #{game.platform}, #{game.year}â€¨
      current value is #{price_service.get_price[:value]}
    EOF
  end
end

# Usage example:
game = Game.new(some_game_data)
webservice = GamePriceService.new(game)
game.price = webservice.get_price

GamePrinter.new(game).print
</pre>
<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>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Wed, 04 May 2011 05:34:38 +0000</pubDate>
				<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 [&#8230;]]]></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>
<pre lang="Ruby">
class Game < ActiveRecord::Base
  belongs_to :category
  validates_presence_of :title, :category_id, :description,
                        :price, :platform, :year

  def get_official_price
    open("http://thegamedatabase.com/api/game/#{name}/price?api_key=ek2o1je")
  end

  def print
    <<-EOF
      #{name}, #{platform}, #{year}â€¨
      current value is #{get_official_price}
    EOF
  end
end
</pre>
<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>
<pre lang="Ruby">
class Game < ActiveRecord::Base
  belongs_to :category
  validates_presence_of :title, :category_id, :description,
                        :price, :platform, :year
end

class GamePriceService
  attr_accessor :game
  
  # we could use a config file
  BASE_URL = "http://thegamedatabase.com/api/game"
  API_KEY = "ek2o1je"
  
  def initialize(game)
    self.game = game
  end
  
  def get_price
    data = open("#{BASE_URL}/#{game.name}/price?api_key=#{API_KEY}")
    JsonParserLib.parse(data)
  end
end

class GamePrinter
  attr_accessor :game
  
  def initialize(game)
    self.game = game
  end
  
  def print
    price_service = GamePriceService.new(game)
    <<-EOF
      #{game.name}, #{game.platform}, #{game.year}â€¨
      current value is #{price_service.get_price[:value]}
    EOF
  end
end
</pre>
<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>4</slash:comments>
		
		
			</item>
		<item>
		<title>[Rant] Menos guerrinhas. Mais princÃ­pios</title>
		<link>http://blog.lucashungaro.com/2011/04/29/rant-menos-guerrinhas-mais-principios/</link>
					<comments>http://blog.lucashungaro.com/2011/04/29/rant-menos-guerrinhas-mais-principios/#comments</comments>
		
		<dc:creator><![CDATA[Lucas HÃºngaro]]></dc:creator>
		<pubDate>Fri, 29 Apr 2011 16:51:47 +0000</pubDate>
				<category><![CDATA[Cultura]]></category>
		<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[OpiniÃ£o]]></category>
		<guid isPermaLink="false">http://blog.lucashungaro.com/?p=406</guid>

					<description><![CDATA[Aviso: o post nÃ£o Ã© lÃ¡ a coisa mais coesa do mundo mas, bem, Ã© um rant, entÃ£o estou despejando pensamentos aqui. 🙂 Ã‰ algo muito bom que cada desenvolvedor possua sua &#8220;stack&#8221; preferida de ferramentas. O apreÃ§o por esse conjunto leva Ã  dedicaÃ§Ã£o e ao domÃ­nio do mesmo. Entre nÃ³s, que orgulhosamente nos categorizamos [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>Aviso</strong>: o post nÃ£o Ã© lÃ¡ a coisa mais coesa do mundo mas, bem, Ã© um rant, entÃ£o estou despejando pensamentos aqui. <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Ã‰ algo muito bom que cada desenvolvedor possua sua &#8220;stack&#8221; preferida de ferramentas. O apreÃ§o por esse conjunto leva Ã  dedicaÃ§Ã£o e ao domÃ­nio do mesmo. </p>
<p>Entre nÃ³s, que orgulhosamente nos categorizamos como &#8220;trabalhadores do conhecimento&#8221;, creio que, apesar desse apreÃ§o Ã  priori nÃ£o causar prejuÃ­zo, trocar de conjunto de ferramentas deveria ser muito fÃ¡cil (e uma habilidade desejÃ¡vel) jÃ¡ que o que importa Ã© a transformaÃ§Ã£o do conhecimento da forma bruta (dados) Ã  forma desejada (informaÃ§Ã£o), independente do que foi utilizado para isso. Ã‰ claro que hÃ¡ sempre a curva de aprendizado numa troca dessas: uma nova linguagem, nova DSL/API etc, mas os fundamentos e princÃ­pios se mantÃ©m.</p>
<p>Nerds, assim como toda pessoa imersa numa sociedade consumista, se definem pelo que consomem e utilizam. Isso Ã© algo bem comum atualmente e vai desde roupas atÃ© computadores, editores de texto, smartphones e, pasmem, Ã  p**** da biblioteca que o cara usa pra fazer parsing de XML. Algo que tornou-se muito comum, principalmente com a facilidade que existe para que cada um publique seus pensamentos (blogs, Twitter e afins), Ã© que ocorram &#8220;guerras&#8221; sobre esse tipo de coisa, jÃ¡ que, em nossa mente, criticar uma coisa que consumo Ã© praticamente criticar a mim e meu modo de viver.</p>
<p>Entre desenvolvedores isso Ã© bem visÃ­vel. AlÃ©m das guerrinhas entre comunidades (.NET x Java, Ruby x Python etc) hÃ¡ tambÃ©m as guerras intra-comunidade, em que escolhas de ferramentas sÃ£o motivo para disputas de ego interminÃ¡veis. O cenÃ¡rio, em geral, mostra uma galera que gosta da ferramenta X e acha que, por isso, a ferramenta Y Ã© uma merda inÃºtil e o pessoal que gosta da ferramenta Y achando o mesmo da ferramenta X.</p>
<p>Passemos a um exemplo num contexto diferente para que prÃ©-disposiÃ§Ãµes nÃ£o afetem nossas conclusÃµes. Imagine que Gordon Ramsay irÃ¡ a sua casa para fazer o jantar. Ele nÃ£o vai levar as facas, panelas e demais utensÃ­lios que usa em seu dia-a-dia. Vai utilizar apenas o que tem em sua casa. Dias depois vocÃª irÃ¡ a casa dele e utilizarÃ¡ todos os utensÃ­lios profissionais Ã  disposiÃ§Ã£o. Bom, a nÃ£o ser que vocÃª seja um anÃ´nimo chef de primeira categoria, sabemos quem irÃ¡ preparar o melhor jantar, nÃ£o? (sem piadinhas hein! :P)</p>
<p>Mais um. Quem serÃ¡ que toca melhor: Steve Vai com uma guitarra Giannini de 500 reais ou vocÃª com as guitarras ultra-caras dele?</p>
<p>Onde estÃ¡ o conhecimento? Na ferramenta ou no profissional?</p>
<p>Algo bizarro que acontece Ã© ver pessoas que deveriam ter bons conhecimentos sobre lÃ³gica confundindo argumento com preferÃªncia. Dizer que vocÃª prefere X porque acha mais bonito ou mais legal Ã© sÃ³ sua preferÃªncia, nÃ£o Ã© um argumento para diminuir as alternativas. Chega de &#8220;RSpec Ã© mais bonito e moderno, entÃ£o Test::Unit sucks!&#8221; e vice-versa (exemplo aleatÃ³rio, sem flames por favor).</p>
<p>BREAKING NEWS: se vocÃª nÃ£o sabe patavinas sobre design de cÃ³digo orientado a objeto e uma meia dÃºzia de princÃ­pios bÃ¡sicos, escrever testes em RSpec nÃ£o vai fazer com que vocÃª escreva cÃ³digo melhor do que escrevendo com Test::Unit. AliÃ¡s, Ã© bem capaz de piorar as coisas, mas isso Ã© conversa pra outro post. <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Em linhas mais prÃ¡ticas, pouco importa para o interessado na informaÃ§Ã£o se ela Ã© processada em PHP ou Ruby, se Ã© formatada em ERB ou HAML ou se estÃ¡ armazenada em MySQL ou PostgreSQL. A ferramenta &#8220;certa&#8221; Ã© a que faz o trabalho. Sempre hÃ¡ muita discussÃ£o sobre isso de &#8220;ferramenta certa&#8221; e, a nÃ£o ser que seja algo obviamente errado como usar o Rails pra fazer uma aplicaÃ§Ã£o desktop com controles nativos, o que sempre acaba entrando em jogo Ã© preferÃªncia, gosto, estÃ©tica e etc. Novamente, isso simplesmente nÃ£o serve como evidÃªncia de que algo Ã© superior ou inferior.</p>
<p>&#8220;Mas <strong>eu</strong> sou mais produtivo com X do que com Y!&#8221;<br />
&#8220;Olha sÃ³ como <strong>meu</strong> cÃ³digo fica mais limpo com Z do que com N!&#8221;</p>
<p>Ã‰, amiguinho. Pra vocÃª. Assim como tem muita gente que acredita em divindades criadoras e muita gente que nÃ£o. Muita gente que acha carros da Porsche bonitos e muita gente que os acha toscos e que os carros da Toyota sim sÃ£o lindos. DaÃ­ a dizer que algum Ã© melhor ou pior Ã© um longo caminho (e, na minha visÃ£o, um caminho inexistente).</p>
<p>Pois bem. Por isso creio que, como comunidade, devemos mudar um pouco nosso foco. Tudo bem falar sobre ferramentas, Ã© algo saudÃ¡vel desde que feito com bom senso. Com argumentos, fatos, contexto e harmonia. NÃ£o com guerrinhas bobas sobre gosto pessoal e como <del datetime="2011-04-29T10:50:26+00:00">seu pau Ã© maior que o dos outros</del> sua gem preferida Ã© a mais fodolenta do OMNIverso. Ã‰ bom para conhecermos alternativas e evoluirmos. Se todo mundo se prendesse ao atual e rejeitasse as novidades, ainda estarÃ­amos perfurando cartÃµes. Enfim, Ã© preciso foco em coisas que realmente fazem a diferenÃ§a na qualidade. Foco em fundamentos e princÃ­pios.</p>
<p>EstatÃ­sticas do DataLucas mostram que, a cada dois dias, surgem dezenas de posts falando sobre alguma gem que Ã© a coisa mais maravilhosa jÃ¡ inventada desde o <del datetime="2011-04-29T10:50:26+00:00">carro voador</del> Toddynho (e que prova que todo o resto Ã© uma merda!), sobre uma mirÃ­ade de workflows para o VCS da moda, sobre porque a minha biblioteca Ã© mais foda que a sua, sobre como o Agile morreu e, claro, como ele ainda estÃ¡ vivo e funciona muito bem sim senhor!</p>
<p>Legal, todo mundo tem uma opiniÃ£o sobre o que prefere e sobre o que nÃ£o gosta. Muito bom, Ã³timo, sensacional. Mas e o que Ã© imutÃ¡vel? Aquilo que determina qualidade independente do meio utilizado? JÃ¡ postei bastante essa frase, mas sempre gosto de relembrar:</p>
<blockquote><p>As to methods there may be a million and then some, but principles are few. The man who grasps principles can successfully select his own methods. The man who tries methods, ignoring principles, is sure to have trouble.</p></blockquote>
<p>â€” Ralph Waldo Emerson</p>
<p>Ainda nÃ£o achei frase que se encaixe mais com meu pensamento sobre desenvolvimento de software. Seja no nÃ­vel gerencial ou tÃ©cnico, dominar mÃ©todos (ferramentas) ignorando princÃ­pios com certeza leva Ã  problema. Manjar de todas as cerimÃ´nias e artefatos das metodologias Ã¡geis nÃ£o vai produzir software de qualidade magicamente. Entender seus princÃ­pios, mesmo que vocÃª nÃ£o aplique toda a parafernalha cerimonial, com certeza trarÃ¡ efeitos positivos.</p>
<p>EntÃ£o fica a pergunta: onde estÃ£o os posts e talks sobre princÃ­pios? Vamos falar sobre coisas como SOLID (nÃ£o, nÃ£o Ã© um besteirol acadÃªmico), acoplamento, coesÃ£o, testes que realmente especificam comportamento, trade-offs arquiteturais e outras questÃµes importantes?</p>
<p>Tentarei fazer a minha parte nisso. Ano passado na RubyConf parte da minha apresentaÃ§Ã£o falou sobre princÃ­pios (e outra sobre ferramentas :P) e penso em continuar com essa temÃ¡tica tanto no blog quanto em futuras apresentaÃ§Ãµes. Gostaria muito que a comunidade valorizasse mais esse tipo de discussÃ£o (wishful thinking&#8230;). </p>
<p>JÃ¡ fiz muito dessas guerrinhas, nÃ£o sou inocente, mas aprendi a valorizar a base, principalmente abrindo a mente (olha a piadinha!)  e dando chances Ã  ferramentas diferentes e, com isso, percebendo que em nossa profissÃ£o, felizmente, hÃ¡ vÃ¡rios meios eficientes para atingir os resultados desejados.</p>
<p>And&#8230; here comes the flames? <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><strong>PS</strong>: se vocÃª Ã© do contra e vai bater o pÃ©zinho dizendo que preferÃªncia e estÃ©tica sÃ£o evidÃªncias qualitativas, pode desistir e vaza. <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f600.png" alt="😀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Leitura recomendada: &#8220;<a href="http://bit.ly/hKN0bQ">A Little Knowledge is a Dangerous Thing</a>&#8220;</p>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.lucashungaro.com/2011/04/29/rant-menos-guerrinhas-mais-principios/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
