Я строю API, функцию, которая загружает файл. Эта функция не будет возвращать ничего / пусто, если файл был загружен правильно, и выдает исключение при возникновении проблемы.
Почему исключение, а не просто ложь? Потому что внутри исключения я могу указать причину сбоя (нет соединения, отсутствует имя файла, неверный пароль, отсутствует описание файла и т. Д.). Я хотел создать собственное исключение (с некоторым перечислением, чтобы помочь пользователю API обрабатывать все ошибки).
Это хорошая практика или лучше возвращать объект (с логическим значением внутри, необязательным сообщением об ошибке и перечислением ошибок)?
java
api-design
exceptions
functions
architectural-patterns
Accollativo
источник
источник
Result<T, E>
гдеT
результат в случае успеха иE
ошибка в случае неудачи. Создание исключения (может быть - не очень уверенно в Java) может быть дорогостоящим, поскольку включает в себя разматывание стека вызовов, но создание объекта Exception обходится дешево. Очевидно, придерживайтесь установленных шаблонов языка, который вы используете, но не объединяйте логические значения и исключения, подобные этому.fillInStackTrace();
вызывается в супер-конструктор, в классеThrowable
Ответы:
Создание исключения - это просто дополнительный способ заставить метод возвращать значение. Вызывающая сторона может проверить возвращаемое значение так же легко, как поймать исключение и проверить это. Поэтому решение между
throw
иreturn
требует других критериев.Часто следует избегать создания исключений, если это ставит под угрозу эффективность вашей программы (создание объекта исключения и раскрутка стека вызовов для компьютера гораздо больше, чем просто добавление значения в него). Но если целью вашего метода является загрузка файла, то узким местом всегда будет сетевой ввод и вывод файловой системы, поэтому оптимизировать метод возврата бессмысленно.
Также плохой идеей является создание исключений для того, что должно быть простым потоком управления (например, когда поиск успешно выполняется путем поиска его значения), потому что это противоречит ожиданиям пользователей API. Но метод, не выполняющий своего предназначения, является исключительным случаем (или, по крайней мере, так и должно быть), поэтому я не вижу причин для того, чтобы не вызывать исключение. И если вы сделаете это, вы также можете сделать это пользовательским, более информативным исключением (но было бы неплохо сделать его подклассом стандартного, более общего исключения
IOException
).источник
Нет абсолютно никаких причин возвращаться
true
в случае успеха, если вы не вернетесьfalse
в случае неудачи. Как должен выглядеть код клиента?В этом случае вызывающему в любом случае нужен блок try-catch, но тогда он может лучше написать:
Таким образом,
true
возвращаемое значение совершенно не имеет значения для вызывающей стороны. Так что просто продолжайте методvoid
.В общем, есть три способа создания режимов сбоев.
void
, выбрасывать (проверено) исключениеВозврат
true
/false
Это используется в некоторых старых API, в основном в стиле c. Недостатки - obviuos, вы понятия не имеете, что пошло не так. PHP делает это довольно часто, что приводит к такому коду:
В многопоточных контекстах это еще хуже.
Бросить (проверено) исключения
Это хороший способ сделать это. В некоторые моменты вы можете ожидать сбой. Java делает это с помощью сокетов. Основным предположением является то, что вызов должен быть успешным, но все знают, что некоторые операции могут завершиться неудачей. Разъемы подключения среди них. Таким образом, вызывающий абонент вынужден справиться с ошибкой. это хороший дизайн, потому что он гарантирует, что вызывающая сторона действительно обрабатывает сбой, и дает вызывающему абоненту элегантный способ справиться с ошибкой.
Возвращаемый результат объекта
Это еще один хороший способ справиться с этим. Его часто используют для разбора или просто вещей, которые необходимо проверить.
Хорошая, чистая логика для звонящего.
Существует немного споров, когда использовать второй случай, а когда использовать третий. Некоторые люди считают, что исключения должны быть исключительными, и что вы не должны проектировать с учетом возможных исключений, и в большинстве случаев будете использовать третьи варианты. Это здорово. Но мы проверили исключения в Java, поэтому я не вижу причин не использовать их. Я использую проверенные исключения, когда основное предположение состоит в том, что вызов должен прерваться (как при использовании сокета), но возможен сбой, и я использую третий вариант, когда очень неясный, должен ли вызов прерваться (как при проверке данных). Но есть разные мнения по этому поводу.
В вашем случае я бы пошел с
void
+Exception
. Вы ожидаете, что загрузка файла завершится, а когда это произойдет, будет исключительной. Но вызывающая сторона вынуждена обрабатывать этот режим сбоя, и вы можете вернуть исключение, которое правильно описывает, какая ошибка произошла.источник
Это действительно сводится к тому, является ли отказ исключительным или ожидаемым .
Если ошибка - это не то, чего вы обычно ожидаете, то вполне вероятно, что пользователь API просто вызовет ваш метод без какой-либо специальной обработки ошибок. Выдача исключения позволяет пузыриться в стеке так, чтобы его заметили.
Если, с другой стороны, ошибки являются обычным явлением, вы должны оптимизировать их для разработчика, который их проверяет, а
try-catch
предложения являются несколько более громоздкими, чем серияif/elif
илиswitch
.Всегда разрабатывайте API в мышлении того, кто его использует.
источник
Не возвращайте логическое значение, если вы никогда не собираетесь возвращаться
false
. Просто сделайте методvoid
и задокументируйте, что он выдаст исключение (IOException
подходит) при сбое.Причина этого заключается в том, что если вы возвращаете логическое значение, пользователь вашего API может заключить, что он / она может сделать это:
Это не будет работать, конечно; то есть существует несоответствие между контрактом вашего метода и его поведением. Если вы выбрасываете проверенное исключение, пользователь метода должен обработать ошибку:
источник
Если ваш метод имеет возвращаемое значение, создание исключения может удивить его пользователей. Если я вижу, что метод возвращает логическое значение, я вполне уверен, что он вернет true, если он завершится успешно, и false, если нет, и я буду структурировать свой код, используя предложение if-else. Если ваше исключение в любом случае будет основано на перечислении, вы также можете вместо этого вернуть значение перечисления, аналогично windows HResults, и сохранить значение перечисления, когда метод завершится успешно.
Также раздражает, что метод вызывает исключение, когда это не последний шаг в процедуре. Необходимость записи контрольного потока и переадресации в блок захвата является хорошим рецептом для спагетти, и его следует избегать.
Если вы идете вперед с исключениями, попробуйте вернуть void вместо этого, пользователи поймут, что это удастся, если не будет выдано никаких исключений, и никто не будет пытаться использовать предложение if-else для перенаправления потока управления.
источник