Подтвердить что ты не робот

Возвращает null после того, как исключение поймано плохой дизайн

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

public Object getObject(){
  try{
    ...
    return object;
  }
  catch(Exception e){
    //I have to return something here but what??
    return null; // is this a bad design??
  }
}

Итак, мои вопросы:

  • Неверный дизайн возврата?
  • Если так, то что рассматривается как более чистое решение?

спасибо.

4b9b3361

Ответ 1

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

Если вы должны вернуть значение, а null - единственная разумная вещь, в этом нет ничего плохого. Просто запишите его и дайте понять пользователям, что нужно делать. Имейте unit test, который показывает, что исключение выбрано так, что разработчики приходят после того, как вы увидите, что должна быть принятая идиома. Он также будет проверять, чтобы ваш код выдавал исключение, когда он должен.

Ответ 2

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

Если вы не знаете, что нужно вернуть, значит, вы не знаете, как обрабатывать исключение. В этом случае повторите бросок. Пожалуйста, не проглатывайте его молча. И, пожалуйста, не возвращать null, вы не хотите принуждать вызывающего кода писать:

Foo foo = bar.getFoo();
if (foo != null) {
    // do something with foo
} 

Это ИМХО плохой дизайн, я лично ненавижу писать нулевые проверки (много раз, нуль используется там, где вместо него должно быть выбрано исключение).

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

Связанные вопросы

Ответ 3

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

Я думаю, у вас есть два варианта:

  • выдает исключение. Таким образом, клиент должен обрабатывать его каким-то образом (и по этой причине я либо документирую его, либо проверяю). Недостатки в том, что исключения медленны и не должны использоваться для потока управления, поэтому я использую это для исключительных обстоятельств (предназначенных для каламбур)
  • Вы можете использовать шаблон NullObject.

Я следую стилю кодирования, в котором я редко возвращаю null. Если/когда я это делаю, это явно документировано, поэтому клиенты могут обслуживать его.

Ответ 4

Исключения означают исключительные случаи. Предполагая, что ваш код должен был возвращать объект, что-то пошло не так на пути (ошибка сети, из памяти, кто знает?), И поэтому вы не должны просто замораживать его, возвращая null.

Однако во многих случаях вы можете видеть в документации, что метод возвращает null, когда такое и такое условие происходит. Клиент этого класса может рассчитывать на это поведение и обрабатывать возвращаемый null, ничего плохого в этом. См., В этом втором примере использования, это не исключительный случай - класс предназначен для возврата null при определенных условиях - и поэтому он прекрасно подходит для этого (но документируйте это предполагаемое поведение).

Таким образом, в конце дня, это действительно зависит от того, не можете ли вы вернуть объект из-за чего-то исключительного на своем пути или просто нет объекта для возврата, и это абсолютно нормально.

Ответ 5

Это ваш код, и это неплохое решение. Но если вы делитесь своим кодом, вы не используете его, потому что он может вызывать неожиданное исключение (как nullpointer one).

Конечно, вы можете использовать

public Object getObject() throws Exception {}

который может предоставить полезную информацию родительской функции и предупредит, что может произойти что-то плохое.

Ответ 6

Исключения всегда должны быть пойманы контроллером в конце.
Передача <null> до контроллера не имеет смысла.
Лучше бросить/вернуть исходное исключение из стека.

Ответ 7

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

Обработка ошибок обычно имеет 3 части: обнаружение, отчетность и восстановление. По моему опыту, ошибки попадают в классы серьезности (ниже - сокращенный список):

  • Журнал только для отладки
  • Приостановите все, что происходит, и сообщите пользователю, ожидая ответа для продолжения.
  • Отказаться и завершить программу с помощью апологетического диалогового окна.

Ваши ошибки следует классифицировать, и обработка должна быть как можно более общей и последовательной. Если вам приходится учитывать, как обрабатывать каждую ошибку каждый раз, когда вы пишете какой-то новый код, у вас нет эффективной стратегии обработки ошибок для вашего программного обеспечения. Мне нравится иметь функцию отчетности, которая инициирует взаимодействие с пользователем, если продолжение зависит от выбора пользователя.

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

Ответ 8

Некоторые мысли о том, как обрабатывать исключения

  • Будет ли возвращать нуль будет хороший или плохой дизайн, зависит от Exception и где этот фрагмент помещается в вашу систему.

  • Если Exception представляет собой исключение NullPointerException, вы, вероятно, примените блокирующий блок несколько поучительным (как управление потоком).

  • Если это что-то вроде InOException, и вы ничего не можете сделать против этой причины, вы должны выбросить исключение в контроллер.

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

Ответ 9

В принципе, я бы сделал это на Duffymo с небольшим дополнением:

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

Если вызывающий абонент должен что-то сделать, но затем должен умереть сам, просто переверните исключение. Как:

SomeObject doStuff()
  throws PanicAbortException
{
  try
  {
    int x=functionThatMightThrowException();
    ... whatever ...
    return y;
  }
  catch (PanicAbortException panic)
  {
    cleanUpMess();
    throw panic; // <-- rethrow the exception
  }
}

Вы также можете переупаковать исключение, например...

catch (PanicAbortException panic)
{
  throw new MoreGenericException("In function xyz: "+panic.getMessage());
}

Ответ 10

Вот почему так много java-кода раздуто с предложениями if (x!=null) {...}. Не создавайте свои собственные исключения Null Pointer.

Ответ 11

Как говорит Йоша Блух в книге "" Эффективная Java", нуль - это ключевое слово Java.

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

Я бы кодировал ваш пример:

public Object getObject(){
  Object objectReturned=new Object();
  try{
    /**business logic*/
  }
  catch(Exception e){
    //logging and eventual logic leaving the current ojbect (this) in a consistent state
  }
  return objectReturned;
}

Недостатком является создание полного объекта в каждом вызове getObject() (тогда в ситуации, когда objectReturned не читается или не записывается).

Но я предпочитаю иметь один и тот же объект бесполезным, а затем NullPointerException, потому что иногда это исключение очень сложно исправить.

Ответ 12

Я бы сказал, что это плохая практика. Если получен null, как я знаю, нет ли object или произошла какая-либо ошибка?

Ответ 13

Мое предложение

Никогда не возвращайте NULL, если Тип записи - это массив или Collection.Instead возвращает пустую коллекцию или пустой массив

Когда тип возвращаемого значения является объектом, вам нужно вернуть значение null, зависит от сценария. Но никогда не проглатывайте исключение и не возвращайте NULL.

Также, если вы возвращаете NULL в любом сценарии, убедитесь, что это задокументировано в menthod.