JavaRush /Blog Java /Random-VI /Các lỗi điển hình trong mã Java.
Sdu
Mức độ

Các lỗi điển hình trong mã Java.

Xuất bản trong nhóm
Tài liệu này chứa các lỗi điển hình nhất mà tôi từng thấy trong mã Java của những người làm việc cùng tôi. Phân tích tĩnh (chúng tôi sử dụng qulice ), vì những lý do hiển nhiên, không thể phát hiện tất cả các lỗi như vậy, đó là lý do tại sao tôi quyết định liệt kê chúng ở đây. Tất cả những lỗi này đều liên quan đến lập trình hướng đối tượng nói chung và Java nói riêng.
Tên lớp
Lớp của bạn phải là một sự trừu tượng hóa của một đối tượng trong đời thực mà không có " trình xác thực " , " trình điều khiển " , " trình quản lý " , v.v. Nếu tên lớp của bạn kết thúc bằng "-er" thì đó là thiết kế tồi. Và tất nhiên, các lớp trợ giúp chống mẫu như StringUtils , FileUtilsIOUtils của Apache là những ví dụ tuyệt vời về các mẫu thiết kế khủng khiếp. Không bao giờ thêm hậu tố hoặc tiền tố để phân biệt giữa giao diện và lớp. Ví dụ: tất cả những cái tên này đều khủng khiếp: IRecord , IfaceEmployee hoặc RecordInterface . Thông thường, tên giao diện là tên của đối tượng thực tế, trong khi tên lớp sẽ giải thích chi tiết triển khai. Nếu không thể nói gì cụ thể về việc triển khai thì các tên " Mặc định ", " Đơn giản " hoặc tên nào đó tương tự sẽ có tác dụng. Ví dụ: class SimpleUser implements User {}; class DefaultRecord implements Record {}; class Suffixed implements Name {}; class Validated implements Content {};
Tên phương thức
Các phương thức có thể trả về " something " hoặc trả về " void ". Nếu một phương thức trả về một cái gì đó thì tên của nó sẽ giải thích cái gì sẽ được trả về. Ví dụ: (không sử dụng tiền tố " get "): boolean isValid(String name); String content(); int ageOf(File file); Nếu trả về " void ", tên phải làm rõ phương thức đó làm gì. Ví dụ: void save(File file); void process(Work work); void append(File file, String line); Chỉ có một ngoại lệ cho quy tắc này - Phương pháp kiểm tra JUnit . Chúng được mô tả dưới đây.
Tên phương pháp thử nghiệm
Tên phương thức trong bài kiểm tra JUnit phải được xây dựng dưới dạng câu tiếng Anh không có dấu cách. Điều này sẽ dễ giải thích hơn bằng một ví dụ: Điều /** * HttpRequest can return its content in Unicode. * @throws Exception If test fails */ public void returnsItsContentInUnicode() throws Exception { } quan trọng là bắt đầu câu đầu tiên trong JavaDoc của bạn bằng tên của lớp bạn đang kiểm tra, theo sau là “ can ”. Vì vậy, câu đầu tiên phải luôn giống như cụm từ " ai đó có thể làm điều gì đó ". Tên phương thức sẽ nêu điều tương tự nhưng không có chủ đề thử nghiệm. Nếu tôi thêm nó vào đầu tên phương thức, tôi sẽ nhận được một câu tiếng Anh hoàn chỉnh, như trong ví dụ trên: “ HttpRequest trả về nội dung của nó ở dạng unicode .” Xin lưu ý rằng tên phương pháp kiểm tra không bắt đầu bằng “ can ”. Chỉ các nhận xét JavaDoc mới bắt đầu bằng " can ". Ngoài ra, tên phương thức không được bắt đầu bằng một động từ ( Từ người dịch: rõ ràng, tác giả muốn nói đến tâm trạng mệnh lệnh của động từ ). Đó là một cách thực hành tốt để chỉ ra rằng một ngoại lệ sẽ được đưa ra khi khai báo một phương thức thử nghiệm.
Tên biến
Tránh các tên biến phức hợp như timeOfDay , firstItem hoặc httpRequest . Ý tôi là cả biến lớp và biến phương thức. Tên biến phải đủ dài để tránh sự mơ hồ trong phạm vi của nó, nhưng không quá dài nếu có thể. Tên phải là danh từ số ít hoặc số nhiều. Ví dụ: Đôi khi có thể xảy ra xung đột giữa các tham số của hàm tạo và các trường lớp nếu hàm tạo lưu trữ dữ liệu đầu vào vào đối tượng đã tạo. Trong trường hợp này, tôi khuyên bạn nên tạo từ viết tắt bằng cách loại bỏ các nguyên âm. Ví dụ: Trong hầu hết các trường hợp, tên biến phù hợp nhất sẽ là tên của lớp tương ứng. Chỉ cần viết hoa nó và bạn sẽ ổn thôi: Tuy nhiên, đừng bao giờ làm điều tương tự đối với các kiểu nguyên thủy như or . Bạn cũng có thể sử dụng tính từ khi có nhiều biến số có đặc điểm khác nhau. Ví dụ: List names; void sendThroughProxy(File file, Protocol proto); private File content; public HttpRequest request; public class Message { private String recipient; public Message(String rcpt) { this.recipient = rcpt; } } File file; User user; Branch branch; Integer number String string String contact(String left, String right);
nhà xây dựng
Không có ngoại lệ, chỉ nên có một hàm tạo lưu trữ dữ liệu vào các biến đối tượng. Tất cả các hàm tạo khác phải gọi hàm này với các tham số khác nhau: public class Server { private String address; public Server(String uri) { this.address = uri; } public Server(URI uri) { this(uri.toString()); } }
Biến một lần
Tránh các biến một lần bằng mọi giá. Khi nói “dùng một lần”, ý tôi là các biến được sử dụng một lần. Giống như trong ví dụ này: String name = "data.txt"; return new File(name); Một biến chỉ được sử dụng một lần và mã có thể được đơn giản hóa thành: return new File("data.txt"); Đôi khi, trong những trường hợp rất hiếm - chủ yếu là do định dạng tốt hơn - có thể sử dụng các biến một lần. Tuy nhiên, hãy cố gắng tránh những tình huống như vậy.
Ngoại lệ.
Tất nhiên, bạn không bao giờ nên "nuốt chửng" các ngoại lệ; chúng nên được ném càng cao càng tốt. Các ngoại lệ từ các phương thức riêng tư phải được xử lý từ bên ngoài. Không bao giờ sử dụng ngoại lệ để kiểm soát luồng. Mã trong ví dụ không chính xác: int size; try { size = this.fileSize(); } catch (IOException ex) { size = 0; } Nghiêm túc mà nói, điều gì sẽ xảy ra nếu IOException thông báo "đĩa đã đầy", bạn có cho rằng kích thước tệp bằng 0 và tiếp tục không?
Thụt lề.
Đối với thụt lề, quy tắc chung là dấu ngoặc đơn phải kết thúc dòng hoặc đóng trên cùng một dòng (quy tắc ngược lại áp dụng cho dấu ngoặc đơn đóng). Trong ví dụ bên dưới, mã không chính xác vì dấu ngoặc đơn đầu tiên không được đóng trên cùng một dòng và có các ký tự sau nó. Dấu ngoặc thứ hai gặp vấn đề tương tự vì có các ký tự trước nó và không có dấu ngoặc mở trên dòng hiện tại. final File file = new File(directory, "file.txt"); Việc thụt lề đúng sẽ trông như thế này: StringUtils.join( Arrays.asList( "first line", "second line", StringUtils.join( Arrays.asList("a", "b") ) ), "separator" ); Quy tắc thụt lề quan trọng thứ hai là bạn nên đặt càng nhiều càng tốt trên một dòng - trong phạm vi 80 ký tự. Ví dụ trên không hợp lệ vì nó có thể được nén: StringUtils.join( Arrays.asList( "first line", "second line", StringUtils.join(Arrays.asList("a", "b")) ), "separator" );
Các hằng số dư thừa
Các hằng số lớp nên được sử dụng khi bạn muốn chia sẻ quyền truy cập thông tin giữa các phương thức lớp và thông tin này là một đặc điểm ( ! ) của lớp bạn. Không sử dụng hằng số để thay thế cho chuỗi hoặc chữ số - cách làm rất tệ, nó dẫn đến ô nhiễm mã. Các hằng số (giống như các đối tượng OOP khác) phải có ý nghĩa trong thế giới thực. Ý nghĩa của các hằng số này trong thế giới thực là gì: class Document { private static final String D_LETTER = "D"; // bad practice private static final String EXTENSION = ".doc"; // good practice } Một lỗi phổ biến khác là sử dụng hằng số trong các thử nghiệm đơn vị để tránh trùng lặp chuỗi/chữ số trong các phương thức thử nghiệm. Đừng làm thế! Mỗi phương pháp thử nghiệm phải hoạt động trên bộ giá trị đầu vào riêng. Sử dụng văn bản và số mới trong mỗi phương pháp kiểm tra mới. Các bài kiểm tra là độc lập. Vậy tại sao họ phải chia sẻ cùng một hằng số đầu vào?
Kiểm tra khớp nối dữ liệu.
Đây là một ví dụ về hooking trong một phương thức thử nghiệm: User user = new User("Jeff"); // maybe some other code here MatcherAssert.assertThat(user.name(), Matchers.equalTo("Jeff")); Ở dòng cuối cùng, chúng ta nối " Jeff " với cùng một chuỗi ký tự được chỉ định ở dòng đầu tiên. Nếu, một vài tháng sau, ai đó muốn thay đổi giá trị ở dòng thứ ba, người đó sẽ phải mất thêm thời gian để tìm kiếm ở nơi nào khác " Jeff " được sử dụng trong phương pháp này. Để tránh việc lấy dữ liệu này, bạn nên giới thiệu một biến.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION