Chap 5 6 - The Art of Readable Code

27
The Art of Readable Code Chapter 5 6: Comment GMO VNLAB Ngô Công Minh

Transcript of Chap 5 6 - The Art of Readable Code

Page 1: Chap 5 6 - The Art of Readable Code

The Art of Readable CodeChapter 5 – 6: Comment

GMO VNLAB – Ngô Công Minh

Page 2: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

Page 3: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

o Comment

o Giúp cho người đọc hiểu rõ như người viết hiểu

o "Giải thích những gì code thực hiện" - là 1 phần nhỏ

o Khi viết code, có rất nhiều thông tin quý giá trong đầu bạn, nhưng khi người

khác đọc code đấy, những thông tin đó bị mất

Page 4: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

o Các phần chính

o Cái gì không cần comment

o Ghi lại suy nghĩ của bạn

o Đặt vào vị trí của người đọc, để tưởng tượng những gì họ cần biết

Page 5: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- What NOT to Comment

o Việc đọc comment tốn thời gian

o Mỗi comment chiếm 1 phần màn hình

o => Cần phân biệt đâu là comment tốt và vô nghĩa

Comment vô nghĩa

vì nó không cung cấp bất kỳ thông

tin mới nào hay giúp người đọc dễ

hiểu code hơn

Page 6: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- What NOT to Comment

o Đừng comment khi có thể nắm bắt code 1 cách nhanh chóng bằng cách đọc nó

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

=> comment không cung cấp thêm thông tin gì

mới

=> Nhìn vào code bạn cuối cùng cũng sẽ hiểu

những gì nó làm

=> Nhưng đọc code có comment sẽ hiểu nhanh

hơn so với cách hiểu code mà không có comment

Page 7: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- What NOT to Comment

o Đừng comment vì bắt buộc phải comment

o Comment vô giá trị - khi khai báo function và comment là giống nhau => bỏ comment

hoặc cải tiến

// Find the Node in the given subtree, with the given name, using the given depth.

Node* FindNodeInSubtree(Node* subtree, string name, int depth);

Viết lại tên function và tham số thành 1 câu comment

// Find a Node with the given 'name' or return NULL.

// If depth <= 0, only 'subtree' is inspected.

// If depth == N, only 'subtree' and N levels below are inspected.

Node* FindNodeInSubtree(Node* subtree, string name, int depth);

Page 8: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- What NOT to Comment

o Đừng comment với “bad name” – Thay vào đó hãy sửa “bad name” đó

o Vì function name được dùng nhiều nơi => Function name tốt sẽ tự giải thích chính nó

o Một cái tên tốt sẽ tốt hơn một comment tốt

o Rule

good code > bad code + good comments

o Đừng viết “crutch comments” – comment cố gắng bù đắp cho sự khó đọc của

code

Page 9: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Recording Your Thoughts

o Nhiều comment tốt có thể đơn giản là "ghi lại suy nghĩ" - những suy nghĩ quan

trọng mà bạn có lúc viết code

o Thêm “lời bình luận”: Comment nên ghi lại thông tin giá trị về code

// Surprisingly, a binary tree was 40% faster than a hash table for this data.

// The cost of computing a hash was more than the left/right comparisons.

=> Cung cấp thông tin và tránh lãng phí thời gian tối ưu hóa

// This heuristic might miss a few words. That's OK; solving this 100% is hard.

=> Không có comment thì người đọc có thể nghĩ là bug, lãng phí thời gian test, fix bug

// This class is getting messy. Maybe we should create a 'ResourceNode' subclass to

// help organize things.

=> Thừa nhận code lộn xộn, khuyến khích sửa nó (với gợi ý cách bắt đầu)

Page 10: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Recording Your Thoughts

o Comment thiếu sót trong code của bạn

o Code không ngừng phát triển và sẽ có nhiều thiếu sót

o Đừng xấu hổ khi ghi lại những sai sót

// TODO: use a faster algorithm

=> cần cải tiến

// TODO(dustin): handle other image formats besides JPEG

=> cần hoàn thiện

o TODO: Việc chưa thực hiện

o FIXME: Biết code có thể lỗi ở đây

o HACK: Thừa nhận giải pháp chưa tốt với vấn đề đó

