Всім привіт, спільното JavaRush. Сьогодні поговоримо про дебати: що це таке і як дебажити в Intellij IDEA. Debug в Intellij IDEA: гайд для новачків - 1Стаття розрахована на людей, які мають вже мінімальні знання Java Core. Тут не буде ні фреймворків, ні складних процесів публікації бібліотек. Легка прогулянка. Тож розташовуйтеся зручніше – почнемо!

Чому Debug тобі необхідний

Давайте відразу прояснимо для себе: коду без багів не буває… Так влаштовано життя. Тому не варто одразу розкисати та кидати все, якщо код працює не так, як ви очікували. Debug в Intellij IDEA: гайд для новачків - 2Але що робити? Звичайно, можна наставити System.out.println скрізь, де тільки можна і потім розгрібати результат у терміналі, сподіваючись на те, що вийде знайти помилку. Все-таки можна... і це роблять, і роблять акуратно за допомогою логування (можна почитати про це тут ). Але якщо є можливість запустити на локальній машині код, краще використовувати Debug. Відразу хочу зауважити, що в цій статті ми розглядатимемо дебаг проєкту всередині Intellij IDEA. Якщо цікаво почитати про віддалений дебаг – ось, будь ласка, стаття з нашого ресурсу.

Що таке Debug

Debug в Intellij IDEA: гайд для новачків - 3Debug — це процес налагодження (перевірки) коду, коли в процесі його виконання можна зупинитись у позначеному місці та подивитися за ходом виконання. Зрозуміти, у якому стані перебуває програма у певному місці. Це так само, якби можна було зупинити життя і подивитися на все збоку. Круто, правда? Наше завдання полягає в тому, щоб швидко і просто навчитися робити налагодження застосунків за допомогою всіх улюблених середовищ розробки Intellij IDEA.

Що потрібно для початку налагодження

Даю безкоштовну пораду: доки читаєте статтю, робіть все те, що тут буде описано, є все для цього. Що потрібно:
  1. Середовище розробки Intellij IDEA версії 2019.3.1 та вище. На випадок, якщо у когось його немає, ось посилання, де можна завантажити. Завантажуйте Community Edition, тому що я використовуватиму саме її.
  2. Клонувати проєкт з GitHub та імпортувати його через IDEA.
Відкриваємо IDEA: Debug в Intellij IDEA: гайд для новачків - 4Вибираємо проєкт debug-presentation, натискаємо OK та отримуємо: Debug в Intellij IDEA: гайд для новачків - 5Залишаємо import project from external sources, Maven та натискаємо Finish. Імпортувавши проєкт, можемо описати процес на живому прикладі.

Небагато теорії… обіцяю :D

Щоб почати трохи бешкетувати, потрібно зрозуміти, що таке 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и неактивними: Debug в Intellij IDEA: гайд для новачків - 10Щоб подивитися, які breakpoint'и вже виставлені, можна або зайти в Debug в лівому нижньому кутку і знайти іконку Debug в Intellij IDEA: гайд для новачків - 11 або натиснути Ctrl+Shift+F8: Debug в Intellij IDEA: гайд для новачків - 12Коли зайдемо до списку breakpoint'ів, побачимо: Debug в Intellij IDEA: гайд для новачків - 13Тут є два preakpoint'и:
  • 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 Ann Reinking звичайна робоча бджола;
  • 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: гайд для новачків - 20Debug в Intellij IDEA: гайд для новачків - 21Щоб отримати повну інформацію, необхідно подивитися в секцію Debug. У ній є Variables, де показані всі змінні, доступні в цій частині програми:
  • nectar = 1.0;
  • nectarCapacity = -1.0.
Виняток викидається справедливо, оскільки значення кількості нектару, що є в медоносі, не може бути негативним. Але чому так відбувається? Адже є перевірка, що якщо нектар закінчився, то повертається нульове значення у рядках 15-17:
if ( nectar == 0 ) {
         return 0;
}
Але проблема в тому, що перевіряє він не ту змінну... і це помилка в коді. Замість того, щоб перевіряти значення нектару в квітці, що лежить у змінній nectarCapacity, програма перевіряє значення nectar, яке приходить у метод і є тією кількістю, яку хочуть взяти у нектару. Ось він, перший баг! Тому ставимо правильно і отримуємо вираз:
if ( nectarCapacity == 0) {
         return 0;
}
Далі, запускаємо main() Метод у звичайному режимі (Run `Main.main()`) і помилки більше немає. Програма відпрацювала: Debug в Intellij IDEA: гайд для новачків - 22Програма відпрацювала і видала відповідь: “33.0 honey was produced by 7 bees from 2 honey plants” Все було б добре, але відповідь неправильна написано, що нектар переходить у мед із пропорцією 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;
  • як проводити навігацію в режимі дебагу.

Що ще почитати

Дивіться також інші мої статті: