<?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>Mon, 05 Jan 2009 22:47:40 GMT</pubDate>
    <lastBuildDate>Tue, 30 Nov 1999 00:00:00 GMT</lastBuildDate>
    <category>rss feed planet collection</category>
    <item>
      <title>Where's Joe?</title>
      <description/>
      <pubDate>Mon, 05 Jan 2009 20:10:33 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309904780&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[I'm writing, not in seeking pity (well, a little pity wouldn't hurt), but as 
    an explaination of why you may not have gotten a response from me for the past few months, or why
    if you did get a response it may have been weeks or even months in coming. 
    
It all started three months ago when Lynne started having some health problems, which became a 
    cancer scare, which it turns out she didn't have, but still ended up in her having two surgeries.
    In preparation for the first surgery she had an EKG and discovered she has an irregular
    heartbeat. Apparently the severity of an "irregular heartbeat" falls into one of two categories: 'really bad' or 'nothing much',
    and that can only be determined by a stress test, which she got done, but sitting around for a couple 
    days wondering whether we were piling a heart condition on top of potential cancer was a bit stressful.
    Turns out that, like me, Lynne had an irregular EKG that falls into the 'nothing much' column.
    Lynne had her surgeries and both were successful, but surgery is surgery and it takes
    a while to recover. Also, between them  
    I had my own pre-scheduled surgery and you heard how well that went. Oh, and during all of this 
    we we're having problems with Reilly's elementary school teacher which finally culminated in us pulling 
    him out to be home schooled.
    

    After all that stress it was with great anticipation that we looked forward to our
    cruise the first week of December, and why it was with great distress that we found ourselves
    in the emergency room with Austin on Thanksgiving. He had come down with Influenza and 
    gotten dehydrated, but an IV, tylenol, montrin, and a prescription for Tamiflu
    and he was doing much better and we were cleared by the doctor to go on our vacation.
    

    When we finally got on the boat four days later Austin spiked a fever which we thought
    was the influenza, but it turns out he had pneumonia, which we didn't find out until 
    we got back from cruise. While we were on the boat Christopher got food poisoning so we
    went to the ships doctor and the doctor promptly quarantined the family to our cabin
    for 36 hours, as a precaution in case it was Norovirus, but it wasn't, and the symptoms
    didn't match, but that didn't stop them from quarantining the whole family. 
    When we got back home we took Austin back to the doctor and found that he had pneumonia, but not before he passed it on to Lynne.
    That landed Lynne in the emergency room when the first antibiotic they gave her
    didn't work on the pneumonia. Luckily the second one did and that helped to know which one 
    worked when Christopher came down with pneumonia a few days later.
    The cruise, instead of being a relaxing break the previous three months of
    stress, was one of the most stressful things I've ever been through.
    

    Oh yeah, no rest after we get back from 'vacation' either, we landed back in North Carolina
    on Sunday afternoon and I had to get up a 3:30am for a business trip to NYC the next day.
    
So, about those emails, bugs, action items, and lunch plans: I am behind, I am catching up,
     and thank you for your patience. Here's to hoping for a less eventful, or at least healthier, new year ahead!<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309904780" />
]]></content:encoded>
      <guid>http://bitworking.org/news/391/wheres-joe</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Text Editor Saving Routines</title>
      <description/>
      <pubDate>Mon, 05 Jan 2009 19:18:40 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309904781&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[I have, for reasons that will become obvious in a week or so, been looking at
    text editors and what happens when you save a file. For example, if we are editing the file
    filename.txt, different things will happen when you
    save the file depending on which editor you are using.
    VIM is fairly straight forward in that it renames the original file
    to filename.txt~, writes the modified
    contents to filename.txt, and then if that is successful
    deletes filename.txt~. 
    
Emacs does roughly the same thing as VIM, but by default doesn't clean up the filename.txt~ file.
    
Eclipse is by far the simplest, truncating filename.txt 
    to a length of 0 and then writing the new contents.
    
Gedit is by far the most byzantine, first it writes the contents of the modified buffer 
    to a hidden file .gedit-save-NNNN, then it renames the original file
    to filename.txt~, then renames .gedit-save-NNN to filename.txt
    and finally deletes filename.txt~.
    What makes Gedit really stand out from other text editors is that
    if for some reason the filesystem doesn't support 'rename' then Gedit refuses
    to save the file, as opposed to VIM and Emacs which will just write new
    contents to filename.txt. As you can imagine that's controversial
    behavior and there's 
    a long and painful bug thread on it, which is filled with all the painful things 
    you'd expect it to be filled with, like claiming it's not a bug, or that
    the bug is in some other piece of software, or that it's not a problem
    under 'normal' usage, or that any other way of saving files is unsafe.
    Like I said, painful.
    

    But I'm willing to believe there are even more complex cases, and if you know of an editor 
    that has an even more convoluted save routine I'd be glad to hear about it.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309904781" />
]]></content:encoded>
      <guid>http://bitworking.org/news/390/text-editor-saving-routines</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Building Firefox with HTML5 parser support</title>
      <description><![CDATA[Instructions on downloading, building, and executing HTML5 Parsing in Gecko: A Build from source, on Ubuntu.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855861" />
]]></description>
      <pubDate>Mon, 05 Jan 2009 16:40:15 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855861&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Start by installing some build prerequisites.  The following are for Ubuntu, adjust as necessary:
sudo apt-get build-dep firefox
sudo apt-get install mercurial libasound2-dev libcurl4-openssl-dev
Now check out the source to an HTML5 enabled Firefox:
mkdir -p ~/hg/
cd ~/hg/
hg clone http://hg.mozilla.org/users/mrbkap_mozilla.com/html5parsing/
The next step requires requires Python, Subversion and JDK 5 or later (JDK 6 and Hardy’s OpenJDK work).
mkdir -p ~/svn/
cd ~/svn/
mkdir checker
cd checker
svn co http://svn.versiondude.net/whattf/build/trunk/ build
python build/build.py checkout dldeps
if you get a timeout from SourceForge, simply try again.  At the present time Google code’s hosting of jing-trang is currently down.  For our purposes, that library is not necessary.  Press on.
You are not done yet.
mkdir tmp
wget http://javaparser.googlecode.com/files/javaparser_2008-06-19.zip -O tmp/javaparser_2008-06-19.zip
unzip tmp/javaparser_2008-06-19.zip -d dependencies/ javaparser_2008-06-19.jar
On to generating the cpp sources from java...
cd htmlparser/translator-src/
javac nu/validator/htmlparser/generator/GenerateNamedCharactersCpp.java
java nu.validator.htmlparser.generator.GenerateNamedCharactersCpp ../doc/named-character-references.html ~/hg/html5parsing/content/html/parser/src/ 
javac -classpath .:../../dependencies/javaparser_2008-06-19.jar nu/validator/htmlparser/cpptranslate/Main.java
java -classpath .:../../dependencies/javaparser_2008-06-19.jar nu.validator.htmlparser.cpptranslate.Main ../src/nu/validator/htmlparser/impl/ ~/hg/html5parsing/content/html/parser/src/ ~/hg/html5parsing/content/html/parser/src/nsHtml5AtomList.h ~/hg/html5parsing/content/html/parser/src/nsHtml5StringLiterals.cpp
Create a mozilla build configuration file in ~/.mozconfig.  Here’s mine:
. $topsrcdir/browser/config/mozconfig
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/ff-opt
# ac_add_options --enable-static --disable-libxul
ac_add_options --disable-tests
ac_add_options --disable-crashreporter
Note the commented out options are documented but don’t work.  Now build firefox.
cd ~/hg/html5parsing
make -f client.mk build
Before running, make sure you reset your expectations.  I ran it with my default profile, but I have plenty of backups.  Caveat emptor.
If you still insist on executing the results, you must first exit all Firefox windows.  Only then can you launch your executable with the following:
ff-opt/dist/bin/firefox]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2939</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>iCalendar Validator?</title>
      <description><![CDATA[Jon Udell: If we recapitulate the RSS/Atom experience with ICS, and lots more ad-hoc ICS feeds arrive on the scene, charts like this will go even redder.  To make them go green, we’ll need a more robust ICS validator.
Jon has done an excellent first step: demonstrating that there is a problem.
The next step is harder.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855862" />
]]></description>
      <pubDate>Sat, 03 Jan 2009 17:34:03 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855862&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Jon Udell: If we recapitulate the RSS/Atom experience with ICS, and lots more ad-hoc ICS feeds arrive on the scene, charts like this will go even redder.  To make them go green, we’ll need a more robust ICS validator.
