Ist die ungarische Notation eine Problemumgehung für Sprachen mit unzureichender statischer Schreibweise? [geschlossen]

28

In Eric Lipperts Artikel What's Up With Hungarian Notation? , erklärt er, dass der Zweck der ungarischen Notation (der guten Art) darin besteht,

Erweitern Sie das Konzept von "Typ", um zusätzlich zu Speicherrepräsentationsinformationen auch semantische Informationen zu erfassen.

Ein einfaches Beispiel wäre das Präfixieren einer Variablen, die eine X-Koordinate darstellt, mit "x" und einer Variablen, die eine Y-Koordinate darstellt, mit "y", unabhängig davon, ob diese Variablen Ganzzahlen oder Gleitkommazahlen sind oder was auch immer, so dass Sie versehentlich schreiben xFoo + yBarsieht der Code eindeutig falsch aus.

Aber ich habe auch über das Typensystem von Haskell gelesen, und es scheint, dass man in Haskell dasselbe erreichen kann (dh "das Konzept des Typs auf semantische Informationen erweitern"), indem man tatsächliche Typen verwendet , die der Compiler für Sie prüft. Im obigen Beispiel xFoo + yBarwürde Haskell die Kompilierung tatsächlich fehlschlagen, wenn Sie Ihr Programm korrekt entworfen hätten, da sie als inkompatible Typen deklariert würden. Mit anderen Worten, es scheint, als ob das Typensystem von Haskell die Prüfung zur Kompilierungszeit unterstützt, die der ungarischen Notation entspricht

Ist die ungarische Notation also nur ein Hilfsmittel für Programmiersprachen, deren Typsysteme keine semantischen Informationen codieren können? Oder bietet die ungarische Notation etwas, das über das hinausgeht, was ein statisches Typensystem wie das von Haskell bietet?

(Natürlich verwende ich Haskell als Beispiel. Ich bin mir sicher, dass es andere Sprachen mit ähnlich ausdrucksstarken (reichen? Starken?) Systemen gibt, obwohl ich keine gefunden habe.)


Der Einfachheit halber spreche ich nicht von der Annotation von Variablennamen mit dem Datentyp , sondern von Informationen über die Bedeutung der Variablen im Kontext des Programms. Beispielsweise kann eine Variable eine Ganzzahl oder ein Gleitkomma oder ein Double oder ein Long sein, aber die Variable hat möglicherweise die Bedeutung, dass es sich um eine relative x-Koordinate handelt, die in Zoll gemessen wird. Dies ist die Art von Informationen, die ich über die Codierung in ungarischer Notation (und über Haskell-Typen) spreche.

Ryan C. Thompson
quelle
Pascal - obwohl, wenn Sie versuchen, einen XCood- und YCoord-Typ hinzuzufügen, den Sie in Pascal definiert haben, erhalten Sie nur eine Compiler-Warnung IIRC
mcottle
1
blog.moertel.com/articles/2006/10/18/… ist ein Artikel darüber, wie man etwas sehr ähnliches wie "Apps hungarian" im Typensystem in Haskell macht.
Logan Capaldo
1
F # hat diese Style-Funktion auch.
Rangoric
Das ist ein wirklich netter Artikel-Link (The moertel.com one), der genau die Art von Dingen zeigt, über die ich nachgedacht habe: Verwenden des Typsystems, um Sicherheitslücken bei der String-Interpolation und dergleichen in Fehler bei der Kompilierung umzuwandeln. Danke für den Link.
Ryan C. Thompson
Ich denke, OO hat die ungarische Semantiknotation sehr eingeholt, denn heute würden Sie wahrscheinlich schreiben: Foo.Position.X + Bar.Position.Y.
Pieter B

Antworten:

27

Ich würde Ja sagen".

Wie Sie sagen, besteht der Zweck der ungarischen Notation darin, Informationen in dem Namen zu codieren, die im Typ nicht codiert werden können. Grundsätzlich gibt es jedoch zwei Fälle:

  1. Diese Information ist wichtig.
  2. Diese Information ist nicht wichtig.

Beginnen wir mit Fall 2: Wenn diese Informationen nicht wichtig sind, ist die ungarische Notation einfach überflüssiges Rauschen.

Der interessantere Fall ist Nummer 1, aber ich würde argumentieren, dass wenn die Informationen wichtig sind, sie überprüft werden sollten, dh sie sollten Teil des Typs sein , nicht des Namens .

