NhaLapTrinh.comNhà Lập Trình
Viết mã dễ đọc

Trường hợp biên: mã tốt khác mã chạy được ở đâu?

Mã chạy được xử lý đúng trường hợp bình thường; mã tốt còn xử lý đúng những trường hợp ở rìa: danh sách rỗng, giá trị không, dữ liệu thiếu, số rất lớn, mạng đứt giữa chừng. Thói quen tự hỏi nếu thứ này rỗng, thiếu hay quá lớn thì sao là thứ phân biệt hai loại mã.

🎙️
📑 Nội dung theo chương
  1. 0:35 Rìa là nơi lỗi sống
  2. 1:16 Rỗng, không và thiếu
  3. 2:10 Một, nhiều và quá nhiều
  4. 3:02 Khi thế giới bên ngoài không hợp tác
  5. 3:49 Tập thói quen hỏi câu biên
  6. 4:46 Câu hỏi thường gặp
🔊 Bản audio (lồng nhạc nền)

Mã chạy được là mã xử lý đúng trường hợp bình thường. Mã tốt còn xử lý đúng những trường hợp nằm ở rìa: danh sách rỗng, giá trị bằng không, dữ liệu bị thiếu, con số rất lớn, mạng đứt giữa chừng. Thói quen tự hỏi nếu thứ này rỗng, thiếu, hay quá lớn thì sao chính là thứ phân biệt hai loại mã.

Chào bạn, đây là Nhà Lập Trình. Khi người mới hoàn thành một chức năng, họ thử với dữ liệu mẫu, thấy chạy, và báo xong. Người có kinh nghiệm nhìn vào và hỏi ngay: nếu khách chưa có đơn hàng nào thì sao? Câu hỏi đó thường làm chức năng vỡ. Tập này là về những câu hỏi như vậy.

Rìa là nơi lỗi sống

Hãy hình dung mã của bạn như một con đường. Ở giữa đường, bằng phẳng, xe chạy êm. Nhưng ở mép đường có ổ gà, có lề sụt, có ranh giới với ruộng. Tai nạn thường xảy ra ở mép, không phải ở giữa.

Trường hợp biên là những mép đó. Lúc bạn viết mã, đầu bạn nghĩ về trường hợp giữa đường: một khách hàng bình thường, có vài đơn hàng bình thường, mua số lượng bình thường. Mã chạy đúng cho trường hợp đó.

Nhưng người dùng thật không bình thường. Có khách vừa đăng ký, chưa có đơn nào. Có khách mua một nghìn món trong một đơn. Có khách để trống ô địa chỉ. Có khách đặt tên có dấu nháy. Có khách bấm nút lúc mạng chập chờn.

Mỗi trường hợp như vậy là một chỗ mà mã chỉ chạy được sẽ vỡ, còn mã tốt thì không.

Rỗng, không và thiếu

Nhóm trường hợp biên phổ biến nhất là những thứ không có gì. Danh sách rỗng: tính trung bình giá trị đơn hàng của một khách chưa có đơn nào, chương trình chia cho không và nổ tung. Chuỗi rỗng: khách để trống ô tên, và trang hiện chào bạn cùng một dấu phẩy.

Giá trị bằng không là một thứ khác với không có giá trị. Một sản phẩm giá bằng không vì là quà tặng khác với sản phẩm chưa được nhập giá. Nếu mã coi hai thứ như nhau, bạn có thể bán miễn phí một món hàng chỉ vì ai đó quên nhập giá.

Dữ liệu thiếu thì ở khắp nơi. Khách cũ đăng ký trước khi có ô số điện thoại. Dữ liệu nhập từ hệ thống cũ bị trống một cột. Dịch vụ bên ngoài trả về kết quả thiếu một trường. Mã giả định mọi thứ luôn có mặt sẽ vỡ khi gặp những bản ghi này.

Với mỗi dữ liệu đầu vào, hãy tự hỏi: nếu nó rỗng thì sao, nếu nó bằng không thì sao, nếu nó không có mặt thì sao. Ba câu hỏi đó bắt được rất nhiều lỗi trước khi người dùng thấy.

Một, nhiều và quá nhiều

Nhóm thứ hai là về số lượng. Mã thường được thử với vài phần tử. Nhưng một phần tử duy nhất đôi khi cũng là trường hợp đặc biệt. Hiện danh sách với dấu phẩy ngăn cách, một phần tử thì không cần dấu phẩy. Chữ một sản phẩm và hai sản phẩm có thể cần cách viết khác nhau.

Quá nhiều là trường hợp khó thấy nhất khi thử. Trang danh sách chạy mượt với mười khách hàng. Khi có một trăm nghìn khách, trang tải mất một phút, hoặc máy chủ hết bộ nhớ. Tệp xuất báo cáo chạy tốt với dữ liệu một tháng, treo máy với dữ liệu một năm.

