Forum: Compiler & IDEs Typpräfixe im Programmcode


von Daniel B. (khani)


Lesenswert?

Hallo,

ich hätte mal eine Frage :
Warum finden manche Leute hier Typpräfixnotation bei Variablen nicht
sinnvoll ?!

Ich finde schon, dass es einen gewissen Nutzen hat, den Typ einer
Variable mit in den Namen der Variable aufzunehmen. Ich bin nicht
derjenige, der die komplette Bedeutung der "ungarischen Notation"
ausschöpfen will. Ich denke aber schon, dass es dem Programmieren nicht
schadet, den Variablentyp mitzuführen.
Mir ist dabei völlig klar, dass es auch ohne geht, aber ich finde es
üebrsichtlicher. Gibt es denn konkrete Vorbehalte oder ist das nur eine
Glaubenssache ?

Ich möchte ein Beispiel bringen :

Bei meinen Arbeiten mit FAT kommen sehr viele verschiedene Datenbreiten
zum Einsatz. Von 8 Bit bis 32 Bit ist alles dabei.

Ich habe nun folgende Schnipsel :
1
uint8_t ui8FATNextDirEntry(uint8_t ui8Item, xFATCursorStruct xCursor,
2
uint16_t *pui16Buffer)
3
{
4
5
  ...
6
7
  ui8ATAReadSector(xCursor.ui32FirstSectorOfCluster +
8
xCursor.ui8SectorOfCluster, 0, 0);
9
10
  ...
11
12
  ui32FirstCluster = *((uint32_t *)(&(pui16Buffer[FATCursor.ui16Offset
13
+ FAT_DIRENTRY_FSTCLUS_WORD])));
14
15
  ...
16
17
   return 0;
18
}

Ich finde das Mitführen eines Typ wirkt sich hier positiv auf das
Umherschaukeln von verschiedenen Typen aus. Über ATA kommen 16bit-Werte
rein, die dann anschließend als 8-, 16-, und 32-bit-Werte interpretiert
und weiter verarbeitet werden müssen.

Ich bin auf Eure Meinungen gespannt. Mir ist völliug klar, dass in
vielen Fällen der Compiler einen auf implizite Typkonversionen hinweist
- in obigem Falle würde der Compiler keinen Anstoß daran nehmen, wenn
man den 16-bit Puffer wie einen 8-bit-Puffer verwendet. Das würde aber
zu äußerst "interessanten" Ergebnissen führen.

MfG, Daniel.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Vielleicht haben viele Leute deshalb eine (rein politisch-religiöse)
Abneigung gegenüber dieser "ungarischen Notation", weil sie von
Microsoft propagiert wird und daher nur schlecht und böse sein kann.

Tatsächliche Argumente fände ich hingegend spannend.

von Ingo (Gast)


Lesenswert?

Ich gehöre wohl zur Gegenseite. Die HN ist nach meinem Empfinden völlig
nutzlos und schlimmstenfalls irreführend bzw. mehrdeutig.

Beispiel xFATCursorStruct. Ich nehme mal an, das ist eine Struktur:

struct xFATCursorStruct
{
...
};

Was passiert, bei einem typedef:
typedef xFATCursorStruct xFATCursorStruct_t;

Ist das nun eine Struct oder ein Typ, wie unterscheidet sich ein xxx_t
von einem yyy_t? Das _t liefert keine nützliche Information!

Was passiert mit einem uint16_t beim compilieren mit tiny optionen
(dann sind alle ints nur 8 bit)?

Wenn man schon nicht mehr weiss, welchen Typ ein Parameter hat, den man
verwendet, wie wenig weiss man dann von dessen Funktion?

Und was signed/unsigned angeht: Da ist man erst fertig, wenn alle
Compilerwarnings geprüft und beseitigt sind (ja, das geht).

von A.K. (Gast)


Lesenswert?

Ich warte auf den ersten Fall, in dem ein solcher ui32Sonstwas 64bit
breit ist, weil man abermillionen Programmierern nicht zumuten kann,
all ihre Programme zu ändern.

von A.K. (Gast)


Lesenswert?

Ich hatte mich erst mal gefragt, warum in C-Compilern für 64bit Windows
der Typ "long" wohl 32bittig ist, obwohl jeder denkende Mensch ganz
natürlich 64bit vermuten wird.

Ist mir dank deiner Frage jetzt klar geworden. MS schreibt doch vor
32bit Typen ein "ul" davor. Und 32bittig mussten sie bleiben. Also
definiert man halt die Sprache neu.

