ATDD in Legacy Code: catch regression bugs before production.
Hands-on work with your team. Limited spaces for 2027.
“What should I do when a use case fails?”
But a use case can fail for completely different reasons.
Maybe:
the customer doesn’t exist
the order hasn’t been paid for
the order cannot be checked out
the payment provider is unavailable
Should the use case handle all of them?
Error Handling at the Application layer
This layer contains your use cases:
checkout order
refund payment
create shipment
reserve seat
This is where application rules are enforced.
Examples:
cannot checkout if another checkout is already in progress
cannot place an order for a customer that doesn’t exist
cannot apply the same coupon twice
These are rules that the use case needs to check because because the information isn't inside the Order itself.
E.g. an Order can’t know whether the customer exists or another checkout is already in progress, or whether a coupon had already been used. The use case can check that information.
These are not technical failures. A database connection dropping is a completely different kind of problem.
❌ Use cases should NOT handle infrastructure exceptions
public void checkout(Order order) {
try {
paymentGateway.charge(order);
orderRepository.save(order);
shippingGateway.notifyWarehouse(order);
} catch (StripeException e) {
throw new RuntimeException("Payment failed");
} catch (SQLException e) {
throw new RuntimeException("Database error");
} catch (HttpException e) {
throw new RuntimeException("Warehouse call failed");
}
}Now the use case is tied to three unrelated technologies:
StripeException— Stripe’s SDKSQLException— JDBC / the databaseHttpException— the HTTP client
Swap Stripe for PayPal, JDBC for an ORM, or the HTTP client for a message queue, and you now have to change the use case too.
But the checkout rules haven’t changed.
That’s the problem.

