
Desde que o Google anunciou o suporte oficial ao Kotlin no Android, mais e mais desenvolvedores desejam usá-lo em seus projetos novos e existentes. Como também sou um grande fã do Kotlin, eu mal podia esperar para poder usar o Kotlin no meu projeto de trabalho. No final, o Kotlin é totalmente compatível com Java, e todos os desenvolvedores estão satisfeitos com isso. Então, o que poderia dar errado?
Bem, na verdade muita coisa pode dar errado. Só estou com medo de que a página oficial da documentação do Android "Introdução ao Kotlin" diga que se você deseja transferir um aplicativo existente para o Kotlin, comece a escrever testes de unidade e, depois de um pouco de experiência com esse idioma, escreva um novo código no Kotlin, e o código Java existente é fácil de converter.
Neste artigo, vou lhe dizer o que aconteceria se eu decidisse seguir imediatamente essa estratégia no produto e não experimentá-lo no meu pequeno projeto.
Conheça meu pequeno projeto
Eu tinha um projeto que criei há mais de um ano em Java e precisava alterá-lo um pouco e adicionar uma nova tela. Eu pensei que era uma ótima oportunidade para verificar se a migração de um projeto existente para o Kotlin é realmente muito simples, como todos dizem. Com base nas recomendações da documentação oficial, comecei escrevendo testes de unidade no Kotlin. Também escrevi novas aulas no Kotlin e converti algumas já existentes. Tudo parecia maravilhoso, mas depois de um tempo descobri um problema desagradável.
Kotlin + Lombok = :(
No meu aplicativo, usei a biblioteca Lombok para gerar getters e setters. Lombok é um processador de anotação para javac. Infelizmente, o compilador kotlin usa javac sem processar anotações [fonte] . Isso significa que os métodos criados com o Lombok não estarão disponíveis no Kotlin:

Mas você pode dizer: “Bem, não será muito legal, mas, em princípio, você pode criar manualmente getters e setters para os campos que serão necessários no código Kotlin. No final, você não precisa fazer isso em todo o projeto imediatamente. "
Eu pensei da mesma maneira. Mas encontrei um problema real quando quis adicionar uma nova tela ao aplicativo.
Kotlin + Lombok + Adaga 2 =: ((((
Meu aplicativo usa o Dagger 2 para injetar dependências. Ao criar uma nova tela, geralmente crio uma estrutura MVP: Atividade, Apresentador, Componente, Módulo e Contrato. Todas as dependências para o apresentador são implementadas usando o Dagger. A atividade chama DaggerSomeComponent.builder().(...).build().inject(this)
para injetar no apresentador as dependências necessárias.
Usar o Dagger 2 com Kotlin não é problema. Antes disso, você precisa aplicar o plugin kapt , que cria as classes auto-geradas necessárias para o Dagger.
E aqui tudo começa a desmoronar
Sem o plugin kapt, eu não poderia usar as classes Dagger geradas nos arquivos Kotlin. Mas depois que adicionei este plugin, todos os métodos criados por Lombok desapareceram!
Antes de aplicar o plugin kapt :

Após aplicar o plugin kapt :

E, infelizmente, não há solução para esse problema. Você pode usar apenas o kapt-plugin ou apenas o Lombok . Felizmente, como era apenas meu pequeno projeto, simplesmente excluí Lombok e escrevi os getters e setters. Mas neste projeto, havia apenas cerca de 50 métodos gerados. No projeto que apoiamos no trabalho, temos cerca de mil deles . Remover Lombok deste aplicativo simplesmente não é possível.
Além disso, é óbvio que desistir do plugin kapt não é a saída. Sem ele, você não pode usar o Kotlin nas classes em que o Dagger é usado. No meu caso, eu precisaria implementar Activity, Component e Module em Java, e apenas Contract e Presenter poderiam ser escritos em Kotlin. A mistura de arquivos Java e Kotlin definitivamente não é ótima. Em vez de uma transição suave do Java para o Kotlin, você simplesmente criaria uma grande bagunça.
É assim que esta terrível estrutura poliglota do MVP seria sem o plugin kapt:

Mas ainda quero mudar para Kotlin. O que eu faço?
Uma maneira é usar módulos diferentes . O Kotlin não verá os métodos que o Lombok irá gerar no código fonte, mas os verá no bytecode.
Pessoalmente, parece-me que esta é a maneira mais preferida. Se você colocar o Kotlin em módulos dependentes separados para cada recurso, reduzirá o risco de problemas de compatibilidade que eu encontrei, ou mais complexos listados no guia oficial .
E isso não é tudo. Existem muitas outras desvantagens em misturar arquivos Kotlin e Java sem uma separação clara. Isso faz com que todos os desenvolvedores que trabalham com você no projeto conheçam os dois idiomas. Também reduz a legibilidade do código e pode levar a um aumento no tempo de compilação [origem] .
Brevemente
- métodos gerados por Lombok não são visíveis no Kotlin;
- o uso do plugin kapt quebra o Lombok;
- sem um plug-in kapt, você não pode usar classes auto-geradas para o Dagger no Kotlin, o que significa que você ainda precisa escrever um novo código Java;
- uma maneira de resolver esse problema é trazer o Kotlin em módulos separados;
- misturar arquivos Kotlin e Java em grandes projetos sem uma separação clara pode levar a problemas inesperados de compatibilidade.