Em 1975, Frederick P. Brooks escreveu o revolucionário The Mythical Man-Month. Quarenta anos depois, esta série de artigos pretende revisar as afirmações e os argumentos do autor. Quanto o ofício da Engenharia de Software evoluiu desde então?
Capítulo 8: Calling the Shot
Neste capítulo, Brooks discorre sobre as dificuldades e algumas armadilhas relacionadas à estimação e à produtividade em projetos de software com base em dados de algumas pesquisas realizadas na época. Vamos conferir o que o autor encontrou a seguir.
Não se estima o esforço total ou cronograma de um projeto de programação simplesmente estimando o tempo de codificação e multiplicando por fatores para incluir as outras tarefas.
O autor propôs em capítulos anteriores a proporção de tempo para se investir em codificação e testes. Porém, trabalhar com código é uma parte menor do total investido na maioria dos projetos de software.
Dados para o desenvolvimento de pequenos sistemas isolados não se aplicam para projetos de sistemas maiores.
Fatores como quantidade de pessoas envolvidas, tamanho do projeto e complexidade do domínio fazem com que não se possa estimar o tamanho do projeto apenas com base na quantidade de código.
A codificação aumenta como uma potência do tamanho do programa. Algumas publicações mostram um expoente de aproximadamente 1,5.
Brooks cita um estudo comparando a produtividade, medida em número de comandos codificados, entre dois projetos de tamanhos diferentes. Num projeto maior, a produtividade cai consideravelmente e, basicamente, o esforço aumenta exponencialmente com uma taxa de 1,5 em relação ao número de instruções.
Outro estudo mostrou que programadores gastam apenas 50% do seu tempo codificando e depurando código, o restante sendo preenchido com pequenas tarefas de alta-prioridade não relacionados com o trabalho principal, reuniões, documentação, coisas da empresa, doenças, tempo pessoal, entre outros.
Ainda outro estudo mostrou que o número de interações necessárias entre os programadores reduz drasticamente a produtividade, o que significa que, quanto maior o projeto e maior o número de pessoas, menos cada um produz.
Finalmente, outro estudo realizado durante o desenvolvimento de um compilador, onde diferente equipes com bastante experiência implementaram partes diferentes do produto, mostrou que a produtividade varia grandemente dependendo da complexidade do módulo em que tais equipes trabalharam.
Produtividade na programação pode ser aumentada até cinco vezes usando uma linguagem de auto nível.
Aqui, Brooks cita mais um estudo que mediu o número de linhas de código produzidos numa linguagem de alto nível, em contraste com o número de instruções produzidas em linguagens de baixo nível. Houve um aparente aumento da produtividade próximo de cinco vezes.
Considerações
Se você já participou de algum processo de estimação, já deve ter visto alguém pegar o resultado e arbitrariamente multiplicar por algum fator. É a tal da gordurinha. É muito interessante que, isto que muitos fazem instintivamente, "no chute", tem uma base científica.
Os dados fornecidos pelo autor neste capítulo são importantíssimos para entendermos como as tarefas adicionais em um projeto de software realmente influenciam sobre o cronograma e não são exatamente proporcionais ao tamanho do código.
A regra é simples: quanto maior ou mais complexo o programa, mais sobrecarga, menos produtividade. O “favor de produtividade” ou “gordurinha” não pode ser o mesmo para diferentes tipos de projetos.
Ao mesmo tempo em que não existe uma fórmula mágica para estimar um projeto, conhecer as variáveis que influenciam no mesmo ajuda a determinar uma aproximação mais favorável ao sucesso do projeto.
Um exemplo prático
Para você ter uma ideia, em minha experiência, algumas vezes vi projetos que estimaram o tempo de codificação e multiplicavam isso por 1,5 ou 2 e sempre atrasavam.
Bem, geralmente são os próprios programadores que estimam o tempo de codificação e, como você deve ter lido nos primeiros capítulos, programadores são otimistas. A primeira coisa que o responsável pela estimação deve fazer é confrontar (no bom sentido) os programadores sobre possíveis riscos e problemas, talvez perguntar o tempo que levaria no pior caso. Acredite, por padrão, frequentemente programadores dão a estimativa do melhor caso.
Além disso, como você notou neste capítulo, programadores codificam apenas 50% do seu tempo, em média. Então o fator mínimo que você deve adotar para multiplicar a estimativa do tempo de codificação é 2.
Finalmente, deve-se levar em conta a complexidade e riscos do projetos que podem comprometer sua entrega.
Paradigma de programação e nível de abstração
Linguagens de alto nível aumentam a produtividade porque permitem ao programador se concentrar no problema a ser resolvido ao invés de ter que lidar com complexidades desnecessários do ambiente operacional.
O autor demonstra ao longo do livro, como vimos na última citação, uma grande esperança que linguagens modernas venham a aumentar muito a produtividade. Vemos tal sentimento reproduzido hoje quando se fala sobre paradigmas de programação mais avançados, tal como as diferentes aplicações do paradigma funcional.
Assim como linguagens procedurais de alto nível foram um grande avanço com relação, por exemplo, à programação em instruções assembler, onde um comando poderia equivaler a dezenas de instruções de máquina, a programação funcional permite expressar conceitos complexos, equivalentes a muitas linhas procedurais, em poucos caracteres.
Entretanto, há pelo menos dois problemas com a tese do autor, isto é, de que usar uma linguagem de mais alto nível aumenta a produtividade:
- Medir produtividade baseando-se em linhas de código ou instruções não faz sentido. Existem muitos tipos de código que são fáceis de serem produzidos e não acrescentam funcionalidade real.
- Sou muito cauteloso ao afirmar que elevar a abstração efetivamente aumenta a produtividade. Uma linguagem que faz muito com poucos comandos, necessariamente possui maior densidade de complexidade, isto é, mais complexidade por cada caractere digitado. Isto necessariamente leva a uma maior curva de aprendizado e codificação mais lenta. Se isto se paga com o tempo ou se a complexidade chega a tal ponto que não se consegue mais evoluir o sistema, é outra discussão. Meu ponto aqui é que não podemos pular rapidamente a conclusões generalizadas.