Kotlin
A concise multiplatform language developed by JetBrains
Escalando a adoção do Kotlin em toda a sua empresa
Postagem convidada de Urs Peter, Engenheiro de Software Sênior e Instrutor de Kotlin certificado pela JetBrains. Para leitores que preferirem uma maneira mais estruturada de adquirir conhecimentos sobre Kotlin, Urs também dirige o Programa de Qualificação em Kotlin da Xebia Academy.
Esta é a quinta postagem da série O guia definitivo para a adoção bem-sucedida do Kotlin em um ambiente dominado pelo Java, que acompanha o processo de adoção do Kotlin por equipes reais, desde a curiosidade de um só desenvolvedor até uma transformação geral da empresa.
Todas as partes da série:
- Como iniciar a adoção do Kotlin por desenvolvedores em Java
- Avaliação do Kotlin em projetos reais
- Como aumentar a adoção do Kotlin na sua empresa
- Como ajudar os tomadores de decisão a dizerem “sim” para o Kotlin
- Escalando a adoção do Kotlin em toda a sua empresa
Fatores de sucesso para a adoção do Kotlin em larga escala
Fazer com que os desenvolvedores comprem a ideia e a administração apoie o Kotlin é um marco significativo, mas não é a linha de chegada. O verdadeiro desafio começa quando você tem que encarar bases de código existentes em Java que precisam coexistir com o Kotlin ou fazer a transição para ele. Como navegar esse mundo híbrido de forma eficaz?
A chave para administrar bases antigas de código é desenvolver uma estratégia alinhada com as metas da sua empresa e a realidade operacional. Esta é uma abordagem comprovada, que tem funcionado bem na prática.
Estratégia do ciclo de vida dos aplicativos
Aplicativos diferentes requerem abordagens diferentes, baseadas nas fases do seu ciclo de vida. Vamos examinar três categorias distintas:
Aplicativos no final da vida útil
Estratégia: não fazer nada.
Se um aplicativo estiver programado para ser desativado, não há um caso de negócios para a migração. Mantenha esses sistemas em Java e concentre as suas energias onde elas fizerem mais diferença. O custo de migrar esses aplicativos nunca será justificado pela vida útil restante para eles.
Novos sistemas
Estratégia: usar o Kotlin como padrão.
Em empresas nas quais a adoção do Kotlin está completa, projetos novos começam naturalmente em Kotlin. Se o processo de adoção estiver em andamento, as equipes costumam poder escolher entre o Java e o Kotlin. Escolha com sabedoria ;-).
Aplicativos em atividade
Estratégia: uma migração pragmática, orientada pelos recursos.
Os aplicativos em atividade são os que requerem uma ponderação cuidadosa: reescrevê-los sem um bom motivo é uma ideia difícil de vender para o proprietário do produto. Em vez disso, combine os esforços de migração com o desenvolvimento de novos recursos. Esta abordagem traz um valor de negócios tangível e também moderniza a sua base de código. Já discutimos os diferentes ângulos de ataque na seção Ampliar ou converter um aplicativo em Java já existente.
Abordagens para a conversão de Java para Kotlin
Ao converter de Java para Kotlin, há várias opções, cada uma com diferentes vantagens e desvantagens:
1. Reprogramação total
Melhor opção para: bases pequenas de código
Desafio: demorada para sistemas maiores
Reprogramar uma base de código do zero resulta no código mais limpo e idiomático em Kotlin. Esta abordagem é adequada para bases pequenas de código, como um microsserviço. Para bases grandes de código, esta abordagem geralmente tende a ter um custo proibitivo.
2. Conversão automática pelo IDE, com refinamentos manuais
Melhor opção para: bases médias de código, com tempo dedicado para refatoração
Desafio: os refinamentos manuais são obrigatórios
O recurso Convert Java to Kotlin, do IntelliJ IDEA, fornece uma tradução literal, que está longe de ser idiomática. Veja este exemplo:
Primeira rodada:
Java
record Developer(
String name,
List languages
) {}
Resultado bruto da conversão automática:
Kotlin
@JvmRecord data class Developer( val name: String?, val languages: MutableList? )
Esta conversão tem vários problemas:
- Tudo pode ter valores nulos (defensivo demais).
- As coleções do Java viram uma
MutableList, em vez da lista-padrão somente para leitura do Kotlin.
Como melhorar a conversão com anotações jspecify:
Felizmente, há uma solução para converter todos os tipos do Java em tipos Nullable do Kotlin, através de anotações @NonNull/@Nullable. Estão disponíveis diversas opções; a mais moderna é jspecify, que recentemente também ganhou suporte no Spring:
org.jspecify
jspecify
1.0.0
implementation("org.jspecify:jspecify:1.0.0")
@jspecify torna possível anotar o código em Java com @Nullable and @NonNull.
Segunda rodada:
Java
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
record Developer(
@NonNull String name,
@NonNull List languages,
@Nullable String email
) {}
Agora a conversão automática produz resultados muito melhores:
Kotlin
@JvmRecord data class Developer( //😃 non-null as requested val name: String, //😃 both, collection and type are non-null val languages: MutableList, //😃 nullable as requested val email: String?, )
Limitações da abordagem de conversão automática:
Mesmo com anotações de jspecify, padrões complexos em Java não se convertem bem. Veja este exemplo de código convertido automaticamente, mostrado na seção 3. O código em Kotlin não tem mais exceções verificadas, mas é mais seguro:
Kotlin
fun downloadAndGetLargestFile(urls: MutableList): String? {
//🤨 using Stream, instead of Kotlin Collections
val contents = urls.stream().map { urlStr: String? ->
//🤨 still using Optional, rather than Nullable types
//🤨 var but we want val!
var optional: Optional
//🤨 useless try-catch, no need to catch in Kotlin
try {
optional = Optional.of(URI(urlStr).toURL())
} catch (e: URISyntaxException) {
optional = Optional.empty()
} catch (e: MalformedURLException) {
optional = Optional.empty()
}
optional
}.filter { it!!.isPresent() }//🤨 discouraged !! to force conversion to non-null
.map {it.get() }
.map { url: URL ->
//🤨 useless try-catch, no need to catch in Kotlin
try {
url.openStream().use { `is` ->
String(`is`.readAllBytes(), StandardCharsets.UTF_8)
}
} catch (e: IOException) {
throw IllegalArgumentException(e)
}
}.toList()
//🤨 usage of Java collections…
return Collections.max(contents)
}
A conversão automática fica muito longe do resultado desejado, idiomático:
Kotlin
fun downloadAndGetLargestFile(urls: List): String? =
urls.mapNotNull {
runCatching { URI(it).toURL() }.getOrNull()
}.maxOfOrNull{ it.openStream().use{ it.reader().readText() } }
A conversão automática dá um ponto de partida, mas é necessário fazer um significativo refinamento manual e ter conhecimento de Kotlin verdadeiramente idiomático para se alcançar este.
3. Conversão assistida por IA
Melhor opção para: bases de código maiores, com uma infraestrutura robusta de testes
Desafio: é necessária revisão manual
Potencialmente, a IA pode produzir resultados mais idiomáticos que uma conversão automática básica, mas o sucesso depende de uma preparação cuidadosa:
Pré-requisitos:
- Cobertura abrangente de testes: como LLMs são imprevisíveis, você precisa de testes confiáveis para detectar alucinações da IA.
- Prompts de sistema bem pensados: crie instruções detalhadas para usar conversões idiomáticas para Kotlin, alinhadas aos seus padrões. Você pode usar este prompt de sistema como ponto de partida.
- Extensa revisão do código: a saída da IA requer uma revisão minuciosa, examinando a correção lógica e idiomática, o que pode ser muito cansativo mentalmente em bases grandes de código.
O resultado é bem satisfatório com o uso deste prompt de sistema proposto para guiar a conversão, mas não é perfeito:
Kotlin
fun downloadAndGetLargestFile(urls: List): String? {
val contents = urls
.mapNotNull {
urlStr -> runCatching { URI(urlStr).toURL() }.getOrNull()
}.mapNotNull { url -> runCatching {
url.openStream().use { it.readAllBytes().toString(UTF_8)
}
}.getOrNull() }
return contents.maxOrNull()
}
4. Conversão automática em escala
Melhor opção para: bases imensas de código, que requeiram transformação sistemática
No momento, não há nenhuma ferramenta oficial para converter bases de código em Java para Kotlin em escala. Porém, a Meta e a Uber encararam esse desafio com sucesso em suas bases de código para Android, usando abordagens que funcionam igualmente bem para aplicativos de back-end. A documentação e as palestras a seguir fornecem insights sobre como a Meta e a Uber abordaram essa missão:
A abordagem da Meta:

- Estratégia: transformação determinista baseada em regras
- Recursos:
A abordagem da Uber:

- Estratégia: transformação determinista baseada em regras, usando IA para gerar as regras de conversão
- Recurso: apresentação na KotlinConf
As duas empresas tiveram sucesso em criar processos sistemáticos e repetíveis, em vez de dependerem da conversão manual ou da automação simples. Suas abordagens baseadas em regras garantem consistência e qualidade em milhões de linhas de código.
Importante: Converter Java em Kotlin em escala introduz um desafio em nível social: para que o código gerado seja confiável, você ainda irá querer “um humano no meio” fazendo uma revisão. Porém, se isso não for planejado com cuidado, os engenheiros podem facilmente ficar sobrecarregados pela enxurrada de solicitações de pull criadas pela conversão automática. Portanto, o impacto social precisa ser examinado com cuidado.
Lembre-se: a adoção bem-sucedida do Kotlin em escala não consiste apenas em converter código — também envolve criar expertise na equipe, estabelecer padrões de programação e criar processos sustentáveis que tragam valor de longo prazo à sua empresa.
Recapitulação rápida de quando usar cada abordagem:
- Aplicativo pequeno ou que esteja mesmo para ser refeito?
→ Reescrever em Kotlin (1) - Bases médias de código, com tempo dedicado para refatoração, ou com a equipe aprendendo Kotlin?
→ Conversão automática pelo IntelliJ IDEA + refinamento (começar pelos testes) (2) - Código médio ou grande, com padrões repetitivos e bons testes?
→ Abordagem assistida por IA (3) - Migração para o Kotlin no nível de toda a empresa e em muitos serviços?
→ Conversão automática em escala, com um plano concreto (conduzido pela plataforma) (4)
Libere todo o potencial do Kotlin
O Kotlin torna os desenvolvedores produtivos rapidamente. Sua sintaxe concisa, seus recursos de segurança e sua rica biblioteca-padrão ajudam muitos desenvolvedores a escreverem código melhor em semanas, não raramente através de autoestudo ou aprendizado no trabalho. Mas sem orientação, muitos caem na armadilha de usar o Kotlin ao estilo do Java: continuando a usar estruturas mutáveis e padrões prolixos e deixando de usar recursos idiomáticos.
Como alcançar um novo patamar
Muitos desenvolvedores não conseguem atingir um novo patamar — adotando a imutabilidade, código orientado para expressões, DSLs e concorrência estruturada com corrotinas (com ou sem threads virtuais).
Neste estágio, descobri que um treinamento externo faz muito mais diferença que o autoestudo. Até desenvolvedores com anos de experiência em Kotlin costumam se beneficiar de um treinamento com foco em adotar padrões idiomáticos e liberar todo o potencial da linguagem.

Usar ou não o Kotlin: que tipo de empresa você quer ser?
No fim das contas, a decisão de adotar o Kotlin reflete a sua cultura de engenharia. Você valoriza:
- A abordagem tradicional (Java): conservadora, cerimoniosa, estável?
- A abordagem progressista (Kotlin): pragmática, moderna, adaptativa?
As duas têm seus méritos. Java vai fazer o trabalho. Provavelmente, Kotlin o fará melhor, com desenvolvedores mais satisfeitos e menos bugs. A questão não é se o Kotlin é melhor — é se a sua empresa está pronta para investir em ser melhor.
A jornada desde aquele primeiro teste do Kotlin até a adoção em toda a empresa nem sempre é suave, mas com a abordagem certa, é notavelmente previsível. Comece pequeno, demonstre o valor, crie uma comunidade e escale criteriosamente.
Seus desenvolvedores — atuais e futuros — lhe agradecerão.
Artigo original em inglês por:
