Archive for the 'linguagens' Category

Testes e especificações

Linguagens são umas criaturas muito flexíveis. As melhores linguagens de programação são as mais maleáveis, aquelas que permitem ao programador moldá-las às necessidades da sua aplicação. Quem usa a biblioteca de testes JUnit em Java, faz scripts de build com Rake em Ruby ou usa o Monad IO em Haskell praticamente não pensa nas primitivas da linguagem. Ao invés disso, a mente passeia pelos termos próprios ao domínio da aplicação. Não se pensa em classes, objetos, métodos e funções, mas em casos de teste, tarefas e comandos.

As linguagens naturais não são diferentes, estão o tempo todo mudando. Basta um grupo de pessoas se comunicando para que jargões e dialetos comecem a se formar. Novas palavras surgem e outras saem de moda com uma velocidade surpreendente. Há oito anos atrás, por exemplo, se a palavra “agilidade” fosse citada em uma conferência de desenvolvedores de software, poderia muito facilmente ser associada a soluções rápidas e sujas. Hoje para muita gente é sinônimo de alta iteratividade, valorização do feedback e adaptação constante. Parece mais com rápido e limpo do que com outra coisa qualquer.

Para que algumas palavras mudem de sentido, basta que sejam usadas por duas pessoas diferentes. “Especificação” é uma dessas famigeradas palavras com muitos significados. Muita gente presume que uma especificação é completa, ou seja, que prevê as saídas para todas as entradas possíveis. Por outro lado, outras tantas pessoas presumem apenas que uma especificação é não-ambígua, isto é, pode ser interpretada de um único modo.

Entretanto, a maioria das pessoas — e isto inclui programadores e seus clientes — não conseguem fazer especificações de nenhum desses dois tipos. Pelo menos não naturalmente. Não sem conscientemente se obrigar a isso. Estas especificações acabam saindo tanto ambíguas quanto incompletas. Seria bom que tivéssemos algum tipo de máquina capaz de garantir pelo menos uma dessas duas propriedades.

O que não é muito difícil de se achar…

Computadores são máquinas construídas exclusivamente para seguir instruções. Eles não podem interpretar a mesma instrução de dois modos diferentes. Podemos então escrever nossas especificações como um programa de computador e só vai haver um modo de interpretá-las. Assim eliminamos a ambigüidade e ainda ganhamos a habilidade de executar tudo automaticamente. Só que o nome “especificação” é um tanto quanto controverso, é melhor chamar estes programas somente de testes. Testes são executáveis. Podem não ser especificações, mas são executáveis.

Para executá-los basta fornecê-los ao computador adequado e eles vão rodar rapidamente. Muito mais rápido do que alguém poderia fazer manualmente. Programadores são especialmente bons em generalizar o comportamento esperado do sistema a partir de um conjunto de entradas. Se escrevermos testes para os casos excepcionais, podemos ficar razoavelmente seguros que o código está completo. Caso não esteja, quase sempre podemos encontrar mais testes. Esta segurança é somente estatística, pois é impossível testar todas as entradas na prática, mas é muito mais segurança do que se tem com uma linguagem natural.

Moral da estória: não dá para especificar tudo com testes automáticos, mas dá para especificar muita coisa.

Desastre na Torre de Babel

Essa nossa língua portuguesa é extremamente e rica e ainda mais extremamente incompreendida. Dia desses descobri uma ótima discussão em pelo menos dois blogs sobre o termo padrão de projeto, tradução já consagrada de design pattern. Os dois parecem concordar que a tradução tradicional tem atrapalhado a indústria brasileira porque as pessoas entendem “padrão” como “norma”. A palavra é realmente ambígua, mas com certeza não é a raiz da questão. A grande prova é que o problema não acontece somente aqui.

É verdade que é bem fácil encontrar no Brasil organizações que promovam uma “arquitetura” normatizada, independentemente do domínio do problema ou do contexto do projeto. Essas organizações realmente parecem gostar de dizer que têm uma “arquitetura” baseada em padrões de projeto. Aliás, a palavra “arquitetura” devia sempre vir envolvida em aspas, já que tem tantos sentidos para tanta gente diferente.

É verdade que é bem fácil encontrar alguns brasileiros integrando a gangue dos padrões. Você já conheceu pelo menos um destes: eles acabaram de sair da faculdade (ou em muitos casos, ainda estão lá) e acham que os padrões de projeto podem resolver todos os problemas do mundo, da guerra no Líbano ao açúcar do cafezinho.

Também é verdade que os brasileiros abusam do padrão Singleton. Mas todos estes problemas acontecem com a mesma freqüência no resto do mundo.

Desde o dia em que aqueles quatro caras popularmente conhecidos por Gang of Four (ou pelo acrônimo GoF) publicaram o Design Patterns: Elements of Reusable Object-Oriented Software (que aliás, é um ótimo livro: se você não leu ainda, corra para ler), as pessoas têm usado mal o padrão Singleton. Esta famigerada criatura não passa de uma variável global vitaminada e a primeira pessoa que abusou do coitado muito provavelmente não o conheceu por litetatura em português. Afinal, os termos foram cunhados originalmente em inglês.

Acontece que o Singleton é especialmente útil para quem tem a mente acostumada com o pensamento imperativo. Ele permite agrupar um conjunto de funções em algo parecido com um objeto e dizer que se usa programação orientada a objetos. É um dos modos mais fáceis de estar na moda (tanto na moda dos objetos quanto na dos padrões) e foi o que muita gente escolheu.

O problema é que algumas pessoas pegaram a febre dos padrões e começaram a vê-los como normas, quase leis, e entraram numa cruzada insana pelo Santo Graal dos padrões. Só precisamos encontrar a cura e o meu palpite é que ela vai levar uma boa dose do bom e velho senso crítico.

Os objetos estão te matando?

Ou é você quem acha que a culpa é deles?

Hoje eu achei um exemplo de código ruim atribuído ao uso de objetos. O interessante é que se você olhar bem, o código na verdade é procedural. Só porque você está usando uma linguagem ou biblioteca com suporte a orientação a objetos, não quer dizer que você esteja programando orientado a objetos. Este é um engano bastante comum. Você já deve ter conhecido algum sistema por aí que parece ter sido construído sobre duas exigências (ou mandamentos) básicas:

1. Usarás uma linguagem orientada a objetos
2. Escreverás somente código procedural

Dava até pra colocar numa tábua de mandamentos.

O objetivo do código do exemplo de Jeff Attwood que disparou este artigo é renderizar um trecho de XML. Vamos dar uma olhada:

1   System.Text.StringBuilder sb =new System.Text.StringBuilder();

    XmlWriterSettings xs = new XmlWriterSettings();
    xs.ConformanceLevel = ConformanceLevel.Fragment;
5   xs.Indent = true;

    XmlWriter xw = XmlWriter.Create(sb, xs);
    xw.WriteStartElement("status");
     xw.WriteAttributeString("code", "1");
10  xw.WriteEndElement();
    xw.WriteStartElement("data");
    xw.WriteStartElement("usergroup");
    xw.WriteAttributeString("id", "usr");
    xw.WriteEndElement();
15  xw.WriteEndElement();
    xw.Flush();
17  return sb.ToString();

Este trecho de código é totalmente procedural, e foi escrito usando uma linguagem e uma biblioteca de objetos (acho que isso é C# junto com alguma biblioteca .Net para XML). A grande estrela desse código é o objeto conhecido por ‘xw’. Ele aqui está sendo usado como um elemento passivo, mero cumpridor de ordens. Tudo que ele precisa fazer é explicitamente requisitado:

— Xw, comece a escrever um elemento ‘status’.
— Sim, senhor!
— Xw, escreva um atributo chamado ‘code’ com valor ’1′.
— Sim, senhor!
— Xw, está bom, pode fechar este elemento.
— Sim, senhor!

… e assim por diante. Dar ordem expressas assim é característica de código procedural, que se confunde com o código imperativo. E código imperativo tem esse nome justamente porque é estruturado ao redor de um conjunto de comandos (ou ordens) básicos.

Esse tipo de argumento anti-objetos parece acontecer muito mais por causa da interface de uma biblioteca do que pelo uso de objetos. Bibliotecas diferentes vão ter interfaces diferentes. Este trecho de código Ruby enviado por um leitor do blog dele exemplifica bem:

  builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)
  builder.person { |p|
    p.name("Jim")
    p.phone("555-1234")
  }

Aqui o estilo é muito mais declarativo. Quase idêntico a escrever o código XML você mesmo, mas sem os perigos de se tentar escrever manualmente em uma linguagem feita para máquinas.

A questão aqui não é a dicotomia orientado-a-objetos x procedural. Talvez isso nem exista. Como o exemplo em C# mostra, é possível escrever código procedural orientado a objetos. Além de possível, é bastante comum. A discussão na verdade é entre os estilos declarativo e procedural.

Quem será que ganha essa última?

EclipseFP 0.9.1 disponível

Hoje foi publicado o release 0.9.1 do projeto EclipseFP. Estou trabalhando neste projeto desde outubro do ano passado e este é o primeiro release de que participo.

O EclipseFP é uma IDE para a linguagem Haskell baseada na plataforma Eclipse. A intenção é ter algo como um HDT (uma a sigla para Haskell Development Tooling), parecido com o JDT (a IDE de Java do Eclipse), com suporte a coisas como assistente de código, refactoring e debugging.

Neste release a maior parte do meu trabalho foi centrada em construir um parser para Haskell em Java. O parser antigo era escrito em Haskell e acessado pelo código Java através de JNI. Uma desvantagem grande dele é que só havia uma versão para plataformas win32, o que quer dizer que os usuários de outras plataformas como Linux e Mac OSX não tinham acesso a nada que envolvia o parser. Agora eles têm.

Para o próximo release estou pensando em trabalhar no suporte ao compilador e no modelo da linguagem, indispensável para termos coisas como ‘Abrir declaração’ (tecla F3 no Eclipse/JDT).