Forum: Compiler & IDEs Sauberen Programmierstil erlernen (in C)


von Tom (Gast)


Lesenswert?

Hallo zusammen,

ich habe mal kurz eine Frage. Es geht um eine ordnungsgemäße bzw. 
saubere Programmierung in C für Mirkocontroller aber auch kleine 
Programme auf dem PC. Vor einigen Jahren habe ich im Rahmen meiner 
Ausbildung die Sprache C und auch Java kennen gelernt und auch genutzt. 
Da diese Sprachen gelehrt wurden, gehörte da auch der "Programmierstil" 
hinzu. Leider liegt das schon Jahre zurück und ich habe seitdem nicht 
mehr viel programmiert.

Jetzt allerdings ist es wieder soweit, dass ich Mikrocontroller 
programmiere und auch das ein oder andere PC Programm um z.B. mit dem 
Mikrocontroller zu kommunizieren. Mit der Sprache C habe ich keine 
Probleme, es fällt mir nicht schwer Funktionen etc. zu programmieren. 
Was mir allerdings etwas zu schaffen macht, ist die Übersichtlichkeit 
und ein sauberer Programmierstil. Das habe ich wohl über die Jahre 
verlernt. Bisher habe ich immer viel mit Merkern gearbeitet, aber ich 
habe schnell gemerkt, dass das sehr unübersichtilich wird. Mittlerweile 
habe ich eine globale Variable in der ich Nachrichten ablege, quasi ein 
Nachrichtensystem, auf das ich dann mit Switch/ Case zugreifen kann.

Allerdings sind das alles Sachen, die ich mir mal so überlegt habe bzw. 
über die ich dann eher zufällig gestolpert bin. Lange Rede kurzer Sinn, 
was würdet ihr vorschlagen, wie kann ich sauberes Programmieren wieder 
erlernen. Gibt es dafür gute Literatur?

Mir geht's darum, wie ich Programme sauber schreibe. Nehme ich für mein 
Vorhaben lieber Merker oder eine Art Nachrichtensystem etc. Wie und wo 
definiere ich Funktionen und Variablen, so dass sich auch andere Leute 
schnell einarbeiten können. Wie sollte ich diese am besten benennen? 
Wann verwende ich Header-Dateien und was lege ich darin fest, solche 
Sachen interessieren mich sehr. Habt ihr da z.B. einen guten Vorschlag 
für Literatur die sich damit auseinander setzt?

Vielen Dank und viele Grüße
Tom

von PittyJ (Gast)


Lesenswert?

Da hilft nur üben, Code schreiben und nochmals üben. Und nach ein paar 
Jahren bekommt man einen guten Stil.
Wichtig ist auch, sich mit anderen auszutauschen. Fragen: warum machst 
du dies und das, und darüber zu diskutieren.

Nett auch dieses Buch: Scott Meyers: Effektiv C++ programmieren.
Ist zwar C++. Aber vielleicht ist C++ eh die bessere Wahl.

von Postix (Gast)


Lesenswert?

Tom schrieb:
> Habt ihr da z.B. einen guten Vorschlag
> für Literatur die sich damit auseinander setzt?

Dazu gibt es so viele Meinungen wie Entwickler. Und wenn man sich 
Sourcecode anderer Leute ansieht, die von sich behaupten sauberen Code 
zu schreiben, merkt mans schnell, dass die Meinungen wohl SEHR weit 
ausseinander gehen und oft eher religioes als argumentativ sind. Ergo 
ist deine Frage nicht sinnvoll beantwortbar. Du wirst einfach deinen Weg 
finden muessen, denn du willst ja deinen Code spaeter wieder lesen 
koennen.

von Christian B. (casandro)


Lesenswert?

Lerne vielleicht erst mal Pascal, da funktionieren viele der 
"schmutzigen" Sachen in C nicht.

von Oliver S. (oliverso)


Lesenswert?

Tom schrieb:
Wie und wo
> definiere ich Funktionen und Variablen, so dass sich auch andere Leute
> schnell einarbeiten können.

Wie groß ist die Chance, daß andere Leute deinen Code überhaupt je zu 
sehen bekommen?

Das wichtigste zunächst einmal ist, daß du selber deinen Code aus 
früheren Zeiten verstehen können wollen willst. Klappt das, ist dein 
"Stil" in Ordnung.

Oliver

von Falk B. (falk)


Lesenswert?


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


Lesenswert?

Danke, Falk!  Ja, der Artikel hatte mir damals beim Wettbewerb schon
gut gefallen.

Ob man nun (gerade bei kleinen Controllerprojekten) für bestimmte Dinge
eher eine globale Variable nimmt oder irgendwelche komplizierteren
Gebilde, ist oft Geschmackssache.  Regeln sollte man nicht dafür
aufstellen, dass sie strikt und auf den Punkt immer befolgt werden
müssen (erst recht nicht, wenn man nur für sich allein arbeitet),
sondern wenn es einen sinnvollen Grund gibt, dann müssen auch
Ausnahmen zulässig sein.  Eins meiner typischen Beispiele für sowas
ist, warum gelegentlich eben ein goto sinnvoll ist.

Längere Funktion, die an mehreren Stellen ggf. einen Fehlerabbruch
haben muss, ohne goto zu benutzen:
1
int
2
func(blah)
3
{
4
  int rv = 0;
5
6
  if (!(error here)) {
7
    /* mach weiter */
8
    ...
9
    if (!(error there)) {
10
      /* mach weiter */
11
      ...
12
      if (!(another error)) {
13
        /* geh zum Ziel */
14
      } else {
15
        rv = ANOTHER_ERROR;
16
      }
17
    } else {
18
      rv = ERROR_THERE;
19
    }
20
  } else {
21
    rv = ERROR_HERE;
22
  }
23
24
  return rv;
25
}

Wenn man in diesem Falle ein goto zulässt, sieht das so aus:
1
int
2
func(blah)
3
{
4
  int rv = 0;
5
6
  if (error here) {
7
    rv = ERROR_HERE;
8
    goto errexit;
9
  }
10
11
  ...
12
  if (error there) {
13
    rv = ERROR_THERE;
14
    goto errexit;
15
  }
16
17
  ...
18
  if (another error) {
19
    rv = ANOTHER_ERROR;
20
    goto errexit;
21
  }
22
23
  /* geh zum Ziel */
24
errexit:
25
  return rv;
26
}

von Uwe B. (derexponent)


Lesenswert?

Hi Jörg,

dein Beispiel würde ich, weil am Goto-Ziel kein Code mehr folgt,
eher ohne GOTO schreiben :
1
int
2
func(blah)
3
{
4
  int rv = 0;
5
6
  if (error here) {
7
    rv = ERROR_HERE;
8
    return rv;
9
  }
10
11
  ...
12
  if (error there) {
13
    rv = ERROR_THERE;
14
    return rv;
15
  }
16
17
  ...
18
  if (another error) {
19
    rv = ANOTHER_ERROR;
20
    return rv;
21
  }
22
23
  return rv;
24
}

aber jeder hat da ja seinen eigenen Stil

Gruss Uwe

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


Lesenswert?

Uwe B. schrieb:
> weil am Goto-Ziel kein Code mehr folgt,
> eher ohne GOTO schreiben

Ja, OK, das Beispiel passt besser dann, wenn am Ende noch irgendwas
aufzuräumen ist.  Da hast du Recht, wenn keine Aufräumarbeiten nötig
sind, kann man sich mit einem direkten return sofort flüchten. ;-)

Aber ein return in der Mitte einer Funktion ist natürlich für die
„GOTO ist böse“-Jünger auch bereits nur ein verkapptes GOTO. :)

von HTI (Gast)


Lesenswert?

PittyJ schrieb:
> Nett auch dieses Buch: Scott Meyers: Effektiv C++ programmieren.
> Ist zwar C++. Aber vielleicht ist C++ eh die bessere Wahl.
C++ ist doch genau dafür entwickelt worden, meine ich,oder?

von Interruptus (Gast)


Lesenswert?

Da es hier gerade passt: Wie macht ihr das, in Bezug auf modulare 
Programmierung und Interrupt-Handler? Man hat ja oft mehrere Dinge, die 
pro (Timer-)Interrupt erledigt werden müssen, aber inhaltlich nichts 
miteinander zu tun haben, beispielsweise eine Echtzeituhr und eine 
Ausgaberoutine für eine Bitfolge, die sehr zeitkritisch ist.

von ♪Geist (Gast)


Lesenswert?

Probiere dich an folgende Regeln zu halten:

+  Defines für mehrfach-benutzte Konstanten
+ Funktion sollte max 3/4 Bildschirmhöhe einnehmen, im anderen Fall 
Unterfunktionen schreiben
+ Module in unter Module auslagern z.B. EEPROM Routinen und Display 
Routinen in unterschiedliche Dateien mit sinnvollen Namen
+ Redundanz vom Code vermeiden
+ Globale variablen nur dann benutzen, wenn diese wirklich notwendig 
sind.
+ Auch wenn du Vorrangregeln kennst, Klammern setzen
+ Nicht sparsam sein, was Leerzeichen und Leerzeilen angeht
+ Funktionen und Variablen sinnvolle Namen vergeben
+ Kryptischen Code a la "p *p (*p) () *(*p) () int *(*p) ();" vermeiden. 
Einen guten Programmiere macht nicht sein "h4}|{[]R57y|_3" Code aus, 
sondern die Qualität. Der Compiler macht den Rest.
1
//bad code
2
ValMax = (x > y) ? ++x : ++y;
3
4
// good code
5
if (x > y) {
6
 x++;
7
} else {
8
 y++;
9
}
-> + Gleiches Ergebnis
-> + Besser lesbar für "Unerfahrene"
-> - mehr Schreibarbeit, aber das Programmieren ist in der Regel: 90% 
Denkarbeit + 10% Schreibarbeit

von Der Rächer der Transistormorde (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Längere Funktion, die an mehreren Stellen ggf. einen Fehlerabbruch
> haben muss, ohne goto zu benutzen:

Ein Errorhandler ist ein Exceptionhandler. Imho der einzige Fall wo goto 
richtig Sinn macht da es eben eine Exception abbildet und (anders als 
break) eine "Zwangsroutine" aufruft.


Tom schrieb:
> Mir geht's darum, wie ich Programme sauber schreibe.

Wer möchte das nicht? Klingt vielleicht blöd aber nach meiner Erfahrung 
als Gelegenheitsprogrammierer ist folgende Regel das Optimum:

Setzt dich mit einem Notizbuch ein Café und schreib als erstes die 
Struktur auf. Handschriftlich ohne die Möglichkeit gleich an der 
Maschine rumzuhacken.

Schreib die einzelnen Funktionen auf und mach dir Gedanken wie du das 
ganze strukturierst.

Dann hack die Basisfunktionen rein und das gleich ein Testprogramm 
dafür.

Das geht es bei mir wesentlich leichter als wenn ich gleich anfange.

Formatierung von Sourcecode und dessen Kommentierung halte ich für 
ausdiskutiert.  Auch best practice (wie z.B. in den Kommentaren hier 
zitiert) ist von mir nicht besser zu machen.

>http://www.mikrocontroller.net/articles/Strukturierte_Programmierung_auf_Mikrocontrollern

Den Sinn der im Artikel erwähnten SVNs habe ich aber nicht verstanden. 
Meiner Meinung nach basteln 2 Leute am gleichen Sourcecode nur bei 
schlechter Entwicklungsstruktur. Bei Einzelprogrammierung ist ein 
kommentiertes zip (oder auch einfach nur ...#1  ...#2 im Namen 
sinnvoller als in SVN) sinnvoller. Eine stündliche Sicherung mache ich 
übrigens automatisch mit Backup Service Home. Das hat mich schon oft vor 
stundenlangen Restaurationen bewahrt.

von Nils (Gast)


Lesenswert?

Als oberste Regel sollte die Lesbarkeit im Vordergrund stehen. Mehrere 
Operationen in einer Zeile sind unleserlich und man muss zu viel 
überlegen. Ruhig Operationen auf mehrere Zeilen aufteilen, der Compiler 
macht da schon seine arbeit.
Ansonsten finde ich die ungarische Notation für Variablen und Funktion 
recht hilfreich.
Wo es sich anbietet setze ich mittlerweile immer State Machines ein 
anstatt von if/else Anweisungen. Zusätzlich erzeuge ich mir über eine 
Struktur Objekte, die sämtliche Variablen enthalten und übergebe diese 
dann immer per Zeiger. Ist am Anfang relativ aufwändig aber ich will es 
heute nicht mehr missen.

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


Lesenswert?

Der Rächer der Transistormorde schrieb:
> Den Sinn der im Artikel erwähnten SVNs habe ich aber nicht verstanden.
> Meiner Meinung nach basteln 2 Leute am gleichen Sourcecode nur bei
> schlechter Entwicklungsstruktur. Bei Einzelprogrammierung ist ein
> kommentiertes zip (oder auch einfach nur ...#1  ...#2 im Namen
> sinnvoller als in SVN) sinnvoller.

Nein.  Das hat man vielleicht vor 20 Jahren so gemacht, aber selbst
damals wäre RCS schon sinnvoller gewesen.

Die wesentliche Funktion eines VCS (Versionsverwaltung, /version
control system/) ist nicht in erster Linie, dass mehrere Leute am
gleichen Code arbeiten können (ist nur ein Nebeneffekt, hat übrigens
nicht zwingend mit schlechter Entwicklungsstruktur zu tun), sondern
dass man seine Werke überhaupt versionieren kann, also einen
bestimmten Zustand mit einem Kommentar versehen für die Ewigkeit
aufheben kann.  Wenn ich mir ein Projekt wie beispielsweise
AVRDUDE ansehe, das hat mittlerweile 1183 Versionen im SVN.  Wie
würdest du bei 1183 verschiedenen Zip-Archiven noch durchblicken
wollen, wofür welches Archiv mal gut war?  OK, du schmeißt alte davon
wieder weg, aber wie alt denn?  Die von letzter Woche?  Was ist,
wenn du nach einem Monat merkst, dass sich da ein Bug eingeschlichen
hatte, der dir jetzt erst auffällt?  Du bist dir ganz sicher, dass es
diesen Bug vor einem halben Jahr noch nicht gab … aber deine
Zipdateien von vor einem halben Jahr hast du natürlich nicht mehr, um
sie vergleichen zu können, was denn alles seither geändert worden war.

Nils schrieb:
> Ansonsten finde ich die ungarische Notation für Variablen und Funktion
> recht hilfreich.

Die Kritikpunkte zu selbiger sind ausgiebig im Internet diskutiert
worden.

von Oliver S. (oliverso)


Lesenswert?

Noch ein Tipp von einem Gelegenheitsprogarmmierer:

Ab und an mal einige Stunden (oder auch Tage) Zeit investieren, und das 
Projekt aufräumen. Wenn es sein muß, mit durchaus erheblichen 
Änderungen. Nicht jeder Ansatz sitzt gleich beim ersten Mal.

Ansonsten bin ich ein Fan von selbst-Dokumentierendem Code:
Um das Beispiel aus dem oben verlinkten Artikel aufzugreifen:
1
schlecht:
2
3
4
maxTests = 5;       # Setze maxTests auf 5        <--- Ach was? Hätte ich jetzt nicht gedacht
5
6
gut:
7
8
9
maxTests = 5;       # Maximal 5 mal abfragen       <--- Ahh!

noch besser:
1
MaxTestAbfrageAnzahl = 5; // gar kein Kommentar erforderlich...

Oliver

von Nils (Gast)


Lesenswert?

Oliver S. schrieb:
> Ab und an mal einige Stunden (oder auch Tage) Zeit investieren, und das
> Projekt aufräumen. Wenn es sein muß, mit durchaus erheblichen
> Änderungen. Nicht jeder Ansatz sitzt gleich beim ersten Mal.

Ist auch schwierig. Manchmal will man eine Funktion umbauen, was aber 
nicht immer beim ersten Schuss klappt. Also was macht man? Man 
kommentiert diese Zeilen aus und lässt den bestehenden Code laufen. 
Natürlich kommt dann irgendwas dazwischen und man kann sich längere Zeit 
nicht mehr mit dieser Funktion beschäftigen. Also bleiben solche Ansätze 
über mehrere neue Versionen als Kommentar erhalten. Aufräumen ist daher 
halt immer so eine Sache, da man ja nicht immer von vorne beginnen 
möchte.

Generell will ich halt sagen, dass es nicht gerade leicht ist sauberen 
Sourcecode zu schreiben und zum anderen ist es ganz einfach 
Geschmackssache. Viele Kleinigkeiten wie defines immer groß schreiben 
oder Variablen eineindeutig ( nicht nur eindeutig ) zu bennen sollte 
klar sein aber was danach kommt kommt ganz allein auf den Programmiere 
an.

Das sieht man ja auch in diesem Thread. Der eine findrt goto-Anweisungen 
ok, der andere hasst sie. Der eine mag die ungarische Notation ( avtl. 
in abgewandelter Form ) und der andere eben nicht.
Schönes We ;-)

von Postix (Gast)


Lesenswert?

Oliver S. schrieb:
> MaxTestAbfrageAnzahl = 5; // gar kein Kommentar erforderlich...

Da fehlt die Information warum.

von ♪Geist (Gast)


Lesenswert?

Oliver S. schrieb:
> noch besser:
> MaxTestAbfrageAnzahl = 5; // gar kein Kommentar erforderlich...
> Oliver

Und noch besser wäre (in dem Fall):
const unsigned char u8MaxTestAbfrageAnzahl = 5;
oder gleich als Dähfain.


Empfehlenswertes zum Lesen:
MISRA C:2012 Guidelines for the use of the C language in critical 
systems

von Patrick C. (pcrom)


Lesenswert?

Vielleicht hilft dir dieses :

http://www.splint.org/ - Ein layer auf der C compiler der auf mehr 
checkt als nur C syntax. Wenn man so etwas benutzt lernt man schnell wo 
die Fallstricke von C liegen.

Doxygen - ein tool um deine Software zu documentieren. Meine erfahrung 
ist das man dadurch regelmaessiger sich die struktur der code anschaut 
und sich ueberlegt ob es vielleicht anders kann

Weiter ist meine software-entwicklung oft einen loop wie volgendes :
1) 'Schnell-Programmierung' als proof-of-concept
2) Denken ueber die Struktur meines Programs
3a) 'Gut-programmierung' der gleichen stueck der code
3b) Documentierung mittels Doxygen
3c) Testprocedures definieren
4) Regelmaessig gucken ob die Struktur noch immer passt. Oft kommen 
spaeter Funktionalitaeten dabei. Wenn die nicht im heutigen Struktur 
passen, ueberleg dir die Struktur anzupassen und nimm die zeit um das 
fuer die ganze code zu tun.

Dann ein schoenes Buch :
http://www.amazon.de/dp/3898644707?tag=wesezubu34dec-21&camp=1410&creative=6378&linkCode=as1&creativeASIN=3898644707&adid=0R0T7ZF3KE82W4S4M9MF&&ref-refURL=http%3A%2F%2Fwww.macht-publik.de%2Fccpp%2Fbsp-doxygen.html

von Bronco (Gast)


Lesenswert?

Was ich persönlich für sehr wichtig halte:
Die Dinge beim Namen nennen, und zwar bei einem eindeutigen und 
nachvollziehbaren Namen!

Beispiele
1
if (ready)
2
{
3
    flag = 1;
4
    x++;
5
    x1++;               // Wegen Fehler vom 23.5.1979 
6
    flag_x = 1334;      
7
    adresse += 10*75;   // 10 funktioniert besser als 9
8
}

Alles klar?

Beispiel:
1
temperature = GetAdc(3);
2
temperature1 = GetAdc(4);

Besser:
1
VorlaufTemperatur  = GetAdc(3);
2
NachlaufTemperatur = GetAdc(4);

Noch besser:
1
VorlaufTemperatur  = GetAdc(ADC_KANAL_VORLAUFTEMPERATUR);
2
NachlaufTemperatur = GetAdc(ADC_KANAL_NACHLAUFTEMPERATUR);

usw.

von Fred (Gast)


Lesenswert?

Es gibt keinen sauberen oder unsauberen Programmierstil. Es gibt nur 
Programme die ihre Funktion erfüllen und die, die es nicht tun.

von ♪Geist (Gast)


Lesenswert?

Fred schrieb:
> Es gibt keinen sauberen oder unsauberen Programmierstil. Es gibt nur
> Programme die ihre Funktion erfüllen und die, die es nicht tun.

Die Ironie hat jetzt jeder verstanden, war aber nicht lustig.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Es gibt ein zentrales Kriterium für guten Programmierstil: Die 
Änderungs- bzw. Erweiterungsfreundlichkeit.

Um ein Programm ändern zu können, muss man es natürlich erst einmal 
verstanden haben. Deswegen ist die bereits genannte Lesbarkeit des 
Quellcodes natürlich ebenfalls wichtig.

Meiner Erfahrung nach lernst du am meisten, wenn du dir Code von anderen 
anschaust. Verstehst du ihn ohne größere Probleme, stellt er ein 
positives Beispiel dar, sonst ein negatives. Mit der Zeit entwickelst du 
ein Gefühl dafür, was die positiven Beispiele gemeinsam haben. Man kann 
zwar versuchen, diese Gemeinsamkeiten in Regeln zu fassen, aber wie du 
am Beispiel mit dem Goto sehen kannst, sind die Regeln  oft recht 
kompliziert und bis zu einem gewissen Grad auch Geschmackssache.

Die Erweiterungsfreundlichkeit eines Programms lässt sich danach 
bewerten, wieviele Codezeilen geändert oder hinzugefügt und an wievielen 
Stellen im Programm diese Änderungen vorgenommen werden müssen, um ein 
bestimmtes neues Feature zu implementieren. Daraus leiten sich dann 
solche Dinge ab wie die Vermeidung von mehreren gleichen oder sehr 
ähnlichen Codeabschnitten. Bei diesen besteht nämlich fast immer das 
Problem, dass du die gleichen Änderungen an mehreren Stellen durchführen 
musst oder – noch schlimmer – zu den bereits bestehenden ähnlichen 
Codeabschnitten noch weitere hinzufügen musst, die sich von den anderen 
ebenfalls nur in ein paar Details unterscheiden. Dadurch bläht sich das 
Programm im Lauf der Zeit immer mehr auf, und heraus kommt ...

... MS Office ;-)

Mach dir aber zum jetzigen Zeitpunkt nicht zu viele Gedanken über deinen 
Programmierstil, sondern nimm die in diesem Thread und dem verlinkten 
Artikel genannten Regeln als ganz grobe Richtlinie und hau einfach in 
die Tasten. Radfahren lernst du auch nicht, in dem du Bücher über 
Kreiselkräfte studierst, sondern indem du dich auf's Fahrrad setzt und 
drauflos pedalierst. Die Qualität deiner Software wird mit der Zeit 
immer besser werden, und das wirst du auch selber merken.

