Warum sollte ich nicht "Ungarische Notation" verwenden?


122

Ich weiß, worauf sich Ungarisch bezieht - Informationen über eine Variable, einen Parameter oder einen Typ als Präfix für ihren Namen. Jeder scheint tollwütig dagegen zu sein, obwohl es in einigen Fällen eine gute Idee zu sein scheint. Wenn ich das Gefühl habe, dass nützliche Informationen vermittelt werden, warum sollte ich sie dann nicht genau dort platzieren, wo sie verfügbar sind?

Siehe auch: Verwenden die Menschen die ungarischen Namenskonventionen in der realen Welt?


Antworten:


174

Die meisten Menschen verwenden die ungarische Notation falsch und erzielen falsche Ergebnisse.

Lesen Sie diesen ausgezeichneten Artikel von Joel Spolsky: Falschen Code falsch aussehen lassen .

Kurz gesagt, die ungarische Notation, bei der Sie Ihren Variablennamen ihre type(Zeichenfolge) (Systems Hungarian) voranstellen, ist schlecht, weil sie nutzlos ist.

Ungarische Notation, wie sie vom Autor beabsichtigt wurde, bei der Sie dem Variablennamen das vorangestellt haben kind(am Beispiel von Joel: sichere Zeichenfolge oder unsichere Zeichenfolge), so genannte Apps Hungarian hat seine Verwendung und ist immer noch wertvoll.


5
Guter Link, eine gute Zusammenfassung dessen, was hinter dem Link steckt, und kein Fanatismus. Ausgezeichnet.
Dustman

12
Beachten Sie, dass sich Joels Beispiel in VBScript befindet, einer Sprache, in der es lange Zeit keine benutzerdefinierten Klassen gab. In einer OO-Sprache würden Sie einfach einen HtmlEncodedString-Typ erstellen und die Write-Methode nur diesen akzeptieren lassen. "Apps ungarisch" sind nur in Sprachen ohne benutzerdefinierte Typen nützlich.
JacquesB

4
Microsoft ist bekannt für seinen früheren Missbrauch der ungarischen Notation. Das Voranstellen von Typinformationen an Bezeichner ist nicht nur nutzlos, sondern kann auch tatsächlich Schaden anrichten. Erstens ist die Lesbarkeit weniger fließend. Zweitens werden in Sprachen, die Polymorphismus oder Ententypisierung unterstützen, die falschen Informationen übergeben.
Wilhelmtell

9
Ich verwende immer noch gerne die ungarische Notation, wenn ich eine reine C-Entwicklung mit einer älteren IDE mache ... auf diese Weise weiß ich, dass es keine Probleme mit dem Typ-Casting gibt.
Beep Beep

3
@Krumia: Dies wird normalerweise verhindert, indem zunächst beschreibende Variablennamen verwendet werden. Wenn Sie jedoch sicher sein möchten, ist es viel sicherer, unterschiedliche Typen (z. B. Strukturen) für Längen, Gewichte usw. zu erstellen und die Operatorüberladung zu verwenden, um sicherzustellen, dass nur gültige Operationen möglich sind.
JacquesB

277

vVerwenden von adjHungarian nnotation vmakes nreading ncode adjdifficult.


101
Schöne Analogie, wenn auch etwas unfair. Vergleichen Sie: vVerwenden von adjHungarian nNotation vMakes nReading nCode adjDifficult.
Chris Noe

27
In diesem Satz sind sowohl Verwenden als auch Lesen Gerundien. Aber ich verstehe den Punkt, den Sie gemacht haben ...
Schimpanse

28
@chimp: das macht die Sache noch offensichtlicher. Nachdem Sie einen Fehler im Typ gefunden haben, werden Sie alle Referenzen umbenennen oder so lassen, wie sie sind, und Fehlinformationen bereitstellen? du verlierst so oder so. Aber dies ist natürlich die falsche Art, die ungarische Notation anzuwenden.
Wilhelmtell

1
@ Chris Noe: Für bestimmte Lesestile (analysieren Sie das Präfix und das Suffix mit einem Blick in die Mitte) macht Ihr Beispiel die Sache nur noch schlimmer. Ich sehe "vUsing" und höre "voosing" in meinem Kopf.
Bob Cross

