Pular para conteúdo

Aula 19 - Análise de Métricas de Software e Qualidade 📈

Objetivo Pedagógico

Objetivo: Implementar medições objetivas da qualidade do código e da eficácia organizacional: complexidade ciclomática de McCabe, débito técnico, cobertura de código e as quatro métricas DORA (DevOps Research and Assessment).


📑 1. Fundamentos Teóricos & Análise Técnica

O que não pode ser medido não pode ser gerenciado de forma científica. A avaliação de engenharia de software contemporânea divide-se em métricas de código-fonte estrutural e métricas de desempenho organizacional: 1. Métricas Estruturais de Código: - Complexidade Ciclomática de McCabe (\(M\)): Quantifica o número de caminhos de execução linearmente independentes no grafo de fluxo de controle de um método: $\(M = E - N + 2P\)$ Onde \(E\) é o número de arestas, \(N\) o número de nós e \(P\) os componentes conexos. Funções com \(M > 10\) apresentam probabilidade exponencialmente maior de conter defeitos e exigem refatoração urgente. - Débito Técnico (Technical Debt Ratio - TDR): Razão entre o custo estimado para corrigir todos os problemas de qualidade de um sistema versus o custo total de desenvolvê-lo do zero. 2. As Quatro Métricas DORA (DevOps Research and Assessment): - Deployment Frequency: Frequência com que o código é publicado em produção (equipes de elite realizam múltiplos deploys diários). - Lead Time for Changes: Tempo decorrido desde o commit até o deploy funcional em produção. - Change Failure Rate: Percentual de deploys que resultam em incidentes ou degradações de serviço exigindo rollback ou hotfix. - Time to Restore Service (MTTR): Tempo médio necessário para restaurar a integridade do sistema após um incidente em produção.

📐 Arquitetura Conceitual & Diagrama de Fluxo

graph TD
    Source["Repositório de Código & PRs"] --> Sonar["Análise Estática SonarQube"]
    Sonar --> Cyclo["Complexidade Ciclomática (M < 10)"]
    Sonar --> Debt["Índice de Débito Técnico (TDR < 5%)"]
    Prod["Eventos de Deploy & Incidentes"] --> DORAEngine["Motor de Métricas DORA"]
    DORAEngine --> D1["Deployment Frequency (Múltiplas/Dia)"]
    DORAEngine --> D2["Lead Time (< 1 Hora)"]
    DORAEngine --> D3["Change Failure Rate (< 5%)"]
    DORAEngine --> D4["Time to Restore (< 1 Hora)"]
    style Source fill:#e1f5fe,stroke:#01579b
    style Sonar fill:#fff3e0,stroke:#e65100
    style Prod fill:#f3e5f5,stroke:#7b1fa2
    style DORAEngine fill:#e8f5e9,stroke:#2e7d32

🔍 Pilares e Diretrizes Técnicas

Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Refatoração Guiada por Complexidade: Decomposição de métodos monolíticos com excesso de bifurcações condicionais (if/else, laços) em funções menores. - Quality Gates Automatizados: Bloqueio formal de merges caso novos débitos técnicos ultrapassem 3% no código novo. - Métricas DORA de Alto Desempenho: Foco em velocidade com segurança: deploys rápidos e pequenos reduzem o impacto de incidentes. - Manutenibilidade de Longo Prazo: Preservação da legibilidade e acoplamento frouxo do código para facilitar a evolução contínua da equipe.


🛠️ 2. Implementação Prática em Métricas DORA, Complexidade Ciclomática e SonarQube

Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:

// complexity_and_dora_tracker.py (Cálculo de Complexidade AST e Métricas DORA)
import ast

class CyclomaticComplexityVisitor(ast.NodeVisitor):
    """Calcula a Complexidade Ciclomática de McCabe analisando a AST Python."""
    def __init__(self):
        self.complexity = 1  # Caminho base inicial

    def visit_If(self, node):
        self.complexity += 1
        self.generic_visit(node)

    def visit_For(self, node):
        self.complexity += 1
        self.generic_visit(node)

    def visit_While(self, node):
        self.complexity += 1
        self.generic_visit(node)

    def visit_ExceptHandler(self, node):
        self.complexity += 1
        self.generic_visit(node)

def analyze_function_complexity(source_code: str):
    tree = ast.parse(source_code)
    visitor = CyclomaticComplexityVisitor()
    visitor.visit(tree)
    print(f"Complexidade Ciclomática da Função: {visitor.complexity}")
    if visitor.complexity > 10:
        print("[ALERTA] Função altamente complexa! Recomenda-se refatoração imediata.")
    else:
        print("[OK] Complexidade dentro dos padrões saudáveis de engenharia.")

if __name__ == '__main__':
    sample_code = """
def processar_pedido(pedido):
    if not pedido.ativo:
        return False
    for item in pedido.itens:
        if item.preco > 100:
            if item.estoque == 0:
                return False
    return True
"""
    analyze_function_complexity(sample_code)

💡 Análise Passo a Passo do Código

  1. Inspeção de AST Nativa: Percorre a árvore de sintaxe abstrata contando bifurcações lógicas de forma exata e independente de formatação.
  2. Detecção Precoce de Débito Técnico: Alerta quando uma função atinge limites arriscados que dificultam a criação de testes unitários abrangentes.
  3. Automatização em Pipelines: Pode ser acoplado em verificações de CI para impedir a introdução de novas funções de alta complexidade.

🎯 3. Próximos Passos & Sequência Didática