Модуль 38

Типові помилки та антипатерни

Ось готовий урок, створений за твоїм майстер-промптом. Я обрав універсальну мову (Python-подібний псевдокод), щоб акцент був саме на логіці, а не на специфіці синтаксису.


🎓 УРОК: Типові помилки та Антипатерни (Code Smells)

Привіт, друзі! Це CS50 (умовно 😉), і сьогодні ми поговоримо про те, що відрізняє код новачка від коду професійного інженера.


1. 🔥 Вступ: Чому ваш код "смердить"?

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

Вечеря готова? Так. Чи смачно? Можливо. Але чи захочете ви готувати на цій кухні завтра, якщо там повний хаос? Чи зможе ваш друг зайти й допомогти вам, не послизнувшись на лушпинні?

У програмуванні це називається "Антипатерни" або "Code Smell" (код із запашком).

Коли ви пишете код, який "просто працює", але ігнорує структуру — ви створюєте бомбу уповільненої дії. * Питання до вас: Ви коли-небудь відкривали свій старий код (написаний місяць тому) і витрачали 20 хвилин просто щоб згадати, що робить змінна a? * І ще одне: Чи траплялося так, що ви виправляли помилку в одному місці, а програма ламалася в трьох інших?

Сьогодні ми навчимося не просто писати код, який працює, а код, який живе довго.


2. 🧠 Теоретична база: Що таке Антипатерн?

Давайте розберемося без зайвих академічних термінів.

Патерн — це перевірений часом рецепт вирішення проблеми. Антипатерн — це рішення, яке здається хорошим прямо зараз, але приносить більше проблем у майбутньому. Це як кредит під 100% річних: гроші є одразу, але платити доведеться дорого.

🔑 Що потрібно запам’ятати (Concept):

  1. Магічні числа (Magic Numbers): Використання цифр прямо в коді без пояснення, що вони означають.
  2. Спагеті-код (Spaghetti Code): Заплутана логіка, де все перемішано, і потік виконання стрибає туди-сюди, як макаронина в тарілці.
  3. DRY (Don't Repeat Yourself): Принцип "Не повторюй себе". Якщо ви скопіювали шматок коду двічі — це вже помилка.
  4. Божественний об'єкт (God Object): Функція або клас, яка робить все: і каву варить, і базу даних оновлює, і користувача вітає.

⚙️ Як це працює "під капотом"?

Комп’ютеру байдуже, наскільки красивий ваш код. Для процесора x = 5 і user_age = 5 — це одне й те саме (виділення пам'яті). Але код пишеться для людей. Для вас у майбутньому і для вашої команди. "Чистий код" знижує когнітивне навантаження на ваш мозок. Замість того щоб тримати в голові всю схему, ви читаєте код як книгу.


3. 🧪 Приклади: Від жаху до краси

Давайте подивимось, як це виглядає на практиці.

Приклад 1: Магічні числа 🧙‍♂️

Поганий код:

price = 100
total = price * 1.2  # Що таке 1.2? Чому саме стільки?

Запитання до вас: Якщо через рік податок зміниться на 22%, скільки місць у коді вам доведеться шукати і змінювати?

Хороший код:

TAX_RATE = 1.2  # Оголошуємо константу
price = 100
total = price * TAX_RATE

Чому це краще: Ми дали числу ім'я. Тепер намір очевидний.


Приклад 2: Copy-Paste (Порушення DRY) 📋

Уявіть, що ми вітаємо користувачів.

Поганий код:

print("Привіт, Андрій!")
print("Твій баланс: 100 грн")
print("Гарного дня!")

print("Привіт, Олена!")
print("Твій баланс: 250 грн")
print("Гарного дня!")

Що тут не так? Якщо ви захочете змінити "Привіт" на "Вітаю", вам доведеться правити це двічі (а в реальному проєкті — сотні разів).

Хороший код:

def print_welcome(name, balance):
    print(f"Привіт, {name}!")
    print(f"Твій баланс: {balance} грн")
    print("Гарного дня!")

print_welcome("Андрій", 100)
print_welcome("Олена", 250)

Чому це краще: Ми ізолювали логіку. Одна зміна виправляє все.


Приклад 3: Гігантська функція (God Function) 🦖

Поганий код (концептуально):

def process_order():
    # 1. Перевіряє наявність товару (10 рядків коду)
    # 2. Рахує знижку (15 рядків коду)
    # 3. Підключається до бази даних (5 рядків)
    # 4. Відправляє email користувачу (20 рядків)
    # 5. Друкує чек (10 рядків)

Це жах. Якщо зламається відправка email, перестане працювати вся функція замовлення!

Хороший код:

def process_order(order):
    if check_availability(order):
        total = calculate_discount(order)
        save_to_db(order, total)
        send_email(order)

Чому це краще: Функція читається як зміст книги. Кожна під-функція робить одну справу добре.


4. 🛠 Практична частина

Час закачати рукави! Ось ваш "брудний код". Ваше завдання — провести рефакторинг (покращення).

Вихідний код (Задача про інтернет-магазин):

# Цей код розраховує вартість доставки
dist = 50
w = 10

if w > 20:
    cost = dist * 5 + 100
else:
    cost = dist * 5

print("Вартість: " + str(cost))

Завдання:

  1. 🔹 Полювання на магію: Знайдіть у коді вище "магічні числа". Що можуть означати 5, 100, 20? Створіть для них іменовані константи (наприклад, BASE_RATE, HEAVY_ITEM_FEE).
  2. 🔹 Імена мають значення: Змінні dist та w — не дуже зрозумілі. Перейменуйте їх так, щоб їхній сенс був очевидний без коментарів.
  3. 🔹 Функціональність: Запакуйте цю логіку в функцію calculate_delivery(distance, weight), яка повертає значення, а не друкує його.
  4. 🔹 А що, якщо... (Міні-кейс): Уявіть, що з'явилася нова умова: якщо відстань менше 5 км, доставка безкоштовна. Додайте цю умову у вашу нову функцію, не зламавши стару логіку.
  5. 🔹 Виправ помилку: У вихідному коді є потенційна логічна проблема. Якщо вага рівно 20, яка умова спрацює? Чи це правильно згідно з вашою логікою "важких предметів"? (Подумайте про >=).

(Спробуйте виконати це подумки або на листочку, перш ніж читати далі)


5. 💡 Мислення як у розробника

Як відрізнити новачка від сеньйора, дивлячись на монітор?

  • Новачок думає: "Як мені змусити комп'ютер зробити це?" (Фокус на синтаксисі).
  • Профі думає: "Як мені структурувати це так, щоб колега (або я через пів року) зрозумів це за 5 секунд?" (Фокус на архітектурі та читабельності).

Типові пастки: 1. "Я потім поправлю". Ні, не поправите. Тимчасові милиці стають постійними несучими конструкціями. Робіть нормально одразу. 2. Передчасна оптимізація. Не пишіть супер-складний код, щоб зекономити 0.001 секунди, якщо цей код стає нечитабельним. Читабельність майже завжди важливіша за мікро-оптимізацію.

Порада з практики:

Пишіть код так, ніби його буде супроводжувати маніяк, який знає, де ви живете. Не дратуйте його заплутаними змінними x, y, data1.


6. 🧩 Підсумок

Отже, що ми сьогодні поклали в нашу скарбничку знань?

  • Ми зрозуміли, що код пишеться для людей, а не тільки для машин.
  • Ми навчилися бачити "Магічні числа" і замінювати їх константами.
  • Ми знаємо про принцип DRY і чому Copy-Paste — це зло.
  • Ми розбили "Божественну функцію" на маленькі зрозумілі кроки.

Тепер ви вмієте не просто писати код, а писати чистий код. Це перетворює вас з "кодера" на "інженера".

🚀 Тизер наступного уроку: Гаразд, наш код тепер чистий. Але що робити, якщо даних стає дуже багато? Як знайти потрібну інформацію серед мільйона записів не за годину, а за мілісекунду? На наступному уроці ми поговоримо про Алгоритми пошуку та Big O.

Це був CS50. Побачимось! 👋