Ergebnis 1 bis 18 von 18

Thema: Wie das T in Delphi - von Ungarischer Notation, Designfehlern und Construktoren

  1. #1

    Wie das T in Delphi - von Ungarischer Notation, Designfehlern und Construktoren

    [EDIT = Ineluki] Ich habe die Posts mal aus dem Urspruenglichen Thread entfernt, da sie nichts mit dem Thema zu schaffen hatten. [/EDIT]

    Nun, ich habe lediglich ausgedrückt, daß das T-Präfix für Delphi typisch ist, dort aber wirklich vor so ziemlich alles nennenswerte geklatscht wird, so daß sich mir die Frage stellt, ob es ein Verlust wäre, es wegzulassen. Und nein, ich glaube nicht an ungarische Notation; der Variablentyp sollte in der Regel aus dem Kontext ersichtlich sein.

    Und es ist so, daß ein reines Bildformat versucht, den Overhead möglichst gering zu halten. Falls das Format tatsächlich Delphi-spezifisch gewesen wäre, wäre "TBitmap" eine für Bildformat-Verhältnisse arg lange magic number gewesen.

    Was mich allerdings verwundert ist, daß offensichtlich Metadaten zum Bild im TImage abgelegt wurden, das Bildformat allerdings nicht. Vielleicht steckt da eine sinnvolle Designentscheidung dahinter; es erscheint mir nur recht merkwürdig, Metadaten teils separat und teils innerhalb des Bytestroms selbst abzulegen.


    Und nein, ich unterstelle nicht, daß die Welt gefälligst beim Zuse Z1 hätte stehen bleiben sollen. Oder warum nicht gleich beim Abakus? Nein warte, Finger kann man auch zum Zählen verwenden. Ich bin tatsächlich schon im Informationszeitalter angekommen; ich kann GUIs bedienen und – oh Wunder – ich sehe sogar einen Existenzgrund für mehr als eine Programmiersprache.

    Ich finde es nur interessant, wie man bei Delphi-Programmen beispielsweise immer wieder findet, daß serialisierte Listen in einem Binärformat vorliegen – tut mir leid, aber andere Sprachen kriegen das eleganter hin und exportieren in Formate, die extern bearbeitbar (oder zumindest lesbar) sind. Ich finde es etwas unschön, wenn die absolut einzige Möglichkeit, das Dokumentenformat eines Programms zu parsen, eine bestimme Programmiersprache ist, die noch dazu nicht auf allen Betriebssystemen verfügbar ist. PHP serialisiert alles (selbst Objekte) in ein einfaches ASCII-Format, Objective-C verwendet XML und C++... naja, C++ ist in vielerlei Hinsicht veraltet.

    Ich mag Delphi nicht besonders, weil ich besonders mit Delphi-Programmen Interoperabilitätsprobleme kriege, die darauf hinauslaufen, daß die Sprache offenbar Leute dazu verleitet, sprachspezifische Datenformate direkt zu exponieren. Das war 1998 noch akzeptabel; 2009 ist das weniger der Fall.

    Und nein, ich beschwere mich nicht über programmspezifische Formate. Bei denen kann der Programmierer einem oft sagen, wie man sie parsen kann. Bei Delphi-Objektdumps ist das kaum der Fall.

    Geändert von Ineluki (17.10.2009 um 19:09 Uhr)

  2. #2
    Zitat Zitat von Jesus_666 Beitrag anzeigen
    Nun, ich habe lediglich ausgedrückt, daß das T-Präfix für Delphi typisch ist, dort aber wirklich vor so ziemlich alles nennenswerte geklatscht wird, so daß sich mir die Frage stellt, ob es ein Verlust wäre, es wegzulassen. Und nein, ich glaube nicht an ungarische Notation; der Variablentyp sollte in der Regel aus dem Kontext ersichtlich sein.
    Die Präfix-Notation besteht nicht nur aus einem T. T steht nur für "Type" und weist auf einen typisieren Datentyp hin. Also einen Datentyp, den man selbst generiert hat. Es gibt aber z.B. noch den P-Präfix, der auf einen Pointer/Zeiger hinweist.
    Die Notation ist nicht wichtig. Man kann sie auch weglassen. Allerdings helfen die Präfixe um zu sehen, ob es nun um einen Standard-Datentyp handelt oder um einen typisierten.
    Man kann es halten, wie ein Dachdecker. Auf der einen Seite können sie eine Hilfe sein aber auf der anderen Seite kann man schon zum größten Teil erkennen, dass es sich hierbei um einen typisierten Datentyp handeln muss.

    Aber wäre es ein Gewinn, es wegzulassen?

  3. #3
    Ja, es wäre besser lesbar. ^^ Ob es vernachläsigbar ist, oder nicht, soll jeder selbst entscheiden, aber einen Buchstaben weniger lesen zu müssen, auf den man sowieso verzichten kann, ist definitiv ein Gewinn.
    Das ist genauso wie Klassennamen in C++ ein "C" voranzustellen um anzumerken, dass es sich um eine Klasse handelt (ja, Leute, die das machen, die aber nicht wissen, dass der Grund für den "C"-Präfix, den Microsoft "erfunden" hat, ein anderer war, als anzudeuten, dass es sich um eine Klasse handelt, gibt es genug).

  4. #4
    Da in diesem Thread die Frage aufgekommen ist, ob die Ungarische Notation sinnvoll ist, greife ich mal dieses Thema hier auf.

    Viele, die diese Konvention befürworten, aber auch viele, die sie kritisieren, wissen nicht, dass Ungarische Notation nicht gleich Ungarische Notation ist, es also gravierende Unterschiede gibt. Joel Spolsky erläutert in Making Wrong Code Look Wrong, wie die Ungarische Notation ursprünglich gedacht war und wie sie missverstanden wurde (der sich darauf beziehende Abschnitt ist "I'm Hungary", die anderen sind aber auch lesenswert).

  5. #5
    Zitat Zitat von Kyuu Beitrag anzeigen
    Ja, es wäre besser lesbar. ^^
    Bei Sprachen die einen new-Operator haben allemale, aber ObjectPascal stellt den constructor als praktisch statische Prozedur da.
    Code:
    var
       MyObj : TObject; // MyObj ist jetzt die Instanzvariable
    ...
       MyObj := TObject.Create(); // hier ist der entscheidende Punkt!
       MyObj := Object.Create(); // kann auch locker irgend ein Objekt sein, das die Methode Create enthält O_o
       MyObj := XMLDoumentManager.Create(); // Neues Objekt vom type XMLDoumentManager oder ein neues XMLDokument?

  6. #6
    Ruby hat auch keinen new-Operator und kann ohne Präfixe auskommen. ^^
    Du kämpfst auf verlorenem Posten, weil du einen Designfehler zu verteidigen versuchst.
    Methodennamen (sowie Prozeduren/-Funktionsnamen) müssen immer das wiedergeben, was sie tun (eine der wichtigsten Regel in der Programmierung) und bei einer Methode, die Create heißt und auf ein Objekt des Typs Object angewendet wird, erwarte ich die Erzeugung einer neuen Instanz des Typs Object. Das wird bei einem Objekt vom Typ ObjectManager auch nicht mehrdeutig. Sollte eine Methode etwas anderes machen, als eine neue Instanz des Typs zurückzugeben, auf dem sie angewendet wird, darf sie nicht Create oder New oder ähnlich heißen. Im Falle, dass ObjectManager eine neue Instanz vom Typ Object zurückgeben soll, muss die Methode auch entsprechend aussehen, also z.B. CreateObject oder CreateNewObject oder ähnlich.

  7. #7
    Dito mit kyuu. Objective-C hat auch keinen new-Operator und Klassen haben oft mehrere Konstruktoren mit verschiedenen Namen. Konventionen helfen hier.

    Grundlegenderweise allokiert man ein Objekt so: NSString* foo = [NSString alloc]; (Der NS-Präfix identifiziert die Klasse als Teil der Standardbibliothek und ist kurz für "NeXTStep".)
    Die so erzeugte Instanz muß man dann noch initialisieren. Im einfachsten Fall sieht das so aus: [foo init];
    Wenn man mit Parametern initialisieren will, dann muß man eine entsprechende Funktion dafür bereitstellen: [foo initWithString:someString];

    Jetzt ist es umständlich, immer NSString* foo = [[NSString alloc] initWithString:someString]; zu schreiben, also gibt es für so etwas statische Wrapper. Mit denen sieht das dann so aus: NSString* foo = [NSString stringWithString:someString];

    Jeder Obj-C-Entwickler erkennt sofort, daß initWithFoo:bar: das Objekt mit einem foo und einem bar initialisiert oder daß [Foo foo] eine statische Methode ist, die ein Foo allokiert und initialisiert. Schlicht, weil die Stilrichtlinien der Sprache und alle sinnvollen Codebeispiele (vor Allem natürlich die ganze API) einem genau das vorleben.

    Letztenendes ist das auch nur eine Konvention, aber es ist eine, die den Code schön lesbar hält.

  8. #8
    Zitat Zitat von Kyuu Beitrag anzeigen
    (ja, Leute, die das machen, die aber nicht wissen, dass der Grund für den "C"-Präfix, den Microsoft "erfunden" hat, ein anderer war, als anzudeuten, dass es sich um eine Klasse handelt, gibt es genug).
    Mal blöd und rein interessehalber in die Runde gefragt: Was war der Grund?

  9. #9
    Zitat Zitat von NPC Fighter Beitrag anzeigen
    Mal blöd und rein interessehalber in die Runde gefragt: Was war der Grund?
    Dito.

  10. #10
    Zitat Zitat von Kyuu Beitrag anzeigen
    Ruby hat auch keinen new-Operator und kann ohne Präfixe auskommen. ^^
    Du kämpfst auf verlorenem Posten, weil du einen Designfehler zu verteidigen versuchst.
    Verloren ja, aber Designfehler? Ansichtssache. z.B. erkenne ich bei Objectiv-C nicht im geringsten was passiert, da es für meine Verhältnise oder Vorstellungen einfach viel zu kryptisch ist.

    Zitat Zitat von Jesus_666
    Jeder Obj-C-Entwickler erkennt sofort, daß initWithFoo:bar: das Objekt mit einem foo und einem bar initialisiert oder daß [Foo foo] eine statische Methode ist, die ein Foo allokiert und initialisiert.
    Aber eben nur die erkennen es. Wenn man mal ganz ehrlich ist, so kann man nicht darauf schließen wenn man [[NSString alloc] initWithString:someString]; sieht, dass dort etwas erzeugt wird. Designfehler? Eben Ansichtssache.

    Zitat Zitat von Kyuu
    Ja, es wäre besser lesbar. ^^ Ob es vernachläsigbar ist, oder nicht, soll jeder selbst entscheiden, aber einen Buchstaben weniger lesen zu müssen, auf den man sowieso verzichten kann, ist definitiv ein Gewinn.
    Ein Buchstabe?

  11. #11
    Zitat Zitat von NPC Fighter Beitrag anzeigen
    Mal blöd und rein interessehalber in die Runde gefragt: Was war der Grund?
    Zur damaligen Zeit waren Namespaces noch nicht Teil des C++-Standards und Programmierer, aber besonders Unternehmen wie Microsoft hatten bei ihren Bibliotheken mit Namenskollisionen zu kämpfen. Z.B. gab es Kollisionen bei allgemeinen Namen wie String oder Vector. Um dieses Problem zu bewältigen, entschied sich Microsoft bei seinen MFC-Klassen ein "C" voranzustellen (aus welchen Gründen auch immer; eventuell ist sogar etwas von dem Hype um die Ungarische Notation reingeflossen). Das ging auch einige Zeit gut, bis andere Programmierer es besonders toll fanden und ebenfalls bei ihren Klassen ein "C"-Präfix verwendeten und schon hatte man das Problem wieder. In neueren Projekten (z.B. das NET-Framework) verzichtet Microsoft auf dieses Präfix bei Klassen und rät davon auch offiziell in den Guidelines ab.

    @Desmulator:

    Programmiersprachen sind natürlich nicht perfekt und jede Sprache hat ihre Macken und Fehler, aber ich würde schon zwischen subjektiven Wahrnehmungen, die z.B. aus fehlender Kenntnis über die Syntax resultieren, und Argumenten, die objektiv auf dem Vergleich aufbauen unterscheiden.
    In C++ ist es z.B. ein Designfehler, dass die Templatesyntax "<" und ">" verwendet, weil das zu unnötigen Parsingkomplikationen führt und teilweise auch unlesbar werden kann, die andere, neuere Sprachen wie z.B. D nicht haben, weil sie aus der negativen Erfahrung gelernt haben. Diese Aussage ist objektiv. Natürlich kann man sich daran gewöhnen, aber das ist nicht der Punkt bei der Kritik.

    Geändert von Kyuu (16.10.2009 um 21:23 Uhr)

  12. #12
    Zitat Zitat von Desmulator Beitrag anzeigen
    Aber eben nur die erkennen es. Wenn man mal ganz ehrlich ist, so kann man nicht darauf schließen wenn man [[NSString alloc] initWithString:someString]; sieht, dass dort etwas erzeugt wird. Designfehler? Eben Ansichtssache.
    Nun, man könnte aus "alloc" schließen, daß etwas allokiert wird und aus "initWith...", daß etwas initialisiert wird. Natürlich sehen Obj-C-Konstruktoren solchen aus C-artigen Sprachen nicht ähnlich, weil sie nicht aus C kommen sondern aus Smalltalk. Allerdings ist es, sofern man weiß, daß [X Y] Funktion Y von Objekt X aufruft, eine sehr schnell gelernte Konvention. Ich unterstelle mal, daß du Probleme mit dem Verstehen des Codes hast, weil du Smalltalk-Syntax nicht gewohnt bist, und nicht weil alloc so wenig auf Allokation hindeutet.

    Und das ist mein ganzes Argument: Objective-C braucht keine besondere Auszeichnung für Klassen, da die Sprachkonventionen so gewählt wurden, daß (sofern der Programmierer sich daran hält und der Leser die Syntax der Sprache kennt) aus dem Kontext heraus ersichtlich ist, was gemeint ist.

  13. #13
    Wenn ich das richtig verstanden habe soll die Ungarische Notation Varibalen-TYPEN genauer beschreiben? (Damit ich mir mal ne Meinung dazu bilden kann xD)

  14. #14
    Bei Apps Hungarian ist die Art der Variable interessant, nicht der Typ. Allerdings gibt man seinen Variablen in den meisten Fällen sowieso Namen, aus denen die Bestimmung ersichtlich ist. Am besten gänzlich auf die Ungarische Notation verzichten, denn der Aufwand zahlt sich nur in sehr seltenen Fällen überhaupt aus.

  15. #15
    @R.D.: Jein. Genauer beschreiben ist wohl der falsche Ausdruck, vielmehr soll gekennzeichnet werden, welchen Datentyp eine Variable überhaupt hat, damit man sie im Laufe des Programms nicht falsch verwendet.
    Edit: Okay, ich schreibe viel zu langsam :P.

    So im Detail kannte ich die ungarische Notation gar nicht. Ich habe sie nur im Sinne der Datentypenkennzeichnung in der Berufsschule gelernt/anwenden müssen. Ohne den Artikel (dessen Link ich gerne behalten hätte :/) genauestens studiert zu haben; ein Bekehrter werde ich nicht mehr. Des Datentyps bin ich mir stets bewusst (natürlich auch Dank den modernen Entwicklungsumgebungen) und eine Bezeichnung der Aufgabe ergibt sich für mich direkt aus dem Variablennamen.
    Vielleicht sehe ich als Java- und C#- Entwickler die Sache einfach anders, als es jemand tut, der in einer weniger streng typisierten Sprache programmiert.

    Geändert von Owly (17.10.2009 um 19:32 Uhr)

  16. #16
    Zitat Zitat von Roedy Greens How To Write Unmaintable Code
    Hungarian Notation is the tactical nuclear weapon of source code obfuscation techniques; use it! Due to the sheer volume of source code contaminated by this idiom nothing can kill a maintenance engineer faster than a well planned Hungarian Notation attack.
    Etwas überspitzt, aber mit Wahrheitsgehalt. Gemeint ist Systems Hungarian.

    Zitat Zitat von Owly Beitrag anzeigen
    Des Datentyps bin ich mir stets bewusst (natürlich auch Dank den modernen Entwicklungsumgebungen) und eine Bezeichnung der Aufgabe ergibt sich für mich direkt aus dem Variablennamen.
    Genau so ist es.
    Ich kann mir durchaus einige sinnvolle Anwendungen für die Ungarische Notation vorstellen.
    Für Apps Hungarian, wenn viele Programmierer gleichzeitig an einem Projekt arbeiten und jeder eigene Vorstellungen davon hat, wie Bezeichner auszusehen haben. In diesem Fall ist ein Standard erforderlich und Apps Hungarian, oder eine Abwandlung davon könnte erfolgsversprechend angewendet werden.
    Oder für Systems Hungarian, wenn man mit einer dynamisch typisierten Sprache zu tun hat und der Code komplex genug ist, um die zusätzlich kodierten Typinformationen im Bezeichner zu rechtfertigen.
    Aber in den meisten Fällen und besonders für Hobbyprogrammierer ist die Ungarische Notation nur unnötiger Ballast, teilweise schwer zu lesen, bringt Wartungs- und Migrationsprobleme mit sich und sollte vermieden werden. Zudem ist das Konzept sowieso überholt, da heutige Compiler viel bessere Typsysteme haben als zur Blütezeit der Ungarischen Notation, moderne Editoren Hervorhebung unterstützen und in objektorientierten Sprachen hat es es sowieso wenig verloren.

  17. #17
    Ok, verstanden.
    Na gut, dann ist es wie Kyuu sagt. Wenn man im Team arbeitet, kann das durchaus von Vorteil sein. Aber wenn ich was progge, dann lege ich mir die Namen so zurecht, das ich sie auch nach einem Monat noch nachvollziehen könnte. (Was MEIßT klappt^^)

  18. #18
    Das Problem ist, daß es oft problematisch ist, ungarische Notation zu verwenden, ohne allzu generisch zu werden oder einen Riesenhaufen Buchstabensalat zu haben.

    Nehmen wir an, ich habe eine Instanz der Klasse Array (namens customerBase), die eine Liste von Pointern auf Instanzen der Klasse CustomerGroup beinhaltet, die wiederum (ohne Pointer) Listen von Instanzen der Klasse PayingCustomer beinhalten. Wie notiere ich das?

    lCustomerBase, weil es eine lokale Variable ist?
    oCustomerBase, weil es ein Objekt ist?
    aCustomerBase, weil es ein Array ist?
    cbaseCustomerBase, weil es CustomerBase-Instanzen beinhaltet?
    paycustCustomerBase, weil es PayingCustomer-Instanzen beinhaltet?

    Um komplett zu beschreiben, was die Variable beinhaltet, müßte ich folgendes schreiben:
    lOACbasePaycustCustomerBase
    Das ist zwar deskriptiv, dauert aber ewig zu lesen und führt beim Nachschreiben garantiert zu Vertippern.

    Man kann zwar mit Konventionen arbeiten – allerdings denke ich, daß man mit Konventionen, sinnvoller Dokumentation und gesundem Menschenverstand dafür sorgen kann, daß Variablen auch ohne ungarische Notation nachvollziehbar sind. Eine erklärende Kommentarzeile kann mehr über das aussagen, was eine Varaible bedeuten soll, als ein 20 Byte langer String.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •