Advertisement
  1. Code
  2. Tools & Tips

Створення документації для коду JavaScript за допомогою YUIDoc

by
Read Time:17 minsLanguages:

Ukrainian (українська мова) 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 під цим звичайно мається на увазі функція-конструктор, проте якщо ви віддаєте перевагу використанню іншого шаблону (* узагальнений опис способу вирішення певного класу завдань) та називати його власним класом, то можете поступати і так. Кожний коментар з тегом @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)), вони у принципі можуть використовуватися згідно з вашим посібником зі стилів (* набір стандартів (правил) написання та форматування документів – для забезпечення одноманітності їх вигляду. Подібний набір правил для конкретної організації визначає те, що часто називають корпоративним стилем (house style). Деякі посібники зі стилів (особливо у графічних платформах) приділяють особливу увагу графічному дизайну. Посібники зі стилів для веб-сторінок містять вказівки не тільки з текстових, але й з візуальних та технічних аспектів реалізації)) або стилю програмування, так що цей тег стане вам у пригоді у цьому випадку.

@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
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.