Có nên khai báo một logger tĩnh cuối cùng của Nhật Bản trong UPPER-CASE không?


243

Trong Java, các biến cuối cùng tĩnh là các hằng số và quy ước là chúng phải ở dạng chữ hoa. Tuy nhiên, tôi đã thấy rằng hầu hết mọi người tuyên bố logger trong trường hợp thấp hơn là vi phạm trong PMD .

ví dụ:

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

Chỉ cần tìm kiếm google hoặc SO cho "logger tĩnh cuối cùng" và bạn sẽ thấy điều này cho chính mình.

Thay vào đó chúng ta có nên sử dụng LOGGER không?


PMD hoặc Checkstyle là những nỗ lực ngây thơ trước khi trưởng thành để tăng khả năng đọc nhưng chúng gây hại nhiều hơn lợi ích. Một phong cách dễ đọc nhất có thể thay đổi theo từng trường hợp dựa trên bối cảnh. Xem Guava hoặc JDK src, những mẫu này không tuân theo bất kỳ khuôn mẫu kiểu nghiêm ngặt nào, nhưng được thực hiện bởi các chuyên gia, điều đó không thể nghi ngờ. ví dụ: DelegatedExecutorService @ docjar.com/html/api/java/util/conciverse/Executors.java.html
Daniel Hári

Quy tắc Sonar ( Rules.sonarsource.com/java/tag/convent/RSPEC-1312 ) cũng có quy tắc nhưprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

Câu trả lời:


306

Tham chiếu logger không phải là hằng số, mà là tham chiếu cuối cùng và KHÔNG nên viết hoa. Một giá trị không đổi nên được viết hoa.

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

private static final double MY_CONSTANT = 0.0;

42
tài liệu tham khảo cuối cùng tĩnh là hằng số nếu chúng là bất biến. theo logic này, bạn sẽ không bao giờ có các chuỗi không đổi bởi vì bất kỳ chuỗi cuối cùng tĩnh nào cũng là một tham chiếu.
Jeffrey Blattman

30
Nhưng java.lang.String bất biến và là một loại lớp đặc biệt dù sao (xem String.i INTERN (), tài liệu về nhóm Sring, v.v.)
Aleksander Adamowski

3
bất biến có nghĩa là trạng thái của đối tượng không thể thay đổi sau khi xây dựng. xem bài viết của tôi dưới đây. loggers không nhất thiết phải thay đổi.
Jeffrey Blattman

4
nếu ai đó vẫn quan tâm đến vấn đề này, vui lòng chia sẻ ý tưởng tại github.com/checkstyle/checkstyle/issues/23 , để phân biệt nơi nào yêu cầu chữ hoa và nơi không.
Roman Ivanov

2
@ Tôi không nghĩ rằng sự bất biến liên quan đến việc nhà nước thay đổi như thế nào, chỉ có điều nó làm. hơn nữa, người dùng là gì? Người dùng bên ngoài chạy chương trình? bạn có thể phân biệt giữa trạng thái được sửa đổi bởi người dùng nhấn nút và trạng thái được sửa đổi bằng bộ định thời bắn ở một khoảng thời gian ngẫu nhiên không? (tôi không nghĩ vậy).
Jeffrey Blattman

235

Để thêm nhiều giá trị hơn cho câu trả lời của crunchdog, Hướng dẫn kiểu mã hóa Java nêu điều này trong đoạn 3.3 Đặt tên trường

Tên của các trường đang được sử dụng như hằng số phải là chữ hoa, với các từ được phân tách bằng dấu gạch dưới. Sau đây được coi là hằng số:

  1. Tất cả các static finalkiểu nguyên thủy (Hãy nhớ rằng tất cả các trường giao diện là vốn có static final).
  2. Tất cả các static finalloại tham chiếu đối tượng không bao giờ được theo sau bởi " ." (dấu chấm).
  3. Tất cả static finalcác mảng không bao giờ được theo sau bởi " [" (mở dấu ngoặc vuông).

Ví dụ:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

Theo quy ước này, loggerlà một static finaltham chiếu đối tượng như được nêu trong điểm 2, nhưng vì nó được theo sau bởi " ." mỗi khi bạn sử dụng nó, nên nó không thể được coi là một hằng số và do đó nên viết thường.


11
Định nghĩa tốt nhất tôi đã thấy cho điều này chưa. Tài liệu được liên kết dường như đã di chuyển ở đây bản cập nhật cs.bilgi.edu.tr/pages/stiterias_project/ mẹo
robert

15
Tôi không nhận được điểm 2. Ví dụ về loại đối tượng không bao giờ được theo sau bởi dấu chấm. Tất cả các loại đối tượng kế thừa từ Objectvà bạn có thể gọi một phương thức như .equalstrên chúng.
dogbane

6
Bạn đúng rồi. Và khi xem một số hằng số Java như Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER hoặc Collections.EMPTY_LIST, chúng cũng có thể được theo dõi ..
chơi cbliard

5
@RomanIvanov Tôi đã tìm thấy nó một lần nữa ở đây: scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy được viết bởi Achut Reddy, cập nhật lần cuối ngày 30 tháng 5 năm 2000
cbliard

1
Tôi tin rằng mục đích của 2 là chỉ định rằng chỉ các lớp được so sánh với các hằng số được coi là hằng số. Lớp học không có nghĩa là 'được sử dụng'. Tôi biết luôn co rúm khi nhìn thấy SOME_CLASS.doStuff (). Nó chỉ là mã hóa. Vấn đề duy nhất với điều này là trong trường hợp chung của một đối tượng không đổi (Chuỗi là ví dụ phổ biến) chỉ nhằm mục đích so sánh, nhưng để tránh kiểm tra null, mã hóa kiểu yoda được sử dụng và do đó được gọi là hằng số. Tôi nghĩ rằng tôi sẽ biến điều này thành một lời cảnh báo đến 2.
Robin

44

Từ java hiệu quả, tái bản lần 2,.

Ngoại lệ duy nhất đối với quy tắc trước đó liên quan đến các trường hằng số, các tên có tên bao gồm một hoặc nhiều từ viết hoa được phân tách bằng ký tự gạch dưới, ví dụ: GIÁ TRỊ hoặc NEGECT_INFINITY. Trường không đổi là trường cuối cùng tĩnh có giá trị là bất biến . Nếu trường cuối cùng tĩnh có loại nguyên thủy hoặc loại tham chiếu không thay đổi (Mục 15), thì đó là trường không đổi. Ví dụ, hằng số enum là các trường không đổi. Nếu một trường cuối cùng tĩnh có loại tham chiếu có thể thay đổi, nó vẫn có thể là trường không đổi nếu đối tượng được tham chiếu là bất biến.

Tóm lại, hằng số == tĩnh cuối cùng, cộng với nếu đó là tham chiếu (so với loại đơn giản), tính bất biến.

Nhìn vào trình ghi nhật ký slf4j, http://www.slf4j.org/api/org/slf4j/Logger.html

Nó là bất biến. Mặt khác, logger JUL có thể thay đổi. Trình ghi nhật ký log4j cũng có thể thay đổi. Vì vậy, để chính xác, nếu bạn đang sử dụng log4j hoặc JUL, thì nó phải là "logger" và nếu bạn đang sử dụng slf4j, thì nó phải là LOGGER.

Lưu ý rằng trang javadocs slf4j được liên kết ở trên có một ví dụ nơi họ sử dụng "logger", không phải "LOGGER".

Đây tất nhiên chỉ là quy ước và không phải là quy tắc. Nếu bạn tình cờ sử dụng slf4j và bạn muốn sử dụng "logger" bởi vì bạn đã quen với điều đó từ các khung công tác khác, hoặc nếu việc nhập dễ dàng hơn hoặc để dễ đọc hơn, hãy tiếp tục.


2
Dựa trên lý do này thì định nghĩa đơn giản của checkstyle là không phù hợp phải không?
robert

3
tôi không biết kiểm tra quy tắc của phong cách. nếu nó chỉ đơn giản nhấn mạnh rằng bất kỳ trận chung kết tĩnh nào cũng phải là chữ hoa, thì đúng, điều đó là sai.
Jeffrey Blattman

5
Làm thế nào chính xác là Logger giao diện bất biến ? Chỉ một final class(như Stringhoặc Integer) có thể đảm bảo tính bất biến. Ngay cả khi bạn không thể tìm thấy bất kỳ triển khai SLF4J có thể thay đổi nào Logger, không ai có thể ngăn bạn tự viết.
Costi Ciudatu

Bởi vì các phương thức trong giao diện không cho phép đột biến vốn có. Bạn đã đúng mặc dù bạn có thể thực hiện giao diện để có tác dụng phụ có thể thay đổi.
Jeffrey Blattman

Kiểm tra các quy tắc phong cách KHÔNG đủ ĐÚNG để ngụ ý khả năng đọc. Khả năng đọc không thể đạt được bằng cách tạo khuôn mẫu, khả năng đọc có thể khác nhau tùy theo từng trường hợp dựa trên ngữ cảnh. Xem mã JDK, nó không tuân theo bất kỳ mẫu kiểu nào và được tạo bởi các chuyên gia, cho thấy một cái gì đó.
Daniel Hári

37

Tôi thích Google đảm nhận điều đó ( Google Java Style )

Mỗi hằng số là một trường cuối cùng tĩnh, nhưng không phải tất cả các trường cuối cùng tĩnh là hằng số. Trước khi chọn trường hợp không đổi, hãy xem xét trường có thực sự cảm thấy như một hằng số không. Ví dụ, nếu bất kỳ trạng thái quan sát nào của trường hợp đó có thể thay đổi, thì gần như chắc chắn đó không phải là hằng số. Chỉ có ý định không bao giờ đột biến đối tượng nói chung là không đủ.

Ví dụ:

// 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
Tôi nghĩ rằng câu đầu tiên tóm tắt điều này một cách cô đọng: "Mỗi hằng số là một trường cuối cùng tĩnh, nhưng không phải tất cả các trường cuối cùng tĩnh đều là hằng số." Thật dễ dàng để sử dụng tư duy cơ học và chỉ có mọi trường cuối cùng tĩnh trong chữ hoa (và tôi đã làm điều này cho đến bây giờ) nhưng điều này là để bỏ lỡ sự tinh tế của ngôn ngữ.
ayahuasca

Theo trích dẫn đó, nó sẽ sôi lên nếu trường "thực sự cảm thấy" như một hằng số. Chúng tôi là kỹ sư, không phải bác sĩ tâm thần.
Jeffrey Blattman

"Hãy xem xét ... nếu nó thực sự cảm thấy như một hằng số". Cảm xúc của ai đó thực sự không nên tham gia vào lĩnh vực kỹ thuật.
Jeffrey Blattman

Sau đó, trong mã của Guava, họ có nóprivate static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Kenston Choi

10

Nếu bạn đang sử dụng một công cụ tự động để kiểm tra các tiêu chuẩn mã hóa của mình và nó vi phạm các tiêu chuẩn đã nói thì nó hoặc các tiêu chuẩn sẽ được sửa chữa. Nếu bạn đang sử dụng một tiêu chuẩn bên ngoài, hãy sửa mã.

Quy ước trong Sun Java là chữ hoa cho các hằng số tĩnh công khai. Rõ ràng một logger không phải là hằng số, nhưng đại diện cho một thứ có thể thay đổi (nếu không sẽ không có phương thức gọi điểm nào trên đó với hy vọng điều gì đó sẽ xảy ra); không có tiêu chuẩn cụ thể cho các trường cuối cùng không liên tục.


10
Tại sao bạn nói logger không phải là hằng số? Có vẻ như thực sự không đổi. Việc ghi nhật ký được tạo ra là một tác dụng phụ của việc gọi các phương thức của nó, nhưng không thay đổi trạng thái quan sát được. Tôi đã bỏ lỡ một cái gì đó?
KLE

Kiểm tra API. Nó có một cặp phương thức add / get. Nhưng dù sao bạn cũng có lý do. Ghi nhật ký là có thể quan sát (nếu không, những gì điểm).
Tom Hawtin - tackline

3
Nếu nó là một StringBuilder chứ không phải là một logger, thì có lẽ rõ ràng là không phải là hằng số. Ngay cả đối với logger, các phương thức như Logger.setLevel () có thể làm thay đổi người nhận một cách quan sát. Nói chung chữ hoa dành cho những hằng số mà ngôn ngữ coi là hằng số và sẽ nội tuyến.
Pete Kirkham

5
Bộ ghi chép không phải là hằng số vì nó là một tham chiếu đến một đối tượng. Các hằng số là các giá trị không thể thay đổi. Tham chiếu đối tượng là cuối cùng (vì vậy tham chiếu đến nó không thể thay đổi, ví dụ như hoán đổi với thứ khác hoặc được đặt thành null) nhưng bản thân đối tượng có thể.
Spoike

1
@JeffreyBlattman Tôi không đồng ý rằng tất cả các tài liệu tham khảo cuối cùng nên viết hoa, nhưng bạn có thể tự do áp dụng bất kỳ tiêu chuẩn mã hóa nào bạn muốn. Tôi xin lỗi vì bạn tìm thấy sự khác biệt giữa 'đối tượng có thể thay đổi' và 'đối tượng đại diện cho một điều có thể thay đổi' gây nhầm lẫn; một ví dụ có thể là số tài khoản trở lại của bạn, bản thân nó không thay đổi, nhưng được sử dụng để truy cập số dư thay đổi. Tìm kiếm sự khác biệt giữa người ký và ý nghĩa và để biết thêm chi tiết, hoặc giới thiệu về các đơn vị của Leibnitz để biết làm thế nào một điều bất biến có thể đại diện cho tính đột biến.
Pete Kirkham

7

Nếu bạn google cái này, bạn có thể thấy rằng trong một số trường hợp, logger không được định nghĩa là cuối cùng tĩnh. Thêm một số bản sao-dán nhanh vào đây và điều này có thể giải thích nó.

Chúng tôi sử dụng LOGGER trong tất cả các mã của chúng tôi và điều này tương ứng với quy ước đặt tên của chúng tôi (và CheckStyle của chúng tôi hài lòng với nó).


Chúng tôi thậm chí còn đi xa hơn, tận dụng quy ước đặt tên nghiêm ngặt trong Eclipse. Chúng tôi tạo một lớp mới với một mẫu mã gồm:

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

Trình ghi nhật ký được nhận xét, vì ban đầu chúng tôi không cần nó. Nhưng chúng ta nên cần nó sau, chúng ta chỉ cần bỏ qua nó.

Sau đó, trong mã, chúng tôi sử dụng các mẫu mã dự kiến ​​trình ghi nhật ký này sẽ xuất hiện. Ví dụ với mẫu thử bắt:

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

Chúng tôi có thêm một vài mẫu sử dụng nó.

Quy ước nghiêm ngặt cho phép chúng tôi làm việc hiệu quả hơn và mạch lạc hơn với các mẫu mã .


5
Bắt Ném có thể là một thực hành xấu, trừ khi bạn đăng nhập và suy nghĩ lại. Ghi nhớ lỗi: OutOfMemeoryError, v.v. Ngoại lệ sự kiện không an toàn để bạn có thể tự mình nắm bắt và xử lý trong các ứng dụng đa luồng.
m_vitaly

2
Cú pháp của Eclipse là: Logger.getLogger ($ {kèm theo_type}. Class);
dogbane

@fahdshariff Cảm ơn cú pháp chính xác. Tôi cập nhật câu trả lời của tôi.
KLE

Nếu "các quy ước nghiêm ngặt" của CheckStyle hoặc PMD có ích, thì tại sao các nguồn Guava và JDK không có BẤT K phong cách áp dụng chung nào? Ví dụ, nguồn của họ có rất nhiều khối nội tuyến đầy đủ khi cần thiết. Khả năng đọc phụ thuộc vào ngữ cảnh, vì vậy sử dụng các quy ước kiểu dáng nghiêm ngặt cho mọi thứ sẽ phá hủy các quyết định dựa trên bối cảnh, do đó làm giảm khả năng đọc.
Daniel Hári

6

Cá nhân tôi nghĩ rằng nó trông thực sự lớn trong trường hợp cao. Hơn nữa, vì đây là một lớp không liên quan trực tiếp đến hành vi của lớp, nên tôi không thấy vấn đề lớn trong việc sử dụng loggerthay vì LOGGER. Nhưng nếu bạn sẽ nghiêm khắc phạm vi, sau đó sử dụng LOGGER.


4

Đừng quên rằng PMD sẽ tôn trọng một bình luận với

// NOPMD

trong đó. Điều này sẽ khiến PMD bỏ qua dòng từ kiểm tra của nó, điều này sẽ cho phép bạn chọn bất kỳ kiểu nào bạn muốn.


6
Hoặc không sử dụng PMD, chúng luôn sai và mã của bạn là hoàn hảo
IAd CHƯƠNG

1
Nếu bạn luôn cần loại trừ séc mỗi lần, thì séc sẽ không có ý nghĩa.
keiki

Không thể đồng ý nhiều hơn - tuy nhiên ... thật hữu ích khi biết nhận xét loại trừ
Fortyrunner

3

Các hằng số thường được viết hoa.

Tuy nhiên, logger không nên tĩnh mà tìm kiếm mọi "mới" của lớp chứa nếu sử dụng mặt tiền slf4j. Điều này tránh một số vấn đề trình nạp lớp khó chịu trong các thùng chứa web đáng chú ý, cộng với nó cho phép khung logger thực hiện các công cụ đặc biệt tùy thuộc vào bối cảnh gọi.


2

Tôi thích 'logger', tức là chữ thường. Lý do không phải là hằng số hay không phải là hằng số (có thể thay đổi hoặc không thay đổi). Nếu chúng ta sử dụng lý do đó, chúng ta sẽ phải đổi tên biến nếu chúng ta thay đổi khung ghi nhật ký (hoặc nếu khung thay đổi khả năng biến đổi của logger).

Đối với tôi, những lý do khác quan trọng hơn.

  1. Một logger là một đối tượng bóng trong lớp và không được nổi bật lắm vì nó không thực hiện logic chính. Nếu chúng ta sử dụng 'LOGGER', thì đó là một công cụ bắt mắt trong mã thu hút quá nhiều sự chú ý.

  2. Đôi khi logger được khai báo ở mức cá thể (tức là không phải là tĩnh) và thậm chí được thêm vào như một phụ thuộc. Tôi sẽ không muốn thay đổi mã của mình nếu tôi quyết định thay đổi cách lấy logger. Các mã ổn định wrt. sự thay đổi này (giả thuyết trong nhiều trường hợp) là lý do khác khiến tôi thích chữ thường hơn.


1

Nếu tiêu chuẩn mã hóa của bạn - nếu bạn có bất kỳ - nói rằng nó nên viết hoa thì có.

Tôi không thấy bất kỳ lý do nghiêm ngặt nào cho cách này hay cách khác. Tôi nghĩ rằng nó hoàn toàn phụ thuộc vào sự tôn trọng cá nhân của bạn. tiêu chuẩn mã hóa công ty của bạn.

BTW: Tôi thích "LOGGER" ;-)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.