Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Для всех открытых элементов АР I пишите dос - комментарии



Если АРI будет использоваться, его нужно описывать. Обычно документация к АРI пишется вручную, и поддержание соответствия между документацией и про­граммным кодом - весьма неприятная работа. Среда программирования Java об­легчает эту задачу с помощью утилиты, называемой /avadoc. Она автоматически генерирует документацию к API, отталкиваясь от исходного текста программы, до­полненного специальным образом оформленными комментариями к документации (documentation comment), которые чаще называют dос - комментариями (doc comment). Утилита Javadoc предлагает простой, эффективный способ документирования АРI и используется повсеместно.

Если вы еще не знакомы с соглашениями для dос - комментариев, то обязаны их изучить. Эти соглашения не являются частью языка программирования Java, но де-факто они образуют свой API, который обязан знать каждый программист. Соглашения сформулированы в "The J avadoc Tool Ноте Page" [Javadoc-b].

Чтобы должным образом документировать API, следует предварять doc - ­комментарием каждую предоставляемую пользователям декларацию класса, интерфейса, конструктора, метода и поля. Единственное исключение обсуждается в конце статьи. Если dос - комментарий отсутствует, самое лучшее, что может сделать Javadoc,- это воспроизвести декларацию элемента АРI как единственно возможную для него документацию. Работа с API, у которого нет комментариев к документации, чревата ошибками. Чтобы создать программный код, приемлемый для сопровождения, вы должны написать dос - комментарии даже для тех классов, интерфейсов, конструк­торов, методов и полей, которые не предоставляются пользователям.

Dос - комментарий для метода должен лаконично описывать соглашения между методом и его клиентами. Соглашение должно оговаривать, что делает данный метод, а не как он это делает. Исключение составляют лишь методы в классах, предназначенных для наследования (статья 15). В dос - комментарии необходимо перечислить все предусловия (precondition), т. е. утверждения, которые должны

127

 

 

быть истинными для того, чтобы клиент мог вызвать этот метод, и постусловия (postcondition), т. е. утверждения, которые будут истинными после успешного завер­шения вызова. Обычно предусловия неявно описываются тегами @throws для необра­ботанных исключений. Каждое необработанное исключение соответствует нарушению некоего предусловия. Предусловия также могут быть указаны вместе с параметрами, которых они касаются, в соответствующих тегах @раrаm.

Помимо пред- и постусловий для методов должны быть также документированы любые побочные эффекты. Побочный эффект (side effect) - это поддающееся наблюдению изменение состояния системы, которое является неявным условием для достижения постусловия. Например, если метод запускает. фоновый поток, это должно быть отражено в документации. Наконец, комментарии к документации должны описывать безопасность класса при работе с потоками (thread safety) , которая обсуждается в статье 52.

В целях полного описания соглашений dос - комментарий для метода должен включать в себя: тег @ракаm для каждого параметра, тег @return, если только метод не возвращает тип void, и тег @throws для каждого исключения, инициируемого этим методом, как обработанного, так инеобработанного (статья 44). По соглашению, текст, который следует за тегом @раrаm или @return, представляет собой именную конструкцию ( noun phrase - термин грамматики английского языка). Описывающую значение данного параметра или возвращаемое значение. Текст, следующий за тегом @throws, должен состоять из слова if и именной конструкции, описывающей условия, при которых инициируется данное исключение. Иногда вместо именных конструкций используются арифметические выражения. Все эти соглашения иллюстрирует следую­щий краткий dос - комментарий из интерфейса List:

/**

* Возвращает элемент, который занимает заданную позицию

* в указанном списке.

       * @ param index - индекс элемента, который нужно возвратить; индекс должен  

       *                        быть неотрицательным, и его значение должно быть           

       *                        меньше размера списка.

       * @ return         элемент, занимающий в списке указанную позицию.

       * @ throws        IndexOutOfBoundsException, если индекс лежит вне диапазона.

       *                       (<tt> index &lt; ()  || index &gt; = this.size()</tt>)

*/

Object get(int index);

 

Заметим, что в этом dос - комментарии используются метасимволы и теги языка HTML. Утилита Javadoc преобразует dос-комментарии в код HTML, и любые со­державшиеся в dос - комментариях элементы HTML оказываются в полученном НТМL - документе. Иногда программисты заходят настолько далеко, что встраивают в свои dос - комментарии таблицы HTML, хотя это не является общепринятым. Чаще

 

128

 

 

