1. Code
  2. JavaScript

JavaScript Dokumentation mit YUIDoc

Quellcode zu dokumentieren ist vergleichbar mit Testen! Wir alle wissen dass es getan werden soll, doch wie es angehen? Und, sind wir mal ehrlich, viele tun es einfach nicht. Diejenigen welche wirklich testen und dokumentieren sind die wirklich Professionellen. Diese Anleitung wird Sie schnell und einfach in die Lage versetzen YUIDoc anzuwenden.
Scroll to top
17 min read

German (Deutsch) translation by Kaspar Thomann (you can also view the original English article)

Quellcode zu dokumentieren ist vergleichbar mit Testen! Wir alle wissen dass es getan werden soll, doch wie es angehen? Und, sind wir mal ehrlich, viele tun es einfach nicht. Diejenigen welche wirklich testen und dokumentieren sind die wirklich Professionellen. Diese Anleitung wird Sie schnell und einfach in die Lage versetzen YUIDoc anzuwenden.


Was ist YUIDoc?

YUIDoc erzeugt eine API Dokumentation welche aus den Kommentaren im Code aufbereitet wird.

YUIDoc ist eine NodeJS App welche eine API Dokumentation (auf HTML Basis) erzeugt. Die Angaben stammen ausschliesslich aus dem JavaScript Quellcode. Überhaupt ist YUIDoc nicht nur für JavaScript Codes; jede andere Programmiersprache kann mit Hilfe von YUIDoc kommentiert werden, solange diese die Begrenzugszeichen /* */ zulässt. Wie vielleicht vermutet wird ist YUIDoc ein Werkzeug von Yahoo! welches im Rahmen deren YUI Library publiziert wird.

Um YUIDoc zu installieren wird NodesJS und der Node Package Manager (npm) vorausgesetzt. Sind die Voraussetzungen erfüllt, lässt sich YUIDoc (in der Rolle admin bzw. superuser) installieren über npm -g install yuidocjs Somit kann YUIDoc benutzt werden. Nutzen Sie schon mal (als normaler User) den Befehl yuidoc -v um sich die installierte Version anzeigen zu lassen. Weiter unten folgt mehr dazu.


Es geht um die Markierungen!

Sie wissen nun dass YUIDoc die Dokumenation über mehrere Zeilen lange Kommentare in der Quellcode Datei erzeugt. Klar werden auch Kommentare im Quellcode stehen, die nicht in die offizielle Dokumentation hinein gehören. Um YUIDoc zu den wichtigen Kommentaren zu leiten muss ein entsprechender Teil mit dem Doppelstern beginnen: /** Hier ein Beispiel:

1
2
/**

3
YUIDoc will process this

4
*/
5
6
/* 

7
But not this

8
*/

Natürlich zählt eben nur was sich innerhalb der Kommentar Blocks befindet. Davon muss sich in jedem Block eines oder gleich mehrere Haupt-Kennzeichen befinden. Zusätzlich können dann auch noch Unter-Kennzeichen vorhanden sein. Wirklich, YUIDoc ist ganz einfach: Kommentare mit den entsprechenden Kennzeichnungen im Quellcode erfassen, und voilà: Dokumentation! Hier sind schon die ersten Haupt-Kennzeichen zum Beginn. Wir gehen wie folgt vor: Anhand einfacher Beispiel wird der Gebrauch der Haupt-Kennzeichen aufgezeigt. Dann schreiben und dokumentieren wir etwas Quellcode um noch deutlicher zu sein wie diese Kennzeichnungen zusammenwirken.


Haupt-Kennzeichen

Zur Wiederholung: denken Sie daran dass jeder einzelne Kommentar-Block nur ein einziges Haupt-Kennzeichen enthalten darf. Auf diese Weise enthält jeder Block eine Erklärung zum Code, was genau geschieht.

@module

