Как дебажить
Перейти к содержимому

Как дебажить

  • автор:

Как дебажить js в браузере

Самый популярный инструмент для отладки кода в браузере — Chrome DevTools.

Откровенно говоря, отладка кода может занимать много времени. Особенно, если использовать такие простые команды как console.log() или alert().

И на этом моменте в игру вступает Chrome DevTools, позволяя нам дебажить код без утомительных команд. С помощью этого инструмента можно легко редактировать CSS и HTML «на лету», тестировать сеть, проверять скорость сайта и даже эмулировать экран мобильных устройств для тестирования адаптивности верстки проекта.

Для запуска отладчика (на примере браузера Chrome) необходимо нажать клавишу F12, или выбрать интересующий элемент на страницы, щелкнуть по нему правой кнопкой мыши и выбрать — Inspect.

Очень хорошо раскрыт вопрос в ролике от Никиты Михайлова , из наставников Хекслета по направлению «Верстальщик».

Debug в Intellij IDEA: гайд для новичков

Java-университет

Debug в Intellij IDEA: гайд для новичков - 1

Всем привет, JavaRush сообщество. Сегодня поговорим о дебаге: что это такое и как дебажить в Intellij IDEA. Статья рассчитана на людей, у которых есть уже минимальные знания Java Core. Здесь не будет ни фреймворков, ни сложных процессов публикации библиотек. Легкая прогулка. Так что располагайтесь поудобнее — начнем!

Почему Debug тебе необходим

Debug в Intellij IDEA: гайд для новичков - 2

Давайте сразу проясним для себя: кода без багов не бывает… Так устроена жизнь. Поэтому не стоит сразу раскисать и бросать все, если код работает не так, как мы ожидали. Но что же делать? Конечно, можно наставить System.out.println везде, где только можно и потом разгребать вывод в терминале в надежде на то, что получится найти ошибку. Все-таки можно… и это делают, и делают аккуратно при помощи логирования (можно почитать об этом здесь). Но если есть возможность запустить на локальной машине код, лучше использовать Debug . Сразу хочу заметить, что в этой статье мы будем рассматривать дебаг проекта внутри Intellij IDEA. Если интересно почитать об удаленном дебаге — вот, пожалуйста, статья из нашего ресурса.

Что такое Debug

Debug в Intellij IDEA: гайд для новичков - 3

Debug — это процесс отладки (проверки) кода, когда в процессе его выполнения можно остановиться в обозначенном месте и посмотреть за ходом выполнения. Понять, в каком состоянии находится программа в определенном месте. Это точно так же, как если бы можно было остановить жизнь и посмотреть на всё со стороны. Круто, правда? Наша задача состоит в том, чтобы быстро и просто научиться проводить отладку приложений при помощи всеми нами любимой среды разработки Intellij IDEA.

Что нужно для начала отладки

Debug в Intellij IDEA: гайд для новичков - 4

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

  1. Среда разработки Intellij IDEA версии 2019.3.1 и выше. На случай, если у кого-то её нет, вот ссылка, где можно скачать. Скачивайте Community Edition, так как я буду использовать именно ее.
  2. Клонировать проект из GitHub и импортировать его через IDEA.

Открываем IDEA: Выбираем проект debug-presentation , нажимаем OK и получаем: Оставляем import project from external sources, Maven и нажимаем Finish . Импортировав проект, можем описать процесс на живом примере.

Немного теории… обещаю 😀

Чтобы начать мало-мальски дебажить, нужно понять, что такое breakPoint и разобраться в нескольких горячих клавишах, которые нужны для начала. BreakPoint — это специальный маркер, который отображает место или состояние, на котором нужно остановить приложение. Поставить breakpoint можно либо нажав левой кнопкой мыши на левую боковую панель, либо кликнув курсором по месту кода и нажав Ctrl + F8 . Breakpoint’ы бывают трех видов: метка на строку, метка на переменную и метка на метод. Выглядит это так:

  • На строку: Debug в Intellij IDEA: гайд для новичков - 6если в выражении есть лямбда, то IDEA предлагает вам выбор — поставить на всю линию или конкретно в лямбда выражение: Debug в Intellij IDEA: гайд для новичков - 7
  • На метод: Debug в Intellij IDEA: гайд для новичков - 8
  • На класс Debug в Intellij IDEA: гайд для новичков - 9

Breakpoint’ы можно удалить, выполнив те же действия, что и при их добавлении. Бывают ситуации, когда нужно сделать их неактивными (замьютить). Для этого в Debug секции, можно найти значок , который сделает все breakpoint’ы неактивными. Чтобы посмотреть, какие уже выставленные breakpoint’ы, можно или зайти в Debug в левом нижнем углу и найти иконку , или нажать Ctrl+Shift+F8 : Debug в Intellij IDEA: гайд для новичков - 12Когда зайдем в список breakpoint’ов, увидим: Debug в Intellij IDEA: гайд для новичков - 13Здесь есть два preakpoint’a:

  • Bee.java:24 — в классе Bee на 24-й строке
  • Main.java:14 — в классе Main на 14-й строке

Хочу заметить, что при клонировании проекта к себе не будет этих BreakPoint’ов: их нужно выставить самостоятельно! Также есть секция Java Exception Breakpoints . Очень полезная вещь. При помощи ее можно добавить неявный breakpoint, чтобы программа останавливалась перед выбрасыванием любого исключения или какого-то конкретного. Добавим для RuntimeException неявный breakpoint. Делается это легко: в верхнем левом углу есть плюсик “+”. Нажимаем на него и выбираем Java Exceptions Breakpoints : Debug в Intellij IDEA: гайд для новичков - 14В появившемся окне пишем имя исключения, которое нужно добавить, выбираем из предложенного списка и нажимаем OK : Debug в Intellij IDEA: гайд для новичков - 15На этом ликбез заканчиваем и переходим к практике.

Поехали, будем врываться в дебри дебага

Debug в Intellij IDEA: гайд для новичков - 16Так как я потомственный пчеловод, для презентации отладки создал проект, который описывает процесс сбора нектара пчелами, переработки нектара в мед и получение меда из улья. На основе документации README файла, который лежит в корне проекта, читаем: ожидаемое поведение — со всех цветков, с которых собирают нектар (как double значение), будет собрано количество меда, равное половине собранного нектара. В проекте есть такие классы:

  • Bee — обычная рабочая пчела;
  • BeeQueen — пчелиная матка;
  • BeeHive — улей;
  • HoneyPlant — медонос, с которого собирают мед;
  • Main — где находится public static void main() метод в котором стартует проект.

Если запустить метод main() , то окажется, что мало того, что не считается количество меда, так еще и выпадает ошибка… Debug в Intellij IDEA: гайд для новичков - 17Нужно посмотреть, что же там не так. Из стек трейса в нижнем правом углу, можем увидеть, что в HoneyPlant.java:20 , выбрасывается исключение RuntimeException: Debug в Intellij IDEA: гайд для новичков - 18Как раз наш случай: есть RuntimeException, добавим поиск такого исключения, как было описано выше, и запустим main() метод в дебаг режиме. Для этого нажмем на зеленую стрелку-треугольник в Intellij IDEA перед методом main() : Debug в Intellij IDEA: гайд для новичков - 19и получим остановленную программу в момент перед тем, как сработает исключение с таким значком Debug в Intellij IDEA: гайд для новичков - 21Чтоб получить полную информацию, нужно посмотреть в секцию Debug. В ней есть Variables , где показаны все переменные, доступные в этой части приложения:

  • nectar = 1.0;
  • nectarCapacity = -1.0.

Исключение выбрасывается справедливо, так как значение количества нектара, которое есть в медоносе, не может быть отрицательным. Но почему же так происходит? Ведь есть же проверка, что если нектар закончился, то возвращается нулевое значение в строках 15-17:

 if ( nectar == 0 )

Но загвоздка в том, что проверяет он не ту переменную… и это ошибка в коде. Вместо того, чтобы проверять значение нектара в цветке, который лежит в переменной nectarCapacity , программа проверяет значение nectar , которое приходит в метод и является тем количеством, которое хотят взять у нектара. Вот же он, первый баг! Поэтому ставим правильно и получаем выражение:

 if ( nectarCapacity == 0)

Debug в Intellij IDEA: гайд для новичков - 22

Далее, запускаем main() метод в обычном режиме (Run `Main.main()`) и ошибки больше нет, программа отработала: Приложение отработало и выдало ответ: “33.0 honey was produced by 7 bees from 2 honey plants” Все бы хорошо, но ответ неправильный… Все потому, что в документации README файле написано, что нектар переходит в мед с пропорцией 2 к 1:

 ## Documentation Presentation based on honey getting process. **Note**: 1 honey point = 2 nectar points 

Из главного метода видно, что есть два медоноса, по 30 и 40 единиц нектара соответственно, поэтому в итоге должно получиться 35 единиц мёда. А пишет, что 33. Куда же делись еще две единицы. Сейчас узнаем! Для этого нужно поставим breakpoint в методе Main.main() на строке №28, где выполняется beeHive.populateHoney() и запускаем main метод в режиме Debug: Debug в Intellij IDEA: гайд для новичков - 23Вот этот момент рассмотрим подробнее. Программа остановилась перед выполнением 28-й строки. В нижней части видим Debug секцию, в которой описана вся информация по запущенному приложению. В части Variables, как уже было сказано, есть все переменные и объекты, которые доступны из этой части приложения. В части Frames показаны шаги, которые проходит приложение, можно посмотреть на предыдущий шаг и получить все локальные данные. Чтобы программа продолжила работу, можно нажать F9 или зеленую иконку, как показано ниже: Debug в Intellij IDEA: гайд для новичков - 24Чтобы остановить программу, нужно нажать на красный квадрат: Debug в Intellij IDEA: гайд для новичков - 25Чтобы перезапустить приложение в режиме дебага, нужно нажать на стрелку: Debug в Intellij IDEA: гайд для новичков - 26Далее, чтобы проходить пошагово по работе приложения, можно использовать две клавиши:

  • F8 — идти по участку кода и не заходить во внутренние методы;
  • F7 — идти по участку кода и заходить во внутренние методы.

Поэтому нам, чтобы зайти в работу метода beeHive.populateHoney() , нужно нажать F7, и мы перейдем далее: Debug в Intellij IDEA: гайд для новичков - 27Далее, проходим в режиме дебага используя F8 по этому методу до конца и опишем, что происходит в этом методе:

  • 25-я строка — используется Stream API, чтобы собрать мед со всех пчел;
  • 26-я строка — мед суммируется уже с существующим;
  • 27-я строка — выделяется 2 единицы меда для матки;
  • 28-я строка — эти две единицы удаляются из общего количества меда;
  • 29-я строка — матка съедает этот мед.

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

 ## Documentation Presentation based on honey getting process. **Note**: * 1 honey point = 2 nectar points * 2 honey point queen bee eats every time when beehive populates the honey. 

И все:, все найденные баги починены, можем спокойно продолжать с умным видом пить кофе и читать статейки на хабре JavaRush 🙂

Подведем итог

  • работы без ошибок не бывает и дебаг — это отличный способ их решить;
  • что такое breakpoint и какой он бывает;
  • как настроить exception breakpoint;
  • как проводить навигацию в режиме дебага.

Статья для почитать

  • Проект, что используется в статье
  • IntelliJ IDEA и Debug: не дайвинг, но снорклинг
  • Горькая правда о программировании.
  • Официальная документация
  • Типы breakpoint’ов. Официальна документация
  • Как тестовое задание на собеседование превратилось в open-source библиотеку
  • Создание системы мониторинга цен на авиабилеты: пошаговое руководство [Часть 1]
  • Гайд по созданию клиента для Skyscanner API и его публикации в jCenter и Maven Central [Часть 1]
  • Логирование: что, как, где и чем?

