понедельник, 22 мая 2017 г.

Бросать исключение без надлежащего контекста - это плохая привычка

Я повторяю одну и ту же ошибку снова и снова. Итак, пришло время остановиться и сделать правило, чтобы этого больше не происходило. Ошибка не фатальна, но очень раздражает. Когда я смотрю на производственные журналы, я часто вижу что-то типа «Файл не существует», и я спрашиваю себя: Какой файл? Где он должен существовать? Что сервер пытался с этим сделать? Что происходило за секунду до того, как он упал? В журнале ошибок нет ответа, и я полностью виноват. Я либо 1) не перебрасываю, либо 2) перебрасываю без предоставления контекста.


This is how the code may look:
if (!file.exists()) {
  throw new IllegalArgumentException(
    "File doesn't exist"
  );
}
It may also look like this:
try {
  Files.delete(file);
} catch (IOException ex) {
  throw new IllegalArgumentException(ex);
}
Оба примера демонстрируют неадекватный стиль обработки ситуаций, связанных с исключениями и сообщениями о них. Что здесь не так? Сообщения об исключениях недостаточно подробны. Они просто не содержат никакой информации о месте, в котором они произошли.
This is how they should look instead:
if (!file.exists()) {
  throw new IllegalArgumentException(
    String.format(
      "User profile file %s doesn't exist",
      file.getAbsolutePath()
    )
  );
}
And the second example should look like this:
try {
  Files.delete(file);
} catch (IOException ex) {
  throw new IllegalArgumentException(
    String.format(
      "Can't delete user profile data file %s",
      file.getAbsolutePath()
    ),
    ex
  );
}
Видите разницу? Это может выглядеть как избыточный код, но это не так. Конечно, когда я пишу все это, мне действительно не нужны журналы и исключения. Я не ожидаю, что этот файл будет отсутствовать.
Но я должен.
Должно быть правило: каждый раз, когда мы бросаем или перебрасываем, сообщение об исключении должно описывать проблему с как можно большим количеством деталей.
Разумеется, мы не можем забывать о безопасности и риске ввода любой конфиденциальной информации в сообщение об исключении, например, паролей, номеров кредитных карт и т.д. Кроме того, необходимо как можно больше подвергать код ловушкам исключений на более высоком уровне.
Бросать исключение - это буквально эскалация проблемы на более высокий уровень управления. Представьте себе, что мой босс просит меня установить новый сервер. Через несколько часов я возвращаюсь к нему и говорю: «Мне не удалось, извините». Это звучит странно. Он хотел бы получить более подробную информацию. Почему я потерпел неудачу? Что именно пошло не так? Можно ли сделать это по-другому? и т.п.
Такой код буквально является признаком неуважения к клиенту:

throw new IllegalArgumentException(
  "File doesn't exist"
);

Я должен быть более подробным и дать более подробную информацию.
И я не одинок в этой ошибке. Я вижу это повсюду, и это действительно затрудняет отладку, особенно в производстве, где практически невозможно сразу воспроизвести проблему.
Таким образом, будьте более подробными в сообщениях об исключительных ситуациях. Я сделаю то же самое в своем коде :)
И еще одна вещь, прежде чем вы идете. На большинстве языков ООП исключения не отмечены, что означает, что их улов не является обязательной операцией, к сожалению. Тем не менее, я рекомендую вам ловить, добавлять контекст и повторно бросать их все, всегда. Это может показаться чистым шумом, но это не так! Просто уменьшите свои методы и убедитесь, что все исключения, отправленные из них, содержат достаточную информацию об их происхождении. Вы сделаете для себя и для всех остальных большую услугу.


Комментариев нет:

Отправить комментарий