7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Tools & Tips

Создание документации для кода JavaScript при помощи YUIDoc

Scroll to top
Read Time: 19 mins

Russian (Pусский) translation by AlexBioJS (you can also view the original English article)

Создание документации для вашего кода напоминает тестирование; всем известно, что это нужно делать, мы не знаем точно как, и некоторые из нас, скажем глядя правде в глаза, просто не выполняют этого, однако те, кто делают, настоятельно рекомендуют это. Это руководство ознакомит вас с последними достижениями в решении этого вопроса – YUIDoc.


Что из себя представляет YUIDoc?

YUIDoc сгенерирует документацию для API (* Application Programming Interface – интерфейс прикладного программирования, программный интерфейс приложения) на основании написанных вами комментариев.

YUIDoc – приложение для NodeJS, которое сгенерирует документацию API (в формате HTML) на основе комментариев, написанных вами в исходном коде JavaScript. Собственно, оно предназначено не только для JavaScript, а для любого языка программирования, в котором имеется поддержка блочных комментариев, отделяемых при помощи /* */. Как вы могли бы догадаться, YUIDoc – один из инструментов, публикуемых Yahoo! вместе со своей библиотекой YUI.

Для того чтобы установить YUIDoc, необходимо, чтобы у вас были установлены NodeJS и npm (* пакетный менеджер Node). Затем вы можете установить YUIDoc при помощи команды npm -g install yuidocjs. Вы будете его использовать за счет выполнения команды yuidoc <path to js folder>; подробнее поговорим об этом позже.


Фишка заключается в правильном использовании тегов

