Sejamos honestos, a maioria das revisões de código parece uma obrigação. Na melhor das hipóteses, são apenas uma aprovação rápida e sem critério. Na pior, são uma crítica minuciosa e desanimadora sobre o nome das suas variáveis. Mas uma boa revisão de código flutter não é nada disso.
O que analisar em um Code Review de Flutter
Arquitetura e Padrões de Gerenciamento de Estado
- Consistência: O código segue o padrão de arquitetura estabelecido (BLoC, Riverpod, Provider, etc.)? Se houver um desvio, existe um motivo forte e documentado para isso?
- Responsabilidade: Os widgets são usados apenas para exibir a UI? A lógica de negócio está devidamente separada em Blocs, controllers ou notifiers? Os services estão tratando as chamadas de API? Cada parte deve ter uma única responsabilidade clara.
- Propagação de Estado: O estado está sendo passado de forma eficiente? Estamos usando as ferramentas certas (como
Provider.of,ref.watchoucontext.select) para evitar reconstruções (rebuilds) desnecessárias?
Responsividade da UI
- Responsividade: O layout funciona em diferentes tamanhos e orientações de tela? Widgets como
LayoutBuilder,FractionallySizedBoxou layouts flexíveis estão sendo usados corretamente? - Profundidade da Árvore de Widgets: A árvore de widgets está desnecessariamente profunda? Métodos
buildcomplexos podem ser divididos em widgets menores e mais gerenciáveis? - Uso de
const: A palavra-chaveconstestá sendo usada sempre que possível para widgets que não mudam? Este é um dos ganhos de performance mais fáceis no Flutter.
Performance e Uso de Memória
Animações travadas e alto consumo de memória são assassinos silenciosos de uma boa experiência do usuário.
- Operações Assíncronas:
Futures eStreams são gerenciados corretamente? Existem estados de loading e erro para a UI assíncrona? Oawaitestá sendo usado eminitStatesem o devido cuidado? - Operações Custosas: Existem cálculos pesados acontecendo no método
build? Eles devem ser movidos para fora e cacheados. - Vazamentos de Memória (Memory Leaks): Controllers, subscriptions (como
StreamSubscription) e outros recursos são devidamente descartados no métododispose()? Esta é uma fonte clássica de bugs.
Tratamento de Erros e Null Safety
- Graceful Failure: O app quebra se uma chamada de API falhar ou exibe uma mensagem de erro amigável para o usuário? Blocos
try-catchsão usados de forma apropriada? - Null Safety: O código é realmente null-safe ou está cheio de bang operators (
!)? Cada!é um crash em potencial em tempo de execução. Questione cada um deles.
Cobertura e Testabilidade
- Existe um teste? A mudança inclui um teste de unidade, de widget ou de integração correspondente?
- Testes Relevantes: Os testes verificam a lógica de negócio e o comportamento da UI ou apenas que o código não quebra?
- Testabilidade: O código em si é fácil de testar? Se não, geralmente é um sinal de componentes fortemente acoplados que deveriam ser refatorados (ex: usando injeção de dependência).
Estilo de Código, Legibilidade e Documentação
Isso é sobre ser um bom colega. A próxima pessoa que mexer neste código (que pode ser você em seis meses) vai agradecer.
- Clareza: Os nomes de variáveis e métodos são claros e não ambíguos?
- Comentários: Os comentários explicam o *porquê*, não o *o quê*? Um bom código se autoexplica; os comentários devem fornecer o contexto que o código não consegue.
- Consistência: O código segue o guia de estilo estabelecido do projeto (ex: Effective Dart)?
✅ Checklist Prático de Code Review Flutter
Aqui vai um checklist rápido pra code review em Flutter.
Arquitetura e Organização
O PR segue o padrão de arquitetura do time (MVC, MVVM, Clean, BLoC, etc.)
Responsabilidades bem separadas (UI, lógica de negócio, acesso a dados)
Pastas e arquivos organizados de forma consistente com o restante do projeto
Estado e Navegação
Gerenciamento de estado consistente (Provider, BLoC, Riverpod, MobX, etc.)
Não há lógica de negócio pesada dentro de Widgets
Navegação bem estruturada (rotas nomeadas, go_router, auto_route, etc.)
Tratamento de cenários de back/navigation (pop, deep links, etc.)
UI/UX
Uso adequado de Widgets reutilizáveis (components, atoms, molecules)
Layout responsivo (tamanhos relativos, MediaQuery, LayoutBuilder)
Respeita tema global (ThemeData, cores e tipografia centralizadas)
Estados de loading, empty e error bem tratados na UI
Performance
Evita rebuilds desnecessários (const, selectors, separação de widgets)
ListViews/Grids usam builders e, se necessário, ListView.builder / CachedNetworkImage
Não há operações pesadas na main isolate sem necessidade (usar Isolates/compute quando preciso)
Removidos prints, logs excessivos e código morto
Tratamento de Erros
Erros e exceções tratados de forma consistente (try/catch, Either/Result, etc.)
Feedback claro para o usuário em caso de falha
Não há leaks de stacktrace sensível para o usuário final
Integração com Backend
Models e DTOs bem definidos (fromJson/toJson, null safety)
Validação de dados de entrada/saída
Timeouts, erros de rede e estados offline considerados
Segurança
Dados sensíveis não estão hardcoded (tokens, keys, URLs privadas)
Uso correto de armazenamento seguro (flutter_secure_storage, etc. quando necessário)
Logs não expõem informações sensíveis
Testes e Qualidade
Há testes unitários e/ou de widget para a lógica crítica
Todos os testes estão passando
Código segue o dart format e regras de lints do projeto
Comentários e nomes de classes/métodos/variáveis são claros e descritivos