Essa discussão continuou por alguns posts, cada qual em seu blog e diversas outras pessoas da comunidade avaliaram o que Joel estava querendo dizer. Pessoas como Avi Bryant e até mesmo Obie Fernandez, da ThoughtWorks.
Como disse antes, em Evolução pela Concorrência, essa é a típica competição onde não saem vencedores pois Joel, em vez de criar críticas construtivas – e até mesmo soluções – preferiu debandar para o time que descrevi como irrelevantes: que apenas sabem xingar. Pior, Joel fez isso para se autopromover, como verão a seguir.
Tudo começou com o post Language Wars (Guerra de Linguagens), no site Joel on Software, em 1 de setembro, quando descreveu o e-mail de um colega perguntando em qual plataforma desenvolver. A velha dúvida “Java ou C#”, “C# ou PHP”. Joel colocou o que achava em seu site. No mesmo dia David Hansson escrevia Fear, Uncertain, and Doubt by Joel Spolsky (Medo, Incerteza e Dúvida por Joel Spolsky) na Loud Thinking. Ele descreveu o artigo de Joel como “a mais pura forma de FUD que já vi contra Ruby on Rails. Nem mesmo os melhores caras de Java conseguem acompanhar Joel nisso”. Veja o trecho mais importante do post do David:
Fear (Medo):
Eu tenho medo de Ruby porque (1) ele demonstra uma absurda antipatia contra Unicode e (2) é conhecido por ser lento, então se você se tornar o próximo MySpace, estará comprando 5 vezes mais máquinas do que o cara de .NET no fim do corredor. Essas coisas podem eventualmente ser consertadas mas por enquanto, você pode arriscar com Ruby em projetos pequenos, mas não em coisas Enterprisy, onde Alguém-Será-Demitido.
Uncertainty (Incerteza):
Eu não tenho muita certeza que você não enfrentará problemas de escala, ou problemas interfaceando com algum velho legado, ou problemas encontrando programadores que possam entender o código, ou o que mais. Então, enquanto Ruby on Rails é a resposta divertida, e sim, ouvi falar da 37signals que estão fazendo aplicativos muito interessantes em Ruby on Rails e fazendo muito dinheiro, mas essa não é a escolha segura por pelo menos mais um ano ou seis.
Doubt (Dúvida):
Ruby é uma linguagem maravilhosa e tenho certeza que você pode se divertir muito desenvolvendo aplicativos nele. De fato, se quiser fazer alguma coisa não-missão-crítica, tenho certeza que se divertirá, mas para as Coisas-de-Negócio-Sérias você realmente tem que reconhecer que simplesmente não existe muita experiência no mundo construindo grandes sistemas web de missão crítica em Ruby on Rails.
Isso é verdadeiro ouro. Ora, ora. Alguns podem acusar Joel de estar um pouco atrasado à festa do FUD. Que a maioria dos convidados já foram para casa. Mas o que são alguns anos atrasado? Não faz muito tempo que Joel imaginava que VBScript era uma linguagem razoável para desenvolvimento Web. Ou que essas novas coisas chamadas “exceptions” não escalam.
Mas vai ficando melhor. Joel termina com um prêmio tão bom que você pode não acreditar a não ser imaginar se ele está puxando seu pé ou não. Em resumo, Ruby e Rails são ambos imaturos, certo? Uma década para a linguagem, mais ou menos dois anos para o framework. Dezenas, se não centenas de milhares de programadores expostos entre os dois.
Ok, eu engulo que isso pode parecer “imaturo” se estivermos comparando quantidade de programadores ou aplicações em produção contra, digamos, Java ou PHP.
Agora, segurem-se e cheguem ao parágrafo final:
FogBugz é escrito em Wasabi, um dialeto de Basic, muito avançado, baseado em programação funcional, com fechamentos e lambdas e active records no estilo Rails, que pode ser compilado em VBScript, JavaScript, PHP 4 ou PHP 5. Wasabi é uma linguagem privada, escrita dentro de casa, por um de nossos melhores desenvolvedores e foi otimizado especificamente para desenvolver FogBugz; o compilador do Wasabi em si é escrito em C#.
Portanto, Joel e seus amigos inventaram sua própria linguagem, que precisa razoavelmente compilar para 3 e meio outras diferentes. Sim, eles estão construindo suas Coisas-de-Negócio-Sérias em uma pequena, linguagem fechada. Então, por favor, faça o que digo, não o que eu faço, droga. E pegue alguma coisa famosa e “segura”.
Isso termina a primeira resposta de David, mas ele vai mais longe. No mesmo dia, no post Was Joel’s Wasabi a joke? (O Wasabi de Joel foi uma piada?). Onde algumas pessoas começaram a imaginar se esse negócio de Wasabi deveria ser apenas uma piada de Joel. Mas depois o próprio Joel escreveu tanto para David quanto em seu site explicando que Wasabi é real. Alguns poderiam imaginar que ele está louco.
Porém, isso fica claro se imaginarmos que publicidade negativa é melhor que publicidade nenhuma. Muitos odiarão Joel, mas muitos poderão se interessar. É a mesma estratégia do Spam. E para aqueles que podem estar concordando com Joel, David explicou:
Comentários rápidos nas duas reclamações originais que tinham algum mérito. Primeiro unicode. Sim, atualmente é menos simples do que poderia ser. Mas não é de forma alguma impossível. Todos os aplicativos da 37signals falam UTF-8. Temos pessoas de mais de 50 países usando Basecamp com conteúdo em suas linguagens nativas. Muitos aplicativos rodam internacionalizados também. Temos uma grande constituição de Rails no Japão, Russia e todos os lugares que fazem isso funcionar. Mas claro, poderia ser mais simples e poderá ser em breve.
Segundo, velocidade. Rails é, para a maior parte dos aplicativos Web, Rápido-o-Suficiente. Temos sites servindo milhões de páginas dinâmicas por dia. Se você acabar com uma página inicial à la Yahoo ou Amazon, provavelmente um framework comum, em QUALQUER linguagem, vai te fazer muito melhor. Você provavelmente terá que criar seu próprio. Mas claro, também gosto de ciclos livres de CPU. Apenas tendencio priorizar mais ciclos livres de desenvolvedores e estou disposto a trocar o primeiro pelo segundo.
E isso é verdade, em meu livro eu mesmo descrevo como fazer Unicode e Internacionalização funcionar com técnicas simples. Outra coisa: não existe mágica que compra no mercado. Para 80% das coisas Rails será excelente, assim como qualquer outro framework. Mas nenhum, jamais conseguirá cumprir 100% de tudo.
A batalha não terminou. Em 12 de setembro, Joel voltou ao FUD. Desta vez tentando atacar pelo canto técnico no seu post Ruby Performance Revisited (Performance de Ruby Revisto). Desta vez resolveu dizer que não está preocupado com a performance de Rails mas sim com a de Ruby. Este post é para desenvolvedores, sugiro que vocês revejam seus conceitos de compiladores. Eis seu argumento:
Sem saber muito da implementação de Ruby, eu chutaria que o maior problema é no late binding, e especialmente no duck typing, que previne inferência de tipo ou strong typing, o que significa que chamadas a função serão sempre lentas porque você nunca terá alguma coisa compilada ao ponto onde uma chamada a função é somente uma simples instrução CALL (em x86) … você sempre precisa explorar o objeto, possivelmente percorrendo uma tabela hash para encontrar a função que quer chamar. Chamar métodos em objetos é realmente, realmente, realmente comum, especialmente em linguagens puramente OO, e aquele pequeno trecho de código precisa chegar pelo menos a um CALL indireto na CPU para Ruby oferecer a mesma performance que linguagens onde o tipo do objeto pode ser determinado em tempo de compilação e onde, portanto, a instrução que você quer chamar pode ser consultada tanto em tempo de compilação (como em C) ou com uma simples indireção por um simple vtable (como em C++).
Muita gente cai nesse tipo de argumento por ter um pseudo-conhecimento (aqueles que “acham que sabem” mas não sabem nada) de como funciona uma máquina virtual, gargage collector, linguagem fortemente tipada (strong typed), linguagem estaticamente tipada (statically typed).
No meu livro, quando explico o que é Ruby, por acaso, reservo algumas páginas justamente para desmistificar esse conceito, de que Ruby é uma linguagem dinamicamente tipada (duck typed, na nomenclatura Ruby que usamos: “se anda como um pato, fala com um pato e parece um pato é porque deve ser um pato”) mas nem por isso deixa de ser fortemente tipada, como muitos acreditam. Javascript é fracamente tipado, mas Ruby é tão fortemente tipado quanto Java ou C#, mas Ruby é dinâmico e Java é estático. Parece conversa de louco, eu sei, mas isso é importante.
No mesmo dia, duas pessoas vieram direto a esse ponto, primeiro Avi Bryant no seu post Ruby e Strongtalk, em seguinda Obie Fernandez no seu post Joel is wrong, Strongtalk exciting (Joel está errado, Strongtalk é excitante), resumindo e dando credibilidade a Avi, dizendo:
Como Avi Bryaing aponta, a afirmação anterior de Joel está simplesmente errada: “uma implementação apropriada de uma linguagem que usa duck typing dará chamadas a método com um simples jump (JMP) mais um simples compare (CMP), 95% do tempo. Não existe necessidade de indireção por vtable, o que significa que isso é geralmente mais rápido do que C++, porque a previsão de branch funciona e o pipeline não trava”.
Levando em conta a expertise da Avi com smalltalk eu acredito nele – mais à frente no mesmo post ele menciona que a Sun liberou o código-fonte de StrongTalk, descrito como “de longe a implementação rápida de Smalltalk já visto”.
Uma das vantagens de StrongTalk é seu sistema de tipagem estática e forte para Smalltalk. “Aha!” você poderia estar proclamando, “por isso que ele é tão rápido, certo?”. NÃO.
De acordo com Avi:
A coisa que é interessante sobre Strongtalk é que ele permite anotação de tipo estático, opcionalmente, mas o otimizador completamente ignora isso: seu código roda com a mesma velocidade se usar somente duck typing ou se tiver tudo tipado estaticamente. Não é porque os desenvolvedores foram folgados – seu objetivo foi produzir o sistema mais rápido possível. O que acontece é que sua implementação dinâmica já era rápido o suficiente para que informações estáticas já não fizessem mais diferença.
Eu acho esse tipo de desenvolvimento muito excitante e promissor para o futuro de Ruby como uma linguagem viável com o tipo de adoção que Java e .NET tem. Como Avi aponta, “a VM Strongtalk daria uma excelente base para a próxima geração de uma VM para Ruby. Dado que a Sun empregou alguns dos engenheiros originais do Strongtalk e acabou de contratar os caras do JRuby, talvez eles possam fazer isso acontecer?”.
Voltando ao post do Joel, além de tentar colocar de volta a hipótese de que uma linguagem estaticamente tipada deveria ser mais rápida do que uma dinamicamente tipada, também falou:
Entendo que existem planos de resolver os problemas de performance de Ruby com algum tipo de compilador para bytecode, o que será bom. Quando essas coisas acontecerem e Ruby começar a ter benchmarks competitivos ele será mais apropriado para mais tipos de aplicativos. Nesse meio tempo eu mantenho minha afirmação que ele não é apropriado para toda situação.
No dia seguinte, 13 de setembro, David retrucou esse último ponto no post Outsourcing the performance-intensive functions (Terceirizando funções de performance intensa), dizendo exatamente o que eu já disse antes: existem razões para termos mais de uma linguagem de programação à nossa disposição. E não é somente porque alguns gostam de usar chaves e outros de identação forçada. É porque são realmente bons em coisas diferentes.
Normalmente não discutimos os extremos. Não ouço muita gente afirmar que sistemas operacionais deveriam ser escritos em PHP. Ou que pequenas páginas de visita deveriam ser escritas em C.
Isso é verdade mesmo em aplicações simples. Yahoo recomenda PHP na superfície, mas usa C++ para a maior parte do back-end porque eles precisam conseguir alguns bilhões de page views por dia. Amazon também tem muita computação principal em C++ (e mesmo em Java), mas usa Perl e Mason para o front-end. Uma razoável divisão-de-trabalho nos maiores sites da internet.
Mas não precisamos ir à Lua para olhar uma rocha. No Basecamp, aceitamos uploads de fotos de pessoas no projeto. Apenas precisamos de uma imagem de 48×48 pixels de tamanho, mas muitas pessoas fazem uploads de imagens multi-megabytes, porque é o que tinham à disposição. Agora estamos completamente ferrados, certo? Ruby é absurdamente lento, então manipular imagens ao vivo teria nos levado a ficar de joelhos, certo? Aqui está nosso método:
system(“/usr/local/bin/convert #{escape(temp)}
-resize 48×48! #{escape(target)}”)
end
Posso ouví-los dizer: “Mas isso é trapacear!”. Claro que é! Trapacear é bom, trapacear funciona.
É uma das maravilhas de viver nas chamadas linguagens de script. Você não precisa inventar um modificador de imagens do zero. Alguém já vez um trabalho estelar em C. Você também não precisa inventar, digamos, um filtro Bayesiano do zero (usado em filtros inteligentes de e-mails spam baseado em estatística, mencionado como exemplo no artigo de Joel). Alguém provavelmente fez um ótimo trabalho em outra linguagem rápida que você pode apenas chamar.
Na maioria das vezes as pessoas institucionalizam a trapaça com uma “trapaça-leve”, com wrappers nativos sobre bibliotecas em C (por exemplo, JNI em Java ou PInvoke em .NET). Para modificar o tamanho de imagens, existe RMagick. Para chamadas a banco de dados, existe MySQL/Ruby. Droga, mesmo PHP começou sendo primariamente uma maneira amigável de chamar funções C.
A era das ilhas está acabada para a maioria dos cenários de desenvolvimento. Você não precisa fazer uma escolha definitiva. Em vez disso, você deve buscar toda a produtividade que conseguir nos casos comuns, então exportar os gargalos para pacotes existentes em linguagens mais rápidas ou construir sua própria extensão quando necessário.
Portanto, não deixe os gargalos (reais ou imaginários, normalmente o último) ditar sua escolha de ambiente de desenvolvimento. Temos um termo para isso e se chama “otimização prematura”. Eu ouço o sr. Knuth (Douglas Knuth, o lendário autor dos livros de algoritmos The Art of Computer Programming) colocar as pessoas em julgamento por violações extremamente grosseiras. E eu realmente espero que o sr. Spolsky esteja recebendo sua intimação para aparecer nos tribunais rápido.
Uma frase muito famosa de Knuth é: otimização prematura é a raíz de todo o Mal (ou pelo menos a maior parte).
Disse David, nesse post, que não mais responderá a provocações de Joel e até agora parece que o caso está encerrado. Joel cometeu o principal erro de todo crítico: nunca, jamais, em tempo algum acuse ou tire conclusões sendo ignorante ao assunto em questão. É como apoiar um Bush a atacar o Oriente Médio sem nem saber onde fica o Oriente Médio. É como apoiar incondicionalmente um Lula sem nem saber o que foi o mensalão.
Mesmo tendo uma grande quantidade de informações é muito difícil tirar uma conclusão definitiva. Entenda: podemos chegar a muitas conclusões, mas não necessariamente a uma resposta definitiva. Isso é difícil. Em um tribunal, quando o Júri chega a um veredito não necessariamente é encontrada a verdade absoluta, apenas todos concordam na verdade mais convincente. Algumas décadas depois alguém pode chegar com uma prova que contradiz o veredito.
A história nos ensina a ser prudentes. Nem por isso devemos ser passivos ou não-participativos. A democracia e a liberdade de expressão nos trazem a chance da discussão, sem censura. Mas existem certas regras de etiqueta, ética e bom senso que não podemos ultrapassar: acusar os outros sem motivos claros é um deles.
Infelizmente, acabamos de ver Joel fazer o contrário do que eu disse em “Evolução pela Concorrência”, mas vimos pessoas como Avi Bryant trazer informações que aumentam nossa qualidade de conhecimento. Como alguém disse em um comentário, parece que Joel está sofrendo a transição de programador para um daqueles gerentes que ainda acham que são técnicos. Quando seus posts se limitam a falar sobre gerenciamento de projetos, algumas idéias são boas, mas quando tenta voltar a falar sobre coisas técnicas, comete grandes gafes.
Moral de história: pensem antes de falar, sempre existe alguém que sabe mais do que você.