Исправить ошибку в коде программы

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

Шаг 1: Занесите ошибку в трекер

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

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

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

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

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

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

Шаг 2: Поищите сообщение об ошибке в сети

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

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

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

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

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

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

Шаг 5: Выясните природу ошибки

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

  1. Ошибка на единицу
    Вы начали цикл for с единицы вместо нуля или наоборот. Или, например, подумали, что метод .count() или .length() вернул индекс последнего элемента. Проверьте документацию к языку, чтобы убедиться, что нумерация массивов начинается с нуля или с единицы. Эта ошибка иногда проявляется в виде исключения Index out of range.
  2. Состояние гонки
    Ваш процесс или поток пытается использовать результат выполнения дочернего до того, как тот завершил свою работу. Ищите использование sleep() в коде. Возможно, на мощной машине дочерний поток выполняется за миллисекунду, а на менее производительной системе происходят задержки. Используйте правильные способы синхронизации многопоточного кода: мьютексы, семафоры, события и т. д.
  3. Неправильные настройки или константы
    Проверьте ваши конфигурационные файлы и константы. Я однажды потратил ужасные 16 часов, пытаясь понять, почему корзина на сайте с покупками виснет на стадии отправки заказа. Причина оказалась в неправильном значении в /etc/hosts, которое не позволяло приложению найти ip-адрес почтового сервера, что вызывало бесконечный цикл в попытке отправить счет заказчику.
  4. Неожиданный null
    Бьюсь об заклад, вы не раз получали ошибку с неинициализированной переменной. Убедитесь, что вы проверяете ссылки на null, особенно при обращении к свойствам по цепочке. Также проверьте случаи, когда возвращаемое из базы данных значение NULL представлено особым типом.
  5. Некорректные входные данные
    Вы проверяете вводимые данные? Вы точно не пытаетесь провести арифметические операции с введенными пользователем строками?
  6. Присваивание вместо сравнения
    Убедитесь, что вы не написали = вместо ==, особенно в C-подобных языках.
  7. Ошибка округления
    Это случается, когда вы используете целое вместо Decimal, или float для денежных сумм, или слишком короткое целое (например, пытаетесь записать число большее, чем 2147483647, в 32-битное целое). Кроме того, может случиться так, что ошибка округления проявляется не сразу, а накапливается со временем (т. н. Эффект бабочки).
  8. Переполнение буфера и выход за пределы массива
    Проблема номер один в компьютерной безопасности. Вы выделяете память меньшего объема, чем записываемые туда данные. Или пытаетесь обратиться к элементу за пределами массива.
  9. Программисты не умеют считать
    Вы используете некорректную формулу. Проверьте, что вы не используете целочисленное деление вместо взятия остатка, или знаете, как перевести рациональную дробь в десятичную и т. д.
  10. Конкатенация строки и числа
    Вы ожидаете конкатенации двух строк, но одно из значений — число, и компилятор пытается произвести арифметические вычисления. Попробуйте явно приводить каждое значение к строке.
  11. 33 символа в varchar(32)
    Проверяйте данные, передаваемые в INSERT, на совпадение типов. Некоторые БД выбрасывают исключения (как и должны делать), некоторые просто обрезают строку (как MySQL). Недавно я столкнулся с такой ошибкой: программист забыл убрать кавычки из строки перед вставкой в базу данных, и длина строки превысила допустимую как раз на два символа. На поиск бага ушло много времени, потому что заметить две маленькие кавычки было сложно.
  12. Некорректное состояние
    Вы пытаетесь выполнить запрос при закрытом соединении или пытаетесь вставить запись в таблицу прежде, чем обновили таблицы, от которых она зависит.
  13. Особенности вашей системы, которых нет у пользователя
    Например: в тестовой БД между ID заказа и адресом отношение 1:1, и вы программировали, исходя из этого предположения. Но в работе выясняется, что заказы могут отправляться на один и тот же адрес, и, таким образом, у вас отношение 1:многим.

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

Шаг 6: Метод исключения

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

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

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

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

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

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

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

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

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

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

Шаг 9: Обратите внимание на совпадения

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

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

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

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

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

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

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

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

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

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

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

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

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

Быстрые исправления ошибок в ReSharper

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

Там, где можно применить быстрое исправление, появляется значок красной (для ошибок) или желтой (для предупреждений, предложений и подсказок) лампочки, который загорается слева от подсвеченнной строки кода при перемещении курсора на нее. Кликните на лампочку или нажмите Alt + Enter, чтобы просмотреть список доступных исправлений для ошибки. Просто выберите нужное исправление из списка, и проблема будет решена.

Применение быстрых исправлений ReSharper в более широкой области (в файле, проекте, по всему решению)

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

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

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

Быстрые исправления действия ReSharper для неразрешенных символов

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

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

  • Если символ существует в некотором пространстве имен, на которое есть ссылка в любом месте вашего решения, ReSharper предложит импортировать все отсутствующие пространства имен в файл.
  • С помощью набора быстрых исправлений Create… вы сможете быстро сгенерировать различные объявления символа в соответствии с контекстом использования.
  • Еще один способ решить эту проблему — опция Find this type on nuget.org…. Откроется NuGet Browser, который поможет найти и установить отсутствующий пакет NuGet.

Быстрые исправления ошибок в ReSharper

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

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

Когда ReSharper выделяет обязательные поля ввода красной рамкой, вы можете принять предложенное значение или изменить его, а затем нажать Tab или Enter, чтобы перейти к следующей позиции ввода, или нажать Shift + Tab для возвращения к предыдущей позиции. Как только вы закончите с последним полем ввода, курсор вернется в обычный режим.

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

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

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

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

Подсветка кода, соответствующего паттерну поиска, и замена его другим паттерном

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

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

Быстрые исправления ошибок в ReSharper

C#: интерполяция строк Пример

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

Быстрые исправления ошибок в ReSharper

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

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

Быстрые исправления ошибок в ReSharper

C#: преобразование цикла foreach в LINQ-выражение Пример

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

Быстрые исправления ошибок в ReSharper

C#: удаление избыточного создания массива Пример

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

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

Быстрые исправления ошибок в ReSharper

C#: введение необязательных параметров Пример

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

Быстрые исправления ошибок в ReSharper

C#: использование явного приведения внутри цикла foreach Пример

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

Быстрые исправления ошибок в ReSharper

VB.NET: указание сравнения строк Пример

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

Быстрые исправления ошибок в ReSharper

TypeScript: добавление условия типа (type guard) Пример

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

Быстрые исправления ошибок в ReSharper

JSON: добавление недостающего обязательного свойства Пример

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

Быстрые исправления ошибок в ReSharper

CSS: удаление компонента альфа-канала Пример

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

Перевод публикуется с сокращениями, автор оригинальной статьи David
Amos.

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

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

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

Основным интерфейсом отладки в IDLE является специальное окно управления (Debug Control window). Открыть его
можно, выбрав в меню интерактивного окна пункт Debug→Debugger.

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

Всякий раз, когда окно отладки
открыто, интерактивное окно отображает [DEBUG ON].

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

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

        for i in range(1, 4):
    j = i * 2
    print(f"i is {i} and j is {j}")
    

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

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

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

        > '__main__'.<module>(), line 1: for i in range(1, 4):
    

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

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

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

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

Кнопка Step

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

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

        > '__main__'.<module>(), line 2: j = i * 2:
    

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

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

Продолжайте нажимать кнопку Step, чтобы пройтись по коду
строка за строкой, и наблюдайте, что происходит в окне отладчика. Когда
доберетесь до строки print(f"i is {i} and j is {j}"), сможете увидеть
вывод, отображаемый в интерактивном окне по одному фрагменту за раз.

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

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

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

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

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

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

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

        > '__main__'.<module>(), line 3: print(f"i is {i} and j is {j}")
    

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

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

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

Over и Out

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

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

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

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

Взглянем на «глючную» программу.

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

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

        def add_underscores(word):
    new_word = "_"
    for i in range(len(word)):
        new_word = word[i] + "_"
    return new_word

phrase = "hello"
print(add_underscores(phrase))
    

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

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

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

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

Шаг 1: Предположение

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

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

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

        phrase = "hello"
print(add_underscores(phrase))
    

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

        def add_underscores(word):
    new_word = "_"
    for i in range(len(word)):
        new_word = word[i] + "_"
    return new_word
    

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

Шаг 2: точка останова

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

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

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

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

Нажмите кнопку Step, чтобы войти в цикл for. Окно отладки
изменится, и новая переменная i со значением 0 отобразится на панели Locals:

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

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

🐍 Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

Шаг 3: Определение ошибки и исправление

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

        new_word = word[i] + "_"
    

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

Чтобы все починить, нужно объединить word[i] + "_"
с существующим значением new_word. Нажмите кнопку Quit в окне отладки, но не
закрывайте его. Откройте окно редактора и измените строку внутри цикла for на
следующую:

        new_word = new_word + word[i] + "_"
    

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

You can only toggle the debugger when
idle

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

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

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

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

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

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

        print(f"i = {i}; new_word = {new_word}")
    

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

        def add_underscores(word):
    new_word = "_"
    for i in range(len(word)):
        new_word = word[i] + "_"
        print(f"i = {i}; new_word = {new_word}")
    return new_word

phrase = "hello"
print(add_underscores(phrase))
    

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

        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_
    

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

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

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

Заключение

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

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

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

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

Дополнительные материалы:

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

Что делать, если в твоем тексте или коде нашли ошибку?

Время на прочтение
4 мин

Количество просмотров 6.5K

Ситуация глазами разработчика

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

Здесь мы не рассматриваем ошибки в бизнес-логике написанного кода — только ошибки на уровне интерпретатора/компилятора, из-за которых приложение «падает».

Чего НЕ нужно делать

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

А еще не нужно оправдываться. Оправдание есть у каждого (открою секрет: ревьюеру не интересно, почему ты допустил ошибку. В первую очередь это должно быть интересно тебе лично — сделай правильные выводы, чтобы такая ошибка не повторялась).

Что нужно сделать

Не нужно исправлять ошибку сразу. Проверь работоспособность всего кода. Повторю — ПРОВЕРЬ РАБОТОСПОСОБНОСТЬ. И исправь ВСЕ выловленные ошибки.

  • Пройдись по коду всеми возможными линтерами и анализаторами (линтер — это как автоматическая проверка орфографии в MS Word, только для кода). 

  • Запусти код еще раз у себя (локально, на тестовом стенде, еще как-нибудь). 

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

  • Поправь найденные ошибки.

  • Повтори все вышенаписанное еще раз.

Почему? 

Наличие ошибки — это повод задуматься о том, что код плохо протестирован самим разработчиком. А ведь прямая обязанность разработчика — это в первую очередь предоставление РАБОТОСПОСОБНОГО кода.

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

Повторяю — нужно исправлять не ошибку, а проверить работоспособность своего кода. Каждой его строчки. И убедиться, что твой код не повлиял на другой функционал.

Запомни: твой коллега-ревьюер — не линтер. В его обязанности не входит построчная проверка кода на синтаксические ошибки.

И тестировщик не линтер. 

Цель ревью — взглянуть на твое решение «свежим» взглядом или с позиции опыта и указать на моменты реализации, которые ты не учел. Но никак не поиск ошибок на уровне кода.

А задача тестировщика — проверить код на соответствие бизнес-требованиям, а также убедиться, что новый функционал не повредил стабильные узлы.

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

Вывод

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

Ревьюерам не хочется постоянно быть нянькой — им хочется выполнять СВОИ задачи, а вместо этого они отвлекаются на поиск ошибок в ТВОЕМ коде.

