Sollte in UPPER-CASE ein "statischer Endlogger" deklariert werden?

243

In Java sind statische Endvariablen Konstanten, und die Konvention lautet, dass sie in Großbuchstaben geschrieben werden sollten. Ich habe jedoch gesehen, dass die meisten Leute Logger in Kleinbuchstaben deklarieren, was einen Verstoß gegen PMD darstellt .

z.B:

private static final Logger logger = Logger.getLogger(MyClass.class);

Suchen Sie einfach in Google oder SO nach "static final logger" und Sie werden es selbst sehen.

Sollten wir stattdessen LOGGER verwenden?

Dogbane
quelle
PMD oder Checkstyle sind vorzeitige naive Versuche, die Lesbarkeit zu verbessern, aber sie verursachen mehr Schaden als Nutzen. Ein am besten lesbarer Stil kann sich je nach Kontext von Fall zu Fall ändern. Siehe Guava oder JDK src, diese folgen keiner strengen Stilvorlage, aber von Profis erstellt, ist dies unbestreitbar. Beispiel: DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
Daniel Hári
Sonar Rules ( rules.sonarsource.com/java/tag/convention/RSPEC-1312 ) hat es auch alsprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

Antworten:

306

Die Logger-Referenz ist keine Konstante, sondern eine endgültige Referenz und sollte NICHT in Großbuchstaben geschrieben werden. Ein konstanter WERT sollte in Großbuchstaben angegeben werden.

private static final Logger logger = Logger.getLogger(MyClass.class);

private static final double MY_CONSTANT = 0.0;
Crunchdog
quelle
42
statische Endreferenzen sind Konstanten, wenn sie unveränderlich sind. Nach dieser Logik würden Sie niemals konstante Zeichenfolgen haben, da jede statische endgültige Zeichenfolge eine Referenz ist.
Jeffrey Blattman
30
Aber java.lang.String ist unveränderlich und sowieso eine besondere Art von Klasse (siehe String.intern (), Dokumentation über den Sring-Pool usw.)
Aleksander Adamowski
3
unveränderlich bedeutet, dass sich der Zustand des Objekts nach dem Bau nicht ändern kann. siehe meinen Beitrag unten. Logger sind nicht unbedingt veränderbar.
Jeffrey Blattman
4
Wenn sich jemand immer noch für dieses Problem interessiert, teilen Sie uns bitte Ihre Ideen unter github.com/checkstyle/checkstyle/issues/23 mit , um zu unterscheiden, wo Großbuchstaben benötigt werden und wo nicht.
Roman Ivanov
2
@Jeach Ich glaube nicht, dass es bei der Unveränderlichkeit darum geht, wie sich der Zustand ändert, nur darum, dass dies der Fall ist. Was ist ein Benutzer? der externe Benutzer, der das Programm ausführt? Würden Sie unterscheiden, ob der Status von einem Benutzer geändert wird, der eine Taste drückt, oder ob er von einem Timer geändert wird, der in einem zufälligen Intervall ausgelöst wird? (Ich glaube nicht).
Jeffrey Blattman
235

Um der Antwort von crunchdog mehr Wert zu verleihen, wird dies im Java Coding Style Guide in Abschnitt 3.3 Feldbenennung angegeben

Die Namen der Felder, die als Konstanten verwendet werden, sollten alle in Großbuchstaben geschrieben sein, wobei die Unterstriche die Wörter trennen. Folgendes wird als Konstante betrachtet:

  1. Alle static finalprimitiven Typen (Denken Sie daran, dass alle Schnittstellenfelder von Natur aus sind static final).
  2. Alle static finalObjektreferenztypen, denen niemals " ." (Punkt) folgt .
  3. Alle static finalArrays, denen niemals " [" folgt (öffnende eckige Klammer).

Beispiele:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

Im Anschluss an diese Konvention loggerist ein static finalObjektverweis als Nummer 2 angegeben ist , sondern weil es ist von „gefolgt .“ jedes Mal wenn Sie es verwenden, kann es nicht als konstant betrachtet werden und somit sollte niedriger Fall sein.

cbliard
quelle
11
Beste Definition, die ich bisher dafür gesehen habe. Das verknüpfte Dokument scheint hierher verschoben worden zu sein. Hier ist das Update cs.bilgi.edu.tr/pages/standards_project/…
robert
15
Ich verstehe Punkt 2 nicht. Was ist ein Beispiel für einen Objekttyp, auf den niemals ein Punkt folgt? Alle Objekttypen erben von Objectund Sie können eine Methode wie .equalsauf sie aufrufen .
Dogbane
6
Du hast recht. Wenn Sie sich einige Java-Konstanten wie Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER oder Collections.EMPTY_LIST ansehen, folgen möglicherweise .auch diese.
Cbliard
5
@ RomanIvanov Ich fand es hier wieder: scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy geschrieben von Achut Reddy, letzte Aktualisierung 30. Mai 2000
cbliard
1
Ich glaube, der Zweck von 2 besteht darin, zu bezeichnen, dass nur Klassen, mit denen verglichen werden soll, als Konstanten betrachtet werden. Die Klasse soll nicht "verwendet" werden. Ich weiß immer zusammenzucken, wenn ich SOME_CLASS.doStuff () sehe. Es ist nur eine flüchtige Codierung. Das einzige Problem dabei ist der häufige Fall eines konstanten Objekts (String ist das übliche Beispiel), das nur zum Vergleich gedacht ist. Um jedoch Nullprüfungen zu vermeiden, wird eine Codierung im Yoda-Stil verwendet und daher wird equals () für die Konstante aufgerufen. Ich denke, ich würde dies die einzige Einschränkung für 2 machen.
Robin
44

Aus effektivem Java, 2. Aufl.,

Die einzige Ausnahme von der vorherigen Regel betrifft "konstante Felder", deren Namen aus einem oder mehreren Großbuchstaben bestehen sollten, die durch den Unterstrich getrennt sind, z. B. VALUES oder NEGATIVE_INFINITY. Ein konstantes Feld ist ein statisches Endfeld, dessen Wert unveränderlich ist . Wenn ein statisches Endfeld einen primitiven Typ oder einen unveränderlichen Referenztyp hat (Punkt 15), ist es ein konstantes Feld. Enum-Konstanten sind beispielsweise konstante Felder. Wenn ein statisches Endfeld einen veränderlichen Referenztyp hat, kann es immer noch ein konstantes Feld sein, wenn das referenzierte Objekt unveränderlich ist.

Zusammenfassend ist Konstante == statisches Finale plus, wenn es sich um eine Referenz (im Vergleich zu einem einfachen Typ) handelt, Unveränderlichkeit.

Schauen Sie sich den slf4j-Logger an: http://www.slf4j.org/api/org/slf4j/Logger.html

Es ist unveränderlich. Andererseits ist der JUL-Logger veränderbar. Der log4j-Logger ist ebenfalls veränderbar. Um korrekt zu sein, wenn Sie log4j oder JUL verwenden, sollte es "logger" sein, und wenn Sie slf4j verwenden, sollte es LOGGER sein.

Beachten Sie, dass die oben verlinkte javadocs-Seite slf4j ein Beispiel enthält, in dem "logger" und nicht "LOGGER" verwendet wird.

Dies sind natürlich nur Konventionen und keine Regeln. Wenn Sie zufällig slf4j verwenden und "logger" verwenden möchten, weil Sie dies von anderen Frameworks gewohnt sind, oder wenn es einfacher zu tippen oder lesbar ist, fahren Sie fort.

Jeffrey Blattman
quelle
2
Aufgrund dieser Überlegungen ist die vereinfachte Definition von checkstyle unangemessen, oder?
Robert
3
Ich kenne die Regeln des Checkstils nicht. Wenn es einfach darauf besteht, dass ein statisches Finale in Großbuchstaben geschrieben wird, dann ist das falsch.
Jeffrey Blattman
5
Wie genau ist die Logger Schnittstelle unveränderlich ? Nur ein final class(wie Stringoder Integer) kann Unveränderlichkeit garantieren. Selbst wenn Sie keine veränderbare Implementierung des SLF4J finden Logger, kann Sie niemand davon abhalten , selbst eine zu schreiben.
Costi Ciudatu
Weil die Methoden in der Schnittstelle keine Mutation von Natur aus zulassen. Sie haben Recht, obwohl Sie die Schnittstelle implementieren könnten, um veränderbare Nebenwirkungen zu haben.
Jeffrey Blattman
Überprüfungsstilregeln sind NICHT REIF genug, um die Lesbarkeit zu implizieren. Die Lesbarkeit kann nicht durch Vorlage eines Stils erreicht werden. Die Lesbarkeit kann je nach Kontext von Fall zu Fall unterschiedlich sein. Sehen Sie sich den JDK-Code an, er folgt keiner Stilvorlage und wurde von Profis erstellt, die etwas anzeigt.
Daniel Hári
37

Ich mag Googles Einstellung ( Google Java Style )

Jede Konstante ist ein statisches Endfeld, aber nicht alle statischen Endfelder sind Konstanten. Überlegen Sie sich vor der Auswahl eines konstanten Falls, ob sich das Feld wirklich wie eine Konstante anfühlt. Wenn sich beispielsweise einer der beobachtbaren Zustände dieser Instanz ändern kann, ist dies mit ziemlicher Sicherheit keine Konstante. Die bloße Absicht, das Objekt niemals zu mutieren, reicht im Allgemeinen nicht aus.

Beispiele:

// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(',');  // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
mateuscb
quelle
6
Ich denke, der erste Satz fasst dies kurz zusammen: "Jede Konstante ist ein statisches Endfeld, aber nicht alle statischen Endfelder sind Konstanten." Es ist einfach, mechanisches Denken anzuwenden und jedes statische Endfeld in Großbuchstaben zu schreiben (und das habe ich bis jetzt getan), aber dies dient dazu, die Subtilität der Sprache zu übersehen.
Ayahuasca
Nach diesem Zitat läuft es darauf hinaus, ob sich das Feld "wirklich" wie eine Konstante anfühlt. Wir sind Ingenieure, keine Psychiater.
Jeffrey Blattman
"Überlegen Sie ... ob es sich wirklich wie eine Konstante anfühlt". Jemandes Gefühle sollten wirklich nicht in den Bereich der Technik eintreten.
Jeffrey Blattman
Dann haben sie es in private static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Guavas
10

Wenn Sie ein automatisiertes Tool verwenden, um Ihre Codierungsstandards zu überprüfen, und diese gegen diese Standards verstoßen, sollten diese oder die Standards behoben werden. Wenn Sie einen externen Standard verwenden, korrigieren Sie den Code.

Die Konvention in Sun Java ist Großbuchstaben für öffentliche statische Konstanten. Offensichtlich ist ein Logger nicht konstant, sondern stellt eine veränderbare Sache dar (andernfalls wäre es sinnlos, Methoden darauf aufzurufen, in der Hoffnung, dass etwas passieren wird); Es gibt keinen spezifischen Standard für nicht konstante Endfelder.

Pete Kirkham
quelle
10
Warum sagen Sie, dass der Logger nicht konstant ist? Es scheint in der Tat konstant zu sein. Die erzeugte Protokollierung ist ein Nebeneffekt beim Aufrufen der Methoden, ändert jedoch nicht den beobachtbaren Status. Habe ich etwas verpasst?
KLE
Überprüfen Sie die API. Es gibt ein Add / Get-Methodenpaar. Aber Ihre Argumentation ist trotzdem fehlerhaft. Die Protokollierung ist beobachtbar (ansonsten, worum geht es).
Tom Hawtin - Tackline
3
Wenn es eher ein StringBuilder als ein Logger wäre, wäre es möglicherweise offensichtlicher nicht konstant. Selbst für Logger mutieren Methoden wie Logger.setLevel () den Empfänger beobachtbar. Im Allgemeinen werden Großbuchstaben für diejenigen Konstanten verwendet, die von den Sprachen als Konstanten behandelt werden und inline sind.
Pete Kirkham
5
Der Logger ist keine Konstante, da er auf ein Objekt verweist. Konstanten sind Werte, die nicht geändert werden können. Die Objektreferenz ist endgültig (daher kann die Referenz darauf nicht geändert werden, z. B. durch etwas anderes ausgetauscht oder auf null gesetzt werden), das Objekt selbst jedoch.
Spoike
1
@ JeffreyBlattman Ich stimme nicht zu, dass alle endgültigen Verweise in Großbuchstaben geschrieben werden sollten, aber Sie können beliebige Codierungsstandards übernehmen. Es tut mir leid, dass Sie den Unterschied zwischen "veränderlichem Objekt" und "Objekt, das eine veränderliche Sache darstellt" verwirrend finden. Ein Beispiel kann Ihre Rückkontonummer sein, die sich selbst nicht ändert, aber für den Zugriff auf einen variablen Kontostand verwendet wird. Suchen Sie nach dem Unterschied zwischen Signifikant und Signifikand, um weitere Einzelheiten zu erfahren, oder nach einer Einführung in Leibnitz 'Monaden, um herauszufinden, wie eine unveränderliche Sache Veränderlichkeit darstellen kann.
Pete Kirkham
7

Wenn Sie dies googeln, stellen Sie möglicherweise fest, dass die Logger in einigen Fällen nicht als statisches Finale definiert sind. Fügen Sie etwas schnelles Kopieren und Einfügen hinzu, und dies könnte es erklären.

Wir verwenden LOGGER in unserem gesamten Code, und dies entspricht unserer Namenskonvention (und unser CheckStyle ist damit zufrieden).


Wir gehen sogar noch weiter und nutzen die strenge Namenskonvention in Eclipse. Wir erstellen eine neue Klasse mit einer Codevorlage von:

    // private static final Logger LOGGER = Logger.getLogger(${enclosing_type}.class);

Der Logger ist auskommentiert, da wir ihn zunächst nicht brauchen. Aber sollten wir es später brauchen, kommentieren wir es einfach aus.

Dann verwenden wir im Code Codevorlagen, die erwarten, dass dieser Logger vorhanden ist. Beispiel mit der Try-Catch-Vorlage:

    try {
      ${cursor} or some other template
    } catch (Exception t) {
      LOGGER.error("${methodName} ${method parameters}", t);
    }

Wir haben noch ein paar Vorlagen, die es verwenden.

Die strenge Konvention ermöglicht es uns, produktiver und kohärenter mit Codevorlagen umzugehen .

KLE
quelle
5
Das Fangen von Throwable ist eine schlechte Praxis, es sei denn, Sie protokollieren und werfen es erneut. Merken Sie sich Fehler: OutOfMemeoryError usw. Die Ereignisausnahme ist nicht so sicher, dass sie in Multithread-Anwendungen von Ihnen selbst abgefangen und behandelt werden kann.
m_vitaly
2
Die Eclipse-Syntax lautet: Logger.getLogger ($ {einschließender Typ} .class);
Dogbane
@fahdshariff Danke für die genaue Syntax. Ich habe meine Antwort aktualisiert.
KLE
Wenn die "strengen Konventionen" von CheckStyle oder PMD helfen, warum haben dann Guava- und JDK-Quellen keinen gemeinsamen Stil angewendet? Zum Beispiel hat ihre Quelle bei Bedarf viele voll inline-Blöcke. Die Lesbarkeit ist kontextabhängig. Die Verwendung strenger Stilkonventionen für alles zerstört kontextbasierte Entscheidungen und verringert somit die Lesbarkeit.
Daniel Hári
6

Ich persönlich denke, dass es in Großbuchstaben wirklich groß aussieht. Da es sich um eine Klasse handelt, die nicht direkt mit dem Klassenverhalten zusammenhängt, sehe ich kein großes Problem darin, loggerstattdessen zu verwenden LOGGER. Aber wenn Sie streng pedantisch sein wollen, dann verwenden Sie LOGGER.

João Silva
quelle
4

Vergessen Sie nicht, dass PMD einen Kommentar mit respektiert

// NOPMD

drin. Dies führt dazu, dass PMD die Zeile von seinen Überprüfungen überspringt. Auf diese Weise können Sie den gewünschten Stil auswählen.

Fortyrunner
quelle
6
Oder verwenden Sie keine PMD, sie sind immer falsch und Ihr Code ist perfekt
IAdapter
1
Wenn Sie jedes Mal einen Scheck ausschließen müssen, ist der Scheck nicht sinnvoll.
Keiki
Konnte nicht mehr zustimmen - aber ... es ist nützlich, den Ausschlusskommentar zu kennen
Fortyrunner
3

Normalerweise werden Konstanten in Großbuchstaben geschrieben.

Logger sollten jedoch nicht statisch sein, sondern bei Verwendung der slf4j-Fassade nach jedem "neuen" der enthaltenen Klasse suchen. Dies vermeidet einige unangenehme Classloader-Probleme in insbesondere Webcontainern und ermöglicht es dem Logger-Framework, abhängig vom Aufrufkontext spezielle Aufgaben auszuführen.

Thorbjørn Ravn Andersen
quelle
2

Ich bevorzuge 'Logger', dh Kleinbuchstaben. Der Grund ist nicht, dass es eine Konstante oder keine Konstante ist (veränderlich oder unveränderlich). Wenn wir diese Argumentation verwenden würden, müssten wir die Variable umbenennen, wenn wir das Protokollierungsframework ändern (oder wenn das Framework die Veränderbarkeit von Protokollierern ändert).

Für mich sind andere Gründe wichtiger.

  1. Ein Logger ist ein Schattenobjekt in der Klasse und sollte nicht sehr prominent sein, da er die Hauptlogik nicht implementiert. Wenn wir 'LOGGER' verwenden, ist dies ein Blickfang im Code, der zu viel Aufmerksamkeit erregt.

  2. Manchmal werden Logger auf Instanzebene deklariert (dh nicht als statisch) und sogar als Abhängigkeit eingefügt. Ich möchte meinen Code nicht ändern, wenn ich die Art und Weise, wie ich den Logger erhalte, ändern möchte. Die Codestabilität wrt. Diese (in vielen Fällen hypothetische) Änderung ist der andere Grund, warum ich Kleinbuchstaben bevorzuge.

fml2
quelle
1

Wenn Ihre Codierungsstandards - falls vorhanden - sagen, dass sie in Großbuchstaben geschrieben werden sollten, dann ja.

Ich sehe keinen strengen Grund für die eine oder andere Weise. Ich denke, es hängt ganz von Ihren persönlichen Vorlieben ab. die Kodierungsstandards Ihres Unternehmens.

Übrigens: Ich bevorzuge "LOGGER" ;-)

Kutzi
quelle