всего применяются следующие теги: <р> для разделения параграфов, <code> и <tt> для представления фрагментов кода, <рге> для более длинных фрагментов кода.

Теги <code> и <tt> в значительной степени эквивалентны. Тег <code> использу­ется чаще и, согласно спецификации HTML 4.01, является более предпочтительным, поскольку <tt> - это элемент стилевого оформления шрифта. (Пользоваться элементами стилевого оформления шрифтов здесь не рекомендуется, предпочтение отдается каскадным таблицам стилей [HTML401]). Некоторые программисты все же предпочитают тег <tt>, поскольку он короче и не столь агрессивен.

Не забывайте, что для генерации метасимволов HTML, таких как знак "мень­ше" «), знак "больше" (» и амперсанд (&), необходимы еsсаре - последователь­ности. Чтобы получить знак "меньше", используйте еsсаре - последовательность "&lt; ", знак "больше" - последовательность "&gt; ", знак амперсанда - последовательность "&аmр; ". В предыдущем dос - комментарии еsсаре -последовательность применена в теге @throws.

Наконец, отметим появление в dос - комментарии слова "this". По соглашению, слово "this" всегда ссылается на тот объект, которому принадлежит вызываемый метод, соответствующий данному dос - комментарию.

Первым предложением любого dос - комментария является общее описание (summary description) того элемента, к которому этот комментарий относится. Общее описание должно позиционироваться как описывающее функции соответствующей сущности. Во избежание путаницы никакие два члена или конструктора в одном клас­се или интерфейсе не должны иметь одинакового общего описания. Особое внимание обращайте на перезагруженные методы, описание которых часто хочется начать с од­ного и того же предложения.

Внимательно следите за тем, чтобы в первом предложении dос - комментария не было точки. В противном случае общее описание будет завершено прежде времени. Например, комментарий к документации, который начинается с фразы "A college degrее, such as В. S., М. S., оr Ph. D. ", приведет к появлению в общем описании фразы "А college degree, sиch as В." Во избежание подобных проблем лучше не использовать в общем описании сокращений и десятичных дробей. Для получения символа точки нужно заменить его числовым представлением (nиmeric encoding) "&#46; ". Хотя это работает, исходный текст про граммы приобретает не слишком красивый вид:

 

/**

* A college degree, such as В &#46;S&#46;, М &#46;S&#46; о r

* Ph&#46;D.

*/

public class Degrее { ... }

 

Тезис, что первым предложением в doc - комментарии является общее описание, отчасти вводит в заблуждение. По соглашению, оно редко бывает законченным пред­ложением. Общее описание методов и конструкторов должно представлять собой

 

 

 

 

129

 

 

глагольную конструкцию (verb phrase - термин грамматики английского языка), которая описывает операцию, осуществляемую этим методом. Например:

 

· ArrayList(int initialCapacity) - создает пустой список с заданной начальной емкостью.

· Collection. size() - возвращает количество элементов в указанной коллекции.

 

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

 

· ТimerTask - задача, которая может быть спланирована классом Тiтeг для однократного или повторяющегося исполнения.

· Math.РI - значение типа double, наиболее близкое к числу (отношение длины окружности к ее диаметру).

 

В этой статье рассмотрены лишь основные соглашения, касающиеся doc - коммен­тариев, существует целый ряд других соглашений. Имеется несколько руководств по стилю написания dос - комментариев [Javadoc-a, VermeulenOO]. Есть также утилиты, проверяющие соблюдение этих правил [Qoclint].

Начиная с версии 1.2.2, утилита Javadoc имеет возможность "автоматически ис­пользовать вновь" и "наследовать" комментарии к методам. Если метод не имеет dос - комментария, Javadoc находит среди приемлемых наиболее близкий dOc-коммента­рий, отдавая при это предпочтение интерфейсам, а не суперклассам. Подробности алгоритма поиска комментариев приводятся в "The Javadoc Manual".

Это означает, что классы могут заимствовать dос - комментарии из реализуемых ими интерфейсов вместо того, чтобы копировать комментарии у себя. Такая возмож­ность способна сократить или вовсе снять бремя поддержки многочисленных наборов почти идентичных dос - комментариев, но у нее есть одно ограничение. Наследование dос – комментариев слишком бескомпромиссно: наследующий метод никак не может поменять унаследованный doc - комментарий. Между тем метод нередко уточняет со­глашения, унаследованные от интерфейс и в этом случае он действительно нуждается в собственном dос - комментарии.     

Простейший способ уменьшить вероятность появления ошибок в комментариях к документации - это пропустить НТМL - файлы, сгенерированные утилитой Javadoc, через программу проверки кода HTML (HTML validity checker). При этом будет обнаружено множество случаев неправильного использования тегов и метасимволов HTML, которые нужно исправить. Некоторые из программ проверки кода HTML, например шеbliпt [WebIint], доступны в Интернете.

Следует привести еще одно предостережение, связанное с комментариями к доку­ментации. Комментарии должны сопровождать все элементы внешнего API, но этого не всегда достаточно. для сложных API, состоящих из множества взаимосвязанных

 

 

130

 

 

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

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

 

131

 

 

Глава 7

Общие вопросы программирования

 

 

Данная глава посвящена обсуждению основных элементов языка Java. В ней рассматриваются интерпретация локальных переменных, использование библиотек и различных типов данных, а также две выходящие за рамки языка возможности: отражение (reflection) и машинно-зависимые методы (native method). Наконец, обсуждаются оптимизация и соглашения по именованию.

 

Сводите к минимуму область видимости локальных переменных

 

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

Язык программирования указывает, что локальные переменные должны декла­рироваться в начале блока. И программисты продолжают придерживаться этого по­рядка, хотя от него уже нужно отказываться. Напомним, что язык программирования Java позволяет объявлять переменную в любом месте, где может стоять оператор.

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

 

132

 

 

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

Почти каждая декларация локальной переменной должна содержать инициа­лизатор. Если у вас недостаточно информации для правильной инициализации пере­менной, вы должны отложить декларацию до той поры, пока она не появится. Исключение из этого правила связано с использованием операторов tгу / catch. Если для инициализации переменной применяется метод, инициирующий появление обраба­тываемого исключения, то инициализация переменной должна осуществляться внутри блока try. Если переменная должна использоваться за пределами блока try, деклари­ровать ее следует перед блоком try, там, где она еще не может быть "правильно ини­циализирована" (статья 35).

Цикл предоставляет уникальную возможность для сужения области видимости переменных. Цикл for позволяет объявлять переменные цикла (loop variabIe), ограни­чивая их видимость ровно той областью, где они нужны. (Эта область состоит из соб­ственно тела цикла, а также из предшествующих ему полей инициализации, проверки и обновления.) Следовательно, если после завершения цикла значения его переменных не нужны, предпочтение следует отдавать циклам for, а не while.

Представим, например, предпочтительную идиому для организации цикла по не­коей коллекции:

 

for (Iterator i = с.iterator(); i.hasNext(); ) {

doSomething(i.next()); }

 

для пояснения, почему данный цикл for предпочтительнее более очевидного цикла while, рассмотрим следующий фрагмент кода, в котором содержатся два цикла while и одна ошибка:

 

Iterator i = c.iterator();

 while (i.hasNext()) {

doSomething(i.next()); }

Iterator i2 = c2.1terator();

      while (i.hasNext()) { // Ошибка l

doSomethingElse(i2.next()); }

 

133

 

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

Если бы аналогичная ошибка копирования была допущена при применении цикла for, полученный код не был бы даже скомпилирован. для той области, где располага­ется второй цикл, переменная первого цикла уже была бы за пределами видимости:

 

for (Iterator i = с. iterator(); i. hasNext(); ) {

doSomething(i.next()); }

// Ошибка компиляции - символ i не может быть идентифицирован

for (Iterator i2 = c2.iterator(); i.hasNext();, ) {

doSomething(i2.next()); }

 

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

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

Приведем еще одну идиом)\ цикла для про смотра списка, которая минимизирует область видимости локальных переменных:

 

// Высокопроизводительная идиома для просмотра списков

// с произвольным доступом

for (int i = 0, n = list.size(); i < n; i++) {

doSomething(list.get(i)); }

 

Эта идиома полезна для реализаций интерфейсов List с произвольным доступом, та­ких как ArrayList и Vector, поскольку для таких списков она, скорее всего, работает быстрее, чем приведенная выше "предпочтительная идиома". По поводу этой идиомы важно заметить, что в ней используются две переменные цикла: i и n, и обе имеют

 

134

 

 

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

Похожие идиомы есть и для других задач с циклами, например:

 

for (int i = 0, n = expensiveComputation(); i < n; i++) {

doSomething(i) ; }

 

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

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

 


Поделиться:



Последнее изменение этой страницы: 2019-04-11; Просмотров: 234; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.047 с.)
Главная | Случайная страница | Обратная связь