Por que code review não é sobre criticar, mas sobre qualidade
\nImagine: você abre um pull request de um colega. São 500 linhas de código, cheira a copia-cola, e em um lugar alguém esqueceu de fechar um recurso. Sua tarefa não é apenas encontrar bugs, mas melhorar o código. Code review em Java não é uma supervisão policial, mas uma criação colaborativa. Um bom revisor salva a equipe da dívida técnica; um ruim desmotiva ou deixa passar vulnerabilidades.
\nNeste artigo, explicarei o que verificar em code review em Java para não perder tempo com detalhes, mas não perder o crítico. Você receberá um checklist pronto e exemplos da prática.
\n\nArquitetura e design: olhando para a raiz
\nAntes de mergulhar nos detalhes, avalie o panorama geral. Uma arquitetura ruim não se cura com formatação.
\nViolação do SOLID
\nVerifique se a classe não se tornou um "objeto divino". Exemplo de violação do Single Responsibility:
\npublic class OrderService {\n public void createOrder(Order order) {\n // validação\n // cálculo de desconto\n // envio de email\n // registro de log\n // salvamento no BD\n }\n}\n\nAqui há cinco motivos para mudança. O correto é extrair o registro de log e o envio para serviços separados.
\nComplexidade excessiva
\nÀs vezes o código resolve um problema simples de forma complexa. Pergunte a si mesmo: "Pode ser mais simples?" Se sim, escreva na revisão. Lembre-se do princípio KISS.
\n\nSegurança: brechas que não podem ser ignoradas
\nRevisão de código Java deve incluir verificação de segurança. Mesmo que o projeto seja interno.
\nInjeção de SQL
\nConcatenação de strings é um mal:
\n// RUIM\nString query = "SELECT * FROM users WHERE name = '" + userName + "'";\nStatement stmt = connection.createStatement();\nResultSet rs = stmt.executeQuery(query);\n\nO correto é usar PreparedStatement:
// BOM\nString query = "SELECT * FROM users WHERE name = ?";\nPreparedStatement pstmt = connection.prepareStatement(query);\npstmt.setString(1, userName);\nResultSet rs = pstmt.executeQuery();\n\nVazamento de dados sensíveis
\nVerifique se senhas, tokens ou números de cartão não estão sendo registrados em log. Use @ToString.Exclude no Lombok ou uma exclusão explícita.
Comparação insegura de objetos
\n// RUIM (comparação de referências)\nif (password == storedPassword) { ... }\n// BOM\nif (password.equals(storedPassword)) { ... }\n\n\nDesempenho: gargalos
\nNão otimize prematuramente, mas também não ignore lentidões óbvias.
\nOperações desnecessárias em loops
\n// RUIM: length() é chamado toda vez\nfor (int i = 0; i < list.size(); i++) { ... }\n// BOM\nint size = list.size();\nfor (int i = 0; i < size; i++) { ... }\n\nUso de Stream para tarefas simples
\nÀs vezes um loop comum é mais legível e rápido:
\n// Excessivo\nlist.stream().filter(x -> x > 5).collect(Collectors.toList());\n// Simples\nList<Integer> result = new ArrayList<>();\nfor (int x : list) {\n if (x > 5) result.add(x);\n}\n\nVazamento de memória
\nVerifique se não esqueceram de fechar InputStream, Connection ou Session. Use try-with-resources:
try (Connection conn = getConnection();\n PreparedStatement stmt = conn.prepareStatement(sql)) {\n // trabalho\n} catch (SQLException e) {\n log.error("Erro no BD", e);\n}\n\n\nLegibilidade e estilo: código como um livro
\nCode review checklist inclui obrigatoriamente a legibilidade. O código é escrito uma vez, lido dezenas de vezes.
\nNúmeros e strings mágicos
\n// RUIM\nif (status == 3) { ... }\n// BOM\nprivate static final int STATUS_COMPLETED = 3;\nif (status == STATUS_COMPLETED) { ... }\n\n