Скачать презентацию Лекция 7 Исключения Что такое исключения Скачать презентацию Лекция 7 Исключения Что такое исключения

Лекция 7.pptx.pptx

  • Количество слайдов: 59

Лекция 7 Лекция 7

Исключения Исключения

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

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

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

Проверяемые и непроверяемые исключения В шарпе нет проверяемых. “Если реализовать этот механизм так, как Проверяемые и непроверяемые исключения В шарпе нет проверяемых. “Если реализовать этот механизм так, как он был реализован в Java, то, я думаю, вы просто размениваете один набор проблем на другой. ”

Как обрабатывать исключения if-else try-catch Как обрабатывать исключения if-else try-catch

Что-когда использовать? Если событие происходит регулярно в рамках нормальной работы программы, используйте программный метод Что-когда использовать? Если событие происходит регулярно в рамках нормальной работы программы, используйте программный метод проверки на наличие ошибок. В случае программной проверки на наличие ошибок при возникновении исключения выполняется больше кода.

Что-когда использовать? Если событие происходит редко, то есть событие носит действительно исключительный характер и Что-когда использовать? Если событие происходит редко, то есть событие носит действительно исключительный характер и указывает на ошибку, то используйте обработку исключений. При использовании обработки исключений в обычных условиях выполняется меньше кода.

Try-catch-finally В блок try помещается код, выполнение которого мы считаем потенциально опасным. Блоки catch Try-catch-finally В блок try помещается код, выполнение которого мы считаем потенциально опасным. Блоки catch обрабатывают возможные виды ошибок. Блок finally используется для очистки ресурсов, если это необходимо.

Примеры try { x = x / y; } catch(Divide. By. Zero. Exception ex) Примеры try { x = x / y; } catch(Divide. By. Zero. Exception ex) { Console. Write. Line("Делить на 0 нельзя!"); }

Пример try { x = x / y; } finally { Console. Write. Line( Пример try { x = x / y; } finally { Console. Write. Line("x = " + x); }

Пример try { x = x / y; } catch(Divide. By. Zero. Exception ex) Пример try { x = x / y; } catch(Divide. By. Zero. Exception ex) { Console. Write. Line("Делить на 0 нельзя!"); } finally { Console. Write. Line("x = " + x); }

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

Блоки catch Если нет блока catch, который определяет соответствующий фильтр исключений, выбирается блок catch, Блоки catch Если нет блока catch, который определяет соответствующий фильтр исключений, выбирается блок catch, в котором не выбран фильтр, если таковой имеется в операторе. Очень важно, чтобы первыми были размещены блоки catch с самыми конкретными (т. е. , самыми производными) типами исключений.

Пример try { x = x / y; } catch (Divide. By. Zero. Exception Пример try { x = x / y; } catch (Divide. By. Zero. Exception ex) { Console. Write. Line("Делить на 0 нельзя!"); } catch (Exception ex) { Console. Write. Line("Случилась какая-то ошибка"); }

Рекомендации В блоках catch следует всегда упорядочивать исключения от более конкретных к более общим. Рекомендации В блоках catch следует всегда упорядочивать исключения от более конкретных к более общим.

Рекомендации Разрабатывайте классы таким образом, чтобы исключение никогда не создавалось при нормальном использовании. В Рекомендации Разрабатывайте классы таким образом, чтобы исключение никогда не создавалось при нормальном использовании. В большинстве случаев следует использовать предопределенные типы исключений. NET Framework.

Рекомендации Создавайте новый класс исключений, только если предопределенное исключение не подходит. Вызывайте исключение Invalid. Рекомендации Создавайте новый класс исключений, только если предопределенное исключение не подходит. Вызывайте исключение Invalid. Operation. Exception, если значение свойства или вызов метода не соответствуют текущему состоянию объекта.

Рекомендации Вызывайте исключение Argument. Exception или класс, производный от Argument. Exception, если передаются недопустимые Рекомендации Вызывайте исключение Argument. Exception или класс, производный от Argument. Exception, если передаются недопустимые параметры.

Фильтры исключений В C# 6. 0 (Visual Studio 2015) была добавлена такая функциональность, как Фильтры исключений В C# 6. 0 (Visual Studio 2015) была добавлена такая функциональность, как фильтры исключений. Они позволяют обрабатывать исключения в зависимости от определенных условий.

Пример try { int result = x / y; } catch(Exception ex) when (y==0) Пример try { int result = x / y; } catch(Exception ex) when (y==0) { Console. Write. Line("y не должен быть равен 0"); } catch(Exception ex) { Console. Write. Line(ex. Message); }

Иерархия исключений Exception является базовым классом для исключений. Некоторые классы исключений наследуют непосредственно от Иерархия исключений Exception является базовым классом для исключений. Некоторые классы исключений наследуют непосредственно от Exception, в том числе классы Application. Exception и System. Exception. Эти два класса образуют основу для почти всех исключений среды выполнения.

System. Exception Среда выполнения создает соответствующий производный класс от класса System. Exception при возникновении System. Exception Среда выполнения создает соответствующий производный класс от класса System. Exception при возникновении ошибок. Эти ошибки возникают из завершившихся неудачно проверок во время выполнения (например, массив ошибок "вне диапазона") и могут возникать при выполнении любого метода.

System. Exception Наиболее тяжелые исключения, которые создаются средой выполнения или при наличии неустранимых условий, System. Exception Наиболее тяжелые исключения, которые создаются средой выполнения или при наличии неустранимых условий, включают Execution. Engine. Exception, Stack. Overflow. Exception и Out. Of. Memory. Exception.

Проброс исключений “Чаще всего код не должен заниматься обработкой исключений - это не его Проброс исключений “Чаще всего код не должен заниматься обработкой исключений - это не его дело. Он должен выполнить некие действия, если получит исключения, пробросит его вызывающему коду, которому можно доверить эту самую обработку (согласно Single responsibility (SOLID), класс не должен брать на себя более одной обязанности). ”

Стек вызовов Это стек, содержащий упорядоченный, по очередности вызова, список функций. Функция 3 Функция Стек вызовов Это стек, содержащий упорядоченный, по очередности вызова, список функций. Функция 3 Функция 2 Функция 1 Главная функция

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

Проброс исключений “В хорошо написанном приложении отношение конструкций tryfinally к trycatch примерно 10 к Проброс исключений “В хорошо написанном приложении отношение конструкций tryfinally к trycatch примерно 10 к 1. ” “вы защищаете себя от исключений, а не обрабатываете их. Обработку исключений вы реализуете где-то в другом месте. ”

Проброс исключений “Я думаю, что вся концепция «обработки» исключений слегка напоминает игру для дураков. Проброс исключений “Я думаю, что вся концепция «обработки» исключений слегка напоминает игру для дураков. Я, наверное, могу посчитать на пальцах одной руки количество случаев, когда я был действительно в состоянии обработать специфический тип исключения и сделать в обработчике что-то интеллектуальное. В 99% случаев ты должен ловить или всё или ничего. Когда выбрасывается исключение любого типа, восстановите стабильное состояние и затем либо продолжайте, либо прерывайте исполнение программы. ”

Как получить стек вызовов? У класса Exception есть свойство Stack. Trace, которое получает строковое Как получить стек вызовов? У класса Exception есть свойство Stack. Trace, которое получает строковое представление непосредственных кадров в стеке вызова. Оно перечисляет вызовы методов в обратном хронологическом порядке, то есть, самый последний вызов метода описан первым.

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

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

Пример Наш класс Пример Наш класс

Пример Встроили в код обработки Пример Встроили в код обработки

Пример Через оператор throw мы сами можем генерировать ошибки Пример Через оператор throw мы сами можем генерировать ошибки

Логирование Логирование

Логи, зачем они нужны? Основные цели, ради которых существуют логи: сказать, что же делает Логи, зачем они нужны? Основные цели, ради которых существуют логи: сказать, что же делает система прямо сейчас, не прибегая к помощи отладчика, т. к. это иногда не оправдано; провести «расследование» обстоятельств, которые привели к определенному состоянию системы (например, падению или багу); проанализировать, на что тратится больше времени/ресурсов, т. е. профилирование.

Простые решения Создать метод, который бы дозаписывал в файл события. public static void Log(string Простые решения Создать метод, который бы дозаписывал в файл события. public static void Log(string message) { File. Append. All. Text("log. txt", message); }

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

А что на практике? На практике, оказывается, что всё не так просто: одного лог-файла А что на практике? На практике, оказывается, что всё не так просто: одного лог-файла становится уже недостаточно, возникают проблемы с многопоточностью, форматом логов, записью времени, производительность и т. д.

Что делать? Существуют готовые решения в виде логгеров для сохранения информации о состояниях системы Что делать? Существуют готовые решения в виде логгеров для сохранения информации о состояниях системы и т. п. Какой логгер считать «хорошим» ?

Уровни логгирования любое сообщение несёт в себе информацию определённой критичности, и время реакции на Уровни логгирования любое сообщение несёт в себе информацию определённой критичности, и время реакции на сообщения отличаются.

Пример Debug. Отправлен запрос в базу на сохранение Debug. Завершён запрос в базу на Пример Debug. Отправлен запрос в базу на сохранение Debug. Завершён запрос в базу на сохранение Debug. Запрос в базу занял 0. 02 секунды, извлечено 1000 записей Info. Проведена транзакция по счёту 400000 (John Doe), получено $2000. Warn. Отклонена транзакция с суммой платежа 0. Error. Ошибка при сохранении транзакции 123: …. . Fatal. Не могу запустить модуль отправки исходящих сообщений MSMQ, из-за ошибки конфигурации модуля (…). Транзакции не будут обрабатываться.

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

Уровни логгирования Debug: сообщения отладки, профилирования. В production системе обычно сообщения этого уровня включаются Уровни логгирования Debug: сообщения отладки, профилирования. В production системе обычно сообщения этого уровня включаются при первоначальном запуске системы или для поиска узких мест (bottleneck-ов).

Уровни логгирования Info: обычные сообщения, информирующие о действиях системы. Реагировать на такие сообщения вообще Уровни логгирования Info: обычные сообщения, информирующие о действиях системы. Реагировать на такие сообщения вообще не надо, но они могут помочь, например, при поиске багов, расследовании интересных ситуаций итд.

Уровни логгирования Warn: записывая такое сообщение, система пытается привлечь внимание обслуживающего персонала. Произошло что-то Уровни логгирования Warn: записывая такое сообщение, система пытается привлечь внимание обслуживающего персонала. Произошло что-то странное. Возможно, это новый тип ситуации, ещё не известный системе. Следует разобраться в том, что произошло, что это означает, и отнести ситуацию либо к инфо-сообщению, либо к ошибке. Соответственно, придётся доработать код обработки таких ситуаций.

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

Уровни логгирования Fatal: это особый класс ошибок. Такие ошибки приводят к неработоспособности системы в Уровни логгирования Fatal: это особый класс ошибок. Такие ошибки приводят к неработоспособности системы в целом, или неработоспособности одной из подсистем. Чаще всего случаются фатальные ошибки из-за неверной конфигурации или отказов оборудования. Требуют срочной, немедленной реакции.

Ротация лог-файлов Логи со временем разрастаются, старые становятся неактуальными. Хороший логгер должен уметь подменять Ротация лог-файлов Логи со временем разрастаются, старые становятся неактуальными. Хороший логгер должен уметь подменять активный файл при наступлении определённых условий. Есть два режима: по дате по размеру файла.

Куда записывать лог Хороший логгер должен поддерживать отправку сообщений по протоколу UDP, запись в Куда записывать лог Хороший логгер должен поддерживать отправку сообщений по протоколу UDP, запись в базу, взаимодействие с очередями сообщений, такими, как MSMQ или JMS. Кроме того, отлично, когда логгер предоставляет возможность реализации собственного потребителя сообщений.

Потокобезопасность Плохой логгер может: пропустить часть сообщений; выбросить исключение отрицательно повлиять на производительность Грамотная Потокобезопасность Плохой логгер может: пропустить часть сообщений; выбросить исключение отрицательно повлиять на производительность Грамотная реализация потокобезопасности в логгере – один из ключевых моментов.

Асинхронное логгирование Типичная практика логгирования – асинхронная запись. При этом важно, чтобы размер буфера Асинхронное логгирование Типичная практика логгирования – асинхронная запись. При этом важно, чтобы размер буфера был гибко настраиваемый, например, debugсообщения можно писать по 100 штук, а error – немедленно после возникновения.

Формат и конфигурация логов Формат должен быть настраиваемый, с возможностью указать то, что писать Формат и конфигурация логов Формат должен быть настраиваемый, с возможностью указать то, что писать и куда писать. Например, можно писать в файл, хранящийся по пути из переменной окружения. Кроме того, полезная фича – динамическая конфигурация логгера, слежение за файлом конфигурации. Надо включить debug-режим – поменяли конфиг и наслаждаемся вкусными логами без перезапуска приложения.

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

Правила записи исключений если вы обработали исключение, возможны три случая: исключение считается обработанным и Правила записи исключений если вы обработали исключение, возможны три случая: исключение считается обработанным и не пробрасывается выше по стеку. В этом случае запишите исключение с подробным стеком в лог;

Правила записи исключений исключение пробрасывается выше по стеку в той же подсистеме. Не логгируйте Правила записи исключений исключение пробрасывается выше по стеку в той же подсистеме. Не логгируйте такое исключение. Однако убедитесь, что выше по стеку его запишут; исключение пробрасывается выше по стеку в другую подсистему. Например, на другую машину или в другой процесс. Залоггируйте такое исключение, или запишите диагностическое сообщение об исключении;

Правила записи исключений если исключение не обрабатывается – не логгируйте его. Однако убедитесь, что Правила записи исключений если исключение не обрабатывается – не логгируйте его. Однако убедитесь, что выше это исключение будет обязательно залоггировано