Отладка через печать — это здорово, и вам не должно быть стыдно за то, что вы её используете! Это инструмент, который работает на всех языках1. Его легко понять и реализовать. Он позволяет сосредоточиться на тщательном чтении и понимании кода, а не теряться в лесу из данных. Отладка через печать действительно эффективна во многих случаях.

Такая отладка — не то же самое, что логирование. Вы включаете печать в попытке выяснить, что пошло не так, и выключаете её, как только разобрались, желательно до того, как сделаете коммит!

Плохая практика?

Люди считают, что отладка через печать — плохая практика. В интернете полно советов о том, как избежать отладки через печать в пользу других способов. Чтобы продемонстрировать настроение, я приведу несколько случайных заголовков без ссылок:

  • «Почему вам не следует использовать console.log( ) для отладки».
  • «Не используйте print. Осваиваем логирование Python».
  • «Перестаньте использовать простую console.log в JavaScript. Вместо нее попробуйте это».
  • «Прекратите использовать печать и начните отладку».
  • «Прекратите использовать Print и начните использовать Logging.
  • «Python без print. Прекратите использовать print для отладки».
  • «Остановитесь c console.log(). Есть способы лучше!».

Я признаю, что некоторые из этих статей пытаются убедить вас использовать какую-нибудь библиотеку, которая выводит более понятные отладочные сообщения. Я только за, хотя печать всё так же очень полезна2. Вместо этого следовало бы назвать отладку через печать хорошей практикой3.

Рабочий процесс отладки через печать

Итак, вот рабочий процесс такой отладки:

  • Найдите проблему.
  • Добавьте инструкции печати в стратегически важных местах, где хотите проверить предположения.
  • Посмотрите, что происходит. Верны ли предположения? На какое-то время поменяйте места печати. Подумайте.
  • Устраните проблему.
  • Уберите всю печать.
  • Готово.

Возможности отладки через печать

Для обработки данных можно использовать выражения! Можно форматировать данные, чтобы удобнее было читать! Можно использовать операторы if, циклы и всё, что вы хотите! Даже простого print("here!") достаточно, чтобы понять, вызывается ли что-то вообще. И всё это на языке программирования, который вы уже знаете.

Еще больше возможностей

Можно написать автоматизированные тесты для части кодовой базы4. Можно даже написать их до того, как вы напишете код!

И вот вы изолировали свою проблему в неудачный тест. Подумайте, как использовать средство запуска тестов, чтобы отделить ее и запускать только этот тест.

Затем используйте отладку через печать только для одного теста, а не для всей программы! Таким образом, если ваш тест задействует только часть поведения или (что ещё лучше) только часть вашей кодовой базы, вы будете знать, что любая печать в вывод связана только с этим тестом. Для поиска ошибки это очень полезно.

Подозреваю, что отчасти причина того, почему люди чаще обращаются к отладчику, заключена в том, что они не разрабатывают автоматизированные тесты вместе с кодовой базой. В итоге что-нибудь очень сложное приходится отлаживать сразу во всех местах. Если вы разрабатываете тесты, то большинство вещей отлаживаете по мере написания. Намного проще, когда вы знаете, что сломали что-то в нескольких новых строках, которые добавили или изменили, а не во всём коде сразу.

Подождите

До того как это каким-нибудь образом превратится в смертельно опасную лучшую практику, я не говорю, что применение более сложных инструментов — это плохо. Используйте их, если они есть и подходят вашим целям. Просто не отказывайтесь от отладки через печать.

P. S. Я не первый

Я не первый, кто указывает на то, что отладка печатью — это хорошо:

«Самым эффективным инструментом отладки по-прежнему остаются тщательные размышления в сочетании с продуманным размещением операторов вывода», — Брайан Керниган, «Unix для начинающих» (1979).

Однако многие по этому поводу извиняются или путаются:

Я взял цитату Кернигана из этой статьи, где он действительно сравнивает это с логированием. И в этой статье рассказывается, почему отладка с помощью печати может быть такой полезной, но затем автор признаёт, что это стыдно, и говорит:

Я не говорю, что отладка с помощью печати — это лучшее конечное состояние для инструментов отладки, это далеко не так. Я просто говорю, что нам следует глубоко задуматься о том, почему отладка с помощью печати так популярна, помимо простого удобства, а затем использовать эти знания в новых инструментах.

Я утверждаю, что отладка с помощью печати работает так хорошо, что, хотя новые инструменты могут быть полезны, они неизбежно не настолько универсальны и просты. Универсальность и простота — большие преимущества отладки через печать. Может быть, отладка с помощью печати на самом деле является оптимальным решением во многих случаях?

В статье The Evolution of Debugging: From Print Statements to Modern Tools хорошо проанализированы компромиссы. Заголовок подразумевает, что отладка через печать — это устаревший, примитивный инструмент, однако несмотря на это статья заканчивается словами «От традиционных методов отладки не стоит отмахиваться».

И вот она перед вами, моя беззастенчивая, непримиримая статья: «‘Print’ Is the Only Debug Tool You Need» (Печать — единственный инструмент отладки, который вам нужен»). Просто, чтобы показать, что я не оригинален.

  1. Даже в Haskell, который не одобряет побочные эффекты, есть нечистая функция под названием traceShow.
  2. Как и в Rust, для которого я нашёл несколько статей, агитирующих против println!. Есть эта статья, направляющая вас применять dbg!(), которая является встроенной и очень полезной. Но я всё равно использую println!() ещё и потому, что так я лучше управляю выводом и он не такой шумный.
  3. Или лучшая практика, но, я думаю, это проблемный термин.
  4. Помогает разделение кода на независимые части. Например, можно разбить кодовую базу на части, которые можно понять и отладить отдельно. Но даже для значительной части вашей кодовой базы отладка с помощью печати всё равно может быть полезна.
  5. Некоторые инструменты тестирования полезны тем, что они ничего не выводят на печать при успешных тестах, а только при неудачных. Хотя иногда это раздражает, и приходится изучать, как отключить функцию.

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Martijn Faassen: Don’t Look Down on Print Debugging

Предыдущая статья6 шагов для старта в машинном обучении в 2025 году 
Следующая статьяОпыт работы с Python в течение 2 лет: уроки и рекомендации