Clean code 101
Mấy năm đi làm, phải review code lần nào cũng có cảm tưởng như cover image, hi vọng những chia sẻ dưới đây có thể giúp anh em tự hào về phần mềm code mình viết ra.
Code offshore chỉ chạy được?
Hơn tám năm đi làm với thị trường offshore, chưa từng thấy code nào là dễ "ngửi" cả. Nhiều đánh giá cho rằng, code offshore chỉ chạy được chứ cứ để khách mở code ra xem thì khách chê thôi rồi.
Đã có quá nhiều trường hợp khách không xem code thì không sao, nhưng cứ mở code ra, hoặc có engineer bên khách mở code ra xem là dự án lại "toang" hoặc bị "cắt".
Nó cũng có nhiều nguyên nhân:
- Nhân sự bên offshore thay đổi ra vào nhiều, không ổn định
- Dự án không có người review code, không chú trọng hoặc không có đủ công số để review code
- Mục đích của dự án là release và chạy được
- Dự án offshore lúc nào 1 team tester, test nên team dev đang "ỉ lại" vào team test
Một trong những dự án có code "thơm" mà mình biết là các dự án mà team dev offshore làm cùng team dev khách hàng, và team dev tự test(điều mà các engineer bên Nhật vẫn đang làm) -> Vì code bị engineer bên Nhật review nên chất lượng code được chú trọng ở team offshore và từ đó chất lượng code được đảm bảo.
Code là một loại văn bản
Code là cách chúng ta communicate với máy tính, và communicate với engineer khác!
Hãy xem 1 bài viết, cuốn sách: đó là cách dùng văn bản để người viết thể hiện, người đọc đọc và hiểu văn bản đó với một ngôn ngữ cụ thể ( tiếng Việt, tiếng Anh).
Người viết, viết được một văn bản tốt sẽ giúp cho người đọc tiếp nhận nội dung văn bản một cách dễ dàng và đẩy đủ( tỉ lệ hiểu đúng, đủ ý của người viết cao%)
Trái lại văn bản được viết, trình bày không tốt, người đọc sẽ không hiểu, hoặc hiểu sai ý của người viết.
Với code, là cách mà chúng ta tạo ra văn bản
- để máy tính có thể hiểu chỉ thị chúng ta đưa ra,
- và chính chúng ta và engineer khác có thể đọc hiểu và dễ dàng maintain hệ thống
Khi tôi review code, chính là việc tôi đọc xem các bạn dev trong team làm đúng với yêu cầu khách không là chính, nhưng đọc 1 đoạn code mà nó không có quy chuẩn gì, dài dòng, ... thì tôi cũng không biết là ông dev làm có đúng logic hay không. Cố mà đọc code đó, nhưng đúng là vừa đọc vừa "chửi" thật các bạn ạ.
Sau 1 vài dự án review code thì tôi thấy chỉ cần chỉ các bạn 1 vài quy tắc viết là các bạn dev có thể viết được code đẹp hơn và thành 1 engineer sánh ngang với engineer bên Nhật.
Tiếp sau đây tôi sẽ đưa 1 số quy tắc để các bạn khi code chú ý giúp.
Các điểm chú khi code
Quy tắc camel case / snake case
Hãy chọn quy tắc đặt tên function, tên variable, tên constant, tên parameter, tên response
# function
getUserIds()
calCashback()
isValidDate()
hasChild()
# constant
MAX_ROOMS
# variable
filtered_tickets
# tên param, response thường được áp dụng khi viết API
p_user_id
res_users
Đặt tên variable
- Viết bằng tiếng Anh
- camel case / snake case tuỳ thuộc quy định của từng dự án
- Tên biến là 1 danh từ hoặc cụm danh từ
- Cụm danh từ trong tiếng Anh thì danh từ chính là ở cuối cùng, và các từ đằng trước đó là các từ bổ nghĩa. Ví dụ
ordered_tickets
expired_tickets` `unconfirmed_users
- Tên biến cần đúng là đơn vị của đối tượng đó và thể hiện được số lượng bằng việc thêm
s
ở cuối :today_new_users
before_updated_user
after_updated_user
Đặt tên function
- Viết bằng tiếng Anh
- Bắt đầu bằng 1 động từ
getWalletBalance
registerNewUser
getUserByName
hoặc các từ để hỏi nếu function trả về true, falseis_parent
has_enough_money
- Nếu bắt đầu bằng 1 động từ thì cần 1 danh từ trong đó để biết động từ đang tác động đến đối tượng nào. Lúc này danh từ cũng nên thể hiện đúng là số ít/nhiều.
importUser
importUsers
- Đặt tên function làm sao để khi đọc tên người ta biết function làm gì và sẽ trả về(return) về gì
Đặt tên constant
- Thường thì tên constant được đặt kiểu `UPPER_CASE`
- Constant cũng là 1 variable nên nó cũng cần áp dụng cách quy tắc đặt tên như 1 variable
Đặt tên cho parameter/response
- Khi code API cần áp dụng
- Nhận diện/phân biệt được parameters thì khi đọc code sẽ biết đó là biến input của api để xem các query vào DB, tính toán đang dùng input đó thích hợp không.
p_user_ids
- API sẽ phải trả về response, thường API sẽ build gán biến đó vào 1 biến nào đó rồi mới build trả về ở xử lý cuối của code. Đầu api đặt tên biến sẽ response
res_users
thì người đọc sẽ biết khi append vàores_users
thì tức là sẽ đc api response cho client.
Viết code có comments
Khi nếu việc đặt tên variable/function tốt rồi thì không cần comment vào code làm gì.
Tuy nhiên nếu cách đặt tên của bạn chưa thể hiện được đủ ý đồ của đoạn xử lý đó thì thì có thể comments để "văn bản code" của bạn được rõ ràng hơn.
Một trong tip để sau khi code xong bạn có comment trong code là:
Giống như viết 1 văn bản, 1 cuốn sách. Bạn sẽ thấy người ta có mục lục, viết mục lục trước rồi mới đắp thêm nội dung vào. Trong lúc đắp nội dung có thể có chỉnh sửa thay đổi cấu trúc, tuy nhiên ban đầu viết gì thì người ta vẫn cần layout ra mục lục, ý chính ra trước.
Viết code cũng vậy, đọc hiểu yêu cầu xong bạn hãy mường tượng trong đầu các bước xử lý và layout vào bằng các comments và sau đó thì thêm các dòng code của bạn phục vụ cho đoạn comment đó.
Chúc mừng bạn: sau khi code xong tự nhiên bạn có code có comments rồi
Viết function không quá dài
Review code dài không follow đc code đang xử lý gì.
Bạn biết cách/quy tắc đặt tên function, và chia code ra thành function sẽ giúp rất nhiều cho việc đọc hiểu code. Review code thấy call sang function khác thì đọc tên function đó có thể hiểu đc function bên ngoài đó là gì rồi, thì sẽ review tiếp rồi tý nữa quay lại xem logic function kia có xử lý đúng như tên nó đặt không là OK.
Sử dụng break line 1 cách thông minh
Break line như 1 công cụ để bạn ngắt ý đọc của người đọc, cho thấy đoạn code đó có liên quan đến nhau đang có chung 1 mục đích xử lý. Giống như viết đoạn văn có ngắt nghỉ, thụt đầu dòng đó bạn. Viết liền tù tỳ, hoặc thụt đầu dòng sai thì việc đọc sẽ khó khăn biết bao.
Fast return
thay vì sau if A
xử lý rất dài , rồi đến else
thì return X
. Bạn hãy if not A
return X
rồi else
xử lý đoạn code dài kia. Nếu không đọc đoạn dài rồi đến else lại không nhờ if là gì và điều kiện tiền đề khi trước vào if là gì, bạn phải load lại trong não thông tin đó để phán định return X
có đúng không.
Code xử lý từng dòng một, theo thứ tự nên đọc code đến đâu thông tin đc nạp vào đầu đến đó để xem mục đích/output của code có đúng không. Khi sử dụng fast return bạn thấy return rồi sẽ kết luận nhanh được ở nhánh rẽ đó, và focus được nhánh chính đó có OK không.
Khi viết if
thì bạn để sẵn else
vào đó để tránh lack cases
khi if/else đi thành 1 set khi viết code. Bạn sẽ có những phán đoán "à else này chưa có yêu cầu, nên xử lý thế nào...". Nếu else không xử lý gì thì có thể log ra hoặc pass qua bằng 1 dòng comment cũng OK. Bằng việc này, code rẽ nhánh sẽ không bị thiếu sót.