2016-08-23 3 views
-1

Когда метод sub генерирует исключение, будет ли считать, что инкапсуляция в специальном исключении «package» считается хорошей оценкой?Выбрасывание исключений через компоненты, хорошая практика?

public String doStuff() throws UtilsException { 
     try { 
      throw new NullPointerException("test"); 
     } catch (NullPointerException e) { 
      throw new UtilsException("something occured", e); 
     } 
    } 

    //use this exception for all classes of this package/component 
    public class UtilsException extends Exception { 
     private static final long serialVersionUID = 1L; 

     public UtilsException() { 
      super(); 
     } 

     public UtilsException(String message, Throwable cause) { 
      super(message, cause); 
     } 

     public UtilsException(String message) { 
      super(message); 
     } 

     public UtilsException(Throwable cause) { 
      super(cause); 
     } 

    } 

Может Optional.empty() быть альтернативой, чтобы избежать метания/ловли сложного приложения?

public Optional<String> doStuff() throws UtilsException { 
     try { 
      return Optional.of("ok"); 
     } catch (NullPointerException e) { 
      LOG.error("Something append... {}", e.getMessage()); 
      return Optional.empty(); 
     } 
    } 
+1

Приобретение исключения на низком уровне в исключение высокого уровня может быть хорошей практикой в ​​некоторых настройках, но это не так, если вы говорите о «NullPointerException». Вы даже не должны улавливать «NullPointerException». Он имеет то же значение на всех уровнях вашего приложения. «Необязательный» инкапсулирует потенциально отсутствующее значение, а не отчет о том, что произошло «NullPointerException». Избегайте «NullPointerException» в первую очередь. Вы можете сделать это, используя «Необязательный». – Holger

+0

Исключение NullPointerException было просто объяснить мою установку. Обертка кажется интересной, чтобы следить за источником исключения. –

+1

Тогда вы выбрали очень плохой пример. Подумайте, 'ClassNotFoundException', инкапсулирующее« IOException », возникшее при загрузке байтов класса. Особым случаем являются слои API, не допускающие проверенных исключений, например. рассмотрите представление «Коллекция» в базе данных. Там должны быть завершены отказы базовой системы хранения, например. в 'IllegalStateException' или' NoSuchElementException'. Думаю, это лучшие примеры. – Holger

ответ

1

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

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

Это, как говорится, (и приходит печально известное выражение), это зависит ...

Исключения «ответственность» за информирование ошибок, таким образом, они должны быть информативными для вызывающего абонента будет использовать их, чтобы решить, что делать. Рассмотрим следующий пример:

public void readFile(String path) throws IOException { 
    // read file content 
    return content; 
} 


try { 
    return readFile("foo.txt"); 
} catch(FileNotFound e) { 
    // For this specific scenario not finding the file is not a problem  
    return ""; 
} catch(IOException e) { 
    // This we are not expecting to happen, if the file exists we should be 
    // able to read it, otherwise we should inform the user. 
    log.error(e); 
    display("We had a problem reading the file, Check the file permissions and try again"); 
} 

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

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

Когда обертывать.

Бывают случаи, когда исключение обертывания является хорошей практикой и является способом перехода. Например, если вы создаете lib, основной функцией которого является получение информации о погоде.

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

public Weather getWeather(Date day) throws HTTPException { 
    return weather.get(day); 
} 

Ваш апи делает довольно хорошо, но вы заметили, что вы делаете слишком много запросов к погоде апи и вам придется начать платить за это очень скоро. Затем вы решили кэшировать результаты в таблице базы данных , чтобы уменьшить количество запросов.

public Weather getWeather(Date day) throws HTTPException, SQLException { 
    Weather w = getFromCache(day); 
    if (w != null) { 
     return w; 
    } else { 
     return getAndCache(day); 
    } 
} 

Теперь у вас есть проблемы, вы не можете добавить новое исключение бросков заявления, потому что вы определенно повредите пользователи кода вашего API.

И если вы думаете об этом, пользователи вашего api не заинтересованы, если у вас возникли проблемы с получением данных из getter api или из вашего кеша, они просто хотят получать информацию об ошибках.Это очень хороший случай, чтобы обернуть эти исключения в более общим, например WeatherFetchException.

Как вы можете видеть, что это действительно зависит ...

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

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