THẾ NÀO LÀ COMMENT CODE CÓ “TÂM”?

Có khi nào bạn mở source code cách đây chừng 2 – 3 tháng thậm chí là mấy ngày của chính bạn nhưng lại không hiểu nổi nó viết cái gì không?

Có thể bạn chưa biết: Thời gian đọc code luôn gấp nhiều lần thời gian viết code. Vậy nên, comment giúp bạn và cả người đọc code của bạn nhanh chóng hiểu được ý nghĩa & mục đích thực sự của đoạn code tại thời điểm được viết, vì khi đọc cùng một đoạn code vào thời điểm khác có thể ý nghĩa của nó sẽ rất khác đấy.

Khi bạn đang viết một chương trình, bạn có thể hiểu tất cả mọi thứ về chương trình (các biến, cấu trúc chương trình, phân nhánh, v.v…) vì bạn đang trong luồng suy nghĩ; nhưng sau một thời gian bạn sẽ quên mất kiến thức, khi đó bạn phải bỏ thời gian tìm hiểu lại; đó chính là một trong những lý do cần có comment.

Tuy nhiên, Comment tồi sẽ là cái bẫy và Comment có giá trị sẽ tiết kiệm đáng kể thời gian phát triển về sau!

Khi nào nên sử dụng comment?

Có một sự thật là: “Không phải comment lúc nào cũng tốt!”. 

Bản thân việc comment là tốt nhưng không phải lúc nào cũng chăm chăm viết comment. Hãy thử hình dung chỉ có 1-2 dòng code dễ hiểu nhưng comment chiếm hết 3-4 dòng, hoặc khi xóa code mà quên xóa comment đi kèm và đến khi kiểm lại sẽ chẳng nhớ nổi comment này là dành cho đoạn code nào!

Các comment không chỉ là code dành cho trình biên dịch, chúng là những từ để truyền đạt các ý tưởng với những người khác. Đừng comment dài dòng, hãy ngắn gọn và súc tích nhất có thể nhưng vẫn mô tả đầy đủ những gì bạn muốn truyền đạt.

Đây là những trường hợp cần viết comment:

1. Cần nói rõ ý định tại sao

Viết code để chương trình hoạt động đúng đã là 1 việc khó, việc làm cho người khác hiểu được ý định của mình đằng sau những đoạn code lại càng khó hơn. Có đôi khi ta có nhiều cách để giải quyết 1 vấn đề, chúng ta cũng nên xem xét việc comment nói rõ “tại sao” ta lại viết đoạn code xử lý như vậy.

Giả sử ta có 1 đoạn code chạy đa luồng với biến hằng NUMBER_OF_THREADS, giả sử ta đều có thể chạy với giá trị 2, 4 hoặc 8 luồng 1 lúc, tuy nhiên ta lại chọn 4 vì nó phù hợp với cấu hình đại đa số người dùng (không quá ngốn RAM chẳng hạn), khi đó chúng ta cũng nên comment để người đọc hiểu được tại sao ta chọn con số 4.

//Can run with value of 2, 4 or 8
// but 4 is best for performance
NUMBER_OF_THREADS = 4;

2. Những đoạn code phức tạp, dễ bị hiểu sai

Đối với những đoạn code phức tạp và dài dòng, hãy comment để khi đọc lại bạn sẽ không phải thắc mắc tại sao mình lại code như vậy.

public class Recorder {
   vector data;
   ...
   public void Clear() {
      vector().swap(data); // Huh? Why not just data.clear()?
   }
}

Chắc chắn sẽ có người thắc mắc rằng tại sao không dùng lệnh clear() của vector mà lại dùng lệnh swap(), hay hẳn là người viết đã sai điều gì đó ở đây?

Trong C++, thì vector chỉ thực sự được giải phóng vùng nhớ nếu chúng ta dùng lệnh swap(), nó là một đặc điểm của thư viện STL chuẩn mà không phải ai cũng biết. Để tránh hiểu lầm không đáng có, tốt nhất nên thêm vào một comment để người sau khỏi hoang mang:

// Force vector to relinquish its memory (look up "STL swap trick")
vector().swap(data);

3. Những comment mang lại cái nhìn bao quát

Nếu bạn tham gia một dự án nào đó, mà bạn không phải là người phát triển ngay từ đầu, điều khó nhất có thể không chỉ là những hiểu biết mang tính kĩ thuật, mà đến từ việc “hiểu được dự án đó đã và đang thực sự làm gì”.

Với một dự án đã được phát triển một thời gian dài, thậm chí tìm được điểm bắt đầu (entry point) của project khi chạy là chỗ nào đã là cả một vấn đề khó khăn rồi. Bạn nghĩ sao nếu với cái đống source code hàng chục file, mỗi file lên tới cả ngàn dòng code, việc đọc code không hề có comment nó khủng khiếp cỡ nào!!!

Giả sử, trong mô hình lập trình web, chúng ta thường dùng mô hình MVC gồm 3 lớp tiêu chuẩn: Models thao tác với dữ liệu, Controller điều khiển nghiệp vụ, View để hiển thị. Thế nhưng, thực tế mọi chuyện không hề đơn giản như thế.

Chúng ta xây dựng thêm các lớp để cache dữ liệu nhằm giảm tải truy vấn xuống DB, chúng ta xây dựng các lớp logic mặt nạ (façade class) để gom nhóm các thao tác ở tầng xử lí thấp hơn, ..v.v.v. Những kĩ thuật nhỏ đó làm code trở nên phức tạp hơn rất nhiều so với mô hình được học, sẽ là tốt hơn nên chúng ta có những comment mang tính bao quát kiểu như:

//This file contains helper functions that provide a more
//convenient interface to process IP value.
//It handles accessing permissions and other nitty-gritty details.
class WBN_IP_Logic{
    //hundreds of functions here
    ...
    function isIPv4(){
    }
    function checkValidIP{
    }
}

Những dòng comment kiểu như thế này sẽ tiết kiệm cho người đọc rất rất nhiều thời gian so với việc đọc hàng ngàn dòng code để thực sự hiểu được chúng thực sự có ý nghĩa gì. Những dòng code này mang ý nghĩa như bản document mô tả lại ý nghĩa thực sự của những đoạn code mà người dùng đang đọc. Thiếu nó thì chắc hẳn người đọc cũng sẽ vẫn hiểu thôi, tuy nhiên chẳng phải là sẽ tốt hơn nếu người đọc có thể hiểu được nhanh hơn hay sao?

4. Những đoạn code tạm thời không sử dụng:

Chỉ nên comment những đoạn code tạm thời không sử dụng, và có thể sẽ phải sử dụng sau này thôi nhé. Những đoạn code chắc chắn không bao giờ dùng nữa thì tốt nhất là nên delete ngay và luôn, hoặc lưu riêng ra chỗ khác.

Khi nào không nên sử dụng comment?

Chúng ta biết rằng nếu như chúng ta viết những dòng comment vào code, thì người đọc sẽ mất thời gian để đọc và hiểu nó là gì, việc đọc comment lấy mất đi thời gian quý báu của người đọc, bởi thế nếu việc comment code gây nên những lãng phí thời gian vô ích thì chúng ta nên xem xét lại sự hiện diện của chúng.

1. Comment code gây lãng phí thời gian vô ích

Hãy xem qua đoạn code sau:

// The class definition for Account
public class Account {
    //Constructor
    Account();
    // Set the profit member to a new value
    public void SetProfit(double profit);
    // Return the profit from this Account
};
    public double ();

Đoạn code này comment khá đầy đủ, nhưng chẳng có ý nghĩa mấy, thời gian viết comment còn nhiều hơn viết code. Đống comment này nhiều nhưng khá vô dụng, đọc rất buồn cười, như thể mấy kẻ “múa rìu qua mắt thợ”, mới học võ công mà bày trò bắt chước các chiêu thức cao siêu trong võ học.

Qua ví dụ trên ta rút ra được kinh nghiệm rằng: Những dòng code đã quá rõ ràng và có thể hiểu được ngay lập tức thì tốt nhất là đừng nên comment. Chỉ nên comment những dòng code phức tạp kiểu thế này thì hợp lý hơn:

//remove everything after the second '*'
name = '*'.join(line.split('*')[:2]);

Mặc dù chúng ta vẫn có thể hiểu được ý nghĩa của những dòng code trên, tuy nhiên sẽ nhanh hơn rất nhiều nếu chúng ta nhận ra ngay được ý tác giả qua dòng comment. Và như tiêu chí mình nói xuyên suốt series này: code nên được viết sao cho người khác dễ hiểu nhất, việc dùng một comment ở đây theo mình là hợp lí.

2. Tránh dùng comment để lấp liếm vấn đề

Đôi khi, việc hạn chế comment cũng giúp người lập trình bớt lười biếng hơn. Khi đó, họ buộc phải viết code có ý nghĩa hơn là việc dùng comment để lấp liếm các dòng code không tốt. Chúng ta xét thử thêm một tình huống mà việc comment trở nên không tốt như sau:

// Releases the handle for this key
// doesn't modify the actual registry in database.
void DeleteRegistry(RegistryKey* key);

Nếu như bạn nào từng lập trình qua C++ thì chắc sẽ biết tới khái niệm con trỏ, trong C++ không có cơ chế giải phóng bộ nhớ tự động như các ngôn ngữ lập trình cấp cao khác, khi không dùng nữa chúng ta cần phải tự delete con trỏ đi để không gây nên vùng nhớ rác.

Ở đây, người lập trình đơn giản chỉ muốn giải phóng vùng nhớ mà con trỏ đang nắm giữ, thế nhưng cách đặt tên hàm thực sự có vấn đề: nó khiến người ta hiểu lầm chức năng của hàm này là xoá 1 Registry ở trong database đi. Để tránh hiểu lầm thì người viết comment một dòng ý nghĩa thực sự cho nó. Việc dùng comment để lấp liếm vấn đề có thể gây thảm hoạ nếu người kế thừa không thực sự hiểu rõ ý nghĩa của nó.

Trong trường hợp này, tốt hơn là chúng ta không nên comment mà nên sửa lại code để bản thân nó đã dễ hiểu mà không cần đến comment để giải thích. Chúng ta sẽ sửa lại tên hàm như sau:

void ReleaseRegistryHandle(RegistryKey* key);

Việc sửa lại tên hàm đã làm cho code trở nên sáng sủa hơn rất nhiều. Rõ ràng, bản thân việc đặt tên biến cũng là một vấn đề rất quan trọng trong lập trình, chúng ta nên cẩn thận.

Kết luận:

Comment sử dụng để cho người review code sau này có thể hiểu được ý định của bạn, từ đó hiểu và giải quyết vấn đề nhanh hơn. Hãy viết comment rõ ràng, ngắn gọn và dễ hiểu; tránh viết dài dòng, lan man. Khi xóa code hãy xóa comment đi kèm để không bị trường hợp code 1 đằng comment 1 nẻo.

Nên viết comment khi:

  • Cần nói rõ ý định tại sao (WHY, HOW)
  • Những đoạn code phức tạp
  • Những comment mang lại cái nhìn bao quát
  • Những đoạn code tạm thời không sử dụng

Không nên viết comment khi:

  • Không comment những đoạn code mà ý nghĩa của nó đã quá rõ ràng.
  • Không comment lấp liếm để che giấu vấn đề, hãy giải quyết vấn đề triệt để và rõ ràng hơn.
  • Xoá ngay lập tức những comment nếu đã xoá code đi kèm, tránh dư thừa comment.

Khi code hãy nhớ câu thần chú: Code tells you HOW, Comments tell you WHY