Dois Revisores, Um Diff, Zero Sobreposição

Dois engenheiros sênior revisam o mesmo pull request. Um sinaliza um null check faltante. O outro detecta uma race condition no cleanup path. Nenhum dos dois encontra ambos.

Se você tivesse designado apenas um revisor, um desses bugs teria sido enviado. Isso não é uma lacuna de habilidade. É uma propriedade previsível da atenção humana, e Michael Fagan a documentou na IBM em 1976.

Fagan estava medindo as taxas de detecção de defeitos no pipeline de software da IBM. Seus dados mostraram algo desconfortável: mesmo inspetores experientes detectavam apenas uma fração dos defeitos totais que o grupo eventualmente encontrava. O valor real não estava na experiência de nenhuma pessoa individual. Estava na combinação estruturada de múltiplas perspectivas.

A maioria das equipes hoje não estrutura essa combinação. Um engenheiro sênior folheia um diff entre reuniões, nota um issue de estilo, aprova e segue em frente. O próximo revisor faz o mesmo. Ambos deixam passar o erro off-by-one que corrompe os dados de produção na próxima terça-feira.

Fagan chamou isso de síndrome de revisão não estruturada. O grupo tem olhos, mas não tem processo.

O Que Realmente É uma Fagan Inspection

Uma Fagan Inspection não é uma reunião onde as pessoas leem código juntas e compartilham sentimentos. É um processo formal com papéis definidos, critérios de entrada e output mensurável. Fagan a projetou porque revisões não estruturadas desperdiçavam tempo e deixavam defeitos vazarem aproximadamente na mesma taxa que nenhuma revisão.

A ideia central é a separação de papéis. Cada um tem exatamente um trabalho:

  • O moderator conduz a reunião e impõe as regras. Ele não inspeciona.
  • O reader parafraseia o código em voz alta. Isso força o grupo a confrontar o que o código realmente faz, não o que o author pretendia.
  • O tester pensa em execution paths, boundary conditions e coverage gaps.
  • O author responde perguntas mas não defende o código.

Essa separação previne o failure mode mais comum da revisão em grupo: o author convencendo todos a ignorar suas preocupações.

Quando o author também é o explicador, ele suaviza a ambiguidade. “Ah, essa variável é sempre definida pelo caller.” O grupo concorda. Ninguém verifica. O papel de reader existe para quebrar esse hábito. Se o reader não conseguir parafrasear uma função em uma frase, a função não está pronta para ser enviada.

Por Que Checklists Vencem a Intuição

Fagan também introduziu inspection checklists. Elas não são coding standards genéricos copiados de um style guide. São adaptadas ao tipo específico de artefato sendo revisado.

Uma checklist para uma state machine pergunta: você tratou cada transição? Uma checklist para um resource allocator pergunta: cada allocation está pareada com uma deallocation em cada path?

A checklist existe porque a atenção humana é irregular. Um especialista que escreveu dez mil queries de banco de dados vai mentalmente pular o bloco BEGIN TRANSACTION. Seu cérebro o autocompleta como correto. Fagan descobriu que inspetores guiados por checklists encontravam defeitos que revisores guiados por intuição deixavam passar, não porque os especialistas fossem descuidados, mas porque a expertise cria blind spots.

Aqui está uma checklist lightweight para uma única função Python:

CHECKLIST = [
    "Can a non-author paraphrase what this function does in one sentence?",
    "Does every execution path return or raise predictably?",
    "What happens at the minimum and maximum valid inputs?",
    "What happens at exactly one step past the boundary?",
    "Does the function mutate any argument, closure, or global state?",
    "Is every resource acquired also released on the error path?",
    "If this raises, can the caller distinguish recoverable from fatal?",
]

Isso não é burocracia. É uma forcing function para atenção sistemática.

Fagan Dividiu as Inspeções em Quatro Fases, e a Reunião É a Mais Curta

Uma Fagan Inspection real tem quatro fases, e a reunião em si é a mais curta.

Preparation. Cada inspetor revisa o material sozinho, com a checklist, antes do grupo se reunir. Fagan descobriu que inspetores preparados encontravam aproximadamente o dobro de defeitos comparado aos que chegavam a frio. A reunião existe apenas para combinar findings, não para gerá-los.

A reunião. O reader percorre o código. O tester faz perguntas do tipo e se. O moderator mantém a duração abaixo de duas horas. O author toma notas. Ninguém corrige código durante a reunião. Os defeitos são registrados e o grupo segue em frente.

Rework. O author corrige os defeitos registrados sozinho.

Follow-up. O moderator verifica se cada defeito foi abordado. Reworks grandes podem desencadear uma segunda inspeção.

Essa estrutura parece pesada para um pull request moderno. Fagan a projetou para software de mainframe onde um único defeito poderia custar milhões. Os princípios ainda se adaptam a contextos menores.

Onde Isso Se Torna Excessivo