Wenn du in einem konkreten Fall unsicher bist, kannst du natürlich auch 
ein Stück Code hier ins Forum stellen und die Leute um ihre Meinung dazu 
bitten. Du wirst dann zig mehr oder weniger begründete Antworten 
bekommen und kannst dir daraus die für dich besten nachvollziehbare 
auswählen.

von Fred (Gast)


Lesenswert?

♪Geist schrieb:
> Fred schrieb:
>> Es gibt keinen sauberen oder unsauberen Programmierstil. Es gibt nur
>> Programme die ihre Funktion erfüllen und die, die es nicht tun.
>
> Die Ironie hat jetzt jeder verstanden, war aber nicht lustig.

Im Beitrag ist keine Ironie enthalten, weder lustig noch nicht lustig. 
Du hast meinen Beitrag einfach nicht verstanden. Ist aber nicht schlimm.

von test (Gast)


Lesenswert?

Fred schrieb:
> ♪Geist schrieb:
>> Fred schrieb:
>>> Es gibt keinen sauberen oder unsauberen Programmierstil. Es gibt nur
>>> Programme die ihre Funktion erfüllen und die, die es nicht tun.
>>
>> Die Ironie hat jetzt jeder verstanden, war aber nicht lustig.
>
> Im Beitrag ist keine Ironie enthalten, weder lustig noch nicht lustig.
> Du hast meinen Beitrag einfach nicht verstanden. Ist aber nicht schlimm.

Im Grunde stimmt die Grundaussage, ist aber eine sehr vereinfachte 
binäre Sichtweise. Die reale Welt ist ein wenig mehr als nur 
schwarz-weiß.

Wir können uns also eine Zielmetrik über die Vollständigkeit des 
"Funktion erfüllens" definieren:

 * stürzt manchmal ab.
 * Funktioniert im Regelfall
 * Funktioniert auch bei unvorhergesehenen Eingaben
 * Stürzt wirklich nicht ab, auch bei böswilligen Eingaben
 * Bei böswilligen Eingaben, wird drauf reagiert, und das System kann 
trotzdem noch funktionieren

Diese Punkte sind jetzt aus dem Bereich Safety/Security 
(Eigensicherheit/Sicherheit vor Angreifern).

Man auch andere Metriken hernehmen, um Codequalität zu beurteilen:
 * Ich kann ohne Probleme den Code lesen, verstehen und ändern
 * Der Code ist wirr geschrieben, aber Änderungen sind möglich
 * Der Code ist so wirr und hat Seiteneffekte, dass eine Änderung 
bestimmt einen Bug oder anderes ungewolltes Verhalten hervorruft.


Es gibt nicht nur Flame wars im Internet zu sauberem Programmierstil,
sondern wird aktiv erforscht.
Sowohl Apple als auch Microsoft haben die ungarische Notation lange Zeit
benutzt (ihren Programmieren vorgeschrieben). Dann gabs statistische 
Untersuchungen an Hand von großen Mengen Code. ("Senkt die Verwendung 
von ungarischer Notation, die Anzahl an Bugs?") Seit ein paar Jahren 
wird die ungarische Notation nicht mehr für neue Projekte verwendet, 
weil keine statistische Signifikanz gezeigt werden konnte.

Eine anderer interessanter Aspekt sind die Untersuchungen in Bezug auf
Fehler/Defekte pro 1000 Zeilen Code. Eine Metrik, um Code bewerten zu 
können ist zum Beispiel http://de.wikipedia.org/wiki/McCabe-Metrik
Diese Metrik ist korreliert mit der durchschnittlichen Anzahl an Bugs 
pro 1000 Zeilen Code.
https://en.wikipedia.org/wiki/Cyclomatic_complexity#Correlation_to_number_of_defects


Das ist jetzt alles hochtrabend formuliert, ist aber alles halb so wild. 
Denn Programmieren lernt man meiner Meinung genauso wie Fahrrad fahren: 
Nur duchs regelmäßige Üben und aus eigenen Fehlern.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

♪Geist schrieb:
> + Funktion sollte max 3/4 Bildschirmhöhe einnehmen, im anderen Fall
> Unterfunktionen schreiben

Das schränkt einen ziemlich ein, gerade wenn man bedenkt, daß Monitore 
heute weniger Vertikalauflösung haben als noch vor ein paar Jahren ...

Bei üblichen toolbarlastigen IDEs und Editoren dürften kaum mehr als die 
klassischen 25 Textzeilen dabei herauskommen, die einem schon das gute 
alte VT100 bot ...


Ich weiß, warum ich meinen Code auf einem hochkant stehenden Monitor 
schreibe (1600 Pixelzeilen, effektiv ~90 Textzeilen).

von Coder (Gast)


Lesenswert?

Stichwörter MISRA-C und CERT. Duck' und weg

von Wilhelm F. (Gast)


Lesenswert?

Tom schrieb:

> Habt ihr da z.B. einen guten Vorschlag
> für Literatur die sich damit auseinander setzt?

Was als Grundbasis überhaupt sehr nützlich ist:

Flußdiagramme und Struktogramme.

Die zwingen einen von alleine in die richtige Richtung.


Als Anfänger vor 20 Jahren hatte ich mal zwei Büchlein:

Paul Koster: Struktogramme. Top-Down-Technik.

Moos-Steinbruch: Programmierlogik.

von es gibt mehr als C (Gast)


Lesenswert?

C und guter Programmierstil widersprechen sich. Die ganzen Befürworter 
hier nutzen ihre unendliche Erfahrung aus tausenden abgestürzter 
Programme, um sich Anfängern gegenüber zu profilieren.

Viele Diskussionen und Beiträge zeigen, dass alle sinnvollen Konstrukte 
aus C auch mit andern Sprachen umzusetzen sind.

Für einen guten Stil würde ich erst eine andere Sprache wählen und dann 
umsteigen. Um einfach etwas hinzu daddeln kannst du gleich mit C durch 
starten.

von Bronco (Gast)


Lesenswert?

es gibt mehr als C schrieb:
> Für einen guten Stil würde ich erst eine andere Sprache wählen

Na, na, na! Ein begabter Chaot kann in jeder Sprache Spaghetticode 
schreiben...

von Simon B. (nomis)


Lesenswert?

Tom schrieb:
> was würdet ihr vorschlagen, wie kann ich sauberes Programmieren wieder
> erlernen.

Was ich vielleicht noch empfehlen möchte:

Verwende von ziemlich Anfang an möglichst ein Versionskontrollsystem. 
Wenn Du da regelmäßig mehr oder weniger funktionierende Versionen 
eincheckst, dann legt man die Angst ab, "alten" Code wegzulöschen. Weil 
er ist ja im Notfall wieder aus dem System hervorzuholen.

Man kann mehrere Varianten in unterschiedlichen Branches entwickeln und 
muss nicht alle gleichzeitig in denselben Sourcecode reinstopfen.

Ohne gleich eine Diskussion lostreten zu wollen: Ich habe gute 
Erfahrungen mit git gemacht. Das braucht zwar einiges an Zeit bis man 
sich an die Konzepte gewöhnt hat, aber hat nur geringen 
Management-overhead.

Viele Grüße,
         Simon

von Wilhelm F. (Gast)


Lesenswert?

Simon Budig schrieb:

> Verwende von ziemlich Anfang an möglichst ein Versionskontrollsystem.

Mal eine Zwischenfrage von mir:

Wie ist das mit der Versionskontrolle eigentlich, wenn dort mal eine 
wichtige Datei beschädigt ist? Ist dann noch was zu retten? Oder macht 
man für so was auch noch mal eine externe Zweitsicherung? Wenn ja: 
Lassen sich dann Dateien zurück spielen?

Ich möchte das Thema Datensicherung jetzt nicht beginnen, meine Dateien 
sind immer an zwei weiteren Orten außerhalb des PCs gesichert.

Dann ist die Frage, ab wo sich der Aufwand des Extra-Programmes lohnt. 
Für ein einzelnes kleines Hobby-Projekt im Jahr doch nicht, oder?

Ansonsten arbeitete ich schon mal mit Dateienvergleichern. Das ist aber 
in einer Versionskontrolle schon mit drinnen.

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


Lesenswert?

Wilhelm F. schrieb:

> Wie ist das mit der Versionskontrolle eigentlich, wenn dort mal eine

(Nitpicking: Versions*verwaltung*.  Das englische “to control”
heißt auf Deutsch nicht in jedem Falle „kontrollieren“.)

> wichtige Datei beschädigt ist? Ist dann noch was zu retten? Oder macht
> man für so was auch noch mal eine externe Zweitsicherung? Wenn ja:
> Lassen sich dann Dateien zurück spielen?

Ein Backup solltest du so oder so haben.

Mit dem Backup kannst du naturgemäß all das wiederherstellen, was zum
Zeitpunkt des Backups vorhanden war.

Bei Versionsverwaltungssystemen mit verteiltem Repository (git,
mercurial) enthält jeder Arbeitsbereich zugleich eine komplette
Kopie des Repositories selbst, insofern ist dort das Replizieren
in eine beliebige Richtung zugleich ein Backup.  Man sollte
natürlich aufpassen, dass man den Überblick behält, wer von wem
repliziert. ;-)

