L’intérêt principal de cette migration ? Migrer du natif vers le multiplateforme, c’est avant tout réduire les coûts et le lead time pour livrer de nouvelles fonctionnalités. Maintenant, pourquoi choisir une migration vers KMP plutôt que Flutter ou React Native ? Car elle peut être réalisée par étapes, en migrant une couche applicative ou une fonctionnalité à la fois, limitant ainsi les risques et facilitant l’intégration.
J’ai moi-même participé à ce genre de migration. Dans ce premier article, je vous explique la méthodologie suivie.
🚀 Dans un deuxième article, je partagerai un retour d’expérience basé sur l’application concrète de cette méthodologie.
Avant de débuter la migration, il est crucial d’identifier les écarts entre les versions iOS et Android de votre application. La migration KMP offre l’opportunité d’unifier certaines de ces différences de comportement, si cela s’avère pertinent.
➡️ Pourquoi cette étape est essentielle ?
Elle évite la création d’une implémentation KMP trop spécifique à Android et garantit que les avantages de la version iOS ne soient pas perdus.
Il existe aussi des différences d’implémentation, ce qui est normal puisque iOS et Android ont chacun leurs spécificités. Pour les différences d’architecture, par contre, notez-les : cela vous aidera à estimer la difficulté de la migration progressive par couche. Plus les couches d’architecture sont différentes, plus la migration par couche sera complexe côté iOS.
Avant de commencer, il est impératif d’effectuer certaines mises à jour :
➡️ L’objectif est d’assurer une transition fluide sans surprises techniques bloquantes.
Plusieurs solutions s’offrent à vous ; elles sont détaillées sur le site de KMP.
Je vous conseille la solution suivante, plus simple pour la maintenance du projet migré :
Cette solution a ses limitations. Pour aller plus loin, vous pouvez consulter cet article de TouchLab (un leader sur KMP) qui parle de leur outil Gitportal.
La migration doit se faire par petites étapes. Commencez par une fonctionnalité isolée, non centrale, une fonctionnalité feuille ou périphérique, pour minimiser les risques.
❓Comment trouver une fonctionnalité feuille ?
🔹 Pourquoi commencer par la couche modèle ?
C’est la couche qui contient normalement le moins de dépendances à des librairies externes. Et donc le moins de code spécifique à une platforme.
🟦 Comment attaquer la couche modèle ?
java.util.UUID
par kotlin.uuid.Uuid
).model
de votre fonctionnalité en dupliquant les classes de votre code Android tout en tenant compte des éventuelles différences avec iOS.La couche modèle est la plus simple à migrer, car elle n’a pas (ou peu) de dépendances externes. C’est le cœur de votre application et la couche qui présente généralement le moins de différences entre les plateformes.model
par ceux des classes du module commun.Après avoir migré la couche modèle avec succès, on pourrait être tenté de passer sur les couches suivantes. Cependant, les couches suivantes auront probablement besoin de vos modules transverses. Par exemple, la couche data de votre fonctionnalité a besoin du module qui crée le client HTTP. Vous aurez aussi besoin de votre logger, des analytics, des fonctions utils
et même de votre design system à un moment.
Il serait donc intéressant de migrer ces modules transverses d'abord. Toutefois, il peut être difficile de se rendre compte si l'on a besoin de migrer tout un module ou seulement une partie liée à la feature que l'on migre.
Il est donc recommandé de continuer les étapes de migrations suivantes en revenant aux modules transverses dès que nécessaire.
La couche Data gère les appels réseau, les accès aux bases de données et les manipulations de fichiers. Elle est étroitement liée à la logique métier. Migrez chaque partie de cette couche une par une.
Vous aurez plus de facilité si vous utilisez déjà les coroutines ou Kotlin Flow plutot que Rx et les Livedata.
Dans le cas où vos données interagissent avec celles d’autres fonctionnalités, trois choix s'offrent à vous :
La partie logique métier contient les règles spécifiques à votre application. Cette couche, proche de la couche modèle, inclut souvent des fonctions qui récupèrent, mettent à jour ou suppriment des données. Elle peut être fortement liée à des bibliothèques externes comme Rx ou LiveData pour rendre les données réactives.Elle communique avec la couche Data pour récupérer les données et les transformer.
Pour migrer cette couche, déplacez vos adaptateurs de code réactif pour les utiliser dans la couche présentation plutôt que dans la couche métier. En faisant cela, vous allez conformer votre couche métier aux librairies de réactivités Kotlin (coroutines, flow).
Cette couche, qui fait appel à la logique métier pour nourrir les vues, est souvent la moins bien architecturée. En effet, le cœur d’une application mobile étant d’organiser l’affichage des données de réagir aux interactions de l’utilisateur, c’est par ici que passe la plupart du code. Par ailleurs c’est la couche qui communique avec les vues, on y retrouve donc souvent du code très (trop ?) proche de la plateforme.Soyez très attentif, c'est ici que vous risquez le plus d'avoir des régressions, complétez vos TUs au besoin.
🎯 Stratégie recommandée
Si vous souhaitez partager la vue entre les plateformes avec Compose Multiplatform, c’est le moment de le faire. Dupliquez les vues Android en réimplémentant les éléments spécifiques à Compose pour Android. Compose Multiplatform étant très proche de Compose pour Android, les modifications nécessaires seront limitées. Une fois que tous les éléments spécifiques à Android seront écartés, votre code Compose sera utilisable sur iOS.
En migrant également les vues, vous limiterez considérablement la communication entre le code KMP et le code Swift. Bien que la promesse de KMP soit la facilité de communication entre le code commun et spécifique, il est toujours plus simple de ne pas avoir à le faire.
À cette étape, la plupart du travail est fait. Il ne reste que quelques éléments spécifiques aux plateformes comme la navigation ou certaines intégrations natives.. Finalisez ces migrations progressivement, sans précipitation.
Dans cette stratégie progressive, le code commun est conçu pour s’adapter à iOS, ce qui permet de ne pas bloquer le développement de l’application iOS tout en s’assurant que l’API du code commun est bien adaptée à cette plateforme.
Plus le code des plateformes est différent dans son architecture, ses composants, ses noms, ses comportements et sa logique, moins la migration progressive pour iOS est intéressante. Cette stratégie peut devenir chronophage et une approche moins progressive pourrait être plus adaptée. On peut se limiter par exemple à une migration progressive feature par feature.
Cette première partie détaille une méthodologie structurée pour migrer progressivement une application mobile vers Kotlin Multiplatform. Plus votre code Android sera loin de l’univers Android et Java et proche de Kotlin, plus la migration sera facile. Plus votre architecture et les interfaces entre les couches seront identiques sur Android et iOS, plus vous aurez l’avantage de migration progressive par couche sur iOS.
Dans la deuxième partie, nous partagerons un retour d’expérience sur l’application concrète de ces étapes, avec les défis rencontrés et les enseignements tirés.
📌 Restez connectés pour la suite ! 🚀