Исключения или коды возврата?
От: Bell Россия  
Дата: 11.09.02 10:11
Оценка:
Сабж навеян топиком "Как это сделать" из форума по С++.
Началось все с того, что Юнусов Булат сказал:

atoi в серьезных прогах вообще лучше не использовать - при невозможности конвертации она ексепшенсы не 
отбрасывает, другими словами прога будет работать до первой неудачной конвертации - потом начнет 
выдавать крутой бред.

С чем я полностью согласен.
На это Vladik ответил , что
Ненавижу эксепшины. (На мой взгляд слабый аргумент)
atoi просто тихо вернет 0. А если я эксепшин в нужном месте не отловлю - тогда да, действительно будет весело.


Но собственно дело конечно же не в atoi (вернее не только в atoi). Дело в принципе — использовать, или не использовать исключения (ну или коды возврата)?

На мой вгляд глупо было бы отдавать предпочтение либо только исключениям, либо только кодам возврата, ибо назначение у этих двух механизмов несколько разное.
Я конечно не открою америку, если скажу, что коды возврата следует использовать тогда, когда есть готовый вариант поведения или готовая реакция на некоторое нестандартное событие. Ну например неправильный ввод данных. Можно спокойно проигнорировать некорректные данные, заменив их чем-то осмысленным(конечно если это допустимый вариант поведения), можно оповестить об этом пользователя и попросить его повторить ввод. Исключения для этого вовсе не обязательны. Главное — чтобы была возможность распознать некорректность данных на нужном этапе (в случае с пресловутой atoi сделать это без дополнительных усилий нельзя), и выбрать нужный вариант поведения.
Теперь рассмотрим такую ситуацию:
Идет формирование некоторой сложной модели, которая весьма чувствительна к корректности исходных данных (любое несоответствие делает дальнейшую работу ненужной). Зачем мне в куче мест вставлять проверки на значения кодов возврата сервисных функций, после чего просто говорить return? Да делать это еще по всему дереву вызовов? Не проще ли выкинуть исключение из этой сервисной функции, и поймать его на верхнем уровне?
ИМХО код будет несколько проще и понятнее.

Ну так вот, а что думает общественность по этому поводу?
Как мне уже сказали, у меня найдется множество аппонентов
Надеюсь, что и сторонников будет не меньше
Любите книгу — источник знаний (с) М.Горький
Re: Исключения или коды возврата?
От: Юнусов Булат Россия  
Дата: 11.09.02 10:19
Оценка:
Здравствуйте Bell, Вы писали:

Время все уже расставило по своим местам.
Народ потянулся в дотнет — тама ексепшенсы рулят.
Re: Исключения или коды возврата?
От: Torero2002 Россия  
Дата: 11.09.02 10:22
Оценка:
И все-таки эксепшены. Аргументы: информативно, удобно, читабельно. Особенно это актуально при COM разработке — очень часто одного кода возврата бывает мало, более того большинство просто возвращает E_FAIL про который вообще ничего нельзя сказать.

А по поводу:

"Ненавижу эксепшины. (На мой взгляд слабый аргумент)
atoi просто тихо вернет 0. А если я эксепшин в нужном месте не отловлю — тогда да, действительно будет весело"

могу сказать следующее: если ты этот тихий ноль не отловишь, то проблем будет не меньше.
Smart? Prove it!
Re: Исключения или коды возврата?
От: SiGMan / iO UpG Южная Корея www.ioupg.com
Дата: 11.09.02 10:37
Оценка:
Иногда ИМХО удобнее сочетать оба способа
А с проверкой кода ошибки можно поступить следующим образом:
Поиметь легкий класс вокруг enum ошибок. В класса есть дополнительный флаг — "проверенно" ( мин нет, Сапер Сидоров ) Оператор равенства ( и неравенства заодно ) сбрасывает этот флаг. В деструкторе имеется проверка на наличие ошибки ( код ошибки != ОК ) и взведенного флага ( не проверил, скотина! ) и там выбрасывать исключение или поставить assert. Т.к. для клиента класса данная обертка будет прозрачна ( в смысле, тоже самое что и enum ) то потом ( после отладки итд ) его можно будет просто заменить на этот самный enum.
Т.е. как это выглядит в коде:
( пример применения )
class MyClass {
public:
    enum Results 
    {
        RES_UNKNOWN            = 1,
        RES_ERROR1,
        RES_FATALERROR,
        RES_MINDBLOWNERROR,
        RES_MAX
    };
    

    static const ResultTable results[ RES_MAX ];
    typedef ResultClass< results, Results > Result;
    
    // 
    
    Result SomeMethod() 
    {
        if ( bad_bad ) {
            return RES_ERROR1;
        }
        
        return OK;
    }
};
....
MyClass obj;
if ( obj.SomeMethod() != OK ) .... /// тут все будет ок
...
obj.SomeMethod(); /// а тут при возврате кода ошибки отличного от ОК, произойдет assert


Система, конечно, не без недостатков, но вдруг кому-то понадобится...
io /l、 
゙(゚、 。 7
 l、゙ ~ヽ
 じしf_, )ノ
Re[2]: Исключения или коды возврата?
От: Admiral Украина  
Дата: 11.09.02 11:22
Оценка:
Здравствуйте Юнусов Булат, Вы писали:

ЮБ>Здравствуйте Bell, Вы писали:


ЮБ>Время все уже расставило по своим местам.

ЮБ>Народ потянулся в дотнет — тама ексепшенсы рулят.

Но MS рекомендует ими не увлекаться.
Performance Tips and Tricks in .NET Applications
Re[2]: Исключения или коды возврата?
От: Lexey Россия  
Дата: 11.09.02 11:55
Оценка:
Здравствуйте Torero2002, Вы писали:

T>И все-таки эксепшены. Аргументы: информативно, удобно, читабельно. Особенно это актуально при COM разработке — очень часто одного кода возврата бывает мало, более того большинство просто возвращает E_FAIL про который вообще ничего нельзя сказать.


Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение. А коды возврата к делу не имеют никакого отношения — никто не мешает надефайнить кучу своих кодов возврата (что, кстати, придется делать и при использовании эксепшенов).

T>А по поводу:


T>"Ненавижу эксепшины. (На мой взгляд слабый аргумент)

T>atoi просто тихо вернет 0. А если я эксепшин в нужном месте не отловлю — тогда да, действительно будет весело"

T>могу сказать следующее: если ты этот тихий ноль не отловишь, то проблем будет не меньше.


Сильно зависит от задачи.

Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.
"Будь достоин победы" (c) 8th Wizard's rule.
Re[3]: Исключения или коды возврата?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.09.02 12:02
Оценка: 32 (1) +2
Здравствуйте Admiral, Вы писали:

A>Но MS рекомендует ими не увлекаться.

A>Performance Tips and Tricks in .NET Applications

MS понятие растяжимое. Это советует конкретный сотрудник. И надо всегда относиться к этому с оглядкой.
Вот смотри. Это тот пример который он привел
public static void Main(string[] args){
  int j = 0;
  for(int i = 0; i < 10000; i++){
    try{   
      j = i;
      throw new System.Exception();
    } catch {}
  }
  System.Console.Write(j);
  return;   
}


А это моя переделка, ибо то что он предлагает оценивать на глаз, та еще с таким малым количеством итераций это поленйший маразм.
public static void Main(string[] args){
  int j = 0;

  int st;
  //Подождем чтобы система устаканилась после загрузки
  System.Threading.Thread.Sleep(1000);
  st = Environment.TickCount;
  for(int i = 0; i < 1000000; i++){
    try{   
      j = i;
      throw new System.Exception();
    } catch {}
  }
  Console.WriteLine((double)(Environment.TickCount-st)/1000000+" ms per cycle");
}


Результат выполения на средненькой по нынешним временам машинке (Celeron 1000) дает такой результат

0,015993 ms per cycle

Т.е. на вызов одного эксепшена вместе с присваиванием уходит меньше двух стотысячных секунды. И это он называет "tremendous overhead"? Даже не смешно. Чтобы это почувствовать надо генерить десятки тысяч эксепшенов в секунду.
... << J 1.0 alpha 4 >>
AVK Blog
Re[3]: Исключения или коды возврата?
От: Bell Россия  
Дата: 11.09.02 12:21
Оценка:
Здравствуйте Lexey, Вы писали:

L>Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение. А коды возврата к делу не имеют никакого отношения — никто не мешает надефайнить кучу своих кодов возврата (что, кстати, придется делать и при использовании эксепшенов).

Можно подробнее — что я должен дефайнить при использовании исключений?
...
L>Сильно зависит от задачи.
Естественно. О чем я и говорил. Если есть допустимый вариант поведения при (возможном) возникновении некоторой нестандартной ситуации — значит это не исключительная ситуация.

L>Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.

А вот в CORBA зачем-то предусмотрены механизмы выброса исключений из серверов и последующей их обработки на клиентах...
Любите книгу — источник знаний (с) М.Горький
Re[4]: Исключения или коды возврата?
От: George Seryakov Россия  
Дата: 11.09.02 13:42
Оценка:
Здравствуйте Bell, Вы писали:

L>>Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение.


Ой, нужно.

L>>А коды возврата к делу не имеют никакого отношения — никто не мешает надефайнить кучу своих кодов возврата (что, кстати, придется делать и при использовании эксепшенов).

B>Можно подробнее — что я должен дефайнить при использовании исключений?

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

L>>Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.


B>А вот в CORBA зачем-то предусмотрены механизмы выброса исключений из серверов и последующей их обработки на клиентах...


Да. И еще нет никого другого способа обработать ошибку в конструкторе класса. Но просто-напросто все ошибки компилятора, которые я встречал в 6-ке, были связаны с обработкой исключений.
GS
Re[3]: Исключения или коды возврата?
От: Torero2002 Россия  
Дата: 11.09.02 13:52
Оценка:
Здравствуйте Lexey, Вы писали:

L>Здравствуйте Torero2002, Вы писали:


T>>И все-таки эксепшены. Аргументы: информативно, удобно, читабельно. Особенно это актуально при COM разработке — очень часто одного кода возврата бывает мало, более того большинство просто возвращает E_FAIL про который вообще ничего нельзя сказать.


L>Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение. А коды возврата к делу не имеют никакого отношения — никто не мешает надефайнить кучу своих кодов возврата (что, кстати, придется делать и при использовании эксепшенов).


Коды возврата в COM, на мой взгляд, значит примерно одно тоже: либо ты послан, либо нет. Ведь не даром "умные дядьки" из Microsoft и в comdef.h и в ATL ввели интерфейсы/классы поддержки COM исключений. Хотя послушать аргументы в пользу использования кодов возврата в COM я бы послушал.

T>>А по поводу:


T>>"Ненавижу эксепшины. (На мой взгляд слабый аргумент)

T>>atoi просто тихо вернет 0. А если я эксепшин в нужном месте не отловлю — тогда да, действительно будет весело"

T>>могу сказать следующее: если ты этот тихий ноль не отловишь, то проблем будет не меньше.


L>Сильно зависит от задачи.


L>Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.
Smart? Prove it!
Re[5]: Исключения или коды возврата?
От: Bell Россия  
Дата: 11.09.02 14:29
Оценка:
Здравствуйте George Seryakov, Вы писали:

GS>Здравствуйте Bell, Вы писали:


L>>>Так-так, нужно сюда Влада позвать. Он подробно расскажет, почему эксепшены в COM'е — это плохое решение.


GS> Ой, нужно.


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

GS> Способы передать информацию об ошибке. Либо однотипный класс исключения и куча кодов возврата, либо куча классов исключения.


Ладно, это была просто придирка
От этого никуда не деться — информацию об ошибке все равно нужно передавать. Либо код возврата, либо тип исключения, либо некоторая их комбинация.
Но главное все-таки не способ представления информации об ошибке, а способ передачи этой информации.
Как я уже говорил — я не призываю всех отказаться от использования кодов возврата, и начать использовать только исключения. Это просто глупо. Главное — грамотно разобраться где использовать исключение, а где обработать код возврата. ИМХО такой код проще
void somefunc()
{
   ...
   if(bSomeCondition)
      throw SomeException();
}

void f1()
{
...
   somefunc();
}
void f2();
...
void fn();

void g()
{
   f1();
   f2();
   ...
   somefunc();
}

void d()
{
   try
   {
      g();
   }
   catch(SomeException& e)
   {
   ...
   }
}

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

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

GS> Да. И еще нет никого другого способа обработать ошибку в конструкторе класса. Но просто-напросто все ошибки компилятора, которые я встречал в 6-ке, были связаны с обработкой исключений.

Ну так у ж и все? Ошибок, связанных с использованием шаблонов тоже хватает. Однако это не повод отказаться от их использования... Хотя это (наличие ошибок) конечно же весьма огорчает
Любите книгу — источник знаний (с) М.Горький
Re[4]: Исключения или коды возврата?
От: Mink Россия  
Дата: 12.09.02 07:34
Оценка: 4 (1)
Здравствуйте Bell, Вы писали:


L>>Мое личное мнение — эксепшены хороши в клиентском коде. В серверном коде (и особенно в COM-серверах) им не место.

B>А вот в CORBA зачем-то предусмотрены механизмы выброса исключений из серверов и последующей их обработки на клиентах...

А в COM предусмотрен интерфейс IErrorInfo, через который и рекомедуется передавать информацию об ошибках семантического характера. А код возврата HRESULT использовать только для сообщения о наличии ошибки. Передавать через HRESULT свой код нехорошо, поскольку HRESULT используется еще и для сообщения об ошибках системного плана, которые могут возникать при работе системного слоя поддержки COM.

А эксепшены в COMе плохое решение именно потому, что в нем нет такого механизма их передачи через границу процесса
Сила, она в ньютонах
Re: Исключения или коды возврата?
От: Nikita Dolgov Россия http://nikitadolgov.narod.ru/
Дата: 12.09.02 09:32
Оценка: 26 (2)
Здравствуйте Bell,

ИМХО данный документ настолько хорош, что практически закрывает тему:

http://www.objectarchitects.de/arcus/cookbook/exhandling/index.htm
Old C programmers never die. They're just cast into void.
Re: Все зависит от системы
От: Снорк  
Дата: 17.09.02 07:47
Оценка:
Нет такой идеи, которую нельзя было бы испоганить. Исключения, коды возврата — один хрен в этом смысле.

Хороший пример из COM — с параметрами [out, retval]. Что происходит при генерации wrapper'а? На сях — каждый метод и свойство дублируются — методы — raw, свойства — Get/Set. Хочешь обрабатывать коды возврата — флаг тебе в руки, хочешь ловить исключения — тоже вперед и с песней. Вот это продуманная вещь.

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

Хочу спросить — а какие есть мнения по аналогичному вопросу: IErrorInfo сотоварищи vs. GetLastErrorInfo? (Тексты и коды передаются вместе).
Re[4]: Исключения или коды возврата?
От: WPooh США  
Дата: 20.09.02 18:13
Оценка:
Здравствуйте AndrewVK, Вы писали:

Не спора ради, а уточнения для.
AVK>А это моя переделка, ибо то что он предлагает оценивать на глаз, та еще с таким малым количеством итераций это поленйший маразм.
Пример действительно не демонстрирует никакого overhead-а.
IMHO, проблема возникает при раскрутке стека вызовов с поиском ближайшего обработчика исключений.
Может оно сейчас эффективней реализуется, прогресс ушел дальше...

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

AVK>Результат выполения на средненькой по нынешним временам машинке (Celeron 1000) дает такой результат

Не такая она и средненькая.

Успехов!
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[5]: Исключения или коды возврата?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.09.02 18:20
Оценка:
Здравствуйте WPooh, Вы писали:

WP>IMHO, проблема возникает при раскрутке стека вызовов с поиском ближайшего обработчика исключений.

WP>Может оно сейчас эффективней реализуется, прогресс ушел дальше...

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

AVK>>Результат выполения на средненькой по нынешним временам машинке (Celeron 1000) дает такой результат

WP>Не такая она и средненькая.

Но студия на ней работает на пределе. По крайней мере разница между ним и AXP 2000+ разительная. Правда на атлоне памяти не 256 а 512 и память DDR333.
... << Янус 1.0 alpha 7 (developers build) >>
AVK Blog
Re[6]: Исключения или коды возврата?
От: WPooh США  
Дата: 23.09.02 04:55
Оценка:
Здравствуйте AndrewVK, Вы писали:

AVK>Ну дядька то в той статье говорил что главный оверхед именно на создание ексепшена идет. А что касаемо раскрутки стека — если приложение грамотно спроектировано то в тех ситуациях когда исключение генериться часто стек до первого кетча будет совсем коротенький.


Про короткий стек — тут писали, что удобно ловить исключение в одном месте, не каждый раз проверять результат выполнения функции и передавать его наверх. Так вот, ИМХО в этом случае и возникает не очень-то короткий стэк до ловушки.
Ну да ладно, тут .NET поднимается, у него вроде бы даже рекомендуется джавовский подход к исключениям. Видимо, механизм переработали.

AVK>>>Результат выполения на средненькой по нынешним временам машинке (Celeron 1000) дает такой результат

WP>>Не такая она и средненькая.

AVK>Но студия на ней работает на пределе. По крайней мере разница между ним и AXP 2000+ разительная. Правда на атлоне памяти не 256 а 512 и память DDR333.

Это-твоя машинка. Разработчика. А есть машинки у клиентов. У них может вообще стоять старый пень 100 мегагерцовый с 64 SIMM.
[off]у нас и некоторых разработчиков не уважают — года по три машины не меняют, гады.[/off]
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[5]: Исключения или коды возврата?
От: adb Россия  
Дата: 30.09.02 05:25
Оценка:
Здравствуйте WPooh, Вы писали:

