Documenting your code

This is a detailed spec on how developers should be documenting their code. While inline code comments are very important, this specification will be focusing on docblock structure.

Docblocks are required for all class methods & properties/attributes. The reason we have this spec, and the reason that actual language standards exist for docblocks, is so that generators will know how to parse your code & render consumable html documentation.

For this reason, documentation standards follow the existing spec’s that are currently community standards at the time of writing, and we should be following them.

There is a lot of overlap in each spec, so this wiki doc will serve as the reference.

Contents

1. Definitions

1.1 Docblock

This is a section of documentation which provides information on several aspects of Structural Elements.

This is what comes first in every docblock. The short description of what a method/variable is. JS example:

/**
 * This is a summary. It should always be the first thing in a
 * docblock. It should **NEVER** span more than two lines.
 */

1.2 Description

This is a more detailed explanation than the summary. It is optional, and if included, it should always come after the summary. JS example:

/**
 * This is a summary. It should always be the first thing in a
 * docblock. It should **NOT** span more than two lines.
 *
 * This is the description. Typically only included when you have
 * more you want to say about the method/variable you're documenting
 * that can't fit in the 2-line summary.
 *
 * Descriptions can be multiple paragraphs, can include *markdown*,
 * headers, code examples `NOTE:`'s, and other things.
 *
 * ### Examples
 *
 * Example of code block in JS:
 * ```
 * var foo = _.map( this.fooBar );
 * ```
 */

1.3 Tags

The technical term for the @ descriptors you use in docblocks. Common ones we all know are @param & @return. A @param tag in a docblock are made up of the tag, a type, a variable name, and a tag description.

Here’s a JS example: * @param {number} input Any number. Where:

1.4 Docblock section

Term referring to the Summary, Description, and different groups of tags that comprise the docblock. Each section should be separated by a line break. JS example:

/**
 * Counter class constructor.
 *
 * @see {@link DialogModal#show} for full list of options.
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/alert}
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/dialog}
 *
 * @throws {InvalidArgumentException} Optional @throws description
 * @throws {DivideByZero} Argument x must be non-zero.
 * @throws Will throw an error if the argument is null.
 *
 * @param {jQuery} textField - This is a tag description.
 * @param {jQuery} [$counterEl] - This is another tag description.
 * @param {string} [maxGlue] - This is the last `@param` tag description.
 * @return {Counter} The is the `@return` tag description.
 */

2. Comprehensive Examples

2.1 Language JS

/**
 * Show the dialog modal.
 *
 * NOTE: you can call this method directly, but would typically
 * call the `alert()` or `confirm()` aliases directly instead.
 *
 * Show a confirmation modal with custom html template content:
 *
 * ```
 * DialogModal.show( {
 *     onConfirm: this.onAchknowledgeError.bind( this ) );
 *     content: _.template( $( "#error-template" ).html() )( data),
 *     error: true,
 *     title: "error-title",
 *     type: "confirm",
 * } );
 * ```
 *
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/alert}
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/dialog}
 *
 * @todo Add unit tests.
 * @todo Add notes in readme.
 *
 * @throws {HttpException} If resource creation fails, throws an exception.
 * @throws {CustomException} If resource query fails, throws an exception.
 *
 * @param {string} reqParam - Required parameters shouldn't have [ ] around them
 * @param {object} [options={}] - Options to pass to show
 * @param {function} [options.cancel] - Callback that executes when user clicks cancel button.
 * @param {string|boolean} [options.cancelButton="cancel-button"] - Cancel button message key. Hides button when false.
 * @param {function} [options.confirm] - Callback that executes when user clicks confirm button.
 * @param {string|boolean} [options.confirmButton="confirm-button"] - Confirm button message key.
 * @param {string} [options.content=""] - Text/html displayed in the dialog.
 * @param {boolean} [options.error=false] - When true, add's error class, and drives error styling.
 * @param {string} [options.title="default-alert-title"] - Translation message key for dialog title bar.
 * @param {boolean} [options.type="alert"] - Type of dialog modal it is. Options are "alert" or "confirm".
 * @return {ConfirmModal} Returns a reference to `this` to allow for chaining
 */
show: function( reqParam, options ) {}

3. General Rules

Bad:

/**
 * Counter class constructor.
 *
 * @param  {jQuery}  $textField   This is a tag description.
 * @param  {jQuery}  [$counterEl] This is another tag description.
 * @return {Counter}              The is the `@return` tag description.
 */

^ This looks good but can become unweildy and annoying, and most importantly super annoying to lint/enforce amongst the team.

Good:

/**
 * Counter class constructor.
 *
 * @param {jQuery} $textField - This is a tag description.
 * @param {jQuery} [$counterEl] - This is another tag description.
 * @return {Counter} The is the `@return` tag description.
 */

Bad:

/**
 * Alias for show(), with some default options set.
 * NOTE: This is a longer more detailed description block.
 * @see {@link DialogModal#show} for full list of options.
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/alert}
 * @param {object|string} options Modal options object. If string, it represents the modal's content.
 * @param {function} [callback] If `options` param is a string, this will be used as the confirm callback.
 * @return {ConfirmModal} Returns a reference to `this` to allow for chaining
 */

Good:

/**
 * Alias for show(), with some default options set.
 *
 * NOTE: This is a longer more detailed description block.
 *
 * @see {@link DialogModal#show} for full list of options.
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/alert}
 *
 * @param {object|string} options - Modal options object. If string, it represents the modal's content.
 * @param {function} [callback] - If `options` param is a string, this will be used as the confirm callback.
 * @return {ConfirmModal} Returns a reference to `this` to allow for chaining.
 */

