if (MyFunction() == CodeErrorType::OneOfError)
{
// обработка ошибки
}
и создавать иерахии исключений, наподобие Java.
Теперь вопрос, как лучше создавать. Для каждого типа делать свои наборы, чтобы было более понятно, что за проблема или ограничиться выделением общих?
Например, есть базовый тип — BaseException, далее APIException(а от него Win32APIException, WSAException), IOException. Далее уже специальные для классов. Например, класс занимается соединением с сервером и обменом даными, тогда можно: AuthException, PacketFormatException, etc.
Еще хотел сделать сокрытие ошибок разного уровня. Тоесть смысл в том, что если какой-либо класс внутри использует класс для работы с сокетами, то он наружу никогда не отдаст исключение от сокета, он выдаст свое исключение.
Здравствуйте, techgl, Вы писали:
T>Я решил полностью уйти он кода вида
"Никогда не говори никогда" :)
К чему этот максимализм? Каждую задачу надо решать подходящим молотком.
"Обработка ошибки" — это на всегда тупой вывод massagebox-ов или очередной строки в лог.
Зачастую обработка ошибки — это важная часть алгоритма, и относить ее непонятно куда, где будет поставлен catch, просто-напросто ухудшит восприятие кода читателем, что является кю.
Поэтому не надо упираться в то, чтобы _все_ ошибки обрабатывались единообразно. Но _единообразные_ ошибки следует обрабатывать одинаково :)
T>Еще хотел сделать сокрытие ошибок разного уровня. Тоесть смысл в том, что если какой-либо класс внутри использует класс для работы с сокетами, то он наружу никогда не отдаст исключение от сокета, он выдаст свое исключение.
А зачем сокрытие? В java выводится трасса исключения. Вы хотите реализовать вручную трассировку исключений?
Критериями могут быть (в порядке убывания важности):
1. Вероятность возникновения ошибки. Другими словами — насколько ошибка походит на исключение. Если веротность возникновения ошибки не велика — это одно дело, но если ошибка возникает в 50% случаев выполнения кода — реализация ее как исключения может дорого стоить (в частности по производительности).
2. Читаемость кода. Как код будет проще / понятнее?
3. Гибкость. Какой подход обеспечит наибольшую гибкость при возможных (насколько возможных?) изменениях?
4. Мнение коллег. Если над проектом работает команда, нужно выработать один подход.
5. Собственная интуиция. (хотя кто-то поставит ее на первое место)
Здравствуйте, techgl, Вы писали:
T>Я решил полностью уйти он кода вида
T>CodeErrorType MyFunction()
T>if (MyFunction() == CodeErrorType::OneOfError) T>{ T> // обработка ошибки T>}
Поддерживаю
T>и создавать иерахии исключений, наподобие Java. T>Теперь вопрос, как лучше создавать. Для каждого типа делать свои наборы, чтобы было более понятно, что за проблема или ограничиться выделением общих? T>Например, есть базовый тип — BaseException, далее APIException(а от него Win32APIException, WSAException), IOException. Далее уже специальные для классов. Например, класс занимается соединением с сервером и обменом даными, тогда можно: AuthException, PacketFormatException, etc.
Мой опыт. Надо сделать базовый класс AppException. Пока всё правильно. Далее не надо делать ничего. Серьёзно.
Т.е. кидаешь везде этот класс. Ловишь везде этот класс. Всё просто, понятно и без кучи лишнего кода.
Если в какой-то момент требуется как-то по особому обрабатывать SocketException. То вводишь этот класс. Естественно наследуешь его от базового. Где надо его кидешь. Где надо его ловишь. Весь остальной код работает по прежнему (т.к. SocketException отнаследован от базового класса).
Вывод. Если ты начнёшь сразу мутить громадную иерархию исключений, типа APIException, Win32APIException, WSAException, IOException, то не поимешь ничего кроме кучи убитого времени. Ничего кроме "стройности и красоты" в кавычках ты не получишь.
T>Еще хотел сделать сокрытие ошибок разного уровня. Тоесть смысл в том, что если какой-либо класс внутри использует класс для работы с сокетами, то он наружу никогда не отдаст исключение от сокета, он выдаст свое исключение.
Аналогично. Пока это тебе не надо, не делай. Что ты хочешь за счёт этого получить, кроме "красивости"? Есть какие-то реальные доводы. На это уйдёт много времени и не более.
Здравствуйте, techgl, Вы писали: T>Теперь вопрос, как лучше создавать. Для каждого типа делать свои наборы, чтобы было более понятно, что за проблема или ограничиться выделением общих?
Лучше всего идти от обратного. Надо понимать, что иерархия классов исключений — не прихоть, а решение совершенно определенных прагматических задач.
Поэтому надо начинать с того, какие ошибки и как планируется обрабатывать.
Вообще говоря, крайне полезно описывать все граничные случаи прямо в требованиях к софту. Типа "Если на счету не хватило денег, то ...", "если нет связи с сервером банка, то ...", и т.д.
Многие документы, описывающие требования, грешат излишним оптимизмом. В том плане, что в них завсегда молчаливо предполагается, что все идет как должно идти. Ключ к успеху — описание всех потребных способов реакции на ошибки.
Даже если на все ошибки предполагается ровно 1 способ (показать окошко с текстом ошибки и отправить стек трейс разработчику) — это уже создает хорошую отправную точку.
Итак, когда тебе известно, что ты хочешь написать в catch, вот тогда ты и сможешь понять, какие классы нужны. Классы исключений нужны для того, чтобы обеспечить правильную поимку их блоками Catch, и ни для чего больше. Если у тебя код перехвата сводится к такому:
то нет никакой нужды заводить что-то кроме Exception. Просто бросай Exception с подходящим Message, и дело в шляпе.
Когда тебе захочется обработать что-то более конкретное, например НЕ отправлять разработчикам информацию о "штатных" исключениях (типа той же нехватки денег на счету — какое дело разработчикам до этого? Может у них у самих денег на счету не хватает), тогда и введешь более специфичный класс:
Ну и так далее. Если у тебя есть документированная стратегия восстановления при специфичных типах сбоев — бросай при этих сбоях исключение соответствующего класса. Если нужна какая-то дополнительная информация об условиях возникновения сбоя, то ее можно добавить в свой класс. Ну и так далее.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, techgl, Вы писали: T>>Теперь вопрос, как лучше создавать. Для каждого типа делать свои наборы, чтобы было более понятно, что за проблема или ограничиться выделением общих?
Да, именно так и делаю. Конкретные ситуации, которые нужно отловить и попытаться поправить а не завершать приложение выделяю в отдельное исключение.