Revisão de código em Swift: como parar de irritar colegas e escrever código de nível sênior
Você já enviou um Pull Request e, uma hora depois, recebeu 15 comentários do líder técnico? "Force unwrap? Sério?", "E onde está o tratamento de erros?", "Este flow controller está na memória há três dias". Familiar? Bem-vindo ao mundo da revisão de código em Swift — um lugar onde até desenvolvedores experientes às vezes se sentem como estagiários.
Neste artigo, reuni os comentários mais frequentes que os seniores deixam nas revisões de código. Analisaremos exemplos reais de código, antipadrões e como corrigi-los. Isso não é teoria chata — é a experiência prática de centenas de revisões que o ajudará a escrever código que não desperte o desejo de reescrever tudo do zero. Vamos lá!
1. Force Unwrap — primeiro amor e maior dor
Vamos começar com o mais banal, mas eterno. Force unwrap (!) é como dirigir sem cinto de segurança. Parece conveniente, mas uma freada brusca e você vai parar no hospital.
Código ruim (típico de júnior):
func getUserName() -> String { let name: String? = UserDefaults.standard.string(forKey: "user_name") return name!}O que o sênior dirá: "E se não houver nada no UserDefaults? Crash. Sempre. Adicione guard let ou defaultValue."
Código bom:
func getUserName() -> String { guard let name = UserDefaults.standard.string(forKey: "user_name") else { return "Convidado" } return name}Exceção: Force unwrap só é permitido em um caso — quando você tem 146% de certeza de que o valor existe. Por exemplo, ao trabalhar com IBOutlets, que certamente serão inicializados. Mas mesmo aqui, o sênior recomendará usar private var label: UILabel! — isso é uma convenção, não uma gambiarra.
2. Números mágicos e strings: o código não deve ser um enigma
A segunda coisa que chama a atenção na revisão de código em Swift são as constantes mágicas. "Por que exatamente 0.75? Ah, é o coeficiente de animação... Qual exatamente?". Se você escreve números e strings diretamente no código, está fazendo seus colegas jogarem de detetive.
Código ruim:
if user.age > 18 { showAdultContent()}button.layer.cornerRadius = 12let url = "https://api.example.com/v1/users"O que o sênior dirá: "18 é um número mágico. Coloque em uma constante. URL — em um enum. cornerRadius — em uma constante estilística. O código deve ser lido como um livro, não como uma cifra."
Código bom:
private enum Constants { static let adultAgeLimit = 18 static let defaultCornerRadius: CGFloat = 12 static let baseURL = "https://api.example.com/v1"}
enum APIEndpoint { case users var url: String { switch self { case .users: return Constants.baseURL + "/users" } }}
if user.age > Constants.adultAgeLimit { showAdultContent()}3. Memory Leaks: como travar o aplicativo acidentalmente
A revisão de código em Swift raramente passa sem discutir retain cycles. Os seniores adoram esse tópico porque mostra se você entende como o ARC funciona. O antipadrão mais popular é capturar self em uma closure sem referência fraca.
Código ruim:
class NetworkManager { func fetchData(completion: @escaping (Data) -> Void) { URLSession.shared.dataTask(with: url) { data, _, _ in self.process(data) // self capturado fortemente completion(data) } }}O que o sênior dirá: "Você está mantendo uma referência forte a self dentro da closure. Enquanto a closure estiver viva, o objeto não será liberado. Adicione [weak self] e verifique se é nil. Ou use [unowned self] se tiver certeza de que self sobreviverá à closure."
Código bom:
func fetchDa