Voir le flux RSS

bouye

[Actualité] Du bon usage de var

Noter ce billet
par , 04/04/2018 à 02h56 (814 Affichages)
La sortie récente du JDK 10 a vu débouler le mot-clé var dans le petit monde de Java ; ainsi comme dans d'autres langages avant lui (C#, JavaScript, etc.), lors de la déclaration de variables locales, il est désormais possible de remplacer :

Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
String message = "Salut le monde !";
Par :
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
var message = "Salut le monde !";

Derrière cette nouvelle syntaxe se cache le JEP 286 - Local-Variable Type Inference (inférence du type des variables locale) destiné à simplifier la vie du développeur ou, selon les mots de son créateur : rendre l’écriture du code Java moins cérémoniale (c'est-à-dire moins "lourdingue"). Ainsi désormais ces 3 lignes sont à peu près équivalentes :

Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
List<String> list = new Arraylist<String>(); // JDK 5.
 
List<String> list = new Arraylist<>();       // JDK 7.
 
var list = new Arraylist<String>();          // JDK 10.

Dans tous les cas, le compilateur saura retrouver le bon type de la variable et acceptera qu'on puisse appliquer les méthodes de l'interface List<String> sur cette variable.

Cependant comme toute nouvelle fonctionnalité, il ne faut pas en abuser quand ce n'est pas nécessaire sous risque de rendre le code illisible, incompréhensible et surtout difficile à maintenir par un autre développeur ou même pour soi. L'OpenJDK vient donc de publier un guide pour l'usage du mot-clé var. Ce guide repose sur quelques principes fondamentaux :

  1. Il est plus important de pouvoir lire du code que de l’écrire - être concis c'est bien, mais pas aux dépens de la relecture ou de la compréhension ;
  2. Le code ne doit pas être dépendant d'une réflexion locale - s'il faut regarder à plusieurs endroits pour arriver à comprendre ce que fait une variable, c'est qu'il y a un souci ;
  3. On ne doit pas se reposer sur son IDE - le code peut être amené à être lu avec des outils divers (autres IDE ou même simple éditeur de texte) ; on ne doit pas se reposer sur un IDE en particulier pour savoir ce que fait cette variable. Utiliser l'IDE pour explorer la variable est déjà en soi une distraction dans l’exercice de programmation ;
  4. Le typage explicite est un compromis - déclarer un type local alourdit certes le code, mais il permet d'un autre côté la compréhension claire et immédiate de ce que ce code effectue.


En se reposant sur ces principes, l'auteur avance donc les règles d'utilisation suivantes :

1. Choisir un nom de variable qui fournit une information
C'est une règle de programmation basique, mais elle devient encore plus nécessaire lorsqu'on utilise le mot-clé var : le code devient tout de suite beaucoup plus parlant si l'information qui auparavant était fournie par le typage est désormais contenue dans le nom de la variable.

2. Minimiser la portée des variables locales
À nouveau une règle de bonne conduite assez basique, mais souvent peu respectée : ici, il ne s'agit pas simplement d'optimisation ou de gestion de la mémoire, mais tout simplement du fait que si une variable déclarée en var est utilisée dans un énorme bloc de code, il y a de fortes chances pour que vous ayez oublié quel est son type lorsque vous êtes enfin arrivé sur la ligne en question et que vous êtes amené à l'utiliser. Vous allez donc devoir repartir en arrière jusqu’à sa déclaration ou son affectation et essayer de vous souvenir quel est son type concret. Si vous êtes amené à faire des modifications sur le type de la variable, vous allez devoir repasser tout le bloc au peigne fin pour savoir quel impact cela a de changer le type.

3. Utiliser var lorsque l'initialisation donne suffisamment d'information au lecteur
La plupart du temps les variables locales sont initialisées en invoquant des constructeurs avec l’opérateur new ou encore des méthodes de fabrique. Dans ces deux cas l'information sur le type est on ne peut plus claire et donc il est tout à fait approprié d'utiliser var.

4. Utiliser var pour découper des expressions chaînées ou encastrées avec des variables locales
L'introduction des flux de données (data streams) dans le JDK 8 a permis de saisir du code concis et performant, mais qui peut se révéler obtus, difficile à relire et dont on peut avoir du mal à saisir toutes les subtilités lorsqu'on enchaîne trop de commandes les unes derrière les autres. Lorsque trop de commandes s’enchaînent, il convient donc de découper sa chaîne en plusieurs parties ; l'utilisation de var permettant de simplifier le typage de chacune des sous-parties en rendant le code plus léger que si on avait dû écrire tous les types comme auparavant.

5. C'est une variable locale, pas besoin de se casser la tête avec l'interface de base !
Ici il est bon de rappeler que var ne peut être utilisé que sur les variables locales et aucunement sur les membres d'instances ou statiques ni même sur les paramètres ou le type de retour des méthodes. Le mot-clé var n'a donc aucun impact dans ces secteurs pour lesquels la règle reste d'utiliser le type le plus généraliste quand cela est possible.

Évidemment classiquement, et comme c'est recommandé, on a tendance à vouloir utiliser les super-interfaces plutôt que les classes concrètes pour le typage des variables locales. Cependant lorsque le type est inféré c'est automatiquement le type concret qui est choisi par le compilateur. Du coup, nous pouvons utiliser toutes les méthodes du type concret ce qui peut former une dépendance dure envers ce type. Si jamais nous sommes amenés à changer le type utilisé pour initialiser la variable, le compilateur générera immédiatement des erreurs en cas d’incompatibilité. Si nous avons respecté la règle de la portée courte, l'impact sera minimal et facile à corriger.

6. Attention à l'utilisation du diamant et des génériques !
Évitez de mélanger var et l’opérateur diamant <> lorsque vous utilisez des génériques ! Ces deux syntaxes sont destinées à alléger l’écriture du code, mais pas à être utilisées ensemble. Le fait de ne plus avoir de type explicite à droite comme à gauche de l'expression d'initialisation va faire que le type le plus général (à savoir Object) va être utilisé.

De manière similaire, l'utilisation de certaines méthodes de fabrique génériques peut être dangereuse lorsque le manque d'argument ne permet pas au compilateur d’inférer le type. Par exemple List.of() : il n'y a aucun souci lorsque la méthode de fabrique dispose d'au moins un argument ; dans ce cas le compilateur pourra inférer le type. Par contre lorsqu'elle n'en a pas, le compilateur ne pourra pas inférer le type et c'est donc le type Object qui sera utilisé.

7. Attention à l'utilisation des littéraux !
Il est tout à fait possible d'utiliser des valeurs littérales pour initialiser des variables déclarées en tant que var. Cela ne pose pas de souci pour des valeurs de type boolean, char, long ou String du fait de leur syntaxe explicite de déclaration (ex. : true, 'a', 10L, "Salut").

Par contre, il faudra faire extrêmement attention aux variables de type byte, short et long qui sont initialisées via des valeurs littérales en notation entière qu'elles soient octales, décimales ou hexadécimales (ex. : 0158, 17, 0x00ff) ; en effet, le compilateur peut être amené à changer le type de votre variable pour les inférer en int !

Pour les nombres flottants, de manière générale, les types sont inférés correctement du fait de la déclaration distincte des valeurs qui sont explicites (ex. : 3.0f, 5.5d). Mais il arrive que dans du code on puisse initialiser une variable locale de type double initialisée à partir d'un champ de type float ; si on utilise var à la place de double alors cette variable sera inférée en type float !

Source : Style Guidelines for Local Variable Type Inference in Java par Stuart W. Marks

Envoyer le billet « Du bon usage de var » dans le blog Viadeo Envoyer le billet « Du bon usage de var » dans le blog Twitter Envoyer le billet « Du bon usage de var » dans le blog Google Envoyer le billet « Du bon usage de var » dans le blog Facebook Envoyer le billet « Du bon usage de var » dans le blog Digg Envoyer le billet « Du bon usage de var » dans le blog Delicious Envoyer le billet « Du bon usage de var » dans le blog MySpace Envoyer le billet « Du bon usage de var » dans le blog Yahoo

Mis à jour 08/04/2018 à 17h59 par ClaudeLELOUP

Catégories
Java , Java

Commentaires

  1. Avatar de longbeach
    • |
    • permalink
    Le mot-clé VAR existe dans C# depuis 2007. Il y a donc plus de 10 ans.
    En Java, ça vient tout juste de pointer son bout du nez ...
  2. Avatar de bouye
    • |
    • permalink
    Citation Envoyé par longbeach
    Le mot-clé VAR existe dans C# depuis 2007. Il y a donc plus de 10 ans.
    En Java, ça vient tout juste de pointer son bout du nez ...
    var existe en ECMA-Script depuis 1997 et C# a seulement attendu 2007 pour supporter ça ! Et ben dis donc.......................
    Mince ca existe en Pascal et d'autres languages depuis plus longtemps encore...

    Tu en as d'autres des remarques intéressantes et constructives ?
    Mis à jour 10/04/2018 à 00h35 par bouye
  3. Avatar de longbeach
    • |
    • permalink
    Pas la peine de répondre de manière agressive.
    Ah mais je vois, c'est toi qui est l'auteur de ce billet. Je comprends mieux ta réaction ...
    Bon, comme d'habitude, vaut mieux se taire plutôt que d'essayer de participer sinon on obtient ce genre de réponse.
  4. Avatar de Dasoft
    • |
    • permalink
    Javascript implémente var parce que c'est un langage faiblement typé contrairement à C# et le langage Pascal a le mot clé var mais c'est pas du tout le même rôle donc hors sujet.
    Longbeach a raison de prendre le C# en exemple car il a été précurseur de l'inférence de type sur les langages fortement typé.
    Maintenant, vous pouvez vous serrer la main
  5. Avatar de longbeach
    • |
    • permalink
    Dasoft: tout à fait.
    Merci à toi pour cette précision que je n'ai pas voulu apporter de peur qu'on m'accuse d'ajouter de l'huile sur le feu.
    De plus, je ne me serais pas amusé à faire cette comparaison avec C# s'il ne s'agissait pas aussi d'inférence de type.

    D'ailleurs, ce n'est pas une compétition : chaque langage s'inspire d'autre langage pour ajouter de nouvelles fonctionnalités et c'est très bien comme ça.
    C# a copié Java et Java a copié C#.
  6. Avatar de Rizzen
    • |
    • permalink
    Je suis pas fan, perso je n'en voie aucun intérêt à par que ça va devenir n'importe quoi. Surtout pour gagner 3 caractères en moins à écrire. #faignasse

    Quand je voie déjà comment sont utilisé des améliorations comme les lambda, qui apportent vraiment pas mal de souplesse. J'ai peur de voir des var partout et qu'on arrive plus du tout à comprendre et aussi avec des bugs à tour de bras car le compilateur décide d'un format différent de ce que croyait avoir le "dev". Je parle même pas de ceux qu'on appelle développeur en France mais qui ne connaissent rien à l'héritage ou au polymorphisme et pissent du code sans le comprendre T_T.