Czy powinienem zadeklarować „statyczny rejestrator końcowy” w GÓRNEJ PRZYPADKU?

243

W Javie statyczne zmienne końcowe są stałymi, a konwencja jest taka, że ​​powinny być pisane wielkimi literami. Widziałem jednak, że większość ludzi deklaruje rejestratory małymi literami, co pojawia się jako naruszenie w PMD .

na przykład:

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

Po prostu wyszukaj w Google lub SO „statyczny rejestrator końcowy”, a zobaczysz to sam.

Czy zamiast tego powinniśmy używać LOGGERA?

dogbane
źródło
PMD lub Checkstyle to naiwne próby przedwczesnego zwiększenia czytelności, ale powodują więcej szkody niż korzyści. Najbardziej czytelny styl może zmieniać litery po literach na podstawie kontekstu. Zobacz Guava lub JDK src, nie są one zgodne z żadnym surowym szablonem stylu, ale wykonane przez profesjonalistów są niekwestionowane. przykład: DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
Daniel Hári
Sonar Rules ( rules.sonarsource.com/java/tag/convention/RSPEC-1312 ) również ma to jakoprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

Odpowiedzi:

306

Odwołanie do programu rejestrującego nie jest stałą, ale ostatecznym odniesieniem i NIE powinno być pisane wielkimi literami. Stała WARTOŚĆ powinna być pisana wielkimi literami.

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

private static final double MY_CONSTANT = 0.0;
crunchdog
źródło
42
statyczne odniesienia końcowe są stałymi, jeśli są niezmienne. dzięki tej logice nigdy nie miałbyś stałych ciągów, ponieważ dowolny statyczny ciąg końcowy jest odniesieniem.
Jeffrey Blattman
30
Ale java.lang.String jest niezmienny i mimo wszystko jest specjalnym rodzajem klasy (patrz String.intern (), dokumentacja o puli Sring itp.)
Aleksander Adamowski
3
niezmienny oznacza, że ​​stan obiektu nie może się zmienić po budowie. zobacz mój post poniżej. rejestratory niekoniecznie są zmienne.
Jeffrey Blattman
4
jeśli komuś nadal zależy na tym problemie, podziel się pomysłami na github.com/checkstyle/checkstyle/issues/23 , aby rozróżnić, gdzie duże litery są potrzebne, a gdzie nie.
Roman Iwanow
2
@ Słuchaj, nie sądzę, że niezmienność dotyczy zmian stanu, tylko że tak się dzieje. ponadto, kim jest użytkownik? użytkownik zewnętrzny uruchamiający program? czy wprowadziłbyś rozróżnienie między stanem modyfikowanym przez użytkownika, który naciska przycisk, a modyfikowaniem przez timer uruchamiany w przypadkowych odstępach czasu? (nie sądzę).
Jeffrey Blattman
236

Aby dodać więcej wartości do odpowiedzi crunchdog, Przewodnik po stylu kodowania Java zawiera to w paragrafie 3.3 Nazewnictwo pól

Nazwy pól używanych jako stałe powinny być pisane wielkimi literami, z podkreślnikami oddzielającymi słowa. Za stałe uważa się:

  1. Wszystkie static finalpierwotne typy (pamiętaj, że wszystkie pola interfejsu są z natury static final).
  2. Wszystkie static finaltypy odwołań do obiektów, po których nigdy nie następuje „ .” (kropka).
  3. Wszystkie static finaltablice, po których nigdy nie następuje „ [” (otwierający nawias kwadratowy).

Przykłady:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

Po tej konwencji, loggerto static finalodwołanie do obiektu, jak wskazano w pkt 2, ale dlatego, że jest następnie „ .” za każdym razem go używać, to nie można uznać za stałą, a zatem powinny być małe.

Cbliard
źródło
11
Najlepsza definicja, jaką do tej pory widziałem. Połączony dokument wydaje się przenieść tutaj jest aktualizacja cs.bilgi.edu.tr/pages/standards_project/…
Robert
15
Nie dostaję punktu 2. Jaki jest przykład typu obiektu, po którym nigdy nie występuje kropka. Wszystkie typy obiektów dziedziczą Objecti możesz wywołać metodę taką jak .equalsna nich.
dogbane
6
Masz rację. A jeśli spojrzymy na niektóre stałe Java, takie jak Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER lub Collections.EMPTY_LIST, mogą być za nimi .również.
cbliard
5
@RomanIvanov Znalazłem go ponownie tutaj: scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy napisany przez Achut Reddy, ostatnia aktualizacja 30 maja 2000 r.
cbliard
1
Uważam, że celem 2 jest wyznaczenie, że tylko klasy, które mają być porównywane, są uważane za stałe. Klasa nie powinna być „używana”. Wiem, że zawsze się denerwuję, gdy widzę SOME_CLASS.doStuff (). To po prostu niezgrabne kodowanie. Jedynym problemem jest wspólny przypadek stałego obiektu (ciąg jest powszechnym przykładem), który służy jedynie do porównania, ale aby uniknąć sprawdzania wartości zerowej, stosowane jest kodowanie w stylu yoda, a zatem wywoływana jest stała (). Myślę, że uczyniłbym to jedynym zastrzeżeniem dla 2.
Robin,
44

Od wersji skutecznej Java, wyd. 2,

Jedyny wyjątek od poprzedniej reguły dotyczy „stałych pól”, których nazwy powinny składać się z jednego lub więcej wielkich liter oddzielonych znakiem podkreślenia, na przykład VALUES lub NEGATIVE_INFINITY. Pole stałe to statyczne pole końcowe, którego wartość jest niezmienna . Jeśli statyczne pole końcowe ma typ pierwotny lub niezmienny typ odniesienia (pozycja 15), to jest to pole stałe. Na przykład stałe wyliczeniowe są polami stałymi. Jeśli statyczne pole końcowe ma zmienny typ odniesienia, może nadal być polem stałym, jeśli obiekt odniesienia jest niezmienny.

Podsumowując, stała == statyczny finał, plus jeśli jest to referencja (w porównaniu z typem prostym), niezmienność.

Patrząc na rejestrator slf4j, http://www.slf4j.org/api/org/slf4j/Logger.html

Jest niezmienny. Z drugiej strony rejestrator JUL jest zmienny. Rejestrator log4j jest również modyfikowalny. Tak więc, aby być poprawnym, jeśli używasz log4j lub JUL, powinien to być „logger”, a jeśli używasz slf4j, powinien to być LOGGER.

Zauważ, że strona slv4j javadocs, do której prowadzi link powyżej, zawiera przykład, w którym używają „logger”, a nie „LOGGER”.

Są to oczywiście tylko konwencje, a nie reguły. Jeśli akurat używasz slf4j i chcesz użyć „loggera”, ponieważ jesteś przyzwyczajony do tego z innych frameworków, lub jeśli łatwiej jest pisać lub dla czytelności, śmiało.

Jeffrey Blattman
źródło
2
Na podstawie tego rozumowania uproszczona definicja checkstyle jest nieodpowiednia, prawda?
Robert
3
nie wiem, sprawdź zasady stylu. jeśli po prostu nalega, aby każdy statyczny finał był pisany wielkimi literami, to tak, to źle.
Jeffrey Blattman,
5
Jak dokładnie Logger interfejs jest niezmienny ? Tylko final class(jak Stringlub Integer) może zagwarantować niezmienność. Nawet jeśli nie możesz znaleźć żadnej modyfikowalnej implementacji SLF4J Logger, nikt nie może Cię powstrzymać przed napisaniem jej.
Costi Ciudatu,
Ponieważ metody w interfejsie nie pozwalają na mutację z natury. Masz rację, ale możesz zaimplementować interfejs, aby wywoływać mutacyjne skutki uboczne.
Jeffrey Blattman,
Sprawdź, czy reguły stylu NIE są wystarczająco dojrzałe, aby sugerować czytelność. Czytelności stylu nie da się odczytać, czytelność może się różnić w zależności od przypadku. Zobacz kod JDK, nie jest zgodny z żadnym szablonem stylu i został stworzony przez profesjonalistów, który coś pokazuje.
Daniel Hári
37

Podoba mi się podejście Google ( Google Java Style )

Każda stała jest statycznym polem końcowym, ale nie wszystkie statyczne pola końcowe są stałymi. Przed wybraniem stałej wielkości, zastanów się, czy pole naprawdę wydaje się stałą. Na przykład, jeśli którykolwiek z obserwowalnych stanów tego wystąpienia może się zmienić, prawie na pewno nie jest stały. Sam fakt, że nigdy nie zmutujesz obiektu, na ogół nie wystarcza.

Przykłady:

// 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
źródło
6
Myślę, że pierwsze zdanie podsumowuje to poprawnie: „Każda stała jest statycznym polem końcowym, ale nie wszystkie statyczne pola końcowe są stałymi”. Łatwe w użyciu myślenie mechaniczne i po prostu każde statyczne pole końcowe pisane wielkimi literami (i robiłem to do tej pory), ale brakuje w tym subtelności języka.
ayahuasca,
Zgodnie z tym cytatem sprowadza się to do tego, czy pole „naprawdę wydaje się” stałe. Jesteśmy inżynierami, a nie psychiatrami.
Jeffrey Blattman,
„Zastanów się… czy to naprawdę wydaje się ciągłe”. Czyjeś uczucia naprawdę nie powinny wchodzić w dziedzinę inżynierii.
Jeffrey Blattman
Następnie w kodzie private static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Guavy
10

Jeśli używasz zautomatyzowanego narzędzia do sprawdzania standardów kodowania, które narusza wspomniane standardy, należy je naprawić. Jeśli używasz zewnętrznego standardu, napraw kod.

Konwencja w Sun Java jest wielka dla publicznych stałych statycznych. Oczywiście logger nie jest stały, ale reprezentuje zmienną rzecz (inaczej nie byłoby sensu wywoływać w nim metod w nadziei, że coś się wydarzy); nie ma określonego standardu dla niestałych pól końcowych.

Pete Kirkham
źródło
10
Dlaczego mówisz, że rejestrator nie jest stały? Rzeczywiście wydaje się stały. Wytwarzanie rejestrowania jest efektem ubocznym wywoływania jego metod, ale nie zmieniaj jego obserwowalnego stanu. Przegapiłem coś?
KLE
Sprawdź API. Ma parę metod dodawania / pobierania. Ale i tak rozumowanie jest błędne. Rejestrowanie jest obserwowalne (w przeciwnym razie o co chodzi).
Tom Hawtin - tackline
3
Gdyby był to StringBuilder, a nie program rejestrujący, być może byłby on oczywiście bardziej niestały. Nawet w przypadku rejestratorów metody, takie jak Logger.setLevel (), mutują zauważalnie odbiornik. Zasadniczo wielkie litery dotyczą stałych, które języki traktują jako stałe i będą wstawiane.
Pete Kirkham,
5
Program rejestrujący nie jest stałą, ponieważ jest odniesieniem do obiektu. Stałe to wartości, których nie można zmienić. Odwołanie do obiektu jest ostateczne (więc odniesienia do niego nie można zmienić, np. Zamieniono na coś innego lub ustawiono na null), ale sam obiekt może.
Spoike,
1
@JeffreyBlattman Nie zgadzam się, że wszystkie końcowe odniesienia powinny być pisane wielkimi literami, ale możesz swobodnie przyjmować dowolne standardy kodowania, które ci się podobają. Przykro mi, że różnica między „przedmiotem zmiennym” a „przedmiotem reprezentującym zmienną rzecz” jest myląca; Jednym z przykładów może być Twój numer konta z powrotem, który sam się nie zmienia, ale służy do uzyskania dostępu do zmiennego salda. Spójrz na różnicę między znacznikiem a znaczeniem, aby uzyskać więcej szczegółów, lub wprowadzenie do monad Leibnitza, aby dowiedzieć się, jak niezmienna rzecz może reprezentować zmienność.
Pete Kirkham,
7

Jeśli google to, może się okazać, że w niektórych przypadkach rejestratory nie są zdefiniowane jako statyczny końcowy. Dodaj do tego szybkie kopiowanie i wklejanie, a to może to wyjaśnić.

Używamy LOGGERA w całym naszym kodzie, co odpowiada naszej konwencji nazewnictwa (i nasz CheckStyle jest z niego zadowolony).


Posuwamy się nawet dalej, korzystając ze ścisłej konwencji nazewnictwa w Eclipse. Tworzymy nową klasę z szablonem kodu:

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

Rejestrator został skomentowany, ponieważ początkowo nie jest nam potrzebny. Ale jeśli będziemy go potrzebować później, po prostu odkomentujemy.

Następnie w kodzie używamy szablonów kodu, które oczekują obecności tego programu rejestrującego. Przykład z szablonem try-catch:

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

Mamy jeszcze kilka szablonów, które z niego korzystają.

Ścisłe konwencja pozwala nam być bardziej wydajne i spójne z szablonów kodu .

KLE
źródło
5
Catching Throwable to zła praktyka, chyba że się zalogujesz i ponownie rzucisz. Zapamiętaj błędy: OutOfMemeoryError itp. Wyjątek zdarzenia nie jest tak bezpieczny, aby zostać złapanym i obsłużonym przez ciebie w aplikacjach wielowątkowych.
m_vitaly
2
Składnia środowiska Eclipse jest następująca: Logger.getLogger ($ {obejmujący_typ} .class);
dogbane
@fahdshariff Dzięki za dokładną składnię. Zaktualizowałem swoją odpowiedź.
KLE
Jeśli pomocne są „ścisłe konwencje” CheckStyle lub PMD, to dlaczego źródła Guava i JDK nie mają ŻADNEGO wspólnego stylu? Na przykład ich źródło ma w razie potrzeby mnóstwo pełnych, wbudowanych bloków. Czytelność zależy od kontekstu, więc stosowanie ścisłych konwencji stylów do wszystkiego niszczy decyzje oparte na kontekście, a zatem zmniejsza czytelność.
Daniel Hári,
6

Osobiście uważam, że wielkie litery wyglądają na naprawdę duże. Co więcej, ponieważ jest to klasa, która nie jest bezpośrednio związana z zachowaniem klasy, nie widzę większego problemu w użyciu loggerzamiast LOGGER. Ale jeśli będziesz ściśle pedantyczny, użyj LOGGER.

João Silva
źródło
4

Nie zapominaj, że PMD uszanuje komentarz

// NOPMD

w tym. Spowoduje to, że PMD pominie linię z kontroli, umożliwi to wybór dowolnego stylu.

Fortyrunner
źródło
6
Lub nie używaj PMD, zawsze są one błędne, a Twój kod jest doskonały
IAdapter
1
Jeśli zawsze musisz wykluczyć czek za każdym razem, czek nie ma sensu.
keiki
Nie można zgodzić się więcej - jednak ... warto znać komentarz na temat wykluczenia
Fortyrunner,
3

Zwykle stałe są pisane wielkimi literami.

Rejestratory nie powinny jednak być statyczne, ale sprawdzane dla każdej „nowej” klasy zawierającej, jeśli używa się fasady slf4j. Pozwala to uniknąć pewnych nieprzyjemnych problemów z modułami ładującymi w kontenerach internetowych, a ponadto umożliwia programowi rejestrującemu wykonywanie specjalnych czynności w zależności od kontekstu wywołania.

Thorbjørn Ravn Andersen
źródło
2

Wolę „logger”, czyli małe litery. Powodem nie jest to, że jest stała lub nie stała (zmienna lub niezmienna). Jeśli użyjemy tego rozumowania, będziemy musieli zmienić nazwę zmiennej, jeśli zmienimy strukturę rejestrowania (lub jeśli struktura zmieni zmienność programów rejestrujących).

Dla mnie ważniejsze są inne powody.

  1. Program rejestrujący jest obiektem cienia w klasie i nie powinien być bardzo widoczny, ponieważ nie implementuje głównej logiki. Jeśli użyjemy „LOGGER”, przyciąga wzrok w kodzie, który przyciąga zbyt wiele uwagi.

  2. Czasami rejestratory są deklarowane na poziomie instancji (tj. Nie jako statyczne), a nawet wstrzykiwane są jako zależność. Nie chciałbym zmieniać kodu, jeśli zdecyduję się zmienić sposób uzyskiwania programu rejestrującego. Wrt stabilność kodu. ta (hipotetyczna w wielu przypadkach) zmiana jest drugim powodem, dla którego wolę małe litery.

fml2
źródło
1

Jeśli twoje standardy kodowania - jeśli je masz - mówią, że powinny być pisane wielkimi literami, to tak.

Nie widzę żadnego wyraźnego powodu z takiego czy innego powodu. Myślę, że to całkowicie zależy od twoich osobistych upodobań. standardy kodowania twojej firmy.

BTW: Wolę „LOGGER” ;-)

Kutzi
źródło