Un "Logger finale statico" deve essere dichiarato in MAIUSCOLO?


243

In Java, le variabili finali statiche sono costanti e la convenzione è che dovrebbero essere in maiuscolo. Tuttavia, ho visto che molte persone dichiarano i logger in minuscolo, il che costituisce una violazione di PMD .

per esempio:

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

Basta cercare su Google o SO "logger finale statico" e lo vedrai da solo.

Dovremmo usare invece LOGGER?


PMD o Checkstyle sono tentativi ingenui pre-maturi per aumentare la leggibilità ma causano più danni che benefici. Uno stile più leggibile può cambiare caso per caso in base al contesto. Vedi Guava, o JDK src, quelli non seguono alcun modello di stile rigoroso, ma realizzato da professionisti è indiscutibile. esempio: DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
Daniel Hári

Sonar Rules ( rules.sonarsource.com/java/tag/convention/RSPEC-1312 ) lo ha anche comeprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

Risposte:


306

Il riferimento del logger non è una costante, ma un riferimento finale e NON deve essere maiuscolo. Un valore costante deve essere in maiuscolo.

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

private static final double MY_CONSTANT = 0.0;

42
i riferimenti finali statici sono costanti se sono immutabili. secondo questa logica, non avresti mai stringhe costanti perché qualsiasi stringa finale statica è un riferimento.
Jeffrey Blattman,

30
Ma java.lang.String è immutabile e comunque un tipo speciale di classe (vedi String.intern (), documentazione sul pool Sring ecc.)
Aleksander Adamowski,

3
immutabile significa che lo stato dell'oggetto non può cambiare dopo la costruzione. vedi il mio post qui sotto. i logger non sono necessariamente mutabili.
Jeffrey Blattman,

4
se qualcuno continua a preoccuparsi di questo problema, si prega di condividere idee su github.com/checkstyle/checkstyle/issues/23 , per distinguere dove la domanda è maiuscola e dove no.
Roman Ivanov,

2
@Jeach non credo che l'immutabilità si preoccupi di come cambia lo stato, solo che lo fa. inoltre, cos'è un utente? l'utente esterno che esegue il programma? faresti una distinzione tra stato modificato da un utente premendo un pulsante e modificato da un timer che si attiva a intervalli casuali? (io non la penso così).
Jeffrey Blattman,

236

Per aggiungere più valore alla risposta di crunchdog, la Guida allo stile di codifica Java lo afferma nel paragrafo 3.3 Denominazione dei campi

I nomi dei campi utilizzati come costanti devono essere tutti in maiuscolo, con caratteri di sottolineatura che separano le parole. Sono considerate costanti:

  1. Tutti static finali tipi primitivi (Ricorda che tutti i campi dell'interfaccia sono intrinsecamente static final).
  2. Tutti i static finaltipi di riferimento oggetto che non sono mai seguiti da " ." (punto).
  3. Tutti gli static finalarray che non sono mai seguiti da " [" (parentesi quadra aperta).

Esempi:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

In base a questa convenzione, si loggerfa static finalriferimento a un oggetto come indicato al punto 2, ma poiché è seguito da " ." ogni volta che lo si utilizza, non può essere considerato come una costante e quindi dovrebbe essere minuscolo.


11
La migliore definizione che abbia mai visto per questo. Il documento collegato sembra essersi spostato qui l'aggiornamento cs.bilgi.edu.tr/pages/standards_project/…
robert

15
Non capisco il punto 2. Qual è un esempio di un tipo di oggetto che non è mai seguito da un punto. Tutti i tipi di oggetto ereditano Objecte puoi chiamare un metodo come .equalssu di essi.
dogbane

6
Hai ragione. E quando si osservano alcune costanti Java come Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER o Collections.EMPTY_LIST, possono anche essere seguite ..
cbliard,

5
@RomanIvanov L'ho trovato di nuovo qui: scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy scritto da Achut Reddy, ultimo aggiornamento 30 maggio 2000
cbliard

1
Credo che lo scopo di 2 sia quello di designare che solo le classi che devono essere confrontate sono considerate costanti. La classe non è pensata per essere "usata". So sempre rabbrividire quando vedo SOME_CLASS.doStuff (). È solo una codifica fugace. L'unico problema con questo è nel caso comune di un oggetto costante (String è l'esempio comune) che è inteso solo per confronto, ma per evitare controlli nulli, viene usata la codifica in stile yoda e quindi viene chiamato equals () sulla costante. Penso che farei questo avvertimento a 2.
Robin

44

Dall'efficace java, 2a edizione,

L'unica eccezione alla regola precedente riguarda i "campi costanti", i cui nomi devono essere costituiti da una o più parole maiuscole separate dal carattere di sottolineatura, ad esempio VALUES o NEGATIVE_INFINITY. Un campo costante è un campo finale statico il cui valore è immutabile . Se un campo finale statico ha un tipo primitivo o un tipo di riferimento immutabile (elemento 15), allora è un campo costante. Ad esempio, le costanti enum sono campi costanti. Se un campo finale statico ha un tipo di riferimento modificabile, può comunque essere un campo costante se l'oggetto a cui si fa riferimento è immutabile.

In sintesi, costante == finale statico, più se si tratta di un riferimento (rispetto a un tipo semplice), immutabilità.

Guardando il logger slf4j, http://www.slf4j.org/api/org/slf4j/Logger.html

È immutabile D'altra parte, il logger JUL è modificabile. Anche il logger log4j è modificabile. Quindi, per essere corretti, se stai usando log4j o JUL, dovrebbe essere "logger", e se stai usando slf4j, dovrebbe essere LOGGER.

Si noti che la pagina javadocs slf4j collegata sopra ha un esempio in cui usano "logger", non "LOGGER".

Queste sono ovviamente solo convenzioni e non regole. Se ti capita di usare slf4j e vuoi usare "logger" perché sei abituato a farlo da altri framework, o se è più facile da scrivere, o per leggibilità, vai avanti.


2
Sulla base di questo ragionamento, la definizione semplicistica di checkstyle è inappropriata, giusto?
robert

3
non so controllare le regole dello stile. se insiste semplicemente sul fatto che qualsiasi finale statico dovrebbe essere in maiuscolo, allora sì, è sbagliato.
Jeffrey Blattman,

5
In che modo l' Logger interfaccia è immutabile ? Solo un final class(come Stringo Integer) può garantire l'immutabilità. Anche se non riesci a trovare un'implementazione mutevole di SLF4J Logger, nessuno può impedirti di scriverne uno tu stesso.
Costi Ciudatu,

Perché i metodi nell'interfaccia non consentono intrinsecamente la mutazione. Hai ragione, anche se potresti implementare l'interfaccia per avere effetti collaterali mutabili.
Jeffrey Blattman,

Verifica che le regole di stile NON siano abbastanza MATURE per implicare la leggibilità. La leggibilità non può essere ottenuta modellando uno stile, la leggibilità può variare caso per caso in base al contesto. Vedi il codice JDK, non segue alcun modello di stile, e realizzato da professionisti, che mostra qualcosa.
Daniel Hári,

37

Mi piace la versione di Google ( Google Java Style )

Ogni costante è un campo finale statico, ma non tutti i campi finali statici sono costanti. Prima di scegliere il caso costante, considera se il campo sembra davvero una costante. Ad esempio, se uno qualsiasi degli stati osservabili di quell'istanza può cambiare, quasi sicuramente non è una costante. La sola intenzione di non mutare mai l'oggetto non è generalmente sufficiente.

Esempi:

// 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"};

6
Penso che la prima frase riassuma questo succintamente: "Ogni costante è un campo finale statico, ma non tutti i campi finali statici sono costanti". È facile usare il pensiero meccanico e avere solo tutti i campi statici finali in maiuscolo (e lo ho fatto fino ad ora) ma questo è da perdere la sottigliezza del linguaggio.
Ayahuasca,

Secondo quella citazione, si riduce a se il campo "si sente davvero" come una costante. Siamo ingegneri, non psichiatri.
Jeffrey Blattman,

"Considera ... se ti sembra davvero una costante". I sentimenti di qualcuno non dovrebbero davvero entrare nel campo dell'ingegneria.
Jeffrey Blattman,

Quindi nel codice di Guava lo hanno comeprivate static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Kenston Choi il

10

Se si utilizza uno strumento automatizzato per verificare gli standard di codifica e viola tali standard, è necessario fissarli. Se si utilizza uno standard esterno, correggere il codice.

La convenzione in Sun Java è maiuscola per le costanti statiche pubbliche. Ovviamente un logger non è costante, ma rappresenta una cosa mutevole (altrimenti non avrebbe senso chiamare metodi su di esso nella speranza che accada qualcosa); non esiste uno standard specifico per i campi finali non costanti.


10
Perché stai dicendo che il logger non è costante? Sembra davvero costante. La registrazione prodotta produce un effetto collaterale della chiamata dei suoi metodi, ma non cambia il suo stato osservabile. Ho dimenticato qualcosa?
KLE,

Controlla l'API. Ha una coppia di metodi add / get. Ma il tuo ragionamento è imperfetto comunque. La registrazione è osservabile (altrimenti, qual è il punto).
Tom Hawtin - tackline

3
Se fosse un StringBuilder piuttosto che un logger, sarebbe forse più ovviamente non costante. Anche per i logger, metodi come Logger.setLevel () mutano osservabilmente il ricevitore. Generalmente in maiuscolo è per quelle costanti che le lingue trattano come costanti e saranno in linea.
Pete Kirkham,

5
Il logger non è una costante in quanto è un riferimento a un oggetto. Le costanti sono valori che non possono essere modificati. Il riferimento all'oggetto è definitivo (quindi il riferimento ad esso non può essere modificato, ad esempio scambiato con qualcos'altro o impostato su null) ma l'oggetto stesso può farlo.
Spoike,

