대문자로 "정적 최종 로거"를 선언해야합니까?


243

Java에서 정적 최종 변수는 상수이며 규칙은 대문자 여야한다는 규칙입니다. 그러나 대부분의 사람들은 로거를 소문자로 선언하여 PMD 에서 위반으로 나타납니다 .

예 :

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

그냥 검색 구글 이나 SO "정적 최종 로거를위한"당신은 자신이 표시됩니다.

대신 LOGGER를 사용해야합니까?


PMD 또는 Checkstyle은 가독성을 높이기위한 조기 순진한 시도이지만 혜택보다 더 많은 해를 입 힙니다. 가장 읽기 쉬운 스타일은 상황에 따라 사례별로 변경할 수 있습니다. Guava 또는 JDK src를 참조하십시오. 엄격한 스타일 템플릿을 따르지 않지만 전문가가 의심 할 여지가 없습니다. 예 : DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
Daniel Hári

수중 음파 탐지기 규칙 ( rules.sonarsource.com/java/tag/convention/RSPEC-1312 )도private static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

답변:


306

로거 참조는 상수가 아니라 최종 참조이며 대문자가 아니어야합니다. 상수 VALUE는 대문자 여야합니다.

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

private static final double MY_CONSTANT = 0.0;

42
정적 최종 참조는 불변 인 경우 상수입니다. 이 논리에 따르면 정적 최종 문자열이 참조이므로 상수 문자열이 없습니다.
Jeffrey Blattman

30
그러나 java.lang.String 불변이며 어쨌든 특별한 종류의 클래스입니다 (String.intern (), Sring pool 등에 관한 문서 참조)
Aleksander Adamowski

3
불변은 시공 후 객체의 상태를 변경할 수 없음을 의미합니다. 아래 내 게시물을 참조하십시오. 로거가 반드시 변경 가능한 것은 아닙니다.
Jeffrey Blattman

4
누군가 여전히이 문제에 관심이 있다면 github.com/checkstyle/checkstyle/issues/23 에서 아이디어를 공유 하여 수요가있는 곳과 그렇지 않은 곳을 구분하십시오.
로마 이바노프

2
@Jeach 나는 불변이 상태의 변화와 관련이 있다고 생각하지 않습니다. 또한 사용자 란 무엇입니까? 프로그램을 실행하는 외부 사용자? 사용자가 버튼을 누르면 수정되는 상태와 임의의 간격으로 타이머가 실행되는 상태를 구별 하시겠습니까? (나는 그렇게 생각하지 않는다).
Jeffrey Blattman

236

crunchdog의 답변에 더 많은 가치를 더하기 위해 Java 코딩 스타일 가이드 는 3.3 절의 필드 이름 지정에이를 설명합니다.

상수 로 사용되는 필드 이름은 모두 대문자 여야하며 밑줄로 단어를 구분해야합니다. 다음은 상수로 간주됩니다.

  1. 모든 static final기본 유형 ( 모든 인터페이스 필드는 기본적으로 있음을 기억하십시오 static final).
  2. static final" ."(점)이 뒤 따르지 않는 모든 객체 참조 유형 .
  3. static final" ["(대괄호 열기)가 뒤 따르지 않는 모든 배열 .

예 :

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

이 규칙에 따라, loggerA는 static final점 2에 명시된 바와 같이 객체 참조하지만,이 때문에 한다 "다음에 .당신이 그것을 사용할 때마다", 그것은 상수로 간주 할 수 없으며, 따라서 소문자이어야한다.


11
내가 아직 본 최고의 정의. 링크 된 문서는 여기로 이사 업데이트의 것으로 보인다 cs.bilgi.edu.tr/pages/standards_project/...
로버트

15
포인트 2를 얻지 못합니다. 점 뒤에 절대로 오지 않는 객체 유형의 예는 무엇입니까? 모든 객체 유형은 상속되며 해당 유형 Object과 같은 메소드를 호출 할 수 .equals있습니다.
dogbane

6
네 말이 맞아 그리고 Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER 또는 Collections.EMPTY_LIST와 같은 일부 Java 상수를 볼 때도 뒤따를 수 있습니다 ..
cbliard

5
: @RomanIvanov 다시 여기 발견 scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy이 2000년 5월 30일, Achut 레디가 쓴 마지막 업데이트를
cbliard

1
2의 목적은 비교 대상 클래스 만 상수로 간주되도록 지정하는 것입니다. 이 수업은 '사용'되지 않습니다. SOME_CLASS.doStuff ()를 볼 때 항상 울었습니다. 그냥 코드를 코딩하는 것입니다. 이것에 대한 유일한 문제는 일반적인 상수 객체 (문자열은 일반적인 예)의 경우에만 비교를위한 것이지만 null 검사를 피하기 위해 yoda 스타일 코딩이 사용되므로 equals ()가 상수에서 호출됩니다. 나는 이것을 2에 대한 하나의 경고로 만들 것이라고 생각합니다.
Robin

44

효과적인 자바에서, 2nd ed.,

이전 규칙에 대한 유일한 예외는 이름이 밑줄 문자로 구분 된 하나 이상의 대문자로 구성되어야하는 "일정 필드"와 관련이 있습니다 (예 : VALUES 또는 NEGATIVE_INFINITY). 상수 필드는 값을 변경할 수없는 정적 최종 필드입니다 . 정적 최종 필드에 기본 유형 또는 변경 불가능한 참조 유형 (항목 15)이 있으면 상수 필드입니다. 예를 들어 열거 형 상수는 상수 필드입니다. 정적 최종 필드에 변경 가능한 참조 유형이있는 경우 참조 된 오브젝트가 변경 불가능한 경우에도 여전히 상수 필드 일 수 있습니다.

요약하면, constant == static final, 그리고 참조 인 경우 (단순한 유형), 불변성.

slf4j 로거를 보면 http://www.slf4j.org/api/org/slf4j/Logger.html

불변입니다. 한편, JUL 로거는 변경 가능합니다. log4j 로거도 변경 가능합니다. 따라서 log4j 또는 JUL을 사용하는 경우 "logger"여야하고 slf4j를 사용하는 경우 LOGGER 여야합니다.

위에 링크 된 slf4j javadocs 페이지에는 "LOGGER"가 아닌 "logger"를 사용하는 예가 있습니다.

이것은 물론 규칙이 아니라 관습 일뿐입니다. slf4j를 사용하고 있고 다른 프레임 워크에서 사용하기 때문에 "로거"를 사용하려는 경우 또는 입력하기 쉬운 또는 가독성을 높이려면 계속하십시오.


2
이 추론을 바탕으로 checkstyle의 단순한 정의가 부적절합니까?
robert

3
나는 체크 스타일의 규칙을 모른다. 정적 결말을 대문자로 사용해야한다고 주장한다면, 그렇습니다.
Jeffrey Blattman

5
어떻게 정확하게 인 Logger 인터페이스 불변는 ? final class(같은 String또는 Integer) 만 불변성을 보장 할 수 있습니다. SLF4J의 변경 가능한 구현을 찾을 수 없더라도 Logger아무도 직접 작성하는 것을 막을 수는 없습니다.
Costi Ciudatu

인터페이스의 방법은 본질적으로 돌연변이를 허용하지 않기 때문입니다. 변경 가능한 부작용을 갖도록 인터페이스를 구현할 수는 있지만 옳습니다.
Jeffrey Blattman

체크 스타일 규칙은 가독성을 내포 할 정도로 성숙하지 않습니다. 스타일을 템플릿하여 가독성을 달성 할 수 없으며, 가독성은 상황에 따라 상황에 따라 다를 수 있습니다. JDK 코드를 참조하십시오. 스타일 템플릿을 따르지 않으며 전문가가 만든 것으로 무언가를 보여줍니다.
Daniel Hári

37

나는 구글이 그것을 좋아한다 ( 구글 자바 스타일 )

모든 상수는 정적 최종 필드이지만 모든 정적 최종 필드가 상수는 아닙니다. 일정한 대소 문자를 선택하기 전에 필드가 실제로 일정하게 느껴지는 지 고려하십시오. 예를 들어, 해당 인스턴스의 관찰 가능한 상태 중 하나라도 변경 될 수있는 경우 거의 일정하지 않습니다. 객체를 절대로 변경하지 않는 것은 일반적으로 충분하지 않습니다.

예 :

// 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
첫 문장은 이것을 간결하게 요약합니다. "모든 상수는 정적 최종 필드이지만 모든 정적 최종 필드가 상수는 아닙니다." 기계적인 사고를 사용하기 쉽고 모든 정적 최종 필드를 대문자로 사용하십시오 (지금 까지이 작업을 수행했습니다). 그러나 이것은 언어의 미묘함을 놓치는 것입니다.
ayahuasca

그 인용에 따르면, 그것은 필드가 상수처럼 "진정한 느낌"인지로 요약됩니다. 우리는 정신과 의사가 아닌 엔지니어입니다.
Jeffrey Blattman

"정말 일정하다고 생각되면 ..." 누군가의 감정은 실제로 공학 분야에 들어가서는 안됩니다.
제프리 Blattman

그런 다음 구아바의 코드에서private static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Kenston Choi

10

자동 도구를 사용하여 코딩 표준을 확인하고 해당 표준을 위반하는 경우 해당 도구 또는 표준을 수정해야합니다. 외부 표준을 사용하는 경우 코드를 수정하십시오.

Sun Java의 규칙은 공용 정적 상수의 대문자입니다. 분명히 로거는 일정하지 않지만 변경 가능한 것을 나타냅니다 (그렇지 않으면 어떤 일이 일어날 것이라는 희망으로 메소드를 호출하는 데 아무런 포인트가 없습니다). 일정하지 않은 최종 필드에 대한 특정 표준은 없습니다.


10
로거가 일정하지 않다고 말하는 이유는 무엇입니까? 실제로 일정 해 보입니다. 로깅이 생성되면 메소드 호출의 부작용이 발생하지만 관찰 가능한 상태는 변경하지 않습니다. 내가 뭐 놓친 거 없니?
KLE

API를 확인하십시오. 메소드의 추가 / 가져 오기 쌍이 있습니다. 그러나 당신은 추론에 결함이 있습니다. 로깅은 관찰 가능합니다 (그렇지 않으면 요점은 무엇입니까).
Tom Hawtin-tackline

3
로거가 아닌 StringBuilder라면 아마도 더 일정하지 않을 것입니다. 로거의 경우에도 Logger.setLevel ()과 같은 메소드는 수신자를 눈에 띄게 변경합니다. 일반적으로 대문자는 언어가 상수로 취급하고 인라인 할 상수에 해당합니다.
Pete Kirkham

5
로거는 객체에 대한 참조이므로 상수가 아닙니다. 상수는 변경할 수없는 값입니다. 객체 참조는 최종적이므로 (참조에 대한 참조는 변경할 수 없습니다 (예 : 다른 것으로 바꾸거나 null로 설정)) 객체 자체는 가능합니다.
Spoike

1
@JeffreyBlattman 모든 최종 참조가 대문자 여야한다는 데 동의하지는 않지만 원하는 코딩 표준을 자유롭게 채택 할 수 있습니다. '변경 가능한 객체'와 '변경 가능한 것을 나타내는 객체'의 차이점을 혼동하여 죄송합니다. 예를 들어 계좌 번호는 변경되지 않지만 가변 잔액에 액세스하는 데 사용됩니다. 더 자세한 내용은 signifier와 significand의 차이점 또는 불변의 것이 어떻게 변이성을 나타낼 수 있는지에 대한 Leibnitz의 모나드 소개를 찾으십시오.
피트 Kirkham

7

당신이 구글을 검색하면 경우에 따라 로거가 정적 인 최종으로 정의되지 않은 것을 알 수 있습니다. 여기에 빠른 복사 후 붙여 넣기를 추가하면 설명이됩니다.

우리 는 모든 코드에서 LOGGER사용 하며 이는 명명 규칙에 해당합니다 (CheckStyle도 만족합니다).


우리는 Eclipse의 엄격한 명명 규칙을 활용하여 더 나아가고 있습니다. 다음과 같은 코드 템플릿으로 새 클래스를 만듭니다.

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

로거는 처음에는 필요하지 않으므로 주석 처리됩니다. 그러나 나중에 필요하면 주석 처리를 제거하십시오.

그런 다음 코드에서이 로거가 존재할 것으로 예상되는 코드 템플릿을 사용합니다. try-catch 템플릿을 사용한 예 :

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

이를 사용하는 템플릿이 몇 가지 더 있습니다.

엄격한 규칙은 우리가 생산성과 코드 템플릿과 일관성이 될 수 있습니다 .


5
Throwable를 잡는 것은 기록하고 다시 던지지 않는 한 나쁜 습관입니다. 오류 기억 : OutOfMemeoryError 등. 이벤트 예외는 다중 스레드 응용 프로그램에서 사용자가 직접 잡아서 처리하기에 안전하지 않습니다.
m_vitaly

2
Eclipse 구문은 다음과 같습니다. Logger.getLogger ($ {enclosing_type} .class);
dogbane

@fahdshariff 정확한 구문에 감사드립니다. 답변을 업데이트했습니다.
KLE

CheckStyle 또는 PMD의 "엄격한 규칙"이 도움이되는 경우 왜 Guava 및 JDK 소스에 공통 스타일이 적용되지 않습니까? 예를 들어 소스에는 필요한 경우 전체 인라인 블록이 많이 있습니다. 가독성은 상황에 따라 다르므로 모든 것에 엄격한 스타일 지정 규칙을 사용하면 상황에 따른 의사 결정이 손상되므로 가독성이 떨어집니다.
Daniel Hári

6

나는 개인적으로 그것이 대문자로 정말로 크게 보인다고 생각합니다. 또한 클래스 동작과 직접 관련이없는 클래스이므로 logger대신을 사용하는 데 큰 문제가 없습니다 LOGGER. 그러나 엄격하게 pedantic이 되려면을 사용하십시오 LOGGER.


4

PMD가 의견을 존중한다는 것을 잊지 마십시오

// NOPMD

그 안에. 이렇게하면 PMD가 검사에서 라인을 건너 뛰게되므로 원하는 스타일을 선택할 수 있습니다.


6
또는 PMD를 사용하지 마십시오. 항상 잘못되었으며 코드가 완벽합니다.
IAdapter

1
매번 수표를 항상 제외해야하는 경우 수표가 의미가 없습니다.
keiki

그러나 더 이상 동의 할 수 없었습니다 ... 제외 의견을 아는 것이 유용합니다
Fortyrunner

3

일반적으로 상수는 대문자입니다.

그러나 로거는 정적이 아니어야하지만 slf4j 파사드를 사용하는 경우 포함 클래스의 모든 "새"항목을 찾아야합니다. 이것은 특히 웹 컨테이너에서 불쾌한 클래스 로더 문제를 피하고 로거 프레임 워크가 호출 컨텍스트에 따라 특별한 작업을 수행 할 수있게합니다.


2

'로거', 즉 소문자를 선호합니다. 그 이유는 상수이거나 상수가 아니기 때문입니다 (변경 가능 또는 변경 불가능). 그 추론을 사용한다면, 로깅 프레임 워크를 변경하거나 프레임 워크가 로거의 변경 가능성을 변경하면 변수의 이름을 바꿔야합니다.

저에게는 다른 이유가 더 중요합니다.

  1. 로거는 클래스의 섀도우 개체이며 기본 논리를 구현하지 않으므로 눈에 띄지 않아야합니다. 'LOGGER'를 사용하면 코드에서 너무 많은 관심을 끄는 눈길을 끄는 것입니다.

  2. 때때로 로거는 인스턴스 레벨에서 선언되고 (정적이 아닌) 심지어 의존성으로 주입되기도합니다. 로거를 얻는 방법을 변경하기로 결정한 경우 코드를 변경하고 싶지 않습니다. 코드 안정성 wrt. 이것이 소문자를 선호하는 또 다른 이유입니다.


1

코딩 표준 (있는 경우)은 대문자 여야한다고 말합니다.

나는 어떤 식 으로든 엄격한 이유를 찾지 못했습니다. 나는 그것이 당신의 개인적인 좋아하는 입술에 전적으로 달려 있다고 생각합니다. 회사 코딩 표준.

BTW : "LOGGER"를 선호합니다 ;-)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.