Могу ли я / я должен использовать исключения для проверки ошибок моей программы? - PullRequest
0 голосов
/ 07 декабря 2011

Основной пример здесь - копирование текстового документа. У меня есть следующие строки кода в моей программе:

try
{
    File.Copy(docTemplatePath, docOutputPath, true);
}
catch (IOException e)
{
    MessageBox.Show(e.ToString());
}

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

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

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

Каков общий консенсус?

Спасибо

Ответы [ 5 ]

2 голосов
/ 07 декабря 2011

Вы должны использовать исключения для обработки исключительных случаев .

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

1 голос
/ 07 декабря 2011

IMO, в .Net исключения должны использоваться для управления непредвиденными ошибками.

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

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

Ваш пример - IMO - хороший пример использования исключений. В глобальном масштабе это просто «большая» попытка / уловка функциональности или конкретных задач.

0 голосов
/ 07 декабря 2011

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

Решение о месте, которое входит в уравнение, заключается в принятии решения о том, каким должен быть контракт подпрограммы.Полезным шаблоном является предоставление как версии «Try» подпрограммы, так и версии «Do»;если «пробная» версия не может выполнить запрошенное действие из-за разумно ожидаемой проблемы, это укажет это, возвращая некоторый тип значения ошибки;если версия «Do» не может выполнить запрошенное действие по какой-либо причине, она выдаст исключение.

В качестве простого примера рассмотрим «Integer.TryParse» и «Integer.Parse».Если у вас есть строка, которая может быть или не быть действительным числом, можно вызвать Integer.TryParse.Integer.TryParse будет использовать возвращенный флаг, чтобы указать, был ли анализ успешным;он будет очень счастливо возвращаться независимо от того, был ли анализ успешным или нет, и вызывающая сторона несет ответственность за обеспечение успешного выполнения TryParse перед попыткой использования возвращенного значения.Напротив, Integer.Parse будет возвращаться, только если число было успешно проанализировано.Если число неверно, Integer.Parse сгенерирует исключение.Таким образом, вызывающий код может использовать значение, возвращаемое Integer.Parse, без необходимости проверки его успешности;если Integer.Parse не удалось, он не вернулся бы.Обратите внимание, что Integer.TryParse может генерировать исключения в некоторых действительно исключительных случаях (например, если небезопасный код сделал переданную ссылку String для какого-либо другого типа объекта);единственная гарантия состоит в том, что он не будет генерировать в разумно ожидаемых случаях (например, передается строка типа «XYZ» вместо строки типа «123»).

Небольшое улучшение шаблона Try / Doчтобы подпрограмма принимала делегата, который будет вызван, если что-то пойдет не так.Во многих случаях прохождение делегата было бы излишним, и зачастую трудно заранее решить, какие параметры должен принимать делегат, но этот подход может быть полезен в тех случаях, когда решение о том, следует ли вмешиваться или отказываться от него, может быть определено извнефакторы.Такие ситуации возникают в сценариях связи, где правильным ответом программы на сбой связи может быть сообщение, уведомляющее пользователя о том, что программа испытывает затруднения, и позволяющее пользователю нажать «отмена», но программа должна повторить операцию.несколько раз, если пользователь не делает.Если операция, которую нужно было повторить, составляла небольшую часть общей операции, которую нужно выполнить, выброс исключения в основную строку «окончательно» прекратил бы более крупную операцию, в то время как выполнение попыток без взаимодействия с пользователем может заставить пользователясидеть долго и досадно, пока компьютер не откажется от операции, которую пользователь может знать, что это не удастся (например, из-за того, что батарея просто разрядилась на устройстве, с которым он связывался).Использование делегата обратного вызова обеспечивает оптимальное взаимодействие с пользовательским интерфейсом без привязки кода связи к какой-либо конкретной реализации пользовательского интерфейса.

0 голосов
/ 07 декабря 2011

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

Тем не менее, иногда необходимо использовать исключения. Я полагаю, что int.TryParse и другие методы TryParse в .NET Framework используют исключения, перехватывают их, если это не работает, а затем возвращают false.

Если нет другого способа узнать, открыт ли файл Word, мое мнение таково, что вы можете использовать Исключение для этого. Хорошо, что вы ловите конкретное исключение, потому что другие вещи могут пойти не так. Проблема заключается в том, что IOException может иметь другой источник (то есть папка назначения недоступна и т. Д.). Это верно не только для вашего примера, но и для всех (сложных) потоков, управляемых исключениями. Пример TryParse, который я привел выше, довольно прост, так что здесь нет особых проблем.

Вывод: не делай этого, если только это не единственный способ, которым ты можешь. А затем попробуйте выделить его отдельным методом. Таким образом, если вы найдете лучшее решение, вы всегда можете изменить свою реализацию. Кроме того, попытайтесь поймать наиболее конкретное исключение и имейте в виду, что исключение может иметь несколько источников.

0 голосов
/ 07 декабря 2011

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

ИМХО этолучше проверить значение divider в выражении int r = val/divider;, чем проверить значение DivideByZeroException

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