---
id: effective-code-review
domain: engineering
agents: [dev, qa]
when: "ao revisar um pull/merge request ou preparar o próprio CL para review"
---

# Code review eficaz — o padrão do Google

A maioria das discussões de code review trava por falta de um critério compartilhado. Sem ele, o
review vira gosto pessoal: o revisor segura o CL até ele ficar "do jeito dele", o autor responde na
defensiva, e o que era pra melhorar o código vira queda de braço. Este pack destila o padrão do Google
(`google/eng-practices`: *How to do a code review* + *The CL author guide*), porque ele resolve isso com
**um único critério-mestre** do qual todo o resto deriva.

> A fonte chama o pull request de **CL** (changelist). Aqui usamos "CL" e "PR/MR" como sinônimos.

## O problema / os tells

Você está num review medíocre quando vê:

1. **Review como busca pela perfeição.** O revisor segura o CL porque "dá pra ficar melhor" — sem que o
   estado atual piore o código. A fonte é direta: *"there is no such thing as 'perfect' code—there is
   only better code."* Perfeição não é o critério; melhoria do code health é.
2. **CLs gigantes.** Um PR de 800 linhas espalhado por 40 arquivos. Ninguém revisa de verdade: *"important
   points get missed or dropped."*
3. **Feedback sem severidade.** Tudo no mesmo tom. O autor não sabe o que é bloqueante e o que é gosto, e
   trata um typo de comentário com o mesmo peso de um bug de concorrência.
4. **Feedback como ordem, nunca como ensino.** O revisor manda "faça X" sem dizer por quê. O autor obedece
   sem aprender; o próximo CL repete o erro.
5. **Descrição de CL inútil.** Título "Fix bug", "Phase 1", "Add patch". Daqui a um ano, o `git log` não
   diz nada a ninguém.
6. **Review parado por dias.** O CL fica encalhado porque autor e revisor não chegam a acordo, ou porque
   o revisor "depois olha". A velocidade do time inteiro cai.
7. **Autor na defensiva.** Resposta no calor, tratando crítica ao código como ataque pessoal — *"never
   respond in anger to code review comments."*

## Os princípios

### 1. O critério-mestre: aprove quando o CL melhora a saúde do código

O propósito do review não é provar que o código é perfeito, é garantir que *"the overall code health of
the codebase is improving over time."* Daí a regra de aprovação:

> *"In general, reviewers should favor approving a CL once it is in a state where it definitely improves
> the overall code health of the system being worked on, even if the CL isn't perfect."*

Isso não é desculpa pra deixar passar lixo — a contrapartida é igualmente firme: *"Don't accept CLs that
degrade the code health of the system."* O CL não precisa ser perfeito; precisa ser **melhor**, e não pode
piorar. Quando ele claramente melhora e só restam refinamentos opcionais, aprove com comentários (o
"LGTM with comments"): você libera o autor e confia que ele endereça os nits.

```text
# ❌ revisor segurando por perfeição
"Funciona e está mais limpo que o anterior, mas não vou aprovar até você
 extrair essas 3 funções, renomear o módulo e adicionar 4 testes a mais."

# ✅ aprovar a melhoria, marcar o resto como opcional
"LGTM. Melhora clara sobre o que existia. Nit: dá pra extrair `parseHeader`
 numa função à parte depois — opcional, não bloqueia o merge."
```

### 2. O que o revisor procura (nesta ordem de importância)

A fonte lista explicitamente o que olhar — **design vem primeiro**, não estilo:

- **Design.** A interação das peças faz sentido? A mudança pertence a este codebase ou a uma lib? É o
  ponto mais importante do review.
- **Funcionalidade.** *"Does this CL do what the developer intended?"* Pensa em edge cases, concorrência,
  bugs. Mudança de UI muitas vezes pede um demo pra entender o impacto real no usuário.
- **Complexidade.** Está *"more complex than it should be"*? O teste prático: se *"can't be understood
  quickly by code readers"*, é complexo demais. Cuidado com over-engineering — resolva o problema que
  você sabe que precisa ser resolvido **agora**, não o especulado.
