Por qué y cómo Meta migró el desarrollo de Android de Java a Kotlin
(engineering.fb.com)- El repo de Android de Meta es un enorme repositorio que incluye Facebook, Instagram, Messenger, Quest y más
- Actualmente contiene más de 10 millones de líneas de código en Kotlin
Por qué cambiaron a Kotlin
- Más allá de su popularidad, estas fueron las principales ventajas
- Nullability: los NPE eran un problema común en Meta, así que probaron varias formas de mitigarlo, pero el manejo integrado de nullability en Kotlin era mucho más potente y más fácil de trabajar
- Programación funcional: las funciones inline y las expresiones lambda de Kotlin permiten aplicar un estilo de FP sin degradar la velocidad de ejecución
- Código más corto
- DSL / Type-safe Builder
- Claro, también había algunas desventajas que no se podían ignorar
- Al introducir otro lenguaje, tenían que mantener durante bastante tiempo una base de código mixta
- Aunque Kotlin es popular, todavía existe una brecha frente a Java en ese aspecto. Por eso hay menos herramientas, y muchas herramientas para Kotlin deben considerar la interoperabilidad entre Kotlin y Java, lo que complica su implementación
- La mayor preocupación era el tiempo de compilación. Desde el principio sabían que compilar Kotlin podía ser más lento que Java. Los tiempos de compilación lentos afectan negativamente la experiencia de los desarrolladores
Cómo abordaron la migración
- La migración a Kotlin fue sorprendentemente sencilla y, al mismo tiempo, muy compleja
- J2K (Java To Kotlin Converter) ayudaba bastante, pero aun así era complicado
- J2K no siempre es preciso, y la interoperabilidad entre Java y Kotlin genera algunos casos extremos
- Había dos opciones para la migración
- Escribir solo el código nuevo en Kotlin y dejar la mayor parte del código en Java
- La ventaja es que requiere menos trabajo, pero al mezclar los dos lenguajes, Kotlin termina usando platform types, lo que puede provocar desreferencias de punteros nulos y causar crashes.
Además, existían problemas como que en Java no se podía etiquetar un type parameter como nullable (hasta hace poco), y que las reglas de sobrecarga de Kotlin sí consideran si null está permitido, mientras que las de Java no
- La ventaja es que requiere menos trabajo, pero al mezclar los dos lenguajes, Kotlin termina usando platform types, lo que puede provocar desreferencias de punteros nulos y causar crashes.
- Intentar convertir a Kotlin todo el código interno
- Escribir solo el código nuevo en Kotlin y dejar la mayor parte del código en Java
Cómo hicieron la migración
- Consideraron ambas opciones y decidieron apuntar a convertir todo el código a Kotlin
- Al principio fue algo lento, pero después de resolver algunos blockers pudieron convertir grandes volúmenes de código
- Actualmente, cada una de las apps de Android de Facebook, Messenger e Instagram incluye 1 millón de líneas de código en Kotlin, y la tasa de conversión sigue aumentando
- En este momento, toda la base de código de Android contiene 10 millones de líneas de Kotlin
Unblocking
- Al comenzar la conversión aparecieron algunos problemas
- Fue necesario actualizar Redex debido a patrones de bytecode
- Algunas librerías internas hacían transformación de bytecode por motivos de rendimiento, y eso no funcionaba en Kotlin
- Si internamente ya tienen muchas optimizaciones, probablemente aparezcan problemas parecidos
- También surgieron problemas con las herramientas existentes
- Como en code review y en la wiki no se resaltaba la sintaxis de Kotlin, actualizaron Pygments
- Desarrollaron por separado Ktfmt, un formateador para Kotlin
Acelerar la migración
- Una vez que las herramientas estuvieron listas, ya podían preparar el código para convertirlo a Kotlin
- Pero cada migración todavía tenía mucho boilerplate que debía hacerse manualmente
- Como J2K es una herramienta genérica, no entiende el contexto del código. Por eso hacía falta mucho trabajo manual
- Por ejemplo, con cosas como las reglas de testing de JUnit
- Así que colocaron J2K en medio de un pipeline de 3 etapas
- Primero, tomaban un paquete de Java y lo preparaban para convertirlo a Kotlin, corrigiendo bugs y aplicando conversiones necesarias para las herramientas internas
- Segundo, ejecutaban J2K automáticamente mediante scripts
- Tercero, procesaban después los nuevos archivos Kotlin. Esta era la parte más importante. Ejecutaban refactorizaciones automáticas, linters, etc., en modo headless
- La automatización no resolvía todos los problemas, pero priorizaron los casos comunes
Lo que aprendieron de la migración a Kotlin
- La longitud del código se redujo
- Se mantuvo la velocidad de ejecución
- El tamaño del build no fue un problema
- Resolución del problema de tiempos de compilación más largos: uso de KSP (Kotlin Symbol Processing API)
4 comentarios
Gracias por compartir este buen artículo. En lo personal, cuando empecé a usar Kotlin, me gustó porque tiene muchas cosas más cómodas que Java y pensé que en adelante Kotlin quizá se volvería la tendencia principal, pero después de usarlo un tiempo también vi que todavía hay bastantes aspectos en los que Java me parece mejor.
Creo que en Android está bien pasarse a Kotlin, pero en otros entornos (como Spring, por ejemplo), si la estabilidad es importante, todavía me parece que Java es una mejor opción.
¿Podrías compartir aunque sea un solo ejemplo de estabilidad? Aún me falta experiencia, así que todavía no me he encontrado con casos así, y me da muchísima curiosidad.
No sé si será porque JetBrains está sacando lanzamientos a lo loco, pero sorprendentemente hay muchos arreglos de bugs del compilador.
https://github.com/JetBrains/kotlin/releases/tag/v1.7.20
A veces incluso se cae el compilador en sí (eso al menos está bien porque pasa antes del despliegue), y también de vez en cuando se incluyen bugs en los artefactos generados.
Además, en Android el optimizador de bytecode R8 también depende de la versión de Kotlin.
Porque existe una función de optimización exclusiva para código Kotlin, pero no hay una documentación oficial con una tabla de compatibilidad para esto (Android Gradle Plugin : Kotlin Version)..
Así que hay que tener cuidado al cambiar la versión de Kotlin en proyectos Android;;;
Reporte de bug relacionado: https://issuetracker.google.com/issues/207397158
Gracias. Hay un mundo profundo y amplio.