Tech

Code Comprehension e seu papel na revisão de código

No post anterior, cobrimos o que é Code Comprehension e falamos sobre alguns exemplos de sua presença no ciclo de vida de desenvolvimento de software. Agora vamos falar sobre o processo de revisão de código, suas motivações, desafios e como a pesquisa de Code Comprehension pode ser útil.

Você também pode ouvir esse conteúdo:

Revisão de código moderna

A revisão de código por pares é uma prática difundida de engenharia de software que é realizada com diferentes motivações. Normalmente é usada para localizar defeitos no código, mas também pode ser usada para outros fins, como transferência de conhecimento e refatoração.

Ela pode ser executada em vários estágios de um projeto de software e de várias formas. Por exemplo, pode-se escolher revisar apenas uma parte do código em que está interessado ou fazer uma revisão completa do código-fonte. Pode-se esperar para revisar quando o software ou algum componente estiver concluído ou revisá-lo continuamente, a cada commit ou pull request.

O artigo de Bacchelli e Bird [1] descreve revisão de código moderna como “(1) informal (em contraste com o estilo Fagan), (2) baseado em ferramentas e que (3) ocorre regularmente na prática hoje em dia, por exemplo, em empresas como Microsoft, Google, Facebook e em outras empresas e projetos de software open-source”. Este tipo de revisão é comumente praticada hoje em dia, seja pelos próprios desenvolvedores, seja por profissionais de garantia de qualidade ou de segurança. Uma vez que uma nova mudança é enviada para o repositório de origem, ela se torna disponível para revisões e este processo geralmente é apoiado por uma ferramenta que pode exibir as mudanças em um formato agradável e permitir que o revisor insira comentários.

Motivações e obstáculos em revisão de códig

No artigo “Expectations, Outcomes, and Challenges Of Modern Code Review” [1], os autores realizaram um estudo usando a análise de estudos anteriores, observações, entrevistas e questionários. Desenvolvedores, revisores de código e gerentes forneceram alguns dados que ajudaram os autores a mapear as motivações, expectativas e os desafios da revisão de código moderna.

De acordo com este estudo, as motivações mais importantes para revisão de código são:

  • Encontro de defeitos – para achar bugs;
  • Melhoria de código – para melhorar a consistência do código, legibilidade, etc.;
  • Soluções alternativas – para encontrar uma melhor implementação;
  • Transferência de conhecimento – para fins de aprendizagem;
  • Conscientização e transparência da equipe – para tornar a equipe ciente da evolução do código e tornar as alterações do código transparentes.
  • Compartilhamento de posse do código – relacionado a “Conscientização e Transparência da Equipe”, mas com conotação de colaboração.

Os resultados mostraram que nem sempre as expectativas são atendidas. Comentários sobre bugs (encontrar bugs foi uma das principais motivações) foram poucos e superficiais. Os desenvolvedores e gerentes esperavam comentários mais aprofundados sobre questões conceituais e de design.

Durante este estudo, muitos comentários apareceram sobre os desafios na revisão do código. O principal fator para uma revisão de código eficaz é a compreensão. Mesmo quando há pequenas mudanças na base do código, o revisor precisa ler outros trechos para obter todo o contexto necessário para entender o que está acontecendo. Leva tempo para entender o código com o qual você não está familiarizado, mas uma vez que o entendimento é adquirido, acreditamos que o resultado da revisão pode ser mais produtivo em termos de tempo gasto no processo e na qualidade do feedback.

Outro estudo [6] investigou questões relacionadas à compreensão das mudanças no código. Os autores queriam saber em quais cenários a compreensão do código é necessária, a frequência desse processo, quais informações são necessárias e o que pode ser feito para melhorar a eficácia e eficiência para entender as alterações do código.

Este artigo listou que a compreensão do código é necessária para:

  • Revisar as mudanças de outras pessoas;
  • Corrigir bugs;
  • Desenvolver nova funcionalidade;
  • Revisar suas próprias mudanças;
  • Escrever / atualizar casos de teste;
  • Refatoração;
  • Resolver conflitos de “merge”.

Sobre a frequência, demonstrou que a maioria dos participantes precisava entender as mudanças de código diariamente.

De acordo com os dados coletados, as 3 principais informações para compreender as mudanças no código são:

  • Justificativa – Qual é a razão por trás dessa mudança de código?
  • Exatidão – Esta alteração está correta? Funciona como esperado?
  • Risco – Essa mudança quebra algum código em outro lugar? Como?

E as informações mais difíceis de adquirir também foram coletadas. As 3 principais são:

  • Consistência – Existem outros lugares que precisam de mudanças semelhantes?
  • Risco – Essa mudança quebra algum código em outro lugar? Como?
  • Comportamento – Como essa mudança altera o comportamento dinâmico do programa?

Sobre o que poderia ser feito para melhorar a eficácia e eficiência para entender as mudanças de código, os autores mapearam duas abordagens:

  • Determinar o risco de uma mudança – De acordo com a maioria dos participantes, testes (por exemplo, testes unitários) e revisão do código são as duas práticas principais para determinar o risco de uma mudança. Duas funcionalidades foram propostas para melhorar estas práticas: 1) uma funcionalidade para detectar o código e os casos de teste afetados pela mudança e também notificar o responsável pelo teste sobre a necessidade de um reteste; 2) uma funcionalidade para permitir análise estática (exemplo, ir para definição) na tela de diff.
  • Decompor uma mudança – Às vezes uma mudança é grande e afeta muitos arquivos; em outras, a mudança é a implementação de muitas funcionalidades ou correções de bugs que não necessariamente relacionados. Isso torna o entendimento do código mais difícil. Para mitigar isso, uma funcionalidade foi proposta para decompor uma mudança em outras menores, agrupadas por seu relacionamento.

Desafios

Em ambos os artigos [1] e [6], podemos extrair comentários que ilustram alguns dos desafios enfrentados por quem está fazendo revisão de código:

“A coisa mais difícil ao fazer uma revisão de código é entender o motivo da mudança” [1]

“A análise de impacto global requer compreensão contextual. Ao revisar uma mudança pequena e desconhecida, muitas vezes é necessário ler muito mais código do que o que está sendo revisado. ” [1]

“Leva muito mais tempo para entender código desconhecido, mas mesmo assim o entendimento não é muito profundo.” [1]

“Normalmente, eu precisaria encontrar manualmente as partes do código que estão usando a parte alterada e descobrir como essa mudança afeta as chamadas. Às vezes não é óbvio pelo próprio código, eu tenho que realmente percorrer o código com o depurador para entendê-la. ” [6]

“É difícil avaliar os impactos em outros componentes, a menos que haja uma interface clara entre este e outros. Muito frequentemente, outros componentes têm algumas suposições sobre este componente, embora essas suposições não estejam documentadas. ” [6]

A revisão de código é uma tarefa demorada e requer algum contexto sobre o código que está sendo revisado. Mesmo para pequenas alterações, o revisor precisa ler mais código, que geralmente estão distribuídos em muitos arquivos. Às vezes, uma mudança de código é grande e não relacionada (por exemplo, diferentes correções de bugs no mesmo commit). Além dos principais desafios extraídos dos artigos, adicionamos a falta de documentação, comentários pouco claros em mensagens de commit e estilo de código inconsistente como outros obstáculos para uma revisão de código mais produtiva.

Como Code Comprehension ajuda?

Como vimos na seção anterior, o entendimento do código é considerado o aspecto mais importante para revisões de código bem-sucedidas. Quando consideramos o processo moderno de revisão de código, isso significa principalmente compreensão da mudança e do contexto. Em um estudo recente [3] sobre por que os defeitos de segurança não são detectados por revisões de código, os pesquisadores descobriram que as vulnerabilidades que não requerem o entendimento de muitas linhas do contexto do código têm uma chance maior de serem detectadas, enquanto as vulnerabilidades que requerem o entendimento de um contexto de código maior têm maiores chances de permanecerem indetectadas.

