Debugging: Finding It Yourself
Практичний посібник з пошуку помилок без попросити допомоги спочатку — як ізолювати, перевірити й насправді зрозуміти свої баги.
Більшість новачків розглядають баг як стіну. Вони їй натикаються, зупиняються й просять когось іншого перелізти через неї. Звичка, яка насправді розвиває навички, інша: ви навчаєтесь розглядати баг як питання з відшукуваною відповіддю, і ви її знаходите перш, ніж йти просити.
Читайте повідомлення про помилку так, наче це доказ, а не шум
Stack traces постійно пропускаються тому, що виглядають страшно. Але зазвичай вони говорять вам прямо де й чому щось зламалося. Якщо ви отримаєте TypeError: 'NoneType' object is not subscriptable у Python, це не випадкова абракадабра — це означає, що змінна, яку ви очікували звести список або dict, насправді None. Номер рядка вам говорить де. Ваше завдання — пройти в зворотному напрямку від цього рядка й знайти, де значення повинно було бути встановлено, але не було.
Робіть це перш ніж щось шукати в інтернеті: прочитайте останній рядок traceback спочатку, потім працюйте в гору. Останній рядок зазвичай називає саме виключення. Рядки вище нього показують ланцюг викликів, який вас туди доставив.
Відтворіть це навмисне
Якщо баг з'являється лише інколи, ви його ще не розумієте. Перш ніж торкатися коду, спробуйте змусити його відбутися надійно. Змінюйте по одному входу за раз. Він не спрацює з порожнім списком, але не з повним? Він не спрацює тільки на другому виклику функції, а не на першому? Баг, який ви можете відтворити за командою, — це баг, який на 80% розв'язаний, тому що тепер ви можете перевірити чи насправді виправка спрацювала, замість того щоб гадати.
Розділіть проблему навпіл, потім знову навпіл
Двійковий пошук — це не лише для відсортованих масивів — це найшвидший спосіб знайти зламаний код у довгій функції чи pipeline. Закоментуйте або обійдіть другу половину своєї логіки й перевірте чи перша половина все ще видає баг. Якщо так, проблема в першій половині. Якщо ні, то в другій. Повторюйте. Це працює для 200-рядкового скрипту так само добре як для багатоетапного data pipeline, де ви перевіряєте виходи на кожному етапі за допомогою print() або df.head().
Це краще, ніж випадково міняти рядки й переносити, що більшість людей роблять під тиском, і це займає набагато більше часу, ніж заощаджує.
Використовуйте debugger замість print(), коли print() перестає працювати
print() вирази гарні для простих випадків, але коли ви переслідуєте стан на кількох викликах функцій, справжній debugger заощаджує справді часу. У Python, покладіть import pdb; pdb.set_trace() прямо перед підозрілим рядком, запустіть скрипт, і ви отримаєте живий prompt де можете перевірити змінні, крок за кроком з n, і крок у виклики функцій з s. Вбудований debugger VS Code робить те ж саме з точками переривання, які ви клікаєте замість введення. У будь-якому разі, мета одна й та ж: спостерігайте за фактичним станом вашої програми замість того щоб гадати які він, мабуть, є.
Ізолюйте його від решти вашого проекту
Якщо баг відбувається всередині великої кодової бази, не дебагтьте його всередині великої кодової бази. Скопіюйте відповідну функцію у свіжий файл з підробленим, мінімальним входом, який запускає той же збій. Якщо баг зникне, щось про оточуючий контекст — глобальна змінна, import, застаріле стан — є справжньою причиною, і ви щойно щось важливе дізналися. Якщо баг залишається в ізоляції, у вас тепер є невелика, спільна, тестуюча справа, і ви набагато ближче до справжньої виправки.
Перевірте ваші припущення проти реальності, а не пам'яті
Людина частина часу дебагування йде на безсумнівні припущення:
Написано з допомогою штучного інтелекту, перевірено та опубліковано Мішалем Пільчем (CISSP), Korra Studio.
Це одна замітка з бази знань Korra Studio — платформа поєднує кожну тему з 1-на-1 менторингом.
Початок безплатноarrow_forward