it-swarm.com.de

Wie soll ich komplexe Projekte in C strukturieren?

Ich habe kaum mehr als C-Kenntnisse für Anfänger und würde gerne wissen, ob es de facto "Standards" gibt, um eine etwas komplexe Anwendung in C zu strukturieren. Sogar GUI-basierte.

Ich habe immer das Paradigma OO in Java und PHP und jetzt, wo ich C lernen will, bin ich Ich habe Angst, dass ich meine Anwendungen falsch strukturieren könnte. Ich weiß nicht, welche Richtlinien zu befolgen sind, um Modularität, Entkopplung und Trockenheit mit einer prozeduralen Sprache zu erreichen.

Haben Sie Lesungen zu empfehlen? Ich konnte kein Anwendungsframework für C finden, auch wenn ich keine Frameworks verwende. Ich habe beim Durchsuchen des Codes immer gute Ideen gefunden.

78
Josh

Der Schlüssel ist die Modularität. Dies ist einfacher zu entwerfen, zu implementieren, zu kompilieren und zu warten.

  • Identifizieren Sie Module in Ihrer App, wie Klassen in einer OO App.
  • Separate Schnittstelle und Implementierung für jedes Modul. Fügen Sie nur die Schnittstelle ein, die von anderen Modulen benötigt wird. Denken Sie daran, dass in C kein Namespace vorhanden ist. Sie müssen also alle Elemente in Ihren Schnittstellen eindeutig definieren (z. B. mit einem Präfix).
  • Blenden Sie globale Variablen in der Implementierung aus und verwenden Sie Accessorfunktionen zum Lesen/Schreiben.
  • Denken Sie nicht in Vererbung, sondern in Zusammensetzung. Versuchen Sie im Allgemeinen nicht, C++ in C nachzuahmen, da dies sehr schwer zu lesen und zu warten ist.

Wenn Sie Zeit zum Lernen haben, werfen Sie einen Blick auf den Aufbau einer Ada-App mit ihren obligatorischen package (Modulschnittstelle) und package body (Modulimplementierung).

Dies ist für die Codierung.

Für die Pflege (denken Sie daran, dass Sie nur einmal programmieren, aber mehrmals) empfehle ich, Ihren Code zu dokumentieren. Doxygen ist eine gute Wahl für mich. Ich schlage auch vor, eine starke Regressionstestsuite zu erstellen, mit der Sie eine Umgestaltung durchführen können.

49
mouviciel

Es ist ein weit verbreitetes Missverständnis, dass OO Techniken in C nicht angewendet werden können. Die meisten können - es ist nur so, dass sie etwas unhandlicher sind als in Sprachen mit einer für den Job bestimmten Syntax.

Eine der Grundlagen eines robusten Systemdesigns ist die Kapselung einer Implementierung hinter einer Schnittstelle. FILE* Und die damit arbeitenden Funktionen (fopen(), fread() usw.) sind ein gutes Beispiel dafür, wie die Kapselung in C angewendet werden kann, um Schnittstellen einzurichten. (Da C keine Zugriffsspezifizierer hat, können Sie natürlich nicht erzwingen, dass niemand in einen struct FILE Hineinschaut, sondern nur ein Masochist würde dies tun.)

Falls erforderlich, kann polymorphes Verhalten in C unter Verwendung von Tabellen von Funktionszeigern erzielt werden. Ja, die Syntax ist hässlich, aber der Effekt ist der gleiche wie bei virtuellen Funktionen:

struct IAnimal {
    int (*eat)(int food);
    int (*sleep)(int secs);
};

/* "Subclass"/"implement" IAnimal, relying on C's guaranteed equivalence
 * of memory layouts */
struct Cat {
    struct IAnimal _base;
    int (*meow)(void);
};

int cat_eat(int food) { ... }
int cat_sleep(int secs) { ... }
int cat_meow(void) { ... }

/* "Constructor" */
struct Cat* CreateACat(void) {
    struct Cat* x = (Cat*) malloc(sizeof (struct Cat));
    x->_base.eat = cat_eat;
    x->_base.sleep = cat_sleep;
    x->meow = cat_meow;
}

struct IAnimal* pa = CreateACat();
pa->eat(42);                       /* Calls cat_eat() */

((struct Cat*) pa)->meow();        /* "Downcast" */
30
j_random_hacker

Alles gute Antworten.

Ich würde nur "Datenstruktur minimieren" hinzufügen. Dies könnte in C sogar einfacher sein, denn wenn C++ "C mit Klassen" ist, versucht OOP) Sie zu ermutigen, jedes Substantiv/Verb in Ihrem Kopf zu nehmen und es in eine Klasse/Methode umzuwandeln Das kann sehr verschwenderisch sein.

Angenommen, Sie haben zu bestimmten Zeitpunkten eine Reihe von Temperaturwerten und möchten diese in Windows als Liniendiagramm anzeigen. Windows hat eine Paint-Meldung, und wenn Sie diese erhalten, können Sie das Array mit LineTo-Funktionen durchlaufen und die Daten beim Konvertieren in Pixelkoordinaten skalieren.

Was ich völlig zu oft gesehen habe, ist, dass Menschen, da das Diagramm aus Punkten und Linien besteht, eine Datenstruktur aus Punktobjekten und Linienobjekten aufbauen, die jeweils in der Lage sind, sich selbst zu zeichnen, und diese dann aus der Theorie, dass dies besteht, beständig machen ist irgendwie "effizienter", oder dass sie möglicherweise in der Lage sein müssen, mit der Maus über Teile des Diagramms zu fahren und die Daten numerisch anzuzeigen, damit sie Methoden in die Objekte einbauen, um damit umzugehen, und das natürlich. beinhaltet das Erstellen und Löschen von noch mehr Objekten.

Sie haben also eine riesige Menge an Code, der so gut lesbar ist, dass Sie nur 90% der Zeit damit verbringen, Objekte zu verwalten.

All dies geschieht im Namen von "guter Programmierpraxis" und "Effizienz".

Zumindest in C wird der einfache, effiziente Weg offensichtlicher und die Versuchung, Pyramiden zu bauen, geringer.

12
Mike Dunlavey

Die GNU-Codierungsstandards haben sich über ein paar Jahrzehnte entwickelt. Es wäre eine gute Idee, sie zu lesen, auch wenn Sie ihnen nicht genau folgen. Wenn Sie über die darin aufgeworfenen Punkte nachdenken, erhalten Sie eine genauere Grundlage für die Strukturierung Ihres eigenen Codes.

11
user25148

Die Kapselung ist immer der Schlüssel für eine erfolgreiche Entwicklung, unabhängig von der Entwicklungssprache.

Ein Trick, mit dem ich "private" Methoden in C zusammengefasst habe, besteht darin, ihre Prototypen nicht in die ".h" -Datei aufzunehmen.

3
Nate

Ich empfehle Ihnen, den Code eines beliebten Open-Source-C-Projekts zu lesen, wie ... hmm ... Linux-Kernel oder Git; und sehen, wie sie es organisieren.

3
Ivan Krechetov

Die Zahlenregel für komplexe Anwendungen: Sie sollte leicht lesbar sein.

Um komplexe Anwendungen zu vereinfachen, verwende ich Teilen und Erobern .

3
MrValdez

Wenn Sie wissen, wie Sie Ihren Code in Java oder C++) strukturieren, können Sie mit C-Code denselben Prinzipien folgen. Der einzige Unterschied besteht darin, dass Sie nicht den Compiler an Ihrer Seite haben und Sie müssen alles extra sorgfältig manuell machen.

Da es keine Pakete und Klassen gibt, müssen Sie zunächst Ihre Module sorgfältig entwerfen. Am häufigsten wird ein separater Quellordner für jedes Modul erstellt. Sie müssen sich auf Namenskonventionen verlassen, um den Code zwischen verschiedenen Modulen zu unterscheiden. Stellen Sie beispielsweise allen Funktionen den Namen des Moduls voran.

Sie können keine Klassen mit C haben, aber Sie können einfach "Abstrakte Datentypen" implementieren. Sie erstellen für jeden abstrakten Datentyp eine C- und eine H-Datei. Wenn Sie es vorziehen, können Sie zwei Header-Dateien haben, eine öffentliche und eine private. Die Idee ist, dass alle Strukturen, Konstanten und Funktionen, die exportiert werden müssen, in die öffentliche Header-Datei verschoben werden.

Ihre Werkzeuge sind auch sehr wichtig. Ein nützliches Tool für C ist lint , mit dessen Hilfe Sie schlechte Gerüche in Ihrem Code finden können. Ein weiteres Tool, das Sie verwenden können, ist Doxygen, mit dessen Hilfe Sie Dokumentation erstellen können.

3
kgiannakakis

Ich würde vorschlagen, als ersten Schritt ein C/C++ - Lehrbuch zu lesen. Zum Beispiel ist C Primer Plus eine gute Referenz. Wenn Sie die Beispiele durchsehen, erhalten Sie eine Vorstellung davon, wie Sie Java OO) auf eine prozedurale Sprache wie C abbilden können.

2
Tosa