Ce qui vous attend dans Kotlin 1.4 et ses versions ultérieures

Delphine Massenhove

Lors de sa keynote à la KotlinConf, Andrey Breslav a présenté notre vision stratégique concernant les principaux axes pour l’évolution de Kotlin, et nos projets pour Kotlin 1.4, qui sera publiée courant 2020.

Regardez toute la keynote ci-dessous :

Notre ambition est de faire de Kotlin un partenaire fiable pour tous vos projets et qu’il devienne votre langage de prédilection. Pour ce faire, nous allons le faire briller sur toutes les plateformes. Plusieurs études de cas d’entreprises reconnues montrent que nous progressons efficacement dans cette direction.

Kotlin 1.4, prévue pour le printemps 2020, permettra à l’écosystème Kotlin de faire un nouveau pas en avant.

L’accent sur la qualité

Avec Kotlin 1.4 nous entendons privilégier avant tout la qualité et les performances. Kotlin est un langage moderne qui est déjà pionnier sur de nombreuses idées et approches. Il va rester moderne et en constante évolution. Cependant, nous pensons qu’actuellement Kotlin a atteint un stade où l’amélioration de l’expérience globale doit primer sur l’ajout de fonctionnalités. C’est pourquoi Kotlin 1.4 n’apportera que quelques petits changements au langage. Ils sont expliqués en détail ci-dessous.

Nous avons déjà réussi à obtenir des résultats impressionnants en améliorant les performances des EDI prenant en charge Kotlin. La saisie automatique du code s’est considérablement accélérée par rapport aux versions précédentes :

En collaboration avec l’équipe Gradle, nous avons accéléré les scripts Gradle. L’importation Gradle en Kotlin 1.3.60 dans Android Studio est environ 2,5 fois plus rapide et demande environ 75% moins de mémoire qu’avec Kotlin 1.3.10 :

Mémoire

De plus, le chargement de build.gradle.kts ne sollicite pratiquement pas le processeur ! De plus, la compilation de Kotlin/Native en mode dev devient jusqu’à 2 fois plus rapide grâce à la mise en cache du code.

Nous comprenons que la vitesse de build est souvent la plus grande préoccupation de nos utilisateurs, et nous améliorons constamment notre chaîne d’outils pour y répondre. Mais des améliorations incrémentielles ne parviennent pas à suivre le rythme de la croissance naturelle des bases de code de production : tandis que nous accélérons la compilation, les utilisateurs écrivent davantage de code, et le temps de build global ne s’améliore pas assez. Il est devenu évident qu’il faudrait réimplémenter le compilateur pour le rendre très rapide.

Nouveau compilateur

La nouvelle implémentation du compilateur doit répondre à trois objectifs : être très rapide, unifier toutes les plateformes prises en charge par Kotlin et fournir une API pour les extensions du compilateur. Il s’agit d’un travail de plusieurs années, mais nous avons commencé il y a un certain temps, donc certaines parties de cette nouvelle implémentation arriveront dès la version 1.4, et la transition sera très progressive. C’est déjà en cours : par exemple, si vous avez essayé le nouvel algorithme pour l’inférence de type, il fait partie du nouveau compilateur. L’approche sera la même pour les autres parties ; c’est-à-dire que les deux versions seront disponibles pendant un certain temps, l’ancienne, et la nouvelle en mode expérimental. Lorsque la nouvelle version sera stable, elle deviendra la version par défaut.

Accélération grâce au nouveau front-end

L’accélération que nous attendons du nouveau compilateur proviendra principalement d’une nouvelle implémentation front-end.

Pour fournir un peu de contexte, la compilation peut être considérée comme un pipeline qui récupère des fichiers source et les transforme progressivement en code exécutable. La première grande étape de ce pipeline est familièrement appelée le front-end du compilateur. C’est la partie qui analyse le code, résout les noms, vérifie les types, etc. Cette partie du compilateur fonctionne également à l’intérieur de l’EDI pour mettre en évidence les erreurs, naviguer vers les définitions et rechercher les utilisations des symboles dans votre projet. Et c’est l’étape qui demande le plus de temps à kotlinc actuellement. Nous voulons donc la rendre beaucoup plus rapide.

L’implémentation actuelle n’est pas encore terminée et elle n’arrivera pas dans la version 1.4. Toutefois, elle effectue déjà la majeure partie du travail le plus fastidieux, et nous pouvons mesurer l’accélération attendue. Nos benchmarks (la compilation de YouTrack et du compilateur Kotlin lui-même) montrent que le nouveau front-end sera environ 4,5 fois plus rapide qu’aujourd’hui.

Extensibilité et back-ends unifiés

Une fois que le front-end a terminé l’analyse du code, un back-end génère les exécutables. Nous avons trois back-ends : Kotlin/JVM, Kotlin/JS et Kotlin/Native. Historiquement, les deux premiers étaient écrits indépendamment et ne partageaient pas beaucoup de code. Lorsque nous avons initié Kotlin/Native, il reposait sur une nouvelle infrastructure construite autour d’une représentation interne (IR) pour le code Kotlin, qui fonctionne de façon quelque peu similaire au bytecode dans les machines virtuelles. Nous migrons maintenant les deux autres back-ends vers le même IR. Par conséquent, nous partagerons une grande partie de la logique des back-ends et disposerons d’un pipeline unifié, qui permettra de mettre en commun la plupart des fonctionnalités, optimisations et corrections de bugs pour toutes les cibles.

Nous migrerons progressivement vers les nouveaux back-ends, et dans la version 1.4, il est peu probable qu’ils soient activés par défaut, mais les utilisateurs pourront choisir de les utiliser explicitement.

Une infrastructure de back-end commune permet d’envisager des extensions de compilateur multiplateformes. On peut se connecter au pipeline pour ajouter des traitements et/ou des transformations personnalisés qui fonctionneront automatiquement pour toutes les cibles. Dans la version 1.4, nous ne fournissons pas d’API publique pour de telles extensions (l’API sera stabilisée plus tard), mais nous travaillons en étroite collaboration avec nos partenaires, notamment JetPack Compose, qui travaillent déjà sur leurs plugins de compilation.

Découvrez KLib : Kotlin Library Format

Pour construire une bibliothèque multiplateforme en Kotlin qui soit véritablement fiable pour les clients, il faut un format de distribution qui fonctionne également sur n’importe quelle plateforme. Nous vous présentons donc KLib : un format de bibliothèque multiplateforme pour Kotlin. Un fichier KLib contient un IR sérialisé. Votre code peut l’ajouter en tant que dépendance et le back-end du compilateur le récupérera et générera du code exécutable pour la plateforme donnée. L’analogie avec le bytecode reste également valable ici : on peut analyser et transformer les KLibs tout comme le bytecode JVM. Toute transformation apportée à l’IR sérialisé affecteront toutes les plateformes pour lesquelles le KLib sera utilisé.

En fait, Kotlin/Native utilise le format des KLibs pour distribuer les bibliothèques natives Kotlin depuis un certain temps, et nous en étendons maintenant le format pour prendre en charge d’autres back-ends et bibliothèques multiplateformes. Le format sera expérimental dans la version 1.4 et nous prévoyons de fournir un ABI stable dans les futures versions.

Plus d’actualités multiplateformes

Exécution de code iOS dans Android Studio

Nous travaillons sur un plugin pour Android Studio qui pourra exécuter, tester et déboguer le code Kotlin sur les appareils iOS et les simulateurs. Le plugin utilise du code propriétaire d’IntelliJ, il sera donc à source fermée. Il n’apportera pas de prise en charge linguistique pour Objective-C ou Swift, et certaines opérations telles que le déploiement sur AppStore pourront nécessiter l’exécution de Xcode, mais tout ce que vous ferez avec le code Kotlin fonctionnera à partir d’Android Studio avec le nouveau plugin installé. Nous prévoyons de proposer un aperçu de ce plugin en 2020.

Améliorations de l’exécution de Kotlin/Native

En plus de Linux, Windows, macOS et iOS, Kotlin/Native fonctionne maintenant sur watchOS et tvOS. Pratiquement tous les appareils peuvent donc exécuter Kotlin. Nous travaillons également sur les performances d’exécution de Kotlin/Native pour accélérer encore les programmes iOS Kotlin.

Bibliothèques principales

Les bibliothèques principales de Kotlin fonctionnent sur toutes les plateformes. Cela inclut kotlin-stdlib qui gère tous les types et collections de base, kotlinx.coroutines, kotlinx.serialization et kotlinx.io. La prise en charge des dates est vraiment nécessaire dans le monde multiplateforme et c’est sur cela que nous travaillons : des durées expérimentales ont déjà été ajoutées à stdlib et la prise en charge de DateTime est en cours.

Autre ajout important aux bibliothèques Kotlin : Flow, une implémentation de Reactive Streams basée sur les coroutines. Flow est excellent pour le traitement des flux de données et il utilise la puissance de Kotlin pour cela. Outre son ergonomie, Flow apporte plus de vitesse. Sur certains benchmarks, il est presque 2 fois plus rapide que les implémentations de Reactive Streams populaires.

Pour les auteurs de bibliothèques

Comme la création de nouvelles bibliothèques est vitale pour l’écosystème Kotlin, nous continuons d’améliorer l’expérience des auteurs de bibliothèques. Le nouveau mode de création des bibliothèques vous aidera à façonner votre code de façon optimale pour obtenir des API stables. De plus, nous allons publier Dokka 1.0 pour prendre en charge la génération de documents pour toutes les plateformes.

Web multiplateforme

Le partage de code entre les plateformes est idéal pour les mobiles, mais également pour les clients Web : beaucoup peuvent être partagés avec le serveur ou avec des applications mobiles. Nous investissons de plus en plus dans les outils Kotlin/JS, et pouvons désormais effectuer des allers-retours de développement très rapides, entre le changement de code Kotlin et la visualisation des résultats dans le navigateur :

Nous avons également amélioré JS interop afin que vous puissiez désormais associer une dépendance NPM à un projet Kotlin et que toutes les définitions de type .d.ts soient récupérées automatiquement par la chaîne d’outils Kotlin.

Le nouveau back-end IR apportera également des améliorations considérables à la taille des binaires. Les fichiers JS compilés peuvent être réduits à la moitié de leur taille actuelle.

Nouvelles fonctionnalités de langage

Kotlin 1.4 apportera quelques nouvelles fonctionnalités linguistiques.

Conversions SAM pour les classes Kotlin

La communauté nous a demandé de prendre en charge les conversions SAM pour les classes Kotlin (KT-7770). La conversion SAM s’applique si vous passez une lambda comme argument lorsqu’une interface ou une classe ne comportant qu’une seule méthode abstraite est attendue comme paramètre. Le compilateur convertit alors automatiquement la lambda en une instance de la classe implémentant la fonction membre abstraite.

Les conversions SAM ne fonctionnent actuellement que pour les interfaces Java et les classes abstraites. L’idée initiale derrière cette conception était d’utiliser explicitement les types de fonction pour de tels cas d’utilisation. Il s’est cependant avéré que les types de fonction et les alias de types ne couvraient pas tous les cas d’utilisation et qu’il fallait donc souvent garder une interface en Java uniquement pour obtenir une conversion SAM.

Contrairement à Java, Kotlin ne permettra pas une conversion SAM pour chaque interface avec une seule méthode abstraite. Nous pensons qu’une intention de rendre une interface applicable à la conversion SAM devrait être explicite. Ainsi, pour définir une interface SAM, vous devrez marquer une interface avec le mot-clé fun, pour souligner qu’elle peut être utilisée en tant qu’interface fonctionnelle :