3
@Jon: Wenn Sie einen Variablennamen haben, der nicht vollständig verrät, was er darstellt, sollte der Fokus auf jeden Fall darauf liegen, ihn in etwas Beschreibenderes umzubenennen (und die ungarische Notation ist im Grunde genommen keine Verbesserung Im besten Fall wird das Symptom behoben - das Problem nicht gelöst.
Hlovdal

104

Joel ist falsch und hier ist warum.

Diese "Anwendungs" -Informationen, über die er spricht, sollten im Typsystem codiert werden . Sie sollten nicht darauf angewiesen sein, Variablennamen umzudrehen, um sicherzustellen, dass Sie keine unsicheren Daten an Funktionen übergeben, die sichere Daten erfordern. Sie sollten es sich um eine Art Fehler machen, so dass es unmöglich , dies zu tun. Unsichere Daten sollten einen Typ haben, der als unsicher markiert ist, damit sie einfach nicht an eine sichere Funktion übergeben werden können. Um von unsicher zu sicher zu konvertieren, sollte eine Verarbeitung mit einer Art Desinfektionsfunktion erforderlich sein.

Viele der Dinge, von denen Joel als "Arten" spricht, sind keine Arten; Sie sind in der Tat Typen.

Was den meisten Sprachen jedoch fehlt, ist ein Typensystem, das ausdrucksstark genug ist, um diese Art von Unterscheidungen durchzusetzen. Wenn C beispielsweise eine Art "starkes typedef" hätte (wobei der typedef-Name alle Operationen des Basistyps enthielt, aber nicht in diesen konvertierbar war), würden viele dieser Probleme verschwinden. Wenn Sie beispielsweise sagen könnten, strong typedef std::string unsafe_string;um einen neuen Typ einzuführen unsafe_string, der nicht in einen std :: string konvertiert werden kann (und somit an der Überlastungsauflösung usw. usw. teilnehmen kann), benötigen wir keine dummen Präfixe.

Die zentrale Behauptung, Ungarisch sei für Dinge, die keine Typen sind, ist also falsch. Es wird für Typinformationen verwendet. Sicherlich umfangreichere Typinformationen als die herkömmlichen C-Typinformationen; Es sind Typinformationen, die eine Art semantisches Detail codieren, um den Zweck der Objekte anzuzeigen. Aber es sind immer noch Typinformationen, und die richtige Lösung bestand immer darin, sie in das Typsystem zu codieren. Die Codierung in das Typsystem ist bei weitem der beste Weg, um eine ordnungsgemäße Validierung und Durchsetzung der Regeln zu erreichen. Variablennamen schneiden einfach nicht den Senf.

Mit anderen Worten, das Ziel sollte nicht sein, "falschen Code für den Entwickler falsch aussehen zu lassen". Es sollte "falschen Code für den Compiler falsch aussehen lassen " sein.


30
Die Absicht der Variablen sollte innerhalb des Variablentyps codiert werden und nicht etwas so Fragilem wie einem verdammten Namensschema überlassen bleiben.
DrPizza

3
Ich würde es gerne auch zum Compiler / Interpreter machen, aber das würde einen enormen Aufwand für dynamische Sprachen (Python, Ruby, PHP oder Javascript) bedeuten.
zu viel PHP

22
"Was den meisten Sprachen jedoch fehlt, ist ein Typensystem, das ausdrucksstark genug ist, um diese Art von Unterscheidungen durchzusetzen." Und da liegt das Problem. AppsHungarian ist eine pragmatische Methode, um Probleme bei der Verwendung dieser Sprachen auf offensichtliche Weise für Programmierer hervorzuheben, die den Code anzeigen, anstatt die Fehlerberichte zu untersuchen.
Neil Trodden

6
@DrPizza: Ich glaube, Sie haben einen der sehr wichtigen Punkte übersehen, die Joel bei der Befürwortung von Apps Hungarian macht: Diese Notation ist nur ein sehr pragmatischer Kompromiss . Es ist ein großes Ziel, den Compiler in die Lage zu versetzen, "falschen Code" zu erkennen, aber ist es immer seine Kosten wert?
Yarik

4
@DrPizza: Joel is wrongund What most languages lack, however, is a type system that's expressive enough to enforce these kind of distinctions.so, da die meisten Sprachen haben den Ausdruck genug fehlen diese Art von Unterscheidungen zu erzwingen, Joel ist richtig. Richtig?
Sampathsris

46

Ich denke, es bringt den Quellcode massiv durcheinander.

Es bringt Ihnen auch nicht viel in einer stark typisierten Sprache. Wenn Sie eine Form von Mismatch-Tomfoolery ausführen, werden Sie vom Compiler darüber informiert.


Beeindruckend. 90 Wiederholungen in 15 Minuten. Guter Anruf.
Dustman

2
Wenn Sie es für Typ verwenden, dann ist es ja nutzlos. Es ist nützlich, andere Informationen zu vermitteln.
Lou Franco

12
@ Lou, genau - persönlich speichere ich einen Revisionsverlauf in meinen Variablennamen: string firstName_wasName_wasNameID_wasSweetCupinCakes
Shog9

@nsanders: Verwenden Sie den Compiler, um zu überprüfen, ob Sie dieselben Maßeinheiten verwendet haben, wenn beide Variablentypen Ganzzahlen sind.
Igor Levicki

1
@ Shog9: Ich denke du hast die Apps Ungarische Notation nicht verstanden. Es geht mehr um sFirstName vs unFirstName (sicher gegen unsicher, nicht bereinigt), auf diese Weise wissen Sie etwas mehr darüber. Trotzdem denke ich, dass es in statischen Sprachen besser ist, String zu subtypisieren, um UnsafeString und SafeString zu erstellen und nur die Ausgabe von SafeString zuzulassen. Die Konvention ist in Ordnung, aber (häufiger) die Durchsetzung der Kompilierung ist besser.
kgadek

28

Die ungarische Notation ist nur in Sprachen ohne benutzerdefinierte Typen sinnvoll . In einer modernen Funktions- oder OO-Sprache würden Sie Informationen über die "Art" des Werts eher in den Datentyp oder die Klasse als in den Variablennamen codieren.

Mehrere Antworten beziehen sich auf Joels Artikel . Beachten Sie jedoch, dass sein Beispiel in VBScript enthalten ist, das benutzerdefinierte Klassen (zumindest lange Zeit) nicht unterstützt. In einer Sprache mit benutzerdefinierten Typen würden Sie das gleiche Problem lösen, indem Sie einen HtmlEncodedString-Typ erstellen und dann die Write-Methode nur diesen akzeptieren lassen. In einer statisch typisierten Sprache erkennt der Compiler alle Codierungsfehler. In einer dynamisch typisierten Sprache wird eine Laufzeitausnahme angezeigt. In jedem Fall sind Sie jedoch vor dem Schreiben nicht codierter Zeichenfolgen geschützt. Ungarische Notationen machen den Programmierer einfach zu einem menschlichen Typprüfer. Dies ist die Art von Arbeit, die normalerweise besser von Software erledigt wird.

Joel unterscheidet zwischen "System-Ungarisch" und "Apps-Ungarisch", wobei "System-Ungarisch" die integrierten Typen wie int, float usw. codiert und "Apps-Ungarisch" "Arten" codiert, bei denen es sich um übergeordnete Metainformationen handelt In einem OO oder einer modernen Funktionssprache können Sie benutzerdefinierte Typen erstellen, sodass in diesem Sinne kein Unterschied zwischen Typ und "Art" besteht - beide können durch das Typsystem dargestellt werden - und "Apps". Ungarisch ist genauso überflüssig wie "Systeme" Ungarisch.

Um Ihre Frage zu beantworten: Systemungarisch wäre nur in einer unsicheren, schwach typisierten Sprache nützlich, in der beispielsweise das Zuweisen eines Gleitkommawertes zu einer int-Variablen das System zum Absturz bringt. Die ungarische Notation wurde in den sechziger Jahren speziell für die Verwendung in BCPL erfunden , einer ziemlich einfachen Sprache, die überhaupt keine Typprüfung durchführte. Ich glaube nicht, dass eine Sprache, die heute allgemein verwendet wird, dieses Problem hat, aber die Notation lebte als eine Art Frachtkultprogramm weiter .

Apps Ungarisch ist sinnvoll, wenn Sie mit einer Sprache ohne benutzerdefinierte Typen arbeiten, z. B. Legacy-VBScript oder frühere Versionen von VB. Vielleicht auch frühe Versionen von Perl und PHP. Auch hier ist die Verwendung in einer modernen Sprache ein reiner Frachtkult.

In jeder anderen Sprache ist Ungarisch nur hässlich, überflüssig und zerbrechlich. Es wiederholt Informationen, die bereits aus dem Typsystem bekannt sind, und Sie sollten sich nicht wiederholen . Verwenden Sie einen beschreibenden Namen für die Variable, der die Absicht dieser bestimmten Instanz des Typs beschreibt. Verwenden Sie das Typsystem, um Invarianten und Metainformationen über "Arten" oder "Klassen" von Variablen zu codieren - dh. Typen.

Der allgemeine Punkt in Joels Artikel - dass falscher Code falsch aussieht - ist ein sehr gutes Prinzip. Ein noch besserer Schutz vor Fehlern besteht jedoch darin, dass - wenn möglich - falscher Code vom Compiler automatisch erkannt wird.


Sprachen mit benutzerdefinierten Typen machen es nicht immer praktisch, Typen anstelle von "Arten" zu verwenden. Betrachten Sie die Präfixe "c", "d", "ix" von Joels Apps Hungarian. Verwenden Sie für diese benutzerdefinierte Ganzzahltypen in allen modernen Sprachen? Das glaube ich nicht. Weil moderne Sprachen immer noch keine benutzerdefinierten Ganzzahltypen für Indizes, Zählungen und Unterschiede zwischen zwei Zahlen haben. Solange wir noch Vanille-Ints verwenden, ist Apps Hungarian nicht redundant und nützlich.
Eldritch Conundrum

27

Ich verwende für alle meine Projekte immer die ungarische Notation. Ich finde es sehr hilfreich, wenn ich mit Hunderten verschiedener Bezeichnernamen zu tun habe.

Wenn ich zum Beispiel eine Funktion aufrufe, die eine Zeichenfolge erfordert, kann ich 's' eingeben und den Steuerbereich drücken, und meine IDE zeigt mir genau die Variablennamen an, denen 's' vorangestellt ist.

Ein weiterer Vorteil, wenn ich u für nicht signierte und i für signierte Ints voranstelle, sehe ich sofort, wo ich signierte und nicht signierte auf potenziell gefährliche Weise mische.

Ich kann mich nicht erinnern, wie oft in einer riesigen Codebasis mit 75000 Zeilen Fehler verursacht wurden (auch von mir und anderen), weil lokale Variablen genauso benannt wurden wie vorhandene Mitgliedsvariablen dieser Klasse. Seitdem stelle ich Mitgliedern immer 'm_' voran.

Es ist eine Frage des Geschmacks und der Erfahrung. Klopfen Sie nicht, bis Sie es versucht haben.


1
Das Codieren der Signiertheit in Variablennamen ist großartig, wenn sich der Code tatsächlich mit der Signiertheit befasst. Dies als Ausrede zu benutzen , um die Konvention für alle Variablen durchzusetzen , ist meiner Meinung nach nur Domatismus.
Plumenator

Sie haben jedoch einen guten Punkt mit Mitgliedsvariablen. Aber in Sprachen wie Python, in denen Sie gezwungen sind, Mitglieder mit dem Selbst / diesem Objekt zu qualifizieren, ist es umstritten.
Plumenator

Es ist nur ein Trick, um die Produktivität zu steigern. Genau wie bei der automatischen Vervollständigung der IDE. Daran ist nichts grundsätzlich Böses. Ich glaube, dass erfahrene Programmierer ihren eigenen Stil verwenden dürfen. Es ist schlecht, jemanden zu zwingen, einen bestimmten Stil zu wählen. Ich arbeite jetzt als einzelner Entwickler, aber ich würde niemandem, mit dem ich zusammengearbeitet habe, einen Stil aufzwingen, es sei denn, ihm fehlte überhaupt ein einheitlicher Stil.
rep_movsd

Sie verwenden also eine Namenskonvention, um die Variablen zu filtern, oder? Ich muss zustimmen, dass es ein bisschen klug ist . :-) Die Art und Weise, wie ich verkabelt bin, der Ankerpunkt (oder das Filterkriterium, wenn Sie möchten) ist jedoch immer die Semantik für mich. Selten der Typ (es sei denn, es ist die Semantik). Ich hoffe das hat Sinn gemacht. TL; DR: Ich würde immer noch halten Sie sich an die Benennung Variablen nach , was sie darstellen , als wie sie dargestellt sind.
Plumenator

1
Ich habe das damals positiv bewertet, da ich für Ungarisch war. Jetzt bereue ich es und würde nie wieder etwas einer Variablen
voranstellen

22

Sie vergessen den Hauptgrund, diese Informationen aufzunehmen. Es hat nichts mit dir zu tun, dem Programmierer. Es hat alles damit zu tun, dass die Person 2 oder 3 Jahre nach dem Verlassen der Firma die Straße runterkommt und das Zeug lesen muss.

Ja, eine IDE identifiziert schnell Typen für Sie. Wenn Sie jedoch einige lange Stapel von 'Geschäftsregeln'-Code lesen, ist es schön, nicht bei jeder Variablen eine Pause einlegen zu müssen, um herauszufinden, um welchen Typ es sich handelt. Wenn ich Dinge wie strUserID, intProduct oder guiProductID sehe, macht das viel aus erleichtert dies die Hochlaufzeit .

Ich bin damit einverstanden, dass MS mit einigen ihrer Namenskonventionen viel zu weit gegangen ist - ich kategorisiere das in den Stapel "zu viel des Guten".

Namenskonventionen sind gute Dinge, vorausgesetzt, Sie halten sich daran. Ich habe genug alten Code durchgesehen, so dass ich mich ständig mit den Definitionen für so viele ähnlich benannte Variablen befasst habe, dass ich auf "Kamelhülle" drücke (wie es bei einem früheren Job genannt wurde). Im Moment bin ich in einem Job, der viele tausend Zeilen völlig unkommentierten klassischen ASP-Codes mit VBScript enthält, und es ist ein Albtraum, Dinge herauszufinden.


Als VIM-Benutzer (keine IDE, keine Hervorhebung, kein Hover-Tell-You-What-Type) verstehe ich dieses Argument überhaupt nicht. Ich verstehe natürlich, dass eine Variable namens name eine Zeichenfolge ist und eine Variable namens i oder count ein int. Braucht man wirklich sName und iCount? Wie hilft es wirklich? Ich würde argumentieren, dass Ihr Produkt-ID-Beispiel ein Sonderfall ist, und vielleicht wäre es dort in Ordnung. Aber selbst dann wäre es eine viel bessere Lösung, konsistent zu sein und Produkt-IDs überall mit Ints oder Strings darzustellen, oder? Die ganze Namenssache scheint eine Ausrede zu sein.
MrFox

6
Es ist für die Konsistenz. Ja, "Name" impliziert von Natur aus eine Zeichenfolge. Aber was würden Sie als "Benutzer-ID" annehmen? Eine Anleitung? String? Ganze Zahl? Sogar so etwas wie "acctno" könnte einen Wert von 42 oder "23X" haben. Die Dokumentation ist in den meisten Codes spärlich genug. Dieser Standard hilft dem Wartungsprogrammierer ein wenig.
David

1
@ David Ich stimme Ihrer Antwort absolut zu - auf einen Blick zu wissen, dass die Absicht der Variablen der Grund ist, warum ich auch Präfixe bevorzuge, mehr noch in einer dynamischen Sprache wie JS.
Daniel Sokolowski

10

Das Anheften von kryptischen Zeichen am Anfang jedes Variablennamens ist nicht erforderlich und zeigt, dass der Variablenname an sich nicht beschreibend genug ist. Die meisten Sprachen erfordern ohnehin den Variablentyp bei der Deklaration, sodass bereits Informationen verfügbar sind.

Es gibt auch die Situation, in der sich während der Wartung ein Variablentyp ändern muss. Beispiel: Wenn eine als "uint_16 u16foo" deklarierte Variable ein 64-Bit-Zeichen ohne Vorzeichen werden muss, geschieht eines von zwei Dingen:

  1. Sie gehen durch und ändern jeden Variablennamen (stellen Sie sicher, dass keine nicht verwandten Variablen mit demselben Namen abgespritzt werden) oder
  2. Ändern Sie einfach den Typ und nicht den Namen, was nur zu Verwirrung führt.

9

Joel Spolsky hat einen guten Blog-Beitrag darüber geschrieben. http://www.joelonsoftware.com/articles/Wrong.html Grundsätzlich kommt es darauf an, dass das Lesen Ihres Codes nicht schwieriger wird, wenn eine anständige IDE Ihnen sagt, dass Sie die Variable eingeben möchten, wenn Sie sich nicht erinnern können. Wenn Sie Ihren Code ausreichend unterteilt haben, müssen Sie sich nicht daran erinnern, welche Variable als drei Seiten höher deklariert wurde.


9

Ist der Umfang heutzutage nicht wichtiger als der Typ, z

* l for local
* a for argument
* m for member
* g for global
* etc

Mit modernen Techniken zum Umgestalten von altem Code ist das Suchen und Ersetzen eines Symbols, da Sie dessen Typ geändert haben, mühsam. Der Compiler erkennt Typänderungen, erkennt jedoch häufig keine falsche Verwendung des Gültigkeitsbereichs. Hier helfen sinnvolle Namenskonventionen.


Andererseits sollte der Code wahrscheinlich nicht so sehr vom Umfang abhängen. :-)
Plumenator

8

Es gibt keinen Grund, warum Sie die ungarische Notation nicht korrekt verwenden sollten . Die Unbeliebtheit ist auf eine lang anhaltende Gegenreaktion gegen den Missbrauch zurückzuführen der ungarischen Notation zurückzuführen, insbesondere in den Windows-APIs.

In den schlechten alten Zeiten, bevor es für DOS etwas gab, das einer IDE ähnelte (wahrscheinlich hatten Sie nicht genügend freien Speicher, um den Compiler unter Windows auszuführen, sodass Ihre Entwicklung unter DOS durchgeführt wurde), erhielten Sie keine Hilfe von Bewegen Sie die Maus über einen Variablennamen. (Angenommen, Sie hatten eine Maus.) Was Sie zu tun hatten, waren Ereignisrückruffunktionen, bei denen alles entweder als 16-Bit-Int (WORD) oder als 32-Bit-Int (LONG WORD) an Sie übergeben wurde. Sie mussten diese Parameter dann in die entsprechenden Typen für den angegebenen Ereignistyp umwandeln. Tatsächlich war ein Großteil der API praktisch typlos.

