Code review em Swift: o que verificar e como dar feedback
Code review não é apenas um procedimento formal, mas uma ferramenta poderosa para melhorar a qualidade do código e o crescimento profissional da equipe. Para desenvolvedores iOS/macOS em Swift, uma revisão bem feita ajuda a evitar bugs, melhorar a arquitetura e manter um estilo de código consistente. Neste artigo, vamos abordar o que observar durante o code review de projetos Swift e como dar feedback que seja útil, não desmotivador.
1. Arquitetura e Separação de Responsabilidades
A primeira coisa a avaliar em uma revisão é o quão bem o código segue a arquitetura escolhida (MVC, MVVM, VIPER, SwiftUI + Combine). Uma arquitetura ruim leva a "God objects" e dificulta a manutenção.
O que verificar:
- A ViewController não está misturando lógica de negócios com código de UI?
- A lógica de rede está separada em serviços específicos (NetworkService)?
- Protocolos estão sendo usados para abstrair dependências?
- Uma única classe não tem responsabilidades demais?
// ❌ Ruim: ViewController sabe sobre URLSession e parsing de JSONclass UserViewController: UIViewController { func fetchUser() { URLSession.shared.dataTask(with: URL(string: "https://api.example.com/user")!) { data, _, _ in let user = try? JSONDecoder().decode(User.self, from: data!) DispatchQueue.main.async { self.updateUI(with: user) } }.resume() }}
// ✅ Bom: lógica extraída para um serviçoprotocol UserServiceProtocol { func fetchUser(completion: @escaping (Result<User, Error>) -> Void)}
class UserViewModel { private let userService: UserServiceProtocol init(userService: UserServiceProtocol) { self.userService = userService } func loadUser() { userService.fetchUser { [weak self] result in // processa o resultado } }}Dica de feedback: Em vez de "Esta classe é muito grande", escreva: "Percebi que o UserViewController é responsável tanto pelas requisições de rede quanto pela UI. Que tal extrair a requisição para um serviço separado, como discutimos na retrospectiva? Isso facilitaria os testes".
2. Segurança de Memória e Gerenciamento do Ciclo de Vida
Swift é uma linguagem com Contagem Automática de Referências (ARC), mas isso não exime o desenvolvedor de se preocupar com ciclos de referência forte. Erros nessa área são uma causa comum de vazamentos de memória em aplicativos iOS.
O que verificar:
[weak self]ou[unowned self]estão sendo usados em closures, especialmente com async/await e Combine?- Não está sendo criado um ciclo de referência entre o delegate e o proprietário?
- Os recursos (observadores, timers) estão sendo liberados corretamente?
// ❌ Potencial vazamento: referência forte a self no closureclass LocationManager { var onLocationUpdate: ((CLLocation) -> Void)? func startUpdating() { someAsyncAPI { location in self.onLocationUpdate?(location) // self capturado fortemente } }}
// ✅ Corrigido com [weak self]class LocationManager { var onLocationUpdate: ((CLLocation) -> Void)? func startUpdating() { someAsyncAPI { [weak self] location in guard let self = self else { return } self.onLocationUpdate?(location) } }}Dica de feedback: Aponte não apenas o problema, mas também as consequências: "Aqui pode ocorrer um vazamento de memória se o LocationManager viver mais do que o necessário. Vamos adicionar [weak self] para quebrar o ciclo".
3. Tratamento de Erros e Opcionais
Swift é uma linguagem fortemente tipada com um poderoso sistema de Optional. O tratamento inadequado de valores opcionais é uma das pri