Forum: Compiler & IDEs C designen lernen


von RestInPieces (Gast)


Lesenswert?

Hallo,

mit folgendem Problem schlage ich mich nun schon seit einiger Zeit 
herum. Ich  beginne ein Gcc Projekt schreibe die ersten funktionen, 
alles prima. Über kurz oder lang wird das ganze aber so unübersichtlich, 
dass der aufwand um weiter funktionen einzubauen zu groß wird und ich 
das Projekt unfertig stehen lasse.

Die Lösung ist denke das Projekt von vornherein zu planen anstatt 
einfach drauf los zu programmieren. Nur hab ich keine Ahnung wie ich 
sowas anfange. Gibt es Tutorials oder Bücher die einen an die Hanmd 
nehmen? Wie macht ihr das bzw wie habt ihr das gelernt?

von Opamp (Gast)


Lesenswert?

Bücher kenne ich leider keine.

Hier jedoch einige Tips für C (nicht C++):

- möglichst viele Funktionen

- Eine Funktion sollte möglichst kurz sein, idealerweise auf einen 
Bildschirm passen

- Benennung von Variablen und Funktionen sind meiner Meinung nach sehr 
wichtig, man sollte auf den ersten Blick am Namen erkennen können um was 
es nich handelt. Ungarische Notation (oder sowas ähnliches, je nach 
Vorliebe) kann auch nicht schaden.

- Die Funktionen und Variablen nach logischen Einheiten in einzelnen .c 
und .h Dateien zusammenfassen

- Schnittstellen zwischen den Logischen Einheiten möglichst klein halten 
(Schnittstelle: Funktionen und Variablen im .h file die von anderen .c 
Dateien benutzt werden)

- hier und da kann Kommentar nicht schaden

- Pattern init/run/done verwenden, auch für Sub-Module

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


Lesenswert?

RestInPieces schrieb:
> Wie macht ihr das bzw wie habt ihr das gelernt?

Top-Down-Entwurf:

Man skizziert zuerst die grobe Funktion (top-level), wobei die
tatsächliche Implementierung einfach mal noch nicht bekannt ist,
sondern als black box (Funktion ohne Inhalt) stehen bleibt.  Bei
einem größeren Projekt kann dann jeder Funktionsblock in einer
Datei stehen, bei einem kleineren Projekt genügt oft auch eine
einzige Datei.

Bottom-Up-Entwurf:

Man implementiert zuerst die Funktionalität einzelner Blöcke, und
testet diese jeweils separat mit einem eigenen Szenario.  Danach
führt man alle diese Funktionsblöcke in einem Gesamtprojekt zusammen.
Ist etwas schwieriger als top-down, weil man natürlich schon eine
grundlegende Idee über die Schnittstellen der Funktionsblöcke nach
oben haben muss, bevor man die Schicht darüber tatsächlich
implementiert hat.

von Falk B. (falk)


Lesenswert?


von High Performer (Gast)


Lesenswert?

>möglichst viele Funktionen

Das steht zwar in allen Lehrbüchern zum Thema so geschrieben, aber ich 
stehe dieser Pauschalaussage inzwischen nicht mehr ganz unkritisch 
gegenüber.
IMO kann die immer weiter verringerte Komplexität und Länge einer 
Funktion/Methode die Komplexität des Gesamtsystems deutlich erhöhen. Man 
sollte also die Funktionalität mit Verstand auf 
Klassen/Methoden/Funktionen aufteilen und nicht mit der 
Lehrbuch-Holzhammermethode. Und man braucht auch kein schlechtes Gefühl 
zu haben, falls eine Methode mal ein wenig länger als die beschriebene 
Bildschirmseite wird. Just my 2 cents.

von flash gordon (Gast)


Lesenswert?

RestInPieces schrieb:
> Die Lösung ist denke das Projekt von vornherein zu planen anstatt
> einfach drauf los zu programmieren. Nur hab ich keine Ahnung wie ich
> sowas anfange. Gibt es Tutorials oder Bücher die einen an die Hanmd
> nehmen? Wie macht ihr das bzw wie habt ihr das gelernt?

ich ändere manchmal bestimmte Abschnitte meines Programmes komplett um, 
nur um dann festzustellen, dass es Quatsch war. Ich arbeite Aktiv an 
meinem Code, um ihn zu verbessern. Versuche möglichst alle Programme so 
zu schreiben, dass sie jederzeit abänderbar sind, so wie du sie 
brauchst. Halte deinen Code so kurz wie möglich. Das erspart dir 
Tipparbeit, wenn du Änderungen vornimmst (Lieber einmal Gedanken über 
ein Array oder eine Klassendefinition gemacht, als 5 mal je 100 
Konstanten abändern zu müssen) Versuche Parameter getrennt und 
übersichtlich zu speichern. Lege Variablen dort an, wo sie auch 
gebraucht werden und initialisiere sie korrekt. Finde einen Kompromiss 
aus Länge und Sinnhaftigkeit deiner Variablenbezeichnungen, separiere 
namen mit _ (zB main_control_grid). Bastle abgeschlossene Funktionen, 
die möglichst nicht auf globale Variablen zurückgreifen.

Bastle dir Scripten, die ein schnelles kompilieren und testen deiner 
Programme ermöglichen.

Versuche jede Compilerwarnung oder Fehler auszumerzen und zwar von der 
Wurzel aus

Überlege bevor du tippst.
Überlege nachdem du getippt hast, ob es gut war.
Scheue nicht davor zurück, Arbeit zu wiederholen, wenn du merkst, den 
Durchblick verloren zu haben. Wenn du code hast, den du selbst nicht 
mehr verstehst, hast du verloren und musst von Vorn anfangen.

von flash gordon (Gast)


Lesenswert?

Versuche, das Rad neu zu erfinden, solange du in der Lernphase bist. Es 
gehört dazu, mal einen eigenen Pseudozufallsgenerator gebastelt zu haben 
oder Stringfunktionen selbst zu programmieren. Später, wenn du weisst, 
wie es geht, kannst du die Standartlibraries benutzen. Lass dir auch mal 
den Assemblercode von deinen eigenen Programmen anzeigen, um ein Gefühl 
zu bekommen, was der Compiler eigentlich macht.

von klaus (Gast)


Lesenswert?

- Überlege dir eine Architektur. Sinnvoll ist häufig der Aufbau in 
Schichten. Trenne z.B. konsequenz hardwareabhängige Teile und 
hardwareUNabhängige Teile voneinander. Zum Beispiel werden alle Module 
welche die Peripherie kapseln in einer Schicht zusammengefaßt 
(Hardwareabstraktionsschicht).

- Denke in Modulen. Jedes Modul sollte eine einzige logisch klar 
definierbare Aufgabe erfüllen. Module sollten so entwickelt sein, dass 
sich die Schnittstelle bei Änderungen der Hardware nicht verändert.

- Abläufe sollten als Zustandsautomaten realisiert werden. Komplexe 
Ausdrücke mit "if then else" die auf vielen Variablen operieren sind 
meist ein Indiz für einen nicht-erkannten Zustandsautomat. Trenne die 
Logik des Zustandsautomaten von der anwendungsspezifischen Logik (kein 
switch case).

- Versuche die Notwendigkeit von Datenstrukturen zu erkennen. Arrays die 
mit einer Index Variable beschrieben werden deuten häufig darauf hin, 
dass eigentlich eine Queue benötigt wird (z.B. gepufferter Empfang von 
Zeichen via UART). Derartige Konstrukte sollten aufgeteilt werden und 
die Queue in einem separaten Modul allgemeingültig implementiert werden.

- Jede Funktion sollte eine einzige logisch klar definierbare Aufgabe 
erfüllen.

von Karl H. (kbuchegg)


Lesenswert?

Und halte dich nicht zu sklavisch an

Entweder Top-Down oder Bottom-Up

In der Praxis ist es ein ständiges Wechseln zwischen den beiden, die 
Wahrheit liegt hier als mehr in der Mitte. Denn wie soll man beim 
Top-Down die Verfeinierungen in die Tiefe machen ohne sich zu 
verzetteln, wenn man nicht weiß, wo die Reise hingehen soll? Man muss 
also auch beim Top-Down immer wieder mal einen Blick auf den Bottom 
werfen und auch nachsehen wo es Berührungspunkte zwischen ein paar 
Schichten Top-Down und ein paar Schichten Bottom-Up geben wird, bzw. 
geben soll.

Bzw. dasselbe in Grün für die umgekehrte Richtung.

von Daniel V. (danvet)


Lesenswert?

RestInPieces schrieb:
> Hallo,
>
> mit folgendem Problem schlage ich mich nun schon seit einiger Zeit
> herum. Ich  beginne ein Gcc Projekt schreibe die ersten funktionen,
> alles prima. Über kurz oder lang wird das ganze aber so unübersichtlich,
> dass der aufwand um weiter funktionen einzubauen zu groß wird und ich
> das Projekt unfertig stehen lasse.
>
> Die Lösung ist denke das Projekt von vornherein zu planen anstatt
> einfach drauf los zu programmieren. Nur hab ich keine Ahnung wie ich
> sowas anfange. Gibt es Tutorials oder Bücher die einen an die Hanmd
> nehmen? Wie macht ihr das bzw wie habt ihr das gelernt?

