Отладка через печать — это здорово, и вам не должно быть стыдно за то, что вы её используете! Это инструмент, который работает на всех языках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» (Печать — единственный инструмент отладки, который вам нужен»). Просто, чтобы показать, что я не оригинален.
- Даже в Haskell, который не одобряет побочные эффекты, есть нечистая функция под названием
traceShow. - Как и в Rust, для которого я нашёл несколько статей, агитирующих против
println!. Есть эта статья, направляющая вас применятьdbg!(), которая является встроенной и очень полезной. Но я всё равно используюprintln!()ещё и потому, что так я лучше управляю выводом и он не такой шумный. - Или лучшая практика, но, я думаю, это проблемный термин.
- Помогает разделение кода на независимые части. Например, можно разбить кодовую базу на части, которые можно понять и отладить отдельно. Но даже для значительной части вашей кодовой базы отладка с помощью печати всё равно может быть полезна.
- Некоторые инструменты тестирования полезны тем, что они ничего не выводят на печать при успешных тестах, а только при неудачных. Хотя иногда это раздражает, и приходится изучать, как отключить функцию.
Читайте также:
- Как ошибка программиста может в одночасье превратить жизнь в ад
- Трассировка стека и более точная отладка
- 10 практик написания кода, на которые полагаются все старшие разработчики
Читайте нас в Telegram, VK и Дзен
Перевод статьи Martijn Faassen: Don’t Look Down on Print Debugging