Jon has done an excellent first step: demonstrating that there is a problem.
The next step is harder, and for the feed validator was borne mostly by Mark.  For each of the red entries on that page, somebody needs to identify what should be tested for, and for each test identify a short message, an explanation, and a solution.  Identifying real issues that prevent real feeds from being consumed by real consumers and describing the issue in terms that makes sense to the producer is what most would call value.
Once this is done, the coding is straightforward.  I’d be willing to volunteer to take on a large chunk of this.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2938</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Dando uma garibada no .irbrc</title>
      <description><![CDATA[<style type="text/css">
<!--
.Statement { color: #ff6600; }
.rubyMethod { color: #dde93d; }
.String { color: #66ff00; }
.Comment { color: #9933cc; font-style: italic; }
.Type { color: #aaaa77; }
.Constant { color: #339999; }
.Special { color: #33aa00; }
.Identifier { color: #ffcc00; }
pre { font-family: monospace; color: #eeeeee; background-color: #000000; }
-->
</style>
<p>
Começo de ano, hora de organizar algumas coisas. Uma delas era o meu <tt>.irbrc</tt> que andava meio diferente em algumas máquina e já estava virando bagunça. Fora que eu sempre preciso atualizar o bicho no computador do <a href="http://www.objecttraining.com.br/object_training/curso_de_ruby">curso de Ruby na Object Training</a> (falando nisso, as turmas desse ano começam daqui a duas semanas!) pois volta e meia instalaram uma distro nova lá.
</p>
<p>
Pois bem, segue o código do meu <tt>.irbrc</tt> abaixo. Alguns podem mencionar alguns projetos muito legais e úteis como o <a href="http://utilitybelt.rubyforge.org/">UtilityBelt</a>, que faz tudo isso e muito mais, mas quem me conhece sabe que eu sou meio cabeçudo e "fução" e acabo fazendo as coisas, se possível, de um jeito enxuto que atende o que eu preciso.
Inclusive, eu escolhi desabilitar os recursos de salvar o histórico e do <i>autocomplete</i> no <a href="http://pablotron.org/software/wirble/">Wirble</a> para ativá-los "na unha" pois alguns ambientes podem não ter o Wirble ou nem o Rubygems instalados. Assim não fico sem esses dois recursos.
</p>
<p>
Divirtam-se!
</p>
<style type="text/css">
<!--
.lnr { color: #ddeeff; background-color: #222222; }
-->
</style>

<pre>
<span class="lnr"> 1 </span><span class="rubyMethod">require</span> <span class="String">&quot;</span><span class="String">irb/completion</span><span class="String">&quot;</span>         <span class="Comment"># activate default completion</span>
<span class="lnr"> 2 </span><span class="rubyMethod">require</span> <span class="String">'</span><span class="String">irb/ext/save-history</span><span class="String">'</span>   <span class="Comment"># activate default history </span>
<span class="lnr"> 3 </span><span class="rubyMethod">require</span> <span class="String">&quot;</span><span class="String">tempfile</span><span class="String">&quot;</span>               <span class="Comment"># used for Vim integration  </span>
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span><span class="Comment"># save history using built-in options</span>
<span class="lnr"> 6 </span><span class="Type">IRB</span>.conf[<span class="Constant">:SAVE_HISTORY</span>] = <span class="Constant">1000</span>
<span class="lnr"> 7 </span><span class="Type">IRB</span>.conf[<span class="Constant">:HISTORY_FILE</span>] = <span class="String">&quot;</span><span class="Special">#{</span><span class="Identifier">ENV</span>[<span class="String">'</span><span class="String">HOME</span><span class="String">'</span>]<span class="Special">}</span><span class="String">/.irb-save-history</span><span class="String">&quot;</span>
<span class="lnr"> 8 </span>puts <span class="String">&quot;</span><span class="String">History configured.</span><span class="String">&quot;</span>
<span class="lnr"> 9 </span>
<span class="lnr">10 </span><span class="Comment"># auto-indent</span>
<span class="lnr">11 </span><span class="Type">IRB</span>.conf[<span class="Constant">:AUTO_INDENT</span>]=<span class="Constant">true</span>
<span class="lnr">12 </span>puts <span class="String">&quot;</span><span class="String">Auto-indent on.</span><span class="String">&quot;</span>
<span class="lnr">13 </span>
<span class="lnr">14 </span><span class="Comment"># try to load rubygems</span>
<span class="lnr">15 </span><span class="Statement">begin</span>
<span class="lnr">16 </span>   <span class="rubyMethod">require</span> <span class="String">&quot;</span><span class="String">rubygems</span><span class="String">&quot;</span>
<span class="lnr">17 </span>   puts <span class="String">&quot;</span><span class="String">Rubygems loaded.</span><span class="String">&quot;</span>
<span class="lnr">18 </span><span class="Statement">rescue</span> <span class="Type">LoadError</span> =&gt; e
<span class="lnr">19 </span>   puts <span class="String">&quot;</span><span class="String">Seems you don't have Rubygems installed: </span><span class="Special">#{</span>e<span class="Special">}</span><span class="String">&quot;</span>
<span class="lnr">20 </span><span class="Statement">end</span>
<span class="lnr">21 </span>
<span class="lnr">22 </span><span class="Comment"># let there be colors</span>
<span class="lnr">23 </span><span class="Comment"># just use Wirble for colors, since some enviroments dont have</span>
<span class="lnr">24 </span><span class="Comment"># rubygems and wirble installed</span>
<span class="lnr">25 </span><span class="Statement">begin</span>
<span class="lnr">26 </span>   <span class="rubyMethod">require</span> <span class="String">&quot;</span><span class="String">wirble</span><span class="String">&quot;</span>
<span class="lnr">27 </span>   <span class="Type">Wirble</span>.init(<span class="Constant">:skip_prompt=</span>&gt;<span class="Constant">true</span>,<span class="Constant">:skip_history=</span>&gt;<span class="Constant">true</span>)
<span class="lnr">28 </span>   <span class="Type">Wirble</span>.colorize
<span class="lnr">29 </span>   puts <span class="String">&quot;</span><span class="String">Wirble loaded. Now you have colors.</span><span class="String">&quot;</span>
<span class="lnr">30 </span><span class="Statement">rescue</span> <span class="Type">LoadError</span> =&gt; e
<span class="lnr">31 </span>   puts <span class="String">&quot;</span><span class="String">Seems you don't have Wirble installed: </span><span class="Special">#{</span>e<span class="Special">}</span><span class="String">&quot;</span>
<span class="lnr">32 </span><span class="Statement">end</span>
<span class="lnr">33 </span>
<span class="lnr">34 </span><span class="Comment"># configure vim</span>
<span class="lnr">35 </span><span class="Identifier">@irb_temp_code</span> = <span class="Constant">nil</span>
<span class="lnr">36 </span>
<span class="lnr">37 </span><span class="Statement">def</span> <span class="Identifier">vim</span>(file=<span class="Constant">nil</span>)
<span class="lnr">38 </span>   file = file || <span class="Identifier">@irb_temp_code</span> || <span class="Type">Tempfile</span>.new(<span class="String">&quot;</span><span class="String">irb_tempfile</span><span class="String">&quot;</span>).path+<span class="String">&quot;</span><span class="String">.rb</span><span class="String">&quot;</span>
<span class="lnr">39 </span>   system(<span class="String">&quot;</span><span class="String">vim </span><span class="Special">#{</span>file<span class="Special">}</span><span class="String">&quot;</span>)
<span class="lnr">40 </span>   <span class="Statement">if</span>(<span class="Type">File</span>.exists?(file) &amp;&amp; <span class="Type">File</span>.size(file)&gt;<span class="Constant">0</span>)
<span class="lnr">41 </span>      <span class="Type">Object</span>.class_eval(<span class="Type">File</span>.read(file))
<span class="lnr">42 </span>      <span class="Identifier">@irb_temp_code</span> = file
<span class="lnr">43 </span>      <span class="String">&quot;</span><span class="String">File loaded from Vim.</span><span class="String">&quot;</span>
<span class="lnr">44 </span>   <span class="Statement">else</span>
<span class="lnr">45 </span>      <span class="String">&quot;</span><span class="String">No file loaded.</span><span class="String">&quot;</span>
<span class="lnr">46 </span>   <span class="Statement">end</span>
<span class="lnr">47 </span><span class="Statement">rescue</span> =&gt; e
<span class="lnr">48 </span>   puts <span class="String">&quot;</span><span class="String">Error on vim: </span><span class="Special">#{</span>e<span class="Special">}</span><span class="String">&quot;</span>
<span class="lnr">49 </span><span class="Statement">end</span>
<span class="lnr">50 </span>puts <span class="String">&quot;</span><span class="String">Vim available.</span><span class="String">&quot;</span>
</pre><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=308835990" />
]]></description>
      <pubDate>Sat, 03 Jan 2009 11:26:12 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=308835990&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F552</link>
      <guid>http://eustaquiorangel.com/posts/552</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>The Algebraist</title>
      <description/>
      <pubDate>Thu, 01 Jan 2009 15:49:03 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309904782&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[The Algebraist by Iain M. Banks
My review
  rating: 4 of 5 starsThis was a really wide ranging book filled with lots of interesting ideas and musings, some on what a species that evolved in a gas giant would look and act like, how an interstellar civilization would operate, etc. The downside was that most of the aliens weren't very alien, you'd see larger differences between different groups of humans than what you saw between the differing alien races. A mix of anthropology, politics and old fashioned science fiction it was well paced and worth the time.
  View all my reviews.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309904782" />
]]></content:encoded>
      <guid>http://bitworking.org/news/389/the-algebraist</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Feliz 2009!</title>
      <description><![CDATA[<p>
Como vocês puderam notar, 2008 foi um ano meio parado aqui no blog. No lado pessoal, foi talvez o pior ano da minha vida (e olhem que já estou perto dos 40), o que atrapalhou o lado profissional, que apesar de ter sido bom, poderia ter sido melhor sem tudo o que foi acontecendo durante o ano. Isso não me deu muita inspiração ou ânimo para escrever aqui e desenvolver algumas coisas que gostaria, inclusive houve um bom período que nem lembrei dessas coisas!
</p>
<p>
Antes que alguém possa ficar mais preocupado, está tudo bem com a turminha aqui de casa, mas algumas pessoas bem próximas se foram e levamos vários outros sustos bem intensos. A vida me deu umas boas bofetadas na cara que com certeza me deixaram perdido sem entender o que estava acontecendo. 
</p>
<p>
Mas isso foi em 2008. Sabemos que quem cria o controle do tempo nas unidades estabelecidas somos nós e não há alguma coisa tipo uma "página virada" imperando cosmicamente ou algo parecido, mas esse ano mais do que nunca eu estou desejando ver a marca dessa página virada nitidamente, e mais do que nunca, saúdo o Ano Novo como um desejo de esperança em dias melhores para todos. Que esse ano cicatrize qualquer ferida que foi aberta, dê um sopro de ar fresco e traga luz onde antes estava abafado e escuro e muita saúde e paz para todos!
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=308835991" />
]]></description>
      <pubDate>Thu, 01 Jan 2009 15:36:31 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=308835991&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F551</link>
      <guid>http://eustaquiorangel.com/posts/551</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Thanks for Volunteering!</title>
      <description><![CDATA[Larry Masinter: “When the C++ committee (ISO/IEC JTC1/SC22/WG21) produces a document, are they producing a Technical Specification of the language, or an Applicability Statement on compiler implementation?”
I don’t yet fully know what I can accomplish as co-chair of the HTML working group, but I do intend to approach every raised issue with a disarmingly simple question: Is this something you intend to work on?<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855863" />
]]></description>
      <pubDate>Wed, 31 Dec 2008 10:27:32 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855863&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Larry Masinter: When the C++ committee (ISO/IEC JTC1/SC22/WG21) produces a document, are they producing a Technical Specification of the language, or an Applicability Statement on compiler implementation?
The context for the above statement is an argument by Ian Hickson that "Technical Specifications", as you are describing them, are worthless.
James Britt:  The consolidation removes this useful competition. This is maybe a plus for folks who prefer Rails, and a gain for people who want to do things the Merb way but can now say they are using Rails. Less useful to people who want to see more distinct options.
The context for the above statement is the fact that Yehuda Katz (of Merb fame) is joining the Rails Core team.
What do Yehuda and Ian have in common in this case?  They are both working on causes they believe in.
Dan Connolly: I also suggest we demote many/most of our OPEN issues to RAISED, and discourage discussion of issues that aren’t OPEN.
The context for the above statement is an Open Issues list where to this day the majority of open items have no actions associated with them, and for those that do have actions, many of the actions are either overdue now, or soon to be so.  If you listen carefully, you might even be able to make out the Whooshing Sounds.
I don’t yet fully know what I can accomplish as co-chair of the HTML working group, but I do intend to approach every raised issue with a disarmingly simple question: Is this something you intend to work on?]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2937</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>AWDwR3 Beta 7</title>
      <description><![CDATA[Beta 1.7 of Agile Web Development with Rails, Third Edition is out.
A few highlights of this edition (as compared to the second edition) are as follows: installation completely updated, static scaffolding (don’t laugh, this completely broke the previous edition’s approach to the Depot application), a balanced focus on REST and non-REST interfaces, atom_feed helper, Internationalization, timestamped migrations, ActiveResource, and Passenger.  And a bazillion or so smaller changes.  A few things left for the next edition: JQuery, Metal, Merb, and Ruby 1.9.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855864" />
]]></description>
      <pubDate>Fri, 26 Dec 2008 20:32:53 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855864&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Beta 1.7 of Agile Web Development with Rails, Third Edition is out; I just completed the most exhausting and time consuming portion of this task: attempting to examine literally every single page of rdoc trying to determine what should be documented and what need not be, and to compare that against what has been documented vs what has not.  This is not as obvious as it sounds, as with all human endeavors there is a mix of pages which are autogenerated which only describe internal details, and other features which are highly dynamic which do not show up on rdoc pages at all.
I was originally intending to do this exercise based on Rails 2.1, but as there was a general feeling that Rails 2.2 was just around the corner, I waited a bit.  It was released last month, and now that I’ve updated the book based on what was included, Rails 2.3 is again “just around the corner”.
Sigh.
Given that Merb is getting merged into Rails 3, it looks like being an author of a Rails book is a full employment proposition.  If kept on top of, it shouldn’t be an issue.  If left untouched for a year or more, updating it will likely be another herculean task.  In all, I must say that this is the hardest I’ve worked on anything for at least a decade, if not in my entire career, so given a choice I’d rather keep on top of it.  In fact, my publisher and I are exploring whether a subscription model makes sense for this book.
In any case, back to now and back to this edition, what should be left is only errors and inadvertent omissions.  Whether such issues are numerous or rare, such issues should be quick to address.
A few highlights of this edition (as compared to the second edition) are as follows: installation completely updated, static scaffolding (don’t laugh, this completely broke the previous edition’s approach to the Depot application), a balanced focus on REST and non-REST interfaces, atom_feed helper, Internationalization, timestamped migrations, ActiveResource, and Passenger.  And a bazillion or so smaller changes.  A few things left for the next edition: JQuery, Metal, Merb, and Ruby 1.9.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2936</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Rack'em Up!</title>
      <description/>
      <pubDate>Wed, 17 Dec 2008 17:10:51 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855865&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Rack is Ruby’s answer to Python’s WSGI.
A year and half later, Rails replaced the guts of script/server with a call out to Rack.
Days later, Phusion Passenger™ essentially became mod_rack, though you can still call it mod_rails if you like.
Yesterday, a new micro-framework named Metal has been introduced which allows one to intercept requests, whether it be for performance reasons or simply to call out to another framework.  Sinatra has already been demonstrated, Merb can’t be far behind.
I love it when a plan comes together<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855865" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2935</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Arrogância, hubris e simples orgulho</title>
      <description><![CDATA[Uma &#8220;modinha&#8221; entre desenvolvedores Rails atualmente é transformar arrogância em uma virtude a ser cultivada. É fácil entender a razão. A briga pelo campo de linguagens dinâmicas, a necessidade de se provar viável e sustentável deixou suas marcas. O problema é entender o tipo de arrogância necessária, algo que passa batido não só no campo [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=301893501" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/12/16/arrogancia-hubris-e-simples-orgulho/#comments</comments>
      <pubDate>Wed, 17 Dec 2008 01:56:45 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=301893501&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F12%2F16%2Farrogancia-hubris-e-simples-orgulho%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Uma &#8220;modinha&#8221; entre desenvolvedores Rails atualmente é transformar arrogância em uma virtude a ser cultivada. É fácil entender a razão. A briga pelo campo de linguagens dinâmicas, a necessidade de se provar viável e sustentável deixou suas marcas. O problema é entender o tipo de arrogância necessária, algo que passa batido não só no campo Rails como em essencialmente todas outras auto-denominadas comunidades.</p>

<p>Larry Wall, criador do Perl, <a href="http://en.wikipedia.org/wiki/Larry_Wall#Virtues_of_a_programmer">dizia</a> com razão que <span class="foreign-word" lang="gr">hubris</span>, ao lado de preguiça e impaciência, são virtudes de todos bons programadores. <span class="foreign-word" lang="gr"><a href="http://en.wikipedia.org/wiki/Hubris">Hubris</a></span> é um termo originalmente grego que denotava orgulho excessivo, uma auto-confiança que desafiava os deuses, e que, muitas vezes, terminava com resultados trágicos para o indivíduo que exibia o comportamento&#8211;como Prometeu, por exemplo.</p>

<p>Wall transformou essa idéia negativa na positiva do zelo que um programador deve ter ao criar programas limpos e claros que causam orgulho e que levam outros programadores a perceberem as qualidades do código. Um virtude, nesse sentido, interessante.</p>

<p>Arrogância pode ser uma arma. Voltando ao Rails, <a href="http://twitter.com/d2h">David Heinemeier Hansson</a> a utilizou com eficiência para criticar problemas válidos no campo da computação&#8211;alguns dos quais estavam impedindo o desenvolvimento e adoção de novos conceitos que hoje são bem mais comuns do que quando o Rails foi lançado.</p>

<p>Como em vários comunidades, muita gente começou a emular esse comportamento como se o mesmo fosse uma justificação própria. O que, ironicamente, leva a um círculo completo terminando no mesmo ponto em que os detratores do Rails estavam originalmente. Nada mais comum hoje ver um desenvolvedor Rails defendendo seu amado <span class="foreign-word" lang="en">framework</span> com unhas e dentes como se o mesmo fosse a única opção válida. Java &amp; .NET <span class="foreign-word" lang="en">anyone</span>?</p>

<p>Não há coisa pior do que o tipo de arrogância que se acha sempre correta. A <span class="foreign-word" lang="gr">hubris</span> sabe dizer &#8220;não sei, mas vou remediar isso&#8221;&#8211;seja aprendendo algo novo ou admitindo que outra pessoa pode ajudar. O resto é simples, e completamente banal, meninice.</p>

<p>Bons programadores exibem o tipo de atitude que Larry Wall definiu. Arrogância, pura e simples, leva a alguém que não aprende, que vai se defasando pouco a pouco até que tenha que partir para a tecnologia <span class="foreign-word" lang="fr">do jour</span> mais uma vez para se manter relevantes.</p>

<p>Confesso que me cansei dessa primeira variedade de arrogantes. São esses os que não aprendem a lição de Santayana e daqui a vinte anos estarão no mesmo ponto em que estão hoje. <span class="foreign-word" lang="la">Pater, dimitte illis, non enim sciunt quid faciunt.</span></p>]]></content:encoded>
      <category>Comportamento</category>
      <guid>http://logbr.reflectivesurface.com/2008/12/16/arrogancia-hubris-e-simples-orgulho/</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>Convergência, redes sociais, realidade aumentada e gaming spaces</title>
      <description><![CDATA[Eu sempre acreditei que a convergência tecnológica não se daria na Web e sim no celular. Quanto mais o tempo passa, mais estou certo disso. Quanto mais cedo as empresas se convencerem disso&#8211;e pode ter certeza de que a Apple está olhando dez anos à frente nisso, ergo o iPhone&#8211;mais elas estarão próximas de seus [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=301893502" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/12/16/convergencia-redes-sociais-realidade-aumentada-e-gaming-spaces/#comments</comments>
      <pubDate>Tue, 16 Dec 2008 13:12:07 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=301893502&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F12%2F16%2Fconvergencia-redes-sociais-realidade-aumentada-e-gaming-spaces%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Eu sempre acreditei que <a href="http://logbr.reflectivesurface.com/2007/05/12/soa-convergencia-e-o-fim-dos-power-users/">a convergência tecnológica</a> não se daria na Web e sim no celular. Quanto mais o tempo passa, mais estou certo disso. Quanto mais cedo as empresas se convencerem disso&#8211;e pode ter certeza de que a Apple está olhando dez anos à frente nisso, ergo o iPhone&#8211;mais elas estarão próximas de seus usuários.</p>

<p>Das minhas últimas leituras sobre redes sociais, um assunto que meio que passa desapercebido da literatura é a convergência que está sendo realizada em torno de <span class="foreign-word" lang="en">gaming spaces</span>.</p>

<p>No Brasil&#8211;e mesmo nos Estados Unidos e Europa&#8211;a falta de jogos de realidade consensual mais ativos como uma atividade regular mascara isso mas basta olhar para a Ásia e ver que mais uma vez estamos atrasados no assunto. No Japão, jogos envolvendo geo-localização e realidade aumentada são um dos setores mais ativos da indústria móvel. Na China, a moeda virtual do <a href="http://qq.com/">QQ</a>, a maior plataforma móvel local, é tão forte que não só é aceita em lojas comuns como incomodou o governo ao ponto de regulamentação ser necessárias.</p>

<p>Declarar que o ser humano é social é óbvio. Perceber a interseção disso com o espaço de jogos em que existimos não é tão fácil. Nossas carreiras são literalmente arquiteturadas ao redor de jogos que possuem implicações reais e imediatas. Transpor isso para um World of Warcraft é só uma maneira secundária de visualizar a questão&#8211;igualmente válida e igualmente importante.</p>

<p>É claro, existe uma grande dependência em torno de grandes transformações necessárias para uma materialização de alguns cenários. Primeiro, sem <span class="foreign-word" lang="en">feedback</span> háptico é mais difícil transpor a barreira para a parte aumentada da realidade&#8211;e um tanto ou quanto menos satisfatório. Segundo, um ambiente seguro, criptografado e distribuído por padrão é necessário. Terceiro, alguns jardins fechados precisam ser abertos pelos menos parcialmente.</p>

<p>Os dois primeiros pontos acima podem ser resolvidos com mais alguns anos de avanço tecnológico. O último vai depender de um tipo de reengenharia humana em escala global que pode demorar mais tempo para acontecer. Já começou mas pode tomar décadas ainda no pior caso.</p>

<p>De qualquer forma, o ponto inicial permanece: convergência móvel é um fato agora e vão sair na frente as empresas que aproveitarem isso.</p>]]></content:encoded>
      <category>Tecnologia</category>
      <guid>http://logbr.reflectivesurface.com/?p=1189</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>Co-Chair HTML WG</title>
      <description><![CDATA[Michael(tm) Smith: effective January 5, there will be a change in the leadership for the HTML Working Group. Sam Ruby has been appointed as a new co-chair by the W3C Director, Tim Berners-Lee, and will be joining Chris Wilson in that role next month; at that time, I’ll be returning to my previous role as the W3C staff contact for the group.
While my primary focus will be inward, let me first get something out of the way: I personally would like to see the XHTML2 and HTML groups brought together or at least the overlaps removed.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855866" />
]]></description>
      <pubDate>Mon, 15 Dec 2008 13:30:45 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855866&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Michael(tm) Smith: effective January 5, there will be a change in the leadership for the HTML Working Group. Sam Ruby has been appointed as a new co-chair by the W3C Director, Tim Berners-Lee, and will be joining Chris Wilson in that role next month; at that time, I’ll be returning to my previous role as the W3C staff contact for the group.
While my primary focus will be inward, let me first get something out of the way: I’ve talked to Steve Holbrook (IBM’s AC representative) and Roland Merrick (XHTML2 co-chair) and each of us personally would like to see the XHTML2 and HTML groups brought together or at least the overlaps removed.
I’m not overly concerned about events, access keys, or even an additional forms model.  If these efforts seek to address different requirements, they can attract their own constituencies.  Or not.  In any case, the web is a big place.
No, my concern is the active development of two incompatible vocabularies being served with the same media type and being defined in the same XML namespace.  A difference in DOCTYPE does not address my concern.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2934</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Exterminaram Terminator</title>
      <description><![CDATA[Eu confesso que realmente tinha gostado do começo de  Terminator: The Sarah Connor Chronicles. A segunda temporada, entretanto, até onde vi agora, está falhando miseravelmente. A minha previsão de que a parte de viagens no tempo se tornaria mais problemática se concretizou e os roteiristas não sabem mais onde enfiar tantos novos exterminadores.

Viagem do [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=301893503" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/12/15/exterminaram-terminator/#comments</comments>
      <pubDate>Mon, 15 Dec 2008 13:00:49 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=301893503&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F12%2F15%2Fexterminaram-terminator%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Eu confesso que realmente <a href="http://logbr.reflectivesurface.com/2008/04/24/terminator-the-sarah-connor-chronicles/">tinha gostado</a> do começo de  <a href="http://en.wikipedia.org/wiki/Terminator:_The_Sarah_Connor_Chronicles">Terminator: The Sarah Connor Chronicles</a>. A segunda temporada, entretanto, até onde vi agora, está falhando miseravelmente. A minha previsão de que a parte de viagens no tempo se tornaria mais problemática se concretizou e os roteiristas não sabem mais onde enfiar tantos novos exterminadores.</p>

<p>Viagem do tempo é sempre algo difícil de fazer. Com exceção de uns poucos filmes como <a href="http://us.imdb.com/title/tt0088763/">De Volta para o Futuro</a> e <a href="http://us.imdb.com/title/tt0114746/">Os 12 Macacos</a>, é mais fácil falhar do que contar uma estória coerente. A questão é que chega uma hora que a coisa toda se converte em uma enorme seqüência de <span class="foreign-word" lang="en">deus ex machina</span>s que torna tudo inteiramente despropositado.</p>

<p>No caso das crônicas, a Skynet envia exterminadores para o passado que seria mais fácil mover a guerra para os dias atuais e dominar tudo antes de que a coisa começasse. A estratégia de mandar um exterminador após o outro é insultante para inteligência dos fãs. Aliás, a coisa toda poderia se resolvida pela Skynet de uma vez por todas se removendo para o futuro e mandando ordens do futuro profundo. Avançar o suficiente no cone histórico para ser quase impossível desalojá-la sem acabar com o resto.</p>

<p>Enfim, a série parece estar fazendo um sucesso moderado e deve continuar por mais um tempo. Mas o futuro é o mesmo do Smallville que divergiu tanto do cronologia oficial que só pode ser considerada uma linha alternativa. É bom, mas é ruim ao mesmo tempo. Eu preferia ver algo mais coerente com o original.</p>]]></content:encoded>
      <category>Filmes e Séries</category>
      <guid>http://logbr.reflectivesurface.com/?p=1184</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>Agile para sua diversão e lucro</title>
      <description><![CDATA[Meu irmão, como já citei outras vezes aqui, tem uma pequena operação em Belo Horizonte prestando serviços em software livre para empresas no Brasil e nos Estados Unidos. Atualmente, a maior parte do trabalho é em Rails e estamos sempre conversando sobre como melhorar e aumentar a eficiência do que ele e o pessoal que [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=301893504" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/12/12/agile-para-sua-diversao-e-lucro/#comments</comments>
      <pubDate>Fri, 12 Dec 2008 15:43:31 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=301893504&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F12%2F12%2Fagile-para-sua-diversao-e-lucro%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Meu irmão, como já citei outras vezes aqui, tem uma <a href="http://bitbucket.com.br/">pequena operação em Belo Horizonte</a> prestando serviços em <span class="foreign-word" lang="en">software</span> livre para empresas no Brasil e nos Estados Unidos. Atualmente, a maior parte do trabalho é em Rails e estamos sempre conversando sobre como melhorar e aumentar a eficiência do que ele e o pessoal que trabalha lá estão fazendo.</p>

<p>Recentemente ele me visitou na <a href="http://www.webcointernet.com/">WebCo</a> e ficou bem curioso ao ver as dezenas de <span class="foreign-word" lang="en">post-its</span> colados nas várias janelas representando os diversos projetos da empresa. Expliquei um pouco de Agile&#8211;usávamos várias técnicas agéis quando eu ainda estava na empresa&#8211;mas Scrum era uma coisa que eu ainda não tinha comentado com ele.</p>

<p>Depois que ele voltou para Belo Horizonte, ele me ligou pedindo que eu explicasse um pouco mais sobre os tais dos <span class="foreign-word" lang="en">sprints</span>. Explique mais um pouco e sugeri que ele experimentasse mesmo com a equipe pequena.</p>

<p>Mais algum tempo passou e em mais uma de nossas conversas ele me explicou com tinha adaptado o que eu estava falando para a realidade de sua empresa:</p>

<p>Com R$126 ele comprou um quadro, alfinetes, post-its coloridos, canetas e marcou as tarefas de vários projetos com cores diferentes para identificar os mesmos. Mesmo tarefas administrativas da empresa foram colorizadas e colocadas no quadro. Ele também separou o progresso das mesmas em &#8220;a fazer&#8221;, &#8220;em progressos&#8221; e &#8220;feitas&#8221;, como no Scrum, mas sem a formalização de <span class="foreign-word" lang="en">daily meetings</span>.</p>

<p>Como isso, ele começou a poupar uma quantidade enorme de trabalho de gerenciamento e acompanhamento de tarefas ao mesmo tempo em que dava maior visibilidade a todos da empresa sobre o que estava acontecendo. Eventualmente, o quadro também se tornou uma reflexão do sistema Trac que ele usa para controle de <span class="foreign-word" lang="en">tickets</span> aumentando ainda mais a produtividade da equipe.</p>

<p>Para alguns puristas, a adaptação que ele fez seria considerada tão longe do Scrum quando um processo <span class="foreign-word" lang="en">waterfall</span>. Esse é o ponto que a maioria das pessoas perde sobre Agile:</p>

<p>Agilidade não tem absolutamente nada a ver com formalização. Assim como <span class="foreign-word" lang="en">waterfall</span> funciona para determinados tipos de processo&#8211;existem milhares de casos de extremo sucesso usando a filosofia&#8211;agilidade só funciona quando a idéia em si é comprada e adaptada à realidade específica dos processos necessários.</p>

<p>No caso do meu irmão, <span class="foreign-word" lang="en">daily meetings</span> com formalizados no Scrum não tem o menor sentido com a equipe pequena e geograficamente distribuída. Aplicar todos os parâmetros que o Scrum oferece teria o efeito contrário de reduzir sua produtividade.</p>

<p>Antes de tudo vem o lúdico, a diversão. E isso leva tão facilmente ao lucro que é impressionante pensar no número de pessoas enganadas quanto à história toda. Mas eu me divirto e sempre sou lembrado de pensar diferente quando vejo adaptações como a feita pelo meio irmão que funciona e resulta em efeitos permanentes positivos. Melhor do que isso é difícil.</p>]]></content:encoded>
      <category>Desenvolvimento</category>
      <guid>http://logbr.reflectivesurface.com/?p=1182</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>Balanço cultural de novembro</title>
      <description><![CDATA[Também com alguns dias de atraso&#8211;o novo BlogBlogs foi lançado ontem com sucesso&#8211;finalmente tive tempo de escrever o balanço cultural de novembro. Como o mês foi ainda mais movimentado do que outubro, o resultado foi bem pequeno:


4 livros
2 quadrinhos
7 filmes


Nos livros comecei com uma releitura de Atlas Shrugged. Fazia tempo que eu estava querendo revisitar [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=301893505" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/12/11/balanco-cultural-de-novembro-2/#comments</comments>
      <pubDate>Fri, 12 Dec 2008 00:39:29 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=301893505&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F12%2F11%2Fbalanco-cultural-de-novembro-2%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Também com alguns dias de atraso&#8211;o <a href="http://blogblogs.com.br/">novo BlogBlogs</a> foi lançado ontem com sucesso&#8211;finalmente tive tempo de escrever o balanço cultural de novembro. Como o mês foi ainda mais movimentado do que outubro, o resultado foi bem pequeno:</p>

<ul>
<li>4 livros</li>
<li>2 quadrinhos</li>
<li>7 filmes</li>
</ul>

<p>Nos livros comecei com uma releitura de <a href="http://en.wikipedia.org/wiki/Atlas_Shrugged">Atlas Shrugged</a>. Fazia tempo que eu estava querendo revisitar o épico trabalho de Ayn Rand que define sua filosofia objetivista&#8211;não por ser um adepto&#8211;mas pela força do trabalho. A estória do homem que decidiu parar o motor do mundo e assim o fez é um <span class="foreign-word" lang="fr">tour de force</span> em pensamento claro e narrativa forte. Apesar de ser condenado por alguns como verboso e prolixo, eu gosto do modo com Rand apresenta os caracteres e transpõe sua filosofia para o enredo sem acabar em pedantismo. Com exceção do capítulo em que o personagem principal define a filosofia em um discurso, o resto do livro é belo e consegue despertar a mente do leitor para as questões propostas sem incomodar.</p>

<p>O segundo livro foi <a href="http://www.thegraveyardbook.com/">The Graveyard Book</a>, o novo infanto-juvenil de Neil Gaiman. Leitores regulares conhecem minha admiração perene pelo trabalho de Gaiman e esse livro me deixou tão satisfeito como seus demais trabalhos. Embora Coraline, seu trabalho infanto-juvenil anterior não tenha me agradado tanto, essa releitura d&#8217;<a href="http://www.estantevirtual.com.br/buscaporautortitulo/Rudyard%20Kipling%20O%20%20Livro%20da%20Selva">O Livro da Selva</a> de Rudyard Kipling na estória de um garoto criado por fantasmas é uma delícia de leitura.</p>

<p>Na seqüência li <a href="http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530">Test-Driven Development by Example</a>, de Kent Beck, um dos maiores evangelistas dessa metodologia. O livro é simples e direto ao ponto mas falha colossalmente em não terminar os exemplos começados. O resultado é a sensação de que os exemplos são artificiais demais. Isso termina passando uma imagem ruim da técnica e deixando o leitor insatisfeito. O livro poderia ter se beneficiado enormemente de mais algumas dezenas de páginas.</p>

<p>Finalmente, li <a href="http://www.patrickrothfuss.com/content/books.asp">The Name of the Wind</a>, o primeiro de um trilogia de Patrick Rothfuss. Atualmente é muito raro que eu leia um livro que é parte de uma série antes que a mesma esteja fechada. Entretanto o livro recebeu tantos elogios de autores que eu considero muito bons que não resisti e comprei. Não me arrependi. A estória é fascinante e eu devorei o livro. Só para dar o gosto, um pequeno trecho do mesmo (o site do livro contem todo um capítulo):</p>

<blockquote>
  <p>I have stolen princesses back from sleeping barrow kings. I burned down the town of Trebon. I have spent the night with Felurian and left with both my sanity and my life. I was expelled from the University at a younger age than most people are allowed in. I tread paths by moonlight that others fear to speak of during day. I have talked to Gods, loved women, and written songs that make the minstrels weep.</p>
  
  <p>You may have heard of me.</p>
</blockquote>

<p>Nas estórias em quadrinhos, li o primeiro volume das <a href="http://en.wikipedia.org/wiki/The_Sandman_(Vertigo)">Crônicas de Sandman</a>, também por Neil Gaiman (roteiro, é claro). O primeiro volume compreende as primeiras oito estórias publicadas sobre o Senhor dos Sonhos, todas fascinantes. Como fã de Neil Gaiman eu sou suspeito para falar, mas como sempre ele consegue produzir uma mistura mitológica que é absolutamente impossível não se impressionar com a pura força da estória e a quantidade de referências que Gaiman consegue por em tão poucas páginas. Já estou com os próximos volumes para finalmente corrigir esse problema na minha educação &#8220;quadrinística&#8221;. <img src='http://logbr.reflectivesurface.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Nos filmes, o mês foi razoavelmente melhor que <a href="http://logbr.reflectivesurface.com/2008/12/06/balanco-cultural-de-outubro-2/">o anterior</a>.</p>

<p>Comecei o mês com <a href="http://us.imdb.com/title/tt0465538/">Michael Clayton</a>. George Clooney está muito no papel de um advogado envolvido em negócios escusos tentando salvar sua pele e sua família e Tilda Swinton é sempre consistente em seus papéis.</p>

<p>Em um mesmo fim de semana vi <a href="http://us.imdb.com/title/tt0469494/">There Will Be Blood</a> e <a href="http://us.imdb.com/title/tt0477348/">No Country for Old Man</a>. É absolutamente assustador o que alguns atores bons conseguem fazer. No primeiro, Daniel Day-Lewis mais uma vez se prova um dos atores mais poderosos de sua geração e no segundo Javier Bardem fornece uma atuação magnífica que me prendeu do começo ao fim. Fica difícil decidir qual dos dois está melhor em seus respectivos papéis e, definitivamente, ambos mereceram todos os prêmios que ganharam.</p>

<p><a href="http://us.imdb.com/title/tt0830515/">Quantum of Solace</a> foi bem inferior ao filme anterior na franquia Bondiana mas consegue divertir. <a href="http://us.imdb.com/title/tt1059786/">Eagle Eye</a> também é divertido mas depende de um furo enorme do enredo para fazer sentido.</p>

<p>Os demais, como sempre, nem valem o comentário. <img src='http://logbr.reflectivesurface.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>]]></content:encoded>
      <category>Filmes e Séries</category>
      <guid>http://logbr.reflectivesurface.com/2008/12/11/balanco-cultural-de-novembro-2/</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>“Just” use Unicode</title>
      <description/>
      <pubDate>Tue, 09 Dec 2008 09:20:38 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855868&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Sean McGrath: Making it possible to write software that will work in any language in any country, in any culture in the world is an extremely laudable goal. A goal that I wholeheartedly sign up to. We should make sure that the software arts make it possible. It is simultaneously the commercially sensible thing to do and the right thing to do from many human perspectives. A rare alignment of drivers indeed.  At this point, a voice somewhere in the room (is that a pointy haired boss I see out of the corner of my eye?) proclaims the answer to be obvious.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855868" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2932</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>seticon</title>
      <description><![CDATA[OK, I admit it.  I’m an ssh junkie.  I often have ssh windows open to several different machines — my Mac Mini, my Ubuntu server, my hosting provider, and even to whichever workstation I happen to be at at the moment.  That’s why the recent change to remove the icon option from profile of gnome-terminal has proven to be a minor but constant irritant.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855869" />
]]></description>
      <pubDate>Sun, 07 Dec 2008 17:32:42 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855869&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[OK, I admit it.  I’m an ssh junkie.  I often have ssh windows open to several different machines — my Mac Mini, my Ubuntu server, my hosting provider, and even to whichever workstation I happen to be at at the moment.  Buying a 22 inch flat-screen monitor only made my addiction worse.
That’s why the recent change to remove the icon option from profile of gnome-terminal has proven to be a minor but constant irritant.  You see, having separate icons is rather handy:
When you have lots of terminal’s open, it can be difficult to distinguish between them. The problem is especially bad when you use Alt+Tab to cycle through the windows, but all their icons look the same.

Eventually, the itch needed to be scratched.
Usage is simple, go to the window that you want to change the icon.  Enter the command seticon, and pass a list of filenames containing icons of various sizes.  Or do the sensible thing, and pass a name of a file containing a single SVG image.
I have a number of small shell scripts, one per host, that does this for the icon for that particular host, issues the appropriate ssh command, and then sets the icon to the utilities-terminal image.  I then created a custom application launcher for each host, and configure each to run the associated script in a terminal window, and select the same icon for the launcher itself.
I’m sure that over time I will want to create a proper autoconf setup for this, but for now the itch is scratched.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2931</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Pede para o Papai Noel</title>
      <description><![CDATA[<img src="/charges/20081206-ballmernatal.jpg" alt="Ballmer no Natal"/>
<p>
<a href="http://info.abril.com.br/aberto/infonews/122008/06122008-1.shl">E lá vem mais um capítulo da novela</a>. Agora está mais fácil já que deixaram o <a href="http://info.abril.com.br/aberto/infonews/112008/18112008-0.shl">Jerry Yang de fora dessa</a> e com o <a href="http://info.abril.com.br/aberto/infonews/112008/28112008-15.shl">Carl Icahn gastando mais uns trocados no Yahoo!</a>. Quem sabe o <a href="http://www.youtube.com/watch?v=wvsboPUjrGc">monkey-boy</a> ganhe isso no Natal e acaba esse drama de uma vez.
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=308835992" />
]]></description>
      <pubDate>Sat, 06 Dec 2008 22:05:31 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=308835992&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F550</link>
      <guid>http://eustaquiorangel.com/posts/550</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Balanço cultural de outubro</title>
      <description><![CDATA[Com mais de um mês e meio de atraso&#8211;falta de tempo com o lançamento próximo do BlogBlogs e viagens diversas&#8211;consegui escrever sobre os livros e filmes vistos em outubro. O resultado do mês foi:


7 livros
10 filmes


Nos livros, o primeiro que li no mês foi Emissaries from the Dead, de Adam-Troy Castro. Eu já tinha lido [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=301893506" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2008/12/06/balanco-cultural-de-outubro-2/#comments</comments>
      <pubDate>Sat, 06 Dec 2008 19:16:12 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=301893506&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2008%2F12%2F06%2Fbalanco-cultural-de-outubro-2%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Com mais de um mês e meio de atraso&#8211;falta de tempo com <a href="http://www.hitechlive.com.br/archives/blogblogs-lanca-proxima-versao-a-partir-deste-domingo/">o lançamento próximo do BlogBlogs</a> e viagens diversas&#8211;consegui escrever sobre os livros e filmes vistos em outubro. O resultado do mês foi:</p>

<ul>
<li>7 livros</li>
<li>10 filmes</li>
</ul>

<p>Nos livros, o primeiro que li no mês foi <a href="http://www.amazon.com/Emissaries-Dead-Andrea-Novel-Novels/dp/0061443727">Emissaries from the Dead</a>, de Adam-Troy Castro. Eu já tinha lido alguns contos do autor, todos excelentes&#8211;inclusive, seu conto <a href="http://www.fictionwise.com/eBooks/eBook28543.htm?cache">The Tangled Strings of the Marionettes</a> é um mais belos e nostálgicos que eu já li&#8211;e ao encontrar o livro na Livraria Cultura resolvi comprar. O livro se passa em um futuro onde a humanidade é uma de milhares de raças que habitam a galáxia e não uma das particularmente melhor posicionadas. Quando um assassinato acontece em uma missão diplomática humana em uma colônia artificial criada por uma AI, uma diplomata humana deve investigar a situação sem implicar os criadores da colônia. O resultado é uma novela detetivesca bem decente que peca apenas em seus momentos finais ao tentar condensar muita informação em <span class="foreign-word" lang="en">infodumps</span> que acabam não sendo tão interessante. Mesmo assim, se houver uma continuação, está na minha lista.</p>

<p>Seguindo, li <a href="http://en.wikipedia.org/wiki/Equal_Rites">Equal Rites</a>, de Terry Pratchett. É um dos livros mais antigos do mundo Discworld e com a cômica premissa de uma confusão em torno de passagem de poder entre magos que resulta na primeira mulher nessa posição em toda história do Discworld. Como todos livros do Pratchett, o humor é bem sarcástico e mórbido. E como nos primeiros livros do Pratchett, o final é bem fraco, fechando a história mas sem tanto impacto.</p>

<p>O próximo livro foi <a href="http://www.amazon.com/Agile-Software-Development-Scrum/dp/0130676349">Agile Software Development with Scrum</a>, de Ken Schwaber e Mike Beedle. O livro foi um dos primeiros a popularizarem o Scrum com uma metodologia/filosofia/processo aceitável de forma geral. O livro consegue um bom balanço de didática e evidência anedótica e explica bem os conceitos por trás do processo. Para quem não tem conhecimento algum ou está começando, é uma boa leitura introdutória.</p>

<p>Continuando, li <a href="http://en.wikipedia.org/wiki/Doomsday_Book_(novel)">Doomsday Book</a>, de Connie Willis. O livro ganhou tanto o Hugo quanto o Nebula em sua publicação e a autora é bem conhecida por trabalhos fortes e contemplativos. A estória do livro é sobre uma estudante de História que consegue autorização para viajar ao ano de 1320 para estudar localmente os hábitos da Idade Média. Infelizmente, uma crise ligando o passado e o futuro interfere e ela se vê lançada em uma época muito pior tendo que lidar com situações inesperadas e dolorosas. O livro é belo em suas descrições e enredo mas acaba sendo um tanto ou quanto previsível. O final, em particular, pode ser visto de longe. Mesmo assim, vale a leitura pela força narrativa.</p>

<p>O livro seguinte foi <a href="http://www.7letras.com.br/detalhe_livro/?id=22">A Fila sem Fim dos Demônios Descontentes</a>, de Bruna Beber. Eu sou super-suspeito para falar já que a Bruna é colega de trabalho e me deu o livro de presente, mas eu realmente gostei da poesia da garota. A Bruna é carioca tresloucada e extremamente competente no que tange à escrita e isso se reflete claramente em seus poemas. <img src='http://logbr.reflectivesurface.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> De pequenos e doces arranjos a poemas fortes e contundentes, ela consegue uma série de textos memoráveis que valem leituras repetidas.</p>

<p>Quase fechando o mês, foi a vez de <a href="http://www.amazon.com/Enterprise-Scrum-Ken-Schwaber/dp/0735623376">The Enterprise and Scrum</a>, também do Ken Schwaber. O livro é quase uma revisão do Agile Software Development with Scrum com aplicações para empresas de porte maior. O livro falha razoavelmente ao tentar cobrir muito material em pouco espaço que faz do mesmo quase uma coleção de apêndices. Vale correr o olho, mas não acrescenta muito ao corpo de material existente.</p>

<p>Finalmente, terminei o mês com <a href="http://www.amazon.com/Black-Swan-Impact-Highly-Improbable/dp/1400063515">The Black Swan</a>, de Nassim Nicholas Taleb. O livro foi aclamado como um dos melhores do ano pela sua suposta explicação de eventos improváveis, mas confesso que, se a explicação está lá, ela está misturada e perdida em meio a centenas de divagações e digressões em que o autor mistura pseudo-ciência, fatos de sua vida e uma atitude de superioridade que com certeza agrada a fãs de verbosidade e explicações &#8220;rebuscadas&#8221;. O livro tem alguns méritos em quebrar algumas concepções, mas é pouco mais do que uma compilação do que outros autores vem falando há vários anos sob um verniz de modernidade e erudição. <span class="foreign-word" lang="en">Boring, boring, boring</span>.</p>

<p>Nos filmes, foi um mês bem fraco. Tirando o belo <a href="http://www.imdb.com/title/tt0443680/">The Assassination of Jesse James by the Coward Robert Ford</a> e interessante <a href="http://www.imdb.com/title/tt0381849/">3:10 to Yuma</a>, os demais quase não valem o comentário. Desses dois, o primeiro consegue demonstrar muito bem a ambigüidade por trás dos fatos conhecidos sobre a relação entre Jesse James e Robert Ford e o segundo consegue resgatar muito bem o espírito real do primeiros filmes e livros de faroeste.</p>

<p><a href="http://www.imdb.com/title/tt0427392/">The Invasion</a>, em contrapartida, consegue ser mais um caro e fracassado <span class="foreign-word" lang="en">remake</span> de um bom filme. Há diretores que realmente acreditam que uns poucos sustos e atores famosos são suficientes para convencer uma platéia de que um filme tem estória. <a href="http://www.imdb.com/title/tt0465494/">Hitman</a> é um fiasco de execução que nem a bela <a href="http://www.imdb.com/name/nm1385871/">Olga Kurylenko</a> consegue salvar (inclusive, parece que o diretório de <a href="http://www.imdb.com/title/tt0830515/">Quantum of Solace</a> pensou a mesma coisa que o diretor de Hitman). Finalmente, <a href="http://www.imdb.com/title/tt0431308/">P.S. I Love You</a> poderia ter sido um belo filme sobre morte e recuperação mas se transforma em um drama barato e choroso.</p>

<p>Os demais filmes realmente dispensam comentários.</p>]]></content:encoded>
      <category>Filmes e Séries</category>
      <guid>http://logbr.reflectivesurface.com/2008/12/06/balanco-cultural-de-outubro-2/</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>Thin-Client Revisited</title>
      <description/>
      <pubDate>Fri, 05 Dec 2008 14:23:48 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855870&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Steven J. Vaughan-Nichols: Now, thanks to a partnership between Canonical, the company behind Ubuntu, and IBM, there’s a way to roll out corporate Linux desktops almost as fast as you can plug them into the network.
This story excites me.  Not for the “... drive significant savings compared with Microsoft-desktop software by amplifying ...” angle, but because hopefully it will mean that more application developers will see it as important that their applications are made available early, and run well, on Linux.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855870" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2930</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <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=308835993" />
]]></description>
      <pubDate>Thu, 20 Nov 2008 22:11:35 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=308835993&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>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=301893507" />
]]></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=301893507&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=301893508" />
]]></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=301893508&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>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=301893509" />
]]></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=301893509&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=301893510" />
]]></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=301893510&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>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=308835994" />
]]></description>
      <pubDate>Fri, 17 Oct 2008 15:17:03 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=308835994&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>Airman</title>
      <description/>
      <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=309855867&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Today was the Airman’s Coin Ceremony.  Pictures:<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=309855867" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:2933</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
  </channel>
</rss>
