Khi mới tiếp nhận một dự án đã được phát triển từ trước, hay nhận nhiệm vụ maintain một hệ thống đã chạy từ rất lâu rồi; chắc hẳn không ít lần bạn ngửa mặt than trời khi gặp những dòng code ấy kiểu như thế này:
for
lồng vào nhau (lẽ ra chỉ cần thuật toán độ phức tạp O(1)
) thì thực tế lại dùng tới O(n^2~3)
)if
else
lồng nhau không cần thiếtreturn
ra cái gì.Và bạn nản chí, không muốn đọc tiếp và tìm hiểu về hệ thống đó nữa!
Như một chàng trai thấy cô gái không đẹp rồi nên không muốn tìm hiểu xem tính cách cô ấy thế nào nữa mặc dù có thể cô gái ấy có tâm hồn rất đẹp, hay nhà cô ấy rất giàu… Hệ thống kia có thể có design rất tốt, tổ chức các class tuyệt vời, nhưng vì kiểu như trên nên ấn tượng để lại trong bạn chỉ là những dòng code xấu xí và khó hiểu mà thôi.
Hôm nay chúng ta sẽ cùng nhau tìm ra cách viết những dòng code sao cho người khác đọc được có thể hiểu nhanh nhất, muốn tìm hiểu hệ thống của chúng ta và muốn code được những dòng code "đẹp" như thế.
Key!
"Với những flow code về điều kiện và vòng lặp thì cố gắng viết một cách thật “tự nhiên”. Tránh để người đọc phải ngừng đọc giữa chừng hay quay lại đọc những dòng code đã đọc ở trước."
Vậy cụ thể hoá của Key
đó là gì?
1. Sắp xếp thứ tự của biến số trong biểu thức điều kiện
Các bạn hãy cùng xem các ví dụ dưới đây xem cách viết nào đọc “tự nhiên” hơn?
VD1:
if (length >= 10) |
và
if (10 <= length) |
VD2:
while (bytes_received < bytes_expected) |
và
while (bytes_expected > bytes_received) |
Hầu hết các lập trình viên sẽ thấy code theo cách đầu tiên dễ đọc hơn. Nguyên tắc chính của nó là.
“Đặt đối tượng muốn so sánh (thay đổi) phía bên trái, và đối tượng dùng để so sánh phía bên phải (ít thay đổi)”
Trong thực tế một vài ngôn ngữ sẽ có lỗi khi lập trình viên sơ xuất viết
if (length == 10) |
Vì viết như vậy không vi phạm syntax của ngôn ngữ nên rất khó debug.
Có một số sách khuyên nên viết thành
if (10 == length) |
để compiler báo lỗi khi biên dịch. Tuy nhiên các viết này không tự nhiên và sẽ gây khó chịu cho người đọc.
2. Sắp xếp thứ tự của điều kiện trong if/else
Chúng ta hãy cùng xem xét 2 cách viết dưới đây.
Cách 1.
|
Cách 2.
if (a == expectedValue) { // Các xử lý -> return giá trị; } else { // Các xử lý -> return null; }
|
Rõ ràng các bạn thấy đọc cách viết thứ 2 cảm thấy thoải mái hơn. Vì nó mang lại cảm giác tích cực vì đưa ra được trường hợp trả về giá trị mà lập trình viên mong muốn trước.
Để xử lý với if/else chúng ta có 3 nguyên tắc cơ bản sau
3. Tránh vòng lặp do/while
Tại sao vòng lặp do/while lại không nên dùng?
Vì bạn rất dễ gặp lỗi sai trong vòng do đầu tiên do chưa check điều kiện. Giống như bạn trượt từ đỉnh núi xuống nhưng gặp quá nhiều chướng ngại vật, bạn ngã lăn lộn xuống chân núi mới thấy có cái biển ghi là “Có nhiều chướng ngại vật nguy hiểm, cấm trượt”. Đáng nhẽ cái biển đó phải đặt ở đỉnh núi, tức là trước vòng Do mới đúng =))
Đơn cử như một ví dụ này thôi:
do { continue; } while (false); |
Theo các bạn thì vòng lặp này sẽ kéo dài vĩnh viễn hay sẽ chạy chỉ 1 lần?
Các bạn tự thử đi nhé!
4. Nhanh chóng return kết quả
Có 2 nguyên nhân để chúng ta viết một function trả về kết quả càng sớm càng tốt.
5. Không sử dụng goto
Quy tắc này có lẽ trong trường đại học các thầy cô cũng nhắc các bạn nhiều rồi. Sử dụng gotogây khó khăn rất lớn cho việc debug vì code thực thi của các bạn sẽ nhảy linh ta linh tinh đi khắp nơi; nhiều trường hợp sẽ rơi vào vòng lặp vĩnh viễn mà không biết đầu đuôi nó ở đâu…vv
Trong hầu hết các trường hợp thì chúng ta có thể thay cách viết dùng goto
bằng một cách viết khác.
Vây nên các bạn hãy chịu khó bỏ thêm chút thời gian nhé
6. Chú ý khi sử dụng toán tử 3 ngôi
Mới đọc qua câu lệnh này liệu các bạn có biết nó trả ra giá trị nào?
return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent); |
Quy tắc ở đây là:
"Việc viết code để người khác hiểu được thì quan trọng hơn là viết code sao cho ngắn nhất!"
Chúng ta có thể viết lại như dưới đây:
if (exponent >= 0) { return mantissa * (1 << exponent); } else { return mantissa * (1 << -exponent); }
|
Toán tử 3 ngôi chỉ nên sử dụng khi điều kiện của nó đơn giản. Về cơ bản các bạn hãy sử dụng if/else nhé!
7. Hạn chế for và if lồng nhau.
Cái này chắc hiển nhiên rồi và cách thường dùng nhất là nhanh chóng trả về kết quả sớm nhất có thể để hạn chế đi sâu vào các vòng for và if bên trong.
Tới đây mình đã trình bày với các bạn phần 1 của series Nghệ thuật viết code đẹp
. Có rất nhiều nguyên tắc cần chú ý tuỳ theo từng trường hợp. Nhưng tổng quan lại thì điều quan trọng nhất là mỗi khi các bạn đặt tay lên bàn phím gõ ra những dòng code, là hãy dành một chút thời gian nghĩ tới những người sẽ đọc hiểu và làm việc với chúng sau này.
Via Techtalk