---
title: Define Exceptions by Caller Needs
impact: HIGH
impactDescription: reduces catch blocks by 3-5× per call site
tags: err, wrapper, classification, design
---

## Define Exceptions by Caller Needs

Define exception classes based on how they are caught, not on their source or type. Often a single exception class is sufficient for a particular area of code. Wrap third-party API exceptions.

**Incorrect (catching many exception types):**

```java
// Caller must handle many different exceptions
try {
    port.open();
} catch (DeviceResponseException e) {
    reportPortError(e);
    logger.log("Device response problem", e);
} catch (ATM1212UnlockedException e) {
    reportPortError(e);
    logger.log("Unlock exception", e);
} catch (GMXError e) {
    reportPortError(e);
    logger.log("Device response exception", e);
} finally {
    // ...
}
```

**Correct (unified exception handling):**

```java
// Wrapper class translates exceptions
public class LocalPort {
    private ACMEPort innerPort;

    public void open() throws PortDeviceFailure {
        try {
            innerPort.open();
        } catch (DeviceResponseException e) {
            throw new PortDeviceFailure(e);
        } catch (ATM1212UnlockedException e) {
            throw new PortDeviceFailure(e);
        } catch (GMXError e) {
            throw new PortDeviceFailure(e);
        }
    }
}

// Clean caller code
try {
    port.open();
} catch (PortDeviceFailure e) {
    reportPortError(e);
    logger.log(e.getMessage(), e);
}
```

**Benefits of wrapping:**
- Minimizes dependencies on third-party APIs
- Easier to mock for testing
- Easier to switch implementations later
- Single exception type per area simplifies catching

Reference: [Clean Code, Chapter 7: Error Handling](https://www.oreilly.com/library/view/clean-code-a/9780136083238/)