Das Ergebnis ist eine API mit Parameternamen wie diesen:

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam);

Beachten Sie, dass die Namen wParam und lParam, obwohl sie ziemlich schrecklich sind, nicht schlechter sind, als sie param1 und param2 zu nennen.

Um die Sache noch schlimmer zu machen, hatte Window 3.0 / 3.1 zwei Arten von Zeigern, nah und fern. So war beispielsweise der Rückgabewert der Speicherverwaltungsfunktion LocalLock eine PVOID, aber der Rückgabewert von GlobalLock war eine LPVOID (mit dem 'L' für lange Zeit). Diese schreckliche Notation wurde dann erweitert , so dass ein l ong p ointer String Präfix wurde lp , es aus einer Zeichenfolge zu unterscheiden , die einfach gewesen malloc'd hatten.

Es ist keine Überraschung, dass es eine Gegenreaktion gegen solche Dinge gab.


6

Die ungarische Notation kann in Sprachen ohne Typprüfung zur Kompilierungszeit nützlich sein, da sich der Entwickler schnell daran erinnern kann, wie die jeweilige Variable verwendet wird. Es tut nichts für Leistung oder Verhalten. Es soll die Lesbarkeit des Codes verbessern und ist hauptsächlich eine Frage des Geschmacks und des Codierungsstils. Aus diesem Grund wird es von vielen Entwicklern kritisiert - nicht jeder hat die gleiche Verkabelung im Gehirn.

Für die Sprachen zur Typprüfung zur Kompilierungszeit ist dies meistens nutzlos. Wenn Sie ein paar Zeilen nach oben scrollen, sollte die Deklaration und damit der Typ angezeigt werden. Wenn Ihre globalen Variablen oder Ihr Codeblock mehr als einen Bildschirm umfassen, treten schwerwiegende Probleme mit dem Design und der Wiederverwendbarkeit auf. Einer der Kritikpunkte ist daher, dass die ungarische Notation es Entwicklern ermöglicht, schlechtes Design zu haben und leicht damit durchzukommen. Dies ist wahrscheinlich einer der Gründe für Hass.

Auf der anderen Seite kann es Fälle geben, in denen selbst Sprachen zur Typprüfung zur Kompilierungszeit von der ungarischen Notation profitieren würden - ungültige Zeiger oder HANDLEs in der win32-API. Dadurch wird der tatsächliche Datentyp verschleiert, und es kann sinnvoll sein, dort die ungarische Notation zu verwenden. Wenn man jedoch den Datentyp zum Zeitpunkt der Erstellung kennen kann, warum nicht den entsprechenden Datentyp verwenden?

Im Allgemeinen gibt es keine schwierigen Gründe, die ungarische Notation nicht zu verwenden. Es ist eine Frage der Vorlieben, Richtlinien und des Codierungsstils.


6

Als Python-Programmierer fällt die ungarische Notation ziemlich schnell auseinander. In Python, es ist mir egal , wenn etwas ist ein String - ist mir egal , ob es kann wie wirken eine Zeichenfolge (dh , wenn es ein hat___str___() Methode , die einen String zurückgibt).

Nehmen wir zum Beispiel an, wir haben foo als Ganzzahl 12

foo = 12

Die ungarische Notation sagt uns, dass wir das iFoo oder so nennen sollten, um es als Ganzzahl zu bezeichnen, damit wir später wissen, was es ist. Außer in Python funktioniert das nicht oder macht keinen Sinn. In Python entscheide ich, welchen Typ ich möchte, wenn ich ihn verwende. Will ich eine schnur gut wenn ich so etwas mache:

print "The current value of foo is %s" % foo

Beachten Sie die %s- Zeichenfolge. Foo ist keine Zeichenfolge, aber der %Operator ruft foo.___str___()das Ergebnis auf und verwendet es (vorausgesetzt, es existiert). fooist immer noch eine Ganzzahl, aber wir behandeln sie als Zeichenfolge, wenn wir eine Zeichenfolge möchten. Wenn wir einen Float wollen, dann behandeln wir ihn als Float. In dynamisch typisierten Sprachen wie Python ist die ungarische Notation sinnlos, da es keine Rolle spielt, um welchen Typ es sich handelt, bis Sie ihn verwenden. Wenn Sie einen bestimmten Typ benötigen, stellen Sie einfach sicher, dass Sie ihn in diesen Typ umwandeln (zfloat(foo) ) benutze es.

Beachten Sie, dass dynamische Sprachen wie PHP diesen Vorteil nicht haben - PHP versucht, im Hintergrund das Richtige zu tun, basierend auf einem obskuren Regelwerk, das fast niemand auswendig gelernt hat, was häufig unerwartet zu katastrophalen Problemen führt. In diesem Fall kann eine Art Benennungsmechanismus wie $files_countoder $file_namenützlich sein.

Aus meiner Sicht ist die ungarische Notation wie Blutegel. Vielleicht waren sie in der Vergangenheit nützlich, oder zumindest schienen sie nützlich zu sein, aber heutzutage ist es nur eine Menge zusätzlicher Eingaben, die nicht viel Nutzen bringen.


Interessant, dass Ihr Beispiel mit .str () in Python nicht darauf zurückzuführen ist, dass die Sprache dynamisch ist. Java, definitiv keine dynamische Sprache, macht dasselbe.
Dustman

C # macht auch das Gleiche, jede Klasse in der Sprache implementiert .ToString(), damit alles gedruckt werden kann
Electric Coffee

5

Die IDE sollte diese nützlichen Informationen vermitteln. Ungarisch hätte vielleicht eine Art (nicht viel, aber eine Art) Sinn ergeben, als IDEs viel weniger fortgeschritten waren.


4
Andererseits sollten Sie sich nicht darauf verlassen, dass die IDE Ihnen mehr sagt. Immerhin kann Code außerhalb der IDE
angezeigt werden

5

Apps Ungarisch ist für mich Griechisch - auf eine gute Art und Weise

Als Ingenieur und nicht als Programmierer ging ich sofort zu Joels Artikel über die Vorzüge von Apps Hungarian über: "Falschen Code falsch aussehen lassen" . Ich mag Apps Ungarisch, weil es nachahmt, wie Ingenieurwesen, Naturwissenschaften und Mathematik Gleichungen und Formeln mithilfe von Symbolen mit und ohne Skripte (wie griechische Buchstaben, mathematische Operatoren usw.) darstellen. Nehmen Sie ein besonderes Beispiel für das Newtonsche Gesetz der universellen Schwerkraft : zuerst in mathematischer Standardnotation und dann im ungarischen Pseudocode von Apps:

Newtons universelles Gravitationsgesetz für Erde und Mars

frcGravityEarthMars = G * massEarth * massMars / norm(posEarth - posMars)

In der mathematischen Notation sind die bekanntesten Symbole diejenigen, die die Art der in der Variablen gespeicherten Informationen darstellen: Kraft, Masse, Positionsvektor usw. Die Indizes spielen eine zweite Geige, um zu verdeutlichen: Position von was? Genau das macht Apps Hungarian. es sagt dir die Art von ersten in der Variable gespeichert Sache und dann ins Detail immer - über den nächsten Code kann eine mathematische Schreibweise erhalten.

Offensichtlich starke Typisierung kann das Beispiel für sichere und unsichere Zeichenfolgen aus Joels Aufsatz auflösen, aber Sie würden keine separaten Typen für Positions- und Geschwindigkeitsvektoren definieren. Beide sind doppelte Arrays der Größe drei, und alles, was Sie wahrscheinlich mit einem tun, kann auf das andere angewendet werden. Darüber hinaus ist es vollkommen sinnvoll, Position und Geschwindigkeit zu verketten (um einen Zustandsvektor zu erstellen) oder ihr Punktprodukt zu nehmen, aber wahrscheinlich nicht hinzuzufügen. Wie würde die Eingabe die ersten beiden zulassen und die zweite verbieten, und wie würde sich ein solches System auf jede mögliche Operation erstrecken, die Sie möglicherweise schützen möchten? Es sei denn, Sie waren bereit, die gesamte Mathematik und Physik in Ihrem Schreibsystem zu kodieren.

Darüber hinaus wird viel Engineering in schwach typisierten Hochsprachen wie Matlab oder alten Sprachen wie Fortran 77 oder Ada durchgeführt.

Wenn Sie also eine ausgefallene Sprache haben und IDE und Apps Ungarisch Ihnen nicht helfen, dann vergessen Sie es - viele Leute haben es anscheinend. Aber für mich, einen schlechteren als einen unerfahrenen Programmierer, der in schwach oder dynamisch typisierten Sprachen arbeitet, kann ich mit ungarischen Apps schneller besseren Code schreiben als ohne.


4

Es ist unglaublich redundant und nutzlos für die meisten modernen IDEs, bei denen sie den Typ gut sichtbar machen.

Außerdem ist es für mich nur ärgerlich, intI, strUserName usw. zu sehen :)


3
Wie TraumaPony Paul Batum sagte, sieht nicht jeder den Code in der IDE.
Chris Charabaruk

4

Wenn ich das Gefühl habe, dass nützliche Informationen vermittelt werden, warum sollte ich sie dann nicht genau dort platzieren, wo sie verfügbar sind?

Wen interessiert es dann, was andere denken? Wenn Sie es nützlich finden, verwenden Sie die Notation.


Weil es nur einen von mir und eine Bajillion anderer Leute gibt, die meinen Code später vielleicht pflegen. Da all diese Leute im Team sind (aber sie wissen es noch nicht), hätte ich gerne eine Idee, wenn sie mich überstimmen.
Dustman

4

Ich bin meine Erfahrung, es ist schlecht, weil:

1 - dann brechen Sie den gesamten Code, wenn Sie den Typ einer Variablen ändern müssen (dh wenn Sie eine 32-Bit-Ganzzahl auf eine 64-Bit-Ganzzahl erweitern müssen);

2 - Dies sind nutzlose Informationen, da der Typ entweder bereits in der Deklaration enthalten ist oder Sie eine dynamische Sprache verwenden, in der der tatsächliche Typ überhaupt nicht so wichtig sein sollte.

Darüber hinaus, mit einer Sprache, die generische Programmierung akzeptiert (dh Funktionen, bei denen der Typ einiger Variablen nicht bestimmt wird, wenn Sie die Funktion schreiben) oder mit einem dynamischen Typisierungssystem (dh wenn der Typ nicht einmal zur Kompilierungszeit bestimmt wird), wie würden Sie Ihre benennen Variablen? Und die meisten modernen Sprachen unterstützen die eine oder andere, wenn auch in eingeschränkter Form.


4

In Joel Spolskys Making Wrong Code Look Wrong erklärt er, dass das, was jeder als ungarische Notation betrachtet (was er Systems Hungarian nennt), nicht das ist, was es eigentlich sein sollte (was er Apps Hungarian nennt). Scrollen Sie nach unten zur Überschrift " Ich bin Ungarn" , um diese Diskussion zu sehen.

Grundsätzlich ist Systems Hungarian wertlos. Es sagt Ihnen nur dasselbe, was Ihr Compiler und / oder Ihre IDE Ihnen sagen werden.

