Как избежать программирования на основе исключений в методах «подключения / отключения» - PullRequest
1 голос
/ 01 октября 2011

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

Я написал свои методы подключения как voidConnect (), поэтому я ничего не возвращаю (потому что на самом деле мне ничего не нужно), но я вызову исключение во многих ситуациях:

  1. Если соединение уже существует
  2. Если в MyDeviceInstance есть какие-то неправильные настройки
  3. Если мой метод взаимодействия deviceConnect завершится неудачно (и это самая большая проблема, потому что он вернет int, представляющий много ошибок)

Если Connect возвращает логическое значение вместо void? Будет много возможностей, которые я выброшу в качестве исключения.

Вторая часть этогоВопрос касается другого метода, называемого void Update () .Этот метод может работать, только если MyDeviceInstance уже подключен.В этом случае я буду выдавать исключения, когда:

  1. Соединение не существует
  2. Соединение потеряно по любой причине (и программист не будет ожидать, что это произойдет, но может)
  3. Другие ошибки взаимодействия

Должно ли обновление возвращать значение bool вместо того, чтобы выдавать все эти исключения (по крайней мере, для ограничения распространенных ошибок, таких как "соединение не существует")?

Спасибо за любой ответ

РЕДАКТИРОВАТЬ 1:

Я должен быть более точным в одном: потому что мы говорим о USB устройство, когда я вызову мой метод Обновление , этот метод может завершиться ошибкой в ​​зависимости от устройства (подключено или нет).Более важно, если я повторно подключу устройство, метод взаимодействия снова начнет работать (и обычный метод будет делать то же самое), без необходимости повторного подключения или подобных вещей (я не знаю, как это работает внутри).

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

Ответы [ 5 ]

2 голосов
/ 01 октября 2011

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

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

Если есть неправильные настройки, это исключение и должно выдавать исключение.

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

При вызове обновления ...

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

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

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

Вот еще один пост SO об исключениях:

Попытка понять исключения в C #

2 голосов
/ 01 октября 2011

Исключения - это именно то, что нужно использовать в этой ситуации.

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

  2. Исключения могут предоставить rich информацию о почему звонок не удался.

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

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

2 голосов
/ 01 октября 2011

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

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

Для Connect уже существующее соединение не может быть исключительной ситуацией. Вы можете сделать его идемпотентом, если хотите. Interop deviceConnect терпит неудачу, безусловно, исключительная ситуация. Что-то, чего вы не ожидали. Вы можете вызвать исключения здесь, возможно, отобразив коды выхода в значимые исключения.

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

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

1 голос
/ 02 октября 2011

Если код, который вызывает метод, будет подготовлен для работы с необычными результатами, метод должен указывать необычные результаты с помощью некоторых средств, кроме исключений. Если вызывающий код не будет готов к работе с необычными результатами, то такие результаты должны вызывать исключения. К сожалению, у класса нет возможности волшебным образом узнать, ожидает ли вызывающий объект необычных результатов, если вызывающий не скажет это каким-либо образом. Распространенный шаблон в .net - это предоставление классом пар методов "DoSomething" и "TryDoSomething":

ResultType DoSomething();
Boolean TryDoSomething(ref ResultType result);

Честно говоря, я думаю, что последняя формулировка была бы лучше выражена как:

ResultType TryDoSomething(ref Boolean ok);

или, возможно:

ResultType TryDoSomething(ref Exception ex);

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

ResultType TryDoSomething(Action failureAction);

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

0 голосов
/ 01 октября 2011

если ваши методы Connect / Update могут потерпеть неудачу, тогда непременно верните bool для неудачи / успеха.Вы также можете добавить код ошибки и / или методы / свойства сообщения об ошибке в ваш класс, к которым программист может получить доступ, если ему / ей это нужно.

...