#java #api #exception
#java #API #исключение
Вопрос:
Интересно, является ли использование исключения IllegalStateException в этом сценарии хорошим выбором дизайна для API.
Сценарий: У меня есть функция, которая проверяет, правильно ли сформирован XML-документ со следующей подписью:
public boolean isXMLDocumentWellFormed(InputStream inXMLDocument)
Эта функция использует следующий фрагмент для загрузки XML-документа:
boolean isXMLDocWellFormed = false;
// Setup document builder
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
.newInstance();
if (docBuilderFactory == null)
throw new IllegalStateException(
"The DocumentBuilderFactory cannot be instanciated");
try {
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
// Parse document
Document doc = docBuilder.parse(inXMLDocument);
if (doc != null)
isXMLDocWellFormed = true;
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IllegalStateException(e);
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IllegalStateException(e);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IllegalStateException(e);
}
return isXMLDocWellFormed;
API разработан так, чтобы быть очень простым в использовании. Однако я хотел бы предоставить пользователям API возможность узнать, почему XML-документ не может быть проверен (пример: DocumentBuilderFactory не может создать объект DocumentBuilder), не перегружая их множеством проверяемых исключений, с которыми им придется иметь дело.
Мои опасения по поводу этого дизайна заключаются в:
a) Является ли хорошей идеей использование одного единственного типа исключения (т. Е. исключения IllegalStateException) для возврата всех возможных перехваченных исключений, указывающих на сбой при выполнении проверки?Я бы сказал «да», поскольку пользователи исключили бы 2 вещи из этой функции:
- Чтобы узнать, правильно ли сформирован XML-документ или нет.
- Знать, если функция не может вернуть ответ (например, из-за исключения), почему функция не смогла предоставить ответ.
б) Если ответ на а) отрицательный, то какое имя исключения или решение было бы наиболее подходящим и почему?
С уважением,
Ответ №1:
Моя первая рекомендация людям — не перехватывать исключения только для эффективного повторного запуска. Поймайте, когда вы действительно можете что-то с ними сделать. Так что подумайте об этом. Но в вашем примере, где вы перехватываете проверенные исключения и оборачиваете их в исключение во время выполнения, я бы задал вопрос — как часто это будет происходить? Если исключения, вероятно, будут распространенными (или серьезными), то вы хотите, чтобы программисты были уверены, что они справляются с ними, поэтому лучше всего использовать checked. Однако, если они не являются распространенными (и несерьезными), то может быть приемлемым использование среды выполнения переноса. Это то, о чем вам нужно подумать, потому что ничто так не раздражает разработчика, как неожиданные исключения.
Ничего не сказав, сказав все это 🙂 если вы собираетесь завершить, я бы подумал о создании вашего собственного исключения, потому что вы хотите, чтобы было ясно, что оно ваше, а не Java. Вы могли бы даже создать иерархию с обобщенным исключением, расширяющим время выполнения, а затем с более конкретными, расширяющими ваше обобщенное исключение. Таким образом, предоставляя пользователям API возможность перехватывать на разных уровнях.
Комментарии:
1. В этом случае я бы сказал, что все пойманные исключения вряд ли произойдут. Поэтому я бы предпочел включить их в более общее исключение — пользовательское исключение. Я не позволю им перехватывать исключения другого уровня, поскольку пользователи API не будут иметь доступа к деталям реализации и не смогут устранить проблему. Следовательно, одно исключение, чтобы перехватить их все.
Ответ №2:
Если вы разрабатываете API, то вам следует объединить все исключения в одно основное исключение. Таким образом, вы не раскрываете детали реализации. Однако ваш личный вкус может отличаться
Однако я не думаю, что исключение IllegalStateException хорошо подходит здесь. Оно очень общее и не объясняет проблему (исключение ввода-вывода — это недопустимое состояние?). Лучшее решение — создать свой собственный пользовательский класс исключений и использовать его.
В качестве побочного узла для вас или кого-либо еще, пожалуйста, не печатайте исключение, если вы его создаете.
Комментарии:
1. API не должен передавать детали реализации. Поэтому я согласен с вами относительно преобразования всех исключений в одно основное исключение. Кроме того, я думаю, что исключение IllegalStateException не является подходящим исключением, и я должен выбрать что-то вроде OperationNotPerformedException, которое указывало бы, что функция не может выполнять свою работу должным образом из-за некоторых исключительных обстоятельств (подробно описано в сообщении об исключении).
Ответ №3:
Я бы предположил, что, вероятно, наиболее полезно иметь обычную утечку четырех типов исключений:
- Исключение CleanFailureException: запрошенная операция завершилась неудачно, но попытка не имела никаких побочных эффектов. Ожидается, что объект, выдающий исключение, находится в допустимом состоянии с его собственной точки зрения, хотя возможно, что он не соответствует некоторым инвариантам, которые может ожидать пользователь класса. Пример: извлечение несуществующего ключа из словаря. Структуры данных словаря могут быть абсолютно корректными, как словарь, но приложение может ожидать, что они будут находиться в состоянии, содержащем запрошенный ключ (также возможно, что словарь находится в правильном состоянии, и что-то другое дало приложению неправильный ключ).
- Исключение PartialOperationException: запрошенная операция не была завершена, но, возможно, была завершена в какой-то неизвестной степени. Как указано выше, объект, выдающий исключение, вероятно, находится в допустимом состоянии со своей собственной точки зрения, но вызывающему объекту придется проверить, находится ли он в состоянии, которое вызывающий объект посчитал бы допустимым.
- Исключение StateCorruptException: запрошенная операция не была завершена, и объект, на который была предпринята попытка, или какой-либо вложенный объект, похоже, имеет поврежденное состояние.
- Исключение SystemOnFireException: состояние всего и вся в системе следует считать подозрительным.
Исключение, вызванное чем-то вроде индекса массива, выходящего за рамки, может попадать в любую из вышеуказанных категорий. Важно не то, что был получен доступ к индексу, выходящему за пределы, а скорее то, что это означает для других объектов. Catch, wrap и rethrow были бы очень полезным шаблоном, поскольку перевод исключения в одну из вышеуказанных категорий даст вызывающей стороне гораздо лучшее представление о том, что с ним делать.