Das bringt uns zurück zum Eric Lippert Zitat:

Erweitern Sie das Konzept von "Typ", um zusätzlich zu Speicherrepräsentationsinformationen auch semantische Informationen zu erfassen.

Eigentlich, das ist nicht „ das Konzept vom Typ“, das ist das Konzept der Art! Der gesamte Zweck von Typen (als Entwurfswerkzeug) besteht darin, semantische Informationen zu codieren! Speicher Darstellung ist eine Implementierung Detail , das in der Regel nicht in der Art gehört überhaupt . (Und speziell in einer OO-Sprache kann man nicht in den Typ gehören, da die Repräsentationsunabhängigkeit eine der Hauptvoraussetzungen für OO ist.)

Jörg W. Mittag
quelle
C, wo die ungarische Notation AFAIK am häufigsten verwendet wurde, ist jedoch keine OO-Sprache.
Péter Török
4
@ PéterTörök: OO ist ein Entwurfsmuster, kein Merkmal einer Sprache, obwohl moderne Sprachen so konzipiert sind, dass es einfach ist, während C es nicht ist.
Jan Hudec
3
@ PéterTörök: Ich habe ziemlich viel objektorientierten Code in C geschrieben. Ich weiß, wovon ich spreche.
Jan Hudec
1
Es mag sein, dass wichtige Informationen in den Typ einer Variablen und nicht in ihren Namen eingebettet sein sollten, aber es gibt viele wichtige Dinge, die gesagt werden sollten, aber welche Typsysteme nicht ausdrücken können. Wenn zum Beispiel S1der einzige Verweis irgendwo im Universum auf einen ist char[], dessen Inhaber ihn jederzeit ändern kann und wird, aber niemals externem Code aussetzen darf, S2ist dies ein Verweis auf einen, char[]den niemand jemals ändern sollte, der jedoch gemeinsam genutzt werden kann mit Objekten, die versprechen, es nicht zu ändern, sollte S1und S2sollte semantisch als die gleiche "Art der Sache" angesehen werden?
Supercat
1
@supercat - Sie beschreiben Eindeutigkeitstypen.
Jack
9

Der gesamte Zweck von Typen (als Entwurfswerkzeug) besteht darin, semantische Informationen zu codieren!

Ich mochte diese Antwort und wollte diese Antwort weiterverfolgen ...

Ich weiß nichts über Haskell, aber Sie können so etwas wie das Beispiel von xFoo + yBarin jeder Sprache ausführen, die eine Form der Typensicherheit wie C, C ++ oder Java unterstützt. In C ++ können Sie XDir- und YDir-Klassen mit überladenen '+' - Operatoren definieren, die nur Objekte ihres eigenen Typs akzeptieren. In C oder Java müssten Sie Ihre Addition mit einer Funktion / Methode add () anstelle des Operators '+' durchführen.

Ich habe immer die ungarische Notation für Typinformationen gesehen, nicht die Semantik (außer, wenn die Semantik durch den Typ dargestellt werden könnte). Eine bequeme Möglichkeit, sich den Typ einer Variablen in den Tagen vor "intelligenten" Programmiereditoren zu merken, die den Typ auf die eine oder andere Weise rechts im Editor anzeigen.

BHS
quelle
Objektorientiert zu sein, ist weder notwendig noch ausreichend, damit eine Sprache xFoo + yBarbenutzerdefinierte Typen zulässt , noch muss der OO-Aspekt von C ++ funktionieren, damit dieses Beispiel funktioniert.
Luc Danton
Du hast recht, es ist nicht OO, es ist Art Sicherheit. Ich habe meine Antwort bearbeitet.
BHS
Hmm. Es ist ein guter Punkt, dass Sie xFoo + yBareinen Kompilierungsfehler (oder zumindest einen Laufzeitfehler) in so ziemlich jeder Sprache machen können. Wäre Mathematik mit XDir- und YDir-Klassen in Java oder C ++ jedoch langsamer als Mathematik mit rohen Zahlen? Ich verstehe, dass in Haskell die Typen zur Kompilierungszeit überprüft werden und dass es dann zur Laufzeit nur rohe Mathematik ohne Typüberprüfung und daher auch nicht langsamer als das Hinzufügen regulärer Zahlen ist.
Ryan C. Thompson
In C ++ wird die Typprüfung auch zur Kompilierungszeit durchgeführt, und die Konvertierung und dergleichen werden in den meisten Fällen wegoptimiert. Java macht das nicht so gut, weil es das Überladen von Operatoren und dergleichen nicht zulässt - so können Sie XCoordinatebeispielsweise ein Int nicht als regulär behandeln .
CHAO
5

Mir ist klar, dass der Ausdruck "Ungarische Notation" etwas anderes bedeutet als das Original , aber ich werde die Frage mit "Nein" beantworten. Das Benennen von Variablen mit semantischem oder rechnerischem Typ entspricht nicht dem SML- oder Haskell-Typ. Es ist nicht einmal ein Pflasterstein. Am Beispiel von C könnten Sie eine Variable gpszTitle nennen, aber diese Variable hat möglicherweise keinen globalen Gültigkeitsbereich und stellt möglicherweise nicht einmal einen Punkt auf eine nullterminierte Zeichenfolge dar.

Ich denke, die moderneren ungarischen Notationen weichen noch stärker von einem starken Typ-Deduktionssystem ab, weil sie "semantische" Informationen (wie "g" für global oder "f" für flag) mit dem rechnerischen Typ ("p" Zeiger, " i "integer, etc etc.) Das endet einfach als ein unheiliges Durcheinander, bei dem Variablennamen nur eine vage Ähnlichkeit mit ihrem Rechentyp haben (der sich mit der Zeit ändert) und alle so ähnlich aussehen, dass Sie nicht" next match "verwenden können finde eine Variable in einer bestimmten Funktion - sie sind alle gleich.

Bruce Ediger
quelle
4

Die ungarische Notation wurde für BCPL erfunden, eine Sprache, die überhaupt keine Typen hatte. Oder besser gesagt, es hatte genau einen Datentyp, das Wort. Ein Wort kann ein Zeiger oder ein Zeichen oder ein Boolescher Wert oder eine einfache Ganzzahl sein, je nachdem, wie Sie es verwendet haben. Offensichtlich war es dadurch sehr einfach, schreckliche Fehler wie die Dereferenzierung eines Charakters zu machen. So wurde die ungarische Schreibweise erfunden, damit der Programmierer zumindest eine manuelle Typprüfung anhand des Codes durchführen konnte.

C, ein Abkömmling von BCPL, hat unterschiedliche Typen für Ganzzahlen, Zeiger, Zeichen usw. Dies machte die ungarische Grundnotation zu einem gewissen Grad überflüssig (Sie mussten den Variablennamen nicht codieren, wenn es ein Int oder ein Zeiger war). Eine darüber hinausgehende Semantik konnte jedoch nicht als Typ ausgedrückt werden. Dies führte zur Unterscheidung zwischen "Systems" und "Apps" Ungarisch. Sie mussten nicht ausdrücken, dass eine Variable ein Int ist, aber Sie können mithilfe von Codebuchstaben angeben, ob das Int eine X- oder Y-Koordinate oder ein Index ist.

In moderneren Sprachen können benutzerdefinierte Typen definiert werden. Dies bedeutet, dass Sie die semantischen Einschränkungen in den Typen und nicht in den Variablennamen codieren können. Beispielsweise hat eine typische OO-Sprache bestimmte Typen für Koordinatenpaare und Flächen, sodass Sie vermeiden, einer y-Koordinate eine x-Koordinate hinzuzufügen.

In Joels berühmtem Artikel , in dem er Apps Hungarian lobt, verwendet er beispielsweise das Präfix usfür eine unsichere Zeichenfolge und seine sichere (HTML-codierte) Zeichenfolge, um HTML-Injection zu verhindern. Der Entwickler kann HTML-Injection-Fehler verhindern, indem er einfach den Code sorgfältig überprüft und sicherstellt, dass die variablen Präfixe übereinstimmen. Sein Beispiel ist VBScript, eine veraltete Sprache, die anfangs keine benutzerdefinierten Klassen zuließ. In einer modernen Sprache kann das Problem mit einem benutzerdefinierten Typ behoben werden, und genau das macht Asp.net mit der HtmlStringKlasse. Auf diese Weise findet der Compiler den Fehler automatisch, was viel sicherer ist, als sich auf menschliches Augapfel zu verlassen. Eine Sprache mit benutzerdefinierten Typen macht also in diesem Fall "Apps Hungarian" überflüssig.

JacquesB
quelle
2

Ja, obwohl viele Sprachen, die ansonsten stark genug sind, immer noch ein Problem haben - die Ausdruckbarkeit neuer Typen, die auf vorhandenen Typen basieren oder diesen ähneln.

