Um "Logger final estático" deve ser declarado em MAIÚSCULAS?

243

Em Java, as variáveis ​​finais estáticas são constantes e a convenção é que elas devem estar em maiúsculas. No entanto, vi que a maioria das pessoas declara loggers em letras minúsculas, o que aparece como uma violação no PMD .

por exemplo:

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

Basta pesquisar no google ou no SO por "logger final estático" e você verá isso por si mesmo.

Em vez disso, deveríamos estar usando LOGGER?

dogbane
fonte
PMD ou Checkstyle são tentativas ingênuas pré-maduras de aumentar a legibilidade, mas causam mais danos do que benefícios. Um estilo mais legível pode mudar caso a caso com base no contexto. Veja Guava, ou o JDK src, que não segue nenhum modelo de estilo rigoroso, mas feito por profissionais é inquestionável. exemplo: DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
Daniel Hári
Regras do sonar ( rules.sonarsource.com/java/tag/convention/RSPEC-1312 ) também o tem comoprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

Respostas:

306

A referência do criador de logs não é uma constante, mas uma referência final e NÃO deve estar em maiúsculas. Um valor constante deve estar em maiúsculas.

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

private static final double MY_CONSTANT = 0.0;
crunchdog
fonte
42
referências finais estáticas são constantes se forem imutáveis. por essa lógica, você nunca teria seqüências constantes porque qualquer sequência final estática é uma referência.
Jeffrey Blattman
30
Mas java.lang.String é imutável e um tipo especial de classe de qualquer maneira (ver String.intern (), documentação sobre a piscina Sring etc.)
Aleksander Adamowski
3
imutável significa que o estado do objeto não pode mudar após a construção. veja meu post abaixo. madeireiros não são necessariamente mutáveis.
Jeffrey Blattman
4
se alguém ainda se importa com esse problema, compartilhe idéias em github.com/checkstyle/checkstyle/issues/23 , para distinguir onde a demanda é maiúscula e aonde não.
Roman Ivanov
2
@Each: Eu não acho que a imutabilidade esteja preocupada com a forma como o estado muda, só que ele muda. além disso, o que é um usuário? o usuário externo executando o programa? você faria uma distinção entre estado sendo modificado por um usuário pressionando um botão e modificado por um timer disparando em algum intervalo aleatório? (Acho que não).
11138 Jeffrey Blattman em 13/03
236

Para adicionar mais valor à resposta do crunchdog, o Java Coding Style Guide declara isso no parágrafo 3.3 Nomeação de campo

Os nomes dos campos usados ​​como constantes devem estar em maiúsculas, com sublinhados separando as palavras. As seguintes são consideradas constantes:

  1. Todos static finalos tipos primitivos (lembre-se de que todos os campos da interface são inerentemente static final).
  2. Todos static finalos tipos de referência de objeto que nunca são seguidos por " ." (ponto).
  3. Todas as static finalmatrizes que nunca são seguidas por " [" (colchete de abertura).

Exemplos:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

Após esta convenção, loggeré uma static finalreferência a objeto, como indicado no ponto 2, mas, como é " ." seguido sempre que você a usa, ela não pode ser considerada uma constante e, portanto, deve ser minúscula.

cbliard
fonte
11
Melhor definição que eu já vi sobre isso ainda. Doc ligada parece ter se mudou para cá é a atualização cs.bilgi.edu.tr/pages/standards_project/...
robert
15
Não entendo o ponto 2. O que é um exemplo de um tipo de objeto que nunca é seguido por um ponto. Todos os tipos de objetos são herdados Objecte você pode chamar um método como .equalseles.
31413 dogbane
6
Você está certo. E ao examinar algumas constantes Java como Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER ou Collections.EMPTY_LIST, elas também podem ser seguidas ..
Cbliard
5
@RomanIvanov Encontrei-o novamente aqui: scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy escrito por Achut Reddy, última atualização 30 de maio de 2000
cbliard
1
Acredito que o objetivo de 2 é designar que apenas as classes que devem ser comparadas são consideradas constantes. A classe não deve ser 'usada'. Sei que sempre me encolho quando vejo SOME_CLASS.doStuff (). É apenas uma codificação fugidia. O único problema com isso está no caso comum de um objeto constante (String é o exemplo comum) que serve apenas para comparação, mas para evitar verificações nulas, a codificação no estilo yoda é usada e, portanto, igual () é chamada na constante. Eu acho que eu faria isso a uma ressalva a 2.
Robin
44

De java eficaz, 2ª ed.,

A única exceção à regra anterior refere-se a "campos constantes", cujos nomes devem consistir em uma ou mais palavras em maiúsculas separadas pelo caractere sublinhado, por exemplo, VALUES ou NEGATIVE_INFINITY. Um campo constante é um campo final estático cujo valor é imutável . Se um campo final estático tiver um tipo primitivo ou um tipo de referência imutável (Item 15), será um campo constante. Por exemplo, constantes enum são campos constantes. Se um campo final estático tiver um tipo de referência mutável, ainda poderá ser um campo constante se o objeto referenciado for imutável.

