Hallo Zusammen, in diesem Thread würde ich gerne wissen, was Ihr unter schönem Code versteht. Damit das eine vernünftige Diskussion wird, würde ich euch bitten, Links auf "exemplarisch schönen Code" zu posten. Hier mal ein Beispiel für sehr intelligenten, aber unschönen code: http://www.ioccc.org/2013/cable3/cable3.c Es ist ein 80186 Emulator der Win3.0 emulieren kann: http://www.ioccc.org/2013/cable3/hint.html Komplizierten Code zu finden ist also einfach, wo aber findet sich schöner Code?
@ chris_ (Gast) >Hier mal ein Beispiel für sehr intelligenten, aber unschönen code: >http://www.ioccc.org/2013/cable3/cable3.c Was ist daran intelligent? Hat da jemand Komplexe, die er mit maximal unleserlichen Makros kompensieren will? Armer Irrer. >Komplizierten Code zu finden ist also einfach, wo aber findet sich >schöner Code? Der Sourcecode von Doom soll gut sein. http://kotaku.com/5975610/the-exceptional-beauty-of-doom-3s-source-code
Allgemein würd ich sagen: 1.)Der Code muss gut kommentiert werden. 2.)Du solltest die einzelnen Abschnitte einrücken 3.)Nach jedem Befehlssatz ein Newline. 4.)Sich wiederholende Abschnitte in Funktionnen(sofern möglich) 5.)Unnötigen Code vermeiden(d.h. Code den man nicht mehr braucht löschen und nicht auskommentieren). 6.)Bei großen Programmen evtl. in neue Dateien. Das würde ich beachten. Aber ich muss zugeben, dass ich das quasi nicht beachte. ;-)
:
Bearbeitet durch User
chris_ schrieb: > in diesem Thread würde ich gerne wissen, was Ihr unter schönem Code > versteht. "Schöner Code" ist ansichtssache. Für den einen ist schöner Code, Code, den man auch noch nach lange Zeit gut Lesen kann, und für den anderen ist schöner Code, Code, der besonders performant ist, egal wie krude das aussieht. Wenn ich für PC programmiere, liegt der Aspekt der Schönheit ganz klar auf gute Lesbarkeit, weil das auch mal andere anschauen (müssen). Wenn ich für einen mC Programmiere, wo außer mir keiner raufschaut, dann liegt der Aspekt der Schönheit ganz klar mehr bei performance. 12V DC schrieb: > 1.)Der Code muss gut kommentiert werden. Das würde ich so nicht unterschreiben. Hört sich zwar blöde an, aber guter und schöner code ist wirklich selbst Erklärend. Wenn man 20 Zeilen Kommentar braucht, um eine Funktion oder einen Algorithmus zu beschreiben, dann sollte man noch mal nachdenken ob es nicht auch anders geht. Lange Kommentare sind immer ein Zeichen für komplexen und damit auch fehleranfälligen Code. Je einfacher der Code ist, desto besser. Viele Leute neigen auch dazu jeden mist zu kommentieren, und wenn ich dann noch sowas höre wie: "Es sollten immer 2/3 Kommentar und 1/3 Code sein!" (ja, das hab ich shcon mehr als ienmal gehört...), dann würd ich dieser Person gerne mal mit nem Doppel-T-Träger ins Gesicht schlagen! Grüße
Dieser Code ist schön, also Optisch ;-).
1 | #define _ F-->00||F-OO--;
|
2 | int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO() |
3 | {
|
4 | _-_-_-_ |
5 | _-_-_-_-_-_-_-_-_ |
6 | _-_-_-_-_-_-_-_-_-_-_-_ |
7 | _-_-_-_-_-_-_-_-_-_-_-_-_-_ |
8 | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ |
9 | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ |
10 | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ |
11 | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ |
12 | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ |
13 | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ |
14 | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ |
15 | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ |
16 | _-_-_-_-_-_-_-_-_-_-_-_-_-_ |
17 | _-_-_-_-_-_-_-_-_-_-_-_ |
18 | _-_-_-_-_-_-_-_ |
19 | _-_-_-_ |
20 | }
|
[Brian Westley, 1988]
Falk Brunner schrieb: > Hat da jemand Komplexe, die er mit maximal unleserlichen Makros > kompensieren will? Armer Irrer. Naja, gerade das ist ja der Sinn dieser Veranstaltung: International Obfuscated C Code Contest
Falk Brunner schrieb: > Hat da jemand Komplexe Obfuscated code contest. https://de.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest
Schöner Code ist, wenn man, ohne die Programmiersprache und den Algorithmus zu kennen, nach kurzem Durchlesen ohne weitere Erläuterungen den Algorithmus versteht. Hier ist ein Beispiel:
1 | quicksort [] = [] |
2 | quicksort (first:rest) = (quicksort lesser) ++ [first] ++ (quicksort greater) |
3 | where |
4 | lesser = filter (< first) rest |
5 | greater = filter (>= first) rest |
chris_ schrieb: > Komplizierten Code zu finden ist also einfach, wo aber findet sich > schöner Code? Da du den letzjährigen IOCCC ausgesucht hast: Der hier sieht doch schön aus: http://www.ioccc.org/2013/cable2/cable2.c Falk Brunner schrieb: > Was ist daran intelligent? > > Hat da jemand Komplexe, die er mit maximal unleserlichen Makros > kompensieren will? Armer Irrer. Du weißt, was der IOCCC ist? Kaj schrieb: > "Schöner Code" ist ansichtssache. Für den einen ist schöner Code, Code, > den man auch noch nach lange Zeit gut Lesen kann, und für den anderen > ist schöner Code, Code, der besonders performant ist, egal wie krude das > aussieht. Oder auch Code, der besonders clever ist, auch wenn er eher unkonventionell und schwer zu verstehen ist. Man denke an das Duff-Device. Das finde ich durchaus schön, was aber nicht heißt, daß ich es bevorzugt einsetzen würde. http://de.wikipedia.org/wiki/Duff’s_Device > Wenn ich für PC programmiere, liegt der Aspekt der Schönheit ganz klar > auf gute Lesbarkeit, weil das auch mal andere anschauen (müssen). Da liegt sicher der Fokus drauf und das sollte das Ziel sein, aber das hat mit Schönheit erstmal direkt nichts zu tun. > Wenn ich für einen mC Programmiere, wo außer mir keiner raufschaut, dann > liegt der Aspekt der Schönheit ganz klar mehr bei performance. Hier gilt das gleiche wie beim Satz davor. > 12V DC schrieb: >> 1.)Der Code muss gut kommentiert werden. > Das würde ich so nicht unterschreiben. Hört sich zwar blöde an, aber > guter und schöner code ist wirklich selbst Erklärend. Man muß noch zwischen Kommentaren im Code und denen über Funktionsköpfen differenzieren. Letztere halte ich schon für sinnvoll und falls es bei den zu übergebenden Parametern irgendetwas zu beachten gibt (was meistens der Fall ist) auch für notwendig. > Viele Leute neigen auch dazu jeden mist zu kommentieren, und wenn ich > dann noch sowas höre wie: "Es sollten immer 2/3 Kommentar und 1/3 Code > sein!" (ja, das hab ich shcon mehr als ienmal gehört...), dann würd ich > dieser Person gerne mal mit nem Doppel-T-Träger ins Gesicht schlagen! Das kenne ich auch. Ich kann mich auch noch einen Prof erinnern, der uns zu besonders ausführlicher Kommentierung erziehen wollte. Bei seinem Manuskript war es ohne Syntax-Highlighting ungelogen schwierig, zwischen den ganzen Kommentaren den eigentlichen Code noch zu finden.
Was ich noch vergessen habe: Schön und praktisch sind zweierlei Dinge. Eine Zierleiste am Auto ist auch schön (oder soll es zumindest sein), hat aber keinen praktischen Nutzen. Und dementsprechend sollte man auch bei Code Schönheit und praktischen Nutzwert nicht verwechseln.
Was ist ne schöne Frau (oder auch Mann)? 1000 Fragen, 1000 Antworten. Schön (für mich) ist, wenn das Ding jahrelang ohne irgendwelche Probleme funktioniert und ich da nie wieder ran muss (und mich dann über andere Schönheitsaspekte ärgere wie fehlende/unzureichende Kommentierung oder z.T. gerfrickelte Sachen)
Yalu X. schrieb: > Hier ist ein Beispiel: > quicksort [] = [] Schon die erste Zeile erzeugt ein großes Fragezeichen bei mir (die anderen aber auch). Ich sehe da nur, es wird einem Ausdruck ein eckiges Klammernpaar zugewiesen. Was soll das bedeuten, welche Programmiersprache ist das? Selbsterklärender Code ist ein Mär. Kommentare beißen nicht.
@ H.Joachim Seifert (crazyhorse) >Was ist ne schöne Frau (oder auch Mann)? >Schön (für mich) ist, wenn das Ding jahrelang ohne irgendwelche Probleme >funktioniert und ich da nie wieder ran muss Freud'sche Fehlleistung? ;-) http://de.wikipedia.org/wiki/Freud%E2%80%99scher_Versprecher
Peter Dannegger schrieb: > Yalu X. schrieb: >> Hier ist ein Beispiel: >> quicksort [] = [] > > Schon die erste Zeile erzeugt ein großes Fragezeichen bei mir (die > anderen aber auch). Pink Shell schrieb: > Ein normaler Mensch blickt durch Dein Beispiel nicht durch. Hmm, als ich diesen Code zum ersten Mal gesehen habe, hatte ich einen unwahrscheinlichen Aha-Effekt. Ein paar Leute, denen ich das Beispiel gezeigt habe, wussten ebenfalls sofort Bescheid. Aber das scheint wohl nicht allen so zu gehen. Deswegen hier noch einmal den Code mit Kommentaren (die Zeilen mit -- am Anfang):
1 | -- Eine leere Liste ergibt sortiert wieder eine leere Liste: |
2 | |
3 | quicksort [] = [] |
4 | |
5 | -- Eine nichtleere Liste, bestehend aus ihrem ersten Element (first) und den |
6 | -- restlichen Elementen (rest), ergibt sortiert die Aneinanderreihung aus |
7 | -- - lesser (sortiert) |
8 | -- - first |
9 | -- - greater (sortiert) |
10 | -- wobei lesser alle Elemente aus rest umfasst, die kleiner als first sind, |
11 | -- und greater alle Elemente, die mindestens so groß wie first sind: |
12 | |
13 | quicksort (first:rest) = (quicksort lesser) ++ [first] ++ (quicksort greater) |
14 | where |
15 | lesser = filter (< first) rest |
16 | greater = filter (>= first) rest |
Vielleicht wird es damit klarer.
:
Bearbeitet durch Moderator
> quicksort [] = []
Bleibt für mich noch die Frage: Welche Programmiersprache? Ich kenne den
Syntax auch nicht.
Peter Dannegger schrieb: > Kommentare beißen nicht. Wobei man es mit den Kommentaren auch übertreiben kann wodurch die Lesbarkeit des Codes wieder reduziert wird. Man darf schon davon ausgehen, dass der, der den Code liest die Programmiersprache beherrscht;)
chris_ schrieb: > Bleibt für mich noch die Frage: Welche Programmiersprache? Ich kenne den > Syntax auch nicht. Hab ich ganz vergessen: Haskell.
Das erste Ergebnis, welches man erhält, wenn man bei Google-Bilder auf dem Tablet "schöner kot" eingibt, ist ein Bild von einem Vogel
Seit wann gibt es Schönheitspreise für Code? Mich regt es auch auf, wenn bei Platinen die Layer in Richtung und Winkel stimmen müssen. Ich hab mal lernen müssen: "So gut wie nötig, und nicht so gut wie möglich" Übertragen: "So schön wie nötig, und nicht so schön wie möglich" Für Frauen gilt das natürlich nicht :-) .
chris_ schrieb: > in diesem Thread würde ich gerne wissen, was Ihr unter schönem Code > versteht. Ich verstehe darunter Code, der sich an sinnvolle Programmierrichtlinien hält. Und über den man idealerweise regelmäßig ein Tool zur statischen Codeanalyse drüberlaufen lässt (und die Findings dazu am besten nicht ignoriert ;-) Um ein konkretes Beispiel zu nennen: Das Buch "Clean Code" von Robert C. Martin ist ein recht guter Maßstab. Kann sich jeder Programmierer gerne mal anschauen. http://www.heise.de/developer/artikel/Clean-Code-1137811.html innerand innerand schrieb: > Peter Dannegger schrieb: > >> Kommentare beißen nicht. > > Wobei man es mit den Kommentaren auch übertreiben kann wodurch die > Lesbarkeit des Codes wieder reduziert wird. > Man darf schon davon ausgehen, dass der, der den Code liest die > Programmiersprache beherrscht;) Das ist aber nicht der Punkt. Wenn man mit bereits existierendem Code arbeiten muss (also in 99% aller Fälle), dann will man möglichst schnell verstehen können, was der Sinn hinter dem Code anderer Leute ist. Dazu sollte man nicht erst die Anforderungsspezifikation hervorholen müssen. Oft genug gibt es die ja nicht einmal, oder es gibt zwar eine aber sie ist unvollständig. Wenn Dein Code korrekt funktioniert und andere Leute Deinen Code leicht verstehen können, dann ist das ein ziemlich sicheres Zeichen dafür, dass er gut ist.
:
Bearbeitet durch User
Peter Dannegger schrieb: > Kommentare beißen nicht. Vielleicht sollte man den Code auch für Dokumentationstools wie "Doxygen" vorbereiten. Ich persöhnlich bevorzuge graphische Darstellungen, das lässt sich mit Doxygen machen. Wenn allerdings die Include-Struktur so aussieht https://trac.adium.im/doxygen/adium/Docs/html/fs-conference-iface_8h.html dann deutet das für mich auf "unschönen Code" hin.
Sch"oner Code ist das was ich schreibe :) Ja, mit den Kommentaren, das sehe ich auch so wie Kaj, allerdings verwende ich den Begriff 'selbstdokumentierend' hierf"ur. Allerdings sind f"ur mich Doxygen/javadoc-Kommentare bei den Prototypen selbstverst"andlich. Nur im Code (*.c) selbst bin ich sparsam. Wichtige Vorraussetzung f"ur sch"onen Code ist das loslassen von alten Regeln. Man_kann_auch_Mikrocontroller_programmieren_ohne_dass_50%_aller_Zeichen Unterstriche_sind!! UND_MAN_MUSS_NICHT_ALLES_GROSS_SCHREIBEN_NUR_WEILS_K&R_ANNO_1970_TATEN! Hat man diese Hirnlosigkeit mal hinter sich gelassen, kann man vielleicht sogar den Code mal wenigstens eintippen ohne Schwielen an den Fingern f"ur SHIFT und _ zu bekommen. Sch"oner Code organisiert Teilfunktionalit"aten in leicht wiederverwendbaren Einheiten und verwendet systematische Namen, Aufrufkonventionen. Sch"oner Code vermeidet Redundanz. UND: sch"onen Code kann man nur schreiben, wenn man mindestens 1 Jahr nur Haskell (und nichts anderes) programmiert hat. Und das mein ich nicht als Witz. Wer nich einmal im Leben von der imperativen Schmuddeldenke weggekommen ist, wird's nie raffen. Ich bin langsamer, ich brauchte 2 Jahre Haskell ;-)
Das Haskell sieht ja wirklich extrem anders aus, als C. Wie sähe z.B. eine Software TX-UART in Haskell aus? Hier mal der C-Code für AVR-GCC:
1 | #define F_CPU 8e6
|
2 | #include <avr/io.h> |
3 | #include <util/delay.h> |
4 | |
5 | struct bits { |
6 | uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; |
7 | } __attribute__((__packed__)); |
8 | #define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
|
9 | #define SBIT(x,y) SBIT_(x,y)
|
10 | |
11 | |
12 | #define BAUD 9600
|
13 | #define STXD SBIT( PORTB, 0 )
|
14 | #define STXD_oe SBIT( DDRB, 0 )
|
15 | |
16 | void sputchar( uint8_t c ) |
17 | {
|
18 | c = ~c; // complement to cause shift in stop bit |
19 | STXD_oe = 1; // output |
20 | STXD = 0; // start bit |
21 | for( uint8_t i = 10; i; i-- ){ // 10 bits |
22 | _delay_us( 1e6 / BAUD ); // bit duration |
23 | if( c & 1 ) |
24 | STXD = 0; |
25 | else
|
26 | STXD = 1; |
27 | c >>= 1; |
28 | }
|
29 | }
|
Und sind meine Kommentare überflüssig oder zu schlecht?
Peter Dannegger schrieb: > Das Haskell sieht ja wirklich extrem anders aus, als C. Ist ja auch ein ganz anderes Programmierparadigma. Kurz zusammenfassen lässt sich das wohl so: Bei funktionalen Programmiersprachen steht eher das "Was soll passieren?" im Vordergrund und nicht das "Wie soll es passieren?". Wenn man Rekursion, Faltung & Co. verstanden hat, dann könnte man sogar argumentieren, dass Haskell und Verwandtschaft (SML, Lisp, etc.) intuitiver und fehlertoleranter sind. Wobei meiner Meinung nach auch ein Teil der Schönheit und Einfachheit verloren geht, sobald man mit der Außenwelt interagiert. Und das ist nun einmal das was z.B. Mikrocontroller die ganze Zeit tun. Bringt nur nicht besonders viel im Kontext von Mikrocontrollern und Betriebssystemen. Da ist C nun einmal das Maß aller Dinge und wird es wohl auch noch für einige Zeit bleiben. Peter Dannegger schrieb: > Und sind meine Kommentare überflüssig oder zu schlecht? Als jemand der sich schon öfter deinen hier veröffentlichten Code angesehen und als Inspiration für eigene Entwicklungen zu Rate gezogen hat, muss ich dir ganz ehrlich sagen, dass dein Code oft nicht besonders intuitiv ist. Das soll nicht heißen, dass er schlecht ist. Ganz im Gegenteil: Nicht selten ist dein Vorgehen ziemlich geschickt. Aber selbst mit deinen Kommentaren bin ich oft nicht auf Anhieb dahinter gekommen und musste teilweise viel Gehirnschmalz sowie Stift und Papier verwenden, um dahinter zu kommen. Vielleicht unterscheiden wir uns in unseren Denkweisen auch einfach nur zu sehr. Im Übrigen halte ich Doxygen z.B. für eine tolle Sache und um Weiten besser als irgendwelche Randnotizen. Das hat den Vorteil ziemlich einheitlich zu sein und lässt sich dazu nutzen automatisiert diverse Referenzdokumente zu erstellen. Gerade bei komplexen Projekten lassen sich so die Abhängigkeiten untereinander ganz gut visualisieren. Was die "Schönheit" von Code angeht, so ist Konsequenz wohl das Stichwort, welches ich in den Vordergrund stellen würde. Das Gehirn ist ganz gut darin Muster zu erkennen, insofern bietet es sich an Dinge immer im gleichen Muster anzuordnen. Da diese Frage aber immer wieder aufkommt, hier meine Antwort von vor einiger Zeit, siehe [1]: Karol Babioch schrieb: > Ein "besser" gibt es hier natürlich nicht. Die Hauptsache ist hier wohl > eher die Konsequenz, gerade wenn man im Team arbeitet. Das erleichtet > vor allem das Lesen von "fremden" Quellcode (und darunter verstehe ich > z.B. auch eingenen Quellcode, der etwas "älter" ist). I.d.R. sind das > aber Fragen, welche im Rahmen von Code Conventions > (https://de.wikipedia.org/wiki/Code_Convention) geklärt werden und > gerade bei größeren Projekten verpflichtend sind. > > Sinnvoll kann es unter Umständen sein die Code Conventions von "großen" > Projekten zu übernehmen. Im Bereich "C" gibt es da unter anderem z.B. > die GNU Coding Standards > (https://www.gnu.org/prep/standards/standards.html) oder den Linux > kernel coding style > (https://www.kernel.org/doc/Documentation/CodingStyle). Mit freundlichen Grüßen, Karol Babioch [1]: Beitrag "Re: Wie setzt ihr Klammern?"
:
Bearbeitet durch User
Hi Peter, hier mein Vorschlag:
1 | /******************************************************************************************
|
2 | |
3 | serial port driver in software
|
4 | |
5 | hardware:
|
6 | |
7 | AVR processor
|
8 | |
9 | *******************************************************************************************/
|
10 | |
11 | #define F_CPU 8000000
|
12 | #include <avr/io.h> |
13 | #include <util/delay.h> |
14 | |
15 | #define BAUD 9600
|
16 | #define PORTPIN (1<<PB0)
|
17 | |
18 | #define PINHIGH { PORTB |= PORTPIN; }
|
19 | #define PINLOW { PORTB &=~PORTPIN; }
|
20 | #define INITIALIZE_PIN { DDRB |= PORTPIN; }
|
21 | |
22 | #define DELAYBIT {_delay_us( 1e6 / BAUD );} // remark: this function may \
|
23 | use to much program memory
|
24 | |
25 | /******************************************************************************************
|
26 | |
27 | void sputchar( uint8_t value )
|
28 | |
29 | Send value through output pin. This routine emulates a serial port.
|
30 | |
31 | preconditions: it may be necessary to disable interrupts before calling this function
|
32 | to assure accurate timing
|
33 | |
34 | input: value to be transmitted
|
35 | |
36 | *******************************************************************************************/
|
37 | void sputchar( uint8_t value ) |
38 | {
|
39 | uint8_t i; |
40 | |
41 | value = ~value; // complement to cause shift in stop bit |
42 | |
43 | INITIALIZE_PIN; |
44 | |
45 | PINLOW; // start bit |
46 | |
47 | for( i = 10; i; i-- ) // 10 bits |
48 | {
|
49 | DELAYBIT; |
50 | |
51 | if( value & 1 ) { PINLOW; } |
52 | else { PINHIGH; } |
53 | |
54 | value >>= 1; // shift right for next bit |
55 | }
|
56 | |
57 | DELAYBIT; // delay for stop bit |
58 | }
|
Peter Dannegger schrieb: > Yalu X. schrieb: >> Hier ist ein Beispiel: >> quicksort [] = [] > > Schon die erste Zeile erzeugt ein großes Fragezeichen bei mir (die > anderen aber auch). > Ich sehe da nur, es wird einem Ausdruck ein eckiges Klammernpaar > zugewiesen. > Was soll das bedeuten, welche Programmiersprache ist das? > > Selbsterklärender Code ist ein Mär. > Kommentare beißen nicht. Wenn man FP/Haskell kennt (also Syntax und Grundidee der Sprache bekannt ist), ist das eine der elegantesten und verständlichsten Arten Quicksort zu notieren...
chris_ schrieb: > hier mein Vorschlag: Wenn du schon Blockkommentare für die Funktionen verwendest, dann kann ich dir o.g. Doxygen [1] wärmstes empfehlen. Dadurch haben die Kommentare auch über verschiedene Projekte (mehr oder weniger) die gleiche Form, es lassen sich, wie schon gesagt, diverse Referenzen daraus erstellen, und auch ein jeder etwas fortschrittlichere Editor hat direkt Unterstützung dafür und kann dir damit z.B. bei Verwendung der Funktion auch den Kommentar einblenden. Außerdem ist das Ganze - zumindest in ähnlicher Form - auch für viele anderen Programmiersprachen verfügbar, z.B. Java [2] und PHP [3]. Gerade bei größeren Projekten ist das fast schon ein Quasi-Standard. Mit freundlichen Grüßen, Karol Babioch [1]: http://www.stack.nl/~dimitri/doxygen/ [2]: http://www.oracle.com/technetwork/java/javase/documentation/index-jsp-135444.html [3]: http://www.phpdoc.org/
Karol Babioch schrieb: > Wenn du schon Blockkommentare für die Funktionen verwendest, dann kann > ich dir o.g. Doxygen [1] wärmstes empfehlen. Dadurch haben die > Kommentare auch über verschiedene Projekte (mehr oder weniger) die > gleiche Form, es lassen sich, wie schon gesagt, diverse Referenzen > daraus erstellen Ich gebe den zusätzlichen Tipp Javadoc-Syntax zu benutzen und Autobrief anzumachen. Dann kann man diese Kommentare schneller runtertippen (@ vs \, kein \brief etc.)
chris_ schrieb: > hier mein Vorschlag: Ja, ein Funktionsheader ist immer ein gute Idee. Ich bin da meistens zu faul dazu. Das letzte "DELAYBIT; // delay for stop bit" ist überflüssig. Die Schleife geht bereits über alle 10 Bit. Will man 2 Stopbits, trägt man eine 11 ein.
Peter Dannegger schrieb: > Das Haskell sieht ja wirklich extrem anders aus, als C. > Wie sähe z.B. eine Software TX-UART in Haskell aus? > > Hier mal der C-Code für AVR-GCC:#define F_CPU 8e6 > #include <avr/io.h> > #include <util/delay.h> > > struct bits { > uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; > } __attribute__((_packed_)); > #define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin) > #define SBIT(x,y) SBIT_(x,y) > #define BAUD 9600 > #define STXD SBIT( PORTB, 0 ) > #define STXD_oe SBIT( DDRB, 0 ) > > void sputchar( uint8_t c ) > { > c = ~c; // complement to cause shift in > stop bit > STXD_oe = 1; // output > STXD = 0; // start bit > for( uint8_t i = 10; i; i-- ){ // 10 bits > _delay_us( 1e6 / BAUD ); // bit duration > if( c & 1 ) > STXD = 0; > else > STXD = 1; > c >>= 1; > } > } > > Und sind meine Kommentare überflüssig oder zu schlecht? Also sch"oner f"ande ich (hab keine Ahnung von Atmega oder "ahnlich) #include ... #define STX.... enum { BAUD = 9600, ONE_BIT_US = 1000000 / BAUD, // Integer-Operation! }; // 8-bit blocking UART send void sputchar(Uint8 c) { c = ~c; STDX_oe = 1; STDX = 0; // start bit for (Int8 b=0; b<10; b++) { // 10bits, including start and stop _delay_us(ONE_BIT_US); STDX = ! c&1; c >>= 1; } } Mit genau so vielen Kommentaren, ausser dem ersten, den sollte man nicht erw"ahnen m"ussen.
Nee, wenn ich mir's nochmal ansehe: c = ~c am Anfang, und sp"ater bei der Ausgabe wieder invertieren?? DAS is unleserlich. (int c) c |= 1<<9 gibt doch viel klarer dein Stopbit. Oder gleich: c = 1 | c<<1 | 1<<9 ; Und eine noch einfachere Schleife. Aber ist ja wieder zu teuer auf 8-bit...
Peter Dannegger schrieb >Das letzte "DELAYBIT; // delay for stop bit" ist überflüssig. Upps, kleiner Denkfehler meinerseits :-) >Und eine noch einfachere Schleife. Aber ist ja wieder zu teuer auf >8-bit... Ich denke, dass die Schönheit von Peters Code im Minmalismus des Resourcenverbrauchs liegt. Der Code ist extrem kurz. Normalerweise würde man für die 10 Bit mehr als ein 8 Bit Register benötigen. Aber durch das "Leerschieben" der Variablen reichen die 8 Bit. Zugegebnermaßen sind das schon wieder Tricks, die das Verstehen des Codes erschweren, wie Du gerade eben festgestellt hast.
chris_ schrieb: > Ich denke, dass die Schönheit von Peters Code im Minmalismus des > Resourcenverbrauchs liegt. Wobei man sich ernsthaft fragen sollte, ob es das wert ist. I.d.R. ist nämlich die Arbeitszeit der Entwickler, die den Code warten/erweitern/anpassen müssen, wertvoller als der "nächstgrößere" Mikrocontroller. Es mag natürlich auch Fälle geben, wo das anders ist, aber ich bin - gerade im Hobbybereich - ein Fan von leserlich und dafür etwas größer als "unleserlich" und klein. Wenn es wirklich um die letzten Bits geht, dann ist C sowieso das falsche Mittel der Wahl, weil der kompilierte Quellcode in den meisten Fällen weit weg vom "Optimum" liegt Mit freundlichen Grüßen, Karol Babioch
:
Bearbeitet durch User
Karol Babioch schrieb: > chris_ schrieb: >> Ich denke, dass die Schönheit von Peters Code im Minmalismus des >> Resourcenverbrauchs liegt. > > Wobei man sich ernsthaft fragen sollte, ob es das wert ist. I.d.R. ist > nämlich die Arbeitszeit der Entwickler, die den Code > warten/erweitern/anpassen müssen, wertvoller als der "nächstgrößere" > Mikrocontroller. Gerade bei kleinen übersichtlichen Codeschnipseln kostet aber eine kompakte implementierung nicht (viel) mehr Zeit. Und es ist auch nicht so, dass man einfach immer mal schnell auf einen Controller mit mehr Speicher ausweichen kann. Wird zwar oft behauptet, geht aber IMO an der Realtität vorbei. > Wenn es wirklich um die letzten Bits geht, dann ist C sowieso das > falsche Mittel der Wahl, weil der kompilierte Quellcode in den meisten > Fällen weit weg vom "Optimum" liegt Das halte ich heutzutage für ein Gerücht. Der GCC z.B. erzeugt doch sehr guten Code, mit dem Vorteil dass man sich der Funktion sehr sicher sein kann. Schon viel zu oft wurde hier gemeckert, dass man doch eine Funktion viel kleiner in ASM schreiben könnte als der GCC und dann waren aber bestimmte Randbedingung nicht abgedeckt. Auch muss es nicht "das letzte Bit" sein, sondern das Vermeiden von mehr oder weniger offensichtlicher Verschwendung reicht meist schon aus. Und das geht in C genauso. Alles mit Maß und Ziel.
cyblord ---- schrieb: > Das halte ich heutzutage für ein Gerücht. Naja, im Bugtracker und (ab und zu) auf der Mailingliste gibt es genug offene Punkte bzw. Diskussionen zum Thema "missed optimization". Ich habe zwar keine Ahnung von den Internas der GCC bzw. inwieweit sich Vergleiche für andere Architekturen übertragen lassen, aber es ist nicht unüblich das bei entsprechendne Vergleichen andere Compiler besser abschneiden als die GCC. Nicht falsch verstehen: Ich liebe die GCC und benutze sie fast ausschließlich. cyblord ---- schrieb: > Der GCC z.B. erzeugt doch sehr > guten Code, mit dem Vorteil dass man sich der Funktion sehr sicher sein > kann. Ich bin auch absolut zufrieden mit den Resultaten und will das gar nicht in Abrede stellen. Ich bin mir aber genauso bewusst, dass das ein erfahrener Assembler-Programmierer mit genug Zeit in den meisten Fällen wohl besser hin bekommt. cyblord ---- schrieb: > sondern das Vermeiden von mehr > oder weniger offensichtlicher Verschwendung reicht meist schon aus. Und > das geht in C genauso. Alles mit Maß und Ziel. Ja, das sehe ich auch so. Ich wollte mit obigen Beitrag nur auf den Umstand hinweisen, dass es nicht unbedingt vorteilhaft ist alles mit dem Ziel zu programmieren, dass das Resultat möglichst klein ist. Mit freundlichen Grüßen, Karol Babioch
Schöner Code bedeutet für mich, dass man den Code schnell versteht. Dafür muss er übersichtlich (Einrückungen, Klammern, Kommentare auf gleicher Höhe), einheitlich (gleiche Schreibweisen für gleiche Funktionen, nicht i == 0 und 0 == i) und verständlich (Kommentare wenn nötig, Defines statt reiner Zahlenwerte, sprechende Variablennamen) sein. Oft überfliegt man Code nur und dann ist es sehr hilfreich, wenn man einfache und komplexe Teile schnell unterscheiden kann. Kommentare helfen vor allem bei hardwarespezifischen Codeteilen (z.B.: asm(nop); // Synchronisierung der Outputs), zu viel lenkt oft vom Code ab. Muss eine Funktion aus bestimmten Gründen (Timing, Hardware...) sehr komplex umgesetzt werden, helfen Kommentare vor der Funktion (gerne im doxygen-Format). Der Quellcode von TeX soll schön sei, auch wenn ich ihn nicht wirklich verstehe (LaTeX reicht mir fast immer aus).
Mal noch was zum Thema "Selbstdokumentierend". Auch fehlerhafter Code kann "selbstdokumentierend" sein, nur eben nicht in dem Sinne funktionieren, wie er soll. Und in sich mag die Funktion, die man aus dem Code liest, durchaus schlüssig sein. Wer diesen Code reviewed, hat alle Chancen, einen Fehler nicht zu finden. Von daher ist dieses "selbstdokumentierend" ziemlich gefährlich und eher unschön. Gruss Axel
Marian B. schrieb: > Wenn man FP/Haskell kennt (also Syntax und Grundidee der Sprache bekannt > ist), ist das eine der elegantesten und verständlichsten Arten Quicksort > zu notieren... Ja, schön. Nur, wer kommt heutzutage noch in die Verlegenheit, selber quicksort notieren zu müssen. Und wie groß ist der Anteil an ähnlichen Algorithmen in einem "real life" Programm? In meinen Bastel-Hobbyprojekten gehen gefühlt 99% des Codes für die Benutzeroberfläche und Bedienerinteraktion drauf, egal, ob auf Microcontroller oder PC. Und ob sowas in Haskell auch so wunderschön anders wird, bezweifele ich mal. Aber zugegebenermassen habe ich mich mit Haskell noch nie befasst. Oliver
doppelschwarz schrieb: > Der Quellcode von TeX soll schön sei, auch wenn ich ihn nicht wirklich > verstehe (LaTeX reicht mir fast immer aus). Wen es interessiert, der kann sich hier die knapp 25.000 Zeilen anschauen: http://ctan.mirrors.hoobly.com/systems/knuth/dist/tex/tex.web
Das ist halt das Problem mit Haskell, wunderschön und völlig unbrauchbar. Hübsche Rekursionen wie bei FP üblich, ist was für den Hörsaal. In der Realität bringt einem das meist wenig. Natürlich gibts da was passendes: http://xkcd.com/1312/
Peter Dannegger schrieb: > Das Haskell sieht ja wirklich extrem anders aus, als C. > Wie sähe z.B. eine Software TX-UART in Haskell aus? So ein Software-UART ist aus mehreren Gründen keine typische Anwendung für Haskell: - Haskell-Programme laufen nicht auf ATtinies oder ähnlich kleinen Mikcrocontrollern. - Haskell ist eine reine funktionale Programmiersprache, d.h. Funktionen haben grundsätzlich keine Nebeneffekte. Da aber ohne Nebeneffekte weder I/O noch ein Zufallsgenarator möglich sind und die Sprache damit nahezu unbrauchbar wäre, wurde dieses Problem auf geniale Weise mit der Einführung so genannter Monaden umgangen, ohne dabei die "Reinheit" der Sprache anzutasten. - Die funktionale Programmierung spielt ihre Stärken vor allem bei komplexen Algorithmen und nicht so sehr der der Programmierung zeitlicher Abläufe mit viel I/O aus. Mittels der o.g. Monaden sind solche Dinge realisierbar, der entsprechende Code erhält dadurch aber eine eher imperative Struktur, wodurch einige zentrale Vorteile der funktionalen Programmierung aufgeweicht werden. - Anders als C bietet Haskell keinen direkten Zugriff auf Speicher und I/O-Register über absolute Adressen. Über externe Funktionen in C oder Assembler sind solche Zugriffe aber möglich. - Wegen der Speicherverwaltung mittels Garbage-Collection ist nur eine eingeschränkte Echtzeitfähigkeit gegeben. Trotzdem habe ich mal versucht, deinen UART-Code in Haskell umzusetzen. Es werden dabei die hardwarenahen Funktionen writeBit (beschreibt ein Bit in einem I/O-Register) und delay (wartet eine Anzahl von µs) als gegeben vorausgesetzt. Wie es guter Stil ist, habe ich den Code nach nebeneffektfreien (pure part) und monadischen Teilen (impure part) getrennt und versucht, möglichst viel von dem Code in den nebeneffektfreien Teil zu packen:
1 | import Data.Bits |
2 | |
3 | ------- pure part ------- |
4 | |
5 | -- definition of parameters |
6 | |
7 | ddrB = 0x17 |
8 | portB = 0x18 |
9 | |
10 | uartPort = portB |
11 | uartDdr = ddrB |
12 | uartBaud = 9600 |
13 | uartBit = 2 |
14 | |
15 | -- extract bits from byte and add start bit and stop bit |
16 | -- example: byte2Bits 0x23 -> [0,1,1,0,0,0,1,0,0,1] |
17 | |
18 | byte2Bits byte = [0] ++ dataBits ++ [1] |
19 | where dataBits = map ((.&. 1) . shiftR byte) [0..7] |
20 | |
21 | ------- impure part ------- |
22 | |
23 | -- send a single bit |
24 | |
25 | sendBit val = do |
26 | writeBit uartPort uartBit val |
27 | delay (1e6 / uartBaud) |
28 | |
29 | -- send a byte by applying sendBit to every bit including start and stop bit |
30 | |
31 | sendByte byte = do |
32 | writeBit uartDdr uartBit 1 |
33 | mapM_ sendBit (byte2Bits byte) |
Ich weiß, dass du Fan davon bist, Bitzugriffe als einfache Zuweisungen schreiben zu können. So etwas geht auch in Haskell. Da das '='-Zeichen aber schon für Bindungen reserviert ist, habe ich einen neuen Operator ($=) für die Bitzuweisung definiert. Hier sind die dafür erforderlichen Definitionen und entsprechend abgeänderte Varianten für sendBit und sendByte:
1 | -- define pins as pairs of port and bit |
2 | |
3 | stxd = (portB, 2) |
4 | stxdOe = ( ddrB, 2) |
5 | |
6 | -- define new infix operator $= for wrapping writeBit |
7 | |
8 | (port, bit) $= val = writeBit port bit val |
9 | |
10 | -- use $= in new variants of sendBit and sendByte |
11 | |
12 | sendBit' val = do |
13 | stxd $= val |
14 | delay (1e6 / uartBaud) |
15 | |
16 | sendByte' byte = do |
17 | stxdOe $= 1 |
18 | mapM_ sendBit' (byte2Bits byte) |
Das Ganze dient aber hauptsächlich dazu zu zeigen, dass man so etwas auch in Haskell prinzipiell realisieren kann. In der Praxis sieht die Sache wieder etwas anders aus: Plattformen, auf denen Haskell anwendbar ist, verfügen meist auch über ein Betriebssystem oder zumindest über einen Hardware-UART, so dass man codemäßig nicht so tief einsteigen muss. Selbst wenn dies nicht der Fall ist, würde man die sendByte-Funktion als C-Funktion schreiben, allein schon deswegen, um das Timing exakt einhalten zu können. cyblord ---- schrieb: > Das ist halt das Problem mit Haskell, wunderschön und völlig > unbrauchbar. Hübsche Rekursionen wie bei FP üblich, ist was für den > Hörsaal. In der Realität bringt einem das meist wenig. Das stimmt nicht. Ja, die Sprache ist exotisch. Nein, in der SPrache wird auch kommerzieller Code geschrieben. Nein, explizite Rekursionen werden auch in der FP vermieden. Sie werden meist nur dort verwendet, wo man sie auch in klassischen Sprachen verwenden würde.
cyblord ---- schrieb: > Das ist halt das Problem mit Haskell, wunderschön und völlig > unbrauchbar. Ich benutz Haskell immer mal wieder um was herauszuknobeln. z.B. welche 2 Widerst"ande benutz ich f"ur 'nen Spannungsteiler mit Verh"altnis p, Wie w"ahle ich die Bauteile f"ur einen LM5008, usw. Halt Sachen, wo man Optimieren oder Suchen muss. Ich hatte mal 'ne Freundin, die mir mit ihren Sudoku-Wahn auf die Nerven ging, dann hab ich ein Sudoku-L"osungsprogramm geschrieben, das ohne Probieren den n"achsten Schritt angab. Ich wollte das nur als Demonstration verstanden wissen, dass Sudoku mit 2 (oder waren es 3?) Regeln auf dem Niveau der Mengenlehre zu l"osen ist. In ganz 'schwierigen' F"allen hab ich dann das Programm gestartet, das Sudoku eingegeben und dann nur verraten, welches Feld als n"achstes bestimmt werden muss/kann. Leider ist das Programm versch"utt gegangen. Zu Haskell gibt's auch eine sch"one Beobachtung: sobald ein Haskell-Programm vom Typ her passt - also vom "Ubersetzer akzeptiert wird - ist es in den meisten F"allen auch korrekt. Weil die Datenstrukturen dann passen.
Mark Brandis schrieb: > MarcVonWindscooting, sei bitte mal so gut und reparier Deine > Umlaute. Die sind nicht kaputt - es gibt Systeme, die keine haben! K"onntest Du problemlos mit griechischen Buchstaben schreiben? Warum werde ich immer nur von DEUTSCHEN so angemacht?? ;-)
Mark Brandis schrieb: > MarcVonWindscooting, sei bitte mal so gut und reparier Deine > Umlaute. PS: daran erkennst Du Leute, die ein paar mehr Anschl"age pro Minute beim Programmieren haben, als Du, der sich beim Griff zur '}' den kleinen Finger auskugelt, hehe!
Ich zähle mich nicht zu den Programmierexperten, habe aber einige Projekterfahrung in C. Für mich ist schöner Code vor allem, wenn Funktionen möglichst sprechend sind und eine halbe Bildschirmseite nicht überschreiten. Dadurch ist ein Teammitglied in der Lage die Funktion zu begreifen und er kann sie selber benutzen. Am besten in einer Lib, klar. Und die Präsentation sollte einheitlich sein, aber dafür gibt es Code beautyfier. Ich habe früher mal einiges in Forth gemacht und finde die Philosophie immer noch sehr gut. Die Worte sollten möglichst auf einen Screen 64x24 passen, inklusive Stack-Kommentar. Besser noch kleiner. Genau wie in der Sprache, wo 5 wort Sätze auf einen Blick erfassbar sind und keinen Interpretationsspielraum bieten, korrekte Interpunktion vorausgesetzt.
@Bernd D. (bernd_d56) Benutzerseite >Für mich ist schöner Code vor allem, wenn Funktionen möglichst sprechend Aussagekräftig. >sind und eine halbe Bildschirmseite nicht überschreiten. Das dürfe in der Praxis nicht haltbar sein. >Dadurch ist ein >Teammitglied in der Lage die Funktion zu begreifen und er kann sie >selber benutzen. Am besten in einer Lib, klar. Dazu muss sie aber nicht auf eine halbe Bildschirmseite passen. Dazu muss man auch KEINE Sekunde den INHALT sehen, geschweige verstehen. Mann muss die FUNKTION und NUTZUNG verstehen. Wecleh Eingangsparameter ergeben welche Ausgangsparameter mit welchen Randbedingungen. >Die Worte sollten möglichst auf einen Screen 64x24 passen, inklusive >Stack-Kommentar. Wir leben nicht mehr in den frühen 80ern, die Bidlschirme sind heute "etwas" größer. 80 Spalten Zeilenlänge sind OK, 100 sind aber auch kein Problem mehr. >Besser noch kleiner. Aua. Am besten doch wieder Assembler? Nö, der Trend geht in die andere Richtung, wenn gleich es ab und an übertrieben wird. Lange, selbsterklärende Variablen und Funktionsnamen, keine kryptischen Abkürzungen.
Falk Brunner schrieb: > @Bernd D. (bernd_d56) Benutzerseite >>sind und eine halbe Bildschirmseite nicht überschreiten. > > Das dürfe in der Praxis nicht haltbar sein. > Mein Begriff von Schönheit, nicht der Projekt standard > >>Die Worte sollten möglichst auf einen Screen 64x24 passen, inklusive >>Stack-Kommentar. > > Wir leben nicht mehr in den frühen 80ern, die Bidlschirme sind heute > "etwas" größer. 80 Spalten Zeilenlänge sind OK, 100 sind aber auch kein > Problem mehr. > >>Besser noch kleiner. > > Aua. Am besten doch wieder Assembler? > Nö, der Trend geht in die andere Richtung, wenn gleich es ab und an > übertrieben wird. Lange, selbsterklärende Variablen und Funktionsnamen, > keine kryptischen Abkürzungen. Klar, es gibt Situationen, da macht eine Zerpflückung in kleinere Funktionen keinen Sinn, oder geht gar nicht, ich persönlich empfinde es einfach lesbarer. Wenn ich recht nachdenke, werde ich auch mal wieder was in FORTH machen. Damals habe ich gerne das System von Tom Zimmer benutzt und seinen Target compiler. (FPC V3.6) Damit hatte ich in der (vor)Grafik Zeit bereits Mausunterstüzung implementiert, war ganz witzig, in einer textbasierenden Anwendung eine Scrollbox zu implementieren, wo der balken abhängig vom Inhalt skaliert wurde. Das war zur Blüte der Mailboxen, ist lange her :-)
:
Bearbeitet durch User
MarcVonWindscooting schrieb: > Die sind nicht kaputt - es gibt Systeme, die keine haben! Weswegen die Alternativen oe, ae und ue erlaubt sind. Aber bis die Tex-Schreibweise es in den Duden schafft, wird es laenger gehen...
Falk Brunner schrieb: >>sind und eine halbe Bildschirmseite nicht überschreiten. > > Das dürfe in der Praxis nicht haltbar sein. > >>Dadurch ist ein >>Teammitglied in der Lage die Funktion zu begreifen und er kann sie >>selber benutzen. Am besten in einer Lib, klar. > > Dazu muss sie aber nicht auf eine halbe Bildschirmseite passen. Dazu > muss man auch KEINE Sekunde den INHALT sehen, geschweige verstehen. Mann > muss die FUNKTION und NUTZUNG verstehen. Wecleh Eingangsparameter > ergeben welche Ausgangsparameter mit welchen Randbedingungen. Das ist jetzt der Fall, dass jemand eine Bibliotheksfunktion benutzt, die als fehlerfrei angesehen werden kann. Von dieser Funktion braucht man tatsächlich nur die API-Dokumentation anzuschauen (sofern diese etwas taugt). Wie der Quellcode der Funktion aussieht, ob kurz oder lang, ob strukturiert oder dahingerotzt, ist dann völlig egal. Ein anderer Fall ist die Fehlersuche. Da bleibt einem oft nichts anderes übrig, als sich Quellcode jeder potentiell fehlerhaften Funktion anzuschauen. Insbesondere wenn der Fehler nicht leicht reproduzierbar ist, können das sehr viele Funktionen sein. Meiner Erfahrung nach steigt der Aufwand für die Fehlersuche in einer Funktion überproportional mit deren Größe, vor allem dann, wenn es sich nicht um linearen, sondern verschachtelten Code handelt. Deswegen stellt die Unterteilung größerer Funktionen in mehrere kleinere Funktionen einen Vorteil dar. Übergroße Funktionen in mehrere Einzelfunktionen zu unterteilen, ist nicht immer leicht (so wie gutes Programmieren generell nicht leicht ist). Die Schwierigkeit liegt jedoch oft gar nicht so sehr in der Unterteilung an sich, sondern in der Findung von treffenden Namen für die Einzelfunktionen. Wer aber hier Probleme hat, wird auf ähnliche Probleme stoßen, wenn er versucht, die Funktion in Prosatext zu dokumentatieren. Das Ergebnis ist dann oft entweder unvollständig oder ein ellenlanges, unpräzise formuliertes Gelaber mit umständlichen Umschreibungen von Sachverhalten, die mit etwas mehr Gehirnschmalz und einer guten Wortwahl auch deutlich knackiger erkärt werden könnten. Wer es hingegen schafft, alle verwendeten Funktionen klein und einfach zu halten und ihnen treffende Namen zu geben, wird auch ohne viel Aufwand eine saubere Dokumentation hinbekommen. Man muss sich heute bei der Funktionsgröße natürlich nicht mehr wie in Zeiten von ASCII-Terminals auf 24 Zeilen beschränken. Meiner Meinung sollten aber in C[++]-Programmen 50 Zeilen (ohne Kopfkommentar, aber einschließlich der Rumpfkommentare) nur in begründeten Ausnahmefällen überschritten werden. In VHL-Sprachen, bei denen die gleiche Funktionalität oft in deutlich weniger Zeilen ausgedrückt werden kann als in C, sollte man dieses Limit entsprechend auf die Hälfte oder noch weniger reduzieren. Um noch einmal das Beispiel Haskell heranzuziehen: In der Bibliothek Data.Graph (Datenstrukturen und Algorithmen für Graphen), die nicht gerade triviale Funktionen enthält, sind diese dank starker Unterteilung überwiegend Einzeiler. Das Maximum liegt bei 12 Zeilen, stellt aber schon eine Ausnahme dar. Gerade dadurch, dass ein großer Teil des Codes aus Funktionsnamen besteht, ist er auch ohne umfangreiche Dokumentation gut zu verstehen.
Falk Brunner schrieb: >>sind und eine halbe Bildschirmseite nicht überschreiten. > > Das dürfe in der Praxis nicht haltbar sein. Dito, komplexe state machines können sehr lang werden, ohne dass die Länge eines logischen Abschnitts mehr als vielleicht 30 oder 40 Zeilen ist. McCabe-Komplexität ist da imho eher interessanter für die Bewertung von Funktionsgrößen. Und da gibt es dann auch enorme Komplexitätswerte für... komplexe state machines. Die wollen also doch irgendwie vernünftig dokumentiert werden, ich empfehle da erstmal ein Zustandsübergangsdiagramm in der Doxygen-Doku (inline-graphviz wird ja seit ein paar Versionen unterstützt). Was bei state machines ansonsten auch gut geht, ist für jeden State eine Funktion zu haben, die die Funktion des nächsten States returned. Hat einen höhern Runtimeoverhead, ist also eher nix für Protokolldekodierer in ISRs oder ähnliche Späße. Falk Brunner schrieb: > Wir leben nicht mehr in den frühen 80ern, die Bidlschirme sind heute > "etwas" größer. 80 Spalten Zeilenlänge sind OK, 100 sind aber auch kein > Problem mehr. Dito, heute ist Speicherplatz und Bildschirmplatz kein Problem mehr und dank semantic-mode (oder anderen Autovervollständigern in anderen Editoren (es gibt andere Editoren?)) ist die Länge von Identifiern eher nebensächlich. Quack schrieb: > MarcVonWindscooting schrieb: >> Die sind nicht kaputt - es gibt Systeme, die keine haben! > > Weswegen die Alternativen oe, ae und ue erlaubt sind. Aber bis die > Tex-Schreibweise es in den Duden schafft, wird es laenger gehen... Ach mecker mal nicht so rum. Mer sin Techniker hier, die Schreibweise sinwa gewöhnt ;)
:
Bearbeitet durch User
@ Yalu X. (yalu) (Moderator) >Man muss sich heute bei der Funktionsgröße natürlich nicht mehr wie in >Zeiten von ASCII-Terminals auf 24 Zeilen beschränken. Meiner Meinung >sollten aber in C[++]-Programmen 50 Zeilen (ohne Kopfkommentar, aber >einschließlich der Rumpfkommentare) nur in begründeten Ausnahmefällen >überschritten werden. Bitte? Wie soll das denn gehen? Da kommt man ja aus den Funktionsnamen und Aufrufen gar nicht mehr raus! >In VHL-Sprachen, bei denen die gleiche Funktionalität oft in deutlich >weniger Zeilen ausgedrückt werden kann Wir reden nicht vom gleich VHDL. > als in C, sollte man dieses Limit >entsprechend auf die Hälfte oder noch weniger reduzieren. Bitte? Das geht überhaupt nicht. Das ist gerade mal EIN popeliger Prozess! Damit würde man sich Unmengen an VHDL Files und IO-Signalen an den Hals holen. Ob das so sinnvoll ist? >Funktionen enthält, sind diese dank starker Unterteilung überwiegend >Einzeiler. Das Maximum liegt bei 12 Zeilen, stellt aber schon eine >Ausnahme dar. Gerade dadurch, dass ein großer Teil des Codes aus >Funktionsnamen besteht, ist er auch ohne umfangreiche Dokumentation gut >zu verstehen. Kann ich irgendwie nicht ganz glauben. Und die Verbreitung von Haskell dürfte das untermauern.
@Marian B. (phiarc) >Dito, komplexe state machines können sehr lang werden, ohne dass die >Länge eines logischen Abschnitts mehr als vielleicht 30 oder 40 Zeilen >ist. Das ist schon was ganz anderes und das könnte ich auch unterschreiben. >Was bei state machines ansonsten auch gut geht, ist für jeden State eine >Funktion zu haben, die die Funktion des nächsten States returned. Früher(tm) hieß das "zurück gibt".
Falk Brunner schrieb: >>Funktionen enthält, sind diese dank starker Unterteilung überwiegend >>Einzeiler. Das Maximum liegt bei 12 Zeilen, stellt aber schon eine >>Ausnahme dar. Gerade dadurch, dass ein großer Teil des Codes aus >>Funktionsnamen besteht, ist er auch ohne umfangreiche Dokumentation gut >>zu verstehen. > > Kann ich irgendwie nicht ganz glauben. Und die Verbreitung von Haskell > dürfte das untermauern. Doch doch, das haut schon hin. FP/Haskell sind sehr stark an mathematische Notationen angelehnt und wenn du dir vielen Algos und Ops auf Algorithmen anschaust, sind die als Formel meist trivial und die Implementierung ist eher schwierig. In Haskell muss ich sozusagen nur die Formel hinschreiben. Falk Brunner schrieb: >>Was bei state machines ansonsten auch gut geht, ist für jeden State eine >>Funktion zu haben, die die Funktion des nächsten States returned. > > Früher(tm) hieß das "zurück gibt". :)
:
Bearbeitet durch User
Yalu X. schrieb: > Man muss sich heute bei der Funktionsgröße natürlich nicht mehr wie in > Zeiten von ASCII-Terminals auf 24 Zeilen beschränken. Meiner Meinung > sollten aber in C[++]-Programmen 50 Zeilen (ohne Kopfkommentar, aber > einschließlich der Rumpfkommentare) nur in begründeten Ausnahmefällen > überschritten werden. "Schoener Code" hat sehr viel mit der verweneten Sprache zu tun und deren Ausdrucksfaehigkeit. Bob Martins "Clean Code" Buch bezieht sich zB. auf Java, da haben Methoden im Idealfall eine Zeile Code, maximal 3-5 Zeilen und nur in Ausnahmen (switch-case zB.) mehr. Da sind dann Kommentare auch verpoent, weil sie schlechten Code dokumentieren sollen, "guter Code" wuerde sich selber dokumentieren. Mal so aus Neugier eine Frage an die C und C++ Entwickler, wie sieht es denn da mit testgetriebener Entwicklung (TDD, nicht Test-First) aus? Wird da praktiziert, oder nicht?
Kollege schrieb: > Mal so aus Neugier eine Frage an die C und C++ Entwickler, wie sieht es > denn da mit testgetriebener Entwicklung (TDD, nicht Test-First) aus? > Wird da praktiziert, oder nicht? Was keinen Test hat ist kaputt. Oder: man muss davon ausgehen, dass es nicht funktioniert, bis ein Test gegenteiliges beweist.
Falk Brunner schrieb: > @ Yalu X. (yalu) (Moderator) > >>Man muss sich heute bei der Funktionsgröße natürlich nicht mehr wie in >>Zeiten von ASCII-Terminals auf 24 Zeilen beschränken. Meiner Meinung >>sollten aber in C[++]-Programmen 50 Zeilen (ohne Kopfkommentar, aber >>einschließlich der Rumpfkommentare) nur in begründeten Ausnahmefällen >>überschritten werden. > > Bitte? Wie soll das denn gehen? Da kommt man ja aus den Funktionsnamen > und Aufrufen gar nicht mehr raus! Und? Wo ist das Problem dabei? >>In VHL-Sprachen, bei denen die gleiche Funktionalität oft in deutlich >>weniger Zeilen ausgedrückt werden kann > > Wir reden nicht vom gleich VHDL. Nein, natürlich nicht. VHL = "Very High Level" hat nichts mit HDLs zu tun (http://en.wikipedia.org/wiki/VHLL) >>Funktionen enthält, sind diese dank starker Unterteilung überwiegend >>Einzeiler. Das Maximum liegt bei 12 Zeilen, stellt aber schon eine >>Ausnahme dar. Gerade dadurch, dass ein großer Teil des Codes aus >>Funktionsnamen besteht, ist er auch ohne umfangreiche Dokumentation gut >>zu verstehen. > > Kann ich irgendwie nicht ganz glauben. Wenn nicht glauben, dann sehen: http://hackage.haskell.org/package/containers-0.2.0.1/docs/src/Data-Graph.html > Und die Verbreitung von Haskell dürfte das untermauern. Klar, die Verbreitung wird nicht nennenswert zunehmen, solange 99% der Softwareentwickler sich die Sache nicht anschauen, sondern nur ihre Vorurteile darüber verbreiten ;-)
Marian B. schrieb: > Was keinen Test hat ist kaputt. Oder: man muss davon ausgehen, dass es > nicht funktioniert, bis ein Test gegenteiliges beweist. Das klingt aber nur hoechstens nach "Test First" oder gar "Test irgendwann". Beim TDD muss der Test vor der Implementierung geschrieben werden. Welches Unit test Framework nimmt man den fuer C? WElches fuer C++? Wuerde mich mal persoenlich interessieren.
Bernd D. schrieb:
>Wenn ich recht nachdenke, werde ich auch mal wieder was in FORTH machen.
Hey, das klingt gut. Ich schreibe gerade an einem
Forth-Entwicklungssystem ( nur zum Spaß ). Da der Code noch nicht
"schöne" genug ist, spaare ich mir den Link noch.
Für was würdest Du das Forth verwenden wollen?
Kollege schrieb: > Ach ja, welche Mock Libraries werden in C++, welche in C verwendet? macht sowas nicht nur bei objektorientierten Sprachen Sinn? Da fällt C dann wohl raus. F+r C++ könnte man GMock und Boost::Test verwenden.
@ Yalu X. (yalu) (Moderator) >> Bitte? Wie soll das denn gehen? Da kommt man ja aus den Funktionsnamen >> und Aufrufen gar nicht mehr raus! >Und? Wo ist das Problem dabei? Dass es man den Aufwand hat, sehr viele Funktionen anzulegen/zu verwalten/zu kennen und in bestimmten Fällen die Performance in den Keller geht (Funktionsaufrufe kosten Zeit und RAM). >> Wir reden nicht vom gleich VHDL. >Nein, natürlich nicht. VHL = "Very High Level" hat nichts mit HDLs zu >tun (http://en.wikipedia.org/wiki/VHLL) Ah, das D hab wohl nur ich gesehen ;-) >Wenn nicht glauben, dann sehen: >http://hackage.haskell.org/package/containers-0.2.... Sagt mir rein gar nichts. >Klar, die Verbreitung wird nicht nennenswert zunehmen, solange 99% der >Softwareentwickler sich die Sache nicht anschauen, sondern nur ihre >Vorurteile darüber verbreiten ;-) Bin kein Softwerker, nur Hardwerker ;-)
Boris B. schrieb: > macht sowas nicht nur bei objektorientierten Sprachen Sinn? Da fällt C > dann wohl raus. War auch mein Verstaendnis. Boris B. schrieb: > F+r C++ könnte man GMock und Boost::Test verwenden. Danke :)
Kollege schrieb: > Marian B. schrieb: >> Was keinen Test hat ist kaputt. Oder: man muss davon ausgehen, dass es >> nicht funktioniert, bis ein Test gegenteiliges beweist. > > Das klingt aber nur hoechstens nach "Test First" oder gar "Test > irgendwann". > Beim TDD muss der Test vor der Implementierung geschrieben werden. > > Welches Unit test Framework nimmt man den fuer C? > WElches fuer C++? > > Wuerde mich mal persoenlich interessieren. Joar, bei kleinen MCU-Projekten ist der Test oft halt auch einfach ein Praxistest. Wie soll man auch effektiv 150 Zeilen Code testen, von denen 90 in ein oder zwei ISRs liegen? C++ -> Catch finde ich sehr schön und ist self-contained: github.com/philsquared/catch C -> CUnit
Yalu X. schrieb: > Klar, die Verbreitung wird nicht nennenswert zunehmen, solange 99% der > Softwareentwickler sich die Sache nicht anschauen, sondern nur ihre > Vorurteile darüber verbreiten ;-) Das könnte aber auch an den dunklen Ecken liegen. Lambda Ausdrücke in Haskel sind oft alles andere als lesbar. Typenreduktion in komplexen Programmen händisch kaum mehr nachzuvollziehen und fehlerträchtig. Freu dich mal auf die nächste FP Vorlesung, die nicht nur die Grundlagen angeht. Nein, ausser in einigen Spezialfällen und als schneller Matlab-Ersatz durch Hugs meide ich Haskel
Falk Brunner schrieb: >>Und? Wo ist das Problem dabei? > > Dass es man den Aufwand hat, sehr viele Funktionen anzulegen/zu > verwalten/zu kennen Aufwand, der sich auszahlt. Man muss es mit der Aufteilung in Teilfunktionen ja nicht übertreiben. > und in bestimmten Fällen die Performance in den Keller geht > (Funktionsaufrufe kosten Zeit und RAM). Nur, wenn der Compiler schlecht optimiert. Wird eine Funktion in mehrere Unterfunktionen unterteilt, lässt man diese üblicherweise in derselben Quelldatei, so dass dem Compiler die Möglichkeit geboten wird, sie zu inlinen. In speziellen Fällen, wo der Compiler die falsche Entscheidung trifft, kann man (zumindest beim GCC) das Inlinen auch explizit vorschreiben (oder auch verbieten).
Yalu X. schrieb: > kann man (zumindest beim GCC) das Inlinen auch explizit > vorschreiben (oder auch verbieten). Ich empfehle -Winline, dann siehst du, dass GCC inline markierte Funktionen bei weitem nicht immer tatsächlich inline nutzt. Damit der Code nicht dupliziert wird muss man natürlich entweder die Funktionen in der gleichen CU haben und dann auch static deklarieren oder LTO benutzen. Auf AVRs nutze ich schon länger LTO und bis auf eine false positive Warnung (misspelled signal handler) funktioniert das exzellent und spart tatsächlich einiges an Code, typ. 10-20 % ggü. normalen Codeerzeugung und -linken. Als Buildtool nutze habe ich für die letzten paar Projekte CMake benutzt, was hervorragend funktioniert und viel angenehmer als einfache Makefiles ist, besonders, wenn man zusätzliche Host-Builds für Unit-Tests haben möchte.
:
Bearbeitet durch User
Marian B. schrieb: > Yalu X. schrieb: >> kann man (zumindest beim GCC) das Inlinen auch explizit >> vorschreiben (oder auch verbieten). > > Ich empfehle -Winline, dann siehst du, dass GCC inline markierte > Funktionen bei weitem nicht immer tatsächlich inline nutzt. Ja, das Schlüsselwort inline hat i.Allg. wenig Wirkung. Ich bezog mich oben aber auf den GCC. Dort gibt es die Attribute noinline und always_inline, und die funktionieren immer.
Achso, ja. Die dann aber besser mit einem #define genießen, man möchte doch nicht unbedingt allen Code an einen Compiler binden...
Maxx schrieb: > Yalu X. schrieb: >> Klar, die Verbreitung wird nicht nennenswert zunehmen, solange 99% der >> Softwareentwickler sich die Sache nicht anschauen, sondern nur ihre >> Vorurteile darüber verbreiten ;-) > > Das könnte aber auch an den dunklen Ecken liegen. > Lambda Ausdrücke in Haskel sind oft alles andere als lesbar. Wie oft werden in Haskell Lambda-Ausdrücke verwendet? Durch partial Evaluation (auch bei Infix-Operatoren) kommt man sehr oft um die Lambdas herum. Und in allen anderen Fällen ist es einem freigestellt, anstelle des Lambdas eine Funktion mit Namen zu definieren, sofern man kein Feind von Funktionsnamen ist ;-) > Typenreduktion in komplexen Programmen händisch kaum mehr > nachzuvollziehen und fehlerträchtig. Was meinst du genau damit? Hast du ein Beispiel? > Freu dich mal auf die nächste FP Vorlesung, die nicht nur die Grundlagen > angeht. Hmm, Vorlesungen besuche ich schon seit Ewigkeiten nicht mehr. Habe ich da vielleicht etwas verpasst? Ich bin zwar kein Haskell-Gott, mir aber der Nachteile dieser Sprache durchaus bewusst. Deswegen würde ich auch nie C oder Python von meiner Platte löschen. Assembler, C, Python und Haskell sind einfach vier völlig unterschiedliche, aber IMHO gleichberechtigte Wege, Softwareentwicklung anzugehen. Welcher der bestgeeignete ist, hängt – wie so oft – vom Anwendungsfall ab.
Yalu X. schrieb: > Ich bin zwar kein Haskell-Gott, mir aber der Nachteile dieser Sprache > durchaus bewusst. Jede Sprache hat immer irgendwo Nachteile. > Deswegen würde ich auch nie C oder Python von meiner > Platte löschen. Assembler, C, Python und Haskell sind einfach vier > völlig unterschiedliche, aber IMHO gleichberechtigte Wege, > Softwareentwicklung anzugehen. Fehlt nur noch das Prolog-Paradigma, in dem man nicht mehr beschreibt, wie man zu einer Lösung kommt, sondern welche Eigenschaften die Lösung haben soll. Es gibt eben mehr als nur eine Art, einer Katze das Fell über die Ohren zu ziehen. Auch wenn es 'die perfekte Sprache' oder auch 'das perfekte Paradigma' nicht gibt, so schadet ein Blick über den Tellerrand nicht. Man kann dabei nur lernen und gewinnen.
:
Bearbeitet durch User
Schöner Code sind funktionierende , gut dokumentierte und strukturierte, kurze Assemblerzeilen die möglichst oft wiederverwendet werden und die gebotenen Features/Eigenschaften des Controllers bestmöglich und hochoptimiert be- und ausnutzen. Manch ein hauptberuflicher Programmierer weiß gar nicht was sein hochsprachenvollgepfropfter Controller dann eigentlich leisten könnte. Denn leider steht da Produktivität an erster Stelle und natürlich ist klar, daß sich diese Sicht der Dinge nur ein Hobbyist mit viel Zeit leisten kann :)
Moby schrieb: > Schöner Code sind funktionierende , gut dokumentierte und strukturierte, > kurze Assemblerzeilen die möglichst oft wiederverwendet werden und die > gebotenen Features/Eigenschaften des Controllers bestmöglich und > hochoptimiert be- und ausnutzen. Manch ein hauptberuflicher > Programmierer weiß gar nicht was sein hochsprachenvollgepfropfter > Controller dann eigentlich leisten könnte. Ui. Das stimmt so nicht. Es gibt zwar Ausnahmen, aber in den meisten Fällen bewegt sich der Overhead durch eine Hochsprache im kleinen einstelligen Prozentbereich. Wahre Geschwindigkeitszuwachs-Orgien durch die Verwendung von Assembler sind nur ganz selten zu erwarten. Den meisten Zuwachs gewinnt man immer noch durch gute Algorithmen und nicht durch die Wahl der Programmiersprache. > Denn leider steht da Produktivität an erster Stelle und natürlich > ist klar, daß sich diese Sicht der Dinge nur ein Hobbyist mit viel > Zeit leisten kann Er kann es sich vor allen Dingen leisten, all die kleinen lästigen Fehler zu suchen, von denen ihn der Einsatz eines Compilers befreit hätte und die er nur deswegen hat, weil er auf zuviele Dinge gleichzeitig achten muss.
:
Bearbeitet durch User
Marian B. schrieb: > static deklarieren > oder LTO benutzen. Ich will eure Diskussion nicht unterbrechen, aber: Was bedeutet "LTO" in diesem Zusammenhang?
Ergänzung: Hab's gefunden: http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html Ignoriert meine Anfrage.
Das tolle an LTO ist einfach, dass der Compiler das gesamte Programm (bei MCUs also alles was auf der Kiste läuft) so optimieren kann, als wäre alles in einer CU. Nicht aufgerufene Funktionen können komplett ausgelassen werden, es wird nur gelinkt, was wirklich benutzt wird. Inlining klappt plötzlich auch über CU-Grenzen hinweg, der Optimierer kann Funktionen an ihre Call-Sites in anderen CUs anpassen usw. usf. Sehr tolle Technik, hat auch noch einiges an Potenzial.
@ Moby (Gast) >Schöner Code sind funktionierende , gut dokumentierte und strukturierte, >kurze Assemblerzeilen die möglichst oft wiederverwendet werden und die >gebotenen Features/Eigenschaften des Controllers bestmöglich und >hochoptimiert be- und ausnutzen. Ja, nennt sich C ;-)
@ Falk von Assemblerzeilen war doch die Rede. Kurz & knapp 1:1 schnörkellos ehrlich das beschreibend was tatsächlich passiert (oder angestoßen wird) und damit auch genau das was nötig für eine Aufgabe. Keine Compilereigenheiten, keine Hochsprachen-Eigenheiten, nichts was da reinregiert. Transparent und durchsichtig. Das hat Charme! Karl Heinz schrieb: > Es gibt zwar Ausnahmen, aber in den meisten Fällen bewegt sich der > Overhead durch eine Hochsprache im kleinen einstelligen Prozentbereich. Das mag ich so nicht glauben. Selbst wenn macht das "schönen Code" doch weniger schön. Karl Heinz schrieb: > Er kann es sich vor allen Dingen leisten, all die kleinen lästigen > Fehler zu suchen, von denen ihn der Einsatz eines Compilers befreit Ja, anfangs ist mit Asm ob der Fehlerchen schon eine erhebliche Frustrationstoleranz vonnöten und Durchbeißen angesagt. Mit den Jahren kann man lernen worauf es ankommt- dank einer einfachen Controllerstruktur und der Konzentration auf nur eine Controller-Familie bzw. wenige Typen daraus.
Moby schrieb: > Das mag ich so nicht glauben. Selbst wenn macht das "schönen Code" doch > weniger schön. Die wenigsten Programme bestehen aus 300 hintereinander aufgeschriebenen
1 | PORTC |= ( 1 << PC0 ); |
Das dieses weniger schön ist, als ein entsprechender Assembler-SBI gestehe ich dir gerne zu. Aber spätestens wenn die Programme dann (nur wenig) komplexer werden und auch das Thema Datenstrukturen zu seinem Recht kommt, dreht sich das ganz schnell um.
Moby schrieb: > Keine Compilereigenheiten, keine Hochsprachen-Eigenheiten, nichts > was da reinregiert. Transparent und durchsichtig. Das hat Charme! Der Charme verfliegt aber sehr schnell, wenn man den gleichen Code auf verschiedenen Prozessoren laufen lassen möchte. Die Portierbarkeit lässt bei Assembler nun mal stark zu wünschen übrig.
Moby schrieb: > von Assemblerzeilen war doch die Rede. Kurz & knapp 1:1 schnörkellos > ehrlich das beschreibend was tatsächlich passiert (oder angestoßen wird) > und damit auch genau das was nötig für eine Aufgabe. Keine > Compilereigenheiten, keine Hochsprachen-Eigenheiten, nichts was da > reinregiert. Transparent und durchsichtig. Das hat Charme! Aber haufenweise plattform- und prozessoreigenheiten, die nirgends im Code stehen. Und Assembler ist einfach der Teufel, wenn es auch nur an ... naja ich will gar nicht komplex sagen, wenn es schon an irgendwelche Datenstrukturen geht, wird es arg nervig. Schon ein simpler B+-Baum ist in Assembler nervig zu implementieren, "komplexe" Datenstrukturen wie einfache on-disk formate ala FAT würde ich als praktisch nicht mehr machbar und wartbar einstufen.
:
Bearbeitet durch User
chris_ schrieb: > Bernd D. schrieb: >>Wenn ich recht nachdenke, werde ich auch mal wieder was in FORTH machen. > > Hey, das klingt gut. Ich schreibe gerade an einem > Forth-Entwicklungssystem ( nur zum Spaß ). Da der Code noch nicht > "schöne" genug ist, spaare ich mir den Link noch. > Für was würdest Du das Forth verwenden wollen? Schönheit liegt immer im Auge des Betrachters. in FORTH war die "Schönheit" in den Anfängen durch den Screen bedingt. Ich habe meinen Brodie gelesen und aufgesogen. Ich kann auch anderen Code lesen, nur schön ist halt etwas anderes. Low Level Forth ist ja nun auch nicht unbedingt schön, sondern wimmelt vor Sonderzeichen, die oberen Ebenen allerdings lesen sich fast wie ein Gedicht, oder eine Anleitung. Das mir da nicht Jeder zustimmt, ist mir klar. Ein kleines Hobby Projekt hatte ich top->down geschrieben, also wirklich mir sinnvolle Wörter ausgesucht und überlegt wie ich den Stank organisiere und dann halt immer tiefer. Wörter die noch nicht fertig waren packeten eben testwerte auf den Stck, damit kann man dem Kunden (mein Kumpel, damals) schon ein Layout zeigen, heute nennt sich das Rapid Prototyping oder auch nicht, keine Ahnung, habe schon etliche Jahre nichts mehr gemacht, in der Richtung. @OP Chris_ Schade, dass du nicht angemeldet bist, ich könnte dir ein paar Sachen erzählen über die nächsten kleinen Projekte. Da es aber 1. noch nicht ausgereift ist, 2. noch länger dauert bis ich anfangen kann, will ich 3. nichts darüber im öffentlichen Bereich darüber schreiben. Zur Verwendung von FORTH nur soviel: Ich finde es erfrichend und produktiv, wenn man sagen wir Elektornik mit Mechanik kombinieren muss und der Feinschliff direkt am laufeneden Objekt mit hilfe eine Terminalprogramms erfolgen kann. Forth ist in den meisten Erscheinugsformen nunmal interaktiv und erlaubt Debuggen, modifizieren von Parameter ad Hoc. Es gab (gibt?) auch Interactiv-C, das habe ich auf einem Handyboard(68HC11) eingesetzt, das war schon genial, es war sogar Multitasking möglich. Aber das geht mit Forth auch, man muss nur mit dem richtigen anfangen, das wirds dann schwierig, sehr viele Möglichkeiten und immer nur eine kleine Community. FORTH hat den Ruf DAS System für Eigenbrödler zu sein, ich finde da ist was dran.
Sch"oner Code ist auch, wenn man mal lieber einen Generator schreibt, als auf biegen und brechen alles von Hand zu machen. Siehe z.B. iocon.h in der Anlage. Tool unionize.pl (Perl script - obwohl das eher eine Hassliebe ist). Zur Info: das Registerfile von IOCON hat L"ucken und manche Sachen sind an der gleichen Adresse (=Offset in Iocon). Ach ja, unionized.h enth"alt ein (leeres) Makro: #define unionized Zeilen mit 'unionized' sind vom Generator erzeugt, nicht vom Programmierer. Es k"onnte irgendein anderes Buchstabenmuster sein, ich habs halt so gew"ahlt. Der Programmierer schreibt nur die //.0x... Adresse und in der n"achsten Zeile den Typ und Feldnamen. Der Rest wird vom Generator erzeugt. 'In Place' sozusagen, d.h. der Quelltext wird von Generator erweitert. Wendet man ihn nochmal drauf an, "andert sich das Resultat nicht mehr - Fixpunkt. ununionize.pl ist der inverse Generator, er entfernt alles Generierte. Vergleicht das Ergebnis mal mit der Entsprechung von 'Code Red' oder sonst einem x-beliebigen professionellen Anbieter. F"allt euch da was auf? Lesbarkeit, Dokumentation, ...
"Ahm vergessen: nat"urlich finde ich Perl-Code generell unsch"on, unleserlich, selbst wenn er von mir ist. Und 'c-lpc8' (die vielleicht sch"onste uC-Bibliothek der Welt...:))) habe ich noch nicht ver"offentlicht - braucht also niemand zu suchen.
Mark Brandis schrieb: > Der Charme verfliegt aber sehr schnell, wenn man den gleichen Code auf > verschiedenen Prozessoren laufen lassen möchte. Die Portierbarkeit lässt > bei Assembler nun mal stark zu wünschen übrig. Deswegen ja Festlegung auf wenige Typen. Ein Xmega z.B. erschlägt jeden denkbaren Anwendungsfall den ich mir vorstellen kann und der ist quasi meine "Standardhardware". Marian B. schrieb: > Aber haufenweise plattform- und prozessoreigenheiten, die nirgends im > Code stehen. Erübrigt sich mit der gleichen Begründung. Marian B. schrieb: > "komplexe" Datenstrukturen wie > einfache on-disk formate ala FAT wird von mir einfach an passende Hardware ausgelagert (z.B. Vinculum). Was Datenstrukturen als solche angeht sind wohl die von mir verwendeten nicht kompliziert genug :) Überhaupt, wenn man seine Codebasis über Jahre aufbaut dann sind irgendwann alle Standardaufgaben (Initialisierung, Schnittstellen-Routinen) gleich einer Hochsprache in 0,nix zusammenkopiert. Möchte jetzt hier niemandem Asm als das non plus ultra verkaufen aber mal aufzeigen, daß sich mit System und Überlegung so durchaus genausoviel nützlicher und auch schöner Code produzieren lässt!
Moby schrieb: > Mark Brandis schrieb: >> Der Charme verfliegt aber sehr schnell, wenn man den gleichen Code auf >> verschiedenen Prozessoren laufen lassen möchte. Die Portierbarkeit lässt >> bei Assembler nun mal stark zu wünschen übrig. > > Deswegen ja Festlegung auf wenige Typen. Ein Xmega z.B. erschlägt jeden > denkbaren Anwendungsfall den ich mir vorstellen kann und der ist quasi > meine "Standardhardware". > > Marian B. schrieb: >> Aber haufenweise plattform- und prozessoreigenheiten, die nirgends im >> Code stehen. > > Erübrigt sich mit der gleichen Begründung. Gut, du kannst dir wohl nicht sonderlich viel vorstellen.
Vermutlich :) Auf jeden Fall ist es sehr angenehm, ohne Zeitdruck fürs Hobby entwickeln zu können- und da kommt dann durchaus mal sehr sehr schöner Code bei raus.
Hallo, ich möchte gerne zwei Sprachen erwähnen, die für mich persönlich dazu neigen „schönen” Code zu produzieren. ELAN ist eigentlich so gut wie tot, habe ich vor über 30 Jahren mal benutzt, aber bis heute fesselt mich, wie schön die Programme waren. In ELAN geschrieben sah irgendwie jedes Problem so trivial aus, wirklich nett. Man konnte Funktionen und Operatoren überladen und es gab auch schon Pakete, aber ich glaube der Trick war ein anderer: Vielleicht hat es was mit den Refinements in ELAN zu tun? Ein Refinement ist eine Art Makro oder inline Funktion ohne Parameter und ohne zusätzliche Syntax (wie Klammern etc). Es hat aber scope. Ein Refinement, das in einer Prozedur definiert wird, ist nur dort sichtbar, ein Refinement, dass in einem Refinement definiert wird, auch nur dort u.s.w. Eine zweite witzige Sache waren glaube ich, die Leerzeichen, ich meine, dass Leerzeichen in Bezeichnen erlaubt waren! (Dafür waren andere Dinge verboten) Man könnte also zum Beispiel schreiben (Bitte nicht festnageln, ist extrem lange her): ..... INT CONST es geht nach oben := 1; INT CONST es geht nach unten := 0; INT VAR richtung := es geht nach unten; SELECT richtung OF CASE es geht nach oben: jetzt runterzaehlen; CASE es geht nach unten: jetzt raufzaehlen; END SELECT jetzt runterzaehlen: if (++pwm == TIMER1_TOP) richtung = es geht nach unten; jetzt raufzaehlen: if (--pwm == 0) richtung = es geht nach oben; ....... Mit Kommentaren erreicht man etwas vergleichbares, aber so hat es irgendwie etwas poetisches. Naja, hat sich jedenfalls erledigt, ich glaube nicht, dass noch mehr als einige dutzend ELAN-Programme im aktiven Dienst sind :-) vlg Timm
Hallo, die andere Sprache, die ich „hübsch” finde ist modernes Objektive-C. Hmm, ist jetzt ein bisschen schwierig, soll ja kein Schwanzvergleich sein, so a la meine Sprache ist besser weil ... Andererseits ist der Reiz so ganz ohne Features auch schwer zu transportieren. Also vielleicht meinte Top-5 ? 1. Message Syntax [Objekt methode]; Ich finde diese Schreibweise mit den eckigen Klammern irgendwie sehr schön, sieht doch richtig aus, als ob eine Nachricht an das Objekt geschickt wird. (Punkt sind übrigens auch erlaubt, rufen automatisch den getter bzw. setter auf, je nachdem ob lvalue) 2. Benannte Argumente [array insertObject:obj atIndex:index]; Argumente sind immer benannt, die Reihenfolge ist immer egal (klar, außer dem ersten, das ist der Name der Methode :-) ) 3. Deklaration und Definition von Klassen Deklaration (@interface) und Definition (@implementation) haben unterschiedliche Schlüsselwörter @interface CustomNSApplication : NSApplication @end @implementation CustomNSApplication - (void) setMainMenu: (NSMenu*) menu { // mach was } @end 4. Getters und Setters für gewöhnliche Member-Variablen können voll automatisch und sprechend erzeugt werden: deklariere ich MyClass mit einem Member "myProperty" @interface MyClass @property (nonatomic, retain) NSString* myProperty; @end kann ich in der Implementierung einfach sagen: @implementation MyClass @synthesize myProperty; @end und es werden automatisch Getter und Setter (in diesem Fall nicht thread safe (nonatomic) und nicht tief kopierend (retain) erzeugt) Ich finde das „schön”, weil das Code durch Beschreibung ersetzt und das auf einen Blick: nonatomic, retain. Alles klar. 5. Schöne Konstrukte aus anderen Sprachen, zum Beispiel ein for in für Enumerationen: for (id object in someArray) ; 6. Ziemlich verrückte Dinge, die durch die Laufzeitumgebung und das späte Binden möglich werden, die ich jetzt aber nicht aufzähle weil sie zwar hübsch aber doch eher Feature-Artig sind. vlg Timm
Timm Reinisch schrieb: > 2. Benannte Argumente > > [array insertObject:obj atIndex:index]; Volle Zustimmung. Das ist auch der Grund, warum ich mir nicht vorstellen kann, in Standard C zu programmieren anstatt in C99. Realwelt-Beispiel aus einer kleinen Temperatursteuerung im Haus:
1 | typedef struct { |
2 | bool tControl; ///< heater switched by temperature. |
3 | int tOnF1024; |
4 | int tOffF1024; |
5 | } Config; |
6 | |
7 | static Config config = { |
8 | .tOnF1024 = 282<<10, // Kelvin |
9 | .tOffF1024 = 284<<10, // Kelvin |
10 | };
|
So richtig Sinn machts dann, wenn man ein paar Werte auf 0 lassen will und sich sozusagen wenige Werte explizit rauspickt.
Marian B. schrieb: > Ich könnte mich ja an dieses ständige NS überall nicht gewöhnen :-) Wieso? Ist doch schon "uber 60Jahre her!
Deutscher Geschichtsunterricht wirds wohl sein. Marc P. schrieb: > Volle Zustimmung. > Das ist auch der Grund, warum ich mir nicht vorstellen kann, in Standard > C zu programmieren anstatt in C99. Realwelt-Beispiel aus einer kleinen > Temperatursteuerung im Haus: Für C++ kann man die nachrüsten, finde ich bei Java z.B. Schade, dass das nicht geht. Würde aber vielleicht auch nicht zum minimalistischem Sprachkonzept von Java passen. In Python finde ich kwargs auch sehr angenehm...
Marc P. schrieb: > Marian B. schrieb: >> Für C++ kann man die nachrüsten > > Hmm? Wie denn? Ich bin nicht up-to-date. Der Trick ist, dass es nur so aussieht wie benannte Parameter. Man definiert Instanzen einer Klasse mit assignment op auf den gewünschten Parametertyp im Scope der Funktion und schreibt dann einfach mit dem Instanznamen ein Assignment hin, der Assignment operator gibt dann einfach den Parameter rein. Ist seit ner Weile in Boost drin, gibt aber auch unabhängige Implementierungen: http://www.boost.org/doc/libs/1_55_0/libs/parameter/doc/html/index.html Anbei kann ich Andrzej's C++ Blog sehr empfehlen: http://akrzemi1.wordpress.com/
>Zur Verwendung von FORTH nur soviel: >Ich finde es erfrichend und produktiv, wenn man sagen wir Elektornik mit >Mechanik kombinieren muss und der Feinschliff direkt am laufeneden >Objekt mit hilfe eine Terminalprogramms erfolgen kann. >Forth ist in den meisten Erscheinugsformen nunmal interaktiv und erlaubt >Debuggen, modifizieren von Parameter ad Hoc. Hi Bernd, hier habe ich mal einen eigenen Thread für das Forth aufgemacht: Beitrag "flexibles Forth mit VM" Vielleicht finden sich ja ein paar Leute, die darüber diskutieren wollen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.