Arquivo de agosto \17\UTC 2006

Protagonistas e coadjuvantes

Em filmes, novelas, livros e em qualquer outro meio que se conte uma estória, há personagens protagonistas e coadjuvantes. Estes últimos desaparecem em meio aos primeiros. Ninguém nota que eles estão lá, mas todos notam algo esquisito se eles não estiverem.

Do mesmo modo, os famigerados “processos de desenvolvimento de software” podem ganhar muito se forem tão naturais que nem se note sua presença. Eles podem funcionar como figurantes de um filme: são essenciais para que tudo corra agradavelmente, mas não prendem a atenção de ninguém. Na verdade, eles estão lá justamente para não chamar a atenção. Quanto mais apropriado o processo estiver para a realidade da equipe, mais as pessoas vão achá-lo natural e mais ele será confundido com o cenário.

Sob esta ótica, uma equipe com o conjunto de práticas ideal vai achar que não há nada além de pessoas trabalhando. Nada de processos ou metodologias.

Melhor que a encomenda

Fazer somente o solicitado pode ser um suicídio completo em qualquer mercado competitivo e, a menos que você detenha algum tipo de monopólio, desenvolvimento de software é um desses mercados. Seus concorrentes muito provavelmente estão fazendo mais do que o estritamente necessário e ninguém quer ficar para trás. O inverso, entretanto, não é receita de sucesso. Fazer mais do que o requisitado pode levar a uma corrida sem fim por novas funcionalidades que vai drenar toda a energia da sua equipe e deixar muita coisa inacabada.

Se você tem uma capacidade de produção limitada (e quem não tem?), é melhor evitar corridas tresloucadas e tentar se destacar no essencial. Fazer menos coisas para que possa fazê-las com mais qualidade.

Acho que este é o exemplo mais batido da Internet hoje em dia (se bem que o iPod está se mostrando um adversário à altura), mas vou usá-lo assim mesmo. No ano 2000, enquanto um de seus maiores concorrentes, o Yahoo, tinha uma página repleta de links e funções, o Google (o sistema de busca, não a empresa) tinham apenas um campo de texto e um botão. Eles tinham uma única coisa para fazer, por isso podiam se concentrar. O resultado é que conseguiram se destacar, apesar dos concorrentes oferecerem mais serviços à época. Você sabe o que é um sucesso, quando uma marca começa a virar verbo. Hoje em dia eles já estão brigando para que a marca não passe para domínio público como sinônimo de busca.

Introduzir novos serviços não solicitados é um jogo de adivinhação e, a menos que você esteja no ramo da clarividência, este não é o tipo de jogo que você quer jogar. Por outro lado, fazer melhor do que o esperado pode colocar você no mesmo pedestal do “mais”, mas sem o risco associado.

Acho que a moral da história dessa vez é: faça melhor que a encomenda, não mais que a encomenda.

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.

Esqueletos, apêndices e fantasmas

Então vocês finalmente conseguiram um cliente. Ele está muito empolgado e tem muitas expectativas para o projeto. Naturalmente, vocês também têm. Por onde começar?

Nesse início de projeto é óbvio que todo mundo está cheio de idéias, tanto vocês quanto o cliente. Todo mundo quer colocar todas as idéias em prática, mas há um limite para o que vocês conseguem entregar. A questão do que fazer primeiro é vital.

Uma idéia é levantar alguns requisitos iniciais com o cliente e escolher as funcionalidades mais representativas do ponto de vista técnico. Ainda não é preciso saber tudo que ele vai querer, somente o suficiente para ter uma idéia geral. Desse modo pode-se montar um esqueleto inicial do sistema sobre o qual as funcionalidades futuras se apoiarão.

Esta não é necessariamente uma boa idéia.

Pelo menos não é desse jeito que os esqueletos vêm tradicionalmente sendo desenvolvidos. Os esqueletos humanos, por exemplo, são produto de alguns milhares de anos de mutação e seleção natural. Não ganhamos este esqueleto que temos hoje de uma hora para a outra, foram necessárias várias gerações e muito refinamento do projeto inicial. Assim como na natureza, é melhor que a estrutura básica de uma aplicação evolua a partir de um conjunto mínimo ao longo do tempo ao invés de ser inventado tentando prever o futuro. Programadores não são muito bons em prever o futuro, então é melhor evitar projetar coisas que não precisaremos e deixar os apêndices evolucionários que ocasionalmente surgirão desaparecer naturalmente.

Mas há um argumento ainda mais forte. Quando levantamos prioridades observando apenas o mérito técnico, ignoramos o valor de negócio. Pode ser que as funções com maior representatividade técnica coincidam com as funções de maior valor para o cliente. Mas isto em geral não acontece. O resultado de priorizar inicialmente o desenvolvimento de um esqueleto normalmente são projetos que iniciam com uma grande fase de infra-estrutura e que, durante este tempo, não atendem a nenhuma necessidade do cliente.

O lado oposto desta idéia é deixar o cliente completamente livre para ordenar as funcionalidades como ele queira. Nesta abordagem tudo se inverte. Ao invés da aplicação se adaptar à infra-estrutura inicial, é a infra-estrutura que vai se adaptando às necessidades da aplicação. Os clientes podem então escolher em que investir.

São eles que estão pagando a conta, é natural deixá-los escolher em que investir. Claro que o papel dos programadores, especialistas em desenvolvimento de software, é mantê-los informados sobre suas opções. Eles podem oferecer seu conhecimento — devem fazer isso — mas a decisão final é dos clientes. Escolher uma funcionalidade ao invés de outra com base somente em quesitos técnicos é privá-los desta decisão.

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.



Seguir

Obtenha todo post novo entregue na sua caixa de entrada.