Как реюзать catch-блоки?
От: Ignoramus  
Дата: 16.11.05 19:15
Оценка: +1
Написал некоторый класс, который внутри себя полностью "прозрачен" и "безопасен" по отношению к исключениям, т.е. нет утечки ресурсов, кругом RAII и все такое , но catch нигде нет.

И вот дошла разработка до самого верхнего, "интерфейсного" класса, который будет предоставлен пользователю.

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

(* не использую сторонних библиотек, исключения могут возникнуть только стандартные и мои собственные)

Итак, я определил какие из интересующих меня стандартных исключений должны быть "завернуты" в MyException, какие MyException я сам буду бросать. Все остальные завертываются в UnknownError (: public MyException ).

Таким образом, получается, мне нужно "обернуть" вызов каждого публичного метода этого "юзерского" класса (включая конструктор) в try/catch с последующим перевыбросом MyException.

Вопросы следующие:

1) Набор блоков catch и код (разбор по типам) в них будет одинаковым для каждого публичного метода юзерского класса. Нет ли способа завернуть их все в какую-нибудь функцию или объект, чтобы не писать несколько раз одно и то же?

2) Какие вообще есть недостатки у такой схемы обработки исключений, которые я возмоно не учел?
Re: Как реюзать catch-блоки?
От: denisku Россия  
Дата: 16.11.05 20:15
Оценка: 4 (1)
Здравствуйте, Ignoramus, Вы писали:

I>1) Набор блоков catch и код (разбор по типам) в них будет одинаковым для каждого публичного метода юзерского класса. Нет ли способа завернуть их все в какую-нибудь функцию или объект, чтобы не писать несколько раз одно и то же?

Только недавно обсуждали здесь
Автор: 0xDEADBEEF
Дата: 05.10.05
Извините за потраченный траффик..
Re: Как реюзать catch-блоки?
От: alexeiz  
Дата: 16.11.05 22:34
Оценка:
Здравствуйте, Ignoramus, Вы писали:

Можно ещё Boost.Python посмотреть. Там такая же стратегия, но на несколько более высоком уровне.
Re: Как реюзать catch-блоки?
От: MuTPu4  
Дата: 17.11.05 15:57
Оценка:
Здравствуйте, Ignoramus, Вы писали:

I>Я решил (кстати, может у кого-нибудь есть другие идеи?), что методы класса не должны бросать что попало, а только исключения определенного класса — например MyException. Я предполагаю, что пользователю будет удобнее централизованно ловить один тип исключений, а не копаться в исключениях разных уровней.

I>...
I>Таким образом, получается, мне нужно "обернуть" вызов каждого публичного метода этого "юзерского" класса (включая конструктор) в try/catch с последующим перевыбросом MyException.

У меня сейчас такая же проблема, только еще куча сторонних библиотек Вовсю использую exception filter но этого все равно не достаточно. Склоняюсь к выводу что исключения С++ не предназначены для таких задач, получается, что для трансляции коды вовзврата и то удобнее, а пока везде понатыканы catch.

//для исключений:
try {
    can_throw( );
}
catch( ... ) {
    exception_filter( );
}

//для кодов:
check_ret( can_fail( ) );


Ну и где же удобство?
Короче, было бы здорово, если бы кто-то подсказал красивое решение, а то тут и до макросов не далеко
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Как реюзать catch-блоки?
От: megawatt Россия http://ruby.inuse.ru
Дата: 17.11.05 16:10
Оценка: +1
Здравствуйте, Ignoramus, Вы писали:

I>Я решил (кстати, может у кого-нибудь есть другие идеи?), что методы класса не должны бросать что попало, а только исключения определенного класса — например MyException. Я предполагаю, что пользователю будет удобнее централизованно ловить один тип исключений, а не копаться в исключениях разных уровней.


I>(* не использую сторонних библиотек, исключения могут возникнуть только стандартные и мои собственные)


I>Итак, я определил какие из интересующих меня стандартных исключений должны быть "завернуты" в MyException, какие MyException я сам буду бросать. Все остальные завертываются в UnknownError (: public MyException ).


Унаследуйся от std::exception, и не придется ничего заворачивать ИМХО
Re[2]: Как реюзать catch-блоки?
От: srggal Украина  
Дата: 21.11.05 15:39
Оценка:
Здравствуйте, MuTPu4, Вы писали:

MTP>Короче, было бы здорово, если бы кто-то подсказал красивое решение, а то тут и до макросов не далеко

Смотрели по ссылке в этом сообщении ?
Re: Как реюзать catch-блоки?
Автор: denisku
Дата: 16.11.05
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: Как реюзать catch-блоки?
От: Аноним  
Дата: 21.11.05 17:20
Оценка:
Здравствуйте, MuTPu4, Вы писали:

MTP>У меня сейчас такая же проблема, только еще куча сторонних библиотек Вовсю использую exception filter но этого все равно не достаточно. Склоняюсь к выводу что исключения С++ не предназначены для таких задач, получается, что для трансляции коды вовзврата и то удобнее, а пока везде понатыканы catch.


MTP>
MTP>//для исключений:
MTP>try {
MTP>    can_throw( );
MTP>}
MTP>catch( ... ) {
MTP>    exception_filter( );
MTP>}

MTP>//для кодов:
MTP>check_ret( can_fail( ) );
MTP>


MTP>Ну и где же удобство?

MTP>Короче, было бы здорово, если бы кто-то подсказал красивое решение, а то тут и до макросов не далеко

>получается, что для трансляции коды вовзврата и то удобнее


то есть писать что то типа

int ret;
.....
ret = can_be_bad () ;
if (ret < 0)
{
    // плохая ветка   
    return ret;
}
....
//продолжаем работать


лучше чем регинирить исключения
просто люди считают что, примененяя exception, они решают все свои проблеммы в плане обработки ошибок.
Это не так. Всё равно обработкой ошибок надо заниматься.
Re[3]: Как реюзать catch-блоки?
От: MuTPu4  
Дата: 22.11.05 19:33
Оценка:
Здравствуйте, srggal, Вы писали:

S>Смотрели по ссылке в этом сообщении ?

S>Re: Как реюзать catch-блоки?
Автор: denisku
Дата: 16.11.05

Кончено, я же написал что использую. Отличная техника, респект автору. А вообще, я сейчас расставил все эти try-catch для трансляции и не так уж много получилось , это у страха глаза велики.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Как реюзать catch-блоки?
От: MuTPu4  
Дата: 22.11.05 19:33
Оценка:
А>то есть писать что то типа

А>
А>int ret;
А>.....
А>ret = can_be_bad () ;
А>if (ret < 0)
А>{
А>    // плохая ветка   
А>    return ret;
А>}
А>....
А>//продолжаем работать
А>


А>лучше чем регинирить исключения

А>просто люди считают что, примененяя exception, они решают все свои проблеммы в плане обработки ошибок.
А>Это не так. Всё равно обработкой ошибок надо заниматься.
Это понятно. Собственно, речь идет не о стратегии обработки исключений/ошибок в программе, а всего лишь о трансляции исключений одного типа в другой. Например, как в моем случае, сторонняя библиотека использует свою иерархию исключений, а я — свою и мне не хочется выпускать исключения библиотеки наружу. Поскольку я использую эту библиотеку не в одной/двух функциях, а пишу враппер над ней, то почти в каждом методе моего класса приходится расставлять try-catch, хотя, обрабатывать исключения я не собираюсь. А коды возврата по своей сути предназначены для перехвата и дальнейшей передачи вверх, что иногда удобно. Позволю себе еще разок привести свой пример для нагладности:

//Везде исключения. Самый неудобый вариант, хоть и с exception_filter.
//Если оборачивать так каждый метод/вызов то читаемость очень сильно падает.
//Кстати, интересно насколько это приемлемо с точки зрения эффективности.
try {
    can_throw( );
}
catch( ... ) {
    exception_filter( );
}

//Везде коды возврата. На мой взглад, это смотрится несколько лучше.
if( ( ret = can_fail( ) ) == fail )
    return( translate_code( ret ) );

//Работает с сишной библиотекой. Наверх отправляем свои исключения.
//Вот хотелось бы такого синтаксиса...
check_ret( can_fail( ) );


Ну да ладно, особой проблемы уменя нет, да и у автора топика, как я понял, тоже. Так что не буду больше никому морочить голову .
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Как реюзать catch-блоки?
От: Ignoramus  
Дата: 23.11.05 07:13
Оценка:
Здравствуйте, MuTPu4, Вы писали:

MTP>Ну да ладно, особой проблемы уменя нет, да и у автора топика, как я понял, тоже. Так что не буду больше никому морочить голову .


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

Проблема возникает в коде, который не является "вещью в себе", а имеет некоторый внешний интерфейс к клиентскому коду, т.е. практически всегда . Исключение составляет только контейнеры а ля STL и тому подобный код, который просто "прозрачно" пропускает через себя все исключения (т.е. подразумевает что клиент сам знает что это за исключения и что с ними делать).

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

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

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

Для этого, как ты правильно заметил, нужно везде ставить обертки try/catch почти во всех классах всех уровнях. Доходит даже до try/catch function-block конструкторов (их единственное применение ).

Так вот, это настолько утомительно и код становится настолько уродским, что я пришел к выводу, что это неоправданно дорогая цена за возможность получить на верхнем уровне информацию вроде "Не удалось сохранить документ потому что диск переполнен". Ограничиваюсь просто "Не удалось сохранить документ" — т.е. единственной затычкой на все исключения в данной функции/команде "Сохранить документ". Максимум — ставлю дискриминаторную затычку на методы только верхнего уровня, вроде описанной в данном топике.

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



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