Forum: Mikrocontroller und Digitale Elektronik schöner Code ?


von chris_ (Gast)


Lesenswert?

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?

von Coder (Gast)


Lesenswert?

Naja, schöner Code ist Code, den du nach einem Jahr auch noch verstehst.

von chris (Gast)


Lesenswert?

in welcher sprache meinste denn??

von Falk B. (falk)


Lesenswert?

@ 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

von 12V DC (Gast)


Lesenswert?

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. ;-)

von Tim  . (cpldcpu)


Lesenswert?


: Bearbeitet durch User
von Kaj (Gast)


Lesenswert?

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

von Roland .. (rowland)


Lesenswert?

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]

von Roland .. (rowland)


Lesenswert?

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

von Pink S. (pinkshell)


Lesenswert?


von Yalu X. (yalu) (Moderator)


Lesenswert?

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

von Pink S. (pinkshell)


Lesenswert?

Ein normaler Mensch blickt durch Dein Beispiel nicht durch.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Was ist ein normaler Mensch? :)

von Rolf Magnus (Gast)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von H.Joachim S. (crazyhorse)


Lesenswert?

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)

von innerand i. (innerand)


Lesenswert?

Schöner Code ist ganz einfach gut lesbar und leicht verständlich.

von Peter D. (peda)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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

von Yalu X. (yalu) (Moderator)


Lesenswert?

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
von chris_ (Gast)


Lesenswert?

> quicksort []           = []

Bleibt für mich noch die Frage: Welche Programmiersprache? Ich kenne den 
Syntax auch nicht.

von innerand i. (innerand)


Lesenswert?

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;)

von Yalu X. (yalu) (Moderator)


Lesenswert?

chris_ schrieb:
> Bleibt für mich noch die Frage: Welche Programmiersprache? Ich kenne den
> Syntax auch nicht.

Hab ich ganz vergessen: Haskell.

von Peter (Gast)


Lesenswert?

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

von Michael_ (Gast)


Lesenswert?

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 :-) .

von Mark B. (markbrandis)


Lesenswert?

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
von chris_ (Gast)


Lesenswert?

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.

von Udo S. (urschmitt)


Lesenswert?

Schöner Code ist der Code, den ich nicht schreiben muss.

von MarcVonWindscooting (Gast)


Lesenswert?

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 ;-)

von Peter D. (peda)


Lesenswert?

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?

von Karol B. (johnpatcher)


Lesenswert?

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
von chris_ (Gast)


Lesenswert?

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
}

von Marian (phiarc) Benutzerseite


Lesenswert?

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...

von Karol B. (johnpatcher)


Lesenswert?

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/

von Marian (phiarc) Benutzerseite


Lesenswert?

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.)

von Peter D. (peda)


Lesenswert?

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.

von MarcVonWindscooting (Gast)


Lesenswert?

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.

von MarcVonWindscooting (Gast)


Lesenswert?

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...

von chris_ (Gast)


Lesenswert?

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.

von Karol B. (johnpatcher)


Lesenswert?

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
von Cyblord -. (cyblord)


Lesenswert?

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.

von Karol B. (johnpatcher)


Lesenswert?

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

von doppelschwarz (Gast)


Lesenswert?

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).

von Axel (Gast)


Lesenswert?

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

von Oliver (Gast)


Lesenswert?

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

von Mark B. (markbrandis)


Lesenswert?

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

von Cyblord -. (cyblord)


Lesenswert?

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/

von Mark B. (markbrandis)


Lesenswert?


von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von MarcVonWindscooting (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

MarcVonWindscooting, sei bitte mal so gut und reparier Deine Umlaute.

von MarcVonWindscooting (Gast)


Lesenswert?

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?? ;-)

von MarcVonWindscooting (Gast)


Lesenswert?

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!

von Bernd D. (Firma: ☣ ⍵ ☣) (bernd_d56) Benutzerseite


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@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.

von Bernd D. (Firma: ☣ ⍵ ☣) (bernd_d56) Benutzerseite


Lesenswert?

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
von Quack (Gast)


Lesenswert?

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...

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Marian (phiarc) Benutzerseite


Lesenswert?

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
von Falk B. (falk)


Lesenswert?

@ 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.

von Falk B. (falk)


Lesenswert?

@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".

von Marian (phiarc) Benutzerseite


Lesenswert?

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
von Kollege (Gast)


Lesenswert?

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?

von Marian (phiarc) Benutzerseite


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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 ;-)

von Kollege (Gast)


Lesenswert?

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.

von Kollege (Gast)


Lesenswert?

Ach ja, welche Mock Libraries werden in C++, welche in C verwendet?

von chris_ (Gast)


Lesenswert?

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?

von Borislav B. (boris_b)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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 ;-)

von Kollege (Gast)


Lesenswert?

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 :)

von Marian (phiarc) Benutzerseite


Lesenswert?

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

von Maxx (Gast)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


Lesenswert?

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).

von Marian (phiarc) Benutzerseite


Lesenswert?

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
von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Marian (phiarc) Benutzerseite


Lesenswert?

Achso, ja. Die dann aber besser mit einem #define genießen, man möchte 
doch nicht unbedingt allen Code an einen Compiler binden...

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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
von Moby (Gast)


Lesenswert?

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 :)

von Karl H. (kbuchegg)


Lesenswert?

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
von Walter Tarpan (Gast)


Lesenswert?

Marian B. schrieb:
> static deklarieren
> oder LTO benutzen.

Ich will eure Diskussion nicht unterbrechen, aber: Was bedeutet "LTO" in 
diesem Zusammenhang?

von Walter Tarpan (Gast)


Lesenswert?

Ergänzung: Hab's gefunden:
http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
Ignoriert meine Anfrage.

von Marian (phiarc) Benutzerseite


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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 ;-)

von Moby (Gast)


Lesenswert?

@ 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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von Marian (phiarc) Benutzerseite


Lesenswert?

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
von Bernd D. (Firma: ☣ ⍵ ☣) (bernd_d56) Benutzerseite


Lesenswert?

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.

von MarcVonWindscooting (Gast)


Angehängte Dateien:

Lesenswert?

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, ...

von MarcVonWindscooting (Gast)


Lesenswert?

"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.

von Moby (Gast)


Lesenswert?

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!

von Marian (phiarc) Benutzerseite


Lesenswert?

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.

von Moby (Gast)


Lesenswert?

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.

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

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

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

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

von Marian (phiarc) Benutzerseite


Lesenswert?

Ich könnte mich ja an dieses ständige NS überall nicht gewöhnen :-)

von Marc P. (marcvonwindscooting)


Lesenswert?

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.

von Marc P. (marcvonwindscooting)


Lesenswert?

Marian B. schrieb:
> Ich könnte mich ja an dieses ständige NS überall nicht gewöhnen :-)

Wieso? Ist doch schon "uber 60Jahre her!

von Marian (phiarc) Benutzerseite


Lesenswert?

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...

von Marc P. (marcvonwindscooting)


Lesenswert?

Marian B. schrieb:
> Für C++ kann man die nachrüsten

Hmm? Wie denn? Ich bin nicht up-to-date.

von Marian (phiarc) Benutzerseite


Lesenswert?

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/

von chris_ (Gast)


Lesenswert?

>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
Noch kein Account? Hier anmelden.