Чистый код. Создание, анализ и рефакторинг (Мартин) - страница 83

В этой главе представлены некоторые соображения и приемы, которые помогают писать чистый и надежный код, то есть код, в котором ошибки обрабатываются стильно и элегантно.

Используйте исключения вместо кодов ошибок

В далеком прошлом многие языки программирования не поддерживали механизма обработки исключений. В таких языках возможности обработки и получения информации об ошибках были ограничены. Программа либо устанавливала флаг ошибки, либо возвращала код, который проверялся вызывающей стороной. Оба способа продемонстрированы в листинге 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) {

>    ...