<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Maurício Szabo</title>
	<atom:link href="http://mauricioszabo.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://mauricioszabo.wordpress.com</link>
	<description>Diário de um Desenvolvedor de Sistemas.</description>
	<lastBuildDate>Fri, 13 Jan 2012 10:08:37 +0000</lastBuildDate>
	<language>pt-br</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='mauricioszabo.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Maurício Szabo</title>
		<link>http://mauricioszabo.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://mauricioszabo.wordpress.com/osd.xml" title="Maurício Szabo" />
	<atom:link rel='hub' href='http://mauricioszabo.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Testes de Controller &#8211; a Saga</title>
		<link>http://mauricioszabo.wordpress.com/2012/01/12/testes-de-controller-a-saga/</link>
		<comments>http://mauricioszabo.wordpress.com/2012/01/12/testes-de-controller-a-saga/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 01:54:31 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[testes]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=327</guid>
		<description><![CDATA[Semana passada comecei finalmente um projeto do zero usando Rails 3.1. A experiência foi novidade para mim, que por causa de uma série de legados (e também por questão de performance) estava preso no Rails 2.3, e não tive a &#8230; <a href="http://mauricioszabo.wordpress.com/2012/01/12/testes-de-controller-a-saga/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=327&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Semana passada comecei finalmente um projeto do zero usando Rails 3.1. A experiência foi novidade para mim, que por causa de uma série de legados (e também por questão de performance) estava preso no Rails 2.3, e não tive a oportunidade de ver como os testes funcionam no Rails 3.</p>
<p>Mas antes de chegar no assunto, vamos rever que o Rails não é puramente MVC. O &#8220;Controller&#8221; do Rails agrega coisas que deveriam ser feitas na view (basicamente, buscar o objeto para ser exibido). Para mais detalhes, ver <a href="http://mauricioszabo.wordpress.com/2011/12/13/model-view-controller/" title="Model View Controller">meu post anterior</a>.</p>
<p>Por esse motivo, e unicamente por este motivo, eu não acredito ser possível fazer teste unitários de controllers.</p>
<p>Um teste unitário deve, em teoria, testar um pedaço do sistema, isoladamente de outras partes. Como fazer um teste unitário de algo que é, essencialmente, um &#8220;glue code&#8221;, ou seja, um código que une regras de negócio (Models) e interfaces (Views)?</p>
<p>Antes do Rails 3, eu usava uma abordagem mais &#8220;integrada&#8221; para esses specs. No controller, eu usava a palavra-chave do rspec-rails &#8220;integrate_views&#8221;, e testava o par &#8220;controller-view&#8221;. Os specs ficavam mais ou menos assim:</p>
<p><pre class="brush: ruby;">
describe PeopleController do
  integrate_views
  
  it 'should show people on &quot;index&quot;' do
    sessions[:user_id] = Factory(:user).id
    Factory :person, :name =&gt; &quot;Foo Bar Baz&quot;
    get :index
    response.should be_success
    response.body.should include(&quot;Foo Bar Baz&quot;)
  end
  
  it 'should render &quot;new&quot; view if validation failed&quot; do
    sessions[:user_id] = Factory(:user).id
    post :create, :person =&gt; { }
    response.should render_template(&quot;new&quot;)
  end
end
</pre></p>
<p>Claramente, isso não é um teste unitário, mas há um grande ganho nessa abordagem: se eu resolver mudar a variável &#8220;@users&#8221; para &#8220;@records&#8221;, e atualizar a view, não preciso mexer em nenhum spec. Na prática mesmo, eu não preciso mexer em nenhum SPEC se eu mudar o layout, adicionar mais informações na view, buscar mais registros no controller e atualizá-los na view, enfim, em qualquer momento eu sei, exatamente, se o teste está falhando ou passando, sem as fragilidades que mocks podem oferecer.<br />
<span id="more-327"></span><br />
No Rails 3, porém, apareceu um novo diretório: spec/requests. No início do projeto que estou fazendo, comecei a usar o spec/controllers para fazer meus testes (com, obviamente, &#8220;render_views&#8221; no lugar de &#8220;integrate_views&#8221;), mas pouco a pouco isso se mostrou um pouco&#8230; inútil, digamos assim. Isso porque o diretório &#8220;spec/requests&#8221; pode usar o &#8220;Capybara&#8221; para fazer seus testes, o que significa que com os drivers corretos, eu posso inclusive rodar javascript, e nesse caso eu posso ter uma abordagem ainda MAIS integrada: ao invés de ir direto para o controller que eu quero testar, eu posso de fato LOGAR o usuário, ver se a ação que eu quero testar está disponível (isto é, se há links que levam até a ação), ver se o usuário tem acesso ou não (e testar mais facilmente os acessos), etc&#8230; o que me levou a, definitivamente, deixar de usar o &#8220;spec/controllers&#8221; para esse tipo de teste. O resultado final é mais ou menos assim (usando Capybara):</p>
<p><pre class="brush: ruby;">
describe 'People' do #Refere-se ao PeopleController
  it 'should list people' do
    Factory :person, :name =&gt; &quot;Foo Bar Baz&quot;
    user = Factory :user
    visit root_path
    click_link 'Sign in'
    fill_in 'Login', :with =&gt; user.login
    fill_in 'Password', :with =&gt; user.password
    click_button 'Login'
    click_link 'People'
    body.should include('Foo Bar Baz')
  end
  
  #... mesma coisa para o &quot;new&quot;, só que preenchendo os formulários
end
</pre></p>
<p>Ok, só que o teste definitivamente ficou maior do que a versão do Controller. Para resolver isso, basta criar um arquivo, digamos, em &#8220;spec/support/login_helper.rb&#8221;, e colocar o código de logar usuário lá. Mais um ou outro helper, e o arquivo fica mais ou menos assim:</p>
<p><pre class="brush: ruby;">
#arquivo spec/support/login_helper.rb
def enter_on_admin_by(link)
  login_user
  click_link link
end

def login_user(user = Factory :user)
  visit root_path
  click_link 'Sign in'
  fill_in 'Login', :with =&gt; user.login
  fill_in 'Password', :with =&gt; user.password
  click_button 'Login'
end
</pre></p>
<p>Aí o SPEC fica assim:</p>
<p><pre class="brush: ruby;">
describe 'People' do
  it 'should list people' do
    enter_on_admin_by 'People'
    body.should include('Foo Bar Baz')
  end
  
  it 'should show errors if creating an invalid person&quot; do
    enter_on_admin_by 'People'
    click_link 'New person'
    click_link 'Save'
    body.should match(/Name can't be blank/)
  end
end
</pre></p>
<p>A maior vantagem desta abordagem é que, quando os códigos nos controllers ou views tiverem um pouco mais de peculiaridades, é possível escrever um código de teste apenas para o controller e testar aquela funcionalidade isoladamente&#8230; claro, desde que isso não introduza testes frágeis.</p>
<p>Enfim, como um &#8220;bonus point&#8221;, uma coisa que eu me preocupo sempre é em escrever poucas linhas de teste para fazer coisas &#8220;the rails way&#8221;, isto é, se eu for testar uma tela de cadastro &#8220;padrão&#8221;, eu não precise escrever demais. Para isso, eu fiz um helper nos meus testes:</p>
<p><pre class="brush: ruby;">
#arquivo spec/support/crud_helper.rb
def assert_created_record(element)
  record = Factory.stub element
  update_each_attribute element, record.attributes
  click_button 'Create'
  body.should include(record.attributes.values[1].to_s)
end

def update_each_attribute(element, attributes)
  attributes.each_pair do |field, value|
    field_name = &quot;#{element}[#{field}]&quot;
    fill_in_field field_name, value
  end
end
private :update_each_attribute

def fill_in_field(field_name, value)
  case value
    when String then fill_in field_name, :with =&gt; value
    when true, false then check field_name
  end
rescue Capybara::ElementNotFound
end
private :fill_in_field
</pre></p>
<p>E então, meus testes podem ficar mais simples quando eu for criar uma pessoa no formato padrão do Rails:</p>
<p><pre class="brush: ruby;">
describe 'People' do
  #...outros testes...
  
  it 'should create a new person' do
    enter_on_admin_by 'People'
    click_link &quot;New person&quot;
    assert_created_record :person
  end
end
</pre></p>
<p>E com isso, se for bem disciplinado, é possível identificar imediatamente &#8220;código-morto&#8221;: se cada teste em seu &#8220;spec/requests&#8221; está cobrindo uma característica de seu programa, basta rodar uma ferramenta de cobertura de código (simple_cov, por exemplo) no diretório spec/requests. Espera-se que todos os controllers estejam cobertos. Se um model tem partes que não estão cobertas, provavelmente essa parte pode ser eliminada do sistema. Até agora, só vi vantagens nessa abordagem.</p>
<p>Por fim, se alguma parte do sistema depender de Javascript, é possível escrever o método com:</p>
<p><pre class="brush: ruby;">
describe 'People' do
  it 'should do something with ajax', :driver =&gt; :webkit do
    click_link &quot;Remote call&quot;
    wait_until { body =~ /Add child/ }
  end
end
</pre></p>
<p>e usar a gem &#8220;capybara-webkit&#8221;, que é muito boa. Só lembrar de SEMPRE usar &#8220;wait_until&#8221;, para assegurar que a página carregou antes de continuar o teste. Outra coisa, esse tipo de abordagem exigiria desabilitar &#8220;transactional_fixtures&#8221;, o que deixa os testes BEM mais lentos. Uma alternativa seria, num arquivo como &#8220;spec/support/ar_shared_connection.rb&#8221;, colocar o código abaixo (retirado do blog da PlataformaTEC):</p>
<p><pre class="brush: ruby;">
#Baseado no artigo da Plataforma:
#http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/

class ActiveRecord::Base
  mattr_accessor :shared_connection
  @@shared_connection = nil
 
  def self.connection
    @@shared_connection || retrieve_connection
  end
end
 
# Forces all threads to share the same connection. This works on
# Capybara because it starts the web server in a thread.
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
</pre></p>
<p>Enfim, é isso. Controllers para specs bem específicos, requests para testar extensivamente o controller em abordagem mais &#8220;integrada&#8221;, e models para testar regras de negócio. Agora, só falta aprender como fazer o SPORK funcionar corretamente :).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/327/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/327/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/327/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/327/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/327/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/327/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/327/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/327/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/327/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/327/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/327/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/327/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/327/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/327/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=327&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2012/01/12/testes-de-controller-a-saga/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>Model View Controller</title>
		<link>http://mauricioszabo.wordpress.com/2011/12/13/model-view-controller/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/12/13/model-view-controller/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 16:56:46 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Divagações]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[paradigmas]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=322</guid>
		<description><![CDATA[Ultimamente, Rails tem se popularizado, e com ele o famoso (e já antigo) MVC. Porém, como todas as coisas, a prática acabou sobrepondo a teoria, então achei que seria interessante falar um pouco sobre MVC, já que parece-me que algumas &#8230; <a href="http://mauricioszabo.wordpress.com/2011/12/13/model-view-controller/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=322&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Ultimamente, Rails tem se popularizado, e com ele o famoso (e já antigo) MVC. Porém, como todas as coisas, a prática acabou sobrepondo a teoria, então achei que seria interessante falar um pouco sobre MVC, já que parece-me que algumas confusões começaram a acontecer. Esse post é imensamente baseado <a href="http://martinfowler.com/eaaDev/uiArchs.html">nesse post do Martin Fowler</a> sobre arquiteturas GUI, então seria interessante ler ele também.</p>
<p>Enfim, vamos lá: no Rails, quando fazemos um &#8220;scaffold&#8221;, é criada uma combinação de coisas para nós: uma &#8220;migration&#8221;, que cria uma tabela no banco. Um &#8220;model&#8221;, que basicamente é o mapeamento dessa tabela para um objeto. Um &#8220;controller&#8221;, que faz a busca do registro certo e repassa para a renderização da tela. Por exemplo, a ação &#8220;edit&#8221;:</p>
<p><pre class="brush: ruby;">
  def edit
    @foo = Foo.find(params[:id])
    render :action =&gt; 'edit' #Isso é redundante, mas deixa explícito um aspecto importante.
  end
</pre></p>
<p>Além disso, há uma série de boas-práticas, tais como não concentrar código de regra de negócio no controller, não colocar lógica nas views, enfim. Porém, essas &#8220;regra gerais&#8221; pecam em um ponto:</p>
<p>Rails não é 100% MVC&#8230;<br />
<span id="more-322"></span><br />
Bom, explicando mais detalhadamente: digamos que todas as telas de cadastro precisem, além dos dados gerais do objeto, um &#8220;select&#8221; que contenha dados de outra model:</p>
<p><pre class="brush: ruby;">
  &lt;p&gt;
    &lt;%= f.label :bars %&gt;&lt;br /&gt;
    &lt;%= f.select :bar_id, Bar.all.map { |b| [b.name, b.id] } %&gt;
  &lt;/p&gt;
</pre></p>
<p>Pelas regras do Rails, isso é lógica na view, e deveria ser movido para outro lugar. Um helper, um controller, enfim. Mas o que é exatamente um helper? O lugar certo do código é realmente em um helper? E se esse código dependesse do registro atual, algo como:</p>
<p><pre class="brush: ruby;">
  &lt;p&gt;
    &lt;%= f.label :bars %&gt;&lt;br /&gt;
    &lt;% 
       bars = if @foo.is_admin?
         Bar.all.map { |b| [b.name, b.id] }
       else
         Bar.only_active.map { |b| [b.name, b.id] }
       end 
    %&gt;
    &lt;%= f.select :bar_id, bars %&gt;
  &lt;/p&gt;
</pre></p>
<p>E agora, isso deve ficar na view, num helper (eu, particularmente, acho estranho colocar lógica num helper quando ele depende de uma variável de instância que veio de um controller), ou no próprio controller?</p>
<p>Bom, a resposta é simples: esse é um código DA VIEW. Só que, a view NÃO É só o HTML (ou, no nosso caso, o ERB, HAML, enfim). No Rails, controllers fazem um papel que é responsabilidade da view, que basicamente é buscar os registros e instanciar os modelos que são necessários para a view existir. Se for usado render :update, :inline, :text ou mesmo &#8220;render_to_string&#8221;, só estamos ainda mais expondo esse método da view no controller.</p>
<p>Então, o que verdadeiramente é o &#8220;V&#8221; e o &#8220;C&#8221;?</p>
<p>Pelo MVC, através de observers, a view é notificada de alterações no &#8220;model&#8221;, e reage de acordo com a alteração. Logo, se o model foi salvo, a view reage identificando se esse salvamento foi bem sucedido, ou se foi mal-sucedido e em cada caso decide o que fazer. A view é também &#8220;independente&#8221; do controller, isso é, uma view contém em si TODAS as informações necessárias para ser exibida. Porém, sabemos que a web é &#8220;stateless&#8221;, logo não podemos guardar o estado do model e da view e &#8220;encaixar&#8221; observers nesse modelo&#8230; mas, poderíamos sim deixar o rails mais &#8220;MVC&#8221;:</p>
<p><pre class="brush: ruby;">
#app/controllers/foos_controller.rb
class FoosController &lt; ApplicationController
  def edit
    render :FooView, :edit #Até poderia ser redundante, também
  end
  #...
end

#app/views/foo_view.rb
class FooView &lt; ActiveView::Base #imaginando uma abordagem...
  def edit
    @foo = Foo.find(params[:id])
    erb :edit
  end

  def bars_collection
    Bar.all.map { |b| [b.name, b.id] }
  end
  private :bars_collection
end

#app/views/foo_view/layouts/edit.html.erb
&lt;% form_for(@foo) do |f| %&gt;
  &lt;p&gt;
    &lt;%= f.label :bars %&gt;&lt;br /&gt;
    &lt;%= f.select :bar_id, bars_collection %&gt;
  &lt;/p&gt;
&lt;% end %&gt;
</pre></p>
<p>BEM mais separado. Além disso, agora toda a lógica de renderização da view fica num lugar correto chamado &#8220;View&#8221;, não espalhados pelos controllers. Por fim, acaba-se a necessidade de &#8220;helpers&#8221;, pois temos uma abordagem &#8220;orientada a objetos&#8221; para views. Alguém afim de implementar isso?</p>
<p>Há uma última coisa a mencionar: &#8220;Models&#8221; não são apenas tabelas em banco de dados. Model é basicamente um &#8220;objeto de domínio&#8221;, ou seja, uma classe que concentra regras de negócio de um determinado tipo, que <strong>podem ou não</strong> estar ligados a dados mesmo. Ou seja, nada me impede de criar um model assim:</p>
<p><pre class="brush: ruby;">
class TaxCalculator
  def initialize(salary)
    @salary = salary
  end

  def ir
    @salary * 0.25 #Hipoteticamente, claro...
  end
end
</pre></p>
<p>E usá-lo em minha view. Recapitulando, então:</p>
<ul>
<li><strong>Models</strong> são objetos de domínio. Podem representar cálculos, dados, registros de banco de dados, coleções de registris em bancos de dados, etc.</li>
<li><strong>Views</strong> são objetos que definem uma tela. Podem ter lógica de programação envolvida, desde que essa lógica se prenda apenas à exibição para o usuário. Reagem a mudanças na view, em casos onde a programação envolve mudança de estados (tal como GUI)</li>
<li><strong>Controllers</strong> são objetos que reagem a interações do usuário (cliques em botões, etc) e roteiam essas ações para causar uma mudança de estados no Model que, consequentemente, informará a View através do mecanismo de &#8220;observers&#8221; que algo mudou, e quem decide como vai atuar naquela mudança é a View.</li>
</ul>
<p>Ok, mas e no mundo &#8220;stateless&#8221; da web, aonde instâncias das views, controllers e models são &#8220;descartadas&#8221; depois de cada requisição, o que fazer? Nesse caso, cada framework tem sua abordagem. No caso do Rails, o Controller server como um &#8220;roteador&#8221;, que a partir de uma reação (GET, POST, PUT ou DELETE numa URL) identifica o que foi feito (através do método HTTP, da URL e dos parâmetros) e roteia para o caminho certo (redireciona para outro controller ou outra action, ou re-renderiza uma página).</p>
<p>Essa foi a abordagem Rails. Não está certa nem errada, mesmo a abordagem &#8220;MVC pura&#8221; não está certa nem errada. O que está errado é defender uma certa prática no MVC porque o Rails faz assim&#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/322/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/322/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/322/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/322/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/322/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/322/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/322/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/322/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/322/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/322/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/322/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/322/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/322/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/322/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=322&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/12/13/model-view-controller/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>Redes Sociais</title>
		<link>http://mauricioszabo.wordpress.com/2011/11/24/redes-sociais/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/11/24/redes-sociais/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 14:57:09 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Divagações]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[Redes Sociais]]></category>
		<category><![CDATA[sociedade]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=317</guid>
		<description><![CDATA[Bom, dei uma parada sobre os posts mais técnicos, mas estou preparando um sobre alguns estudos que fiz em Scala. Até lá, vou falar de um assunto que ultimamente tem me deixado meio pensativo: redes sociais. Para os que me &#8230; <a href="http://mauricioszabo.wordpress.com/2011/11/24/redes-sociais/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=317&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Bom, dei uma parada sobre os posts mais técnicos, mas estou preparando um sobre alguns estudos que fiz em Scala. Até lá, vou falar de um assunto que ultimamente tem me deixado meio pensativo: redes sociais.</p>
<p>Para os que me conhecem mais a fundo, sabem que eu sou meio &#8220;alérgico&#8221; a redes sociais. Aderi ao twitter e ao facebook depois que muita gente já estava usando, e não tenho linkedin, nem google buzz ou google+. Só que eu acho que algumas pessoas estão &#8220;perdendo o fio&#8221; do que é cada rede social. Usei o twitter, sempre, mais como uma forma de me manter atualizado tecnicamente do que para encontrar amigos-afinal, eu não vejo o motivo de ficar trocando mensagens de 140 caracteres com amigos meus (e deixar isso disponibilizado para o mundo). Aliás, cabe aqui uma observação interessante: a língua, o idioma, é absolutamente frágil. Por isso existem tantas formas de dizer algo, de falar ou pronunciar uma palavra, um sentido&#8230; por isso o &#8220;<a href="http://en.wikipedia.org/wiki/Turing_test">teste de Turing</a>&#8221; ainda não foi vencido, por isso que é tão difícil processar linguagem natural, por isso que existem trocadilhos e poesias-todos, abusando de características da linguagem que podem dar duplo-sentido, dupla-interpretação, etc.</p>
<p>Isso, na linguagem falada. A linguagem escrita é MUITO pior.</p>
<p>Porque, na linguagem escrita, você não tem aspectos simples como o olhar da pessoa, sorrisos, movimento corporal, tom de voz, e às vezes é difícil de dar a entender que uma coisa é sarcasmo quando se está escrevendo (antes, se usava itálico, tipo &#8220;Hahaha, <em>claro</em> que eu vou fazer isso!&#8221;). E em 140 caracteres, é MUITO mais difícil. Especialmente em português, que é um idioma que notavelmente se escreve demais (&#8220;Right click&#8221; vs &#8220;Clique com o botão esquerdo do mouse&#8221; é um exemplo bem notável). Percebo isso no twitter quando eu não gosto de algo e posto lá: pra não ser subentendido, eu preciso escrever mais de 140 caracteres&#8230;<br />
<span id="more-317"></span><br />
Mas voltando ao assunto: redes sociais. Aí, começam a surgir os clones, que são &#8220;o facebook do X&#8221; ou o &#8220;twitter do Y&#8221;, ou os clones open-source, ou os clones de empresas que querem mercado &#8220;*cof* Google *cof*&#8221;, enfim. E também tem os usuários que retwittam algo no facebook, ou colocam hashtags no facebook, ou informam que &#8220;tão saindo de casa&#8221;, &#8220;tão almoçando&#8221;, ou fazendo check-in nos lugares pelo 4square (ou um de seus clones)&#8230; e eu acho que essas pessoas perdem um pouco o fio da meada de uma coisa:</p>
<p>Quando você publica algo no facebook, você está postando algo para CENTENAS de pessoas. Por exemplo, no meu facebook, eu possuo cerca de 150 amigos-e me considero alguém que tem poucos amigos, já que eu só adiciono quem eu conheço, etc&#8230; mas usando uma média para baixo, vamos pensar em 200 amigos. Digamos que eu poste algo no meu &#8220;mural&#8221;-só com isso, duzentas pessoas estão vendo. Se uma dessas pessoas compartilhar, são mais duzentas. Digamos que vocês compartilhem 50 amigos, sua postagem foi para 350 pessoas. Se você postou algo que é uma piada interna, e pode ser mal-interpretado&#8230; no caso do 4square, já imaginou que ao fazer &#8220;check-in&#8221; na sua casa, com dois simples &#8220;compartilhar&#8221; de seus amigos você está publicando o endereço da sua casa para umas 300 pessoas que você nunca viu na vida? Que se alguém quiser saber se você está em casa, basta acessar seu mural e esperar pelo seu &#8220;check-in&#8221; em algum lugar muito longe? E que as coisas que publicamos em nossos murais dizem muito a respeito da nossa condição social, etc. Em resumo, um possível ladrão pode:</p>
<p>- Saber seu nome, e de seus parentes (e grau de parentesco)<br />
- Saber quais são seus &#8220;gadgets&#8221; e computadores em casa<br />
- Saber AONDE é sua casa<br />
- Saber AONDE você ESTÁ<br />
- E tudo isso SEM SAIR DE CASA&#8230;</p>
<p>Apenas com um computador, conectado na internet. É absurdo, porém verdadeiro.</p>
<p>Outra coisa: você é um ativista em prol do socialismo, veganismo, budismo, do metal, à favor ou contra determinada lei, enfim, você pode postar algo assim no Facebook. MAS, e isso é um <strong>GRANDE MAS</strong>, a partir do momento que você posta algo você dá ao direito das pessoas</p>
<p>- Concordarem com você<br />
- Discordarem de você<br />
- Não darem a mínima</p>
<p>E aí, acontecem os não-raros posts falando &#8220;puxa, o mundo está passando fome, e ninguém dá a mínima&#8221; ou os &#8220;essa é minha opinião, se você não concorda guarde pra você&#8221; e outros &#8220;mimimimimi&#8221;s. Só que, o que as pessoas esquecem especialmente no segundo caso, e que <b>se você postou algo pra algumas pessoas que você sabe que podem discordar ou até não gostar, quem deveria ter guardado isso pra si é você</b>, a não ser claro que você esteja disposto a aceitar que as pessoas possam discordar. E nisso pode sim surgir discussões úteis. Como ferramenta de discussão, a internet pode ser até melhor do que pessoalmente, SÓ QUE isso exige uma maturidade que eu, sinceramente, acredito que nós ainda não adquirimos.</p>
<p>Se há algo de bom nisso tudo é que o twitter, o facebook, nos ajudam a desenvolver uma tolerância maior a certas coisas (meio que um &#8220;teste de fogo&#8221;). Quantas vezes eu já quis deletar um usuário do twitter porque os tweets dele era superficiais (e cegos) em determinados assuntos, mas não o fiz porque outros tweets dele são muito bons? No fim das contas, acabei desenvolvendo uma tolerância maior à opiniões-mesmo que elas sejam incorretas (e mesmo que nenhuma explicação lógica do mundo faça a pessoa mudar de idéia). Isso é algo que os botões de &#8220;ignore&#8221; tiraram de nós, essa habilidade-no primeiro momento que alguém começou a escrever coisas que fisgam um pouco suas idéias, &#8220;ignore&#8221; nele&#8230;</p>
<p>Por fim, e o mais estranho, quando alguém diz que quer colocar monitoramento na internet, as pessoas gritam em nome da &#8220;privacidade&#8221;. Qual privacidade, quando deliberadamente informamos tanta coisa na internet pra qualquer um ver, sem distinção nenhuma?</p>
<p>Lembrando que eu sou, sim, muito a favor da privacidade na internet. Porém, me preocupa o fato de que se eu me recuso a deixar explicitado na internet quem eu sou, como eu sou, aonde eu moro, enfim, todas as possíveis informações sobre mim, de repente eu sou a pessoa estranha&#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/317/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/317/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/317/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/317/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/317/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/317/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/317/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/317/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/317/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/317/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/317/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/317/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/317/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/317/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=317&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/11/24/redes-sociais/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>Ensaio Sobre Graduação</title>
		<link>http://mauricioszabo.wordpress.com/2011/11/05/ensaio-sobre-graduacao/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/11/05/ensaio-sobre-graduacao/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 14:59:03 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Divagações]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[estruturas de dados]]></category>
		<category><![CDATA[sociedade]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=313</guid>
		<description><![CDATA[Depois de assistir a palestra do Tenderlove no RubyConfBR (e ficar impressionado porque estava estudando EXATAMENTE os assuntos de Automatos há pouco tempo atrás), vi uns tweets sobre graduação. Na verdade, foi principalmente o tweet do @dannluciano que trouxe uma &#8230; <a href="http://mauricioszabo.wordpress.com/2011/11/05/ensaio-sobre-graduacao/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=313&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Depois de assistir a palestra do Tenderlove no RubyConfBR (e ficar impressionado porque estava estudando EXATAMENTE os assuntos de Automatos há pouco tempo atrás), vi uns tweets sobre graduação. Na verdade, foi principalmente <a href="https://twitter.com/#!/dannluciano/status/132421908338708480">o tweet do @dannluciano</a> que trouxe uma série de respostas de outros tweets que eu concordo até certo ponto, e discordo de muitos outros pontos.</p>
<p>Proponho uma pergunta: qual é a idéia da graduação, nos tempos como hoje? Explicando, em tempos de Wikipedia, de Google, aonde entra uma graduação? Acho que aqui, temos que separar duas coisas: Faculdade, Universidade, e Colegial Técnico.</p>
<p>Pra maior parte das pessoas (e infelizmente, para nosso país e o mercado de trabalho e governo dele), a graduação é um &#8220;upgrade&#8221; da formação média, e o &#8220;colegial técnico&#8221; fica meio perdido nesse meio do caminho&#8230; além disso, muitos professores (e infelizmente eu conheço isso, tendo trabalhado numa universidade federal) ainda acham, nos dias da Wikipedia, que são donos do conhecimento, e ninguém chega ao conhecimento sem o intermédio deles.</p>
<p>Os que me acompanham no Twitter devem ter visto que eu prestei o Poscomp.  Num dos livros que peguei, havia a seguinte frase:</p>
<blockquote><p>Função injetora é aquela que, para dois elementos distintos a, a&#8217; ∈ A, f(a) ≠ f(a&#8217;)</p></blockquote>
<p>Uhn&#8230; então, eu resolvi ir para a <a href="http://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_injetora">Wikipedia</a>:</p>
<blockquote><p>Uma função diz-se injectiva (ou injetora) se e somente se quaisquer que sejam x1 e x2 pertencentes ao domínio da função, se x1 é diferente de x2 implica que f(x1) é diferente de f(x2)</p></blockquote>
<p>Há um &#8220;Link&#8221; para &#8220;domínio&#8221;, e há um gráfico mostrando graficamente essa explicação. Não precisa ser um gênio para entender que a explicação da Wikipedia está mais simples e melhor explicada e exemplificada. Ok. Mas, e isso é importante notar, eu não chegaria ao artigo da Wikipedia sem o livro, sem o poscomp, e não teria entendido a palestra do Tenderlove sem ter estudado para o Poscomp (ainda que eu tenha usado os livros como &#8220;grandes índices&#8221; e a Wikipedia como forma de aprender, propriamente dita).<br />
<span id="more-313"></span><br />
Continuando: o que é a graduação? Antes disso, vamos pensar na etimologia: universidade, vem de &#8220;Universo&#8221;, ou seja, você tem um universo de informações à sua disposição. Universidade não deveria ser um &#8220;level-up&#8221; da faculdade, onde ela adquire determinado número de alunos e cursos e, de repente, é uma universidade. Algo que eu sempre digo, pintar uma casa abandonada de verde não vai melhorar a estrutura dela, ou a localização, ou a segurança-ela continua sendo uma casa abandonada, porém agora está pintada de verde&#8230;</p>
<p>Vamos pensar no seguinte assunto (coisas q eu não vi na minha &#8220;universidade&#8221;, mas enfim): Automatos, Linguagens, Linguagens Regulares, e até mesmo complexidade de algoritmos. Tenderlove falou sobre o assunto e mostrou como aplicar esses conceitos na hora de criar uma nova forma de identificar rotas no Rails 3.2. Interessante, porém mesmo quem já viu automatos, linguagens regulares, etc. nas faculdades provavelmente não sabia aonde aplicar esses conceitos. Mas estou saindo do assunto de novo, então voltando: todos esses conceitos são, sim, importantes de ver numa universidade, e até mesmo numa faculdade, <b>porém</b> (e esse porém é bem grande) na maioria das vezes um desenvolvedor de sistemas NÃO PRECISA saber estes conceitos, a não ser que você vá criar um framework super famoso usado por milhares ou até milhões de pessoas como o&#8230; Rails, por exemplo&#8230;</p>
<p>O problema, não é a graduação, mas a necessidade dela para conseguir empregos melhores (ou até para conseguir empregos, simplesmente), e o que se ensina nela sem aplicação. Conheço aos montes pessoas que sabem o que são linguagens regulares mas não conhecem expressões regulares, que sabem o que são AST, Bytecodes, Interpretadores, JIT, e acham que os programas feitos em Java não são interpretados, que Ruby 1.9.2 não tem bytecode (só pq não tem um arquivo, digamos, RBC contendo o bytecode) ou até mesmo que confundem &#8220;linguagens dinâmicas e estáticas&#8221; com &#8220;linguagens interpretadas e compiladas&#8221;, respectivamente.</p>
<p>Resultado final: 80% (sem exagero) dos programadores só precisam de um &#8220;colegial técnico&#8221;, ou nem isso. Para um programador acima da média, ele aprenderia MUITO mais rápido (e poderia ser um programador pleno ao invés de júnior ou estagiário) conceitos interessantes numa faculdade <strong>DESDE QUE</strong> a faculdade se importasse em ensinar coisas importantes, como SOLID, boas-práticas, TDD (no nosso cenário atual, só teste automatizado já estaria bom), programação funcional (de um jeito decente, não essas &#8220;brincadeiras acadêmicas de calcular fatorial recursivamente&#8221;), enfim, outros conceitos que se usam em 80% do mercado de trabalho. O colegial técnico, nessa história, serviria para o profissional saber programar, única e exclusivamente. Esses dois lugares PRECISAM ENTENDER que não são mais detentores exclusivos do conhecimento, então eles devem atuar como facilitadores no acesso à informação. A idéia aqui é: se eu posso procurar algo na Wikipedia, porque eu não o faria? Então, o colegial e a faculdade precisariam me apontar nessa direção, me ensinar o básico ou o intermediário, e não acharem que só porque há um professor formado me ensinando eu não vou ter conhecimentos fora o que me ensinam. Ao mesmo tempo, o trabalho dessas duas instituições seria também acabar com os vícios que muitos programadores tem (ok, isso é quase uma piada, já que na faculdade e no colegial técnico normalmente é o lugar aonde se adquirem mais vícios, mas isso teria que ser repensado também).</p>
<p>A universidade fica como o lugar aonde se ensinaria, verdadeiramente, conceitos que fariam o profissional conhecer estruturas de dados complexas (eu não estou falando de pilhas e filas, isso os profissionais realmente empenhados aprendem sozinhos porque são estruturas simples) e <b>saber como aplicá-las na solução de problemas</b> e ainda digo mais: <b>quanto MAIS comum for o problema que for possível ser resolvido com uma estrutura dessas, melhor</b>. Se eu sei resolver um problema simples com automatos, é MUITO mais fácil eu aprender aonde aplicar em problemas complexos. Ao mesmo tempo, precisamos acabar com as &#8220;Javaschools&#8221;. Precisamos, nessas universidades, parar de pensar em resolver todo e qualquer problema com apenas Java ou C++. Automatos, Árvores B, não são fáceis de implementar. Pseudocódigo não significa NADA, porque não roda. Podemos escrever o código em Ruby, ou Python, ou outra linguagem SIMPLES, porque o intuito do trabalho é ensinar a ESTRUTURA DE DADOS e APLICÁ-LA na resolução de um problema (se possível, mostrando quão melhor é o desempenho dessas estruturas ao invés de usar os algoritmos comuns), e não ficar brigando pra fazer a implementação de algo que o aluno já sabe, conceitualmente, porque a linguagem escolhida não é declarativa o suficiente.</p>
<p>Mas, como isso infelizmente é ilusório demais, prefiro continuar brigando e batendo cabeça ao afirmar que uma graduação, da forma como é feita hoje, não é necessária para um bom profissional. Se existissem livros mostrando aplicações de estruturas de dados, eu até afirmaria que ler esses diversos livros é importante. Porém, da forma como se ensina hoje ciência da computação, não vejo nem a presença nem a ausência da graduação como qualquer fator se o profissional é bom ou não.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/313/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=313&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/11/05/ensaio-sobre-graduacao/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>Sou um Anti-Identação</title>
		<link>http://mauricioszabo.wordpress.com/2011/10/19/sou-um-anti-identacao/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/10/19/sou-um-anti-identacao/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 05:12:05 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Linguagens de Programação]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[código-fonte]]></category>
		<category><![CDATA[orientação a objeto]]></category>
		<category><![CDATA[procedural]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=310</guid>
		<description><![CDATA[O título desse post parece estranho, mas vamos lá. De fato, eu sou um anti-identação, não gosto de ver meu código identado. Não estou dizendo que eu não idento meu código-longe disso. Apenas que eu prefiro evitar a identação sempre &#8230; <a href="http://mauricioszabo.wordpress.com/2011/10/19/sou-um-anti-identacao/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=310&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>O título desse post parece estranho, mas vamos lá. De fato, eu sou um anti-identação, não gosto de ver meu código identado.</p>
<p>Não estou dizendo que eu não idento meu código-longe disso. Apenas que eu prefiro evitar a identação sempre que for possível. Mas vamos por partes&#8230;</p>
<p>Primeira coisa, isso começou há algum tempo quando uma pessoa propôs o seguinte problema: montar uma lista encadeada (Linked List) com as seguintes regras:</p>
<p>1) A lista deve validar se ela está vazia, e lançar um erro caso tente-se retirar um item da lista vazia<br />
2) Cada método pode ter, no máximo, uma linha<br />
3) Não se pode usar &#8220;if&#8221; em momento algum</p>
<p>Claro que é uma bela loucura, mas depois que eu consegui resolver esse código, pensei: se eu consegui resolver um problema desses com apenas uma linha por método, será que meus códigos não tem coisa demais?</p>
<p>Aí, comecei a experimentar isso em código de produção. Isso meio que criou um estilo de codificar bem interessante, e vou tentar mostrar aqui com alguns exemplos:<br />
<span id="more-310"></span><br />
Digamos, por exemplo, que temos um código que valida determinados atributos. Depois, um método que, se os atributos forem válidos, salva. Caso contrário, exibe algo na tela. Somos tentados a escrever um código assim:</p>
<p><pre class="brush: ruby;">
def save
  if valid?
    save_product_without_validations
    return true
  else
    puts &quot;Invalid record!&quot;
    return false
  end
end
</pre></p>
<p>Não é difícil de ver que esse método faz coisas demais&#8230; ele tem a lógica do que deve ser feito se o produto for <b>válido</b> e se ele for <b>inválido</b>. Pensando numa descrição breve do que esse método faz, &#8220;save deve salvar o produto se ele for válido&#8221; já mostra que tem algum código a mais&#8230; e se retirarmos a identação?</p>
<p><pre class="brush: ruby;">
def save
  return invalid_product unless valid?
  save_product_without_validations
  return true
end

def invalid_product
  puts &quot;Invalid record!&quot;
  return false
end
private :invalid_product
</pre></p>
<p>E essa é uma das táticas que eu uso. A outra, basicamente, é em relação aos &#8220;case&#8221;. Eu, particularmente, não idento o &#8220;when&#8221; no mesmo nível do &#8220;case&#8221;, e isso é por apenas um motivo: cada &#8220;case&#8221; tem apenas um comando.</p>
<p><pre class="brush: ruby;">
case age
  when 18 then just_completed_18
  when 21 then buy_a_car_already
  else uninteresting_age_found
end
</pre></p>
<p>Isso auxilia, absurdamente, a idéias das boas-práticas de qualquer sistema. Claro que, como sempre, isso não é uma regra-de fato, se existe uma regra sobre <b>código limpo</b> é que não existem regras absolutas sobre o código limpo&#8230; simplesmente porque, seguir regras cegamente não garante um bom &#8220;design&#8221;, caso isso fosse possível já teríamos encontrado uma regra matemática para um bom design e todo o processo de refatoração poderia ser feito automaticamente-já que já existem &#8220;ofuscadores de código&#8221;, porque não um &#8220;refatorador automatizado&#8221;?</p>
<p>Claro que esse tipo de prática não serve para algumas linguagens. Por exemplo, qual o uso do exemplo acima no caso de Java:</p>
<p><pre class="brush: java;">
switch(age) {
  case 18: justCompleted18(); break;
  case 21: buyACarAlready(); break;
  default: uninterestingAgeFound();
}
</pre></p>
<p>Não faz muito sentido quando se precisa forçar o &#8220;break&#8221; no código, na verdade. Mas voltando às identações, isso vale não só para condicionais, como para loops também:</p>
<p><pre class="brush: ruby;">
metadata.each { |m| create_record(m) }
</pre></p>
<p>(que, nesse caso, funciona ainda melhor na versão em Scala)</p>
<p><pre class="brush: scala;">
metadata foreach createRecord
</pre></p>
<p>Finalizando esse curto post: a idéia não é evitar identar o código-simplesmente, a idéia é evitar aqueles códigos que parecem um sinal de maior (&gt;) aonde se tem diversos &#8220;ifs&#8221; encadeados, ou coisas parecidas&#8230; sempre que for abrir um IF, ver se não faz mais sentido criar um novo método e usar o &#8220;if&#8221; com uma linha só. Sempre que for abrir &#8220;case&#8221;, deixar cada condição do case num método separado. E, se isso estiver dando muito trabalho, se em cada um dos novos métodos estiver chamando outro &#8220;if&#8221;, talvez seja hora de pensar numa mudança no design, talvez extraindo uma classe separada (ou uma Factory) para as condições.</p>
<p>E, vale a pena dizer: se um código tem mais de quatro níveis de identação, ele tem um <b>sério</b> problema&#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/310/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=310&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/10/19/sou-um-anti-identacao/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>Orientado a Objetos versus Funcional</title>
		<link>http://mauricioszabo.wordpress.com/2011/10/05/orientado-a-objetos-versus-funcional/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/10/05/orientado-a-objetos-versus-funcional/#comments</comments>
		<pubDate>Wed, 05 Oct 2011 16:42:33 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Linguagens de Programação]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[árvore]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[código-fonte]]></category>
		<category><![CDATA[funcional]]></category>
		<category><![CDATA[linguagens]]></category>
		<category><![CDATA[orientação a objeto]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=301</guid>
		<description><![CDATA[Bom, esses dias estava estudando Scala. Uma linguagem multi-paradigma, mas que parece mais &#8220;funcional&#8221; do que &#8220;imperativa&#8221;. Scala cai numa posição ainda nebulosa para a maior parte das pessoas (e acho até que para o mercado também). Afinal, imutabilidade é &#8230; <a href="http://mauricioszabo.wordpress.com/2011/10/05/orientado-a-objetos-versus-funcional/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=301&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Bom, esses dias estava estudando Scala. Uma linguagem multi-paradigma, mas que parece mais &#8220;funcional&#8221; do que &#8220;imperativa&#8221;. Scala cai numa posição ainda nebulosa para a maior parte das pessoas (e acho até que para o mercado também). Afinal, imutabilidade é &#8220;programação funcional&#8221;? Scala não faz nada que impede &#8220;side-effects&#8221; no código, como Haskell por exemplo, então ela é funcional mesmo?</p>
<p>Como mesmo eu não tenho muitos conhecimentos em linguagens funcionais, resolvi propor um problema para mim mesmo: implementar uma <a href="http://pt.wikipedia.org/wiki/%C3%81rvore_bin%C3%A1ria">árvore binária</a> em Ruby, e depois portá-la para Scala, tentar uma abordagem imutável em Scala, e depois portar para Haskell. O código <a href="https://github.com/mauricioszabo/learning/tree/master/binary_tree">está no github</a>, mas algumas coisas vão ser discutidas aqui.</p>
<p>Primeiramente, a árvore imutável é feita recriando a árvore inteira. Claro, não podemos re-criar apenas um nó e apontar, digamos, a referencia de seu pai para esse novo nó, porque o pai é imutável (assim como qualquer outro aspecto do programa). </p>
<p><pre class="brush: scala;">
class Node[A &lt;% Ordered[A]](value: A = None, left: Option[Node[A]] = None, right: Option[Node[A]] = None) {
    def insertNew(newValue: A): Node[A] = value match {
        case v if(newValue &lt; v) =&gt; insertLeft(newValue)
        case _ =&gt; insertRight(newValue)
    }

    private def insertLeft(newValue: A) = new Node(value, newChild(left, newValue), right)
    private def insertRight(newValue: A) = new Node(value, left, newChild(right, newValue))
    private def newChild(child: Option[Node[A]], newValue: A) = child match {
        case Some(child) =&gt; Some(child insertNew newValue)
        case None =&gt; Some(new Node(newValue))
    }
}
</pre><br />
<span id="more-301"></span><br />
Para esse código, eu usei a idéia de Option, de Scala. Note que o tipo &#8220;A&#8221; é polimórfico, e forçadamente diz que ele precisa implicitamente ser um Ordered (facilitando: &#8220;A&#8221; é um tipo, em Scala, que implemente comparações (menor, igual, maior, etc). Ou seja, um &#8220;Int&#8221; vale, um &#8220;String&#8221; também). A idéia do Option é semelhante ao nulo. O valor pode estar lá, ou não. É muito usado em buscas:</p>
<p><pre class="brush: scala;">
val a = List(1, 2, 3) //Cria uma lista. O método &quot;find&quot;, abaixo, retorna um Option[Int]
//para essa lista, pois essa lista é do tipo List[Int].
val b = a.find(e =&gt; e == 2) //&quot;b&quot; é uma instância do tipo Some[Int]. O tipo &quot;Option&quot; i
</pre></p>
<p>Option, em Scala, tem dois valores possíveis (duas sub-classes): &#8220;Some&#8221;, e &#8220;None&#8221;. Some é quando o valor foi encontrado, None quando não foi encontrado. É possível fazer &#8220;pattern match&#8221; nesses casos, igual ao &#8220;case Some(child)&#8221;. Enfim, a idéia funciona, a árvore é re-criada, mas precisamos ficar pensando em casos que a sub-árvore existe (Some) e em casos aonde ela não existe (None), e é quase como trabalhar com nulos, mas de uma forma mais &#8220;abstraída&#8221;, que no nosso caso se reflete no compilador reclamando se você não tratar um Option.</p>
<p>Agora, a versão em Haskell. Primeiro, definimos um tipo de dados:</p>
<p><pre class="brush: fsharp;">
data Tree a = EmptyTree | Node a (Tree a) (Tree a)
</pre></p>
<p>A árvore (Tree) ou é uma árvore vazia (EmptyTree) ou um nó que contém um valor, uma árvore à direita e uma à esquerda.</p>
<p>Wow.</p>
<p>Sério, o ponto aqui não é a API. É simplesmente o que isso significa. Eu não disse que uma &#8220;árvore vazia&#8221; é um nulo, um None, ou qq coisa que o seja. Eu descrevi o que é, para mim, uma árvore. Além disso, Haskell permite definir seus métodos de acordo com o que eles esperam receber. Ou seja, um método pode ser definido de forma diferente se ele espera &#8220;1&#8243; ou se ele espera outros valores, como no caso do fatorial:</p>
<p><pre class="brush: fsharp;">
fat 0 = 1
fat x = x * (fat x - 1)
</pre></p>
<p>Ok, estamos chegando em algum lugar. E se implementássemos nossa árvore assim também?</p>
<p><pre class="brush: fsharp;">
(&lt;&lt;) EmptyTree value = Node value EmptyTree EmptyTree
(&lt;&lt;) (Node value left right) newValue = if newValue &lt; value 
    then Node value (left &lt;&lt; newValue) right
    else Node value left (right &lt;&lt; newValue)
</pre></p>
<p>Nesse código, (&lt;&lt;) é para definir uma função chamada &quot;&lt;&lt;&quot;. Em Haskell, qualquer função que não seja composto por caracteres alfanuméricos pode ser escrito entre os operadores. Assim, uma função chamada &quot;<strong>($@) parametro1 parametro2</strong>&quot; pode ser escrita ou como &quot;<strong>($@) parametro1 parametro2</strong>&quot; ou como &quot;<strong>parametro1 $@ parametro2</strong>&quot; (note a ausência de parenteses, que Haskell não precisa e nem deixa). Achei que a idéia de fazer um método &quot;<strong>arvore &lt;&lt; valor</strong>&quot; faz mais sentido do que &quot;insertInto arvore valor&quot;. Voltando ao código acima, repare em uma coisa incrível: esse código, SOZINHO, monta uma árvore. Nem mais, nem menos. Podemos fazer isso em Scala?</p>
<p>A verdade, é que podemos.</p>
<p><pre class="brush: scala;">
class Tree[A &lt;% Ordered[A]]() extends Traversable[A] {
    def &lt;&lt; (newValue: A): Tree[A] = this match {
        case EmptyTree() =&gt; Node(newValue, EmptyTree[A], EmptyTree[A])
        case Node(value, left, right) if(newValue &lt; value) =&gt; Node(value, left &lt;&lt; newValue, right)
        case Node(value, left, right) =&gt; Node(value, left, right &lt;&lt; newValue)
    }
}
case class EmptyTree[A &lt;% Ordered[A]]() extends Tree[A]
case class Node[A &lt;% Ordered[A]](a: A, left: Tree[A], right: Tree[A]) extends Tree[A]
</pre></p>
<p>Repare nos &quot;case class&quot;. São o equivalente ao &quot;data&quot; do Haskell, só que BEM menos descritivos, infelizmente. Agora, vamos pensar numa forma de percorrer essa árvore. Em Haskell, podemos criar uma lista e podemos imprimir os valores da árvore:</p>
<p><pre class="brush: fsharp;">
toArray EmptyTree = []
toArray (Node value left right) = toArray left ++ value : toArray right

printTree EmptyTree = return ()
printTree (Node value left right) = do
    printTree left
    print value
    printTree right
</pre></p>
<p>PORÉM, não podemos aproveitar uma função para a outra&#8230; porque, a função &quot;toArray&quot; é &quot;pura&quot;, pois não tem efeitos colaterais e retorna um valor único (a lista). Já o printTree retorna um valor simbólico (chamado de &quot;IO ()&quot;, que indica que ela tem efeitos colaterais (o IO) e que não retorna nada (um conjunto vazio)). Tentei usar um meio de aplicar uma função, e ver se essa função &quot;aplicada&quot; poderia ou imprimir ou retornar uma lista, mas não rola &#8211; uma tem efeitos colaterais e não é &quot;pura&quot;, a outra não tem e é &quot;pura&quot;, e Haskell é bem categórico em dividir o código entre essas duas partes.</p>
<p>Já o código em Scala:</p>
<p><pre class="brush: scala;">
class Tree[A &lt;% Ordered[A]]() extends Traversable[A] {
    def foreach[U](f: (A =&gt; U)) = this match {
        case Node(value, left, right) =&gt; left foreach f; f(value); right foreach f
        case EmptyTree() =&gt;
    }
}
</pre></p>
<p>Como eu extendo o Traversable (o equivalente ao Enumerable do Ruby), eu posso aproveitar isso para o toList e tudo o mais. Porém, como é possível ver, essa função não é &quot;pura&quot;, pois no caso do EmptyTree, ela simplesmente não retorna.</p>
<p>Isso é desejável? Isso é uma aberração dos paradigmas? Claro, isso dá uma flexibilidade que nem Haskell nem Java (ou Ruby) possuem, mas aí vem a pergunta: que paradigma é esse? É um &quot;pseudo-funcional&quot;, &quot;orientado a objetos e funções&quot;? Quais as implicações, as regras que aprendemos continuam valendo?</p>
<p>Eu ainda busco a minha resposta para isso. Mas, como o que eu mais gosto em uma linguagem é a flexibilidade que ela me oferece, não posso negar que, hoje, Scala disputa com Ruby em linguagem mais flexível.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/301/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/301/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/301/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/301/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/301/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/301/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/301/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/301/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/301/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/301/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/301/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/301/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/301/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/301/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=301&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/10/05/orientado-a-objetos-versus-funcional/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>Testando Javascript no Rails</title>
		<link>http://mauricioszabo.wordpress.com/2011/09/21/testando-javascript-no-rails/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/09/21/testando-javascript-no-rails/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 13:55:33 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[envjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[johnson]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[testes]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=294</guid>
		<description><![CDATA[Continuando os estudos com Javascript e Ruby, esses dias tive um problema bem chato: existe uma gem (muito boa, por sinal) para Rails chamada &#8220;cells&#8220;, que basicamente cria uma camada, semelhante a &#8220;mini controllers&#8221; para coisas específicas em Rails (tipo &#8230; <a href="http://mauricioszabo.wordpress.com/2011/09/21/testando-javascript-no-rails/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=294&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Continuando os estudos com Javascript e Ruby, esses dias tive um problema bem chato: existe uma gem (muito boa, por sinal) para Rails chamada &#8220;<a href="http://cells.rubyforge.org/">cells</a>&#8220;, que basicamente cria uma camada, semelhante a &#8220;mini controllers&#8221; para coisas específicas em Rails (tipo &#8220;sidebar&#8221;, &#8220;carrinhos de compra&#8221;, &#8220;menus&#8221; e outras funcionalidades que são, basicamente, fragmentos de &#8220;views&#8221;, normalmente feitas com a combinação &#8220;partials+helpers&#8221; mas que ficam relativamente difíceis de testar). Junto com o <a href="http://cells.rubyforge.org/">Cells</a>, foi criado o <a href="http://apotomo.de/">Apotomo</a>, uma gem para criar &#8220;widgets&#8221;, e aí que está o problema: testar um widget. Claro, é possível testá-lo com integration test, mas &#8220;unit-tests&#8221;, quando envolvem Javascript+Rails, envolvem <a href="https://github.com/jeffwatkins/jasmine-dom">HTML Fixtures</a>, <a href="http://pivotal.github.com/jasmine/">linguagens de teste diferentes</a>, enfim, nada produtivo.</p>
<p>Aí, entrou a gem <a href="https://github.com/jbarnette/johnson">Johnson</a>. Basicamente, é um interpretador Javascript dentro de Ruby, de forma que seja possível rodar código JS dentro do Ruby (e o resultado vem como uma Ruby String, ou um Numeric, enfim). Já falei sobre isso quando estudei &#8220;<a href="http://mauricioszabo.wordpress.com/2010/05/17/conectando-javascript-e-ruby/" title="Conectando Javascript e Ruby">The Ruby Racer</a>&#8221; e os testes com V8 no Ruby, até me interessei pelo &#8220;env.js&#8221;, porém na época a versão que rodava com Johson estava muito ruim ainda (e infelizmente, ainda está)</p>
<p>Porém, o novo <a href="https://github.com/envjs/env-js/tree/1.3.pre1">Env.JS</a> (1.3) já roda no Johnson. E está muito melhor.<br />
<span id="more-294"></span><br />
Enfim, o env.js, porém, nessa versão virou mais um &#8220;browser&#8221; do que uma &#8220;biblioteca&#8221;, então acabei fazendo umas adaptações para ele rodar como biblioteca do Johnson. Junto com isso, fiz um pequeno hack:</p>
<p><pre class="brush: jscript;">
document.oldGetElementById = document.getElementById;
document.getElementById = function(id) {
    var element = document.oldGetElementById(id);
    if(element) return element;
    element = document.oldGetElementById('someDivThatWillNeverBeOverwrited');
    var newDiv = document.createElement('div');
    newDiv.id = id;
    newDiv.innerHTML = &quot;&quot;;
    element.appendChild(newDiv)
    return newDiv;
}
</pre></p>
<p>A idéia, aqui, é ao invés do &#8220;getElementById&#8221; retornar &#8220;undefined&#8221; se o elemento não for encontrado, criar um novo elemento sempre. Isso é importante porque, criando sempre um novo elemento, é possível testar o comportamento de um javascript, sem necessitar de &#8220;fixtures&#8221;. Esse foi o primeiro passo, basicamente. O segundo, foi implementar uma classe para abstrair todas as alterações na página, rodar o Javascript, identificar eventos e ligar com o Env.JS. Como estou usando Johnson, chamei essa classe de <a href="https://github.com/mauricioszabo/EnvJohnson">EnvJohnson</a>.</p>
<p>Enfim, a idéia principal é: criar um ambiente Javascript, re-escrever o &#8220;getElementById&#8221; do &#8220;document&#8221;, salvar a página como estava antes e rodar um script que veio do Rails nele, salvando a página que veio depois. Isso traz um sumário de tudo o que foi alterado na página, como por exemplo, elemento que foi substituído, elemento que foi alterado, elemento que mudou a cor, mudou as propriedades tipo &#8220;style&#8221;, &#8220;class&#8221;, etc. A API que achei, por hora, é assim:</p>
<p><pre class="brush: ruby;">
js_for response.body, :prototype do |js|
  js.should replace_inner_html_of(:example)
  js.should_not replace_inner_html_of(:example2)
end
</pre></p>
<p>A primeira linha inclui o &#8220;prototype&#8221;, e cria um &#8220;EnvJohnson&#8221; para o que vier de resultado no &#8220;response.body&#8221;. A partir daí, o resultado é computado e pode-se usar os modelos tipo &#8220;replace_inner_html_of&#8221; e outros que ainda vão surgir.</p>
<p>Claro, a biblioteca ainda está bem no começo, mas confio que muitas alterações serão feitas para ser uma abordagem possível para testes unitários bem menos &#8220;dolorosos&#8221; no Rails. Como sempre, <a href="https://github.com/mauricioszabo/EnvJohnson">o código está no github</a>. Ele não funciona muito bem com prototype (problemas no Env.JS) mas JQuery roda bem, pelo menos o que eu testei até agora.</p>
<p>Aguardo pull requests :)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/294/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=294&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/09/21/testando-javascript-no-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>Em Patópolis, Programe como os Patos</title>
		<link>http://mauricioszabo.wordpress.com/2011/08/16/em-patopolis-programe-como-os-patos/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/08/16/em-patopolis-programe-como-os-patos/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 20:46:02 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[código-fonte]]></category>
		<category><![CDATA[duck-typing]]></category>
		<category><![CDATA[orientação a objeto]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=280</guid>
		<description><![CDATA[Este é um post sobre &#8220;Duck Typing&#8221;, e finalmente eu escrevi ele (estava enrrolando para fazê-lo). Acho esse post bem importante porque eu percebi, com a experiência em Ruby, que poucas pessoas sabem lidar com o dinamismo da linguagem (e &#8230; <a href="http://mauricioszabo.wordpress.com/2011/08/16/em-patopolis-programe-como-os-patos/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=280&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Este é um post sobre &#8220;Duck Typing&#8221;, e finalmente eu escrevi ele (estava enrrolando para fazê-lo). Acho esse post bem importante porque eu percebi, com a experiência em Ruby, que poucas pessoas sabem lidar com o dinamismo da linguagem (e aproveitá-la ao máximo).</p>
<p>Então, vamos falar um pouco sobre Duck Typing. O básico, a maioria já sabe:</p>
<p><pre class="brush: ruby;">
def imprimir(objeto)
  print objeto.falar
end
</pre></p>
<p>Ou seja, na declaração do método eu não defino nenhuma regra do que aquele objeto pode receber; apenas chamo os métodos que eu o objeto passado como parâmetro deveria implementar, e confio que vai dar certo. Parece simples, e até um pouco inseguro, então tem gente que prefere fazer umas checagens antes (tipo usando objeto.is_a?(Pessoa) ou objeto.respond_to?(:falar)), mas eu acho que isso quebra a idéia de Duck Typing. Para mim, tudo se resume a uma palavra: Protocolo.</p>
<p><span id="more-280"></span></p>
<p>Quem já leu algo sobre protocolos na internet deve ter visto coisas sobre, digamos, o HTTP, SMTP, etc. Qual a idéia? Um protocolo, basicamente, define um conjunto de regras que devem ser seguidas caso você queira se comunicar com aquele serviço/servidor/whatever e ser entendido. Simples, fácil. Como um exemplo bem tosco, vamos tentar acessar o Google usando os seguintes comandos:</p>
<blockquote><p>
  telnet google.com<br />
  **montes de informação**<br />
  GET /
</p></blockquote>
<p>Bom, você verá que, milagrosamente, o google responde para nós uma página. Agora, no lugar do &#8220;GET /&#8221;, tente escrever algo arbitrário, tipo &#8220;Hello, world&#8221;, e o que você ganha é uma mensagem de erro (que pode, ou não, ser um HTML válido).</p>
<p>O que isso significa? Significa, na verdade, que o Google espera um protocolo: para exibir páginas, você usa esse comando &#8220;GET&#8221;, com mais uns parâmetros, e recebe uma página. Se você usar um comando que não existe, recebe um erro. Para quem entende HTTP, isso é óbvio. </p>
<p>Em Ruby, assim como outras linguagens dinâmicas, a linguagem se comporta de forma parecida. Você documenta, informalmente (quando eu falo &#8220;informalmente&#8221;, eu quero dizer que o código não força aquela forma de programar. Assim como no HTTP, você pode mandar comandos que não existem, eles só não serão entendidos e podem gerar erro), como cada classe, cada método, cada parte do programa funciona, e espera que o programador tenha bom-senso suficiente para fazer as chamadas do jeito correto.</p>
<p>Essa é uma mudança muito mais drástica do que se espera. Por exemplo, no Rails, digamos que queremos um comportamento assim: sem usar um banco de dados, queremos fazer uma validação. Digamos, um &#8220;CAPTCHA&#8221;. Você digita aquelas letrinhas que aparecem na imagem, e se estiver errado, o campo fica vermelho, igual o Rails faz. A documentação do Rails peca aqui, mas para termos o mesmo comportamento, precisamos que o objeto (digamos, uma instancia de CaptchaValidator, talvez?) implemente os seguintes métodos: <strong>errors</strong> (que deve retornar um objeto semelhante a um hash), <strong>error_on(field)</strong> (que retorna o erro naquele campo), e <strong>errors.full_messages</strong> (que retorna as mensagens de erro em texto puro, num formato semelhante a um Array). Se você implementar esses três métodos, mais um atributo (<strong>attr_accessor</strong>) para receber a informação do captcha, definido mais um ou dois métodos (no rails 3, mais um, na classe: &#8220;model_name&#8221;, que tem que retornar um ActiveModel::Name) você pode fazer uma view assim:</p>
<p><pre class="brush: xml;">
&lt;% form_for @captcha do |f| %&gt;
  &lt;%= f.error_messages %&gt;
  &lt;p&gt;&lt;%= f.label :capcha_text %&gt;&lt;%= f.text_field :captcha_text %&gt;&lt;/p&gt;
  &lt;p&gt;&lt;%= f.submit 'Login' %&gt;&lt;/p&gt;
&lt;% end %&gt;
</pre></p>
<p>Sem conhecer o código, vendo &#8220;de fora&#8221;, o @label é um registro num banco de dados, é um objeto, o que ele é? Sinceramente, não importa. O que importa é que o @label atenda um <b>protocolo</b>, e é por isso que recomenda-se que o protocolo seja o mais simples o possível (Rails peca um pouco aqui também. Ao invés de ter que implementar o método <b>error_on(field)</b>, o ideal seria que ele pegasse direto do errors, como &#8220;errors[field]&#8220;). </p>
<p>Aliás, isso é a regra de mix-in também: a idéia do mix-in (originalmente, pelo que parece) é de dar poder a um objeto usando um <b>protocolo</b>; por isso os modules padrão do Ruby, pelo menos a maioria, tem nomes que terminam com -able (-ável, em português) como Comparable ou Enumerable (Comparável e Enumerável). No caso do Comparable, você está dando poder a uma classe de ser comparada com outra-o protocolo diz para implementar um método (<strong>&lt;=&gt;(other)</strong>) que, quando for rodado, compara esse objeto com outro e retorna -1 se este objeto for maior, 0 se forem iguais, ou +1 se o outro for maior. Quando você mixar o Comparable, métodos como ==, &lt; , &lt;=, virão de brinde. O Enumerable, idem, você só precisa implementar o método &quot;each&quot;. Claro, muita gente usa modules como se fossem &quot;herança múltipla&quot;, e em alguns casos são implementações muito boas (ActiveModel::Validations sendo um ótimo exemplo), mas idealmente isso é herança múltipla, não mix-in, e isso tem que ficar claro.</p>
<p>Então, duck-typing de novo: a idéia de se programar nesse paradigma basicamente é assim: se você quer um objeto que se comporte como se fosse uma herança de determinada classe, tudo o que se precisa fazer é descobrir quais métodos precisam ser implementados (isso pode ser de varias formas, até mesmo criando uma classe vazia e ir acompanhando erro a erro de &quot;undeclared method&quot;) e, então, implementá-los. Parece simples (e de fato é), porém é aonde muita gente peca, criando classes que definem um método aonde ele só lança uma exception (para que declará-lo, afinal?), esperando que ele seja herdado, ou usando mix-in como herança múltipla (tipo o que o DataMapper faz, e não, na minha opinião não é algo desejável), ou ainda herdando classes e usando &quot;remove_method&quot; para remover métodos que não seriam usados. Ruby é uma linguagem no qual a idéia de duck-typing é muito presente, o tempo todo. Abuse de composição, a linguagem facilita para você. </p>
<p>Claro, ainda há muito mais o que falar sobre Ruby e duck-typing, mas isso fica para outros posts.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/280/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/280/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/280/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=280&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/08/16/em-patopolis-programe-como-os-patos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>Regras de Negócio e Rails</title>
		<link>http://mauricioszabo.wordpress.com/2011/08/03/regras-de-negocio-e-rails/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/08/03/regras-de-negocio-e-rails/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 01:20:16 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[orientação a objeto]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=269</guid>
		<description><![CDATA[Bom, esse post é resultado de uma conversa que tivemos no Grupo de Usuários de Ruby de SP. Mas, antes de entrar no que interessa, vamos divagar um pouco sobre &#8220;Model&#8221; e &#8220;Rails&#8221;. Muitos programadores Rails sabem a regra &#8220;Controllers &#8230; <a href="http://mauricioszabo.wordpress.com/2011/08/03/regras-de-negocio-e-rails/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=269&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Bom, esse post é resultado de uma conversa que tivemos no Grupo de Usuários de Ruby de SP. Mas, antes de entrar no que interessa, vamos divagar um pouco sobre &#8220;Model&#8221; e &#8220;Rails&#8221;.</p>
<p>Muitos programadores Rails sabem a regra &#8220;Controllers magros, Models gordos&#8221;. É interessante também saber um pouco sobre o porque dessa regra, mas antes disso, vamos discorrer sobre o que é o &#8220;Model&#8221; de Rails, comparando com o &#8220;Model&#8221; da maior parte dos frameworks Java (lembrando que eu não sou programador Java, se eu falar qualquer besteira, me corrijam).</p>
<p>Pegando por exemplo o Hibernate, normalmente há uma classe que mapeia um objeto para uma tabela, e outra classe que faz as buscas (chamada normalmente de Facade). Então, teríamos um diagrama como: JDBC -&gt; Model -&gt; Facade. Já no caso do Rails, o mapeador ActiveRecord já abstrai a parte de &#8220;ter que mapear um objeto para uma tabela&#8221;, e também já nos oferece formas de buscar esses registros. Resultado, que o &#8220;Model&#8221; do Rails é meio que uma junção de &#8220;Model&#8221; e &#8220;Facade&#8221; do Java, e isso sozinho. Parece então óbvio que regras de negócio vão para ele, não é? Senão, qual o uso de uma classe vazia?</p>
<p>Bom, minha abordagem não é bem essa. E para isso, eu uso o princípio das CRC Cards, da metodologia XP.<br />
<span id="more-269"></span><br />
CRC &#8211; Class, Responsability, Collaboration,  é uma forma bem simples de identificar entidades e classes num projeto. Como exemplo, uma classe &#8220;Pessoa&#8221;:</p>
<blockquote><p>
Classe: Pessoa<br />
Responsabilidade: Representar uma pessoa válida no banco de dados<br />
Colaboração: <i>vamos deixar de fora por enquanto</i>
</p></blockquote>
<p>Digamos agora que eu preciso saber o salário líquido daquela pessoa. É prática comum, infelizmente, a partir do campo (atributo) &#8220;salario&#8221;, fazer todos os cálculos de imposto, descontos, e então dar o resultado. Mas isso está certo? Olhando para a &#8220;responsabilidade&#8221; da classe Pessoa, ela deveria &#8220;Representar uma pessoa válida no banco de dados&#8221;. A responsabilidade da classe são, então, validações, e assegurar que os dados que ela vai retornar são representações de parte daquela pessoa (como exemplo, um método &#8220;nome_completo&#8221;, que concatena o &#8220;nome&#8221; e &#8220;sobrenome&#8221;).</p>
<p>Minha abordagem é a seguinte: No Rails 2, no arquivo environment.rb, tem uma linha:<br />
<pre class="brush: ruby;">
  # config.load_paths += %W( #{RAILS_ROOT}/extras )
</pre></p>
<p>Eu descomento essa linha e adiciono uma lista de diretórios para minhas regras de negócio:</p>
<p><pre class="brush: ruby;">
  config.load_paths += [&quot;#{RAILS_ROOT}/app/calculos&quot;]
</pre></p>
<p>No rails 3, é necessário adicionar (no caso do meu aplicativo chamar-se Exemplo):</p>
<p><pre class="brush: ruby;">
Exemplo::Application.configure do
  config.autoload_paths += [&quot;#{RAILS_ROOT}/app/calculos&quot;]
end
</pre></p>
<p>Agora, no diretório &#8220;app/calculos&#8221;, eu crio um arquivo como &#8220;salarios.rb&#8221;:</p>
<p><pre class="brush: ruby;">
class Salarios
  def initialize(pessoa)
  end
  
  def salario_liquido
  end

  def impostos
  end
end
</pre></p>
<p>Enfim, com todas as regras que eu precisaria. Agora, para um exemplo mais real: uma vez, tive que montar um sistema que as regras de validação de um cadastro eram variáveis. Para não expor código que pode estar protegido, vamos inventar aqui uma regra arbitrária: administradores podem alterar todos os dados de uma pessoa. Porém, se o usuário NÃO FOR um administrador, aí ele não pode diminuir o salário de uma pessoa, somente aumentar. O que impacta aqui é o &#8220;update&#8221; do controller. Primeiramente, vamos fazer uma pequena alteração no controller:</p>
<p><pre class="brush: ruby;">
PeopleController &lt; ApplicationController
  def update
    @person_updater = PersonUpdaterRule.return_rule_for current_user, params[:person_id]
    @person = @person_updater.person
    if @person_updater.update_attributes(params[:person])
      redirect_to @person
    else
      render :action =&gt; 'edit'
    end
  end
end
</pre></p>
<p>Retirei algumas coisas para ficar mais breve. A idéia aqui é que, ao invés de listar os erros do @person, listamos os erros do @person_updater. No rails 2, é possível fazer isso com o helper &#8220;error_messages_for :person_updater&#8221;. No rails 3, é necessário fazer isso manualmente, infelizmente. Outra possibilidade é o @person ser o próprio PersonUpdater, e delegar todos os métodos desconhecidos (name, age, salary, em resumo, qualquer método que pertença ao model) para o lugar correto, nesse caso o model <strong>Person</strong>.</p>
<p>Agora, a implementação. Uma possível implementação dos Updaters é:</p>
<p><pre class="brush: ruby;">
#arquivo app/rules/person_updater_rule.rb
module PersonUpdaterRule
  def self.return_rule_for(current_user, person_id)
    #Para os que gostam de design pattern, isso é uma Factory :)
    if current_user.admin?
      PersonUpdaterRule::Admin.new person_id
    else
      PersonUpdaterRule::NonAdmin.new person_id
    end
  end
end

#arquivo app/rules/person_updater_rule/admin_rule.rb
module PersonUpdaterRule
  class AdminRule
    include Validatable #se for rails 2. Instalar a gem durran-validatable
    include ActiveModel::Validations #se for rails 3
    validate :valid_person
    attr_reader :person

    def initialize(person_id)
      @person = Person.find person_id
    end

    #Validações padrão da pessoa relacionada a esse modelo
    def valid_person
      @person.valid?
      @person.errors.each { |k, v| errors.add(k, v) }
    end
    private :valid_person

    def update_attributes(params = {})
      return false unless valid?
      @person.update_attributes(params)
    end
  end
end

#arquivo app/rules/person_updater_rule/non_admin_rule.rb
module PersonUpdaterRule
  class NonAdminRule &lt; AdminRule #Herdando as regras de validação do Admin.
    validate :salary_not_lower

    def salary_not_lower
      before, after = @person.changes['salary']
      return if before.nil?
      errors.add(:salary, &quot;can't lower&quot;) if(before.to_i &gt; after.to_i)
    end
    private :salary_not_lower
  end
end
</pre></p>
<p>A vantagem dessa abordagem é separar, claramente, as validações específicas de cada situação. Esse tipo de validação não tem sentido ser implementado no modelo; afinal, uma pessoa vãlida precisa ter um salário, e essa é a única regra que pertence ao <b>registro</b>. Da mesma forma, não faz sentido ter que passar, sempre que for atualizar o registro, qual o usuário logado atualmente no sistema. Finalmente, essa é uma regra de negócio que pode ser alterada com o tempo, e é ideal que ela esteja separada do resto das regras para que possa ser facilmente atacada quando necessário.</p>
<p>Por fim, mais para frente escreverei um post sobre &#8220;Duck Typing&#8221; que talvez explique um pouco mais o código acima. Mas a idéia é, SEMPRE, evitar concentrar lógica demais num lugar só. Fica bem mais desacoplado, faz mais sentido e evita o <a href="http://en.wikipedia.org/wiki/God_object" target="_blank">God Anti-Pattern</a>, ou seja, um &#8220;super-objeto&#8221; que faz tudo.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/269/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/269/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/269/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/269/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/269/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/269/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/269/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/269/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/269/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/269/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/269/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/269/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/269/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/269/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=269&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/08/03/regras-de-negocio-e-rails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
		<item>
		<title>AgileBrazil 2011 &#8211; parte 3</title>
		<link>http://mauricioszabo.wordpress.com/2011/07/18/agilebrazil-2011-parte-3/</link>
		<comments>http://mauricioszabo.wordpress.com/2011/07/18/agilebrazil-2011-parte-3/#comments</comments>
		<pubDate>Mon, 18 Jul 2011 14:18:39 +0000</pubDate>
		<dc:creator>Maurício Szabo</dc:creator>
				<category><![CDATA[Divagações]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[sociedade]]></category>

		<guid isPermaLink="false">http://mauricioszabo.wordpress.com/?p=265</guid>
		<description><![CDATA[Por fim, essa parte é sobre Fortaleza. É um post nada técnico, mas acho que vale a pena comentar. Fortaleza, logo nos primeiros dias, mostrou a minha insanidade. Sinceramente. Escancarou a insanidade que é viver em São Paulo, nessa selva &#8230; <a href="http://mauricioszabo.wordpress.com/2011/07/18/agilebrazil-2011-parte-3/">Continue lendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=265&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Por fim, essa parte é sobre Fortaleza. É um post nada técnico, mas acho que vale a pena comentar.</p>
<p>Fortaleza, logo nos primeiros dias, mostrou a minha insanidade. Sinceramente. Escancarou a insanidade que é viver em São Paulo, nessa selva de pedra, completamente desumana. Para começar, logo no primeiro dia, o taxista conversando conosco (às 0h), e, do nada, vê que passou o hotel e resolve dar ré&#8230; numa avenida. E tudo bem, um outro carro passou por ele como se nada tivesse acontecido.</p>
<p>A população tem um olhar mais vivo por lá. Os passos são sadios, calmos, não apressados e ansiosos como em São Paulo. Aliás, as pessoas olham para você. Parece bobo, e de fato é, mas tente andar na Paulista e impressione-se em ver como as pessoas não fazem contato visual. Nem na Berrini, ou qualquer um desses &#8220;centros comerciais&#8221; de São Paulo.</p>
<p>Mercado, e as pessoas comentando: &#8220;o quê, você vai embora às sete?&#8221;. Detalhe, o mercado fecha oficialmente às sete mas, seis e meia, o pessoal já está arrumando as coisas, afinal o mercado fecha às sete, não às oito ou &#8220;até o último cliente&#8221;.<br />
<span id="more-265"></span><br />
Fui parado duas vezes na rua por pessoas, uma com uma nota de vinte na mão, outra de cinquenta. O motivo? Saber se eu conseguia trocar a nota pra ela. À noite, a avenida beira-mar é lotada de gente, correndo, praticando esportes, andando de patins ou qualquer coisa parecida. Nenhum contrato, nenhuma formalidade, só chegar lá e praticar com o pessoal. Simples assim. Simples como um dono de uma barraquinha que, ao ver que as crianças estavam jogando bola sozinhas, foi lá jogar com elas. Algum tempo depois, as crianças cansaram, foram até o pai, que as pegou na mão e foram embora. Nenhuma palavra trocada entre o pai ou o dono da barraca, nenhum olhar hostil, como se aquele comportamento fosse tão normal por lá que é o que se espera de qualquer pessoa.</p>
<p>Isso faz pensar um pouco. O ritmo que vivemos em São Paulo, é sustentável? É agradável? Isso é engraçado pensar, porque todos os acessos à informação que eu tenho são de contatos em São Paulo-toda a idéia de empreendedorismo que eu tenho é de São Paulo, a idéia de &#8220;dedicar-se dias e noites ao trabalho para fazer algo grandioso e ficar rico ou próximo de rico&#8221; ou algo assim. Essa &#8220;realidade&#8221; é real em Fortaleza, ou em lugares mais calmos? Existe mesmo uma &#8220;regra&#8221; como essa, ou será que estamos apenas repetindo idéias divulgadas por países como os EUA, sem ver a &#8220;big picture&#8221;?</p>
<p>Enfim, Fortaleza. Talvez, a primeira cidade que eu visitei, e pensei: &#8220;aqui, é um lugar bom para morar&#8221;. É comum para nós, de São Paulo, pensarmos no estado como a &#8220;locomotiva do país&#8221;, &#8220;quem carrega o Brasil nas costas&#8221;, e coisas assim. Será que estamos realmente com essa bola toda? Ou será isso apenas uma desculpa, um motivo para vivermos e aceitarmos a vida que vivemos?</p>
<p>Just saying :)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mauricioszabo.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mauricioszabo.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mauricioszabo.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mauricioszabo.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mauricioszabo.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mauricioszabo.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mauricioszabo.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mauricioszabo.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mauricioszabo.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mauricioszabo.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mauricioszabo.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mauricioszabo.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mauricioszabo.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mauricioszabo.wordpress.com/265/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mauricioszabo.wordpress.com&amp;blog=9798529&amp;post=265&amp;subd=mauricioszabo&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mauricioszabo.wordpress.com/2011/07/18/agilebrazil-2011-parte-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f45c92880baef3593e58fb0b241212cc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Maurício Szabo</media:title>
		</media:content>
	</item>
	</channel>
</rss>
