Dev (Back & Front)ARTIGO

Qual o efeito da propriedade do código sobre o código?

Aprendi que, independentemente da sua equipe, não é possível permitir que as pessoas trabalhem completamente sozinhas.

Em meu último artigo, falei sobre modelos de propriedade de código e as razões pelas quais você escolheria um modelo (estrito, restrito ou coletivo) em vez de outro. A maior parte dos argumentos relativos à propriedade do código foca em gerenciamento de pessoas, dinâmica de times e efeitos no ritmo de desenvolvimento. Mas e quanto aos efeitos de longo prazo sobre o formato, a estrutura e a qualidade do código? O modelo de propriedade do código exerce alguma influência? Quais são os efeitos de permitir que todos trabalhem em um mesmo código ou ter 1 ou 2 pessoas trabalhando num mesmo trecho de código por um longo tempo?

Propriedade coletiva e qualidade do código

Com o tempo, mudanças tendem a se concentrar em certas áreas do código: na lógica do core e por trás de interfaces (assista à fascinante exposição de Michael Feather intitulada Discovering Startling Things from your Version Control System). Isso significa que quanto mais tempo um sistema está em funcionamento, maiores são as chances de que pessoas diferentes mexam num mesmo código. Alguns trabalhos de pesquisa bastante interessantes confirmam o que deveria ser óbvio: as pessoas que têm a melhor compreensão de um determinado código são aquelas que trabalham mais tempo com ele, e que as pessoas que conhecem melhor o código cometem menos erros.

Em Don’t Touch my Code! (pdf), pesquisadores da Microsoft (aliás, o principal autor, Christian Bird não é meu parente, ou pelo menos não um parente que eu conheça) descobriram que quanto mais pessoas mexem em um mesmo trecho de código, maiores são as chances de mal entendidos e erros. Não é surpresa que pessoas que não trabalharam num trecho de código anteriormente cometeram mais erros, e na medida em que o número de desenvolvedores trabalhando em um mesmo módulo aumentou, aumentaram também as chances de introduzir bugs.

Outro estudo, Onwnership and Experience in Fix-Inducing Code (pdf), tenta responder o que é mais importante na qualidade do código: “muito fogo entorna o caldo”, ou “given enough eyeballs, all bugs are shallow” (com um número suficiente de olhos, todos os bugs são visíveis)? Mais pessoas trabalhando em um mesmo código levam a mais bugs, ou isso significa que há mais chances de encontrar os bugs num tempo menor? Esse time de pesquisa descobriu que a experiência específica de um programador com um código foi o fator mais importante para determinar a qualidade do código – código alterado pelo programador que faz a maior parte do trabalho nesse código é de qualidade superior quando comparado a código escrito por outra pessoa que não tem familiaridade com o código, mesmo que essa outra pessoa seja um desenvolvedor sênior que trabalhou em outras partes do projeto. E eles descobriram que quanto menos gente trabalhando em um trecho de código, menos são os bugs a serem corrigidos.

Um estudo de mantenedores do Linux (pdf) reforça que o número de desenvolvedores trabalhando num mesmo trecho de código aumenta significativamente as chances de bugs e problemas de segurança: código escrito por mais do que 9 desenvolvedores é 16 vezes mais propenso a problemas de vulnerabilidades de segurança, e mais vulnerabilidades são introduzidas pelos desenvolvedores que estão realizando mudanças em muitos trechos de código diferentes.

Efeitos no longo prazo do modelo de propriedade na estrutura do código

Já trabalhei em empresas onde o mesmo programador era responsável pelo mesmo código por 3, 4, 5 ou mesmo 10 (e as vezes até mais) anos. Com o passar do tempo, as inclinações, os pontos positivos, as deficiências e as idiossincrasias daquele programador vão sendo todas amplificadas, deixando marcas profundas no código. Isso pode ser uma coisa boa ou ruim.

A coisa boa é que com uma pessoa fazendo a maior parte das mudanças, a consistência interna em qualquer trecho de código será maior – você poderá olhar para um pedaço de código escrito por esse desenvolvedor e, uma vez que você entender a sua maneira de fazer as coisas, de pensar, seus padrões e os idiomas que ele prefere, tudo se tornará familiar e fácil de seguir. O seu estilo e a abordagem talvez mudem ao longo do tempo, na medida em que ele aprende e evolui como desenvolvedor, mas você normalmente será capaz de antecipar como o restante do código funcionará; e reconhecerá no que ele é bom e quais são os seus pontos fracos, que tipo de erros ele tende a fazer: como mencionei no artigo anterior, isso torna o código mais fácil de revisar e testar e, portanto, mais fácil de encontrar e corrigir os bugs.

Se um desenvolvedor tender a escrever código bom, limpo e conciso, e se ele for diligente quanto a refatorar e a manter o código dessa forma, então a maior parte do código será boa, limpa, concisa e fácil de entender. É claro que isso também é válido caso ele tenda a escrever código sujo, difícil de entender e mal estruturado. Então a maior parte do código também seguirá essa mesma tendência. Mais uma vez, até isso pode ser uma coisa boa – pelo menos o código ruim é isolado, e você sabe o que precisa reescrever, em vez de ter alguém que espalhou um pouco de porcaria por todos os cantos.

Quando a propriedade é alterada – quando o mantenedor principal deixa o projeto e um novo chega -, a estrutura e o estilo do código também serão alterados. Talvez não do jeito certo, porque um novo mantenedor leva algum tempo para se acostumar com o código antes de colocar sua marca nele, mas em algum ponto ele colocará sua marca nele – mesmo inconscientemente – segundo suas próprias preferências, inclinações e formas de pensar ao refatorar ou reescrever o código para adaptá-lo a elas.

Se muitos desenvolvedores trabalharam num mesmo pedaço de código, eles introduzirão diferentes ideias, técnicas e abordagens ao longo do tempo à medida que cada um faz sua parte, ao reescrever ou refatorar as coisas de acordo com suas próprias ideias do que é fácil de compreender ou não, do que é certo ou errado. Cada um deixará diferentes tipos de erros. Mesmo com convenções e padrões compartilhados consistentemente pelo time, diferenças e inconsistências podem se acumular ao longo do tempo, conforme pessoas entram e saem da equipe, criando dissonâncias e tornando mais difícil seguir o código, testar e revisar, conservando seu design.

Modelos de propriedade e refatoração

Mas como Michael Feathers descobriu ao garimpar históricos de controle de versão, há também um efeito positivo na propriedade do código, na medida em quem mais pessoas mexem nele.

Com o tempo, métodos e classes tendem a se tornar maiores porque é mais fácil acrescentar código a um método existente do que escrever um novo método, e é mais fácil acrescentar um novo método a uma classe existente do que criar uma nova classe. Ao relacionar o número de desenvolvedores que mexeram num código com o tamanho dos métodos deste, a pesquisa de Feathers mostra que na medida em que a quantidade de desenvolvedores aumenta, o tamanho médio dos métodos tende a diminuir. Em outras palavras, ter várias pessoas trabalhando em um mesmo código incentiva a refatoração e um código simples, porque as pessoas que não estão familiarizadas com o código precisam simplificá-lo primeiro para poder entendê-lo.

Feathers também descobriu que código por trás de APIs tendem a ser especialmente bagunçados – porque algumas interfaces são muito difíceis de modificar, os programadores são forçados a criar suas próprias gambiarras por trás delas. Martin Fowler explica como esse problema é agravado pela propriedade estrita do código, que inibe a refatoração e torna o código mais rígido internamente:

No modelo de propriedade estrita do código, há o meu código e o seu código, e eu não posso mudar o seu código. Se eu quiser mudar o nome de um dos meus métodos, e se ele for chamado pelo seu código, preciso fazer com que você mude a chamada, antes que eu possa mudar o meu nome. Ou eu terei que passar por todo o processo de obsolescência. Essencialmente, qualquer uma das minhas interfaces usadas por você torna-se publicada nessa situação, porque não posso tocar seu código de maneira alguma.