Besser sieht's mit ul32Sonstwas aus. Wenn das noch lesbar wäre.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Typdefinitionen wie uint16_t etc. haben nichts mit der "ungarischen
Notation" zu tun.
Auch sind diese nicht von Microsoft erfunden oder gar eingeführt
worden.

"Ungarische Notation" bedeutet, daß Variablennamen mit einem den Typ
beschreibenden Präfix versehen werden, das kleinzuschreiben ist.

Also beispielsweise

   void* pBuffer;
   int iWert;
   unsigned long ulWert;

   char* pszText;

(psz: "Pointer to Zero-terminated String")

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mein persönliches wesentlichstes Gegenargument ist, dass die
Lesbarkeit unter all diesen Präfixen drastisch leidet.  Ich mag
Bezeichner, die man flüssig lesen kann bzw. die man (als des
Englischen Kundiger) automatisch mit einer gängigen Abkürzung
verbindet.

Wenn ich beispielsweise was von lpFoo lese, dann assoziiert sich für
mich damit automatisch irgendwas, das mit einem Drucker (lp = line
printer) zu tun hat.  Bei "w" (word) stellt sich sofort die Frage,
ob
das Wort nun eigentlich 16, 32 oder 64 bits breit sei.

Außerdem ist es für das Lesen und Verstehen einer Implementierung in
aller Regel völlig unerheblich, wie groß diese Variable jetzt gerade
genau ist.  Wenn ich eine Variable srcaddr habe, dann ist es für mich
wesentlich wichtiger zu erkennen, dass es sich hier um die
Quelladresse handelt, als dass ich mir das über ulSrcAddr verschandeln
lassen würde (ist das eine unterstrichene Quelladresse, "underlined
source address"? ;-) -- zumal oft genug dann so eine Adresse ganz
anders strukturiert ist, als das der simple "ul"-Präfix suggerieren
würde.

Für die Datentypen selbst habe ich mich inzwischen gut an die
C99-Typen aus stdint.h gewöhnen können.  Es wurde einfach Zeit, dass
das mal standardisiert wird.

Suffixe für typedefs mit _t finde ich weniger dramatisch als all die
HN-Präfixorgien, zumal auch gängige Syntaxhighlighter damit recht gug
umgehen können.

von Rolf Magnus (Gast)


Lesenswert?

> Vielleicht haben viele Leute deshalb eine (rein
> politisch-religiöse) Abneigung gegenüber dieser "ungarischen
> Notation", weil sie von Microsoft propagiert wird und daher nur
> schlecht und böse sein kann.

Da sieht man's mal... bei mir ist es umgekehrt.

> Tatsächliche Argumente fände ich hingegend spannend.

Also meine sind:

* Ich halte es für vollkommen überflüssig
* Die Lesbarkeit der Namen ledet darunter
* Ich finde, es sieht hässlich aus (zugegeben sehr subjektiv)

Das erste ist für mich eigentlich schon das k.o.-Kriterium.

von Peter Dannegger (Gast)


Lesenswert?

"Ich warte auf den ersten Fall, in dem ein solcher ui32Sonstwas 64bit
breit ist, weil man abermillionen Programmierern nicht zumuten kann,
all ihre Programme zu ändern."


Das sehe ich auch so.
Den Funktionen ist es in der Regel egal, welchen Wertebereich die
Parameter haben, sie funktionieren immer.

Würde man also die Typgröße mit angeben, käme man aus dem Umeditieren
bei Änderungen gar nicht mehr raus.

Und die Kettenraktionen erst (Parameterübergaben, temporäre
Variablen).


Kurz gesagt, man halst sich damit ne ganze Hucke an Arbeit auf und hat
kaum einen Gegenwert, dafür aber etwas schlechter lesbaren Code.


Ich bin auch eher Minimalist, mag also kurze Variablennamen. Daher habe
ich selbst die Typen abgekürzt (u8,s8,u16,s16,u32,s32).


Peter

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

ich halte die UN auch für nicht besonders toll lesbar. Das enzige was
ich in dieser Richtung anwende ist das vorgestellte m bei
Objektvariablen. Das hilft manchmal und schadet der Lesbarkeit eher
weniger.

Matthias

von Unbekannter (Gast)


Lesenswert?

Die entscheidende Frage beim Programmieren ist, für wen man
programmiert. Das klingt zwar komisch, aber der Hintergrund ist
folgender:

In erster Linie programmiert man für den Menschen, und nicht für den
Compiler. D.h. der Code muss von Menschen leicht gelesen werden können,
einfach nachzuvollziehen und leicht verständlich sein.

Z.B., ganz konkret:

Was macht folgende Funktion??

      ui8ATAReadSector()

Liest sie ein einzelnes uint8_t aus einem Sektor? Oder liest sie einen
kompletten Sektor?

Offensichtlich ist ja das Problem, das ein Sektor verschieden
strukturierte Daten enthalten kann, also z.B. einfacher Dateiinhalt,
Directory-Nodes und was es sonst noch für Sachen gibt.

Wären dann Funktion mit diesem Namen nicht besser:

      ata_read_raw_sector()
      ata_read_directory_entry_sector()
      ata_read_cluster_sector()

(Keine Ahnung was für Sektor-Typen es beim FAT gibt, aber das Prinzip
sollte klar sein).

(Die Diskussion Unterstrich vs. Großbuchstaben soll nicht das Thema
sein, ich finde die Unterstrich-Version ist flüssiger lesbar und
deutlich schneller und einfacher getippt.)

Der Witz an der Sache ist, dass aus dem Funktionsnamen für Menschen
ersichtlich ist, was die Funktion macht und was das Ergebnis davon ist.


Dabei macht ata_read_raw_sector() die ganze Arbeit. Die anderen
ata_read_xyz_sector() Funktionen sind im Extremfall nur Einzeiler, die
den void*-Buffer von ata_read_raw_sector() per typecast in eine
entsprechende Struktur umwandeln.

Ganz entscheidend ist bei der Sache, wie die Funktionen konkret benannt
werden, und auch Variablen etc. Dabei helfen folgende Regeln:

Funktionen, die etwas machen, sollten mit Verben bezeichnet werden.
(read, write, open, close, clear, flush, search, advance, ...)

Variablen sollten mit Substantive bezeichnet werden. (root_sector,
cursor, item_number, counter, file_name, ...)

In Sprachen wie C, sollten/können Funktionen die Atribute abfragen,
auch mit Substantive bezeichnet werden.

Adjektive kann man für genauere Bezeichnungen von Atributen verweden.

Wichtig ist eben eine gute und eindeutige Namenswahl. Z.b. kann ein
Curser auf die nächste Position verschoben werden.

Ein schlechter Name dafür wäre:

   cursor_next()

Das liest sich eher so, als ob da irgendetwas Nächstes zurückgegebn
wird, vielleicht ein Cursor. Aber so ganz klar ist das nicht.

Viel besser wäre z.B.

   advance_cursor()

Aus diesem Namen wird viel deutlicher, was die Funktion macht und vor
allem, das sie den übergeben Cursor offensichtlich manipuliert und
nichts zurück gibt (höchsten einen Fehlercode).

Langer Rede kurzer Sinn: Bei diesen ausdrucksstarken Funktions- und
Varaiblennamen stört die Ungarische Notation ungemein. Wenn es einen
Type cursor_t gibt, dann spielt es keine Rolle, wie der Implementiert
ist. Das kann ein einfacher Integer sein oder eine komplizierte
Struktur. Was den Programmierer, bzw. den Leser eines Programmes,
interessiert ist was mit dem Cursor so gemacht wird.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Hier mal ein lesenswertes Dokument zur "ungarischen" Notation,
gefunden in der Höhle des Löwen höchstselbst:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs600/html/HungaNotat.asp

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Hier mal ein lesenswertes Dokument zur "ungarischen" Notation...

Von seinem ,Schöpfer' halt, insofern verwundert es auch nicht, dass
es
keinen der üblichen Kritikpunkte an der HN auch nur ansatzweise
würdigen würde.

Die im Dokument enthaltenen Beispiele sind ein völlig typischer
Vertreter der Gattung, die drastisch belegen, was für ein unlesbarer
Kauderwelsch bei der HN herauskommt...  Im Gegensatz zu Herrn Simonyi
gibt es aber eben auch einen Haufen Programmierer, die weder an seinem
Problem der offensichtlich Stunden dauernden Namenswahl leiden noch
den (behaupteten, bewiesen wird ja nichts) Vorzug der inhärenten
Typinformation in den Bezeichnernamen irgendwie nachvollziehen können.

von Daniel B. (khani)


Lesenswert?

Hallo nochmal,

ein paar kleine Seiteninformationen :

 - der gepostete Code ist nur aus meiner Erinnerung getippt und kommt
so
   nicht in meinen Projekten vor.
 - der Prototyp von ui8ATAReadSector lautet korrekt :
1
uint8_t ui8ATAReadSector(uint32_t ui32Sector,
2
                         uint16_t *pui16Buffer,
3
                         uint16_t ui16Offset,
4
                         uint8_t  ui8WordCount);
   mir war da ein Fehler unterlaufen in obigem Beispiel.
 - ich persönlich verwende NICHT die ungarische Notation (was dem
   geneigten leser wahrscheinlich schon aufgefallen ist), sondern
   lediglich ein gewisses Typinformationskürzel.
 - 'x' steht für 'komplexer Datentyp'. Mag heißen structs usw.
 - meine Variablennamen sind schon englisch lesbar, ich finde es aber
   auch sehr praktisch schon gleich den richtigen Typ zu wissen.
   Wenn man sehr knapp mit der Bitbreite arbeitet, fällt einem
   schneller auf, wo ein Überlauf einem den Tag verderben kann.
 - IMO kann das jede(r) halten wie er/sie das will. Bei Interesse
   kann ich mal eine anständige Portion meines Codes hier herein
   stellen und dann zur Diskussion laden.
 - Meine Typinformationskürzel sind an die Notation der FreeRTOS-
   Sourcen angelehnt - da fand ich das sehr praktisch.

MfG, Daniel.

von Daniel B. (khani)


Lesenswert?

Tja, da fehlt wohl was (dann eben als Text....)
uint8_t ui8ATAReadSector(uint32_t ui32Sector,
                         uint16_t *pui16Buffer,
                         uint8_t  ui8WordOffset,
                         uint8_t  ui8WordCount);

Warum das mit dem Code nicht funktioniert hat ? Keine Ahnung.

MfG, Daniel.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

selbst Microsoft hat sich mit den .NET Sprachen von der ungarischen
Notation getrennt.

Hinzu kommt das die Codeeditoren mitlerweile soweit sind den Typ einer
Variblen direkt anzuzeigen (als Tooltip oder in einer Statuszeile) wenn
der Cursor auf dem Namen steht.

Es bleibt also nur der Vorteil den Typ (und dort auch nur die simplen
Typen) einer Variablen zu erkennen auf deren Namen der Cursor nicht
steht. Dieser minimale Vorteil wird aber durch den Nachteil der
schlechteren Lesbarkeit der Namen meiner Meinung nach deutlich
überwogen.

Matthias

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Fassen wir also zusammen:

Ob "ungarische" Notation verwendet wird oder nicht, ist exakt genauso
eine Geschmackssache des jeweiligen Entwicklers, wie die genaue
Formatierung des Quelltextes (Art der Einrückungen, Anordnung von
geschweiften Klammern, Umgang mit Whitespace etc. etc.)

Diskussionen über Geschmackssachen mutieren i.d.R. äußerst schnell zu
"flame wars" und sind daher müßig.

Wichtig ist, daß man als Entwickler für sich selbst seinen persönlichen
Stil findet und den konsistent beibehält.

Zugegeben:
"unlesbare" Codeformatierung lässt sich mit 'nem Beautifier
ersetzen, ästhetisch nicht ansprechende Namensgebung hingegen nicht.

Andererseits ließe sich zumindest in Ansätzen ein Automatismus dafür
finden:

Ersetze Großbuchstaben in Bezeichnern durch den jeweiligen
Kleinbuchstaben und füge davor einen Unterstrich ein, sofern der
Großbuchstabe nicht der erste im Namen ist.

Ganz mutige können den "Algorithmus" erweitern um:

Entferne führende Kleinbuchstaben in Bezeichnern, wenn in denen nach
obiger Vorschrift ersetzbare Großbuchstaben auftauchen.

Beides sollte mit regex hinzubekommen sein.

Vorsichtigere Gemüter extrahieren vorher alle verwendeten Bezeichner in
eine Tabelle, führen entsprechenden Ersatz auf diese Tabelle durch und
überprüfen Doubletten. Gibt es keine, kann munter automatisiert
"ent-ungarisiert" werden.


@Daniel:
Hast Du möglicherweise
"eckige Klammer auf - kleines 'c' - eckige Klammer zu" und
"eckige Klammer auf - '/' kleines 'c' - eckige Klammer zu"

um Deinen Quelltext geschrieben?

Mit 'nem großen C funktionierts:
1
uint8_t ui8ATAReadSector(uint32_t ui32Sector,
2
                         uint16_t *pui16Buffer,
3
                         uint8_t  ui8WordOffset,
4
                         uint8_t  ui8WordCount);

von Daniel B. (khani)


Lesenswert?

Hallo Rufus,

falls nach Deinem Doppelpunkt Code kommen sollte, kann ich den nicht
sehen ;-). Am Browser sollte es nicht liegen, denn meinen Originalpost
kann in seiner ganzen Schönheit betrachten.

Außerdem Danke für diesen Beitrag - ich erwarte von Dir meist eher
flammende Kommentare oder starken Zynismus, aber in diesem Fall habe
ich mich anscheinend geirrt (positiv).

MfG, Daniel

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.