¿Debería declararse un "Logger final estático" en MAYÚSCULAS?

243

En Java, las variables finales estáticas son constantes y la convención es que deberían estar en mayúsculas. Sin embargo, he visto que la mayoría de las personas declara a los madereros en minúsculas, lo que se considera una violación en PMD .

p.ej:

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

Simplemente busque en google o SO "logger final estático" y verá esto por sí mismo.

¿Deberíamos usar LOGGER en su lugar?

dogbane
fuente
PMD o Checkstyle son intentos ingenuos prematuros para aumentar la legibilidad pero causan más daño que beneficio. Un estilo más legible puede cambiar caso por caso según el contexto. Vea Guava, o el JDK src, esos no siguen ninguna plantilla de estilo estricta, pero hecha por profesionales es incuestionable. ejemplo: DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
Daniel Hári
Sonar Rules ( rules.sonarsource.com/java/tag/convention/RSPEC-1312 ) también lo tiene comoprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

Respuestas:

306

La referencia del registrador no es una constante, sino una referencia final, y NO debe estar en mayúscula. Un valor constante debe estar en mayúsculas.

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

private static final double MY_CONSTANT = 0.0;
crunchdog
fuente
42
Las referencias finales estáticas son constantes si son inmutables. según esta lógica, nunca tendría cadenas constantes porque cualquier cadena final estática es una referencia.
Jeffrey Blattman
30
Pero java.lang.String es inmutable y un tipo especial de clase de todos modos (ver String.intern (), documentación sobre el grupo Sring, etc.)
Aleksander Adamowski
3
inmutable significa que el estado del objeto no puede cambiar después de la construcción. mira mi post a continuación. Los registradores no son necesariamente mutables.
Jeffrey Blattman
44
Si alguien todavía se preocupa por este problema, comparta ideas en github.com/checkstyle/checkstyle/issues/23 , para distinguir dónde demanda mayúsculas y dónde no.
Roman Ivanov
2
@Jeach, no creo que la inmutabilidad se preocupe por cómo cambia el estado, solo que lo hace. además, ¿qué es un usuario? El usuario externo que ejecuta el programa? ¿haría una distinción entre el estado modificado por un usuario que presiona un botón y un temporizador disparando a intervalos aleatorios? (No lo creo).
Jeffrey Blattman
236

Para agregar más valor a la respuesta de crunchdog, la Guía de estilo de codificación de Java establece esto en el párrafo 3.3.

Los nombres de los campos que se usan como constantes deben estar en mayúsculas, con guiones bajos que separan las palabras. Los siguientes se consideran constantes:

  1. Todos static finallos tipos primitivos (recuerde que todos los campos de la interfaz son inherentemente static final).
  2. Todos los static finaltipos de referencia de objeto que nunca son seguidos por " ." (punto).
  3. Todas static final matrices que nunca van seguidas de " [" (corchete de apertura).

Ejemplos:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

Siguiendo esta convención, loggeres una static finalreferencia de objeto como se indica en el punto 2, pero debido a que es seguido por " ." cada vez que lo utilice, no se puede considerar como una constante y por lo tanto debe estar en minúsculas.

cbliard
fuente
11
La mejor definición que he visto para esto todavía. El documento vinculado parece haberse movido. Aquí está la actualización cs.bilgi.edu.tr/pages/standards_project/…
robert el
15
No entiendo el punto 2. ¿Cuál es un ejemplo de un tipo de objeto que nunca es seguido por un punto? Todos los tipos de objetos heredan Objecty puede llamar a un método como .equalsen ellos.
dogbane
66
Tienes razón. Y al mirar algunas constantes de Java como Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER o Collections.EMPTY_LIST, también pueden seguirse ..
cbliard
55
@RomanIvanov Lo encontré nuevamente aquí: scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy escrito por Achut Reddy, última actualización 30 de mayo de 2000
cbliard
1
Creo que el propósito de 2 es designar que solo las clases que se deben comparar se consideran constantes. La clase no está destinada a ser 'utilizada'. Sé que siempre me avergüenzo cuando veo SOME_CLASS.doStuff (). Es solo una codificación fugosa. El único problema con esto es en el caso común de un objeto constante (String es el ejemplo común) que solo está destinado a la comparación, pero para evitar verificaciones nulas, se usa la codificación de estilo yoda y, por lo tanto, se llama a igual () en la constante. Creo que haría de esto la única advertencia para 2.
Robin
44

De java efectivo, 2da ed.,

La única excepción a la regla anterior se refiere a "campos constantes", cuyos nombres deben consistir en una o más palabras en mayúscula separadas por el carácter de subrayado, por ejemplo, VALUES o NEGATIVE_INFINITY. Un campo constante es un campo final estático cuyo valor es inmutable . Si un campo final estático tiene un tipo primitivo o un tipo de referencia inmutable (Elemento 15), entonces es un campo constante. Por ejemplo, las constantes enum son campos constantes. Si un campo final estático tiene un tipo de referencia mutable, aún puede ser un campo constante si el objeto referenciado es inmutable.