o XXX: Có vấn đề

- Phổ biến

- Phụ thuộc vào

team phát triển

Page 11: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Recording Your Thoughts

o Điều quan trọng là nên comment suy nghĩ của bạn về cách code có thể thay đổi

trong tương lai.

o Comment cung cấp cho người đọc 1 cái nhìn về chất lượng và trạng thái code

o => có thể có 1 số định hướng cải tiến

Page 12: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Recording Your Thoughts

o Comment on Your Constants

o Khi định nghĩa hằng số, thường có 1 "câu chuyện" về việc mà hằng số làm, lý do có

hằng số này

NUM_THREADS = 8

NUM_THREADS = 8 # as long as it's >= 2 * num_processors, that's good enough.

=> hiểu hơn về nó, và có thể thay đổi thích hợp

o Một số hằng số không cần comment vì bản thân nó đã đủ rõ ràng

SECONDS_PER_DAY

o Các hằng số nên có comment -> những gì bạn nghĩ khi quyết định giá trị hằng số

Page 13: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Put Yourself in the Reader’s Shoes

o Tưởng tượng code của bạn sẽ trông như thế nào với outsider - người không quen

thuộc với project của bạn

o Hữu ích để nhận ra những gì cần comment

o Câu hỏi cần đặt ra khi comment function hoặc class là: Có gì ngạc nhiên với code

này? Làm thế nào có thể sử dụng sai?

o Suy nghĩ và dự đoán vấn đề người khác có thể gặp phải khi sử dụng code của bạn

Giả sử viết 1 chức năng gửi mail tới user

void SendEmail(string to, string subject, string body);

=> chức năng cần kết nối với 1 external email service => cần thời gian

=> không biết => có thể gây ra việc "treo" web

// Calls an external service to deliver email. (Times out after 1 minute.)

void SendEmail(string to, string subject, string body);

Page 14: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Put Yourself in the Reader’s Shoes

o “Big Picture” Comments

o Một trong những việc khó nhất với thành viên mới của team là hiểu tổng quan về hệ

thống: các class tương tác như thế nào, data flow ra sao, ...

o => high-level comments

o Bên trong các function -> tốt hơn khi có các “Big Picture” Comment

# Find all the items that customers purchased for themselves.

for customer_id in all_customers:

for sale in all_sales[customer_id].sales:

if sale.recipient == customer_id:

...

=> Không có comment người đọc sẽ mơ hồ mặc dù hiểu đoạn code làm gì

Page 15: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Put Yourself in the Reader’s Shoes

o “Big Picture” Comments

o Hữu ích khi comment tóm tắt function với nhiều khối bên trong

def GenerateUserReport():

# Acquire a lock for this user

...

# Read user's info from the database

...

# Write info to a file

...

# Release the lock for this user

Page 16: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Các bước đơn giản

o Viết ra bất kỳ comment nào có trong đầu bạn

o Đọc nó, và xem cần cải thiện gì

o Cải tiến nó

Page 17: Chap 5 6 - The Art of Readable Code

Chapter 5: Knowing What to Comment

- Tổng kết

o Những comment không cần thiết

o Khi có thể hiểu nhanh chóng bằng cách đọc code

o Đừng viết “Crutch comments” bù đắp cho bad code – hãy sửa code

o Những suy nghĩ nên ghi lại

o “Bình luận”, hiểu biết về code

o Những thiết sót của code

o “Câu chuyện” về giá trị của hằng số

o Đặt vào vị trí người đọc

o Dự đoán phần code mà người đọc có thể khó hiểu

o Dùng “big picture” comment

o Tóm tắt các khối code

Page 18: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

o Khi viết comment cần tỉ mỉ - cụ thể và chi tiết nhất có thể

o Nhưng comment cần thời gian đọc và chiếm màn hình -> cần vắn tắt

o => Comment nên có tỉ lệ thông tin/không gian cao

Page 19: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- Keep Comments Compact

o Giữ comment ngắn gọn

// The int is the CategoryType.

// The first float in the inner pair is the 'score',

// the second is the 'weight'.

typedef hash_map<int, pair<float, float> > ScoreMap;

=> Tại sao cần 3 dòng comment, khi mà có thể giải thích nó trong 1 dòng

// CategoryType -> (score, weight)

typedef hash_map<int, pair<float, float> > ScoreMap;

Page 20: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- Avoid Ambiguous Pronouns

o Tránh comment với đại từ mơ hồ

o It, this -> có thể mang nhiều nghĩa

// Insert the data into the cache, but check if it's too big first.

=> “it” có thể là data, cũng có thể là cache

=> Tránh dung “it”

// Insert the data into the cache, but check if the data is too big first.

=> Hoặc tái cấu trúc câu để “it” có nghĩa rõ ràng

// If the data is small enough, insert it into the cache.

Page 21: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- Polish Sloppy Sentences

o Nhiều trường hợp comment tỉ mỉ và ngắn gọn đi đôi với nhau

# Depending on whether we've already crawled this URL before, give it a different priority.

# Give higher priority to URLs we've never crawled before.

=> Đơn giản hơn, ngắn hơn, nhiều thông tin hơn

Page 22: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- Describe Function Behavior Precisely

o Mô tả chức năng một cách rõ ràng

// Return the number of lines in this file.

int CountLines(string filename) { ... }

=> Có nhiều cách định nghĩa “line”

"" (an empty file)—0 or 1 line?

"hello"—0 or 1 line?

"hello\n"—1 or 2 lines?

"hello\n world"—1 or 2 lines?

"hello\n\r cruel\n world\r"—2, 3, or 4 lines?

// Count how many newline bytes ('\n') are in the file.

int CountLines(string filename) { ... }

=> comment dài hơn, nhưng nhiều thông tin hơn

Page 23: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- Use Input/Output Examples That Illustrate Corner Cases

o Lựa chọn I/O cẩn thận để minh họa => can be worth a thousand words

// Remove the suffix/prefix of 'chars' from the input 'src'.

String Strip(String src, String chars) { ... }

Is chars a whole substring that is to be removed, or effectively just an unordered set

of letters?

What if there are multiples of chars on the end of src?

// Remove the suffix/prefix of 'chars' from the input 'src'.

// Example: Strip("abba/a/ba", "ab") returns "/a/"

String Strip(String src, String chars) { ... }

Page 24: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- State the Intent of Your Code

o Nêu mục đích ở mức high-level chứ không phải là các chi tiết cụ thể

void DisplayProducts(list<Product> products) {

products.sort(CompareProductByPrice);

// Iterate through the list in reverse order

for (list<Product>::reverse_iterator it = products.rbegin(); it != products.rend();

++it)

DisplayPrice(it->price);

...

}

=> Comment mô tả các dòng code phía dưới

// Display each price, from highest to lowest

for (list<Product>::reverse_iterator it = products.rbegin(); ... )

=> Giải thích code ở mức độ cao hơn

Page 25: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- “Named Function Parameter” Comments

o Dùng inline comment để giải thích các tham số của hàm

void Connect(int timeout, bool use_encryption) { ... }

// Call the function with commented parameters

Connect(/* timeout_ms = */ 10, /* use_encryption = */ false);

o Khi comment giá trị tham số là Boolean thì chú ý /* name */ trước giá trị

// Don't do this!

Connect( ... , false /* use_encryption */);

// Don't do this either!

Connect( ... , false /* = use_encryption */);

Page 26: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- Use Information-Dense Words

o Sử dụng các từ Information-Dense

o Các từ ngắn gọn mà gói gọn nhiều ý nghĩa

// This class contains a number of members that store the same information as in the

// database, but are stored here for speed. When this class is read from later, those

// members are checked first to see if they exist, and if so are returned; otherwise the

// database is read from and that data stored in those fields for next time.

// This class acts as a caching layer to the database.

Page 27: Chap 5 6 - The Art of Readable Code

Chapter 6: Making Comments Precise and Compact

- Tổng kết

o Tránh các đại từ “it”, “this” – có thể có nhiều nghĩa

o Mô tả function chính xác

o Minh họa bằng các ví dụ I/O được lựa chọn cẩn thận

o Nêu mục đích của code ở mức high-level, chứ không phải mức chi tiết

o Sử dụng inline comment để giải thích các tham số

o Comment bằng các từ ngữ ngắn gọn nhưng gói gọn nhiều ý nghĩa