Một bản tóm tắt ngắn về các thực hành tốt nhất về mã hóa Java

dựa trên các tiêu chuẩn mã hóa của Oracle, Google, Twitter và Spring Framework

Mục tiêu của bài viết này là cung cấp cho bạn một bản tóm tắt nhanh về làm và không nói cách khác thích và tránh dựa trên các tiêu chuẩn mã hóa từ những người khổng lồ công nghệ như Oracle, Google, Twitter và Spring Framework.

Bạn có thể hoặc có thể không đồng ý với một số thực tiễn tốt nhất được trình bày ở đây, và điều đó hoàn toàn tốt miễn là có một số tiêu chuẩn mã hóa được áp dụng.

Tại sao tiêu chuẩn mã hóa ở nơi đầu tiên? Có nhiều lý do chính đáng nếu bạn Google nó và tôi sẽ để lại cho bạn hình minh họa sau

Mã hóa tài liệu tiêu chuẩn có thể dài và nhàm chán. Bài viết này chọn các mẩu và mẩu từ các quy ước mã hóa của Google, Oracle, Twitter và Spring và mục tiêu của nó là cung cấp cho bạn một bộ thực hành dễ thực hiện và ít nhàm chán để làm cho mã của bạn dễ đọc và duy trì.

Hầu như bạn luôn tham gia các nhóm làm việc trên phần mềm hiện có và rất có khả năng hầu hết các tác giả đã rời khỏi hoặc chuyển sang các dự án khác nhau, khiến bạn bị mắc kẹt với các phần mã khiến bạn phải đặt câu hỏi cho nhân loại.

Hãy cùng đi sâu vào thực tiễn tốt nhất từ ​​các tiêu chuẩn mã hóa khác nhau.

Tệp nguồn Java

Sau đây được coi là thực tiễn tốt nhất khi nói đến các tệp nguồn java:

  • Độ dài tệp nguồn thấp hơn 2.000 dòng mã
  • Tệp nguồn được tổ chức với nhận xét tài liệu, khai báo gói, theo sau là nhận xét lớp, nhập nhóm (cuối cùng tĩnh), chữ ký lớp / giao diện, v.v.
gói com.example.model;
/ **
 * Phối cảnh không có triển khai để các nhà phát triển đọc
 * người có thể không nhất thiết phải có mã nguồn trong tay
 *
 * @ Tác giả x, y, z
 * @ngày
 * @phiên bản
 * @copyright
 *
 * /
nhập com.example.util.FileUtil;
/ *
 * Nhận xét cụ thể của lớp
 *
 * /
lớp công khai someClass {
  // Biến tĩnh theo thứ tự khả năng hiển thị
  Số nguyên tĩnh cuối cùng PUBLIC_COUNT = 1;
  Số nguyên cuối cùng tĩnh PROTECTED_COUNT = 1;
  Số nguyên tĩnh cuối cùng riêng tư PRIVATE_COUNT = 1;
  // Biến sơ thẩm theo thứ tự khả năng hiển thị
  Tên chuỗi công khai;
  Chuỗi mã bưu điện;
  địa chỉ chuỗi riêng;
  // Trình xây dựng và quá tải theo thứ tự tuần tự
  công khai someClass () {}
  công khai someClass (Tên chuỗi) {
    this .name = name;
  }
  // Phương thức
  chuỗi công khai doS SomethingUseful () {
    trả lại "Một cái gì đó hữu ích";
  }
  // getters, setters, bằng, hashCode và toString ở cuối
}

Đặt tên

Tên lớp và giao diện là CamelCase và nên sử dụng toàn bộ từ và tránh các từ viết tắt / viết tắt. Ví dụ: lớp Raster hoặc lớp ImageSprite

  • Gói - tên com.deepspace trên com.deepSpace hoặc com.deep_space
  • Tên tệp là CamelCase và kết thúc bằng .java khớp với tên lớp. Có một lớp công khai cho mỗi tệp với mỗi lớp cấp cao nhất trong tệp của nó
  • Phương thức - tên phải là động từ trong trường hợp hỗn hợp với mỗi từ nội bộ được viết hoa ví dụ run (); hoặc runFast ();
  • Các hằng số - nên được viết hoa bằng chữ viết hoa, phân tách từng từ, ví dụ int MIN_WIDTH = 44; và int MAX_WIDTH = 99;
  • Biến - một tên cho người đọc chương trình biết biến đó đại diện cho nghĩa là gì nếu bạn đang lưu trữ một lớp kiểm tra thì chọn lớp so với var1. Giữ tên biến ngắn tránh bao gồm siêu dữ liệu.
// Prefer () - tên biến ngắn và mô tả những gì nó lưu trữ
int trườngId;
int [] đã lọcSchoolIds;
int [] uniqueSchooldIds;
Bản đồ  usersById;
Chuỗi giá trị;
// Tránh (x) - Đặt tên biến quá chi tiết
int schoolIdentificationNumber;
int [] userProvidedSchoolIds;
int [] schoolIdsAfterRemovingD trùng lặp;
Bản đồ  idToUserMap;
Chuỗi valueString;

Ghi nhớ - tên biến phải ngắn gọn và dễ dàng cho người đọc biết giá trị của nó. Sử dụng phán đoán của bạn.

Thích & Tránh

Định dạng và thụt lề là tất cả về cách tổ chức mã của bạn để dễ đọc và bao gồm khoảng cách, độ dài dòng, kết thúc và ngắt, v.v.

  • Thụt lề - Sử dụng 2 hoặc 4 dấu cách và duy trì sự nhất quán
  • Độ dài dòng - Tối đa 70 đến 120 ký tự tùy thuộc vào ảnh hưởng đến khả năng đọc. Nó rất quan trọng để loại bỏ sự cần thiết phải cuộn ngang và ngắt dòng sau một dấu phẩy và toán tử.

Phương pháp - Dưới đây là danh sách các thực tiễn tốt nhất

// Thích () Ngắt dòng là tùy ý và ngắt sau dấu phẩy.
Chuỗi tải xuống ANI Internet (Internet internet, ống ống,
    Blog của thế giới blog, Số lượng  băng thông) {
  ống.d Download (internet);
}
// Tránh (x) Phương thức khó tìm khác biệt với thân phương thức
Chuỗi tải xuống ANI Internet (Internet internet, ống ống,
    Blog của thế giới blog, Số lượng  băng thông) {
    ống.d Download (internet);
}
// Thích () Thêm 8 (gấp đôi 2 hoặc 4) khoảng trắng cho thụt sâu
horking đồng bộ hóa tĩnh riêng tưLongMethodName (int anArg,
        Đối tượng AnotherArg, String yetAotherArg,
        Đối tượng vàStillAnther) {
  ...
}
// Thích () Dễ dàng quét và thêm không gian cột.
Tải xuống chuỗi công khaiAnI Internet (
    Internet
    Ống ống,
    Blog của thế giới blog,
    Số lượng  băng thông) {
  ống.d Download (internet);
  ...
}
Một bài kiểm tra đơn vị sẽ bắt được rằng

Kiểm tra nếu - IMO viết mã được định dạng tốt giúp dễ dàng phát hiện lỗi chính tả và lỗi cho tác giả và người đánh giá mã, xem bên dưới:

// Tránh (x) Đừng bỏ qua {}
nếu (điều kiện)
  tuyên bố;
// Tránh (x)
if (x <0) âm (x);
// Tránh (x)
if (a == b && c == d) {
...
}
// Thích ()
if ((a == b) && (c == d)) {
...
}
// Thích ()
nếu (điều kiện) {
  các câu lệnh;
} khác nếu (điều kiện) {
  các câu lệnh;
} khác nếu (điều kiện) {
  các câu lệnh;
}
// Tránh (x)
if ((condition1 && condition2)
    | | (điều kiện3 && điều kiện4)
    ||! (condition5 && condition6)) {// BAD WRAPS
    doS Something AboutIt (); // TẠO DÒNG NÀY DỄ DÀNG ĐỂ NHỚ
}
// Thích ()
if ((condition1 && condition2)
        | | (điều kiện3 && điều kiện4)
        ||! (điều kiện5 && điều kiện6)) {
    doS Something AboutIt ();
}

Toán tử ternary - Và dưới đây là các thực hành được khuyến nghị

alpha = (aLongBooleanExpression)? beta: gamma;
alpha = (aLongBooleanExpression)? beta
        : gamma;
alpha = (aLongBooleanExpression)
        ? beta
        : gamma;

Chuyển đổi - Khi nói đến chuyển đổi, nó thực hành tốt nhất

  • Luôn có trường hợp mặc định ngay cả khi không có mã
  • Sử dụng / * rơi qua * / để biểu thị điều khiển rơi vào trường hợp tiếp theo
chuyển đổi (điều kiện) {
  trường hợp ABC:
    các câu lệnh;
  / * rơi qua * /
  trường hợp DEF:
    các câu lệnh;
    phá vỡ;
  mặc định:
    các câu lệnh;
     phá vỡ;
}

Thông báo ngoại lệ - Khi ném một ngoại lệ ở đây là các mẫu tin nhắn tốt và kém thụt lề.

// Tránh (x) - Không dễ đọc
ném IllegalStateException mới ("Không thể xử lý yêu cầu" + request.getId ()
    + "cho người dùng" + user.getId () + "truy vấn: '" + query.getText ()
    + "'");
// Thích () - Dễ đọc hơn
ném IllegalStateException mới ("Không thể xử lý"
    + "yêu cầu" + request.getId ()
    + "cho người dùng" + user.getId ()
    + "truy vấn: '" + query.getText () + "'");

Lặp và luồng - Luồng đang trở nên phổ biến hơn và đôi khi nó có thể rất phức tạp do đó, nó rất quan trọng để thụt lề để dễ đọc.

// Tránh (x) - Không dễ đọc
Có thể lặp  mô đun = ImmutableList.  builder (). Add (new LifecyclModule ())
    .add (AppLauncherModule ()) mới. add ALL (application.getModules ()). build ();
// Thích () - Dễ đọc hơn
Có thể lặp  mô-đun = ImmutableList.  builder ()
    .add (Vòng đời mới ())
    .add (AppLauncherModule ()) mới
    .add ALL (application.getModules ())
    .xây dựng();
Chỉ cần tuân theo một tiêu chuẩn mã hóa - bất kỳ thực sự

Tuyên bố và chuyển nhượng Bản khai Một dòng trên mỗi dòng được khuyến nghị vì nó khuyến khích các bình luận như dưới đây.

// Thích ()
cấp độ int; // mức thụt
int sizeMeter; // kích thước của bảng
// Tránh (x) ủng hộ ở trên
int level, sizeMeter;
// Ưu tiên (✔) - Bao gồm đơn vị trong tên hoặc loại biến
pollIntervalMs dài;
int fileSizeGb;
Số lượng  fileSize;
// Tránh (x) các kiểu trộn
int foo, fooarray [];
// Tránh (x) - Không phân tách bằng dấu phẩy
Format.print (System.out, lỗi lỗi trực tiếp), thoát (1);
// Tránh (x) nhiều nhiệm vụ
fooBar.fChar = barFoo.lchar = 'c';
// Tránh (x) các bài tập được nhúng để cố gắng tăng hiệu suất // hoặc lưu một dòng. Tôi có tội khi làm điều này :(
d = (a = b + c) + r;
// Thích () hơn ở trên
a = b + c;
d = a + r;
// Thích ()
Chuỗi [] lập luận
// Tránh (x)
Chuỗi args []
// Thích () Sử dụng lâu "L" thay vì "l" để tránh nhầm lẫn với 1
thời gian chờ dài = 3000000000L;
// Tránh (x) - Khó để nói chữ cái cuối cùng là l chứ không phải 1
thời gian chờ dài = 3000000000l;

Chỉ khai báo ở đầu các khối (Một khối là mã được bao quanh bởi dấu ngoặc nhọn {và}). Đừng chờ đợi để khai báo các biến cho đến khi sử dụng lần đầu tiên của họ; nó có thể gây nhầm lẫn cho lập trình viên không mong muốn và cản trở tính di động của mã trong phạm vi.

// Ưu tiên () khai báo ở đầu khối.
công khai void doS Something () {
  int whatIRepftime; // bắt đầu khối phương thức
  nếu (điều kiện) {
    int someFlag; // bắt đầu của khối if nếu khối
    Giáo dục
  }
}

Nó cũng quan trọng để tránh các tuyên bố địa phương che giấu các tuyên bố của các cấp cao hơn và là để tránh nhầm lẫn như được hiển thị dưới đây

số lượng int;
...
công khai void doS Something () {
  nếu (điều kiện) {
    số lượng int; // TRÁNH!
    ...
  }
  ...
}

Giãn cách & ngắt dòng - Tránh sự cám dỗ của việc lưu 1 dòng mã22 với chi phí dễ đọc. Dưới đây là tất cả các thực tiễn tốt nhất khi nói đến khoảng cách và các dòng trống (Một khoảng trắng sẽ tạo ra sự khác biệt)

  • Một (1) dòng trống giữa các phương thức và các nhà phát triển Spring khuyến nghị hai (2) dòng trống sau các hàm tạo, khối tĩnh, các trường và lớp bên trong
  • Toán tử không gian, tức là sử dụng int foo = a + b + 1; trên int foo = a + b + 1;
  • Tách tất cả các toán tử nhị phân trừ trừ.. Từ các toán hạng sử dụng khoảng trắng
  • Niềng răng mở {{xuất hiện ở cuối cùng dòng với câu lệnh hoặc phương thức khai báo và đóng dấu ngoặc nhọn}} Bắt đầu một dòng tự thụt lề
// Thích () - Khoảng trắng sau "while" và trước "("
trong khi (đúng) {
  ...
}
// Tránh (x) - Không giống như trên không có không gian
trong khi (đúng) {
  ...
}
// Thích () - Không có khoảng cách giữa "doS Something" và "("
công khai void doS Something () {
  ...
}
// Tránh (x) - Không giống như không gian trên
công khai void doS Something () {
  ...
}
// Thích () - Thêm khoảng trắng sau một đối số
công khai void doS Something (int a, int b) {
  ...
}
// Ưu tiên () - Khoảng cách giữa toán hạng và toán tử (tức là +, =)
a + = c + d;
a = (a + b) / (c * d);
trong khi (d ++ = s ++) {
  n ++;
}

Tài liệu và bình luận

Điều đáng nói là hầu như tất cả các mã đều thay đổi trong suốt vòng đời của nó và sẽ có lúc bạn hoặc ai đó đang cố gắng tìm ra một khối mã phức tạp, một phương thức hoặc một lớp dự định làm gì trừ khi được mô tả rõ ràng. Thực tế hầu như luôn luôn như sau

Có những lúc nhận xét về một đoạn mã, phương thức, lớp phức tạp không thêm bất kỳ giá trị nào hoặc phục vụ mục đích của nó. Điều này thường xảy ra khi bình luận vì lợi ích của nó.

Nhận xét nên được sử dụng để cung cấp tổng quan về mã và cung cấp thêm thông tin không có sẵn trong chính mã. Bắt đầu nào. Có hai loại ý kiến

Nhận xét triển khai - có nghĩa là để nhận xét mã hoặc nhận xét về việc triển khai cụ thể của mã.

Nhận xét Tài liệu - có nghĩa là để mô tả đặc điểm kỹ thuật của mã từ góc độ không triển khai được đọc bởi các nhà phát triển, những người có thể không nhất thiết phải có mã nguồn trong tay.

Tần suất bình luận đôi khi phản ánh chất lượng mã kém. Khi bạn cảm thấy bắt buộc phải thêm một bình luận, hãy xem xét viết lại mã để làm cho nó rõ ràng hơn.

Các loại ý kiến ​​thực hiện

Có bốn (4) loại ý kiến ​​thực hiện như dưới đây

  • Chặn nhận xét - xem ví dụ bên dưới
  • Nhận xét một dòng - khi nhận xét không dài hơn một dòng
  • Trailing comment - Nhận xét rất ngắn được chuyển đến cuối bên phải
  • Kết thúc dòng bình luận - bắt đầu một bình luận tiếp tục đến dòng mới. Nó có thể nhận xét một dòng hoàn chỉnh hoặc chỉ một dòng một phần. Nó không nên được sử dụng trên nhiều dòng liên tiếp để bình luận văn bản; tuy nhiên, nó có thể được sử dụng trong nhiều dòng liên tiếp để nhận xét các phần của mã.
// Chặn bình luận
/ *
 * Cách sử dụng: Cung cấp mô tả về tệp, phương thức, cấu trúc dữ liệu
 * và thuật toán. Có thể được sử dụng ở đầu mỗi tập tin và
 * trước mỗi phương thức. Được sử dụng cho các bình luận dài không phù hợp với
 * dòng đơn. 1 dòng trống để tiến hành sau khi nhận xét khối.
 * /
// Nhận xét dòng đơn
nếu (điều kiện) {
 / * Xử lý tình trạng. * /
  ...
}
// Nhận xét
if (a == 2) {
 trả lại ĐÚNG; /* trương hợp đặc biệt */
} khác {
 trả về isPrime (a); / * chỉ hoạt động cho lẻ a * /
}
// Nhận xét cuối dòng
if (foo> 1) {
  // Thực hiện lật đôi.
  ...
} khác {
  trả lại sai; // Giải thích tại sao ở đây.
}
// nếu (thanh> 1) {
//
// // Thực hiện lật ba lần.
// ...
//}
// khác
// trả về sai;

Nhận xét tài liệu (tức là Javadoc)

Javadoc là một công cụ tạo tài liệu HTML tạo thành mã java của bạn bằng cách sử dụng các nhận xét bắt đầu bằng / ** và kết thúc bằng * / - xem Wikipedia để biết thêm chi tiết về cách Javadoc hoạt động hoặc chỉ đọc theo.

Đây là một ví dụ về Javadoc

/ **
 * Trả về một đối tượng Hình ảnh có thể được vẽ trên màn hình.
 * Đối số url phải chỉ định {@link URL} tuyệt đối. Tên
 * đối số là một công cụ xác định có liên quan đến đối số url.
 * 

 * Phương thức này luôn trả về ngay lập tức, cho dù có hay không  * hình ảnh tồn tại. Khi applet này cố gắng vẽ hình ảnh trên  * màn hình, dữ liệu sẽ được tải. Các nguyên thủy đồ họa  * vẽ hình ảnh sẽ tăng dần trên màn hình.  *  * @param url một URL tuyệt đối cho vị trí cơ sở của hình ảnh  * @param đặt tên cho vị trí của hình ảnh, liên quan đến đối số url  * @return hình ảnh tại URL được chỉ định  * @see Hình ảnh  * /  hình ảnh công khai getImage (url URL, tên chuỗi) {         thử {             return getImage (URL mới (url, tên));         } bắt (MalformedURLException e) {             trả về null;         }  }

Và ở trên sẽ dẫn đến một HTML như sau khi javadoc chạy với mã có ở trên

Xem tại đây để biết thêm

Dưới đây là một số thẻ chính mà bạn có thể sử dụng để nâng cao chất lượng của tài liệu java được tạo.

@ Tác giả => @ Tác giả
@code => {@code A  C}
@deprecated => @deprecated khấu hao-tin nhắn
@exception => @exception IOException bị ném khi
@link => {@link gói. class # nhãn thành viên}
@param => @param mô tả tên tham số
@return => Phương thức trả về
@see => @see "chuỗi" HOẶC @see  
@since => Để chỉ ra phiên bản khi phương thức truy cập công khai được thêm vào

Đối với một danh sách đầy đủ và mô tả chi tiết hơn xem tại đây

Tiêu chuẩn mã hóa Twitter khuyên khuyên không nên sử dụng thẻ @ Tác giả

Mã có thể thay đổi tay nhiều lần trong đời và thường thì tác giả gốc của tệp nguồn không liên quan sau vài lần lặp. Chúng tôi thấy nó tốt hơn khi tin tưởng vào lịch sử cam kết và các tệp OWNERS để xác định quyền sở hữu của một bộ mã.

Sau đây là những ví dụ về cách bạn có thể viết bình luận tài liệu sâu sắc như được mô tả trong tiêu chuẩn mã hóa Twitter.

// Xấu.
// - Tài liệu không cho biết khai báo phương thức nào.
// - Đây là 'tài liệu phụ'. Nó sẽ vượt qua kiểm tra phong cách, nhưng
không giúp được ai
/ **
 * Tách một chuỗi.
 *
 * @param s Một chuỗi.
 * @return Một danh sách các chuỗi.
 * /
Danh sách  split (Chuỗi s);
// Tốt hơn.
// - Chúng tôi biết phương thức chia tách trên.
// - Vẫn còn một số hành vi không xác định.
/ **
 * Chia một chuỗi trên khoảng trắng.
 *
 * @param s Chuỗi cần chia. Chuỗi {@code null} được coi là một chuỗi rỗng.
 * @return Một danh sách các phần được phân tách bằng khoảng trắng của đầu vào.
 * /
Danh sách  split (Chuỗi s);
// Tuyệt quá.
// - Bao gồm một trường hợp cạnh khác.
/ **
 * Chia một chuỗi trên khoảng trắng. Ký tự khoảng trắng lặp đi lặp lại
 * bị sụp đổ.
 *
 * @param s Chuỗi cần chia. Chuỗi {@code null} được coi là một chuỗi rỗng.
 * @return Một danh sách các phần được phân tách bằng khoảng trắng của đầu vào.
 * /
Danh sách  split (Chuỗi s);

Điều quan trọng là phải chuyên nghiệp khi viết bình luận

// Tránh (x)
// Tôi ghét xml / xà phòng rất nhiều, tại sao nó không thể làm điều này cho tôi!?
thử {
  userId = Integer.parseInt (xml.getField ("id"));
} bắt (NumberFormatException e) {
  ...
}
// Thích ()
// TODO (Jim): Xác thực trường xác thực trong thư viện.
thử {
  userId = Integer.parseInt (xml.getField ("id"));
} bắt (NumberFormatException e) {
  ...
}

Và điều quan trọng là phải nhớ không ghi lại phương pháp ghi đè trừ khi việc triển khai đã thay đổi.

Và đây là một vài điểm cần lưu ý

  • Tránh nhập ký tự đại diện - như được mô tả trong các tiêu chuẩn mã hóa Twitter, nó làm cho nguồn của lớp không rõ ràng. Tôi làm việc trong một nhóm với sự kết hợp của người dùng Eclipse và IntelliJ và tôi phát hiện ra rằng Eclipse loại bỏ nhập khẩu ký tự đại diện và IntelliJ giới thiệu nó. Có lẽ có một tùy chọn để tắt nó, chỉ muốn chỉ ra mặc định cho cả hai.
  • Luôn sử dụng chú thích @Override khi ghi đè
  • Khuyến khích sử dụng @Nullable khi một trường hoặc phương thức trả về null
  • Sử dụng các nhận xét đặc biệt cho công việc trong tương lai và đừng quên để lại một tài liệu tham khảo cho chính mình để người khác biết ai sẽ hỏi câu hỏi Y của họ thay vì đoán, xóa nó hoặc kiểm tra git đổ lỗi để tìm ai đã thêm nó. Một số IDE như Eclipse và IntelliJ cũng giúp liệt kê những thứ này để dễ truy cập cũng như nhắc nhở.
// FIXME (Raf): Một thông điệp có thể hành động mô tả những gì cần phải được thực hiện
// TODO (Raf): Thông báo có thể thực hiện được mô tả những gì cần được thực hiện

Trò chơi kết thúc là viết mã giúp cuộc sống của các tác giả và nhà bảo trì trong tương lai trở nên dễ dàng.

Trò chơi kết thúc

Tài liệu đọc khác có liên quan

Một danh sách các bài viết có liên quan có liên quan đến việc viết mã sạch sẽ, có cấu trúc tốt, dễ đọc và dễ bảo trì. Nếu bạn muốn đọc thêm, chắc chắn đề nghị những điều sau đây

và một danh sách tốt các mẹo để viết mã sạch