Используйте исключения вместо кодов ошибок
В далеком прошлом многие языки программирования не поддерживали механизма обработки исключений. В таких языках возможности обработки и получения информации об ошибках были ограничены. Программа либо устанавливала флаг ошибки, либо возвращала код, который проверялся вызывающей стороной. Оба способа продемонстрированы в листинге 7.1.
Листинг 7.1. DeviceController.java
>public class DeviceController {
> ...
> public void sendShutDown() {
> DeviceHandle handle = getHandle(DEV1);
> // Проверить состояние устройства
> if (handle != DeviceHandle.INVALID) {
> // Сохранить состояние устройства в поле записи
> retrieveDeviceRecord(handle);
> // Если устройство не приостановлено, отключить его
> if (record.getStatus() != DEVICE_SUSPENDED) {
> pauseDevice(handle);
> clearDeviceWorkQueue(handle);
> closeDevice(handle);
> } else {
> logger.log("Device suspended. Unable to shut down");
> }
> } else {
> logger.log("Invalid handle for: " + DEV1.toString());
> }
> }
> ...
>}
У обоих решений имеется общий недостаток: они загромождают код на стороне вызова. Вызывающая сторона должна проверять ошибки немедленно после вызова. К сожалению, об этом легко забыть. По этой причине при обнаружении ошибки лучше инициировать исключение. Код вызова становится более понятным, а его логика не скрывается за кодом обработки ошибок.
В листинге 7.2 представлен тот же код с выдачей исключений в методах, способных обнаруживать ошибки.
Обратите внимание, насколько чище стал код. Причем дело даже не в эстетике. Качество кода возросло, потому что два аспекта, которые прежде были тесно переплетены — алгоритм отключения устройства и обработка ошибок, — теперь изолированы друг от друга. Вы можете рассмотреть их по отдельности и разобраться в каждом из них независимо.
Листинг 7.2. DeviceController.java (с исключениями)
>public class DeviceController {
> ...
> public void sendShutDown() {
> try {
> tryToShutDown();
> } catch (DeviceShutDownError e) {
> logger.log(e);
> }
> }
> private void tryToShutDown() throws DeviceShutDownError {
> DeviceHandle handle = getHandle(DEV1);
> DeviceRecord record = retrieveDeviceRecord(handle);
> pauseDevice(handle);
> clearDeviceWorkQueue(handle);
> closeDevice(handle);
> }
> private DeviceHandle getHandle(DeviceID id) {
> ...