Структура и обработка ошибок — Примеры
Пример 1 — Сбой, дошедший до клиента нулём
Функция ниже списывает деньги с карты, а когда шлюз отказывает, переходит к нулевой сумме. Трассировка — то, что увидел оператор. Скажите, что получил клиент, затем перепишите путь отказа так, чтобы причина сохранилась.
async function charge(order) {
try {
return await gateway.charge(order);
} catch (e) {
console.log("charge failed");
return { total: 0, status: "ok" };
}
}
trace:
gateway.charge(order) -> 502 от провайдера
строка журнала: "charge failed"
вызывающий: заказ #4471 подтверждён на 0.00
Решение
async function charge(order) {
try {
return await gateway.charge(order);
} catch (cause) {
throw new PaymentFailed(`charge failed for order ${order.id}`, { cause });
}
}
Нулевая сумма со статусом ok — правдоподобное значение для сломанной операции. Сбой из-за этого продолжает маскироваться под данные и всплывает через две системы позже неверным счётом. Если перебросить ошибку, прикрепив к ней id заказа и исходную причину, детали сохранятся там, где ими владеет только этот слой, а вызывающему это позволит решить, повторять или отказываться. Ловушка в том, что catch написали, чтобы удержать запрос живым: намерением была устойчивость, а результатом стало то, что сбой выглядит как успех.
Пример 2 — Защитные условия вместо четырёх уровней вложенности
Функция ниже вычисляет скидку, и каждое правило вложено в предыдущее. Скажите, что читатель вынужден держать в голове, затем перепишите её с неверными случаями, защищёнными вначале.
function discountFor(customer, order) {
if (customer) {
if (customer.active) {
if (order && order.total > 0) {
if (customer.years > 1) {
return order.total * customer.years * 0.01;
}
}
}
}
return 0;
}
Решение
function discountFor(customer, order) {
if (!customer || !customer.active) return 0;
if (!order || order.total <= 0) return 0;
if (customer.years <= 1) return 0;
return order.total * customer.years * 0.01;
}
Каждое защитное условие возвращает тот же ноль, поэтому вложенность не несла никакой дополнительной информации — она лишь заставляла читателя отслеживать четыре условия сразу. В плоском виде условия читаются как список причин обойтись без скидки, а единственный возврат в конце безошибочно указывает на обычный случай. Ловушка в том, что вложенность кажется безопаснее, потому что группирует правила, хотя на деле внешние условия не связаны друг с другом, — именно это форма и скрывала.