- **Testes.** Há testes unit/integration/e2e adequados? Eles **falham quando o código quebra** e fazem
  asserções úteis, sem complexidade desnecessária.
- **Nomes.** *"long enough to fully communicate what the item is or does, without being so long that it
  becomes hard to read."*
- **Comentários.** Bons comentários *"explain why"* o código existe — a razão que o código não mostra
  sozinho —, não parafraseiam o que ele faz.
- **Estilo / consistência.** Style guide é autoridade. Divergência de gosto pessoal vira `Nit:`, não
  bloqueio.
- **Documentação.** README, docs e referências acompanham a mudança quando relevante.
- **Cada linha.** Revise todo o código designado — entender cada peça importa pro próximo dev.
- **Contexto.** Olhe o impacto sistêmico, não só o diff. E **elogie o que está bom**: reconheça boas
  soluções, não só aponte problemas.

### 3. CLs pequenos: o multiplicador de qualidade

Tamanho não é detalhe — é o fator que mais muda a qualidade do review. A régua da fonte:

> *"100 lines is usually a reasonable size for a CL, and 1000 lines is usually too large."*

E o tamanho é sobre **mudança lógica autocontida**, não só contagem bruta: *"A 200-line change in one file
might be okay, but spread across 50 files it would usually be too large."* O CL certo faz **uma coisa**.
Na dúvida, *"write CLs that are smaller than you think you need to write."*

Por que pequeno ganha: é revisado mais rápido (cinco minutos várias vezes), revisado a fundo (em CL
grande *"important points get missed or dropped"*), introduz menos bugs, desperdiça menos trabalho se a
direção estiver errada, dá menos conflito de merge, é mais fácil de desenhar bem e de reverter.

```text
# ❌ um CL: "Add user profiles"
  migration + model + 3 endpoints + UI + refactor do auth + rename de 12 arquivos
  → 900 linhas, 40 arquivos, ninguém revisa de verdade

# ✅ sequência de CLs autocontidos
  CL1: migration + model              (~80 linhas)
  CL2: endpoints de leitura + testes  (~120 linhas)
  CL3: UI de profile                  (~150 linhas)
  → cada um revisável em minutos, mergeável e reversível sozinho
```

### 4. Dar feedback: severidade explícita, ensinar não impor

**Marque a severidade.** O autor precisa distinguir bloqueante de sugestão. Prefixos da fonte:

- `Nit:` — *"a minor thing. Technically you should do it, but it won't hugely impact things."*
- `Optional (ou Consider):` — *"I think this may be a good idea, but it's not strictly required."*
- `FYI:` — *"I don't expect you to do this in this CL, but you may find this interesting."*

**Ensine, não mande.** *"Pointing out problems and letting the developer make a decision often helps the
developer learn."* Explique o **porquê**. E quando o código está complexo demais, *"encourage developers
to simplify code or add code comments instead of just explaining the complexity to you"* — o ganho fica
no código, não na conversa do review. Sempre: *"courteous and respectful while also being very clear and
helpful."*

```text
# ❌ ordem sem razão, severidade ambígua
"Use um map aqui."

# ✅ aponta o problema, ensina, marca severidade
"Este loop aninhado é O(n²); com a lista de pedidos crescendo isso vira gargalo.
 Um map de id→pedido resolve em O(n). Required."

# nit de verdade, marcado como tal:
"Nit: `d` poderia ser `daysUntilDue` pra ficar autoexplicativo. Opcional."
```

### 5. O guia do AUTOR

