Guten Tag!
Ich möchte mir einen guten C Stil aneignen. Dabei scheint mir der NASA
style guide eine gute Basis zu sein:
http://homepages.inf.ed.ac.uk/dts/pm/Papers/nasa-c-style.pdf
Wie ist eure Meinung zu diesem style guide?
Viele Grüße
Coder
dgps schrieb:> Meiner Meinung nach sollte in einem Variablennamen immer der Dateityp> ersichtlich sein.
Meh! Eigentlich eine vollkommen überflüssige Information. Sollte man
beim Lesen von Fremdcode wirklich mal wissen wollen welchen Typ eine
Variable hat, so reicht ja das Drüberfahren mit der Maus (die IDE zeigt
dann für gewöhnlich die relevanten Daten an).
Das muss man meiner Meinung nach nicht die ganze Zeit vor Augen haben...
dgps schrieb:> Meiner Meinung nach sollte in einem Variablennamen immer der Dateityp> ersichtlich sein.
wie willst du das bei Klassen und Objekten machen?
Dater Penegger schrieb im Beitrag #3050997:
> Was, wenn du ein Programm schreibst, dass nur mit Integer-Werten> arbeitet?
dann brauche ich es auch nicht, denn ich weiss ja das ich nur int werte
habe.
Peter II schrieb:> Dater Penegger schrieb im Beitrag #3050997:>> Was, wenn du ein Programm schreibst, dass nur mit Integer-Werten>> arbeitet?>> dann brauche ich es auch nicht, denn ich weiss ja das ich nur int werte> habe.
Trollantwort.
Dater Penegger schrieb im Beitrag #3051018:
> Damit zeigt sich, was von Style-vorgaben zu halten ist.>> So hat man in den 90ern programmiert, heute denkt man>> da freizügiger ;)
Genau, Gangnam Style war gestern, heute ist Harlem Shake ;-)
Schreibt doch einfach was ihr vom NASA style guide haltet :)
Datentypen im Variablennamen wurden schon in anderen threads besprochen.
Sollte man eher nicht tun.
Dater Penegger schrieb im Beitrag #3051018:
> So hat man in den 90ern programmiert
Da das Dokument mit August 1994 datiert ist scheint das ja konsistent zu
sein. Allerdings ist 1994 auch schon fast 20 Jahre her.
Nach meinem Halbwissen ist ANSI C als Standard weit verbreitet, ich muss
aber passen, in wieweit darin Stilfragen behandelt werden.
Ich denke, der NASA-Style guide ist - ähnlich vielen anderen Styles -
weitestgehend in gängige Praxis übergegangen. Ich habe da jetzt nichts
wesentlich anderes gefunden, als das, was die meisten kompetenten
Mitstreiter hier im Forum auch empfehlen.
Unwissender mit Meinung schrieb:> Nach meinem Halbwissen ist ANSI C als Standard weit verbreitet, ich muss> aber passen, in wieweit darin Stilfragen behandelt werden.
Gar nicht.
Und die sog. Hungarian Notation gehört zu den am meisten
missverstandenen Dingen in der Geschichte der Programmierung.
Nicht erst seit Microsoft die Falschinterpretation in die Welt gesetzt
hat.
Die Grundidee hinter der HN ist es NICHT, den Datentyp im Variablennamen
anzugeben, sondern in den Variablennamen in einen Bezugskontext mit den
Kürzeln herzustellen.
Schreiben wir ein CAD-Programm, dann gibt es Koordinaten in Form von
absoluten Korrdinaten und Objekt-lokalen Koordinaten.
Ein
absCenter
sagt mir dann, dass diese Mittelpunktsangabe eines Kreises in absoluten
Einheiten angebeben wurde, während ein
relCenter
eine Korrdinatenangabe in Bezug auf das Objekt darstellt (relativ zu
diesem Objekt), welches den Kreis enthält.
Das war die Idee hinter der Hungarian Notation und nicht dass man einen
Zero-Terminated String mit dem Kürzel sz als Prefix bedenkt.
Peter II schrieb:> bei Klassen und Objekten
Man schreibt einfach immer o davor, dann weiß jeder, dass es ein Objekt
ist, bei objektorientierter Programmierung ist das schließlich sehr
wichtig.
>NASA
boxed comments verschwenden Platz ohne Mehrnutzen und sorgen dafür, dass
niemand die Kommentare anpasst, um die Sternchenformatierung nicht zu
verbiegen. Kommentare im Doxygenformat sind hier viel sinnvoller.
Standard short names sind Mist. Wenn sich für die Variable kein
vernünftiger Name anbietet, ist der Code falsch struklturiert.
Die gigantische Länge der Funktion GetReference() im Beispielcode würde
ich auch nicht als Vorbild nehmen.
'standard short names' benutzt so gut wie jeder!
Jetzt erzähl mir nicht, dass Du noch nie für einen lokalen pointer p
als Namen benutzt hast. Oder klassischerweise i als Array- oder
Schleifenindex...
Sieht alles sehr vernünftig aus. Ich vermisse nur die Festlegung, dass
in Kontrollstrukturen (if, else, switch, do, while) immer Klammern
gesetzt werden müssen, auch wenn danach nur ein Statement folgt. Das
erleichtert das Einfügen neuer Statements und das Finden von Fehlern.
Beispiel: Was macht man, wenn man über diesen Code stolpert? Ist das nur
falsch eingerückt oder ein Fehler?
1
if(x)
2
if(y)
3
mach_dies();
4
else
5
mach_das();
6
mach_jenes();
7
mach_nochwas();
Noch eins: Fehlt hier ein Strichpunkt oder die Einrückung?
1
while(!x)
2
mach_dies();
3
mach_das();
Mit Klammern wäre sofort klar, was gemeint war. Außerdem sieht der Code
wesentlich sauberer aus, wenn es zu jedem if, else, do, while, switch
und case eine Klammer auf der gleichen Ebene gibt und nicht irgendwo
zwei oder mehr Ebenen auf einmal "zurückgesprungen" wird.
Ich habe mir deshalb angewöhnt, auch nach jedem case in einem
switch-Statement Klammern zu setzen. Allerdings ist das zugegebenermaßen
eher unüblich:
Wow, ist ja wirklich ein Zufall!! Ich mache das genauso schon seit
Jahren und dabei habe ich vorher nie was von irgendeinem NASA style
gehört. Ich habs mir so angewöhnt, weil ich immer die Übersicht behalten
will.
Fabian O. schrieb:> [..] Ich vermisse nur die Festlegung, dass> in Kontrollstrukturen (if, else, switch, do, while) immer Klammern> gesetzt werden müssen, auch wenn danach nur ein Statement folgt. Das> erleichtert das Einfügen neuer Statements und das Finden von Fehlern.> [..]
Da gibt es ein ganzes Kapitel drüber:
Patrick Dohmen schrieb:> Da gibt es ein ganzes Kapitel drüber:
Darin wird aber nicht festgelegt, dass immer Klammern gesetzt gehören:
> We encourage the use of braces to improve readability. Use your own> judgment when deciding whether or not to use braces, remembering that what> is clear to you may not be obvious to others who read your code.> [...]> If else statements that have only simple statements in both the if and else> sections do not require braces but should be indented one level
So macht es wieder jeder wie er will, und dann noch nicht mal
konsistent. Manchmal Klammern obwohl nur ein Statement, manchmal nicht,
je nach Geschmack ...
Ebenso halte ich das hier für schlechten Stil:
> If a for or while statement has a dummy body, the semicolon should go on> the next line. It is good practice to add a comment stating that the> dummy body is deliberate.
1
for(char_p=string;*char_p!=EOS;char_p++)
2
;/* do nothing */
Warum nicht auch konsequent mit Klammern?
1
for(char_p=string;*char_p!=EOS;char_p++){
2
/* do nothing */
3
}
Mal abgesehen davon, dass ich in dem Fall eine while-Schleife passender
fände:
Fabian, ich kann Dich schon verstehen. Das ist vermutlich einer der
Punkte, warum es so viele "verschiedene" styles gibt. Die meisten
unterscheiden sich wirklich in Details.
:-)
Davis schrieb:> Peter II schrieb:>> Dater Penegger schrieb im Beitrag #3050997:>>> Was, wenn du ein Programm schreibst, dass nur mit Integer-Werten>>> arbeitet?>>>> dann brauche ich es auch nicht, denn ich weiss ja das ich nur int werte>> habe.>> Trollantwort.
Nö, absolut üblicher, guter Stil.
Was mir an dem NASA-Style nicht gefällt:
IMO
- öffnende Klammern gehören nie in eine eigene Zeile, dass führt nur
dazu das bei komplexeren Algorithmen zu wenig auf den Bildschirm passt.
- Kommentare kommen nicht ans Zeilenende, beim nächsten Refactoring
sieht die u.U. keiner mehr oder nur zum Teil
- Underscore-Massaker gemixt mit CamelCase
- sinnlos Suffixe/Präfixe
- return ist keine Funktion (schreiben sie zwar selber, die Beispiele
sind aber alle return(xyz);)
- sowas
1
2
for(i=0;i<n;i++)
3
if(vec[i]>max)
4
max=vec[i];
geht gar nicht, 1. widerspricht es den eigenen Regeln (u.a. Leerzeichen
vor/nach Zuweisungen, Vergleichen etc.), 2. da fehlen Klammern, falls so
was irgendwann mal erweitert werden sollte
- einiges ist dem Alter des Dokuments geschuldet...
Vielen Dank erstmal für die vielen statements! :)
@Fabian, Arc Net:
- Ich würde die Klammer immer in die nächste Zeile schreiben:
1
char_p=string;
2
while(*char_p!=EOS)
3
{
4
char_p++;
5
}
Ist doch deutlich besser zu lesen wie
1
char_p=string;
2
while(*char_p!=EOS){
3
char_p++;
4
}
Und gerade bei längeren Algorithmen sollte gute Lesbarkeit gewährleistet
werden. Scrollen wird man früher oder später immer müssen. Aber ich habe
keine wahnsinns Erfahrung. ;) Wer stimmt mir zu, wer nicht? :)
Zweite Frage:
Underscore-Massaker oder CamelCase? Welchen Stil benutzt ihr? Ich habe
früher upper CamelCase benutzt, bin aber am Überlegen, ob ich nicht doch
mit underscores arbeiten sollte. ?
Ist beides reine Geschmackssache. Wichtig ist vor allem, dass man sich
für einen Stil entscheidet und den konsequent durchzieht, vor allem
nicht innerhalb einer Datei hin- und herwechselt.
Die öffnenden Klammern in eine neue Zeile zu setzen benötigt eine Menge
Platz, so dass man weniger Code auf dem Bildschirm überblicken kann:
1
if(a)
2
{
3
mach_dies();
4
}
5
else
6
{
7
mach_das();
8
}
Da kommt man schnell in Versuchung, die Klammern wegzulassen, um Platz
zu sparen, mit den oben genannten unschönen Auswirkungen:
1
if(a)
2
mach_dies();
3
else
4
mach_das();
Setzt man die Klammern dagegen in die gleiche Zeile, ist der Code kaum
länger:
1
if(a){
2
mach_dies();
3
}else{
4
mach_das();
5
}
Zu CamelCase vs. Underscore: CamelCase ist kürzer und ggf. besser
lesbar, wenn man sprechende Namen benutzt. Allerdings sind Underscores
in C üblicher. In der Standardbibliothek gibt es zumindest afaik keine
CamelCase-Bezeichner. Auf jeden Fall würde ich Funktionsnamen mit einem
Kleinbuchstaben beginnen lassen, damit Aufrufe von Standardfunktionen
und eigenen Funktionen einheitlich aussehen.
Dann kommt noch dazu, dass man den öffentlichen Funktionen eines Moduls
sinnvollerweise den Namen des Moduls (= Name der c-Datei) voranstellen
sollte. Das sieht mit Underscores imo am gefälligsten aus:
1
lcd_init()
2
lcd_set_cursor()
3
lcd_putchar()
Netter Nebeneffekt: Man kann Bezeichner aus der Standardbibliothek wie
putchar ohne Stilbruch 1:1 übernehmen.
Wie würde man das mit CamelCase machen?
1
lcdInit()
2
lcdSetCursor()
3
lcdPutChar()
Nicht so schön. Mit Großbuchstaben wirds hübscher, aber passt wie gesagt
nicht zu Funktionsaufrufen der Standardbibliothek. Außerdem müsste man
die Datei dann konsequenterweise Lcd.c statt lcd.c nennen:
1
LcdInit()
2
LcdSetCursor()
3
LcdPutChar()
Oder nur das Präfix mit Underscore und den Rest CamelCase:
1
lcd_init()
2
lcd_setCursor()
3
lcd_putChar()
bzw.
1
lcd_init()
2
lcd_setCursor()
3
lcd_putchar()
Kann man imo noch am ehesten machen, ist aber eben beides gemischt in
einem Bezeichner. Daher finde ich in C konsequenten Verzicht auf
CamelCase am stimmigsten. Ist aber wie gesagt wirklich Geschmackssache.
Solange man einen Stil einheitlich durchzieht gibt es kein richtig oder
falsch. Na gut, außer vielleicht:
Zu CamelCase vs underscores fällt mir ein:
http://whathecode.wordpress.com/2011/02/10/camelcase-vs-underscores-scientific-showdown/
Code-Style ist schwierig, jeder hat da seine Eigenarten.
Für manche Sprachen (z.B. Python) gibt es da "offizielle" Richtlinien
und man wird regelrecht geköpft, wenn man einen anderen Code-Style hat.
In anderen Sprachen ist dann wirklich alles offen.
Ich denke alleine die Diskussion über CamelCase oder underscores zeigt
wie sehr es nicht die eierlegende Wollmilchsau gibt.
Ich denke, dass an dem NASA Dokument die Dinge zu bemängeln sind, die
oben schon genannt wurden.
Ich persönlich würde (mittlerweile, das war auch mal anders) immer
öffnende Klammern in die gleiche Zeile setzen.
Was Kürzel in Variablennamen angeht, bin ich (sozusagen) generell
dagegen. Ich denke es hat einen effektiven Mehrwert, wenn man die Namen
eher ausschreibt. Auch wenn dabei Monster-Namen zustande kommen. Endlich
mal ein Vorteil der heutigen Widescreen-Monitore ^^.
Allgemein anerkannte Kürzel wie "str" für String sind aber OK finde ich.
Dass der Typ einer Variablen in den Namen gehört, ist für mich nur
gegeben, wenn man den Fall hat, dass man die gleiche Variable mehrfach
in verschiedenen Datentypen vorhanden hat. Ansonsten kann man
nachschauen.
Grüße
Danke für die Beteiligung an der Diskussion ^^
Blöde Sache mit den verschiedenen Stilen -.-
Mir persönlich scheint dieser Stil am schönsten:
LCD_Init();
TCP_Init();
I2C_StandardConfig();
Was dafür spricht:
1)
Man kann hier sehr schön die einzelnen Module unterscheiden. Genial!
2)
Die Namen sind nicht zu lang, weil man anstatt "standard_config"
zusammenfasst zu "StandardConfig". Das jetzt nur als kleines Beispiel.
3)
Finde die Lesbarkeit einmalig gut. ^^ Viel besser, wie pures camelCase
oder pures underscore.
4)
Ausserdem achte ich drauf, dass Bezeichner nicht zu lang werden.
Erschwert sonst das Lesen ungemein. Zum Beispiel nicht
"Motion_Detector_Countdown", sondern "MotDet_Cntdwn". Hier ist es vll
nicht sooo einsichtig, aber in größeren Codeblöcken machen riesige
Bezeichner das Lesen zur Qual und man
muss immer ganz genau lesen, ob es immer noch der gleiche Bezeichner
"Motion_Detector_Countdown" ist oder doch der "Motion_Detector_Counter"
gemeint ist. Das hier nur auch als kleines Beispiel :)
Meine Datei heißt dann übrigens auch TCP.c oder StandardConfig.c
Hab an dieser Stelle keine Probleme mit Großbuchstaben.
Fabian O. schrieb:> Netter Nebeneffekt: Man kann Bezeichner aus der Standardbibliothek wie> putchar ohne Stilbruch 1:1 übernehmen.
Das natürlich ein Argument. An dieser Stelle würde ich aber eventuell
auch so weit gehen, dass ich LCD_putchar() schreibe, anstatt
LCD_Putchar().
Müsste ich mir aber noch genauer überlegen ;)