Mit dem @module Tag werden die darin enthaltenen Klassen beschrieben. (Na klar, aber JavaScript kennt gar keine Klassen: YUIDoc bezieht sich damit auf Kontruktor Funktionen in diesem Modul.) Sollte BackboneJS bspw. mit YUIDoc beschrieben werden, so würde das Backbone Objekt als Modul erfasst werden, da es Model, Collection, View, und noch weitere Klassen enthält. Gleich nach dem @modul Kennzeichen folgt der eigentliche Modul-Name.

1
2
/**

3
@module Backbone

4
 */
5
 var Backbone = Backbone || {};

@class

Mit dem @class Tag wird eine einzelne Klasse beschrieben. In der YUI Library wird damit eine Konstruktor Funktion bezeichnet. Doch sollten andere Meinungen bestehen wofür dieser Tag verwendet werden sollte, ist dies auch zulässig. Jeder Kommentar zum @class Tag könnte zusätzlich mit @static oder @constructor Tag ergänzt werden.

1
2
/**

3
@class Model

4
 */
5
 function Model () {}

Sollte die Klasse Teil eines Modules sein braucht man im @class Kommentar nichts weiteres dafür vorzumerken. Es muss lediglich ein @module Kommentar Block zu Beginn dieser Datei vorhanden sein.

@method

Bestimmt hat jede Klasse ein paar Methoden. So wird jede Methode mit einem @method Tag beschrieben. Der Name der Methode folgt unmittelbar darauf und mit @return und @params wird die Methode dann weiter beschrieben.

1
2
/**

3
@method render

4
*/
5
View.prototype.render = function (data) {}

@property

Mit dem @property Tag werden die Eigenschaften einer Klasse aufgeführt. Sie werden bestimmt auch @type und @default Tag verwenden

1
2
/**

3
@property templateString

4
*/
5
this.templateString = "div";

@event

Arbeitet eine Klasse mit Events, so wird der @event Tag zur Beschreibung der Ereignisse benutzt. Lesen Sie was die YUIDoc Dokumentation dazu schreibt:

Ein @event Block ist vergleichbar mit dem @method Block, mit dem Unterschied dass @return völlig irrelevant ist, und @param zur Beschreibung der Eigenschaft im Zusammenhang mit dem Callback zum Event Objekt verwendet wird.


Sekundäre Tags

Kommentarblöcke können mehr als einen Sekundär Bezeichner enthalten; vielmehr sind davon gleich mehrere vorhanden und zudem erscheint derselbe Type gleich merhfach. Schauen wir uns doch die wohl am häufigsten benutzten Secondary Tags an.

@submodule - Unter-Modul

Sollten die Module weiter unterteilt werden (vielleicht ein Submodul pro Datei, oder auch nicht), so wird das @submodule Tag zur Einteilung benutzt.

1
2
/**

3
@module Util

4
@submodule array

5
*/
6
Util.array = {};

@extends - erweitert

Das @extends Tag wird für Beziehungen zwischen Superclass / Subclass eingesetzt. Man kann damit den Parent der aktuell beschriebenen Class bestimmen.

1
2
/**

3
@class AppView

4
@extends Backbone.View

5
*/
6
var AppView = Backbone.View.extend({});

@constructor

Eine Class wird in der Regel durch eine Konstruktor-Funktion instanziiert. Mit der standard Prototype Verwendung in JavaScript ist die Class Deklaration auch gleich der Konstuktor. Somit wird meist folgendes zu sehen sein:

1
2
/**

3
@class Recipe

4
@constructor

5
*/
6
function Recipe () {}

Man wird sich möglicherweise an meine Aussage erinnern, dass jede @class entweder ein @constructor oder ein @static Tag (Sekundärer Bezeichner) haben solle.

@static - statisch

Apropos @static, hier kommts. Von einer static Class kann keine Instanz gebildet werden. Ein gutes Beispiel dafür ist das eingebaute Math Objekt: davon wird nie eine Instanz erstellt ( new Math() ). Die Methoden werden immer dirket von der Class selbst benutzt.

1
2
/**

3
@class MathHelpers

4
@static

5
*/
6
var MathHelpers = {};

Methoden können auch static sein: in einer instanziierten Class sind Methoden auf der Class-Ebene statisch (sie werden über die Class aufgerufen und nicht über die Instanz).

1
2
/**

3
@class Person

4
@constructor

5
*/
6
function Person () {}
7
8
/**

9
@method all

10
@static

11
*/
12
Person.all = function () {};

In diesem Beispiel hier kann eine Instanz von Person kreiert werden, doch die all Methode ist static.

@final

Dieses Tag wird für Eigenschaften bzw. Attribute benutzt, und markiert diese als Konstante: also nicht verändern. Da JavaScript z.Zt. keine wirklichen Konstanten kennt, soll doch im Code oder in der Beschreibung dazu auf konstante Werte hiigewiesen werden können.

1
2
/**

3
@property DATE_FORMAT

4
@final

5
*/
6
var DATE_FORMAT = "%B %d, %Y";

@param

Hier kommt was sehr wichtiges: mit dem @param Tag sind Parameter für @method (eingeschliesslich @constructor ) und auch solche für @event beschrieben. Jeder @param wird mit drei Teilen genauer umschrieben: sein Name, dessen Type (optional) sowie die Beschreibung. Diese können entweder in der Reihefolge Name Type Beschreibung oder Type Name Beschreibung vorliegen; in jedem Fall aber muss Type in geschweiten Klammer stehen.

1
2
/**

3
@method greet

4
@param person {string} The name of the person to greet

5
*/
6
function greet (person) {}

Auch gibt es diverse Arten mit dem Paramter Name weitere Angaben dazu zu erfassen. Optionale Parameter-Namen stehen in eckigen Klammern. Die zusätzliche Angabe wie =einWert verdeutlicht eine allfällige Voreinstellung (offensichtlich aber besitzen nur optionale Parameter eine solche Angabe). Platzhalter für mehr als ein Argument bekommen ein * angefügt, um dies anzuzeigen. (Offenkundig ist name* ein Platzhalter für 1 oder mehrere Argumente, während [name]* ein solcher für 0 oder mehrere Argumente beschriebt).

1
2
/**

3
@class Template

4
@constructor

5
@param template {String} The template string

6
@param [data={}] {Object} The object whose properties will be rendered in the template

7
*/
8
function Template (template, data) {}

@return

Meistens wird eine Methode einen Rückgabewert senden. Mit diesem Tag wird der Rückgabewert beschrieben. Der Type des Rückgabewertes und ein Beschreibung dazu sollten selbstverständlich mit dabei sein.

1
2
/**

3
@method toHTML

4
@param [template=Recipe.defaultTemplate] {Template} A template object

5
@return {String} The recipe contents formatted in HTML with the default or passed-in template.

6
*/
7
Recipe.prototype.toHTML = function (template) {
8
    return "whatever";
9
};

@type

Oben wurde doch der @property Tag beschrieben, ja? Sicher sollen Angaben zum Type von Eigenschaften (properties) vorhanden sein! Nun, der @type Tag ist genau dazu geeignet. Spezifizieren Sie den Type nach diesem Tag. Mehrfache Typen werden durch vertikale Striche getrennt:

1
2
/**

3
@property URL

4
@type String

5
*/
6
URL: "http://net.tutsplus.com",
7
8
/**

9
@property person

10
@type String|Person|Object

11
*/
12
this.person = new Person();

@private / @protected

Traditionelle Programmiersprachen besitzen private Eigenschaften und Methoden: ausserhalb der Instanz nicht zugängliche Komponenten. Genau gleich wie schon bei Konstanten gesehen, verhält sich JavaScript mit dem @private Tag. Private Komponenten existieren nur in der Handhabung der Programmierung, die Sprache selbst kennt sie (noch) nicht. Für YUIDoc ist jedoch bemerkenswert dass private Einheiten in der generierten Dokumentation nicht erscheinen. Damit sind solche Angaben echt privater Natur. Sie bleiben Ihnen vorbehalten und werden nicht publiziert.

1
2
/**

3
@method _toString

4
@private

5
*/
6
var _toString = Object.prototype.toString.call;

Protected Eigenschaften und Methoden befinden sich halbwegs zwischen öffentlich undprivat: sie nur innerhalb der Instanz und SubClasses davon zugänglich. Sollte dies im JavaScript vorkommen, hier ist der Tag dazu: @protected .

