Mã sạch, rõ ràng và hiệu suất cao là mục tiêu mà các nhà phát triển phần mềm luôn theo đuổi.
Để đạt được mục tiêu này, cần phải luyện tập liên tục và rút ra kinh nghiệm từ quá trình phát triển. Thường thì mã của các kỹ sư cấp cao sẽ gọn gàng hơn và ít lỗi hơn so với các lập trình viên mới vào nghề. Dưới đây là một số nguyên tắc giúp cải thiện chất lượng mã:
- Quy Tắc Đặt Tên.
Quy tắc đặt tên theo dạng CamelCase là chuẩn mực trong Java, nhưng khi viết API, chúng ta có thể gặp phải các quy tắc đặt tên khác từ các hệ thống bên ngoài. Ví dụ:
public class ThanhToanTraVe {<br></br> private String MA_SO_DOI_TUONG;
}
Nếu yêu cầu từ hệ thống bên ngoài là trường MA_SO_DOI_TUONG, liệu cách viết trên có tốt không? Trong quá trình kiểm thử, nó trở thành maSoDoiTuong.
public class ThanhToanTraVe {
@JSONField(name = "MA_SO_DOI_TUONG")
private String MA_SO_DOI_TUONG;<br></br>}
Cách này vẫn còn vấn đề vì khi sử dụng các framework chung như MyBatisPlus hoặc Apache BeanUtils.copyProperties, sự không đồng nhất trong tên gọi có thể gây ra lỗi.
public class ThanhToanTraVe {
@JSONField(name = "MA_SO_DOI_TUONG")
private String maSoDoiTuong;
}
Bây giờ cả tên lớp và tên trường đều tuân thủ quy tắc đặt tên trong Java, chỉ cần dùng @JSONField để chuyển đổi khi tương tác với hệ thống bên ngoài.
- Phân Chia Trách Nhiệm, Bố Cục Mã.
Chúng ta đều biết nguyên tắc trách nhiệm duy nhất, áp dụng trong phát triển phần mềm, ví dụ như tầng Controller chỉ nhận yêu cầu và ghi log, logic cụ thể thực hiện ở tầng Service. Nhiều khi, do nghiệp vụ đơn giản, chúng ta thực hiện luôn trong Controller. Nếu file nhỏ và dễ hiểu thì cũng chấp nhận được, nhưng nếu mã dài, vượt quá 1000 dòng, điều này là không hợp lý và làm cho cấu trúc bị mất cân đối.
- Loại Bỏ Mã Lặp.
Khi mới vào nghề, tôi đã được thầy dạy rằng không nên viết mã lặp lại trong chương trình. Mã lặp không chỉ dư thừa mà còn khó sửa khi thay đổi nghiệp vụ. Tuy nhiên, mã lặp thường không phải do chúng ta tạo ra mà có thể trùng với mã của người tiền nhiệm. Khi đó, chúng ta cần tái sử dụng.
Có những trường hợp chúng ta không nhận ra mình viết mã tương tự ở hai nơi, chỉ khác một chút. Lúc này cần khả năng trừu tượng hóa để tách mã giống nhau ra thành mã mẫu, giảm thiểu sự lặp lại. Nhưng thiết kế cẩn thận này có thể làm chậm tiến độ phát triển, cần phải cân nhắc.
- Tư Duy Trừu Tượng.
Trong thời trung học, giáo viên toán của tôi luôn nhấn mạnh về tư duy trừu tượng, nhưng tôi chưa thật sự hiểu rõ. Có lẽ nó tương tự như triết lý của Lão Tử, tức là cần nhìn nhận vấn đề một cách tổng quát. Trong máy tính, tư duy trừu tượng rất quan trọng, hay nói cách khác là đóng gói, nghĩa là không cần hiểu chi tiết cách thức hoạt động mà chỉ cần sử dụng. Qua việc sử dụng, chúng ta dần hiểu sâu hơn về hệ thống.
Ví dụ, ổ cứng vật lý có thể được xem như một đối tượng lưu trữ dữ liệu với các phương thức đọc và ghi.
Khi thiết kế hệ điều hành, tư duy phân lớp rất phổ biến. Ví dụ, OS quản lý phần cứng, ứng dụng chỉ có thể sử dụng phần cứng thông qua giao diện do OS cung cấp. Trong Docker, hình ảnh (image) được xây dựng theo từng lớp, đây là một chủ đề chuyên môn phức tạp.
- Ví Dụ Thực Tế
Tôi đã từng gặp mã nguồn phía sau của công ty rất lộn xộn, ví dụ như file LoiXuLyImpl.java chứa nhiều vấn đề, dưới đây là một số ví dụ về cách viết mã đẹp:
A. File lớn, hơn 1000 dòng, chắc chắn tồn tại vấn đề thiết kế, mức độ trừu tượng kém, phát triển thiếu tổ chức. Nên giới hạn khoảng 300-500 dòng.
B. Phương pháp chung được viết trong lớp chuyên dụng, thiếu cấu trúc và tư duy phân lớp, dẫn đến hỗn loạn.
C. Trong file KiemTraNhiemVuJob.java, đa luồng được mở ra vô ích, làm tăng độ phức tạp và sao chép mã không cần thiết.
D. Trong file PhuTungThuVienVo.java, xuất hiện lớp cùng tên nhưng khác package, dễ gây nhầm lẫn, nên phân biệt bằng cách thêm tên phụ, ví dụ DonGianPhuTungThuVienVo.java.
Tài liệu tham khảo: "Refactoring, Clean Code".