ЗмістНатисність на посилання, щоб перейти до потрібного місця
Комбінаторний вибух - це явище, коли кількість можливих варіантів стрімко зростає зі збільшенням кількості елементів. Усе виглядає безневинно, поки не починаєш рахувати.
Наприклад:
- Маємо 3 сорти піци і хочемо вибрати 2 — це лише 3 варіанти.
- Але якщо маємо 20 топінгів і хочемо обрати будь-яку комбінацію? Вже понад мільйон варіантів!
У математиці це пов’язано з комбінаторикою - розділом, що вивчає способи вибору та упорядкування об’єктів.
У програмуванні, штучному інтелекті чи теорії ігор комбінаторний вибух - справжній ворог. Наприклад, у шахах кількість можливих позицій після 5 ходів — понад 69 мільярдів. Перебрати всі варіанти просто нереально — потрібні оптимізації, евристики й обхідні стратегії.
Комбінаторний вибух - це ситуація, коли "усе порахувати" стає неможливо, бо варіантів — забагато.
Термін звучить трохи драматично - і недарма. Він добре ілюструє, як швидко з простого завдання може вирости справжня математична буря.
Комбінаторний вибух при створенні нового класу в Ruby
У Ruby (як і в інших ООП-мовах) комбінаторний вибух може виникати, коли ти намагаєшся передбачити усі можливі комбінації поведінки об’єктів або залежностей між параметрами класу.
Приклад невдалого проєктування класу Notification:
class Notification def initialize(user:, type:, channel:, urgency:) @user = user @type = type # :comment, :like, :mention, :follow @channel = channel # :email, :sms, :push @urgency = urgency # :low, :medium, :high end def deliver # logic based on all combinations end end
Тепер маємо:
- 4 типи подій (:comment, :like, :mention, :follow)
- 3 канали надсилання (:email, :sms, :push)
- 3 рівні терміновості (:low, :medium, :high)
Це вже 4 × 3 × 3 = 36 комбінацій, кожна з яких потенційно потребує окремої логіки доставки (deliver). Додай ще 2 параметри — і от уже сотні варіантів, які складно протестувати й підтримувати.
Як уникнути комбінаторного вибуху?
1. Об’єкти-стратегії:
class EmailNotificationStrategy; def deliver; ...; end; end class PushNotificationStrategy; def deliver; ...; end; end
2. Розділяй відповідальність (SOLID):
- Notification не має знати все про всі канали.
- Кожен канал сам реалізує свою поведінку.
3. Метапрограмування (треба робити з розумом):
rubyCopyEditdefine_method("deliver_#{channel}_#{type}_#{urgency}") do # ... end
Але якщо методів 100+, це лише погіршить ситуацію. Комбінаторний вибух у класі виникає, коли ти намагаєшся "зашити" у клас занадто багато варіантів логіки, пов’язаних із комбінацією параметрів. З часом це призводить до нечитабельного коду, багів і болю.
Цей допис поки що не має жодних доповнень від автора/ки.