Boas Práticas Nathan Geeksman

Métricas de Qualidade de Código: Cobertura, Complexidade Ciclomática

Métricas de Qualidade de Código: Cobertura, Complexidade Ciclomática

Métricas de Qualidade de Código: Cobertura, Complexidade Ciclomática

Introdução

O desenvolvimento de software é um processo contínuo que envolve a criação, manutenção e melhoria das aplicações software. À medida que as aplicações crescem em complexidade e escala, é cada vez mais importante medir e melhorar a qualidade do código-fonte.

Uma abordagem comum para alcançar isso é utilizar métricas de qualidade de código, que permitem avaliar aspectos específicos do código e identificar áreas de melhoria. Nesse artigo, vamos focar nas duas métricas mais importantes: Cobertura e Complexidade Ciclomática.

Essas métricas são relevantes porque ajudam a garantir que o código esteja bem estruturado, fácil de manter e menos propenso a erros. Elas também permitem avaliar se as melhorias implementadas tiveram um impacto positivo na qualidade do código.

Ao final desse artigo, você terá uma compreensão clara sobre o que são Cobertura e Complexidade Ciclomática, como elas são medidas e por quais razões são importantes no desenvolvimento de software.

O que é e por que importa

A Cobertura é a medida quantitativa da percentagem de linhas de código dentro de um determinado conjunto de teste que são executadas durante a execução dos testes. Ela é calculada dividindo o número de linhas cobertas pelos testes pelo total de linhas de código do software e multiplicando por 100.

Por exemplo, se um conjunto de teste abrange 80% das linhas de código de um projeto e há 10 mil linhas em todo o código, a cobertura é de 80%.

A Cobertura é importante porque demonstra que os testes estão cobrindo as áreas mais críticas do software. Com uma boa cobertura, podemos ter confiança na qualidade do produto e reduzir o risco de erros ocultos.

Por outro lado, a Complexidade Ciclomática (CC) é uma métrica que mede a complexidade de um módulo de código considerando não apenas a estrutura, mas também as interações entre as instruções. Ela está relacionada ao número de decisões tomadas pelo programa ao executar, e seu valor aumenta à medida que o programa torna-se mais complicado.

A Complexidade Ciclomática é calculada usando a fórmula: CC = P + 1, onde P é o número de predicados (condições) no código. Por exemplo, se um bloco de código tem quatro condições e uma instrução sem condição, a complexidade ciclomática seria de 5.

A Complexidade Ciclomática é importante porque ajuda a identificar áreas do código que são propensas a erros ou necessitam de revisão. Ela também é útil para avaliar se as melhorias implementadas na codificação resultaram em uma redução da complexidade, tornando o software mais fácil de manter e menos propenso a problemas futuros.

Como funciona na prática

Para entender como a Cobertura e a Complexidade Ciclomática funcionam na prática, vamos analisar as etapas abaixo:

Calculando a Cobertura

  • Especificar testes: Identifique os cenários de teste que precisam ser cobertos. Isso inclui casos de sucesso e erro para garantir que o software seja testado em todas as possibilidades.
  • Mapeamento do código: Analise o mapa do código, identificando as linhas de código importantes para garantir a execução dos cenários de teste planejados.
  • Implementação de testes: Implemente os testes correspondentes às especificações. Certifique-se de que cada linha crítica esteja sendo coberta por um ou mais testes.

Calculando a Complexidade Ciclomática

  • Análise do código: Analise as estruturas condicionais (if, switch, etc.) e os loops no código para determinar o número de predicados (P) presentes.
  • Contagem de decisões: Para cada bloco de código, contabilize o número de decisões tomadas. Isso inclui não apenas as estruturas condicionais, mas também o loop.
  • Cálculo da Complexidade Ciclomática: Use a fórmula CC = P + 1 para calcular a Complexidade Ciclomática do módulo de código.

Integração com Ferramentas

  • Configuração das ferramentas: Configure as ferramentas de teste e análise de código para coletar dados sobre a Cobertura e a Complexidade Ciclomática.
  • Execução dos testes: Execute os cenários de teste planejados para calcular a Cobertura.
  • Análise da complexidade ciclomática: Use ferramentas que podem calcular a Complexidade Ciclomática diretamente, sem necessidade de uma análise manual.

Essas etapas fornecem uma visão geral de como implementar e integrar as métricas de Qualidade de Código no seu processo de desenvolvimento.

Exemplo real