- **Descrição do CL.** Primeira linha = resumo curto, no **imperativo** ("Delete the FizzBuzz RPC and
  replace it with the new system"), dizendo **o que** muda. Corpo = **o quê e por quê**, com números de
  bug, benchmarks e links de design. Ruins (da fonte): "Fix bug", "Fix build", "Add patch", "Phase 1",
  "kill weird URLs" — *"do not provide enough useful information."* Bom: *"RPC: Remove size limit on RPC
  server message freelist. Servers like FizzBuzz have very large messages and would benefit from reuse."*
- **Responder a reviews.** *"Don't take it personally"* — a crítica é ao código, não a você. Nunca
  responda com raiva. Se o revisor não entendeu, **conserte o código** primeiro; se não dá pra clarear,
  adicione um comentário no código explicando o porquê; explicar só no review tool é último recurso (o
  próximo leitor não vê a thread do PR).
- **Discordar bem.** Pense em colaboração, não defesa: *"I went with X because of [these pros/cons]... Are
  you suggesting that Y better serves the original tradeoffs?"*

### 6. Resolver conflitos e velocidade

Conflito entre autor e revisor se resolve por **fatos, não preferências**: *"Technical facts and data
overrule opinions and personal preferences."* Style guide é autoridade no estilo. Busquem consenso; se
não houver, apliquem os princípios deste padrão e, persistindo, escalem pra liderança técnica. Acima de
tudo: *"Don't let a CL sit around because the author and the reviewer can't come to an agreement."*

**Velocidade:** o que importa é o **tempo de resposta**, não o tempo total do CL. A régua: *"One business
day is the maximum time it should take to respond to a code review request."* Se você não está no meio de
uma tarefa focada, revise logo que o CL chega; se está codando concentrado, *"don't interrupt yourself"*
— responda num ponto natural de pausa. Review lento derruba a velocidade do time inteiro.

## Checklist

Antes de **aprovar** um CL:

- [ ] O CL **melhora** a saúde do código e **não a piora**? (critério-mestre — não exija perfeição)
- [ ] O **design** faz sentido e a mudança pertence a este codebase?
- [ ] Faz o que o autor pretendeu, incluindo edge cases e concorrência?
- [ ] Não está mais complexo que o necessário, sem over-engineering pra o futuro?
- [ ] Tem testes que **falham quando o código quebra**, com asserções úteis?
- [ ] Nomes claros, comentários que explicam o **porquê**, docs atualizadas?
- [ ] Revisei **cada linha** designada e elogiei o que está bom?
- [ ] Marquei a **severidade** (`Nit:`/`Optional:`/`FYI:`) e expliquei o **porquê** de cada comentário?
- [ ] Respondi em até **um dia útil**?

Antes de **enviar** o próprio CL:

- [ ] É **uma mudança autocontida** (~100 linhas; 1000 é grande demais; cuidado com o espalhamento)?
- [ ] A descrição tem primeira linha no imperativo + corpo com **o quê e por quê** (não "Fix bug")?
- [ ] Vou responder ao review sobre o **código**, sem levar pro pessoal?

## Tabela de decisão

| Situação | O que fazer |
|---|---|
| CL melhora o código mas não está perfeito | **Aprove** (LGTM with comments); marque refinamentos como `Nit:`/`Optional:` |
| CL piora a saúde do código | **Não aprove**; aponte o problema com o porquê |
| Comentário é gosto pessoal / estilo | `Nit:`; não bloqueie o merge por isso |
| Comentário é design/funcionalidade/segurança | Required; bloqueie e explique o porquê |
| CL > ~1000 linhas ou espalhado por dezenas de arquivos | Peça pra **quebrar** em CLs autocontidos |
| Código complexo demais de entender | Peça **simplificar ou comentar no código** — não aceite explicação só no PR |
| Quer que o dev aprenda | Aponte o **problema** e deixe ele decidir, em vez de dar a ordem pronta |
| Autor e revisor não chegam a acordo | Decida por **fatos/dados** e pelo style guide; persistindo, **escale** — não deixe o CL parado |
| Chegou um review e você não está focado em outra coisa | Revise **logo** (alvo: resposta em ≤ 1 dia útil) |
| Chegou um review e você está codando concentrado | Não se interrompa; responda numa **pausa natural** |
| Revisor não entendeu seu código | **Conserte o código** ou comente nele o porquê; explicar só no PR é último recurso |

---

**Fonte:** Google Engineering Practices — `google.github.io/eng-practices`
(*How to do a code review* e *The CL author guide*).