Apps Ungarisch sagt Ihnen, was die Variable bedeuten soll und kann tatsächlich nützlich sein.


4

Ich habe immer gedacht, dass ein oder zwei Präfixe an der richtigen Stelle nicht schaden würden. Ich denke, wenn ich etwas Nützliches vermitteln kann, wie "Hey, das ist eine Schnittstelle, zähle nicht auf ein bestimmtes Verhalten", genau dort, wie in IEnumerable, sollte ich es tun. Kommentare können viel mehr durcheinander bringen als nur ein oder zwei Zeichen.


1
Ich habe nie das ISomethingable bekommen. Wenn es ein -able ist, impliziert das sowieso eine Schnittstelle. (Zumindest in Java)
Tunaranch

4

Dies ist eine nützliche Konvention zum Benennen von Steuerelementen in einem Formular (btnOK, txtLastName usw.), wenn die Liste der Steuerelemente in einer alphabetischen Pulldown-Liste in Ihrer IDE angezeigt wird.


4

Ich verwende die ungarische Notation normalerweise nur mit ASP.NET-Serversteuerelementen . Andernfalls fällt es mir zu schwer, herauszufinden, welche Steuerelemente in dem Formular enthalten sind.

Nehmen Sie diesen Code-Ausschnitt:

<asp:Label ID="lblFirstName" runat="server" Text="First Name" />
<asp:TextBox ID="txtFirstName" runat="server" />
<asp:RequiredFieldValidator ID="rfvFirstName" runat="server" ... />

Wenn jemand einen besseren Weg zeigen kann, diese Kontrollnamen ohne Ungarisch zu haben, wäre ich versucht, dorthin zu wechseln.


4

Joels Artikel ist großartig, aber er scheint einen wichtigen Punkt wegzulassen:

Ungarisch macht eine bestimmte „Idee“ (Art + Name des Bezeichners) in der gesamten Codebasis eindeutig oder nahezu eindeutig - sogar in einer sehr großen Codebasis.

Das ist riesig für die Code-Wartung. Dies bedeutet, dass Sie eine gute alte einzeilige Textsuche (grep, findstr, 'in allen Dateien finden') verwenden können, um JEDE Erwähnung dieser 'Idee' zu finden.

Warum ist das wichtig, wenn wir IDEs haben, die wissen, wie man Code liest? Weil sie noch nicht sehr gut darin sind. Dies ist in einer kleinen Codebasis schwer zu erkennen, in einer großen jedoch offensichtlich - wenn die "Idee" in Kommentaren, XML-Dateien, Perl-Skripten und auch an Orten außerhalb der Quellcodeverwaltung (Dokumente, Wikis, Fehlerdatenbanken) erwähnt wird.

Sie müssen auch hier ein wenig vorsichtig sein - z. B. kann das Einfügen von Token in C / C ++ - Makros Erwähnungen des Bezeichners verbergen. Solche Fälle können mithilfe von Codierungskonventionen behandelt werden, und sie betreffen ohnehin nur eine Minderheit der Bezeichner in der Codebasis.

PS Bis zur Verwendung des Typsystems im Vergleich zu Ungarisch - es ist am besten, beide zu verwenden. Sie benötigen nur falschen Code, um falsch auszusehen, wenn der Compiler ihn nicht für Sie abfängt. Es gibt viele Fälle, in denen es nicht möglich ist, den Compiler zum Abfangen zu bringen. Aber wo es machbar ist - ja, bitte machen Sie das stattdessen!

Berücksichtigen Sie bei der Prüfung der Machbarkeit jedoch die negativen Auswirkungen der Aufteilung von Typen. In C # hat das Umschließen von 'int' mit einem nicht integrierten Typ enorme Konsequenzen. Es ist also in einigen Situationen sinnvoll, aber nicht in allen.


4

Die Vorteile der ungarischen Notation entlarven

  • Es bietet eine Möglichkeit zur Unterscheidung von Variablen.

Wenn der Typ alles ist, was den einen Wert von einem anderen unterscheidet, kann er nur für die Konvertierung eines Typs in einen anderen verwendet werden. Wenn Sie denselben Wert haben, der zwischen Typen konvertiert wird, sollten Sie dies wahrscheinlich in einer Funktion tun, die der Konvertierung gewidmet ist. (Ich habe gesehen, dass ungarische VB6-Reste Zeichenfolgen für alle ihre Methodenparameter verwenden, nur weil sie nicht herausfinden konnten, wie ein JSON-Objekt deserialisiert oder wie deklarierbare Typen deklariert oder verwendet werden. ) Wenn Sie zwei Variablen haben, die nur durch die unterschieden werden Ungarisches Präfix, und sie sind keine Konvertierung von einem zum anderen, dann müssen Sie Ihre Absicht mit ihnen ausarbeiten.

  • Dadurch wird der Code besser lesbar.

Ich habe festgestellt, dass die ungarische Notation Menschen mit ihren Variablennamen faul macht. Sie haben etwas, durch das sie es unterscheiden können, und sie haben nicht das Bedürfnis, auf seinen Zweck einzugehen. Dies ist, was Sie normalerweise in ungarischem notiertem Code vs. modern finden: sSQL vs. groupSelectSql ( oder normalerweise überhaupt kein sSQL, weil sie das ORM verwenden sollen, das von früheren Entwicklern eingegeben wurde . ), SValue vs. formCollectionValue ( oder normalerweise auch kein sValue, da sie sich zufällig in MVC befinden und die Modellbindungsfunktionen verwenden sollten ), sType vs. PublishSource usw.

Es kann nicht lesbar sein. Ich sehe mehr sTemp1, sTemp2 ... sTempN von einem bestimmten ungarischen VB6-Rest als alle anderen zusammen.

  • Es verhindert Fehler.

Dies wäre aufgrund der Nummer 2 falsch.


