Em busca da bala de prata

Photo by You X Ventures on Unsplash

Em 1986, Frederick Brooks escreveu um artigo onde afirmava que, na década seguinte, não surgiria nenhuma técnica de gestão ou evolução tecnológica capaz de aumentar a produtividade, a confiabilidade e/ou a facilidade para desenvolver software.

Mais de vinte anos depois, essa afirmação ainda é válida? Ou continuamos, como dizia o autor, tentando resolver problemas acidentais e não essenciais?

O autor

Frederick Phillips Brooks Jr é um engenheiro de software e cientista da computação que nasceu em 1931, na Carolina do Norte, EUA. Nos anos 1960, gerenciou o projeto que deu origem à arquitetura System/360 e o sistema operacional OS360, da IBM.

Este projeto é considerado um dos mais importantes da História da Computação, uma vez que pela primeira vez um fabricante de computadores lançou no mercado uma arquitetura que permitia ao cliente adquirir um computador e fazer upgrades posteriores, mantendo seu investimento anterior em hardware e software.

Em 1975, Brooks contou sua experiência num livro seminal chamado The Mythical Man-Month, que apesar de toda evolução tecnológica das últimas décadas, ainda levanta questões fundamentais para a engenharia de sofware. Este livro foi relançado em 1995, numa edição de aniversário que incorporou a versão original do artigo e alguns comentários do autor sobre o que havia mudado desde então.

O que seria a “Bala de Prata”?

Para Brooks, as lendas sobre lobisomens são assustadores porque falam de alguém que nos é familiar e que, repentinamente, se transforma em algo selvagem, violento, fora de controle e mortal. E a única arma efetiva contra esse monstro é uma rara bala feita de prata.

Ainda na introdução do artigo, o autor afirma que, assim como os lobisomens, muitos projetos de software também começam com um planejamento familiar, assertivo e seguro, mas que em algum momento se transformam num monstro de cronogramas perdidos, orçamentos estourados e produtos com defeito.

A bala de prata da engenharia de software, portanto, seria aquela técnica de gestão imbatível, aquela metodologia de desenvolvimento revolucionária, aquela ferramenta salvadora que impediria que nossos projetos se transformassem em criaturas fora de controle.

E Fred Brooks afirmava não ver, no horizonte da década seguinte, nenhuma bala de prata à disposição de engenheiros de software e gerentes de projeto.

Mais de cinquenta anos passaram desde o lançamento do System/360. Trinta anos nos separam da primeira publicação do artigo. Mais de duas décadas já se foram desde a revisão publicada pelo próprio autor. Mas não podemos negar que muitos fatores ainda contribuem para comprometer nossos prazos, afetar nossos custos e prejudicar a qualidade do nosso produto final.

Para avaliar se isso acontece por novos fatores ou se a análise de Brooks continua válida, precisamos entender dois conceitos fundamentais que ele pegou emprestado do filósofo Aristóteles para descrever o processo de construção de software: dificuldades essenciaisdificuldades acidentais.

Dificuldades Essenciais

Para Brooks, todo software é um conjunto interligado de recursos abstratos: conjuntos de dados, algoritmos, funções… Qualquer que seja a forma que escolhemos para representar esse software, sua essência (seu conjunto de recursos abstratos inter-relacionados) seria a mesma.

Em outras palavras, não importa se desenhamos um sistema usando técnicas da Análise Estruturada ou da Orientação a Objetos; não importa se construímos o software em Assembler, em Cobol ou em Swift; a dificuldade essencial de qualquer software estará na concepção correta de todos os recursos abstratos necessários e na correta relação e convivência desses recursos.

Acontece que toda forma de representação do software busca, de alguma maneira, abstrair sua complexidade e seus detalhes, adiando-os para etapas posteriores à fase de concepção e desenho. Não é difícil concordar que, qualquer que seja a abordagem de especificação, é sempre este o caminho que percorremos: partimos de alguns requisitos muito específicos (mas não muito detalhados) e a primeira coisa que fazemos, intuitivamente, é buscar os “diagramas de primeiro nível”, os “mock-ups iniciais”, as “funcionalidades do primeiro ciclo”, que, na prática apenas nos mantêm mais longe das infinitas combinações possíveis das máquinas de estado de cada componente do software.

Além da complexidade, outra dificuldade essencial estaria na expectativa de mudanças. Fred Brooks afirma que carros, prédios e computadores também são construídos para serem modificados, mas num nível bem menos profundo ao que se espera dos softwares. Ninguém constrói um carro pensando que, um dia, seu dono poderá transformá-lo num ônibus; ou uma casa que pode crescer e virar um arranha-céu.

Com sistemas é diferente. Eles nascem para atender a determinadas funcionalidades mas, com o tempo, os usuários passam a operá-los no limite, exigindo que essas funcionalidades sejam expandidas. Está em sua própria essência a possibilidade infinita de modificações, afinal softwares são conjuntos de instruções que programam uma caixa de componentes eletrônicos para fazer o que queremos. Se precisamos de funcionalidades diferentes, “só temos que alterar essas instruções”.

Existe aí um paradoxo sugerido por Brooks mas sobre o qual, realmente, pensamos muito pouco:  um computador pode ser reprogramado infinitamente, mas um software não. A intervenção contínua num sistema leva a um processo de entropia que, com o tempo, vai encarecer exponencialmente a sua manutenção.

Qualquer um que tenha trabalhado com sistemas legados já experimentou essa situação: algo conceitualmente simples de implementar exige um esforço aparentemente desproporcional. Mas eu não conheço nenhuma medida definitiva e fácil de ser apurada que mostre que um software atingiu seu limite de modificação. E, mesmo que houvesse uma, não acredito que fornecedores, analistas e programadores teriam coragem de recusar um serviço ou projeto por conta dessa limitação.

Outra dificuldade essencial mencionada por Brooks diz respeito a seu caráter “unvisualizable“, cuja tradução para “invisível” não seria perfeita. É possível elaborar alguns poucos desenhos para uma casa que se pretende construir: uma planta baixa da construção, uma planta da instalação elétrica, uma planta da instalação hidráulica, talvez um ou outro corte transversal, todos na mesma escala. Sobrepondo alguns desses desenhos é fácil perceber os ajustes necessários e os erros de “design”. E eles guiarão os empreiteiros até o final, ainda que algumas mudanças sejam possíveis durante e após a construção.

A realidade dos sistemas, mais uma vez, é diferente. Não dá pra botar um diagrama de fluxo de dados sobre um diagrama de entidades e relacionamentos e perceber os erros de concepção. Eles representam coisas muito diferentes, ainda que inter-relacionadas. A UML talvez tenha trazido mais complexidade a uma etapa que deveria, conceitualmente, facilitar a construção. Existe uma miríade de diagramas, modelos e templates que dependem da nossa capacidade de abstração para entender como eles se relacionam.

Um cliente consegue ver a planta baixa de uma casa e imaginar-se andando pelos aposentos, utilizando a cozinha e/ou posicionando seus móveis. Mas quando um usuário vê um de nossos diagramas, talvez ele tenha (e muito provavelmente terá) um entendimento consideravelmente diferente do nosso. E as maiores divergências surgirão mais adiante, quando as correções serão mais trabalhosas.

Dificuldades Acidentais

Brooks afirma que quando analisamos o progresso da engenharia de software das últimas décadas percebemos que os ganhos foram obtidos através da simplificação de dificuldades acidentais, e não das dificuldades essenciais que vimos até agora.

O maior ganho de produtividade se deu, por exemplo, com o surgimento das linguagens de programação de alto nível e seus diferentes graus de abstração. Programar em Cobol, Java, PHP ou Ruby pode ser muitas vezes mais rápido do que escrever o mesmo código em Assembler. Mas o código é apenas uma das muitas representações do software, e não a sua essência. O desenvolvimento de linguagens de alto nível, portanto, eliminou uma dificuldade acidental (a complexidade de escrever um algoritmo pensando em bits, registradores, canais, branches e sinalizações), mas não a complexidade essencial dos componentes lógicos e abstratos que precisam se relacionar para atender às necessidades do usuário.

Fred Brooks também menciona a evolução do compartilhamento de recursos e dos ambientes de desenvolvimento como grandes contribuidores para o aumento da produtividade na construção de software. De fato, a evolução desses ambientes – da perfuração de cartões nos anos 1960 às IDEs dos anos 2000/2010 – indiscutivelmente simplificaram bastante a atividade de desenvolvimento e manutenção de sistemas.

Editores integrados a bancos de dados, libraries e frameworks; gestão de configuraçãoQBEs; Work dispatching… Esses recursos são ferramentas que aceleram determinadas fases do processo de construção de software. Mas são como os robôs da indústria automobilística ou os CADs dos arquitetos: eles simplificam a execução de determinadas atividades: dificuldades acidentais. Mas eles pouco (ou nada) acrescentam para atenuar a complexidade lógica e a falta de visibilidade na concepção do software.

As perspectivas, em 1985

Brooks discute também algumas das soluções “promissoras” apontadas pelo mercado e pela comunidade científica em meados dos anos 1980 e que, em sua opinião, poderiam realmente endereçar as dificuldades essenciais da construção de software.

Ele menciona, por exemplo, a possibilidade de “comprar ao invés de construir”. De fato, o que vimos de lá para cá foi o crescimento de soluções como SAP e outros ERPs: “a melhor forma de evitar a complexidade da construção de um sistema é não desenvolvê-lo”, nas palavras do autor. Ainda que alguns produtos ofereçam um bom nível de customização, é fato que alguma concessão tem que ser feita por parte do cliente/usuário que pretende adotar uma solução pronta. Muitos “pacotes de prateleira” realmente reduziram (mas não eliminaram) a necessidade de manutenção de algumas aplicações. Mas a sobrevivência dos sistemas legados em grandes instalações mostra que esta não foi uma solução definitiva.

O autor analisa também os possíveis benefícios da prototipação, do refinamento progressivo de requerimentos e do desenvolvimento incremental. Em sua opinião, usuários não sabem o que querem, não conseguem antecipar todas as respostas que o sistema deve fornecer, e raramente pensaram nos problemas com o nível de detalhe que o analista de sistemas precisa para fazer seu trabalho.

De qualquer forma, Brooks sugere que a especificação de qualquer sistema exige uma intensa interação entre analistas e usuários.  Ele vai além e afirma, categoricamente, que considera impossível que alguém consiga compreender plenamente o que o cliente/usuário precisa antes de construir e testar “algumas versões diferentes” do produto.

O desenvolvimento incremental proposto anos antes por Harlan Mills seria, portanto, uma solução possível para enfrentar as dificuldades essenciais da engenharia de software. O entusiasmo que percebemos hoje com Agile, Scrum e XP aparentemente confirmam a opinião do autor. Eu, particularmente, ainda tenho dúvidas sobre a aplicabilidade comercial desse tipo de abordagem, principalmente em projetos cujos entregáveis tenham que estar 100% prontos em determinado momento. Mas isso é tema para reflexão em outro post.

Conclusão

O artigo termina com uma conclusão provocadora: a construção de software é um processo criativo, e “grandes sistemas são produzidos por grandes designers“. Apesar disso, Brooks afirma que vê as empresas investirem muito mais na capacitação gerencial do que na evolução de seus engenheiros de software.

O autor sugere que as empresas devam identificar seus top designers o mais cedo possível, porque “os melhores nem sempre são os que têm mais experiência”. Defende também que esses top designers sejam mentorizados, tenham um plano de carreira específico e sejam incentivados a atuar em comunidades de técnicas, onde a troca de experiências estimule o desenvolvimento profissional.

Técnicas e ferramentas poderiam facilitar o trabalho de “grandes engenheiros de software”, mas não garantiriam a construção de “grandes sistemas”. Se a conclusão do autor estiver certa, caímos mais uma vez no paradigma de que a engenharia de software está muito mais próxima do artesanato do que da engenharia.

Mas como conciliar esse aspecto criativo da atividade de construção de sistemas com as exigências comerciais e competitivas do business da Tecnologia da Informação? Como estabelecer uma operação confiável, que possa ser planejada, monitorada e implementada sem depender exclusivamente de talentos e genialidades individuais?

Essas são perguntas cujas respostas ainda estamos procurando.


Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *