Un «enregistreur final statique» doit-il être déclaré en MAJUSCULE?

243

En Java, les variables finales statiques sont des constantes et la convention est qu'elles doivent être en majuscules. Cependant, j'ai vu que la plupart des gens déclarent les enregistreurs en minuscules, ce qui constitue une violation dans PMD .

par exemple:

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

Recherchez simplement sur Google ou SO pour "enregistreur final statique" et vous le verrez par vous-même.

Devrions-nous plutôt utiliser LOGGER?

dogbane
la source
PMD ou Checkstyle sont des tentatives naïves prématurées d'augmenter la lisibilité, mais elles causent plus de tort que d'avantages. Un style plus lisible peut changer au cas par cas en fonction du contexte. Voir Guava, ou le JDK src, ceux-ci ne suivent aucun modèle de style strict, mais fabriqués par des professionnels, c'est incontestable. exemple: DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
Daniel Hári
Sonar Rules ( rules.sonarsource.com/java/tag/convention/RSPEC-1312 ) l'a également commeprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

Réponses:

306

La référence de l'enregistreur n'est pas une constante, mais une référence finale et ne doit PAS être en majuscules. Une VALEUR constante doit être en majuscules.

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

private static final double MY_CONSTANT = 0.0;
crunchdog
la source
42
les références finales statiques sont des constantes si elles sont immuables. selon cette logique, vous n'auriez jamais de chaînes constantes car toute chaîne finale statique est une référence.
Jeffrey Blattman
30
Mais java.lang.String est immuable et un type spécial de classe de toute façon (voir String.intern (), documentation sur le pool Sring, etc.)
Aleksander Adamowski
3
immuable signifie que l'état de l'objet ne peut pas changer après la construction. voir mon post ci-dessous. les enregistreurs ne sont pas nécessairement modifiables.
Jeffrey Blattman
4
si quelqu'un se soucie toujours de ce problème, veuillez partager vos idées sur github.com/checkstyle/checkstyle/issues/23 , pour distinguer où la demande est en majuscules et où non.
Roman Ivanov
2
@Jeach, je ne pense pas que l'immuabilité se préoccupe de la façon dont l'état change, seulement ce qu'il fait. de plus, qu'est-ce qu'un utilisateur? l'utilisateur externe exécutant le programme? feriez-vous une distinction entre l'état modifié par un utilisateur en appuyant sur un bouton et celui-ci étant modifié par une minuterie tirant à un intervalle aléatoire? (je ne pense pas).
Jeffrey Blattman
236

Pour ajouter plus de valeur à la réponse de crunchdog, le Java Coding Style Guide l' indique au paragraphe 3.3 Attribution d'un nom de champ

Les noms des champs utilisés comme constantes doivent être en majuscules, avec des traits de soulignement séparant les mots. Les éléments suivants sont considérés comme des constantes:

  1. Tous static finalles types primitifs (n'oubliez pas que tous les champs d'interface sont intrinsèquement static final).
  2. Tous static finalles types de référence d'objet qui ne sont jamais suivis de " ." (point).
  3. Tous les static finaltableaux qui ne sont jamais suivis de " [" (ouverture du crochet carré).

Exemples:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

Suivant cette convention, loggerest une static finalréférence d'objet comme indiqué au point 2, mais parce qu'elle est suivie par " ." chaque fois que vous l'utilisez, elle ne peut pas être considérée comme une constante et doit donc être en minuscules.

cbliard
la source
11
La meilleure définition que j'ai jamais vue pour ça. Le document lié semble avoir bougé, voici la mise à jour cs.bilgi.edu.tr/pages/standards_project/…
robert
15
Je n'obtiens pas le point 2. Qu'est-ce qu'un exemple d'un type d'objet qui n'est jamais suivi d'un point. Tous les types d'objets héritent de Objectet vous pouvez appeler une méthode comme celle- .equalsci.
dogbane
6
Vous avez raison. Et lorsque vous regardez certaines constantes Java comme Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER ou Collections.EMPTY_LIST, elles peuvent également être suivies ..
cbliard
5
@RomanIvanov Je l'ai retrouvé ici: scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy écrit par Achut Reddy, dernière mise à jour le 30 mai 2000
cbliard
1
Je crois que le but de 2 est de désigner que seules les classes qui sont censées être comparées sont considérées comme des constantes. La classe n'est pas destinée à être «utilisée». Je sais toujours grincer des dents quand je vois SOME_CLASS.doStuff (). C'est juste un codage extravagant. Le seul problème avec cela est dans le cas commun d'un objet constant (String étant l'exemple commun) qui est uniquement destiné à la comparaison, mais pour éviter les vérifications nulles, le codage de style yoda est utilisé et donc égal () est appelé sur la constante. Je pense que j'en ferais la seule mise en garde à 2.
Robin
44

De java efficace, 2e éd.,

La seule exception à la règle précédente concerne les «champs constants», dont les noms doivent consister en un ou plusieurs mots en majuscules séparés par le caractère de soulignement, par exemple, VALEURS ou NEGATIVE_INFINITY. Un champ constant est un champ final statique dont la valeur est immuable . Si un champ final statique a un type primitif ou un type de référence immuable (article 15), alors c'est un champ constant. Par exemple, les constantes enum sont des champs constants. Si un champ final statique a un type de référence mutable, il peut toujours être un champ constant si l'objet référencé est immuable.

En résumé, constante == statique finale, plus s'il s'agit d'une référence (par rapport à un type simple), l'immuabilité.

En regardant l'enregistreur slf4j, http://www.slf4j.org/api/org/slf4j/Logger.html

C'est immuable. D'un autre côté, l'enregistreur JUL est modifiable. L'enregistreur log4j est également modifiable. Donc pour être correct, si vous utilisez log4j ou JUL, ce devrait être "logger", et si vous utilisez slf4j, ce devrait être LOGGER.

Notez que la page javadocs slf4j liée ci-dessus a un exemple où ils utilisent "logger", pas "LOGGER".

Ce ne sont bien sûr que des conventions et non des règles. Si vous utilisez slf4j et que vous souhaitez utiliser "logger" parce que vous êtes habitué à celui d'autres frameworks, ou s'il est plus facile à taper, ou pour plus de lisibilité, allez-y.

Jeffrey Blattman
la source
2
Sur la base de ce raisonnement, la définition simpliste de checkstyle est inappropriée, n'est-ce pas?
robert
3
je ne connais pas les règles de style. s'il insiste simplement sur le fait que toute finale statique doit être en majuscules, alors oui, c'est faux.
Jeffrey Blattman
5
Comment l' Logger interface est-elle immuable ? Seul un final class(comme Stringou Integer) peut garantir l'immuabilité. Même si vous ne trouvez aucune implémentation mutable du SLF4J Logger, personne ne peut vous empêcher d'en écrire une vous-même.
Costi Ciudatu
Parce que les méthodes de l'interface ne permettent pas de mutation intrinsèquement. Vous avez raison, bien que vous puissiez implémenter l'interface pour avoir des effets secondaires modifiables.
Jeffrey Blattman
Vérifiez que les règles de style NE SONT PAS suffisamment MATURES pour impliquer la lisibilité. La lisibilité ne peut pas être obtenue en modélisant un style, la lisibilité peut différer au cas par cas en fonction du contexte. Voir le code JDK, il ne suit aucun modèle de style, et fait par des professionnels, qui montre quelque chose.
Daniel Hári
37

J'aime l'approche de Google ( Google Java Style )

Chaque constante est un champ final statique, mais tous les champs finaux statiques ne sont pas des constantes. Avant de choisir un cas constant, demandez-vous si le champ ressemble vraiment à une constante. Par exemple, si l'un des états observables de cette instance peut changer, ce n'est certainement pas une constante. L'intention de ne jamais muter l'objet n'est généralement pas suffisante.

Exemples:

// 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
la source
6
Je pense que la première phrase résume bien ceci: "Chaque constante est un champ final statique, mais tous les champs finaux statiques ne sont pas des constantes." Il est facile d'utiliser la pensée mécanique et juste d'avoir tous les champs finaux statiques en majuscules (et je l'ai fait jusqu'à présent), mais c'est manquer la subtilité du langage.
ayahuasca
Selon cette citation, cela se résume à si le champ "se sent vraiment" comme une constante. Nous sommes des ingénieurs, pas des psychiatres.
Jeffrey Blattman
"Considérez ... si cela ressemble vraiment à une constante". Les sentiments de quelqu'un ne devraient vraiment pas entrer dans le domaine de l'ingénierie.
Jeffrey Blattman
Ensuite, dans le code de Guava, ils l'ont commeprivate static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Kenston Choi
10

Si vous utilisez un outil automatisé pour vérifier vos normes de codage et qu'il viole lesdites normes, alors il ou les normes doivent être corrigées. Si vous utilisez un standard externe, corrigez le code.

La convention dans Sun Java est en majuscule pour les constantes statiques publiques. De toute évidence, un enregistreur n'est pas constant, mais représente une chose mutable (sinon il n'y aurait aucun intérêt à appeler des méthodes dessus dans l'espoir que quelque chose se produise); il n'y a pas de norme spécifique pour les champs finaux non constants.

Pete Kirkham
la source
10
Pourquoi dites-vous que l'enregistreur n'est pas constant? Cela semble en effet constant. La journalisation est produite est un effet secondaire de l'appel de ses méthodes, mais ne changez pas son état observable. Ai-je oublié quelque chose?
KLE
Vérifiez l'API. Il a une paire add / get de méthodes. Mais votre raisonnement est de toute façon imparfait. La journalisation est observable (sinon, à quoi ça sert).
Tom Hawtin - tackline
3
S'il s'agissait d'un StringBuilder plutôt que d'un enregistreur, alors ce serait peut-être plus évidemment non constant. Même pour les enregistreurs, des méthodes telles que Logger.setLevel () mutent le récepteur de manière observable. Généralement, les majuscules désignent les constantes que les langues traitent comme des constantes et seront alignées.
Pete Kirkham
5
L'enregistreur n'est pas une constante car c'est une référence à un objet. Les constantes sont des valeurs qui ne peuvent pas être modifiées. La référence d'objet est finale (donc la référence à elle ne peut pas être modifiée, par exemple échangée avec quelque chose d'autre ou définie sur null), mais l'objet lui-même peut.
Spoike
1
@JeffreyBlattman Je ne suis pas d'accord pour que toutes les références finales soient en majuscules, mais vous êtes libre d'adopter les normes de codage que vous souhaitez. Je suis désolé que vous trouviez la différence entre «objet mutable» et «objet qui représente une chose mutable» déroutant; un exemple peut être votre numéro de compte arrière, qui lui-même ne change pas, mais est utilisé pour accéder à un solde variable. Recherchez la différence entre signifiant et signifiant pour plus de détails, ou une introduction aux monades de Leibnitz pour savoir comment une chose immuable peut représenter la mutabilité.
Pete Kirkham
7

Si vous effectuez une recherche sur Google, vous constaterez peut-être que, dans certains cas, les enregistreurs ne sont pas définis comme statiques finaux. Ajoutez un peu de copier-coller rapide à cela, et cela pourrait l'expliquer.

Nous utilisons LOGGER dans tout notre code, ce qui correspond à notre convention de dénomination (et notre CheckStyle en est satisfait).


Nous allons même plus loin, en profitant de la convention de dénomination stricte d'Eclipse. Nous créons une nouvelle classe avec un modèle de code de:

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

L'enregistreur est commenté, car au départ nous n'en avons pas besoin. Mais si nous en avons besoin plus tard, nous le décommentons simplement.

Ensuite, dans le code, nous utilisons des modèles de code qui s'attendent à ce que cet enregistreur soit présent. Exemple avec le modèle try-catch:

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

Nous avons quelques autres modèles qui l'utilisent.

La convention stricte nous permet d'être plus productifs et cohérents avec les modèles de code .

KLE
la source
5
Catching Throwable est une mauvaise pratique, sauf si vous vous connectez et la relancez. N'oubliez pas les erreurs: OutOfMemeoryError, etc. L'exception d'événement n'est pas si sûre d'être interceptée et gérée par vous-même dans des applications multi-thread.
m_vitaly
2
La syntaxe Eclipse est: Logger.getLogger ($ {enclosing_type} .class);
dogbane
@fahdshariff Merci pour la syntaxe précise. J'ai mis à jour ma réponse.
KLE
Si les «conventions strictes» de CheckStyle ou de PMD sont utiles, alors pourquoi les sources Guava et JDK n'ont AUCUN style commun appliqué? Par exemple, leur source contient de nombreux blocs intégrés complets, le cas échéant. La lisibilité dépend du contexte, donc l'utilisation de conventions de style strictes pour tout détruit les décisions basées sur le contexte, ce qui diminue la lisibilité.
Daniel Hári
6

Personnellement, je pense que ça a l'air vraiment gros en majuscules. De plus, comme c'est une classe qui n'est pas directement liée au comportement de la classe, je ne vois pas de problème majeur à utiliser à la loggerplace de LOGGER. Mais si vous allez être strictement pédant, utilisez-le LOGGER.

João Silva
la source
4

N'oubliez pas que PMD respectera un commentaire avec

// NOPMD

en elle. Cela entraînera PMD à sauter la ligne de ses vérifications, cela vous permettra de choisir le style que vous souhaitez.

Fortyrunner
la source
6
Ou n'utilisez pas PMD, ils ont toujours tort et votre code est parfait
IAdapter
1
Si vous devez toujours exclure un chèque à chaque fois, alors le chèque n'a pas de sens.
keiki
Je ne pourrais pas être plus d'accord - cependant ... il est utile de connaître le commentaire d'exclusion
Fortyrunner
3

Habituellement, les constantes sont en majuscules.

Les enregistreurs, cependant, ne doivent pas être statiques mais recherchent chaque "nouveau" de la classe contenante si vous utilisez la façade slf4j. Cela évite certains problèmes de chargeur de classe désagréables dans des conteneurs Web notamment, et permet au framework de journalisation de faire des choses spéciales en fonction du contexte d'appel.

Thorbjørn Ravn Andersen
la source
2

Je préfère «logger», c'est-à-dire les minuscules. La raison n'est pas que c'est une constante ou pas une constante (mutable ou immuable). Si nous utilisons ce raisonnement, nous devons renommer la variable si nous modifions le cadre de journalisation (ou si le cadre modifie la mutabilité des enregistreurs).

Pour moi, d'autres raisons sont plus importantes.

  1. Un enregistreur est un objet fantôme dans la classe et ne doit pas être très visible car il n'implémente pas la logique principale. Si nous utilisons 'LOGGER', c'est un accroche-regard dans le code qui attire trop d'attention.

  2. Parfois, les enregistreurs sont déclarés au niveau de l'instance (c'est-à-dire qu'ils ne sont pas statiques) et sont même injectés en tant que dépendance. Je ne voudrais pas changer mon code si je décide de changer la façon dont j'obtiens l'enregistreur. La stabilité du code wrt. ce changement (hypothétique dans de nombreux cas) est l'autre raison pour laquelle je préfère les minuscules.

fml2
la source
1

Si vos normes de codage - si vous en avez - disent qu'il devrait être en majuscules, alors oui.

Je ne vois aucune raison rigoureuse d'une manière ou d'une autre. Je pense que cela dépend totalement de vos goûts personnels resp. les normes de codage de votre entreprise.

BTW: je préfère "LOGGER" ;-)

Kutzi
la source