DEV Community

Marko V
Marko V

Posted on

3 1

How to increase your CoQ.

Code Quality. What did you think it meant?

I've already written about linting, unit-testing is another and documentation is a third. JSDoc is one way to keep track of things. If you haven't encountered it before, it's a structured way to maintain your in-line comments and make use of it as a documentation tool. You can express the in's and out's of functions, what their usage is, their limitations and dependencies. You can define your modules and classes.. and finally, you can generate an interactive documentation site based on your comments.

So to get started it's quite simple. In Visual Studio, and VS Code, you can start to type "/**" and it will auto-complete the beginnings of a JSDoc entry if it's a .js file. If you do it above the line of a function definition, and you press enter it will auto-complete the parameters for you and all you need to do is add typing (unless that is already clearly defined and the IDE can detect it) and the usage of the parameter.

So to start documenting your code, it kind of looks like this;

Sample

/**
 * Localization Service for angular
 * @exports services/localeService
 * @param {NgModule} $http injection of the AngularJS native $http module (supplies access to XHR requests)
 * @param {NgModule} $window injection of the AngularJS native $window module (supplies access to the window object)
 * @param {NgModule} $q injection of the AngularJS native $q module (supplies promises)
 * @param {NgModule} $cookies injection of the AngularJS native $cookies module (supplies access to cookies)
 * @returns { function } a localeService singleton
 */
Enter fullscreen mode Exit fullscreen mode

@exports defines what this file/function exports/relates to in terms of modules. This one in particular is a part of the shared service modules and is called localeService
@param is quite clear. It defines one of the parameters, what type it is, it's name and what it is used for.
@returns just states the return type and what it contains.

Ok, so now that you've documented everything, well... atleast something, you can now run jsdoc command-line tool to generate the documentation site.

First, install the jsdoc tool

npm i jsdoc -g

Next add a jsdoc config file, you can name it whatever you want, I named mine jsdoc.conf.json

{
  "plugins": [ "plugins/markdown" ],
  "recurseDepth": 10,
  "source": {
    "includePattern": ".+\\.js(doc|x)?$",
    "excludePattern": "(^|\\/|\\\\)_|.+es5.js|.+es2015.js|JsonEditor.js|angular.js|angular-cookies.js|angular-mocks.js|angular-sanitize.js"
  },
  "sourceType": "module",
  "tags": {
    "allowUnknownTags": true,
    "dictionaries": [ "jsdoc", "closure" ]
  },
  "templates": {
    "cleverLinks": false,
    "monospaceLinks": false
  }
}
Enter fullscreen mode Exit fullscreen mode

Next, run the command-line tool. All of our scripts are contained in a hierarchy inside the Scripts folder of our web application, so this is the line I ran.

jsdoc Scripts --recurse -c jsdoc.conf.json

And voilá... a nice documentation site is now available in the output path (which you can change btw). Default an "out" folder is created in the working directory you run this command from.

JSDoc Site

References;

Full Example (with redacted code blocks)

/**
 * Localization Service for angular
 * @exports services/localeService
 * @param {NgModule} $http injection of the AngularJS native $http module (supplies access to XHR requests)
 * @param {NgModule} $window injection of the AngularJS native $window module (supplies access to the window object)
 * @param {NgModule} $q injection of the AngularJS native $q module (supplies promises)
 * @param {NgModule} $cookies injection of the AngularJS native $cookies module (supplies access to cookies)
 * @returns { function } a localeService singleton
 */
function localeService($http, $window, $q, $cookies) {
    'use strict';
    var self = this;
    /**
     * Function to find out which locale is relevant for the user and if we support it.
     * @returns { string } A string representing the localization moniker.
     * */
    this.resolveBrowserLocale = function () {
      // ... redacted ...
    };
    /**
     * Initialization function that tries to get the current list of valid translations provided by a service
     * @returns { Promise } A promise that contains the translations
     * */
    this.init = function () {
      // ... redacted ...
    };
    /**
     * Waits for the resolution of the translations to retrieve an entry from the resultset.
     * @param { string } entry representing the dotannotated path to lookup a translation for.
     * @param { boolean } debug a true/false value to whether or not output debug data in the console.
     * @returns { Promise } A promise containing the attempted lookup. If it fails to find it, it will return the string provided in entry.
     */
    this.getEntry = function (entry, debug) {
        return $q(function (resolve, reject) {
          // ... redacted ...
        });
    };
    /**
     * A complex function to do translation lookup based on the provided object and property to do lookup on. Multiple paths of execution.
     * @param {any} obj Object that contains values to translate
     * @param {string} propToRepl If provided, it will attempt to do lookup on this property and replace it's content before returning the modified object.
     * @param {string} propToLookUp If provided, it will attempt to do lookup on this property-value compounded with propToRepl and insert the found value in propToRepl
     * @param {boolean} tdebug true/false if truthy it will log data to console.
     * @returns { any } The modified object is returned.
     */
    this.translateObject = function (obj, propToRepl, propToLookUp, tdebug) {
      //... redacted ...        
    };
    /**
     * Internal logger function
     * @param {any} obj Object to inject to console.log
     * @param {any} logthis if defined at all, it will use it as a truthy value and output data to console.
     * @returns {void} It outputs data to console. It has no return value.
     */
    this.logger = function (obj, logthis) {
      // ... redacted ...
    };
    /**
     * Lookup helper function, not intended for external consumption/usage.
     * @param {string} dotValue Lookup value to find.
     * @param {any} logThis if defined, it will log data through the private logger function.
     * @returns {string} A translated string or the original string
     */
    this.getDotAnnotatedValue = function (dotValue, logThis) {
      // ... redacted ...
    };
    /** A promise that contains the initialization status of the singleton and it's returned value */
    this.initialized = this.init();
    this.initialized.then(function (data) { self.data = data; });
    return this;
}
/** Injects the localeService into the angular module myAteaApp.services for others to consume */
angular.module('myApp.services').factory('localeService', ['$http', '$window', '$q', '$cookies', localeService]);
Enter fullscreen mode Exit fullscreen mode

Tags: https://jsdoc.app/index.html#block-tags
Getting started: https://jsdoc.app/about-getting-started.html

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay