Mais Braço: Por que Desenvolver Software é Diferente de Colher Cana-de-Açúcar
A afirmação no título desse post pode parecer óbvia, mas não é essa a impressão que se tem quando acompanhamos muitas das decisões tomadas na área de desenvolvimento de software no Brasil e no mundo. Não é incomum ver gerentes ou líderes de negócio tentando lidar com prazos apertados através da simples disponibilização de mais recursos (humanos ou não) para a equipe que está com a mão na massa. Se o caso for simples o suficiente, uma emergência pode até ser resolvida, mas isso não quer dizer que a produtividade da equipe foi imediatamente aumentada. Como assim?
A produtividade é a razão entre o valor gerado e os recursos aplicados no processo produtivo. Portanto, se você aplicou mais recursos apenas para garantir a entrega que já era esperada, sem nenhum ganho adicional, sua produtividade necessariamente caiu. Sendo assim, vê-se que volume de entrega é diferente de produtividade. Isso não impede que muitos líderes tentem lidar com esse tipo de problema através de:
Mais “braço”: aumentar o tamanho da equipe. Na maioria dos casos emergenciais, isso é uma falácia. A adição de pessoas a uma equipe de desenvolvimento tem o efeito imediato de diminuir a volume de entrega, já que o processo de absorção desse novo membro (treinamento, passagem de contexto, configuração de ambiente de desenvolvimento, etc.) vai exigir que outros desenvolvedores deixem de produzir para ajudá-lo. Em um contexto não-emergencial, essa perda de capacidade é compensada quando o novo membro finalmente passa a trabalhar em velocidade de cruzeiro, o que realmente pode aumentar o volume de entrega.
Mais tempo: a liberação de horas extras. Essa é outra falácia, já que a equipe irá necessariamente ficar mais cansada, o que pode diminuir não apenas o volume, mas também a qualidade das entregas.
Mais incentivo: a equipe pode até se animar com o prospecto de bônus ou mais folgas, mas os problemas provocados pelo cansaço e estresse também podem ocorrer aqui.
O que mais me impressiona sobre esse abordagem é que ela tem os mesmos princípios básicos da gerência de uma típica plantation de séculos atrás. Para aumentar o volume produzido, um fazendeiro daquela época poderia comprar mais escravos (mais braço), colocá-los para trabalhar por mais horas do dia (mais tempo) e/ou castigá-los mais severamente quando começassem a demonstrar cansaço (mais “incentivo”). Em outras palavras, temos líderes tentando gerenciar uma indústria de alta tecnologia no século XXI como se gerenciassem fazendas de cana-de-açúcar dos séculos XVII ou XVIII.
Veja que essa lógica está longe até do século XX. Nos primórdios do desenvolvimento de software, tentou-se usar uma abordagem semelhante a linha de produção do fordismo, com equipes separadas por atividades específicas no ciclo de desenvolvimento do modelo em cascata. Posteriormente, alguns processos ágeis de desenvolvimento se inspiraram parcialmente no toyotismo, adaptando mecanismos como o Kanban e o lean manufacturing para modernizar o processo de desenvolvimento. Ainda assim, há uma divergência na forma como a gerência e os programadores enxergam o processo de desenvolvimento como um todo.
Por mais que a gerência (ou a área de negócios, ou o cliente, etc.) queira que o processo de desenvolvimento seja perfeitamente previsível, a ponto de tentar prever a duração de cada atividade, a natureza desse trabalho não permite esse nível de determinismo. Ainda que seja fruto de uma disciplina exata, as quantidades de soluções possíveis e de variações no problema sendo resolvido são tão altas que o processo acaba se tornando extremamente subjetivo. Não se trata de achar a solução correta, mas de se decidir quais das soluções corretas melhor atendem o cenário que está sendo tratado. Em alguns casos, é tão difícil tomar essa decisão de antemão que só resta à equipe técnica “rolar os dados” e mitigar os riscos.
Um dos relatos mais claros que vi recentemente sobre os pormenores do desenvolvimento de software foi feito pelo jornalista Andrew Smith nesse artigo para a 1843 Magazine. Indo além da programação, ele começa a entender melhor como funciona a cabeça dos programadores e qual é a natureza dos problemas com os quais eles têm que lidar diariamente.
Durante as seis semanas que passo construindo um mini-website, aprendo algumas valiosas lições. A mais importante é que computadores são insanamente literais e pedantes. É fácil deixar passar uma vírgula a menos ou um colchete a mais e isso pode fazer com que a máquina fique olhando para você incompreensivelmente, com dedinhos metafóricos batendo na mesa. Uma programadora de alta-tecnologia me conta como passou seis meses em busca de um bug dentro de um grande sistema, sabendo que outros já haviam tentado e falhado, e finalmente rastreando o problema para um sublinhado que deveria ser um traço. Um “demônio do shift”, ela o chama. Não me admira que programadores possam parecer irritáveis e secos para pessoas de fora.
E ele se surpreende com a subjetividade já no início de seu pequeno projeto:
Muitas vezes, Javascript faz parecer que uma sopa de letrinhas foi vomitada na tela; já Python é organizada e comparativamente fácil de se olhar. Fico chocado ao entender que minha afinidade por Python é primariamente uma questão estética, um capricho do meu próprio temperamento. Estou começando a entender porque diferentes tipos de personalidade se aglomeram ao redor de diferentes linguagens.
Quando a fase de treinamento finalmente acaba e ele se considera pronto para começar a escrever seu código, Smith não faz ideia do que fazer ou por onde começar, sofrendo do que parece ser um bloqueio criativo. Sobre isso, um dos programadores que o ajudam faz uma interessante observação:
“O que as pessoas esquecem”, ele diz, “e que eu considero importante saber, é que programação nunca é fácil. Você nunca faz a mesma coisa duas vezes, pois o código é infinitamente reproduzível, e se você já resolveu um problema e o encontra novamente, você apenas usa sua solução anterior. Então, por definição, você meio que está sempre nessa fronteira além do que você já sabe. E uma das coisas que você tem que aprender é aceitar esse sentimento – de estar constantemente errado.”
E, depois de ser prejudicado por seu próprio preciosismo e indecisão, Smith atinge um novo grau de maturidade.
Finalmente, eu me reorganizo, me lembrando de um email que me foi enviado por Gerald Weinberg, autor de um livro chamado The Psychology of Computer Programming, no qual ele sugere que um computador é “como um espelho mental que reflete de forma cintilante todo seu mais pobre pensamento.” Minha maior fraqueza pessoal? Uma tendência de tentar complicar demais as coisas (eu sou um “arquiteto astronauta“, no jargão da área). Eu apago o meu código e começo novamente. Mais tarde, Nicholas Tollervey me consola dizendo que meu tempo não foi desperdiçado, pois eu estava praticando – o equivalente em programação a formação de caráter – e eu fiquei quase tentado a acreditar nessa gentileza.
Essa “formação de caráter” é vital. A maturidade é a principal característica de uma equipe de alta performance, pois permite que ela evite muitas das falácias possíveis nessa área, maximizando o volume e a qualidade das entregas e, consequentemente, a produtividade. Porém, ao contrário do que se pode pensar, tempo de experiência não é sinônimo de maturidade.
Nesse sentido, é mais importante observar a capacidade da equipe de aprender com os próprios erros e com os erros dos outros, além da capacidade de evitar armadilhas como as do excesso de autoconfiança (sobre o qual comentei um pouco aqui) ou o novelty bias (a tendência que temos de achar que uma tecnologia nova é melhor simplesmente porque é nova). Consequentemente, é muito difícil contratar uma equipe dessas, exigindo que organizações que estejam dispostas a ir nessa direção também estejam dispostas a arcar com o processo de evolução necessário, até que suas equipes atinjam o nível desejado de excelência.