
Depuis que Google a annoncé la prise en charge officielle de Kotlin sur Android, de plus en plus de développeurs souhaitent l'utiliser dans leurs projets nouveaux et existants. Comme je suis aussi un grand fan de Kotlin, je ne pouvais pas attendre de pouvoir utiliser Kotlin dans mon projet de travail. Au final, Kotlin est entièrement compatible avec Java, et tous les développeurs en sont ravis. Alors qu'est-ce qui pourrait mal tourner?
Eh bien, beaucoup de choses peuvent mal tourner. J'ai juste peur que la page officielle Android Getting Started with Kotlin indique que si vous voulez porter une application existante sur Kotlin, il vous suffit de commencer à écrire des tests unitaires, puis, après un peu d'expérience avec cette langue, vous devriez écrire du nouveau code dans Kotlin, et le code Java existant est facile à convertir.
Dans cet article, je vais vous dire ce qui se passerait si je décidais de suivre immédiatement cette stratégie sur la prod et de ne pas l'essayer sur mon petit projet.
Rencontrez mon petit projet
J'avais un projet que j'ai créé il y a plus d'un an à Java, et je devais le changer un peu et ajouter un nouvel écran. J'ai pensé que c'était une excellente occasion de vérifier si la migration d'un projet existant vers Kotlin est vraiment très simple, comme tout le monde le dit. Sur la base des recommandations de la documentation officielle, j'ai commencé par écrire des tests unitaires sur Kotlin. J'ai également écrit de nouvelles classes dans Kotlin et converti certaines existantes. Tout semblait merveilleux, mais après un certain temps, j'ai découvert un problème désagréable.
Kotlin + Lombok = :(
Dans mon application, j'ai utilisé la bibliothèque Lombok pour générer des getters et setters. Lombok est un processeur d'annotation pour javac. Malheureusement, le compilateur kotlin utilise javac sans traiter les annotations [source] . Cela signifie que les méthodes créées avec Lombok ne seront pas disponibles dans Kotlin:

Mais vous pouvez dire: «Eh bien, ce ne sera pas très cool, mais en principe, vous pouvez créer manuellement des getters et setters pour les champs qui seront nécessaires dans le code Kotlin. En fin de compte, vous n’avez pas besoin de le faire immédiatement dans l’ensemble du projet. »
J'ai pensé la même chose. Mais j'ai rencontré un vrai problème lorsque j'ai voulu ajouter un nouvel écran à l'application.
Kotlin + Lombok + Dague 2 =: (((
Mon application utilise Dagger 2 pour injecter des dépendances. Lors de la création d'un nouvel écran, je crée généralement une structure MVP: Activité, Présentateur, Composant, Module et Contrat. Toutes les dépendances du présentateur sont implémentées à l'aide de Dagger. L'activité appelle DaggerSomeComponent.builder().(...).build().inject(this)
pour injecter au présentateur les dépendances nécessaires.
L'utilisation de Dagger 2 avec Kotlin ne pose aucun problème. Juste avant cela, vous devez appliquer le plugin kapt , qui crée les classes auto-générées nécessaires pour Dagger.
Et ici, tout commence à s'effondrer
Sans le plugin kapt, je ne pourrais pas utiliser les classes Dagger générées dans les fichiers Kotlin. Mais après avoir ajouté ce plugin, toutes les méthodes créées par Lombok ont disparu!
Avant d'appliquer le plugin kapt :

Après avoir appliqué le plugin kapt :

Et, malheureusement, il n'y a pas de solution à ce problème. Vous pouvez utiliser uniquement le plugin kapt ou uniquement Lombok . Heureusement, comme c'était juste mon petit projet, j'ai simplement supprimé Lombok et écrit moi-même les getters et setters. Mais dans ce projet, il n'y avait qu'une cinquantaine de méthodes générées. Dans le projet que nous accompagnons au travail, nous en avons environ un millier . Supprimer Lombok de cette application n'est tout simplement pas possible.
De plus, il est évident que l'abandon du plugin kapt n'est pas la solution. Sans cela, vous ne pouvez pas utiliser Kotlin dans les classes où Dagger est utilisé. Dans mon cas, je devrais implémenter Activity, Component et Module en Java, et seuls Contract et Presenter pourraient être écrits en Kotlin. Mélanger des fichiers Java et Kotlin n'est certainement pas génial. Au lieu d'une transition en douceur de Java à Kotlin, vous créeriez simplement un gros gâchis.
Voici à quoi ressemblerait cette terrible structure MVP polyglotte sans un plugin kapt:

Mais je veux toujours passer à Kotlin. Que dois-je faire?
Une façon consiste à utiliser différents modules . Kotlin ne verra pas les méthodes que Lombok générera dans le code source, mais les verra dans le bytecode.
Personnellement, il me semble que c'est la voie la plus privilégiée. Si vous placez Kotlin dans des modules dépendants distincts pour chaque fonctionnalité, vous réduisez le risque de problèmes de compatibilité que j'ai rencontrés ou de problèmes plus complexes répertoriés dans le guide officiel .
Et ce n’est pas tout. Il existe de nombreux autres inconvénients à mélanger les fichiers Kotlin et Java sans séparation claire. Cela permet à tous les développeurs travaillant avec vous sur le projet de connaître les deux langues. Cela réduit également la lisibilité du code et peut entraîner une augmentation du temps de génération [source] .
Brièvement
- les méthodes générées par Lombok ne sont pas visibles dans Kotlin;
- l'utilisation du plugin kapt casse Lombok;
- sans plugin kapt, vous ne pouvez pas utiliser de classes auto-générées pour Dagger dans Kotlin, ce qui signifie que vous devez encore écrire du nouveau code Java;
- un moyen de résoudre ce problème consiste à intégrer Kotlin dans des modules séparés;
- le mélange de fichiers Kotlin et Java dans de grands projets sans séparation claire peut entraîner des problèmes de compatibilité inattendus.