Программы с кодами исправляющие ошибки

Перевод публикуется с сокращениями, автор

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

IDLE (Integrated Development and Learning Environment) – кроссплатформенная интегрированная среда разработки и обучения для Python, созданная Гвидо ван Россумом.

Отладка программы призвана выискивать «вредителей» кода и устранять их. За это отвечают отладчик и журналирование для вывода сведений о программе.

В предыдущей части мы рассмотрели исходный код и его составляющие.

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

Программы с кодами исправляющие ошибки

Это часто вызвано ошибками, известными как дефекты или исключительные ситуации во время выполнения. Акт обнаружения и удаления ошибок из нашего кода – это отладка программы. Вы лучше разберетесь в отладке на практике, используя ее как можно чаще. Мы не только отлаживаем собственный код, но и порой дебажим написанное другими программистами.

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

Программы с кодами исправляющие ошибки

Синтаксические ошибки

Эти эрроры не позволяют скомпилировать исходный код на компилируемых языках программирования. Они обнаруживаются во время компиляции или интерпретации исходного кода. Они также могут быть легко обнаружены статическими анализаторами (линтами). Подробнее о линтах мы узнаем немного позже.

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

Семантические ошибки

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

Рассмотрим данный пример:

3 + 5 * 6

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

3 + 5, заключенные в скобки, дадут желаемый результат, а именно 48.

Ошибки в процессе выполнения

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

Вот хороший пример:

input = 25
x = 0.8/(Math.sqrt(input) — 5)

Фрагмент кода выше будет скомпилирован успешно, но input 25 приведет к ZeroDivisionError. Это ошибка во время выполнения. Другим популярным примером является StackOverflowError или IndexOutofBoundError. Важно то, что вы идентифицируете эти ошибки и узнаете, как с ними бороться.

Существуют ошибки, связанные с тем, как ваш исходный код использует память и пространство на платформе или в среде, в которой он запущен. Они также являются ошибками во время выполнения. Такие ошибки, как OutOfMemoryErrorand и HeapError обычно вызваны тем, что ваш исходный код использует слишком много ресурсов. Хорошее знание алгоритмов поможет написать код, который лучше использует ресурсы. В этом и заключается отладка программы.

Процесс перезаписи кода для повышения производительности называется оптимизацией. Менее популярное наименование процесса – рефакторинг. Поскольку вы тратите больше времени на кодинг, то должны иметь это в виду.

Отладка программы

Вот несколько советов о том, как правильно выполнять отладку:

  • Использовать Linters. Linters – это инструменты, которые помогают считывать исходный код, чтобы проверить, соответствует ли он ожидаемому стандарту на выбранном языке программирования. Существуют линты для многих языков.
  • Превалирование IDE над простыми редакторами. Вы можете выбрать IDE, разработанную для языка, который изучаете. IDE – это интегрированные среды разработки. Они созданы для написания, отладки, компиляции и запуска кода. Jetbrains создают отличные IDE, такие как Webstorm и IntelliJ. Также есть NetBeans, Komodo, Qt, Android Studio, XCode (поставляется с Mac), etc.
  • Чтение кода вслух. Это полезно, когда вы ищете семантическую ошибку. Читая свой код вслух, есть большая вероятность, что вы зачитаете и ошибку.
  • Чтение логов. Когда компилятор отмечает Error, обязательно посмотрите, где он находится.

Двигаемся дальше

Поздравляем! Слово «ошибка» уже привычно для вас, равно как и «отладка программы». В качестве новичка вы можете изучать кодинг по книгам, онлайн-урокам или видео. И даже чужой код вам теперь не страшен 🙂

В процессе кодинга измените что-нибудь, чтобы понять, как он работает. Но будьте уверены в том, что сами написали.

Викторина

input = Hippo’
if input == ‘Hippo’:
print ‘Hello, Hippo’

Ответы на вопросы

2. Синтаксическая ошибка: Отсутствует стартовая кавычка в первой строке.

Все мы знаем про стандарты оформления кода в PHP сообществе и пытаемся им следовать. Несмотря на это, мы все люди и допускаем ошибки. Это значит, что у нас есть несколько вариантов решения данной проблемы:

1) Править все ошибки стиля вручную.

2) Использовать плагины для IDE или другие инструменты для запуска в терминале.

Эти два варианта не те, которые я хотел бы использовать. На самом деле есть еще один вариант — все автоматизировать. Я буду использовать Git и PHP CS Fixer, но несмотря на это принципы очень просты и вы легко сможете применить их к вашему языку программирования и системе контроля версий. Продолжайте читать, чтобы избавиться от рутины и стать более продуктивным разработчиком.

Почему не первые два варианта?

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

— Рутина. Представьте, что вы правите ошибки оформления кода день за днем. Разве вам не хотелось бы заняться чем-то более интересным? Уверен, что хотелось бы!

— Трата времени. Прочитайте пункт выше.

— Отсутствие постоянства. Вы хотите исключить все ошибки оформления кода из вашего проекта, верно? Если же вы делаете проверку стиля вручную, время от времени, то все это со временем приведет к дополнительным комитам в Git, содержащим только исправления форматирования кода. Это будет выглядеть плохо:

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

Еще один момент: это также усложнит code review и сделает его менее продуктивным. Вместо того, чтобы сфокусироваться на серьезных и важных частях кода из pull request’а, ревьювер будет отвлекаться на посторонний шум — правки по стилю кода.

Плагины для IDE

Данный подход не так плох как первый, но:

— Плагина для вашего IDE может и не быть.

— Вам понадобится настроить ваше IDE таким образом, чтобы оно запускало PHP CS fixer при каждом соханении файла. Только таким образом вы добьетесь постоянства. Если же ваше IDE такого не умеет, значит вам не повезло.

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

Именно поэтому мы должны решить проблему постоянного мониторинга и исправления ошибок оформления кода на самом низком уровне, который не зависит от IDE и подойдет всем.

Запуск инструментов в терминале

Если вам не повезло с IDE, тогда данный вариант скорее всего тот, с которым вам прийдется иметь дело. Тем не менее, он также имеет недостатки:

— Отсутствие постоянства. Снова, вы должны не забывать запускать PHP CS fixer вручную в терминале.

— Трата времени. Представьте себе следующую ситуацию: вы добавили несколько файлов в staging область в Git. Затем вы вспомнили, что еще не запускали исправление оформления кода. Вы запускаете его и исправленные версии ваших файлов появляются в working области. Вам снова необходимо делать git add.

Автоматизация

Я хочу описать пару простых шагов, которые улучшат картину в целом. Если вы все еще страдаете от использования SVN, советую прочитать Git-SVN bridge.

Чтобы следовать принятым соглашениям, необходимо выполнить следующие шаги:

1) Проверять и исправлять ошибки в оформлении кода на клиенте еще до того, как он сделает комит и тем более до того, как код попадет в главный репозиторий.

2) Т.к. мы не можем доверять проверкам на клиенте, нам также потребуется настроить дополнительные проверки на стороне сервера.

В этот раз я опишу реализацию только первого шага.

Автоматизация на клиенте

Я использую PHP в моих проектах, поэтому буду использовать соответствующие инструменты по проверке оформления кода. Вы же можете адаптировать все под себя.

В PHP среде у нас есть отличный инструмент — PHP Coding Standards Fixer. Он позволяет вам проверять ваш код на наличие ошибок или даже исправлять их. Т.к. нашей целью является автоматизация исправления подобных ошибок, то и fixer мы будем использовать в соответствующем режиме.

Git pre-commit хук

В Git мы имеем pre-commit хук. Как можно догадаться из его названия, его основная цель предельно проста: запустить данный файл перед окончательным подтверждением комита. Если данный хук вернет 0, то комит будет разрешен, если 1 — комит будет запрещен.

Все хуки находятся в папке .git/hooks в корневой папке вашего проекта. Там вы можете найти файлы с расширением *.sample и ознакомиться с примерами. Все что нам сейчас необходимо — это создать pre-commit файл или же переименовать pre-commit.sample в pre-commit. После этого Git будет запускать его каждый раз, когда вы будете делать комит.

Отлично! Давайте более подробно опишем наши требования к самой автоматизации.

Требования к автоматизации

Если вы не знакомы с состояниями файлов в Git, советую прочитать The Three States in Git.

Читать также:  Часть программы или маленькая отдельная программа для решения проблем с программным обеспечением 4 буквы, а также отдельная система для решения проблем с программами

1) В первую очередь, я не хочу чтобы fixer каждый раз обрабатывал все файлы в моем проекте. Необходимо чтобы он анализировал и правил только те файлы, которые добавлены в staging область и будут в комите. Это ускорит процесс.

2) Очевидное: fixer должен именно исправлять ошибки, а не показывать их.

3) После исправлений файлы должны быть автоматически добавлены в staging area.

Если файлы из staging области исправлены fixer’ом, то их исправленные версии попадут в working directory. Если мы их не добавим опять в staging область, то в комите получим старую версию файлов без исправлений.

Именно поэтому процесс автоматизации должен уметь добавлять исправленные файлы обратно в staging область. Таким образом мы будем уверенны, что в комите только валидные файлы и не будем тратить на это свое время.

