

Tên chính xác
Tên chính xác cải thiện khả năng đọc mã, do đó giảm thời gian cần thiết để bạn làm quen với mã, bởi vì việc sử dụng một phương thức sẽ dễ dàng hơn nhiều khi tên của nó mô tả gần đúng chức năng của nó. Mọi thứ trong mã bao gồm tên (biến, phương thức, lớp, đối tượng, tệp, v.v.), vì vậy điểm này trở nên rất quan trọng khi tạo mã chính xác, rõ ràng. Dựa trên những điều trên, tên phải truyền đạt ý nghĩa, ví dụ: tại sao biến tồn tại, nó làm gì và nó được sử dụng như thế nào. Tôi sẽ lưu ý nhiều lần rằng nhận xét tốt nhất cho một biến là đặt cho nó một cái tên hay.
từ phim truyền hình "Sherlock" (2010-2017)
giao diện đặt tên
Các giao diện thường có tên bắt đầu bằng chữ in hoa và được viết bằng CamelCase. Khi viết một giao diện, cách tốt nhất là thêm tiền tố "I" để chỉ định nó là một giao diện (ví dụ: IUserService), nhưng điều đó trông khá xấu và gây mất tập trung. Trong những trường hợp như vậy, tốt hơn là bỏ qua tiền tố (UserService) và thêm "Impl" làm hậu tố cho tên triển khai của nó (ví dụ: UserServiceImpl). Hoặc có thể, như một phương sách cuối cùng, hãy thêm tiền tố "C" vào tên của việc triển khai (ví dụ: CUserService).tên lớp
Cũng giống như giao diện, tên lớp được viết hoa và sử dụng CamelCase. Không quan trọng nếu chúng ta đang đối mặt với ngày tận thế của thây ma, không quan trọng nếu ngày tận thế đã cận kề — không bao giờ, không bao giờ, không bao giờ nên để tên của một lớp là một động từ! Tên lớp và đối tượng phải là danh từ hoặc danh từ ghép (UserController, UserDetails, UserAccount, v.v.). Bạn không nên gắn chữ viết tắt của ứng dụng vào cuối tên của mỗi lớp, vì điều đó chỉ làm tăng thêm độ phức tạp không cần thiết. Ví dụ: nếu chúng tôi có ứng dụng Di chuyển dữ liệu người dùng, vui lòng không thêm "UDM" vào mỗi lớp, ví dụ: UDMUserDetails, UDMUserAccount, UDMUserController.Tên phương thức
Thông thường, tên phương thức bắt đầu bằng một chữ cái viết thường, nhưng chúng cũng sử dụng kiểu chữ hoa lạc đà (camelCase). Ở trên, chúng tôi đã nói rằng tên lớp không bao giờ được là động từ. Ở đây, tình huống hoàn toàn ngược lại: tên của các phương thức phải là động từ hoặc cụm động từ: findUserById, findAllUsers, createUser, v.v. Khi tạo một phương thức (cũng như các biến và lớp), nên sử dụng quy ước đặt tên nhất quán để tránh nhầm lẫn. Ví dụ: để tìm người dùng, một phương thức có thể được đặt tên là getUserById hoặc findUserById. Và một điều nữa: đừng sử dụng sự hài hước trong tên của các phương pháp, bởi vì những người khác có thể không hiểu trò đùa này. Kết quả là, họ có thể không nắm bắt được tác dụng của phương pháp này.Tên biến
Trong hầu hết các trường hợp, tên biến bắt đầu bằng một chữ cái viết thường và cũng sử dụng camelCase, trừ khi biến là hằng số toàn cục. Trong những trường hợp như vậy, tất cả các chữ cái của tên được viết bằng chữ hoa và các từ được phân tách bằng dấu gạch dưới ("_"). Để thuận tiện, bạn có thể sử dụng ngữ cảnh có ý nghĩa khi đặt tên biến. Nói cách khác, khi một biến tồn tại như một phần của thứ gì đó lớn hơn, chẳng hạn như FirstName, lastName hoặc status. Trong những trường hợp như vậy, bạn có thể thêm tiền tố cho biết đối tượng mà biến này thuộc về. Ví dụ: userFirstName, userLastName, userStatus. Bạn cũng nên tránh đặt tên tương tự cho các biến khi chúng có ý nghĩa hoàn toàn khác nhau. Dưới đây là một số từ trái nghĩa thường gặp được sử dụng trong tên biến:- bắt đầu/kết thúc
- đầu tiên/cuối cùng
- bị khóa/mở khóa
- nhỏ nhất lớn nhất
- tiếp theo/trước
- cũ mới
- mở / đóng
- hữu hình/vô hình
- nguồn/đích
- điểm đến gốc
- lên xuống
Tên biến ngắn
Khi chúng tôi có các biến như x hoặc n hoặc đại loại như vậy, chúng tôi không thấy ngay ý định của người viết mã. Không rõ n làm gì. Tìm ra điều đó đòi hỏi phải suy nghĩ cẩn thận hơn (và điều này có nghĩa là thời gian, thời gian, thời gian). Ví dụ: giả sử chúng ta có một trường đại diện cho id của người dùng chịu trách nhiệm. Thay vì một số tên biến như x hoặc đơn giản là id, chúng tôi sẽ đặt tên biến này là "responsibleUserId", điều này ngay lập tức cải thiện khả năng đọc và nội dung thông tin. Điều đó nói rằng, các tên ngắn như n có một vị trí như các biến cục bộ trong các phương thức nhỏ, trong đó khối mã liên quan đến biến này chỉ dài một vài dòng và tên phương thức mô tả hoàn hảo những gì xảy ra ở đó. Nhìn thấy một biến như vậy, nhà phát triển hiểu rằng nó có tầm quan trọng thứ yếu và có phạm vi rất hạn chế. Kết quả là, phạm vi có một sự phụ thuộc nhất định vào độ dài của tên biến: tên càng dài, biến đó càng toàn cầu và ngược lại. Ví dụ: đây là phương pháp tìm người dùng được lưu cuối cùng theo ngày:
public User findLastUser() {
return findAllUsers().stream()
.sorted((x, y) -> -x.getCreatedDate().compareTo(y.getCreatedDate()))
.findFirst()
.orElseThrow(() -> new ResourceNotFoundException("No user exists"));
}
Ở đây, chúng tôi sử dụng các biến có tên ngắn x và y để sắp xếp luồng và sau đó chúng tôi quên chúng đi.
chiều dài tối ưu
Hãy tiếp tục với chủ đề về độ dài của tên. Độ dài tên tối ưu nằm trong khoảng từ n đến maxNumberOfUsersInTheCurrentGroup. Nói cách khác, những cái tên ngắn thường thiếu ý nghĩa, trong khi những cái tên quá dài sẽ kéo dài chương trình mà không tăng thêm tính dễ đọc và đơn giản là chúng ta quá lười để viết chúng mỗi lần. Ngoài trường hợp được mô tả ở trên đối với các biến có tên ngắn như n, bạn nên chọn độ dài khoảng 8-16 ký tự. Đây không phải là một quy tắc nghiêm ngặt, chỉ là một hướng dẫn.khác biệt nhỏ
Tôi không thể không đề cập đến sự khác biệt tinh tế trong tên. Đây cũng là một cách làm không tốt, vì những điểm khác biệt này có thể đơn giản là gây nhầm lẫn hoặc đòi hỏi phải dành nhiều thời gian hơn để chú ý đến chúng. Ví dụ: khó có thể nhận ra sự khác biệt giữa InvalidDataAccessApiUsageException và InvalidDataAccessResourceUsageException khi nhìn thoáng qua. Sự nhầm lẫn cũng thường xảy ra khi sử dụng chữ thường L và O, vì chúng có thể dễ dàng bị nhầm với 1 và 0. Ở một số phông chữ, sự khác biệt rõ ràng hơn, ở một số phông chữ thì ít hơn.Ý nghĩa
Chúng ta cần làm cho các tên có ý nghĩa, nhưng không tạo ra sự mơ hồ thông qua các từ đồng nghĩa, ví dụ, UserData và UserInfo thực sự có cùng một ý nghĩa. Trong trường hợp này, chúng ta sẽ phải tìm hiểu sâu hơn về mã để hiểu đối tượng cụ thể nào chúng ta cần. Tránh những từ không truyền đạt thông tin hữu ích. Ví dụ, trong firstNameString, tại sao chúng ta cần có từ String? Đây thực sự có thể là một đối tượng Ngày không? Dĩ nhiên là không. Vì vậy, chúng tôi chỉ cần sử dụng firstName. Tôi cũng muốn đề cập đến các biến boolean. Ví dụ, lấy một giá trị boolean có tên là flagDeleted. Cờ từ không có ý nghĩa. Gọi là isDeleted thì hợp lý hơn.thông tin sai lệch
Tôi cũng muốn nói vài lời về quy ước đặt tên không chính xác. Giả sử chúng ta có một biến tên là userActivityList, nhưng thay vì là một Danh sách, đối tượng này là một loại vùng chứa khác hoặc đối tượng lưu trữ tùy chỉnh. Điều này có thể gây nhầm lẫn cho lập trình viên trung bình: tốt hơn nên gọi nó là userActivityGroup hoặc userActivities.Tìm kiếm
Một trong những hạn chế của các tên ngắn và đơn giản là khó tìm thấy chúng trong một lượng lớn mã — Cái nào sẽ dễ tìm hơn: "tên" hoặc "NAME_FOR_DEFAULT_USER"? Tùy chọn thứ hai, tất nhiên. Chúng ta nên tránh các từ (chữ cái) thường gặp trong tên, vì chúng sẽ chỉ làm tăng số lượng tệp phù hợp trong quá trình tìm kiếm, điều này không tốt. Tôi muốn nhắc bạn rằng các lập trình viên dành nhiều thời gian để đọc mã hơn là viết mã, vì vậy hãy thông minh khi đặt tên cho các phần tử trong ứng dụng của bạn. Nhưng nếu một cái tên hay không thể được tìm thấy thì sao? Điều gì xảy ra nếu tên của một phương thức không mô tả tốt chức năng của nó? Đây là nơi nhận xét bước vào sân khấu.Bình luận

Các loại nhận xét
-
Nhận xét pháp lý — Nhận xét ở đầu mỗi tệp nguồn vì lý do pháp lý, ví dụ:
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-
Nhận xét mang tính thông tin — Nhận xét đại diện cho lời giải thích về mã (cung cấp thông tin bổ sung hoặc giải thích về ý định của một phần mã nhất định).
Ví dụ:
/* * Combines the user from the database with the one passed for updating * When a field in requestUser is empty, it is filled with old data from foundUser */ private User mergeUser(User requestUser, User foundUser) { return new User( foundUser.getId(), requestUser.getFirstName() == null ? requestUser.getFirstName() : foundUser.getFirstName(), requestUser.getMiddleName() == null ? requestUser.getMiddleName() : foundUser.getMiddleName(), requestUser.getLastName() == null ? requestUser.getLastName() : foundUser.getLastName(), requestUser.getAge() == null ? requestUser.getAge() : foundUser.getAge() ); }
Trong trường hợp này, bạn có thể làm mà không cần bình luận, vì tên của phương thức và các tham số của nó, cùng với chức năng rất minh bạch, tự mô tả chính xác.
-
Nhận xét cảnh báo — Nhận xét nhằm cảnh báo các nhà phát triển khác về hậu quả không mong muốn của một hành động (ví dụ: cảnh báo họ về lý do tại sao một bài kiểm tra được đánh dấu là @Ignore):
// Takes too long to run // Don't run if you don't have a lot of time @Ignore @Test public void someIntegrationTest() { …… }
-
TODO — Nhận xét là một lưu ý về điều gì đó cần được thực hiện trong tương lai nhưng vì lý do nào đó không thể thực hiện được ngay bây giờ. Đây là một cách làm tốt, nhưng những bình luận như vậy nên được xem xét thường xuyên để loại bỏ những bình luận không liên quan và tránh lộn xộn.
Một ví dụ sẽ là:
// TODO: Add a check for the current user ID (when the security context is created) @Override public Resource downloadFile(File file) { return fileManager.download(file); }
Ở đây, chúng tôi lưu ý rằng chúng tôi cần thêm so sánh giữa người dùng thực hiện thao tác tải xuống (có ID mà chúng tôi sẽ trích xuất từ ngữ cảnh bảo mật) với người đã thực hiện thao tác lưu.
-
Củng cố nhận xét — Nhận xét nhấn mạnh tầm quan trọng của một tình huống mà thoạt nhìn có vẻ không đáng kể.
Ví dụ, hãy xem xét một phần của phương thức điền vào cơ sở dữ liệu thử nghiệm bằng một số tập lệnh:
Stream.of(IOUtils.resourceToString("/fill-scripts/" + x, StandardCharsets.UTF_8) .trim() .split(";")) .forEach(jdbcTemplate::update); // The trim() call is very important. It removes possible spaces at the end of the script // so that when we read and split into separate requests, we don't end up with empty ones
-
Nhận xét Javadoc - Nhận xét mô tả API cho chức năng nhất định. Có lẽ có những nhận xét hữu ích nhất, vì API được ghi lại dễ làm việc hơn nhiều. Điều đó nói rằng, chúng cũng có thể lỗi thời giống như bất kỳ loại bình luận nào khác. Vì vậy, đừng bao giờ quên rằng đóng góp chính cho tài liệu không phải do nhận xét, mà là do mã tốt.
Đây là một ví dụ về một phương pháp khá phổ biến để cập nhật người dùng:
/** * Updates the passed fields for a user based on its id. * * @param id id of the user to be updated * @param user user with populated fields for updating * @return updated user */ User update(Long id, User user);
bình luận xấu
-
bình luận lẩm bẩm — Các bình luận thường được viết vội vàng và chỉ nhà phát triển đã viết chúng mới hiểu được ý nghĩa của chúng, vì chỉ người đó mới nhận thức được tình huống sắc thái mà bình luận đề cập đến.
Hãy xem xét ví dụ này:
public void configureSomeSystem() { try{ String configPath = filesLocation.concat("/").concat(CONFIGURATION_FILE); FileInputStream stream = new FileInputStream(configPath); } catch (FileNotFoundException e) { // If there is no configuration file, the default configuration is loaded } }
Ai tải các cài đặt này? Chúng đã được tải chưa? Phương pháp này có bắt được ngoại lệ và tải cài đặt mặc định không? Quá nhiều câu hỏi phát sinh mà chỉ có thể được trả lời bằng cách đi sâu vào điều tra các phần khác của hệ thống.
- Nhận xét dư thừa — Nhận xét không mang bất kỳ tải ngữ nghĩa nào, vì những gì đang xảy ra trong một phần nhất định của mã là rất rõ ràng. Nói cách khác, bình luận không dễ đọc hơn mã.
Hãy xem một ví dụ:
public class JdbcConnection{ public class JdbcConnection{ /** * The logger associated with the current class */ private Logger log = Logger.getLogger(JdbcConnection.class.getName()); /** * Creates and returns a connection using the input parameters */ public static Connection buildConnection(String url, String login, String password, String driver) throws Exception { Class.forName(driver); connection = DriverManager.getConnection(url, login, password); log.info("Created connection with db"); return connection; }
Điểm của những bình luận như vậy là gì? Mọi thứ họ giải thích đã hoàn toàn rõ ràng.
-
Nhận xét không đáng tin cậy — Nhận xét không đúng sự thật và chỉ gây hiểu lầm (thông tin sai lệch). Ví dụ, đây là một.
/** * Helper method. Closes the connection with the scanner if isNotUsing is true */ private void scanClose(Scanner scan, boolean isNotUsing) throws Exception { if (!isNotUsing) { throw new Exception("The scanner is still in use"); } scan.close(); }
Có gì sai với nhận xét này? Thực tế là nó nói dối chúng ta một chút, ở chỗ kết nối bị đóng nếu isNotUsing là sai chứ không phải ngược lại, như nhận xét cho chúng ta biết.
-
Nhận xét bắt buộc — Các nhận xét được coi là bắt buộc (ví dụ: nhận xét Javadoc), nhưng trên thực tế, đôi khi chúng chồng chất quá mức, không đáng tin cậy và không cần thiết (bạn cần suy nghĩ xem những nhận xét này có thực sự cần thiết hay không).
Ví dụ:
/**
* Create a user based on the parameters
* @param firstName first name of the created user
* @param middleName middle name of the created user
* @param lastName last name of the created user
* @param age age of the created user
* @param address address of the created user
* @return user that was created
*/
User createNewUser(String firstName, String middleName, String lastName, String age, String address);
Bạn có thể hiểu phương pháp này làm gì nếu không có những nhận xét này không? Rất có thể, vâng, vì vậy các bình luận trở nên vô nghĩa ở đây.
Nhật ký nhận xét — Nhận xét đôi khi được thêm vào đầu mô-đun mỗi khi mô-đun được chỉnh sửa (giống như nhật ký thay đổi).
/**
* Records kept since January 9, 2020;
**********************************************************************
* 9 Jan 2020: Providing a database connection using JDBC Connection;
* 15 Jan 2020: Adding DAO-level interfaces for working with the database;
* 23 Jan 2020: Adding integration tests for the database;
* 28 Jan 2020: Implementation of DAO-level interfaces;
* 1 Feb 2020: Development of interfaces for services,
* in accordance with the requirements specified in user stories;
* 16 Feb 2020: Implementation of service interfaces
* (implementation of business logic related to the work of the database);
* 25 Feb 2020: Adding tests for services;
* 8 Mar 2020: Celebration of International Women's Day (Terry is drunk again);
* 21 Mar 2020: Refactoring the service layer;
*/
Cách tiếp cận này đã từng được chứng minh, nhưng với sự ra đời của các hệ thống kiểm soát phiên bản (ví dụ: Git), nó đã trở thành một sự lộn xộn và phức tạp không cần thiết của mã.
Nhận xét về quyền tác giả — Nhận xét có mục đích chỉ ra người đã viết mã, vì vậy bạn có thể liên hệ với anh ấy/cô ấy và thảo luận về cách thức, nội dung và lý do, ví dụ:
* @author Bender Bending
Một lần nữa, các hệ thống kiểm soát phiên bản nhớ chính xác ai đã thêm bất kỳ đoạn mã nào và khi nào, vì vậy phương pháp này là không cần thiết.
Mã bị nhận xét - Mã đã được nhận xét vì lý do này hay lý do khác. Đây là một trong những thói quen tồi tệ nhất, bởi vì điều xảy ra là bạn bình luận điều gì đó rồi quên nó đi, và sau đó các nhà phát triển khác không đủ can đảm để xóa nó (xét cho cùng, nếu đó là thứ gì đó có giá trị thì sao?).
// public void someMethod(SomeObject obj) {
// .....
// }
Kết quả là, mã nhận xét tích lũy như rác. Trong mọi trường hợp, bạn không nên để lại mã như vậy. Nếu bạn thực sự cần nó, đừng quên hệ thống kiểm soát phiên bản.
Nhận xét không rõ ràng — Nhận xét mô tả điều gì đó theo cách quá phức tạp.
/*
* Start with an array large enough to store
* all the data bytes (plus filter bytes) with a cushion, plus 300 bytes
* for header data
*/
this.dataBytes = new byte[(this.size * (this.deep + 1) * 2)+300];
Một bình luận nên giải thích mã. Bản thân nó không cần một lời giải thích. Vậy có gì sai ở đây? "byte bộ lọc" là gì? Tất cả "+ 1" đó là gì? Tại sao chính xác là 300?
- Sử dụng các phong cách dễ duy trì: duy trì các phong cách quá lạ mắt và kỳ lạ sẽ gây khó chịu và tốn thời gian.
- Không sử dụng các chú thích cuối dòng đề cập đến các dòng đơn lẻ: kết quả là một đống lớn các chú thích. Hơn nữa, rất khó để nghĩ ra một bình luận có ý nghĩa cho mỗi dòng.
- Khi bạn viết bình luận, hãy cố gắng trả lời câu hỏi "tại sao" chứ không phải "như thế nào".
- Tránh thông tin rút gọn. Như tôi đã nói ở trên, chúng ta không cần lời giải thích cho một lời bình luận: bản thân lời bình luận đã là lời giải thích.
- Bạn có thể sử dụng nhận xét để ghi chú các đơn vị và phạm vi giá trị.
- Đặt các bình luận gần với mã mà chúng mô tả.
GO TO FULL VERSION