Опубликован: 02.12.2009 | Уровень: специалист | Доступ: свободно | ВУЗ: Тверской государственный университет
Лекция 11:

Корректность и устойчивость программных систем

< Лекция 10 || Лекция 11: 123456

Класс Exception

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

Основными свойствами класса являются:

  • Message - строка, задающая причину возникновения исключения. Значение этого свойства устанавливается при вызове конструктора класса, когда создается объект, задающий исключение;
  • HelpLink - ссылка (URL) на файл, содержащий подробную справку о возможной причине возникновения исключительной ситуации и способах ее устранения;
  • InnerException - ссылка на внутреннее исключение. Когда обработчик выбрасывает новое исключение для передачи обработки на следующий уровень, то текущее исключение становится внутренним для вновь создаваемого исключения;
  • Source - имя приложения, ставшего причиной исключения;
  • StackTrace - цепочка вызовов - методы, хранящиеся в стеке вызовов в момент возникновения исключения;
  • TargetSite - метод, выбросивший исключение.

Из методов класса отметим метод GetBaseException, - при подъеме по цепочке вызовов он позволяет получить исходное исключение - первопричину возникновения последовательности выбрасываемых исключений.

Класс имеет четыре конструктора, из которых три уже упоминались. Один из них - конструктор без аргументов, второй принимает строку, становящуюся свойством Message, третий имеет еще один аргумент: исключение, передаваемое свойству InnerException.

В предыдущий пример я внес некоторые изменения. В частности, добавил еще один аргумент при вызове конструктора исключения в catch -блоке метода Pattern:

throw(new MyException("Все попытки Pattern безуспешны", me));

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

static public void PrintProperties(Exception e)
  {
     Console.WriteLine("Свойства исключения:");
     Console.WriteLine("TargetSite = {0}", e.TargetSite);
     Console.WriteLine("Source = {0}", e.Source);
     Console.WriteLine("Message = {0}",e.Message);
   if (e.InnerException == null)
           Console.WriteLine("InnerException = null");
     else Console.WriteLine("InnerException = {0}", e.InnerException.Message);
     Console.WriteLine("StackTrace = {0}", e.StackTrace);
     Console.WriteLine("GetBaseException = {0}", e.GetBaseException());
  }

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

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

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

Стиль программирования

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

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

Правила стиля излагаются в разных источниках. В великолепной книге Бертрана Мейера стилю программирования посвящена отдельная лекция. Руководство по стилю программированию на C# (C# Coding Style Guide) Майкла Крюгера является общепризнанным документом. На его основе фирмы - разработчики ПО - создают свои собственные стандарты, например, стандарт, принятый в Высшей школе программирования (Programming in C#: Rules and Recommendations).

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

Документирование

Код должен быть документируемым. Документируемые комментарии должны быть непременной частью кода. Вот как формулируется основное правило документирования кода:

Правило 1: " И не вздумайте!"

И не вздумайте написать общедоступную ( public ) сущность без заголовочного комментария. Все public -классы, методы, поля должны иметь документируемые комментарии. Механизм тегов на C#, прежде всего тега summary, великолепно поддерживает это правило, обеспечивая в награду интеллектуальную подсказку при работе с документированными сущностями, так же как и возможность автоматической генерации отчетов.

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

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

Именование

Есть целый ряд правил стиля, посвященных тому, как именовать те или иные сущности. Главное правило в том разделе формулируется так:

Правило 2: "Never, never, never" (Никогда, никогда, никогда!)

Имена сущностей должны быть содержательными! Никогда, никогда, никогда не используйте аббревиатуры для именования сущностей, особенно - общедоступных сущностей. В первую очередь это касается имени класса, его методов и полей, всего, что входит в интерфейс класса. Название правила заимствовано мной из письма Евгения Веселова, одного из российских программистов, который ныне работает в Microsoft, занимая там ведущие позиции. Я послал ему на рецензию вариант этого курса и вот цитата из его письма:

"These are private members, so it's not required to use full words for them. But meaningless m and n seem inappropriate anyway. In production code we never Never NEVER use abbreviations." ( Это закрытые члены класса, так что для их имен не требуются полные слова. Но не имеющие смысла m и n в любом случае кажутся неподходящими. В промышленном коде мы никогда, Никогда, Никогда не используем аббревиатуры.)

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

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

Понимание кода

Ряд правил стиля направлены на облегчение понимания написанного кода. Прежде всего, текст должен быть структурирован. Сегодня эти правила не столь важны, поскольку среда разработки автоматически поддерживает структурированность кода. Более того, для облегчения понимания используется цветовая разметка кода.

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

Рассмотрим несколько правил, связанных с размером создаваемого кода.

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

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

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

Еще одно важное правило стиля, направленное на понимание кода, требует, чтобы объявление сущностей было приближено к точке их использования. Это в полной мере относится к локальным переменным, которые стоит объявлять в блоке непосредственно перед их использованием. Поля класса, используемые многими методами, следует объявлять сосредоточенно, как правило, в начале объявления класса. Среда разработки облегчает понимание кода, предоставляя контекстное меню с такими элементами, как " Перейти к определению", "Найти все ссылки".

Разное

Приведу еще несколько обычно задаваемых правил стиля.

Каждый класс должен сохраняться в отдельном файле. Среда разработки поддерживает это правило, если в проект класс добавляется через пункт меню AddClass. При переименовании класса переименовывайте и файл, его содержащий.

Задавая объявления, на одной строке объявляйте только переменные одного типа. Иногда применяется более строгое правило - на одной строке следует объявлять одну переменную.

Имена классов и полей классов должны задаваться существительными, имена методов - глаголами (глагольными формами в повелительном наклонении).

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

Задачи

  1. Напишите метод, вычисляющий сумму элементов массива, и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  2. Напишите метод, вычисляющий произведение элементов массива и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  3. Напишите метод, вычисляющий максимальный элемент массива и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  4. Напишите метод, вычисляющий минимальный элемент массива и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  5. Напишите метод, вычисляющий максимальный и минимальный элемент массива и докажите его корректность.
  6. Напишите метод пузырьковой сортировки элементов массива и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  7. (*) Напишите метод быстрой сортировки Хоара элементов массива и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  8. (**) Напишите метод сортировки Шелла элементов массива и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  9. (*) Напишите класс Stack и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  10. (*) Напишите класс Queue и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.

Проекты

  1. Постройте класс MyMath - аналог класса Math и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.
  2. Постройте класс Sorting с универсальными методами сортировки и докажите его корректность. Инварианты цикла, предусловия, постусловия и другие предикаты, используемые в доказательстве, включите в документацию проекта.

Итоги

В первой части курса я попытался рассмотреть начала программирования на C#, во второй - основы объектного программирования, программирования в классах. Насколько это удалось, судить читателям.

В отличие от предыдущей книги ("Основы программирования на C#") в данном курсе больше внимания уделено описанию классических алгоритмов, входящих в базисную подготовку программистов. Особенностью является и то, что каждая лекция заканчивается задачами. Эти новинки, возможно, не всем придутся по душе, поскольку уводят от непосредственного изучения возможностей языка C#, но многим они должны понравиться. Надеюсь, что те, кто изучает этот курс на сайте открытого университета ИТ - intuit.ru смогут обмениваться решениями задач. Лучшие решения смогут стать образцами и дать больше полезной информации в сравнении с тем, что содержится в курсе.

Для тех, кто хотел бы получить больше информации о многообразных возможностях C#, его новых версиях, возможностях Visual Studio и Framework .Net, могу только сообщить, что работа продолжается и, надеюсь, появится продолжение этого курса.

Пишите, ругайте, хвалите. Мой адрес: Vladimir.Billig@tversu.ru

< Лекция 10 || Лекция 11: 123456
Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?

Илья Ардов
Илья Ардов

Добрый день!

Я записан на программу. Куда высылать договор и диплом?