Fagan Inspections não são gratuitas. O tempo de preparation sozinho adiciona uma sobrecarga significativa. Para um bugfix de dez linhas, uma Fagan Inspection completa é absurda. Você não precisa de quatro pessoas e uma checklist para detectar um import faltante.

A curva de payoff é não linear. Os dados de Fagan sugeriram que as inspeções valiam mais a pena para modules complexos e de alto risco: state machines, parsers, resource managers, qualquer coisa com non-local state ou ordering constraints sutis. Para handlers CRUD e tests boilerplate, revisão informal está bem.

O erro real é aplicar a mesma estratégia de revisão para cada mudança. Um erro de digitação em uma mensagem de log não precisa de uma Fagan Inspection. Um distributed transaction coordinator provavelmente precisa.

Uma Versão Lightweight Que Você Pode Usar Hoje

Você não precisa da cultura de reuniões da IBM para obter a maior parte do benefício. Aqui está uma adaptação lightweight que funciona para equipes modernas:

  1. Exigir revisão individual antes da discussão em grupo. Cada revisor envia comentários escritos antes de qualquer pessoa falar. Isso impede que a primeira opinião forte domine.

  2. Rotacionar o papel de reader. Peça a um revisor para resumir a mudança com suas próprias palavras antes de qualquer pessoa criticá-la. Se ele não conseguir, a mudança é grande demais ou confusa demais.

  3. Construir uma checklist da equipe. Comece com as sete perguntas acima. Adicione itens específicos do domínio. Revise-a trimestralmente.

  4. Separar author e defensor. O author responde perguntas factuais. Ele não argumenta que o código está bem. Se um revisor está confuso, isso é um dado, não um debate.

  5. Registrar defeitos, corrigi-los depois. Não reescreva código durante a revisão. Registre o issue, termine, depois corrija.

Aqui está um script simples para gerar uma review checklist para qualquer module Python:

import ast
import sys
from pathlib import Path

def generate_checklist(source_path: str) -> list[str]:
    """Generate a Fagan-style checklist from a Python module."""
    source = Path(source_path).read_text()
    tree = ast.parse(source)

    checklist = [
        f"Module {Path(source_path).name}: {len(tree.body)} top-level statements",
        "Can a non-author state the module's responsibility in one sentence?",
    ]

    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            checklist.append(
                f"Function '{node.name}': does every path return or raise?"
            )
            if any(isinstance(n, ast.Try) for n in ast.walk(node)):
                checklist.append(
                    f"Function '{node.name}': is every exception handled explicitly?"
                )

    return checklist

if __name__ == "__main__":
    for item in generate_checklist(sys.argv[1]):
        print(f"[ ] {item}")

Execute assim:

python inspection_checklist.py src/transaction.py

Ele não vai encontrar seus bugs. Ele o força a olhar nos lugares certos.

Contratar Pessoas Mais Inteligentes Não Vai Corrigir um Problema de Processo

A pesquisa de Fagan tem quase cinquenta anos, mas a conclusão não mudou. Revisores individuais são inconsistentes. Grupos também são inconsistentes, a menos que você os estruture. A variância entre revisores não é um problema a ser eliminado. É um recurso a ser organizado.

Da próxima vez que um revisor encontrar um bug que outro deixou passar, não pergunte quem é melhor. Pergunte se seu processo é estruturado o suficiente para combinar o que ambos veem. Fagan já tentou contratar seu caminho para fora disso. Não funciona.

FAQ

O que é uma Fagan Inspection?

Uma Fagan Inspection é um processo formal e estruturado de code review desenvolvido por Michael Fagan na IBM em 1976. Ela usa papéis definidos (moderator, reader, tester, author), requisitos de preparation e checklists para maximizar a detecção de defeitos em artefatos de software.

Por que revisores diferentes encontram bugs diferentes?

A atenção humana é seletiva. Especialistas desenvolvem atalhos mentais que permitem ler código rapidamente, mas esses mesmos atalhos criam blind spots. Revisores diferentes têm backgrounds e padrões cognitivos diferentes, então seus blind spots não se sobrepõem perfeitamente. A pesquisa de Fagan mostrou que o valor da inspeção vem da combinação de múltiplas perspectivas incompletas, não de encontrar um revisor perfeito.

As Fagan Inspections ainda são usadas hoje?

O processo formal completo é raro fora de indústrias críticas para segurança como aeroespacial e dispositivos médicos. No entanto, os princípios subjacentes — preparation individual, separação de papéis e revisão guiada por checklists — são cada vez mais adaptados por equipes de software high-performing. As ideias centrais também influenciaram práticas modernas como structured walkthroughs e formal technical reviews.

Quando o overhead de uma Fagan Inspection completa vale a pena?

Para modules onde um defeito tem consequências graves: lógica de distributed consensus, security boundaries, resource lifecycles e state machines. Para mudanças de rotina, adaptações lightweight geralmente são suficientes. Combine o rigor da revisão com o risco real, não o mesmo processo para cada diff.