Re[8]: эксепшины vs коды возврата
От: Vladik Россия  
Дата: 12.09.02 12:09
Оценка:
Здравствуйте Mink, Вы писали:

M>У меня было очень сильное подозрение, что ты их используешь именно так

M>Все, что я могу посоветовать, обратись к первоисточнику, может прояснится сознание

Ну покажи как правильно.
Как все запущенно...
Re[9]: эксепшины vs коды возврата
От: Mink Россия  
Дата: 12.09.02 12:23
Оценка:
Здравствуйте Vladik, Вы писали:

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


M>>У меня было очень сильное подозрение, что ты их используешь именно так

M>>Все, что я могу посоветовать, обратись к первоисточнику, может прояснится сознание

V>Ну покажи как правильно.


Страуструпп, Язык С++, издание 3, глава 14.
Сила, она в ньютонах
Re[10]: эксепшины vs коды возврата
От: Vladik Россия  
Дата: 12.09.02 12:30
Оценка:
Здравствуйте Mink, Вы писали:

V>>Ну покажи как правильно.

M>Страуструпп, Язык С++, издание 3, глава 14.

У меня нету под рукой 3-го издания Страуструпа, оставишь меня в невединии? Пример маленький, неужели так сложно переписать его правильно?
Как все запущенно...
Re[7]: эксепшины vs коды возврата
От: Bell Россия  
Дата: 12.09.02 13:17
Оценка:
Здравствуйте Vladik, Вы писали:

V>Позволю немного упростить пример:


V>
V>if (!OpenFile())
V>  DoAnotherThihg();
V>else
V>{
V>  if(!WriteFile(str))
V>      DoSomething();

V>  CloseFile();
V>}
V>


V>Т.е. CloseFile должно сработать независимо от успеха WriteFile


M>>А вот с try/catch:


V>

V>
V>try
V>{
V>  OpenFile();

V>  try
V>  {
V>    WriteFile();
V>  }
V>  catch(CFileExeption* ) 
V>  {
V>      DoSomething();
V>  }

V>  CloseFile();
V>}
V>catch(CFileExeption* ) 
V>{  
V>  DoAnotherThihg();
V>}
V>



V>Ы?


Ну, постепенно проясняется причины нелюбви к исключениям
Ты хотя бы ради интереса смотрел на диаграмму "Exception classe" в MFC? ИМХО редкостное убожество. С такой системой исключений действительно трудно сделать что-либо номальное. Хотя даже здесь сожно обойтись одним try:

try
{
   OpenFile();
   WriteFile();
   CloseFile();
}
catch(CFileException* e)
{
   if(e->m_cause == /* ошибка открытия */)
      DoAnotherThihg();
   else if(e->m_cause == /* ошибка чтения/записи */)
   {
      DoSomething();
   }
}



конечно этот код не блещет изящностью, к тому же нужно разбираться с возможными значениями m_cause.
НО! Не стоит кричать "ислючения маст дай" из-за откровенно неудачных примеров.
Любите книгу — источник знаний (с) М.Горький
Re[8]: эксепшины vs коды возврата
От: Vladik Россия  
Дата: 12.09.02 13:35
Оценка:
Здравствуйте Bell, Вы писали:

B>Ну, постепенно проясняется причины нелюбви к исключениям

B>Ты хотя бы ради интереса смотрел на диаграмму "Exception classe" в MFC? ИМХО редкостное убожество.

Вообще нелюбовь к исключениям у меня пошла от VCL MFC, хоть и "редкостное убожество", как ты говоришь, но зато не злоупотребляет ими.

B>С такой системой исключений действительно трудно сделать что-либо номальное. Хотя даже здесь сожно обойтись одним try:


B>
B>try
B>{
B>   OpenFile();
B>   WriteFile();
B>   CloseFile();
B>}
B>catch(CFileException* e)
B>{
B>   if(e->m_cause == /* ошибка открытия */)
B>      DoAnotherThihg();
B>   else if(e->m_cause == /* ошибка чтения/записи */)
B>   {
B>      DoSomething();
B>   }
B>}
B>


А как же CloseFile?

B>конечно этот код не блещет изящностью, к тому же нужно разбираться с возможными значениями m_cause.

B>НО! Не стоит кричать "ислючения маст дай" из-за откровенно неудачных примеров.

Хорошо, типа я стал жертвой убожеств в лице MFC и VCL (или по поводу VCL будут возражения?). Каково же все-таки правильное решение с эксепшинами для данного примера с файлом? Кстати, понятно, что CloseFile будет делать деструктор класса файла, но тем не менее его явный вызов хотелось бы оставить как пример кода, который должен быть выполнен независимо от возникновения каких-то отдельных эксепшинов.
Как все запущенно...
Re[9]: эксепшины vs коды возврата
От: Bell Россия  
Дата: 12.09.02 14:07
Оценка:
Здравствуйте Vladik, Вы писали:


V>А как же CloseFile?


V>Хорошо, типа я стал жертвой убожеств в лице MFC и VCL (или по поводу VCL будут возражения?). Каково же все-таки правильное решение с эксепшинами для данного примера с файлом? Кстати, понятно, что CloseFile будет делать деструктор класса файла, но тем не менее его явный вызов хотелось бы оставить как пример кода, который должен быть выполнен независимо от возникновения каких-то отдельных эксепшинов.


Лучший вариант — вообще поместить CloseFile после try — catch блока. Естественно, если он сам не бросает исключений, и если корректно работает на неоткрытом файле. Предвижу ехидные улыбки, но ничего лучшего для данного случая предложить не могу. При несоблюдении этих условий придется втыкать этот вызов в несколько мест, что плохо.
Любите книгу — источник знаний (с) М.Горький
Re: эксепшины vs коды возврата
От: Анатолий СССР  
Дата: 12.09.02 14:43
Оценка: 18 (3)
Несколько сентенций, с вашего позволения:

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

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

Попытка вывода:
Каждый подход хорош на своем месте и в данных обстоятельствах (см. соотвественно п. Конкретика и п.Философия).

С уважением.
Re[10]: эксепшины vs коды возврата
От: m.a.g. Мальта http://dottedmag.net/
Дата: 13.09.02 09:39
Оценка:
Здравствуйте Bell, Вы писали:

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


B>Лучший вариант — вообще поместить CloseFile после try — catch блока. Естественно, если он сам не бросает исключений, и если корректно работает на неоткрытом файле. Предвижу ехидные улыбки, но ничего лучшего для данного случая предложить не могу. При несоблюдении этих условий придется втыкать этот вызов в несколько мест, что плохо.


А как же магические слова "выделение ресурса есть инициализация"? Либо в языке есть деструкторы, либо есть finally.
Re[11]: эксепшины vs коды возврата
От: Bell Россия  
Дата: 13.09.02 09:58
Оценка:
Здравствуйте m.a.g., Вы писали:

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


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


B>>Лучший вариант — вообще поместить CloseFile после try — catch блока. Естественно, если он сам не бросает исключений, и если корректно работает на неоткрытом файле. Предвижу ехидные улыбки, но ничего лучшего для данного случая предложить не могу. При несоблюдении этих условий придется втыкать этот вызов в несколько мест, что плохо.


MAG>А как же магические слова "выделение ресурса есть инициализация"? Либо в языке есть деструкторы, либо

есть finally.
Там выше было замечание, что CloseFile надо вызвать явно (то что файл закрывается в деструкторе — это ясно)
Любите книгу — источник знаний (с) М.Горький
Re[7]: эксепшины vs коды возврата
От: Sergey Zhulin  
Дата: 13.09.02 10:21
Оценка:
Здравствуйте Vladik, Вы писали:

V>
V>try
V>{
V>  OpenFile();

V>  try
V>  {
V>    WriteFile();
V>  }
V>  catch(CFileExeption* ) 
V>  {
V>      DoSomething();
V>  }

V>  CloseFile();
V>}
V>catch(CFileExeption* ) 
V>{  
V>  DoAnotherThihg();
V>}
V>


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


class File
{
  public:
  File(){}
  ~File(){ CloseFile(); }
  open(){ OpenFile(); }
  write( Param params ){}
};

//....//
File file;
try
{
  file.open();
  file.write( someParam );
}
catch(FileOpeningFailed&  )
{
  DoSomething();
}
catch(CFileWritingFailed&  )
{
  DoAnotherThihg();
}


V>Ы?

Чтобы пользоваться исключениями надо и проектировать соответственно, а простая подмена проверки кода возврата на обработку исключений только испортит стройность кода и читабельность, рефакторинг нужен.
Re[12]: эксепшины vs коды возврата
От: Vladik Россия  
Дата: 13.09.02 10:29
Оценка:
Здравствуйте Bell, Вы писали:

MAG>>А как же магические слова "выделение ресурса есть инициализация"? Либо в языке есть деструкторы, либо

B>есть finally.

finally нет в стандарте, и с ним есть свои заморочки (кто-то выступал на эту тему).
Как все запущенно...
Re[8]: эксепшины vs коды возврата
От: Vladik Россия  
Дата: 13.09.02 10:41
Оценка:
Здравствуйте Sergey Zhulin, Вы писали:

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


Не надо таких высокопарных слов. Я привел простой пример. Естественно, изменив архитектуру можно переписать его так, чтобы с исключениями все было гладко. Однако, я изначально делал упор на вредность библиотечных исключений как раз из-за того, что используя уже готовые классы, их архитектуру ты уже не поменяешь нужным под твою задачу образом. Поэтому в конце концов все опять сведется к упавке во вложенные try/catch и прочим маразмам.
Как все запущенно...
Re[13]: эксепшины vs коды возврата
От: m.a.g. Мальта http://dottedmag.net/
Дата: 13.09.02 12:05
Оценка:
Здравствуйте Vladik, Вы писали:

MAG>>>А как же магические слова "выделение ресурса есть инициализация"? Либо в языке есть деструкторы, либо

B>>есть finally.

V>finally нет в стандарте, и с ним есть свои заморочки (кто-то выступал на эту тему).


Зато в стандарте есть деструкторы.
Разве исключения — это прерогатива С++?
Re[9]: эксепшины vs коды возврата
От: Sergey Zhulin  
Дата: 13.09.02 12:16
Оценка:
Здравствуйте Vladik, Вы писали:

V>Здравствуйте Sergey Zhulin, Вы писали:


V>Не надо таких высокопарных слов. Я привел простой пример. Естественно, изменив архитектуру можно переписать его так, чтобы с исключениями все было гладко. Однако, я изначально делал упор на вредность библиотечных исключений как раз из-за того, что используя уже готовые классы, их архитектуру ты уже не поменяешь нужным под твою задачу образом. Поэтому в конце концов все опять сведется к упавке во вложенные try/catch и прочим маразмам.


А не надо простых примеров, если говоришь о глобальных вещах, типа "никогда не используй исключения в библиотеках". На оба подхода можно написать чушь со вложенными try/catch или протаскивая кучу кодов возврата с switch или if/else if/else и тд.

Участвую в разработке большого проекта, в котором присутствует большое число компонент и библиотек, разработанных внутри компании и третьими фирмами. Изначально была продумана стратегия обработки исключений. Ни одного места в исходниках нет со вложенными try/catch. Принимаю участие в code review, поэтому могу говорить практически за весь исходный код проекта, за исключением небольших компонент разработанных очень давно или на Си.

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

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

С уважением Сергей.
Re[14]: эксепшины vs коды возврата
От: Vladik Россия  
Дата: 13.09.02 12:40
Оценка:
Здравствуйте m.a.g., Вы писали:

V>>finally нет в стандарте, и с ним есть свои заморочки (кто-то выступал на эту тему).

MAG>Зато в стандарте есть деструкторы.

Я рад. Предлагаешь весь код, который должен быть выполнен в случае неудачи упаковывать в деструктор?

MAG>Разве исключения — это прерогатива С++?


См. самое первое мое письмо. Обсуждаем исключительно С++.
Как все запущенно...
Re[2]: эксепшины vs коды возврата
От: Sergey Zhulin  
Дата: 13.09.02 12:47
Оценка:
Здравствуйте Patalog, Вы писали:

P>В доконку хотел бы подкинуть пост из недр "знаменитого" топика "Выйти из двух циклов сразу" http://www.rsdn.ru/forum/Message.aspx?mid=61162&only=1
Автор: m.a.g.
Дата: 06.06.02

P>Как насчет данного случая? В плане применябельности эксепшенов.

Я встречал и более корявый код:


//..
try
{
  if( RIGHT_VALUE != someVariable ) throw SomeException;
}
catch(SomeException&)
{
  someVariable = RIGHT_VALUE;
}
//..


Этот кусок кода многое говорит о разработчике, но ничего за и/или против использования механизма исключений.
Re[10]: эксепшины vs коды возврата
От: Vladik Россия  
Дата: 13.09.02 12:51
Оценка:
Здравствуйте Sergey Zhulin, Вы писали:

SZ>Участвую в разработке большого проекта, в котором присутствует большое число компонент и библиотек, разработанных внутри компании и третьими фирмами. Изначально была продумана стратегия обработки исключений. Ни одного места в исходниках нет со вложенными try/catch. Принимаю участие в code review, поэтому могу говорить практически за весь исходный код проекта, за исключением небольших компонент разработанных очень давно или на Си.


Я тоже не вчера родился. Мой опыт говорит, что исключения в С++ ничем кроме геморроя с try/catch и вылетом неизвестно откуда неизвестно куда не оборачиваются. За редким исключением.

SZ>Нету вредности исключений пробрасываемых из библиотек, есть вредность плохо написанных библиотек, в которых применение исключений приводит к кошмару.


По поводу плохих библиотек я уже писал. Возможно когда я увижу правильную библиотеку, я изменю свое мнение.

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


Именно так я и делаю. Я не против исключений вообще, я против маразмов типа:


bool success=true;
    try
    {
        f();
    }
    catch(exception)
    {
        success=false;
    }

    if (success)
    {
    ...
    }
    else
    {
    ...
    }


которые неизбежно получаются при широком использовании эксепшинов, особенно в левосторонних библиотеках.
Как все запущенно...
Re[11]: эксепшины vs коды возврата
От: Sergey Zhulin  
Дата: 13.09.02 13:12
Оценка:
Здравствуйте Vladik, Вы писали:

V>Я тоже не вчера родился. Мой опыт говорит, что исключения в С++ ничем кроме геморроя с try/catch и вылетом неизвестно откуда неизвестно куда не оборачиваются. За редким исключением.


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

Например:

class SomeClass
{
  bool m_bInit;
public:
  SomeClass():m_bInit(false){}
  int init()
  {
    bool bRet = true;
    if( !bInit )
    {
      //Инициализация
      if( bProblem ) bRet = false;
    }
    return bRet;
  }

  bool someFunction()
  {
    if( !bInit ) return false;
    //..выполнить действия
    return true;
  }
};


так вот, получается, что для обеспечения инварианта каждый метод класса должен содержать проверку индикаторов. Инициализацию невозможно поместить в конструктор, так как нету кода возврата. Это простейший случай, для инициализации объекта, но если после исполнения какого-нибудь метода инвариант нарушен, то с таким объектом можно продолжать работать не зная о том, что он более не валиден, и никто об этом не просигналит, если забыли проверить возвращенное значение.
Re[15]: эксепшины vs коды возврата
От: Sergey Россия  
Дата: 13.09.02 13:21
Оценка:
Здравствуйте Vladik, Вы писали:

V>>>finally нет в стандарте, и с ним есть свои заморочки (кто-то выступал на эту тему).

MAG>>Зато в стандарте есть деструкторы.

V>Я рад. Предлагаешь весь код, который должен быть выполнен в случае неудачи упаковывать в деструктор?


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


try
{
   struct closer
   {
       closer(A &owner) : _a(owner) {}
       ~closer() { _a.CloseFile(); }
   private:
       A _a;
   };

   OpenFile();
   closer(*this);
   WriteFile();
}
catch(CFileException* e)
{
   if(e->m_cause == /* ошибка открытия */)
      DoAnotherThihg();
   else if(e->m_cause == /* ошибка чтения/записи */)
   {
      DoSomething();
   }
}
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[12]: эксепшины vs коды возврата
От: Vladik Россия  
Дата: 13.09.02 13:27
Оценка: -1
Здравствуйте Sergey Zhulin, Вы писали:

SZ>Хорошо. Тогда как с помощью кода возврата обеспечить инвариант класса, если проблемы могут возникнуть при конструировании объекта без использования отложенной инициализации и членов индикаторов?


Кстати, опять возвращаясь к моему первому письму — исключения в конструкторах в С++ как-бы есть, но работают настолько криво, что все-равно лучше их там не использовать.

SZ>Например:


SZ>class SomeClass

SZ>{
SZ> bool m_bInit;

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

SZ>public:

SZ> SomeClass():m_bInit(false){}
SZ> int init()
SZ> {
SZ> bool bRet = true;
SZ> if( !bInit )
SZ> {
SZ> //Инициализация
SZ> if( bProblem ) bRet = false;
SZ> }
SZ> return bRet;
SZ> }

SZ> bool someFunction()

SZ> {
SZ> if( !bInit ) return false;

assert(bInit);

SZ> //..выполнить действия

SZ> return true;
SZ> }
SZ>};

SZ>[/ccode]


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


Это вполне нормально.

SZ>Инициализацию невозможно поместить в конструктор, так как нету кода возврата. Это простейший случай, для инициализации объекта, но если после исполнения какого-нибудь метода инвариант нарушен, то с таким объектом можно продолжать работать не зная о том, что он более не валиден, и никто об этом не просигналит, если забыли проверить возвращенное значение.


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