En resumen, constante == final estático, más si es una referencia (frente a un tipo simple), inmutabilidad.

Mirando el registrador slf4j, http://www.slf4j.org/api/org/slf4j/Logger.html

Es inmutable. Por otro lado, el registrador JUL es mutable. El log4j logger también es mutable. Para ser correcto, si está utilizando log4j o JUL, debería ser "logger", y si está utilizando slf4j, debería ser LOGGER.

Tenga en cuenta que la página slf4j javadocs vinculada anteriormente tiene un ejemplo en el que usan "logger", no "LOGGER".

Por supuesto, estas son solo convenciones y no reglas. Si está utilizando slf4j y desea utilizar "logger" porque está acostumbrado a eso desde otros marcos, o si es más fácil de escribir, o para facilitar la lectura, continúe.

Jeffrey Blattman
fuente
2
Basado en este razonamiento, la definición simplista de checkstyle es inapropiada, ¿verdad?
robert el
3
No sé verificar las reglas de estilo. si simplemente insiste en que cualquier final estático debe estar en mayúscula, entonces sí, eso está mal.
Jeffrey Blattman
55
¿Cómo es exactamente la Logger interfaz inmutable ? Solo un final class(me gusta Stringo Integer) puede garantizar la inmutabilidad. Incluso si no puede encontrar ninguna implementación mutable del SLF4J Logger, nadie puede evitar que escriba uno usted mismo.
Costi Ciudatu
Porque los métodos en la interfaz no permiten la mutación inherentemente. Tiene razón, aunque podría implementar la interfaz para tener efectos secundarios mutables.
Jeffrey Blattman
Las reglas de verificación de estilo NO SON MADURAS para implicar legibilidad. La legibilidad no se puede lograr al crear un estilo, la legibilidad puede diferir caso por caso según el contexto. Vea el código JDK, no sigue ninguna plantilla de estilo, y está hecho por profesionales, que muestra algo.
Daniel Hári
37

Me gusta la versión de Google ( Google Java Style )

Cada constante es un campo final estático, pero no todos los campos finales estáticos son constantes. Antes de elegir un caso constante, considere si el campo realmente se siente como una constante. Por ejemplo, si cualquiera de los estados observables de esa instancia puede cambiar, es casi seguro que no es una constante. La simple intención de nunca mutar el objeto generalmente no es suficiente.

Ejemplos:

// 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
fuente
66
Creo que la primera oración resume esto sucintamente: "Toda constante es un campo final estático, pero no todos los campos finales estáticos son constantes". Es fácil usar el pensamiento mecánico y solo tener todos los campos finales estáticos en mayúsculas (y he estado haciendo esto hasta ahora), pero esto es perder la sutileza del lenguaje.
ayahuasca
Según esa cita, se reduce a si el campo "realmente se siente" como una constante. Somos ingenieros, no psiquiatras.
Jeffrey Blattman
"Considera ... si realmente se siente como una constante". Los sentimientos de alguien realmente no deberían entrar en el campo de la ingeniería.
Jeffrey Blattman
Luego, en el código de Guava, lo tienen comoprivate static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Kenston Choi
10

Si está utilizando una herramienta automatizada para verificar sus estándares de codificación y viola dichos estándares, entonces o los estándares deben ser reparados. Si está utilizando un estándar externo, arregle el código.

La convención en Sun Java es mayúscula para las constantes estáticas públicas. Obviamente, un registrador no es constante, pero representa una cosa mutable (de lo contrario, no tendría sentido invocar métodos con la esperanza de que algo suceda); No existe un estándar específico para los campos finales no constantes.

Pete Kirkham
fuente
10
¿Por qué estás diciendo que el registrador no es constante? Parece constante de hecho. El registro se produce es un efecto secundario de llamar a sus métodos, pero no cambie su estado observable. ¿Me he perdido algo?
KLE
Revisa la API. Tiene un par de métodos add / get. Pero tu razonamiento es defectuoso de todos modos. El registro es observable (de lo contrario, cuál es el punto).
Tom Hawtin - tackline
3
Si se tratara de un StringBuilder en lugar de un registrador, entonces sería más obvio que no es constante. Incluso para los registradores, métodos como Logger.setLevel () mutan el receptor de manera observable. Generalmente mayúscula es para aquellas constantes que los lenguajes tratan como constantes y estarán en línea.
Pete Kirkham el
55
El registrador no es una constante, ya que es una referencia a un objeto. Las constantes son valores que no se pueden cambiar. La referencia del objeto es final (por lo que la referencia no se puede cambiar, por ejemplo, se intercambia con otra cosa o se establece en nulo), pero el objeto en sí sí.
Spoike
1
@JeffreyBlattman No estoy de acuerdo con que todas las referencias finales sean mayúsculas, pero usted es libre de adoptar los estándares de codificación que desee. Lamento que encuentre confusa la diferencia entre 'objeto mutable' y 'objeto que representa una cosa mutable'; Un ejemplo puede ser su número de cuenta atrás, que en sí mismo no cambia, pero se utiliza para acceder a un saldo variable. Busque la diferencia entre significante y significado para obtener más detalles, o una introducción a las mónadas de Leibnitz sobre cómo una cosa inmutable puede representar la mutabilidad.
Pete Kirkham el
7

Si googleas esto, es posible que en algunos casos, los registradores no estén definidos como estáticos finales. Agregue un poco de copiar y pegar a esto, y esto podría explicarlo.

Usamos LOGGER en todo nuestro código, y esto corresponde a nuestra convención de nomenclatura (y nuestro CheckStyle está contento con eso).


Incluso vamos más allá, aprovechando la estricta convención de nomenclatura en Eclipse. Creamos una nueva clase con una plantilla de código de:

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

El registrador está comentado, ya que inicialmente no lo necesitamos. Pero si lo necesitamos más tarde, simplemente lo descomentamos.

Luego, en el código, usamos plantillas de código que esperan que este registrador esté presente. Ejemplo con la plantilla try-catch:

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

Tenemos algunas plantillas más que lo usan.

La convención estricta nos permite ser más productivos y coherentes con las plantillas de código .

KLE
fuente
55
Catching Throwable es una mala práctica, a menos que lo registres y lo vuelvas a lanzar. Recordar errores: OutOfMemeoryError, etc. La excepción de evento no es tan segura de ser atrapada y manejada por usted mismo en aplicaciones de subprocesos múltiples.
m_vitaly
2
La sintaxis de Eclipse es: Logger.getLogger ($ {enclosing_type} .class);
dogbane
@fahdshariff Gracias por la sintaxis precisa. Actualicé mi respuesta.
KLE
Si las "convenciones estrictas" de CheckStyle o PMD ayudan, entonces ¿por qué las fuentes Guava y JDK no tienen NINGÚN estilo común aplicado? Por ejemplo, su fuente tiene muchos bloques en línea completos donde sea necesario. La legibilidad depende del contexto, por lo que el uso de convenciones de estilo estrictas para todo destruye las decisiones basadas en el contexto, por lo que disminuye la legibilidad.
Daniel Hári
6

Personalmente, creo que se ve muy grande en mayúsculas. Además, dado que es una clase que no está directamente relacionada con el comportamiento de la clase, no veo un problema importante en el uso en loggerlugar de LOGGER. Pero si vas a ser estrictamente pedante, entonces úsalo LOGGER.

João Silva
fuente
4

No olvides que PMD respetará un comentario con

// NOPMD

en eso. Esto hará que PMD omita la línea de sus controles, esto le permitirá elegir el estilo que desee.

Fortyrunner
fuente
66
O el uso Dont PMD, que siempre están mal y su código es perfecto
iadapter
1
Si siempre necesita excluir un cheque cada vez, entonces el cheque no tiene sentido.
keiki
No podría estar más de acuerdo, sin embargo ... es útil saber el comentario de exclusión
Fortyrunner
3

Por lo general, las constantes están en mayúsculas.

Sin embargo, los registradores no deben ser estáticos, sino que deben buscar cada "nuevo" de la clase que los contiene si se usa la fachada slf4j. Esto evita algunos problemas desagradables del cargador de clases en contenedores web, además, permite que el marco del registrador haga cosas especiales dependiendo del contexto de invocación.

Thorbjørn Ravn Andersen
fuente
2

Prefiero 'logger', es decir, la minúscula. La razón no es que sea una constante o no una constante (mutable o inmutable). Si usáramos ese razonamiento, tendríamos que cambiar el nombre de la variable si cambiamos el marco de registro (o si el marco cambia la mutabilidad de los registradores).

Para mí, otras razones son más importantes.

  1. Un registrador es un objeto sombra en la clase y no debe ser muy prominente ya que no implementa la lógica principal. Si usamos 'LOGGER', es un punto de atracción en el código que atrae demasiada atención.

  2. A veces, los registradores se declaran a nivel de instancia (es decir, no como estáticos) e incluso se inyectan como una dependencia. No me gustaría cambiar mi código si decido cambiar la forma en que obtengo el registrador. El código de estabilidad wrt. Este cambio (hipotético en muchos casos) es la otra razón por la que prefiero la minúscula.

fml2
fuente
1

Si sus estándares de codificación, si tiene alguno, diga que debe estar en mayúscula, entonces sí.

No veo ninguna razón estricta de una manera u otra. Creo que depende totalmente de tus gustos personales resp. los estándares de codificación de su empresa.

Por cierto: prefiero "LOGGER" ;-)

Kutzi
fuente