1
@JeffreyBlattman Non sono d'accordo sul fatto che tutti i riferimenti finali debbano essere in maiuscolo, ma sei libero di adottare qualunque standard di codifica ti piaccia. Mi dispiace che tu trovi confusa la differenza tra "oggetto mutabile" e "oggetto che rappresenta una cosa mutevole"; un esempio potrebbe essere il tuo numero di conto posteriore, che di per sé non cambia, ma viene utilizzato per accedere a un saldo variabile. Cerca la differenza tra significante e significato per maggiori dettagli o un'introduzione alle monadi di Leibnitz su come una cosa immutabile può rappresentare la mutabilità.
Pete Kirkham,

7

Se lo cerchi su Google, potresti scoprire che in alcuni casi i logger non sono definiti come final statici. Aggiungi un po 'di copia e incolla a questo, e questo potrebbe spiegarlo.

Usiamo LOGGER in tutto il nostro codice e questo corrisponde alla nostra convenzione di denominazione (e il nostro CheckStyle ne è soddisfatto).


Andiamo anche oltre, sfruttando la rigida convenzione di denominazione in Eclipse. Creiamo una nuova classe con un modello di codice di:

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

Il logger è commentato, poiché inizialmente non ne abbiamo bisogno. Ma dovremmo averne bisogno in un secondo momento, lo decommentiamo.

Quindi, nel codice, utilizziamo modelli di codice che prevedono che questo logger sia presente. Esempio con il modello try-catch:

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

Abbiamo alcuni altri modelli che lo usano.

La rigorosa convenzione ci consente di essere più produttivi e coerenti con i modelli di codice .


5
Catturare Throwable è una cattiva pratica, a meno che non si acceda e lo si ripeti. Ricorda gli errori: OutOfMemeoryError, ecc. L'eccezione di evento non è così sicura da essere rilevata e gestita da solo nelle applicazioni multi-thread.
m_vitaly,

2
La sintassi di Eclipse è: Logger.getLogger ($ {enclosing_type} .class);
dogbane,

@fahdshariff Grazie per la sintassi precisa. Ho aggiornato la mia risposta.
KLE,

Se le "convenzioni rigide" di CheckStyle o PMD sono d'aiuto, allora perché le fonti Guava e JDK non hanno QUALSIASI stile comune applicato? Ad esempio, la loro fonte ha molti blocchi completamente incorporati dove necessario. La leggibilità dipende dal contesto, quindi l'utilizzo di rigide convenzioni di stile per tutto distrugge le decisioni basate sul contesto, quindi diminuisce la leggibilità.
Daniel Hári,

6

Personalmente penso che sia davvero grande in maiuscolo. Inoltre, dal momento che è una classe che non è direttamente correlata al comportamento della classe, non vedo un grosso problema nell'uso loggerinvece di LOGGER. Ma se stai per essere rigorosamente pedante, allora usa LOGGER.


4

Non dimenticare che PMD rispetterà un commento con

// NOPMD

dentro. Questo farà sì che PMD salti la linea dai suoi controlli, questo ti permetterà di scegliere lo stile che desideri.


6
Oppure non usare PMD, hanno sempre torto e il tuo codice è perfetto
IAdapter,

1
Se è sempre necessario escludere un controllo ogni volta, il controllo non ha senso.
keiki

Non potrei essere più d'accordo - tuttavia ... è utile conoscere il commento di esclusione
Fortyrunner,

3

Di solito le costanti sono in maiuscolo.

I logger, tuttavia, non dovrebbero essere statici ma cercare ogni "nuovo" della classe contenente se si utilizza la facciata slf4j. Ciò evita alcuni fastidiosi problemi con il classloader in particolare i container web, inoltre consente al framework logger di fare cose speciali a seconda del contesto di invocazione.


2

Preferisco il "logger", ovvero il minuscolo. Il motivo non è che è una costante o non una costante (mutabile o immutabile). Se utilizzassimo tale ragionamento, dovremmo rinominare la variabile se cambiamo il framework di registrazione (o se il framework cambia la mutabilità dei logger).

Per me, altri motivi sono più importanti.

  1. Un logger è un oggetto ombra nella classe e non dovrebbe essere molto importante in quanto non implementa la logica principale. Se usiamo 'LOGGER', è un elemento che attira l'attenzione nel codice che attira troppa attenzione.

  2. A volte i logger sono dichiarati a livello di istanza (cioè non come statici) e persino iniettati come dipendenza. Non vorrei cambiare il mio codice se decido di cambiare il modo in cui ottengo il logger. La stabilità del codice wrt. questo (ipotetico cambiamento in molti casi) è l'altro motivo per cui preferisco il minuscolo.


1

Se i tuoi standard di codifica, se ne hai, dicono che dovrebbe essere maiuscolo allora sì.

Non vedo alcun motivo rigoroso per un modo o per l'altro. Penso che dipenda totalmente dalle tue preferenze personali. gli standard di codifica della tua azienda.

A proposito: preferisco "LOGGER" ;-)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.