Что ж, вы знаете, что YUIDoc генерирует документацию, используя многострочные комментарии, содержащиеся в исходном файле. Конечно же, у вас могут иметься комментарии, которые не являются частью документации. Для того чтобы YUIDoc распознавала комментарий как значимый, в его начальной части должны содержаться два символа звездочки: /** Поэтому:

Естественно, что учитывается то, что находится внутри того (то есть внутри блоков с комментариями). Каждый должен содержать один и только один первичный тег; также в нем могут содержаться от 0 и более вторичных тегов. Серьезно, использовать YUIDoc вот так просто: добавьте комментарии с необходимыми тегами в ваш код и вуаля – документация готова! Так что давайте рассмотрим некоторые теги. Мы сделаем это следующий образом: пройдемся по их особенностям и случаям использования, а также простеньким примерам их использования; затем мы напишем некоторый код и сгенерируем для него документацию, благодаря чему вы лучше поймете, как комбинировать различные теги.


Превичные теги

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

@module

При помощи тега @module описывается группа родственных классов. (Да, да, в JavaScript отсутствуют классы: здесь имеются ввиду функции-конструкторы (* в Javascript конструктором становится любая функция, вызванная через new. Согласно ES-2015 в JavaScript имеются классы – «синтаксический сахар» для задания конструктора вместе с прототипом)). Если бы вы использовали YUIDoc для создания документации для кода BackboneJS, то объект Backbone был бы модулем, поскольку он содержит классы Model, Collection, View и другие. Сразу после тега вы помещаете имя модуля.

@class

При помощи тега @class описывается как раз таки описывается один класс. В контексте библиотеки YUI под этим обычно подразумевается функция-конструктор, однако если вы предпочитаете использовать другой паттерн (* обобщённое описание способа решения определённого класса задач. Идея применения шаблонов разработки восходит к работам Криса Александра (Chris Alexander, 1977 г.) и впервые была реализована в языке Smalltalk-80) и называть его собственным классом, то можете делать и так тоже. Каждый комментарий с тегом @class также должен иметь тег @static или @constructor (вторичные теги, которые мы опишем позже).

Если ваш класс является частью модуля, то вам не нужно ничего делать внутри комментария с тегом @class для указания этого: просто убедитесь, что в верхней части файла, где он располагается, имеется блок комментария с тегом @module.

@method

Естественно, что у каждого класса будет как минимум несколько методов и вы будете использовать тег @method для их описания. Имя метода будет идти после тега, и вы будете использовать вторичные теги @return и @params для описания метода.

@property

Тег @property используется для добавления свойств класса. Вам наверняка захочется использовать вместе с этим вторичные теги @type и @default.

@event

Если вы добавили собственные специальные события, которые класс может сгенерировать, то вы захотите воспользоваться тегом @event для их описания. Вот что нам сообщает документация YUIDoc по этому поводу:

Блок комментария с тегом @event является чем-то подобным блоку комментария с тегом @method, за исключением того что @return здесь роли не играет и @param используются для описания свойств объекта испускаемого события, который получают функции обратного вызова, ожидающие его.


Вторичные теги

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

@submodule

Если вы делите ваши модули на подмодули (возможно, что при этом вы хотите, чтобы каждый подмодуль находился в отдельном файле, а возможно нет), то тег @submodule к вашим услугам:

@extends

Тег @extends полезен, если у вас в коде имеются отношения "суперкласс - подкласс" (наследование). Вы можете указать, какой класс является родительским для класса, который вы документируете в данный момент:

@constructor

Если нужно создать экземпляр класса, то это означает, что для него необходима функция-конструктор. Если вы используете в коде JavaScript стандартный паттерн Прототип (* паттер, согласно которому объекты создаются на основе свойства prototype - объекта, содержащего свойства и методы, которые должны быть доступны в экземплярах конкретного ссылочного типа), то объявление класса также является и объявлением конструктора. Это означает, что вы часто увидите нечто подобное:

И вправду, вы, наверное, припоминаете, как я говорил о необходимости наличия у каждого тега @class либо тега @constructor, либо тега @static.

@static

Кстати, вот и он. Класс считается статическим, когда вы не можете создать его экземпляр. Хорошим примером такого класса может послужить встроенный объект Math: вы никогда не создаете его экземпляр (new Math()), вы вызываете его методы из самого класса.

Метод также может быть статическим: если можно создать экземпляр класса, однако он также имеет некоторые методы уровня класса, то эти методы считаются статическими (они вызываются при использовании класса, но не метода).

В данном примере вы можете создать экземпляр класса Person, однако метод all является статическим.

@final

Этот тег используется для свойств или атрибутов и указывает, что вышеупомянутое свойство является константой – ее значение не следует менять. Хотя в текущей версии JavaScript нет настоящих констант (* в ES-2015 предусмотрены константы (объявляются за счет ключевого слова const)), они в принципе могут использоваться согласно вашему руководству по стилю (* набор стандартов (правил) написания и форматирования документов - для обеспечения единообразия их вида) или стилю программирования, так что этот тег пригодиться вам в этом случае.

@param

Мы подошли к рассмотрению важного тега. Тег @param используется для определения параметров метода, описанного при помощи тега @method, и конструктора, описанного тегом @constructor, или события, описанного при помощи тега @event. После тега @param располагается три кусочка информации: имя параметра, тип (который необязательно нужно указывать) и описание. Они могут располагаться как в порядке name type description, так и в порядке type name description; но в любом случае type должен быть окружен фигурными скобками.

Также имеется несколько вариантов синтаксиса и для кусочка name. За счет помещения его в квадратные скобки указывается, что он является необязательным, в то время как при помощи добавления =someVal (* где someVal - некоторое значение) после него указывается значение по умолчанию параметра (дума понятно, что только у необязательного параметра имеется значение по умолчанию). Также если нужно указать, что в качестве параметра может быть передано более одного аргумента, то добавьте * (* согласно документации YUIDoc 2018 года для этой цели используется ...name (подобно параметру rest стандарта ES-2015 с оператором ... в function showName(firstName, lastName, ...rest))). (Очевидно, что name* используется, когда необходимо указать, что в качестве параметра может быть передано от 1 и более аргументов, тогда как [name]* используется в случае, если нужно указать, что в качестве параметра может быть передано от 0 и более аргументов (* согласно документации YUIDoc 2018 года с этой целью используется [...name])).

@return

Большинство ваших методов будут возвращать значение, и этот тег используется для его описания. Не забудьте указать тип этого значения и его описание.

@type

Помните первичный тег @property? Вы захотите указать тип тех свойств, правда ведь? Как раз для этого и служит тег @type. Укажите тип после тега; вы также можете перечислить несколько типов, разделяя их вертикальными чертами.

@private / @protected

В традиционных языках программирования используются приватные свойства или методы - те, что недоступны снаружи объекта. Также как и в случае с константами, они используются в JavaScript только для обеспечения работоспособности объектов, однако вы можете воспользоваться @private для того чтобы их отметить. Обратите внимание, что в документации, сгенерированной YUIDoc, приватные свойства не показываются (звучит вполне разумно), так что это позволяет вам создавать комментарий о некоторой возможности для себя без отображения его в документации.

Защищенные свойства и методы – нечто среднее между публичными и приватными, поскольку доступ к ним имеется только в экземплярах классов и подклассов. Если вы используете их в коде JavaScript, то применяйте тег @protected.

@requires

Ессли модуль зависит от одного или нескольких других модулей, то вы можете отметить это при помощи тега @requires:

Обратите внимание, что после тега @requires могли бы быть также перечислены несколько завиисмостей, разделенных запятыми.

@default

При объявлении свойства, описываемого при помощи тега @property, вам могло бы показаться уместным задать для него значение по умолчанию, описываемое при помощи тега @default. @default должен всегда использоваться вместе с тегом @type.

@uses

Как я уже упомянул, JavaScript не имеет настоящих классов, однако этот язык достаточно гибок для создания иллюзии классов и даже подклассов. Еще более круто то, что он гибок достаточно для создания миксин, или модулей, – тот случай, когда один класс «ворует» свойства или методы другого класса (* при этом миксин не должен быть родительским для базового класса). И это не относится к наследованию, поскольку вы можете примешать части более чем одного класса (естественно, YUI предоставляет возможность реализовать их, так же как и Dojo и другие библиотеки). Если вы пользуетесь ими, то тег @uses покажется вам очень полезным: он позволяет вам указать, части каких классов добавлены к данному классу.

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

@example

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

@chainable

Вы, вероятно, знакомы с возможностью сцепления методов на примере библиотеки jQuery. Знаете, когда вы можете вызвать метод из вызова метода, поскольку методы возвращают объект? Отметьте, что ваши методы способны на это при помощи @chainable.

@deprecated / @since / @beta

Все эти три тега используются для добавление информации о поддержке кода (и это мог бы быть любой код: модуль, класс, метод или о что-нибудь еще). Используйте @deprecated для того, чтобы указать, что некоторая функциональная возможность считается устаревшей (и вероятно будет удалена в следующей версии кода). По желанию вы можете добавить сообщение, которое поясняет, какой имеется альтернативный вариант.

Тег @since используется просто для указания того, начиная с какой версии данный код был добавлен. И тег @beta используется для указания того, что код находится в бета-версии (* предварительная версия программного продукта, выпущенная для тестирования): Согласно YUI предполагается, что код, находящийся в  бета-версии и описанный при помощи тега @beta, возможно будет «подвергнут изменениям, в результате которых код может стать несовместимым с предыдущими версиями, в ближайшем будущем».

@extension / @extensionfor / extension_for

Тег @extension (и его псевдонимы) является почти полной противоположностью тега @uses. Используйте его для указания того, к каким классам этот класс для расширения возможностей других может быть добавлен. Конечно же, учтите, что это вовсе не означает то, что он всегда добавляется к другим классам, но то, что может быть добавлен.


Комментарии и Markdown

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

Во-первых, вы часто захотите добавить чуть больше информации о вашем коде по сравнению с тем, что предлагают теги. Возможно, вы хотите описать цель методов или то, какую роль отыгрывает класс в программе в целом. Добавьте эти комментарии вверху блока с комментарием, выше всех тегов. YUIDoc опознает их и добавит в документацию.

Во-вторых, вам будет приятно узнать, что эти комментарии, равно как и любые описания или сообщение, написанные после тегов, могут быть написаны на Markdown (* упрощенный язык разметки, в котором для форматирования используется чистый текст), и YUIDoc преобразует этот код в корректный код на HTML. Вы даже можете выделить отступом блоки с примерами кода в ваших комментариях, в результате чего синтаксические элементы будут выделены яркостью или цветом!


Пример использования

Теперь, когда мы рассмотрели теги, давайте собственно напишем некоторый код и создадим для него документацию. Давайте создадим модуль Store, в котором содержатся два класса: Item и Cart. Каждый экземпляр Item будет являться типом товара на складе; у него будут свойства для указания имени, цены и количества. Экземпляр класса Cart может добавлять товары в корзину и вычислять общую цену товаров в корзине (включая налог с продаж (* косвенный налог, взимаемый в виде процента от розничной стоимости продаваемых товаров)). Тут все довольно просто, однако при этом у нас имеется достаточно разнообразный функционал, чтобы воспользоваться многими из рассмотренных нами тегов. Весь далее рассматриваемый код я поместил в файл store.js.

Мы начинаем с создания модуля:

Теперь давайте создадим «константу» – налоговую ставку (* фиксированная сумма, которая должна быть уплачена с единицы товара).

Это свойство является константой (описываемой при помощи тега @final) типа Number, описываемого при помощи тега @type. Обратите внимание на то, что я добавил тег @static. Это так, потому что по какой-то причине при создании нами документации для этого файла YUIDoc отобразит эту константу как свойство класса Item. Похоже, что YUIDoc не распознает свойства, добавленные к модулю. Думаю, что мог бы создать статический класс для размещения этой константы (и других констант, которые могли бы понадобиться, если бы мы разрабатывали наш модуль дальше), однако я оставил все как есть для напоминания: для того чтобы воспользоваться всеми потенциальными возможностями YUIDoc, вам, вероятно, необходимо будет изменить свой стиль программирования. Вы должны будете решить, подходит ли вам это.

Теперь переходим к классу Item:

Как вы видите, этот конструктор принимает три параметра. Затем внутри конструктора к объекту добавляются три свойства, которые мы также описываем. Поскольку мы хотим добавить к каждому экземпляру Item уникальный ID (* identifier – идентификатор), нам необходимо добавить статическое (уровня класса) свойство для увеличения значения ID и другое статическое свойство – объект, при помощи которого добавленные экземпляры Item отслеживаются на основании их ID.

Как насчет класса Cart?

Тут нет ничего особо нового: обратите внимание, что мы указываем в качестве состояния по умолчанию (изначального) свойства items пустой объект.

Теперь рассмотри методы. Переходим к addItem. Один из его параметров необязателен, так что мы объявляем его соответственно и задаем в качестве его значения по умолчанию 1. Также обратите внимание, что мы добавляем для метода возможность сцепления методов, что описывается при помощи @chainable..

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

Если вы хотите протестировать этот код, то ниже приводятся простые тесты:


Созданем документацию

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

Если вы установили YUIDoc глобально при помощи npm, то вы сможете для этого просто выполнить команду yuidoc {path to js} (* path to js - путь к файлу js). В моем случае это

После этого вы увидите, что у вас имеется папка out в указанной; откройте out/index.html и вы увидите документацию. Ниже показано, как выглядит часть документации класса Cart:

YUIDoc DocumentationYUIDoc DocumentationYUIDoc Documentation

Настраиваем результат

Имеется несколько параметров конфигурации, которые вы можете задать при использовании YUIDoc. Конечно же, вы можете задать их в виде флажков (* переключателей) командной строки, однако я бы предпочел установить их при помощи конфигурационного файла в формате JSON (* JavaScript Object Notation – текстовый формат обмена данными, основанный на JavaScript). В папке вашего проекта создайте файл под названием yuidoc.json. Для начала, вы можете указать множество общей информации о проекте; она особо не влияет на конечный результат, однако может оказаться полезной:

Также имеется ряд собственно опций, которые вы можете задать. Ниже перечислены некоторые особо интересные:

  • linkNatives: установите в качестве ее значения “true”, чтобы добавить для нативных (* описанных в стандартах Javascript) типов вроде String или Number ссылки на документацию MDN
  • outdir: используйте этот параметр для того, чтобы переименовать папку out
  • paths: используйте этот параметр для установления путей, по которым YUIDoc ищет файлы JavaScript
  • exclude: задайте в качестве этой опции список разделенных запятой необходимых вам файлов, чтобы они были проигнорированы YUIDoc

Если вы установили значение опции paths, то вы можете выполнить команду yuidoc -c yuidoc.json и YUIDoc запустится. Даже если вы не задали значение для paths и просто выполнили yuidoc ., YUIDoc увидит тот конфигурационный файл и воспользуется им.

Ниже приведен весь мой конфигурационный файл для этого проекта:


Оценка

На основании предлагаемых YUIDoc тегов вы можете понять, что это приложение было создано для документирования кода JavaScript, написанного в традиционном ООП (* объектно-ориентированное программирование) стиле, а также специально для виджетов YUI и тому подобное (собственно, я не затронул некоторые специфичные для YUI теги). По этой причине вы можете решить, что некоторые теги не особо вам полезны. Затем вы должны спросить себя, хотели ли бы вы изменить свой стиль программирования, чтобы лучше подстроиться под стиль, которым «думает» YUIDoc. Но даже если вы не собираетесь изменять его, я думаю, вы обнаружите, что многие теги YUIDoc вполне вписываются в ваш стиль.

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

Вышенаписанный нами код примера состоит из 120 строк с комментариями, а без них – из 40. Очевидно, что это чрезвычайно простой пример, и почти любой пример из реального мира разработки был бы более сбалансированным; однако, при чтении такого кода могли бы возникнуть трудности. Лично я собираюсь справедливо оценить его: Я буду документировать мой код JavaScript по мере написания (или как минимум рядом с ним (* в отдельном файле)) в течение ближайших нескольких недель. Мне будет интересно узнать, влияет ли или как влияет это на мой стиль программирования и мой трудовой процесс.

Вы знаете заведенный порядок: понравилось вам YUIDoc или нет, дайте мне знать об этом в комментариях!


За подробностями обращайтесь к следующий ресурсам:

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.