Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Философия обработки Exception-ов


Автор: ivashkanet 18.3.2008, 10:33
Всем привет. 

Заметил, что совсем не умею обрабатывать эксепшены :( 

1) В 90% случаев просто логирую и/или показываю юзеру // т.е. ничего толкогового с информацией об ошибке не делаю.
2) Любимый catch блок -- catch (Exception ex) // А как же обрабатывать только конкретную ошибку?
3) Больше в голову ничего не приходит, но есть четкое ощущение, что я с эксцепшенами не дружу :( 


Что можете посоветовать, уважаемые форумчане?

Зарание спасибо, ivashkanet.

P.S. Если кто считает, что но еще! не "уважаемый" форумчанин -- спешу его поправить, для меня важно мнение каждого!


Автор: tol05 18.3.2008, 11:55
Я не философ, но свое мнение имею ... и его выскажу  smile 

Цитата(ivashkanet @  18.3.2008,  09:33 Найти цитируемый пост)
1) В 90% случаев просто логирую и/или показываю юзеру // т.е. ничего толкогового с информацией об ошибке не делаю.

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


Цитата(ivashkanet @  18.3.2008,  09:33 Найти цитируемый пост)
2) Любимый catch блок -- catch (Exception ex) // А как же обрабатывать только конкретную ошибку?

каждый конкретный exception - класс, производный от базового Exsception (например ArgumentException, InvalidOperationException и т.д.) поэтому и ловить нужно несколькими catch-ами 
Код

catch (InvalidOperationException ex) ...
catch (ArgumentException ex) ...
catch (Exception ex) ...

это не только удобочитаемо и культурно... каждый из классов Exception-ов имеет свои поля и свойства для дополнительной информации об ошибке, которых нет в базовом (иначе зачем создавать потомков, не так ли?). Если же у тебя какая-то кустомная ошибка может быть - создавай свои классы Exception-ов, я так часто делаю... Создаю свой класс Exception-а, который, к примеру, имеет поля типов DataRow, DataColumn, SessionId и т.д. и т.п. И если где-нибудь в иерархии происходит исключение и мне удается привести его к классу своего exception-а ... то польза от этого становится весьма и весьма ощутимой...

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


Цитата(ivashkanet @  18.3.2008,  09:33 Найти цитируемый пост)
3) Больше в голову ничего не приходит, но есть четкое ощущение, что я с эксцепшенами не дружу :( 

ммм... надо батенька, надо. smile
действительно хорошие статьи:
http://msdn.microsoft.com/library/rus/default.asp?url=/library/RUS/cpguide/html/cpconbestpracticesforhandlingexceptions.asp
http://msdn2.microsoft.com/en-us/library/ms954599.aspx#emag__exception_management

Автор: ivashkanet 18.3.2008, 12:11
tol05, эхххььь, это теория. Я это все знаю :( Мне бы применять научиться...

Цитата(tol05 @  18.3.2008,  10:55 Найти цитируемый пост)
нужно закрывать ресурсы, чтобы приложение не вредило машине и работало дальше.

Это я делаю, но неужели это все? Не верю! 
Можно ведь проанализировать эксепшен и, если это возможно, вернуться в начало, возможно что-то исправить, и повторить попытку (Server unaccessible)...
Цитата(tol05 @  18.3.2008,  10:55 Найти цитируемый пост)
это не только удобочитаемо ...

Эт тоже в курсе smile 

А вот за статьи реально спасибо!

Добавлено через 10 минут и 39 секунд
Цитата(ivashkanet @  18.3.2008,  11:11 Найти цитируемый пост)
А вот за статьи реально спасибо! 

Прочитал первую. Очень неплохой экскурс в правила "хорошего тона". Большое спасибо. 
Вторая -- многа букафф, отметил к прочтению.

Автор: ivashkanet 18.3.2008, 12:26
Пролистал вторую --- ИМХО, то что мне надо! 
Но почему же так много букаффф  smile  smile 
Перенес "к прочтению" на "к прочтению сегодня на ночь"  smile 

Автор: tol05 18.3.2008, 14:24
Цитата(ivashkanet @  18.3.2008,  11:11 Найти цитируемый пост)
Это я делаю, но неужели это все? Не верю! 

а что? мало?  smile

Цитата(ivashkanet @  18.3.2008,  11:11 Найти цитируемый пост)
Можно ведь проанализировать эксепшен и, если это возможно, вернуться в начало, возможно что-то исправить, и повторить попытку (Server unaccessible)


Исправить и вернуться - нельзя, т.к. исключение выбрасывает тебя их стека выполнения (стек очищается, кто его второй раз заполнит?). 

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

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

Автор: ivashkanet 18.3.2008, 15:01
Цитата(tol05 @  18.3.2008,  13:24 Найти цитируемый пост)
а что? мало?

Как-то да smile Я же говорю не до конца понимаю принципы smile 

Цитата(tol05 @  18.3.2008,  13:24 Найти цитируемый пост)
т.е. вряд ли тебе удастся что-то исправить и вернуться в метод...

Да, я когда писал понял, что это почти невероятная ситуация (именно поэтом у меня так много "возможно" smile

Автор: ivashkanet 19.3.2008, 14:06
Прочитал. То что надо  smile Где бы еще опыта получить... smile 

Выжимки:

Когда ловить исключения:
Цитата

Ловите (catch) только когда вы хотите сделать любое действие из:
    * Собрать информацию для логирования
    * Добавить существенную информацию к исключению
    * Выполнить очистку ресурсов
    * Попробовать восстанвиться (Attempt to recover)


Требуемая информация по группам "пользователей":
Цитата

Конечные пользователи:
Выполнен ли запрос.
Хорошо оформленное сообщение, показывающее что прошло неправильно
Инструкции, поясняющие что нужно сделать чтобы исправить ошибку

Разработчики:
Дата и время возникновения ислючения.
Точное расположение в коде.
Тип исключения.
Информация, ассоциированная с исключением и состояние системы в момент возникновения ошибки

Операторы:
Дата и время возникновения ислючения.
Точное расположение в коде.
Тип исключения.
Кого нужно известить и какую информацию им передать
Тип исключения показывающий была ли это проблема ресурсов или кода.


Как получить требуемую информацию в коде:
Цитата

Дата и время возникновения:    DateTime.Now
Имя машины:  Environment.MachineName
Источник исключения  Exception.Source
Тип исключения  Type.FullName obtained from Object.GetType
Сообщение    Exception.Message
Стэк вызовов исключения  Exception.StackTrace—стек вызовов начиная с точки где была выброшена и наполняется по мере пробрашивания вверх по стеку вызовов
Стек вызовов  Environment.StackTrace — полный стек вызовов.
Имя домена приложения  AppDomain.FriendlyName
Имя сборки  AssemblyName.FullName, в System.Reflection пространстве имен
Версия приложения  Included in the AssemblyName.FullName
ID потока  AppDomain.GetCurrentThreadId
Thread user  Thread.CurrentPrincipal in the System.Threading namespace


Каждое приложение должно ловить исключение до того как оно попадет к конечному пользователю!
Для этого используют:
ASP .Net 
Cекцию customErrors файла web.config:
Код

<customErrors defaultredirect="http://hostname/error.aspx" mode="on">   
  <error statuscode="500" redirect="/errorpages/servererror.aspx" />
  <error statuscode="404" redirect="/errorpages/filenotfound.htm" />
</customErrors>

Дерективы конкретной страницы:
Код

<%@ Page ErrorPage="customerror.aspx" %>

Код:
Код

// In global.asax file
protected void Application_Error(Object sender, EventArgs e)
{
      Exception exc = Server.GetLastError();
      // Perform logging, send any notifications, etc.
}

// на самой странице
Page.Error += new System.EventHandler(Page_Error);


Самостоятельное приложение:

Код

[STAThread] 
static void Main() 
{
  Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

  // пошел код
}


Так-то вот ;-)

Автор: QryStaL 10.6.2008, 12:50
Вот еще интересная статья
http://blogs.msdn.com/kcwalina/archive/2007/01/30/ExceptionHierarchies.aspx

Автор: source777 10.6.2008, 20:53
Цитата(tol05 @  18.3.2008,  11:55 Найти цитируемый пост)
В catch обычно нужно не только сообщения формировать или логировать для истории ... нужно закрывать ресурсы, чтобы приложение не вредило машине и работало дальше.
Лол, приехали,  закрывать ресурсы надо в блоках finally!!!


ivashkanet Вот тебе несколько философских аксиом для размышлений:
1) Исключения можно генерировать только в исключительных случаях, никогдане используй исключения для управления потоком выполнения.
2) Исключения должны перехватываться только в том месте, где они могут быть обработаны с уровнем знаний достаточным для того, чтобы справиться с исключением наилучшим образом, например, выполнить откат.
3) Надо стремиться писать нейтральный к исключениям код, под этим понимается что ты сначала выполняешь тот код, который потенциально может генерировать исключение, и только потом фиксируешь изменение состояния при помощи операций 100% не генерирующих исключения.

