Simplifying Loops and Logic

Simplifying Loops and Logic

  • Trong bài này chúng ta sẽ đi sâu hơn và thảo luận về "các vòng lặp và logic" trong chương trình của bạn: luồng điều khiển, các biểu thức logic, và các biến làm cho code bạn hoạt động. Như mọi khi, mục tiêu của chúng ta là làm cho các thành phần này trong code của bạn trở nên dễ hiểu.
  • Chúng ta làm điều này để cố làm giảm thiểu việc phải hoạt động trí óc nhiều khi xem code của bạn. Khi bạn đọc một vòng lặp phức tạp, một biểu thức khổng lồ, hoặc một số rất rất lớn, nó làm cho bạn cảm thấy mệt mỏi đầu óc hơn. Nó yêu cầu bạn phải suy nghĩ nhiều hơn và nhớ nhiều hơn. Nó thật sự là đi ngược lại việc làm cho code dễ hiểu. Khi code của bạn bao gồm nhiều thành phần khó đọc, khó hiểu thì sẽ dễ phát sinh nhiều bug hơn và code của bạn sẽ trở nên khó khăn hơn để thay đổi. Làm giảm hứng thú khi làm việc.

I. Making Control Flow Easy to Read

Screenshot from 2015-11-24 09:32:35.png

  • Nếu code của bạn không có bất kì điều kiện nào, vòng lặp hay bất kì câu lệnh điều khiển luồng thì thật dễ dàng để đọc, hiểu. Bây giờ ta hãy xem xem một nhánh khác khi mà code phức tạp hơn bao gồm các thành phần như vòng lặp, biểu thức phức tạp hay nhiều luồng điều khiển .
  • Hãy xem xét để làm sao cho những luồng điều khiển này trong code của bạn trở nên dễ hiểu.

**KEY IDEA: Hãy làm cho các điều kiện trong code của bạn, các vòng lặp, và những thay đổi khác của luồng điều khiển được tự nhiên nhất có thể - viết code bằng cách mà không làm cho người đọc phải dừng lại hay phải đọc lại code của bạn để có thể hiểu chúng.

1. Thứ tự của các đối số trong câu lệnh điều kiện

  • Xem xét 2 ví dụ dưới đây

Screenshot from 2015-11-24 09:43:18.png

Hoặc

Screenshot from 2015-11-24 09:43:56.png

Trong 2 ví dụ trên thì theo bạn ví dụ nào dễ đọc hơn ? Với đa số lập trình viên thì ví dụ đầu là dễ hiểu nhất. Nhưng hãy xem xét tiếp 2 ví dụ dưới đây :

Screenshot from 2015-11-24 09:45:41.png

Screenshot from 2015-11-24 09:45:56.png

Có vẻ như ví dụ đầu tiên là dễ đọc hơn. Vì sao ? đâu là luật chung mà ta có thể áp dụng ? làm sao bạn có thể quyết định được liệu cái nào là tốt hơn a < b hay b > a

Dưới đây là một số hướng dẫn của chúng tôi

  • Vế trái của biểu thức : là các giá trị mà có tính không ổn định và dễ thay đổi.

  • Vế phải của biểu thức: là giá trị mang tính ổn định, có thể là một hằng số.

  • Trong cuộc sống chúng ta cũng có thể đưa ra những ví dụ tương tự như: Nếu thu nhập của bạn là ít nhất 10 triệu/ tháng hoặc Nếu bạn lớn hơn 18 tuổi không ai nói rằng nếu 18 tuổi là ít hơn hoặc bằng tuổi của bạn. Cách nói như vậy không được tự nhiên.

  • Điều này giải thích tại sao while (bytes_received < bytes_expected) trở nên dễ đọc hơn. bytes_received là giá trị mà chúng ta đang xét đến nó có thể đang tăng lên khi chạy vòng lặp còn giá trị bytes_expected thì phù hợp hơn khi dùng để so sánh.

2. Thứ tự của các blocks if/else

Screenshot from 2015-11-24 10:00:15.png

  • Khi viết các cấu lệnh if/else, bạn thường xuyên có quyền thay đổi thứ tự các blocks. Trong trường hợp bạn có thể viết như thế này

Screenshot from 2015-11-24 10:02:11.png

  • Bạn có thể không nghĩ nhiều về nó trước đây, nhưng trong một vài trường hợp đó là lý do tốt để đặt một block trên một vài block khác.

    +) Nên để các biểu thức trong if/else ở dạng tích cực trước ví dụ như if ($a) thay vì if (!$a) +) Nên đặt các block if/else mà có các biểu thức đơn giản trước +) Nên đặt các block mà có các biểu thức thú vị hoặc rõ ràng lên trước.

  • Một vài trường hợp sẽ tồn tại các block thỏa mãn cả 3 điều kiện trên khi đó bạn sẽ là người đưa ra quyết định đưa block nào lên đầu. Làm sao cho nó mang tính rõ ràng nhất.

  • Ví dụ, giả sử bạn có một web server rằng xây dựng một respon dựa trên liệu đường dẫn URL có chứa tham số của query tên là expand_all hay không

Screenshot from 2015-11-24 10:26:29.png

Khi và người đọc nhìn vào dòng đầu tiên, bộ não của họ sẽ ngay lập tức nghĩ về trường hợp expand_all. Giống như một ai đó nói rằng Đừng nghĩ về một con voi màu hồng. bạn không thể giúp nhưng hay nghĩ về nó - Đừng để ý về những thứ không bình thường như con voi sao lại có màu hồng.

  • Và ở đây expand_all giống như con voi màu hồng trong ví dụ trên. Bởi vì nó là một trường hợp thú vị hơn vì vậy hãy đưa nó lên đầu

Screenshot from 2015-11-24 10:31:27.png

  • Mặt khác, đây là một tình huống mà block mang biểu thức ở dạng tiêu cực lại đơn giản hơn và thú vị hơn, vì vậy chúng ta đặt nó lên đầu:

Screenshot from 2015-11-24 10:35:42.png

**KẾT LUẬN: phụ thuộc vào nội dung của các block mà có cách sắp xếp sao cho phù hợp, ưu tiên các block có nội dung đơn giản dễ hiểu lên trước.

3. Tránh dùng do/while

Screenshot from 2015-11-24 10:43:57.png

  • Rất nhiều ngôn ngữ lập trình nổi tiếng như Perl có cấu lệnh dạng do/while. Các câu lệnh điều kiện sẽ được thực hiện cuối cùng. Hãy xem xét một ví dụ:

Screenshot from 2015-11-24 10:46:52.png

  • Khối mã do/while có thể chỉ được chạy một lần, thông thường biểu thức điều kiện logic ở trên đoạn code trong hình, chúng sẽ kiểm soát việc nó làm việc. Và vì chúng ta đọc code từ trên xuống nên thông thường sẽ phải mất công đọc lại lần nữa sau khi đọc xong các biểu thức điều kiện trong while.

  • Theo tôi nên sử dụng vòng lặp while() bở vì bạn biết điều kiện chạy trước khi đọc đoạn code trong block. Khi đó đoạn code có thể viết như sau :

Screenshot from 2015-11-24 10:51:21.png

Chúc các bạn thành công.

Tài liệu tham khảo: The Art of Readable Code by Dustin Boswell and Trevor Foucher.