Thế nào là một chương trình sai, coder đã nắm chắc rồi chứ?

Bạn đã bao giờ dừng lại để đặt câu hỏi: Một chương trình chạy sai nghĩa là thế nào? Điều gì có thể khiến chương trình của bạn chạy sai? Nó sai từ môi trường thực thi, sai từ logic hay sai từ … thiết kế?

“Ăn code, ngủ code” hằng ngày, lập trình viên thường phải đối mặt với hàng trăm case khó nhằn trước khi cho ra đời một chương trình được coi là ưng ý. Code sai ư? Hãy cùng giải lý giải một cách đơn giản nhất để làm rõ thế nào là một chương trình sai nhé. Có nhiều định nghĩa cho vấn đề này, cùng xem qua 3 định nghĩa phổ biến nhất dưới đây:

Định nghĩa số 1:

Một chương trình sai nếu nó chạy và cho kết quả sai. Trong đó, biểu hiện dễ thấy nhất là qua 2 lỗi: lỗi khi thực thi (performance bugs), lỗi khó sử dụng (usability bugs).. vv. Nói ngắn gọn, lỗi thực thi xảy ra khi đoạn code không chạy được, và lỗi khó sử dụng là việc chương trình chạy không theo mong muốn ban đầu của coder hoặc chưa tối ưu. 

Có thể hình dung cụ thể như sau: Ta bỏ một miếng bánh mì vào máy nướng bánh, nhưng không có gì xảy ra, đó chính là một lỗi thực thi. Một trường hợp khác, thay vì trả lại cho chúng ta một miếng bánh mì nướng, chiếc máy trả lại một thứ hoàn toàn khác, như một miếng cá chẳng hạn…rõ ràng đó là một usability bugs. 

Chương trình vẫn thường có thể đưa ra kết quả không chính xác. Vậy nên việc cần làm có vẻ như là “đập đi xây lại”…

Định nghĩa số 2:

Một chương trình bị sai nếu trên một vài môi trường mà chuỗi các sự kiện, hoặc “đầu vào” của chương trình khiến nó sinh ra một kết quả sai. Bây giờ chúng ta hãy thử loại bỏ tất cả những điều đó, ta sẽ fix các lỗi trên phần mềm và cho code chạy chính xác bằng cách chạy hàng tỷ monkeys test case ở các góc độ khác nhau, khi đó có lẽ không có gì có thể làm chương trình chạy sai nữa. 

Tuy nhiên code vẫn có thể bị sai. Một đoạn code không bị lỗi, vẫn có thể chạy sai, khi mà việc đọc các giá trị đối số cũng như xử lý logic bên trong phụ thuộc vào các điều kiện phức tạp từ compiler và cách bố trí bộ nhớ (memory)

Định nghĩa số 3:

Một chương trình có thể sai nếu tiếu chuẩn “đúng – sai” do chúng ta đề ra có lỗ hổng. 

Để dễ tiếp cận và tìm ra lỗi sai khi code, ta nên thuộc nằm lòng một điều cốt lõi, đó là 3 cấp độ của một chương trình:

Cấp độ 1: Thực thi (chạy thử code)

Dễ thấy ở cấp độ này là việc vừa chạy thử chương trình thì trình dịch đã báo lỗi sai. Ta thường gặp các vấn đề với những giá trị cụ thể, môi trường cụ thể từ một cách vận hành của chương trình. Đòi hỏi phải sửa khá nhiều lỗi khi vận hành chương trình.

Cấp độ 2: Mã nguồn

Ở cấp độ này, chúng ta nghĩ về việc đoạn mã này sẽ ra sao khi xử lý những input bất kì ở trên những môi trường khác nhau. Cụ thể là mục tiêu code ban đầu hướng tới một mục tiêu A, nhưng sau khi chạy thử nó lại “bẻ lái” sang một hướng B, không đúng ý coder.

Cấp độ 3: Thiết kế/logic

Tại đây, ta cần xem xét tính trừu tượng của từng đơn vị trong chương trình. Tức là để tránh lỗi, coder phải xem xét tất cả các trường hợp có thể xảy ra trong quá trình code. Thậm chí có những chương trình được coi là “đúng” ở cấp độ thực thi, nhưng khi đến cấp độ logic nó lại không còn “đúng” vì chưa tối ưu. Tức là có thể tồn tại một lỗi sai tại một case mà coder chưa thể hình dung ra, dẫn đến sự “sai” trong tương lai. Ta gọi đây là “lỗi lập luận từng phần”, bởi vì ta không thể tranh cãi xem một chức năng là đúng hay sai nếu chỉ nhìn vào mã nguồn và các quy ước giữa các phần của nó. Hầu hết các thiết kế phần mềm được hoàn thiện ở cấp độ logic. Nói tóm lại, ở cấp độ này, định nghĩa “sai” là khi chương trình chưa tối ưu, thuật toán còn có thể tìm cách rút ngắn được hơn, code khó đọc hoặc khó duy trì…

Để hình dung rõ ba cấp độ này, ta hãy liên tưởng đến việc xây nhà để ở. 

Cấp độ một là khi ta xây sai và tòa nhà đổ sập, thập chí không thành hình. 

Cấp độ 2 là việc tòa nhà vẫn được dựng lên nhưng không ở được, mà phải dùng cho một mục đích khác như chứa đồ chẳng hạn. 

Cấp độ 3 chính là tòa nhà được xây nên, ta dọn đến ở nhưng thiết kế và công năng của nó chưa tối ưu, thậm chí có thể tiềm ẩn các nguy cơ trong tương lai.

Hi vọng qua bài viết này, chúng ta sẽ hiểu rõ hơn về 3 cấp độ của một chương trình và như thế nào là một chương trình sai để cải thiện quá trình code hiệu quả hơn!