# Bugs Difíceis de Achar

Caloni, 2009-06-18 computer [up] [copy]

Saiu um artigo na Wired News sobre os piores bugs da história. Entre eles estão a explosão de um oleoduto soviético em plena guerra-fria (como se não bastasse chernobyl), o primeiro worm da Internet (que se aproveita de um buffer overflow da função gets) e o famoso erro de divisão em ponto flutuante do Pentium; um erro de cálculo de cerca de 0,006% que causou um prejuízo de 457 milhões de dólares para a Intel.

Mas o que achei mais legal, apesar de não estar na lista, estava relacionado com o Mariner 1, primeira espaçonave de um programa da NASA para pesquisar Marte, Vênus e Mercúrio em võos automatizados. Mariner 1 não chegou a sair de órbita, pois houve uma falha na antena de comunicação entre módulos e um bug no programa do computador de bordo.

Falava-se que o bug havia sido gerado ao trocar uma vírgula por um ponto em um loop escrito em FORTRAN. Apesar de não ter sido esse o causador da falha do computador da nave do projeto Mariner, ele existiu de fato em outro projeto da NASA, o Mercury. A linha fatal no caso era essa:

   DO 17 I = 1. 10

É óbvio que a intenção do programador foi fazer um loop até o label 17 dez vezes, pois a instrução para isso é:

   DO 17 I = 1, 10

Mas pela troca da vírgula pelo ponto, e como em FORTRAN os caracteres de espaço não são significativos, a linha com o bug não representa mais um loop, mas uma atribuição a uma variável chamada "DO17I":

   DO17I = 1.10

Esse detalhe esdrúxulo de uma das linguagens mais famosas da época nos leva a crer que antigamente os programadores deveriam estar muito mais atentos durante a digitação de código do que os programadores de hoje em dia, com seus ambientes com verificação sintática embutida. Existe inclusive um texto humorístico de longa data comparando programadores de verdade e programadores de linguagens estruturadas como PASCAL recém-saídos da faculdade, carinhosamente citados no texto como "Quiche Eaters" (comedores de pastelão).

O tipo de erro de falta de atenção do programa da NASA lembra uma das mais duras críticas às linguagem C e C++: é fácil escrever um código errado do ponto de vista lógico mas sintaticamente correto (compilável). Alguns exemplos famosos:

// batata entre os iniciantes

if( isActived && isTimeToLaunch );

     doTheStuff();

// dizem que até Brian Kernighan criticava

switch( value )

{

     case 10: 
        evaluateSentence();
     case 11: 
        elevenException();

}

// programado no notepad

value = 12; /* agora somos obrigados a atualizar a variável rates

rates = value * 8; /* nunca apague esta linha! */

// mais um "top beginner"

if( newValue = 20 )

     doSpecificStuff();

// infelizmente isso é muito comum

int calcPayment()

{

     if( testing == true ) return 1000;
     else if( newValue > 500 ) return 1500;

}

// o perigo dos brackets opcionais

if( value == 12 )

     //func();

doSpecificStuff();

Dessa coleção de problemas, o compilador nos brinda com dois warnings:

   warning C4390: ";": empty controlled statement found; is this the intent?
   warning C4715: "calcPayment": not all control paths return a value

Em nível 4 (o padrão de um projeto é 3) há um warning adicional:

   
   warning C4706: assignment within conditional expression

Agora imagine o número de horas noturnas em frente ao micro que você não poderia ter economizado em sua vida se aumentasse o nível de warning e lêsse-os de vez em quando? =)

Mais um Bug

Colaborando com a lista de bugs difíceis de achar do artigo ai vai código/piadinha:

   /** 
    * The Hitch Hiker"s Guide to the Galaxy 
    * The Answer to Life, the Universe, and Everything
    */
   #include <iostream>
   
   #define SIX    1 + 5
   #define NINE   8 + 1
   
   using namespace std;
   
   int main(void) {
       cout << "The Answer to Life, "
               "the Universe, "
               "and Everything is " 
            << SIX * NINE 
            << endl;
       return EXIT_SUCCESS;
   }

