Refatoração de código legado em Kotlin: estratégia e exemplos
Trabalhar com código legado é uma parte inevitável da vida de qualquer desenvolvedor. Muitas vezes, esse código é escrito em Java, mas mesmo projetos em versões antigas do Kotlin podem conter "code smells" e erros arquiteturais. Neste artigo, vamos analisar uma estratégia passo a passo para refatorar código legado em Kotlin, fornecer exemplos concretos de transformações e mostrar como evitar erros típicos.
1. Preparação para a refatoração: segurança em primeiro lugar
A primeira e mais importante etapa é garantir a segurança das alterações. Sem uma boa cobertura de testes, qualquer refatoração se transforma em um jogo de roleta-russa.
- Adicione testes unitários. Se não houver testes, escreva-os para as partes críticas do código. Use os frameworks
JUnit 5eMockKpara Kotlin. - Registre o comportamento. Escreva testes que verifiquem o comportamento atual do sistema (characterization tests), mesmo que pareça incorreto. Isso permitirá não quebrar a lógica durante a refatoração.
- Use um sistema de controle de versão. Faça commits após cada etapa logicamente concluída para que seja possível reverter.
Exemplo de um teste simples para uma função legada em Kotlin:
import org.junit.jupiter.api.Testimport kotlin.test.assertEquals
class LegacyServiceTest { @Test fun `test calculateTotal`() { val service = LegacyService() val result = service.calculateTotal(listOf(10.0, 20.0, 30.0)) assertEquals(60.0, result) }}2. Migração gradual de Java para Kotlin
Se o seu código legado está escrito em Java, não tente reescrever tudo de uma vez. Use conversores automáticos (por exemplo, o integrado no IntelliJ IDEA: Code → Convert Java File to Kotlin File) e, em seguida, melhore o resultado manualmente.
Principais pontos a serem observados após a conversão:
- Null safety. Substitua
@Nullablee@NonNullpelos operadores?e!!(este último, apenas se tiver certeza da ausência de null). - Data classes. Em vez de classes Java com
equals()ehashCode(), usedata class. - Extension functions. Extraia métodos estáticos utilitários para extension functions.
Exemplo de transformação de uma classe Java para Kotlin:
// Javapublic class User { private String name; private int age;
public User(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; } public int getAge() { return age; }}
// Kotlin (após refatoração)data class User(val name: String, val age: Int)3. Melhorando a arquitetura: eliminando o código "spaghetti"
O código legado frequentemente sofre com violações dos princípios SOLID. Aqui estão três técnicas específicas que ajudarão a organizar o código:
3.1. Separação de responsabilidades (Single Responsibility)
Encontre classes que fazem demais. Por exemplo, um "God Object" que armazena dados, valida e envia requisições. Divida-o em várias classes com áreas de responsabilidade claras.
3.2. Substituição de longas cadeias if-else por when
O Kotlin fornece o poderoso operador when, que torna o código mais legível:
// Antes da refatoraçãofun getStatusText(status: Int): String { if (status == 0) return "Pending" else if (status == 1) return "Active" else if (status == 2) return "Blocked" else return "Unknown"}
// Após a refatoraçãofun getStatusText(status: Int): String = when (status) { 0 -> "Pending" 1 -> "Active" 2 -> "Blocked" else -> "Unknown"}