Conforme descrito no primeiro post desta série [7], os ambientes de desenvolvimento integrado (IDEs) modernos já incorporam e fornecem muitas funcionalidades de suporte à compreensão de código, como visualizações de hierarquia de chamadas, navegação de código, localizador de referências, localizador de definições e visualização dividida. Esse tipo de ferramenta às vezes oferece suporte a atividades de revisão de código e, portanto, essas funcionalidades podem ser usadas para melhorar a compreensão do código. No entanto, é comum que as revisões de código sejam conduzidas em ferramentas Web que podem carecer dessas funcionalidades e fornecer apenas o highlight da sintaxe do diff contendo a alteração do código, o que pode tornar mais difícil para o revisor alcançar a compreensão da mudança e do contexto.

Outras pesquisas vão um passo além e exploram tópicos mais avançados, como decomposição de conjuntos de mudanças para revisão de código [2], relação da carga mental e a capacidade de memória de trabalho com a eficácia da revisão de código [4], influência da ordem em que as mudanças de código são apresentadas ao revisor [4] e redução da carga cognitiva do revisor [5].

Se beneficiando como revisor

Um conselho para os revisores é dar preferência a ferramentas que suportem pelo menos funcionalidades básicas de compreensão de código. Isso ajudará no processo de compreensão do contexto do código e como as alterações afetam a base de código existente. Isso é ainda mais importante em situações em que o revisor tem pouco ou nenhum conhecimento prévio sobre o código envolvido nas mudanças, como é o caso de desenvolvedores revisando o código de um componente no qual não trabalharam ou profissionais de segurança terceirizados revisando as mudanças de código para encontrar vulnerabilidades, por exemplo.

Outro ponto é sobre como preservar o conhecimento obtido durante uma revisão de código e torná-lo acessível para revisões subsequentes. Hoje em dia é comum os revisores apenas deixarem comentários nas telas de revisão de código, mas isso poderia ser melhorado? O que poderia tornar mais fácil para o revisor compreender algumas alterações no código? Isso é algo para se pensar.

Conclusão

Neste post, cobrimos o processo moderno de revisão de código, seus desafios e principais requisitos para revisões bem-sucedidas. Vimos algumas pesquisas [1, 6] que descrevem a compreensão do código como o elemento mais importante nas revisões. Também vimos como os estudos de Code Comprehension se relacionam com essa área.

Este é o segundo post no blog de uma série sobre Code Comprehension. Fique ligado para mais conteúdo sobre o assunto!

Referências

  1. Expectations, Outcomes, and Challenges Of Modern Code Review
  2. Helping Developers Help Themselves: Automatic Decomposition of Code Review Changesets
  3. Why Security Defects Go Unnoticed during Code Reviews? A Case-Control Study of the Chromium OS Project
  4. Associating Working Memory Capacity and Code Change Ordering with Code Review Performance
  5. Cognitive-Support Code Review Tools
  6. Code Comprehension: O que é?

Autores deste artigo:
Gabriel Quadros – Sênior Information Security Analyst
Ricardo Silva – Information Security Analyst

Nova call to action
About author

Articles

Uma equipe de profissionais, altamente conectados com as notícias, técnicas e informações sobre a segurança de aplicações.
Related posts
Segurança de AplicaçãoTech

Técnicas de Programação Segura em JavaScript

O JavaScript é uma das linguagens de programação mais utilizadas para o desenvolvimento de…
Read more
Segurança de AplicaçãoTech

Tudo que você precisa saber de Log4j e como garantir a segurança de sua aplicação

Uma falha importante de segurança na biblioteca Apache Log4j, escrita em Java, foi revelada em 9 de…
Read more
Code FightersTech

Introdução a secure code review em aplicações Go

Antes de entrarmos, de fato, à nossa introdução a secure code review em aplicações Go, vamos a…
Read more

Deixe um comentário