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

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

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

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

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

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

В отличие от

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

Короче:

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

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

Ответ 5

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

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

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

Ответ 6

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

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

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

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

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

Ответ 7

Я считаю, что принцип механизма исключения - это теория fail fast.

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

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

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