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?
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. ;-)
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
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
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:
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.cFalk 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:
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;)
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.htmlinnerand 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.
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 ;-)
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?"
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
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
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
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 :-)
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 ;)
@ 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".
:)
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.
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.
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.
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.
Marian B. schrieb:> static deklarieren> oder LTO benutzen.
Ich will eure Diskussion nicht unterbrechen, aber: Was bedeutet "LTO" in
diesem Zusammenhang?
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.
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
typedefstruct{
2
booltControl;///< heater switched by temperature.
3
inttOnF1024;
4
inttOffF1024;
5
}Config;
6
7
staticConfigconfig={
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.
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.