A arte de fazer cronogramas

junho 8th, 2006

A maioria dos projetos de desenvolvimento que falham tem prazos impossíveis. E, quando estes prazos são definidos por um departamento comercial ávido de ganhar sua comissão, a razão disso é óbvia. Infelizmente, porém, quando esta responsabilidade está com os desenvolvedores o resultado não é muito diferente. Como mudar isso?

A verdade é que, para que um cronograma tenha o menor desvio possível é necessário conhecer:

  • As funcionalidades a serem desenvolvidas a ponto de desmembrá-las em tarefas;
  • O cliente, de modo a saber a qualidade, nível de documentação e detalhes que o mesmo pode solicitar da sua aplicação, bem como a sua disponibilidade;
  • Os recursos que farão parte do projeto a ponto de saber a produtividade deles em cada tipo de tarefa, bem como sua freqüência de ausências (problemas de saúde, pessoais etc.);

Contudo, a maioria das pessoas diria que não é possível conhecer nenhum dos três. E isso explica por que os prazos quase sempre estouram :-) Na maioria dos casos, realmente não é possível ter essas informações no nível desejado para se elaborar um cronograma que funcione, mas a idéia é chegar o mais próximo possível deste cenário para que o desvio não seja tão grande ou ainda contornar cenários comuns.

Por exemplo, digamos que a documentação e/ou nível de informações a respeito das funcionalidades é escassa demais. Provavelmente, a melhor alternativa seria desmembrar o projeto em dois: um projeto de análise de negócio e outro de desenvolvimento, sendo que o segundo terá um cronograma apenas quando o primeiro for encerrado. Se isto não for possível, o ideal é mostrar ao cliente a necessidade de obter o máximo possível de informações para que o cronograma (e o orçamento) proposto sejam reais. Se nada disto for possível, a última alternativa é analisar outros softwares semelhantes ao que o cliente está solicitando, fazer as estimativas baseadas neles e deixar claro que o cronograma proposto baseia-se naqueles produtos. Isto talvez faça com que o cliente se expresse a respeito do que quer exatamente, reduzindo ou aumentando o escopo e, conseqüentemente, o cronograma.

É extremamente importante ter as funcionalidades divididas em tarefas, pois isso permite alocar horas ou poucos dias a cada “fração” da funcionalidade, gerando uma precisão muito maior da duração da funcionalidade como um todo, além de permitir entender melhor o que pode ser paralelizado ou agrupado de forma a otimizar o cronograma. Ao fazer isto, geralmente percebe-se que as coisas “simples” vão demorar muito mais do que se esperava inicialmente.

O conhecimento do cliente é importante para determinar a extensão das tarefas e da documentação, mas especialmente para duas coisas: restrições tecnológicas e disponibilidade do cliente. É essencial, para se ter uma estimativa correta, saber quais tecnologias poderão ser utilizadas, bem como que tipo de padrões de código e documentação o cliente possui. Esta pode ser a diferença entre o projeto de três meses e o que leva um ano porque os desenvolvedores têm que lutar diariamente contra limitações dos frameworks ou da versão do JDK que usam ou porque têm que produzir grandes quantidades de documentos que têm de ser quase que completamente alterados a cada vez que o código é modificado.

Em quase todos os projetos é necessário obter informações adicionais do cliente à medida que o desenvolvimento é feito ou para que as funcionalidades já implementadas sejam validadas. Isto costuma ser um problema, visto que o cliente normalmente não se considera parte da equipe do projeto nem acha que depende dele o cumprimento do cronograma. Metodologias como XP motivam o envolvimento contínuo do cliente, mas nem sempre o cliente concorda com este grau de comprometimento com o projeto. Nestes casos, é necessário especificar no cronograma em que pontos a participação do cliente será necessária, por quantas horas, bem como os “pontos de parada”, i.e., pontos em que se o cliente não estiver disponível o projeto fica parado e deixar claro que é responsabilidade do cliente compensar tais falhas.

Uma vez que as tarefas do projeto estão definidas e que sabe-se como o cliente irá influenciar o projeto, o próximo passo é determinar a alocação de recursos para que seja possível determinar o tempo de cada uma delas. O modo ideal de se fazer isso é explicar aos próprios recursos as tarefas que você pretende alocar para eles, a fim de verificar se são realmente capazes de executá-las, bem como solicitar deles o tempo previsto para cada uma delas.

Obviamente, muitas pessoas não tem a mínima noção de quanto tempo realmente levam para cada tarefa. Por isso, o papel de quem faz o cronograma do projeto é ter dois números para auxiliar nesta etapa: a estimativa de horas ideais e o fator de desvio do recurso. As horas ideais são as horas que um determinado recurso mais confiável em estimativas diz que são necessárias para realizar a tarefa. Normalmente, o recurso confiável acaba sendo a própria pessoa que faz o cronograma ou alguém mais sênior na empresa. O fator de desvio do recurso refere-se a quantas vezes mais tempo aquele recurso leva para executar uma tarefa. Isto se deve a diferença de conhecimento, grau de concentração, capacidade técnica, taxa de “compartilhamento” de recurso (quando a pessoa é utilizada em outros projetos/tarefas ao mesmo tempo que faz o seu projeto) e outras razões. Obviamente, ambos os números só podem ser obtidos com a experiência e/ou medição de projetos anteriores. Comparando a estimativa do recurso com a sua estimativa, chega-se ao número de horas ideais e, multiplicando-se esse valor pelo fator de desvio, obtem-se o total de horas que o recurso deverá gastar.

A explicação acima leva em conta algo que a maioria dos que fazem cronogramas esquecem: recursos são pessoas e pessoas são únicas. Não existe Recurso Jr, Pleno e Sr; existe sim o José, a Maria e o João, que mesmo sendo todos plenos, por exemplo, gastam tempos diferentes para a mesma tarefa e que, para tarefas diferentes, não mantém a mesma taxa de eficácia.

Uma vez que se percebe isto, percebe-se também o quão difícil é fazer cronogramas quando os recursos são desconhecidos. A técnica das horas ideais ainda precisa ser utilizada, mas o fator de desvio terá também de ser estimado. A melhor forma de determinar o fator de desvio a usar é calculá-lo com base na média do fator de desvio dos recursos que serão possivelmente usado para a tarefa e decidir se deve-se considerar o pior caso, i.e., que o recurso com o maior fator de desvio será utilizado.

Ao final de tudo isso, usando-se uma ferramenta como o GanttProject, você provavelmente vai descobrir que o projeto vai levar muito mais tempo do que você pensava inicialmente. Ótimo, isso provavelmente também significa que agora você chegou a um cronograma realista. :-) Por mais que este não seja o cronograma que você vai apresentar ao cliente, por medo de ele não aceitar o tempo – o que eu não concordo -, é com este cronograma que você tem que calcular os custos, pois é o real.

Espero ter ajudado em alguma coisa ou ter deixado vocês completamente desesperados… :-)

GWT e desenvolvimento web

junho 6th, 2006

O Google Web Toolkit ainda não fez um mês e já é o novo assunto quente na comunidade Java (ok, excluindo-se quem fala de Ruby). O fato é que nenhuma solução Ajax chega aos pés do que o GWT faz, pelo menos mantendo a simplicidade.

Embora o GWT seja excelente, ainda não é o framework que atende todas as necessidades nesse mundo complicado da web. Falta o modo HTML puro (que o Google possui, mas não disponibiliza no framework). O cenário em que um designer é responsável pelo HTML não é coberto pelo framework. Um modelo de programação POJO e sem grandes limitações ainda está longe de ser implementado.

Na minha utopia para web, você poderia ter apenas um XHTML bem formado, sem nenhuma extensão de schema, ou um HTML base, como no proposto pelo GWT, um POJO com a lógica de display (tratamento dos dados, controle de habilitação/visibilidade de widgets, como o modelo de binding do genesis) e uma classe ou mapeamentos para navegação e configuração de binding. O framework faz toda a mágica para você, assim como o compilador do GWT. Isso é plenamente possível de ser implementado hoje; o único problema é que é relativamente difícil de fazer e consome um tempo razoável. Espero que, em breve, possa concretizar essa idéia.

Oportunidade na Summa

junho 6th, 2006

Temos uma nova oportunidade na Summa, a empresa em que trabalho e onde trabalham também Bruno JavaMan Souza, Cláudio Miranda, Gustavo Nalle, Edgar Silva e outras figurinhas da comunidade Java. Segue a descrição:

  • Projeto:
    Desenvolvimento de software, Desenvolvimento de Portais e Serviços Técnicos de Informática.
  • Requisitos Técnicos:
    • Experiência comprovada no desenvolvimento de aplicações em Java/JEE
    • Experiência no uso de EJB’s e WebServices
    • Mandatório conhecimento de OO
    • Experiência no uso de Design Patterns
    • Conhecimento de linguagem SQL e Banco de Dados Relacional
  • Diferenciais:
    • Experiência no desenvolvimento de Portais
    • Experiência no desenvolvimento de aplicações B2B para o mercado financeiro
    • Experiência com RUP
    • Experiência na utilização da IDE Eclipse
    • Experiência nos produtos da Sun Microsystems (Application Server e Portal Server)
    • Certificação

Aos interessados, por favor, encaminhem seu curriculo no endereço curriculo@summa-tech.com aos cuidados de Thais Fernandes.

JustJava 2006

junho 6th, 2006

O site do JustJava 2006 já está no ar e a chamada de trabalhos, vulgo CFP (Call For Papers) já começou. Confira!

