Go n’a pas besoin de génériques – DZone Web Dev


Sommaire

Une etude recente (https://blog.golang.org/survey2019-results) suggère que 79% des répondants estiment que les génériques sont une caractéristique manquante «critique» de Go.

Je peux seulement supposer que ces programmeurs doivent:

  • J’ai une notion très différente de la critique que la mienne.
  • Travailler dans des domaines problématiques très différents.
  • Exagérer.
  • Une combinaison de ce qui précède.

Je n’essaierai pas de déterminer ce qui s’applique. Je vais plutôt simplement expliquer pourquoi je n’ai jamais pensé que Go avait besoin de génériques. Je vais commencer par expliquer ce que j’ai trouvé en utilisant des génériques pendant des années en Java, des versions 1.5 à 1.8.

Je dirai que je ne suis pas un programmeur religieux. Je n’ai pas de phrases sur la programmation impliquant des phrases comme “doit”, “jamais”, “toujours”, “tu ne peux pas”, etc. personne à mon avis. Si quelqu’un pense que les génériques sont super importants, c’est un pays libre.

Génériques Java

J’ai commencé à utiliser Java personnellement dès sa sortie et j’ai commencé à l’utiliser professionnellement avec Java 1.5. Lorsque les génériques sont arrivés pour la première fois dans Java 1.5, je n’ai pas soupiré de soulagement. J’avais principalement utilisé des génériques dans les listes et les cartes, et je n’ai pas trouvé que le casting était un fardeau. Après tout, vous n’avez besoin de lancer que lorsque vous retirez des objets (retourne le résultat) et non lorsque vous les placez (paramètres).

Techniquement, l’utilisation de listes brutes et de cartes en Java permet d’ajouter des types différents et aléatoires et d’obtenir probablement des ClassCastExceptions lors de la lecture de valeurs. Dans la pratique, la plupart des listes et des cartes sont localisées dans une méthode – la structure est créée à l’intérieur d’une méthode et jetée avant son retour. Dans de telles utilisations localisées, il est assez évident de savoir quel type de données est censé être utilisé, donc la conversion correcte des valeurs n’est guère difficile.

Peu importe si vous devez exprimer des valeurs lorsque vous les retirez? Après tout, l’effacement de type Java nécessite l’ajout de transtypage au code qui utilise de toute façon des résultats de retour génériques. Ce n’est pas parce que vous ne le voyez pas qu’il n’est pas là.

J’ai rencontré quelques problèmes avec les génériques en Java, je vais juste donner quelques exemples.

Les développeurs Java ne comprennent pas plus que les bases

Essayez de poser à 10 développeurs Java les questions suivantes et voyez combien ils sont corrects (il est probable que ce sera zéro):

  • Comment puis-je acquérir Class >?
  • Quelle est la différence entre List, Listeet Liste?
  • Dans quelles conditions un type générique est-il conservé au moment de l’exécution, plutôt que perdu à l’effacement de type?
  • Si un type générique est conservé lors de l’exécution, comment puis-je déterminer s’il s’agit de Map par réflexion?

D’après mon expérience, les développeurs moyens ne comprennent pas ces détails et s’en moquent tout simplement. Ils le voient comme hors de propos car ils n’écrivent presque jamais leurs propres classes ou méthodes génériques. Leur utilisation des génériques est généralement limitée aux collections.

Les génériques sont difficiles à utiliser dans les bibliothèques et les cadres

Je ne pense pas? Essayez d’en écrire un! Essayez de gérer les éléments suivants:

  • Types primitifs et objets
  • Veiller à ce que les primitives et leurs enveloppes associées soient traitées de manière interchangeable
  • Gestion des tableaux génériques, des caractères génériques, des limites inférieures, des limites supérieures et des variables de type
  • Analyser les signatures génériques des champs, des paramètres et des types de retour pour s’assurer qu’ils suivent un modèle attendu
  • Traduire des objets entre différents types génériques (par exemple traduire une liste lister<[]String> en mappant chaque chaîne à un tableau à un élément)

Quel est le véritable avantage?

Si les développeurs n’utilisent en moyenne que des génériques pour les collections, et qu’il est difficile d’écrire avec des bibliothèques, alors ne va-t-il pas de soi que les collections sont leur seul cas d’utilisation significatif? Peut-être que les concepteurs de Go l’ont compris et l’ont appliqué en créant des tranches et des cartes de Go intrinsèquement génériques grâce à la syntaxe du langage.

Mes collègues, qui, comme moi, ont appris Go en provenance de Java, n’ont jamais fait mention de génériques au cours de l’année et des mois qui ont suivi l’utilisation de Go. Littéralement, le mot n’a échappé aux lèvres de personne. Je suis confiant si je leur demandais quel était leur facteur de soin, ils diraient que les tranches et les cartes sont assez bonnes, tout comme moi.

Stratégies en cours

Étant donné que Go n’a pas de génériques, du moins pour l’instant, il est judicieux de trouver des moyens de le gérer. Je peux penser à quelques simples.

Le plus évident est de souligner que nous pouvons tout passer pour les paramètres d’interface vides, c’est uniquement pour les types de retour que nous devons transtyper. Utiliser des paramètres chaque fois que c’est possible est la solution la plus simple.

Dans un autre article sur le modèle de conception des visiteurs, j’ai montré une stratégie consistant simplement à ne pas déclarer la seule méthode du modèle qui devrait renvoyer différents types dans les interfaces déclarées. Au lieu de cela, laissez chaque implémentation de structure déclarer la méthode pour renvoyer le type requis. En effet, nous avons un contrat de conception – chaque implémentation devrait fournir un certain nom de méthode avec une signature similaire, elle n’est tout simplement pas formalisée avec une interface.

Supposons qu’une structure possède un petit nombre de méthodes qui retournent une interface vide. Une autre structure pourrait en incorporer une instance et déclarer à nouveau les quelques méthodes en question pour renvoyer un type particulier. L’implémentation appellerait simplement la méthode struct intégrée et transtyperait le type au nom de l’appelant, comme ceci:

Voir Go Playground

Conclusion

J’espère personnellement que Go n’a jamais de génériques, ou si c’est le cas, les concepteurs trouvent un moyen d’éviter la complexité et les difficultés que j’ai vues dans les génériques Java et les modèles C ++. Il n’y a pas de problèmes importants en utilisant du vieux code Go simple, et il correspond parfaitement à mes propres préférences. Go est une bouffée d’air frais, en particulier parce que la communauté semble généralement épouser la simplicité sur des cadres géants trop compliqués. J’espère sincèrement que rien de tout cela ne changera jamais dans Go.

Close Menu