{"id":674737,"date":"2026-01-16T10:15:42","date_gmt":"2026-01-16T09:15:42","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=674737"},"modified":"2026-01-16T10:15:47","modified_gmt":"2026-01-16T09:15:47","slug":"developper-l-adoption-de-kotlin-dans-votre-entreprise","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/fr\/kotlin\/2026\/01\/developper-l-adoption-de-kotlin-dans-votre-entreprise\/","title":{"rendered":"D\u00e9velopper l&#8217;adoption de Kotlin dans votre entreprise"},"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 troisi\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><strong>Tous les articles de la s\u00e9rie\u00a0:<\/strong><\/p>\n<ol>\n<li><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><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/fr\/kotlin\/2026\/01\/evaluer-kotlin-dans-des-projets-reels\/\" target=\"_blank\" rel=\"noreferrer noopener\" data-type=\"link\" data-id=\"https:\/\/blog.jetbrains.com\/kotlin\/2025\/10\/evaluating-kotlin-in-real-projects\/\">\u00c9valuer Kotlin dans des projets r\u00e9els<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2025\/11\/growing-kotlin-adoption-in-your-company\/\" target=\"_blank\" rel=\"noreferrer noopener\">D\u00e9velopper l&#8217;adoption de Kotlin dans votre entreprise<\/a><\/li>\n<\/ol>\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n<h2 class=\"wp-block-heading\"><strong>Faire passer le message\u00a0: convaincre vos coll\u00e8gues d\u00e9veloppeurs<\/strong><\/h2>\n<p>\u00c0 pr\u00e9sent, vous avez un noyau dur de d\u00e9veloppeurs convaincus des avantages de Kotlin. Vient alors la phase critique\u00a0: comment accro\u00eetre l&#8217;adoption\u00a0?\u00a0<\/p>\n<p>Au cours de cette phase, la cl\u00e9 est de convaincre les d\u00e9veloppeurs Java sceptiques. Plusieurs facteurs techniques et culturels peuvent faire la diff\u00e9rence\u00a0:<\/p>\n<p>Facteurs techniques\u00a0: le code<\/p>\n<ul>\n<li>Laissez parler le code<\/li>\n<\/ul>\n<p>Facteurs culturels\u00a0: soutenir et connecter les d\u00e9veloppeurs<\/p>\n<ul>\n<li>Facilitez l&#8217;int\u00e9gration des nouveaux membres<\/li>\n<li>Proposez des ressources d&#8217;autoformation<\/li>\n<li>Mettez en place une communaut\u00e9 Kotlin en interne<\/li>\n<li>Soyez patient\u2026<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\"><strong>Laissez parler le code<\/strong><\/h3>\n<p>Capitalisez sur l&#8217;exp\u00e9rience acquise en (r\u00e9-)\u00e9crivant une application en Kotlin et d\u00e9montrez-en les avantages de mani\u00e8re tangible et accessible\u00a0:<\/p>\n<ul>\n<li><strong>Montrer plut\u00f4t qu&#8217;expliquer<\/strong>\u00a0: pr\u00e9sentez la concision gagn\u00e9e avec Kotlin en comparant des extraits de code Java et Kotlin.\u00a0<\/li>\n<li><strong>Se concentrer sur les paradigmes principaux<\/strong>\u00a0: Kotlin n\u2019est pas simplement <em>diff\u00e9rent<\/em> de Java ; il repose sur des fondements de s\u00e9curit\u00e9, de concision pour une lisibilit\u00e9 et une maintenabilit\u00e9 optimales, d\u2019extensibilit\u00e9 et d\u2019une importance capitale accord\u00e9e aux fonctions. Ensemble, ces paradigmes pallient les limitations fondamentales de Java, tout en pr\u00e9servant une interop\u00e9rabilit\u00e9 totale avec l\u2019\u00e9cosyst\u00e8me Java.<\/li>\n<\/ul>\n<p>Voici quelques exemples concrets\u00a0:<\/p>\n<p><strong>1. S\u00e9curit\u00e9 contre les valeurs null\u00a0: la fin des erreurs \u00e0 un milliard de dollars\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=\"\">\/\/This is why we have the billion-dollar mistake (not only in Java\u2026)\nBooking booking = null; \/\/\ud83e\udd28 This is allowed but causes:\nbooking.destination; \/\/Runtime error \ud83d\ude31\n\nOptional booking = null; \/\/Optionals aren\u2019t safe from null either: \ud83e\udd28\nbooking.map(Destination::destination); \/\/Runtime error \ud83d\ude31<\/pre>\n<p>Au fil du temps, Java a ajout\u00e9 des fonctionnalit\u00e9s de s\u00e9curit\u00e9 contre les valeurs null, comme \u00ab\u00a0Optional\u00a0\u00bb et les Annotations (par exemple, <code>@NotNull<\/code>), mais cela n&#8217;a pas permis de r\u00e9soudre ce probl\u00e8me fondamental. De plus, le projet <a href=\"https:\/\/openjdk.org\/projects\/valhalla\/\" target=\"_blank\" rel=\"noreferrer noopener\">Valhalla<\/a> (types Null-Restricted et Nullables) n&#8217;introduira pas la s\u00e9curit\u00e9 contre les valeurs null en Java, mais offrira plut\u00f4t davantage d&#8217;options parmi lesquelles choisir.\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=\"\">\/\/Important to realize that null is very restricted in Kotlin:\nval booking:Booking? = null \/\/\u2026null can only be assigned to Nullable types \u2705\u00a0\nval booking:Booking = null \/\/null assigned to a Non-nullable types yields a Compilation error \ud83d\ude03\u00a0\n\nbooking.destination \/\/unsafely accessing a nullable type directly causes a Compilation error \ud83d\ude03\nbooking?.destination \/\/only safe access is possible\u00a0 \u2705<\/pre>\n<p>L&#8217;un des grands avantages de la s\u00e9curit\u00e9 contre les valeurs null de Kotlin est qu&#8217;en plus d&#8217;\u00eatre s\u00fbre, elle est tr\u00e8s facile \u00e0 utiliser. Voici exemple classique de la possibilit\u00e9 \u00ab\u00a0d&#8217;avoir le beurre et l&#8217;argent du beurre\u00a0\u00bb\u00a0:<\/p>\n<p>Supposons que nous ayons ce domaine\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=\"\">data class Booking(val destination:Destination? = null)\ndata class Destination(val hotel:Hotel? = null)\ndata class Hotel(val name:String, val stars:Int? = null)<\/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=\"\">public record Booking(Optional destination) {\n\n\u00a0\u00a0\u00a0public Booking() { this(Optional.empty()); }\n\n\u00a0\u00a0\u00a0public Booking(Destination destination) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(Optional.ofNullable(destination));\n\u00a0\u00a0\u00a0}\n}\n\npublic record Destination(Optional hotel) {\n\n\u00a0\u00a0\u00a0public Destination() { this(Optional.empty()); }\n\n\u00a0\u00a0\u00a0public Destination(Hotel hotel) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(Optional.ofNullable(hotel));\n\u00a0\u00a0\u00a0}\n}\n\npublic record Hotel(String name, Optional stars) {\n\n\u00a0\u00a0\u00a0public Hotel(String name) {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(name, Optional.empty());\n\n\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0public Hotel(String name, Integer stars) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this(name, Optional.ofNullable(stars));\n\u00a0\u00a0\u00a0}\n}<\/pre>\n<p><strong>Construction d&#8217;objets<\/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=\"\">\/\/Because Optional is a wrapper, the number of nested objects grows, which doesn\u2019t help readability\nfinal Optional booking = Optional.of(new Booking(\n      Optional.of(new Destination(Optional.of(\n            new Hotel(\"Sunset Paradise\", 5))))));<\/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=\"\">\/\/Since nullability is part of the type system, no wrapper is needed: The required type or null can be used.\u00a0\nval booking:Booking? = Booking(Destination(Hotel(\"Sunset Paradise\", 5)))<\/pre>\n<p><strong>Navigation entre objets imbriqu\u00e9s<\/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=\"\">\/\/traversing a graph of Optionals requires extensive unwrapping\nfinal var stars = \"*\".repeat(booking\n\u00a0\u00a0                        .flatMap(Booking::getDestination)\n                          .flatMap(Destination::getHotel)\n                          .map(Hotel::getStars).orElse(0)); \/\/-&gt; \"*****\"<\/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=\"\">\/\/Easily traverse a graph of nullable types with: \u2018?\u2019, use\u00a0 ?: for the \u2018else\u2019 case.\nval stars = \"*\".repeat(booking?.destination?.hotel?.stars ?: 0) \/\/-&gt; \"*****\"<\/pre>\n<p><strong>D\u00e9ballage d&#8217;un objet imbriqu\u00e9<\/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=\"\">\/\/extensive unwrapping is also needed for printing a leaf\u00a0\nbooking.getDestination()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.flatMap(Destination::getHotel)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.map(Hotel::getName)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.map(String::toUpperCase)\n\u00a0\u00a0\u00a0      .ifPresent(System.out::println);<\/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=\"\">\/\/In Kotlin we have two elegant options:\n\/\/1. we can again traverse the graph with \u2018?\u2019\nbooking?.destination?.hotel.?name?.uppercase()?.also(::println)\n\n\/\/2. We can make use of Kotlin\u2019s smart-cast feature\nif(booking?.destination?.hotel != null) {\n\u00a0\u00a0\u00a0\/\/The compiler has checked that all the elements in the object graph are not null, so we can access the elements as if they were non-nullable types\n\u00a0\u00a0\u00a0println(booking.destination.hotel.uppercase())\n}<\/pre>\n<p>Le manque de prise en charge de la s\u00e9curit\u00e9 contre les valeurs null en Java est un probl\u00e8me majeur pour les d\u00e9veloppeurs. Il entra\u00eene une programmation d\u00e9fensive, diff\u00e9rentes constructions de nullabilit\u00e9 (ou aucune), et augmente la verbosit\u00e9. De plus, les \u00ab\u00a0NullPointerException\u00a0\u00bb sont responsables d&#8217;environ un tiers des plantages d&#8217;applications (<a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2020\/11\/productive-server-side-development-with-kotlin-stories\/\" target=\"_blank\" rel=\"noreferrer noopener\">Le blog JetBrains<\/a>). La v\u00e9rification au moment de la compilation de Kotlin emp\u00eache totalement ces \u00e9checs lors de l&#8217;ex\u00e9cution. C&#8217;est pourquoi, aujourd&#8217;hui encore, <strong>la s\u00e9curit\u00e9 contre les valeurs null est la principale raison de migrer vers Kotlin<\/strong>.<\/p>\n<p><strong>2. Les Collections sont vos alli\u00e9es, pas vos ennemies<\/strong><\/p>\n<p>Le cr\u00e9ateur de Spring, Rod Johnson, a d\u00e9clar\u00e9 dans une interview r\u00e9cente que ce n&#8217;\u00e9taient pas les types Nullable qui l&#8217;avaient pouss\u00e9 \u00e0 utiliser Kotlin, mais la complexit\u00e9 excessive de l&#8217;API Java Streams\u00a0: <a href=\"https:\/\/youtu.be\/Rx3XZoqbi78?t=1018\" target=\"_blank\" rel=\"noreferrer noopener\">Creator of Spring: No desire to write Java<\/a>.\u00a0<\/p>\n<p>L&#8217;exemple suivant illustre les diverses raisons pour lesquelles l&#8217;API Java Streams est si horriblement compliqu\u00e9e et montre comment Kotlin r\u00e9sout tous ces probl\u00e8mes\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 Product(String name, int... ratings){}\nList products = List.of(\n\u00a0\u00a0new Product(\"gadget\", 9, 8, 7),\u00a0\n\u00a0\u00a0new Product(\"goody\", 10, 9)\n);\n\nMap maxRatingsPerProduct =\n\n\u00a0\u00a0\u00a0\/\/\ud83e\udd28 1. Stream introduces indirection\n\u00a0\u00a0\u00a0products.stream()\n\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83e\udd28 1. Always to and from Stream conversion\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.collect(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83e\udd28 2. Lacks extension methods, so wrappers are required\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Collectors.groupingBy(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Product::name,\n\u00a0 \u00a0         \/\/\ud83e\udd28 2. Again\u2026\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Collectors.mapping( groupedProducts -&gt;\n\u00a0               \/\/\ud83e\udd28 3. (too) low-level types, arrays, and primitives cause extra complexity\n\u00a0               \/\/\ud83e\udd28 4. No API on Array, always wrap in stream\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Arrays.stream(groupedProducts.ratings())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .max()\n                      \/\/\ud83e\udd28 5. Extra verbosity due to Optional\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0         .orElse(0.0),\n\u00a0              \/\/\ud83e\udd28 6. No named arguments: what does this do?\n\u00a0               Collectors.reducing(0, Integer::max)\n              )\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ));<\/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=\"\">\/\/\ud83d\ude03 rich and uniform Collection API - even on Java collections - due to extension methods\nval maxRatingsPerProduct = products.\n      .groupBy { it.name }\n      .mapValues { (_, groupedProducts) -&gt; \/\/\ud83d\ude03 destructuring for semantic precision\n            \/\/\ud83d\ude03 built-in nullability support, and the same API for\u00a0\n            \/\/arrays like other Collections\n            groupedProducts.flatMap { it.ratings }\n                  .maxOrNull() ?: 0\u00a0\n            }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/pre>\n<p>Gr\u00e2ce au framework collection uniforme de Kotlin, la conversion entre plusieurs types de collections est tr\u00e8s simple\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=\"\">int[] numbers = {1, 3, 3, 5, 2};\n\nSet unique = Arrays.stream(numbers).boxed().collect(Collectors.toSet());\n\nMap evenOrOdd = unique.stream()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.collect(Collectors.toMap(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0n -&gt; n,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0n -&gt; n % 2 == 0));<\/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 numbers = arrayOf(1, 3, 3, 5, 2)\n\nval unique: Set = numbers.toSet() \/\/\ud83d\ude03 simply call to to do the conversion\n\nval evenOrOdd: Map = unique.associateWith { it % 2 == 0 }<\/pre>\n<p><strong>Effet net\u00a0:<\/strong><\/p>\n<ul>\n<li><strong>API Collection riche en fonctionnalit\u00e9s et intuitive\u00a0:<\/strong> les pipelines se lisent de gauche \u00e0 droite, comme en anglais, pas dans des appels de collecteur imbriqu\u00e9s.<\/li>\n<li><strong>Moins de code r\u00e9utilisable et de complexit\u00e9\u00a0:<\/strong> pas de Collectors.groupingBy, pas de Stream, pas d&#8217;Optional, pas d&#8217;Arrays.stream.<\/li>\n<li><strong>Mod\u00e8le mental unique\u00a0:<\/strong> que vous partiez d&#8217;une <code>List<\/code>, d&#8217;un <code>Set<\/code>, d&#8217;un <code>Array<\/code> ou d&#8217;un tableau primitif, vous recherchez les <em>m\u00eames<\/em> op\u00e9rateurs de collection.<\/li>\n<li><strong>Performances sans douleur\u00a0:<\/strong> le compilateur ins\u00e8re du boxing ou du unboxing uniquement l\u00e0 o\u00f9 c&#8217;est in\u00e9vitable ; vous \u00e9crivez du code normal.<\/li>\n<li>\u200b\u200b<strong>S\u00e9curit\u00e9 int\u00e9gr\u00e9e contre les valeurs null\u00a0:<\/strong> l&#8217;API Collection prend enti\u00e8rement en charge la nullabilit\u00e9 avec diff\u00e9rentes m\u00e9thodes utilitaires souvent suffix\u00e9es avec <code>orNull (\u2026)<\/code>.<\/li>\n<li><strong>Interop\u00e9rabilit\u00e9 transparente avec Java gr\u00e2ce \u00e0 des wrappers idiomatiques\u00a0:<\/strong> gr\u00e2ce aux m\u00e9thodes d&#8217;extension, vous b\u00e9n\u00e9ficiez du \u00ab\u00a0meilleur des deux mondes\u00a0\u00bb\u00a0: des collections riches en fonctionnalit\u00e9s en plus des collections Java.<\/li>\n<\/ul>\n<p>Pour le dire simplement, Kotlin \u00e9l\u00e8ve les t\u00e2ches routini\u00e8res avec les collections (filtrage, mappage, regroupement, etc.) au rang de fonctions de premi\u00e8re classe qui peuvent \u00eatre <em>compos\u00e9es<\/em>, afin que vous puissiez exprimer <em>ce que<\/em> vous voulez, au lieu de <em>comment<\/em> y parvenir.<\/p>\n<p><strong>3. Avec Kotlin, fini les exceptions v\u00e9rifi\u00e9es, mais le code est plus s\u00fbr<\/strong><\/p>\n<p>Java est l&#8217;un des rares langages qui prend encore en charge les Exceptions v\u00e9rifi\u00e9es. Bien qu&#8217;initialement impl\u00e9ment\u00e9es comme fonctionnalit\u00e9 de s\u00e9curit\u00e9, elles n&#8217;ont pas tenu leur promesse. Leur verbosit\u00e9, les blocs catch inutiles qui ne font rien ou relancent une Exception en tant que <code>RuntimeException<\/code>, et leur manque d&#8217;alignement avec les lambdas sont unes des quelques raisons pour lesquelles elles entravent davantage votre code qu&#8217;elles ne le s\u00e9curisent.<\/p>\n<p>Kotlin suit le paradigme \u00e9prouv\u00e9 utilis\u00e9 par presque tous les autres langages de programmation (C#, Python, Scala, Rust et Go) qui consiste \u00e0 n&#8217;utiliser les exceptions que pour des situations irr\u00e9cup\u00e9rables.<\/p>\n<p>Les exemples suivants mettent en \u00e9vidence les obstacles que les Exceptions v\u00e9rifi\u00e9es introduisent dans votre code, sans ajouter de s\u00e9curit\u00e9\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 String downloadAndGetLargestFile(List urls) {\n\u00a0\u00a0\u00a0List contents = urls.stream().map(urlStr -&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Optional optional;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0optional = Optional.of(new URI(urlStr).toURL());\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83e\udd28 Within lambdas checked exceptions are not supported and must always be caught...\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (URISyntaxException | MalformedURLException e) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0optional = Optional.empty();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return optional;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}).filter(Optional::isPresent) \u00a0 \u00a0 \u00a0 \/\/Quite a mouthful to get rid of the Optional...\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.map(Optional::get)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.map(url -&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try (InputStream is = url.openStream()) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return new String(is.readAllBytes(), StandardCharsets.UTF_8);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} catch (IOException e) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83e\udd28\u2026 or re-thrown, which is annoying, I don\u2019t really care about IOE\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw new IllegalArgumentException(e);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}).toList();\n\u00a0\u00a0\u00a0\/\/\ud83e\udd28 An empty List results in a NoSuchElementException, so why is it not checked? The chance that the List is empty is as high as the other two cases above...\n\u00a0\u00a0\u00a0return Collections.max(contents);\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=\"\">\/\/\ud83d\ude03 safe return type\nfun downloadAndGetLargestFile(urls: List): String? =\n\u00a0\u00a0\u00a0urls.mapNotNull { \u00a0\u00a0\u00a0\/\/\ud83d\ude03 convenient utility methods to rid of null\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\ud83d\ude03 try catch is possible, yet runCatching is an elegant way to convert an exception to null\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0runCatching { URI(it).toURL() }.getOrNull()\n\u00a0\u00a0\u00a0}.maxOfOrNull{ \u00a0\/\/\ud83d\ude03 safe way to retrieve the max value\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0it.openStream().use{ it.reader().readText() } \u00a0\/\/\ud83d\ude03 convenient extension methods to make java.io streams fluent\n\u00a0\u00a0\u00a0}<\/pre>\n<p><strong>4. Les fonctions comme citoyens de premi\u00e8re classe<\/strong><\/p>\n<p>Kotlin consid\u00e8re les fonctions comme des citoyens de premi\u00e8re classe, ce qui peut soulever des questions pour les d\u00e9veloppeurs Java : qu\u2019est-ce que cela signifie et pourquoi est-ce important ?<\/p>\n<p>La diff\u00e9rence essentielle r\u00e9side dans l&#8217;approche limit\u00e9e de Java\u00a0: ses capacit\u00e9s fonctionnelles se concentrent principalement sur le site d&#8217;appel via les lambdas, tandis que le c\u00f4t\u00e9 d\u00e9claration reste li\u00e9 \u00e0 des interfaces fonctionnelles verbeuses et moins intuitives. En Kotlin, vous pouvez d\u00e9finir, passer, retourner et composer des fonctions sans aucun code g\u00e9n\u00e9rique, ce qui rend la programmation fonctionnelle bien plus expressive et naturelle.<\/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 void doWithImage(\n      URL url,\u00a0\n      \/\/\ud83e\udd28 Function interfaces introduce an indirection: because we don\u2019t see the signature of a Function we don\u2019t know what a\u00a0 BiConsumer does, unless we look it up\n      BiConsumer f) throws IOException {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0f.accept(url.getFile(), ImageIO.read(url));\n}\n\n\/\/\ud83e\udd28 Same here\npublic void debug(Supplier f) {\n\u00a0\u00a0\u00a0if(isDebugEnabled()) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0logger.debug(\"Debug: \" + f.get());\n\u00a0\u00a0\u00a0}\n}\n\n\/\/\ud83e\udd28 calling no-argument lambdas is verbose\ndebug(() -&gt; \"expensive concat\".repeat(1000));<\/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=\"\">fun doWithImage(\n\u00a0\u00a0\u00a0url: URL,\n\u00a0 \/\/\ud83d\ude03 Kotlin has a syntax for declaring functions: from the signature, we see what goes in and what goes out\u00a0\n\u00a0\u00a0\u00a0f:(String, BufferedImage) -&gt; Unit) =\u00a0\n      f(url.file, ImageIO.read(url))\n\n\u00a0\u00a0\/\/\ud83d\ude03 same here: nothing goes in, a String goes out\nfun debug(msg: () -&gt; String) {\n\u00a0\u00a0\u00a0if(isDebugEnabled) {\n            logger.debug(msg())\n\u00a0\u00a0\u00a0}\n}\n\n\/\/\ud83d\ude03 convenient syntax to pass a lambda: {}\ndebug{\"expensive concat\".repeat(1000)}<\/pre>\n<p>Kotlin offre une syntaxe claire et concise pour d\u00e9clarer des fonctions\u00a0: rien qu&#8217;\u00e0 partir de la signature, vous pouvez imm\u00e9diatement voir ce qui entre et ce qui sort, sans avoir \u00e0 naviguer vers une interface fonctionnelle externe.\u00a0<\/p>\n<p>Java \u00ab\u00a0divulgue\u00a0\u00bb ses fonctionnalit\u00e9s de programmation fonctionnelle via un large ensemble d&#8217;interfaces <code>java.util.function.*<\/code> aux signatures longues et complexes, ce qui rend souvent la programmation fonctionnelle fastidieuse. Kotlin, \u00e0 l&#8217;inverse, traite les fonctions comme des citoyens de premi\u00e8re classe : ces interfaces restent cach\u00e9es aux yeux du d\u00e9veloppeur, tout en restant pleinement interop\u00e9rables avec l&#8217;approche de Java\u00a0:<\/p>\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-655829\" style=\"aspect-ratio: 1.1355932203389831; width: 510px; height: auto;\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/11\/unnamed-16.png\" alt=\"\" width=\"804\" height=\"708\" \/><\/figure>\n<p>Par cons\u00e9quent, l&#8217;utilisation des fonctions en Kotlin est beaucoup plus simple, directe et intuitive, ce qui facilite grandement l&#8217;exploitation de ce puissant concept de programmation pour votre propre code.\u00a0<\/p>\n<p><strong>5. Concurrence sans souci avec les coroutines<\/strong><\/p>\n<p>Si vous avez besoin d&#8217;un d\u00e9bit \u00e9lev\u00e9, d&#8217;un traitement parall\u00e8le au sein d&#8217;une m\u00eame requ\u00eate ou de streaming, la seule option dont vous disposez en Java est une biblioth\u00e8que r\u00e9active, comme Reactor et RxJava, disponible dans des frameworks tels que Spring WebFlux, Vert.X, Quarkus, etc.<\/p>\n<p>Le probl\u00e8me avec ces biblioth\u00e8ques, c&#8217;est qu&#8217;elles sont notoirement compliqu\u00e9es, et vous obligent \u00e0 utiliser la programmation fonctionnelle. Leur courbe d&#8217;apprentissage est donc assez rude, et pourtant il est tr\u00e8s facile de commettre des erreurs qui peuvent avoir des cons\u00e9quences d\u00e9sastreuses lorsque l&#8217;application est soumise \u00e0 une forte charge. C&#8217;est tr\u00e8s probablement la raison pour laquelle la programmation r\u00e9active ne s&#8217;est jamais g\u00e9n\u00e9ralis\u00e9e.\u00a0<\/p>\n<div class=\"alert \">\n<p><strong>Remarque\u00a0:<\/strong> les VirtualThreads ne remplacent pas les biblioth\u00e8ques r\u00e9actives, m\u00eame s&#8217;il existe un certain chevauchement. Les VirtualThreads offrent des entr\u00e9es\/sorties non bloquantes, mais ne fournissent pas de fonctionnalit\u00e9s telles que le traitement parall\u00e8le ou les flux r\u00e9actifs. La concurrence structur\u00e9e et les valeurs d\u00e9limit\u00e9es permettront \u00e9galement le traitement parall\u00e8le une fois que les principaux frameworks prendront en charge cette fonctionnalit\u00e9. Pour les flux r\u00e9actifs, vous devrez toujours vous appuyer sur une biblioth\u00e8que r\u00e9active.<\/p>\n<\/div>\n<p>Supposons donc que vous \u00eates un d\u00e9veloppeur Java utilisant Spring Boot et que vous souhaitez effectuer un appel parall\u00e8le au sein d&#8217;une m\u00eame requ\u00eate. Voici le r\u00e9sultat que vous obtenez\u00a0:\u00a0<\/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=\"\">@PostMapping(\"\/users\")\n@ResponseBody\n@Transactional\npublic Mono storeUser(@RequestBody User user) {\n\u00a0\u00a0\u00a0Mono avatarMono = avatarService.randomAvatar();\n\u00a0\u00a0\u00a0Mono validEmailMono = emailService.verifyEmail(user.getEmail());\n\u00a0\u00a0\u00a0\/\/\ud83e\udd28 what does \u2018zip\u2019 do?\n\u00a0\u00a0\u00a0return Mono.zip(avatarMono, validEmailMono).flatMap(tuple -&gt;\u00a0\n\u00a0      if(!tuple.getT2()) \/\/what is getT2()? It\u2019s the validEmail Boolean\u2026\n\u00a0\u00a0\u00a0     \/\/\ud83e\udd28 why can I not just throw an exception?\n\u00a0\u00a0\u00a0      Mono.error(new InvalidEmailException(\"Invalid Email\"));\n\u00a0      else personDao.save(UserBuilder.from(user)\n                                          .withAvatarUrl(tuple.getT1()));\n\u00a0\u00a0\u00a0\u00a0\u00a0);\u00a0\u00a0\n\u00a0\u00a0}<\/pre>\n<p>M\u00eame si ce code fonctionne parfaitement du point de vue de l&#8217;ex\u00e9cution, la complexit\u00e9 accidentelle introduite est \u00e9norme\u00a0:\u00a0<\/p>\n<ul>\n<li>Le code est domin\u00e9 par <code>Mono\/Flux<\/code> tout au long de la cha\u00eene d&#8217;appels, ce qui vous oblige \u00e0 encapsuler tous les objets de domaine.<\/li>\n<li>Il y a de nombreux op\u00e9rateurs complexes partout, comme <code>zip<\/code>, <code>flatMap<\/code>, etc.<\/li>\n<li>Vous ne pouvez pas utiliser des constructions de programmation standard telles que la lev\u00e9e d&#8217;exceptions.\u00a0<\/li>\n<li>L&#8217;intention initiale de votre code en souffre consid\u00e9rablement\u00a0: le code se concentre sur les <code>Monos<\/code> et <code>flatMap<\/code>, occultant ainsi ce qui se passe r\u00e9ellement d&#8217;un point de vue m\u00e9tier.<\/li>\n<\/ul>\n<p>La bonne nouvelle, c&#8217;est qu&#8217;il existe un rem\u00e8de puissant\u00a0: les Coroutines Kotlin. Les coroutines peuvent \u00eatre consid\u00e9r\u00e9es comme une impl\u00e9mentation r\u00e9active au niveau du langage. En tant que telles, elles combinent le meilleur des deux mondes\u00a0:\u00a0<\/p>\n<ul>\n<li>Vous \u00e9crivez du code s\u00e9quentiel comme vous le faisiez auparavant.<\/li>\n<li>Le code s&#8217;ex\u00e9cute de mani\u00e8re asynchrone\/en parall\u00e8le au moment de l&#8217;ex\u00e9cution.<\/li>\n<\/ul>\n<p>Le code Java ci-dessus, converti en coroutines, ressemble \u00e0 ceci\u00a0:<\/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=\"\">@GetMapping(\"\/users\")\n@ResponseBody\n@Transactional\nsuspend fun storeUser(@RequestBody user:User):User = coroutineScope {\n\u00a0\u00a0\u00a0val avatarUrl = async { avatarService.randomAvatar() }\n\u00a0  val validEmail = async { emailService.verifyEmail() }\n\u00a0\u00a0\u00a0if(!validEmail.await()) throw InvalidEmailException(\"Invalid email\")\n\u00a0\u00a0\u00a0personRepo.save(user.copy(avatar = avatarUrl.await()))\n}<\/pre>\n<p>Le mot-cl\u00e9 \u00ab\u00a0suspend\u00a0\u00bb de Kotlin permet une ex\u00e9cution structur\u00e9e et non bloquante, de mani\u00e8re claire et concise. Combin\u00e9 \u00e0 <code>async{}<\/code> et <code>await()<\/code>, il facilite le traitement parall\u00e8le sans avoir besoin de rappels profond\u00e9ment imbriqu\u00e9s ou de constructions complexes telles que <code>Mono<\/code> ou <code>CompletableFuture<\/code>.<\/p>\n<p>C&#8217;est pourquoi la complexit\u00e9 va diminuer, tandis que la satisfaction des d\u00e9veloppeurs et la maintenabilit\u00e9 vont augmenter, avec exactement les m\u00eames caract\u00e9ristiques de performance.\u00a0<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-655845\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/11\/unnamed-17.png\" alt=\"\" width=\"1566\" height=\"456\" \/><\/figure>\n<p><strong>Remarque\u00a0<\/strong>: tous les frameworks web majeurs bas\u00e9s sur Java ne prennent pas aussi bien en charge les coroutines. Spring s&#8217;en sort tr\u00e8s bien, tout comme Micronaut. Quarkus offre actuellement une prise en charge limit\u00e9e des coroutines.<\/p>\n<p><strong>6. Mais bon, Java \u00e9volue aussi\u00a0!<\/strong><\/p>\n<p>Java poursuit son \u00e9volution avec des fonctionnalit\u00e9s comme les enregistrements, la correspondance des sch\u00e9mas, et des projets \u00e0 venir tels qu&#8217;Amber, Valhalla et Loom. Cette \u00e9volution constante renforce la JVM et b\u00e9n\u00e9ficie \u00e0 l&#8217;ensemble de l&#8217;\u00e9cosyst\u00e8me.<\/p>\n<p>Mais il y a un hic\u00a0: la plupart de ces \u00ab\u00a0nouvelles\u00a0\u00bb fonctionnalit\u00e9s Java sont des choses dont les d\u00e9veloppeurs Kotlin b\u00e9n\u00e9ficient depuis des ann\u00e9es. La s\u00e9curit\u00e9 contre les valeurs null, les classes de valeurs, les fonctions de niveau sup\u00e9rieur, les arguments par d\u00e9faut, les collections concises et la place pr\u00e9pond\u00e9rante des fonctions sont tous int\u00e9gr\u00e9s dans la conception de Kotlin, livr\u00e9s d&#8217;une mani\u00e8re plus unifi\u00e9e et conviviale pour les d\u00e9veloppeurs. C&#8217;est pourquoi le code Kotlin para\u00eet souvent plus propre, plus s\u00fbr et beaucoup plus productif.<\/p>\n<p>Et ce n&#8217;est pas tout\u00a0: Kotlin b\u00e9n\u00e9ficie \u00e9galement des innovations de Java. Les avanc\u00e9es au niveau de la JVM comme les Virtual Threads et Loom en g\u00e9n\u00e9ral, ou les gains de performance de Valhalla, s&#8217;appliquent aussi de mani\u00e8re transparente \u00e0 Kotlin.<\/p>\n<p>En bref\u00a0: Java \u00e9volue, mais Kotlin a \u00e9t\u00e9 con\u00e7u d\u00e8s le d\u00e9part pour offrir aux d\u00e9veloppeurs les outils modernes dont ils ont besoin, ce qui en fait un choix s\u00fbr, moderne et p\u00e9renne.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-655858\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/11\/kotlin-castle-1.png\" alt=\"\" width=\"1698\" height=\"1780\" \/><\/figure>\n<p><strong>7. L&#8217;avantage \u00e9volutif de Kotlin<\/strong><\/p>\n<p>Les langages de programmation plus anciens tra\u00eenent in\u00e9vitablement un certain bagage historique par rapport aux alternatives modernes. Mettre \u00e0 jour un langage tout en prenant en charge des bases de code existantes massives pr\u00e9sente des d\u00e9fis uniques pour les concepteurs du langage. Kotlin b\u00e9n\u00e9ficie de deux avantages cruciaux\u00a0:<\/p>\n<p><strong>R\u00e9f\u00e9rences solides<\/strong>\u00a0: plut\u00f4t que de r\u00e9inventer la roue, l&#8217;\u00e9quipe de conception initiale de Kotlin a rassembl\u00e9 des paradigmes \u00e9prouv\u00e9s issus des langages de programmation majeurs et les a unifi\u00e9s dans un ensemble coh\u00e9rent. Cette approche a maximis\u00e9 l&#8217;apprentissage \u00e9volutif gr\u00e2ce \u00e0 la taille \u00e9largie de la communaut\u00e9 de d\u00e9veloppement.<\/p>\n<p><strong>Apprendre des lacunes de Java<\/strong>\u00a0: les concepteurs de Kotlin ont pu observer les d\u00e9fauts de Java et d\u00e9velopper des solutions solides d\u00e8s le d\u00e9part.<\/p>\n<p>Pour aller plus loin sur l&#8217;\u00e9volution de Kotlin, Andrey Breslav, membre de l&#8217;\u00e9quipe de conception originale de Kotlin, a donn\u00e9 une excellente conf\u00e9rence au KotlinDevDay d&#8217;Amsterdam\u00a0: <a href=\"https:\/\/www.youtube.com\/watch?v=7z_K-hTTeqI&amp;ab_channel=Xebia\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Shoulders of Giants: Languages Kotlin Learned From<\/em> \u2013 par Andrey Breslav<\/a><\/p>\n<p><strong>Facteurs culturels\u00a0: soutenir et connecter les d\u00e9veloppeurs dans leur parcours d&#8217;adoption de Kotlin<\/strong><\/p>\n<h3 class=\"wp-block-heading\"><strong>1. Facilitez l&#8217;int\u00e9gration des nouveaux membres<\/strong><\/h3>\n<p>L&#8217;objectif des exemples de code expressifs Java vs Kotlin est de susciter l&#8217;int\u00e9r\u00eat pour Kotlin. Toutefois, le code seul n&#8217;est pas suffisant pour convaincre les d\u00e9veloppeurs Java. Pour acc\u00e9l\u00e9rer l&#8217;adoption et assurer un bon d\u00e9marrage, fournissez\u00a0:<\/p>\n<ul>\n<li><strong>Un exemple de projet<\/strong>\u00a0: un projet pr\u00eat \u00e0 ex\u00e9cuter avec du code Java et Kotlin c\u00f4te \u00e0 c\u00f4te, offrant aux \u00e9quipes une r\u00e9f\u00e9rence pratique pendant la migration.<\/li>\n<li><strong>Des v\u00e9rifications de qualit\u00e9 int\u00e9gr\u00e9es<\/strong>\u00a0: pr\u00e9configur\u00e9es avec des outils comme SonarQube, ktlint et detekt pour favoriser un code propre, coh\u00e9rent et maintenable d\u00e8s le premier jour. Cela vous permettra d&#8217;appliquer des r\u00e8gles de linting, des frameworks de tests, des biblioth\u00e8ques et des pipelines de CI coh\u00e9rents, afin de r\u00e9duire les frictions entre les \u00e9quipes.<\/li>\n<li><strong>Un accompagnement et du soutien<\/strong>\u00a0: des ing\u00e9nieurs Kotlin exp\u00e9riment\u00e9s disponibles pour coacher les nouvelles \u00e9quipes, r\u00e9pondre aux questions et fournir des conseils pratiques durant les premi\u00e8res \u00e9tapes du d\u00e9veloppement.\n<ul>\n<li>Ce point est particuli\u00e8rement important\u00a0: avec seulement quelques heures de conseils d&#8217;un d\u00e9veloppeur exp\u00e9riment\u00e9 d&#8217;une autre \u00e9quipe qui a d\u00e9j\u00e0 franchi ces \u00e9tapes, vous \u00e9viterez beaucoup de d\u00e9g\u00e2ts et de dette technique.\u00a0<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Quelques mesures de soutien et d&#8217;accompagnement sont le moyen le plus efficace de nourrir un enthousiasme durable pour Kotlin.<\/p>\n<h3 class=\"wp-block-heading\"><strong>2. Proposez des ressources d&#8217;autoformation<\/strong><\/h3>\n<p>Pour des d\u00e9veloppeurs Java, l&#8217;apprentissage des bases de Kotlin peut se faire de fa\u00e7on autonome. Fournir des ressources en amont facilite le parcours vers une utilisation productive de Kotlin et abaisse les barri\u00e8res \u00e0 l&#8217;entr\u00e9e.\u00a0<\/p>\n<ul>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/getting-started.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Le \u00ab\u00a0Tour of Kotlin \u00bb de JetBrains (Guide de d\u00e9marrage)<\/strong><br \/><\/a>Un court tutoriel bas\u00e9 sur un navigateur sur le site officiel de Kotlin.<\/li>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/koans.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Kotlin Koans<br \/><\/strong><\/a>Un ensemble de petits d\u00e9fis de programmation maintenus par JetBrains.<\/li>\n<li><a href=\"https:\/\/www.udacity.com\/course\/kotlin-bootcamp-for-programmers--ud9011\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Formation \u00ab\u00a0Kotlin Bootcamp for Programmers\u00a0\u00bb sur Udacity<\/strong><br \/><\/a>Un cours enti\u00e8rement en vid\u00e9os, cr\u00e9\u00e9 en partenariat avec Google.<\/li>\n<\/ul>\n<div class=\"alert \">\n<p><strong>Remarque\u00a0<\/strong>: bien que l&#8217;autoformation soit pr\u00e9cieuse pour saisir les bases, elle pr\u00e9sente aussi certains inconv\u00e9nients. L&#8217;un de ces inconv\u00e9nients est son caract\u00e8re facultatif\u00a0: pris dans la fr\u00e9n\u00e9sie du quotidien, il est tentant de n\u00e9gliger l&#8217;autoformation. De plus, vous ne b\u00e9n\u00e9ficierez pas des retours d&#8217;un praticien aguerri, qui ma\u00eetrise les subtiles nuances d&#8217;un Kotlin idiomatique correctement appliqu\u00e9. Il y a de fortes chances qu&#8217;apr\u00e8s un cours d&#8217;autoformation, vous \u00e9criviez du Kotlin \u00e0 la mani\u00e8re de Java, ce qui vous apporte certains avantages, mais ne permet pas d&#8217;exploiter tout le potentiel du langage.\u00a0<\/p>\n<\/div>\n<p>\u00c0 moins de b\u00e9n\u00e9ficier d&#8217;un bon encadrement, un cours classique peut \u00eatre tr\u00e8s b\u00e9n\u00e9fique. Il est n\u00e9cessaire d&#8217;y participer\u00a0; vous pourrez \u00e9changer avec des pairs de votre niveau et obtenir des r\u00e9ponses \u00e0 vos questions de la part d&#8217;un professionnel exp\u00e9riment\u00e9, ce qui vous permettra d&#8217;\u00eatre op\u00e9rationnel beaucoup plus rapidement, avec moins de Kotlin non idiomatique lors de la transition initiale.\u00a0<\/p>\n<h3 class=\"wp-block-heading\"><strong>3. Mettez en place une communaut\u00e9 Kotlin en interne<\/strong><\/h3>\n<p>L&#8217;un des moyens les plus rapides d&#8217;am\u00e9liorer l&#8217;expertise en Kotlin dans votre entreprise est de cr\u00e9er et, surtout, de faire vivre une communaut\u00e9 interne.<\/p>\n<ul>\n<li><strong>Lancez une communaut\u00e9 Kotlin en interne<\/strong>\n<ul>\n<li>Premi\u00e8re \u00e9tape\u00a0: recherchez un noyau d&#8217;\u00e9quipe d&#8217;au moins 3 \u00e0 6\u00a0d\u00e9veloppeurs d\u00e9sireux de s&#8217;investir dans une communaut\u00e9 Kotlin. Assurez-vous \u00e9galement qu&#8217;ils b\u00e9n\u00e9ficient de temps et de reconnaissance de la part de leurs responsables pour cette t\u00e2che.<\/li>\n<li>Une fois l&#8217;\u00e9quipe constitu\u00e9e, organisez un lancement \u00e0 l&#8217;\u00e9chelle de l&#8217;entreprise avec des intervenants reconnus de la communaut\u00e9 Kotlin. Cela va susciter de l&#8217;int\u00e9r\u00eat pour Kotlin et lancer le mouvement.<\/li>\n<li>Organisez des rencontres r\u00e9guli\u00e8res (mensuelles ou bimensuelles) pour maintenir la dynamique.<\/li>\n<li>Cr\u00e9ez un canal de chat ou un wiki partag\u00e9 pour les questions, les extraits de code et les notes d&#8217;\u00e9v\u00e9nements.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Invitez des conf\u00e9renciers (externes)<\/strong>\n<ul>\n<li>Faites venir des ing\u00e9nieurs ayant d\u00e9j\u00e0 d\u00e9ploy\u00e9 Kotlin en production pour partager leurs r\u00e9cits de guerre en toute franchise.<\/li>\n<li>Alternez entre des pr\u00e9sentations techniques approfondies (coroutines, KMP, programmation fonctionnelle) et des \u00e9tudes de cas de plus haut niveau (strat\u00e9gies de migration, astuces concernant les outils).<\/li>\n<\/ul>\n<\/li>\n<li><strong>Pr\u00e9sentez les le\u00e7ons tir\u00e9es d&#8217;autres projets internes<\/strong>\n<ul>\n<li>Demandez aux chefs de projet de pr\u00e9senter leurs retours d&#8217;exp\u00e9rience sur Kotlin\u00a0: ce qui a fonctionn\u00e9, ce qui n&#8217;a pas fonctionn\u00e9, et les r\u00e9sultats mesurables.<\/li>\n<li>Ces informations peuvent \u00eatre consign\u00e9es dans un \u00ab\u00a0Guide Kotlin\u00a0\u00bb que les nouvelles \u00e9quipes pourront consulter.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Laissez le devant de la sc\u00e8ne \u00e0 vos propres d\u00e9veloppeurs<\/strong>\n<ul>\n<li>Organisez des sessions courtes lors desquelles chacun peut pr\u00e9senter en 5 \u00e0 10\u00a0minutes une astuce, une biblioth\u00e8que ou une difficult\u00e9 surmont\u00e9e.<\/li>\n<li>F\u00e9licitez les contributeurs publiquement \u2013 les mentions sp\u00e9ciales lors des r\u00e9unions g\u00e9n\u00e9rales ou dans les newsletters internes stimulent l&#8217;implication et le partage des connaissances.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Maintenez des boucles de r\u00e9troaction courtes<\/strong>\n<ul>\n<li>Apr\u00e8s chaque session, organisez des sondages rapides sur leur clart\u00e9 et leur utilit\u00e9, puis ajustez les programmes \u00e0 venir en cons\u00e9quence.<\/li>\n<li>Faites tourner les responsabilit\u00e9s organisationnelles pour que la communaut\u00e9 ne d\u00e9pende pas d&#8217;un seul expert et reste r\u00e9siliente sur le long terme.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Remarque\u00a0<\/strong>: beaucoup des suggestions ci-dessus semblent simples. Mais il ne faut pas sous-estimer l&#8217;effort n\u00e9cessaire pour maintenir une communaut\u00e9 dynamique et vivante.\u00a0<\/p>\n<h3 class=\"wp-block-heading\"><strong>4. Soyez patient\u2026<\/strong><\/h3>\n<p>Un changement culturel prend du temps. Le risque, quand on s&#8217;enthousiasme \u00e0 propos d&#8217;un outil qui fait une diff\u00e9rence pour nous, c&#8217;est de pousser les choses, ce qui peut \u00eatre contre-productif. Une approche efficace consiste \u00e0 favoriser le processus d&#8217;adoption \u00e0 l&#8217;aide de toutes les activit\u00e9s d\u00e9crites ci-dessus, en gardant \u00e0 l&#8217;esprit qu&#8217;<em>une image vaut mieux que mille mots<\/em>.<\/p>\n<h3 class=\"wp-block-heading\">Suite de la s\u00e9rie<\/h3>\n<p>Nous changeons de focus pour parler des moyens de convaincre les d\u00e9cideurs. Le prochain article montre comment construire une analyse de rentabilit\u00e9 convaincante pour l&#8217;adoption de Kotlin, \u00e0 partir de donn\u00e9es concr\u00e8tes et de r\u00e9sultats mesurables. Vous apprendrez \u00e0 traduire les r\u00e9ussites des d\u00e9veloppeurs en arguments \u00e0 l&#8217;intention des d\u00e9cideurs, \u00e0 relier les gains de productivit\u00e9 aux \u00e9conomies de co\u00fbts, et \u00e0 d\u00e9montrer pourquoi Kotlin est plus qu&#8217;une mise \u00e0 niveau technique\u00a0; c&#8217;est une d\u00e9cision strat\u00e9gique, pour les \u00e9quipes comme pour les entreprises.<\/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 ans 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":674787,"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\/674737"}],"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=674737"}],"version-history":[{"count":9,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin\/674737\/revisions"}],"predecessor-version":[{"id":674810,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/kotlin\/674737\/revisions\/674810"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media\/674787"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media?parent=674737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/categories?post=674737"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/tags?post=674737"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/cross-post-tag?post=674737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}