Đặt tên biến, hàm chuẩn: code tự giải thích
Đặt tên là một trong hai việc khó nhất trong lập trình, và nó ảnh hưởng trực tiếp tới tốc độ đọc hiểu của cả đội. Tên tốt biến code thành thứ tự giải thích, không cần comment. Bài này đưa ra nguyên tắc cụ thể để bạn đặt tên biến, hàm và class sao cho người khác không phải đoán ý.
Vì sao tên quan trọng đến vậy
Chúng ta đọc code nhiều hơn viết rất nhiều lần. Mỗi cái tên là một lời giải thích thu nhỏ. Tên mơ hồ như data, temp, handle buộc người đọc phải nhảy đi nơi khác để hiểu, làm chậm mọi thao tác review và sửa lỗi. Tên chính xác giúp giữ toàn bộ ngữ cảnh ngay tại chỗ.
Nguyên tắc đặt tên tốt
Tên nêu ý định, không nêu cách cài đặt
Đặt tên theo “nó là gì” hoặc “nó làm gì”, không theo kiểu dữ liệu. userList kém hơn activeUsers vì cái sau nói lên ý nghĩa. Nếu sau này bạn đổi list thành set, tên activeUsers vẫn đúng.
Độ dài tỉ lệ với phạm vi
Biến sống trong một vòng lặp ngắn có thể tên i. Biến sống xuyên suốt module cần tên đầy đủ. Phạm vi càng rộng, tên càng cần rõ.
Hàm dùng động từ, biến boolean dùng câu hỏi
- Hàm làm hành động:
calculateTotal,sendEmail. - Boolean nên đọc như khẳng định:
isActive,hasPermission,canEdit.
Nhất quán một từ cho một khái niệm
Đừng lúc getUser, lúc fetchUser, lúc retrieveUser cho cùng một việc. Chọn một từ và dùng xuyên suốt để giảm tải trí nhớ cho người đọc.
Tránh những cái tên gây nhiễu
| Tên nên tránh | Vì sao | Thay bằng |
| data, info, temp | Không nói lên gì | invoiceRows, cachedUser |
| flag | Không rõ bật để làm gì | isPublished |
| list1, list2 | Phân biệt bằng số vô nghĩa | pendingOrders, shippedOrders |
| manager, processor, data | Từ chung chung, không giới hạn trách nhiệm | PaymentValidator |
Ví dụ thực tế
Đoạn code khó đọc:
const d = u.filter(x => x.a > 30);
Người đọc phải đoán u, x.a, và số 30 nghĩa là gì. Viết lại:
const inactiveUsers = users.filter(user => user.daysSinceLogin > 30);
Giờ dòng code tự kể chuyện: lọc ra user không đăng nhập hơn 30 ngày. Không cần comment, không cần đoán. Con số 30 lý tưởng nên đặt thành hằng có tên như INACTIVE_THRESHOLD_DAYS.
Lỗi thường gặp và cách sửa
- Viết tắt khó hiểu.
usrCnt,calcAmt. Sửa: viết đầy đủuserCount, trừ các viết tắt cả ngành đều biết nhưid,url. - Nhồi kiểu dữ liệu vào tên.
strName,arrUsers. Sửa: bỏ tiền tố kiểu, để tên nói ý nghĩa. - Tên nói dối. Hàm tên
getUsernhưng lại ghi vào database. Sửa: đổi tên khớp đúng hành vi thật. - Tên quá dài không cần thiết.
theListOfAllUsersInTheSystem. Sửa:allUsersđã đủ trong ngữ cảnh. - Lạm dụng comment để bù cho tên tệ. Sửa: nếu phải viết comment giải thích một biến, hãy đổi tên biến trước.
Checklist đặt tên
- Đọc tên lên có đoán được nó là gì hoặc làm gì không?
- Hàm có bắt đầu bằng động từ không?
- Biến boolean có đọc được thành câu đúng/sai không?
- Cùng một khái niệm có đang dùng cùng một từ không?
- Có số hoặc chuỗi ma nào nên tách thành hằng có tên không?
Kết luận
Đặt tên tốt là kỹ năng rèn được, không phải năng khiếu. Bước tiếp theo: trong lần review code tới, mỗi khi bạn phải dừng lại đoán một cái tên, hãy coi đó là tín hiệu để đổi tên. Sau vài tuần thói quen này, code của đội sẽ dễ đọc hơn rõ rệt.
Câu hỏi thường gặp
Tên nên viết tiếng Anh hay tiếng Việt?
Đa số codebase dùng tiếng Anh vì từ khóa ngôn ngữ và thư viện đều tiếng Anh, trộn ngôn ngữ dễ rối. Nếu đội thống nhất tiếng Việt không dấu cho một số domain đặc thù thì vẫn được, miễn nhất quán.
Tên dài có làm code khó đọc hơn không?
Tên dài vừa đủ để rõ nghĩa thì tốt. Chỉ khi tên dài vì lặp ngữ cảnh đã hiển nhiên mới nên rút gọn. Rõ ràng quan trọng hơn ngắn gọn.
Có nên đặt tên theo design pattern như Factory, Manager?
Chỉ khi lớp đó thật sự là pattern đó và cả đội hiểu quy ước. Manager thường là dấu hiệu lớp ôm quá nhiều trách nhiệm, nên cân nhắc tách nhỏ.
Đổi tên có rủi ro không?
Với công cụ refactor trong IDE hiện đại, đổi tên trong phạm vi dự án khá an toàn. Rủi ro cao hơn khi tên là phần của API công khai hoặc khóa trong dữ liệu, khi đó cần cân nhắc tương thích ngược.
Tham khảo
- Robert C. Martin, sách Clean Code, chương về đặt tên có ý nghĩa.
- Tài liệu quy ước đặt tên trong style guide của các ngôn ngữ phổ biến (ví dụ PEP 8 cho Python).