Когда повторно вызывать исключение, а когда возвращать FALSE?

Я разрабатываю оболочку для сторонней библиотеки функций, которая взаимодействует с некоторым специальным оборудованием. Итак, в основном, я хочу инкапсулировать функции dll (bool Connect(), void Disconnect() и т. д.) В MyHardwareObject с помощью методов подключения и отключения.

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

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

 bool MyHardwareObject.Connect()
{
    try
    {
        ThirdPartyLibrary.Connect();
    }
    catch (SomeException)
    {
        return false;
    }
    return true;
}

В отличие от

 bool MyHardwareObject.Connect() 
{
    ThirdPartyLibrary.Connect();
    return true;
}

(или во втором случае лучше void MyHardwareObject.Connect(), так как мы либо возвращаем true, либо выкидываем исключение?)

Или что бы вы еще сделали? И самое главное: почему?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
15
0
4 522
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

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

Ответ принят как подходящий

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

В последнее время я больше склоняюсь к «не бросать исключение, если оно того не стоит». Наши исключения выполняют много работы: они регистрируют данные, создают трассировки стека и т. д. Если я просто хочу преобразовать строку в целое число, генерировать исключение, если входная строка имеет неправильный формат, вероятно, не стоит. С другой стороны, у меня есть объекты, которые мне просто не нужны в моей системе, если они не могут быть построены из правильных данных, и в этом случае их конструкторы выдают исключения.

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

Я бы пропустил исключения. В противном случае вы маскируете потенциально важную информацию, которая может быть полезна позже. Я знаю, что вы не используете его сейчас, но что, если вы решите в будущем обрабатывать восстановление по-другому в зависимости от типа ошибки. На этом этапе вам нужно будет отменить весь код, который вы написали, чтобы замаскировать исключение. Хотя я не согласен с @MadKeithV в отношении того, чтобы сделать его истинным / ложным, я думаю, что он имеет смысл обернуть исключение в ваше собственное исключение, которое, возможно, имеет лучшую семантику для вашего приложения.

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

Joris Timmermans 03.12.2008 16:51

Я считаю, что принцип механизма исключения - это теория "быстро потерпеть неудачу".

Вы хотите, чтобы клиентское приложение «быстро выходило из строя» при неудачном соединении?
Если да, просто отбросьте исключение или инкапсулируйте исключение в собственное прикладное исключение.

Если клиент проигнорирует это исключение, его приложение остановится.

Возврат false означает, что клиент может проигнорировать проблему, его приложение все равно может вылететь, но «позже» ...

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

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

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

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

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

Это необходимо - взаимодействие с этим оборудованием является основной задачей приложения. Правильно ли я вас понимаю: вы бы не использовали возвращаемое значение, потому что кто-то может использовать, просто позвонив MyObject.Connect(), без проверки возвращаемого значения, как в if (!MyObject.Connect())...?

Treb 03.12.2008 18:50

Я бы предложил второй. Ответственность за обработку исключения и принятие правильных действий в соответствии с исключением будет лежать на вызывающей стороне. Предположим, Connect выдает исключение AccountExpiredException, NetworkUnavailableException, InvalidCredentialsException и т. д. (Это всего лишь примеры). Я могу предложить пользователю «исправить» исключение (обратитесь к администратору, проверьте сетевой кабель, проверьте имя пользователя / пароль). Я бы даже предложил удалить возвращаемое значение (индикатор) и просто сделать его недействительным. Взгляните на метод SqlConnection Open - он похож на метод Connect - он не возвращает значение, а выдает исключение. Чтобы проглотить такое исключение

 bool MyHardwareObject.Connect()
{
    try
    {
        ThirdPartyLibrary.Connect();
    }
    catch (SomeException)
    {
        return false;
    }
    return true;
}

ИМХО не очень хорошая идея. Я бы порекомендовал вам реализовать шаблон IDisposable. Только мои 2 цента.

Прочтите это: http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

Суммируя:

Может ли вызывающая сторона использовать возвращаемое значение? Сможет ли он вылечить или ошибка конец света? Если это небольшая проблема, используйте код возврата. Если различные состояния происходят одинаково часто (в 50% случаев происходит сбой, в 50% это работает), используйте код возврата, потому что вызывающий должен обрабатывать ситуацию в любом случае, и исключение не помогает.

Вы хотите пропустить дополнительную информацию (например, настройку стороннего устройства, чтобы у кого-то была возможность отладить то, что произошло позже)? Используйте исключение.

Другие вопросы по теме