[Code sao cho chuẩn] – Bài 1: Hãy nghĩ tới việc viết code tốt hơn.

     Với những ai đã từng viết code, ngoài việc đảm bảo output đúng, chúng ta cũng thường đặt câu hỏi: “viết code thế này đã chuẩn chưa?”. Hầu hết mọi người, nhất là những bạn còn đi học hoặc chưa có nhiều kinh nghiệm, đều nhiều lần tặc lưỡi nghĩ rằng “code chạy đã, đẹp xấu tính sau”. Chính suy nghĩ này dẫn tới việc ngay bản thân họ, một thời gian sau cũng không còn hiểu được họ đã viết cái gì nữa. Bởi thế, chúng ta nên suy nghĩ cách nghiêm túc về việc viết code sao cho chuẩn.

Thế nào là code chuẩn

       Khi nhắc tới “viết code”, đừng nhắc tới ngay những thứ đao to búa lớn kiểu như: kiến trúc tổng quát của project, chọn lựa những mẫu thiết kế (design patterns), các kĩ thuật caching, .v.v.. Mặc dù những thứ này là quan trọng, nhưng hầu hết những vấn đề chúng ta gặp phải liên quan đến những thứ cơ bản hơn rất nhiều, ví dụ như:

  • Đặt tên biến như thế nào cho dễ nhớ.
  • Viết vòng lặp thế nào cho tối ưu.
  • Có nên tách hàm nhỏ để xử lí hay là viết hết tất cả vào một nơi.
  • Phân nhiệm vụ các modules thế nào?

     Nếu những thứ cơ bản chưa đảm bảo, đừng vội nói tới những thứ to lớn hơn.

clean code
Hãy là một người viết code có tâm, vì biết đâu chính bạn sẽ phải đọc nó sau này (Nguồn ảnh: The art of readable code)

       Dưới đây là một vài cấp độ, mà theo mình thì tất cả chúng ta cần phải xem xét tới khi viết code, đó là:

  • Mức 1 – nhập môn: Ở mức độ này, chúng ta quan tâm tới việc viết code cho dễ hiểu: đặt tên sao cho chuẩn, comment code sao cho dễ hiểu mà lại không quá dài, format code ngay ngắn … Mức độ này là bắt buộc với mọi người ở cấp cơ bản nhất.
  • Mức 2 – học nghề: Lúc này, chúng ta quan tâm tới chi tiết hơn một chút xíu: viết vòng lặp sao cho tối ưu, tổ chức logic code tách bạch và rõ ràng, tối ưu các khối lệnh rẽ nhánh, quan tâm tới tính đơn nhiệm của hàm … Những người có ý định trở thành một lập trình viên nghiêm túc cần phải luyện kĩ mức này.
  • Mức 3 – lành nghề: Tới mức này, chúng ta sẽ phóng tầm nhìn ra xa, nơi cấu trúc source code: tách các modules con với nhiệm vụ chuyên biệt, giảm thiểu sự phụ thuộc lẫn nhau của các thành phần, thiết kế component chung để tránh lặp code (DRY – Don’t Repeat Yourself), áp dụng các nguyên tắc thiết kế để đảm bảo tính mở rộng của ứng dụng, tối ưu code …. Cấp độ này mất khá nhiều thời gian, nhưng hãy kiên nhẫn và chăm chỉ.
  • Mức 4 – nghệ nhân: Tới đây, bạn đã phải làm chủ được kĩ thuật để tập trung vào việc sáng tạo “mĩ thuật”. Code viết ra không những đúng, đẹp, tối ưu mà còn khiến người đọc thấy sướng. Sử dụng thành thạo kĩ thuật, biết điểm mạnh yếu để áp dụng cho phù hợp với hoàn cảnh.

Viết code không khó, viết code chuẩn mới khó.

      Mặc dù không dễ để có thể đạt được cảnh giới tối cao – sẽ mất rất nhiều thời gian và công sức – nhưng cái gì cũng có cái giá của nó, phần thưởng sẽ xứng đáng. Và mặc dù không có đường tắt nào cả, nhưng nếu chúng ta chăm chỉ đọc sách, học hỏi từ những người nhiều kinh nghiệm, chăm chỉ luyện tập … Cũng sẽ nhanh thôi.

Nói đơn giản hơn đi

      Ai cũng đều muốn code của mình “đẹp”, code của mình “chuẩn”, những tiêu chí nói ở trên quá dài để hiểu nhanh, vậy thì như thế nào mới được coi là “đẹp” và “chuẩn” nhỉ? Trước hết, điều căn bản của code “chuẩn” là:

Code có thể được người khác hiểu một cách dễ dàng

        Một đoạn mã lệnh tốt trước tiên phải dễ hiểu, dễ hiểu bởi chính người viết ra nó, và cũng phải dễ dàng hiểu được với những người đọc nó.

      Tất nhiên, càng tới những cấp độ cao hơn thì code càng cần nhiều sức lực hơn để hiểu, nhưng hãy luôn làm nó đơn giản nhất ở mức độ của nó. Hãy luôn nhớ rằng: mọi thứ tự nhiên đều dễ hiểu. Hãy cố gắng vì điều đó.

Ranh giới giữa tốt và không tốt rất mong manh

Chúng ta thử xét ví dụ này nhé:


for( Node* node = list->head; node != NULL; node = node->next ){
    Print(node->value);
}

Node* node = list->head;
 If( node == NULL ) return;

While( node->next != NULL ){
     Print( node->value );
     Node = node->next;
 }
 If( node != NULL ) Print( node->value );

        Rõ ràng là bạn có thể thấy được là cách viết đầu tiên “tốt hơn” rất nhiều so với cách viết thứ 2 phải không nào? Nhưng có những lúc, sẽ khó để phân biệt tốt/xấu hơn:

return exponent >= 0
       ? mantissa * ( 1 << exponent )
       : mantissa / ( 1 << exponent ); 

và một cách viết khác của logic này:

 if( exponent >= 0 ){
    return mantissa * ( 1 << exponent );
} else {
    return mantissa / ( 1 << exponent );
}

       Cách đầu tiên có vẻ như ngắn gọn hơn, thế nhưng cách thứ 2 lại có vẻ tường minh và dễ hiểu hơn. Thế thì tiêu chí nào được đánh giá cao hơn? Theo mình thì không có câu trả lời nào là hoàn toàn đúng trong trường hợp này, mỗi người sẽ có 1 quan điểm riêng, và còn tuỳ vào mục đích của dòng code này để làm gì, và ai sẽ là người đọc nó nữa.

      Nhưng dù sao, hãy luôn nhớ câu thần chú này:

Những dòng code nên được viết sao cho người khác mất “ít thời gian nhất” để hiểu được chúng

      “Người khác” ở đây hàm ý tới người không trực tiếp viết ra những dòng code này, hoặc cũng có thể là chính bạn 6 tháng sau đó, khi mà bạn đã gần như xa lạ với chính những dòng code của mình.

       Đôi khi ngắn nhất không phải là tốt nhất, “dễ hiểu nhất” cần được đặt lên hàng đầu. Không tin ư, hãy xem thử đoạn code sau:

assert( ( !( bucket = findBucket( key ) ) ) || !bucket->IsOccupied() )

         Sẽ tốn nhiều thời gian để hiểu hơn đoạn code:

bucket = findBucket( key );
if( bucket != NULL ) assert(!bucket->IsOccupied() );

Tổng kết

      Mặc dù code ngắn gọn là một mục tiêu nên hướng tới, tuy nhiên thì tính dễ hiểu đôi khi còn là một mục tiêu quan trọng hơn. Nó sẽ giúp ích cho bạn rất nhiều sau này đấy.

      Hãy nhớ những mức độ của “code chuẩn” mà mình đã chỉ ra ở trên, hãy luôn rèn luyện để tăng dần cấp độ nhé. Chúc vui!

<– *** –>

Tham khảo:
Sách: Clean Code: A Handbook of Agile Software Craftsmanship
Sách: The art of readable code

6 thoughts on “[Code sao cho chuẩn] – Bài 1: Hãy nghĩ tới việc viết code tốt hơn.

    1. Đúng rùi đó bạn, đã edit:
      return exponent >= 0 ? mantissa * ( 1 << exponent ) : mantissa / ( 1 <
      –>
      return exponent >= 0 ? mantissa * ( 1 << exponent ) : mantissa / ( 1 << exponent );

      Cảm ơn bạn nhé 🙂

      Like

  1. Pingback: [Giới thiệu sách] The art of readable code – Cái tên đã nói lên tất cả – Webbynat

  2. Pingback: [Giới thiệu sách] Sách hay đầu năm 2017 (P1) – Những dòng code vui

  3. Pingback: [Code sao cho chuẩn] – Bài 2: đặt tên biến, việc đơn giản nhưng bạn đã làm đúng? – Những dòng code vui

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s