Bei Versionsverwalungssystemen mit zentralem Repository (SVN, CVS
dürfte heute niemand mehr als Neuanfang nehmen) muss man halt
regelmäßige Backups des Servers anfertigen.

> Dann ist die Frage, ab wo sich der Aufwand des Extra-Programmes lohnt.

Ja, immer, sowie man mehr als eine Version einer Datei hat.

Wirklich immer.

von Pascal (Gast)


Lesenswert?

1
/*Pascal.h*/
2
#ifndef _PASCAL_H_
3
#define _PASCAL_H_
4
5
#define BEGIN  {
6
#define THEN   {
7
#define DO     {
8
#define IF     if
9
#define WHILE  while
10
#define END    }
11
#define ENDIF  }
12
#define LOOP   }
13
#define WEND   }
14
#define ELSEIF } else {
15
#define FUNCTION  int
16
#define PROCEDURE void
17
18
#endif //_PASCAL_H_


1
/*Test.c*/
2
#include <avr/io.h>
3
#include "pascal.h"
4
5
PROCEDURE Test(int a, int b)
6
BEGIN
7
 IF (a>b) THEN
8
   a=a-1;
9
 ENDIF
10
END
11
12
13
FUNCTION main(void)
14
BEGIN
15
 int a=7,b=10;
16
 Test(a,b);
17
 WHILE(1) DO
18
   IF (a==b) THEN
19
     main();
20
   ELSEIF
21
     a=a+1;
22
   ENDIF
23
 LOOP
24
END

duck und weg

von Klaus W. (mfgkw)


Lesenswert?

... und jetzt erklär mal, wie du den fehlenden Punkt am Programmende 
noch unterkriegst :-)

von real pascal (Gast)


Lesenswert?

Pascal schrieb:
> /*Pascal.h*/
> #ifndef _PASCAL_H_
> #define _PASCAL_H_
...

Na ja, Pascal ist das ja nicht. Könnte was Basicabgewandeltes sein.

von W.S. (Gast)


Lesenswert?

Tom schrieb:
> ich habe mal kurz eine Frage.

hehe, das war Gretchen mit ihrer berüchtigten Gretchenfrage ("Sprich 
Heinrich, wie hältst du es mit der Religion?") oder "Sprich, 
Programmierer, wie hältst du es mit dem guten Stil?"

Ganz klar: Wenn du 10 Programmierer nach gutem Stil fragst, kriegst du 
11 völlig verschiedenen Antworten.

Im Prinzip sind das mehrere Dinge:
a) der formale Stil, also ob man einrückt, ob man Klammern so setzt, daß 
man Zugehörigkeiten erkennen kann oder nicht, ob man lieber groß oder 
klein schreibt, ob man mit Leerzeilen um sich wirft oder eher kompakt 
schreibt usw.

Nach meiner Erfahrung liest sich Code am besten, wenn man dezent 
einrückt, so daß Klammern in gleicher Spalte stehen, nur mäßig mit 
Leerzeilen arbeitet und Groß- und Kleinschreibung nicht stupid nach 
irgendwelchen Vorgaben benutzt, sondern zum Strukturieren von 
Bezeichnern verwendet.

also nicht so:
#define MAXCOLONSONINPUTLINE  12
if (numcolonsonthisline > MAXCOLONSONINPUTLINE) {
  doblabla();
  doblablabla();
} else {
  nixblabl();
}

sondern so:
#define maxColonsOnInputLine  12
if (numColonsOnThisLine > maxColonsOnInputLine)
{ doBlabla();
  doBlablabla();
}
else
{ nixBlabla();
}

b) der Stil bei der Verwendung von Sprachelementen. Es gibt ne Menge 
Leute, die sich besonders großartig fühlen, wenn sie alles mögliche 
zusammenziehen oder degenerierte Anweisungen schreiben. Das ist Mist. 
Achte lieber darauf, Deklarationen und Instanziierungen 
auseinanderzuhalten. Beispiel:

schlecht:
void blabla(void)
{ int x = 3;
  blablabla(x);
  ...


viel besser:
void blabla(void)
{ int x;

  x = 3;
  blablabla(x);
  ...

ebenso blöd ist es, mit ellenlangen Ketten aus if (..) else if (..) else 
if (... usw. zu arbeiten. Für sowas gibt es mit switch ne bessere 
Variante, es zu formulieren. Andererseits ist switch mit nur 1 case ne 
Alberheit.


c) Spaghetticode, den man lieber vermeidet. Ich meine jetzt NICHT die 
Verwendung von goto, sondern fehlende oder falsch angelegte 
Modularisierung und das Voraussetzen von Dingen außerhalb des Codes. 
Salopp gesagt: die Quell-Codes für den USART, für die Tasten, für das 
Menü, für den Systemtimer, für Hinz und für Kunz sollten sich nicht 
kreuz und quer aufeinander beziehen - das wäre Spaghetticode. Und in die 
Headerfiles gehört nur das hinein, was man seitens des aufrufenden 
Programmes auch wirklich braucht.

Ebenso grottenschlechter Mist sind ad hoc Definitionen, also wenn 
wichtige Dinge nicht in den Quellen, sondern auf der Kommandozeile oder 
in irgendwelchen Makefiles oder so stehen. Auch vorgegebene 
Directory-Strukturen gehören dazu:

grottenschlecht:
#include "\..\..\..\drivers\lpc12345\system\sysdefs.h"

So.

W.S.

von G++ (Gast)


Lesenswert?

Wer Anforderungen ordentlich in einer von Computer verstandenen und 
ausführbaren Sprache formulieren kann, der braucht nicht die 
Spezialsprache, die verhindert, daß er Stuss schreibt. Und wer das nicht 
kann, dem Hilft auch die Sprache mit Airbag nichts. Oder schreiben wir 
alle noch in der Schrift aus der ersten Klasse?

von Trolloge (Gast)


Lesenswert?

Die C Jünger hier schon. ;-)

von G++ (Gast)


Lesenswert?

Nur das Pascal eben die Schreibschrift für die Ausbildung ist. Das ist 
auch ok so, den Wirth wollte die "Algorithmen und Datenstrukturen" 
lehren und brauchte dazu eine Sprache, die sich nicht selbst in den 
Vordergrund drängt. Irgendwann muß man aber ans Eingemachte!

von Trolloge (Gast)


Lesenswert?

Und wieder Schwanz Vergleich?

Da gab es gerade mehrere Threads zum Thema. Und wie sich zeigte, ist mit 
Pascal und mit C das gleiche möglich. Es handelt sich nur um eine andere 
Syntax. Sonst nix.:-P

von Dr. Sommer (Gast)


Lesenswert?

W.S. schrieb:
> int x = 3;
Das ist sogar eher sauberer Stil als dein

W.S. schrieb:
>  int x;
>
>   x = 3;

denn so ist x immer initialisiert und enthält nie ungültige Werte. 
Man kann also nicht versehentlich zwischen definition und 1. Zuweisung 
die Variable uninitialisiert verwenden. Einer der Hauptvorteile von C++ 
zB ist es dass man Strukturen so designen kann dass sie immer 
initialisiert sind und nie ungültige Werte haben. Gleiches kann - und 
sollte - man auch für ordinäre Integer verwenden. Außerdem sollte man 
lokale Variablen erst dann definieren wenn man sie braucht, und in den 
tiefsten verschachtelten Scope packen wie möglich, also zB in die 
innerste Schleife in der sie gebraucht werden. So sieht man sofort, wie 
lange ein Wert Relevanz hat und was von ihm beeinflusst wird, im 
Gegensatz zum Stil, alles an den Anfang einer Funktion zu packen (wie es 
in C89(?) nur möglich ist).

W.S. schrieb:
> wenn sie alles mögliche
> zusammenziehen oder degenerierte Anweisungen schreiben.
Das ist nicht "zusammengezogen", das ist eine korrekte und genau so 
gedachte Initialisierung.

W.S. schrieb:
> #define MAXCOLONSONINPUTLINE  12
Macros sollte man nur einsetzen wenn sie absolut unvermeidbar sind. Hier 
kann man es leicht durch ein "const int" ersetzen. Abgesehen davon 
empfiehlt sogar Stroustrup Macros komplett groß zu schreiben und ihnen 
laaange Namen zu geben, damit man immer sieht dass es hässliche 
vorsichtig zu benutzende Dinger sind.

W.S. schrieb:
> Für sowas gibt es mit switch ne bessere
> Variante, es zu formulieren.
Es sei denn, die Bedingung ist komplexer als eine Variable...

W.S. schrieb:
> grottenschlecht:
> #include "\..\..\..\drivers\lpc12345\system\sysdefs.h"
Wenn die sysdefs.h zum selben Projekt gehört, ist das ok, denn das 
funktioniert dann bei jedem der das Projekt so als ganzes auscheckt. 
Aber sonst ists gruselig, ja.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

W.S. schrieb:
> sondern so:
> #define maxColonsOnInputLine  12
> if (numColonsOnThisLine > maxColonsOnInputLine)
> { doBlabla();
>   doBlablabla();
> }
> else
> { nixBlabla();
> }

Geschmäcker sind ja verschieden :-)

Was das "formale" Aussehen betrifft, mach ich das schon lang nicht mehr 
selbst, sondern überlass das dem GNU indent. Das ist speziell dann 
hilfreich, wenn mehrere Leute (im OpenSource-Bereich viele Leute) zum 
selben Projekt beitragen.

Man probiert etwas die verschiedenen Stile von indent aus, einigt sich 
auf einen, und dann wird gnadenlos jeder Source vom indent neu 
eingerückt (wobei indent nicht nur einrückt, sondern auch "falsche" 
Klammerung wie oben zeilenübergreifend korrigieren kann, und auch 
leerzeichen vor/nach Klammern, und noch eine Menge mehr)

Ich mach das seit gut 15 Jahren so, und habe nur die besten Erfahrungen 
damit.

Von Vorteil ist natürlich, wenn sich der Editor a) an dieselben Regeln 
hält, und b) überhaupt einrücken kann. Also: Emacs ;-)

PS ich bevorzuge -kr "Use Kernighan & Ritchie coding style."

von der mechatroniker (Gast)


Lesenswert?

Irgendwie hat W.S. bei seinen ersten drei Beispielen das "So nicht" mit 
dem "Sondern so" vertauscht. Wobei das erste (Indent) noch 
Geschmackssache ist, bei den beiden folgenden handfeste Gründe 
existieren, es "so nicht nicht" zu machen.

von joquis (Gast)


Lesenswert?

Beim Programmierstil geht es nicht um Sauberkeit, sondern um 
Verständlichkeit. Eine Voraussetzung dafür ist verständliches Denken. 
Das sollte man immer üben, denn es ist nicht nur zum Programmieren 
nützlich.

Wer Verständlichkeit mit Sauberkeit verwechselt, wird auch Variablen und 
Funktionen falsch und/oder irreführend benennen und das ist das größte 
Problem beim Versuch, unbekannte Programme zu verstehen. Selbst wenn 
formal alle möglichen Regeln und Dogmen eingehalten werden.

von Thomas (Gast)


Lesenswert?

Codeformatierungen sind doch heutzutage sowas von egal.
Soll doch jeder machen wie er mag.

Mittlerweile sollten doch wohl alle Editoren in der Lage sein, den 
gesamten Code auf Knopfdruck nach den eigenen Wünschen umzuformatieren.

von Pascal (Gast)


Lesenswert?

>Noch besser:
>
>VorlaufTemperatur  = GetAdc(ADC_KANAL_VORLAUFTEMPERATUR);
>NachlaufTemperatur = GetAdc(ADC_KANAL_NACHLAUFTEMPERATUR);

Nein, ist "noch schlechter": Viel zu viel Tipparbeit ==> Tippfehler!
Die Kunst ist: kurze und dennoch prägnante Bezeichner zu finden
1
  TempV = GetAdc(ChTempV);  //Vorlauf Temperatur
2
  TempN = GetAdc(ChTempN);  //Nachlauf Temperatur

von Falk B. (falk)


Lesenswert?

@Thomas (Gast)

>Codeformatierungen sind doch heutzutage sowas von egal.
>Soll doch jeder machen wie er mag.

Parteiprogramm der Piraten?

Im produktiven Einsatz ist das alles andere als egal.
Und wie bereits gesagt, es ist nicht nur die Formatierung, sondern auch 
die logische Strutur, die wichtig ist.

von Jobst Q. (joquis)


Lesenswert?

Pascal schrieb:
>>Noch besser:
>>
>>VorlaufTemperatur  = GetAdc(ADC_KANAL_VORLAUFTEMPERATUR);
>>NachlaufTemperatur = GetAdc(ADC_KANAL_NACHLAUFTEMPERATUR);
>
> Nein, ist "noch schlechter": Viel zu viel Tipparbeit ==> Tippfehler!
> Die Kunst ist: kurze und dennoch prägnante Bezeichner zu finden
>   TempV = GetAdc(ChTempV);  //Vorlauf Temperatur
>   TempN = GetAdc(ChTempN);  //Nachlauf Temperatur

Volle Zustimmung. Nicht nur viel Tipparbeit, sondern auch viel 
Lesearbeit. Auch sind TempV und TempN sinnvoller als VTemp und NTemp bzw 
VorlaufTemperatur und NachlaufTemperatur, da es Sinn macht gleichartige 
Variablen auch gleich anfangen zu lassen.

von test (Gast)


Lesenswert?

