4 Stimmen

Code-Anordnung in Quelldateien - Vorwärtsdeklarationen vs. "Wiederholen Sie sich nicht"?

Wenn Sie in C programmieren und Ihren Compiler so konfigurieren, dass er darauf besteht, dass alle Funktionen deklariert werden, bevor sie verwendet werden (oder wenn Sie in C++ programmieren), dann können Sie mit einer von (mindestens) zwei Organisationen für Ihre Quelldateien enden.

Entweder:

  • Kopfzeilen
  • Weiterleitungsdeklarationen von (statischen) Funktionen in dieser Datei
  • Externe Funktionen (primäre Eingangspunkte)
  • Statische - nicht-öffentliche - Funktionen

Oder:

  • Kopfzeilen
  • Statische - nicht-öffentliche - Funktionen
  • Externe Funktionen (primäre Eingangspunkte)

Mir ist klar, dass in C++ der Begriff "statisch" nicht bevorzugt wird, aber ich bin in erster Linie C-Programmierer, und in C++ gibt es das entsprechende Konzept, nämlich Funktionen in einem anonymen Namensraum innerhalb der Datei.

Pregunta:

  • Welche Organisation verwenden Sie, und warum bevorzugen Sie sie?

Als Referenz verwendet mein eigener Code das zweite Format, so dass die statischen Funktionen definiert werden, bevor sie verwendet werden, so dass es nicht notwendig ist, sie sowohl zu deklarieren als auch zu definieren, was es erspart, die Informationen über die Funktionsschnittstellen zweimal auszuschreiben - was wiederum den Overhead (geringfügig) reduziert, wenn eine interne Schnittstelle geändert werden muss. Der Nachteil dabei ist, dass die ersten in der Datei definierten Funktionen die Routinen der untersten Ebene sind - diejenigen, die von später in der Datei definierten Funktionen aufgerufen werden -, so dass der wichtigste Code nicht ganz oben, sondern eher unten in der Datei steht. Inwieweit ist das für Sie von Bedeutung?

Ich gehe davon aus, dass alle von außen zugänglichen Funktionen in Headern deklariert werden und dass diese Form der Wiederholung notwendig ist - ich denke, das sollte nicht umstritten sein.

6voto

Robert Gamble Punkte 101657

Ich habe immer die Methode Nr. 1 verwendet, weil ich gerne schnell erkennen möchte, welche Funktionen in einer bestimmten Datei definiert sind und ihre Signaturen alle an einem Ort sehen möchte. Das Argument, dass man die Prototypen zusammen mit der Funktionsdefinition ändern muss, finde ich nicht besonders überzeugend, da man in der Regel sowieso den gesamten Code ändert, der die geänderten Funktionen aufruft, und die Änderung der Funktionsprototypen scheint relativ trivial zu sein.

3voto

Adam Hawes Punkte 5403

In C-Code verwende ich eine einfache Regel:

  • Jede C-Datei mit nicht-statischen Elementen hat eine entsprechende Header-Datei, die diese Elemente definiert.

Das hat für mich in der Vergangenheit sehr gut funktioniert - es macht es einfach genug, die Definition einer Funktion zu finden, weil sie in der gleichnamigen .h-Datei steht, wenn ich sie nachschlagen muss. Es funktioniert auch gut mit Doxygen (mein bevorzugtes Tool), weil der ganze Ballast im Header bleibt, wo ich nicht die meiste Zeit verbringe - die C-Datei ist voller Code.

Bei statischen Elementen in einer Datei bestehe ich darauf, die Deklarationen so anzuordnen, dass sie bei der Instanziierung ohnehin vor der Verwendung definiert werden. Außerdem vermeide ich zirkuläre Abhängigkeiten in Funktionsaufrufen fast immer.

Für den C++-Code habe ich Folgendes versucht:

  • Der gesamte Code wird in der Header-Datei definiert. Verwenden Sie #pragma interface/#pragma implementation, um den Compiler darüber zu informieren; ähnlich wie bei Templates, die den gesamten Code in den Header stellen.

Das hat bei mir in C++ sehr gut funktioniert. Es bedeutet, dass man am Ende riesige Header-Dateien hat, die in einigen Fällen die Kompilierzeit erhöhen können. Sie erhalten auch eine C++-Body-Datei, in die Sie einfach den Header einbinden und kompilieren. Sie können Ihre statischen Mitgliedsvariablen hier instanziieren. Es wurde auch zu einem Albtraum, weil es viel zu einfach war, die Methodenparameter zu ändern und den Code zu zerstören.

Ich zog nach

  • Header-Datei mit Doxygen-Kommentaren (mit Ausnahme von Templates, bei denen der Code in den Header aufgenommen werden muss) und vollständige Body-Datei, mit Ausnahme kurzer Methoden, von denen ich weiß, dass ich es vorziehe, sie bei Verwendung zu inlinen.

Die Trennung der Implementierung von der Definition hat den entscheidenden Vorteil, dass es schwieriger ist, die Signaturen Ihrer Methoden/Funktionen zu ändern, so dass es weniger wahrscheinlich ist, dass Sie es tun und Dinge kaputt machen. Es bedeutet auch, dass ich riesige Doxygen-Blöcke in der Header-Datei haben kann, die dokumentieren, wie die Dinge funktionieren und im Code relativ unterbrechungsfrei arbeiten kann, abgesehen von nützlichen Kommentaren wie "deklariere eine Variable namens i" (ironisch gemeint).

Ada zwingt Ihnen die Konvention und das Dateibenennungsschema auf. Den meisten dynamischen Sprachen wie Ruby, Python usw. ist es im Allgemeinen egal, ob und wo man etwas deklariert.

2voto

EvilTeach Punkte 27313

Nummer 2 für mich.

Ich denke, dass die Verwendung von statischen oder anderen Methoden, um Ihre Modulfunktionen und -variablen privat für das Modul zu machen, eine gute Praxis ist.

Ich ziehe es vor, meine API-Funktionen am Ende des Moduls zu haben. Umgekehrt setze ich die API-Funktionen an den Anfang meiner Klassen, da Klassen im Allgemeinen wiederverwendbar sind. Wenn man die API-Funktionen ganz oben platziert, sind sie schneller zu finden. Die meisten IDEs können Sie ziemlich direkt zu jeder Funktion führen.

2voto

Darius Bacon Punkte 14645

Nummer 2: Da ich viele kurze Funktionen schreibe und sie beliebig umstrukturiere, wäre es ein großes Ärgernis, Forward-Deklarationen zu pflegen. Wenn es eine Emacs-Erweiterung gibt, die das ohne viel Aufhebens für Sie erledigt, wäre ich daran interessiert, denn die Top-Down-Organisation ist ein bisschen lesbarer. (Ich bevorzuge Top-Down in z.B. Python.)

Eigentlich nicht ganz Ihre Nummer 2, denn ich fasse verwandte Funktionen in der Regel in der .c zusammen, unabhängig davon, ob sie öffentlich oder privat sind. Wenn ich alle öffentlichen Deklarationen sehen will, schaue ich in der Kopfzeile nach.

1voto

Giacomo Punkte 10677

(Apropos C-Code)

Nummer 2 für mich, weil ich immer vergessen, die Forward Decls zu aktualisieren, um die Änderungen der statischen Funktionen zu berücksichtigen.

Aber ich denke, dass die beste Praxis sein sollte

  • Kopfzeilen
  • Forward-Deklarationen + Kommentar zum Funktionsverhalten für jede einzelne Funktion
  • exportierte Funktionen + eventuelle Kommentare zu Implementierungsdetails, wenn der Code nicht klar genug ist
  • statische Funktionen + eventuelle Kommentare zu Implementierungsdetails

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X