Das kann aber auch am Editor liegen. Bei "Eclipse" z.B. hast du eine 
gute Syntax-Hervorhebung und noch einige andere nette Features. Ein 
reiner Editor ist sehr mühsam, weil man sich z.B. die Strukturelemnte 
selbst zusammen suchen muss, Eclipse bietet dir die Strukturelemente 
einer Struktur an.

von RestInPieces (Gast)


Lesenswert?

Da ist ja schon ne ganze Menge zusammengekommen, danke euch!

Falk danke, den Artikel kannte ich noch nicht.

Kapselung habe ich probiert, ich kam aber dann an die Stelle wo ich wild 
durch die Module gesprungen bin um eine aktion durchzuführen :P

Ich denke das sinnvollste ist für mich mal bottom up zu probieren und 
mir das ganze vorher mal aufzuzeichnen. Dann kann ich erstmal einzelne 
Module für die Hardware schreiben und die damit kapseln.

Datenstruckturen ist so ne Sache, meisten hab ich einfach mal ne 
Variable angelegt und wenn sie nicht mehr "gereicht" hat wurde sie 
"aufgebohrt". Was dann erstmal zu zig Fehlern geführt hat, weil ich 
diese natürlich noch an anderen Stellen verwendet hatte.

Ich denke da fehlt mir einfach die Weitsicht (oder Übersicht?)

Eclipse hatte ich probiert war mir aber zu langsam, ich kanns nicht 
haben wenn ich auf den PC warten muss :P Arbeite jetzt mit CodeBlocks. 
Das letzte Projekt ist allerdings auch schon etwas her. Da ich aber 
demnächst wieder was vorhabe dachte ich frage ich mal hier nach wie mans 
richtig macht/lernt.

Zustandsautomaten: Bisher hatte ich mich auf einfache switch case 
beschränkt. Werd mir das mal genauer ansehen.

- Pattern init/run/done verwenden, auch für Sub-Module
Kannst du das etwas genauer ausführen? Meinst du das sequentiell oder 
funktional? Bisher hatte ich oft eine Init und eine ausführende 
Funktion. Bzw eine Init eine -Aktion anstoßende- und eine -Daten 
abholende- Funktion.

von Karl H. (kbuchegg)


Lesenswert?

RestInPieces schrieb:

> Datenstruckturen ist so ne Sache, meisten hab ich einfach mal ne
> Variable angelegt und wenn sie nicht mehr "gereicht" hat wurde sie
> "aufgebohrt". Was dann erstmal zu zig Fehlern geführt hat, weil ich
> diese natürlich noch an anderen Stellen verwendet hatte.

Das macht ja nichts. Die findet der Compiler.

> Ich denke da fehlt mir einfach die Weitsicht (oder Übersicht?)

Genau da liegt der springende Punkt.
Man braucht Übung.

Das ist wie Bilder malen. Das kann man auch nicht aus einem Handbuch 
lernen. Aber mit der Zeit kriegt man Übung was Bildkomposition, 
Farbkompoasition etc. angeht.

Genauso auch hier. Mit der Zeit kriegt man es ins Gefühl, wie eine gute 
Struktur aussehen muss. Gerade in OOP ist es immer in gutes Zeichen, 
wenn die Einzelteile zusammenpassen und sich 'höhere Funktionen' ganz 
zwanglos, fast schon wie von alleine, ergeben und alles wie bei den 
letzten Puzzlestückchen von alleine in Position fällt.

Muss man hingegen krampfhaft ständig umcasten, hat die Werte die man 
benötigt nicht in den Klassen, dann kann man darauf wetten, dass das 
Design mies ist.

von Loonix (Gast)


Lesenswert?

flash gordon schrieb:
> Versuche, das Rad neu zu erfinden, solange du in der Lernphase bist. Es
> gehört dazu, mal einen eigenen Pseudozufallsgenerator gebastelt zu haben
> oder Stringfunktionen selbst zu programmieren.

Seh ich auch so, steht der exklusiven Meinung des ein- oder anderen 
Foren-Urgesteins übrigens entgegen. ("Warum nimmst du nicht MEINEN 
Scheduler?";))
Es gibt aus meiner Sicht keinen Fachbereich, wo man mehr vom 
"Learning-by-doing" profitiert als bei der Softwareentwicklung.

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.