Bad:

/**
 * Alias for show(), with some default options set.
 *
 * NOTE: This is a longer more detailed description block.
 *
 * @param {object|string} options Modal options object. If string, it represents the modal's content.
 *
 * @return {ConfirmModal} Returns a reference to `this` to allow for chaining.
 *
 * @todo Add unit tests :).
 *
 * @see {@link DialogModal#show} for full list of options.
 */

Good:

/**
 * Alias for show(), with some default options set.
 *
 * NOTE: This is a longer more detailed description block.
 *
 * @see {@link DialogModal#show} for full list of options.
 *
 * @todo Add unit tests :).
 *
 * @param {object|string} options - Modal options object. If string, it represents the modal's content.
 * @return {ConfirmModal} Returns a reference to `this` to allow for chaining.
 */

Bad:

/**
 * @returns {boolean}
 */

Good:

/**
 * @return {boolean}
 */

Bad:

/**
 * @param  {jQuery}   textField    This is a tag description.
 */

Good:

/**
 * @param {jQuery} textField - This is a tag description.
 */

Bad:

/**
 * counter class constructor
 *
 * @param {jQuery} textField - this is a tag description
 */

Good:

/**
 * Counter class constructor.
 *
 * @param {jQuery} textField - This is a tag description.
 */

4. Tech Debt

Things we’ve done wrong in the past, that should be changed:

5. Code Examples in Docblocks

It’s extremely helpful for reference purposes to include examples in your docblocks. It’s important to note, there’s multiple different ways to do this in both PHP & JS, but we’ll show you the recommended & acceptable ways of doing it here.

5.1 JS Example

Good:

/**
 * Indented, normal Markdown:
 *
 *     var foo = _.map( this.fooBar );
 */

Acceptable:

/**
 * Example of code block in JS using Github Flavored Markdown:
 *
 * ```
 * var foo = _.map( this.fooBar );
 * ```
 */

Bad:

/**
 * Indented, normal Markdown. INDENTED CODE BLOCKS NEED A LINE BREAK BEFORE THEM!
 *     var foo = _.map( this.fooBar );
 */

Not Recommended:

/**
 * @example
 * var foo = _.map( this.fooBar );
 */

6. Nested Parameters

It’s nice knowing that a specific method parameter is an array/object, but what about the properties/attributes of that parameter? Sometimes it’s very helpful to include details about “nested parameters” when you’re passing in an array or object into a method. JS & PHP have very different ways of handling this.

6.1 JS Nested Parameters

JSDoc takes a different approach to parameters with properties. All the properties should be listed as their own @param’s with the parent object prepended in the variable name, i.e. options.nestedProperty.

See: http://usejsdoc.org/tags-param.html#parameters-with-properties

Example:

/**
 * Show the dialog modal.
 *
 * @param {object} [options={}] - Modal options.
 * @param {function} [options.onCancel] - Callback that executes when user clicks cancel button.
 * @param {string|boolean} [options.cancelButton="cancel-button"] - Cancel button message key. Hides button when false.
 * @param {function} [options.onConfirm] - Callback that executes when user clicks confirm button.
 * @param {string|boolean} [options.confirmButton="confirm-button"] - Confirm button message key.
 * @param {string} [options.content=""] - Text/html displayed in the dialog.
 * @param {boolean} [options.error=false] - When true, add's error class, and drives error styling.
 * @param {string} [options.title="default-alert-title"] - Translation message key for dialog title bar.
 * @param {boolean} [options.type="alert"] - Type of dialog modal it is. Options are "alert" or "confirm".
 * @return {ConfirmModal} Returns a reference to `this` to allow for chaining
 */
show: function(options) {}

7. Types

* @param {string} input - Any string.

^^ In this example, string refers to the “type”. Here are the different types you should be using for PHP & JS.

7.1 JS Types

See: http://usejsdoc.org/tags-type.html

NOTE: It’s recommended that you lowercase any primitive types (boolean, null, undefined, number, string), and capitalize other types.

  1. string
  2. number
  3. boolean
  4. mixed
  5. null
  6. undefined
  7. Array - It’s preferred that you use one of the following, rather than just Array • mixed[] - array of mixed types • string[] - array of strings • number[] - array of numbers • array[] - array of arrays • object[] - array of objects • MyClass[] - array of type MyClass • etc.
  8. object - For object literals, NOT instance objects. If you want to provide more details about the object properties, you can in the format: object.<string, number>, which would represent an object with string keys and number values. NOTE: If your method takes or returns an instance of a specific class, you should specify the class name as the type, e.g. jQuery, Promise, Element, Event, etc.

8. Default & Optional Parameters

See http://usejsdoc.org/tags-param.html#optional-parameters-and-default-values

JS Example:

Optional param’s have their var names wrapped in square brackets. Defaults get specified following the variable name and an equals sign.

/**
 * @param {jQuery} textField - This is a REQUIRED parameter.
 * @param {string} bar="" - This param is required, with an empty string default `""`.
 * @param {jQuery} [$counterEl] - This is an OPTIONAL parameter. Denoted by square brackets.
 * @param {number} [max=50] - This param is optional, with a default of `50`.
 * @param {boolean} [shown=false] - This boolean param is optional, with a default of `false`.
 * @param {string} [foo="Foo Bar"] - This param is optional, with a default of `"Foo Bar"`.
 */

9. Editor Integration

9.1 Writing Docblocks in VSCode

Install the Docblockr plugin (https://github.com/FlyDreame/vscode-docBlocker) to easy generate Docblocks.