![]() |
Модераторы: Partizan, gambit |
![]() ![]() ![]() |
|
nikitao |
|
||||||
![]() Кот-программист ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1206 Регистрация: 30.8.2005 Где: Спб Репутация: 4 Всего: 26 |
Добрый день.
Хочется разобраться в этой теме. Как я понял единства и стандарта в использовании исключений не наблюдается. К примеру Рихтер и Макконнелл 2 ортогональных мнения высказывают в своих книгах ( как мне показалось). Первый говорит - используйте их как можно больше и лучше. Все минусы с лихвой окупятся их плюсами. Второй - "Генерируйте исключения , только в исключительных ситуациях". В Рихтере приводится пример ( пишу по памяти ) : Есть клиент банка , у него есчь счет. Он хочет перевести деньги на другой счет. Пишем :
И дальше метод Transfer должен генирировать исключения , если не достаточно денег на счету , или доступ к одному из аккаунтов запрещен или просто банковская система повисла и т д. Но это все идет в разрез с тем , что говорит Макконнелл( на мой взгляд ) , потому что какие ж это исключительные ситуации - я вполне могу представить , что денег на счету меньше , чем их хотят перевести. Типичная, а не исключительная ситуация... Очень популярна фраза "Генерируйте исключения , только в исключительных ситуациях". И дальше автор приводит какой то травильный пример. Создается впечатление , что понятие исключительная ситуация у программиста впитывается с молоком матери ![]() Я серьезно , для меня так самое сложное понять для себя - что такое исключительная ситуация. Просто напросто, если я подумал о какой то ситуации , что она может возникнуть - то она уже не исключительная , раз я ее смог предусмотреть. Бывают случаи , когда действительно понятно , когда надо их генерировать. Там деление на 0 или отсутствие доступа к файлу. Тут понятно, что метод ничего не может поделать, поэтому лучше всего кинуть исключение. Но меня же интересуют совершенно другие ситуации. Приведу пример (уже из моей практики ) Есть какой то класс , которые отправляет сообщения на сервер
Это сообщение может не отправиться с 10 причин : доступ этому аккаунту запрещен , внутренняя ошибка сервера , сервер запросил дополнительную авторизация , сообщение не проходит по каким то фильтрам и т д. Считать это исключительными ситуацией или нет ? Это ошибка - безусловна да. Исключительная ситуация - ну у меня язык не поворачивается это назвать исключительной ситуацией , потому что они возникают чаще , чем не исключительные. (Ну вот там такая специфика работы) Тогда здесь лучше коды возврата использовать ( через енумы ) или как то еще ? Проблема еще в том , что я то пишу библиотеку и я не знаю , как ей будет пользоваться ее пользователь. Как ему будет удобнее ( через енумы или через коды возврата ) Или вот еще пример , где не понятно :
Возвращает -1 , если достигнут конец потока. С чего ? Почему он возвращает -1 , а не генерирует исключение ? По этой логике при делении на 0 - надо возвращать бесконечность или минус бесконечность. Хочется выработать какой то внутренний стандарт относительно этого вопроса. Спасибо. -------------------- Жизнь - печальная штука. |
||||||
|
|||||||
wester |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 675 Регистрация: 27.2.2009 Репутация: 4 Всего: 13 |
Я думаю что это все зависит от архитектуры проекта в целом.
Может архитектура закладывает падать при любой ошибке - например медицинская техника, где при любой ошибке безопаснее выключать аппарат что бы не случилось опасности. для биллинга исключения на мой взгляд лучше не закладывать, а все писать в большой лог. Про деление на ноль. Лично я возвращал бы -1. В своих проектах исключения я просто заменяю на енумы. Удобнее и понятнее.
это все вырабатывается собственным опытом. везде писал "лично" ибо все зависит от архитектуры проекта |
|||
|
||||
nikitao |
|
|||
![]() Кот-программист ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1206 Регистрация: 30.8.2005 Где: Спб Репутация: 4 Всего: 26 |
Ну вот на самом деле хочется как раз узнать кому что их личный опыт подсказывает.
wester, я правильно понял , что вы обычно исключения вообще избегаете ? А если в ф-цию передаются неверные параметры ( там null к примеру в кач-ве одного из параметров) вы тоже код возвращаете ? Насчет архитектуры это интересно. Но если предположить , что я пишу библиотеку , то у меня нет всего приложение и значит всей архитектуры в целом. Что тогда делать ? Как считаете ? Это сообщение отредактировал(а) nikitao - 8.6.2011, 23:58 -------------------- Жизнь - печальная штука. |
|||
|
||||
ДобренькийПапаша |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 14.1.2006 Где: г.Москва Репутация: нет Всего: 7 |
nikitao, спасибо за тему. Тоже очень хотелось бы узнать мнение более опытных коллег. Особенно в случае, когда архитектура никакая не ясна. С чётким проектированием и разработкой архитектуры начинаются далеко не все проекты и не во всех компаниях
![]() -------------------- Меня зовут Себастьян Парейра, торговец чёрным деревом. |
|||
|
||||
Stolzen |
|
||||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1041 Регистрация: 17.10.2005 Репутация: нет Всего: 48 |
Я думаю, прежде всего следуюет определиться с методом - какой контракт между ним и вызывающим его?
Например, возьмем класс Iterator в джаве. По контракту, перед вызовом метода next() нужно вызывать метод hasNext(), иначе в некоторый момент можно поймать исключение NoSuchElementException. Ситуация вполне обыденная - мы часто пользуемся итераторами для прохождения по коллекциям, однако мы всегда соблюдаем контракт (и исключение заставляет нас это делать). Поэтому при переводе денег, я думаю, лучше сделать вызов метода hasEnoughMoney - и с чистой совестью бросать эксепшн, если денег на счету нет. Тут -1 или null не вернешь - исключительная ситуация прямо напрашивается. В случае с сервером все исключения, я думаю, можно объеденить по какому-то признаку, и бросать, скажем, два - AuthorisationException, ConnectException. Остальные можно не афишировать, но бросать так же (внутренняя ошибка сервера - большая проблема). В джаве для таких случаев для первых двух лучше использовать checked exception, для остальных - unchecked. Однако при правильной архитектуре сервера потребность в большом количестве исключений отпадет. Например, сделать метод isReachable() и возвращать булеву. После этого делать login() и бросать в нем ConnectionException (его сделать unchecked, если для джавы). Затем передавать какие-либо данные. Ну идея понятна, я думаю. Насчет перечислений - я думаю иногда есть смысл, но лучше перечисление добавлять непосредственно в сам класс и делать его недоступным извне - для сохраниения текущего состояния и быстрой проверки допустимых в текущий момент операций - например, сервер переходит в стостояние CONNECTED после соединения и т.п. Вот тут есть пример из книги EffectiveJava, в котором перечисление используется подобным образом. Некоторые программисты делают так - создают два метода. Один бросает исключение, когда контракт не соблюден, другие же просто возвращают null. Например, poll() и remove() в интерфейсе Queue в джаве задают именно такой контракт. В целом, я думаю, нужно делать так, как удобнее. Проверять на -1 при чтении потока иногда удобнее, хотя я бы сделал метод isEof() и бросал бы исключение (как в паскале). Насчет бесконечности при делении на ноль - так возвращается при некоторых условиях (F тут обозначает float):
Но если тип целый, то никакой бесконечности не может быть, да и целые на ноль не делят обычно. И это исключение служит маячком, что что-то в коде не так - почему-то приходит ноль. Добавлено через 2 минуты и 45 секунд
Нужно проверять это либо с помощью assert либо бросать AssertionException. Тут код, я думаю, возвращать неправильно - исключительная ситуация хорошо поможет в отладке, если каким-то образом случайно передается null. По стектрейсу не составит большого труда определить причину (в большинстве случаев). |
||||||
|
|||||||
wester |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 675 Регистрация: 27.2.2009 Репутация: 4 Всего: 13 |
В последнем проекте использовал исключение только в одном случае исключение - если недоступен интернет-ресурс. В этом случае завершалась работа программы, ибо работать в таком случае нельзя. В остальных случаях я возвращал код ошибки через енумы.
По поводу передачи некорректного параметра - проверяю параметры на разных уровнях. К примеру у меня реализована работа с БД и заполнением ее данными из инета. Данные которые поступают от пользователя, проверяю на первом уровне и если все данные верны, то вызываю методы (второго уровня) заполнения БД. В противном случае возвращаю код ошибки. Этакий Code Contracts , только со своими плюсами. маленькое обсуждение http://stackoverflow.com/questions/161942/...-net-exceptions Это сообщение отредактировал(а) wester - 9.6.2011, 15:35 |
|||
|
||||
mihryak |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 19 Всего: 36 |
т.е. попробовать списать с клиента деньги за услугу, узнать, что их не хвататет - ну и фиг с ним, потом в логе кто-нибудь заметит, так? неприемлимо без блокирующей транзакции, т.к. между проверкой и списанием деньги может списать ещё кто-нибудь так что в этом случае - исключение с откатом, и никак иначе! я придерживаюсь следующих принципов для исключений: - неправильные аргументы - недопустимая операция для текущего состояния - несколько несовместимых причин, из-за которых выполнить операцию невозможно (это исключает появление кодов ошибок c-style) - код неспособен как-либо разумно поступить в сложившейся ситуации например, метод List<T>.Remove(T) может вполне себе спокойно вернуть false, если объект не найден но Dictionary<TKey, TValue)[Tkey] не может придумать, что бы ему такого вернуть, если ключ не найден ServiceClient.SendPost() может завалиться по совсем разным причинам, тут исключение, т.к. использовать коды ошибок в .нете не принято |
|||
|
||||
Fieral |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 250 Регистрация: 10.12.2007 Репутация: нет Всего: 1 |
Для установки эксепшонов работает простое правило: Выбрасывай исключение только когда больше ничего сделать нельзя.
Это автоматически отвечает на вопрос: "Что такое исключительная ситуация?" - это когда больше ничего сделать нельзя. Если можно - разруливай. --------------------
Если собака свернулась калачиком, значит будет дождь, а если сидит выпучив глаза, значит у неё запор. |
|||
|
||||
![]() ![]() ![]() |
Прежде чем создать тему, посмотрите сюда: | |
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |