Упс! Не вдала спроба:(
Будь ласка, спробуйте ще раз.

Як тестування коду може покращити його «‎чистоту»

14 березня 2024 7 хвилин читання

Жодне тестування саме по собі не покаже забрудненості коду. Однак у процесі написання тестів можна знайти проблемні частини коду та виправити їх. Найпростіше це показують Unit-тести. Як саме, пояснюють РНР developer Філіпп Кучерявенко та JS developer Олександр Дробот.

Для чого потрібні Unit-тести 

Перевіряючи найменші частинки коду, Unit-тести допомагають зробити його модульним. Створити тест для гарного модульного коду досить просто: логіка зрозуміла, завдання очевидне. Та якщо у блоці коду багато різної функціональності, то і з тестами виникнуть проблеми.

Припустімо, є функція з трьома вхідними аргументами, котра видає різний результат залежно від вхідних аргументів. Під час написання тесту для такої функції треба підготувати вхідні дані на всі можливі комбінації вхідних параметрів. Інакше тест не буде повним. І добре, якщо це аргументи по типу bool — тоді у вас буде лише девʼять варіантів. Але якщо аргументи — це перелічення (enumerate) чи взагалі текст або число, то комбінацій вийде значно більше. Уявіть, яку кількість змін у коді та у тестах доведеться внести, якщо треба виправити роботу з одним із аргументів.

Але в багатьох випадках подібні функції можна розбити на менші: з точнішою назвою, з меншою кількістю аргументів та зі спрощеною логікою всередині. Наведений приклад можна спробувати розділити на три функції: по одному аргументу в кожному, плюс одна загальна функція, яка оперує меншими. Тести для таких дрібних функцій будуть простішими, з меншою кількістю тестових даних. Логіка функцій та їхніх тестів стане прозорішою, а вірогідність потреби змінити кожну з них у майбутньому теж сильно падає. Схожі рекомендації стосуються і складних та глибоких розгалужень логіки всередині функций (if-else), а також безлічі залежностей одного класу від інших.

Якщо вам складно написати тест на код, то й сам код, імовірно, складний

Покриття тестами краще робити до етапу рефакторингу коду. Якщо ви не впевнені, що система працює, як слід, немає сенсу її «‎очищувати» та намагатися зробити зрозумілою. В гіршому випадку ви можете винести в продакшен баг чи взагалі «‎покласти» базу даних.

Підписуйтеся на наші соцмережі

Тому радимо всім у команді закладати в естімейти час на тести для кожного блоку коду, над яким ви працюєте.

Тести не перевіряють коректність функції. Їхнє завдання — зафіксувати її поведінку

Тобто впасти, якщо щось змінили в коді. Саме через тести, що впали розробник може побачити які частини системи працюють інакше після внесення змін в код. Якщо впали очікувані тести, логічно буде виправити їх, додати нові тестові дані або змінити старі. Якщо впали тести, які не мали б цього робити, імовірно, відредагований код, неявно використовується в інших місцях, і потрібні додаткові виправлення.

Якщо після редагування коду нічого не впало або впало не все, що очікувалося, то це зовсім не говорить про високу якість рефакторингу. Лише — про погану якість тестів або покриття ними. Тож радимо зробити крок назад і покращити тести перед подальшим рефакторингом.

Для фіксації поведінки коду недостатньо викликати функцію чи метод і перевірити, що він не впав Інколи тест викликає функцію, але не перевіряє, що повернулось. Або в тесті недостатнє різноманіття комбінацій вхідних аргументів. Тому при рефакторингу тести ніби не падають, але виникає помилка, і, припустимо, за замовлення на $5 інтернет-магазин списує з рахунку $500. Тому дуже важливо памʼятати про необхідність перевіряти усі можливі комбінації даних і результатів роботи коду, і що модульний код робить цю задачу простішою.

Робимо код «чистим‎»: підходи та інструменти

За таким чеклистом рекомендуємо новачкам перевіряти й оптимізувати свою роботу:

  • Чітко зрозумійте, що ви взагалі збираєтесь робити: це лише ідея, схема або ж драфтовий код, написаний у блокноті. Наявність хоча б орієнтовного плану спростить подальші дії.
  • Далі пишете код, аби покрити потрібний функціонал. Інколи ця стадія проходить без великого натхнення чи цікавих ідей, але це не критично. Головне — щоб все працювало. Тому вже на цьому етапі починайте писати тести: Unit, E2E тощо.
  • Підходимо до етапу основного рефакторингу. Для цього відкрийте IDE та перевірте всі чейнджі. Так ви можете побачити дублювання, багато залежностей, блоки, що потребують розділення, некоректні назви тощо.
  • Після рефакторингу ще раз все тестуєте та переконуєтесь, що під час оптимізації ви нічого не зламали. Інколи код читається легко, але не працює. Наприклад, через обмеження фреймворку. Тож це може бути пуш для хардскілів.
  • Фінальний крок — швидкий перегляд коду перед пул реквестом. Тут будьте уважні. Початківці часом забувають видалити з коду свої To-do, а це демонструє неуважність до деталей.

Якщо мова не про створення коду з нуля, а про рефакторинг чужого, план роботи той самий. Придумуєте, що будете змінювати, переписуєте і перевіряєте все очима й тестами, а потім відправляєте на код рев’ю. З «‎чистотою» коду є й інший момент — так би мовити «‎політичний». Зазвичай клієнти не охоче погоджуються на такий рефакторинг.

Девелоперу складно читати, але це не аргумент. Бізнесу потрібні конкретні розрахунки, що замовник виграє після «‎очищення» коду. Наприклад, на модернізацію та виправлення помилок у майбутньому буде витрачатися на 20% менше часу (а значить, і бюджету). Спрогнозувати ці показники можливо не завжди. Простіший варіант — узгодити з лідом чи проєктним менеджером переписування тих маленьких фіч, з якими ви стикаєтеся мало не щодня. Так ви і код покращите, і здобудете необхідну практику.

Щодо інструментів, які можуть полегшити «‎очищення» коду, то їх безліч. Щоб визначити, що вам підійде, спершу розберіться у функціоналі вашої IDE. Там може ховатися чимало цікавих фіч. Наприклад, IntelliJ IDEA та PhpStorm показують ієрархію викликів: які функції зверталися до цієї функції і навпаки. Це класний допоміжний інструмент. Також можна використовувати лінтери, які покращують синтаксис.

Серед готових інструментів варто згадати SonarQube. Ця платформа багато знає про «‎чистоту» коду та показує проблеми глибоких функцій із великою кількістю if. А ще можна пробувати ChatGPT, Copilot та інші тулзи на основі штучного інтелекту, проте з обережністю. Команда має надати дозвіл на виведення коду за межі проєкту. Системи на базі ШІ добре генерують новий код, але за очищенні наявного не враховують усієї картини проєкту.

Якщо ви хочете поділитися з читачами SPEKA власним досвідом, розповісти свою історію чи опублікувати колонку на важливу для вас тему, долучайтеся. Відтепер ви можете зареєструватися на сайті SPEKA і самостійно опублікувати свій пост.
0
Icon 0

Підписуйтеся на наші соцмережі

Інші матеріали

Секрети успішних публічних виступів: як подолати страх сцени?

Олеся Руденко 20 березня 2025 13:45

Як зацікавити роботодавця за 30 секунд: Elevator Pitch

Олеся Руденко 21 березня 2025 08:41

Психологія війни: турбота про душу.

Юлія Доля 19 березня 2025 22:19

Рекап п’ятого сезону «Закрив Раунд»: Пригадуємо найцікавіші випуски головного подкасту про технології

Спекотне промо 19 березня 2025 17:34

Операційний менеджмент у стилі ніндзя: як керувати процесами, залишаючись непомітним

Polina Salnikova 20 березня 2025 16:30