Grund für die Platzierung von Funktionstyp und Methodenname in verschiedenen Zeilen in C


16

Ich habe gerade bei einer Firma angefangen und einer der Stilkommentare bei meiner ersten Codeüberprüfung war, dass der Rückgabetyp und der Methodenname in verschiedenen Zeilen stehen sollten. Zum Beispiel das

void foo() {
}

sollte das sein

void
foo() {
}

Ich habe immer den ersten Stil verwendet und mich gefragt, ob es einen anderen Grund als den persönlichen gibt, warum Leute den zweiten Stil verwenden. Ich glaube nicht, dass die erste überhaupt die Lesbarkeit beeinträchtigt. Ist eines bei C-Programmierern und großen Open-Source-Projekten häufiger als das andere?


3
Dies steht im GNU-Standard (nicht unbedingt, dass es eine gute Sache ist, die Art der Verspannung ist seltsam). gnu.org/prep/standards/standards.html#Formatting
Gauthier

Antworten:


19

Ich habe mich gefragt, ob es einen anderen Grund als den persönlichen gibt, warum Menschen den zweiten Stil verwenden.

Das ist ein Stil, der in den frühen Tagen von C populär war. Der Grund dafür mag sein, dass sie es schon sehr lange so gemacht haben. Sie haben eine Menge Code, der so aussieht, und genau das ist es jeder ist es gewohnt. Nicht so sehr persönliche Vorlieben als unternehmerische Dynamik.

Ein weiterer Grund ist, dass Funktionsnamen immer in der ersten Spalte beginnen. Rückgabetypen variieren in der Länge und können etwas komplex sein. Wenn Sie den Typ in eine eigene Zeile setzen, ist der Funktionsname leichter zu finden.

Wenn das Unternehmen einen festgelegten Stil hat, verfügt es möglicherweise auch über ein Dokument mit Kodierungsstandards. Frag danach. Möglicherweise werden die Gründe für diese Auswahl erläutert, und eine Kopie hilft Ihnen, ähnliche Probleme bei zukünftigen Überprüfungen zu vermeiden.


2
Ich vermute, es hängt auch mit der 80-Zeichen-Grenze zusammen, die immer noch von vielen Programmierern verwendet und verteidigt wird. Wenn Sie eine Beschränkung von 80 Zeichen und beschreibende Methoden- / Funktionsnamen verwenden möchten, müssen Sie einige Kompromisse eingehen. Das Aufteilen des Methodenkopfes ist eine davon.
Sulthan

Die Deklaration kann auch länger sein - denken Sie an andere (nicht standardmäßige) Modifikatoren, z. B. Aufruf von Konventionskennungen (stdcall usw.), Informationen zur Sichtbarkeit von Symbolen (DLLEXPORT) oder an __attributes. Und dann, wenn Sie sich auch C ++ ansehen, können Sie relativ komplexe Rückgabetypen haben, so dass man irgendwo einen Zeilenumbruch hinzufügen muss.
Johannes

@ Sulthan Interessanterweise sind es nicht nur Programmierer (die mit Terminal-Fenstern und Terminal-Editoren vertraut sind). Beim Schriftsatz werden im Allgemeinen 72 bis 80 Zeichen als ideale Breite für eine Textspalte im Hinblick auf die Lesbarkeit angesehen. (Daher verwenden TeX und seine Derivate standardmäßig die für manche Leute seltsam engen Spalten.)
JAB

1
@JAB Ich hab das eigentlich jetzt. Ich weiß auch, dass das Lesen eines berechtigten Textes und des Quellcodes zwei sehr unterschiedliche Dinge sind und fast nichts gemeinsam haben, weshalb die ideale Breite keine Rolle spielt.
Sulthan

1
"Ein weiterer Grund ist, dass Funktionsnamen immer in der ersten Spalte beginnen und somit leichter zu finden sind." Und das ist weit mehr als nur ein visueller Vorteil: Jetzt können wir nach dem regulären Ausdruck suchen ^start_of_a_long_funcund sofort zu der Funktion weitergeleitet werden, nach der wir suchen.
Underscore_d

7

Dies ist so ziemlich die einzige Regel zur Code-Formatierung, von der ich festgestellt habe, dass sie die Lesbarkeit spürbar beeinflusst, und es ist nahezu mühelos (vorausgesetzt, Ihr Code-Editor führt keinen Streit mit Ihnen darüber).

Es ist ein gutes Programmiersprachen-Design, Namen in Deklarationen / Definitionen an einer konsistenten Position erscheinen zu lassen. Das Grundprinzip ist einfach: Sie haben einen schönen visuellen Anker (eine geschweifte Klammer oder nur eine hängende Einrückung), mit dem Sie den Anfang des Namens sofort finden können. Sie müssen die Sprache beim Durchsuchen einer Datei nicht analysieren, um den Namen zu finden.

Es ist das gleiche wie beim Formatieren eines Dokuments: Wenn Sie einen neuen Abschnitt beginnen, wird der Name fett hervorgehoben - oft in einer eigenen Zeile - und nicht undifferenziert in einem langen Satz vergraben.

Frühes C hatte sehr knappe Signaturen: Rückgabetypen waren optional und Argumenttypen wurden nach der Signatur deklariert. Die Namen waren in der Regel auch sehr kurz. Dies milderte die Auswirkung einer gelegentlichen Rückgabe, die den Namen verschiebt.

double dot(x, y);

Ist noch ziemlich bekömmlich.

C ++ hat das ein bisschen schlimmer gemacht. Argumenttypspezifikationen wurden in Signaturen verschoben, wodurch die Signaturen länger wurden. Diese Syntax wurde später bei der Standardisierung von C übernommen.

static struct origin *find_origin(struct scoreboard *sb,
                  struct commit *parent,
                  struct origin *origin)

ist weniger verdaulich, aber nicht schlecht. (Auszug aus Git)

Betrachten Sie nun moderne Programmierpraktiken mit langen, beschreibenden Namen und parametrisierten Typen und sehen Sie, wie katastrophal diese Wahl geworden ist. Ein Beispiel aus einem Boost-Header:

template <class A1, class A2, class A3, class A4, class A5, class A6>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&)
{ 
   typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
   return result_type(); 
}

Wenn Sie generischen Code schreiben, sind solche Signaturen nicht einmal ungewöhnlich. Sie können Beispiele für viel schlimmere Fälle finden, ohne sich zu sehr anzustrengen.

C, C ++ und ihre Derivate Java und C # scheinen die Ausnahme für lesbare Deklarationen / Definitionen zu sein. Ihre beliebten Vorgänger und Kollegen (Fortran, ALGOL, Pascal) stellten Namen vor die Ergebnistypen, und glücklicherweise haben auch viele ihrer Nachfolger (Go, Scala, TypeScript und Swift, um nur einige zu nennen) lesbarere Syntaxen gewählt.


1
Seien Sie dankbar, dass Sie keine Fortran-Programme schreiben müssen. Ich sage Ihnen, wenn Sie Ihre Funktionsargumente separat deklarieren, gehen Sie ziemlich schnell auf die Nerven, wenn Sie dazu gezwungen werden. Vor allem, wenn Sie versuchen, eine Funktionssignatur zu lesen, um zu verstehen, welche Argumente erwartet werden: In C ++ werden die Typen genau dort platziert, wo sie hingehören. Fortran zwingt Sie dazu, eine visuelle Schlüsselwortsuche nach dem Variablennamen zu starten, um den Typ zu bestimmen.
cmaster

2
Wurden die Typen in die Funktionsdeklaration tatsächlich von C ++ erfunden? Ich hatte noch nie davon gehört und kämpfe darum, Zitate zu finden.
Underscore_d

1
Siehe Die Entwicklung der C-Sprache . Im Abschnitt Standardisierung erwähnt Ritchie, dass die Syntax von C ++ entlehnt wurde.
User2313838

5

Ich habe diesen Stil zum ersten Mal im 19. Jahr mit C & C ++ kennengelernt. War ziemlich ratlos darüber, wie jemand dieses böse Ding erfinden konnte.

Der einzige (möglicherweise) positive Punkt, den ich finden konnte, ist, dass Sie die Funktionsdefinition mit grep ^ FuncName finden können. Könnte vor mehr als einem Jahrzehnt in einigen Communitys mit echtem Werkzeughass relevant gewesen sein ... An der Stelle, an der ich gesehen habe, wurde es auf C ++ - und Klassenmitglied-Funktionen angewendet, die sogar dieses Attribut zunichte machen.

Errate meine Meinung. :)


1
grep -P '^(\w+::)?FuncName'
Kyle Strand

Ja, Klassentypen in Funktionsnamen behindern diese Verwendung überhaupt nicht. Es ist also immer noch eine nützliche Sache, um schnell in den Quelldateien zu navigieren. Es sieht böse aus oder was auch immer, Meinungen sind Meinungen: Ich bin zu dem Schluss gekommen, dass es besser aussieht.
Underscore_d
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.