en Documentación

JSDoc series II – Documentación básica

Introducción

En esta segunda entrega de la serie JSDoc se realizará una documentación básica de un código de javascript, por lo que se requiere ya tener instalado y configurado JSDoc en un proyecto de nodejs.

En la entrega anterior se realizó la instalación y configuración inicial, por lo que se recomienda verlo para efectos de continuidad en esta entrega.

Documentación de código básico

Configuración para el desarrollador (opcional)

A continuación la siguiente figura muestra el código que se quiere docuementar (izquierda) y la derecha un archivo de configuración del editor de código (en este caso vscode) , el cual permite activar una caraterística de desarrollo.

Para activar dicha propiedad en vscode se presiona F1 y se escribe open Settings (JSON), eso abrirá el archivo de configuración de la derecha y se escribe la siguiente propiedad: «js/ts.implicitProjectConfig.checkJS»: true. Esto permitirá al editor realizar análisis de código con respecto a JSDoc, es decir, que lo que es descrito (documentación) sea coherente con lo implementado (código).

Esto permite al desarrollador encontrar errores cuando declara los tipos de datos y los documenta, sirviendo así como una ventaja. Esto es debido a que en javascript no existe el tipado fuerte, por lo que una variable puede tomar cualquier valor. Por ello es de interés del desarrollador ser consistente con los datos, es así como ayuda al desarrollador esta propiedad, añadiendo un tipado fuerte sobre el código.

Esta es una de la razones por las cuales se escoge vscode como editor de código en este tutorial.

La otra manera de hacerlo es usando una condidición de JSDoc, la cual hay que colocar en cada archivo donde se quiera utilizar dicha documentación; simplemente se coloca //@ts-check al inicio del archivo y realizará la misma función.

Documentando primitivas

Para comenzar una documentación con JSDoc sobre alguna sección de código se debe escribir una sintaxis específica, la cual es entendida por dicho paquete. Dicha sintaxis es la siguiente:

/**
 *
 */ 

Con esto, JSDoc entiende que tiene analizar lo que está ahí escrito y además sabe que la siguiente porción de código es donde aplica dicha documentación.

Como se observa en la figura anterior, la forma de documentar brevemente consiste en describir el tipo de dato y dar una descripción, además se puede describir que valor por defecto va tener una variable o constante.

A continuación se brinda una manera resumida de documentar primitivas (tipos de datos como: string, number, boolean, Array, entre otros).

/**
 * A integer number
 * @type {number}
 * @default 2000
 */
const interger = 2000

/**
 * A float number
 * @type {number}
 */
const float = 12.5

/**
 * This is the name of a person
 * @type {string}
 */
const fullName = "Esteban Arroyo"

/**
 * Array of user's ages
 * @type {Array<number>}
 */
const ageArray = [21, 28, 32, 37, 40]

/**
 * Array of number and string
 * @type {Array<number|string>}
 */
const mixArray = ["21", 28, "32", 37, "40"]

Del código anterior se observa que en la documentación utiliza una palabras reservadas o keywords, los cuales son entendidos por JSDoc.

  • @type {type}: Básicamente describe el tipo de dato que se encuentra en la siguiente porción de código. (Si se activo la propiedad del desarrollador, al declarar la variable si no coincide con lo descrito en la documentación, se señalará un error de incosistencia)
  • @defualt valor: Describe que existe un valor por defecto para dicha varible.
  • Una breve descripción, la cual no requiere un keyword para ser entendida, pues con solo estar dentro del bloque del comentario, JSDoc entiende que es una descripción, por ejemplo del código anterior de una descripción es:
This is the name of a person

Un caso interesante son los Arrays, los cuales a veces pueden ser una combinación de tipos de datos, como el mostrado en el código anterior, donde hay una combinación de tipo number y tipo string.

Para que JSDoc entienda que una variable puede ser de un tipo, o del otro o bien de ambos, basta con describirselo como se vé en el código anterior: Array<tipo_dato_1_|tipo_dato_2>.

Lo anterior aplica para cualquier elemento del código, ya sea una función, una variable o bien una clase.

Al correr el siguiente comando

npm run docs

Se genera la siguiente documentación expuesta en la figura:

Al lado derecho del sitio web se encuentran todas las variables, constantes o bien funciones que se hayan declarado hasta el momento bajo el tag «General», mientras que por el lado izquierdo se encuentra la descripción respectiva de los mismos.

Documentando funciones

Además de poder documentar tipos de datos primitivos, también es posible documentar funciones y objetos, la gran diferencia con lo anteriores es que estos requieren ser más descritos, esto con el objetivo de dejar en claro que realizan y cuales son sun propiedades.

El siguiente código muestra la docuementación en JSDoc para dos funciones, una que realiza una suma y otra que realiza un división:

/**
 * This function add to numbers
 * @param {number} n1 - A first number
 * @param {number} n2 - A second number
 * @returns {number} Operation result
 */
function add(n1, n2) {
    return  n1 + n2
}

/**
 * This function add to numbers
 * @param {number} n1 - A first number
 * @param {number} n2 - A second number
 * @returns {number | string} Operation result
 */
function divide(n1, n2) {
    if(n2 != 0) {
        return  n1 + n2
    } else {
        return "Error: Cannot divide by 0"
    }
}

La primer diferencia de documentar una función es el nivel de descripción mínimo que solicita JSDoc, lo cual básicamente corresponde a las entradas y salidas, es decir que parámetros recibe la función y que retorna.

  • @param {param_type} param_namedescription: Establece el tipo de dato que es el parámetro con el nombre «name» y con la descripción «description»
  • @returns{type} – description: Similar al anterior pero para el caso del resultado, es decir, la descripción del dato que retorna y su tipo.

Otra caso interesante, es cuando una función puede retornar varios tipos de datos, por lo que similiar al caso del Array, se describe el dato como múltiple tipo.

A realizar la documentación se obtiene lo siguiente:

Lo cual corresponde a la documentación de las dos funciones anteriormente implementadas. Es de notar que el nivel de descripción aumenta con respecto a los casos anteriores y esto es gracias a nivel de detalle que solicita JSDoc para el caso de la funciones.

Documentado objectos y separando en módulos

Otro tipo de datos que es de interés documentar son los objetos, debido a la organización que tienen con los datos y el fácil manejo que tienen.

El siguiente código muestra dos formas de documentar objetos, una con mayor detalle que la otra:

/**
 * @module objects
 */

/**
 * Person object
 * @type {{id: number | string, firstName: string, lastName: string, age: number}}
 */
const person = {
    id: 1289,
    firstName: "Chapulin",
    lastName: "Colorado",
    age: 40
}

/**
 * Pet
 * @typedef {object} Pet
 * @property {string} name - The pet name
 * @property {number | string} age - The pet age
 * @property {string} type - The pet type
 * @property {string} [ability] - A pet ability
 * @property {boolean} isActive - An alives indicator
 */

 /**
  * @type {Pet}
  */
 const myPet = {
    name: "Pepe",
    age: 10,
    type: "dog",
    ability: "Ultra sleep",
    isActive: true
}
  • @Module module_name: Indica que se está documentado un módulo, esto permititrá organizar la documentación en otro tag dado por el «module_name», de esta manera se evita tener todo dentro del tag «Global»
  • @typedef {data_type} data_name: Declara un tipo de dato personalizado con nombre dado por «data_name».
  • @property {data_type} property_name – description: Permite describir una propiedad que está dentro del dato definido, en este caso un objeto, brindandole un tipo de dato, un nombre y una descripción.

Un característica de JSDoc es describir cuando un dato es opcional, en el código anterior

 * @property {string} [ability] - A pet ability
La propiedad de habilidad se describe como opcional al encerrarla en corchetes [].

Al generar la documentación se obtiene el siguiente sitio web:

Note como el nivel de detalle brindado en la documentación del segundo objeto (Pet) da una mayor comprensión del dato, a diferencia del primero (Person). Esto nuevamente debido al nivel de detalle brindado en la docuementación.

Además con respecto al sitio web, se empieza a ver de la siguiente manera

El cual luce un poco más organizado, gracias al keyword de «@module». De esta manera se puede estructurar mejor el sitio web.

Documentando clases y ejemplos de uso

Finalmente otro elemento de programación muy usado son las clases, las cuales permiten instanciar objetos con los métodos (funciones) definidos dentro la clase.

El siguiente código presenta una forma de documentar las clases:

/**
 * Class to create a petStore object
 * @example
 * const petStore_1 = new PetStore(Pet, 'Doberman', 200)
 * petStore_1.getInfo()
 * @todo Create stoke logic
 */
class PetStore {

    /**
     * A class constructor
     * @param {Pet} pet Pet's information
     * @param {string} breeds Pet race
     * @param {number} price Pet plate  
     */
    constructor(pet, breeds, price) {
        this.name = pet.name
        this.type = pet.type
        this.breeds = breeds
        this.age = pet.age
        this.price = price 
    }

    /**
     * Get pet information
     * @returns {void}
     */
    getInfo() {
        console.log(`Name: ${this.name} 
        Type: ${this.type}
        Race: ${this.breeds} 
        Age: ${this.age} 
        Price: $${this.price}
        `)
    }

}

 /**
  * @type {Pet}
  */
 const myPet1 = {
    name: "Solon",
    age: 12,
    type: "Cat",
    ability: "Reform democracy",
    isActive: false
}

 /**
  * @type {Pet}
  */
 const myPet2 = {
    name: "Seneca",
    age: 7,
    type: "Rabbit",
    ability: "Philosophize",
    isActive: true
}

/**
  * @type {Pet}
  */
 const myPet3 = {
    name: "Incitatus",
    age: 15,
    type: "Horse",
    ability: "Consul",
    isActive: false
}

/**
 * Know more about it in {@Link PetStore}
 */
const pet1 = new PetStore(myPet1, "American Curl", 50)
const pet2 = new PetStore(myPet2, "Alaska", 70)
const pet3 = new PetStore(myPet3, "Azteca", 250)

pet1.getInfo()
pet2.getInfo()
pet3.getInfo()

Como es de notar, la mayoría de keywords son ya conocidos, esto es debido a que se está documentando elementos de programanción que antreriormente se han visto, tales como objetos y funciones.

Destacan acá los siguientes keywords:

  • @example: El cual brinda un ejemplo de uso para la clase. Esto dependerá del grado de descripción que se le quiera dar a la clase.
  • @todo – description: Una manera de explicar que a esta clase le faltan más operaciones y propiedades por implementar, es decir, lo que falta por realizar, siendo esto algo bastante útil para la comunicación entre desarrolladores.
  • {@Link element_to_see}: Una forma de hacer enlazes de interés en la documentación.

Al realizar la documentación se obtiene el siguiente resultado:

Además JSDoc por defecto separa las clases del tag «General» y las coloca dentro de otro tag llamado «Classes»

Conclusiones

En esta segunda entrega se realizó la documentación básica de varios componentes utilizandos en la programación, tales como: tipos de datos (number, string, boolean), funciones, objetos y clases.

Se puede decir entonces que JSDoc es una buena herramienta para realizar la documentación de código , pero de que tan claro quede está documentación dependerá del grado de detalle y descripción que se le quiera dar al código.

En la siguiente entrega se verán más propiedades avanzadas de JSDoc y una manera de extender su capacidad por medio plugins, esto para documentar de una menara más apropiada un API.

Escribe un comentario

Comentario

Webmenciones

  • JSDoc series III - Documentación Avanzada - Klooid 28 de agosto de 2022

    […] Los demás keyword pertenencen a la documentación básica de JSDoc, los cuales fueron analizados en la entrega anterior. […]