3

Mit den Worten des Meisters:

http://www.joelonsoftware.com/articles/Wrong.html

Eine interessante Lektüre wie immer.

Auszüge:

"Irgendwo las jemand Simonyis Artikel, in dem er das Wort" Typ "verwendete, und dachte, er meinte Typ, wie Klasse, wie in einem Typsystem, wie die Typprüfung, die der Compiler durchführt. Er tat es nicht. Er erklärte es sehr sorgfältig genau das, was er mit dem Wort "Typ" meinte, aber es half nicht. Der Schaden wurde angerichtet. "

"Aber Apps Hungarian hat immer noch einen enormen Wert, da es die Kollokation im Code erhöht, wodurch der Code leichter zu lesen, zu schreiben, zu debuggen und zu warten ist und vor allem falscher Code falsch aussieht."

Stellen Sie sicher, dass Sie etwas Zeit haben, bevor Sie Joel On Software lesen. :) :)


Keine Zeit mehr, da ich Stackoverflow habe. Ich denke, Spolskys bloße Verbindung mit dem Projekt muss es tun. :) :)
Dustman

3

Mehrere Gründe:

  • Jede moderne IDE gibt Ihnen den Variablentyp, indem Sie einfach mit der Maus über die Variable fahren.
  • Die meisten Typnamen sind sehr lang (denken Sie an HttpClientRequestProvider ), um vernünftigerweise als Präfix verwendet zu werden.
  • Die Typinformationen enthalten nicht die richtigen Informationen, sondern umschreiben lediglich die Variablendeklaration, anstatt den Zweck der Variablen zu skizzieren (denken Sie an myInteger vs. enthalten pageSize ).

2

Ich glaube nicht, dass jeder tollwütig dagegen ist. In Sprachen ohne statische Typen ist dies ziemlich nützlich. Ich bevorzuge es definitiv, wenn es verwendet wird, um Informationen zu geben, die nicht bereits im Typ enthalten sind. Wie in C sagt char * szName , dass die Variable auf eine nullterminierte Zeichenfolge verweist - was in char * nicht impliziert ist - natürlich würde auch ein typedef helfen.

Joel hatte einen großartigen Artikel über die Verwendung von Ungarisch, um festzustellen, ob eine Variable HTML-codiert war oder nicht:

http://www.joelonsoftware.com/articles/Wrong.html

Wie auch immer, ich neige dazu, Ungarisch nicht zu mögen, wenn es verwendet wird, um Informationen zu vermitteln, die ich bereits kenne.


Ich denke, dass der erste Satz den Antworten auf dieser Seite glauben könnte.
Dustman

@Dustman Nun, wissen Sie nicht schon , dass C-Strings nullterminiert sind? Ich sehe, wie nützlich es wäre, wenn die Zeichenfolge nicht vorhanden wäre, aber das ist selten, und daher denke ich, dass die Verwendung der Konvention auf diese Fälle beschränkt sein sollte.
Plumenator

Nicht jedes Zeichen * ist eine nullterminierte c-Zeichenfolge. Der Sinn des Ungarischen ist es, es für jede Variable zu verwenden, auch für diejenigen, die in den allgemeinen Fall fallen. Letztendlich fühle ich mich wie Sie - und deshalb benutze ich es nicht in C.
Lou Franco


2

Ich fing an zu programmieren, als die ungarische Notation erfunden wurde und als ich zum ersten Mal gezwungen war, sie für ein Projekt zu verwenden, hasste ich sie.

Nach einer Weile wurde mir klar, dass es tatsächlich geholfen hat, wenn es richtig gemacht wurde, und heutzutage liebe ich es.

Aber wie alles Gute muss es gelernt und verstanden werden und es braucht Zeit, um es richtig zu machen.


1

Die ungarische Notation wurde insbesondere von Microsoft missbraucht, was zu Präfixen führte, die länger als der Variablenname sind, und zeigt, dass sie ziemlich starr ist, insbesondere wenn Sie die Typen ändern (das berüchtigte lparam / wparam, unterschiedlicher Typ / Größe in Win16, identisch in Win32 ).

Daher wurde es sowohl aufgrund dieses Missbrauchs als auch aufgrund seiner Verwendung durch M $ als nutzlos eingestuft.

Bei meiner Arbeit codieren wir in Java, aber der Gründer kommt aus der MFC-Welt. Verwenden Sie daher einen ähnlichen Codestil (ausgerichtete Klammern, das gefällt mir!, Großbuchstaben zu Methodennamen, ich bin daran gewöhnt, Präfix wie m_ für Klassenmitglieder (Felder) ), s_ zu statischen Elementen usw.).

Und sie sagten, dass alle Variablen ein Präfix haben sollten, das ihren Typ anzeigt (z. B. ein BufferedReader heißt brData). Was sich als schlechte Idee herausstellt, da sich die Typen ändern können, die Namen jedoch nicht folgen oder die Codierer bei der Verwendung dieser Präfixe nicht konsistent sind (ich sehe sogar aBuffer, theProxy usw.!).

Persönlich habe ich mich für ein paar Präfixe entschieden, die ich nützlich finde. Das wichtigste ist b, um boolesche Variablen zu präfixieren, da dies die einzigen sind, bei denen ich Syntax wie zulasse if (bVar)(keine Verwendung von Autocast einiger Werte auf true oder false). Beim Codieren in C habe ich ein Präfix für Variablen verwendet, die malloc zugewiesen wurden, um daran zu erinnern, dass es später freigegeben werden sollte. Etc.

Grundsätzlich lehne ich diese Notation nicht als Ganzes ab, sondern nehme das, was für meine Bedürfnisse angemessen erscheint.
Und wenn ich zu einem Projekt (Arbeit, Open Source) beitrage, verwende ich natürlich nur die geltenden Konventionen!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.