genesis com suporte Swing

junho 5th, 2006

Muitas pessoas me perguntam quando o genesis irá suportar Swing. A resposta é que ele já suporta.

A versão atualmente no HEAD do CVS tem suporte Swing há algum tempo – bem como a anotações do Java 5 -, mas simplesmente não tivemos tempo de atualizar a documentação completamente ainda. Contudo, estou trabalhando nisso nestes dias.

O exemplo useradmin já utiliza Thinlet e Swing e serve de referência de uso da API. Para quem não tiver paciência de aguardar a documentação atualizada, pode conferir o snapshot de janeiro aqui.

Novo blog

junho 5th, 2006

Bem, após a morte do JavaBlogs, essa é a nova casa dos meus comentários sobre o mundo Java. Espero postar com mais freqüência.

NullPointerException – um mal necessario

junho 5th, 2006

Quem programa em Java e nunca escreveu código que lançou uma NullPointerException, que atire a primeira pedra. A NPE talvez seja a exceção mais comum em Java e causa ódio em algumas pessoas, que acham que a linguagem podia “engoli-la” de algum jeito. Posso dizer pra vocês que isso, definitivamente, é uma péssima idéia.

No meu projeto atual tivemos, por várias razões, que escrever um pedaço do código em PL/SQL. Num é que a tal da linguagem “engole” os erros de operações com null? Funciona mais ou menos assim: qualquer coisa que você faz com null, dá null! Parece bom? Que nada! Imagina que isso:

IF X > 0 THEN
   ...
ELSE
   ...
END IF;

pode cair no else se x for null! Quem conhece PL, pode dizer: mas existe o NVL pra isso! Usar NVL(var, valor) retorna valor se var for null. Agora, imagina usar NVL pra quase todo uso de variável numérica no seu código. Pois é, nojento mesmo! O bonito é quando você não faz isso. O resultado pode acabar sendo um null como retorno da function ou em um campo da tabela. Aí, vai achar por que deu null… :-(

Por isso eu digo: benditas NPEs!!! Pelo menos, tem um stack trace onde eu sei exatamente em que linha os problemas ocorrem e limito meu escopo de “caça” ao null. BTW, um dia eu pego o cara que decidiu que as coisas fossem assim em PL… :-P

Covariancia

junho 5th, 2006

Uma das mudanças do Tiger que eu não coloquei nos slides da minha palestra no BrasilOne é o suporte a covariância. O que é isso?

Basicamente, no escopo do Tiger, isso se refere ao fato de um método poder sobrescrever outro retornando uma subclasse do tipo de retorno do método original. Algo assim:

public interface Product {
   //...
}

public abstract class Factory {
   public abstract Product create();

   //...
}

public class ConcreteProduct implements Product {
   //...
}

public class ConcreteFactory extends Factory {
   public ConcreteProduct create() {
      //...
   }

   //...
}

O exemplo de covariância é o método create(). A “graça” de ter covariância é que você elimina os casts quando está acessando o tipo concreto diretamente, o que seria muito bom pra quando você tem uma família de interfaces sendo implementadas todas juntas por um conjunto de classes concretas que são dependentes entre si. O código fica muito mais “limpo” do que é hoje.

Mais uma API medonha: java.awt.Font

junho 5th, 2006

Pois é, mais uma importante lição para o arquivo: java.awt.Font é mais uma API medonha do JDK. O problema é como funciona o carregamento de fontes.

A API provê um método chamado getFont(String name) que carrega uma fonte dado seu nome. Caso não encontre uma fonte com este nome, retorna null. A maior parte do código de terceiros, i.e., fora do JDK, que carrega fontes pelo nome, usa este método e geralmente utiliza uma fonte default caso o método retorne null. Como usar outra fonte pode ter impactos altamente negativos para diversos usos, como impressão de formulários específicos, geralmente não é este comportamento que o desenvolvedor deseja na aplicação.

Existe uma maneira padrão de se carregar uma fonte em Java: o método createFont(int fontFormat, java.io.InputStream fontStream), que funciona com fontes TrueType, criadas com fontFormat Font.TRUETYPE_FONT. Ou seja, se você anexar a sua aplicação os arquivos .TTF das fontes que você usou, é possível carregá-los dinamicamente. Mas, nem tudo é bonito assim :-/

Embora a API, ao carregar um arquivo de fonte, seja capaz até mesmo de identificar o nome da fonte, não existe na API uma forma de associar um nome a uma fonte. Em outras palavras, você consegue carregar uma fonte por nome, mas não é possível afetar ou customizar o retorno de getFont(String). Levando em conta que, como eu disse antes, a maior parte do código do mundo “acredita” em getFont(String), a menos que a fonte esteja instalada no S.O. – e exatamente a mesma fonte, o que raramente acontece :-/ -, tudo dá errado.

Qual a solução para o problema? Se você está lidando com open-source, existe a possibilidade de reescrever o código para usar seu próprio esquema de carregamento de fontes por nome, que permita associar o nome a certa instância de Font. Você pode também escrever um aspecto que intercepte a chamada a getFont(String) se você não quiser manter um branch ou se o software for fechado (e a licença permitir modificação binária).

Diga que nao vai dar certo!

junho 5th, 2006

Como prometido, vou falar um pouco sobre projetos em si. Na maioria dos projetos que falham, sempre alguém – ou quase todo mundo – sabe que as coisas vão dar errado logo no começo. Os motivos são vários: prazo impossível, equipe sub-dimensionada, despreparo, gerência caótica, restrições técnicas ridículas e absurdas etc. O problema acaba sendo que ninguém fala e depois fica reclamando, no velho esquema sabia-desde-o-começo-que-não-ia-funcionar. Alguns não falam simplesmente porque isso não funcionou das outras vezes e acham que nada vai ser diferente se fizerem alguma coisa. Então, do que adianta falar que as coisas vão dar errado? Depende da sua atitude.

Se você tiver argumentos para justificar a sua expectativa de falha – projetos passados que deram errado são uma ótima referência nessas horas -, use-os. Procure convencer as pessoas que trabalham com você antes de tentar convencer gerentes e/ou outros responsáveis. Muitas vezes você poderá ouvir coisas do tipo: “fizemos tal mudança depois da última vez, logo dessa vez vai funcionar”. O fato é que, se as coisas não deram certo da vez anterior, só vão dar certo depois da primeira vez que não ocorrer um fracasso. Logo, se a última vez tudo deu errado, dessa vez provavelmente o máximo que pode acontecer é que tudo não seja um desastre completo, a menos que alguém que tenha um histórico em entregar projetos bem-sucedidos esteja liderando a equipe ou tenha poder de decisão dentro dela.

Outra coisa que geralmente as pessoas dizem é que você não está a fim de se matar de trabalhar. Bem, se isso for verdade, parabéns; afinal você é um dos poucos profissionais de TI que acha que existe vida fora do micro :-) Agora, falando sério, projetos funcionam como uma maratona: só adianta dar um gás perto do final e, se você sabe que o prazo final não é nem de longe a linha de chegada, você seria apenas um idiota de se gastasse suas energias agora e morresse bem antes da metade do caminho. É mais fácil – e vai causar muito menos danos ao cliente e a todos os envolvidos – se você disser na primeira semana do projeto que a entrega vai atrasar do que avisar uma semana depois do término do prazo… Infelizmente, a maioria das consultorias acredita que a segunda estratégia seja a mais inteligente, mas acredito que você, que vai passar seis meses sem ver sua família e seus amigos, deixando sua vida as traças e se sentindo um zumbi durante todo esse período – e mais algum tempo depois, geralmente -, não compartilhe desse mesmo pensamento.

