
En avril, le langage Go s’est doté d’un nouveau logo, une première étape dans la refonte de l’image du langage. Désormais, place à la conception de Go 2 annoncé l’année dernière. À l’occasion du sommet de contributeurs de Go qui se tient annuellement, les participants ont eu droit à un avant-goût des ébauches de possibles designs pour les changements à venir dans le langage. Dans le cadre de ce processus de design de Go 2, l’équipe de développement a publié ces brouillons afin de lancer le débat sur trois sujets : la généricité, la gestion des erreurs et la sémantique des valeurs d’erreur.
La gestion d’erreurs
L’effort autour de Go 2 a pour objectif global de se pencher sur les façons les plus significatives qui empêchent Go de garder son évolutivité à de larges bases de code et d’amples efforts de développeurs.
« Une façon qui fait que les programmes Go échouent à garder leur évolutivité réside dans l’écriture du code de vérification et de gestion d’erreurs, » a écrit Russ Cox, développeur de Google. « En général, les programmes de Go ont trop de code de vérification d’erreurs et pas assez pour s’en charger. L’ébauche du design vise à se pencher sur ce problème en introduisant une syntaxe allégée pour le contrôle d’erreur. »
Pour assurer l’évolutivité de larges bases de code, les programmes de Go doivent être légers sans répétition inutile, mais aussi robustes et gérant avec élégance les erreurs lorsqu’ils remontent en surface.
« Dans le design de Go, nous avons fait un choix conscient d’utiliser des résultats et des contrôles d’erreurs explicites. Par opposition, C typiquement utilise le contrôle explicite d’un résultat d’erreur implicite, errno, alors que la gestion d’exception, se trouvant dans beaucoup de langages comme C++, C#, Java et Python, représente un contrôle implicite de résultats implicites, » a écrit Cox.
« Les subtilités du contrôle implicite sont traitées dans « Cleaner, more elegant, and wrong » (2004), et « Cleaner, more elegant, and harder to recognize » (2005). En substance, parce que vous ne pouvez pas voir les contrôles implicites, il est difficile de vérifier par inspection que la gestion d’erreurs se recouvre de l’état du programme au moment où il y a un échec de contrôle. »
Cox a donné un exemple pour illustrer ce problème. On prend en considération ce code écrit en Go avec des exceptions :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 | func CopyFile(src, dst string) throws error { r := os.Open(src) defer r.Close() w := os.Create(dst) io.Copy(w, r) w.Close() } |
D’autre part, l’équivalent de ce code aujourd’hui est :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | func CopyFile(src, dst string) error { r, err := os.Open(src) if err != nil { return err } defer r.Close() w, err := os.Create(dst) if err != nil { return err } defer w.Close() if _, err := io.Copy(w, r); err != nil { return err } if err := w.Close(); err != nil { return err } } |
Le code a aussi une seconde omission dans son contrôle des erreurs. Les fonctions doivent inclure typiquement des informations pertinentes sur leurs arguments dans leurs erreurs, comme os.Open qui retourne le nom du fichier ouvert. Retourner l’erreur non modifiée produit un échec sans aucune information sur la séquence d’opération qui a conduit à cette erreur.
Pour résumer, ce code inclut beaucoup trop de vérifications d’erreur et pas assez de contrôle. Une version plus robuste avec plus d’erreurs utiles serait :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | func CopyFile(src, dst string) error { r, err := os.Open(src) if err != nil { return fmt.Errorf("copy %s %s: %v", src, dst, err) } defer r.Close() w, err := os.Create(dst) if err != nil { return fmt.Errorf("copy %s %s: %v", src, dst, err) } if _, err := io.Copy(w, r); err != nil { w.Close() os.Remove(dst) return fmt.Errorf("copy %s %s: %v", src, dst, err) } if err := w.Close(); err != nil { os.Remove(dst) return fmt.Errorf("copy %s %s: %v", src, dst, err) } } |
Valeurs d'erreur et programmation générique
De ce fait, Cox note que Go 2 vise à rendre le contrôle d’erreurs plus léger, en réduisant la quantité du texte dans le programme Go dédié à la vérification d’erreurs. Il y a aussi l’envie de rendre l’écriture de gestion d’erreurs plus pratique, ce qui augmente la chance que les programmeurs vont allouer du temps à le faire. Tout ça sans mentionner le fait que la vérification et le contrôle d’erreurs doit rester explicite, donc explicite dans le texte du programme.
En plus de la gestion d’erreur, l’équipe veut faire en sorte que les programmes larges doivent être en mesure de tester et réagir aux erreurs et aussi les rapporter d’une bonne façon.
« Une façon qui fait que les programmes en Go échouent à bien garder leur évolutivité réside dans la capacité d’erreurs typiques. Une variété de paquets populaires ajoute des fonctionnalités qui vont au-delà de l’interface d’erreur standard, mais dans des façons incompatibles, » a écrit Cox. « Avec Go 2, nous envisageons de standardiser des “interfaces optionnelles” pour des erreurs afin de permettre aux paquets d’interopérer et idéalement en réduire le besoin. »
Pour faire cela, Cox a cité deux objectifs qui correspondent à ces problèmes : d’abord, il y a un besoin de rendre l’inspection par programmes plus facile et moins exposée aux erreurs, le but étant d'améliorer le contrôle d’erreurs et la robustesse des programmes réels. Deuxièmement, l’équipe veut rendre possible l’impression d’erreurs avec des détails additionnels dans une forme standard.
Enfin, l’équipe a parlé de la programmation générique et comment elle compte l’implémenter dans Go. En programmation, la généricité (ou programmation générique), consiste à définir des algorithmes identiques opérant sur des données de types différents. On définit de cette façon des procédures ou des types entiers génériques. On pourrait ainsi programmer une pile, ou une procédure qui prend l'élément supérieur de la pile, indépendamment du type de données contenues.
Cox note que l’équipe est consciente du potentiel de la généricité, pour rendre Go plus flexible et puissant et en même temps loin d’être plus compliqué. En gros, l’équipe veut rendre possible le polymorphisme paramétrique avec des paramètres de type. Mais cette implémentation va se faire à petits pas histoire d’apprendre et éviter les problèmes que la généricité a causés dans C++ et Java.
Pour consulter en détail ces brouillons, veuillez consulter les documents publiés par l’équipe de Go.
Source : googlesource
Et vous ?



Voir aussi


