Отладка программ: действуй, как детектив

Перевод статьи «Tips for Debugging Software like a Detective».

Photo by Hans Veth on Unsplash

Чтобы эффективно заниматься отладкой ПО, веб-разработчику нужно быть своего рода детективом. По мере своего профессионального развития я не только расширила свои знания о различных способах неожиданного выхода программного обеспечения из строя, но и отточила навыки отладки.

https://twitter.com/indigitalcolor/status/1392464056011866114
«Когда что-то в программе идет не так, разработчику приходится поработать детективом. ПОДСКАЗКА: компьютер, вероятно, делает именно то, что вы сказали ему делать, но есть некоторые вещи, способные помочь при отладке программ».

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

Дело в том, что компьютеры интерпретируют инструкции буквально. Поэтому для устранения несоответствия между фактическим и ожидаемым поведением программы вам может потребоваться пересмотреть свои предположения!

Разработчики могут иметь много необоснованных или даже ложных убеждений, которые способны привести к неадекватной обработке «крайних случаев».

К такого рода предположениям можно отнести убежденность в том, что имя пользователя является постоянным или что имя должно состоять из X символов, или что имя непременно имеет структуру «фамилия, имя, отчество» (в англ. варианте — «имя, второе имя, фамилия»), хотя на самом деле это не факт.

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

Бывает, что проблема вроде бы изолирована в локальной среде и что-то перестало работать без каких-либо заметных изменений в коде. В таких случаях я могу «выключить и снова включить», т. е. попробовать некоторые из следующих действий:

  • восстановить базу данных,
  • заново установить node_modules,
  • перезапустить docker или компьютер и т. д.

Но что делать, если это не решает проблему?

1. Воспользуйтесь линтером

Выполните линтинг. Подсвечиваются ли какие-нибудь синтаксические ошибки? Не ссылается ли ваш код на неопределенную переменную?

Куда чаще, чем мне хотелось бы, мой код не компилировался (локально) из-за красной буквы «f», которую я каким-то образом добавила к случайной строке. Этот неуместный символ часто убирается при линтинге. Но если приложение успешно скомпилировано, а мне хочется просмотреть изменения самостоятельно, я воспользуюсь Git Lens — интеграцией VS Code. Этот инструмент помогает выявить, не выделяется ли что-нибудь как несоответствующее.

Аналогично, если в вашем терминале, консоли браузера или веб-странице выскакивают какие-нибудь другие ошибки — не пугайтесь. Они призваны помочь вам разобраться, что именно происходит не так. Когда я только начинала учиться программированию, я скорее их не читала, а просто пялилась широко открытыми от ужаса глазами. Если вы пока только привыкаете к сообщениям об ошибках, ознакомьтесь с советами Ники Мейлеман о том, как научиться их понимать.

2. Изменяйте только одну вещь за раз

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

Для проверки того, как изменения работают в различных тестовых случаях, будут полезны автоматизированные тесты. Они также гарантируют, что вы по незнанию не нарушите уже существующие тестовые случаи, которые ранее были пройдены.

3. Проверьте все свои допущения

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

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

4. Для подтверждения допущений и проверки потенциальных решений полагайтесь на тесты

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

При таком подходе исключается ситуация, когда вы создаете слишком большую часть функционала без тестирования на работоспособность.

В Git также есть команда git bisect, которую можно использовать для быстрого поиска проблемного коммита. Эта функция Git применяет двоичный поиск. Вы указываете, какой коммит является «плохим» («bad»), т. е., точно содержащим баг, и «хорошим» (точно НЕ содержащим баг). Затем Git выбирает между этими двумя коммитами промежуточный и спрашивает, является ли он «плохим» или «хорошим». Постепенно диапазон поисков сужается, и вы находите проблемный коммит.

А чтобы сделать процесс выявления проблемных коммитов еще более эффективным, git bisect можно скомбинировать с автоматическим тестированием.

Photo by Mark König on Unsplash

5. Изучите ваш код построчно

Попробуйте прочитать его свежим взглядом, даже если для этого потребуется пятиминутный перерыв в работе. Бывает, бьешься, бьешься над проблемой — и все безуспешно. А потом переспишь с ней, и наутро все уже гораздо понятнее. Меня это постоянно поражает.

В общем, даже если вы не сидите, глядя в экран, ваш мозг продолжает искать решение.

6. Посмотрите исходный код стороннего пакета

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

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

7. Google — ваш лучший друг

Быстрый поиск может стать лучшим другом разработчика. Допустим, вы используете новую функцию или пакет. Можете ли вы найти пример, где это работает? Если вы хотите увидеть код, использующий же API, в контексте, рекомендую поискать в вашем локальном репозитории. Или можете поискать репозитории с открытым кодом при помощи grep.app.

8. Звонок другу

Советую интегрировать git blame в вашу среду разработки. Я использую плагин Git lens, который показывает, кто является автором определенных изменений файлов, прямо в этих файлах в редакторе кода. Также этот плагин показывает связанный пул-реквест, что может быть полезно для быстрого получения большего контекста относительно решений (вы можете просмотреть этот пул-реквест или напрямую обратиться к его автору).

Эффективным способом отладки и обмена знаниями может быть парное программирование. Я уже упомянула о «волшебном» нахождении решений после сна или перерыва. Есть еще один полезный прием: «утиный дебаггинг». Суть его в том, что простое объяснение проблемы кому-то другому (даже неодушевленной резиновой уточке) может помочь сделать решение более очевидным.

Разобравшись с ошибкой, не забудьте задокументировать полученные знания. Даже если это будет всего лишь небольшая заметка для себя на будущее.

[customscript]techrocks_custom_after_post_html[/customscript]

[customscript]techrocks_custom_script[/customscript]

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх