<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-8900086</id><updated>2009-11-09T19:04:25.531-02:00</updated><title type='text'>MecanicaMente</title><subtitle type='html'>Alucinações de uma mente mecânica</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default?start-index=26&amp;max-results=25'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>115</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8900086.post-301168227046656850</id><published>2009-10-29T02:19:00.002-02:00</published><updated>2009-10-29T02:24:36.718-02:00</updated><title type='text'>O mito da "recuperação do atraso"</title><content type='html'>Não tem dessa de "recuperar o atraso" em um projeto de software...&lt;br /&gt;&lt;br /&gt;&lt;object id="prezi_fyjtqpvyrd1o" name="prezi_fyjtqpvyrd1o" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="550" height="400"&gt; &lt;param name="movie" value="http://prezi.com/bin/preziloader.swf"/&gt;  &lt;param name="allowfullscreen" value="true"/&gt;  &lt;param name="allowscriptaccess" value="always"/&gt;  &lt;param name="bgcolor" value="#ffffff"/&gt;  &lt;param name="flashvars" value="prezi_id=fyjtqpvyrd1o&amp;amp;lock_to_path=1&amp;amp;color=ffffff&amp;amp;autoplay=no"/&gt;  &lt;embed id="preziEmbed_fyjtqpvyrd1o" name="preziEmbed_fyjtqpvyrd1o" src="http://prezi.com/bin/preziloader.swf" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="550" height="400" bgcolor="#ffffff" flashvars="prezi_id=fyjtqpvyrd1o&amp;amp;lock_to_path=1&amp;amp;color=ffffff&amp;amp;autoplay=no"&gt; &lt;/embed&gt; &lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Boa referência aqui também: &lt;a href="http://www.stickyminds.com/s.asp?F=S12529_ART_2"&gt;What Is the Cost of a Requirement Error?&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-301168227046656850?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/301168227046656850/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=301168227046656850' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/301168227046656850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/301168227046656850'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/10/o-mito-da-recuperacao-do-atraso.html' title='O mito da &quot;recuperação do atraso&quot;'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-8340739282029539219</id><published>2009-10-26T15:36:00.004-02:00</published><updated>2009-10-26T15:50:09.737-02:00</updated><title type='text'>Técnicas, não ferramentas</title><content type='html'>Acho que nós da área de desenvolvimento temos um grande problema onde focamos nossos estudos. Normalmente estudamos demais a coisa errada, e as coisas certas não estudamos o suficiente.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Também é difícil dizer qual é o foco "correto". Cada um vai ter uma opinião diferente e não há estudos pra basear nenhum dos nossos "achismos". (Hmmm... já reparou como quase todo desenvolvimento de software comercial/corporativo tem esse problema?)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pessoalmente, depois de ficar perdendo muito tempo estudando frameworks, descobri que o que interessa são &lt;b&gt;técnicas, não ferramentas&lt;/b&gt;. Tenho hoje a nítida percepção que a ferramenta vêm naturalmente se você tem a técnica.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;O que seriam as técnicas?&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Idiomas das linguagens&lt;/li&gt;&lt;li&gt;Patterns dos mais variados&lt;/li&gt;&lt;li&gt;Modelos de arquitetura&lt;/li&gt;&lt;li&gt;TDD/BDD&lt;/li&gt;&lt;li&gt;Paradigmas de programação (OO / Funcional / Imperativo / Declarativo)&lt;/li&gt;&lt;li&gt;DSLs ou Interfaces Fluentes&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ou seja, independente da linguagem, os &lt;i&gt;conceitos &lt;/i&gt;serão úteis.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;E as ferramentas?&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Qualquer linguagem (Ruby, Java, Haskell...)&lt;/li&gt;&lt;li&gt;Qualquer framework (Rails, Spring...)&lt;/li&gt;&lt;li&gt;Qualquer biblioteca ou API (REXML, JDOM...)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hoje, eu foco o máximo na técnica e só estudo a ferramenta até o nível suficiente para o problema atual. O efeito que isso causa é bastante interessante, normalmente consigo responder se algo existe na ferramenta sem conhecê-la, porque, conceitualmente, a coisa deveria estar lá. :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Estou certo? Sei lá. Pra mim funciona melhor do que antes, quando eu me matava pra ficar aprendendo ferramenta e a cada 3 anos vinha uma nova e todo o conhecimento era perdido. Agora o conhecimento &lt;i&gt;acumula&lt;/i&gt;, e o que tenho que &lt;i&gt;renovar &lt;/i&gt;é menor.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-8340739282029539219?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/8340739282029539219/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=8340739282029539219' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/8340739282029539219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/8340739282029539219'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/10/o-foco-correto.html' title='Técnicas, não ferramentas'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-5283263481753657745</id><published>2009-10-01T02:31:00.002-03:00</published><updated>2009-10-01T02:45:08.010-03:00</updated><title type='text'>Metaphone em português para Java</title><content type='html'>Custou um pouquinho para achar um banco com nomes para testar e acertar as rebarbas, mas finalmente está aí: codificação fonética em Metaphone para português (&lt;a href="http://github.com/ruliana/MTFN"&gt;http://github.com/ruliana/MTFN&lt;/a&gt;) :)&lt;br /&gt;&lt;br /&gt;Se você quiser saber do que estou falando:&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Metaphone"&gt;http://en.wikipedia.org/wiki/Metaphone&lt;/a&gt; e &lt;a href="http://www2.varzeapaulista.sp.gov.br/metaphone"&gt;http://www2.varzeapaulista.sp.gov.br/metaphone&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Muito simples de usar, muito simples de customizar e vem com um banco de dados de teste, cortesia do Marco "Kiko" Carnut (&lt;a href="http://www.postcogito.org/"&gt;http://www.postcogito.org/&lt;/a&gt;) e seu trabalho sobre descobrir o sexo da pessoa somente pelo nome (&lt;a href="http://www.postcogito.org/Kiko/PlanilhaMascFemPtBr.html"&gt;http://www.postcogito.org/Kiko/PlanilhaMascFemPtBr.html&lt;/a&gt;, trabalho muito legal, vale a pena conferir!)&lt;br /&gt;&lt;br /&gt;Só que, com a massa de testes e estudando um pouco melhor a fonética da língua portuguesa, deu pra perceber que a coisa pode ser melhorada. Como por exemplo, considerar "P" e "B" como equivalentes, assim como "M" e "N". Desconsiderar algumas consoantes nos finais dos nomes e assim por diante.&lt;br /&gt;&lt;br /&gt;Optei primeiro por liberar um algoritmo bastante similar àquele que me baseei, que já é muito bom! Agora começo a refiná-lo com meus próprios "achismos". Vamos ver no que vai dar. ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-5283263481753657745?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/5283263481753657745/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=5283263481753657745' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5283263481753657745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5283263481753657745'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/10/metaphone-em-portugues-para-java.html' title='Metaphone em português para Java'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-4482990764365017768</id><published>2009-09-27T20:43:00.002-03:00</published><updated>2009-09-27T20:57:42.410-03:00</updated><title type='text'>Functors? Hmmm... nhammy</title><content type='html'>Ando estudando Haskell de farra ultimamente, confesso que ainda não entendi ainda qual é o barato dos monads, mas funções como cidadãos de primeira classe, combinação de funções e currying são conceitos bem legais.&lt;br /&gt;&lt;br /&gt;Dei uma checada no que havia para Java (é... Java) e esbarrei com alguns projetos interessantes, mas todos muito trabalhosos para minha preguiça. Então, como todo bom nerd, se você não acha uma ferramenta que goste, você cria uma.&lt;br /&gt;&lt;br /&gt;Então, com um pouco de Java Voodoo do Brabo,  fiz o "&lt;a href="http://github.com/ruliana/YoDaFunkta"&gt;Yo da Funkta!&lt;/a&gt;" pra satisfazer meu ego e minha preguiça. Acho que ficou bonzinho...&lt;br /&gt;&lt;br /&gt;Agora... estou muito interessado em... Metaphone...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-4482990764365017768?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/4482990764365017768/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=4482990764365017768' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/4482990764365017768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/4482990764365017768'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/09/functors-hmmm-nhammy.html' title='Functors? Hmmm... nhammy'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-3050853828185860582</id><published>2009-06-15T13:24:00.002-03:00</published><updated>2009-06-15T13:26:56.378-03:00</updated><title type='text'>Sims ensina</title><content type='html'>Sou um jogador casual de "Sims", jogando ele acabei aprendendo algumas dicas boa para o dia a dia:&lt;br /&gt;&lt;br /&gt;- Compre uma boa cama (com um excelente colchão), vale a pena!&lt;br /&gt;- Não dá tempo de fazer tudo o que se quer.&lt;br /&gt;- Gastar todo seu tempo livre com diversão não te leva a lugar nenhum, mas é preciso gastar algum tempo só com diversão.&lt;br /&gt;- É possível aprender se divertindo, mas nem sempre dá pra se divertir aprendendo.&lt;br /&gt;- Investir na carreira é ótimo, e tem que ser feito com intenção.&lt;br /&gt;- Sozinho não se vai muito longe.&lt;br /&gt;&lt;br /&gt;E por aí vai...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-3050853828185860582?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/3050853828185860582/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=3050853828185860582' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/3050853828185860582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/3050853828185860582'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/06/sims-ensina.html' title='Sims ensina'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-5256109779581037998</id><published>2009-06-03T00:13:00.006-03:00</published><updated>2009-06-03T00:30:47.357-03:00</updated><title type='text'>A difícil arte de explicar o abstrato</title><content type='html'>Tenho um problema básico de comunicação quando tratando com pessoal "não-nerd" como os gerentes (e a minha esposa). Toda vez que tenho que explicar "o código está ruim", eles me olham com aquela cara de tela azul do windows. Dá quase pra ouvir o somzinho no fundo: "pãm...!"&lt;br /&gt;&lt;br /&gt;Aí comento que é difícil dar manutenção, que leva mais tempo, que para fazer algo precisamos arrumar um pouco a coisa, que as estimativas não são confiáveis.&lt;br /&gt;&lt;br /&gt;"pãm...!?"&lt;br /&gt;&lt;br /&gt;Torna explicar que mexer ali pode causar problemas em outros lugares, que pode quebrar o que funciona, etc... etc...&lt;br /&gt;&lt;br /&gt;"pãm... pãm...!?"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Finalmente, achei um jeito bom de explicar quando digo "o código está nojento" e eles entenderem a encrenca que é mexer naquilo. As imagens abaixo (do post &lt;a href="http://www.tvsnob.com/archives/016683.php"&gt;http://www.tvsnob.com/archives/016683.php&lt;/a&gt; ) ajudaram muito:&lt;br /&gt;&lt;br /&gt;Primeiro, isso é um código bom:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_r2sndwUwTPI/SiXs3KM2x5I/AAAAAAAAACg/Vb14JKt39vA/s1600-h/cable2.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_r2sndwUwTPI/SiXs3KM2x5I/AAAAAAAAACg/Vb14JKt39vA/s320/cable2.jpg" alt="" id="BLOGGER_PHOTO_ID_5342936965320198034" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;E isso aqui é "código ruim:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_r2sndwUwTPI/SiXtLiKKjfI/AAAAAAAAACw/7JsGOi0n6_c/s1600-h/cablemess.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_r2sndwUwTPI/SiXtLiKKjfI/AAAAAAAAACw/7JsGOi0n6_c/s320/cablemess.jpg" alt="" id="BLOGGER_PHOTO_ID_5342937315348745714" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Leia novamente as frases acima, mas observando as imagens... não fica óbvio?&lt;br /&gt;&lt;br /&gt;Agora, sempre que vamos conversar, eu mantenho essa imagens por perto, hora que o pessoal começa a viajar muito, eles colocam o povo na terra. E tudo mundo entende o problema que temos nas mãos.&lt;br /&gt;&lt;br /&gt;As imagens corretas valem por um milhão de palavras.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-5256109779581037998?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/5256109779581037998/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=5256109779581037998' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5256109779581037998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5256109779581037998'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/06/dificil-arte-de-explicar-o-abstrato.html' title='A difícil arte de explicar o abstrato'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_r2sndwUwTPI/SiXs3KM2x5I/AAAAAAAAACg/Vb14JKt39vA/s72-c/cable2.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-5788108488722340098</id><published>2009-04-26T03:50:00.002-03:00</published><updated>2009-04-26T04:16:35.556-03:00</updated><title type='text'></title><content type='html'>É tarde da noite... passei horas incontáveis programando. Tomo um banho e tento dormir, não consigo. Linhas de código passam pela minha cabeça, penso em "if levantar", "sono -= 1", "sono += ler", blog, blog, coisas esquecidas...&lt;br /&gt;&lt;br /&gt;Levanto, pego o Mac e abro. Fico olhando a tela azul, quando me dou conta, me loguei mas não consigo me lembrar quando digitei a senha.&lt;br /&gt;&lt;br /&gt;O blog aparece, também não lembro de ter entrado aqui. Começo a digitar a esmo, as palavras vão saindo antes que eu consiga montar uma frase completa na cabeça. E agora, o que estou escrendo?&lt;br /&gt;&lt;br /&gt;Continuo vendo linhas de código passando na minha frente, o Código chama. Não posso responder ao Código, preciso programar. Não posso, fiz isso por tempo demais. Preciso escrever, já estou, mas não me dei conta.&lt;br /&gt;&lt;br /&gt;Queria poder escrever rápido como o Akita, programar como Kent Beck, arquiteturar como Fowler, ter a consciência do _Why. Pra quê? Não sei bem, mas imagino que deve ser divertido.&lt;br /&gt;&lt;br /&gt;Abro o terminal, "ruby -v". &lt;br /&gt;&lt;br /&gt;__"ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-darwin9.6.0]" - a máquina responde feliz.&lt;br /&gt;&lt;br /&gt;"irb", eu digo a ela.&lt;br /&gt;&lt;br /&gt;Um prompt me saúda, o cursor pisca, perguntando o que eu quero.&lt;br /&gt;&lt;br /&gt;text = &amp;lt;&amp;lt;TEXT&lt;br /&gt;&lt;br /&gt;Colo o texto que escrevi&lt;br /&gt;&lt;br /&gt;TEXT&lt;br /&gt;&lt;br /&gt;words = text.split&lt;br /&gt;words[rand(words.size)]&lt;br /&gt;&lt;br /&gt;O prompt responde: &lt;br /&gt;&lt;br /&gt;"dormir"&lt;br /&gt;&lt;br /&gt;Sensato como Ronaldo Ferraz. Deveria, mas ainda náo consigo. Se eu rodar de novo, acho que ele responde "Deixa de frescura e vai pra cama". Direto e contundente como o TaQ. Fico com medo que ele responda isso mesmo e fecho o terminal.&lt;br /&gt;&lt;br /&gt;Me dou por vencido.&lt;br /&gt;&lt;br /&gt;Fecho o Mac, uma luzinha branca me lembra que ele ainda vigia. Desisto e fecho os olhos. Amanhã vou rir disso... acho.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-5788108488722340098?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/5788108488722340098/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=5788108488722340098' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5788108488722340098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5788108488722340098'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/04/e-tarde-da-noite.html' title=''/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-6286155381334181138</id><published>2009-03-30T19:34:00.003-03:00</published><updated>2009-03-30T19:41:32.617-03:00</updated><title type='text'>case-insensitive e accent-insensitive no PostgreSQL</title><content type='html'>Gosto muito do PostgreSQL. Pessoalmente é um dos bancos que menos me causa o efeito "WTF", quando estou trabalhando com ele, com uma notável exceção... não tem nenhum parâmetro nem coisa parecida para poder fazer pesquisas case-insensitive e accent-insensitive.&lt;br /&gt;&lt;br /&gt;E isso é um grande "WTF" pra qualquer um que possua acentos na língua.&lt;br /&gt;&lt;br /&gt;Procurando uma solução, encontrei esses posts aqui:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.laudatio.com/wordpress/2008/11/05/postgresql-83-to_ascii-utf8/"&gt;http://www.laudatio.com/wordpress/2008/11/05/postgresql-83-to_ascii-utf8/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.mail-archive.com/pgsql-general@postgresql.org/msg112591.html"&gt;http://www.mail-archive.com/pgsql-general@postgresql.org/msg112591.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.postgresonline.com/journal/index.php?/archives/9-How-to-create-an-index-based-on-a-function.html"&gt;http://www.postgresonline.com/journal/index.php?/archives/9-How-to-create-an-index-based-on-a-function.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Como meu banco é UTF-8, combinei elas em uma única solução:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION to_ascii(bytea, name)&lt;br /&gt;RETURNS text STRICT AS 'to_ascii_encname' LANGUAGE internal;&lt;br /&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION norm(a_string text)&lt;br /&gt;RETURNS text AS $$&lt;br /&gt;  BEGIN&lt;br /&gt;    RETURN lower(to_ascii(convert_to(a_string, 'latin1'), 'latin1'));&lt;br /&gt;  END&lt;br /&gt;$$ LANGUAGE plpgsql&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E como quando fazemos isso sempre precisamos de índice, em tese podemos criar os índices assim: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE INDEX norm_tabela_campo_idx&lt;br /&gt;  ON tabela&lt;br /&gt;  USING btree norm(campo);&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-6286155381334181138?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/6286155381334181138/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=6286155381334181138' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/6286155381334181138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/6286155381334181138'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/03/case-insensitive-e-accent-insensitive.html' title='case-insensitive e accent-insensitive no PostgreSQL'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-9153211828875171150</id><published>2009-03-29T03:29:00.002-03:00</published><updated>2009-03-29T03:30:06.438-03:00</updated><title type='text'>Sugestões para programar</title><content type='html'>Aqui tem uma lista de sugestões que eu uso quando estou programando.&lt;br /&gt;&lt;br /&gt;Faço questão de colocar elas para mim mesmo de uma maneira um tanto... "enfática", digamos assim. Descobri que quando fico indignado eu lembro melhor das coisas. Por isso, perdoe minhas "ênfases".&lt;br /&gt;&lt;br /&gt;Sugestão 1&lt;br /&gt;&lt;br /&gt;Nomes significativos: pelo amor de JC e sua gangue, pare um pouco e coloque um nome decente nas coisas que faz (variáveis, métodos e classes). Sempre vale a pena colocar um bom nome, mesmo que isso custe vários minutos pensando. A razão disso? Crie um programa com nomes bem ruins e pouco significativos e depois tente dar manutenção nele, você vai lembrar do que eu disse agora.&lt;br /&gt;&lt;br /&gt;Sugestão 2 &lt;br /&gt;&lt;br /&gt;Indireção: use e abuse. Crie métodos a rodo, crie dezenas de classes pequenas, jogue o que puder para uma classe pai, abstraia ao máximo. O efeito disso é criar naturalmente Template Methods e DSLs, sem falar em diminuir a duplicação. Aliás, já repararam como template methods se parecem com micro DSLs?&lt;br /&gt;&lt;br /&gt;Sugestão 3 &lt;br /&gt;&lt;br /&gt;Valide o que vai usar para o método que está escrevendo. Se vai usar parâmetros, alguns "ifs" para validar que não está vindo lixo sempre são bemvindos. Se vai usar atributos, teste para ver se estão do jeito que você esperava encontrá-los. Se estiver com muita preguiça, mas muita mesmo, valide ao menos os nulos. Ah... e antes que eu me esqueça... NÃO, isso NÃO vai fazer seu programa ficar lento.&lt;br /&gt;&lt;br /&gt;Sugestão 4&lt;br /&gt;&lt;br /&gt;Estado: se você está programando orientado a objeto. USE A PORRA DO ESTADO! Comece a computação em um método, termine em outro, jogue todas as variáveis possíveis para atributos. Se ficar com atributos de computações diferentes em uma única classe, use a dica 2. Se essa classe for compartilhada por múltiplas threads, não use essa sugestão.&lt;br /&gt;&lt;br /&gt;Sugestão 5&lt;br /&gt;&lt;br /&gt;Pais? Sim, use muito classes pais, evite delegação. Ela dá um trabalho danado (principalmente se sua linguagem do coração não tiver proxies dinâmicos) e o benefício é mais teórico que prático. Ahhmm... mas todo mundo diz que é melhor usar delegação do que herança. Poisé, e eu estou dizendo o contrário. Você está programando orientado a objeto ou não, afinal? Delegação é boa sim, onde fizer sentido, como por exemplo, em wrappers.&lt;br /&gt;&lt;br /&gt;Sugestão 6&lt;br /&gt;&lt;br /&gt;Não use cegamente sugestões e boas práticas. Sempre, sempre, sempre (eu falei SEMPRE, caralho!) conheça os prós e principalmente os contras de toda técnica que você vai usar. Boa prática só é boa se você sabe quando não deve usá-la. Isso vale especialmente para as sugestões que acabei de listar. ;)&lt;br /&gt;&lt;br /&gt;Que sugestões você colocaria na lista? Ou modificaria?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-9153211828875171150?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/9153211828875171150/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=9153211828875171150' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/9153211828875171150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/9153211828875171150'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/03/sugestoes-para-programar-aqui-tem-uma.html' title='Sugestões para programar'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-2871099653285883092</id><published>2009-03-25T01:58:00.001-03:00</published><updated>2009-03-25T02:06:38.080-03:00</updated><title type='text'>Flamings e Einstein</title><content type='html'>É muito comum ver por aí nos fóruns de tecnologias alguns tópicos que são "&lt;a href="http://en.wikipedia.org/wiki/Flaming_(Internet)"&gt;flamings&lt;/a&gt;". Fiquei imaginando o que causam esses flames e como é difícil distinguir idéias completamente furadas das idéias que realmente tem algo de bom. Acho que consegui chegar em uma pequena fórmula que deve resolver parte do problema, ao menos para mim.&lt;br /&gt;&lt;br /&gt;O raciocínio veio quando estava lembrando do que fez Albert Einstein. O cara foi tão ponto fora da curva que criou sua teoria da relatividade de cabeça, não por que ele quis assim, mas porque simplesmente não havia (e acho que ainda não há) experimentos possíveis para provar que a idéia é verdadeira ou não. Aliás, no meio acadêmico, isso é bastante comum.&lt;br /&gt;&lt;br /&gt;Como ele fez isso (e aliás, como os cientistas fazem isso, normalmente)? Ele partiu de um "pressuposto" e começou a raciocinar em cima dele. No caso, o pressuposto é de que a luz possui velocidade constante. Matutando e pensando, ele chegou a conclusões incríveis... desde que a velocidade da luz seja constante.&lt;br /&gt;&lt;br /&gt;O que tem isso de importante? Bom, se provarem que realmente é uma constante (se já não provaram), é grande a chance de que toda a teoria esteja correta. Se provarem que não é constante, então toda a teoria vai pro brejo.&lt;br /&gt;&lt;br /&gt;Aí nossa opinião sobre a teoria da relatividade se resume a analisar 2 coisas:&lt;br /&gt;&lt;br /&gt;1 - Se concordamos com o pressuposto;&lt;br /&gt;&lt;br /&gt;2 - Se achamos que o raciocínio do cara não tem falhas lógicas.&lt;br /&gt;&lt;br /&gt;Em software temos um problema similar ao que tinha o tio Einstein. Temos grandes dificuldades de provar nossas idéias e teorias sobre software. Acho que daí nascem os flamings e todas essas discussões que ficam parecendo mais discussões religiosas do que discussões sobre uma ciência exata.&lt;br /&gt;&lt;br /&gt;Como em software não temos quase limitação nenhuma, quase qualquer idéia dá certo com o esforço suficiente aplicado, mesmo as idéias muito idiotas.&lt;br /&gt;&lt;br /&gt;Essas idéias, idiotas ou não, também são criadas a partir de pressupostos. Não sei se todos, mas todos os softwares, apis, frameworks e posts de blog que consigo lembrar são baseados em alguns pressupostos.&lt;br /&gt;&lt;br /&gt;O problema é que nunca deixamos claros quais pressupostos são esses. Então nossas idéias são analisadas a partir dos pressupostos que cada pessoa escolhe. Depende do que ele escolhe como pressuposto, sua opinião vai ser favorável ou não a nossa idéia.&lt;br /&gt;&lt;br /&gt;A "pequena fórmula" para resolver o problema dos flamings, e também o problema para se detectar uma idéia boa de uma idéia idiota é simplesmente deixar bem claro os pressupostos que se tomou para a idéia.&lt;br /&gt;&lt;br /&gt;Não, não foi dessa vez que descobri a América ou inventei algo novo e inédito, pelo visto. Mas para mim é um coisa que vem dando certo quando tenho que analisar algumas coisas, como Frameworks e posts de blogs. :)&lt;br /&gt;&lt;br /&gt;Querem ver um pequeno exercício? Você pode concordar ou discordar de tudo isso que eu disse, mas se ela é uma boa idéia ou não é mais fácil analisar se eu colocar os pressupostos aqui. Aí vão eles:&lt;br /&gt;&lt;br /&gt;- É comum flaming nos fóruns de tecnologia;&lt;br /&gt;- O que causa o flaming é a dificuldade de se separar idéias boas das ruins;&lt;br /&gt;- É difícil separar as idéias porque é difícil prová-las;&lt;br /&gt;- É difícil prová-las porque quase qualquer idéia sobre software funciona se aplicarmos esforço suficiente;&lt;br /&gt;- As pessoas tendem a analisar as idéias pelos seus próprios pressupostos;&lt;br /&gt;- Podemos separar as idéias se conhecermos claramente os pressupostos em que foram baseadas;&lt;br /&gt;&lt;br /&gt;Parece uma linha de raciocínio, mas na verdade não é. Cada linha da lista acima pode ser contestada facilmente e não pode ser provada, são pressupostos. Se você concordar com todos eles, provavelmente vai concordar com a minha teoria como um todo. Se deixar de concordar com qualquer uma delas, provavelmente vai achar minha teoria um lixo.&lt;br /&gt;&lt;br /&gt;Se todos eles puderem ser provados com sucesso, então a teoria é verdadeira. Se qualquer um deles for provado em contrário, então ela é furada.&lt;br /&gt;&lt;br /&gt;Com tantos pressupostos (são ao menos seis, se não esqueci nada), dá pra ver que essa minha idéia é bem frágil.&lt;br /&gt;&lt;br /&gt;Bom, agora você conhece a teoria e conhece claramente no que me baseei para montá-la. Espero que fique fácil analisar se ela tem fundamento ou não para você e o porquê disso.&lt;br /&gt;&lt;br /&gt;E aí? Tem fundamento?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-2871099653285883092?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/2871099653285883092/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=2871099653285883092' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/2871099653285883092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/2871099653285883092'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/03/flamings-e-einstein.html' title='Flamings e Einstein'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-466921944136969277</id><published>2009-02-06T13:08:00.001-02:00</published><updated>2009-02-06T13:08:13.647-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reclamação nota_mental publicidade chefes'/><title type='text'>Da série "notas mentais"</title><content type='html'>Não aconteceu comigo, mas com um amigo... &lt;br /&gt;&lt;br /&gt;Quem efetivamente resolve o problema e faz acontecer não aparece em jornal. Quem aparece é o chefe, que é incapaz de gerar soluções e que mentiu o tempo todo para o cliente.&lt;br /&gt;&lt;br /&gt;C'est la vie.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-466921944136969277?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/466921944136969277/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=466921944136969277' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/466921944136969277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/466921944136969277'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/02/da-serie-mentais.html' title='Da série &amp;quot;notas mentais&amp;quot;'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-3143373375774965618</id><published>2009-01-30T16:12:00.001-02:00</published><updated>2009-01-30T16:12:08.230-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='estúpido cerimoniosa linguagem Java'/><title type='text'>Fadado a ser estúpido</title><content type='html'>Tentei escrever um pequeno mecanismo para transações explícitas em Java. Na primeira versão, ou o programador faz "try catch" direitinho (e repetitivamente), ou a coisa não funciona. &lt;br /&gt;&lt;br /&gt;Implementei depois usando uma classe anônima. Fica parecido com closure, e resolve esse problema, mas ficou desagradável e com aquele gosto de "gambiarra" na boca.&lt;br /&gt;&lt;br /&gt;A solução mais estúpida pareceu melhor...&lt;br /&gt;&lt;br /&gt;Tentei também um mecanismo simples de reflexão no banco para poder gravar tabelas simples sem precisar fazer "dança da chuva" toda hora. Consegui, mas ainda ficou um negócio meio repetitivo e com o mesmo gosto de "gambiarra".&lt;br /&gt;&lt;br /&gt;A solução mais idiota, criar beans pra tudo, tinha uma aparência melhor.&lt;br /&gt;&lt;br /&gt;Moral da história: Ou sou realmente estúpido e minhas soluções são idiotas, ou sou esperto e a linguagem me faz parecer um estúpido. Ou seja, de qualquer maneira, sou estúpido.&lt;br /&gt;&lt;br /&gt;Veja, eu adoro Java, é uma linguagem excelente. Mas ela não presta para fazer coisas dinâmicas do mesmo jeito que Ruby não presta pra fazer concorrência.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-3143373375774965618?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/3143373375774965618/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=3143373375774965618' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/3143373375774965618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/3143373375774965618'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/01/fadado-ser-estupido.html' title='Fadado a ser estúpido'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-5684077771517797160</id><published>2009-01-28T19:20:00.001-02:00</published><updated>2009-01-28T19:20:42.158-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='generalizações lição_aprendida hibernate JSTL clojure'/><title type='text'>Generalizando como o diabo...</title><content type='html'>Flash 1:&lt;br /&gt;Estava aprendendo "clojure" (http://clojure.org) esses dias e o autor (Rich Hickey) fala sobre os problemas de variáveis mutáveis para multi-threading. Aí advoga sobre linguagens funcionais são melhores para multi-thread.&lt;br /&gt;&lt;br /&gt;Flash 2:&lt;br /&gt;Hoje, esbarrei com um código JSP e para tentar fazer uma besteirinha (colocar um valor padrão se um atributo não era fornecido) precisei de 5 linhas de "JSTL". Fiquei indignado e meti um operador ternário dentro da Expression Language.&lt;br /&gt;&lt;br /&gt;Flash 3:&lt;br /&gt;Estamos em um sistema que quase não possui regras de negócio. 90% são cadastros com simples validações (tem uma parte de GIS, mas essa é outra história). E temos dezenas de cadastros. Ao invés de criar um objeto "bean burro" para cada entidade e usar o hibernate como manda a cartilha, fizemos um objeto parecido com um Map que resolve pra todo mundo. O resultado é conseguimos fazer um CRUD simples com regras de validação em 4 minutos (mais ou menos), e esse tempo ainda vai cair...&lt;br /&gt;&lt;br /&gt;O que esses 3 flashes me ensinam? Generalizações são extremamente perigosas. Se você não tem discernimento suficiente para saber quando quebrar um regra, tome cuidado ao segui-la. Você não sabe por que a está seguindo...&lt;br /&gt;&lt;br /&gt;Adição: sempre existem regras que não sabemos quando quebrar.&lt;br /&gt;&lt;br /&gt;Corolário: só respeitar a opinião de alguém se ele souber me dar um contra-exemplo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-5684077771517797160?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/5684077771517797160/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=5684077771517797160' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5684077771517797160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5684077771517797160'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2009/01/generalizando-como-o-diabo.html' title='Generalizando como o diabo...'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-7674179385802873220</id><published>2008-06-02T11:37:00.002-03:00</published><updated>2008-06-19T15:33:27.317-03:00</updated><title type='text'>Princípios de OO segundo Alan Knight (e Dilbert) (parte 2)</title><content type='html'>Essa é a segunda parte &lt;a href="http://mecanicamente.blogspot.com/2008/05/princpios-de-oo-segundo-alan-knight-e.html"&gt;desse post aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Evite responsabilidades&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Objetos devem ser preguiçosos ao extremo. Evite responsabilidades, se tiver que aceitá-las, mantenha-as vagas e delegue o trabalho de verdade para outros.&lt;br /&gt;&lt;br /&gt;O efeito final é que cada método vai fazer um fragmento muito pequeno de trabalho. Segundo o próprio Alan Kay, em um sistema orientado a objetos bem feito, você não consegue saber onde o trabalho está sendo realmente feito, quando você vê, já foi.&lt;br /&gt;&lt;br /&gt;Apesar de um fluxo em específico ser mais difícil de seguir (experimenta debugar em Smalltalk q vc vai entender do que eu estou falando), os métodos todos são tão simples que você consegue entendê-los em segundos.&lt;br /&gt;&lt;br /&gt;A segunda parte da proposição: "mantenha a responsabilidade vaga", significa que você deve desconfiar de especificações do tipo "o objeto deve persistir em banco todas as entradas". Isso porque ele contém detalhes de implementação, na verdade, o que interessa para os outros objetos não é como a informação vai ser guardada, mas como ela vai ser recuperada. Uma especificação melhor seria "o objeto deve saber informar as entradas feitas". Se isso será feito em banco de dados, em arquivo texto, distribuído na rede ou por sinal de fumaça, não interessa, o que nos dá muito mais flexibilidade.&lt;br /&gt;&lt;br /&gt;No final a idéia é aumentar o reuso. Evitando responsabilidades e delegando o trabalho, na verdade estou procurando reutilizar o que outras classes já fazem. Mantendo as responsabilidades vagas estou escondendo como faço as coisas (encapsulamento).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-7674179385802873220?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/7674179385802873220/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=7674179385802873220' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/7674179385802873220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/7674179385802873220'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2008/06/princpios-de-oo-segundo-alan-knight-e.html' title='Princípios de OO segundo Alan Knight (e Dilbert) (parte 2)'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-1277117498888385662</id><published>2008-05-20T15:36:00.010-03:00</published><updated>2008-05-28T10:21:01.399-03:00</updated><title type='text'>Princípios de OO segundo Alan Knight (e Dilbert) (parte 1)</title><content type='html'>(nossa como faz tempo que não posto... :p)&lt;br /&gt;&lt;br /&gt;Faz uns anos eu achei um artigo &lt;a href="http://www.cincomsmalltalk.com/userblogs/cincom/digest?content=2001-files-ooprinciples"&gt;artigo obscuro escrito por Alan Knight por volta de 2000 ou 2001&lt;/a&gt; que é um excelente resumo de como deve ser um bom código orientado a objetos. O mais interessante é que o artigo faz analogia aos princípios "Dilbert", e por incrível que pareça, a analogia encaixa como uma luva.&lt;br /&gt;&lt;br /&gt;O texto é curto e muito divertido, recomendo a leitura!&lt;br /&gt;&lt;br /&gt;Como sempre mostro esse artigo pra todo mundo que eu conheço, achei que já era hora de citar ele no blog e fazer um resumo em português pra quem não conhece bem o gringolês. Como posts grandes ninguém lê, vou postando os princípios aos poucos.&lt;br /&gt;&lt;br /&gt;Nota: &lt;span style="color:red"&gt;AS IDÉIAS AÍ EMBAIXO NÃO SÃO MINHAS, OKAY? EU GOSTO MUITO DELAS, MAS O AUTOR ORIGINAL É O "TIUZÃO TOP FODA" ALAN KNIGHT!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Avisados? Ótimo! Senão depois o TaQ briga comigo por estar levando crédito por idéias alheias :).&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Princípio 1: Nunca faça nada que alguém possa fazer para você.&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Esse é basicamente o princípio do "tell, don't ask". Basicamente, objetos não podem ser caras legais. Nada de "Olha, preciso do total dos custos desde o começo do mês, mas não se incomode, me dê os dados aí que eu mesmo faço o cálculo, não deve ser muito complicado, não é?"&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  total = centro_de_custo.itens.inject(0) do|soma, item| &lt;br /&gt;    if item.data &gt; Date.parse('2008-05-01')&lt;br /&gt;      soma += item.valor &lt;br /&gt;    else&lt;br /&gt;      soma&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Objetos devem ser grandes FDPs. Objeto bom é grosso como seu chefe: "Cara, quero o total dos custos desde o começo do mês! Não quero nem saber e não me interessa como você calcula isso, quero o resultado, e quero JÁ!".&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  total = centro_de_custo.total_desde('2008-05-01')&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Em Java, vejo muito uma coisa um pouco mais esquisita, normalmente envolve um DAO, injeção de dependência e costumeiramente um Date que não se pode construir diretamente pois o construtor está "deprecated":&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  // getCentroDeCustoDAO foi alimentado antes pelo Spring&lt;br /&gt;  // e "new Date" costuma ser gerado via Calendar, pq esse&lt;br /&gt;  // construtor está deprecated faz tempo...&lt;br /&gt;  List&lt;Item&gt; itens = getCentroDeCustoDAO().procurarPorDataDesde(new Date(2008, 4, 1));&lt;br /&gt;  BigDecimal resultado = new BigDecimal(0);&lt;br /&gt;  for(Item item : itens) {&lt;br /&gt;    resultado = resultado.add(item.getCusto());&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Mesmo que você goste muito desse padrão, seria um pouco melhor do jeito abaixo. Embora já tenha ouvido que isso é regra de negócio e não deveria ser feita no DAO.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  // getCentroDeCustoDAO foi alimentado antes pelo Spring&lt;br /&gt;  // e "new Date" costuma ser gerado via Calendar, pq esse&lt;br /&gt;  // construtor está deprecated faz tempo...&lt;br /&gt;  BigDecimal resultado = getCentroDeCustoDAO().calcularCustoTotalPorDataDesde(new Date(2008, 4, 1));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;"Tell, don't ask" &lt;= "Mande, não peça"...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-1277117498888385662?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/1277117498888385662/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=1277117498888385662' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/1277117498888385662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/1277117498888385662'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2008/05/princpios-de-oo-segundo-alan-knight-e.html' title='Princípios de OO segundo Alan Knight (e Dilbert) (parte 1)'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-1521210158418256713</id><published>2008-03-17T12:50:00.002-03:00</published><updated>2008-03-17T13:07:41.348-03:00</updated><title type='text'>Avanço tecnológico às avessas...</title><content type='html'>Não sei se porque ando lendo coisas subversivas mas ando com a nítida impressão que estamos andando em círculos ao invés de fazer avanços na área de software...&lt;br /&gt;&lt;br /&gt;Alguns fatos me deram essa impressão:&lt;br /&gt;&lt;br /&gt;1 - "Redescoberta" de closures -&gt; coisa que antes do hype do Ruby ninguém dava bola, e agora é a discussão do momento. Só que isso existe desde 58 com LISP. Ou, se vc quiser uma roupagem mais moderna, desde 78 com Smalltalk. (Clipper tb tinha, alguém lembra?)&lt;br /&gt;&lt;br /&gt;2 - Domain Driven Development -&gt; não entrei muito a fundo, mas me parece basicamente o que o pessoal do movimento O.O. de 1970 e uns quebrados pregava.&lt;br /&gt;&lt;br /&gt;3 - TDD -&gt; okay, mesmo o Kent Beck confessava que isso não era novidade.&lt;br /&gt;&lt;br /&gt;4 - Uma &lt;a href="http://www.infoq.com/interviews/mccarthy-elephant-2000"&gt;entrevista&lt;/a&gt; com John McCarthy (criador do LISP) na InfoQ -&gt; Tem uma pergunta quase no final da entrevista sobre LISP sendo citado como influência para novas linguagens:&lt;br /&gt;&lt;br /&gt;"...many modern programming languages like Ruby are claiming big influences from Lisp..."&lt;br /&gt;&lt;br /&gt;McCarthy confessa que não conhece Ruby, mas pergunta:&lt;br /&gt;&lt;br /&gt;"Does it use, for example, list structures as data?"&lt;br /&gt;&lt;br /&gt;O entrevistador responde negativamente, e McCarthy completa:&lt;br /&gt;&lt;br /&gt;"So if you want to compute with sums and products, you have to parse every time? So, in that respect Ruby still isn't up to where Lisp was in 1960."&lt;br /&gt;&lt;br /&gt;Interessante...&lt;br /&gt;&lt;br /&gt;Existem alguns outros pequenos fatos aqui e ali, pequenos demais pra eu estar totalmente consciente deles, mas ando sentindo um "deja vu" desgramado. Será que sei pouco e na verdade há um avanço nessas coisas que não estou percebendo ou será que sei o suficiente e realmente estamos andando em círculos em algumas coisas?&lt;br /&gt;&lt;br /&gt;Como eu sempre assumo que não sei o suficiente, a questão agora está em saber o que não estou percebendo. Toca estudar mais... :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-1521210158418256713?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/1521210158418256713/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=1521210158418256713' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/1521210158418256713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/1521210158418256713'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2008/03/avano-tecnolgico-s-avessas.html' title='Avanço tecnológico às avessas...'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-5814911958952515910</id><published>2008-03-12T18:18:00.007-03:00</published><updated>2008-03-12T18:51:05.169-03:00</updated><title type='text'>Sobrecarga de métodos em Ruby</title><content type='html'>Uma das coisas muito legais que o Java possui é sobrecarga de métodos (várias vezes confundido com polimorfismo) que é a capacidade de possuir métodos diferentes com mesmo nome, mas com parâmetros diferentes.&lt;br /&gt;&lt;br /&gt;Bom, isso não existe em Ruby, mas nada impede que isso seja implementado. Rascunhei isso aqui:&lt;br /&gt;&lt;br /&gt;&lt;span class="S5"&gt;class&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S8"&gt;Object&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S5"&gt;def&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S9"&gt;self&lt;/span&gt;&lt;span class="S10"&gt;.&lt;/span&gt;generate_method_name_for&lt;span class="S10"&gt;(&lt;/span&gt;method_name&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;*&lt;/span&gt;parameter_types&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S2"&gt;# Usamos espaços no nome dos métodos gerados para evitar chamadas acidentais&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S6"&gt;"&lt;/span&gt;&lt;span class="S10"&gt;#{&lt;/span&gt;method_name&lt;span class="S10"&gt;}&lt;/span&gt;&lt;span class="S6"&gt;_&lt;/span&gt;&lt;span class="S10"&gt;#{&lt;/span&gt;parameter_types&lt;span class="S10"&gt;.&lt;/span&gt;collect&lt;span class="S10"&gt;{|&lt;/span&gt;it&lt;span class="S10"&gt;|&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;it&lt;span class="S10"&gt;.&lt;/span&gt;to_s&lt;span class="S10"&gt;}.&lt;/span&gt;join&lt;span class="S10"&gt;(&lt;/span&gt;&lt;span class="S7"&gt;' '&lt;/span&gt;&lt;span class="S10"&gt;)}&lt;/span&gt;&lt;span class="S6"&gt;"&lt;/span&gt;&lt;span class="S10"&gt;.&lt;/span&gt;to_sym&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S5"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S5"&gt;def&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S9"&gt;self&lt;/span&gt;&lt;span class="S10"&gt;.&lt;/span&gt;def_method&lt;span class="S10"&gt;(&lt;/span&gt;method_name&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;*&lt;/span&gt;parameter_types&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;&amp;amp;&lt;/span&gt;block&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S2"&gt;# Definindo o método genérico da classe,&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;define_method&lt;span class="S0"&gt; &lt;/span&gt;method_name&lt;span class="S10"&gt;.&lt;/span&gt;to_sym&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S5"&gt;do&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;|*&lt;/span&gt;params&lt;span class="S10"&gt;|&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;send&lt;span class="S10"&gt;(&lt;/span&gt;&lt;span class="S6"&gt;"&lt;/span&gt;&lt;span class="S10"&gt;#{&lt;/span&gt;method_name&lt;span class="S10"&gt;}&lt;/span&gt;&lt;span class="S6"&gt;_&lt;/span&gt;&lt;span class="S10"&gt;#{&lt;/span&gt;params&lt;span class="S10"&gt;.&lt;/span&gt;collect&lt;span class="S10"&gt;{|&lt;/span&gt;it&lt;span class="S10"&gt;|&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;it&lt;span class="S10"&gt;.&lt;/span&gt;class&lt;span class="S10"&gt;.&lt;/span&gt;to_s&lt;span class="S10"&gt;}.&lt;/span&gt;join&lt;span class="S10"&gt;(&lt;/span&gt;&lt;span class="S7"&gt;' '&lt;/span&gt;&lt;span class="S10"&gt;)}&lt;/span&gt;&lt;span class="S6"&gt;"&lt;/span&gt;&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;*&lt;/span&gt;params&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S5"&gt;end&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S29"&gt;unless&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S5"&gt;self&lt;/span&gt;&lt;span class="S10"&gt;.&lt;/span&gt;method_defined?&lt;span class="S10"&gt;(&lt;/span&gt;method_name&lt;span class="S10"&gt;.&lt;/span&gt;to_sym&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S2"&gt;#Definindo cada método específico&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;specific_method&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;=&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;generate_method_name_for&lt;span class="S10"&gt;(&lt;/span&gt;method_name&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;*&lt;/span&gt;parameter_types&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;define_method&lt;span class="S10"&gt;(&lt;/span&gt;specific_method&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;&amp;amp;&lt;/span&gt;block&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S5"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="S5"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;E para usar:&lt;br /&gt;&lt;br /&gt;&lt;span class="S5"&gt;class&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S8"&gt;Test&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;def_method&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S14"&gt;:test&lt;/span&gt;&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;String&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;String&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S5"&gt;do&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;|&lt;/span&gt;a&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;b&lt;span class="S10"&gt;|&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;puts&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S6"&gt;"Duas strings"&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S5"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;def_method&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S14"&gt;:test&lt;/span&gt;&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;String&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S5"&gt;do&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;|&lt;/span&gt;a&lt;span class="S10"&gt;|&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;puts&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S6"&gt;"Uma string"&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S5"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;def_method&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S14"&gt;:test&lt;/span&gt;&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;Fixnum&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S5"&gt;do&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;|&lt;/span&gt;a&lt;span class="S10"&gt;|&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;puts&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S6"&gt;"Um número"&lt;/span&gt;&lt;br /&gt;&lt;span class="S0"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="S5"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="S5"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;x&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S10"&gt;=&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;Test&lt;span class="S10"&gt;.&lt;/span&gt;new&lt;br /&gt;&lt;br /&gt;x&lt;span class="S10"&gt;.&lt;/span&gt;test&lt;span class="S10"&gt;(&lt;/span&gt;&lt;span class="S6"&gt;"a"&lt;/span&gt;&lt;span class="S10"&gt;,&lt;/span&gt;&lt;span class="S0"&gt; &lt;/span&gt;&lt;span class="S6"&gt;"b"&lt;/span&gt;&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;x&lt;span class="S10"&gt;.&lt;/span&gt;test&lt;span class="S10"&gt;(&lt;/span&gt;&lt;span class="S6"&gt;"a"&lt;/span&gt;&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;x&lt;span class="S10"&gt;.&lt;/span&gt;test&lt;span class="S10"&gt;(&lt;/span&gt;&lt;span class="S4"&gt;1&lt;/span&gt;&lt;span class="S10"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;É lógico que isso custa desempenho, mas serve. Acho também que o código poderia ser grandemente melhorado, até pq não sei se isso funcionaria corretamente com herança e polimorfismo, mas não quis perder mais tempo brincando nisso :)&lt;br /&gt;&lt;br /&gt;Moral da história: adoro classes abertas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-5814911958952515910?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/5814911958952515910/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=5814911958952515910' title='7 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5814911958952515910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5814911958952515910'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2008/03/sobrecarga-de-mtodos-em-ruby.html' title='Sobrecarga de métodos em Ruby'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-8585298871890345690</id><published>2008-01-14T18:49:00.000-02:00</published><updated>2008-01-14T18:47:00.807-02:00</updated><title type='text'>O que é preciso para DSLs?</title><content type='html'>(Se vc não sabe o que é DSL, &lt;a href="http://www.balanceonrails.com.br/articles/2006/08/02/a-fronteira-do-dsl"&gt;Akita explica&lt;/a&gt;... se quiser uma discussão aprumada e ajeitada sobre o assunto, dá uma olhada no que &lt;a href="http://logbr.reflectivesurface.com/2008/01/10/domain-specific-languages-implementando-magica/"&gt;diz o tio Ronaldo&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Alguns dizem que Smalltalk, Ruby e Lisp são boas linguagens para criar DSLs. Mas Java, C# e afins não são tão boas? Por quê?&lt;br /&gt;&lt;br /&gt;Depois de ler um tanto e experimentar mais outro tanto, acredito que para criar DSLs internas (veja o que &lt;a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html"&gt;diz Martin Fowler&lt;/a&gt; sobre DSLs internas e externas), uma linguagem precisaria dos seguintes items:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Reflexão(de verdade), ou seja, capacidade de inspecionar e alterar suas próprias definições em tempo de execução - DSL normalmente envolve criar e inspecionar código, e sem reflexão decente não dá pra fazer metaprogramação&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Metaprogramação, ou seja, código que gera código - Muito da DSL na verdade é fazer com que pouco código faça muita coisa, às vezes de maneiras pouco convencionais. Para isso sua linguagem precisa conseguir criar código "on the fly" sem grandes maracutaias, porque afinal, você já vai estar fazendo maracutaias, aí a metaprogramação fica maracutaia ao quadrado :p&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Closures (ou lambdas) - Permitir passar blocos de código pra cima e pra baixo são essencias para você codificar em um ponto e poder executar em outro, normalmente após preparar o terreno para a execução da closure&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Sintaxe flexível - Não é essencial, mas ajuda a vc criar uma DSL simples. Sintaxes rígidas limitam a maneira com a qual você pode se expressar nas DSLs e elas acabam ficando mais complicadas sem necessidade. Um exemplo desse princípio é a tal da &lt;a href="http://martinfowler.com/bliki/FluentInterface.html"&gt;"interface fluente"&lt;/a&gt;. Sem um sintaxe flexível, ela fica meio canhestra.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Classes abertas - Isso é uma extensão da "Reflexão", na verdade é permitir que você possa redefinir tipos básicos como String, Integer e outros. Se você olhar a tal da "interface fluente" vai ver que com classes abertas ficaria bem mais fácil criá-las&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;Tem gente que acha que uma linguagem de programação que permita essas coisas deveria ser queimada, triturada, empalada e que todos que programam nela são hereges que deveriam queimar no Inferno de Knuth.&lt;br /&gt;&lt;br /&gt;No final, tenho uma teoria (grandes coisa minhas teorias, mas como o blog é meu, vou postar). Tenho a teoria que, na verdade, Orientação a Objeto é uma maneira de criar DSLs internas, mas sem que pensemos em termos de linguagem. Toda boa API OO me lembra muito DSLs.&lt;br /&gt;&lt;br /&gt;Acho que nosso trabalho é puramente criar abstrações, quanto melhores, mais somos produtivos e menos dores de cabeça temos. Em um texto, as abstrações são tão maiores quanto mais técnico é o texto, onde uma única palavra (por exemplo: "Façade") abstrai uma idéia um bocado complexa. Do nosso lado, criar classe, métodos e refatorar código  é basicamente melhorar as abstrações.&lt;br /&gt;&lt;br /&gt;Estou certo? Estou errado? Não importa muito, isso é mais retórico do que prático, no final. Mas esse tipo de pensamento muda um pouco minha maneira de encarar o que eu aprendo de novo...&lt;br /&gt;&lt;br /&gt;Editado: um "PS" aqui... esse artigo estava rascunhado no meu blog faz quase um ano... tou ficando velho e preguiçoso, e talvez um pouco lelé...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-8585298871890345690?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/8585298871890345690/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=8585298871890345690' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/8585298871890345690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/8585298871890345690'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2007/02/o-que-preciso-para-dsls.html' title='O que é preciso para DSLs?'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-1334328495827115536</id><published>2008-01-10T14:49:00.000-02:00</published><updated>2008-01-10T15:00:01.219-02:00</updated><title type='text'>Desgaste de informação</title><content type='html'>Hoje me deparei com uma situação que todo mundo passa, conhece, mas parece que ninguém toma medidas para conter o problema: quanto mais gente no meio entre a fonte de informação e o utilizador (EU!), pior a informação vai ficando.&lt;br /&gt;&lt;br /&gt;Cliente pede uma feature -&gt; Relacionamento com cliente repassa para Gerente de projeto -&gt; Gerente de projeto passa para Analista -&gt; Analista passa para desenvolvedor.&lt;br /&gt;&lt;br /&gt;Nesse caminho, o que o cliente pediu já foi interpretado de maneiras diferente QUATRO vezes (Relacionamento, Gerente, Analista e Desenvolvedor). Em cada interpretação a informação sofreu um certo desgaste, detalhes se perderam e o pior: detalhes que podem ser irrelevantes foram adicionados.&lt;br /&gt;&lt;br /&gt;Esse é de longe o maior problema da informática, depois da comunicação falha (que é relacionada, mas não é a mesma coisa). Alguém sabe se existe alguma área que estuda o que acontece com a informação?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-1334328495827115536?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/1334328495827115536/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=1334328495827115536' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/1334328495827115536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/1334328495827115536'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2008/01/desgaste-de-informao.html' title='Desgaste de informação'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-8809168785220954547</id><published>2007-12-20T17:27:00.001-02:00</published><updated>2007-12-20T17:37:45.319-02:00</updated><title type='text'>Closures para quê?</title><content type='html'>&lt;blockquote&gt;&lt;br /&gt; &lt;p&gt;“Beware of the Turing tar-pit in which everything is possible but nothing of interest is easy.”—Alan Perlis, “Epigrams on Programming”&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;(Esse artigo tem exemplos em Java e Ruby. Estou ignorando as sutis diferenças entre closures e blocos de código no Ruby)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Outro dia, num papo nerd com um colega (“O Francês”), ele me disse que não via &lt;del&gt;nenhuma utilidade para closures&lt;/del&gt; com bons olhos a inclusão de Closures no Java. &lt;del&gt;Que até já tinha olhado e brincado um pouco, mas que tudo que closures fazem é perfeitamente possível de fazer sem usá-las.&lt;/del&gt;(É... ele me fez corrigir o texto :) )&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Bom, ficou bem difícil argumentar aquilo no momento. Realmente, tudo que se pode fazer com closures também é possível fazer sem, da mesma maneira que é possível escrever um programa web em C (muita gente ainda faz e adora) ou escrever um aplicativo comercial em Assembly.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Depois dessa conversa comecei a tentar catalogar usos interessantes de closures. Pode ser que isso não convença ninguém de que são úteis, mas ao menos me serviu para organizar minhas próprias idéias. A seguir listo uma série de usos bem interessantes e bastante comuns de closures.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Bom, minha intenção não é explicar o que são closures – para isso o Akita tem um &lt;a href="http://www.akitaonrails.com/2007/11/30/anatomia-de-ruby-blocks-closures"&gt;excelente artigo&lt;/a&gt; – mas sim mostrar onde o uso de closures é legal.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Callbacks&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Talvez um dos melhores usos de closures sejam &lt;a href="http://en.wikipedia.org/wiki/Callback_%28computer_science"&gt;callbacks&lt;/a&gt;), ou seja, uma função que será executada posteriormente. Trocando em miúdos, é um código que queremos que seja executado quando algum evento acontece no sistema, por exemplo quando um botão é pressionado (conhecido como “events”...), quando uma aplicação inicia, quando algo é gravado ou alterado (“triggers” ou “listeners”...?), ou quando algum estado no sistema muda (“hooks”...?).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Cada linguagem tem sua solução para implementar callbacks, como ponteiros para funções (C e afins), a função como “cidadão de primeira classe” (Python, Javascript), classes anônimas (Java), “delegates” (C#) ou … closures, óbvio (que é solução para Smalltalk e Ruby)!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Cada um defende sua linguagem como gosta, mas independente disso, closures são muito práticas. Eu posso definir um callback de um botão da seguinte forma:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;(Código em Ruby/GTK2)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; # Cria um botão&lt;br /&gt; button = Gtk::Button.new("Click me")&lt;br /&gt;&lt;br /&gt; # Quando clicar, imprime "Cliquei no botão"&lt;br /&gt; button.signal_connect("clicked") { puts "Cliquei no botão" }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A parte do ’{ puts “Cliquei no botão” }’ é um closure. Nesse caso, é o código que vai ser usado quando o botão for ativado (“puts” é para imprimir o texto na console).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Simples assim, sem declarações, sem pré-requisitos, sem detalhes. Simplesmente “toma aqui esse código para executar depois”.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Iteradores (“visitors”)&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Estamos sempre processando coleções e iterando sobre elementos. Na maior parte dos casos, um simples loop resolve o problema, mas em outros, somos obrigados a repetir o mesmo loop em uma série de métodos diferentes pois as operações são parecidas, mas não idênticas. Em outros casos a lógica de iteração é um pouco mais complexa e se mistura com a lógica que processa cada elemento.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Closures são fantásticos para resolver esses problemas. Vejamos um exemplo que aconteceu recentemente comigo. Eu precisava substituir o mapeamento do Hibernate em umas 400 classes java. Fiz um pequeno método que encontrava as classes e para cada uma encontrada, eu aplicava a lógica de substituição.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;O método para percorrer as classes ficou assim:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; def on_java_classes&lt;br /&gt;   Find.find(@root) do |file_name|&lt;br /&gt;     yield(file_name) if file_name =~ /\/vo\/.*\.java$/&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Esse método percorre toda a árvore de diretórios abaixo de @root e se o arquivo encontrado estiver sob um diretório “vo” e terminar com ”.java”, o bloco de código é executado.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;E para usar o método para trocar um mapeamento fica assim:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; on_java_classes do |file_name|&lt;br /&gt;   change_hibernate_mapping(file_name)&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;É lógico que eu poderia usar esse loop e meu método tudo em um bolo só, mas agora eu tenho um método genérico que me permite percorrer essas classes e executar o que eu quiser com elas &lt;em&gt;sem duplicar a lógica que itera sobre as classes&lt;/em&gt;. Posso, por exemplo, listar todos os mapeamentos, contar quantos “VOs” tenho, vasculhar se existem mapeamentos fora do padrão e outras coisas do tipo.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;A coisa fica tão transparente, que posso usar coisas como “next” (para processar o próximo elemento) e “break” (para parar a iteração) dentro dos closures e eles funcionam como esperado. Por exemplo, se eu quisesse apenas fazer um teste com os 10 primeiros arquivos, poderia colocar um “break” no meio, dessa forma:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   i = 1&lt;br /&gt;   on_java_classes do |file_name|&lt;br /&gt;       break if i &amp;gt; 10 # passou de 10 arquivos, caia fora do método&lt;br /&gt;       change_hibernate_mapping(file_name)&lt;br /&gt;       i += 1&lt;br /&gt;   end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Processamento “durante”&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Quase todas as operações que fazemos de IO precisam de algo para “abrir” a operação e garantir que ela seja “fechada” quando terminamos o que precisamos. Isso vale para streams, arquivos, sockets, transações, record sets e sei lá mais quantas coisas.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Isso implica em uma lógica bastante incoveniente que costuma ser repetida à exaustão: abra conexão, execute o que precisar, garanta que foi fechado (normalmente com um bloco para tratamento de exceção).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Conexões com bancos de dados são particularmente um porre, porque costumam abrir e fechar vários objetos.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Com closures, resolvemos isso com facilidade. Aqui um exemplo de como se usar o &lt;a href="http://ruby-dbi.rubyforge.org/"&gt;Ruby-DBI&lt;/a&gt; da maneira tradicional. O exemplo foi tirado da própria página do Ruby-DBI, mas com o tratamento de exceções apropriado.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; require 'dbi'&lt;br /&gt;&lt;br /&gt; dbh = nil&lt;br /&gt;&lt;br /&gt; begin&lt;br /&gt;   dbh = DBI.connect('DBI:Mysql:test', 'testuser', 'testpwd')&lt;br /&gt;&lt;br /&gt;   sth = nil&lt;br /&gt;   begin&lt;br /&gt;     sth = dbh.prepare('select * from simple01')&lt;br /&gt;     sth.execute&lt;br /&gt;&lt;br /&gt;     while row = sth.fetch do&lt;br /&gt;       p row&lt;br /&gt;     end&lt;br /&gt;&lt;br /&gt;   # Precisamos tentar fechar o statement, não importa qual o erro&lt;br /&gt;   ensure&lt;br /&gt;     sth.finish if sth&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt; # Precisamos tentar fechar a conexão também&lt;br /&gt; ensure&lt;br /&gt;   dbh.disconnect if dbh&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Com closures, a coisa fica bem mais simples. Podemos criar coisas para serem executadas &lt;em&gt;ao redor&lt;/em&gt; do bloco de código e simplesmente esquecermos da necessidade de ficar abrindo e fechando objetos. (Aviso: o DBI já tem métodos que funcionam assim).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Primeiro, criamos dois métodos:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; # Esse método cuida de abrir a conexão, executar algo&lt;br /&gt; # e garantir q a conexão seja fechada.&lt;br /&gt; def connect(uri, user, password)&lt;br /&gt;   dbh = nil&lt;br /&gt;   begin&lt;br /&gt;     dbh = DBI.connect(uri, user, password)&lt;br /&gt;     yield(dbh)&lt;br /&gt;   ensure&lt;br /&gt;     dbh.disconnect if dbh&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; # Esse método executa algo para cada registro recuperado&lt;br /&gt; # em um SQL. Ele cuida de fechar os objetos envolvidos&lt;br /&gt; # no processo. &lt;br /&gt; def for_each_record_in(dbh, sql)&lt;br /&gt;   sth = nil&lt;br /&gt;   begin&lt;br /&gt;     sth = dbh.prepare(sql)&lt;br /&gt;     sth.execute&lt;br /&gt;&lt;br /&gt;     while row = sth.fetch do&lt;br /&gt;       yield(row)&lt;br /&gt;     end&lt;br /&gt;   ensure&lt;br /&gt;     sth.finish if sth&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;E agora, o código para fazer exatamente a mesma coisa que o primeiro exemplo passa a ser:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; connect('DBI:Mysql:test', 'testuser', 'testpwd') do |connection|&lt;br /&gt;   for_each_record_in(connection, 'select * from simple01') do |record|&lt;br /&gt;     p record&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Toda vez que precisamos de um código “de preparação” e um código “de finalização” podemos usar closures para poupar trabalho. Além das óbvias vantagens de redução de duplicação, fica bem mais difícil esquecer de fechar algo :)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Só para constar, existe um padrão pra isso, é o “Open During” do Kent Beck. Está no livro dele de “Best Smalltalk Patterns”.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Lógica condicional&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Não somente de “ifs” e “switches” vivem os condicionais. Com closures, podemos simular condicionais para condições mais complexas.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Digamos que eu tenha um analisador de texto que me retorne palavrões encontrados em um HTML qualquer. Caso eu encontre qualquer palavrão, quero mostrar uma mensagem de erro.Uma maneira de fazer isso seria assim:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; # O método "find_dirty_words me retorna a coleção de palavrões&lt;br /&gt; # encontrados no texto.&lt;br /&gt; dirty_words = html.find_dirty_words&lt;br /&gt; unless words.empty?&lt;br /&gt;   show_error_message(html, dirty_words, "Bad, bad, no cookies for you.")&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Por outro lado, posso criar isso em um método com closures dessa maneira:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; class Html&lt;br /&gt;   def when_dirty_words_found&lt;br /&gt;     dirty_words = html.find_dirty_words&lt;br /&gt;     yield(dirty_words) unless words.empty?&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;E agora, posso usar assim:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; html.when_dirty_words_found do |dirty_words|&lt;br /&gt;   show_error_message(html, dirty_words, "Bad, bad, no cookies for you.")&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Aliás, agora posso executar qualquer lógica com esses palavrões. Posso tentar limpá-los, contar sua frequência (estatística?), colocá-los em uma lista negra e assim por diante.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;O melhor exemplo real de execução condicional com closures talvez seja o &lt;a href="http://www-128.ibm.com/developerworks/java/library/j-cb08016/#N101FF"&gt;uso de REST no Rails&lt;/a&gt; (veja o método “respond_to” no “Listing.5”).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Domain Specific Language&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Arrisco dizer que é impossível implementar uma boa DSL Interna (definição segundo &lt;a href="http://martinfowler.com/articles/languageWorkbench.html#InternalDsl"&gt;Martin Fowler&lt;/a&gt;) sem closures.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Isso porque eles permitem uma grande flexibilidade na sintaxe, permitindo que você use os closures como blocos de código que podem ser armazenados, executados, repetidos, omitidos, reestruturados, postergados ou quaisquer que sejam as transformações necessárias para sua DSL funcionar.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Exemplos ótimos de DSL são o &lt;a href="http://builder.rubyforge.org/"&gt;XML Builder&lt;/a&gt; e o &lt;a href="http://rake.rubyforge.org/"&gt;Rake&lt;/a&gt;. Com pouco esforço você conseguem sintaxes perfeitas que se encaixam dentro do Ruby como se fosse parte da linguagem.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Veja por exemplo, como construir um xml com o XML Builder:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; require 'builder'&lt;br /&gt;&lt;br /&gt; xml = Builder::XmlMarkup.new(:target=&amp;gt;STDOUT, :indent=&amp;gt;2)&lt;br /&gt; xml.usuario(:id =&amp;gt; 127) do&lt;br /&gt; xml.nome("Ronie")&lt;br /&gt; xml.sobrenome("Uliana")&lt;br /&gt; xml.idade(31, :type =&amp;gt; "integer")&lt;br /&gt; xml.preferencias do&lt;br /&gt;   ["strogonoff", "lasanha", "bolo de carne"].each do |item|&lt;br /&gt;     xml.comida(item)&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Isso gera o seguinte xml:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;usuario id="127"&amp;gt;&lt;br /&gt; &amp;lt;nome&amp;gt;Ronie&amp;lt;/nome&amp;gt;&lt;br /&gt; &amp;lt;sobrenome&amp;gt;Uliana&amp;lt;/sobrenome&amp;gt;&lt;br /&gt; &amp;lt;idade type="integer"&amp;gt;31&amp;lt;/idade&amp;gt;&lt;br /&gt; &amp;lt;preferencias&amp;gt;&lt;br /&gt;   &amp;lt;comida&amp;gt;strogonoff&amp;lt;/comida&amp;gt;&lt;br /&gt;   &amp;lt;comida&amp;gt;lasanha&amp;lt;/comida&amp;gt;&lt;br /&gt;   &amp;lt;comida&amp;gt;bolo de carne&amp;lt;/comida&amp;gt;&lt;br /&gt; &amp;lt;/preferencias&amp;gt;&lt;br /&gt;&amp;lt;/usuario&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Nesse exemplo, cada aninhamento é um closure, e o builder os rastreia para saber como montar o xml. Muito simples e prático, na verdade.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Generators&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Esse eu confesso que nunca me resolveu nenhum grande problema até o momento, mas é uma técnica boa para se ter no cinto de utilidades.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Basicamente, é uma função que retorna outra, a primeira “configura” a segunda. Um exemplo simples que achei foi esse aí abaixo. Ele gera um closure que adiciona sempre o mesmo número ao número passado como parâmetro. Por exemplo, gero uma closure que adiciona sempre 5 a qualquer número que eu passe para ela. No exemplo abaixo criei dois desses, um “adicionador de cincos” e um “adicionador de oitos”.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;O exemplo é meio bobo, mas se você pensar um pouco vai achar possibilidades interessantes para isso. Não sei se essas idéias seriam práticas, mas com certeza serão interessantes.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; def create_adder(number)&lt;br /&gt;   lambda {|x| number + x}&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; add5 = create_adder(5)&lt;br /&gt; add8 = create_adder(8)&lt;br /&gt;&lt;br /&gt; puts add5.call(10) # retona 15, ou seja, 10 + 5&lt;br /&gt;&lt;br /&gt; # "add5.call(10)" é a mesma coisa que fazer add5&amp;lt;sup&amp;gt;&amp;lt;a href="#fn10"&amp;gt;10&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;&lt;br /&gt; # Pra facilitar, vamos usar essa notação nos exemplos abaixo&lt;br /&gt; puts add8[ 30 ] # retona 38, ou seja, 30 + 8&lt;br /&gt; puts add8[ add5[ 1 ] ] # retona 14, ou seja, 1 + 5 + 8&lt;br /&gt; puts add5[ add5[ add5[ 0 ] ] ] # retorna 15... adivinha porquê :)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Um bocado complicado de entender? Bom, “lambda” é uma função que pega um bloco de código (o que está entre ”{}”) e retonar uma closure de verdade. Na prática, estou retornando uma função que será atribuída a uma variável para ser executada mais tarde. A parte legal é que essa função é “configurada” com o parâmetro “number”.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Esse é realmente embaçado, acho que fazer um equivalente em Java pode ajudar alguns (só espero não complicar o resto do povo)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; public class ClosureExample {&lt;br /&gt;&lt;br /&gt;   public static interface Adder {&lt;br /&gt;     public int call ( int x );&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public static Adder createAdder ( final int number ) {&lt;br /&gt;     return new Adder () {&lt;br /&gt;       public int call ( int x ) {&lt;br /&gt;         return x + number;&lt;br /&gt;       }&lt;br /&gt;     };&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public static void main ( String [] args ) {&lt;br /&gt;     Adder add5 = createAdder ( 5 );&lt;br /&gt;     Adder add8 = createAdder ( 8 );&lt;br /&gt;&lt;br /&gt;     System.out.println ( add5.call ( 10 ) );&lt;br /&gt;     System.out.println ( add8.call ( 30 ) );&lt;br /&gt;     System.out.println ( add8.call ( add5.call ( 1 ) ) );&lt;br /&gt;     System.out.println ( add5.call ( add5.call ( add5.call ( 0 ) ) ) );&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Com uma pequena variação disso da para fazer acumuladores. Ou seja, uma função que preserva a memória cada vez que é executada.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; def create_accum&lt;br /&gt;   memory = 0&lt;br /&gt;   lambda{|x| memory += x}&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; accum = create_accum&lt;br /&gt; puts accum[ 5 ] // retorna 5&lt;br /&gt; puts accum[ 10 ] // retorna 15&lt;br /&gt; puts accum[ 130 ] // retorna 145&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Conclusão&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Closures são muito úteis para várias tarefas comuns da computação. Não é porque sua linguagem favorita não tem e você acha que se vira muito bem nela que Closures deixam de ter sua utilidade. :)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Fechando o artigo do mesma maneira que abri:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt; &lt;p&gt;“Beware of the Turing tar-pit in which everything is possible but nothing of interest is easy.”—Alan Perlis, “Epigrams on Programming”&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Have a nice coding! :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-8809168785220954547?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/8809168785220954547/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=8809168785220954547' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/8809168785220954547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/8809168785220954547'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2007/12/closures-para-qu.html' title='Closures para quê?'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-5422772668135694274</id><published>2007-10-08T15:26:00.000-03:00</published><updated>2007-10-08T15:34:20.373-03:00</updated><title type='text'>Off-Topic: O Ronie foi abduzido (de novo!!!!)</title><content type='html'>Só pra avisar... Vários colegas andam tentando me contactar e nada d'eu responder. Não fiquei mal-educado de repente, não mais que o habitual, pelo menos. Mas estamos numa das fases mais críticas do projeto, bem no esquema "ou vai ou racha".&lt;br /&gt;&lt;br /&gt;Com isso, estou há algumas semanas sem comer ou dormir muito bem, sem abrir meu e-mail pessoal, sem postar no RubyOnBr, sem responder Skype ou Messenger e coisas do tipo. Sei que é uma tremenda viadagem, mas nesse ponto, quero fazer esse projeto funcionar.&lt;br /&gt;&lt;br /&gt;Dado esse estado de "podreira-meio-aviadado-não-responde-ao-maldito-e-mail" que eu me encontro, por favor, peço sua compreensão e uma doação pra pagar meu analista, ou então um abraço coletivo.&lt;br /&gt;&lt;br /&gt;Juro que antes de Dezembro volto a responder os e-mails.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-5422772668135694274?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/5422772668135694274/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=5422772668135694274' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5422772668135694274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/5422772668135694274'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2007/10/off-topic-o-ronie-foi-abduzido-de-novo.html' title='Off-Topic: O Ronie foi abduzido (de novo!!!!)'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-7616836149335793642</id><published>2007-09-23T11:20:00.000-03:00</published><updated>2007-09-23T13:12:24.028-03:00</updated><title type='text'>Pra que ORM se não se usa OO?</title><content type='html'>Pra que usar um sistema de mapeamento objeto-relacional se você trata seus objetos como dados?&lt;br /&gt;&lt;br /&gt;Objeto sem comportamento é exatamente igual a uma estrutura de dados. Reza o mito que você deve ter "classes de negócio" que executam regras. Bom... essas classes fazem coisas com suas classes sem comportamento... então... qual a diferença disso para uma função PHP que manipula linhas em tabelas?&lt;br /&gt;&lt;br /&gt;Bom, UMA das diferenças, certamente, é que usamos um monte de traquitanas a mais para obter os dados. Outra é que ganhamos alguns métodos convenientes para buscar dados relacionados. Mas fora isso, qual o ganho?&lt;br /&gt;&lt;br /&gt;Sinceramente, mais de uma vez vejo gente defendendo com unhas e dentes frameworks de ORM e usando ele para fazer sistemas que são basicamente, um PHP com mais camadas. E batem no peito pra dizer que é um "Sistema Grande".&lt;br /&gt;&lt;br /&gt;Veja, não tenho nada contra ORM. É algo absolutamente necessário se você usa um sistema &lt;span style="font-weight: bold; font-style: italic;"&gt;realmente &lt;/span&gt;OO... Caso contrário, é só um trambolho a mais para cuidar.&lt;br /&gt;&lt;br /&gt;Como vejo gente demais fazendo isso, eu devo estar deixando escapar alguma coisa muito importante. Mas alguém me diga o quê.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-7616836149335793642?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/7616836149335793642/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=7616836149335793642' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/7616836149335793642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/7616836149335793642'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2007/09/pra-que-orm-se-no-se-usa-oo.html' title='Pra que ORM se não se usa OO?'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-3128149986882513306</id><published>2007-09-12T23:15:00.001-03:00</published><updated>2007-09-12T23:19:11.266-03:00</updated><title type='text'>Esbarrando com gente conhecida...</title><content type='html'>Ontem (ou foi anteontem?), entrevistei o Kenobi (posta muito no GUJ) para uma vaga na empresa em que eu trabalho. Fiz a maior confusão com as vagas e acabei falando a vaga errada pra ele :( ê vida besta.&lt;br /&gt;&lt;br /&gt;É um cara bastante seguro de si, só acho que causou uma má impressão na moça que comecou a conversa com ele.&lt;br /&gt;&lt;br /&gt;Engraçado como a gente vive esbarrando com gente "virtualmente" conhecida. Acho que o mundo da informática (pelo menos no Brasil) é menor do que eu suspeitava... ou então preciso viajar mais para o resto do país e sair um pouco da Cidade da Garoa :p&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-3128149986882513306?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/3128149986882513306/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=3128149986882513306' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/3128149986882513306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/3128149986882513306'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2007/09/esbarrando-com-gente-conhecida.html' title='Esbarrando com gente conhecida...'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-8389602401154132205</id><published>2007-09-12T19:39:00.001-03:00</published><updated>2007-09-12T20:07:28.190-03:00</updated><title type='text'>Melhorando o detector de "bullshit"</title><content type='html'>Sabe quando você está lendo um texto, não chegou nem na metade e pensa: "bullshit".&lt;br /&gt;&lt;br /&gt;Poisé, faz um tempo tenho um "detector mental de bullshit" pra esse tipo de coisa. Funciona igual aos "code bad smells": você está numa conversa, ou está lendo algo, e algumas palavras fazer o detector tilintar. Aí você lê com mais atenção pra ver se é balela mesmo ou se tem fundamento.&lt;br /&gt;&lt;br /&gt;Tem algumas palavras que fazem o detector simplesmente gritar :) Muitas delas juntas, então, quase dão dor de cabeça!&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Enterprise (top top!)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Arquitetura (ou pior, um texto todo em português, mas usando o termo em inglês)&lt;/li&gt;&lt;li&gt;Flexível&lt;/li&gt;&lt;li&gt;Robusto&lt;/li&gt;&lt;li&gt;Ágil (todo mundo virou ágil depois que isso virou &lt;a href="http://en.wikipedia.org/wiki/Power_word"&gt;power word&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Escalável&lt;/li&gt;&lt;li&gt;Performance (principalmente se não vem com NENHUMA medição)&lt;/li&gt;&lt;li&gt;"O correto é" ("correto" depende muuuuito do que você está fazendo)&lt;/li&gt;&lt;li&gt;Grande porte (parece que o povo mistura "muitas regras de negócio", "muitos usuários" ou "transações bagaraio" sem muita discriminação)&lt;/li&gt;&lt;li&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Entre outras...&lt;br /&gt;&lt;br /&gt;Recentemente fiz um "upgrade" no detector. Adicionei uma regra: "&lt;span style="font-weight: bold;"&gt;discussões sobre méritos de tecnologias em que o cara dá argumentos sobre performance&lt;/span&gt;". Muito, mas muito raramente mesmo, isso tem algum embasamento maior do que mero "achismo". E, &lt;span style="font-weight: bold;"&gt;pessoalmente&lt;/span&gt;, "rápido o suficiente" já está bom.&lt;br /&gt;&lt;br /&gt;Por outro lado, tem palavras que entram no "white list" e aliviam a coisa:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Teste&lt;/li&gt;&lt;li&gt;Padrão ou Anti-padrão&lt;/li&gt;&lt;li&gt;Pragmático&lt;/li&gt;&lt;/ul&gt;É... minha white list tá pequena! :D&lt;br /&gt;&lt;br /&gt;E aí? Alguém tem outras palavras que fazem o "detector de bullshit" tocar? (Garanto que tem gente que coloca a palavra "Rails" na lista :D)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-8389602401154132205?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/8389602401154132205/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=8389602401154132205' title='6 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/8389602401154132205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/8389602401154132205'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2007/09/melhorando-o-detector-de-bullshit.html' title='Melhorando o detector de &quot;bullshit&quot;'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8900086.post-7801857861966050600</id><published>2007-09-10T14:23:00.000-03:00</published><updated>2007-09-10T14:29:23.305-03:00</updated><title type='text'>Da série "Notas Mentais": Pessoas Sérias</title><content type='html'>Não consigo levar a sério pessoas que se levam muito a sério...&lt;br /&gt;&lt;br /&gt;Por quê? Bom, cedo ou tarde, vamos todos virar adubo pra grama, que é a mesma função que um belo monte de merda faz. Aliás, o "belo monte de merda" deve ser um adubo melhor do que nós seremos... :p&lt;br /&gt;&lt;br /&gt;Aí que está a parte complicada... O cara vem todo importante, botando marra e arrotando peru... aí me vem esse pensamento em mente e não consigo ficar sério. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8900086-7801857861966050600?l=mecanicamente.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mecanicamente.blogspot.com/feeds/7801857861966050600/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8900086&amp;postID=7801857861966050600' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/7801857861966050600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8900086/posts/default/7801857861966050600'/><link rel='alternate' type='text/html' href='http://mecanicamente.blogspot.com/2007/09/da-srie-notas-mentais-pessoas-srias.html' title='Da série &quot;Notas Mentais&quot;: Pessoas Sérias'/><author><name>Ronie Uliana</name><uri>http://www.blogger.com/profile/12434188987754512726</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='03354937145935936619'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>