Вопрос проверяет понимание, когда использовать исключения для обработки ошибок бизнес-логики, а когда предпочесть другие подходы, чтобы избежать накладных расходов и неоднозначности.
Исключения (exceptions) — это механизм обработки ошибок, который прерывает нормальный поток выполнения программы и передаёт управление специальному обработчику (catch-блоку). В контексте бизнес-логики, которая реализует правила и операции предметной области, важно чётко различать, когда исключения уместны, а когда нет.
Рассмотрим функцию проверки баланса пользователя перед списанием. Использование исключения для ожидаемой ситуации (недостаточно средств) может быть излишним.
// Пример на TypeScript: использование исключения для бизнес-правила
class InsufficientFundsError extends Error {
constructor(public userId: number, public required: number) {
super(`User ${userId} lacks ${required} credits.`);
}
}
function withdraw(userId: number, amount: number): void {
const balance = getBalance(userId); // получаем баланс из БД
if (balance < amount) {
// Бизнес-ошибка: недостаточно средств
throw new InsufficientFundsError(userId, amount);
}
// ... логика списания
}
// Обработка на верхнем уровне (например, в Express-маршруте)
try {
withdraw(123, 1000);
res.status(200).json({ success: true });
} catch (error) {
if (error instanceof InsufficientFundsError) {
res.status(400).json({ error: error.message });
} else {
// Неожиданная ошибка (например, проблема с БД)
res.status(500).json({ error: 'Internal server error' });
}
}Альтернативный подход — возврат объекта-результата, который явно указывает на успех или неудачу, что может быть эффективнее и понятнее для ожидаемых сбоев.
// Альтернатива: возврат результата без исключения
interface WithdrawalResult {
success: boolean;
errorMessage?: string;
}
function withdrawSafe(userId: number, amount: number): WithdrawalResult {
const balance = getBalance(userId);
if (balance < amount) {
return { success: false, errorMessage: 'Insufficient funds' };
}
// ... логика списания
return { success: true };
}
const result = withdrawSafe(123, 1000);
if (!result.success) {
// Обрабатываем ожидаемую бизнес-ошибку
console.log(result.errorMessage);
}Вывод: Исключения стоит использовать для обработки действительно исключительных, неожиданных ситуаций (например, сбой базы данных, потеря сетевого соединения). Для ожидаемых ошибок бизнес-логики (невалидный ввод, недостаток средств) предпочтительнее использовать возвращаемые значения или специальные типы результатов (Result/Option), так как это делает поток управления явным и снижает накладные расходы.