Forum: Mikrocontroller und Digitale Elektronik Programmier Stil für Mikrocontroller


von Christian J. (Gast)


Lesenswert?

Hallo,

da mein Multiprozessor Projekt grösser und grösser wird habe ich in der 
letztenn Zeit den Code schwer überarbeiten müssen, um noch den 
Durchblick zu behalten. Da ich kaum Veqrgleiche habe frage ich mal an, 
was ihr von folgenden Dingen haltet:

- Alle Hardwareeinheiten haben ein eigenes .c File + Header
- Alle Files binden die Module eine, die sie brauchen, auch wenn diese 
schon woanders gelinkt wurden
- Alle globalen Variablen werden trotzdem als Zeiger übergeben, auch 
durch mehrere Ebenen hindurch. Da ich sonst nie weiss wer was ändert.
- Jede Routine hat einen kompletten Dokumentenkopf, der tabellarisch 
genau das beschreibt, was die Routine macht, welche Eingangs und 
Ausgangsgrössen vorhanden sind und was verändert wird.
- Hardwaretreiber Files, die nur Bits schieben haben die Endung _raw.c, 
alle darüber liegenden Schichten haben _1st _2nd usw.
- Die SPU Kommunikation ist gekapselt, alle Prozessoren benutzen die 
gleiche Routine auf Low Level, setzen nur ihr eigenes Protoll drüber.
- Alle Variablennamen fangen mit dem  Datentyp an also ui für unsigned 
integer, f für float usw.
- Verwendung von "typedef uint8_t ..."  usw Typen, die scheinbar 
Stándard sind.
- Vernwendung einer defines.h um globale Defines (zB SPI Kommandos) für 
alle sichtbar zu machen
- verwendung einer config.c um mit #define nur jene Module einzubinden, 
die gebraucht werden
- Taktunabhängige Routinen, Teiler für SPI usw. werden berechnet, je 
nach eingestelltem Takt
- Vermeidung von zu vielen #ifdef #endif im Code, um es nicht 
unübersichtlich zu machen.

Was gibt es noch?

Gruss,
Christian

Was wäre noch sinnvoll?

von ... .. (docean) Benutzerseite


Lesenswert?

-doku(Komentare) Doxygen Freundlich machen

von ... (Gast)


Lesenswert?

verwende unbedingt source control

versionskontrolle ala subversion zum beispiel..

von Matthias N. (vbchaos)


Lesenswert?

Da waere natuerlich noch die Codeformatierung selbst. Sprich:

- anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)

- Inhalt von Schleifen und Bedingungen IMMER einklammern

- Inhalt von Schleifen und Bedingungen IMMER einruecken

- Bei einer bestimmten Zeilenstelle muss die Codezeile aufhoeren (hab 
mir Column 79 angewoehnt)

- Kommentare beginnen immer in der selben Zeilenstelle und enden beim 
definierten Zeilenende

- Kommentare macht man nicht mit "//" sondern mit "/* */"

- Codedateien sollten eine bestimmte Anzahl Zeilen nicht ueberschreiten 
(gaengig sind bei uns 1000)

- Jede Datei beinhaltet einen Kopf, den Dateinamen, Autor, Version, 
Erstellungsdatum und das Datum groesserer Aenderungen

- Sinnvolle Namensgebung fuer Variablen. Namen wie "i", "x", "xyz" sind 
Tabu. Schleifenzaehler nennt man "loopcnt", "loopcntr" oder aehnlich 
aussagekraeftig. Wenn sie was bestimmtes zaehlen zB Aepfel ist es ein 
"applecntr".

- Kommentare, und zwar reichlich. Code is obviously written for people 
to read! Aussagekraeftige aber kurze Kommentare. Am Besten in Englisch.


Dann gibt es noch so Dinge, wo sich die Geister scheiden...

- Jede Funktion hat einen einzigen Punkt, an dem sie beendet wird, 
naemlich ihre letzte Zeile. RETURN-Anweisungen irgendwo weiter vorn zum 
Abbrechen der Funktion sind verboten. Ich persoenlich versuche mich 
weitestgehend dran zu halten, manchmal ist es aber einfach viel 
einfacher. Generell aber praktisch, da man nicht ewig in der Funktion 
suchen muss, wo sie unter umstaenden abgebrochen wurde.

- Striktes Vermeiden von "goto"!!! Kann man in ganz ganz bestimmten 
Faellen trotzdem benutzen, aber dann extrem gut kommentiert, weil es 
sonst ein heiloses Durcheinander wird.

von Peter (Gast)


Lesenswert?


von Karl H. (kbuchegg)


Lesenswert?

> - Alle Variablennamen fangen mit dem  Datentyp an also ui
> für unsigned integer, f für float usw.

Darüber kann man streiten.
Das Problem sind nicht die einfachen Datentypen sondern Strukturen 
u.dgl.
Irgendwann hast du dann nämlich soviele Präfixe, dass du für die Präfixe 
wieder ein Inhaltsverzeichnis brauchst.

Ich hab mir diese ungarische Notation wieder abgewöhnt. Das einzige was 
geblieben ist, ist ein 'p' für Pointer. Das hilft bei 
Mehrstern-Programmierung auseinanderzuhalten, welchen Wert man nun 
eigentlich tatsächlich verändert. Aber abgesehen davon hat sich diese 
Datentypmarkierung für mich eigentlich nicht bewährt. Vernünftige, 
aussagekräftige Variablennamen bringen IMHO mehr.

> - Die SPU Kommunikation ist gekapselt, alle Prozessoren benutzen
> die gleiche Routine auf Low Level, setzen nur ihr eigenes Protoll
> drüber.

Dieses Prinzip kann man auch ausbauen: Die Software in Layern aufbauen, 
so dass es eine strikte Aufrufhierarchie gibt. So ist zb. der Aufruf von 
Ausgabefunktionen aus niedrigen Hierarchiestufen absolut tabu (GUI 
Funktionalität ist normalerweise in einer sehr hohen Stufe angesiedelt)

von P. S. (Gast)


Lesenswert?

Matthias Nix wrote:
> Da waere natuerlich noch die Codeformatierung selbst. Sprich:
>
> - anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)

Anstatt Leerstellen immer Tab benutzen.

> - Bei einer bestimmten Zeilenstelle muss die Codezeile aufhoeren (hab
> mir Column 79 angewoehnt)

Sollte. Mit zu engen Regeln kann man auch das Gegenteil erreichen.

> - Kommentare macht man nicht mit "//" sondern mit "/* */"

Kommentare beginnen nie mit /* */, damit man ohne Probleme Codeteile 
auskommentieren kann.

> - Codedateien sollten eine bestimmte Anzahl Zeilen nicht ueberschreiten
> (gaengig sind bei uns 1000)

Aufteilen von Codedateien nur dann, wenn die Teile noch einen Sinn 
ergeben. Mann will ja den Code nachher auch finden...

> - Jede Datei beinhaltet einen Kopf, den Dateinamen, Autor, Version,
> Erstellungsdatum und das Datum groesserer Aenderungen

Keine Infos im Dateikopf, die fuer den Code nicht von belang (z.B. 
Autor) oder bereits im revision control system enthalten sind - es sei 
denn, die Pflege kann automatisiert werden.

> - Sinnvolle Namensgebung fuer Variablen. Namen wie "i", "x", "xyz" sind
> Tabu. Schleifenzaehler nennt man "loopcnt", "loopcntr" oder aehnlich
> aussagekraeftig. Wenn sie was bestimmtes zaehlen zB Aepfel ist es ein
> "applecntr".

Verwendung der Shifttaste und moeglichster Verzicht auf Abkuerzungen. 
AppleCounter oder LoopCounter ist wesentlich besser lesbar und die paar 
Umlaute bringen einen nicht um.

> - Kommentare, und zwar reichlich. Code is obviously written for people
> to read! Aussagekraeftige aber kurze Kommentare. Am Besten in Englisch.

Kommentare um stets zu erklaeren, warum etwas gemacht wird - nie 
Kommentare die erklaeren, was gemacht wird. Das steht ja im Code.

> Dann gibt es noch so Dinge, wo sich die Geister scheiden...

