Рубрики
Без рубрики

Эффективная Java: Используйте Исключения только для Исключительных Обстоятельств

Погружение в главу 69 Эффективной Java. Помеченный java, эффективный, исключения, архитектура.

В какой-то момент вашей карьеры программиста вам может не повезти столкнуться с кодом, который выглядит примерно так:

try {
  int i = 0;
  while (true) {
    items[i++].process();
  }
} catch (ArrayIndexOutOfBoundsException ignored) {
}

Вероятно, то, что делает этот код, не сразу бросается вам в глаза, особенно по сравнению с аналогичной функцией, которая выполняет ту же функцию, написанную так:

for (Item item : items) {
  item.process();
}

Мало того, что первая функция содержит больше кода, ее сложнее обрабатывать и на самом деле она имеет меньшую производительность. К сожалению, очевидно, что некоторые разработчики, которые пишут код, подобный первому примеру, ищут улучшения производительности, ошибочно полагая, что, поскольку проверка границ все равно произойдет, они будут дублировать выполняемый код, включая проверку границ (проверка границ подразумевается в приведенном выше примере). Это неправильно по нескольким причинам:

  • Исключения не оптимизированы до уровня логических проверок в JVM.
  • Компилятор не может безопасно выполнить некоторые из своих оптимизаций, если ваш код находится в блоке try-catch.
  • Избыточные проверки, которые видит программист, достаточно распространены, чтобы оптимизировать JVM, чтобы устранить избыточность.

Принцип, который, я думаю, здесь можно понять, заключается в том, что, особенно в управляемой среде выполнения, такой как JVM, чем больше вы будете следовать тому, как был разработан язык программирования для использования, тем больше вероятность того, что вы получите преимущества в производительности с места в карьер, а также в будущем, когда разработчики языка и компилятора оптимизируют и улучшают общие рабочие процессы.

Учитывая все это, исключения должны быть зарезервированы, как следует из их названия, для исключительных обстоятельств. Если есть случаи, когда конкретная функция нуждается в том, чтобы ее состояние находилось в определенном состоянии до ее вызова, вы должны предоставить разработчику механизм, использующий вашу функцию, чтобы определить, находится ли она в этом правильном состоянии. Одним из примеров этого, который мы имеем в основных библиотеках, является функция Iterator ‘s next . Если эта функция вызывается, когда нет следующего элемента, создается исключение NoSuchElement . Чтобы не вынуждать разработчиков использовать разработку на основе исключений, разработчики API также создали функцию hasNext . Это позволяет пользователю API определить, ожидается ли успешный следующий вызов функции перед вызовом. Этот метод определенно может хорошо работать на практике.

Другой метод, который можно использовать и который имеет дополнительное преимущество в том, что его можно использовать в случаях, когда возможен параллельный доступ, – это метод назначенных возвращаемых значений или Необязательных <> возвращаемых типов. С назначенным типом возвращаемого значения специальное значение (-1, null , пустая коллекция и т.д.) Обозначается как специальное значение, которое будет возвращено, если объект находится в неправильном состоянии. Это менее явный показатель для пользователя API, чем исключение или Необязательный так что я, скорее всего, больше не буду его использовать, учитывая, что Опционально доступен. Параметр Необязательно аналогичен тому, что специальное значение Необязательно.пустой может пометить объект как неправильное состояние. В этом случае, однако, это гораздо более очевидно, когда есть значение или нет, и Необязательные API позволяют упростить обработку как допустимого состояния, так и пустого состояния. Как указано выше, оба этих параметра “назначенное значение” имеют то преимущество, что их можно использовать в ситуации одновременного доступа, которая не подходит для стиля hasIterator примера выше, потому что состояние может измениться между вызовом функции hasIterator и вызовом next .

Последний вопрос, который разработчик должен задать себе, заключается в том, что является исключительным? Хотя для меня приведенный выше пример вовсе не кажется исключительным, есть и другие случаи, когда все может стать не таким резким и сухим. Например, я работал с разработчиками, которые не считают, что исключения следует использовать для проверки бизнеса. Например, они никогда не напишут код, который при получении недопустимого значения, скажем, повторяющегося имени, когда это запрещено, вызовет пользовательское исключение DuplicateNameException . Я встречал других разработчиков, которые предпочли бы такой подход. В этом, безусловно, есть преимущества для обеих сторон, и вам, вероятно, потребуется определить, на какую сторону попадет ваше приложение.

Исключения делаются в исключительных случаях (что бы это ни значило для вас). Если вы будете следовать этому руководству, ваш код станет более производительным, простым в обслуживании и намного ближе к тому, что задумывали разработчики языка, что может означать, что он получает бесплатные улучшения по мере развития базового движка.

Оригинал: “https://dev.to/kylec32/effective-java-use-exceptions-for-only-exceptional-circumstances-1el6”