Esse não é pego pelos alertas dos compiladores (pelo menos não pelos que eu uso)... É um bom motivo para usar const no lugar de define em alguns casos, ou no mínimo cercar o define por parênteses "(" e ")"

Outro bug muito comum entre iniciantes é o de templates aninhados, apesar de que compiladores mais novos lidam melhor com o bug e trazem mensagens de erro mais claras:

   list<list<int>>  // inválido no caso, é assumido o operador de stream ">>"
   list<list<int> > // válido

# Programadores de verdade não usam Java

Caloni, 2009-06-18 blogging [up] [copy]

Quando era um newbie (e um wanna-be) gostava de ler o "Real Programmers Don't Use Pascal", um texto humorístico que mais me influenciou e encorajou a caminho da iluminação C/C++ do que o livro de K&R. A partir dele, supunha eu, ser um "programador de verdade" era ser tudo. Ser um Quiche Eater (Comedor de Torta) não era nada. Programadores de verdade é que resolvem os problemas de verdade! Quiche Eaters são os losers que estudam os conceitos acadêmicos da ciência da computação e nunca fazem um maldito programa que preste (conhece alguém assim?).

Piadas à parte, para mim o humor do texto ainda pode ser aproveitado por aqueles que já se acham muito bons e acreditam não terem mais como crescer profissionalmente. Quando meu ego infla demais, ainda me lembro que enquanto programo com APIs de brincadeirinha e um sistema operacional que é uma piada tem gente projetando uma nave que vai sair da órbita do Sistema Solar!

Por outro lado, muitas pessoas recém-saídas da faculdade de computação ainda acham programação uma matéria difícil. Esse texto nos lembra que difícil era a vida 20, 40, 70 anos atrás, quando engenheiros e programadores eram a mesma pessoa, e quando se você não soubesse o que estava fazendo colocaria projetos de milhões em risco.

Por consequência, o programador de verdade vive no passado. E ele sempre se valoriza frente ao povão jovem, porque ele sabe resolver aquele problema de tela azul que mais ninguém sabe. E como eu costumo dizer, parafraseando uma figura ilustre da televisão brasileira, quem tem medo de abrir o Visual Studio e em vez disso fica projetando eternamente o software não vai muito longe: "quem sabe faz na hora!".

Aqui segue um breve resumo do texto original adaptado para os tempos atuais e com a minha visão preconceituosa de pensar sobre o assunto. Se quiser, use sua parte politicamente correta da mente e critique à vontade!

Linguagens. Lembre-se: inventar que você precisa de mais linguagens/recursos para fazer seu trabalho é lembrar que você é incompetente o suficiente para inventar esse tipo de desculpinha. Você é daqueles que diz "cada problema tem sua ferramenta específica" ou algo do tipo. Ou seja, um programador politicamente correto e ineficiente. Não vê que tudo o que você precisa está na linguagem C. Se não estiver, então está no assembly. Se não estiver nem no C nem no assembly não vale a pena ser pensado a respeito.

Programação Estruturada. É o primeiro e último paradigma a ser aplicado. Afinal de contas, Orientação a Objetos é mais uma desculpinha para não programar. São abstrações e mais abstrações para inventar que, uma vez que você é um peso morto que não consegue resolver um problema com funções e variáveis, precisa de classes, herança, templates e outras tranqueiras que vão transformar seu código simples e reto em uma cornucópia mágica que só vai impressionar os outros pela inutilidade e complexidade da solução!

Estrutura de dados. Outro ótimo conceito para enganar a si mesmo. Hoje são muitos os que se escravizam nos leiautes SQL e classes estranhas de frameworks estranhos que fazem todo o trabalho. Todos sabemos que a única estrutura realmente útil de saber é o array. O resto são variantes do mesmo tema: filas e pilhas.

