Следует ли использовать исключения (Exception) для реализации бизнес-логики в Java?

«Следует ли использовать исключения (Exception) для реализации бизнес-логики в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, это считается антипаттерном. Исключения предназначены для обработки неожиданных ошибок (ошибки ввода/вывода, сетевая недоступность), а не для управления нормальным потоком выполнения программы.

Почему это плохо:

  • Производительность: Создание исключения — дорогая операция из-за построения полного stack trace.
  • Читаемость: Логика программы становится скрытой в блоках try-catch, что усложняет понимание.
  • Семантика: Исключения для ожидаемых условий (например, "пользователь не найден") размывают границу между ошибкой и нормальным состоянием системы.

Лучшие альтернативы:

  1. Возврат специальных значений или кодов состояния.
  2. Использование Optional<T> для обозначения возможного отсутствия результата.
  3. Применение паттерна Result/Either, который явно инкапсулирует успех или неудачу.

Пример (антипаттерн vs. правильный подход):

// ПЛОХО: Использование исключения для бизнес-правила
try {
    processOrder(user.getActiveSubscription());
} catch (NoActiveSubscriptionException e) {
    showUpsellPage(); // Это не ошибка, а нормальный сценарий
}

// ХОРОШО: Явная проверка состояния
Optional<Subscription> activeSub = user.getActiveSubscription();
if (activeSub.isPresent()) {
    processOrder(activeSub.get());
} else {
    showUpsellPage(); // Понятный поток логики
}