Refactoring và chuyện tập làm văn
Khi tôi viết code một ứng dụng, sẽ chẳng có vấn đề gì nếu đoạn code đó chỉ có tôi dùng hoặc chẳng bao giờ dùng lại. Rõ ràng là code tốt hay code xấu thì có thể nó đều chạy đúng cả, nhưng, với môi trường teamworks trong doanh nghiệp thì rõ ràng là tôi phải làm cho nó dễ đọc và dễ hiểu. Đồng nghiệp có thể sẽ phải thêm tính năng, fix 1 số lỗi hay phát triển code của tôi sau này. Dù lập trình trên bất kỳ ngôn ngữ nào, dựa trên kinh nghiệm cha ông để lại, luôn có good practice và bad practice. Để hiểu hơn việc quan trọng của việc viết code đẹp. Hãy tìm hiểu code xấu là gì?
Có rất nhiều nguyên nhân gây ra code xấu:
- Deadline
- Không ý thức được tầm quan trọng của code đẹp
- Không tính được những thay đổi trong tương lai
Cũng có rất nhiều dấu hiệu của code xấu (từ tổng quan cho tới cụ thể):
- Cứng nhắc
- Các thành phần phụ thuộc nhiều vào nhau. 1 thay đổi kéo theo nhiều thay đổi
- Khó thay đổi, 1 thay đổi có thể phá vỡ cấu trúc hiện tại
- Khó hiểu và khó đọc:
- Tài liệu không rõ ràng, không có README
- Đặt tên mọi thứ(module, class, function, variable) khó hiểu, không đồng nhất: Ví dụ như tôi không đặt tên 2 method là findAllDog() và getAllCat(). Hãy dùng đồng nhất “get” hoặc “find”. Hãy nhớ khi làm 1 việc theo 1 cách nhất định, hãy làm việc tương tự theo cách như vậy. Đặt tên luôn là vấn đề khó nhất và đau đầu nhất trong khi code.
- Magic number: if (x > 5) What the *** is 5 here?
- Ở mức function, 1 function làm quá nhiều việc, quá dài hoặc có nhiều logic if/else, loop cũng là 1 nguyên nhân gây code khó hiểu
- Comments không cần thiết: Nếu 1 vấn đề thông thường và code đủ tốt, ai cũng có thể hiểu nó mà không cần comment. Bạn chỉ nên comment khi có 1 cái logic loằng ngoằng mà bạn nghĩ chính người khác cũng sẽ khó hiểu
- Không thể test được hoặc khó test
- Dùng trực tiếp instance của class khác trong class
- Dùng biến global
- Statics khắp nơi
- Rồi thì Singleton khắp nơi
- Dùng final methods bừa bãi (Java, Scala)
- Lặp lại
- Biểu hiện rõ ràng nhất là các hàm có nội dung tương tự(hoặc gần tương tự) ở khắp mọi nơi
- Độ phức tạp không cần thiết
- Kiểu dùng dao mổ trâu đi giết gà á
Một số tips dựa theo cuốn Clean Code
- Quy tắc chung:
- Dựa theo tiêu chuẩn team đã quy ước
- Luôn tìm ra gốc rễ vấn đề và giải quyết
- Luôn chọn cách đơn giản nhất có thể
- Các quy tắc thiết kế
- Luôn giữ các file cấu hình ở “high level” và tránh lạm dụng
- Tránh lạm dụng if/else. Hãy dùng đa hình khi có thể
- Các module, object, class, … tránh phụ thuộc vào nhau
- Sử dụng DI
- Tránh việc lặp code bằng cách dùng module, component
- Dễ hiểu
- Khi làm 1 việc theo 1 cách nhất định, hãy làm việc tương tự theo cách như vậy.
- Sử dụng tên có ý nghĩa, dễ phân biệt, dễ tìm kiếm. Tránh việc thêm tiền tố, hậu tố
- Dùng object thay vì kiểu nguyên thuỷ
- Tránh việc method phụ thuộc vào 1 thứ khác trong cùng class
- Dùng các điều kiện dạng khẳng định thay vì phủ định: isEqual() tốt hơn !isNotEqual()
- Thay các con số bằng các hằng số có ý nghĩa
- Hàm
- Hàm nhỏ, làm duy nhất 1 việc, tên có ý nghĩa
- Dùng ít tham số, không nên có side effect
- Tránh sử dụng flag
- Object
- Tránh sử dụng static
- Hạn chế tạo nhiều thể hiện (instance)
- Base class nên đóng gói và không được biết thể hiện làm gì
- Hãy sử dụng Data Transfer Object khi cần
- Tránh sử dụng Hybrid Objects
Tổng kết
Túm cái váy lại, do quá trình phát triển, ta tiếp thu liên tục yêu cầu từ khách hàng, áp lực từ deadline khiến thời gian coding của chúng ta giảm đi, làm giảm chất lượng code. Hậu quả là dần dần việc tích hợp thêm tính năng, bảo trì code ngày càng khó khăn, technical debt cộng dồn có thể dẫn đến dead project. Việc Refactor không thể làm lớn trong thời gian dài được. Hãy làm từng chút một hoặc tích hợp luôn vào sprint đang phát triển. Quan trọng là bạn luôn ý thức được tầm quan trọng của nó.
Trong bài viết này, tôi chỉ nêu ra các vấn đề, không giải thích để tránh nó quá dài, ngán ngẩm khi đọc. Nếu có ý kiến hay có thiếu sót gì phía tôi, hãy để lại bình luận. Thank you! ( À nếu bạn có thắc mắc tiêu đề thì … chỉ để “giật tits” thôi :D)