Sistema operacional. Mac e Windows são brinquedinhos e Linux é um vídeo-game que dá mais trabalho de configurar do que de jogar. O programador de verdade usa algo como mainframes ou qualquer outro sistema operacional beta, que são bem esquisitos de mexer e que podem fazer um verdadeiro estrago nas mãos de quem não tiver lido TODO o manual. E saber todos os bugs conhecidos e importantes do kernel e sua localização de cor na hora de bootar é vital.

Ferramentas. Se você depende de uma IDE que tem Code Completion e outros penduricalhos do tipo, ou depende de algum outro editor seu favorito com seus 17459 plugins instalados, então você não é um programador de verdade. um programador de verdade usa o que tiver à mão na hora que precisar, seja um notepad, um hexdump ou até mesmo alguns beeps. A ferramenta não é limite para quem sabe programar de verdade.

Depuração. Vai dizer que precisa do código-fonte para depurar? Então você não faz a mínima ideia do que o programa faz. Apenas algumas olhadas na call stack e nos registradores podem fazer um programador de verdade solucionar um bug que os comedores de torta não conseguiriam depois de analisar aqueles gráficos UML com caixinhas dentro e casos de uso por meses a fio.

O Trabalho de programadores de verdade com certeza não é fazer programinhas que acessam basezinhas de SQL com opção de consulta e cadastro. Nem são aqueles saitezinhos com PHP/Apache, scripts e mais scripts. Não, senhor. São programas que lidam com o Sistema Operacional de uma forma mais íntima (criptografia de HD, drivers de File System, serviços de comunicação crítica, etc), ou são programas que fazem algo de verdadeiramente útil (compiladores, o próprio sistema operacional). Ou tavez que mexam diretamente com hardware (microcontroladores complexos, robôs, naves, aparelhagem médica, etc).

A Diversão de todo programador de verdade é conversar com os amigos (sobre programação), ler alguma coisa (sobre programação) e assistir filmes inteligentes (sobre programação ou pessoas que fizeram algum tipo de desafio intelectual "na marra"). Existe algo mais divertido que isso?

E, por fim, em seu Habitat Natural, poderemos encontrar páginas de código assembly espalhadas em volta da mesa, um computador travado por uma depuração remota de kernel por cabo serial, algumas anotações em hexa em um pedaço de papel, algumas dezenas de páginas abertas no navegador sobre comportamento das funções BIOS em HDs SATA com mais de 500 GB trabalhando em RAID4, café, salgadinhos, manchas no carpete. Quando não há nada para fazer, o ambiente está arrumadíssimo e não se nota a presença de programadores de verdade à vista.

E o Futuro do programador de verdade? Bom, a linguagem C pode até estar morrendo. Mas, e daí? Essa tal de C++ ainda suporta ponteiros. O resto das abstrações afeminadas como classes e herança podem ser totalmente ignoradas. O básico sempre existirá. Esqueça as versões com herança múltipla e o enigmático concepts. Seja homem!

O fato é que, independente de quanto mais o mundo se tornar "gerenciado" por trás de frameworks e programadores que preferem "fazer projetos" atrás de seus pacotes de escritório e casos de uso, quando algum problema pipocar, algum bug tenebroso ameaçar a vida útil de um projeto, um programador de verdade estará lá para salvar o dia, pois só um programador de verdade sabe fazer o seu trabalho. E bem feito.

PS: Na verdade, me lembrei. Eu peguei esse cacoete de falar "quem sabe faz na hora" do meu amigo Thiago. Ele também dizia "se vira nos 30!". Bom, se eu citar todas as frases brilhantes que ele usava quando trabalhávamos juntos o texto vai ficar bem longo =)

Se você gostou desse texto, talvez goste de eXtreme Go Horse!


[2009-05] [2009-07]