Namenskonvention: Endgültige Felder (nicht statisch)

23

Heute hatte ich eine Diskussion mit einem Mitarbeiter über die Benennung von finalFeldern in Java-Klassen.

In seiner Sichtweise finalsollten Felder auch als Konstanten betrachtet werden, da sich ihre Werte nach dem Erstellen der Instanz nicht ändern.

Dies würde zu der folgenden Namenskonvention für finalFelder führen:

public class Foo {
    private static final String BLA_BLA = "bla";

    private final String BAR_BATZ;

    ...
}

Meiner Meinung nach sollten nur static finalFelder als Konstanten betrachtet werden, während Felder, die nur finalsind, der üblichen camelCase-Namenskonvention folgen sollten.

public class Foo {
    private static final String BLA = "bla";

    private final String barBatz;

    ...
}

Jetzt bin ich ein bisschen unsicher, da er ein weitaus erfahrenerer Programmierer ist als ich, und ich stimme normalerweise seiner Meinung zu und betrachte ihn als einen sehr guten Entwickler.

Irgendwelche Eingaben dazu?

Sascha Wolf
quelle
Ihre Beispiele sind keine Konstanten; Sie haben ihnen zum Zeitpunkt der Kompilierung keine Werte zugewiesen. Ergo folgen sie nicht den Namenskonventionen für Konstanten.
Robert Harvey
@RobertHarvey Danke, du hast recht. Das ...sollte jeden möglichen Konstruktor symbolisieren, der das finalFeld setzt, aber das ist für das static finalFeld offensichtlich nicht möglich .
Sascha Wolf
1
@Zeeker Sie interessieren sich vielleicht für die static { }Blöcke, mit denen statische Felder innerhalb einer Klasse einmalig beim Laden der Klasse gesetzt werden können. Verwandte Arbeiten mit statischen Konstruktoren in Java .
@ Robert Harvey Ich kenne mich mit denen aus. Trotzdem vielen Dank.
Sascha Wolf
1
Da die Variable zu einer Instanz gehört, unterscheidet sie sich von Instanz zu Instanz, sodass sie nicht als Konstante gilt. Ich würde Kamelkasten benutzen.
Florian F

Antworten:

20

Sun (und jetzt Oracle) haben ein Dokument mit dem Titel " Code Conventions for the Java Programming Language" (Codekonventionen für die Java-Programmiersprache ) gepflegt . Das letzte Update dazu war '99, aber die Essenz der Stilrichtlinie lebt weiter.

Kapitel 9 behandelt Namenskonventionen.

Für einen Bezeichnertyp von 'Konstanten':

Die Namen der als Klassenkonstanten deklarierten Variablen und der ANSI-Konstanten sollten in Großbuchstaben mit durch Unterstriche ("_") getrennten Wörtern angegeben werden. (ANSI-Konstanten sollten vermieden werden, um das Debuggen zu vereinfachen.)

Die angeführten Beispiele:

static final int MIN_WIDTH = 4;

static final int MAX_WIDTH = 999;

static final int GET_THE_CPU = 1;

In einem neueren Dokument ist es eingedrungen. Aus Variablen (Die Java-Tutorials> Lernen der Java-Sprache> Sprachgrundlagen :

Wenn der von Ihnen gewählte Name nur aus einem Wort besteht, buchstabieren Sie dieses Wort in Kleinbuchstaben. Wenn es aus mehr als einem Wort besteht, schreiben Sie den ersten Buchstaben jedes nachfolgenden Wortes in Großbuchstaben. Die Namen gearRatiound currentGearsind Paradebeispiele für diese Konvention. Wenn Ihre Variable einen konstanten Wert speichert, wie z. B. static final int NUM_GEARS = 6, ändert sich die Konvention geringfügig, wobei jeder Buchstabe in Großbuchstaben geschrieben und nachfolgende Wörter mit dem Unterstrich getrennt werden. Gemäß der Konvention wird der Unterstrich an keiner anderen Stelle verwendet.

Viele statische Analysatoren für Java versuchen dies zu erzwingen. Zum Beispiel Checkstyle erzwingt:

Überprüft, ob die Namen der Konstanten einem Format entsprechen, das in der format-Eigenschaft angegeben ist. Eine Konstante ist ein statisches und endgültiges Feld oder ein Schnittstellen- / Anmerkungsfeld mit Ausnahme von serialVersionUIDund serialPersistentFields. Das Format ist ein regulärer Ausdruck und hat den Standardwert ^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$.


Das läuft wirklich auf die Konventionen der Community hinaus, die den Code schreiben ... und ihn im Idealfall beibehalten.

Die obigen Beispiele sind als static finalsolche angegeben , die wahrscheinlich von den C-Konventionen für abgeleitet sind #define- die wie C während der Kompilierung und nicht zur Laufzeit im Code ersetzt werden.

Die Frage, die dann gestellt werden sollte, lautet: "Verhält sich das wie eine Konstante? Oder verhält es sich wie ein Feld zum einmaligen Schreiben?" - und dann die Konventionen entsprechend befolgen. Der Lackmustest für eine solche Frage wäre "Wenn Sie das Objekt serialisieren würden, würden Sie das letzte Feld einschließen?". Wenn die Antwort lautet, dass es sich um eine Konstante handelt, behandeln Sie sie als solche (und serialisieren Sie sie nicht). Auf der anderen Seite ist es keine Konstante, wenn es Teil des Zustands des Objekts ist, der serialisiert werden müsste.

In jedem Fall ist es wichtig, den Code-Stil beizubehalten, so richtig oder falsch er auch sein mag. Aus inkonsistenten Konventionen innerhalb eines Projekts entstehen schlimmere Probleme als nur etwas, das das Auge verletzt. Erwägen Sie, statische Analysetools zu erwerben und diese so zu konfigurieren, dass die Konsistenz erhalten bleibt.


quelle
@RobertHarvey Ich könnte mir Situationen vorstellen, in denen sich ein Instanzfeld wie eine Konstante verhält. Eine Fabrik zum Beispiel, die etwas bevölkert, was sonst eine Konstante im Objekt wäre ... obwohl es sich dabei um ziemlich ausgeklügelte Beispiele handelt, die mir den Kopf verletzen, wenn ich nur darüber nachdenke, warum man das tun würde.
Danke für diese ausführliche Antwort. Der Lackmustest über die Serialisierung des Objekts machte den Deal für mich.
Sascha Wolf
Ein Kollege sagte kürzlich, dass die Redakteure früher nicht sehr gut darin waren, statische / statische Endergebnisse usw. hervorzuheben, weshalb diese Namenskonvention wichtig war. Heutzutage sind IDEs ziemlich gut, so dass wir vielleicht schönere Namen für sie machen können, zB: MinWidthstatt MIN_WIDTH. Eine andere Frage ist: Was ist mit statischen Endloggern? Nennen Sie sie LOG/ LOGGERoder log/ logger. Persönlich logsieht es im Code besser aus, aber wann ist Inkonsistenz akzeptabel, wenn überhaupt?
ndtreviv
5

BAR_BATZist in diesem Beispiel keine Konstante. Die Konstruktoren von Fookönnen es auf Objektebene auf unterschiedliche Werte setzen. Beispielsweise

public class Foo {
    private final String BAR_BATZ;

    Foo() {
       BAR_BATZ = "ascending";
    } 

    Foo(String barBatz) {
       BAR_BATZ = barBatz;
    }
}
Kirby
quelle