Teste de Funcionalidade - Autenticação Usuário

public class UsuarioController {
    public boolean autenticarUsuario(String login, String senha) {
        // Buscar no banco de dados a senha correspondente ao login
        String senhaBd = buscarSenhaNoBanco(login);
        
        if (senhaBd != null && senhaBd.equals(senha)) {
            return true;
        } else {
            return false;
        }
    }

    private String buscarSenhaNoBanco(String login) {
        // Simulando busca no banco de dados
        String senha = "password123";
        
        if (login.equals("admin")) {
            senha = "senhaAdmin";
        }
        
        return senha;
    }
}

Neste exemplo, temos um método autenticarUsuario que verifica se o login e a senha fornecidas são válidos. O método buscarSenhaNoBanco é usado para simular a busca da senha no banco de dados.

Considerando as métricas de Qualidade de Código, podemos calcular a Cobertura do código como segue:

  • Linha 1: public boolean autenticarUsuario(String login, String senha): Essa linha é importante porque define o método que será testado.
  • Linhas 3 e 4: String senhaBd = buscarSenhaNoBanco(login); e if (senhaBd != null && senhaBd.equals(senha)): Essas linhas são importantes porque definem a lógica da autenticação.
  • Linha 9: return false;: Essa linha é importante porque define o comportamento caso a senha seja inválida.

Portanto, se implementarmos os testes correspondentes às especificações, teremos cobertura para as linhas de código importantes.

Agora, vamos calcular a Complexidade Ciclomática do método autenticarUsuario:

  • Estruturas condicionais: 1 (na linha 4)
  • Loops: 0
  • Número de decisões: 2

Usando a fórmula CC = P + 1, calculamos:

CC = 2 + 1 = 3

Portanto, a Complexidade Ciclomática do método autenticarUsuario é 3.

Essa análise pode ser feita para outros métodos da classe UsuarioController, garantindo que o software seja testado em todas as possibilidades e que a complexidade ciclomática seja minimizada.

Boas práticas e armadilhas comuns

Boas práticas

  • Use testes unitários para cobrir todas as possibilidades de cada método, garantindo que a lógica esteja correta.
  • Implemente métodos pequenos e focados em uma tarefa específica, facilitando o manuseio da complexidade ciclomática.
  • Utilize variáveis com nomes descritivos para melhorar a legibilidade do código.

Armadilhas comuns

  • Testes insuficientes: é fundamental implementar testes que cubram todas as possibilidades de cada método, evitando assim falhas ocultas.
  • Complexidade ciclomática alta: métodos com muitas decisões podem tornar difícil a manutenção do código. Tente dividir esses métodos em menores e mais focados.

Conclusão

Em resumo, as métricas de qualidade de código são ferramentas fundamentais para avaliar a eficácia e manutenibilidade do software. A Cobertura de Código garante que os testes estejam abrangendo todas as linhas críticas do código, enquanto a Complexidade Ciclomática identifica áreas onde o código pode ser otimizado.

Para seguir em frente, é importante implementar testes unitários para cada método e garantir que eles estejam cobrindo todas as possibilidades. Além disso, é recomendável dividir métodos com muitas decisões em menores e mais focados para minimizar a complexidade ciclomática.

Aprofundamento em áreas relacionadas, como Test-Driven Development (TDD) e refatoração de código, pode ajudar a melhorar ainda mais a qualidade do software. Além disso, é importante monitorar as métricas e ajustá-las periodicamente para garantir que o software esteja evoluindo de acordo com os requisitos da empresa.

Referências

  • Fowler, M. (2022). Code Smells. Disponível em: https://www.martinfowler.com/bliki/CodeSmell.html. Acesso: 2024.
  • OWASP (Organização para a Segurança no Desenvolvimento de Aplicativos Web). (2023). Princípios de Design de Software. Disponível em: https://owasp.org/www-pdf-archive/OWASP%20Design%20Principles.pdf. Acesso: 2024.
  • Kent Beck. (2009) “Test Driven Development By Example” pág.12. Capítulo "The Story of the Three Little Pigs"
  • Thoughtworks.com. (2023). A Guide to Code Quality Metrics and Tools. Disponível em: https://www.thoughtworks.com/insights/blog/code-quality-metrics-tools. Acesso: 2024.
  • Martin Fowler. (2018) “Refactoring – Improving the Design of Existing Code” Capítulo "Don’t Repeat Yourself".