Ceux qui me lisent régulièrement savent que je suis plutôt orienté C# / .NET plutôt que plateforme Java. Ce qui ne veut pas dire que je rejette toute JVM en bloc. J’ai utilisé du Java pour mon job d’architecte lorsque cela s’est avéré plus intéressant, et j’ai bossé un bout de temps sur le client Java de mon ancien employeur. J’ai encore récemment choisi Java pour animer une de mes conférences sur la prévalence.
Mais personnellement, j’ai une préférence pour C#. J’ai eu l’an passé le plaisir de présenter une session “Java compareTo .NET” avec Nicolas De Loof lors du BreizhCamp, et (en toute malhonnêteté), j’ai été gentil de ne pas trop insister là où ça faisait mal : Linq, prise en main par Oracle, retard dans les versions, etc.
Toutefois, un sain émolument nécessite deux bons concurrents, et je suis content de voir que Java reprend – un peu – de poil de la bête avec les nouvelles versions. Mon esprit pinailleur (ainsi que le désir irrépressible de taquiner Nicolas) m’amène toutefois à formuler deux-trois remarques, à partir de ce que j’ai lu ici.
Diamond
L’écriture ci-dessous est un peu lourde, c’est vrai :
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
Java en version 7 propose de la raccourcir sous cette forme :
Map<String, List<String>> myMap = new HashMap<>();
C# a une autre approche, à savoir :
var myMap = new Map<String, List<String>>();
Et bien, vous ne serez peut-être pas surpris outre mesure, mais je pense sincèrement que la grammaire C# est plus logique. Lorsqu’on crée une instance, on a toujours besoin de connaitre le type de ce qui va être créé, tandis que le type de la variable qui va pointer dessus est moins important. Dans la plupart des cas, il reprend simplement le type de la classe, mais les quelques pourcents qui restent sont utilisés typiquement avec une classe de plus haut niveau dans la hiérarchie d’héritage ou une interface que la classe instanciée implémente.
Du coup, n’est-ce pas plus dans le sens du polymorphisme d’écrire ceci :
// Même chose Chien c = new Chien(); var d = new Chien(); // Polymorphisme Animal a = new Chien();
En effet, dans tous les cas, c’est bien une instance de Chien qu’on crée, mais dans un cas, on reste sur une variable de référence qui est par défaut, et dans l’autre, on utilise une classe plus haute. A côté, Java parait moins logique, car le type de la variable peut changer, mais aussi la façon d’écrire le type à instancier.
En plus, le mot clé var de C# fonctionne dans tous les cas, et pas seulement les génériques, mais n’importe quelle classe, y compris les classes anonymes.
Catch multiple
Là, on va peut-être me dire que je suis passé à côté de quelque chose, mais pourquoi écrire quelque chose comme ceci ?
catch (IOException|SQLException ex) { logger.log(ex); throw ex; }
Je ne dis pas que le fait de catcher plusieurs exceptions en même temps soit une mauvaise idée, mais ce qui m’embête vraiment dans cette grammaire, pour le coup, c’est qu’une variable ne soit pas précisément typée. Comment sait-on quel membre on peut lire sur ex ? Ceux de IOException ? Ceux de SQLException ? Ceux communs ? Et dans ce cas-là, à quel niveau de communauté dans la hiérarchie d’héritage ?
Il y a peut-être quelque chose que je ne comprends pas sur les exceptions Java, qui ne fonctionnent pas comme celles de C# où toutes doivent dériver de System.Exception, mais je ne vois pas comment des outils comme la validation de type statique ou la complétion automatique peuvent fonctionner sur ce genre de grammaire…
Linq
En voyant ceci, j’étais à deux doigts de féliciter Oracle pour avoir enfin reproduit Linq dans Java (ce qui à mon sens est un grand manque) :
double max = students.filter(#{Student s -> s.gradYear == 2010})
.map(#{Student s -> s.score})
.max();
Mais je viens de voir que ceci était planifié pour la version 8, prévue pour le deuxième semestre 2012. Dommage… Surtout si Oracle est aussi en retard que pour la version 7 (désolé, Nico, c’est du mauvais esprit )
Conclusion
J’espère que ce blog ne parait pas trop peu constructif : je taquine, mais le but n’est pas de polémiquer. J’aime bien le monde Java aussi, surtout pour le foisonnement de projets d’une grande richesse (je rêve en particulier d’avoir les fonctionnalités de Prevayler dans Bamboo), mais ces quelques points me confortent dans l’idée que l’approche de Microsoft est plus cohérente globalement (je n’ai pas dit meilleure, juste cohérente). C’est certainement bêtement dû au fait que Microsoft est seul à la barre du langage, mais je trouve ça appréciable.
Quelques dernières remarques (en espérant qu’elles réussiront à éloigner les trolls anti-Microsoft des commentaires) :
- Je ne pense pas qu’Oracle ou Google abusent non plus de la philanthropie
- Ce genre de ressource montre que Microsoft a compris que ses intérêts passaient aussi par un certain niveau d’ouverture, même s’ils restent bien sûr une entreprise commerciale
- Le langage C# est normalisé ECMA
- La CLI est normalisée ECMA
- De la même manière que Java a son implémentation GNU, .NET a son implémentation libre, à savoir Mono, maintenant passé sous la bannière Xamarin.
- Et pour finir, même les modules additionnels (c’était le dernier argument des acharnés) sont désormais également en Open Spec
Excellent article. J’ai appris à programmer en langage C# grâce à des vidéos sur http://www.alphorm.com/tutoriel/formation-en-ligne-programmer-en-csharp-avec-visual-studio-2015. Cependant, je trouve cet article très captivant. Je vais l’étudier de très près. Merci pour le partage.