Как дебажить PHP

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

register_shutdown_function(function() if (error_get_last())  var_export(error_get_last()); > >); 

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

Вывод данных отладки в браузере

Наиболее простой способ вывести любую переменную это функции print_r(), var_dump() и var_export()

print_r() — выводит структуру переменной в удобочитаемом виде

var_dump() — также выводит тип данных для всех переменных

var_export() — выводит структуру переменно в формате пригодным для выполнения в PHP

По умолчанию выводы этих функций используют ‘\n’ в качестве переносов на новую строку.

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

echo '
'; print_r($var); echo '

';

echo '
' . print_r($var, true) . '

';

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

echo '
'; print_r($variables['user']); var_dump($variables['user']); var_export($variables['user']); echo '

';

Array ( [id] => 3 [type] => guest ) array(2)  ["id"]=> int(3) ["type"]=> string(5) "guest" > array ( 'id' => 3, 'type' => 'guest', ) 

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

Вывод данных отладки в файл

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

Для записи данных отладки в файл нам поможет функция file_put_contents, можно использовать ее со следующими аргументами:

file_put_contents("umitest", print_r([__FILE__.' '.__LINE__, $variable], true).PHP_EOL, FILE_APPEND | LOCK_EX); 

В результате выполнения данной функции рядом с файлом, из которого было запущено выполнение PHP (обычно это index.php в корне сайта), будет создан файл umitest в который запишется имя файла, строка в нем и содержимое переменной $variable.

__FILE__ — это волшебная константа PHP которая всегда содержит имя текущего файла.

__LINE__ — это волшебная константа PHP которая всегда содержит номер строки в файле в котором она была вызвана.

Эти константы рекомендуется добавлять в вывод по нескольким причинам:

1) Удобство отслеживания из какого файла и строки в нем была сделана запись

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

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

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

Можно вывести в файл все переменные, доступные в текущей области видимости:

file_put_contents("umitest", print_r([__FILE__.' '.__LINE__, get_defined_vars()], true).PHP_EOL, FILE_APPEND | LOCK_EX); 

или только некоторые из них

file_put_contents("umitest", print_r([__FILE__.' '.__LINE__, $var1, $var2], true).PHP_EOL, FILE_APPEND | LOCK_EX); 

Получить стек вызова функции при помощи debug_backtrace

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

$debug_arr = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) 

Также в качестве второго аргумента можно указать глубину стека.

Стек вызова можно вывести как в браузер:

echo '
' . print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true) . '

';

так и записывать в файл:

file_put_contents("umitest", print_r([__FILE__.' '.__LINE__, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)], true), FILE_APPEND | LOCK_EX); 

Получить расположение используемого класса, метода или функции

Стек вызовов дает информацию откуда была вызвана функция, но иногда необходимо узнать где находится используемый в коде класс, метод или функция. Для решения этой задачи в PHP есть специальные классы ReflectionFunction, ReflectionClass и ReflectionMethod, методы которых дают возможность получить всю необходимую для этого информацию.

Информация о функции
$reflectionMethod = new ReflectionFunction('function_name'); file_put_contents("umitest", print_r([__FILE__.' '.__LINE__, $reflectionMethod->getFileName(), $reflectionMethod->getStartLine()], true), FILE_APPEND | LOCK_EX); 

Этот код запишет в файл umitest путь до файла и номер строки в нем в которой находится функция ‘function_name’.

Информация о классе
$reflectionClass = new ReflectionClass('class_name'); file_put_contents("umicheck", print_r([__FILE__.' '.__LINE__, $reflectionClass->getFileName(), $reflectionClass->getStartLine()], true), FILE_APPEND | LOCK_EX); 

Этот код запишет в файл umitest путь до файла и номер строки в нем в которой находится класс ‘class_name’.

Информация о методе
$reflectionMethod = new ReflectionMethod('class_name', 'method_name'); file_put_contents("umicheck", print_r([__FILE__.' '.__LINE__, $reflectionMethod->getFileName(), $reflectionMethod->getStartLine()], true), FILE_APPEND | LOCK_EX); 

Этот код запишет в файл umitest путь до файла и номер строки в нем в которой находится метод ‘method_name’ класса ‘class_name’.

Первым аргументом при создании ReflectionMethod можно передавать не только имя класса, но и его экземпляр, например:

namespace DebugNamespace; $className = new class_name(); $reflectionMethod = new \ReflectionMethod($className, 'method_name'); file_put_contents("umicheck", print_r([__FILE__.' '.__LINE__, $reflectionMethod->getFileName(), $reflectionMethod->getStartLine()], true), FILE_APPEND | LOCK_EX); 

Обратите внимание, что в данном случае в файле задан namespace ‘DebugNamespace’, поэтому при получении экземпляра класса \ReflectionMethod необходимо наличие косой черты в начале иначе произойдет ошибка: Ошибка (Error): Class ‘DebugNamespace\ReflectionMethod’ not found

Время выполнения скрипта

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

$start = microtime(true); // тут код время выполнения которого необходимо посчитать $stop = microtime(true) - $start; file_put_contents("umitest", print_r([__FILE__.' '.__LINE__, $stop], true).PHP_EOL, FILE_APPEND | LOCK_EX); 
  • Решение проблем и ошибок
  • Вопросы и уроки разработки сайтов на UMI.CMS

PHP + Xdebug + PHP Strom: Как дебажить MVC-приложение, если xdebug соскакивает на роутере, не идет дальше.

введите сюда описание изображения

xdebug у меня в PHP Storm установлен через файл, вот так: Если пытаюсь посмотреть, что приходит в контроллер, то это не выходит. Из индексного файла по точкам останова прохожу в router.php, но на коде:

public function processRequest() < $path = $this->findControllerAndMethod(); $method = $path['method']; if(empty($path['argument'])) < (new $path['controller']()) ->$method(); > else < (new $path['controller']()) ->$method($path['argument']); > > 

у меня ставится Variables are not avilable. Может это потому что работает приложение только через бразуер, там же нужен url для ‘REQUEST_METHOD (где маршрутизация). Подскажите, пожалуйста что я делаю не так, как мне дебажить контроллеры?

Отслеживать
задан 24 ноя 2022 в 14:25
263 2 2 серебряных знака 11 11 бронзовых знаков

Что значит «соскакивает»? Зачем такой долгий путь чтобы войти в метод? Вывод ошибок настроен в приложении? Никакие не выдаёт? Почему не поставить точку останова прямо на первой строке контроллера? Причём тут REQUEST_METHOD и что с ним не так? «телефончик» в phpstrom на панели дебага включен? . «как мне дебажить контроллеры?» — поставить бряк в метод контроллера и всё. «Variables are not avilable» — о каких variables речь? и где это показывает?

24 ноя 2022 в 14:36

1. соскакивает — доходит до точки останова напротив ->$method(); и дальше дебаггин прекращается, консоли дебага уже нет никаких логово что пришло — что ушло только надпись Variables are not avilable.

24 ноя 2022 в 14:51

2. «Зачем такой долгий путь чтобы войти в метод?» — почему долго, вроде норм? ничего лишнего.. 3. в целом дебаг работает сам роутер он проходит и показывает в консоли дебага все данные, которые из переменной в переменную идут

24 ноя 2022 в 14:53
4. Попробовал в первую строчку контроллера поставить точку останова — все равно не работает
24 ноя 2022 в 14:55

у меня без телефончика работает, но я его включил — не помогло, правда дебаг показывает $path = null и все другие в переменной null

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

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