Die scheiden sich oben aber auch schon ordentlich :-)

Ansonsten gilt: Kein Muss, nur viele Sollte. Es gibt immer Faelle, wo 
Ausnahmen sinnvoll sind.

von Christian J. (Gast)


Lesenswert?

Hallo,

Doxygen finde ich persönlich grausam und finde mich darin auch nicht 
zurecht, daher setze ich es nicht ein. Versionskontrolle ist für 
Hobbyprojekte auch nicht sinnvoll. Da ich mit dem notepad++ oder Crimson 
Editor arbeite was eine automatische Ergänzung nach den ersten 
Buchstaben vornimmt sind komplizierte Variablennamen auch kein Problem 
mehr, der Editor kennt alle Wörter aus Files die grad geladen sind und 
bildet sie in einer Datenbank ab.

von Michael A. (micha54)


Lesenswert?

Hallo,

die Zusammenstellung der Programmierregeln finde ich gut, auch wenn ich 
im einzelnen mal anderer Ansicht bin:

Header files dienen meist zweierlei Zweck:
- Veröffentlichung von Daten und Funktionen (Interface eines Moduls)
- Definition von Modulparametern (Portzuweisungen, Bitstrukturen, etc.)
Ich würde hier gelegentlich eine Aufteilung in XYZ.h und XYZ_private.h 
bevorzugen, um das Interface deutlicher zu trennen.

Die Anmerkugnen zum return und goto kann ich nachvollziehen, aber der 
Sprung aus der Schleife per Break mit nachfolgendem return ist auch 
nicht viel besser.

Bei bestimmten Projekten versuche ich über ein configure.h eine 
Übersicht über die Hardwarenutzung zu geben, leider gelingt mir das 
nicht unbedingt optimal, weil ich über Metaegriffe wie twi_timeout = 
timer1, rtc = timer2 gehen muss.

Evtl war die Kernidee bei den Includes nicht ausdrücklich genug:
Ich finde, jedes includierte file sollte per #ifndef....#endif nur 
einmalig wirksam sein können, so daß man in diesem freizügig alle 
notwendigen header files ebenfalls includieren kann. Unter Umständen 
steht dann avr/io.h halt in jedem header file und auch in jeder C-Datei.

Gruß,
Michael

von Peter (Gast)


Lesenswert?

>- Sinnvolle Namensgebung fuer Variablen. Namen wie "i", "x", "xyz" sind
>Tabu.

Möglichst kurze, einfache Variabeln-Namen sind einprägsam, machen den 
Code lesbarer, ersparen viel Tipparbeit und Tippfehler werden 
vermindert.

z.B. "i", "x", "n", "c"  für Indexe, lokale Schlaufezähler, temporäre 
Char's etc... sind durchwegs sinnvoll und oft angebracht.

von Matthias N. (vbchaos)


Lesenswert?

Peter Stegemann wrote:

>> - anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)
>
> Anstatt Leerstellen immer Tab benutzen.

Genau! Ist super lesbar im 0815 Texteditor! Das Einruecken wird dann zum 
Familienspass

>> - Kommentare macht man nicht mit "//" sondern mit "/* */"
>
> Kommentare beginnen nie mit /* */, damit man ohne Probleme Codeteile
> auskommentieren kann.

Ich sprach von Kommentaren. Jene, die dir Hinweise auf die Funktion des 
Codes geben. Nicht davon, Code zum debuggen rauszuwerfen.

>> - Codedateien sollten eine bestimmte Anzahl Zeilen nicht ueberschreiten
>> (gaengig sind bei uns 1000)
>
> Aufteilen von Codedateien nur dann, wenn die Teile noch einen Sinn
> ergeben. Mann will ja den Code nachher auch finden...

Daher "sollten" und nicht "duerfen"

>> - Sinnvolle Namensgebung fuer Variablen. Namen wie "i", "x", "xyz" sind
>> Tabu. Schleifenzaehler nennt man "loopcnt", "loopcntr" oder aehnlich
>> aussagekraeftig. Wenn sie was bestimmtes zaehlen zB Aepfel ist es ein
>> "applecntr".
>
> Verwendung der Shifttaste und moeglichster Verzicht auf Abkuerzungen.
> AppleCounter oder LoopCounter ist wesentlich besser lesbar und die paar
> Umlaute bringen einen nicht um.

Shifttaste laesst man lieber, nervt nur beim tippen. Ist aber 
Geschmacksache.
>
>> - Kommentare, und zwar reichlich. Code is obviously written for people
>> to read! Aussagekraeftige aber kurze Kommentare. Am Besten in Englisch.
>
> Kommentare um stets zu erklaeren, warum etwas gemacht wird - nie
> Kommentare die erklaeren, was gemacht wird. Das steht ja im Code.

Ja, bei einfachereren Zuweisungen ist das OK, bei richtig fiesem 
Bit-f*cking oder x-fachen Verschachtelungen finde ich eine 2-Zeilen 
Zusammenfassung des ganzen sehr hilfreich. Warum muss ich 200 Zeilen 
Code lesen UND verstehen, wenns in 2 Zeilen auch erklaert werden kann? 
Geht doch viel schneller.

>> Dann gibt es noch so Dinge, wo sich die Geister scheiden...
>
> Die scheiden sich oben aber auch schon ordentlich :-)

Wenn du meinst...

>
> Ansonsten gilt: Kein Muss, nur viele Sollte. Es gibt immer Faelle, wo
> Ausnahmen sinnvoll sind.

Generell solls doch eh jeder so machen, wie er will, oder wie sein Chef 
es ihm vorschreibt...

Ich persoenlich finde Doxygen auch totalen Mist, weil es Kommentare 
unleserlich macht und den ganzen Code unnoetig aufblaeht. Soll aber auch 
jedem selbst ueberlassen sein...

von ... (Gast)


Lesenswert?

>Versionskontrolle ist für
>Hobbyprojekte auch nicht sinnvoll.

Hui, da will ich kurz dagegenhalten...
für eine eventuelle spätere bugsuche fast unverzichtbar...

stell dir vor, immer wenn du ein teilchen weiterbist, einfach kurz den 
aktuellen stand commiten...

wenn es auf einmal nicht mehr läuft, kannst du entweder verzweifelt 
lange suchen, oder mit dem diff tool die codestände durchgehen, dann 
siehst genau was du wann, wo, wie gemacht hast...

ich würde den einstaz von versionskontrolle (source-code-control) von 
der komplexität abhängig machen. die unterscheidung privat/geschäftlich 
ist unfug.

von der peterle (Gast)


Lesenswert?

>>> - anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)
>> Anstatt Leerstellen immer Tab benutzen.
> Genau! Ist super lesbar im 0815 Texteditor! Das Einruecken wird dann zum
> Familienspass
Verstehe ich nicht. Selbst der bei Windows mitgelieferte notepad kann
mit Tabs umgehen? Ich bevorzuge abenfalls Tabs, da können sich die
Zwei-Leerzeichen-Einrücker gerne den Kram in ihrem Editor anschauen wie
sie es gerne hätten und ich kann bei meiner Acht-Leerzeichen-
Schrittweite bleiben. Mit Leerstellen würde das nie funktionieren, außer
man lässt immer einen Autoindenter vorher rüberbügeln.

Ach ja, zur Liste:
- Acht Leerzeichen zum Einrücken verwenden. ;-)

Aber auch das ist Geschmackssache, diese Liste hier kann nur ein Hinweis
sein, bei uns in der Firma wird mit zwei Leerzeichen eingerückt, und
beim mergen von Code achtet keiner auf die Einrückung. Das sieht aus...

von Peter (Gast)


Lesenswert?

@der peterle
> Acht Leerzeichen zum Einrücken verwenden

Das ganze mit
> Bei einer bestimmten Zeilenstelle muss die Codezeile aufhoeren (hab
> mir Column 79 angewoehnt

und

> Sinnvolle Namensgebung fuer Variablen. Namen wie "i", "x", "xyz" sind
> Tabu. Schleifenzaehler nennt man "loopcnt", "loopcntr" oder aehnlich
> aussagekraeftig. Wenn sie was bestimmtes zaehlen zB Aepfel ist es ein
> "applecntr".

Wenn man dann auch noch etwas schachtelt steht der code von spalte 
70-79.

von Severino R. (severino)


Lesenswert?

Matthias Nix wrote:

> Ja, bei einfachereren Zuweisungen ist das OK, bei richtig fiesem
> Bit-f*cking oder x-fachen Verschachtelungen finde ich eine 2-Zeilen
> Zusammenfassung des ganzen sehr hilfreich. Warum muss ich 200 Zeilen
> Code lesen UND verstehen, wenns in 2 Zeilen auch erklaert werden kann?
> Geht doch viel schneller.

Der Kommentar beschreibt, was der Programmierer glaubt, dass der Code 
tut.
Beim Verstehen des Codes merkt man vielleicht, dass der Code etwas 
Anderes tut als angenommen...

Aber warum nicht : das eine tun und das andere nicht lassen.

von Karl H. (kbuchegg)


Lesenswert?

> Mit Leerstellen würde das nie funktionieren, außer
> man lässt immer einen Autoindenter vorher rüberbügeln.

Ach, das funktioniert eigentlich ganz gut und ist beim Schreiben kaum 
Mehraufwand, wenn der Programmier-Editor einen Tab gleich mal auf 
Leerzeichen expandiert.

Spätestens wenn Code weitergegeben wird (weil er zb in Source-Form 
verkauft wird) oder mehrere Leute am gleichen Projekt arbeiten, kriegst 
mit Tabs automatisch Augenkrebs :-)

von Karl H. (kbuchegg)


Lesenswert?

Funktionen sollen das tun, was drauf steht!

Klingt zwar banal, ist aber in der Praxis oft nicht so. Funktionen 
machen viel mehr als ihr Name vermuten lässt.

Auch nicht davor zurückschrecken, mal etwas umzubenennen, wenn sich die 
dahinterstehende Funktion verändert hat.

Globale Flag-Variablen.
Sind ein zweischneidiges Schwert. Wenns zuviele werden, verliert man 
schnell mal den Überblock, welches Flag wann und wo gesetzt werden muss, 
damit eine bestimmte Funktionalität ausgelöst wird. Spätestens dann, 
wenn einzelne Statements von if abhängen, in denen 3 bis 4 Flags mittels 
&& und || verknüpft werden, wirds Zeit über ein Redesign nachzudenken.

Die zentrale Mainloop hat sich bewährt. In der mainloop werden alle 
möglichen Aktionen über Jobflags ausgelöst. Wenn ein anderer Codeteil 
was will, 'startet er den Job' in dem er das zugehörige Jobflag setzt.

von Michael H. (mah)


Lesenswert?

Versionskontrolle würde ich unbedingt machen, nicht nur wegen der 
Historie.

Ich verwende Eclipse auf einem iMac und einem Laptop, und stelle alle 
Projekte auf einen CVS Server. Wenn ich vom imac auf den Laptop wechsle, 
mache ich ein CVS update und habe den Stand vom anderen Rechner.

Kein Hin- und Herkopieren von Projekten, und Datensicherung fällt mit 
dabei ab.

Eclipse würde ich wärmstens empfehlen - hat eine Lernkurve, ist aber mit 
der Zeit angenehm wie ein alter Patschen.

Die ungarische Notation ist mE für die Lesbarkeit von Code die Hölle.

-Michael

von der peterle (Gast)


Lesenswert?

>> Sinnvolle Namensgebung fuer Variablen. Namen wie "i", "x", "xyz" sind
>> Tabu. Schleifenzaehler nennt man "loopcnt", "loopcntr" oder aehnlich
>> aussagekraeftig. Wenn sie was bestimmtes zaehlen zB Aepfel ist es ein
>> "applecntr".
> Wenn man dann auch noch etwas schachtelt steht der code von spalte
> 70-79.
>
Wieso? Mehr als 3- oder 4-mal sollte man eh nicht einrücken. Ansonsten
sollte man sich den Code-Aufbau eh noch mal überdenken...

>> Mit Leerstellen würde das nie funktionieren, außer
>> man lässt immer einen Autoindenter vorher rüberbügeln.
> Ach, das funktioniert eigentlich ganz gut und ist beim Schreiben kaum
> Mehraufwand, wenn der Programmier-Editor einen Tab gleich mal auf
> Leerzeichen expandiert.
>
Wenn alle mit der gleichen Einrückung arbeiten...

> Spätestens wenn Code weitergegeben wird (weil er zb in Source-Form
> verkauft wird) oder mehrere Leute am gleichen Projekt arbeiten, kriegst
> mit Tabs automatisch Augenkrebs :-)
>
Darauf wollte ich hinaus. ;-)

von Sven P. (Gast)


Lesenswert?

Um Codeblöcke zwecks Debugging rauszuschmeißen empfiehlt sich ganz arg 
der Präprozessor mit #if. Mein Editor markiert z.B. einen Block, der mit 
'#if 0' anfängt, automatisch.

Wenns ums Kommentieren von Code geht, folgendes Prinzip einhalten:
Wenn ich zehn Zeilen Kommentar brauche, um eine Zeile Quelltext zu 
beschreiben, stimmt etwas mit der Zeile nicht.

von der mechatroniker (Gast)


Lesenswert?

Nichtssagende Wörter in Variablennamen wie Number, Num, Zahl usw. 
vermeiden (ist ElementNum jetzt die Anzahl der Elemente, oder die Nummer 
[i.S.v. Index] des aktuellen Elements?)

Variablen im globalen Scope reduzieren, besser sind schon 
static-Variablen im Modulen. Die verbleibenden dürfen etwas 
ausschweifende Namen bekommen, hauptsache aussagekräftig. Lokale 
Variablen dürfen kürzer sein, bei einem Zehnzeiler mit einer einzigen 
Schleife ist i für den Schleifenzähler völlig ok.

Return-Anweisungen nur am Ende von Funktionen. Wird aus irgendwelchen 
Gründen davon abgewichen, etwa weil Sonderfälle bei den 
Eingangsparametern geprüft werden müssen, dann das Gegenteil: diese 
Prüfungen nicht zwischendrin, sondern gesammelt unmittelbar am Anfang 
der Funktion

Nicht zuviele Einrückungsebenen. Geschachte for-Schleifen sind ok, wenn 
die verarbeiteten Daten "von Natur aus" zweidimensional sind (etwa 
Bilddaten), ansonsten ein Zeichen dafür, dass mit der Codestruktur was 
faul ist.

von P. S. (Gast)


Lesenswert?

Matthias Nix wrote:
> Peter Stegemann wrote:

>>> - anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)
>> Anstatt Leerstellen immer Tab benutzen.
> Genau! Ist super lesbar im 0815 Texteditor! Das Einruecken wird dann zum
> Familienspass

Bei jedem gescheiten Editor laesst sich die Tabbreite einstellen.

>>> - Kommentare macht man nicht mit "//" sondern mit "/* */"
>> Kommentare beginnen nie mit /* */, damit man ohne Probleme Codeteile
>> auskommentieren kann.
> Ich sprach von Kommentaren. Jene, die dir Hinweise auf die Funktion des
> Codes geben. Nicht davon, Code zum debuggen rauszuwerfen.

Und was passiert, wenn du einen Block auskommentieren willst, in dem ein 
Kommentar mit /* */ steht?

>> Verwendung der Shifttaste und moeglichster Verzicht auf Abkuerzungen.
>> AppleCounter oder LoopCounter ist wesentlich besser lesbar und die paar
>> Umlaute bringen einen nicht um.
> Shifttaste laesst man lieber, nervt nur beim tippen. Ist aber
> Geschmacksache.

Nein, ist wissenschaftlich nachgewiesen schlecht zu lesen. Kann man von 
jedem Lingusiten erfahren.

>>> Dann gibt es noch so Dinge, wo sich die Geister scheiden...
>> Die scheiden sich oben aber auch schon ordentlich :-)
> Wenn du meinst...

Warum so zickig?

