Тверской государственный университет
Опубликован: 02.12.2009 | Доступ: свободный | Студентов: 2369 / 261 | Оценка: 4.47 / 4.24 | Длительность: 14:45:00
Лекция 10:

Декларативность. Атрибуты и теги

< Лекция 9 || Лекция 10: 12345 || Лекция 11 >

Тэги

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

В языке C# большое внимание уделяется средствам документирования кода. Разработчики кода могут комментировать код, используя специальный синтаксис, содержащий XML-текст. Комментарии, использующие этот синтаксис, называются документируемыми комментариями. Для поддержки работы с такими комментариями имеется специальный инструментарий - генератор документации, - позволяющий извлекать такие комментарии и строить автоматически файл документации - XML-отчет. Генератор документации является частью компилятора C#. Для запуска генератора и построения отчета достаточно включить соответствующий флажок на странице свойств проекта. При работе с командной строкой достаточно скомпилировать проект с включенной опцией /doc. Предполагается, что файл документации может подаваться на вход инструментальному средству, позволяющему удобно работать с полученным отчетом. Можно считать, что подсказка IntelliSense и браузер объектов являются частью такого инструментария. Эти средства отображают информацию, заданную в тегах summary, param, remarks и некоторых других тегах. Интеллектуальная подсказка крайне важна при работе клиентов с классом. Поэтому профессиональный стиль разработки требует, чтобы все открытые для клиентов и потомков сущности класса были снабжены документируемыми комментариями. Хотелось бы иметь как отдельный инструментарий и браузер отчетов, но в настоящее время он не входит в состав инструментария Visual Studio 2008.

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

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

/// Это однострочный комментарий
/**
   * Это многострочный комментарий с ограничителями
*/

Первая форма соответствует однострочным комментариям, вторая допускает расположение комментария на нескольких строках. Оба комментария должны непосредственно предшествовать программной сущности, с которой они связаны. В роли сущностей могут выступать классы и все их частные случаи, а также поля, свойства, методы и события класса. Если аннотируемая сущность имеет атрибуты, то атрибуты рассматриваются как часть объявления сущности, и комментарии непосредственно предшествуют атрибутам. Заметьте, обычный строчный комментарий начинается с двух символов слеша, а документируемый - с трех, что позволяет компилятору находить документируемый комментарий. Для многострочных комментариев признаком документируемого комментария являются две звездочки, идущие за слешем, в отличие от одной звездочки обычного комментария.

Комментарии в отличие от атрибутов не включаются в метаинформацию, и, следовательно, не могут быть извлечены в процессе отражения. Но они могут быть включены в файл документации проекта. Стандартные теги имеют предопределенный смысл и функциональность. Программист при желании может задавать собственные теги. Единственное, что от него требуется в этом случае, - это соблюдение общих синтаксических правил, предъявляемых к XML-тексту. В табл. 9.1 приведен набор стандартных тегов C# с пояснением их смысла.

Таблица 9.1. Стандартные теги С#
Тег Смысл
<c> Для тела тега - текста, размещенного между открывающим и закрывающим тегом, используется шрифт, применяемый для кода.
<code> Аналогичен тегу <c>. Обычно первый тег применяется для кратких текстов, второй для длинных текстов из нескольких строк.
<example> Применяется, когда в комментариях встречается пример кода. Обычно сочетается с тегом <code>
<exception> * Обычно связывается с методом и описывает исключения, которые могут быть выброшены в процессе работы метода. Синтаксис: <exception cref = " тип исключения" > Описание причины исключения </exception> Выполняется проверка, существует ли указанный тип исключения.
<include>* Stop!!! Для больших проектов может существовать общий XML-файл с документацией. Тег include позволяет ссылаться на нужное место в этом файле. Синтаксис: <include file = 'имя файла' path = 'путь к описанию тега'> Выполняется проверка, существует ли указанный файл и путь к тегу.
<list> Позволяет внутри комментария задавать структуру списка или таблицы, что улучшает читаемость отчета документации.
<para> Позволяет внутри комментария задавать абзацы с той же целью улучшения читаемости отчета.
<param>* Позволяет комментировать параметры метода. Обычно строится автоматически вместе с тегом summary, когда документируемый комментарий вставляется перед методом. Текст описания отображается в подсказке IntelliSense и в браузере объектов. Выполняется проверка, существует ли указанный параметр у комментируемого метода.
<paramref> Позволяет внутри комментария указать, что некоторое слово текста является параметром (ссылкой на параметр метода), - это позволяет в отчете выделить это слово.
<permission>* Позволяет документировать безопасность доступа, задавая ссылку на поле или метод, доступный для вызова в данном окружении.
<remarks> Задает описание программной сущности. Обычно это некоторое дополнение - ремарка к основному описанию, задаваемому тегом summary. Но иногда тег remarks используется вместо тега summary. Следует иметь в виду, что в этом случае описание, заданное тегом, не отображается в подсказке IntelliSense, хотя и отображается в браузере объектов.
<returns> Тег returns позволяет описать значение, возвращаемое методом. Когда документируемый комментарий вставляется перед началом метода, достаточно набрать три слеша - признак начала документируемого комментария, как автоматически в комментарий добавляются тег summary и теги param и returns, если метод имеет параметры и возвращаемое значение, отличное от void.
<see>* Позволяет внутри описания (в теге summary ) сделать ссылку на поле или метод. Синтаксис:
<see cref = "member" |/>
Выполняется проверка существования элемента, заданного ссылкой. Пример:
///<summary>
///Метод Move перемещает точку на плоскости в новое положение. 
///В отличие от метода < see cref = "Offset" />, выполняющего сдвиг точки.
///</summary>
public void Move(int x, int y) {…}
<seealso>* Аналогичен тегу <see>. Создает в файле документации специальный раздел "смотри также".
<summary> Задает описание полей и методов. Вставляется автоматически, как только заданы три слеша, начинающие документирующий комментарий. Описание, заданное тегом, показывается в подсказке IntelliSense и в браузере объектов. Если строится файл документации, то требуется задание этого тега для всех public полей и методов. В противном случае выдаются предупреждение, что элемент не имеет комментария, что нарушает правила стиля профессионального программирования.
<typeparam>* Позволяет описать параметр типа для универсального класса - класса с типовыми параметрами. Так же, как и теги summary, param, returns автоматически добавляется в документирующий комментарий. Выполняется проверка, что соответствующий параметр действительно есть у класса или метода.
<typeparamref> Задает ссылку на параметр типа.
<value>* Позволяет описать метод-свойство.