Falk Brunner schrieb:
> Im produktiven Einsatz ist das alles andere als egal.
> Und wie bereits gesagt, es ist nicht nur die Formatierung, sondern auch
> die logische Strutur, die wichtig ist.

Definitiv! Dazu eine gescheite Versionsverwaltung.

Oder um es mit den Worten eines anderen Foristen zu sagen:
"80 Prozent der IT Projekte scheitern am Change Management" ;)

von Thomas (Gast)


Lesenswert?

> Im produktiven Einsatz ist das alles andere als egal.
> Und wie bereits gesagt, es ist nicht nur die Formatierung,
> sondern auch die logische Strutur, die wichtig ist.
Ich sprach aber einzig von der Formatierung.

> Definitiv! Dazu eine gescheite Versionsverwaltung.
Stimmt, Versionsverwaltung hatte ich vergessen.
Zumindest vor dem Einchecken sollte die Formatierung wieder den 
Projektvorgaben entsprechen (kann man ja automatisieren).
Käme blöd, wenn die eigentlichen Änderungen ständig in den 
Umformatierungen verloren gehen...

von mar IO (Gast)


Lesenswert?

Jobst Quis schrieb:
> Pascal schrieb:
>>>Noch besser:
>>>
>>>VorlaufTemperatur  = GetAdc(ADC_KANAL_VORLAUFTEMPERATUR);
>>>NachlaufTemperatur = GetAdc(ADC_KANAL_NACHLAUFTEMPERATUR);
>>
>> Nein, ist "noch schlechter": Viel zu viel Tipparbeit ==> Tippfehler!
>> Die Kunst ist: kurze und dennoch prägnante Bezeichner zu finden
>>   TempV = GetAdc(ChTempV);  //Vorlauf Temperatur
>>   TempN = GetAdc(ChTempN);  //Nachlauf Temperatur
>
> Volle Zustimmung. Nicht nur viel Tipparbeit, sondern auch viel
> Lesearbeit.

Als Programmierer sollte man sich auf einer Tastatur zurechtfinden und 
Schreiben können! Auch ist die Lesbarkeit vom obigen Beispiel viel 
besser als der untere und nicht so fehleranträchtig.

Im unteren Beispiel können schnell Tippfehler passieren! TempV und TempN 
unterscheiden sich nur durch einen Buchstaben. Da muss man genau lesen 
und sich nicht beim Hacken verschreiben. Ein ordentlicher Editor 
unterstützt den Programmierer beim Schreiben und bei einen Schreibfehler 
meckert spätestens der Compiler. Ausserdem kann man sich bei geeigneter 
Wahl des Variablennamen auch den Kommentar sparen.

In diesem Fall ist das minimalistische Beispiel nicht gut:
- Tippfehler (V und N verwechselt)
- einfacher Code der schlecht lesbar ist (was ist N? was ist V?), so 
dass man sogar kommentieren muss

von Simon B. (nomis)


Lesenswert?

Wilhelm F. schrieb:
> Simon Budig schrieb:
>
>> Verwende von ziemlich Anfang an möglichst ein Versionskontrollsystem.
>
> Mal eine Zwischenfrage von mir:
>
> Wie ist das mit der Versionskontrolle eigentlich, wenn dort mal eine
> wichtige Datei beschädigt ist? Ist dann noch was zu retten? Oder macht
> man für so was auch noch mal eine externe Zweitsicherung? Wenn ja:
> Lassen sich dann Dateien zurück spielen?

Ein RCS ist kein Ersatz für ein Backup.

Git arbeitet aber sehr zentral mit kryptographisch sinnvollen Hashes, 
d.h. eine Korruption wird sehr zuverlässig erkannt.

Und es macht tatsächlich das replizieren an einem anderen Ort sehr 
einfach. Insofern hilft es einem da indirekt.

> Dann ist die Frage, ab wo sich der Aufwand des Extra-Programmes lohnt.
> Für ein einzelnes kleines Hobby-Projekt im Jahr doch nicht, oder?

Wie lange entwickelst Du an dem Projekt? Wenn Du mal eben ein 
Testprogramm zusammenhackst, um irgendeine libc-Spezialität 
auszuprobieren, dann lohnt es eher nicht. Das schmeißt Du nach dem 
Erkenntnisgewinn dann aber auch eher weg und fasst es nie wieder an. 
Wenn aber absehbar ist, dass du über einen längeren Zeitraum an dem 
Projekt arbeitest, dann lohnt sich sowas unbedingt.

Viele Grüße,
         Simon

von Peter S. (psavr)


Lesenswert?

@mar IO
>In diesem Fall ist das minimalistische Beispiel nicht gut:
>- Tippfehler (V und N verwechselt)
>- einfacher Code der schlecht lesbar ist (was ist N? was ist V?), so
>dass man sogar kommentieren muss

Also ich find das Beispiel mit der Kurschreibweise viel besser 
(schneller Lesbar, schneller zu tippen und insgesamt weniger 
fehleranfällig.

Der Programmierer ist ja völlig im seinem Themakontext drin und weiss 
sehrwohl was N wohl V bedeutet, er hat es vermutlich ja selber 
definiert. Für alle Anderen kann man es noch im Kommentar beschreiben 
(ich mach das in der Regel nur einmal in der Deklaration) Und wer N und 
V nicht unterscheiden kann, hat ein Legasthenie-Problem! Der Unterschied 
von "TempN" und "TempV" springt mich geradezu an, bei 
"ADC_KANAL_VORLAUFTEMPERATUR" und "ADC_KANAL_NACHLAUFTEMPERATUR" ist es 
hingegen ein regelrechtes Versteckspiel!

Bezeichner mit einer Länge von maximal 8...10 Zeichen erfasst der 
durchschnittliche Leser bzw. sein Hirn visuell sofort als ganzes "Wort" 
und muss vom Hirn nicht Buchstabe um Buchstabe entziffert bzw. geparst 
werden.

Noch krasser wird es wenn man dann noch Berechnungen macht und einen 
Term mit 5..8 Bezeichner auf eine Zeile bringen will, da wird es mit 
langen Namen absolut unübersichtlich.

von fooo (Gast)


Lesenswert?

G++ schrieb:
> Nur das Pascal eben die Schreibschrift für die Ausbildung ist

ich schreib nach der grundschule nun auch am gymnasuim wieder die 
druckschrift. hat mir besser gefallen
das geliche mit C

von G++ (Gast)


Lesenswert?

Für alle dies immer noch nicht verstanden haben: G++ übersetzt kein 
"Pascal"!

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


Lesenswert?

G++ schrieb:
> G++ übersetzt kein "Pascal"!

Obiges Pseudo-Pascal würde er schon übersetzen, aber darum ging es
in diesem Thread gar nicht.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter S. schrieb:
> Bezeichner mit einer Länge von maximal 8...10 Zeichen erfasst der
> durchschnittliche Leser bzw. sein Hirn visuell sofort als ganzes "Wort"
> und muss vom Hirn nicht Buchstabe um Buchstabe entziffert bzw. geparst
> werden.

Schwierig sind vor allem lange Bezeichner, die sich nur in ein paar 
Zeichen in der Mitte unterscheiden, wie das eben bei 
ADC_KANAL_VORLAUFTEMPERATUR" und ADC_KANAL_NACHLAUFTEMPERATUR der Fall 
ist. In solchen Fällen muss ich immer zweimal hinschauen, um zu 
erkennen, dass das wirklich zwei verschiedene Namen sind.

Unterscheiden sich zwei Bezeichner hingegen in den ersten oder in den 
letzten Zeichen, springt der Unterschied viel schneller ins Auge. So 
geht es zumindest mir. Deswegen sehe ich den Unterschied zwischen 
ChTempV und ChTempN sofort, zumal die unterschiedlichen Endungen durch 
die Großschrift zusätzlich ins Auge springen.

Generell sollte man die Länge von Bezeichnern abhängig von der Größe des 
Gültigkeitsbereichs wählen. Bei lokalen Variablen, die einen Scope von 
nur wenigen Codezeilen haben, genügt meist eine Länge von 1 bis 3 
Zeichen. Membervariablen in objektorientierten Programmiersprachen sind 
"halbglobal" und dürfen deswegen gerne etwas mehr von sich erzählen (4 
bis 7 Zeichen). Gleiches gilt für modullokale Variablen (in C die 
globalen Variablen mit "static"). Echte globale Variablen, die im 
kompletten Programm sichtbar sind, können auch 8 bis 12 oder mehr 
Zeichen lang sein. Sie sollten dann aber gut voneinander unterscheidbar 
sein. Heißen zwei globale Variablen fast gleich, bedeutet dies, dass sie 
in enger Beziehung zueinander stehen. Dann packt man sie am besten 
zusammen in eine globale Struktur, gibt dieser Struktur einen längeren 
und den Strukturelementen kürzere Namen, bspw. so:
1
struct {
2
  double vorlauf, nachlauf;
3
} temperaturen;

Und für Funktionsnamen gilt – was ihren Länge betrifft – genau das 
gleiche wie für Variablennamen.

von Jobst Q. (joquis)


Lesenswert?

Yalu X. schrieb:
> Bei lokalen Variablen, die einen Scope von
> nur wenigen Codezeilen haben, genügt meist eine Länge von 1 bis 3
> Zeichen.

Seh ich auch so. Da lokale Variablen im selben Sichtbereich deklariert 
werden, nötigenfalls mit Kommentar ,ist ihre Bedeutung auch nicht schwer 
zu erkennen.

Zusätzlich mach ich es mir zur Regel, lokale Variablen immer klein 
anfangen zu lassen und globale Variablen immer groß, so dass schnell 
ersichtlich ist, ob und wo auf nichtlokale Daten zugegriffen wird.

von Karl (Gast)


Lesenswert?

Bei mir tragen globale Variablen immer die Modul-Bezeichnung davor, sind 
dafür aber auch klein geschrieben wie alle Variablen. Großer erster 
Buchastabe ist für Funktionen vorbehalten :-)

zB:
- Spi_rxBuffer
- Adc_GetValue()

von RS (Gast)


Lesenswert?

Globale Variablen und Structs benenne ich immer mit g_....

z.B. g_ADC_GetValue

Wenn man das richtig durchzieht, sieht man sofort ob die Variable / 
Funktion Global ist oder nicht. Da ich geschäftlich viel Code von 
anderen Leuten sehe und andere auch meinen Code weiterführen habe ich 
mir das so angeeignet und auch schon eingies an "Lob" bekommen, dass 
mein Code sehr gut lesbar ist.

Wenn man Code austauschen will, oder ein SW-Projekt mit mehreren 
Entwicklern gleichzeitig auf die Beine stellen muss, lernt man, der 
kürzeste Quellcode ist meist der Schlechteste... Nicht unbedingt bez. 
des Codes an sich, sondern weil er nicht einfach zu lesen / wartbar ist.

Ich schaue daher, dass mein Code in erster Linie gut lesbar ist und 
seinen Zweck erfüllt. Ausgenommen sind hierbei lediglich zeitkritische 
Sachen. Anstatt aber dann irgendwelche C Würgereien zu machen um die 
Laufzeit zu optimieren, nehme ich lieber ein paar Zeilen Inline 
Assembler.

Gruss RS

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


Lesenswert?

Karl schrieb:
> Bei mir tragen globale Variablen immer die Modul-Bezeichnung davor

Dann bist du eigentlich nicht mehr weit weg von C++. ;-)

von Nicolas S. (Gast)


Lesenswert?

Karl schrieb:
> Adc_GetValue()

Hmm.....adc_getvalue wäre bei mir eine Funktion. Überhaupt sind alle 
Wörter, die Verben enthalten Funktionen. Globale Variablen hießen bei 
mir
1
gl_adcvalue
2
gl_isAdcvalue

von der mechatroniker (Gast)


Lesenswert?

> Hmm.....adc_getvalue wäre bei mir eine Funktion. Überhaupt sind alle
> Wörter, die Verben enthalten Funktionen.

Unterschreib. Und umgekehrt, (fast) alle Funktionsnamen enthalten ein 
Verb. Ausnahmen: Konstruktoren (dies es in C aber nicht gibt), 
Konvertierungsfunktionen, die dafür ein "From" oder "To" im Namen haben.

von der mechatroniker (Gast)


Lesenswert?

Um noch meinen Senf zu Diskussion über TempV und TempN hinzuzufügen:

Die beiden Bezeichner fallen bei mir aus mehreren Gründen durch:

a) unnötig verkürzt, man könnte statt des V und N zumindest "Vor" und 
"Nach" ausschreiben, was den Code auch nicht unnötig in die Länge ziehen 
würde, aber zumindest keinen Leser rätseln lässt, wofür das V und N 
steht.

b) Keine Info darüber enthält, worum es sich handelt (nicht um den WERT, 
sondern um den ADC-Kanal)

c) Von der aus guten Gründen (weil man mit #defines eben böse Dinge 
anstellen kann) existierenden Konvention abweicht, dass Makros in 
GROSSBUCHSTABEN geschrieben werden.

Ich würde sie ADC_TEMP_VORLAUF und ADC_TEMP_NACHLAUF oder so nennen.

von Moritz A. (moritz_a)


Lesenswert?

Nicolas S. schrieb:
> Hmm.....adc_getvalue wäre bei mir eine Funktion. Überhaupt sind alle
> Wörter, die Verben enthalten Funktionen.

Funktionen tragen englische Namen, Variablen deutsche Namen :P

von Jobst Q. (joquis)


Lesenswert?

der mechatroniker schrieb:
> b) Keine Info darüber enthält, worum es sich handelt (nicht um den WERT,
> sondern um den ADC-Kanal)

Wenn man nicht lesen kann, nützt auch der "sauberste" Programmierstil 
nichts. TempV war in dem Beispiel der Wert, ChTempV der Kanal.

>> TempV = GetAdc(ChTempV);  //Vorlauf Temperatur

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Moritz A. schrieb:
> Funktionen tragen englische Namen, Variablen deutsche Namen

Jeweils im ersten Semester beliebiger Informatik-Vorlesungen kursieren 
Beschreibungen abstruser Sprachen wie "Vatikal", bei der Variablen die 
Namen katholischer Heiliger tragen; weibliche Heilige waren ganzzahlig 
und männliche Heilige float, außer irische, die waren Zeichenketten.

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


Lesenswert?

Rufus Τ. Firefly schrieb:
> weibliche Heilige waren ganzzahlig und männliche Heilige float, außer
> irische, die waren Zeichenketten.

FORTRAN lässt grüßen. :)  "IMPLICIT INTEGER I-N" …

Davon stammt ja auch der Spruch: “GOD is REAL.  Unless declared 
INTEGER.”

von Yalu X. (yalu) (Moderator)


Lesenswert?

Fortran ist das Konkurrenzprodukt der Evangeliken. Da diese keine 
Heiligen haben, mussten eben andere Namensmerkmale für die implizite 
Typdeklaration herhalten.

von Wilhelm F. (Gast)


Lesenswert?

Jörg Wunsch schrieb:

> männliche Heilige float

Männliche Heilige floaten bestimmt mal gerne. ;-)

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


Lesenswert?

Wilhelm F. schrieb:
> Jörg Wunsch schrieb:
>
>> männliche Heilige float

Nein, das schrieb ich nicht.

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.