Em resumo, constante == estática final, mais se for uma referência (versus um tipo simples), imutabilidade.

Olhando para o slf4j logger, http://www.slf4j.org/api/org/slf4j/Logger.html

É imutável. Por outro lado, o registrador JUL é mutável. O log4j logger também é mutável. Portanto, para ser correto, se você estiver usando log4j ou JUL, deve ser "logger" e, se estiver usando slf4j, deve ser LOGGER.

Observe que a página slf4j javadocs vinculada acima tem um exemplo em que eles usam "logger", não "LOGGER".

Naturalmente, essas são apenas convenções e não regras. Se você estiver usando o slf4j e quiser usar o "logger" porque está acostumado a isso em outras estruturas, ou se é mais fácil digitar ou para facilitar a leitura, vá em frente.

Jeffrey Blattman
fonte
2
Com base nesse raciocínio, a definição simplista do checkstyle é inadequada, certo?
Robert4
3
não sei verificar as regras do estilo. se está simplesmente insistindo que qualquer final estático deve estar em maiúsculas, então sim, está errado.
precisa saber é o seguinte
5
Como exatamente a Logger interface é imutável ? Somente um final class(como Stringou Integer) pode garantir imutabilidade. Mesmo que você não consiga encontrar nenhuma implementação mutável do SLF4J Logger, ninguém poderá impedi-lo de escrever uma.
Costi Ciudatu
Porque os métodos na interface não permitem mutação inerentemente. Você está certo de poder implementar a interface para ter efeitos colaterais mutáveis.
Jeffrey Blattman
As regras de verificação de estilo NÃO SÃO MADURAS o suficiente para implicar legibilidade. A legibilidade não pode ser alcançada com o modelo de um estilo; a legibilidade pode diferir caso a caso com base no contexto. Veja o código JDK, ele não segue nenhum modelo de estilo, e feito por profissionais, que mostra algo.
Daniel Hári 18/03/19
37

Gosto da opinião do Google ( Google Java Style )

Toda constante é um campo final estático, mas nem todos os campos finais estáticos são constantes. Antes de escolher um caso constante, considere se o campo realmente parece uma constante. Por exemplo, se qualquer estado observável dessa instância puder mudar, quase certamente não é uma constante. Apenas a intenção de nunca alterar o objeto geralmente não é suficiente.

Exemplos:

// 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
fonte
6
Penso que a primeira frase resume isso sucintamente: "Toda constante é um campo final estático, mas nem todos os campos finais estáticos são constantes". É fácil usar o pensamento mecânico e apenas ter todos os campos estáticos finais em maiúsculas (e eu venho fazendo isso até agora), mas isso é perder a sutileza da linguagem.
Ayahuasca
De acordo com essa citação, tudo se resume a se o campo "realmente parece" uma constante. Somos engenheiros, não psiquiatras.
Jeffrey Blattman
"Considere ... se realmente parece uma constante". Os sentimentos de alguém realmente não devem entrar no campo da engenharia.
Jeffrey Blattman em 14/02/19
Então, no código da Guava, eles têm isso comoprivate static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Kenston Choi 06/01
10

Se você estiver usando uma ferramenta automatizada para verificar seus padrões de codificação e violar os padrões, então ele ou os padrões devem ser corrigidos. Se você estiver usando um padrão externo, corrija o código.

A convenção no Sun Java é maiúscula para constantes estáticas públicas. Obviamente, um criador de logs não é constante, mas representa uma coisa mutável (caso contrário, não faria sentido chamar métodos na esperança de que algo aconteça); não existe um padrão específico para campos finais não constantes.

Pete Kirkham
fonte
10
Por que você está dizendo que o criador de logs não é constante? Parece constante mesmo. O registro produzido é um efeito colateral da chamada de seus métodos, mas não altera seu estado observável. Perdi alguma coisa?
KLE
Verifique a API. Ele possui um par de métodos add / get. Mas seu raciocínio é falha de qualquer maneira. O registro é observável (caso contrário, qual é o objetivo).
Tom Hawtin - tackline
3
Se fosse um StringBuilder e não um criador de logs, talvez fosse obviamente mais constante. Mesmo para os registradores, métodos como Logger.setLevel () modificam o receptor de maneira observável. Geralmente em maiúsculas é para aquelas constantes que os idiomas tratam como constantes e serão alinhadas.
Pete Kirkham
5
O criador de logs não é uma constante, pois é uma referência a um objeto. Constantes são valores que não podem ser alterados. A referência do objeto é final (portanto, a referência a ela não pode ser alterada, por exemplo, trocada por outra coisa ou definida como nula), mas o próprio objeto pode.
Spoike 14/09/09
1
@JeffreyBlattman Não concordo que todas as referências finais sejam maiúsculas, mas você é livre para adotar os padrões de codificação que desejar. Lamento que você ache a diferença entre 'objeto mutável' e 'objeto que representa uma coisa mutável' confusa; Um exemplo pode ser o número da sua conta anterior, que não é alterado, mas é usado para acessar um saldo variável. Procure a diferença entre significante e significante para obter mais detalhes ou uma introdução às mônadas de Leibnitz sobre como uma coisa imutável pode representar mutabilidade.
Pete Kirkham
7

Se você pesquisar no Google, poderá descobrir que, em alguns casos, os registradores não são definidos como estáticos finais. Adicione uma cópia-e-colar rápida a isso, e isso pode explicar.

Usamos LOGGER em todo o nosso código, e isso corresponde à nossa convenção de nomenclatura (e nosso CheckStyle está satisfeito com isso).


Vamos ainda mais longe, aproveitando a convenção estrita de nomenclatura no Eclipse. Criamos uma nova classe com um modelo de código de:

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

O logger é comentado, pois inicialmente não precisamos dele. Mas, se precisarmos mais tarde, apenas descomentamos.

Em seguida, no código, usamos modelos de código que esperam que esse criador de logs esteja presente. Exemplo com o modelo try-catch:

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

Temos mais alguns modelos que o utilizam.

A convenção estrita nos permite ser mais produtivos e coerentes com os modelos de código .

KLE
fonte
5
Capturar Throwable é uma prática ruim, a menos que você o registre e repita. Lembre-se de erros: OutOfMemeoryError, etc. A exceção de evento não é tão segura para ser capturada e manipulada por você mesmo em aplicativos multithread.
m_vitaly
2
A sintaxe do Eclipse é: Logger.getLogger ($ {enclosing_type} .class);
13139 dogbane
@fahdshariff Obrigado pela sintaxe precisa. Eu atualizei minha resposta.
KLE
Se as "convenções estritas" do CheckStyle ou PMD ajudam, então por que as fontes Guava e JDK não têm QUALQUER estilo comum aplicado? Por exemplo, sua fonte possui muitos blocos embutidos completos, quando necessário. A legibilidade depende do contexto; portanto, o uso de convenções de estilo estritas para tudo destrói as decisões baseadas em contexto, diminuindo a legibilidade.
Daniel Hári 18/03/19
6

Pessoalmente, acho que parece muito grande em maiúsculas. Além disso, como é uma classe que não está diretamente relacionada ao comportamento da classe, não vejo um grande problema em usar em loggervez de LOGGER. Mas se você for estritamente pedante, use LOGGER.

João Silva
fonte
4

Não esqueça que o PMD respeitará um comentário com

// NOPMD

iniciar. Isso fará com que o PMD pule a linha de suas verificações, permitindo que você escolha o estilo que desejar.

Fortyrunner
fonte
6
Ou o uso não faça PMD, eles estão sempre errados e seu código é perfeito
IAdapter
1
Se você sempre precisar excluir uma verificação todas as vezes, a verificação não faz sentido.
keiki
Não poderia concordar mais - no entanto ... é útil saber o comentário de exclusão
Fortyrunner
3

Normalmente, as constantes estão em maiúsculas.

Os criadores de logs, no entanto, não devem ser estáticos, mas consultados para cada "novo" da classe que contém, se estiverem usando a fachada slf4j. Isso evita alguns problemas desagradáveis ​​do carregador de classes em contêineres da Web, além de permitir que a estrutura do criador de logs faça coisas especiais, dependendo do contexto da chamada.

Thorbjørn Ravn Andersen
fonte
2

Eu prefiro 'logger', ou seja, minúsculas. O motivo não é que seja uma constante ou não (mutável ou imutável). Se usarmos esse raciocínio, teremos que renomear a variável se alterarmos a estrutura de log (ou se a estrutura alterar a mutabilidade dos loggers).

Para mim, outros motivos são mais importantes.

  1. Um criador de logs é um objeto de sombra na classe e não deve ser muito importante, pois não implementa a lógica principal. Se usarmos 'LOGGER', é atraente no código que atrai muita atenção.

  2. Às vezes, os loggers são declarados no nível da instância (ou seja, não são estáticos) e até são injetados como uma dependência. Não gostaria de alterar meu código se decidir alterar a maneira de obter o logger. A estabilidade do código wrt. essa mudança (hipotética em muitos casos) é a outra razão pela qual prefiro a minúscula.

fml2
fonte
1

Se os seus padrões de codificação - se você tiver algum - dizem que devem estar em maiúsculas, então sim.

Não vejo nenhuma razão estrita de uma maneira ou de outra. Eu acho que depende totalmente de seus gostos pessoais resp. padrões de codificação da sua empresa.

BTW: eu prefiro "LOGGER" ;-)

Kutzi
fonte