Чи можна використовувати try/catch для управління логікою?

← Чи можна використовувати try/catch для управління логікою?

Ashterix

docs: English JsonRpcBundle docs, REST and MCP Bundle sections, package cards

uk/articles/from-tg/architecture/try-catch.md новий файл +55 −0

Чи можна використовувати try/catch для управління логікою?

Питання читача
  1. Чи можна використовувати try catch для управління логікою? Я досі використовував, але сьогодні натрапив на твердження, що це не є хороша практика.
  2. Наскільки ресурсозатратне використання вкладених try catch? Прочитав, що сам try catch сам по собі "дешевий", а от throw вимагає багато ресурсів. Це так?

1. Чи можна використовувати try/catch для управління логікою?

Так, можна, і це цілком робочий підхід. Питання тут не в "правильно/неправильно", а в тому, яка філософія тобі ближча і що підходить під конкретну архітектуру.

Насправді, це дуже холіварна тема.

Є табір, який каже "винятки тільки для виняткових ситуацій", а є табір, який спокійно використовує їх як механізм flow control. І обидва підходи живуть собі нормально.

Я особисто вважаю, що це питання зручності, а не абсолютна істина. Мені зручніше обʼєктно-орієнтований підхід. ІМХО, якщо код читається краще — значить, підхід має право на життя.

Приклад:

try {
    $code = $repo->getByUrl($url);
} catch (NotFoundException) {
    $code = $this->generateAndSave($url);
}

У такій ситуації це працює природно і зрозуміло: "немає? створи". Немає нічого поганого в тому, щоб ловити конкретний виняток і робити fallback-логіку.

Проблеми починаються тільки тоді, коли exception використовується замість звичайного if у найпростіших місцях, або коли репозиторій починає кидати винятки там, де очікувано повертати null. Але то вже питання дизайну коду.

2. Чи дійсно throw дорогий?

Так, це правда.

try/catch сам по собі майже нічого не коштує. Їх можна хоч вкладати — накладні витрати мізерні, але throw — дорогий, бо PHP генерує backtrace і створює повноцінний Exception-об’єкт, що виїдає процесор.

Тому:

  • Якщо throw трапляється рідко — взагалі не проблема.
  • Якщо "not found" стає нормальним шляхом виконання (часто), тоді варто задуматись, чи не простіше повертати null або Result-об’єкт — чисто з точки зору продуктивності.

Але й тут все залежить від контексту. Якщо навантаження невелике — різниця взагалі не має сенсу.

Підсумую мою позицію

  • Використовувати try/catch для логіки можна. Це не є поганою практикою само по собі, це питання смаку, стилю і команди.
  • Якщо код читається краще — я завжди за.
  • try/catch дешевий, throw дорожчий, але в реальних проєктах це рідко стає bottleneck’ом.

Якщо тобі це зручно і воно вписується в архітектуру — продовжуй використовувати.


Вперше опубліковано в Telegram-каналі «Створений щоб помирати» 14.11.2025.