WP>Здравствуйте AndrewVK, Вы писали:


WP>Не спора ради, а уточнения для.

AVK>>А это моя переделка, ибо то что он предлагает оценивать на глаз, та еще с таким малым количеством итераций это поленйший маразм.
WP>Пример действительно не демонстрирует никакого overhead-а.
WP>IMHO, проблема возникает при раскрутке стека вызовов с поиском ближайшего обработчика исключений.
WP>Может оно сейчас эффективней реализуется, прогресс ушел дальше...

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



Эффективней некуда. В том то вся и прелесть текущей реализации, что оверхэд возникает _только_ при выбрасывании исключения. Потому и советуют их выбрасывать в действительно исключительных ситуациях. Раньше не знаю как у всех, но по крайней мере в нашем компиляторе реализовывалась схема setjmp/longjmp — что дает просто существенный оверхед при _нормальной работе_. Плюс еще и создаются специальные таблицы в сегменте данных, с помошью которых находят обработчики исключений. Собственно поэтому во встроенных системах и реал-тайме, где размер и время работы даже в исключительных ситуациях на вес золота, исключений стараются избегать.
Re[6]: Исключения или коды возврата?
От: WPooh США  
Дата: 01.10.02 07:39
Оценка:
Здравствуйте adb, Вы писали:

adb>Эффективней некуда. В том то вся и прелесть текущей реализации, что оверхэд возникает _только_ при выбрасывании исключения. Потому и советуют их выбрасывать в действительно исключительных ситуациях. Раньше не знаю как у всех, но по крайней мере в нашем компиляторе реализовывалась схема setjmp/longjmp — что дает просто существенный оверхед при _нормальной работе_. Плюс еще и создаются специальные таблицы в сегменте данных, с помошью которых находят обработчики исключений. Собственно поэтому во встроенных системах и реал-тайме, где размер и время работы даже в исключительных ситуациях на вес золота, исключений стараются избегать.


Вот про ваш компилятор — кто это такой, расскажите плиз. Ну или намекните.
Вот у меня вопрос как к специалисту. По стандарту говорится, что деструкторы должны отработать для всех корректно созданных объектов с момента вхождения в try соответствующей ловушки. Как вы осуществляли вызовы деструкторов? Я что-то посмотрел в стандарт, не нашел слов по поводу того, что указатель на деструктор находится первым в таблице методов класса. Да, ежели он виртуальный — он должен быть в vtbl. На этот счет есть флажок или всегда генерируете vtbl и помещаете туда указатель на деструктор в любом случае, вне зависимости от того, виртуальный он или нет? Ну это мелочь, собственно.
А вот более интересно, как определяете какие именно объекты были сконструированы — раскруткой стека и анализом кода? Просто если при нормальной работе overhead-а нет, значит, никакие списки сконструированных объектов не генерируются. Тогда получается, что самая тяжелая операция — анализ на предмет сгенерированных объектов и вызов деструкторов. Это так?
Заранее благодарен за ответ.
К этому моменту у меня внутри 0.5, 0.7, 0.33 (с) НС
Re[7]: Исключения или коды возврата?
От: Anatolix Россия https://www.linkedin.com/in/anatolix/
Дата: 01.10.02 08:11
Оценка:
Здравствуйте WPooh, Вы писали:

WP>Вот про ваш компилятор — кто это такой, расскажите плиз. Ну или намекните.

WP>Вот у меня вопрос как к специалисту. По стандарту говорится, что деструкторы должны отработать для всех корректно созданных объектов с момента вхождения в try соответствующей ловушки. Как вы осуществляли вызовы деструкторов? Я что-то посмотрел в стандарт, не нашел слов по поводу того, что указатель на деструктор находится первым в таблице методов класса. Да, ежели он виртуальный — он должен быть в vtbl. На этот счет есть флажок или всегда генерируете vtbl и помещаете туда указатель на деструктор в любом случае, вне зависимости от того, виртуальный он или нет? Ну это мелочь, собственно.
WP>А вот более интересно, как определяете какие именно объекты были сконструированы — раскруткой стека и анализом кода? Просто если при нормальной работе overhead-а нет, значит, никакие списки сконструированных объектов не генерируются. Тогда получается, что самая тяжелая операция — анализ на предмет сгенерированных объектов и вызов деструкторов. Это так?

Деструкторы вызываются для локальных переменных. Их настоящий тип
известен на момент компиляции и проблем с виртуальностью едесь нет никаких.

Если же ты создал объект по new сам его и грохни. Не хочешь возиться с исключениями auto_ptr тебе в помощь.
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.