<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/_xslt/rss20_xhtml10_strict.xsl" type="text/xsl" media="screen"?>
<rss version="2.0">
  <channel>
    <title>Eine Zufuhransammlung</title>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://www.xfruits.com/lsdr/planet/" type="text/xml"/>
    <link>http://xfruits.com/lsdr/</link>
    <description/>
    <language>en-us</language>
    <copyright/>
    <generator>xFruits - http://www.xfruits.com</generator>
    <pubDate>Fri, 21 Nov 2008 00:54:46 GMT</pubDate>
    <lastBuildDate>Tue, 30 Nov 1999 00:00:00 GMT</lastBuildDate>
    <category>rss feed planet collection</category>
    <item>
      <title>Homem-Aranha: Um Dia a Mais</title>
      <description><![CDATA[<img src="/images/dsc05269.jpg" alt="Vazio"/>
<br/><i>Vai é criar teia de aranha ali...</i>

<p>
Eu estava doido para escrever sobre isso, mas na época que saiu a revista Homem Aranha 82 seria um baita de um <i>spoiler</i> para quem ainda não havia comprado, e decidi esperar mais, não antes de mandar um email para a <a href="http://www.paninicomics.com.br">Editora Panini expressando a minha opinião sobre o que aconteceu.
</p>

<p>
O negócio é o seguinte ... a tal "saga" <a href="http://www.paninicomics.com.br/CollanaNews.jsp?Action=Carica&Id=2176">"Um Dia a Mais"</a> do Homem Aranha, onde o mentecapto do <a href="http://en.wikipedia.org/wiki/Joe_Quesada">Joe Quesada</a> fez <b>a maior cagada que eu já vi desde comecei a ler HQ</b>. E olha que já vi muita coisa brava como <a href="http://pt.wikipedia.org/wiki/A_Morte_do_Superman">"A Morte do Super-Homem"</a>, <a href="http://pt.wikipedia.org/wiki/Saga_do_Clone">"A Saga do Clone"</a>, <a href="http://pt.wikipedia.org/wiki/Batman#Morte_na_Fam.C3.ADlia">"A Queda do Morcego"</a>, todas esses nhé-nhé-nhés dramáticos que eles aprontam para tentar vender mais revistas. Só que chega uma hora que o saco acaba e coincidentemente os caras extrapolam.
</p>

<p>
Nessa "saga", a múmia do Quesada resolve <b>apagar quase 20 anos de história do Homem-Aranha</b>. É. Apagou. E de um dos jeitos mais bestas que tem para fazer isso: meteu uma entidade poderosa no meio (Mefisto), que, através de um pacto onde o <a href="http://pt.wikipedia.org/wiki/Peter_parker">Peter Parker</a> e a <a href="http://pt.wikipedia.org/wiki/Mary_jane_watson">Mary Jane</a> decidiram entregar o seu amor e tudo que poderia vir de bom nele no futuro para o coisa-ruim, passou uma borracha na história do Amigão da Vizinhança para que a Tia May pudesse viver depois de ter levado um tiro que era para o Peter, que ficou naquelas de "é culpa minha blá blá blá". Ele estava conseguindo ser mais chato e reclamão do que o <a href="http://pt.wikipedia.org/wiki/Surfista_prateado">Surfista Prateado</a> era nas histórias de uns 20 anos atrás. Mas enfim, o Peter voltou a ser solteiro, morando com a tia, andando de bicicleta, e ainda "resetaram" o <a href="http://pt.wikipedia.org/wiki/Harry_Osborn">Harry Osborn</a>, o <a href="http://pt.wikipedia.org/wiki/Flash_thompson">Flash Thompson</a> e sabe lá quem mais. 
</p>

<p>
Pelo que eu li folheando na banca a seção de cartas do número 83, parece que os editores esperavam uma resposta mais negativa. Teve gente que argumentou que foi uma boa para "descomplicar" a história do Aranha e alguns que disseram que gostaram pois eles vão começar a ler agora praticamente do zero. Eu discordo dos primeiros, pois é batata que daqui alguns anos vão complicar tudo de novo. Quem está lendo as revistas importadas está mencionando que voltaram meio num estilo "anos 80" mais divertido, que eu duvido que dure muito. Quem começou a ler agora realmente levou vantagem se não liga para a história do personagem. 
</p>

<p>
Mas e nós, que lemos faz sei lá quantas décadas? Eu me senti o maior idiota do mundo por ter suportado todas aquelas fases medonhas acreditando que ia melhorar (e melhorou por vezes, eu estava gostando da <a href="http://pt.wikipedia.org/wiki/Guerra_Civil_(Marvel_Comics)">Guerra Civil</a>!), mas é tanta porcaria e tiro saindo pela culatra que acho que com o tempo a gente vai ficando de saco <b>muito</b> cheio. Tipo quando a Editora Abril começou a publicar a linha Premium, que custava caro e vinha com um discurso grande sobre qualidade blá blá blá. Aí os tontos (eu) compraram para na esperança de "dar uma força", tentar ajudar o mercado nacional de HQ não afundar, e após alguns meses eles cancelaram tudo e lançaram as revistas no papel mais vagabundo que eu já vi com outro discurso totalmente diferente, sobre ser acessível etc e tal. 
</p>

<p>
E essa "Um Dia a Mais" realmente para mim foi a maior forcação de barra que já vi e talvez a gota d'água para transbordar tudo. A imagem acima é da divisória da minha estante, especialmente feita para abrigar minhas HQs, onde até hoje estavam as revistas do Homem-Aranha publicadas pela Panini. Elas foram para o setor de "arquivo", juntamente com os Aranhas Premium e os formatinhos da Abril. <b>Eu parei de ler Homem-Aranha depois de várias décadas. Chega.</b> E se começarem com muito mais graça desse tipo, eu paro com outros também. X-Men estava uma chatice e aproveitei e parei junto. Ontem li que ano que vem estão querendo tirar o Bruce Wayne do manto do Batman. Ainda nutro alguma esperança que venha a ser alguma coisa decente por ter Neil Gaiman e Grant Morrison envolvidos, mas se começar com lenga-lenga de novo, eu paro também.
</p>

<p>
Não sei se estou mais velho e chato, sem paciência, ou se esse pessoal realmente não aprende e fica insistindo nos mesmos erros de sempre, e o pior, piorando ainda mais. Podem estar apostando numa nova geração que nem compra a revista direito e só faz download pela web e afugentando quem era leitor fiel. Se eu penso que o mercado de HQ pode se abalar por causa de todas essas barbeiragens? Que se dane. O mercado de HQ pode se sustentar enquanto produzir coisas boas e tratarem os seus clientes, ou seja, nós, leitores, de forma justa. Se pararem com isso, não tem sentido de existir mais. Ainda bem que existem algumas revistas como a <a href="http://pixelquadrinhos.com.br/?cat=12">Pixel Magazine</a>.
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290962472" />
]]></description>
      <pubDate>Thu, 20 Nov 2008 22:11:35 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290962472&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F549</link>
      <guid>http://eustaquiorangel.com/posts/549</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Half Full</title>
      <description><![CDATA[Roy Fielding: When did you stop beating your wife, Ian?
If HTML5 were redefined to be the set of things over which we can come to rough consensus over the next 18 months or so, it would in all likelihood be (a) delivered on time, (b) be significantly smaller than the current working draft, and (c) as consistent as we collectively know how to make it with the full 2022 vision.
Repeat that process ever three or so years, and I’m confident that we will eventually converge on full consensus.  Possibly even by 2022.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922632" />
]]></description>
      <pubDate>Thu, 20 Nov 2008 19:45:34 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922632&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Roy Fielding: When did you stop beating your wife, Ian?
The apparent catalyst for this exchange was a document put out by Mike Smith.
Clearly there are areas of disagreement.  Not just between Roy and Ian, but between many of the participants in the working group.  Many are focusing on such details as to what should be normative, and how such specifications should be arranged.  My opinion is that this discussion is premature and can’t be settled without first establishing a common understanding of the context and goals of the effort.
Meanwhile, it is important to note the Mike’s document does not attempt to be inconsistent with the ongoing HTML5 work, it merely attempts to capture a subset of this information, and present it from a different perspective.

The bigger problem is that HTML5 will be finished in 2022.  Or in 2010.
The first thing that needs to be recognized is that the WHATWG’s goals (are these documented?) won’t be met in 2010.  The second thing is that neither will the W3C’s.
There are many ways to address this.  One that I would not be in favor of is adjusting the W3C’s date significantly.
IMHO, what’s needed is a chair that will take consensus whenever he (or she) can find it, and graciously accept defeat when that’s not possible.  Again, not all of the goals are achievable by 2010.  Whether they ever could have been or not is irrelevant, at this point it clearly is not the case.
And it is worth repeating that the intent is that Mike’s document and Ian’s document aren’t in conflict.  One way to resolve any apparent conflicts is to relabel the document which is intended to be later.  Picking some dates out of the air, how about HTML5=2010; HTML6=2013; HTML7=2016; HTML8=2019; and HTML9=2022?  Meanwhile...

Question: Do we need to resolve whether ping is in HTML9?
Answer: Not today.
Question: Do we need to resolve whether the DOM bindings are in HTML9 or are in a separate document?
Answer: Not today.

I could go on, but the basic point is that if HTML5 were redefined to be the set of things over which we can come to rough consensus over the next 18 months or so, it would in all likelihood be (a) delivered on time, (b) be significantly smaller than the current working draft, and (c) as consistent as we collectively know how to make it with the full “2022” vision.
Repeat that process ever three or so years, and I’m confident that we will eventually converge on full consensus.  Possibly even by 2022.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2925</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Yogurt Oreo</title>
      <description/>
      <pubDate>Tue, 18 Nov 2008 17:40:08 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290004593&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Yogurt Oreo
Do we now see the dawn of SSEO: Speach Search Engine Optimization?<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290004593" />
]]></content:encoded>
      <guid>http://bitworking.org/news/387/yogurt-oreo</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Flay, eliminando repetições em código Ruby</title>
      <description><![CDATA[Flay é uma ferramenta útil para cercear repetições de código em programas Ruby. Analisando o código semanticamente, o Flay é capaz de pegar repetições em casos que geralmente passam despercebidos no melhor dos códigos.

Em algumas casos, a repetição será inevitável e mesmo necessária para deixar o código mais legível. Geralmente, entretanto, repetição significa código que [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150522" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/11/13/flay-eliminando-repeticoes-em-codigo-ruby/#comments</comments>
      <pubDate>Thu, 13 Nov 2008 21:12:35 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150522&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F11%2F13%2Fflay-eliminando-repeticoes-em-codigo-ruby%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a href="http://ruby.sadi.st/Flay.html">Flay</a> é uma ferramenta útil para cercear repetições de código em programas Ruby. Analisando o código semanticamente, o Flay é capaz de pegar repetições em casos que geralmente passam despercebidos no melhor dos códigos.</p>

<p>Em algumas casos, a repetição será inevitável e mesmo necessária para deixar o código mais legível. Geralmente, entretanto, repetição significa código que ainda não está DRY o suficiente.</p>

<h3>Instalação</h3>

<p>Para instalar o Flay, basta rodar o comando <kbd>gem</kbd>:</p>

<pre><code>~$ sudo gem install flay
</code></pre>

<p>Esse comando instala a <span class="foreign-word" lang="en">gem</span> em si e um executável que pode ser usado na linha de comando.</p>

<h3>Um exemplo</h3>

<p>Para demonstrar o uso da ferramenta, vamos rodar o Flay contra <a href="http://github.com/rails/rails/tree/master">o código mais recente do Active Record</a>:</p>

<p>O resultado (um trecho apenas), depois de alguns minutos de trabalho com a CPU a 100%, é o seguinte:</p>

<pre><code>Matches found in :defn (mass = 290)
  ./test/cases/associations/join_model_test.rb:237
  ./test/cases/associations/join_model_test.rb:262
  ./test/cases/associations/join_model_test.rb:271
  ./test/cases/associations/join_model_test.rb:623
  ./test/cases/associations/join_model_test.rb:650

Matches found in :defn (mass = 270)
  ./test/cases/validations_test.rb:929
  ./test/cases/validations_test.rb:937
  ./test/cases/validations_test.rb:945
  ./test/cases/validations_test.rb:953
  ./test/cases/validations_test.rb:961
  ./test/cases/validations_test.rb:969

Matches found in :defn (mass = 236)
  ./test/cases/validations_i18n_test.rb:491
  ./test/cases/validations_i18n_test.rb:510
  ./test/cases/validations_i18n_test.rb:529
  ./test/cases/validations_i18n_test.rb:549

Matches found in :scope (mass = 204)
  ./test/migrations/duplicate/3_innocent_jointable.rb:12
  ./test/migrations/interleaved/pass_1/3_innocent_jointable.rb:12
  ./test/migrations/interleaved/pass_2/3_innocent_jointable.rb:12
  ./test/migrations/interleaved/pass_3/3_innocent_jointable.rb:12
  ./test/migrations/missing/4_innocent_jointable.rb:12
  ./test/migrations/valid/3_innocent_jointable.rb:12

Matches found in :call (mass = 172)
  ./test/models/author.rb:64
  ./test/models/project.rb:17

Matches found in :defn (mass = 171)
  ./test/cases/validations_test.rb:977
  ./test/cases/validations_test.rb:991
  ./test/cases/validations_test.rb:1079</code></pre>

<p>Note especialmente código que está sendo repetido em arquivos diferentes. No caso acima, como o código está em arquivos de teste, é provável que a repetição seja desejável para não poluir o escopo dos mesmos.</p>

<p>Vamos tomar um outra caso na biblioteca em si:</p>

<pre><code>Matches found in :if (mass = 165)
  ./lib/active_record/associations/has_and_belongs_to_many_association.rb:82
  ./lib/active_record/associations/has_many_association.rb:100
  ./lib/active_record/associations/has_many_through_association.rb:194</code></pre>

<p>O código repetido em questão é o seguinte:</p>

<pre><code>if @reflection.options[:counter_sql]
  @counter_sql = interpolate_sql(@reflection.options[:counter_sql])
elsif @reflection.options[:finder_sql]
  # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */
  @reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT (\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
  @counter_sql = interpolate_sql(@reflection.options[:counter_sql])
else
  @counter_sql = @finder_sql
end</code></pre>

<p>Vendo os arquivos, é possível observar que o código é o mesmo. Considerando que os três arquivos representam classes com um pai em comum seria possível reduzir a repetição movendo o código para um método a classe pai.</p>

<p>Esse tipo de repetição tende a sumir com refatoramentos e o código acima provavelmente sumirá por um processo similar (alguém se habilita para um <span class="foreign-word" lang="en">patch</span>?).</p>

<h3>Conclusão</h3>

<p>Como é possível perceber, o Flay representa mais uma forma de observar o seu código em busca de coisas que podem ser melhoradas. É claro que isso não deve ser converter em uma obsessão de remover toda e qualquer repetição, o que demoraria mais tempo do que codificar coisas novas.</p>

<p>Como de usual, sugestões, críticas e dúvidas são bem-vindos.</p>]]></content:encoded>
      <category>Programação</category>
      <guid>http://logbr.reflectivesurface.com/2008/11/13/flay-eliminando-repeticoes-em-codigo-ruby/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Flog, analisando complexidade em Ruby</title>
      <description><![CDATA[Flog é outro analisador de complexidade para Ruby. Diferentemente do Saikuro, que mede a complexidade ciclomática real do código, o Flog tem o propósito de mostrar padrões de tortuosidade no seu código. É mais uma ferramenta interessante e de fácil uso para analisar a evolução da complexidade do seu código:

Instalação

Para instalar o Flog, basta rodar [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150523" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/11/13/flog-analisando-complexidade-em-ruby/#comments</comments>
      <pubDate>Thu, 13 Nov 2008 18:12:35 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150523&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F11%2F13%2Fflog-analisando-complexidade-em-ruby%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a href="http://ruby.sadi.st/Flog.html">Flog</a> é outro <a href="http://logbr.reflectivesurface.com/2008/11/12/conceitos-de-programacao-complexidade-ciclomatica/">analisador de complexidade</a> para Ruby. Diferentemente do <a href="http://logbr.reflectivesurface.com/2008/11/13/saikuro-complexidade-ciclomatica-para-ruby/">Saikuro</a>, que mede a complexidade ciclomática real do código, o Flog tem o propósito de mostrar padrões de tortuosidade no seu código. É mais uma ferramenta interessante e de fácil uso para analisar a evolução da complexidade do seu código:</p>

<h3>Instalação</h3>

<p>Para instalar o Flog, basta rodar o comando <kbd>gem</kbd>:</p>

<pre><code>~$ sudo gem install flog
</code></pre>

<p>Esse comando instala a <span class="foreign-word" lang="en">gem</span> em si e um executável que pode ser usado na linha de comando.</p>

<h3>Um programa de exemplo</h3>

<p>Para demonstrar o uso da ferramenta, vamos utilizar o mesmo exemplo que mostrarmos no artigo sobre <a href="http://logbr.reflectivesurface.com/2008/11/13/saikuro-complexidade-ciclomatica-para-ruby/">o uso do Saikuro</a>.</p>

<pre><code>require "test/unit"

class DocumentHasher

  def initialize(object, options = {})
    @object = object
    @options = options
  end

  def hash
    hash = { :id => @object.id }
    if @options[:fields]
      @options[:fields].each do |field|
        hash[field] = @object.send(field)
      end
    end
    if @options[:extra_fields]
      @options[:extra_fields].each do |field|
        hash[field] = @object.send(field.to_s + "_field")
      end
    end
    hash
  end

  def self.hash(object, options = {})
    self.new(object, options).hash
  end

end

class DocumentHasherTest < Test::Unit::TestCase

  Struct.new("HashExample", :id, :title, :author)

  TITLE_FIELD = "Test"
  AUTHOR_FIELD = "Author"
  EXTRA_FIELD = "Extra"

  def setup
    @object = Struct::HashExample.new(1, TITLE_FIELD, AUTHOR_FIELD)
    class << @object
      def extra_field
        "Extra"
      end
    end
  end

  def test_hash_id
    result = DocumentHasher.hash(@object)
    assert_equal 1, result[:id]
  end

  def test_hash_fields
    result = DocumentHasher.hash(@object, 
      :fields => [:title, :author])
    assert_equal TITLE_FIELD, result[:title]
    assert_equal AUTHOR_FIELD, result[:author]
  end

  def test_hash_extra_fields
    result = DocumentHasher.hash(@object, 
      :fields => [:title, :author], 
      :extra_fields => [:extra])
    assert_equal EXTRA_FIELD, result[:extra]
  end

end</pre>

<p></code></p>

<p>Salve esse arquivo para um arquivo chamado <var>hasher.rb</var> e rode-o com o comando abaixo para verificar sua execução:</p>

<pre><code>~$ ruby hasher.rb
</code></pre>

<h3>Utilização</h3>

<p>Com esse programa, podemos rodar o Flog. O comando é simples:</p>

<pre><code>~$ flog hasher.rb
</code></pre>

<h3>Resultado inicial</h3>

<p>O resultado da execução acima pode ser visto na listagem abaixo:</p>

<pre><code>Total Flog = 57.7 (7.2 +/- 62.8 flog / method)

DocumentHasher#hash: (27.3)
     9.0: send
     8.6: assignment
     5.8: []
     5.4: branch
     2.8: each
     1.9: to_s
     1.7: +
     1.5: new
     1.3: hash
     1.3: id
DocumentHasherTest#setup: (8.3)
     6.5: sclass
     1.3: assignment
     1.3: new
     0.4: lit_fixnum</code></pre>

<p>Note que o método <code>hash</code> possui um fator de &#8220;tortuosidade&#8221; de 27 e que os maiores culpados são o envio de mensagens (<code>send</code>) e atribuições. A &#8220;tortuosidade&#8221; total do programa está em 57.7, que representa o cômputo de todos os métodos do programa.</p>

<h3>Alterando o programa</h3>

<p>Para fins de exemplo, podemos tentar reduzir a complexidade do método <code>hash</code> como fizemos no artigo anterior usando o exemplo abaixo:</p>

<pre><code>require "test/unit"

class DocumentHasher
  
  def initialize(object, options = {})
    @object = object
    @options = options
  end
  
  def hash  
    hash = { :id => @object.id }
    build_fields(hash, @options[:fields] || {})
    build_extra_fields(hash, @options[:extra_fields] || {})
    hash
  end
  
  def self.hash(object, options = {})
    self.new(object, options).hash
  end
  
  protected
  
  def build_fields(hash, fields)
    fields.each do |field|
      hash[field] = @object.send(field)
    end
  end
  
  def build_extra_fields(hash, fields)
    fields.each do |field|
      hash[field] = @object.send(field.to_s + "_field")
    end
  end    
  
end

class DocumentHasherTest < Test::Unit::TestCase
  
  Struct.new("HashExample", :id, :title, :author)
  
  TITLE_FIELD = "Test"
  AUTHOR_FIELD = "Author"
  EXTRA_FIELD = "Extra"
  
  def setup
    @object = Struct::HashExample.new(1, TITLE_FIELD, AUTHOR_FIELD)
    class << @object
      def extra_field
        "Extra"
      end
    end
  end
  
  def test_hash_id
    result = DocumentHasher.hash(@object)
    assert_equal 1, result[:id]
  end

  def test_hash_fields
    result = DocumentHasher.hash(@object, 
      :fields => [:title, :author])
    assert_equal TITLE_FIELD, result[:title]
    assert_equal AUTHOR_FIELD, result[:author]    
  end

  def test_hash_extra_fields
    result = DocumentHasher.hash(@object, 
      :fields => [:title, :author], 
      :extra_fields => [:extra])
    assert_equal EXTRA_FIELD, result[:extra]
  end
  
end</code></pre>

<p>Rodando o comando novamente, teríamos:</p>

<pre><code>Total Flog = 58.1 (5.3 +/- 10.3 flog / method)

DocumentHasher#hash: (10.7)
     3.2: []
     3.0: branch
     2.6: assignment
     1.5: new
     1.3: build_extra_fields
     1.3: hash
     1.3: build_fields
     1.3: id
DocumentHasher#build_extra_fields: (9.4)
     4.2: send
     2.8: assignment
     1.8: to_s
     1.6: +
     1.3: branch
     1.3: each
DocumentHasherTest#setup: (8.3)
     6.5: sclass
     1.3: assignment
     1.3: new
     0.4: lit_fixnum
DocumentHasherTest#test_hash_fields: (7.0)
     3.0: []
     2.6: assert_equal
     1.3: hash
     1.3: assignment</code></pre>

<p>Note que a complexidade dos métodos caiu substancialmente. Os métodos estão mais simples e mais balanceados. A &#8220;tortuosidade&#8221; geral subiu um pouco com a adição de algumas chamadas, mas, analisando os métodos individualmente é possível observar que a somatória de complexidade dos três métodos envolvidos é menor do que a complexidade original. Mais uma vez, o código está mais legível e mais testável.</p>

<h3>Conclusão</h3>

<p>O Flog representa uma métrica arbitrária de complexidade que, mesmo assim, pode ser usada para acompanhar o desenvolvimento de um base de código. Um exemplo disso pode ser visto no texto do Carlos Villela mostrando <a href="http://www.lixo.org/archives/2008/07/26/a-look-at-rails-complexity/">a evolução do código do Rails</a> ao longo dos anos.</p>

<p>Como de usual, sugestões, críticas e dúvidas são bem-vindos. No próximo artigo, esfolando o seu código Ruby com mais ferramentas de análise de complexidade.</p>]]></content:encoded>
      <category>Programação</category>
      <guid>http://logbr.reflectivesurface.com/2008/11/13/flog-analisando-complexidade-em-ruby/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Utensils</title>
      <description/>
      <pubDate>Thu, 13 Nov 2008 14:05:22 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922633&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Patrick Mueller: We fundamentally have the wrong tools to do the job. We’re using a spoon where we should be using a backhoe. Look down! You’re using a spoon for bleep's sake! Don’t you realize it? Slap yourself around a little and clear the fog from your eyes. Expect better.
I’ve seen applications that have been built using a backhoe.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922633" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2924</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Saikuro, complexidade ciclomática para Ruby</title>
      <description><![CDATA[Saikuro é uma analisador de complexidade ciclomática para Ruby. A instalação e uso do mesmo são bem simples e serão descritos aqui brevemente.

Instalação

Para instalar o Saikuro, basta rodar o comando gem:

~$ sudo gem install Saikuro


Esse comando instala a gem em si e um executável que pode ser usado na linha de comando.

Um programa de exemplo

Para [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150524" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/11/12/saikuro-complexidade-ciclomatica-para-ruby/#comments</comments>
      <pubDate>Thu, 13 Nov 2008 02:49:05 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150524&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F11%2F12%2Fsaikuro-complexidade-ciclomatica-para-ruby%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a href="http://saikuro.rubyforge.org/">Saikuro</a> é uma analisador de complexidade ciclomática para Ruby. A instalação e uso do mesmo são bem simples e serão descritos aqui brevemente.</p>

<h3>Instalação</h3>

<p>Para instalar o Saikuro, basta rodar o comando <kbd>gem</kbd>:</p>

<pre><code>~$ sudo gem install Saikuro
</code></pre>

<p>Esse comando instala a <span class="foreign-word" lang="en">gem</span> em si e um executável que pode ser usado na linha de comando.</p>

<h3>Um programa de exemplo</h3>

<p>Para demonstrar o uso da ferramenta, vamos utilizar um programa de referência. Esse programa será um simples transformador de objetos Ruby em <span class="foreign-word" lang="en">hashes</span> equivalentes e está listado abaixo, com os testes necessários:</p>

<pre><code>require "test/unit"

class DocumentHasher

  def initialize(object, options = {})
    @object = object
    @options = options
  end

  def hash
    hash = { :id => @object.id }
    if @options[:fields]
      @options[:fields].each do |field|
        hash[field] = @object.send(field)
      end
    end
    if @options[:extra_fields]
      @options[:extra_fields].each do |field|
        hash[field] = @object.send(field.to_s + "_field")
      end
    end
    hash
  end

  def self.hash(object, options = {})
    self.new(object, options).hash
  end

end

class DocumentHasherTest < Test::Unit::TestCase

  Struct.new("HashExample", :id, :title, :author)

  TITLE_FIELD = "Test"
  AUTHOR_FIELD = "Author"
  EXTRA_FIELD = "Extra"

  def setup
    @object = Struct::HashExample.new(1, TITLE_FIELD, AUTHOR_FIELD)
    class << @object
      def extra_field
        "Extra"
      end
    end
  end

  def test_hash_id
    result = DocumentHasher.hash(@object)
    assert_equal 1, result[:id]
  end

  def test_hash_fields
    result = DocumentHasher.hash(@object, 
      :fields => [:title, :author])
    assert_equal TITLE_FIELD, result[:title]
    assert_equal AUTHOR_FIELD, result[:author]
  end

  def test_hash_extra_fields
    result = DocumentHasher.hash(@object, 
      :fields => [:title, :author], 
      :extra_fields => [:extra])
    assert_equal EXTRA_FIELD, result[:extra]
  end

end</pre>

<p></code></p>

<p>Salve esse arquivo para um arquivo chamado <var>hasher.rb</var> e rode-o com o comando abaixo para verificar sua execução:</p>

<pre><code>~$ ruby hasher.rb
</code></pre>

<h3>Utilização</h3>

<p>Com esse programa, podemos rodar o Saikuro. O comando é simples:</p>

<pre><code>~$ saikuro -c -t -y 0 -w 11 -e 16 -i hasher.rb -o report
</code></pre>

<p>Esse comando roda o analisador de complexidade com os seguintes parâmetros:</p>

<ul>
<li><kbd>-t</kbd>, para analisar <span class="foreign-word" lang="en">tokens</span> também</li>
<li><kbd>-y 0</kbd>, para exibir a complexidade de todos os métodos</li>
<li><kbd>-w 11</kbd>, para exibir <span class="foreign-word" lang="en">warnings</span> para métodos de complexidade superior a 11</li>
<li><kbd>-e 16</kbd>, para exibir erros para métodos de complexidade superior a 16</li>
<li><kbd>-i hasher.rb</kbd>, o arquivo a ser analisado (pode ser um diretório também)</li>
<li><kbd>-o report</kbd>, o diretório onde gerar o relatório de saída</li>
</ul>

<h3>Resultado inicial</h3>

<p>O resultado da execução acima pode ser visto, parcialmente, na imagem abaixo, que mostra os resultados somente para a classe em que estamos interessados:</p>

<p><img src="http://logbr.reflectivesurface.com/wp-content/uploads/2008/11/saikuro-1.png" alt="Saikuro 1" /></p>

<p>Note que o método <code>hash</code> possui complexidade 5 que reflete os 4 comandos decisórios (2 <code>if</code> e 2 <code>each</code>) mais um ponto de saída pelo <a href="http://logbr.reflectivesurface.com/2008/11/12/conceitos-de-programacao-complexidade-ciclomatica/">cálculo mais simples da complexidade</a>. Os demais métodos, puramente lineares, possuem complexidade 1.</p>

<p>No diretório de resultado há também um arquivo que mostra a quantidade de <span class="foreign-word" lang="en">tokens</span> gerados no programa. Este relatório, com os níveis de aviso baixo, tende a reportar erros mesmo em condições consideradas normais.</p>

<h3>Alterando o programa</h3>

<p>Para fins de exemplo, podemos tentar reduzir a complexidade do método <code>hash</code>. Digamos que façamos a seguinte alteração:</p>

<pre><code>require "test/unit"

class DocumentHasher
  
  def initialize(object, options = {})
    @object = object
    @options = options
  end
  
  def hash  
    hash = { :id => @object.id }
    build_fields(hash, @options[:fields] || {})
    build_extra_fields(hash, @options[:extra_fields] || {})
    hash
  end
  
  def self.hash(object, options = {})
    self.new(object, options).hash
  end
  
  protected
  
  def build_fields(hash, fields)
    fields.each do |field|
      hash[field] = @object.send(field)
    end
  end
  
  def build_extra_fields(hash, fields)
    fields.each do |field|
      hash[field] = @object.send(field.to_s + "_field")
    end
  end    
  
end

class DocumentHasherTest < Test::Unit::TestCase
  
  Struct.new("HashExample", :id, :title, :author)
  
  TITLE_FIELD = "Test"
  AUTHOR_FIELD = "Author"
  EXTRA_FIELD = "Extra"
  
  def setup
    @object = Struct::HashExample.new(1, TITLE_FIELD, AUTHOR_FIELD)
    class << @object
      def extra_field
        "Extra"
      end
    end
  end
  
  def test_hash_id
    result = DocumentHasher.hash(@object)
    assert_equal 1, result[:id]
  end

  def test_hash_fields
    result = DocumentHasher.hash(@object, 
      :fields => [:title, :author])
    assert_equal TITLE_FIELD, result[:title]
    assert_equal AUTHOR_FIELD, result[:author]    
  end

  def test_hash_extra_fields
    result = DocumentHasher.hash(@object, 
      :fields => [:title, :author], 
      :extra_fields => [:extra])
    assert_equal EXTRA_FIELD, result[:extra]
  end
  
end</code></pre>

<p>Rodando o comando novamente, teríamos:</p>

<p><img src="http://logbr.reflectivesurface.com/wp-content/uploads/2008/11/saikuro-2.png" alt="Saikuro 2" /></p>

<p>Como os testes demonstram, o programa funciona da mesma forma. E como o relatório de complexidade também demonstra, a complexidade do programa permanece a mesma no geral e a dos métodos diminuiu. O resultado é um programa mais legível e mais facilmente testável.</p>

<h3>Conclusão</h3>

<p>Embora métricas em si não tenham nenhum poder de tornar o código de um programa melhor, acompanhar a evolução das mesmas é uma ferramenta fundamental para garantir a qualidade do código. Para quem usa o Ruby, o Saikuro é uma ferramenta simples e rápida para isso. Para quem não usa, é fácil achar <a href="http://www.google.com/search?q=cyclomatic+complexity+tools&amp;ie=UTF-8&amp;oe=UTF-8">ferramentas que se adequam a outras linguagens</a>.</p>

<p>Como de usual, sugestões, críticas e dúvidas são bem-vindos. No próximo artigo, ainda hoje, esfolando o seu código Ruby com mais ferramentas de análise de complexidade.</p>]]></content:encoded>
      <category>Programação</category>
      <guid>http://logbr.reflectivesurface.com/2008/11/13/saikuro-complexidade-ciclomatica-para-ruby/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Conceitos de Programação: Complexidade Ciclomática</title>
      <description><![CDATA[Este é o quarto artigo em uma série sobre conceitos de programação. Os demais artigos podem ser encontrados na página de resumo sobre a série. Como nos demais artigos, um aviso: o tratamento dado aos assuntos aqui é informativo e podem existir erros nos mesmos. Como nos demais artigos neste blog, comentários e correções são [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150525" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/11/12/conceitos-de-programacao-complexidade-ciclomatica/#comments</comments>
      <pubDate>Thu, 13 Nov 2008 02:23:39 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150525&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F11%2F12%2Fconceitos-de-programacao-complexidade-ciclomatica%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Este é o quarto artigo em uma série sobre conceitos de programação. Os demais artigos podem ser encontrados na <a href="http://logbr.reflectivesurface.com/categoria/conceitos/">página de resumo sobre a série</a>. Como nos demais artigos, um aviso: o tratamento dado aos assuntos aqui é informativo e podem existir erros nos mesmos. Como nos demais artigos neste <span class="foreign-word" lang="en">blog</span>, comentários e correções são sempre bem-vindos.</p>

<h3>Complexidade Ciclomática</h3>

<p>Neste quarto artigo, vamos tratar um pouco de <strong>complexidade ciclomática</strong>. Apesar do nome esdrúxulo, complexidade ciclomática (também conhecida como complexidade condicional) é uma métrica simples para determinar, como o próprio nome sugere, a complexidade de um programa estruturado (cíclico).</p>

<p>Essa métrica foi desenvolvida em 1976 por Thomas J. McCabe e reflete diretamente o número de caminhos independentes que um programa pode tomar durante a sua execução.</p>

<p>Qualquer desenvolvedor que já tenha testado código em sua vida, sabe que a quantidade de testes necessária para exercitar um determinado trecho de código é diretamente proporcional à sua árvore decisória. Em outras palavras, quanto mais caminhos o código puder tomar (seja por meios de condicionais ou <span class="foreign-word" lang="en">loops</span>), maior a quantidade de testes necessários. E como veremos abaixo, há realmente uma relação direta entre a complexidade ciclomática e a cobertura de um código.</p>

<h3>Calculando a complexidade ciclomática</h3>

<p>Antes de mostrar exatamente como o cálculo pode ser feito, vamos observar algumas coisas em relação a um programa qualquer. Digamos que você esteja desenvolvendo um programa que lhe dê o maior divisor comum entre dois números. Uma fórmula simples é o <a href="http://en.wikipedia.org/wiki/Euclidean_algorithm">algoritmo de Euclides</a> que pode ser descrito da seguinte forma:</p>

<blockquote>
  <p>Dados dois números naturais <em>a</em> e <em>b</em>, verifique se <em>b</em> é zero. Se sim, <em>a</em> é o maior divisor comum entre os mesmos; caso contrário, repita o processo usando <em>b</em> e o resto da divisão de <em>a</em> por <em>b</em>.</p>
</blockquote>

<p>Esse algoritmo pode ser expresso pelo seguinte programa em Ruby (note que ele não está em Ruby idiomático):</p>

<pre><code>require "test/unit"

def euclid(m, n)
  if n > m
    r = m
    m = n
    n = r
  end
  r = m % n
  while r != 0
    m = n
    n = r
    r = m % n
  end
  n
end

class EuclidTest < Test::Unit::TestCase
  
  SETS = [[5, 10,  5], [2,  6,  2], [11,  7,  1], 
    [80, 64, 16], [2, 2, 2]]
  
  def test_euclid
    SETS.each do |set|
      assert_equal set[2], euclid(set[0], set[1])
    end
  end
  
end</code></pre>

<p>Se o programa acima for executado, ele rodará o caso de teste logo abaixo da função que verificará se a mesma está correta. Você pode adicionar mais casos ao conjunto <code>SETS</code> se desejar.</p>

<p>A função <code>euclid</code> pode ser descrita por um grafo simples que conecta os caminhos entre as várias declarações que a mesma contém. Esse grafo é o mostrado abaixo (clique para expandir):</p>

<p><a href="http://logbr.reflectivesurface.com/wp-content/uploads/2008/11/algoritmo-de-euclides-versao-nao-idiomatica.png"><img src="http://logbr.reflectivesurface.com/wp-content/uploads/2008/11/algoritmo-de-euclides-versao-nao-idiomatica.png" alt="" title="Algoritmo de Euclides (versão não-idiomática)" width="300" height="30" class="alignnone size-full wp-image-1155" /></a></p>

<p>Com base nesse grafo, podemos definir a complexidade ciclomática de um programa da seguinte forma:</p>

<pre><code>CC = A - N + 2C
</code></pre>

<p>Nessa fórmula:</p>

<ul>
<li>CC é a complexidade ciclomática</li>
<li>A é o número de arestas do grafo</li>
<li>N é o número de nós do grafo</li>
<li>C é o número de componentes conectados</li>
</ul>

<p>Como se trata de uma função simples com um único ponto de entrada e saída, o número de componentes é 1 e a fórmula pode ser reduzida para:</p>

<pre><code>CC = A - N + 2
</code></pre>

<p>Se a função possuísse múltiplos pontos de saída, entretanto, a complexidade ciclomática seria definida como:</p>

<pre><code>CC = A - N + C + R
</code></pre>

<p>Nessa fórmula, R é o número de declarações de saída (em Ruby, o número de <code>return</code>s).</p>

<p>Voltando ao grafo mostra na figura, vemos que o mesmo possui 11 nós e 12 arestas, o que nós dá uma complexidade ciclomática de 12 - 11 + 2, ou seja, 3.</p>

<p>Uma outra maneira bem simples de descobrir a complexidade ciclomática é contar o número de <span class="foreign-word" lang="en">loops</span> fechados no grafo (que são formados por condicionais e <span class="foreign-word" lang="en">loops</span>) e somar ao número de pontos de saída. No grafo acima, temos 2 <span class="foreign-word" lang="en">loops</span> fechados (os <code>if</code> e <code>while</code>) e um ponto de saída, resultando no mesmo valor 3 para a complexidade da função.</p>

<p>Uma coisa interessante é que a complexidade permanece a mesma quando a sintaxe de uma linguagem é levada em questão sem alterar a semântica do programa. Tome por exemplo a versão idiomática do algoritmo em Ruby:</p>

<pre><code>def euclid(m, n)
  m, n = n, m if n > m
  m, n = n, m % n while m % n != 0
  n
end</code></pre>

<p>O grafo gerado nesse caso é (clique para expandir):</p>

<p><a href="http://logbr.reflectivesurface.com/wp-content/uploads/2008/11/algoritmo-de-euclides-versao-idiomatica.png"><img src="http://logbr.reflectivesurface.com/wp-content/uploads/2008/11/algoritmo-de-euclides-versao-idiomatica.png" alt="" title="Algoritmo de Euclides (versão idiomática)" width="300" height="43" class="alignnone size-full wp-image-1156" /></a></p>

<p>Node que embora o número de nós e arestas tenha mudado, a relação entre eles não mudou e a complexidade permanece a mesma.</p>

<h3>Testando</h3>

<p>De uma forma geral, o valor da complexidade ciclomática define um limite superior para a quantidade de testes necessários para cobrir todos os caminhos decisórios no código em questão. Esse é um limite superior já que nem todos os caminhos são necessariamente realizáveis.</p>

<p>Disso se infere que quanto menor a complexidade, menor a quantidade de testes necessários <strong>para o método em questão</strong>. Esse fato implica em outro curioso: quebra um método em vários reduz a complexidade dos métodos mas aumenta a complexidade geral do código e, de forma geral, mantém a testabilidade do programa completo no mesmo nível.</p>

<h3>Referências</h3>

<p>Obviamente, já que a complexidade é um valor específico, é possível extrair da mesma uma referência. Baseado no trabalho de McCabe, esses valores de referência são:</p>

<ul>
<li>1-10, métodos simples, sem muito risco</li>
<li>11-20, métodos medianamente complexos, com risco moderado</li>
<li>21-50, métodos complexos, com risco alto</li>
<li>51 ou mais, métodos instáveis de altíssimo risco</li>
</ul>

<h3>Conclusão</h3>

<p>Essa foi uma pequena introdução ao assunto com o objetivo de abrir o caminho para artigos posteriores mostrando ferramentas de apoio ao cálculo e monitoramento da complexidade ciclomática. Como de usual, sugestões e correções são bem vindos.</p>]]></content:encoded>
      <category>Conceitos</category>
      <guid>http://logbr.reflectivesurface.com/2008/11/12/conceitos-de-programacao-complexidade-ciclomatica/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>gae-sqlite</title>
      <description/>
      <pubDate>Wed, 12 Nov 2008 16:20:04 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290004594&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[App Engine Fan:

Last month, I wrote I would not post the sql connector's source code until it was a little more functional. Guess what? I changed my mind: you can find all the code at http://code.google.com/p/gae-sqlite/.

From the code.google.com project page:
This is a module that will allow you to run Google's App Engine development server with an SQLite backend. The concept is intended to be generic enough that other databases (mysql, SQL Server, Oracle...) can follow with only minimal modifications.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290004594" />
]]></content:encoded>
      <guid>http://bitworking.org/news/386/gae-sqlite</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>RDFaification</title>
      <description/>
      <pubDate>Wed, 12 Nov 2008 14:29:29 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922634&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Shelley Powers: One unfortunate consequence of switching DOCTYPEs is that when I do use embedded SVG, the page won’t validate. However, this won’t impact on the user agents and their ability to process the SVG correctly, so I’ll just have to live with the invalidation errors. That’s the joy of DOCTYPEs.
We either need a DOCTYPE that supports both RDFa and SVG and that a validator recognizes, or a validator that doesn’t rely on DOCTYPE that supports RDFa.
oliver, Henri: suggestions?<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922634" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2923</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Google App Engine</title>
      <description/>
      <pubDate>Tue, 11 Nov 2008 17:49:49 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290004595&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[I've just started as a Developer Advocate for Google App Engine and 
    there's been a lot of talk of "lock-in" recently. Google will have more
    to say officially in the future, as obviously my blog isn't the place to 
    read about Google's official position, but I would like to point out the following
    things that have come up in conversation that people didn't know:
    

The development kit is open sourced.
All of the documentation for App Engine is CC licensed.
Much of the underlying technology has been described in academic publications.
Some of that underlying technology has been open sourced, such as protocol buffers.


      Also, you can see that other issues are on the roadmap 
      to be addressed, such as bulk upload and download.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290004595" />
]]></content:encoded>
      <guid>http://bitworking.org/news/384/google-app-engine</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Native JSON parser</title>
      <description/>
      <pubDate>Tue, 11 Nov 2008 12:11:03 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922635&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Mark Pilgrim: HTML 5 will not ... expose a native JSON parser for web content
HTML 5 may not, but the plan is that ECMAScript will (section 15.12).  It is already supported in IE8 beta 2.  Firefox has landed support, and is tracking it as a part of an overall plan to support ES3.1.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922635" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2922</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Content Drives Demand</title>
      <description><![CDATA[Jeff Schiller: These days, Internet Explorer is the last browser I look at… as long as all my textual content is actually visible, then that’s just fine by me.
I think I’ll take a bit of Ian’s advice, and drop my use of the X-UA-Compatible header.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922637" />
]]></description>
      <pubDate>Fri, 07 Nov 2008 21:40:46 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922637&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Mark Pilgrim: The <section> element is a very straightforward HTML 5 feature that you can’t actually use yet.
Jeff Schiller: These days, Internet Explorer is the last browser I look at… as long as all my textual content is actually visible, then that’s just fine by me.
With apologies to Mark (and I truly understand where he is coming from), it seems to me that we would all be a lot better off if less people listened to him and more listened to Jeff.
Frankly, I’m surprised that more WHATWG members don’t have the cojones to make use of straightforward markup innovations like the section element.
Meanwhile, I think I’ll take a bit of Ian’s advice, and drop my use of the X-UA-Compatible header, making my blog’s front page simultaneously demonstrate both Mark and Jeff’s points.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2920</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Benefits of Uniformity</title>
      <description><![CDATA[Jon Udell: These are, of course, best practices for an ecosystem sustained by web standards like URI, HTTP, and XML. But it was wonderful to see those best practices clearly demonstrated in a PDC keynote.
In many ways it feels like we are now about at the point in the evolution of the web where we were two decades ago with respect to GUIs.  For that reason, it pleases me greatly to hear that Don Box was on stage demonstrating the value of Hi-Rest.  And it pleases me that Atom/AtomPub played a role in this.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922639" />
]]></description>
      <pubDate>Sat, 01 Nov 2008 13:30:02 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922639&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Jon Udell: These are, of course, best practices for an ecosystem sustained by web standards like URI, HTTP, and XML. But it was wonderful to see those best practices clearly demonstrated in a PDC keynote.
In many ways it feels like we are now about at the point in the evolution of the web where we were two decades ago with respect to GUIs.  For that reason, it pleases me greatly to hear that Don Box was on stage demonstrating the value of Hi-Rest.  And it pleases me that Atom/AtomPub played a role in this.
On the off chance that anybody is reading this, there is considerable value to be obtained from Lo-Rest.  But it comes at a great cost.  And the way forward is not to have servicebus.windows.net and user-ctp.windows.net/V0.1/Mesh/MeshObjects using different interfaces.  Instead it means adopting HTML as a carrier wave for your signal — which, yes, implies that you need to employ the modern equivalent of screen scraping.  And have to deal with cookies.  HTML is far from uniform: there are a lot of different tag soup parsers out there at various levels of quality.  Having everybody parse HTML consistently would be a huge step forward.  At the present time, HTML5 is the most comprehensive and complete approach to this.  Having Microsoft more actively participate, and spinning off and fast tracking just those parts of HTML5 necessary to implement this part of the HTML5 vision; well, that would be a huge win.
And there are Hi-Rest analogs to this.  I’m confident that the service documents and feeds produced for the PDC demo were all well-formed, and valid.  As more people try to emulate this with PHP and templates, this won’t be true quite as much.  The first time a “smart quote” or a non-Latin1 character gets into the stream, it will fall over.  Having everybody recover in the same manner would also be a big win, though not quite as huge as it is for HTML.  Anne calls his explorations into this topic XML5.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2918</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Ubuntu on a Stick</title>
      <description><![CDATA[My plans are to do a fresh install of Intrepid Ibex on a number of computers, and since I had a spare machine, I thought I would recover Windows to a known clean slate, insert a second hard drive, and use that install to clone existing machines which would then be wiped and restored.
A few bumps along the way, none of which affect my overall plan.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922640" />
]]></description>
      <pubDate>Fri, 31 Oct 2008 18:16:40 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922640&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[My plans are to do a fresh install of Intrepid Ibex on a number of computers, and since I had a spare machine, I thought I would recover Windows to a known clean slate, insert a second hard drive, and use that install to clone existing machines which would then be wiped and restored.
A few bumps along the way, none of which affect my overall plan.
The recovering of Windows went fine, as did the installs of the various updates.
My first problem occurred when I tried to boot Ubuntu from CD-ROM.  The machine wouldn’t recognize the disk.  Other machines booted fine from this disk.  So I tried another (unrelated) disk, and it wouldn’t recognize it either.  The BIOS and Windows recognized that there was a CD reader, and could even be told to eject a disk, but couldn’t read anything.
I swapped out the CD reader for another one.  Same symptoms.  I swapped out the IDE cable.  Same symptoms.
Stumped, I decided to try out the new bootable USB maker.  System » Administration » Create a USB startup disk and within a few minutes I was happily installing.
After I installed Ubuntu on the second drive and rebooted, I was into Windows.  So I went into BIOS setup and reversed the boot order of the hard drives, and could boot into Ubuntu
My next problem was after I booted.  I got to the login screen, but after a successful login, all I could see was a background.  I could not Ctrl-Alt-Delete.  I could not Ctrl-Alt-F2 to see an alternate console.  But by rebooting and then doing a Ctrl-Alt-F2 before logging in, I could log in.  Looking at my Xorg.0.log file, I saw a number of messages like this:
[mi] EQ overflowing. The server is probably stuck in an infinite loop.
[mi] mieqEnequeue: out-of-order valuator event; dropping.
Based on this bug, I removed compiz and compiz-core and could then login to Gnome.
Finally, I could no longer boot via grub into Windows, but these instructions worked like a champ.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2917</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>OpenId Minus Id Equals Wide Open</title>
      <description><![CDATA[Martin Atkins: Yahoo!'s OP and now it seems Microsoft’s OP both ignore the value of openid.identity provided to them, and just return an assertion for whatever user’s logged in.
I may ultimately need to black-list such ids.  If everybody uses the same URI, I can’t tell them apart.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922641" />
]]></description>
      <pubDate>Wed, 29 Oct 2008 12:07:16 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922641&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Martin Atkins: Yahoo!'s OP and now it seems Microsoft’s OP both ignore the value of openid.identity provided to them, and just return an assertion for whatever user’s logged in.
I may ultimately need to black-list such ids.
Looking at live.com instructions:
At any Web site that supports OpenID 2.0, type openid.live-INT.com in the OpenID login box to sign in to that site by means of your Windows Live ID OpenID alias.

If everybody uses the same URI, I can’t tell them apart.  That doesn’t concern me much, but do find it a bit distressing that that’s the recommended usage.
What concerns me is that people may use such a URI for delegation.  If Jorgen, for example, were to add such a generic URI as his openid.delegate link, then anybody who has a windows live id could authenticate using his blog URI.
What concerns me more is if somebody follows these instructions for delegation.  Then anybody with a Windows Live id could authenticate using his blog.
I note that Jorgen left a comment on Martin’s blog using http://openid.live-int.com/jt.  As long as that URI is uniquely his, and can’t be used by anybody else, that’s fine.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2916</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Algumas dicas para testes melhores</title>
      <description><![CDATA[O Lucas Húngaro escreveu recentemente sobre a necessidade de abandonar testes quebradiços com uma forma de manter seus testes saudáveis, citando vários exemplos de como isso pode ser feito. Desnecessário dizer, concordo com o que ele disse.

Um conselho dele em particular me parece a melhor consideração sobre o assunto. Falando sobre mocks e stubs, ele [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150526" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/10/27/algumas-dicas-para-testes-melhores/#comments</comments>
      <pubDate>Mon, 27 Oct 2008 14:08:38 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150526&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F10%2F27%2Falgumas-dicas-para-testes-melhores%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>O <a href="http://www.makemesimple.com/blog/">Lucas Húngaro escreveu recentemente</a> sobre a necessidade de abandonar testes quebradiços com uma forma de manter seus testes saudáveis, citando vários exemplos de como isso pode ser feito. Desnecessário dizer, concordo com o que ele disse.</p>

<p>Um conselho dele em particular me parece a melhor consideração sobre o assunto. Falando sobre <span class="foreign-word" lang="en">mocks</span> e <span class="foreign-word" lang="en">stubs</span>, ele diz:</p>

<blockquote>
  <p>Algumas soluções pra isso são: não utilizar <span class="foreign-word" lang="en">mocks</span> e <span class="foreign-word" lang="en">stubs</span> (o que é um tanto extremista), aumentar o encapsulamento das classes ou aceitar isso e continuar.</p>
</blockquote>

<p>Chamo a atenção para a parte final: algumas vezes, você tem simplesmente que aceitar que alguns testes devem ser de certa forma para garantir uma cobertura mais compreensiva.</p>

<p>Dito isso, seguem algumas dicas para testes melhores:</p>

<h4><span class="foreign-word" lang="en">Mocks</span> e <span class="foreign-word" lang="en">Stubs</span></h4>

<p>Uma regra simples que pode ajudar a entender quando usar essas duas técnicas é a seguinte: <strong>Se o comportamento esperado deve ser conhecido, use <span class="foreign-word" lang="en">mocks</span> e <span class="foreign-word" lang="en">stubs</span>. Caso contrário, não.</strong></p>

<p>Isso torna fácil perceber que testes de modelos&#8211;no caso do Rails, por exemplo&#8211;raramente (ou nunca) deve usar essas técnicas. Quando se trata do domínio da aplicação, encapsulamento é uma propriedade básica de sistemas orientados a objetos que não deve ser violada se possível. Obviamente, <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">abstrações vazam</a>; mas isso não deve ser uma desculpa para quebrá-las em testes.</p>

<h4>Não teste a abstração imediatamente inferior</h4>

<p>Se você está usando Rails, por exemplo, não faz o menor sentido testar a abstração inferior. É muito comum ver testes como:</p>

<pre><code>it "should return all current books" do
  Book.current.proxy_options.should == { :conditions =&gt; { :current =&gt; true } }
end
</code></pre>

<p>Esse tipo de teste verifica se o Rails está funcionando da maneira como deve funcionar e não se o seu código está correto. O resultado é que pequenas mudanças e principalmente a introdução de algum comportamento ortogonal pode quebrar completamente a aplicação enquanto o teste continua a funcionar.</p>

<p>Digamos, por exemplo, que você agora tenha que usar alguma esquema de <span class="foreign-word" lang="en">caching</span> em sua aplicação. No interesse de que a abstração não vaze, você envolve o método acima em alguma abstração que faça isso. O teste acima provavelmente quebrará de imediato, porque está testando a abstração inferior e não o comportamento da aplicação.</p>

<p>O teste correto, nesse caso, seria verificar se a lista retorna é realmente correta, mesmo que isso envolva alguma manipulação de dados que reduza a velocidade do teste.</p>

<h4>Use testes de sanidade</h4>

<p>Conversamente, é importante também ter alguns testes de sanidade. Às vezes é necessário saber se alguma coisa está declarada, mesmo que a forma final daquela declaração não seja importante.</p>

<p>Um exemplo disso são testes em <span class="foreign-word" lang="en">views</span>. Geralmente, testar se algum conteúdo está aparecendo em uma <span class="foreign-word" lang="en">view</span> é inteiramente desnecessário e pode gerar testes que devem ser refeitos a cada pequena mudança para se adaptar a novas condições.</p>

<p>Mesmo assim, em alguns casos é importante a existência de testes que correm esse risco como forma de testar a sanidade da aplicação; em outras palavras, testar se condições básicas estão sendo supridas.</p>

<h4>Não teste nada que não seja público</h4>

<p>Uma pergunta muito comum em listas de discussão é como testar métodos privados ou protegidos de uma classe. A reposta geralmente envolve o uso de reflexão e violação de abstrações.</p>

<p>Um exemplo comum seria o código abaixo:</p>

<pre><code>it "should prepare the environment" do
  Manager.send(:prepare_environment)
  Manager.environment.name.should == "development"
end
</code></pre>

<p>A resposta correta deveria ser: nunca faça isso. Se seus testes contém alguma necessidade desse tipo, você está violando o encapsulamento e isso indica alguma problema arquitetural mais básico da aplicação. Provavelmente alguma necessidade de separação de dependências que você ainda não identificou.</p>

<p>Nesse casos, funcionalidade básica que envolva código encapsulado pode ser melhor testada pelo seu efeito em outras partes da aplicação.</p>

<h4>Cuidado com a ordem dos seus testes</h4>

<p>Uma coisa interessante é tentar rodar os seus testes em ordem arbitrária. Existe opções para isso em alguns dos <span class="foreign-word" lang="en">frameworks</span> existentes que podem ajudar a identificar dependências escondidas em seus testes.</p>

<h4>Finalizando</h4>

<p>Para terminar, esse são apenas alguns dos muitos conselhos possíveis nessa área. Fiquem à vontade para usar a área de comentários do texto para expandir sobre o assunto.</p>

<p>Um conselho final: use seus testes como oportunidades para pensar sobre a sua aplicação. Se você se vê em uma situação em que testar está se convertendo em algo progressivamente mais complicado, alguma coisa está errada na forma como você desenhou seu código. Pare, pense sobre o assunto, e refatore. Seu código e seu tempo agradecem.</p>]]></content:encoded>
      <category>Programação</category>
      <guid>http://logbr.reflectivesurface.com/2008/10/27/algumas-dicas-para-testes-melhores/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Algumas considerações sobre TDD e BDD</title>
      <description><![CDATA[Parece haver muita confusão sobre a diferença entre TDD e BDD na comunidade Rails. A criação de vários frameworks competidores (RSpec, Shoulda, Expectations, etc) parece não ter ajudado muito já que cada proponente torce um pouco a visão dada por cada um deles.

A grande divisão

O problema é que a maioria das pessoas que pratica uma [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150527" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/10/27/algumas-consideracoes-sobre-tdd-e-bdd/#comments</comments>
      <pubDate>Mon, 27 Oct 2008 10:32:16 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150527&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F10%2F27%2Falgumas-consideracoes-sobre-tdd-e-bdd%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Parece haver muita <a href="http://www.google.com/search?client=safari&amp;rls=en-us&amp;q=tdd+vs+bdd&amp;ie=UTF-8&amp;oe=UTF-8">confusão sobre a diferença entre TDD e BDD</a> na comunidade Rails. A criação de vários <span class="foreign-word" lang="en">frameworks</span> competidores (<a href="http://rspec.info/">RSpec</a>, <a href="http://www.thoughtbot.com/projects/shoulda">Shoulda</a>, <a href="http://blog.jayfields.com/2007/12/ruby-expectation-gem.html">Expectations</a>, etc) parece não ter ajudado muito já que cada proponente torce um pouco a visão dada por cada um deles.</p>

<h4>A grande divisão</h4>

<p>O problema é que a maioria das pessoas que pratica uma variante ou outra nunca leu a literatura sobre o assunto e por causa disso há uma falta de formalização sobre o assunto. Muito do que se vê escrito hoje tanto sobre TDD ou BDD é escrito da forma que aquela pessoa em particular pratica o assunto e não como o conceito foi sendo desenvolvido ao longo das anos.</p>

<p>Tome, por exemplo, TDD como <a href="http://www.agiledata.org/essays/tdd.html">popuralizado originalmente por Kent Beck</a> no contexto de <span class="foreign-word" lang="en">Extreme Programming</span>. Existe uma granularidade envolvida no crescimento do código que pode ser descrita como orgânica.</p>

<h4><span class="foreign-word" lang="en">Design</span> ou <span class="foreign-word" lang="en">Development</span>?</h4>

<p>Uma das coisas que sempre me ajudou a enxergar o modo apropriado de construir uma aplicação a partir de testes foi pensar no D final de TDD ou BDD não como desenvolvimento, mas como <span class="foreign-word" lang="en">design</span>.</p>

<p>Voltando ao tema de granularidade, se você fizer uma experimento e acompanhar dezenas de pessoas que &#8220;praticam&#8221; TDD ou BDD, o mais provável é que você perceba que os testes estão sendo escritos como uma forma de cobrir o código e não como uma forma de pensar no código em si. Um teste é escrito que demonstra um certo caso de uso da classe ou método em questão e o código para aquele trecho é então escrito.</p>

<p>É muito comum, dentro da prática descrita acima, que vários testes seja escritos em seqüência e o código da classe ou método inteiro seja depois implementado. Voltando ao modo como Kent Beck explicou o processo originalmente, nada por estar mais longe da realidade.</p>

<p>De fato, nos seus exemplos concretos sobre o assunto, Kent Beck compara o uso de TDD ao uso de uma lista de tarefas para a construção de código, o que força o desenvolvedor a pensar em detalhes sobre a arquitetura que está criando. Volta aqui o sentido de <span class="foreign-word" lang="en">design</span> e não de desenvolvimento puro.</p>

<p>Chega-se então ao ponto de que cada teste é pensado como uma forma de evoluir a arquitetura do código e pensar em como aquela classe ou método existe dentro do contexto mais generalizado da aplicação. Não é surpreendente que quando isso é feito, coberturas de 100% são factíveis, métodos ou funções não possuem mais do que algumas poucas linhas fazendo exatamente e o que deve fazer e não mais e uma delegação efetiva de responsabilidades acontece.</p>

<h4>TDD versus BDD</h4>

<p>Chega-se então ao ponto central da conversa? Qual é a diferença principal entre TDD e BDD? No ponto mais básico da cadeia, a resposta é: nenhuma.</p>

<p>Tanto TDD quando BDD são formas de se pensar em testes partindo de premissas ligeiramente diferentes mas chegando ao mesmo resultado prático. Sendo feitas de maneira apropriada, o resultado final dentro das necessidades acima (cobertura, delegação, arquitetura) é o mesmo e a conversação que deve acontecer no desenvolvimento ocorre naturalmente.</p>

<p>Apesar disso, há uma diferença histórica que está evoluindo com o tempo e que, em última instância, está se convertendo no foco de debate entre os dois campos. Essa diferença foi inicialmente expressa por <a href="http://dannorth.net/introducing-bdd">Dan North</a> (responsável pelo desenvolvimento do RBehave, que mais tarde se tornaria a base do Story Runner do RSpec) e depois elaborada por <a href="http://gilesbowkett.blogspot.com/2008/02/david-chelimsky-on-tdd-vs-bdd.html">David Chelimsky</a>.</p>

<p>Esse posicionamento coloca BDD não como uma oposição direta a TDD em termos práticas, mas como uma corrente filosófica que engloba TDD e expande o discurso para incluir elementos que vão além do metodológico e já começam a cair no processual.</p>

<p>Um exemplo claro disso é a ascensão de <span class="foreign-word" lang="en">frameworks</span> orientados a estórias (<a href="http://en.wikipedia.org/wiki/User_acceptance_testing#User_acceptance_testing">testes de aceitação de usuários</a>) como o <a href="http://github.com/aslakhellesoy/cucumber/tree/master">Cucumber</a>. Esses esforços representam a graduação de BDD não somente com uma forma de fazer testes mas como um processo de pensar e executar testes ao longo de toda a gama de necessidades de uma aplicação (de unitários e visuais).</p>

<p>Essa conversa é a parte mais importante do BDD e, no caso do Rails e Ruby, o RSpec representa apenas uma faceta de tudo o que vem sendo pensado pela comunidade. Eventualmente, como Chelimsky coloca, TDD será um parte de algo maior que será chamado de BDD.</p>

<h4>Finalizando</h4>

<p>A confusão experimentada atualmente é mais resultado da conversação acima do que da diferença real entre os <span class="foreign-word" lang="en">frameworks</span>. Ainda citando Chelimsky, quando BDD era somente sobre testes unitários, não havia diferença nenhum entre TDD e BDD. Ambos eram e são sobre a melhor forma de testar uma aplicação e nada mais do que isso.</p>

<p>Para dar um exemplo, atualmente eu tenho preferido a combinação Test/Unit + Shoulda + RR ao invés do meu usual RSpec. Gosto da leveza dos anteriores em relação ao último quando os testes se tornam mais envolvidos. Mas isso representa apenas dores de crescimento do RSpec. É bem possível que quando este último estiver mais estabilizado, lidando mais com a magia negra que ele precisa para sua sintaxe, eu mude novamente de prática.</p>

<p>De uma forma geral, então, escolha o <span class="foreign-word" lang="en">frameworks</span> que melhor lhe convier. Desde que a forma como você faz testes esteja correta, o resultado final estará correto também.</p>]]></content:encoded>
      <category>Rails</category>
      <guid>http://logbr.reflectivesurface.com/2008/10/27/algumas-consideracoes-sobre-tdd-e-bdd/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Quem imaginaria?</title>
      <description><![CDATA[Lendo essa entrada no blog do Jon Taplin (muito recomendado, por sinal) é interessante ver que o Brasil figura entre as economias emergentes de menor vulnerabilidade durante a crise econômica atual. De fato, entre os países listados abaixo, ele é o menor vulnerável.

Isso não quer dizer, é claro, que ele não seja muito vulnerável. Como [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150528" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/10/25/quem-imaginaria/#comments</comments>
      <pubDate>Sat, 25 Oct 2008 03:12:45 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150528&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F10%2F25%2Fquem-imaginaria%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Lendo <a href="http://jtaplin.wordpress.com/2008/10/24/the-road-ahead/">essa entrada no <span class="foreign-word" lang="en">blog</span> do Jon Taplin</a> (muito recomendado, por sinal) é interessante ver que o Brasil figura entre as economias emergentes de menor vulnerabilidade durante a crise econômica atual. De fato, entre os países listados abaixo, ele é o menor vulnerável.</p>

<p>Isso não quer dizer, é claro, que ele não seja muito vulnerável. Como Taplin mesmo aponta, o governo está tendo que queimar milhões de reais para manter a moeda em um nível de valorização razoável. Da mesma forma, a queda da bolsa brasileira é uma das mais acentuadas.</p>

<p>Mesmo assim, é interessante ver que, na situação atual, o Brasil está em uma posição bem diferente da imaginada há alguns anos atrás. Ninguém apostaria suas fichas nem de longe em um Brasil com um economia estável e um poder de influência razoável no mercado global. Se nem tudo são flores, pelo menos não há um pânica generalizado em um momento que outros já estão em plena fuga.</p>

<p>Agora, se ao menos houvesse um jeito de exilar todos especuladores&#8230;</p>]]></content:encoded>
      <category>Mundo</category>
      <guid>http://logbr.reflectivesurface.com/2008/10/25/quem-imaginaria/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Aprendendo Rails</title>
      <description><![CDATA[O dia nove de outubro passado marcou os dois anos da liberação do meu tutorial Rails para sua Diversão e Lucro. Oito meses depois do lançamento, o mesmo já havia ultrapassado 15 mil downloads somente no meu servidor. Considerando que a licença é GFDL e que o mesmo foi reproduzido em dezenas de sites, o [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150529" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/10/23/aprendendo-rails/#comments</comments>
      <pubDate>Thu, 23 Oct 2008 13:22:02 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150529&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F10%2F23%2Faprendendo-rails%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>O dia nove de outubro passado marcou os dois anos da liberação do meu tutorial <a href="http://logbr.reflectivesurface.com/2006/10/09/rails-para-sua-diversao-e-lucro/">Rails para sua Diversão e Lucro</a>. Oito meses depois do lançamento, o mesmo já havia ultrapassado 15 mil <span class="foreign-word" lang="en">downloads</span> somente no meu servidor. Considerando que a licença é GFDL e que o mesmo foi reproduzido em dezenas de <span class="foreign-word" lang="en">sites</span>, o número atual deve ter sido bem maior mesmo na época.</p>

<p>No geral, foi uma experiência bem positiva. Para um tutorial que começou <a href="http://logbr.reflectivesurface.com/2006/10/19/mao-na-massa-rails-para-sua-diversao-e-lucro/">como material para um curso</a>, a quantidade de pessoas interessadas foi surpreendente. Mesmo na época, havia uma carência enorme de informações sobre o assunto. Coincidentemente, <a href="http://forum.rubyonbr.org/forums/5/topics/20">o primeiro livro de Rails</a> no Brasil também foi lançado na mesma época. Acho muito legal, inclusive, <a href="http://logbr.reflectivesurface.com/2007/06/04/rails-para-sua-diversao-e-lucro-o-balanco/#comment-3868">que pessoas que hoje são extremamente ativas</a> na comunidade tenham tido contato inicial com Rails através do tutorial.</p>

<p>Bem, esse monte de reminiscências é para anunciar aos leitores regulares que possam eventualmente desejar aprender Rails e aos visitantes que volta e meia chegam aqui perguntando sobre o assunto e topando com um tutorial desatualizado que uma nova versão está disponível.</p>

<p>No melhor espírito da GFDL, Cássio Souza <a href="http://www.devlab.com.br/rails">atualizou o tutorial para Rails 2.1</a>, modificando o material antigo, removendo as partes ultrapassadas e acrescentando muito material novo em um novo tutorial que reflete mais precisamente a versão atual do Rails (de 1.2 para 2.1). O material também é acompanhando de  <span class="foreign-word" lang="en">screencast</span> que explica mais detalhes práticos sobre o assunto.</p>

<p>Fica aí a dica para quem quer aprender sobre Rails de maneira prática. E que venha os <span class="foreign-word" lang="en">downloads</span>. <img src='http://logbr.reflectivesurface.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>]]></content:encoded>
      <category>Rails</category>
      <guid>http://logbr.reflectivesurface.com/2008/10/23/aprendendo-rails/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>A falsa dicotomia: generalista versus especialista</title>
      <description><![CDATA[Um papo semi-presente na área de TI é a velha dúvida: generalista ou especialista? Como em essencialmente qualquer carreira em que a dicotomia é possível, há sempre uma grande questão em torno do que decidir quando se pensa em um plano para o futuro.

De um lado, especialistas justificam sua escolha em termos de melhores salários, [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150530" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/10/22/a-falsa-dicotomia-generalista-versus-especialista/#comments</comments>
      <pubDate>Thu, 23 Oct 2008 00:57:36 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150530&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F10%2F22%2Fa-falsa-dicotomia-generalista-versus-especialista%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Um papo semi-presente na área de TI é a velha dúvida: <strong>generalista ou especialista</strong>? Como em essencialmente qualquer carreira em que a dicotomia é possível, há sempre uma grande questão em torno do que decidir quando se pensa em um plano para o futuro.</p>

<p>De um lado, especialistas justificam sua escolha em termos de melhores salários, pouco rotatividade, maior reconhecimento. Do outro lado, os generalistas justificam com maior estabilidade, menos rotina, maior amplitude de oportunidade. Sempre há uma certa tensão entre as duas versões do profissional de TI e como qualquer dicotomia, geralmente <strong>a verdade é uma coisa inteiramente diferente</strong>.</p>

<p>No tempo que eu tenho de carreira, o que eu observo é que <strong>a dicotomia é inteiramente falsa</strong>. Se existe o bom profissional, não há como o mesmo ser especialista ou generalista. Em um área como a nossa, onde a velocidade de transformação é enorme, medida em meses e semanas ao invés de décadas e anos, qualquer coisa que não seja a fusão dos dois conceitos é simplesmente impensável.</p>

<p>Ironicamente, algumas das raízes dessa separação refletem, ou talvez até tenham sua origem, na antiga disputa entre consultores e empreendedores&#8211;centrada, por sua vez, na <strong>igualmente inválida dicotomia entre engenheiros e artesãos</strong>. Como a maioria das comparações feitas para explicar o desenvolvimento de <span class="foreign-word" lang="en">software</span>, as analogias passam longe de explicar a realidade.</p>

<p>Recentemente, a popularização de <span class="foreign-word" lang="en">frameworks</span> e linguagens fora do <span class="foreign-word" lang="en">mainstream</span> como Rails/Ruby e Django/Python permitiu uma rara observação de como qualquer separação explícita geralmente é de aplicação limitada.</p>

<p>Um caso usual é tomar um profissional que trabalha com uma dessas tecnologias, que está tentando sair do comum em seu trabalho, seja como forma de criar uma nova carreira ou mudar sua empresa para obter uma carreira mais interessante, e por via dessa necessidade forja uma aliança entre áreas díspares como gerência, <span class="foreign-word" lang="en">design</span>, usabilidade, programação e outras (às vezes acumulando todas essas funções sobre si mesmo) e usar isso como exemplo de que o generalizado é melhor do que o especializado.</p>

<p>O mesmo erro é tomar uma disciplina como medicina e usar para ilustrar a outra proposição. Enquanto o exemplo do parágrafo anterior é um erro ao assumir que o mesmo é um exemplo de arte, o segundo é um erro em assumir que &#8220;engenharia&#8221; é uma metáfora inteiramente válida para o desenvolvimento de <span class="foreign-word" lang="en">software</span>.</p>

<p>A realidade é que, como em qualquer área, <strong>o nosso grau de proficiência é inteiramente dependente do âmbito do que estamos fazendo no momento</strong> e das circunstâncias transitórias em que esse trabalho se exprime. A especialização, nesse sentido, vem mais como força da acumulação de experiência do que de uma escolha explícita.</p>

<p>Um desenvolvedor é um engenheiro? Sim. É um artista? Também. Por extensão, a mesma pergunta pode ser feita para a dicotomia inicial. É um generalista? Sim. É um especialista? Também.</p>

<p>Isso é o que Dave Thomas fala quando explica sobre o <strong><span class="foreign-word" lang="en"><a href="http://www.google.com/search?hl=en&amp;lr=&amp;safe=off&amp;q=Dreyfus+Model+for+Skills+Acquisition&amp;btnG=Search">Dreyfus model</a></span></strong>. Você vai de um lado do espectro ao outro e às vezes está em vários pontos em várias áreas. Quando isso é considerado, a dicotomia cai imediatamente por terra.</p>

<p>Em última instância, como a maioria das preocupações similares, o único resultado da eterna discussão é o gasto de tempo e calorias que poderiam ser postos para melhor uso em projetos mais interessantes. Na próxima vez que alguém quiser discutir isso com você, dê de ombros e ignore. Você não estará perdendo nada de valor para sua carreira futura.</p>

<p><strong>Atualização</strong>: A propósito, acabaram de chamar a minha atenção que o <a href="http://www.nomedojogo.com/">Carlos Brando</a> e o <a href="http://www.akitaonrails.com/">Fábio Akita</a> fazem essencialmente o mesmo ponto no <a href="http://www.nomedojogo.com/2008/10/22/rails-podcast-brasil-episodio-34-especial-rails-summit/">Rails Podcast Brasil #34</a>. Desnecessário dizer, concordo.</p>]]></content:encoded>
      <category>Trabalho</category>
      <guid>http://logbr.reflectivesurface.com/2008/10/22/a-falsa-dicotomia-generalista-versus-especialista/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Como blogar efetivamente, ficar famoso e ganhar leitores sem parecer um plagiador</title>
      <description><![CDATA[O Google registra nada menos que 77 milhões de referências a &#8220;como blogar&#8221;. Milhares de conselhos dispensados por famosos e não famosos que tentar ensinar a outros (e convencer a si próprios) como chegar à ponta da vasta cauda longa que compreende as múltiplas e dissonantes blogosferas espalhadas por aquilo que se convencionou chamar a [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=288150531" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/10/20/como-blogar-efetivamente-ficar-famoso-e-ganhar-leitores-sem-parecer-um-plagiador/#comments</comments>
      <pubDate>Mon, 20 Oct 2008 08:50:01 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=288150531&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F10%2F20%2Fcomo-blogar-efetivamente-ficar-famoso-e-ganhar-leitores-sem-parecer-um-plagiador%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>O Google registra <a href="http://www.google.com/search?client=safari&amp;rls=en-us&amp;q=how+to+blog&amp;ie=UTF-8&amp;oe=UTF-8">nada menos que 77 milhões</a> de referências a &#8220;como blogar&#8221;. Milhares de conselhos dispensados por famosos e não famosos que tentar ensinar a outros (e convencer a si próprios) como chegar à ponta da vasta cauda longa que compreende as múltiplas e dissonantes blogosferas espalhadas por aquilo que se convencionou chamar a Web.</p>

<p>O que nenhum desse milhões de textos diz é que a verdade é bem mais simples do que parece. Neste pequeno texto, chame de cartilha se quiser, apresento o método mais efetivo, mais seguro e mais recompensador de se erguer aos pináculos da sua blogosfera de escolha. E isso tudo sem o inconveniente de parecer um plagiador.</p>

<p>O método descrito abaixo compreende a criação de um formato específico de artigo, necessariamente longo&#8211;o que significa que a técnica só vai funcionar para aqueles com paciência de escrever algo além das médias três linhas que compõem o usual texto de um <span class="foreign-word" lang="en">blog</span>&#8211;dispensado aos leitores em doses ocasionais, duas a três vezes por semana. Esse texto possui seções específicas que agora descrevo:</p>

<h3>Parte I - Do assunto</h3>

<p>O primeiro passo é escolher um tema que esteja em voga. Atualmente, por exemplo, pode ser algo relacionado à <a href="http://blogsearch.google.com/blogsearch?hl=en&amp;ie=UTF-8&amp;q=crise+econômica&amp;btnG=Search+Blogs">crise econômica</a>, <a href="http://blogsearch.google.com/blogsearch?hl=en&amp;ie=UTF-8&amp;q=obama+vs+mccain&amp;btnG=Search+Blogs">Obama versus McCain</a>, <a href="http://blogsearch.google.com/blogsearch?hl=en&amp;ie=UTF-8&amp;q=startups&amp;btnG=Search+Blogs">o sempre presente fluxo de <span class="foreign-word" lang="en">start ups</span> Web</a>, <a href="http://www.readwriteweb.com/">os lançamentos de produtos de firmas</a> Web famosas e assim por diante. Se você não consegue ter idéias, basta <a href="http://www.techcrunch.com/">visitar um site de notícias Web qualquer</a> e usar a inspiração.</p>

<p>Como é possível ver, escolher o assunto é muito simples. Basta reusar algo que está sendo falado ou que está no &#8220;inconsciente coletivo&#8221; da Web no momento. Você vai perceber depois de alguns artigos que não é necessário nenhum tipo de originalidade. Afinal de contas, ninguém é original.</p>

<h3>Parte II - Do título</h3>

<p>O título, novamente, é tão simples quando escolher o assunto. Na verdade, existem somente três tipos de títulos que levam ao estrelato. A menos que você queira variar ocasionalmente, para surpreender um ou outro leitor, você deve ser conformar a estes três padrões, que são:</p>

<ul>
<li>Como [alguma coisa]. Por exemplo, Como blogar efetivamente, ficar famoso e ganhar leitores sem parecer um plagiador; ou Como entender as eleições americanas, ou Como ser um marketeiro eficaz.</li>
<li>[N] passos para [alguma coisa]. Por exemplo, 5 passos para blogar efetivamente, ficar famoso e ganhar leitores sem parecer um plagiador; ou 3 frases para entender as eleições americanas, ou 9 atitudes para ser um marketeiro eficaz.</li>
<li>D[a/as/o/os] um [assunto qualquer]. Por exemplo, Dos passos para blogar efetivamente, ficar famoso e ganhar leitores sem parecer um plagiador; ou Das necessidades de entender as eleições americanas, ou Das vantagens de ser um marketeiro eficaz.</li>
</ul>

<p>Como é possível perceber, não existe esforço nenhum em criar um título eficiente. Basta adaptar alguma frase pequena nos moldes acima e você terá um <span class="foreign-word" lang="en">pagerank</span> vencedor à sua espera.</p>

<h3>Parte III - Da introdução</h3>

<p>Depois de falar na parte fácil, é hora de falar da parte mais difícil. Como o seu professor de literatura da quinta série costumava dizer, a introdução e a conclusão são duas das partes mais importantes de um texto. Já que só sobra o desenvolvimento, acho que esses professores estavam pensando em seus alunos como blogueiros futuros.</p>

<p>Mas, infelizmente, tais professores estavam certos. A parte mais difícil de um texto vencedor é a introdução. E isso porque, de todo o resto, é a única que vai exigir um módico de originalidade. Se você começar a copiar na introdução, vai ser sacado rapidamente. Mas não se preocupe, como uma boa introdução não passa de dois ou três parágrafos&#8211;que podem ser curtos&#8211;o risco de errar é mínimo.</p>

<p>Para uma boa introdução, basta criar esses dois os três parágrafos&#8211;que podem ser duas ou três linhas na verdades, mas não se esqueça das quebras para torná-los mais convincentes&#8211;com alguma citação famoso seguida de uma declaração sobre como você vai iluminar o assunto. Varie isso a cada artigo e os leitores vão achar que você é, além de tudo, um erudito.</p>

<h3>Parte IV - Do conteúdo, ou, da verborréia necessária</h3>

<p>Se a introdução é complicada, o conteúdo em si é absurdamente simples. Tudo o que é necessário é uma quantidade razoável de verborréia parafraseadas, citada e puramente copiada e você está pronto para a glória.</p>

<p>Para acertar a mão, basta seguir os passos abaixo:</p>

<ol>
<li><p>Primeiro, encontre um autor que tenha escrito algo que seja pertinente ao seu assunto (mesmo que apenas de leve) e que esteja em voga. Atualmente, livros como <a href="http://www.amazon.com/Black-Swan-Impact-Highly-Improbable/dp/1400063515">A Lógica do Cisne Negro</a>, <a href="http://www.gladwell.com/blink/">Blink</a>, <a href="http://www.gladwell.com/tippingpoint/index.html">The Tipping Point</a>, <a href="http://en.wikipedia.org/wiki/Freakonomics">Freakonomics</a>, <a href="http://www.thelongtail.com/">The Long Tail</a>, <a href="http://www.nicholasgcarr.com/bigswitch/">The Big Switch</a>, <a href="http://www.amazon.com/Linked-Everything-Connected-Else-Means/dp/0452284392">Linked</a> ou qualquer outra nessa linha de assuntos modernosos que se propõem a explicar tudo sobre tudo.</p></li>
<li><p>Livro escolhido, você precisa agora seguir um padrão bem simples: três parágrafos de paráfrase, ou seja, falando exatamente o que o autor falou em algum ponto do livro com suas palávras, e um parágrafo citando o autor do livro. Para cada conjunto desse, coloque um título parafraseado do próprio lido ou inventado na hora mesmo.</p></li>
<li><p>Para não ficar ainda mais interessante, a cada dez ou doze parágrafos, introduza alguma citação ou paráfrase de outro autor. Se leitores vão achar você ainda mais erudito pela profundidade das correlações.</p></li>
</ol>

<p>E é só. Desde que o artigo seja grande, o esforço será notado. Caso você não queira se dar ao trabalho de ler um livro ou mesmo escaneá-lo em busca de citações interessantes, um artigo em uma publicação da sua área também serve. Seja a <a href="http://www.infoq.com/">InfoQ</a>, <a href="http://www.wired.com/">Wired</a> ou <a href="http://www.nytimes.com/">The New York Times</a>, o importante é contar a estória direito.</p>

<h3>Parte V - Da conclusão</h3>

<p>Finalizar, ao contrário do que o seu professor dizia, não é tão complicado. Basta criar alguma expectativa no leitor de como ter lido aquele artigo mudou a vida dele ou explicar como, de posse das informações que você passou, que você tão cuidadosamente colou em um artigo de proporções avassaladoras, vai transformar a sua compreensão de tudo o mais e torná-lo mais erudito, famoso ou eficiente. Qualquer dessas palavras ou similares em uma frase já é vencedora.</p>

<h3>Conclusão</h3>

<p>Como você pode ver, o processo todo é simples (embora um pouquinho trabalhoso). Mas, como já diziam os antigos, <span class="foreign-word" lang="en">no pain, no gain</span>. Basta seguir as instruções, gastar uns 20 ou 30 minutos coletando citações de suas obras favoritas e você terá algo original, digno de uma mestrado ou doutorado.</p>

<p>Para terminar, depois de postar o texto, sente-se e aguarde as dezenas de comentários congratulando você por sua elegância, erudição e compreensão do mercado. Depois de tanto trabalho, você mereceu.</p>

<hr />

<p><strong>P.S.: Disclaimer</strong> Eu presumo que os leitores regulares vão perceber imediatamente que o texto acima é irônico. Mas, como várias pára-quedistas podem pensar o contrário, fica aqui o <span class="foreign-word" lang="en">disclaimer</span>. Não vai adiantar muito, provavelmente, mas o seguro morreu de velho.</p>]]></content:encoded>
      <category>Blogging</category>
      <guid>http://logbr.reflectivesurface.com/2008/10/19/como-blogar-efetivamente-ficar-famoso-e-ganhar-leitores-sem-parecer-um-plagiador/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Se divertindo com encodings no Ruby 1.9</title>
      <description><![CDATA[<style type="text/css">
<!--
.Identifier { color: #ffcc00; }
.Constant { color: #339999; }
.Type { color: #aaaa77; }
.Comment { color: #9933cc; font-style: italic; }
.Statement { color: #ff6600; }
pre { font-family: monospace; color: #eeeeee; background-color: #000000; }
.lnr { color: #ddeeff; background-color: #222222; }
-->
</style>

<p>
<b>Disclaimer:</b> Post descaradamente copiando <a href="http://pragdave.blogs.pragprog.com/pragdave/2008/04/fun-with-ruby-1.html">um do Dave Thomas</a>, mas que vai servir para resolver uma dúvida que apareceu durante o <a href="http://www.locaweb.com.br/railssummit">Rails Summit Latin America</a>.
</p>

<p>
Pronto, dito isso, posso continuar. :-) Apareceu uma dúvida da platéia sobre como fazer pluralizações em atributos do ActiveRecord que utilizam acentuação nos seus nomes. Apesar de achar estranho usar acentuação (cada um, cada um né), uma coisinha interessante que vai vir no Ruby 1.9 é o suporte de encodings diferentes nos arquivos (e em fluxos de IO, Strings, regexps, símbolos, etc, como bem disse o Dave). Isso permite fazer algumas coisinhas interessantes como ele mostrou no artigo original, do qual eu derivei esse exemplo:
</p>

<pre>
<span class="lnr">1 </span><span class="Comment"># encoding: utf-8</span>
<span class="lnr">2 </span><span class="Statement">module</span> <span class="Type">Enumerable</span>
<span class="lnr">3 </span>   <span class="Statement">def</span> &#8721;
<span class="lnr">4 </span>      <span class="Constant">self</span>.inject {|<span class="Identifier">memo</span>,<span class="Identifier">val</span>| memo += val}
<span class="lnr">5 </span>   <span class="Statement">end</span>
<span class="lnr">6 </span><span class="Statement">end</span>
<span class="lnr">7 </span>
<span class="lnr">8 </span>puts [<span class="Constant">1</span>,<span class="Constant">2</span>,<span class="Constant">3</span>].&#8721;
<span class="lnr">9 </span>puts (<span class="Constant">0</span>..<span class="Constant">3</span>).&#8721;
</pre>

<p>
Interessante hein? Para quem quiser inserir esses caracteres malucos no <a href="http://www.vim.org">Vim</a>, consulte o help dos <tt>digraphs</tt> com <tt>:help digraphs</tt>. Esse do exemplo é feito usando, no modo de inserção, <tt>CTRL+K +Z</tt>.
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290962473" />
]]></description>
      <pubDate>Fri, 17 Oct 2008 15:17:03 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290962473&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F548</link>
      <guid>http://eustaquiorangel.com/posts/548</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Datas alteradas no horário de verão</title>
      <description><![CDATA[<style type="text/css">
<!--
.PreProc { color: #aaffff; }
.String { color: #66ff00; }
.Type { color: #aaaa77; }
.Statement { color: #ff6600; }
.Constant { color: #339999; }
.Special { color: #33aa00; }
pre { font-family: monospace; color: #eeeeee; background-color: #000000; }
.lnr { color: #ddeeff; background-color: #222222; }
-->
</style>
<p>
Tive um problema aqui em um procedimento que faz algumas verificações de arquivos nas máquinas dos usuários. Para não dar nada, eram usuários daquele sistema operacional <i>legal</i> que insiste em nos dar algumas surpresinhas malucas de vez em quando. Eu achei estranho, fui dar uma fuçada para ver qual era a razão do problema e encontrei uma situação bem interessante. Vamos levar em conta o seguinte programa simples em C chamado <tt>conf.c</tt>:
</p>





<pre>
<span class="lnr"> 1 </span><span class="PreProc">#include </span><span class="String">&lt;time.h&gt;</span>
<span class="lnr"> 2 </span><span class="PreProc">#include </span><span class="String">&lt;stdio.h&gt;</span>
<span class="lnr"> 3 </span><span class="PreProc">#include </span><span class="String">&lt;stdlib.h&gt;</span>
<span class="lnr"> 4 </span><span class="PreProc">#include </span><span class="String">&lt;sys/stat.h&gt;</span>
<span class="lnr"> 5 </span>
<span class="lnr"> 6 </span><span class="Type">int</span> main(<span class="Type">int</span> argc, <span class="Type">char</span>** argv){
<span class="lnr"> 7 </span>   <span class="Type">struct</span> stat   stDir;
<span class="lnr"> 8 </span>   <span class="Statement">if</span>(argc&lt;<span class="Constant">2</span>)
<span class="lnr"> 9 </span>      exit(<span class="Constant">1</span>);
<span class="lnr">10 </span>
<span class="lnr">11 </span>   printf(<span class="String">&quot;Checando </span><span class="Special">%s</span><span class="Special">\n</span><span class="String">&quot;</span>,argv[<span class="Constant">1</span>]);
<span class="lnr">12 </span>   <span class="Statement">if</span>(stat(argv[<span class="Constant">1</span>],&amp;stDir)&lt;<span class="Constant">0</span>)
<span class="lnr">13 </span>      exit(<span class="Constant">1</span>);
<span class="lnr">14 </span>
<span class="lnr">15 </span>   printf(<span class="String">&quot;</span><span class="Special">%ld</span><span class="String"> </span><span class="Special">%s</span><span class="Special">\n</span><span class="String">&quot;</span>,stDir.st_ctime,ctime(&amp;stDir.st_ctime));
<span class="lnr">16 </span>   <span class="Statement">return</span> <span class="Constant">0</span>;
<span class="lnr">17 </span>}
</pre>

<p>
Esse programa faz uma coisa bem simples: verifica a data e hora da última alteração do status de um arquivo (ou um diretório) usando a função <a href="http://www.opengroup.org/onlinepubs/000095399/functions/stat.html"><tt>stat</tt></a>, que retorna algumas informações na estrutura <a href="http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/stat.h.html"><tt>stat</tt></a>, de onde eu formato a data de criação do arquivo usando a função <a href="http://www.opengroup.org/onlinepubs/000095399/functions/ctime.html"><tt>ctime</tt></a>. Nada de complicado. Rodando esse programa no GNU/Linux duas vezes, <b>alterando a data para uma data dentro do horário de verão</b> entre as chamadas, tenho o seguinte resultado:
</p>

<pre>
[taq@taq~]$ date
Ter Out 14 09:51:30 BRT 2008
[taq@taq~]$ conf .mozilla/
Checando .mozilla/
1205268188 Tue Mar 11 17:43:08 2008

[taq@taq~]$ date
Sáb Out 25 12:00:03 BRST 2008
[taq@taq~]$ conf .mozilla/
Checando .mozilla/
1205268188 Tue Mar 11 17:43:08 2008
</pre>

<p>
Ok, o meu diretório <tt>~/.mozilla</tt> foi criado em 11/03/2008 17:43:08, que foi comprovado em ambas as chamadas. Agora vou fazer a mesma coisa no "outro sistema":
</p>

<pre>
C:\>date
Data atual: ter 14/10/2008
Digite a nova data: (dd-mm-aa)

C:\>conf c:\windows\temp
Checando c:\windows\temp
<span style="color:red">1201084518 Wed Jan 23 08:35:18 2008</span>

C:\>date
Data atual: sáb 25/10/2008
Digite a nova data: (dd-mm-aa)

C:\>conf c:\windows\temp
Checando c:\windows\temp
<span style="color:red">1201088118 Wed Jan 23 09:35:18 2008</span>
</pre>

<p>
Uai! Alterando a data para uma dentro do horário de verão, a data do arquivo retornada muda também? Achei a causa do problema na verificação dos arquivos! O timestamp original do arquivo <b>nunca</b> vai bater com o retornado atualmente. 
</p>

<p>
Qual é a razão disso eu ainda não entendi direito. IMHO o retorno da data do arquivo não deveria ser alterada <b>nunca</b> e o procedimento do GNU/Linux é que está correto, pois independente da situação corrente o arquivo foi criado em uma determinada data e hora, que no segundo caso era 23/01/2008 08:35:18. Fica aí a dica se alguém tiver algum problema do tipo.
</p>

<p>
Outra dica: se alguém precisar usar o <tt>gcc</tt> para o segundo teste, pode utilizar o <a href="http://www.mingw.org">MingW</a>. O programa compila de boa utilizando <tt>gcc -o conf.exe -Wall -D_GNU_SOURCE conf.c</tt>.
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290962474" />
]]></description>
      <pubDate>Tue, 14 Oct 2008 14:04:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290962474&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F547</link>
      <guid>http://eustaquiorangel.com/posts/547</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Fissurados no Vim</title>
      <description><![CDATA[<img src="/charges/20081009-viciovim.jpg" alt="Fissurados no Vim"/>
<p>
Nem preciso dizer que eu sou um desses malucos. Mas não tenho isso aqui em casa não! :-)
</p>
<p>
<b>P.S.</b>: Podia ter colocado só <tt>:x</tt>, mas o <tt>:wq</tt> é mais ... clássico. :-)
</p>
<p>
<b>P.S.2</b>: As requested, here's <a href="/charges/20081009-viciovim-en.jpg">a link to the English version</a>.
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290962475" />
]]></description>
      <pubDate>Fri, 10 Oct 2008 12:13:58 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290962475&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F546</link>
      <guid>http://eustaquiorangel.com/posts/546</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Um jeito high tech de pegar bebuns</title>
      <description><![CDATA[<img src="/charges/20081008-mailgoogles.jpg" alt="Mail Googles"/>
<p>
Vai falar que esse não é um jeito <i>cool</i> de pegar os bebuns, usando o <a href="http://gmailblog.blogspot.com/2008/10/new-in-labs-stop-sending-mail-you-later.html">Mail Googles</a>? Não precisa de <a href="http://www.google.com.br/search?q=bafometro+superfaturado">bafômetros superfaturados</a> e ainda pode entrar na onda do 3G e dos minis.
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290962476" />
]]></description>
      <pubDate>Wed, 08 Oct 2008 20:18:38 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290962476&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F545</link>
      <guid>http://eustaquiorangel.com/posts/545</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>gem install ibm_db</title>
      <description><![CDATA[Antonio Cangiano: The IBM API development team has released version 1.0 of the ibm_db gem, which includes both the Ruby driver, and the Rails adapter, for IBM’s databases.
This was just over three years in the making.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922636" />
]]></description>
      <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922636&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Antonio Cangiano: The IBM API development team has released version 1.0 of the ibm_db gem, which includes both the Ruby driver, and the Rails adapter, for IBM’s databases.
This was just over three years in the making.  Perhaps there is even some of my original code in there — though in reality, that matters not.  In the six months prior to that post, I spent a fair amount of time in meetings with people discussing whether it should be done, could it be done, and how much would it cost.  Addressing all three at once was too hard, so ultimately I decided to implement just enough code and test cases to demonstrate that it could be done, and no more.  This enabled those within IBM who organizationally should be responsible for such a thing to take over — a win, win for all concerned.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2921</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Go Long</title>
      <description><![CDATA[Lauren Wood: The bit I have found most disconcerting in the whole process, which has been going on for months now, is the demonisation of each side’s supporters, the assumption they’re not intelligent/patriotic/… enough. The level of vitriol hurled around is astounding, not only at the candidates themselves, but at their supporters
Now is a time for a bit of optimism; and a time for winning, or losing, gracefully.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=290922638" />
]]></description>
      <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=290922638&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Tim Bray: this generation of Republicans aren’t reasonable people with whom I have disagreements, they’re corrupt lying torturing malevolent buffoons.

Short People got no reason
Short People got no reason
Short People got no reason
To live
Campaign high point and low point.

They got little hands
And little eyes
And they walk around
Tellin' great big lies
They got little noses
And tiny little teeth
They wear platform shoes
On their nasty little feet
Lauren Wood: The bit I have found most disconcerting in the whole process, which has been going on for months now, is the demonisation of each side’s supporters, the assumption they’re not intelligent/patriotic/… enough. The level of vitriol hurled around is astounding, not only at the candidates themselves, but at their supporters

Well, I don’t want no Short People
Don’t want no Short People
Don’t want no Short People
Round here
Apparently Democrats and Republicans agree that we need to privatize profit and socialize risk.  And that Habeas corpus is passé.  On the other hand, they do disagree on whether socialism starts at somewhere around 40% or at 35% marginal tax rates.

Short people are just the same
As you and i
(a fool such as I)
All men are brothers
Until the day they die
(its a wonderful world)
Perhaps somebody should introduce Tim and Lauren.

Short People got nobody
Short People got nobody
Short People got nobody
To love
Optimist view.  Realist view.  Until the conventions, I would have said that either presidential candidate would have done an adequate job, and certainly a better one than any of the three predecessors in that position.  Since then, the last two months have shown a clear difference between the two candidates.

They got little baby legs
That stand so low
You got to pick em up
Just to say hello
They got little cars
That go beep, beep, beep
They got little voices
Goin peep, peep, peep
They got grubby little fingers
And dirty little minds
Theyre gonna get you every time
Well, I dont want no short people
Dont want no short people
Dont want no short people
round here

— Randy Newman
Now is a time for a bit of optimism; and a time for winning, or losing, gracefully.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2919</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
  </channel>
</rss>
