Возврат Исключения VS Ошибка возврата в Try, Catch, Наконец - PullRequest
3 голосов
/ 10 июля 2009

Я почти уверен, что уже знаю ответ, но мне все еще интересно, каково мнение об обработке ошибки в блоке Try, Catch, finally - , но когда вы повторяете себя.

Кстати - я не говорю о пользовательском вводе - я использую его для примера, потому что он ясный и короткий

Рассмотрим этот бит кода ...

try {    
    if (success) {
        return someSuccessMessage;
    }
    else {
        logError("User input not correct format");
        return someErrorMessage; // repeats itself
    }
}
catch (Exception ex) {
    logError(ex.Message);
    return someErrorMessage; // repeats itself
}

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

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

try {    
    if (success) {
        return someSuccessMessage;
    }
    else {
        throw new Exception("User input not correct format");
    }
}
catch (Exception ex) {
    logError(ex.Message);
    return someErrorMessage;
}

Это не лучший пример, но я для краткости собирался повторить код.

Известно, что исключения приводят к снижению производительности, но что вы думаете о такой ситуации?

Ответы [ 6 ]

4 голосов
/ 10 июля 2009

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

Я также настоятельно рекомендую вам регистрировать ex.ToString (), а не ex.Message.

3 голосов
/ 10 июля 2009

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

Относитесь к Исключению как к катастрофическому (центр данных в огне, землетрясении и т. Д.). Таким образом, вы увидите разницу между обработкой «обычной ошибки» и «исключения».

И да, бросание и отлов Exception стоят больших затрат производительности, лучше всего избегать их.

2 голосов
/ 10 июля 2009

Извлеките дублированный код в функцию, если вы чувствуете, что повторение - это проблема.

error_code_t fail (string message) {
    logError(message);
    return someErrorMessage;
}

// ...

try {    
    if (success) {
        return someSuccessMessage;
    }
    else {
        return fail("User input not correct format");
    }
}
catch (Exception ex) {
    return fail(ex.Message);
}

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

1 голос
/ 10 июля 2009

Я бы согласился с вашей логикой в ​​вашем примере, однако, как вы думаете, какое исключение вы обрабатываете в своем блоке обработки исключений по сравнению с вашим программным тестом? Я подозреваю, что ваш блок обработки исключений действительно "на всякий случай, если что-то случилось". Так что все сводится к правилу обработки исключений.

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

Если функциональность вызывается из кода, вы либо захотите проверить результат с помощью некоторого представления статуса, например ответа (HRESULT является ярким примером этого. 0 == SUCCESS,! = 0 == сбой), либо используйте исключения.

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

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

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

Кстати, вы можете записать трассировку стека, а также просто сообщение, используя ToString (), поскольку это даст вам более полезную информацию для решения проблемы.

НТН

1 голос
/ 10 июля 2009

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

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

Это правда, что исключения в C # дороги, поэтому ими не следует злоупотреблять. Сказав, что, когда у вас есть ошибка, 50 мс или около того попадание в производительность, как правило, не имеет значения, поэтому я склонен использовать их для поддержания чистоты кода.

0 голосов
/ 10 июля 2009

в этом случае, я бы на самом деле сказал, что try / catch не нужен, так как ваш if более чем адекватно обрабатывает вашу ошибку

но нижний - стиль, который, как мне кажется, следует использовать для более сложных ситуаций

...