Beim Codieren eines großen Projekts in CI ist ein Problem aufgetreten. Wenn ich weiterhin Code schreibe, wird es manchmal schwierig sein, den Code zu organisieren. Ich meine, dass die Benennung von Funktionen und Variablen für verschiedene Teile des Programms verwechselt zu sein scheint.
Ich überlegte, ob es nützliche Namenskonventionen gibt, die ich für C-Variablen und -Funktionen verwenden kann.
Die meisten Sprachen schlagen eine Namenskonvention vor. Aber für C ist das einzige, was ich bisher gelesen habe, dass die Namen für die Lesbarkeit des Codes beschreibend sein sollten.
BEARBEITEN:
Beispiele für einige Beispiele für vorgeschlagene Namenskonventionen:
Ich habe irgendwo weitere Namenskonventionen für Java gelesen, konnte mich aber nicht erinnern, wo.
order.c
, können Sie die Funktionen nennenorder_add()
,order_del()
und so weiter . Möglicherweise gibt es alte Systeme, die Ihnen mitteilen, dass der Name innerhalb der ersten 8 Zeichen eindeutig sein muss. Wenn Sie später versehentlich zu c ++ wechseln, werden Sie es lieben,order::add()
undorder::del()
dann zu schreiben .Antworten:
Dies ist Ihr Problem: Richtige Organisation, und der Stil sollte leichter fließen.
Warten Sie nicht , um Ihren Code zu organisieren: Halten Sie Ihren Code organisiert, während Sie gehen. Obwohl die Sprache dies nicht für Sie erledigt, sollte der Code dennoch in Module mit geringer Kopplung und hoher Kohäsion organisiert sein.
Diese Module liefern dann natürlich einen Namensraum. Kürzen Sie den Modulnamen (falls er lang ist) und stellen Sie den Funktionsnamen das Modul voran, um Kollisionen zu vermeiden.
Auf der Ebene der einzelnen Identifikatoren sind dies ungefähr in aufsteigender Reihenfolge der Subjektivität:
function_like_this(struct TypeLikeThis variable)
ist üblichVermeiden Sie auf jeden Fall die ungarische Notation (sorry JNL)
es sei denn, Sie sind bereit, es wie ursprünglich beabsichtigt zu verwenden, was bedeutet, dass Simonyis Apps nicht die Version für schreckliche Systeme sind, sondern die Notation für Apps
Warum? Ich könnte einen Aufsatz darüber schreiben, aber ich schlage stattdessen vor, dass Sie diesen Artikel von Joel Spolsky lesen und dann noch ein paar mehr suchen, wenn Sie interessiert sind. Unten finden Sie einen Link zu Simonyis Originalarbeit.
Vermeiden Sie Zeigertypedefs, es sei denn, sie sind wirklich undurchsichtige Cookie-Typen - sie verwirren nur die Dinge
Was meine ich mit einem undurchsichtigen Cookie-Typ ? Ich meine etwas, das in einem Modul (oder einer Bibliothek oder was auch immer) verwendet wird und an Client-Code weitergegeben werden muss, aber dieser Client-Code kann nicht direkt verwendet werden. Es wird einfach an die Bibliothek zurückgegeben.
Beispielsweise kann eine Datenbankbibliothek eine Schnittstelle wie diese verfügbar machen
Jetzt ist der Kontext für den Client-Code undurchsichtig , da Sie nicht hineinsehen können. Sie geben es einfach an die Bibliothek zurück. So etwas
FILE
ist auch undurchsichtig, und ein Integer-Dateideskriptor ist auch ein Cookie , ist aber nicht undurchsichtig.Ein Hinweis zum Design
Ich habe den Ausdruck niedrige Kopplung und hohe Kohäsion oben ohne Erklärung verwendet, und ich fühle mich ein bisschen schlecht dabei. Sie können danach suchen und wahrscheinlich einige gute Ergebnisse finden, aber ich werde versuchen, es kurz anzusprechen (wieder könnte ich einen Aufsatz schreiben, aber ich werde versuchen, es nicht zu tun).
Die oben skizzierte DB-Bibliothek weist eine geringe Kopplung auf, da sie eine kleine Schnittstelle zur Außenwelt freigibt. Durch das Ausblenden der Implementierungsdetails (teilweise mit dem undurchsichtigen Cookie-Trick) wird verhindert, dass der Client-Code von diesen Details abhängt.
Anstelle des undurchsichtigen Cookies deklarieren wir die Kontextstruktur so, dass ihr Inhalt sichtbar ist. Dazu gehört auch ein Socket-Dateideskriptor für eine TCP-Verbindung zur Datenbank. Wenn wir anschließend die Implementierung ändern, um die Verwendung eines gemeinsam genutzten Speichersegments zu unterstützen, wenn die Datenbank auf demselben Computer ausgeführt wird, muss der Client neu kompiliert und nicht nur neu verknüpft werden. Noch schlimmer ist , könnte der Client gestartet mit dem Dateideskriptor, zum Beispiel rief
setsockopt
die Standardpuffergröße zu ändern, und jetzt braucht es eine Codeänderung als auch. All diese Details sollten in unserem Modul verborgen sein, wo dies praktisch ist, und dies ergibt eine geringe Kopplung zwischen den Modulen.Das Beispiel zeigt auch eine hohe Kohäsion , da sich alle Methoden im Modul auf dieselbe Aufgabe beziehen (DB-Zugriff). Dies bedeutet , dass nur der Code , dass Bedürfnisse über die Implementierungsdetails kennen (das heißt, die Inhalte unserer Online - Cookie) tatsächlich Zugang zu ihnen haben, das erleichtert das Debuggen.
Sie können auch feststellen, dass die Auswahl eines Präfixes für die Gruppierung dieser Funktionen durch ein einzelnes Anliegen vereinfacht wurde.
Es ist einfach zu sagen, dass dieses Beispiel gut ist (zumal es noch nicht vollständig ist), aber es hilft Ihnen nicht sofort. Der Trick besteht darin, beim Schreiben und Erweitern des Codes auf Funktionen zu achten, die ähnliche Aufgaben ausführen oder mit denselben Typen arbeiten (die möglicherweise Kandidaten für ihr eigenes Modul sind), und auch auf Funktionen, die viele separate Aufgaben ausführen, die nicht erforderlich sind. Es ist wirklich verwandt und könnte Kandidaten für eine Aufteilung sein.
quelle
with low coupling and high cohesion
. Was bedeutet das? Und erklären Sie bitte über undurchsichtige Cookie-Typen. Ich habe keine Ahnung was das heißt.low coupling and high cohesion
. Es bedeutet also im Grunde, Dinge zu kapseln, wenn ich kann, und es sollte so geschehen, dass die Funktionen, die tatsächlich benötigt werden, Zugriff haben sollten. Einige Dinge gingen mir über den Kopf, aber ich glaube immer noch, dass ich deinen Standpunkt verstanden habe.Meiner Meinung nach sind 90% des Namensproblems gelöst, wenn Sie drei Dinge beachten: a) Machen Sie Ihre Variablen- und Funktionsnamen so aussagekräftig wie möglich, b) Seien Sie im gesamten Code konsistent (dh, wenn eine Funktion den Namen addNumbers hat, a Die zweite Funktion sollte multiplyNumbers heißen und nicht numbersMul) und c) versuchen, die Namen möglichst kurz zu machen, da wir sie eingeben müssen.
Wenn Sie sich jedoch andere Aspekte zu diesem Thema ansehen möchten, finden Sie auf der Wikipedia-Seite zu Namenskonventionen eine gute Liste von Dingen, die Sie beachten sollten. Es gibt auch einen Abschnitt zu C und C ++:
quelle
Die einzige harte Einschränkung in C ist, dass es keine Namespaces gibt. Daher müssen Sie eine Möglichkeit finden, die
rename()
Funktion Ihrer Dateisystembibliothek von derrename()
Funktion Ihrer Medienbibliothek zu unterscheiden . Die übliche Lösung ist ein Präfix wie:filesystem_rename()
undmedia_rename()
.Der andere allgemeine Rat lautet: Bleiben Sie innerhalb eines Projekts oder eines Teams konsequent. Die Lesbarkeit wird verbessert.
quelle
WENN SIE NACH EINEM GLOBAL AKZEPTIERTEN FORMAT SUCHEN
MISRA / JSF / AUTOSAR deckt nahezu 100% aller Industriestandards für die Benennung und Organisation von C / C ++ - Code ab. Das Problem ist, dass sie nicht kostenlos erhältlich sind, dh jeder Reiseführer kostet etwas Geld. Ich weiß, dass MISRA 2008 C / C ++ - Codierungsstandardbuch wahrscheinlich ungefähr 50 USD kostet.
Sie können sich diese als die Harvard-Referenz für Bibliografie und zusätzliche Lektüre vorstellen, wenn Sie eine Zeitschrift schreiben. Ich habe MISRA verwendet und es ist eine gute Möglichkeit, Ihre Funktionen und Variablen zu benennen und sie für die ordnungsgemäße Verwendung zu organisieren.
WENN SIE NACH ETWAS VORÜBERGEHENDEM SUCHEN
Ich denke, die Referenzen, die Sie für Python und Java angegeben haben, sind in Ordnung. Ich habe Leute gesehen, die den Javadoc-Stil angenommen haben, um Code zu kommentieren, zu benennen und zu organisieren. Tatsächlich musste ich in meinem letzten Projekt C ++ - Code in Java-ähnlichen Funktionen / Variablennamen schreiben. Zwei Gründe dafür:
1) Es war anscheinend einfacher zu folgen.
2) Die Anforderungen an den Produktionscode haben den Grund für sicherheitskritische Software-Systemstandards nicht berührt.
3) Legacy-Code war (irgendwie) in diesem Format.
4) Doxygen erlaubte Javadoc-Kommentaren. Zu diesem Zeitpunkt verwendeten wir Sauerstoff, um die Dokumentation für die Produktionsmitarbeiter zu erstellen.
Viele Programmierer werden sich dem widersetzen, aber ich persönlich bin der Meinung, dass es nichts auszusetzen hat, wenn man in C / C ++ die Benennung von Funktionen und Variablen im Javadoc-Stil anwendet. Ja, natürlich müssen die Praktiken der Organisation Ihrer Flusskontrolle, der Fadensicherheit usw. unabhängig davon behandelt werden. Ich bin hier jedoch kein Bewerber. Ich weiß auch nicht, wie streng Ihre Anforderungen an das Format des Produktionscodes sind. Ich schlage vor, dass Sie Ihre Anforderungen überprüfen, herausfinden, inwieweit Sie von einer bestimmten Namenskonvention abhängig sind, und eine Lösung wählen, die in den Antworten von mir und anderen erwähnt wurde, ohne sie in einen nicht thematischen Bereich umzuleiten
Hoffe das hat geholfen !?
quelle
Einige wichtige Dinge, die bei der Benennung beachtet werden müssen, sind:
Schauen Sie sich den Typ actionObject oder ObjectAction an. (Objekt Nicht für C. Aber im Allgemeinen, wenn Sie zu anderen objektorientierten Sprachen wechseln.) Dies sollte helfen
Rest wäre konsequent, kurz und beschreibend sicher.
quelle
Die meisten Antworten sind gut, aber ich möchte einige Dinge über Namenskonventionen für Bibliotheken und eingeschlossene Dateien sagen, ähnlich wie bei der Verwendung von Namespaces in anderen Sprachen wie C ++ oder Java:
Wenn Sie eine Bibliothek erstellen, suchen Sie ein gemeinsames Präfix für Ihre exportierten Symbole, dh globale Funktionen, Typendefs und Variablen. Dies verhindert Konflikte mit anderen Bibliotheken und identifiziert die Funktionen als von Ihnen stammend. Dies ist ein bisschen Apps ungarischen Notationen.
Vielleicht gehen Sie noch weiter und gruppieren Ihre exportierten Symbole: libcurl verwendet curl_ * für globale Symbole, curl_easy_ *, curl_multi_ * und curl_share_ * für die verschiedenen Schnittstellen. Zusätzlich zur Verwendung von curl_ * für alle Funktionen haben sie eine weitere Ebene von "Namespaces" für die verschiedenen Schnittstellen hinzugefügt: Der Aufruf einer curl_easy_ * -Funktion für ein curl_multi_ * -Handle sieht jetzt falsch aus (siehe Funktionsnamen unter http: // curl). haxx.se/libcurl/c/
Unter Beibehaltung der Regeln für exportierte Symbole sollten Sie diese für statische Funktionen in
#include
ed-Dateien verwenden: Versuchen Sie, ein gemeinsames Präfix für diese Funktionen zu finden. Vielleicht haben Sie statische String-Utility-Funktionen in einer Datei namens "my_string"? Stellen Sie all diesen Funktionen my_string_ * voran.quelle