In vielen Sprachen, in denen wir das Typensystem mehr verwenden könnten, tun wir dies nicht, weil der Aufwand, einen neuen Typ zu erstellen, der im Grunde genommen mit einem vorhandenen Typ mit Ausnahme von name und einigen Konvertierungsfunktionen identisch ist, zu groß ist.

Im Wesentlichen benötigen wir eine Art stark typisierter typedefs, um die ungarische Notation in diesen Sprachen vollständig zu töten (F # style UoM könnte dies auch tun).

jk.
quelle
2

Denken Sie daran, es gab eine Zeit, in der IDEs keine Popup-Hinweise zum Typ einer Variablen hatten. Es gab eine Zeit, in der IDEs den Code, den sie bearbeiteten, nicht verstanden, sodass Sie nicht einfach von der Verwendung zur Deklaration wechseln konnten. Es gab auch eine Zeit, in der Sie einen Variablennamen nicht umgestalten konnten, ohne die gesamte Codebasis manuell zu durchlaufen, die Änderung manuell vorzunehmen und zu hoffen, dass Sie keinen verpasst haben. Suchen & Ersetzen konnte nicht verwendet werden, da bei der Suche nach Kunde auch der Kundenname angezeigt wird.

In diesen dunklen Tagen war es hilfreich zu wissen, welcher Typ eine Variable war, in der sie verwendet wurde. Wenn richtig gepflegt (ein GROSSES wenn wegen des Mangels an Refactoring-Tools), gab Ihnen die ungarische Notation das.

Die Kosten für die schrecklichen Namen, die es in diesen Tagen hervorbringt, sind zu hoch, aber das ist eine relativ junge Sache. Es gibt immer noch viel Code, der älter ist als die von mir beschriebenen IDE-Entwicklungen.

mcottle
quelle
1
Wenn ich mich nicht irre, ist dies eine andere Antwort, die sich auf eine andere Art ungarischer Notation bezieht als die, nach der das OP fragt.
MatrixFrog
2
Diese Antwort beschreibt, was als "Ungarisches System" bezeichnet wurde, wobei das Präfix die Sprachstufe "Typ" bezeichnet. Die Frage stellt sich nach "Apps Hungarian", wo das Wort "Typ" nicht missverstanden wurde und den semantischen Typ bedeutet. Systemungarisch wird heutzutage fast allgemein verurteilt (und das zu Recht; es ist eine Bastardisierung des wahren Zwecks der ungarischen Notaion). Apps ungarisch können jedoch eine gute Sache sein.
cHao
Editoren, die in der Lage sind, nach sCustomer zu suchen, ohne auf sCustomerName zuzugreifen (vi und emacs sind zwei Beispiele), gibt es seit den 70er Jahren.
Larry Coleman
@ Larry, vielleicht, aber auf den Systemen, die ich in den 80ern programmiert habe, konnte man sie nicht zum Laufen bringen
Mcottle
@cHAo, nein, tut es nicht - Ich wollte erklären, warum die Leute die zusätzlichen Informationen allgemein in Variablennamen setzen. Ich habe es sorgfältig vermieden, eine Version der ungarischen Notation zu erwähnen. Vielleicht sieht das Beispiel, das ich im Abschnitt "Warum Suchen & Ersetzen im Quellcode nicht funktioniert" gegeben habe, wie "Ungarisches System" aus, aber es war nicht dazu gedacht. Ich habe die führenden "s" gelöscht, um die Verwirrung zu vermeiden.
mcottle
0

Richtig!

Außerhalb völlig untypisierter Sprachen wie Assembler ist die ungarische Notation überflüssig und ärgerlich. Zweifelsohne, wenn Sie bedenken, dass die meisten IDEs die Typensicherheit prüfen, während Sie tippen.

Das zusätzliche "i" "d" und "?" Präfixe machen den Code nur weniger lesbar und können wirklich irreführend sein - wie wenn ein "Cow-Orker" den Typ von iaSumsItems von Integer auf Long ändert, sich aber nicht darum kümmert, den Feldnamen umzugestalten.

James Anderson
quelle
9
Ihre Antwort legt nahe, dass Sie den Unterschied zwischen dem ursprünglichen, intelligenten "Apps" -Ungarisch und der dummen Bastardisierung "Systems" -Ungarisch nicht verstehen. Lesen Sie joelonsoftware.com/articles/Wrong.html
Ryan Culpepper