
Desde que Google anunció el soporte oficial para Kotlin en Android, cada vez más desarrolladores quieren usarlo en sus proyectos nuevos y existentes. Como también soy un gran admirador de Kotlin, no podía esperar para poder usar Kotlin en mi proyecto de trabajo. Al final, Kotlin es totalmente compatible con Java, y todos los desarrolladores están encantados con él. Entonces, ¿qué podría salir mal?
Bueno, en realidad muchas cosas pueden salir mal. Me da miedo que la página oficial de Android Getting Started with Kotlin diga que si quieres portar una aplicación existente a Kotlin, solo tienes que comenzar a escribir pruebas unitarias, y luego, después de un poco de experiencia con este idioma, deberías escribe un nuevo código en Kotlin, y el código Java existente es fácil de convertir.
En este artículo, le diré lo que sucedería si decidiera seguir inmediatamente esta estrategia en el producto y no probarla en mi pequeño proyecto.
Conoce mi pequeño proyecto
Tenía un proyecto que creé hace más de un año en Java, y necesitaba cambiarlo un poco y agregar una nueva pantalla. Pensé que esta era una gran oportunidad para verificar si la migración de un proyecto existente a Kotlin es realmente muy simple, como dicen todos. Basado en las recomendaciones de la documentación oficial, comencé escribiendo pruebas unitarias en Kotlin. También escribí nuevas clases en Kotlin y convertí algunas existentes. Todo parecía ser maravilloso, pero después de un tiempo descubrí un problema desagradable.
Kotlin + Lombok = :(
En mi aplicación, utilicé la biblioteca Lombok para generar captadores y establecedores. Lombok es un procesador de anotaciones para javac. Desafortunadamente, el compilador de kotlin usa javac sin procesar anotaciones [fuente] . Esto significa que los métodos creados con Lombok no estarán disponibles en Kotlin:

Pero puede decir: “Bueno, no será muy bueno, pero en principio, puede crear captadores y establecedores manualmente para los campos que serán necesarios en el código de Kotlin. Al final, no necesita hacer esto en todo el proyecto de inmediato ".
Pensé de la misma manera. Pero encontré un problema real cuando quería agregar una nueva pantalla a la aplicación.
Kotlin + Lombok + Daga 2 =: ((((
Mi aplicación usa Dagger 2 para inyectar dependencias. Al crear una nueva pantalla, generalmente creo una estructura MVP: Actividad, Presentador, Componente, Módulo y Contrato. Todas las dependencias para el presentador se implementan utilizando Dagger. La actividad llama a DaggerSomeComponent.builder().(...).build().inject(this)
para inyectar al presentador las dependencias necesarias.
Usar Dagger 2 con Kotlin no es un problema. Justo antes de eso, debe aplicar el complemento kapt , que crea las clases autogeneradas necesarias para Dagger.
Y aquí todo comienza a desmoronarse
Sin el complemento kapt, no podría usar las clases Dagger generadas en los archivos de Kotlin. Pero después de agregar este complemento, ¡todos los métodos creados por Lombok desaparecieron!
Antes de aplicar el complemento kapt :

Después de aplicar el complemento kapt :

Y, desafortunadamente, no hay solución para este problema. Puede usar solo kapt-plugin o solo Lombok . Afortunadamente, dado que era solo mi pequeño proyecto, simplemente borré Lombok y escribí los captadores y establecedores yo mismo. Pero en este proyecto solo había unos 50 métodos generados. En el proyecto que apoyamos en el trabajo, tenemos alrededor de mil de ellos . Eliminar Lombok de esta aplicación simplemente no es posible.
Además, es obvio que renunciar al complemento kapt no es la solución. Sin él, no puedes usar Kotlin en clases donde se usa Dagger. En mi caso, tendría que implementar Activity, Component y Module en Java, y solo Kotlin podría escribir Contract y Presenter. Mezclar archivos Java y Kotlin definitivamente no es genial. En lugar de una transición suave de Java a Kotlin, simplemente crearías un gran desastre.
Así es como se vería esta terrible estructura MVP políglota sin un complemento kapt:

Pero todavía quiero cambiar a Kotlin. Que hago
Una forma es usar diferentes módulos . Kotlin no verá los métodos que Lombok generará en el código fuente, pero los verá en el código de bytes.
Personalmente, me parece que esta es la forma más preferida. Si coloca Kotlin en módulos dependientes separados para cada función, reduce el riesgo de los problemas de compatibilidad que encontré, o los más complejos enumerados en la guía oficial .
Y eso no es todo. Existen muchas otras desventajas al mezclar archivos Kotlin y Java sin una separación clara. Esto hace que todos los desarrolladores que trabajan con usted en el proyecto conozcan ambos idiomas. También reduce la legibilidad del código y puede conducir a un aumento en el tiempo de compilación [fuente] .
Brevemente
- los métodos generados por Lombok no son visibles en Kotlin;
- el uso del complemento kapt rompe Lombok;
- sin un complemento kapt, no puede usar clases autogeneradas para Dagger en Kotlin, lo que significa que todavía tiene que escribir un nuevo código Java;
- una forma de resolver este problema es llevar a Kotlin a módulos separados;
- mezclar archivos Kotlin y Java en proyectos grandes sin una separación clara puede generar problemas de compatibilidad inesperados.