Автор: jonie 10.6.2008, 22:29
Цитата

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

Автор: source777 10.6.2008, 23:33
Цитата(jonie @  10.6.2008,  22:29 Найти цитируемый пост)
что скажете насчет проброски иключений ? 
Допустимо при использовании логирования или присоединения к исключению доп. информации. А перехватывать исключение лишь для того, чтобы пробросить его дальше - это дурно пахнет... 

Автор: ivashkanet 11.6.2008, 11:11
Во некроманты  smile 
source777, за это время я столько литературы перелопатил... в том числе и про исключения.
Тем более Exception Management Architecture Guide ответила на все мои вопросы.

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

Автор: source777 11.6.2008, 14:13
Цитата(ivashkanet @  11.6.2008,  11:11 Найти цитируемый пост)
Во некроманты  smile 
А я чё, я ничего... это QryStaL... да и прошло то меньше 3 месяцев... не 3 года всё-таки.


Цитата(ivashkanet @  11.6.2008,  11:11 Найти цитируемый пост)
В третьем вообще фигня какая-то написана. 

Ошибаешься, там очень полезная методика описана.

Цитата(ivashkanet @  11.6.2008,  11:11 Найти цитируемый пост)
А если при фиксировании состояния объект выкидывает исключение (нарушение бизнес-правил)? 
В том то вся и фишка, фиксирование состояние производится операциями, которые гарантировано не генерируют исключений, например, присваивание ссылок. Для подобных методов даже спец. атрибут есть [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

Грамотно применяя эту технику, можно писать нейтральный к исключениям код с минимальном кол-вом блоков try/catch... и возможностью отката при возникновении исключения.

Автор: ivashkanet 11.6.2008, 14:26
Цитата(source777 @  11.6.2008,  14:13 Найти цитируемый пост)
Ошибаешься, там очень полезная методика описана.

Ну так переубеди меня smile 

Цитата(source777 @  11.6.2008,  14:13 Найти цитируемый пост)
В том то вся и фишка, фиксирование состояние производится операциями, которые гарантировано не генерируют исключений, например, присваивание ссылок. Для подобных методов даже спец. атрибут есть [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

Грамотно применяя эту технику, можно писать нейтральный к исключениям код с минимальном кол-вом блоков try/catch... и возможностью отката при возникновении исключения.

Опять ничего не понятно. smile 
Раз затронул эту тему развивай ее: давай ссылки, примеры, ... ;-)

Добавлено через 1 минуту и 16 секунд
QryStaL, спасибо за статью, но "Exception Management Architecture Guide" все же покруче будет.

Автор: QryStaL 11.6.2008, 14:33
Цитата(ivashkanet @  11.6.2008,  14:26 Найти цитируемый пост)
"Exception Management Architecture Guide" все же покруче будет

Согласен. Эта статья просто в дополнение темы.

Автор: PashaPash 11.6.2008, 14:39
Есть еще отличная вещь под названием http://msdn.microsoft.com/en-us/library/cc511522.aspx для применения этого гайда на практике.

Автор: source777 11.6.2008, 21:03
Цитата(ivashkanet @  11.6.2008,  14:26 Найти цитируемый пост)
Раз затронул эту тему развивай ее: давай ссылки, примеры, ... ;-)
Ну вот, например, http://accu.org/index.php/journals/261. Я просто эту идею из книг подчерпнул, а не из инета, но думаю при желании ты найдёшь описание по фразе "exception-neutral code"...

Автор: neutrino 8.11.2010, 11:31
В компиляторе является ли ошибка компиляции ексепшеном? В некоторых случаях можно продолжать компилировать, чтобы найти остальные ошибки.

Автор: KelTron 8.11.2010, 14:32
Цитата(neutrino @  8.11.2010,  11:31 Найти цитируемый пост)
В компиляторе является ли ошибка компиляции ексепшеном? 

Думаю нет, т.к. это обыденное явление, а не исключительное..

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)