Giả thuyết, ghi log, và tìm kiếm nhị phân
Một khi AI đề xuất một nguyên nhân, đừng chỉ chấp nhận nó ngay. Hãy kiểm chứng nó với chi phí thấp. Cách kiểm chứng rẻ nhất thường là một dòng log.
Yêu cầu AI thêm log tạm thời:
"Trước khi chúng ta thay đổi bất cứ điều gì, hãy thêm một
console.log(hoặcuserngay trước dòng 14, để chúng ta có thể thấy liệu nó có thực sự là undefined hay không."
Chạy nó, dán kết quả trở lại. Bây giờ bạn có bằng chứng, không phải một lý thuyết. Có thể user là undefined — xác nhận giả thuyết. Có thể nó ổn và thủ phạm thực sự nằm ở một tầng cao hơn. Dù thế nào, bạn cũng đã tiến lên phía trước. Hãy ghi log rộng rãi trong khi điều tra: giá trị của biến, và một nhãn cho biết đó là biến nào và log đó nằm ở đâu. Một console.log(user) trần trụi in ra undefined sẽ kém hữu ích hơn nhiều so với console.log("user at validate.js:14 =", user). Và nhớ rút những log tạm thời đó ra sau khi bug đã được sửa xong — log gỡ lỗi còn sót lại tự nó cũng là một mớ hỗn độn nhỏ.
Khi bug ẩn náu ở đâu đó trong một quy trình dài và bạn không thể biết ở đâu, hãy dùng tìm kiếm nhị phân (binary search). Cắt đôi vùng nghi vấn: thêm một log ở điểm giữa.
Ý tưởng là: mỗi lần kiểm tra loại bỏ một nửa số còn lại, nên một không gian tìm kiếm khổng lồ sẽ thu hẹp rất nhanh. Ở đây, một bug ẩn ở đâu đó giữa bước 1 và bước 8 — ba lần kiểm tra là dồn nó vào chân tường:
step: 1 2 3 4 5 6 7 8 a bug is somewhere in here
░░░░░░░░░░░░░░░░░░░░░░
check 1 ── log at 4 ── OK ──▶ bug is AFTER 4, drop 1–4
░░░░░░░░░░░ (5 6 7 8 left)
check 2 ── log at 6 ── BAD ─▶ bug is AT/BEFORE 6, drop 7–8
░░░░░ (5 6 left)
check 3 ── log at 5 ── OK ──▶ bug is at step 6 ✔ found
8 steps → 3 checks. 1000 steps → about 10 checks.
Giá trị ở đó trông có đúng không? Vậy thì bug nằm sau nó — hãy tìm kiếm ở nửa đó. Nó đã trông sai ngay từ đó rồi phải không? Bug nằm trước nó — hãy tìm kiếm ở nửa đó. Mỗi bước chia đôi không gian tìm kiếm, nên ngay cả một đường dẫn dài cả ngàn dòng cũng sẽ thu hẹp lại chỉ trong khoảng mười lần kiểm tra. Hãy nói rõ với AI: "Giúp tôi chia đôi (bisect) chỗ này — điểm giữa mà tôi nên ghi log là ở đâu?" Kỹ thuật tương tự cũng hiệu quả với lịch sử, không chỉ với mã: nếu một tính năng hoạt động tốt tuần trước nhưng hôm nay bị hỏng, hãy chia đôi (bisect) các của bạn để tìm ra chính xác thay đổi nào đã gây ra bug.