Если вы уже используете Java 8, возможно, вы видели несколько новых тегов Javadoc: @apiNote , @implSpec и @implNote . Что с ними? И что вам нужно делать, если вы хотите их использовать?
обзор
Этот пост будет иметь быстрый просмотр происхождения и текущего статуса тегов. Затем он объяснит их значение и подробно расскажет, как их можно использовать с IDE, инструментом Javadoc и с помощью плагина Maven Javadoc.
Я создал демонстрационный проект на GitHub, чтобы показать некоторые примеры и необходимые дополнения к pom.xml Maven. Для облегчения неприятия Maven он уже содержит сгенерированный Javadoc .
контекст
происхождения
Новые теги Javadoc являются побочным продуктом JSR-335 , в котором представлены лямбда-выражения. Они возникли в контексте методов по умолчанию, потому что они требовали более стандартизированной и детальной документации.
В январе 2013 года Брайан Гетц дал мотивацию и сделал предложение об этих новых тегах. После недолгого обсуждения он превратился в запрос на функцию через три недели. К апрелю JDK Javadoc производитель был обновлен, и список рассылки сообщил, что они готовы к использованию.
Текущий статус
Важно отметить, что новые теги официально не документированы (они отсутствуют в официальном списке тегов Javadoc ) и, следовательно, могут быть изменены. Кроме того, разработчик Майк Дуйго написал :
Не планируется пытаться популяризировать эти конкретные теги вне использования документации JDK.
Поэтому, хотя, безусловно, полезно понимать их значение, командам следует тщательно обдумать, стоит ли их использовать риск, связанный с использованием недокументированного поведения. Лично я так думаю, так как считаю значительные инвестиции, уже сделанные в JDK, слишком высокими, чтобы их можно было обратить вспять. Также было бы легко удалить или найти / заменить их вхождения в базе кода, если это станет необходимым.
@apiNote , @implSpec и @implNote
Давайте рассмотрим суть вещей. В чем смысл этих новых тегов? И где и как они используются?
Смысл
Новые теги Javadoc довольно хорошо объясняются в описании запроса функции (я немного изменил макет):
Есть много вещей, которые мы могли бы документировать о методе в API. Исторически мы формулировали их как «спецификации» (например, необходимые постусловия) или «замечания по реализации» (например, подсказки, которые дают пользователю представление о том, что происходит под капотом). Но на самом деле, есть четыре блока (и мы втиснули их в два, или на самом деле 1,5):
{API, реализация} x {спецификация, примечания}
(Мы иногда используем термины нормативный / информативный, чтобы описать разницу между спецификацией / примечаниями.) Вот некоторые описания того, что принадлежит каждому блоку.
1. Спецификация API.
Это тот, кого мы знаем и любим; описание, которое в равной степени применимо ко всем допустимым реализациям метода, включая предварительные условия, постусловия и т. д.2. API заметки.
Комментарий, обоснование или примеры, относящиеся к API.3. Спецификация реализации.
Именно здесь мы говорим, что значит быть допустимой реализацией по умолчанию (или переопределяемой реализацией в классе), такой как «throws UOE». Точно так же здесь мы опишем, что делает по умолчанию дляputIfAbsent
. Именно из этого окна потенциальный исполнитель получает достаточно информации, чтобы принять разумное решение относительно того, следует ли переопределять.4. Замечания по реализации.
Информативные заметки о реализации, такие как характеристики производительности, которые являются специфическими для реализации в этом классе в этом JDK в этой версии и могут измениться. Эти вещи могут варьироваться в зависимости от платформ, поставщиков и версий.Предложение: добавьте три новых тега Javadoc, @apiNote , @implSpec и @implNote . (Оставшееся поле, API Spec, не нуждается в новом теге, поскольку именно так Javadoc уже используется.) @Impl {spec, note} может одинаково хорошо применяться к конкретному методу в классе или методу по умолчанию в интерфейсе.
Таким образом, новые теги Javadoc предназначены для классификации информации, приведенной в комментарии. Он различает спецификацию поведения метода, класса,… (которая актуальна для всех пользователей API — это «обычный» комментарий и будет @apiSpec, если он существует) и другой, более эфемерной или менее универсально полезной документации. , Более конкретно, пользователь API не может полагаться ни на что, написанное в @implSpec или @implNote , потому что эти теги связаны с этой реализацией метода, не говоря уже о переопределении реализаций.
Это показывает, что использование этих тегов в основном поможет разработчикам API. Но даже Joe Developer, работающий над большим проектом, может считаться дизайнером в этом контексте, так как его код наверняка потребляется и / или изменяется его коллегами в какой-то момент в будущем. В этом случае полезно, если в комментарии четко описаны различные аспекты API. Например, «выполняется за линейное время» часть спецификации метода (и, следовательно, не должно быть ухудшено) или деталь текущей реализации (чтобы ее можно было изменить).
Примеры
Давайте посмотрим несколько примеров! Сначала из демонстрационного проекта, чтобы показать некоторые причины использования тегов, а затем из JDK, чтобы увидеть их в работе.
Лотерея
Проект содержит интерфейс Lottery
из какой-то фиктивной библиотеки. Интерфейс был впервые включен в версию 1.0 библиотеки, но для версии 1.1 должен быть добавлен новый метод. Для обеспечения обратной совместимости это метод по умолчанию, но планируется сделать его абстрактным в версии 2.0 (что даст клиентам некоторое время для обновления своего кода).
С помощью новых тегов документация метода четко различает значения его документации:
Документация Lottery.pickWinners
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/** * Picks the winners from the specified set of players. * <p> * The returned list defines the order of the winners, where the first * prize goes to the player at position 0. The list will not be null but * can be empty. * * @apiNote This method was added after the interface was released in * version 1.0. It is defined as a default method for compatibility * reasons. From version 2.0 on, the method will be abstract and * all implementations of this interface have to provide their own * implementation of the method. * @implSpec The default implementation will consider each player a winner * and return them in an unspecified order. * @implNote This implementation has linear runtime and does not filter out * null players. * @param players * the players from which the winners will be selected * @return the (ordered) list of the players who won; the list will not * contain duplicates * @since 1.1 */ default List<String> pickWinners(Set<String> players) { return new ArrayList<>(players); } |
JDK
JDK широко использует новые теги. Несколько примеров:
-
ConcurrentMap
:- Несколько @implSpec, определяющих поведение реализаций по умолчанию, например для
replaceAll
. - Интересные @implNote с
getOrDefault
иforEach
. - Повторял @implNote s для абстрактных методов, которые имеют реализации по умолчанию в Map, документируя, что «Эта реализация намеренно повторно абстрагирует неподходящее значение по умолчанию, предоставленное в Map.», Например,
replace
.
- Несколько @implSpec, определяющих поведение реализаций по умолчанию, например для
-
Objects
использует @apiNote, чтобы объяснить, почему были добавлены, казалось бы, бесполезные методыisNull
иnonNull
. - Абстрактный класс
Clock
использует @implSpec и @implNote в своем комментарии к классу, чтобы различать, какие реализации следует остерегаться и как реализованы существующие методы.
наследование
Когда переопределяющий метод не имеет комментариев или наследует свой комментарий через {@inheritDoc}
, новые теги не включаются. Это хорошая вещь, так как они обычно не применяются. Чтобы наследовать определенные теги, просто добавьте фрагмент комментария @tag {@inheritDoc}
в комментарий.
Реализуемые классы в демонстрационном проекте исследуют различные возможности. README дает обзор.
Поддержка инструментов
Иды
Вы, вероятно, захотите увидеть улучшенную документацию (JDK и, возможно, свою собственную) в своей IDE. Так как же наиболее популярные из них сейчас справляются с ними?
Eclipse отображает теги и их содержимое, но не обеспечивает никакого специального рендеринга, такого как упорядочивание или предварительная обработка заголовков тегов. Есть запрос функции для решения этой проблемы.
В текущей версии сообщества IntellyJ 14.0.2 не отображаются ни теги, ни их содержимое. Очевидно, это было решено в канун Рождества (см. Этот билет ), поэтому я думаю, что в следующей версии больше не будет этой проблемы. Я не могу ничего сказать относительно рендеринга, хотя.
NetBeans также не отображает ни тегов, ни содержимого, и я не смог найти ни одного запроса с просьбой исправить это.
В целом не красивая картинка, но понятная, учитывая тот факт, что это не официальная функция Javadoc.
Генерация Javadoc
Если вы начнете использовать эти теги в своем собственном коде, вы скоро поймете, что генерирование Javadoc не выполняется из-за неизвестных тегов. Это легко исправить, вы просто должны сказать ему, как обращаться с ними.
Командная строка
Это можно сделать с помощью аргумента командной строки -tag . Следующие аргументы разрешают эти теги везде (т. Е. Для пакетов, типов, методов и т. Д.) И присваивают им заголовки, используемые в настоящее время JDK:
Рассказывая Javadoc о новых тегах
1
2
3
|
-tag "apiNote:a:API Note:" -tag "implSpec:a:Implementation Requirements:" -tag "implNote:a:Implementation Note:" |
(Я читаю официальную документацию, как будто эти аргументы должны быть -tag apiNote: a: ”Примечание API:” [обратите внимание на кавычки], но это не работает для меня. Если вы хотите ограничить использование новых тегов или не включать их вообще, документация -tag говорит вам, как это сделать.)
По умолчанию все новые теги добавляются в конец сгенерированного документа, который помещает их ниже, например, @param и @return . Чтобы изменить это, все теги должны быть перечислены в желаемом порядке, поэтому вы должны добавить известные теги в список ниже трех выше:
Перечисление известных тегов после новых
1
2
3
4
5
6
7
|
-tag "param" -tag "return" -tag "throws" -tag "since" -tag "version" -tag "serialData" -tag "see" |
специалист
Плагин Maven Javadoc имеет тег настройки конфигурации, который используется для подробного создания одинаковых аргументов командной строки. Демонстрационный проект на GitHub показывает, как это выглядит в pom .
отражение
Мы видели, что были добавлены новые теги Javadoc @apiNote , @implSpec и @implNote для разделения документации на части с различной семантикой. Понимание их полезно для каждого разработчика Java. Разработчики API могут использовать их в своем собственном коде, но имейте в виду, что они все еще не документированы и поэтому могут быть изменены.
Мы наконец-то взглянули на некоторые из задействованных инструментов и увидели, что поддержка IDE нуждается в улучшении, но инструмент Javadoc и плагин Maven можно параметризировать, чтобы в полной мере использовать их.
Ссылка: | Новые теги Javadoc @apiNote, @implSpec и @implNote от нашего партнера JCG Николая Парлога в блоге CodeFx . |