В примерах данного курса документируемые комментарии создавались для многих открытых сущностей класса, что отвечает правилам стиля профессионального программирования. Иногда требования стиля не соблюдались по причине увеличения объема текста, затрудняющего его восприятие. Для программного текста увеличение объема не имеет принципиального значения, поскольку текст комментария всегда может быть свернут, не мешая восприятию программного кода. Но, когда программный код копируется и становится частью текста книги, свертка не действует, и комментарий появляется в развернутом виде, мешая иногда восприятию программного кода. По этой причине в примерах документируемые комментарии построены далеко не всюду, где они должны появляться в соответствии с правилами стиля. Тем не менее было много вариантов использования основных тегов - summary, param, returns. Приводить примеры применения всех тегов нет особой необходимости. В табл. 9.1 дано достаточно подробное описание их назначения. Ограничусь одним примером использования тега exception, позволяющего описать причину исключения, которое может возникнуть в ходе работы метода класса. Давайте слегка модифицируем уже известный нам пример одного из методов класса OurClass:

/* * * 
<summary>
Третий метод. Лучший из всех методов. 
</summary>    
* */
        /// <exception cref = "OurClassException">
        /// Исключение возникает после дождика в четверг!
        /// Оно будет перехвачено и обработано.
        /// </exception>       
        [History("В. Биллиг", "2.04.2009",
        comment = "Первый вариант реализации алгоритма")]
        [History("В. Биллиг", "5.04.2009",
                comment = "Изменение спецификаций")]
        public void Third()
        {
            const string message = "Дождь в четверг!";
            const string result = "Хорошо собирать грибы!";
            try
            {
                bool rainInThursday = true;
                if (rainInThursday) throw (new OurClassException(message));
            }
            catch (OurClassException e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(result);
            }
        }

У метода два атрибута и два тега. Тег summary размещен в многострочном комментарии, тег exception - в однострочном. В теге exception задан параметр cref, задающий имя класса исключений. Подобный параметр имеется во многих тегах, где он задает имя некоторой сущности. Такие теги являются тегами с проверкой - проверяется существование сущности, заданной параметром cref. Для класса OurClass создан, как положено, класс исключений OurClassException. Поэтому проверка, проводимая для тега exception, закончится успехом, обнаружив этот класс.

Приведу пример фрагмента XML отчета, связанного с рассматриваемым методом:

<member name="M:ConsoleAttributes.OurClass.Third">
            <summary>Третий метод. Лучший из всех методов. </summary>
            
            <exception cref="T:ConsoleAttributes.OurClassException">
            Исключение возникает после дождика в четверг!
            Оно будет перехвачено и обработано.
            </exception>       
      </member>

Заметьте, вся информация из тегов попала в отчет. Благодаря проверке приводится полная информация, включающая имя пространства имен, имя класса и имя сущности. Однобуквенные идентификаторы, предшествующие описанию сущности, характеризуют ее тип ( M - метод, T - исключение, F - поле и так далее).

Подводя итоги

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

Программный текст должен быть не только хорошим. Он должен быть хорошо документирован. Без тегов и атрибутов в этом случае не обойтись.

Проекты

  1. Постройте классы Person, Student, Car, Firm. Задайте стандартные атрибуты для классов, полей, методов, параметров и возвращаемых значений методов класса. Постройте классы PersonReflection и другие, где, используя стандартные классы отражения из пространства имен Reflection, получите информацию о сущностях построенных классов. Постройте соответствующий интерфейс Windows-проекта, позволяющий получать информацию о классе. Можно ли построить универсальный класс TReflection с родовым параметром T, позволяющий получать информацию о произвольном классе T?
  2. Постройте собственный атрибутный класс. Снабдите сущности классов Person, Student, Car, Firm собственными атрибутами. Постройте процесс отражения, получая информацию об атрибутированных сущностях классов.
  3. Постройте классы Person, Student, Car, Firm. Классы должны включать события и предусматривать обработку исключительных ситуаций. Задайте в каждом классе стандартные теги всех возможных видов. Постройте соответствующий интерфейс Windows-проекта, позволяющий получать полный отчет о классе и частные отчеты о деталях класса - полях класса, методов класса, событиях, исключительных ситуациях.
< Лекция 9 || Лекция 10: 12345 || Лекция 11 >
Илья Ардов
Илья Ардов

Добрый день!

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

Дарья Федотова
Дарья Федотова
Александр Мигунов
Александр Мигунов
Россия