И это повод:

  1. Обновить свой инструментарий: обвесить свою IDE (или редактор кода) линтерами и анализаторами или настроить скрипт, который при изменениях прогонял бы код проекта через них.

  2. Подумать над средой для тестирования задач. Чтобы можно было собрать проект и «погонять» его при разных условиях. Не так глубоко, как это делают тестировщики. Но основные кейсы нужно обязательно протестировать самостоятельно. Лайфхак: спроси у коллег, как они тестируют свой код перед отправкой в ревью.

  3. При постановке задачи сформировать (с постановщиком, тестировщиком или самостоятельно) тест-кейсы. 

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

  5. Подумать о внедрении подходов и инструментов тестирования (Unit-тесты, TDD, например, если их нет) лично для себя или на уровень всего отдела.

Ситуация глазами редактора

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

Нет. 

Исправить ошибку и снова отправить на проверку. 

Да. 

Внимательно — весьма внимательно — пройтись по всему тексту и перепроверить все запятые и буквы. 

Почему? 

1 

Время принимающего текст (например, старшего редактора) для бизнеса стоит дороже. Он может либо править твои ошибки, либо делать более сложную задачу.  

2

Страдает твоя личная репутация. Неимоверно бесит два или три раза подряд отправлять текст на правку элементарных вещей. ​​

3

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

Как быть? 

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

Хитрость

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

Вывод

Пропущенная запятая — не ошибка, а сигнал о повторной тщательной проверке. 

P.S. 

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

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

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

1.Открываем

сайт

. Нажимаем “Fix you code”

Поиск и исправление ошибок в программном коде с помощью нейросети

2. Выбираем язык программирования, на котором написан ваш код. Мы будем показывать на примере Pythone.

3. Спускаемся в раздел “Error Message”. В пустое поле вводим наш код, в котором хотим найти ошибки исправить его.

4. После того, как ввели нужный нам код, необходимо нажать на кнопку “Debug”.

5. Высветился попап, в котором нас попросят ввести ключ от OpenAI. Переходим по ссылке на эту нейросеть. Если вы находитесь на территории России, вам понадобится VPN, иначе вы не сможете зарегистрироваться на данном сервисе для получения ключа. Можете использовать расширение в Chrome – “

Browsec VPN

6. Нажимаем “Log in” если у вас уже есть аккаунт в этом сервисе и авторизуемся в него. Нажимаем “Sign up”, чтобы создать новый аккаунт.

Если вы создаете новый аккаунт, используем адрес электронной почты или авторизуемся с помощью Google или Microsoft

Вводим имя и фамилию какую угодно и нажимаем “Continue”

Далее нас попросит ввести номер телефона. Если вы из России, то будем использовать

Sms-activate

. В поиске сервисов вводим “OpenAI” и покупаем любой номер, например Индонезия.

Возвращаемся на сервис и вставляем полученный номер, нажимаем “Send code via SMS”.

Ожидаем получения кода на “Sms-activate” и вставляем его. В следующем шаге на вопрос “Как вы в основном будете использовать OpenAI?” выбираем любой пункт.

7. Открылась страница для получения ключа. Чтобы сгенерировать его, нажмите на “Create new secret key”

8. Появится окно с вашим ключом, копируем его

9. Вставляем его и нажимаем “Done”

10. Нажимаем еще раз “Debug”, чтобы нейросеть начала процесс исправления.

11. Справа в разделе “Error Explanation” будет описана в чем проблема

12. В панели с кодом нейросеть предложит исправления. Чтобы исправить нажмите “Use me”

Если вы хотите узнать как написать код с помощью нейросети OpenAI, можете ознакомиться с этой статьей

Надеюсь статья была полезной для вас!

Понравилась статья? Поделить с друзьями:
  • Исправить ошибку в коде питон онлайн
  • Исправить ошибку в коде оквэд
  • Исправить ошибку в коде python онлайн
  • Исправить ошибку в карте памяти для фотоаппарата
  • Исправить ошибку в кадастровой стоимости