4) Какие бы файлы не были добавлены в комит, fixer должен проверять только *.php файлы, т.к. нет смысла проверять файлы с другими расширениями.

5) Необходима возможность использовать конфигурационный файл для fixer’а без исправления кода в pre-commit хуке.

Хорошо, требования сформированы, давайте реализуем их.

Файл. git/hooks/pre-commit

Это все! Теперь каждый раз перед комитом Git будет запускать pre-commit файл и все ошибки относящиеся к  оформлению кода будут исправлены на клиенте автоматически.

Не забудьте выставить права на файл:

Тестируем PHP CS Fixer

Для теста создадим несколько файлов:

1) with-issues.php (этот файл мы добавим в комит).

2) unstaged.php (этот оставим в working directory).

3) test.txt (текстовый файл нужен нам для того чтобы проверить, что fixer игнорирует их).

Файлы созданы. Давайте добавим пару из них в staging область:

  • git add with
  • git add test

Если выполнить git status, то мы увидим:

  • to be committed
  • what will be committed

Как мы видим, только два файла будут добавлены в комит. Давайте закомитим их:

  • were added to the commit after fixes
  • automated code style check

Из этого следует, что наши файлы были добавлены в комит, при этом PHP fixer исправил только один из них, с расширением .php. Также хочу обратить ваше внимание на то, что fixer не проверил unstaged.php файл т.к. мы его не добавлили в staging область. Это именно то, что нам нужно.

Если выполнить git status еще раз, вы увидите, что unstaged.php по прежнему там.

Давайте посмотрим файл with-issues.php и убедимся, что fixer исправил его:

Как мы видим, все в порядке. Еще один момент, который мы не проверили — использование конфиг файла для fixer’а.

Кастомный конфиг файл

PHP Coding Standards Fixer по умолчанию пытается найти .php_cs файл в корневой папке вашего проекта. Если вы хотите использовать кастомный конфиг файл, то просто добавьте его и напишите в нем ваши настройки. Файл должен вернуть SymfonyCSConfigInterface интерфейс.

Важно

Вы не можете хранить pre-commit файл в репозитории (он не передастся при git clone), поэтому вам необходимо убедиться, что он есть у всех членов вашей команды.

Выводы

Как вы видите, реализация задуманного весьма проста. Это сохранит ваше время, сделает жизнь немного лучше и историю комитов в Git более красивой. Надеюсь данная небольшая статья поможет вам автоматизировать валидацию и исправление ошибок оформления кода в вашем собственном проекте. Используя данный хук вы не будете отвлекаться на ненужный шум, а вместо этого сможете сфокусироваться на более значимых вещах при code review.

Искать ошибки в программах — непростая задача. Здесь нет никаких готовых методик или рецептов успеха. Можно даже сказать, что это — искусство. Тем не менее есть общие советы, которые помогут вам при поиске. В статье описаны основные шаги, которые стоит предпринять, если ваша программа работает некорректно.

Занесите ошибку в трекер

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

  • Вы забыли какую-то важную деталь об ошибке, например, в чем она заключалась.
  • Вы могли делегировать ее кому-то более опытному.

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

Вы должны записать в трекер следующую информацию:

  • Что делал пользователь.
  • Что он ожидал увидеть.
  • Что случилось на самом деле.

Это должно подсказать, как воспроизвести ошибку. Если вы не сможете воспроизвести ее в любое время, ваши шансы исправить ошибку стремятся к нулю.

Поищите сообщение об ошибке в сети

Если у вас есть сообщение об ошибке, то вам повезло. Или оно будет достаточно информативным, чтобы вы поняли, где и в чем заключается ошибка, или у вас будет готовый запрос для поиска в сети. Не повезло? Тогда переходите к следующему шагу.

Найдите строку, в которой проявляется ошибка

Если ошибка вызывает падение программы, попробуйте запустить её в IDE под отладчиком и посмотрите, на какой строчке кода она остановится. Совершенно необязательно, что ошибка будет именно в этой строке (см. следующий шаг), но, по крайней мере, это может дать вам информацию о природе бага.

Найдите точную строку, в которой появилась ошибка

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

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

Выясните природу ошибки

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

  • Ошибка на единицу
    Вы начали цикл for с единицы вместо нуля или наоборот. Или, например, подумали, что метод .count() или .length() вернул индекс последнего элемента. Проверьте документацию к языку, чтобы убедиться, что нумерация массивов начинается с нуля или с единицы. Эта ошибка иногда проявляется в виде исключения Index out of range.
  • Состояние гонки
    Ваш процесс или поток пытается использовать результат выполнения дочернего до того, как тот завершил свою работу. Ищите использование sleep() в коде. Возможно, на мощной машине дочерний поток выполняется за миллисекунду, а на менее производительной системе происходят задержки. Используйте правильные способы синхронизации многопоточного кода: мьютексы, семафоры, события и т. д.
  • Неожиданный null
    Бьюсь об заклад, вы не раз получали ошибку с неинициализированной переменной. Убедитесь, что вы проверяете ссылки на null, особенно при обращении к свойствам по цепочке. Также проверьте случаи, когда возвращаемое из базы данных значение NULL представлено особым типом.
  • Некорректные входные данные
    Вы проверяете вводимые данные? Вы точно не пытаетесь провести арифметические операции с введенными пользователем строками?
  • Присваивание вместо сравнения
    Убедитесь, что вы не написали = вместо ==, особенно в C-подобных языках.
  • Ошибка округления
    Это случается, когда вы используете целое вместо Decimal, или float для денежных сумм, или слишком короткое целое (например, пытаетесь записать число большее, чем 2147483647, в 32-битное целое). Кроме того, может случиться так, что ошибка округления проявляется не сразу, а накапливается со временем (т. н. Эффект бабочки).
  • Переполнение буфера и выход за пределы массива
    Проблема номер один в компьютерной безопасности. Вы выделяете память меньшего объема, чем записываемые туда данные. Или пытаетесь обратиться к элементу за пределами массива.
  • Программисты не умеют считать
    Вы используете некорректную формулу. Проверьте, что вы не используете целочисленное деление вместо взятия остатка, или знаете, как перевести рациональную дробь в десятичную и т. д.
  • Конкатенация строки и числа
    Вы ожидаете конкатенации двух строк, но одно из значений — число, и компилятор пытается произвести арифметические вычисления. Попробуйте явно приводить каждое значение к строке.
  • 33 символа в varchar(32)
    Проверяйте данные, передаваемые в INSERT, на совпадение типов. Некоторые БД выбрасывают исключения (как и должны делать), некоторые просто обрезают строку (как MySQL). Недавно я столкнулся с такой ошибкой: программист забыл убрать кавычки из строки перед вставкой в базу данных, и длина строки превысила допустимую как раз на два символа. На поиск бага ушло много времени, потому что заметить две маленькие кавычки было сложно.
  • Некорректное состояние
    Вы пытаетесь выполнить запрос при закрытом соединении или пытаетесь вставить запись в таблицу прежде, чем обновили таблицы, от которых она зависит.
  • Особенности вашей системы, которых нет у пользователя
    Например: в тестовой БД между ID заказа и адресом отношение 1:1, и вы программировали, исходя из этого предположения. Но в работе выясняется, что заказы могут отправляться на один и тот же адрес, и, таким образом, у вас отношение 1:многим.

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

Метод исключения

Если вы не можете найти строку с ошибкой, попробуйте или отключать (комментировать) блоки кода до тех пор, пока ошибка не пропадет, или, используя фреймворк для юнит-тестов, изолируйте отдельные методы и вызывайте их с теми же параметрами, что и в реальном коде.

Читать также:  Назовите типы ошибок которые могут возникнуть в программе

Логгируйте все подряд и анализируйте журнал

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

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

Исключите влияние железа или платформы

Замените оперативную память, жесткие диски, поменяйте сервер или рабочую станцию. Установите обновления, удалите обновления. Если ошибка пропадет, то причиной было железо, ОС или среда. Вы можете по желанию попробовать этот шаг раньше, так как неполадки в железе часто маскируют ошибки в ПО.

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

Ради интереса, переключите кабель питания в другую розетку или к другому ИБП. Безумно? Почему бы не попробовать?

Если у вас возникает одна и та же ошибка вне зависимости от среды, то она в вашем коде.

Обратите внимание на совпадения

  • Ошибка появляется всегда в одно и то же время? Проверьте задачи, выполняющиеся по расписанию.
  • Ошибка всегда проявляется вместе с чем-то еще, насколько абсурдной ни была бы эта связь? Обращайте внимание на каждую деталь. На каждую. Например, проявляется ли ошибка, когда включен кондиционер? Возможно, из-за этого падает напряжение в сети, что вызывает странные эффекты в железе.
  • Есть ли что-то общее у пользователей программы, даже не связанное с ПО? Например, географическое положение (так был найден легендарный баг с письмом за 500 миль).
  • Ошибка проявляется, когда другой процесс забирает достаточно большое количество памяти или ресурсов процессора? (Я однажды нашел в этом причину раздражающей проблемы «no trusted connection» с SQL-сервером).

Обратитесь в техподдержку

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

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