>> Ansonsten gilt: Kein Muss, nur viele Sollte. Es gibt immer Faelle, wo
>> Ausnahmen sinnvoll sind.
> Generell solls doch eh jeder so machen, wie er will, oder wie sein Chef
> es ihm vorschreibt...

Wenn du keine Lust auf andere Meinungen hast, solltest du bloggen und 
nicht in Foren posten.

> Ich persoenlich finde Doxygen auch totalen Mist, weil es Kommentare
> unleserlich macht und den ganzen Code unnoetig aufblaeht. Soll aber auch
> jedem selbst ueberlassen sein...

Eine ordentliche, standardisierte Headerdokumentation ist gold wert, vor 
allem, wenn man einen Editor hat, der das automatisch einblendet. 
Eclipse macht das sehr schoen - das spart einem seher viel 
Nachschlagearbeit. Und die Wahrscheinlichkeit, dass andere die 
Dokumentation auch mal lesen, wenn sie so leicht zugreifbar ist, ist 
auch hoeher.

von Daniel F. (df311)


Lesenswert?

die frage nach dem richtigen code-stil lässt sich gleich beantworten wie 
die frage nach dem richtigen editor ;-)

ich bevorzuge tabs zum einrücken (dargestellt mit 2 leerzeichen), da 
dann in projekten jeder selbst festlegen kann, wie viel er einrücken 
möchte.

auf svn möchte ich für die meisten meiner projekte nicht mehr verzichten 
- habe es für beide bakkarbeiten verwendet, verwende es für die 
diplomarbeit, für größere µC-projekte, homepage-verwaltung, ...

für schleifen gibts meistens kurze variablen zum zählen (i, j, k, ...) 
sonst sinnvolle bezeichner, die aber nicht zu lang sein sollten - für 
mich liegt die grenze bei 10-15 zeichen.

kommentare sind ein kapitel für sich - für doxygen verwende ich die 
javadoc-syntax (auch in c(++)), da sie mir einfach am besten gefällt. 
über die anzahl lässt ich auch streiten, daher werfe ich dazu nur ein 
schwedisches sprichwort in die runde: "lagom är bäst" [1].

[1]: "just enough is best" - Joe Armstrong, "Programming Erlang", 
Kapitel über Multicore-CPUs

von Christian J. (elektroniker1968)


Lesenswert?

Mal ein praktisches Beispiel. Der Header für eine IR Kommunikation mit 
einem TSOP 17xx von Vishay. Oben kann man Parameter ändern, alles 
darunter berechnet sich von selbst. Ich finde so sollten alle Header 
ausschauen, leider findet man immer wieder "magische Zahlen" in Codes.
1
// Übertragungsparameter: Vom Anwender veränderbare Grössen
2
3
#define IR_F_OSC  8000000             // Quarzfrequenz in Mhz  
4
#define F_TSOP    36000               // Trägerfrequenz TSOP
5
#define  F_CORE    (IR_F_OSC/4)        // Taktfrequenz der CPU (1/4)
6
7
#define BIT_0_IRCYC  12                  // Zyklenzahl "0" 
8
#define BIT_1_IRCYC  25                  // Zyklenzahl "1" 
9
#define GAP_IRCYC  15                  // Zyklenzahl für GAP 
10
#define SETDELAY  100                 // (ms) Trennung zwischen Datensätzen
11
#define PRMBL_IRCYC  100                 // IR Zyklenzahl für Preambel
12
13
//////////////////////////////////////////////////////////////////////////////////////
14
// Abgeleitete und fixe Größen (NICHTS VERÄNDERN)
15
16
#define CLOCKS_CYC      (F_CORE/F_TSOP)             // uC Takte für einen Zyklus (27,7us)
17
#define TPERIODE        ((1000000/F_TSOP)+1)        // (us) 1 Zyklus ~ 28us
18
19
// Ideale Empfangszeiten (us) für Bits 0 und 1 (keine Verzerrung)
20
#define T_BIT_1_IDEAL   (TPERIODE*BIT_1_IRCYC)      // (672us) us für "1" Bit 
21
#define T_BIT_0_IDEAL   TPERIODE*BIT_0_IRCYC)       // (336us) us für "0" Bit 
22
23
// Empfangstoleranzen (us) für die Bits 0 und 1
24
#define T_LOWER_DEV     (TPERIODE*3)                // (84us) untere Abweichung Empfang (Datenblatt)
25
#define T_UPPER_DEV     (TPERIODE*6)                // (168us) obere Abweichung Empfang (Datenblatt)
26
#define T_BIT_0_MIN     (T_BIT_0_IDEAL-T_LOWER_DEV) // (252us) Empfangsbereich "0" Bit
27
#define T_BIT_0_MAX     (T_BIT_0_IDEAL+T_UPPER_DEV) // (504us)
28
#define T_BIT_1_MIN     (T_BIT_1_IDEAL-T_LOWER_DEV) // (588us) Empfangsbereich "1" Bit
29
#define T_BIT_1_MAX     (T_BIT_1_IDEAL+T_UPPER_DEV) // (849us)
30
31
// Empfangstoleranzen für die Preambel
32
#define T_PRMBL_IDEAL   (TPERIODE*PRMBL_IRCYC)    // (2800us)
33
#define T_PRMBL_MIN     (T_PRMBL_IDEAL-T_LOWER_DEV)
34
#define T_PRMBL_MAX     (T_PRMBL_IDEAL+T_UPPER_DEV)
35
36
// Parameter für Senden
37
#define HI_ZYK     (CLOCKS_CYC/3)          // uC Takte für High in Zyklus
38
#define LO_ZYK     (CLOCKS_CYC-HI_ZYK)      // uC Takte für Lo in Zyklus
39
#define GAP_CYC     (GAP_IRCYC*CLOCKS_CYC)      // uC Takte für eine GAP von 15 IR Zyklen
40
#define PRE_CYC      (PRMBL * TPERIODE)       // uC Takte für eine Preambel

von P. S. (Gast)


Lesenswert?

Christian J. wrote:

> #define T_BIT_0_IDEAL   TPERIODE*BIT_0_IRCYC)       // (336us) us für
> "0" Bit

Wollte gerade die konsequente Klammerung loben, da fiel mir auf, dass 
hier eine oeffnende Klammer fehlt :-)

von Christian J. (elektroniker1968)


Lesenswert?

Oops... danke! Wäre mir gar nicht aufgefallen....

Ohne Klammerung geht auch wohl nicht, Punkrechnug vor Strichrechnung 
usw. gefährlich wird wohl wenn der Pre Compiler den Ausdruck nicht mehr 
ausrechnen kann, weil der 32 Bit überschreitet, bin da schonmal auf die 
Nase gefallen

Bin da grad auch wieder an so einer ästhetischen Frage:

Soll das so stehenbleiben
1
byte PORT_SendFrame(chips dev,uint8_t *tosend, uint8_t ssize,uint8_t *receive,uint8_t *rsize)

oder doch lieber einen Zeiger auf einen Struct übergeben, zb wie diesen 
hier, damit nur ein Parameter im Kopf steht.
1
struct _SPI_DataFrame
2
{
3
    enum chips  device;         // angesprochenes Device
4
    uint8_t     tx_size;        // Grösse des TX Datensatzes
5
    uint8_t     tx_buf[64];     // Sendepuffer
6
    uint8_t     rx_size;        // Grösse des RX Datensatzes
7
    uint8_t     rx_buf[64];     // Empfangspuffer
8
};   
9
10
struct  _SPI_DataFrame SPI_DataFrame;

Ja, man kanns auch übertreiben :-)

von Matthias N. (vbchaos)


Lesenswert?

Peter Stegemann wrote:
>
>>>> - anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)
>>> Anstatt Leerstellen immer Tab benutzen.
>> Genau! Ist super lesbar im 0815 Texteditor! Das Einruecken wird dann zum
>> Familienspass
>
> Bei jedem gescheiten Editor laesst sich die Tabbreite einstellen.

Meinen Erfahrungen nach fuehrt das zu unleserlichem Code, weil die 
Tab-Taste einen nicht-festen Abstand einfuegt. Notepad und Notepad++ 
interpretieren TAB-Tasten aus was-für-Gründen-auch-immer manchmal 
unterschiedlich, und ich hab keine Lust, das erst muehsam einzustellen. 
Jeder mir bekannte Programmierumgebung erlaubt das Ersetzen von Tabs 
durch eine beliebige Anzahl Leerzeichen, und das werde ich auch 
weiterhin vorziehen. Im 0815 Notepad siehts dann so aus, wie ich will, 
ohne irgendwas eingestellt zu haben.
>
>>>> - Kommentare macht man nicht mit "//" sondern mit "/* */"
>>> Kommentare beginnen nie mit /* */, damit man ohne Probleme Codeteile
>>> auskommentieren kann.
>> Ich sprach von Kommentaren. Jene, die dir Hinweise auf die Funktion des
>> Codes geben. Nicht davon, Code zum debuggen rauszuwerfen.
>
> Und was passiert, wenn du einen Block auskommentieren willst, in dem ein
> Kommentar mit /* */ steht?

Da du weiter unten Eclipse schon erwaehnst: Shortcut "CTRL+/" - 
Einfacher geht es wirklich nicht mehr, und viele normale Texteditoren 
wie Notepad++ unterstützen diese Funktion ebenfalls. Ich kenne 
eigentlich keine Umgebung, die kein "Block auskommentieren" als Funktion 
hat.
>
>>> Verwendung der Shifttaste und moeglichster Verzicht auf Abkuerzungen.
>>> AppleCounter oder LoopCounter ist wesentlich besser lesbar und die paar
>>> Umlaute bringen einen nicht um.
>> Shifttaste laesst man lieber, nervt nur beim tippen. Ist aber
>> Geschmacksache.
>
> Nein, ist wissenschaftlich nachgewiesen schlecht zu lesen. Kann man von
> jedem Lingusiten erfahren.

Abgesehen davon, dass Umlaute bitte tunlichst zu vermeiden sind (du 
meinst wohl Vokale), mag man sich da weiterhin streiten. Abkürzungen wie 
"cntr" für Counter sind m.M.n. ersichtlich. Was der Linguist, was auch 
immer er damit zu tun haben sollte, sagt, ist nicht aussagekräftig, da 
der gemeine Linguist in dieser Fragestellung nichts zu sagen hat. Es sei 
denn, er ist Computerlinguist und mit gängigen Abkürzungen vertraut. 
Würde diesbezüglich die angesprochene, wissenschaftliche Studie gerne 
sehen.
>
>>>> Dann gibt es noch so Dinge, wo sich die Geister scheiden...
>>> Die scheiden sich oben aber auch schon ordentlich :-)
>> Wenn du meinst...
>
> Warum so zickig?

Eher gleichgültig... Kann deine Anregungen kaum nachvollziehen, 
vielleicht arbeite ich mit zu allgemeinen Programmen, aber Autorennamen 
gehören nunmal in den Dateiheader. Will nicht immer SVN bemühen und 
gucken, wer was wie befummelt hat. Wer größere Änderungen vornimmt, 
verewigt sich. Wirst du so in jedem professionellen Example-Code 
vorfinden, auch in vernünftigen offenen Projekten. Wer für sich ganz 
alleine privat programmiert, kann sowas natürlich weglassen, aber m.M.n. 
gehört sowas in jeden professionell erstellten Code.
Beispiel: Ein alter Code wird in ein neues Projekt eingefügt. Der neue 
Bearbeiter setzt es bei SVN (oder wo auch immer) ein, also gilt er 
deiner Ansicht nach nun als Ersteller, und der ursprüngliche Autor ist 
nur noch auf Umwegen oder u.U. gar nicht mehr zu ermitteln.

>>> Ansonsten gilt: Kein Muss, nur viele Sollte. Es gibt immer Faelle, wo
>>> Ausnahmen sinnvoll sind.
>> Generell solls doch eh jeder so machen, wie er will, oder wie sein Chef
>> es ihm vorschreibt...
>
> Wenn du keine Lust auf andere Meinungen hast, solltest du bloggen und
> nicht in Foren posten.

Ich mag andere Meinungen, aber deine fand ich in weiten Teilen halt 
nicht nachvollziehbar (siehe die TAB Sache). Und ansonsten finde ich 
nunmal, dass sich jeder in Gewissem Rahmen seinen eigenen Stil 
angewöhnen soll und muss, und/oder es so machen soll/muss, wie sein Chef 
es vorgibt. Es gibt in dieser Fragestellung sehr viele persoenliche 
und/oder betriebsbedingte Aspekte, die zu beachten sind. Ich habe meine 
Erfahrungen und Überzeugungen dazu dargestellt, wenn du es anders 
machst, hast du sicher deine Gründe. Mehr gibts dazu nicht zu sagen

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter Stegemann wrote:
> Matthias Nix wrote:
>> Peter Stegemann wrote:
>
>>>> - anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)
>>> Anstatt Leerstellen immer Tab benutzen.
>> Genau! Ist super lesbar im 0815 Texteditor! Das Einruecken wird dann zum
>> Familienspass
>
> Bei jedem gescheiten Editor laesst sich die Tabbreite einstellen.

Du willst vielleicht auch mal was von jemand anderem editieren und 
gescheit darstellen, ohne ständig deinen Editor umzukonfigurieren. 
Genau das passiert, wenn man TABs verwendet. Für manche heisst es 8, 
manchmal 4, manchchmal bis zum nächsten Tabstop. Mit Leerzeichen (kann 
ebenfalls jeder gute Editor) sieht's überall gleich aus.

>>>> - Kommentare macht man nicht mit "//" sondern mit "/* */"
>>> Kommentare beginnen nie mit /* */, damit man ohne Probleme Codeteile
>>> auskommentieren kann.
>> Ich sprach von Kommentaren. Jene, die dir Hinweise auf die Funktion des
>> Codes geben. Nicht davon, Code zum debuggen rauszuwerfen.
>
> Und was passiert, wenn du einen Block auskommentieren willst, in dem ein
> Kommentar mit /* */ steht?

Zu Ausblenden geht auch #if 0

>>> Verwendung der Shifttaste und moeglichster Verzicht auf Abkuerzungen.
>>> AppleCounter oder LoopCounter ist wesentlich besser lesbar und die paar
>>> Umlaute bringen einen nicht um.
>> Shifttaste laesst man lieber, nervt nur beim tippen. Ist aber
>> Geschmacksache.

Variablennamen sinnvoll wählen. Eine Schleifenvariable, die nur über 2 
Zeilen lebt, als thisisaloopvariableandwilldietwolinesbelow zu nennen 
ist Käse. Da ist i oder n voll ok, und es verschleiert nicht den Blick 
aufs Wesentliche. Horror sind solche Bezeichner jedoch, wenn sie über 
weitere Codesequenzen gültig sind, dann sind sprechendere Namen 
angesagt.


Christian J. wrote:
> Hallo,
>
> da mein Multiprozessor Projekt grösser und grösser wird habe ich in der
> letztenn Zeit den Code schwer überarbeiten müssen, um noch den
> Durchblick zu behalten. Da ich kaum Veqrgleiche habe frage ich mal an,
> was ihr von folgenden Dingen haltet:
>
> - Alle Hardwareeinheiten haben ein eigenes .c File + Header
> - Alle Files binden die Module eine, die sie brauchen, auch wenn diese
> schon woanders gelinkt wurden
Du meinst "woanders includet"? Ja, wenn sie explizit Zeug aus dem 
anderwärtig includeten Header brauchen, steht der mit oben.

> - Alle globalen Variablen werden trotzdem als Zeiger übergeben, auch
> durch mehrere Ebenen hindurch. Da ich sonst nie weiss wer was ändert.
Egal wie codiert, gehört das in die Kommentare/Doku im Funktionkopf.

> - Die SPU Kommunikation ist gekapselt, alle Prozessoren benutzen die
> gleiche Routine auf Low Level, setzen nur ihr eigenes Protoll drüber.

Nennt man HAL das (hardware abstraction layer).

> - Alle Variablennamen fangen mit dem  Datentyp an also ui für unsigned
> integer, f für float usw.
Halte ich persönlich für Käse. Ein Kollege fing das mal an, aber es ist 
nicht durchzuhalten. Ein Zeiger auf eine Union, die Volatile daten 
enthält, ...

> - Vernwendung einer defines.h um globale Defines (zB SPI Kommandos) für
> alle sichtbar zu machen

Unschön. Wenn man nicht spi.h includen will, dann wenigstens ein 
spi-commands.h mit den Defines oder Enums.

> - verwendung einer config.c um mit #define nur jene Module einzubinden,
> die gebraucht werden

???

> - Taktunabhängige Routinen, Teiler für SPI usw. werden berechnet, je
> nach eingestelltem Takt
Kommt drauf an, was "taktunabhängig sein soll" SPI-Takt? Ich vermute mal 
CPU-Takt. Die Vorberechnungen kann ein Präprozessor machen, wenn die 
SPI-Taktrate bzw, CPU-Taktrate nicht zur Laufzeit geändert werden soll.

Daher mag ich keine Makros wie #define F_CPU 1000000UL

Das UL hat nix da zu suchen und der Präprozessor verdaut das nicht. 
Beispiel aus einem Projekt:
1
#define PRESCALE ...
2
#define IRQS ...
3
...
4
#if (F_CPU % (PRESCALE * IRQS)) != 0
5
#   warning Timer2 arbeitet ungenau
6
#endif
7
8
#if F_CPU / PRESCALE / IRQS-1 > 0xff
9
#   error Timer2 zu langsam getaktet
10
#endif 
11
12
#if F_CPU / PRESCALE / IRQS-1 < 1
13
#   error Timer2 zu schnell getaktet
14
#endif 
15
16
static void timer2_init (void)
17
{
18
    // Mode #2 (CTC) und PRESCALE=8
19
    TCCR2A = (1 << WGM21);
20
    TCCR2B = (1 << CS21);
21
22
    // OutputCompare für gewünschte Timer2 Frequenz
23
    OCR2A = (unsigned short) ((unsigned long) F_CPU / PRESCALE / IRQS-1);
24
25
    // OutputCompare-Interrupt A für Timer 2
26
    TIMSK2 = (1 << OCIE2A);
27
}

Bei Änderungen zur Laufzeit muss man rechnen oder in einer Tabelle 
nachschlagen, je nach Gusto/Anwendungsfall.

> - Vermeidung von zu vielen #ifdef #endif im Code, um es nicht
> unübersichtlich zu machen.

Jupp. Vor allen zu verwenden, daß der Code korrekt geklammert bleibt!

> Was gibt es noch?

Vielleicht mal in verschiedene Coding Rules/Conventions reinschauen und 
sehen, was die so schreiben. Nicht alles ist sinnvoll, aber oft viele 
gute Ideen sind dabei.

-- Umlaute vermeiden: da stolpert mancher Debugger drüber (ich debug 
meinen Code nicht, daher stehen bei mir oben Umlaute drin.)

-- Abenso Glaubenskrieg entfachen wie TAB/SPACE kann die Positionierung 
von { und } und der Umbruch überlanger Zeilen/Ausdrücke.

Bei mir stehen { und } immer untereinander, gleiche Ebenen gleich tief 
eingerückt. Der Grund: wenn Ausdrücke gebrochen werden, sieht man 
dennoch den Blockanfang. Hier ein Beispiel aus avr-gcc:
1
  for (reg = 0; reg < 32; reg++)
2
    {
3
      /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
4
   any global register variables.  */
5
      if (fixed_regs[reg])
6
  continue;
7
8
      if ((int_or_sig_p && !cfun->machine->is_leaf && call_used_regs[reg])
9
    || (df_regs_ever_live_p (reg)
10
        && (int_or_sig_p || !call_used_regs[reg])
11
        && !(frame_pointer_needed
12
       && (reg == REG_Y || reg == (REG_Y+1)))))
13
  {
14
    if (set)
15
      SET_HARD_REG_BIT (*set, reg);
16
    count++;
17
  }
18
    }
Das ist ein Copy & Paste. Übrigens wäre der Code richtig eingerückt, 
wenn die Quelle ohne TABs geschrieben wäre (ich hatte keine Lust, das 
jetzt von Hand nachzuflicken) Aber der untere If-Block ist gut 
abgesetzt; sein Anfang wäre bei { rechts hinter dem if wesentlich 
schlechter erfassbar.

Johann

von ich (Gast)


Lesenswert?

> anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)
> Wie kommt man auf so einen Mist? Wer hat dr das beigebracht?

> Kommentare macht man nicht mit "//" sondern mit "/* */"
Schwachsinn, probier mal dabei einen größeren Codeblock 
auszukommentieren

> - Bei einer bestimmten Zeilenstelle muss die Codezeile aufhoeren (hab
> mir Column 79 angewoehnt)

Aha, wes für eie coole Weisheit

>- Codedateien sollten eine bestimmte Anzahl Zeilen nicht ueberschreiten
> (gaengig sind bei uns 1000)

Aha, weil sich dann die Funktionen schlecht finden lassen oder warum?

von Christian J. (elektroniker1968)


Lesenswert?

johann: Danke für die Ausführungen!

Was bedeutet #if 0

Ich kann mir da nicht viel drunter vorstellen. Ach ja, eine union habe 
ich noch nie verwendet, weil ich dann einen Knoten im Hirn kriege. Fiele 
mir auch derzeit nicht ein wozu man die brauchen kann.

Was mir noch fehlt ist eine Maske, die über einen uint8_t Array gelegt 
bestimmte Positionen mit Namen belegt.

Bisher lade ich die Zellen einzeln laut Protokoll aber sicherlich geht 
das noch schöner.
1
struct _SPI_Frame
2
{
3
    enum chips  device;         // angesprochenes Device
4
    uint8_t     tx_size;        // Grösse des TX Datensatzes
5
    uint8_t     tx_buf[64];     // Sendepuffer
6
    uint8_t     rx_size;        // Grösse des RX Datensatzes
7
    uint8_t     rx_buf[64];     // Empfangspuffer
8
};   
9
10
11
SPI_Frame.tx_buf[idx++] = CMD_PORT2_DIR;   // Kommando Portrichtung
12
SPI_Frame.tx_buf[idx++] = portdata;
13
SPI_Frame.tx_size       = idx;             // 2 Zeichen
14
  
15
  answer = PORT_SendFrame(&SPI_Frame);

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

"ich" wrote:
> so einen Mist?
> Schwachsinn
> wes für eie coole Weisheit

lern ersma Manieren!

PLONK

von Matthias N. (vbchaos)


Lesenswert?

ich wrote:
>> anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)
>Wie kommt man auf so einen Mist? Wer hat dr das beigebracht?

Wers dem Dr. beibrachte? Keine Ahnung. Mir diverse Kollegen und 
Tutorials. Erläuterungen siehe oben. Wie machst du es? TAB und Spaß 
dabei?
>
>> Kommentare macht man nicht mit "//" sondern mit "/* */"
> Schwachsinn, probier mal dabei einen größeren Codeblock
> auszukommentieren

Siehe oben, klappt ganz toll, schnell und problemlos. Komplett mit "//" 
auskommentierte Blöcke lassen sich zudem leichter wiederfinden, weil das 
"//" in Column 1 nunmal auffällt, wenn mans nur dafuer benutzt. Wie 
machst du es? Immer oben ein /* und unten ein */? Schoen von Hand 
eingefuegt?

>> - Bei einer bestimmten Zeilenstelle muss die Codezeile aufhoeren (hab
>> mir Column 79 angewoehnt)
>
> Aha, wes für eie coole Weisheit

Ich weiss. Sieht darueber hinaus auch noch toll aus. Bis zu welcher 
Stelle schreibst du? Column 200? hast du ne 3D scroll maus oder ist dir 
Langweilig? Oder bist du Freund neuer Breitbildformate und haste einen 
50:10 Schirm der dir soviel gleichzeitig anzeigt? Wie druckst du 
Code-Fragmente? In Schriftgroeße 3? oder klebst du 4 DinA4 Seiten 
aneinander? 79 passt meistens ganz gut auf ein DinA4 Blatt in lesbarer 
Größe.