Há um terreno intermediário, que eu chamo de propriedade restrita. Com ela, há o meu código e o seu código, mas é aceitável que eu possa alterar o seu código. Há uma expectativa de que você ainda seja responsável pela qualidade geral do seu código. Se eu for mudar apenas um nome de método no meu código, eu simplesmente faria. Mas, por outro lado, se eu fosse mover algumas responsabilidades entre as classes, devo ao menos informar a você o que eu faria antes de efetuar a mudança, uma vez que é o seu código. Isso é diferente do modelo de propriedade coletiva de software.

Propriedade restrita e refatoração combinam; propriedade coletiva de código e refatoração combinam. Mas propriedade estrita de código e refatoração, não, porque a maior parte das fatorações que você deseja fazer não pode ser feita. E você não pode fazer porque não tem autorização para mudar o código de chamada. Por isso, a propriedade estrita de código não se dá bem com refatoração. (Princípios de Desing e Propriedade de Código)

Propriedade, deficiência técnica e percepção profunda

Alguém que é o único responsável por um determinado código tem uma tolerância maior para sua complexidade, porque, apesar de tudo, é o código dele, e ele sabe como este funciona. Portanto, ele não precisa ficar constantemente simplificando o código apenas para alterar ou corrigir alguma coisa. É fácil para ele tomar um atalho e mesmo “atalhos de atalhos”. Esse tipo de coisa pode se acumular com o tempo e você pode acabar com um sério problema de deficiência técnica – uma pessoa que sempre trabalha no código, não porque o problema é altamente especializado, mas porque o código atingiu um ponto em que ninguém além do “João” consegue entendê-lo e trabalhar com ele.

Há também um outro lado em despender mais tempo no código. Quanto mais tempo você gasta no mesmo problema, maior é a sua compreensão em relação a ele. Ao retornar ao mesmo código várias vezes, é possível reconhecer os padrões e as áreas que você quer evoluir, e aceitar que está disposto a aceitar mais. Na medida que você aprender mais sobre a linguagem e sobre os frameworks, pode voltar ao código e reescrevê-lo de uma maneira mais simples e segura. Poderá ver como o design realmente deveria ser, para onde o código precisa ir e conduzi-lo até lá.

Há também a oportunidade de não se ater a certas áreas. Focar-se em um problema permite que você crie soluções melhores. Especificamente, desenvolva uma visão do que precisa ser feito e trabalhe em prol dessa visão, revisando constantemente aquilo que é necessário… Se você pula de problema em problema, é mais provável que crie uma solução inferior. Você resolverá o problema, mas criará um maior custo de manutenção para o projeto no longo prazo. Jay Fields, em Taking a Second Look at Collective Code Ownership

Até agora, a única forma que encontrei de um time resolver um problema realmente grande é quebrá-lo em pedaços e permitir que diferentes pessoas cuidem de diferentes partes da solução. Isso significa que resolver problemas e custos no longo e no curto prazo, trocar qualidade e produtividade por flexibilidade e consistência – não apenas flexibilidade e consistência em relação ao funcionamento do time, mas em relação ao código também.

O que aprendi até hoje é que não importa se você tem um time no qual cada um está cuidando de um pedaço do seu código, ou em um ambiente mais aberto em relação a isso, ou mesmo que todos estejam trabalhando em todos os códigos ao mesmo tempo, o tempo todo; não é possível permitir que as pessoas trabalhem completamente sozinhas. É altamente relevante ter pessoas trabalhando juntas, quer seja pareando em XP (Extreme Programming) ou realizando revisões regulares, deixando o ego de lado. Para ajudar pessoas a trabalharem em um código que elas nunca viram antes – ou para auxiliar mantenedores de longa data a perceberem seus pontos fracos, para atuar como mentor e compartilhar novas ideias e técnicas, evitar que pessoas caiam em maus hábitos, ter controle sobre a complexidade, reforçar a consistência sobre toda a base de código ou em trechos específicos.

***

Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://swreflections.blogspot.com.br/2013/04/what-does-code-ownership-do-to-code.html

É um CTO, gerente de desenvolvimento de software e gerente e projetos experiente, que vem trabalhando em desenvolvimento e manutenção de software, qualidade de software e segurança. Nos últimos 15 anos, gerenciou equipes na construção e na operação de sistemas financeiros de alto desempenho. Tem especial interesse em como pequenas equipes podem ser mais efetivas na construção de software real.

Ver perfil