Полезные советы (когда ничего не помогает)

  • Позовите кого-нибудь еще.
    Попросите коллегу поискать ошибку вместе с вами. Возможно, он заметит что-то, что вы упустили. Это можно сделать на любом этапе.
  • Внимательно просмотрите код.
    Я часто нахожу ошибку, просто спокойно просматривая код с начала и прокручивая его в голове.
  • Рассмотрите случаи, когда код работает, и сравните их с неработающими.
    Недавно я обнаружил ошибку, заключавшуюся в том, что когда вводимые данные в XML-формате содержали строку xsi:type=’xs:string’, все ломалось, но если этой строки не было, все работало корректно. Оказалось, что дополнительный атрибут ломал механизм десериализации.
  • Идите спать.
    Не бойтесь идти домой до того, как исправите ошибку. Ваши способности обратно пропорциональны вашей усталости. Вы просто потратите время и измотаете себя.
  • Сделайте творческий перерыв.
    Творческий перерыв — это когда вы отвлекаетесь от задачи и переключаете внимание на другие вещи. Вы, возможно, замечали, что лучшие идеи приходят в голову в душе или по пути домой. Смена контекста иногда помогает. Сходите пообедать, посмотрите фильм, полистайте интернет или займитесь другой проблемой.
  • Закройте глаза на некоторые симптомы и сообщения и попробуйте сначала.
    Некоторые баги могут влиять друг на друга. Драйвер для dial-up соединения в Windows 95 мог сообщать, что канал занят, при том что вы могли отчетливо слышать звук соединяющегося модема. Если вам приходится держать в голове слишком много симптомов, попробуйте сконцентрироваться только на одном. Исправьте или найдите его причину и переходите к следующему.

Что вам точно не поможет

  • Паника
    Не надо сразу палить из пушки по воробьям. Некоторые менеджеры начинают паниковать и сразу откатываться, перезагружать сервера и т. п. в надежде, что что-нибудь из этого исправит проблему. Это никогда не работает. Кроме того, это создает еще больше хаоса и увеличивает время, необходимое для поиска ошибки. Делайте только один шаг за раз. Изучите результат. Обдумайте его, а затем переходите к следующей гипотезе.
  • «Хелп, плиииз!»
    Когда вы обращаетесь на форум за советом, вы как минимум должны уже выполнить шаг 3. Никто не захочет или не сможет вам помочь, если вы не предоставите подробное описание проблемы, включая информацию об ОС, железе и участок проблемного кода. Создавайте тему только тогда, когда можете все подробно описать, и придумайте информативное название для нее.
  • Переход на личности
    Если вы думаете, что в ошибке виноват кто-то другой, постарайтесь по крайней мере говорить с ним вежливо. Оскорбления, крики и паника не помогут человеку решить проблему. Даже если у вас в команде не в почете демократия, крики и применение грубой силы не заставят исправления магическим образом появиться.

Ошибка, которую я недавно исправил

Это была загадочная проблема с дублирующимися именами генерируемых файлов. Дальнейшая проверка показала, что у файлов различное содержание. Это было странно, поскольку имена файлов включали дату и время создания в формате yyMMddhhmmss. Шаг 9, совпадения: первый файл был создан в полпятого утра, дубликат генерировался в полпятого вечера того же дня. Совпадение? Нет, поскольку hh в строке формата — это 12-часовой формат времени. Вот оно что! Поменял формат на yyMMddHHmmss, и ошибка исчезла.

Перевод статьи «How to fix bugs, step by step»

Определение ошибки и исправление

Как мы уже выяснили – на каждой итерации цикла new_word
перезаписывается следующим символом в строке «hello» и подчеркиванием.
Поскольку внутри цикла есть только одна строка кода, проблема должна быть именно
там:

Код указывает Python получить следующий символ word,
прикрепить подчеркивание и назначить новую строку переменной new_word. Это
именно то неверное поведение, которое мы наблюдали.

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

You can only toggle the debugger when
idle

Всегда нажимайте кнопку Go или Quit, когда заканчиваете отладку,
иначе могут возникнуть проблемы с ее повторным запуском.

Кнопка Step

Нажмите Step и окно отладки будет выглядеть
следующим образом:

Программы с кодами исправляющие ошибки

Обратите внимание на два отличия. Во-первых, сообщение на
панели стека изменилось:

На этом этапе выполняется line 1 и отладчик останавливается перед
выполнением line 2.

Во-вторых – новая переменная i со значением 1 на панели Locals. Цикл for в line 1
создал переменную и присвоил ей это значение.

