Когда отбрасывать исключение, когда возвращать FALSE? - PullRequest
14 голосов
/ 03 декабря 2008

Я разрабатываю оболочку для сторонней библиотеки функций, которая взаимодействует с некоторым специальным оборудованием. В общем, я хочу инкапсулировать функции 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, либо выкидываем исключение?)

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

Ответы [ 7 ]

9 голосов
/ 03 декабря 2008

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

7 голосов
/ 03 декабря 2008

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

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

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

6 голосов
/ 03 декабря 2008

Читать это: http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

Короче говоря:

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

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

6 голосов
/ 03 декабря 2008

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

3 голосов
/ 03 декабря 2008

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

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

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

1 голос
/ 03 декабря 2008

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

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

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

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

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

0 голосов
/ 03 декабря 2008

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...