Поганий код — це сленгова назва вихідного коду низької якості: нечитабельного, погано структурованого та складного в підтримці. За даними звіту Stripe (2022), розробники витрачають до 40% робочого часу на читання та розуміння погано написаного коду. У російськомовній спільноті термін настільки поширений, що існує спеціалізований сайт govnokod.ru, де розробники публікують приклади особливо яскравих випадків.
Головне
Поганий код — це суб’єктивна, але загальноприйнята характеристика коду, який не відповідає мінімальним стандартам якості. Роберт Мартін у книзі «Чистий код» (2008) визначає поганий код як код, який «заважає зрозуміти, що він робить». Поганий код може бути синтаксично правильним і навіть працювати, але його підтримка перетворюється на жах для команди.
Термін поганий код поширений саме в російськомовній спільноті. В англійській мові використовуються більш формальні терміни: spaghetti code, dirty code, technical debt code. Однак емоційне забарвлення «поганого коду» точніше передає ставлення розробників до такого коду — суміш роздратування, огиди та професійної образи.
За даними дослідження McKinsey (2023), компанії з високим рівнем технічного боргу — а поганий код є його головною складовою — витрачають на 20–40% більше ресурсів на розробку нових функцій. Якість коду безпосередньо впливає на бізнес-показники, і це не метафора, а підтверджений факт.
Об’єктивних метрик не існує, але є практичні критерії: якщо розробник витрачає більше 5 хвилин на розуміння функції з 20 рядків — це поганий код. Якщо зміна одного рядка ламає три не пов’язані модулі — це поганий код. Якщо код неможливо покрити тестами без повного переписування — це поганий код.
Копіпаста (copy-paste programming) — одна з найяскравіших ознак. Коли один і той самий блок коду повторюється в кількох місцях з мінімальними змінами, це не просто поганий код, а джерело майбутніх багів. Виправлення в одному місці та пропуск в іншому — типова ситуація.
Безглузді імена змінних — класика. Змінні з іменами `a`, `b`, `x`, `data`, `temp`, `tmp`, `result`, `list`, `obj` не несуть жодної інформації про своє призначення. Читач коду змушений аналізувати всю функцію, щоб зрозуміти, що зберігається в змінній. Роберт Мартін називає це «брехнею в імені» — ім’я обіцяє інформацію, але не дає її.
Глибока вкладеність — коли умови, цикли та обробка помилок створюють конструкцію з 5+ рівнями відступів. Такий код неможливо читати без бокової прокрутки або ментального відстеження всіх рівнів. Це прямий шлях до помилок: логічні оператори легко переплутати, а закриваючі дужки — не помітити.
| Ознака | Приклад поганого коду | Чистий код |
|---|---|---|
| Копіпаста | Один блок скопійовано 5 разів | Винесено у функцію |
| Імена | `var a = getData()` | `var userList = getData()` |
| Вкладеність | 6 рівнів if/for | 2–3 рівні з return early |
| Функції | Функція на 300 рядків | Розбита на 3–5 методів |
| Коментарі | `i++ // збільшити i` | Зрозумілий код без коментарів |
Dead code — функції, змінні, класи, які ніде не використовуються. Це збільшує об’єм коду, відволікає розробника та створює хибне враження про можливості системи. Магічні числа — числа без контексту. God-класи — класи, які роблять все одразу, порушуючи принцип єдиної відповідальності (SOLID: S).
Нестача часу — найпоширеніша причина. Коли дедлайни горять, розробники жертвують якістю на користь швидкості. Тактично це може бути виправдано, але стратегічно — це накопичення технічного боргу. Проблема в тому, що «тимчасовий» поганий код рідко повертаються виправляти.
Відсутність код-рев’ю — друга за значущістю причина. Коли код пишеться наодинці без перевірки колегами, погані патерни закріплюються і розмножуються. Code review — це не просто контроль якості, але й передача знань усередині команди. Проекти без рев’ю неминуче скочуються до поганого коду.
Низька кваліфікація розробника або відсутність менторства. Junior-розробники, залишені без нагляду, природним чином пишуть поганий код — це частина процесу навчання. Проблема виникає, коли цей код потрапляє в продакшн без рев’ю та рефакторингу.
У командах, де «працює — і добре» є девізом, поганий код процвітає. Відсутність стандартів кодування, вимог до тестування та процесів рев’ю створює середовище, в якому якість коду нікого не хвилює. Такі проекти швидко стають «легасі» — кодом, який бояться чіпати.
Основний наслідок поганого коду — уповільнення розробки. Парадокс поганого коду в тому, що він дозволяє швидко написати першу версію, але кожне наступне виправлення займає все більше часу. Графік залежності швидкості розробки від якості коду експоненціальний — після певного порогу додавання нових функцій стає практично неможливим.
Плинність кадрів — непрямий, але серйозний наслідок. Розробники, особливо досвідчені, не хочуть працювати з поганим кодом. За даними Stack Overflow Developer Survey 2024, 47% розробників називають якість кодової бази одним із ключових факторів при виборі місця роботи. Проекти з поганим кодом втрачають найкращих співробітників.
Безпека — ще одна жертва поганого коду. Погано написаний код містить більше вразливостей: необроблені винятки, SQL-ін’єкції, XSS, витоки пам’яті. Якісний код з unit-тестами та код-рев’ю відловлює більшість таких проблем до продакшну.
SonarQube та аналогічні інструменти вміють оцінювати технічний борг у людино-годинах або днях. Наприклад, 500 попереджень про копіпасту, 200 — про магічні числа і 50 — про глибоку вкладеність дають оцінку в 30 днів технічного боргу. Ці цифри можна й потрібно показувати менеджменту для обґрунтування рефакторингу.
Принцип DRY (Don’t Repeat Yourself) — перше, що потрібно впровадити. Кожен фрагмент логіки повинен існувати в єдиному екземплярі. Замість копіпасти — винесіть повторюваний код в окрему функцію, клас або модуль. Замість магічних чисел — іменовані константи. Замість довгих функцій — кілька маленьких.
Принцип KISS (Keep It Simple, Stupid) захищає від надмірної складності. Якщо завдання можна вирішити в 10 рядків — не треба писати 50. Якщо цикл простіший за стрим — використовуйте цикл. Якщо звичайна функція зрозуміліша за декоратор — пишіть функцію. Простота — головна якість коду, який підтримується.
Принцип Boy Scout Rule — «залиш код кращим, ніж ти його знайшов». Навіть невеликі покращення при кожному редагуванні з часом перетворюють поганий код на пристойний. Перейменувати змінну, розбити велику функцію, додати тест — будь-яке покращення має значення.
// поганий код — копіпаста, магічні числа, погані імена
function calc(a, b, c) {
let x = a * 0.85;
if (b > 1000) { x = x * 0.9; }
let y = c * 0.85;
if (b > 1000) { y = y * 0.9; }
return x + y;
}
// чистий код — зрозумілі імена, DRY, константи
const DISCOUNT_RATE = 0.85;
const BULK_THRESHOLD = 1000;
const BULK_DISCOUNT = 0.9;
function applyDiscount(amount, quantity) {
let price = amount * DISCOUNT_RATE;
if (quantity > BULK_THRESHOLD) {
price = price * BULK_DISCOUNT;
}
return price;
}
function calculateTotal(items, quantity) {
return items.reduce((sum, item) => {
return sum + applyDiscount(item, quantity);
}, 0);
}
Розглянемо типовий приклад на Python. Функція обробляє замовлення, але робить це погано: 80 рядків, глибока вкладеність, магічні числа, дублювання. Після рефакторингу код стає читабельним, тестованим і супроводжуваним.
# поганий код — одна функція робить все
def process_order(order):
if order.get("type") == "premium":
if order["amount"] > 100:
discount = 0.8
else:
discount = 0.9
else:
discount = 1.0
total = order["amount"] * discount
return total
# чистий код — винесені функції та константи
class OrderProcessor:
PREMIUM_DISCOUNT_HIGH = 0.8
PREMIUM_DISCOUNT_LOW = 0.9
PREMIUM_THRESHOLD = 100
def get_discount(self, order):
if order.type == "premium" and order.amount > self.PREMIUM_THRESHOLD:
return self.PREMIUM_DISCOUNT_HIGH
return self.PREMIUM_DISCOUNT_LOW
def calculate_total(self, order):
return order.amount * self.get_discount(order)
Хороша функція робить одну річ і робить її добре. Якщо функція робить три різні дії — розбийте її. Якщо функція містить більше 20 рядків — швидше за все, її можна розбити. Якщо у функції більше двох рівнів відступів — потрібен рефакторинг.
Статичні аналізатори коду — перша лінія оборони проти поганого коду. ESLint (JavaScript), Pylint (Python), SonarQube (мультимовний), Checkstyle (Java) автоматично виявляють копіпасту, магічні числа, порожні catch-блоки, надто довгі функції та сотні інших антипатернів.
Code style і форматери — другий рівень захисту. Prettier, Black, gofmt автоматично форматують код, усуваючи проблеми з пробілами, відступами та дужками. Єдиний стиль у команді робить код читабельним незалежно від того, хто його писав. Суперечки про форматування мають бути автоматизовані.
Код-рев’ю — третій і найважливіший рівень. Жоден аналізатор не замінить людину, яка помітить, що архітектура рішення неправильна або що розробник обрав невірний підхід. Ефективне рев’ю потребує часу, але воно окупається зниженням кількості поганого коду в рази.
Часті запитання
Вкрай рідко. У прототипуванні або хакатонах швидкість важливіша за якість, але такий код має бути позначений як тимчасовий і не повинен потрапляти в продакшн без рефакторингу. У продакшні виправдань поганому коду немає — будь-яка економія часу зараз перетвориться на багаторазові втрати в майбутньому.
Код новачка — це недосвідчений, але часто щирий код, який виправляється зі зростанням навичок. Поганий код — це свідоме або байдуже нехтування якістю. Новачок може написати неоптимальний, але читабельний код. Поганий код же нечитабельний принципово — його автору все одно, чи зрозуміють його інші.
Переписування — крайній захід. Поступовий рефакторинг безпечніший: ви виділяєте модуль, покриваєте його тестами, переписуєте частину за частиною. Повне переписування ризиковане — ви можете втратити бізнес-логіку, накопичену в старому коді, включаючи обробку edge cases, які ніхто не документував.
Використовуйте метрики: SonarQube покаже технічний борг у годинах. Покажіть, скільки часу витрачається на баги в старому коді. Порівняйте швидкість розробки нової функціональності в «чистій» і «брудній» частинах проекту. Переведіть на мову бізнесу: час — це гроші, а поганий код коштує грошей.
«Чистий код» Роберта Мартіна (2008) — біблія якісного програмування. У ній описані принципи іменування, форматування, обробки помилок і тестування. Додатково: «Ідеальний код» Стіва Макконнелла, «Рефакторинг» Мартіна Фаулера, «Банди чотирьох» про патерни проектування. Ці книги повинен прочитати кожен розробник.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також