{"id":674421,"date":"2026-01-13T14:08:17","date_gmt":"2026-01-13T13:08:17","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=674421"},"modified":"2026-01-13T14:11:16","modified_gmt":"2026-01-13T13:11:16","slug":"evaluer-kotlin-dans-des-projets-reels","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/fr\/kotlin\/2026\/01\/evaluer-kotlin-dans-des-projets-reels\/","title":{"rendered":"\u00c9valuer Kotlin dans des projets r\u00e9els"},"content":{"rendered":"<p><em>Article de notre invit\u00e9 <a href=\"https:\/\/www.linkedin.com\/in\/urs-peter-70a2882\/\" target=\"_blank\" rel=\"noreferrer noopener\" data-type=\"link\" data-id=\"https:\/\/bit.ly\/urs-peter-linked-in\">Urs Peter<\/a>, Ing\u00e9nieur logiciel senior et Formateur Kotlin certifi\u00e9 JetBrains. Pour les lecteurs qui souhaitent une approche plus structur\u00e9e pour d\u00e9velopper leurs comp\u00e9tences en Kotlin, Urs anime \u00e9galement le <\/em><a href=\"https:\/\/academy.xebia.com\/upskilling\/kotlin-academy\/\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Kotlin Upskill Program<\/em><\/a><em>\u00a0\u00e0 la Xebia Academy.<\/em><\/p>\n<p><em>Ceci est le deuxi\u00e8me article du <\/em><strong><em>Guide complet pour r\u00e9ussir l&#8217;adoption de Kotlin dans un environnement Java<\/em><\/strong><em>, qui explique concr\u00e8tement comment l&#8217;adoption de Kotlin peut \u00eatre progressivement d\u00e9ploy\u00e9e au sein d&#8217;une \u00e9quipe, en partant de la curiosit\u00e9 d&#8217;un d\u00e9veloppeur pour aboutir \u00e0 une transformation \u00e0 l&#8217;\u00e9chelle de l&#8217;entreprise.<\/em><\/p>\n<p>Lire la premi\u00e8re partie\u00a0: <a href=\"https:\/\/blog.jetbrains.com\/fr\/kotlin\/2026\/01\/premiers-pas-avec-kotlin-pour-les-developpeurs-java\/\" target=\"_blank\" rel=\"noreferrer noopener\">Premiers pas avec Kotlin pour les d\u00e9veloppeurs Java<\/a><\/p>\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n<h2 class=\"wp-block-heading\"><strong>L&#8217;\u00e9tape d&#8217;\u00e9valuation\u00a0: au-del\u00e0 de l&#8217;exp\u00e9rimentation avec Kotlin<\/strong><\/h2>\n<p>Une fois que vous \u00eates \u00e0 l&#8217;aise avec Kotlin dans les tests, il est temps de proc\u00e9der \u00e0 une \u00e9valuation plus substantielle. Pour cela, il y deux principales approches\u00a0:<\/p>\n<ol>\n<li><a href=\"#1.-build-a-new-microservice\/application-in-kotlin\" data-type=\"link\" data-id=\"https:\/\/blog.jetbrains.com\/#1.-build-a-new-microservice\/application-in-kotlin\">Cr\u00e9er un microservice \/ une application en Kotlin<\/a><\/li>\n<li><a href=\"#2.-extend\/convert-an-existing-java-application\" data-type=\"link\" data-id=\"https:\/\/blog.jetbrains.com\/#2.-extend\/convert-an-existing-java-application\">\u00c9tendre \/ convertir une application Java existante<\/a><\/li>\n<\/ol>\n<h3 id=\"1.-build-a-new-microservice\/application-in-kotlin\" class=\"wp-block-heading\"><strong>1. Cr\u00e9er un microservice \/ une application en Kotlin<\/strong><\/h3>\n<p>Cr\u00e9er une application ou un microservice \u00e0 partir de z\u00e9ro vous apporte l&#8217;exp\u00e9rience Kotlin compl\u00e8te, sans les contraintes d&#8217;un code h\u00e9rit\u00e9. Cette approche offre souvent la meilleure exp\u00e9rience d&#8217;apprentissage et c&#8217;est celle qui d\u00e9montre le plus clairement les points forts de Kotlin.<\/p>\n<div class=\"wp-block-columns is-layout-flex wp-container-3 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis: 66.66%;\">\n<p><strong>Astuce de pro<\/strong>\u00a0: demandez l&#8217;aide d&#8217;experts \u00e0 ce stade. Bien que les d\u00e9veloppeurs soient naturellement confiants dans leurs capacit\u00e9s, \u00e9viter les erreurs de d\u00e9butant comme \u00e9crire du code Kotlin dans le style Java ou ne pas utiliser les biblioth\u00e8ques Kotlin natives peut vous \u00e9pargner des mois de dette technique.<\/p>\n<\/div>\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis: 33.33%;\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-646384\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/10\/unnamed-5.png\" alt=\"\" width=\"600\" height=\"400\" \/><\/figure>\n<\/div>\n<\/div>\n<p>Si vous \u00eates un d\u00e9veloppeur Java, voici comment \u00e9viter les pi\u00e8ges courants lorsque vous utilisez Kotlin :<\/p>\n<p><em>Pi\u00e8ge\u00a0: choisir un autre framework que celui que vous utilisez en Java.<\/em><\/p>\n<p>Astuce\u00a0: <strong>gardez votre framework actuel<\/strong>.\u00a0<\/p>\n<p>Vous utilisiez probablement Spring Boot avec Java, alors utilisez-le aussi avec Kotlin. La prise en charge de Spring Boot pour Kotlin est de premier ordre, il n&#8217;y a donc pas d&#8217;int\u00e9r\u00eat particulier \u00e0 utiliser autre chose. De plus, cela vous obligerait \u00e0 apprendre un nouveau framework en plus d&#8217;un nouveau langage, ce qui ne ferait qu&#8217;ajouter de la complexit\u00e9 sans offrir aucun avantage.<\/p>\n<p><strong>Important<\/strong>\u00a0: Spring interf\u00e8re avec le principe de \u00ab\u00a0l&#8217;h\u00e9ritage par conception\u00a0\u00bb de Kotlin, qui requiert de marquer explicitement les classes comme ouvertes pour pouvoir les \u00e9tendre.<\/p>\n<p>Afin de ne pas avoir \u00e0 ajouter le mot-cl\u00e9 \u00ab\u00a0open\u00a0\u00bb \u00e0 toutes les classes li\u00e9es \u00e0 Spring (comme <code>@Configuration<\/code>, etc.), utilisez le plugin de build suivant\u00a0: <a href=\"https:\/\/kotlinlang.org\/docs\/all-open-plugin.html#spring-support\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/kotlinlang.org\/docs\/all-open-plugin.html#spring-support<\/a>. Si vous cr\u00e9ez un projet Spring avec l&#8217;outil en ligne bien connu <a href=\"https:\/\/start.spring.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Spring initializr<\/a>, ce plugin de build est d\u00e9j\u00e0 configur\u00e9 pour vous.<\/p>\n<p><em>Pi\u00e8ge\u00a0: \u00e9crire du Kotlin \u00e0 la mani\u00e8re de Java, en s&#8217;appuyant sur les API Java courantes plut\u00f4t que sur la biblioth\u00e8que standard de Kotlin.<\/em><\/p>\n<p>Cette liste peut \u00eatre tr\u00e8s longue, concentrons-nous donc sur les pi\u00e8ges les plus courants\u00a0:<\/p>\n<h4 class=\"wp-block-heading\"><em>Pi\u00e8ge\u00a01\u00a0: utiliser Java Streams plut\u00f4t que Kotlin Collections<\/em><\/h4>\n<p>Astuce\u00a0: <strong>utilisez toujours les collections Kotlin.<\/strong><\/p>\n<p>Les collections Kotlin sont enti\u00e8rement interop\u00e9rables avec les collections Java et fournissent des fonctions d&#8217;ordre sup\u00e9rieur concises et riches en fonctionnalit\u00e9s, \u00e9liminant ainsi le besoin de stream Java.\u00a0<\/p>\n<p>Voici un exemple qui vise \u00e0 s\u00e9lectionner les 3\u00a0produits qui g\u00e9n\u00e8rent le plus de chiffre d&#8217;affaires (prix * quantit\u00e9 vendue) regroup\u00e9s par cat\u00e9gorie de produits\u00a0:<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">record Product(String name, String category, double price, int sold){}\n\nList products = List.of(\n           new Product(\"Lollipop\", \"sweets\", 1.2, 321),\n           new Product(\"Broccoli\", \"vegetable\", 1.8, 5);\n\nMap&lt;String, List&gt; top3RevenueByCategory =\n       products.stream()\n          .collect(Collectors.groupingBy(\n                Product::category,\n                Collectors.collectingAndThen(\n                    Collectors.toList(),\n                    list -&gt; list.stream()\n                              .sorted(Comparator.comparingDouble(\n                                  (Product p) -&gt; p.price() * p.sold())\n                                   .reversed())\n                                   .limit(3)\n                                   .toList()\n                       \t\t)\n          )\n);<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val top3RevenueByCategory: Map&lt;String, List&gt; =\n   products.groupBy { it.category }\n       .mapValues { (_, list) -&gt;\n           list.sortedByDescending { it.price * it.sold }.take(3)\n       }<\/pre>\n<p>L&#8217;interop\u00e9rabilit\u00e9 de Kotlin avec Java vous permet de travailler avec des classes et des records Java comme s&#8217;ils \u00e9taient natifs de Kotlin, bien que vous puissiez \u00e9galement utiliser une classe (data) Kotlin \u00e0 la place.<\/p>\n<h4 class=\"wp-block-heading\"><em>Pi\u00e8ge\u00a02\u00a0: continuer \u00e0 utiliser les types optional de Java.<\/em><\/h4>\n<p>Astuce\u00a0: <strong>adoptez les types nullables<\/strong>.\u00a0<\/p>\n<p>L&#8217;une des principales raisons pour lesquelles les d\u00e9veloppeurs Java passent \u00e0 Kotlin est la prise en charge de la nullabilit\u00e9 int\u00e9gr\u00e9e \u00e0 Kotlin. Adieu les NullPointerExceptions\u00a0! Essayez donc d&#8217;utiliser uniquement des types nullables, et plus de ne plus utiliser types optionnels. Avez-vous encore des types optionnels dans vos interfaces ? Voici comment vous en d\u00e9barrasser facilement en les convertissant en types nullables\u00a0:<\/p>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/Let\u2019s assume this repository is hard to change, because it\u2019s a library you depend on\nclass OrderRepository {\n      \/\/it returns Optional, but we want nullable types\n      fun getOrderBy(id: Long): Optional = \u2026\n}\n\n\/\/Simply add an extension method and apply the orElse(null) trick\nfun OrderRepository.getOrderByOrNull(id: Long): Order? = \n                                    getOrderBy(id).orElse(null)\n\n\/\/Now enjoy the safety and ease of use of nullable types:\n\n\/\/Past:\n val g = repository.getOrderBy(12).flatMap { product -&gt;\n     product.goody.map { it.name }\n}.orElse(\"No goody found\")\n\n\/\/Future:\n val g = repository.getOrderByOrNull(12)?.goody?.name ?: \"No goody found\"<\/pre>\n<h4 class=\"wp-block-heading\"><em>Pi\u00e8ge\u00a03\u00a0: continuer \u00e0 utiliser des wrappers statiques.<\/em><\/h4>\n<p>Astuce\u00a0: <strong>adoptez les m\u00e9thodes d&#8217;extension<\/strong>.\u00a0<\/p>\n<p>Les m\u00e9thodes d&#8217;extension vous apportent de nombreux avantages\u00a0:<\/p>\n<ul>\n<li>Elles rendent votre code beaucoup plus fluide et lisible que les wrappers.<\/li>\n<li>Vous pouvez les trouver \u00e0 l&#8217;aide de la saisie semi-automatique du code, ce qui n&#8217;est pas le cas pour les wrappers.<\/li>\n<li>Comme les extensions doivent \u00eatre import\u00e9es, elles vous permettent d&#8217;utiliser de fa\u00e7on s\u00e9lective des fonctionnalit\u00e9s \u00e9tendues dans une section sp\u00e9cifique de votre application.<\/li>\n<\/ul>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/Very common approach in Java to add additional helper methods\npublic class DateUtils {\n      public static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = \n           DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss\");\n\n      public String formatted(LocalDateTime dateTime, \n\t\t              DateTimeFormatter formatter) {\n         return dateTime.format(formatter);\n      }\n\n      public String formatted(LocalDateTime dateTime) {\n         return formatted(dateTime, DEFAULT_DATE_TIME_FORMATTER);\n      }\n}\n\n\/\/Usage\n formatted(LocalDateTime.now());\n<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">val DEFAULT_DATE_TIME_FORMATTER: DateTimeFormatter = \nDateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss\")\n\n\/\/Use an extension method, including a default argument, which omits the need for an overloaded method.\u00a0\nfun LocalDateTime.asString(\n\u00a0\u00a0\u00a0formatter: DateTimeFormatter = DEFAULT_DATE_TIME_FORMATTER): String =\u00a0\n      this.format(formatter)\n\n\/\/Usage\nLocalDateTime.now().formatted()<\/pre>\n<p>Notez que Kotlin propose des m\u00e9thodes et variables de niveau sup\u00e9rieur. Cela implique que nous pouvons simplement d\u00e9clarer le <em><code>DEFAULT_DATE_TIME_FORMATTER<\/code><\/em> au niveau sup\u00e9rieur sans avoir besoin de le lier \u00e0 un objet comme c&#8217;est le cas en Java, par exemple.<\/p>\n<h4 class=\"wp-block-heading\"><em>Pi\u00e8ge\u00a04\u00a0: Utiliser les API Java (de mani\u00e8re maladroite)<\/em><\/h4>\n<p>Astuce\u00a0: <strong>utilisez l&#8217;alternative \u00e9l\u00e9gante de Kotlin.\u00a0<\/strong><\/p>\n<p>La biblioth\u00e8que standard Kotlin utilise des m\u00e9thodes d&#8217;extension pour am\u00e9liorer la convivialit\u00e9 des biblioth\u00e8ques Java, m\u00eame si l&#8217;impl\u00e9mentation sous-jacente reste en Java. Presque toutes les biblioth\u00e8ques et tous les frameworks majeurs tiers, comme Spring, ont fait de m\u00eame.<\/p>\n<p><strong>Exemple de la biblioth\u00e8que standard\u00a0:<\/strong><\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">String text;\ntry (\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var reader = new BufferedReader(\n                  new InputStreamReader(new FileInputStream(\"out.txt\"), \n            StandardCharsets.UTF_8))) {\n\u00a0\u00a0\u00a0text = reader\n            .lines()\n            .collect(Collectors.joining(System.lineSeparator()));\n}\nSystem.out.println(\"Downloaded text: \" +\u00a0 text + \"n\");<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/Kotlin has enhanced the Java standard library with many powerful extension methods, like on java.io.*, which makes input stream processing a snap due to its fluent nature, fully supported by code completion\n\nval text = FileInputStream(\"path\").use {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0     it.bufferedReader().readText()\n           }\nprintln(\"Downloaded text: $textn\");<\/pre>\n<p><strong>Exemple de Spring<\/strong>\u00a0: <br \/><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">final var books =\u00a0 RestClient.create()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.get()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.uri(\"http:\/\/...\/api\/books\")\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.retrieve()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.body( new ParameterizedTypeReference&lt;List&gt;(){}); \/\/ \u21e6 inconvenient ParameterizedTypeReference<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import org.springframework.web.client.body\nval books = RestClient.create()\n\u00a0\u00a0\u00a0.get()\n\u00a0\u00a0\u00a0.uri(\"http:\/\/...\/api\/books\")\n\u00a0\u00a0\u00a0.retrieve()\n\u00a0\u00a0\u00a0.body&lt;List&gt;() \/\/\u21e6 Kotlin offers an extension that only requires the type without the need for a ParameterizedTypeReference<\/pre>\n<h4 class=\"wp-block-heading\"><em>Pi\u00e8ge\u00a05\u00a0: utiliser un fichier s\u00e9par\u00e9 pour chaque classe publique<\/em><\/h4>\n<p>Astuce\u00a0: <strong>combinez des classes publiques connexes dans un m\u00eame fichier.\u00a0<\/strong><\/p>\n<p>Cela vous permet de bien comprendre comment un (sous-)domaine est structur\u00e9 sans avoir \u00e0 naviguer dans des dizaines de fichiers.<\/p>\n<p><strong>Java<\/strong><\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-647331\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/10\/unnamed-15.png\" alt=\"\" width=\"1114\" height=\"934\" \/><\/figure>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/For domain classes consider data classes - see why below\ndata class User(val email: String,\n            \/\/Use nullable types for safety and expressiveness\n\u00a0 \u00a0        val avatarUrl: URL? = null,\u00a0\n           var isEmailVerified: Boolean)\n\ndata class Account(val user:User,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val address: Address,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val mfaEnabled:Boolean,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val createdAt: Instant)\n\ndata class Address(val street: String,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val city: String,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 val postalCode: String)<\/pre>\n<h4 class=\"wp-block-heading\"><em>Pi\u00e8ge\u00a06\u00a0: s&#8217;appuyer sur le paradigme de programmation mutable<\/em><\/h4>\n<p>Astuce\u00a0: <strong>adoptez l&#8217;immutabilit\u00e9, le comportement par d\u00e9faut en Kotlin<\/strong><\/p>\n<p>La tendance dans de nombreux langages de programmation (y compris en Java) est claire\u00a0: l&#8217;immutabilit\u00e9 l&#8217;emporte sur la mutabilit\u00e9.\u00a0<\/p>\n<p>La raison est simple\u00a0: l&#8217;immutabilit\u00e9 emp\u00eache les effets secondaires impr\u00e9vus, ce qui rend le code plus s\u00fbr, plus pr\u00e9visible et plus facile \u00e0 comprendre. Elle simplifie \u00e9galement la concurrence, car les donn\u00e9es immuables peuvent \u00eatre partag\u00e9es librement entre les threads sans risque des conditions de concurrence.<\/p>\n<p>C&#8217;est pourquoi la plupart des langages modernes, et notamment Kotlin, mettent l&#8217;accent sur l&#8217;immutabilit\u00e9 par d\u00e9faut ou l&#8217;encouragent fortement. En Kotlin, l&#8217;immutabilit\u00e9 est le comportement par d\u00e9faut, bien que la mutabilit\u00e9 reste possible si elle est r\u00e9ellement n\u00e9cessaire.<\/p>\n<p>Voici un guide rapide des <strong>puissant pack d&#8217;immutabilit\u00e9<\/strong> de Kotlin\u00a0:<\/p>\n<p>1. Utilisez <code>val<\/code> plut\u00f4t que <code>var<\/code><\/p>\n<p>Pr\u00e9f\u00e9rez <code>val<\/code> \u00e0 <code>var<\/code>. IntelliJ IDEA vous notifiera si vous avez utilis\u00e9 une <code>var<\/code> pour laquelle une <code>val<\/code> pourrait \u00eatre utilis\u00e9e.\u00a0<\/p>\n<p>2. Utilisez des classes de donn\u00e9es (immuables) avec <code>copy(\u2026)<\/code><\/p>\n<p>Pour les classes li\u00e9es au domaine, utilisez des classes <code>data<\/code> avec <code>val<\/code>. Les classes <code>data<\/code> de Kotlin sont souvent compar\u00e9es aux <code>records<\/code> de Java. Bien qu&#8217;il y ait un certain chevauchement, les classes <code>data<\/code> offrent la fonctionnalit\u00e9 <code>copy(\u2026)<\/code>, dont l&#8217;absence rend la transformation de <code>record<\/code>, souvent requise dans la logique m\u00e9tier, si fastidieuse\u00a0:<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/only immutable state\npublic record Person(String name, int age) {\n\u00a0\u00a0\u00a0\/\/Lack of default parameters requires overloaded constructor\n\u00a0\u00a0\u00a0public Person(String name) {\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(name, 0);\n\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\/\/+ due to lack of String interpolation\n\u00a0 public String sayHi() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return \"Hello, my name is \" + name + \" and I am \" + age + \" years old.\";\n\u00a0\u00a0\u00a0}\n}\n\n\/\/Usage\nfinal var jack = new Person(\"Jack\", 42);\njack: Person[name=Jack, age=5]\n\n\/\/The issue is here: transforming a record requires manually copying the identical state to the new instance \u2639\ufe0f\nfinal var fred = new Person(\"Fred\", jack.name);<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/also supports mutable state (var)\ndata class Person(val name: String,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val age: Int = 0) {\n\u00a0 \/\/string interpolation\n\u00a0 fun sayHi() = \"Hi, my name is $name and I am $age years old.\"\n}\nval jack = Person(\"Jack\", 42)\njack: Person(name=Jack, age=42)\n\n\/\/Kotlin offers the copy method, which, due to the \u2018named argument\u2019 feature, allows you to only adjust the state you want to change \ud83d\ude03\nval fred = jack.copy(name = \"Fred\")\nfred: Person(name=Fred, age=42)<\/pre>\n<p>De plus, vous devriez utiliser des classes de donn\u00e9es pour les classes li\u00e9es au domaine chaque fois que possible. Leur nature immuable garantit une exp\u00e9rience s\u00fbre, concise et fluide lorsque vous travaillez avec le c\u0153ur de votre application.\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<p>Astuce\u00a0: <strong>pr\u00e9f\u00e9rez les collections immuables aux collections mutables<\/strong><\/p>\n<p>Les collections immuables pr\u00e9sentent des avantages clairs en mati\u00e8re de s\u00e9curit\u00e9 des threads, peuvent \u00eatre transmises en toute s\u00e9curit\u00e9 et sont plus faciles \u00e0 appr\u00e9hender. Bien que Java offre certaines fonctionnalit\u00e9s d&#8217;immutabilit\u00e9 pour les collections, leur utilisation est dangereuse, car elle provoque facilement des exceptions lors de l&#8217;ex\u00e9cution\u00a0:<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">List.of(1,2,3).add(4); \u274cunsafe \ud83d\ude2c! .add(...) compiles, but throws UnsupportedOperationException<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/The default collections in Kotlin are immutable (read-only)\nlistOf(1,2,3).add(4); \u00a0\/\/\u2705safe: does not compile\n\nval l0 = listOf(1,2,3)\u00a0\nval l1 = l0 + 4 \/\/\u2705safe: it will return a new list containing the added element\nl1 shouldBe listOf(1,2,3,4) \/\/\u2705<\/pre>\n<p>Il en va de m\u00eame pour l&#8217;utilisation de <code>Collections<em>.unmodifiableList(\u2026)<\/em><\/code>, qui est non seulement peu s\u00fbre, mais requiert \u00e9galement une allocation suppl\u00e9mentaire\u00a0:<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class PersonRepo {\n\u00a0\u00a0\u00a0private final List cache = new ArrayList();\n\u00a0\u00a0\u00a0\/\/ Java \u2013 must clone or wrap every call\n\u00a0\u00a0\u00a0public List getItems() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Collections.unmodifiableList(cache); \u00a0 \/\/\u26a0\ufe0fextra alloc\n\u00a0\u00a0\u00a0}\n}\n\n\/\/Usage\npersonRepo.getItems().add(joe) \u274cunsafe \ud83d\ude2c! .add(...) can be called but throws UnsupportedOperationException<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class PersonRepo {\n\n\/\/The need to type \u2018mutable\u2019 for mutable collections is intentional: Kotlin wants you to use immutable ones by default. But sometimes you need them:\n\n\u00a0\u00a0\u00a0private val cache: MutableList = mutableListOf()\n\n\u00a0\u00a0\u00a0fun items(): List = cache \/\/\u2705safe: though the underlying collection is mutable, by returning it as its superclass List, it only exposes the read-only interface\n\n}\n\n\/\/Usage\npersonRepo.items().add(joe) \/\/\u2705safe:\ud83d\ude2c! Does not compile<\/pre>\n<p>En mati\u00e8re de concurrence, il est pr\u00e9f\u00e9rable d&#8217;utiliser des structures de donn\u00e9es immuables, notamment les collections. En Java, des efforts suppl\u00e9mentaires sont n\u00e9cessaires avec les collections sp\u00e9ciales, qui offrent une API diff\u00e9rente ou limit\u00e9e, telles que <code>CopyOnWriteArrayList<\/code>. Avec Kotlin, en revanche, la <code>List<\/code> en lecture seule fonctionne pour presque tous les cas d&#8217;utilisation.\u00a0<\/p>\n<p>Si vous avez besoin de collections modifiables et s\u00fbres pour les threads, Kotlin propose des collections persistantes (<code>persistentListOf(...)<\/code>, <code>persistentMapOf(...)<\/code>), qui partagent toutes la m\u00eame interface puissante.<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ConcurrentHashMap persons = new ConcurrentHashMap();\npersons.put(\"Alice\", 23);\npersons.put(\"Bob\", \u00a0 21);\n\n\/\/not fluent and data copying going on\nMap incPersons = new HashMap(persons.size());\npersons.forEach((k, v) -&gt; incPersons.put(k, v + 1));\n\n\/\/wordy and data copying going on\npersons\n\u00a0\u00a0\u00a0.entrySet()\n\u00a0\u00a0\u00a0.stream()\n\u00a0\u00a0\u00a0.forEach(entry -&gt;\u00a0\n      entry.setValue(entry.getValue() + 1));<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">persistentMapOf(\"Alice\" to 23, \"Bob\" to 21)\n\u00a0\u00a0\u00a0      .mapValues { (key, value) -&gt; value + 1 } \/\/\u2705same rich API like any other Kotlin Map type and not data copying going on<\/pre>\n<h4 class=\"wp-block-heading\"><em>Pi\u00e8ge\u00a07\u00a0: continuer \u00e0 utiliser des constructeurs (ou pire encore\u00a0: essayer d&#8217;utiliser Lombok)\u00a0<\/em><\/h4>\n<p>Astuce\u00a0: <strong>utilisez des arguments nomm\u00e9s.<\/strong><\/p>\n<p>Les constructeurs sont tr\u00e8s courants en Java. Bien qu&#8217;ils soient pratiques, ils rajoutent du code, sont peu s\u00fbrs et augmentent la complexit\u00e9. En Kotlin, ils sont inutiles, car une simple fonctionnalit\u00e9 du langage les remplace\u00a0: les arguments nomm\u00e9s.\u00a0<\/p>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public record Person(String name, int age) {\n\n\u00a0\u00a0\u00a0\/\/ Builder for Person\n\u00a0\u00a0\u00a0public static class Builder {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private String name;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private int age;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Builder() {}\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Builder name(String name) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.name = name;\n\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return this;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Builder age(int age) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.age = age;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return this;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Person build() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return new Person(name, age);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0}\n}\n\n\/\/Usage\nnew JPerson.Builder().name(\"Jack\").age(36).build(); \/\/compiles and succeeds at runtime\n\nnew JPerson.Builder().age(36).build(); \/\/\u274cunsafe \ud83d\ude2c: compiles but fails at runtime.<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">data class Person(val name: String, val age: Int = 0)\n\n\/\/Usage - no builder, only named arguments.\nPerson(name = \"Jack\") \/\/\u2705safe: if it compiles, it always succeeds at runtime\nPerson(name = \"Jack\", age = 36) \/\/\u2705<\/pre>\n<h3 id=\"2.-extend\/convert-an-existing-java-application\" class=\"wp-block-heading\"><strong>2. \u00c9tendre \/ convertir une application Java existante<\/strong><\/h3>\n<p>Si vous n&#8217;avez pas la possibilit\u00e9 d&#8217;utiliser Kotlin dans un projet enti\u00e8rement nouveau, <a href=\"https:\/\/www.jetbrains.com\/help\/idea\/get-started-with-kotlin.html#add-kotlin-dependency\" target=\"_blank\" rel=\"noreferrer noopener\">l&#8217;ajout de nouvelles fonctionnalit\u00e9s Kotlin ou de modules Kotlin entiers \u00e0 une base de code Java existante<\/a> est la solution. Gr\u00e2ce \u00e0 l&#8217;interop\u00e9rabilit\u00e9 parfaite entre Kotlin et Java, vous pouvez \u00e9crire du code Kotlin qui ressemble \u00e0 du code Java et qui peut \u00eatre appel\u00e9 depuis du code Java. Cette approche permet\u00a0:<\/p>\n<ul>\n<li>Une migration progressive sans r\u00e9\u00e9criture majeure<\/li>\n<li>Des tests en conditions r\u00e9elles de Kotlin dans votre contexte sp\u00e9cifique<\/li>\n<li>Le renforcement de la confiance de l&#8217;\u00e9quipe avec du code Kotlin en production<\/li>\n<\/ul>\n<p>Plut\u00f4t que de commencer <em>au hasard<\/em>, vous pouvez envisager ces approches\u00a0:<\/p>\n<p><strong>De l&#8217;ext\u00e9rieur vers l&#8217;int\u00e9rieur\u00a0:<\/strong><\/p>\n<p>D\u00e9marrez dans la section \u00ab\u00a0feuille\u00a0\u00bb de votre application, par exemple le contr\u00f4leur, la t\u00e2che par lot, etc., puis remontez vers le domaine principal. Cela pr\u00e9sente les avantages suivants\u00a0:\u00a0<\/p>\n<ul>\n<li><strong>Isolation lors de la compilation<\/strong>\u00a0: les classes du niveau feuille ont rarement quelque chose qui d\u00e9pend <em>d&#8217;elles<\/em>, vous pouvez donc les convertir en Kotlin et g\u00e9n\u00e9rer le reste du syst\u00e8me sans modification.<\/li>\n<li><strong>Moins de modifications en cascade.<\/strong> Gr\u00e2ce \u00e0 une interop\u00e9rabilit\u00e9 parfaite, une interface utilisateur ou un contr\u00f4leur converti ne n\u00e9cessite que peu ou pas de modifications lors de l&#8217;appel de code de domaine Java existant.<\/li>\n<li><strong>De plus petites requ\u00eates d&#8217;extraction, des r\u00e9visions plus faciles.<\/strong> Vous pouvez migrer fichier par fichier ou fonctionnalit\u00e9 par fonctionnalit\u00e9.<\/li>\n<\/ul>\n<p><strong>De l&#8217;int\u00e9rieur vers l&#8217;ext\u00e9rieur\u00a0:<\/strong><\/p>\n<p>Commencer par le noyau et progresser ensuite vers les couches externes est g\u00e9n\u00e9ralement une approche plus risqu\u00e9e, car elle \u00e9limine les avantages de l&#8217;approche de l&#8217;ext\u00e9rieur vers l&#8217;int\u00e9rieur mentionn\u00e9e ci-dessus. C&#8217;est toutefois une option viable dans les cas suivants\u00a0:<\/p>\n<ul>\n<li><strong>Noyau tr\u00e8s petit ou autonome.<\/strong> Si votre couche de domaine n&#8217;est compos\u00e9e que d&#8217;une poign\u00e9e de POJO et de services, la basculer t\u00f4t peut \u00eatre \u00e9conomique et d\u00e9bloquer imm\u00e9diatement des constructions idiomatiques (classes de donn\u00e9es, classes de valeurs, hi\u00e9rarchies scell\u00e9es).<\/li>\n<li><strong>R\u00e9architecture d\u00e9j\u00e0 pr\u00e9vue.<\/strong> Si vous pr\u00e9voyez de refactoriser des invariants ou d&#8217;introduire des sch\u00e9mas de DDD (objets de valeur, agr\u00e9gats) lors de votre migration, il peut parfois \u00eatre plus propre de repenser d&#8217;abord le domaine en Kotlin.<\/li>\n<li><strong>Contrats de s\u00e9curit\u00e9 stricts pour les valeurs null.<\/strong> Mettre Kotlin au centre transforme le domaine en une \u00ab\u00a0forteresse null-safe\u00a0\u00bb\u00a0; les couches Java externes peuvent toujours envoyer des valeurs null, mais les limites deviennent explicites et plus faciles \u00e0 contr\u00f4ler.<\/li>\n<\/ul>\n<p><strong>Module par module<\/strong><\/p>\n<ul>\n<li>Si votre architecture est organis\u00e9e par fonctionnalit\u00e9s plut\u00f4t que par couches, et que les modules ont une taille g\u00e9rable, les convertir un par un est une bonne strat\u00e9gie.<\/li>\n<\/ul>\n<p><strong>Fonctionnalit\u00e9s du langage pour convertir du Java en Kotlin<\/strong><\/p>\n<p>Kotlin propose plusieurs fonctionnalit\u00e9s, principalement des annotations, qui permettent \u00e0 votre code Kotlin de se comporter comme du Java natif. Ceci est particuli\u00e8rement utile pour les environnements hybrides dans lesquels Kotlin et Java coexistent au sein de la m\u00eame base de code.<br \/><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Person @JvmOverloads constructor(val name: String,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 var age: Int = 0) {\n\u00a0 companion object {\n\n\u00a0 @JvmStatic\n\u00a0 @Throws(InvalidNameException::class)\n\u00a0 fun newBorn(name: String): Person = if (name.isEmpty())\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw InvalidNameException(\"name not set\")\n\u00a0\u00a0\u00a0\u00a0\u00a0else Person(name, 0)\n\n\u00a0\u00a0\u00a0@JvmField\n\u00a0\u00a0\u00a0val LOG = LoggerFactory.getLogger(KPerson.javaClass)\n\u00a0\u00a0}\n}<\/pre>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/thanks to @JvmOverloads an additional constructor is created, propagating Kotlin\u2019s default arguments to Java\nvar john =\u00a0 new Person(\"John\");\n\n\/\/Kotlin automatically generates getters (val) and setters (var) for Java\njohn.setAge(23);\nvar name = ken.getName();\n\n\/\/@JvmStatic and @JvmField all accessing (companion) object fields and methods as statics in Java\n\n\/\/Without @JvmStatic it would be: Person.Companion.newBorn(...)\nvar ken =\u00a0 Person.newBorn(\"Ken\");\u00a0\n\n\/\/Without @JvmField it would be: Person.Companion.LOG\nPerson.LOG.info(\"Hello World, Ken ;-)\");\n\n\/\/@Throws(...) will put the checked Exception in the method signature \ntry {\n\u00a0 Person ken =\u00a0 Person.newBorn(\"Ken\");\n} catch (InvalidNameException e) {\n\u00a0 \/\/\u2026\n}<\/pre>\n<p><strong>Kotlin<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@file:JvmName(\"Persons\")\npackage org.abc\n\n@JvmName(\"prettyPrint\")\n\nfun Person.pretty() =\n\u00a0 \u00a0 \u00a0 Person.LOG.info(\"$name is $age old\")<\/pre>\n<p><strong>Java<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/@JvmName for files and methods makes accessing static fields look like Java: without it would be: PersonKt.pretty(...)\nPersons.prettyPrint(ken)<\/pre>\n<p><strong>Convertisseur Java vers Kotlin d&#8217;IntelliJ IDEA<\/strong><\/p>\n<p>IntelliJ IDEA propose un convertisseur Java vers Kotlin, donc th\u00e9oriquement, l&#8217;outil peut le faire pour vous. Le code r\u00e9sultant est toutefois loin d&#8217;\u00eatre parfait, utilisez-le donc uniquement comme un point de d\u00e9part. \u00c0 partir de l\u00e0, vous pouvez le convertir en une repr\u00e9sentation plus Kotlinesque. Nous aborderons ce sujet plus en d\u00e9tail dans la derni\u00e8re partie de cette s\u00e9rie d&#8217;articles\u00a0: <em>Facteurs de r\u00e9ussite pour l&#8217;adoption de Kotlin \u00e0 grande \u00e9chelle.<\/em><\/p>\n<p>Utiliser Java comme point de d\u00e9part vous fera tr\u00e8s probablement \u00e9crire du Kotlin \u00e0 la sauce Java, ce qui vous apportera certains avantages, mais n&#8217;exploitera pas pleinement le potentiel de Kotlin. \u00c9crire une nouvelle application est donc l&#8217;approche que je pr\u00e9f\u00e8re.\u00a0<\/p>\n<h3 class=\"wp-block-heading\">Suite de la s\u00e9rie<\/h3>\n<p>Ce volet de notre s\u00e9rie du <em>Guide complet pour r\u00e9ussir l&#8217;adoption de Kotlin dans un environnement Java<\/em> vous a montr\u00e9 comment des exp\u00e9rimentations avec Kotlin peuvent \u00e9voluer vers du code de production. Notre prochain article se concentrera sur l&#8217;aspect humain de l&#8217;adoption\u00a0: convaincre vos coll\u00e8gues. Il expliquera comment pr\u00e9senter des arguments clairs ax\u00e9s sur le code, guider les nouveaux d\u00e9veloppeurs et cr\u00e9er une communaut\u00e9 Kotlin, petite mais durable, au sein de votre \u00e9quipe.<\/p>\n<p><em>Auteurs de l&#8217;article original en anglais<\/em> :<\/p>\n<div class=\"about-author \">\n<div class=\"about-author__box\">\n<div class=\"row\">\n<div class=\"about-author__box-img\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/10\/a3f7-400o400o1-QYUavRYyARnAVJLCpM1m8M.webp\" alt=\"\" \/><\/div>\n<div class=\"about-author__box-text\">\n<h4>Urs Peter<\/h4>\n<p>Urs est un ing\u00e9nieur logiciel exp\u00e9riment\u00e9, architecte de solutions, conf\u00e9rencier et formateur avec plus de 20\u00a0ans d&#8217;exp\u00e9rience dans la cr\u00e9ation de syst\u00e8mes r\u00e9silients, \u00e9volutifs et critiques, dont la plupart impliquent Kotlin et Scala.<\/p>\n<p>Outre son activit\u00e9 de consultant, il est \u00e9galement un formateur passionn\u00e9 et l&#8217;auteur d&#8217;une grande vari\u00e9t\u00e9 de cours sur des sujets allant des langages Kotlin et Scala \u00e0 l&#8217;architecture comme les microservices et les architectures pilot\u00e9es par les \u00e9v\u00e9nements.<\/p>\n<p>Sociable de nature, il aime partager ses connaissances, inspirer et \u00eatre inspir\u00e9 par ses pairs lors de rencontres et de conf\u00e9rences. Urs est un formateur Kotlin certifi\u00e9 par JetBrains.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\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:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/08\/photo_2021-08-03_15-27-43-200x200.jpg\" width=\"200\" height=\"200\" alt=\"Alyona Chernyaeva\" 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                                            <h4>Alyona Chernyaeva<\/h4>\n                                                        <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n","protected":false},"author":813,"featured_media":674434,"comment_status":"closed","ping_status":"closed","template":"","categories":[],"tags":[],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin\/674421"}],"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=674421"}],"version-history":[{"count":7,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin\/674421\/revisions"}],"predecessor-version":[{"id":674492,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin\/674421\/revisions\/674492"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media\/674434"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media?parent=674421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/categories?post=674421"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/tags?post=674421"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/cross-post-tag?post=674421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}