Здесь важно, что можно отслеживать растущие значения i и j по
мере прохождения цикла for. Это полезная фича поиска источника ошибок в коде.
Знание значения каждой переменной в каждой строке кода может помочь точно
определить проблемную зону.

Альтернативные способы поиска ошибок

Использование отладчика может быть сложным и трудоемким, но
это самый надежный способ найти ошибки в коде. Однако отладчики не всегда есть в наличии. В подобных ситуациях можно использовать print debugging для поиска
ошибок в коде. задействует функцию print() для отображения в консоли текста, указывающего место выполнения программы и состояние
переменных.

Например, вместо отладки предыдущего примера можно добавить
следующую строку в конец цикла for:

Измененный код будет выглядеть следующим образом:

Вывод должен выглядеть так:

i = 0; new_word = h_
i = 1; new_word = e_
i = 2; new_word = l_
i = 3; new_word = l_
i = 4; new_word = o_
o_

работает, но имеет
несколько недостатков по сравнению с отладкой дебаггером. Вы должны запускать
всю программу каждый раз, когда хотите проверить значения переменных, а также помнить про удаление вызовов функций print().

Один из способов улучшить наш цикл – перебирать символы в
word:

def add_underscores(word):
new_word = «_»
for letter in word:
new_word = new_word + letter + «_»
return new_word

Over и Out

Кнопка Over работает, как сочетание Step и Go – она
перешагивает через функцию или цикл. Другими словами, если вы собираетесь попасть
в функцию с помощью отладчика, можно и не запускать код этой функции – кнопка
Over приведет непосредственно к результату ее выполнения.

Аналогично если вы уже находитесь внутри функции или цикла –
кнопка Out выполняет оставшийся код внутри тела функции или цикла, а затем
останавливается.

В следующем разделе мы изучим некоторые ошибки и узнаем, как
их исправить с помощью IDLE.

Предположение

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

Обратите внимание, что программа разделена на два раздела:
определение функции add_underscores() и основной блок, определяющий переменную
со значением «hello» и выводящий результат.

Посмотрим на основной раздел:

phrase = «hello»
print(add_underscores(phrase))

Очевидно, что здесь все хорошо и проблема должна быть в
определении функции:

Первая строка создает переменную new_word со значением «_». Промах,
проблема находится где-то в теле цикла for.

Обзор окна управления отладкой

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

Сохраните все, откройте окно отладки и нажмите клавишу F5 –
выполнение не завершилось.

Окно отладки будет выглядеть следующим образом:

Программы с кодами исправляющие ошибки

Обратите внимание, что панель в верхней части окна содержит сообщение:

Расшифруем: код for i in range(1, 4): еще не запущен, а ‘__main__’.module() сообщает, что в данный момент мы находимся в
основном разделе программы, а не в определении функции.

Читать также:  Программа сопровождения и их проблемы

Ниже панели стека находится панель Locals, в которой
перечислены непонятные вещи: __annotations__, __builtins__, __doc__ и т. д. – это
внутренние системные переменные, которые пока можно игнорировать. По мере
выполнения программы переменные, объявленные в коде и отображаемые в этом окне,
помогут в отслеживании их значений.

В левом верхнем углу окна расположены пять кнопок:
Go, Step, Over, Out и Quit – они управляют перемещением отладчика по коду.

В следующих разделах вы узнаете, что делает каждая из
этих кнопок.

Борьба с багами

Взглянем на «

Следующий код определяет функцию add_underscores(), принимающую
в качестве аргумента строковый объект и возвращающую новую строку – копию слова с каждым символом, окруженным подчеркиванием. Например,
add_underscores(«python») вернет «_p_y_t_h_o_n_».

Вот неработающий код:

Введите этот код в редактор, сохраните и нажмите F5.
Ожидаемый результат – _h_e_l_l_o_, но вместо этого выведется o_.

Если вы нашли, в чем проблема, не исправляйте ее. Наша цель – научиться
использовать для этого IDLE.

Рассмотрим 4 этапа поиска бага:

  • предположите, где может быть ошибка;
  • установите точку останова и проверьте код по строке за раз;
  • определите строку и внесите изменения;
  • повторяйте шаги 1-3, пока код не заработает.

Используйте окно управления отладкой

если отладка отсутствует в строке меню, убедитесь, что интерактивное окно находится
в фокусе.

Точка останова

Определив, где может быть ошибка, установите точку
останова в начале цикла for, чтобы проследить за происходящим внутри кода:

Программы с кодами исправляющие ошибки

Запустим. Выполнение останавливается на строке с определением
функции.

Нажмите кнопку Go, чтобы выполнить код до точки останова:

Программы с кодами исправляющие ошибки

Код останавливается перед циклом for в функции
add_underscores(). Обратите внимание, что на панели Locals отображаются две
локальные переменные – word со значением «hello», и new_word со значением «_»,

Программы с кодами исправляющие ошибки

Переменная i – это счетчик для цикла for, который можно
использовать, чтобы отслеживать активную на данный момент итерацию.

Нажмите кнопку Step еще раз и посмотрите на панель Locals –
переменная new_word приняла значение «h_»:

Программы с кодами исправляющие ошибки

Это неправильно т. к. сначала в new_word было значение «_», на
второй итерации цикла for в ней должно быть «_h_». Если нажать Step еще
несколько раз, то увидим, что в new_word попадает значение e_, затем l_ и так
далее.

Быстрые исправления

ReSharper предоставляет более 1200 автоматических исправлений, которые помогают мгновенно устранять большинство обнаруженных проблем в коде на C#, VB.NET, XAML, ASP.NET, JavaScript, TypeScript и других поддерживаемых языках. Чтобы применить быстрое исправление, просто нажмите Alt + Enter на строке с подсвеченной проблемой и выберите наиболее подходящий способ исправить ошибку или улучшить код.

Программы с кодами исправляющие ошибки

Применение быстрых исправлений

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

Программы с кодами исправляющие ошибки

(для ошибок) или желтой

Программы с кодами исправляющие ошибки

Программы с кодами исправляющие ошибки

Глобальные исправления

Некоторые быстрые исправления (Remove unused directives, Make field read-only, Remove redundant cast, и др.) могут находить и мгновенно устранять проблемы в текущем файле, проекте или даже во всем решении.

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

Программы с кодами исправляющие ошибки

Исправление неразрешенных символов

Для ошибок, вызванных ссылками на неразрешенные символы, ReSharper предлагает целый ряд быстрых исправлений, например:

Программы с кодами исправляющие ошибки

Интерактивные быстрые исправления

Программы с кодами исправляющие ошибки

Быстрые исправления vs. контекстные действия

В ReSharper есть контекстные действия, которые отображаются в том же раскрывающемся списке, что и быстрые исправления.

Разница проста: ReSharper предлагает быстрые исправления только для подсвеченных проблем с целью их устранения, в то время как контекстные действия представляют собой мини-рефакторинги, которые всегда доступны в раскрывающемся меню по нажатию Alt + Enter.

Программы с кодами исправляющие ошибки

Пользовательские быстрые исправления

В ReSharper есть функция Structural Search and Replace, которая позволяет найти код, соответствующий определенному паттерну, и при необходимости заменить его кодом, соответствующим другому паттерну. Более того, ReSharper может вести непрерывный мониторинг решения на предмет заданных паттернов поиска, подсвечивать код, соответствующий паттерну, и предлагать быстрые исправления для замены кода в соответствии с паттернами замены.

Программы с кодами исправляющие ошибки

Интерполяция строк

Долгие годы использование метода String.Format и других методов, поддерживающих составное форматирование, было единственным способом встраивания значений переменных C# в строковые литералы. Доступная с версии C# 6.0 интерполяция строк предоставляет более понятный и удобный синтаксис. Благодаря быстрому исправлению заменить составное форматирование на интерполяцию строк можно всего за пару нажатий.

Программы с кодами исправляющие ошибки

Обработка возможных исключений NullReferenceException

При обнаружении вызова метода для объекта с возможным значением null, что может привести к исключению System.NullReferenceException, ReSharper предлагает два варианта быстрых исправлений. Традиционное исправление добавит процедуру проверки на null перед вызовом. Однако более лаконичный способ заключается в использовании оператора проверки на null .?, который был добавлен в C# 6.0 специально для обработки подобных сценариев.

Программы с кодами исправляющие ошибки

Преобразование цикла foreach в LINQ-выражение

Если вам нравится синтаксис LINQ, ReSharper поможет проверить существующие кодовые базы на наличие циклов, которые могут быть преобразованы в LINQ-выражения. Используйте автоматическое исправление, чтобы выполнить преобразование быстро и безопасно.

Программы с кодами исправляющие ошибки

Удаление избыточного создания массива

Если в метод C# может передаваться переменное число аргументов с ключевым словом params, компилятор автоматически генерирует массив аргументов, чтобы не приходилось создавать массив аргументов в вызове метода самостоятельно.

Более того, ReSharper предложит быстрое исправление, которое уберет весь избыточный код в выбранной области, включая ненужные квалификаторы, аргументы, преобразования типов, проверки условий, неиспользуемые присвоения, недостижимый код и многое другое.

Программы с кодами исправляющие ошибки

Введение необязательных параметров

Если единственная задача перегружаемой функции заключается в вызове «реализующей» функции, в которой для некоторых аргументов заданы значения по умолчанию, ReSharper помогает убрать эту перегрузку и использовать необязательные параметры в «реализующей» функции.

Программы с кодами исправляющие ошибки

Использование явного приведения внутри цикла foreach

foreach устроен так, что допускает скрытое приведение к производному типу. С одной стороны, так проще, но с другой стороны, это может привести к исключению System.InvalidCastException во время выполнения. Быстрое исправление, которое предлагает ReSharper, поможет сделать приведение явным. Это по-прежнему не безопасно, однако по крайней мере поведение больше не является скрытым.

Программы с кодами исправляющие ошибки

Указание сравнения строк

Многие быстрые исправления работают для нескольких языков. Рассмотрим пример быстрого исправления, доступного как в C#, так и в VB.NET: чтобы сделать более ясным сравнение строго двух строк, ReSharper предлагает заменить оператор равенства вызовом String.Equals(), который обрабатывает регистр символов и заставляет сравнение учитывать культурные особенности.

Программы с кодами исправляющие ошибки

Добавление условия типа (type guard)

Работать с типами объединений TypeScript бывает непросто. Например, если в значении типа объединения используется член, не являющийся общим для всех типов, компилятор выдает ошибку. В этом случае ReSharper предлагает ряд быстрых исправлений, добавляющих различные условия типа для устранения двусмысленности такого члена.

Программы с кодами исправляющие ошибки

Добавление недостающего обязательного свойства

В файлах JSON ReSharper предлагает быстрые исправления для недостающих обязательных свойств, сверяясь со сведениями обо всех обязательных свойствах, полученными из связанных схем JSON.

Программы с кодами исправляющие ошибки

Удаление компонента альфа-канала

CSS уровня 3 и ниже не поддерживает значения альфа-канала в шестнадцатеричной нотации цвета. Поэтому ReSharper предлагает вам либо заменить шестнадцатеричный цвет на RGBA или HSLA, либо просто удалить значение альфа-канала.

Точки останова и кнопка Go

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

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

Чтобы установить точку останова, щелкните правой кнопкой мыши
(Ctrl для Mac) по строке кода, на которой хотите сделать паузу, и выберите
пункт Set Breakpoint – IDLE выделит линию желтым. Чтобы удалить ее, выберите Clear
Breakpoint.

Установите точку останова в строке с оператором print(). Окно
редактора должно выглядеть так:

Программы с кодами исправляющие ошибки

Сохраните и запустите. Как и раньше, панель стека указывает, что отладчик запущен и ожидает выполнения line 1. Нажмите
кнопку Go и посмотрите, что произойдет:

Программы с кодами исправляющие ошибки

Теперь на панели стека информация о выполнении line 3:

На панели Locals мы видим, что переменные i и j имеют значения 1
и 2 соответственно. Нажмем кнопку Go и попросим отладчик запускать код до точки
останова или до конца программы. Снова нажмите Go – окно отладки теперь выглядит так:

Программы с кодами исправляющие ошибки

На панели стека отображается то же сообщение, что и раньше –
отладчик ожидает выполнения line 3. Однако значения переменных i и j теперь
равны 2 и 4. Интерактивное окно также отображает выходные данные после первого
запуска строки с помощью функции print() через цикл.

Нажмите кнопку в третий раз. Теперь i и j равны 3 и 6. Если
нажать Go еще раз, программа завершит работу.

Повторение шагов 1-3, пока ошибка не исчезнет

Сохраните изменения в программе и запустите ее снова. В окне
отладки нажмите кнопку Go, чтобы выполнить код до точки останова. Понажимайте
Step несколько раз и смотрите, что происходит с переменной new_word на каждой
итерации – все работает, как положено. Иногда необходимо повторять этот процесс
несколько раз, прежде чем исправится ошибка.

Заключение

Теперь вы знаете все об отладке с помощью DLE.
Вы можете использовать этот принцип с
различными дебагерами.

В статье мы разобрали следующие темы:

  • использование окна управления отладкой;
  • установку точки останова для глубокого понимания работы кода;
  • применение кнопок Step, Go, Over и Out;
  • четырехэтапный процессом выявления и удаления ошибок.

Не останавливайтесь в обучении и практикуйте дебаггинг – это
весело!

  • ТОП-10 книг по Python: эффективно, емко, доходчиво
  • Парсинг сайтов на Python: подробный видеокурс и программный код
  • Python + Visual Studio Code = успешная разработка
  • 29 Python-проектов, оказавших огромное влияние на разработку
  • 15 вопросов по Python: как джуниору пройти собеседование

Добавить комментарий

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