La notation hongroise est-elle une solution de contournement pour les langues avec un typage statique insuffisamment expressif? [fermé]

28

Dans l'article d'Eric Lippert Qu'est-ce qui se passe avec la notation hongroise? , il déclare que le but de la notation hongroise (le bon type) est de

étendre le concept de "type" pour englober les informations sémantiques en plus des informations de représentation de stockage.

Un exemple simple serait de préfixer une variable qui représente une coordonnée X avec "x" et une variable qui représente une coordonnée Y avec "y", que ces variables soient des nombres entiers ou flottants ou autre, de sorte que lorsque vous écrivez accidentellement xFoo + yBar, le code semble clairement faux.

Mais j'ai également lu sur le système de types de Haskell, et il semble que dans Haskell, on puisse accomplir la même chose (c'est-à-dire "étendre le concept de type pour englober les informations sémantiques") en utilisant des types réels que le compilateur vérifiera pour vous. Ainsi, dans l'exemple ci-dessus, xFoo + yBardans Haskell, la compilation échouerait si vous avez correctement conçu votre programme, car ils seraient déclarés comme des types incompatibles. En d'autres termes, il semble que le système de type de Haskell supporte efficacement la vérification à la compilation équivalente à la notation hongroise

Ainsi, la notation hongroise est-elle juste un pansement pour les langages de programmation dont les systèmes de types ne peuvent pas coder les informations sémantiques? Ou la notation hongroise offre-t-elle quelque chose au-delà de ce qu'un système de type statique comme celui de Haskell peut offrir?

(Bien sûr, j'utilise Haskell comme exemple. Je suis sûr qu'il existe d'autres langages avec des systèmes de type également expressifs (riches? Forts?), Bien que je n'en ai pas rencontré.)


Pour être clair, je ne parle pas d'annoter des noms de variables avec le type de données , mais plutôt des informations sur la signification de la variable dans le contexte du programme. Par exemple, une variable peut être un entier ou flottant ou double ou long ou autre, mais peut-être que la signification de la variable est que c'est une coordonnée relative x mesurée en pouces. C'est le genre d'informations dont je parle sur l'encodage via la notation hongroise (et via les types Haskell).

Ryan C. Thompson
la source
Pascal - bien que si vous essayez d'ajouter un type XCood et YCoord que vous avez défini dans Pascal, vous obtiendrez juste un avertissement du compilateur IIRC
mcottle
1
blog.moertel.com/articles/2006/10/18/… est un article sur la façon de faire quelque chose de très similaire aux "applications hongroises" dans le système de type de Haskell.
Logan Capaldo
1
F # a également cette fonctionnalité de style.
Rangoric
C'est un très bon lien d'article (celui de moertel.com) montrant exactement le genre de chose à laquelle je pensais: utiliser le système de type pour transformer les vulnérabilités de sécurité d'interpolation de chaîne et autres en erreurs de compilation. Merci pour le lien.
Ryan C. Thompson,
Je pense que OO a beaucoup rattrapé la notation hongroise pour la sémantique, car aujourd'hui vous écririez probablement: Foo.Position.X + Bar.Position.Y.
Pieter B

Réponses:

27

Je dirais "oui".

Comme vous le dites, le but de la notation hongroise est d'encoder des informations dans le nom qui ne peuvent pas être encodées dans le type. Cependant, il existe essentiellement deux cas:

  1. Cette information est importante.
  2. Cette information n'est pas importante.

Commençons d'abord par le cas 2: si ces informations ne sont pas importantes, la notation hongroise est tout simplement un bruit superflu.

Le cas le plus intéressant est le numéro 1, mais je dirais que si l'information est importante, elle doit être vérifiée, c'est-à-dire qu'elle doit faire partie du type , pas du nom .

Ce qui nous ramène à la citation d'Eric Lippert:

étendre le concept de "type" pour englober les informations sémantiques en plus des informations de représentation de stockage.

En fait, ce n'est pas « étendre le concept de type », qui est le concept de type! L' objectif des types (en tant qu'outil de conception) est d'encoder des informations sémantiques! La représentation du stockage est un détail d'implémentation qui n'appartient généralement pas du tout au type . (Et spécifiquement dans une langue OO ne peut pas appartenir au type, car l'indépendance de la représentation est l'une des principales conditions requises pour OO.)

Jörg W Mittag
la source
C, où la notation hongroise était AFAIK la plus utilisée, n'est cependant pas une langue OO.
Péter Török
4
@ PéterTörök: OO est un modèle de conception, pas une caractéristique d'un langage, bien que les langages modernes soient conçus pour le rendre facile alors que le C ne l'est pas.
Jan Hudec
3
@ PéterTörök: J'ai écrit pas mal de code orienté objet en clair C. Je sais de quoi je parle.
Jan Hudec
1
S'il est vrai que des informations importantes doivent être intégrées dans le type d'une variable plutôt que dans son nom, il y a beaucoup de choses importantes à dire, mais quels types de systèmes ne peuvent pas exprimer. Par exemple, si S1est la seule référence n'importe où dans l'univers à un char[], dont le détenteur peut et le changera à tout moment, mais ne doit jamais s'exposer à du code extérieur, et S2est une référence à un char[]que personne ne devrait jamais changer, mais qui peut être partagé avec des objets qui promettent de ne pas le changer, doit S1et doit S2être considéré sémantiquement comme le même "genre de chose"?
supercat
1
@supercat - Vous décrivez des types d'unicité.
Jack
9

L'objectif des types (en tant qu'outil de conception) est d'encoder des informations sémantiques!

J'ai aimé cette réponse et je voulais donner suite à cette réponse ...

Je ne sais rien de Haskell, mais vous pouvez accomplir quelque chose comme l'exemple de xFoo + yBardans n'importe quel langage qui prend en charge une certaine forme de sécurité de type comme C, C ++ ou Java. En C ++, vous pouvez définir des classes XDir et YDir avec des opérateurs '+' surchargés qui ne prennent que des objets de leur propre type. En C ou Java, vous devez effectuer votre ajout à l'aide d'une fonction / méthode add () au lieu de l'opérateur '+'.

J'ai toujours vu la notation hongroise utilisée pour les informations de type, pas la sémantique (sauf dans la mesure où la sémantique pouvait être représentée par type). Un moyen pratique de se souvenir du type d'une variable dans les jours précédant les éditeurs de programmation «intelligents» qui affichent le type pour vous d'une manière ou d'une autre directement dans l'éditeur.

BHS
la source
Être orienté objet n'est ni nécessaire ni suffisant pour qu'un langage permette xFoo + yBardes types définis par l'utilisateur, ni l'aspect OO de C ++ nécessaire pour que cet exemple fonctionne.
Luc Danton
Vous avez raison, ce n'est pas OO, c'est la sécurité de type. J'ai édité ma réponse.
BHS
Hmm. C'est un bon point que vous pourriez faire xFoo + yBarune erreur de compilation (ou au moins une erreur d'exécution) dans à peu près n'importe quelle langue. Cependant, les mathématiques avec les classes XDir et YDir en, disons, Java ou C ++ seraient-elles plus lentes que les mathématiques avec des nombres bruts? D'après ce que je comprends, dans Haskell, les types sont vérifiés au moment de la compilation, puis à l'exécution, ce ne serait que des calculs bruts sans vérification de type, et donc pas plus lent que l'ajout de nombres réguliers.
Ryan C. Thompson,
En C ++, la vérification de type se ferait également au moment de la compilation, et la conversion, etc., serait optimisée dans la plupart des cas. Java ne le fait pas aussi bien, car il ne permet pas la surcharge de l'opérateur et ainsi de suite - vous ne pouvez donc pas traiter un XCoordinatecomme un entier normal, par exemple.
cHao
5

Je me rends compte que l'expression "Notation hongroise" a fini par signifier quelque chose de différent que l'original , mais je répondrai "non" à la question. Nommer des variables de type sémantique ou informatique ne fait pas la même chose que le typage de style SML ou Haskell. Ce n'est même pas un panda. En prenant C comme exemple, vous pourriez nommer une variable gpszTitle, mais cette variable pourrait ne pas avoir une portée globale, elle pourrait même ne pas constituer un point vers une chaîne terminée par null.

Je pense que les notations hongroises plus modernes ont une divergence encore plus grande par rapport à un système de déduction de type fort, car elles mélangent des informations "sémantiques" (comme "g" pour global ou "f" pour flag) avec le type de calcul (pointeur "p", " i "entier, etc etc.) qui finit juste comme un gâchis impie où les noms de variables n'ont qu'une vague ressemblance avec leur type de calcul (qui change avec le temps) et tous semblent si similaires que vous ne pouvez pas utiliser la" correspondance suivante "pour trouver une variable dans une fonction particulière - ils sont tous les mêmes.

Bruce Ediger
la source
4

La notation hongroise a été inventée pour BCPL, une langue qui n'avait aucun type. Ou plutôt, il avait exactement un type de données, le mot. Un mot peut être un pointeur ou un caractère ou un booléen ou un nombre entier simple selon la façon dont vous l'avez utilisé. Évidemment, cela a rendu très facile de commettre des erreurs horribles comme le déréférencement d'un personnage. La notation hongroise a donc été inventée pour que le programmeur puisse au moins effectuer une vérification de type manuelle en consultant le code.

C, un descendant de BCPL, a des types distincts pour les entiers, les pointeurs, les caractères, etc. mais la sémantique au-delà de ce niveau ne pouvait toujours pas être exprimée sous forme de types. Cela a conduit à la distinction entre ce qui a été appelé "Systems" et "Apps" en hongrois. Vous n'aviez pas besoin d'exprimer qu'une variable était un entier, mais vous pouviez utiliser des lettres de code pour indiquer si l'int était par exemple une coordonnée x ou y ou un index.

Des langages plus modernes permettent des définitions de types personnalisés, ce qui signifie que vous pouvez encoder les contraintes sémantiques dans les types, plutôt que dans les noms de variables. Par exemple, un langage OO typique aura des types spécifiques pour les paires de coordonnées et les zones, vous évitez donc d'ajouter une coordonnée x à une coordonnée y.

Par exemple, dans le célèbre article de Joels faisant l'éloge d'Apps Hongrois, il utilise l'exemple du préfixe uspour une chaîne non sécurisée et spour une chaîne sûre (encodée en html), afin d'empêcher l'injection HTML. Le développeur peut éviter les erreurs d'injection HTML en inspectant simplement soigneusement le code et en s'assurant que les préfixes des variables correspondent. Son exemple est en VBScript, un langage désormais obsolète qui ne permettait pas initialement les classes personnalisées. Dans une langue moderne, le problème peut être résolu avec un type personnalisé, et c'est bien ce que fait Asp.net avec la HtmlStringclasse. De cette façon, le compilateur trouvera automatiquement l'erreur, ce qui est beaucoup plus sûr que de se fier à l'œil humain. Il est donc clair qu'une langue avec des types personnalisés élimine le besoin d '"applications hongroises" dans ce cas.

JacquesB
la source
2

Oui, bien que de nombreuses langues qui ont par ailleurs des systèmes de types suffisamment forts aient toujours un problème - l'expressibilité des nouveaux types basés sur / similaires aux types existants.

c'est-à-dire que dans de nombreuses langues où nous pourrions utiliser davantage le système de types, nous ne le faisons pas, car le surcoût de création d'un nouveau type qui est fondamentalement le même qu'un type existant autre que nom et quelques fonctions de conversion est trop grand.

Essentiellement, nous avons besoin d'une sorte de typedefs fortement typés pour tuer complètement la notation hongroise dans ces langues (UoM de style F # pourrait également le faire)

jk.
la source
2

Souvenez-vous, il fut un temps où les IDE ne disposaient pas d'indications contextuelles vous indiquant le type d'une variable. Il fut un temps où les IDE ne comprenaient pas le code qu'ils éditaient, vous ne pouviez donc pas passer facilement de l'utilisation à la déclaration. Il fut aussi un temps où vous ne pouviez pas refactoriser un nom de variable sans parcourir manuellement l'intégralité de la base de code, en effectuant le changement à la main et en espérant que vous n'en manquiez aucun. Vous ne pouvez pas utiliser la fonction de recherche et de remplacement, car la recherche de client vous permet également d'obtenir CustomerName ...

À l'époque sombre, il était utile de savoir de quel type était une variable là où elle était utilisée. S'il est correctement entretenu (un GRAND si en raison du manque d'outils de refactoring) la notation hongroise vous a donné cela.

De nos jours, le coût des noms horribles qu'il produit est trop élevé, mais c'est une chose relativement récente. Il existe encore beaucoup de code antérieur aux développements IDE que j'ai décrits.

mcottle
la source
1
Si je ne me trompe pas, c'est une autre réponse qui aborde un type de notation hongroise différent de celui sur lequel l'OP pose des questions.
MatrixFrog
2
Cette réponse décrit ce que l'on a appelé les "systèmes hongrois", où le préfixe désigne le "type" au niveau de la langue. La question porte sur les "applications hongroises", où le mot "type" n'a pas été mal compris et signifie le type sémantique . Les systèmes hongrois sont presque universellement condamnés ces jours-ci (et à juste titre; c'est une bastardisation du véritable objectif de la notaion hongroise). Cependant, les applications hongroises peuvent être une bonne chose.
cHao
Les éditeurs capables de rechercher sCustomer sans saisir sCustomerName (vi et emacs en sont 2 exemples) existent depuis les années 70.
Larry Coleman,
@Larry, peut-être, mais vous ne pouviez pas les faire fonctionner sur les systèmes que je programmais dans les années 80
mcottle
@cHAo, non, ce n'est pas le cas - mon point de vue était d'expliquer pourquoi les gens mettaient les informations supplémentaires dans les noms de variables en général. J'ai soigneusement évité de mentionner toute version de la notation hongroise. Peut-être que l'exemple que j'ai donné dans la section "Pourquoi la recherche et le remplacement ne fonctionne pas sur le code source" vous ressemble-t-il à "Systèmes hongrois", mais ce n'était pas le cas. J'ai supprimé les "s" principaux pour éviter la confusion.
mcottle
0

Correct!

En dehors des langages totalement non typés tels que l'assembleur, la notation hongroise est superflue et ennuyeuse. Doublement donc quand on considère que la plupart des IDE vérifient la sécurité des types comme vous, euh, tapez.

Les "i" "d" et "?" Supplémentaires les préfixes rendent simplement le code moins lisible et peuvent être vraiment trompeurs - comme lorsqu'un "cow-orker" change le type de iaSumsItems de Integer en Long mais ne prend pas la peine de refactoriser le nom du champ.

James Anderson
la source
9
Votre réponse suggère que vous ne comprenez pas la différence entre le "Apps" hongrois original et intelligent et la bastardisation stupide appelée "Systems" hongrois. Lire joelonsoftware.com/articles/Wrong.html
Ryan Culpepper