>>- Codedateien sollten eine bestimmte Anzahl Zeilen nicht ueberschreiten
>> (gaengig sind bei uns 1000)
>
> Aha, weil sich dann die Funktionen schlecht finden lassen oder warum?

Ich scrolle ungern durch 20k Zeilen Code in einer Datei. Da ist der 
scrollbalken so klein. Meine IDE erlaubt mir darueber hinaus, Funktionen 
direkt anzuspringen oder sie zu SUCHEN.

Darueberhinaus: Lern' mal Umgangsformen, oder sprichst du so mit deinen 
Kollegen? Oder mit deiner Mami? Müsste die dich nich lange ins Bett 
gebracht haben? Oder dir zumindest Rechtschreibung beibringen?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Christian J. wrote:
> johann: Danke für die Ausführungen!
>
> Was bedeutet #if 0

Mit
1
#if 0
2
...
3
#else // 0
4
...
5
#endif // 0
Kann man auch Varianten austesten oder was auskommentieren, bzw. hier 
durch den Präprozessor ausblenden lassen. Dito für #ifdef. 0 ist immer 
false, 1 ist immer true.

Aber es gilt das Gleiche wie für Kommentare: in Kommentare gehört kein 
Code! Das ist nur in der Entwicklungsphase. Manche 
(Sicherheits)Standards verbieten sogar Code in Kommentaren, obwohl das 
nix zur Funktion beiträgt.

> Ich kann mir da nicht viel drunter vorstellen. Ach ja, eine union habe
> ich noch nie verwendet, weil ich dann einen Knoten im Hirn kriege. Fiele
> mir auch derzeit nicht ein wozu man die brauchen kann.

Genau für das, was du unten fragst...

> Was mir noch fehlt ist eine Maske, die über einen uint8_t Array gelegt
> bestimmte Positionen mit Namen belegt.
>
> Bisher lade ich die Zellen einzeln laut Protokoll aber sicherlich geht
> das noch schöner.
>
>
1
> struct _SPI_Frame
2
> {
3
>     enum chips  device;         // angesprochenes Device
4
>     uint8_t     tx_size;        // Grösse des TX Datensatzes
5
>     uint8_t     tx_buf[64];     // Sendepuffer
6
>     uint8_t     rx_size;        // Grösse des RX Datensatzes
7
>     uint8_t     rx_buf[64];     // Empfangspuffer
8
> };
9
> 
10
> 
11
> SPI_Frame.tx_buf[idx++] = CMD_PORT2_DIR;   // Kommando Portrichtung
12
> SPI_Frame.tx_buf[idx++] = portdata;
13
> SPI_Frame.tx_size       = idx;             // 2 Zeichen
14
> 
15
>   answer = PORT_SendFrame(&SPI_Frame);
16
>

...könnte man eine Union hernehmen. Eine Union stellt unterschiedliche 
Sichten auf ein und dieselben Daten dar. In deinem Falls sind die Puffer 
jedoch recht groß, und jedes Byte einzeln zu benennen mag ne Overdose 
sein.

Johann

von Boris Bukowski (Gast)


Lesenswert?

> struct _SPI_Frame
> {
>     enum chips  device;         // angesprochenes Device
>     uint8_t     tx_size;        // Grösse des TX Datensatzes
>     uint8_t     tx_buf[64];     // Sendepuffer
>     uint8_t     rx_size;        // Grösse des RX Datensatzes
>     uint8_t     rx_buf[64];     // Empfangspuffer
> };
>
>
Das ist auf jeden Fall ein Beispiel für total sinnlose Komentare ;^)

Boris

von Christian J. (elektroniker1968)


Lesenswert?

>>Das ist auf jeden Fall ein Beispiel für total sinnlose Komentare ;^)

Lieber Boris,

wenn Du erstmal die Erkenntnis gemacht hast nach 2 Jahren überhaupt 
nicht mehr zu wissen, was Dein Code überhaupt verbricht, dann wirst Du 
wie ich dazu übergehen lieber etwas mehr als zu wenig zu kommentieren 
zudem beim Überfliegen immer die "lesbaren" Anteilen haften bleiben, 
nicht aber die cryptischen.

Aber wie alles Geschmackssache ;-)

i++; //i um 1 erhöhen :-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Christian J. wrote:
>>>Das ist auf jeden Fall ein Beispiel für total sinnlose Komentare ;^)
>
> Lieber Boris,
>
> wenn Du erstmal die Erkenntnis gemacht hast nach 2 Jahren überhaupt
> nicht mehr zu wissen, was Dein Code überhaupt verbricht, dann wirst Du
> wie ich dazu übergehen lieber etwas mehr als zu wenig zu kommentieren
> zudem beim Überfliegen immer die "lesbaren" Anteilen haften bleiben,
> nicht aber die cryptischen.

Jo, schon. Aber oben bleiben viele Fragen offen:
-- Warum fängt der Struct mit einem _ an???
-- Warum ist die Puffergröße genau 64?
-- Warum braucht man überhaupt ne Struktur, und schreibt nicht was wie

int n_received = SPItransmit (chipId, buffer, n_send);

Ist zwar ne tachnische Frage und hat nix mit Codier-Richtlinien zu tun, 
stellt sich aber trotzdem. Ist vielleicht woanders beantwortet. Zudem 
müsste das technisch anders gemacht werden, weil das den gleichen Puffer 
verwendet.

Beim Kommentieren hat man immer das Problem, daß das, was man gerade am 
klöppeln ist, alles klar und selbstverständlich ist. Man hat irgendwie 
nicht den Nerv und die Zeit Dinge hinzutexten, die einem eh sonnenklar 
sind und die sich vielleicht bald wieder ändern, weil es noch nicht 
fertig ist; und dann wär die Arbeit doppelt (anpassen von Quelle und 
Doku). Aber wenn man den richtigen Zeitpunkt für's 
Dokumentieren/Kommentieren verschnarcht, blick't man es selber nicht 
mehr so genau (3 Monate später) und die Kommentare werden dann womöglich 
sogar etwas inkonsistent mit dem, was die Quelle treibt.

Das beste an Kommentaren, was ich je sah, war ein Projekt an der Uni. Es 
war in C und jede Funktion hatte in etwa den Aufbau:
1
int funktion (...)
2
{
3
    /* Deklaration der Variablen */
4
    some-10-up-to-30-lines-of-decls-and-decl-inits
5
6
    /* Initialisierung der Variablen */
7
    some-10-up-to-30-lines-of-initializations
8
9
    /* Code der Funktion */
10
    some-1000-lines-of-undocumented-but-highly-sophisticated-code
11
12
    /* Ende der Funktion */
13
    return fourtytwo;
14
}

von der peterle (Gast)


Lesenswert?

> Peter Stegemann wrote:
>> Matthias Nix wrote:
>>> Peter Stegemann wrote:
>>
>>>>> - anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)
>>>> Anstatt Leerstellen immer Tab benutzen.
>>> Genau! Ist super lesbar im 0815 Texteditor! Das Einruecken wird dann
>>> zum Familienspass
>>>
>> Bei jedem gescheiten Editor laesst sich die Tabbreite einstellen.
> Du willst vielleicht auch mal was von jemand anderem editieren und
> gescheit darstellen, ohne ständig deinen Editor umzukonfigurieren.
> Genau das passiert, wenn man TABs verwendet. Für manche heisst es 8,
> manchmal 4, manchchmal bis zum nächsten Tabstop. Mit Leerzeichen (kann
> ebenfalls jeder gute Editor) sieht's überall gleich aus.
Also den Satz verstehe ich nicht, wie der Editor den Tab interpretiert
stellt man genau einmal ein, eventuell einmal pro Suffix. Bei
Leerzeichen ist man auf das eingenordet, was der Vorgänger verwendet
hat. Außer man lässt den Autoindenter rüber, ich habe da kein Problem
mit, (g)vim kann das sehr gut, aber wenn der Code dann wieder zurück
zum ursprünglichen Programmierer soll... gibt es mecker oder man muss
es wieder zurück konvertieren.
Ich muss mir eh mal universalindent reinziehen... für per Hand sind die
Projekte zu groß.

>>>>> - Kommentare macht man nicht mit "//" sondern mit "/* */"
>>>> Kommentare beginnen nie mit /* */, damit man ohne Probleme Codeteile
>>>> auskommentieren kann.
>>> Ich sprach von Kommentaren. Jene, die dir Hinweise auf die Funktion des
>>> Codes geben. Nicht davon, Code zum debuggen rauszuwerfen.
>> Und was passiert, wenn du einen Block auskommentieren willst, in dem ein
>> Kommentar mit /* */ steht?
> Zu Ausblenden geht auch #if 0
Beim Testen von verschiedenen Algorythmen, -> #if 0
temporäres auskommentieren mit Editor oder /**/.

>>> Verwendung der Shifttaste und moeglichster Verzicht auf Abkuerzungen.
>>> AppleCounter oder LoopCounter ist wesentlich besser lesbar und die paar
>>> Umlaute bringen einen nicht um.
>> Shifttaste laesst man lieber, nervt nur beim tippen. Ist aber
>> Geschmacksache.
Ich stehe da auch eher auf CamelCase...

> Variablennamen sinnvoll wählen. Eine Schleifenvariable, die nur über 2
> Zeilen lebt, als thisisaloopvariableandwilldietwolinesbelow zu nennen
> ist Käse. Da ist i oder n voll ok, und es verschleiert nicht den Blick
> aufs Wesentliche. Horror sind solche Bezeichner jedoch, wenn sie über
> weitere Codesequenzen gültig sind, dann sind sprechendere Namen
> angesagt.

Eine for mit i,j,k,... ist vollkommen i.O..

von Micha (Gast)


Lesenswert?

Würde es nicht Sinn machen die genannten Punkte in einem eigenen Artikel 
zu sammeln? Die strittigen Punkte könnten ja mit einem entsprechendem 
Vermerk versehen werden.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Matthias Nix wrote:
> - anstatt TAB immer Leerstellen benutzen (auch bei Druck auf TAB)

Das erscheint vielen unverständlich.
Grund ist folgender: Anhand der Syntax eines C/C++-Programms (und 
zusammen mit Codier-Richtlinien) ist immer klar, wie weit eine Zeile 
einzurücken ist -- auch dann, wenn überlange Austrücke gebrochen werden.
Von daher besteht in einem C-Programm nie die Notwendigkeit, von Hand 
Einrückungen vorzunehmen, es sei denn, ein Editor unterstützt Enrückung 
nicht vollständig. Die TAB-Taste ist alse komplett überflüssig :-) Oder 
man bekommt eine mit TABs zerfrickelte Quelle/Snip.

Ich kenne keinen Editor, der Einrückung so perfekt unterstützt wie 
Emacs. Weder AVR-STudio, noch Eclipse, noch Code::Blocks, noch TextPad, 
noch Programmer's Notepad, noch Borland IDEs, noch vi oder JEdit oder 
wie sie alle heißen.

Beim Drücken auf TAB geschieht folgendes:
-- Nichts (wenn die Zeile korrekt eingerückt ist
-- Die Zeile wird anhend des Kontextes korrekt eingerückt, indem SPACEs 
eingefügt/entfernt werden (falls sie nicht schon richtig eingerückt war)

Es gibt auch die Möglichkeit, von Hand über Sonderkommando TAB an die 
aktuelle Caret-Position einzufügen, das wird man aber nie brauchen...

> - Inhalt von Schleifen und Bedingungen IMMER einklammern

Eine Ausnahme gibt es hier, und zwar if-else-Spaghettis
1
if (x)
2
{
3
   ...
4
}
5
else if (y)
6
{
7
   ...
8
}
9
else if (z)
10
{
11
   ...
12
}
13
else
14
{
15
   ...
16
}
Das wird eingerückt wie abgedeutet. Wenn man hier if immer wieder 
klammert und dementsprechend einrückt, dann läuft der Code nach rechts 
weg und wird unlesbar. Gleiches auch ohne Klammerung, wenn if in der 
nächsten Zeile stehen würde!

Im Zweifelsfalls emacs fragen :o)

> - Kommentare beginnen immer in der selben Zeilenstelle und enden beim
> definierten Zeilenende
>
> - Kommentare macht man nicht mit "//" sondern mit "/* */"
>
> - Codedateien sollten eine bestimmte Anzahl Zeilen nicht ueberschreiten
> (gaengig sind bei uns 1000)
>
> - Jede Datei beinhaltet einen Kopf, den Dateinamen, Autor, Version,
> Erstellungsdatum und das Datum groesserer Aenderungen
>
> - Sinnvolle Namensgebung fuer Variablen. Namen wie "i", "x", "xyz" sind
> Tabu.

Nein, nicht Tabu. Siehe
    Beitrag "Re: Programmier Stil für Mikrocontroller"

> - Kommentare, und zwar reichlich. Code is obviously written for people
> to read! Aussagekraeftige aber kurze Kommentare. Am Besten in Englisch.
Ich schreib kommentare inzwischen in Deutsch :-) Natürlich nur das, was 
ich privat mache. Ist anfangs recht seltsam... aber man gewöhnt sich 
dran. Was ich provat mache, wird eh kein anderer verwenden. Und warum 
soll ich für mich selbst in Englisch schreiben? Dann schon lieber 
Burundi oder Sanskrit, dann lernt man wenigstens was :o)

Oder man codiert direkt in Latein:
   http://www.csse.monash.edu.au/~damian/papers/HTML/Perligata.html

> Dann gibt es noch so Dinge, wo sich die Geister scheiden...
Ich würd mal behaupten, es gibt kaum Dinge, die die Geister nicht 
scheiden.

> - Jede Funktion hat einen einzigen Punkt, an dem sie beendet wird,
> naemlich ihre letzte Zeile. RETURN-Anweisungen irgendwo weiter vorn zum
> Abbrechen der Funktion sind verboten. Ich persoenlich versuche mich
> weitestgehend dran zu halten, manchmal ist es aber einfach viel
> einfacher. Generell aber praktisch, da man nicht ewig in der Funktion
> suchen muss, wo sie unter umstaenden abgebrochen wurde.

Sieht wie ne esoterische MISRA-Regel aus. Wenn eine Funktion komplex 
ist, wirst du sie auch nicht besser blicken ob des einzigen return. Vom 
Fluß her ist ein
1
if (error)
2
   return -1;
wesentlich klarer als 100-fach verschachtelte if-else, in denen Stati 
mitgeschleppt werden die nur dazu dienen, den Fluß nach unten 
durchfallen zu lassen. IdR werden zig neue Hilfsvariablen gebraucht, und 
das verschleiert alles den Fluß, anstsatt ihn zu klären. 
Standardbeispiel:
Such in einer Funktion was in einem 3-dimensionalen Array und liefere 
die Adresse des gefundenen Objektes oder NULL, wenn es nicht drinne ist.

> - Striktes Vermeiden von "goto"!!! Kann man in ganz ganz bestimmten
> Faellen trotzdem benutzen, aber dann extrem gut kommentiert, weil es
> sonst ein heiloses Durcheinander wird.

Meine Quellen enthalten goto. Pro Projekt so 1-2 Stück, würde ich 
schätzen. Die Gefahr ist, wenn man es übertreibt. Aber 
zig-verschachtelte Schleifen sind auch nicht erhellend, hier gilt 
ähnliches wie eben für "return" gesagt. Teilweise lassen sich 
goto-Konstrukte ersetzen durch.
1
while (1)
2
{
3
    ...
4
    if (panic)
5
        break; 
6
    ...
7
}
Ob das "break" (oder im Falle eines Rücksprunges ein "continue") jedoch 
klarer sind als ein "goto" mit expliziter Marke, sei dahingestellt. Wenn 
die Quelle komplex ist und man erst rumrudern muß um die } zu finden, an 
dem das "break" landet, kann das ziemlich nerven.

Ausser Frage steht natürlich, daß sich jedes Programm auch ohne "goto" 
formulieren lässt. Eine weitere Möglichkeit kann eine inline-Funktion 
mit mehreren returns sein, die nach dem Inlinen wie goto wirken.

Johann

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.