{"id":219023,"date":"2021-12-21T09:09:36","date_gmt":"2021-12-21T08:09:36","guid":{"rendered":"https:\/\/blog.jetbrains.com\/kotlin\/2021\/12\/compose-multiplatform-toolbox-case-study\/"},"modified":"2022-01-20T11:27:36","modified_gmt":"2022-01-20T10:27:36","slug":"etude-de-cas-compose-multiplatform-toolbox","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/fr\/kotlin\/2021\/12\/etude-de-cas-compose-multiplatform-toolbox\/","title":{"rendered":"\u00c9tude de cas JetBrains Toolbox App : Migration d&#8217;un million d&#8217;utilisateurs vers Kotlin et Compose Multiplatform"},"content":{"rendered":"<p><em>Victor Kropp, chef d&#8217;\u00e9quipe Toolbox App chez JetBrains, raconte le passage de Kotlin et de Compose Multiplatform sur ordinateurs de bureau.<\/em><\/p>\n<p>L&#8217;<a href=\"https:\/\/www.jetbrains.com\/fr-fr\/toolbox-app\/\" target=\"_blank\" rel=\"noopener\">application JetBrains Toolbox App<\/a> constitue le point d&#8217;entr\u00e9e unique pour d\u00e9velopper avec les IDE de JetBrains. Elle sert de panneau de commande pour les outils et les projets, et rend l&#8217;installation et la mise \u00e0 jour des IDE JetBrains plus simple et rapide. Lanc\u00e9e en 2015 en tant que projet de hackathon, l&#8217;application compte d\u00e9sormais un million d&#8217;utilisateurs actifs par mois et renforce leur productivit\u00e9 avec les produits JetBrains.<\/p>\n<p>L&#8217;\u00e9quipe Toolbox App a migr\u00e9 son application de C++ et JavaScript vers Kotlin et Compose Multiplatform avec succ\u00e8s et a ainsi rendu son code plus facile maintenir et utiliser tout en livrant des artefacts plus petits et avec de meilleures performances d&#8217;ex\u00e9cution.<\/p>\n<p>Pour en savoir plus, lisez ce qui suit ou \u00e9coutez le t\u00e9moignage de Victor Kropp, Responsable de l&#8217;\u00e9quipe Toolbox App chez JetBrains, dans le podcast Talking Kotlin n\u00b0107.<\/p>\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\">\n<div class=\"wp-block-embed__wrapper\"><iframe loading=\"lazy\" title=\"Migration d'un million d'utilisateurs vers Kotlin et Compose : JB Toolbox App | Talking Kotlin n\u00b0107\" src=\"https:\/\/www.youtube.com\/embed\/sVRbsz_QI4g?start=121&amp;feature=oembed\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/div>\n<\/figure>\n<h3>Victor, pouvez-vous pr\u00e9senter l&#8217;architecture et la pile technologique utilis\u00e9es par JetBrains Toolbox App ?<\/h3>\n<p>Toolbox App est une application client-serveur type. L&#8217;application de bureau demande une liste des outils disponibles au serveur, la montre \u00e0 l&#8217;utilisateur et t\u00e9l\u00e9charge les mises \u00e0 jour des produits JetBrains si n\u00e9cessaire. Nous avons impl\u00e9ment\u00e9 la partie c\u00f4t\u00e9 serveur de notre application en Kotlin d\u00e8s le d\u00e9but. Mais pour l&#8217;application de bureau, c&#8217;\u00e9tait une autre histoire.<\/p>\n<p>Lorsque nous avons commenc\u00e9 \u00e0 cr\u00e9er l&#8217;application de bureau pour JetBrains Toolbox App en 2015, nous avons utilis\u00e9 C++ pour impl\u00e9menter sa logique m\u00e9tier et Chromium Embedded Framework avec React et HTML\/CSS\/JS pour cr\u00e9er l&#8217;interface utilisateur. Nous avons fait ce choix \u00e0 une \u00e9poque o\u00f9 Kotlin 1.0 n&#8217;\u00e9tait pas encore sorti, pas plus que le JDK modulaire qui est arriv\u00e9 avec Java 9. Nous ne pouvions pas nous permettre d&#8217;avoir un environnement d&#8217;ex\u00e9cution Java pesant des centaines de m\u00e9gaoctets pour une petite application utilitaire et ne voulions pas obliger nos utilisateurs \u00e0 configurer leur environnement manuellement. Nous avons donc choisi une approche radicalement diff\u00e9rente.<\/p>\n<p>En 2021, nous sommes finalement pass\u00e9s en 100\u00a0% Kotlin en migrant l&#8217;interface utilisateur de React vers Compose Multiplatform, plus pr\u00e9cis\u00e9ment Compose for Desktop.<\/p>\n<p align=\"center\"><a class=\"ek-link jb-download-button\" title=\"CTA\" href=\"https:\/\/www.jetbrains.com\/fr-fr\/lp\/compose-desktop\/\" target=\"_blank\" rel=\"noopener\">Visitez le site web de Compose for Desktop<\/a><\/p>\n<h3>Comment utilisez-vous Kotlin et ses biblioth\u00e8ques dans votre produit ?<\/h3>\n<p>La migration vers Kotlin \u00e9tant termin\u00e9e, nous l&#8217;utilisons partout. Outre Compose for Desktop pour l&#8217;interface utilisateur, nous faisons un usage intensif des <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\" target=\"_blank\" rel=\"noopener\">kotlinx.coroutines<\/a> pour tous les jobs asynchrones. Toolbox App manipule beaucoup d&#8217;objets JSON, nous utilisons donc naturellement <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.serialization\" target=\"_blank\" rel=\"noopener\">kotlinx.serialization<\/a> pour la (d\u00e9)s\u00e9rialisation.<\/p>\n<p>Nous avons fait en sorte que le c\u00f4t\u00e9 serveur reste aussi simple que possible. En fait, il ne s&#8217;agit pas d&#8217;un serveur HTTP comme on pourrait l&#8217;imaginer. Toutes les informations et les descriptions des outils installables (appel\u00e9s \u00ab\u00a0feeds\u00a0\u00bb dans Toolbox App) sont g\u00e9n\u00e9r\u00e9es de mani\u00e8re statique et fournies sous forme de fichiers JSON \u00e0 partir du CDN. Comme ils ne changent pas souvent, nous les mettons \u00e0 jour uniquement lorsque la nouvelle version d&#8217;un outil est publi\u00e9e dans le cadre du pipeline de livraison continue sur <a href=\"https:\/\/www.jetbrains.com\/fr-fr\/teamcity\/\" target=\"_blank\" rel=\"noopener\">TeamCity<\/a>. Le g\u00e9n\u00e9rateur est un simple programme Kotlin en ligne de commande, qui est appel\u00e9 en tant que \u00ab\u00a0configuration de build\u00a0\u00bb (nom donn\u00e9 par TeamCity \u00e0 un job) et se d\u00e9clenche automatiquement \u00e0 chaque build des produits pris en charge. Un second job fusionne ensuite p\u00e9riodiquement tous les feeds nouvellement g\u00e9n\u00e9r\u00e9s, \u00e9limine les feeds obsol\u00e8tes et effectue la validation.<\/p>\n<h3>Pourquoi l&#8217;\u00e9quipe Toolbox App a-t-elle d\u00e9cid\u00e9 d&#8217;utiliser Kotlin pour le d\u00e9veloppement de l&#8217;application de bureau ?<\/h3>\n<p>Avant de migrer vers Compose for Desktop, nous utilisions <a href=\"https:\/\/en.wikipedia.org\/wiki\/Chromium_Embedded_Framework\" target=\"_blank\" rel=\"noopener\">Chromium Embedded Framework<\/a> pour g\u00e9n\u00e9rer l&#8217;interface utilisateur de Toolbox App, et l&#8217;utilisation de C++ en natif pour notre logique m\u00e9tier facilitait la compatibilit\u00e9 avec les principaux syst\u00e8mes d&#8217;exploitation d&#8217;ordinateurs de bureau. Les choses ont bien chang\u00e9 depuis et nous avons pris la d\u00e9cision de migrer toute la logique m\u00e9tier en C++ vers Kotlin sur la JVM en 2020.<\/p>\n<p>En 2015, c&#8217;\u00e9taient d&#8217;excellents choix pour lancer le projet ! Nous pouvions r\u00e9utiliser les composants de <a href=\"https:\/\/github.com\/JetBrains\/ring-ui\" target=\"_blank\" rel=\"noopener\">Ring UI<\/a>, une biblioth\u00e8que de composants d&#8217;interface utilisateur web cr\u00e9\u00e9e par JetBrains. Et nous pouvions \u00e9galement une grande exp\u00e9rience du d\u00e9veloppement web et du travail avec React.<\/p>\n<p>Toutefois, ces choix pr\u00e9sentaient aussi des inconv\u00e9nients :<\/p>\n<ul>\n<li>Le Chromium Embedded Framework est connu pour sa consommation de ressources. M\u00eame en veille, JetBrains Toolbox App utilisait au moins 200 Mio de RAM. Nous ne pouvions pas non plus d\u00e9charger l&#8217;ensemble du framework lorsque la fen\u00eatre \u00e9tait invisible, car cela aurait entra\u00een\u00e9 un d\u00e9lai de plusieurs secondes pour toute interaction avec l&#8217;application.<\/li>\n<li>Nous avions besoin d&#8217;une architecture client-serveur compl\u00e8te dans une seule application de bureau. L&#8217;interface utilisateur web int\u00e9gr\u00e9e et la logique m\u00e9tier avaient \u00e9t\u00e9 \u00e9crites dans des langages diff\u00e9rents et par des personnes diff\u00e9rentes. Cela compliquait le processus de d\u00e9veloppement et obligeait les ressources \u00e0 envoyer des m\u00e9gaoctets de JSON dans les deux sens \u00e0 l&#8217;int\u00e9rieur de l&#8217;application, en utilisant les ressources du processeur pour la (d\u00e9)s\u00e9rialisation de donn\u00e9es d\u00e9j\u00e0 pr\u00e9sentes.<\/li>\n<\/ul>\n<p>Apr\u00e8s le passage de notre application en 100\u00a0% Kotlin, la situation s&#8217;est nettement am\u00e9lior\u00e9e :<\/p>\n<ul>\n<li>Compose for Desktop est d\u00e9sormais beaucoup moins gourmand en ressources. Le framework Compose offre de meilleures performances d&#8217;ex\u00e9cution par rapport \u00e0 notre impl\u00e9mentation JavaScript et a permis de r\u00e9duire consid\u00e9rablement la RAM utilis\u00e9e par l&#8217;application lors de l&#8217;ex\u00e9cution inactive en arri\u00e8re-plan.<\/li>\n<li>L&#8217;utilisation d&#8217;un langage unique permet \u00e0 chaque d\u00e9veloppeur de pouvoir cr\u00e9er une fonctionnalit\u00e9 du d\u00e9but \u00e0 la fin sans avoir \u00e0 changer de contexte. Le d\u00e9veloppement est plus rapide, moins sujet aux erreurs, et le partage des connaissances entre les d\u00e9veloppeurs s&#8217;en trouve am\u00e9lior\u00e9. L&#8217;ensemble de l&#8217;application utilise la m\u00eame repr\u00e9sentation pour les donn\u00e9es en m\u00e9moire, ce qui \u00e9vite les \u00e9tapes suppl\u00e9mentaires de (d\u00e9)s\u00e9rialisation.<\/li>\n<\/ul>\n<h3>Pouvez-vous partager votre exp\u00e9rience concernant l&#8217;introduction de Kotlin dans Toolbox App ?<\/h3>\n<p>Nous avons \u00e9t\u00e9 confront\u00e9s \u00e0 de nombreux d\u00e9fis. Tout d&#8217;abord, nous devions migrer une base de code vieille de cinq ans, avec toutes ses fonctionnalit\u00e9s et ses particularit\u00e9s, vers une pile diff\u00e9rente. Pour garantir le bon fonctionnement du noyau de notre application, nous avons migr\u00e9 tous nos tests unitaires. Notre application requiert toutefois de nombreuses d\u00e9pendances externes, qui varient \u00e9videmment selon les \u00e9cosyst\u00e8mes. Certaines parties dysfonctionnelles dans l&#8217;impl\u00e9mentation pr\u00e9c\u00e9dente ont commenc\u00e9 \u00e0 fonctionner dans la nouvelle sans aucune autre action de notre part, simplement parce que la nouvelle d\u00e9pendance les prenait en charge. A l&#8217;inverse, d&#8217;autres composants que nous tenions pour acquis ont cess\u00e9 de fonctionner. Dans certains cas, nous n&#8217;avons eu connaissance de ces diff\u00e9rences qu&#8217;apr\u00e8s la publication. Les diff\u00e9rents aspects de l&#8217;int\u00e9gration d&#8217;un syst\u00e8me d&#8217;exploitation illustrent ces deux cas de figure, avec par exemple l&#8217;ic\u00f4ne de la barre d&#8217;\u00e9tat syst\u00e8me (menubar) ou les serveurs proxy et les certificats SSL. D&#8217;autre part, nous avons pu r\u00e9utiliser le code Kotlin \u00e9crit par d&#8217;autres \u00e9quipes de JetBrains, comme le code qui r\u00e9git la recherche de projets dans IntelliJ IDEA, r\u00e9utilis\u00e9 dans l&#8217;onglet \u00ab\u00a0<em>Projets<\/em>\u00a0\u00bb de Toolbox App, ou la d\u00e9tection de configurations sp\u00e9cifiques de Toolbox App utilis\u00e9es par les entreprises.<\/p>\n<p>Nous avons commenc\u00e9 \u00e0 utiliser Compose for Desktop avant m\u00eame qu&#8217;il ne soit annonc\u00e9 publiquement et avons donc souvent \u00e9t\u00e9 les premiers \u00e0 rencontrer les probl\u00e8mes qui se posaient avec le framework. En tant que pionniers de Compose for Desktop, nous avons constat\u00e9 toutes sortes de probl\u00e8mes \u00e0 nos d\u00e9buts, et nous les avons tous signal\u00e9s \u00e0 nos coll\u00e8gues de l&#8217;\u00e9quipe Compose Multiplatform. L&#8217;\u00e9quipe s&#8217;est montr\u00e9e tr\u00e8s efficace et r\u00e9active, et tous les probl\u00e8mes ont \u00e9t\u00e9 r\u00e9gl\u00e9s tr\u00e8s rapidement. Nous avons parfois pu obtenir une nouvelle version avec un correctif le jour-m\u00eame&#8230; Tr\u00e8s impressionnant ! Ils nous ont \u00e9galement beaucoup aid\u00e9 lors de l&#8217;adoption de Compose et dans les cas o\u00f9 nous avions des difficult\u00e9s avec le framework.<\/p>\n<p>Nous avons pu r\u00e9aliser un clone complet de notre design pr\u00e9c\u00e9dent. \u00c0 premi\u00e8re vue, Compose offre moins de primitives de mise en page que ce que nous avions en HTML\/CSS, mais il est rapidement apparu que de simples empilements horizontaux et verticaux (Row et Column dans Compose) couvraient d\u00e9j\u00e0 99 % de tous nos besoins. Lorsque nous avons commenc\u00e9, il manquait encore quelques \u00e9l\u00e9ments \u00e0 Compose for Desktop, comme la prise en charge des graphiques SVG, mais nos coll\u00e8gues de l&#8217;\u00e9quipe Compose nous ont aid\u00e9s \u00e0 couvrir ces besoins tr\u00e8s rapidement.<\/p>\n<p>Au d\u00e9part, nous avons utilis\u00e9 les composants mat\u00e9riels de Compose dans toute l&#8217;application. Ces composants sont tr\u00e8s bien pens\u00e9s, mais ils ciblent essentiellement les interfaces tactiles. Les \u00e9l\u00e9ments ont de marges importantes (afin de pouvoir les activer facilement avec le doigt), n&#8217;ont pas d&#8217;\u00e9tats de survol (\u00e9tant donn\u00e9 qu&#8217;il n&#8217;y en a pas sur les \u00e9crans tactiles) et ont un retour visuel tactile tr\u00e8s visible. Or sur un ordinateur de bureau, les composants r\u00e9agissent lorsqu&#8217;ils sont survol\u00e9s et le retour visuel pour les clics ne concerne que l&#8217;\u00e9l\u00e9ment en cours (car il n&#8217;est pas couvert par un doigt). Nous avons donc remplac\u00e9 les composants mat\u00e9riels par les n\u00f4tres, qui fonctionnent mieux sur ordinateur de bureau. Nous pr\u00e9voyons \u00e9galement de donner libre acc\u00e8s \u00e0 notre biblioth\u00e8que de composants \u00e0 l&#8217;avenir, alors restez \u00e0 l&#8217;\u00e9coute.<\/p>\n<h3>Avant de choisir Compose for Desktop, avez-vous envisag\u00e9 d&#8217;utiliser d&#8217;autres frameworks d&#8217;interface utilisateur ?<\/h3>\n<p>Une alternative aurait \u00e9t\u00e9 de convertir l&#8217;application en une interface enti\u00e8rement native, mais cela aurait demand\u00e9 trois fois plus d&#8217;efforts pour chaque fonctionnalit\u00e9. Nous voulions quelque chose de multiplateforme, esth\u00e9tique et parfaitement compatible avec Kotlin.<\/p>\n<p>Nous avons estim\u00e9 que Swing \u00e9tait trop vieux et que l&#8217;utilisation de JavaFX n&#8217;\u00e9tait pas suffisamment r\u00e9pandue. C&#8217;est pourquoi nous avons finalement opt\u00e9 pour Compose for Desktop, m\u00eame s&#8217;i venait tout juste de sortir \u00e0 l&#8217;\u00e9poque. L&#8217;assistance directe de la part de l&#8217;\u00e9quipe et la boucle de r\u00e9troaction \u00e9troite se sont \u00e9galement av\u00e9r\u00e9s \u00eatre de gros avantages.<\/p>\n<h3>Quels sont les principaux avantages que Kotlin a apport\u00e9s \u00e0 votre produit ?<\/h3>\n<p>Kotlin a consid\u00e9rablement simplifi\u00e9 notre travail au quotidien. Nous utilisons le m\u00eame langage pour l&#8217;ensemble de l&#8217;application, ce qui permet aux d\u00e9veloppeurs de notre \u00e9quipe de partager le code et les connaissances beaucoup plus facilement qu&#8217;auparavant. Nous avons \u00e9galement beaucoup plus de plaisir \u00e0 \u00e9crire en Kotlin plut\u00f4t qu&#8217;en C++ et en JavaScript !<\/p>\n<h3>Avez-vous des conseils ou des recommandations pour nos lecteurs ?<\/h3>\n<p>Si vous d\u00e9cidez de changer de framework pour une application existante, ne sous-estimez pas la complexit\u00e9 de la migration. C&#8217;est presque comme d&#8217;\u00e9crire une nouvelle application \u00e0 partir de z\u00e9ro ! Vous devrez in\u00e9vitablement r\u00e9impl\u00e9menter non seulement les fonctionnalit\u00e9s, mais aussi toutes les petites nuances dans le comportement de votre application, qu&#8217;elles soient intentionnelles ou non.<\/p>\n<p>Je crois fermement que Compose for Desktop est la solution id\u00e9ale pour cr\u00e9er des applications multiplateforme pour ordinateurs de bureau. Par rapport aux technologies similaires, Kotlin donne acc\u00e8s \u00e0 un \u00e9cosyst\u00e8me \u00e9prouv\u00e9 sur la JVM, son adoption est bien plus importante que celle de Dart et Flutter, et il est bien plus efficace qu&#8217;Electron avec React\/JS.<\/p>\n<p align=\"center\"><a class=\"ek-link jb-download-button\" title=\"CTA\" href=\"https:\/\/www.jetbrains.com\/fr-fr\/lp\/compose-desktop\/\" target=\"_blank\" rel=\"noopener\">Cr\u00e9ez votre premi\u00e8re application de bureau avec Compose for Desktop<\/a><\/p>\n<p><a class=\"ek-link\" href=\"https:\/\/twitter.com\/kropp\" target=\"_blank\" rel=\"noopener\">Victor Kropp<\/a> est Responsable de l&#8217;\u00e9quipe JetBrains Toolbox App.<\/p>\n\n\n<p><em>Auteur de l&#8217;article original en anglais<\/em> : <\/p>\n\n\n    <div class=\"about-author \">\n        <div class=\"about-author__box\">\n            <div class=\"row\">\n                <div class=\"about-author__box-img\">\n                    <img decoding=\"async\" src=\"https:\/\/secure.gravatar.com\/avatar\/?s=200&#038;r=g\" width=\"200\" height=\"200\" alt=\"\" loading=\"lazy\"  class=\"avatar avatar-200 wp-user-avatar wp-user-avatar-200 photo avatar-default\">\n                <\/div>\n                <div class=\"about-author__box-text\">\n                                                        <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n","protected":false},"author":813,"featured_media":219026,"comment_status":"closed","ping_status":"closed","template":"","categories":[89],"tags":[1433,6481,6706,514,4198],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin\/219023"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/users\/813"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/comments?post=219023"}],"version-history":[{"count":10,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin\/219023\/revisions"}],"predecessor-version":[{"id":219072,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin\/219023\/revisions\/219072"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media\/219026"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media?parent=219023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/categories?post=219023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/tags?post=219023"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/cross-post-tag?post=219023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}