Uma armadilha comum é começar a se convencer de que as coisas vão dar certo. Por quê? Os outros acreditam, é isso? Por um acaso deu certo da última vez em que os outros acreditavam? Realmente mudou alguma coisa? Existe alguma evidência concreta de que as coisas vão ser diferentes? Não adianta tentar se enganar, pois quem vai pagar o pato é você mesmo. Se você ganha (bem) por hora e prefere o dinheiro a sua vida, pode se dar por feliz, mas se não for o caso, é melhor manter sua posição inicial se você quiser passar pelo menos algumas horas fora do escritório. Caso contrário, você ainda corre o risco de se matar e ouvir de alguém da gerência coisas do tipo: “mas vocês trabalharam tanto pra entregar só isso no final?”, “são muitas horas, não sei se teremos como pagar” ou ainda “se você sabia que ia dar errado, por que mudou de idéia?”, que, com certeza, vai ser muito pior do que continuar lembrando porque as coisas vão dar errado…

Resumindo, dizer que as coisas não vão dar certo no começo, quando se tem base pra isso, não é ser pessimista nem preguiçoso, mas é, na realidade, uma forma de economizar o dinheiro da empresa – que não vai queimar recursos achando que miraculosamente vai entregar em três meses o projeto que vai levar um ano pra ser desenvolvido e que provavelmente vai ter condições de fazer a coisa certa, mudando radicalmente a situação ou tomando medidas reais para lidar com o atraso -, não decepcionar de verdade o cliente, dizendo depois do prazo que ainda falta mais do que o tempo de projeto inicial para entregar o que ele pediu, e poupar a sua própria vida, ou salvar a sua pele, se assim preferir. Como esse é um post um tanto quanto existencial – quem disse que projetos e desenvolvimento de software são ciências exatas estava delirando e muito -, comentários, mesmo que desmintam totalmente o que eu disse, são bem-vindos :-)