Notez que le passage d’une lambda au lieu d’une interface fun ne sera pris en charge que dans un nouvel algorithme d’inférence de type.

Mélange d’arguments nommés et positionnels

Kotlin interdit de mélanger des arguments comportant des noms explicites (“nommés”) et des arguments normaux sans noms (“positionnels”), à moins que vous ne placiez tous les arguments nommés après tous les arguments positionnels. Il existe toutefois un cas dans lequel c’est vraiment problématique : lorsque tous les arguments restent dans leur position correcte et que vous souhaitez spécifier un nom pour un argument qui se trouve au milieu. Kotlin 1.4 résoudra ce problème, vous pourrez donc écrire du code comme :

Optimisation des propriétés déléguées

Nous allons améliorer la compilation sous-jacente de la propriété lazy et de quelques autres propriétés déléguées.

En règle générale, une propriété déléguée peut accéder à l’objet de réflexion KProperty correspondant. Par exemple, lorsque vous utilisez Delegates.observable, vous pouvez afficher des informations sur la propriété modifiée :

Pour rendre cela possible, le compilateur Kotlin génère une propriété de membre syntaxique supplémentaire, un tableau stockant tous les objets KProperty qui représente les propriétés déléguées utilisées dans la classe :

Cependant, certaines propriétés déléguées n’utilisent pas du tout KProperty. Pour celles-ci, la génération d’un objet dans $$delegatedProperties n’est pas optimale. La version Kotlin 1.4 optimisera ces cas. Si les opérateurs de propriété délégués sont inlige et que le paramètre KProperty n’est pas utilisé, les objets de réflexion correspondants ne seront pas générés.

L’exemple le plus remarquable est la propriété lazy. L’implémentation de getValue pour la propriété lazy est inline et n’utilise pas le paramètre KProperty :

À partir de Kotlin 1.4, lorsque vous définirez une propriété lazy, l’instance KProperty correspondante ne sera plus générée. Si les seules propriétés déléguées que vous utilisez dans une classe sont des propriétés lazy (et d’autres propriétés conformes à cette optimisation), aucun tableau $$delegatedProperties ne sera généré pour la classe :

Virgules de fin

Cette modification syntaxique mineure s’avère incroyablement pratique ! Vous pouvez placer une virgule de fin supplémentaire après le dernier paramètre d’une liste de paramètres. Vous pouvez ensuite échanger des lignes ou ajouter de nouveaux paramètres sans avoir à ajouter ou supprimer de virgules.

Autres changements notables

Une fonction typeof utile introduite dans Kotlin 1.3.40 va devenir stable et prise en charge sur toutes les plateformes.

La fonctionnalité qui vous permet d’activer break et continue à l’intérieur de when était déjà décrite dans l’article de blog de la version 1.3.60 .

Merci !

Nous remercions tous ceux qui ont essayé les versions EAP de Kotlin et les fonctionnalités expérimentales et nous faire part de leurs retours d’expérience. Nous développons le langage Kotlin avec vous et beaucoup de nos décisions de conception reposent sur vos précieuses contributions. Préserver la rapidité et l’efficacité de cette boucle de rétroaction avec la communauté est vraiment important pour développer et améliorer Kotlin !

Nous sommes vraiment reconnaissants à tous les membres de notre communauté qui créent tant de choses incroyables avec Kotlin. Continuons à Kotliner ensemble !

Au fait, le plugin Kotlin dans IntelliJ IDEA et Android Studio recueille des statistiques anonymisées sur votre utilisation de ses fonctionnalités. Nous vous prions de bien vouloir activer ces statistiques, car elles nous aident à comprendre ce qui fonctionne, ce qui pose problème et sur quelles améliorations nous devons nous concentrer.

Auteur de l’article original en anglais : Svetlana Isakova