@requires

Sollte ein Module von anderen abhängig sein, wird dies mit @requires markiert.

1
2
/**

3
@module MyFramework.localstorage

4
@requires MyFramework

5
*/

In @requires kann gleich eine Liste von anbhängigen Modulen erscheinen. Die Namen werden durch Komma getrennt.

@default

Oftmals ist ein @default Wert für ein @property wünschenswert. Für @default sollte immer eine @type Angaben vorhanden sein.

1
2
/**

3
@property element

4
@type String

5
@default "div"

6
*/
7
element: "div",

@uses

Wie schon gesagt, JavaScript hat nicht wirkliche Classen, aber es ist felxibel genug um die Illusion von Classen und sogar von Sub-Classen zu unterstützen. Und was noch cooler ist, ist dass Mengen oder Module möglich sind, worin eine Class Eigenschaften oder Methoden von anderen Classen "borgt". Aber es ist dennoch keine Vererbung, da Teile von mehr als einer Class vermengt werden dürfen. (Natürlich kennen YUI, Dojo und andere Libraries dies Möglichkeit auch). Sollte dies nötig sein, so wird @uses dazu benutzt: damit lassen sich Mengen aus verschiedenen Classen aufzeigen.

1
2
/**

3
@class ModalWindow

4
@uses Window

5
@uses DragDroppable

6
*/
7
var ModalWindow = new Class({
8
    mixes: [Window, DragDroppable],
9
    ...
10
});

Beachte: Ich habe diesen Mengen Syntax gemacht, doch bin ich sicher dies schon mal irgendwo anderes gesehen zu haben.

@example

Es soll ein Beispiel her wie ein bestimmtes Stück benutzt werden soll? Dafür ist der @example Tag gedacht. Unten nach folgt das Beispiel, gleich um eine Stufe weiter eingerückt. Und es können soviele Beispiele wie gewünscht platziert werden.

1
2
/**

3
@method greet

4
@example

5
    person.greet("Jane");

6
*/
7
Person.prototype.greet = function (name) {};

@chainable

Vielleicht sind Verkettungen von Methoden aus jQuery bekannt. Gemeint ist, dort wo Methoden Aufruf auf Aufruf folgt, weil jede Methode ein Object zurück liefert. Solche Methoden werden daher durch @chainable markiert.

1
2
/**

3
@method addClass

4
@chainable

5
*/
6
jQuery.prototype.addClass = function (class) {
7
    // stuff;

8
    return this;
9
}

@deprecated / @since / @beta

Diese drei Tags sind Aussagen zum Support von Codes (und gemeint ist jegliche Art von Code: Module, Classen, Methoden oder andere Teile). Mit @deprecated werden Teile markiert welche nicht mehr weiter benutzt werden sollten, da mittlerweile besseren Ersatz dafür exsitiert. (So markierte Teile könnten in einer zukünftigen Version wegfallen). Zusätzlich kann eine Erklärung den neuen Weg aufzeigen. 

1
2
/**

3
@method toJSON

4
@deprecated Pass the object to `JSON.parse` instead

5
*/
6
Something.toJSON = function () {};

Der @since Tag erklärt, ab welcher Version der entspr. Code hinzu kam. Und mit @beta wird eben genau Beta-Code beschrieben: YUI meint, dass für mit @beta markierte Teile "in naher Zukunft eine Unverträglichkeit mit älteres Codes einhergehen könne".

1
2
/**

3
@class Tooltip

4
@since 1.2.3

5
@constructor

6
*/
7
function Tooltip () {}

@extension / @extensionfor / extension_for

Der @extension Tag (und dessen Aliases) ist ziemlich genau das Gegenteil von @uses. Dies um anzuzeigen welche Class einer Extension-Class beigemischt werden kann. Es sollte klar sein, dass eine Beimischung möglich wäre, aber nicht in jedem Falle sein muss.

1
2
/**

3
@class Draggable

4
@extensionfor ModalWindow

5
*/

Kommentare und Markdown (vereinfachte Auszeichnungen)

Hiernach wird ein aktuelles Beispiel gezeigt, wobei ich zwei drei Dinge zur Dokumentation von Kommentarblöcken zeigen möchte.

Erstens: Meistens möchte man etwas mehr an Informationen über den Code liefern, als wofür der aktuelle Tag wirklich gut ist. Vielleicht um den Zweck von Methoden zu beschreiben, oder wie eine Class ins Gesamtbild hinein passt. Solche Kommentare werden ganz zu Beginn im Block notiert, oberhalb jeglicher Tags. YUIDoc wird dies erkennen und diese Teile in die Dokumentation einschliessen.

1
2
/**

3
The `Router` class is used for . . .

4
@class Router

5
@static

6
*/
7
var Router = {};

Zweitens: erfreulicherweise können Kommentare und Beschreibungen jeweils nach Tags in einfacher Auszeichung (Markdown) formatiert werden, und YUIDoc wird auch die formatierten Teile korrekt in HTML umwandeln. Auch eingerückter Beispielcode kann in Kommentaren sein, dessen Syntax wird hervorgehoben! 


Ein Beispiel

Nun da alle Tags vorgestellt wurden wird etwas Code geschrieben um diesen anschliessend zu dokumentieren. Wir bauen ein Store Module mit den beiden Classen Item und Cart. Jede Item Instanz findet sich in der Artikelliste des Warenhauses mit Name, Preis und einer Mengenangabe. Der Cart kann mit  Artikeln gefüllt werden, wobei der Gesamtpreis aller Artikel im Warenkorb berechnet wird (inkl. MWSt.) Diese Aufgabe ist realtiv einfach gehalten, doch zeigt sie genügend Funktionen um einige der vorgestellten Tags anzuwenden. Der folgende Code ist in der Datei store.js gespeichert.

Nun wird das Modul erzeugt:

1
2
/**

3
* This module contains classes for running a store.

4
* @module Store

5
*/
6
7
var Store = Store || {};

Nun wird eine "Konstante" erzeugt: die MWSt. ( TAX_RATE )

1
2
/**

3
* `TAX_RATE` is stored as a percentage. Value is 13.

4
    * @property TAX_RATE

5
    * @static

6
    * @final

7
    * @type Number

8
*/
9
10
Store.TAX_RATE = 13;

Da dies eine Konstante ist wird durch @final deutlich gemacht. Dem @property Tag wird der Name zugefügt und dass es sich um eine Zahl handelt beschreibt der @type Tag. Zu beachten ist der @static Tag: da YUIDoc sonst TAX_RATE als Eigenschaft der Item Class generiert; es scheint dass YUIDoc sonst keine Eigenschaften auf Modulebene haben möchte. Es könnte vermutlich eine statische Class erzeugt werden um diese Konstante aufzunehmen (und allenfalls weitere, falls der Code ausgebaut würde), doch soll es jetzt einmal so stehen bleiben als Mahnung, um zu zeigen dass YUIDoc nur ganz ausgereitzt werden könnte wenn man nur entsprechend programmiert. Ob Sie dies wirklich möchten bleibt Ihnen überlassen!

Nun, für die Item Class:

1
2
/**

3
 * @class Item

4
 * @constructor

5
 * @param name {String} Item name

6
 * @param price {Number} Item price

7
 * @param quantity {Number} Item quantity (the number available to buy)

8
 */
9
10
Store.Item = function (name, price, quantity) {
11
    /**

12
     * @property name

13
     * @type String

14
     */
15
    this.name = name;
16
    /**

17
     * @property price

18
     * @type String

19
     */
20
    this.price = price * 100;
21
    /**

22
     * @property quantity

23
     * @type Number

24
     */
25
    this.quantity = quantity;
26
    /**

27
     * @property id

28
     * @type Number

29
     */
30
    this.id = Store.Item._id++;
31
    Store.Item.list[this.id] = this;
32
};

Leicht zu sehen sind die drei Parameter des Konstuktors. Zum Konstruktor gehören drei Eigenschaften welche auch beschrieben werden. Da jedes Item zudem mit einer ID gekennzeichnet wird, braucht es dazu eine statische Eigenschaft (auf Class Ebene) um die ID zu erhöhen, sowie eine weitere statische Eigenschaft welche das Item über die ID kennzeichnet.

1
2
/**

3
 * `_id` is incremented when a new item is created, so every item has a unique ID

4
 * @property id

5
 * @type Number

6
 * @static

7
 * @private

8
 */
9
Store.Item._id = 1;
10
11
/**

12
 * @property list

13
 * @static

14
 * @type Object

15
 */
16
Store.Item.list = {};

Und wie steht es mit der Cart Class?

1
2
/**

3
 * @class Cart

4
 * @constructor

5
 * @param name {String} Customer name

6
 */
7
8
Store.Cart = function (name) {
9
    /**

10
     * @property name

11
     * @type String

12
     */
13
    this.name = name;
14
    /**

15
     * @property items

16
     * @type Object

17
     * @default {}

18
     */
19
    this.items = {};
20
};

Hier ist nicht wirklich Neues zu finden: wir deklarieren das der Default- od.Initial-Wert der Item Eigenschaft ein leeres Objekt ist.

Nun, hier die Methoden. In addItem ist ein Parameter optional, weshalb dies auch so beschrieben wird, und es wird eine 1 gespeichert, falls nichts angegeben wird. Zudem ist die Methode verkettet @chainable nutzbar.

1
2
/**

3
 * Adds 1 or more of a given item to the cart, if the chosen quantity 

4
 * is available. If not, none are added.

5
 *

6
 * @method addItem

7
 * @param item {Object} An `Item` Object

8
 * @param [quantity=1] {Number} The number of items to add to the cart

9
 * @chainable

10
 */
11
12
Store.Cart.prototype.addItem = function (item, quantity) {
13
    quantity = quantity || 1;
14
    if (item.quantity >= quantity) {
15
        this.items[item.id] = this.items[item.id] || 0;
16
        this.items[item.id] += quantity;
17
        item.quantity -= quantity;
18
    }
19
    return this;
20
};

Schliesslich ist die Rückgabe der Gesamtpreis inkl MWSt. Beachten Sie dass die Preisberechung in cents erfolgt um sie  nachher in Dollar, auf zwei Nachkomastellen gerundet, auszugeben.

1
2
/**

3
 * @method total

4
 * @return {Number} tax-included total value of cart contents

5
 */
6
7
Store.Cart.prototype.total = function () {
8
    var subtotal, id;
9
    subtotal = 0;
10
    for (id in this.items) {
11
        if(this.items.hasOwnProperty(id)) {
12
            subtotal += Store.Item.list[id].price * this.items[id];
13
        }
14
    }
15
    return parseFloat(((subtotal * (1 + Store.TAX_RATE / 100)) / 100).toFixed(2));
16
};

Hier folgt nun ein einfacher Test um den Code überprüfen zu können.

1
2
var apple, pear, book, desk, assertEquals;
3
4
assertEquals = function (one, two, msg) {
5
    console.log(((one === two) ? "PASS : " : "FAIL : ") + msg);
6
};
7
8
apple = new Store.Item('Granny Smith Apple', 1.00, 5);
9
pear  = new Store.Item('Barlett Pear', 2.00, 3);
10
book  = new Store.Item('On Writing Well', 15.99, 2);
11
desk  = new Store.Item('IKEA Gallant', 123.45, 1);
12
cart  = new Store.Cart('Andrew');
13
14
cart.addItem(apple, 1).addItem(book, 3).addItem(desk, 1);
15
16
assertEquals(apple.quantity, 4, "adding 1 apple removes 1 from the item quantity");
17
assertEquals(book.quantity, 2, "trying to add more books than there are means none are added");
18
assertEquals(cart.total(), 140.63, "total price for 1 apple and 1 desk is 140.63");

Generierung der Dokumentation

Nun, da der Code programmiert und mit Kommentar-Blocks versehen wurde, ist es Zeit die Dokumentation zu generieren.

Wenn YUIDoc global, mit npm installiert wurde, so folgt der Aufruf mittels yuidoc {Pfad zur js Datei} In meinem Fall ist dies

1
2
yuidoc .

Nun ist ein out Verzeichnis in diesem Ordner entstanden; um die generierte Dokumentation zu lesen wird out/index.html geöffnet. Hier nun den Teil der Cart Class Dokumenation:

YUIDoc DocumentationYUIDoc DocumentationYUIDoc Documentation

Ausgabe konfigurieren

YUIDoc bietet verschiedene Optionen in der Konfiguration um die Ausgabe zu steuern. Klar, alles kann über die Aufrufzeile mit Flags eingestellt werden, doch eine JSON Konfig-Datei bietet Vorteile. Dafür wird im Projekt Verzeichnis die yuidoc.json Datei erstellt. Zuerst werden generellen Projekt Informationen gesetzt; wobei diese die Ausgabe nicht wirklich gross beeinflussen. Doch ist es gut auch diese zu dokumentieren:

1
2
{
3
    "name": "Documenting JavaScript with YUIDoc",
4
    "description": "A tutorial about YUIDoc, for Nettuts+",
5
    "version": "1.0.0",
6
    "url": "http://net.tutsplus.com"
7
}

Dann folgt eine Anzahl von einstellbaren Optionen. Hier eine Auswahl der wohl interssanteren Optionen;

  • linkNatives : auf "true" eingestellt um native Typen wie String oder Number mit der MDN Doc zu koppeln.
  • outdir: hier lässt sich der Name des out Verzeichnisses bestimmen.
  • paths: steuert die Pfade wo YUIDoc nach JavaScript Dateien suchen darf.
  • exclude: Dateiliste, durch Komma getrennt, welche YUIDoc ingnorieren soll.

So wie die paths Option gesetzt ist, wird YUIDoc ganz einfach über yuidoc -c yuidoc.json gestartet. Auch wenn paths nicht gesetzt wurde und lediglich yuidoc . aufgerufen wird, so verwendet YUIDoc die Werte aus der Konfig Datei.

Hier folgt meine ganze Konfig Datei für dieses Projekt:

1
2
{
3
    "name": "Documenting JavaScript with YUIDoc",
4
    "description": "A tutorial about YUIDoc, for Nettuts+",
5
    "version": "1.0.0",
6
    "url": "http://net.tutsplus.com",
7
    "options": {
8
        "linkNatives": "true",
9
        "outdir": "./docs",
10
        "paths": "."
11
    }
12
}

Auswertung

Mit den in YUIDoc angebotenen Tags wird evident, dass dieses Werkzeug für JavaScript nicht nur für traditionellen OOP, sondern auch für YUI Widget u.a. sehr hilfreich ist. (Tatsächlich habe ich die YUI-spezifischen Tags weggelassen). Aus diesem Grund kann es sein dass mehrere Tags für Ihren Gebrauch nichts dienen werden. Das ist dann der Moment zu überlegen, ob die Codierung angepasst werden sollte, um diesen besser mit YUIDoc dokumentieren zu können. (orig. "match the way YUIDoc 'thinks'"). Auch wenn der Code deswegen nicht verändert wird, werden die YUIDoc Tags mehrheitlich verwendet werden können.

Die wohl wichtigere Frage für mich ist, ob die Dokumentation gleich mit und im Code vorliegen soll und mit diesem überein stimmt.

Obiges Beispiel weist 120 Zeilen mit Kommentaren auf und 40 Zeilen ohne Kommentare. Offensichtilich ist dieser Code super einfach. Bestimmt würde jedes praktische Beispiel ausgewogener wirken; doch solch vermischte Codes zu lesen ist eben auch eine Herausforderung. Persönlich denke ich, für die nächsten paar Wochen YUIDoc eine gewisse Weile nutzen zu wollen während ich codiere. Ich bin gespannt zu sehen wie dies die Art und Weise der Codierung und die Abläufe beeinflussen wird.

Die Routine macht doch alles: liebe es oder hasse es! Senden Sie mir Ihre Kommentare!


Weitere Informationen