Con số rất lớn cũng là biên. Số tiền vượt quá giới hạn của kiểu số được chọn. Số lượng người dùng nhập nhầm thêm vài số không. Một ô văn bản mà ai đó dán vào nguyên cuốn sách.

Với mỗi thứ có số lượng, hãy hỏi: nếu chỉ có một thì sao, nếu có hàng triệu thì sao. Và với mỗi ô người dùng nhập, hãy đặt giới hạn hợp lý thay vì tin rằng không ai nhập quá dài.

Khi thế giới bên ngoài không hợp tác

Nhóm thứ ba là những thứ ngoài tầm kiểm soát của bạn. Mạng đứt giữa lúc đang lưu. Dịch vụ thanh toán không trả lời. Ổ đĩa đầy. Tệp người dùng tải lên bị hỏng. Hai người cùng sửa một bản ghi.

Mã chạy được giả định mọi thứ bên ngoài luôn hoạt động. Mã tốt hỏi: nếu bước này thất bại thì hệ thống ở trạng thái nào? Có bị nửa vời không, ví dụ tiền đã trừ mà đơn chưa tạo? Người dùng có biết chuyện gì đã xảy ra không? Có thử lại được không?

Không phải lúc nào cũng xử lý được hoàn hảo. Nhưng ít nhất, hãy để hệ thống thất bại một cách rõ ràng, báo lỗi cho người dùng bằng lời dễ hiểu, và ghi đủ thông tin vào nhật ký để người vận hành xử lý.

Điều tệ nhất là thất bại âm thầm: bước gửi thư lỗi mà không ai biết, khách không nhận được xác nhận, và ba ngày sau mới có người gọi điện phàn nàn.

Tập thói quen hỏi câu biên

Tư duy về trường hợp biên không phải bẩm sinh, nó là thói quen luyện được. Cách đơn giản nhất là giữ một danh sách câu hỏi và đi qua nó mỗi khi viết xong một chức năng: rỗng, không, thiếu, một, rất nhiều, rất lớn, ký tự lạ, thất bại giữa chừng, hai người cùng lúc.

Viết bài thử nghiệm cho các trường hợp biên. Trường hợp bình thường thì bạn đã thử tay rồi, các trường hợp biên mới là thứ dễ quên và dễ bị phá vỡ khi người sau sửa mã.

Khi xem lại mã của đồng nghiệp, hãy hỏi những câu biên. Không phải để bắt lỗi, mà để cả hai cùng nghĩ. Nhiều khi người viết đã nghĩ tới và xử lý rồi, chỉ là không rõ ràng trong mã. Câu hỏi của bạn giúp họ làm nó rõ hơn.

Nhưng cũng đừng rơi vào hoang tưởng, xử lý mọi trường hợp có thể tưởng tượng ra. Hãy cân nhắc trường hợp nào thực sự có thể xảy ra và hậu quả nặng nhẹ ra sao. Xử lý kỹ những gì liên quan tới tiền và dữ liệu người dùng, còn những trường hợp cực hiếm mà hậu quả nhẹ thì một thông báo lỗi rõ ràng là đủ.

Câu hỏi thường gặp

Trường hợp biên là gì?

Là những tình huống nằm ở giới hạn hoặc ngoài dự tính thông thường, như dữ liệu rỗng, giá trị bằng không, số lượng cực lớn, dữ liệu thiếu hoặc lỗi từ bên ngoài. Đây là nơi lỗi phần mềm hay xuất hiện nhất.

Giá trị trống và giá trị bằng không khác nhau thế nào?

Giá trị bằng không là một giá trị cụ thể, ví dụ giá quà tặng. Giá trị trống nghĩa là chưa có thông tin, ví dụ chưa nhập giá. Nhầm lẫn hai thứ này có thể gây lỗi nghiêm trọng.

Có cần viết thử nghiệm cho mọi trường hợp biên không?

Nên ưu tiên những trường hợp có khả năng xảy ra và có hậu quả nặng, nhất là liên quan tới tiền và dữ liệu. Với trường hợp cực hiếm, hậu quả nhẹ, một thông báo lỗi rõ ràng là đủ.

Thất bại âm thầm là gì và vì sao nguy hiểm?

Là khi một bước bị lỗi mà không báo cho ai và không ghi nhật ký. Nó nguy hiểm vì lỗi chỉ được phát hiện muộn, khi đã ảnh hưởng tới nhiều người dùng.

Làm sao luyện thói quen nghĩ về trường hợp biên?

Giữ một danh sách câu hỏi như rỗng, không, thiếu, rất nhiều, rất lớn, thất bại giữa chừng và đi qua nó mỗi khi viết xong một chức năng. Sau một thời gian, bạn sẽ tự hỏi mà không cần danh sách.

Cần tư vấn cụ thể cho trường hợp của bạn?

Chúng tôi sẽ liên hệ trong vòng 24 giờ.

Đăng ký tư vấn ngay

Bài viết liên quan

Bạn cần hỗ trợ thêm?

Để lại thông tin, chúng tôi sẽ liên hệ trong 24 giờ.