The Revealing Module Pattern in Specific Example

The Revealing Module Pattern in Specific Example

The last part of the Customizing Google Charts series

NOTE: This article contains snippets of code from a project I worked on in 2016! It uses jQuery and Google charts API that could have changed.

In the first part of this series, we created a Treemap using getBoundingClientRect() method. In the 2nd part, we created a custom Line Chart legend. We are going to put these 2 charts together utilizing the revealing module pattern (to put it simply, make our code cleaner and easier to maintain). When we interact for example with Line chart, it is reflected also on the Treemap and vice versa. Here is what it looks like:

Interconnected charts

Even though we display only 2 charts, our codebase got more complex and we have to consider the possibility of expanding it. Therefore we should also consider applying a design pattern to our code that will prevent us from writing some spaghetti code.

Photo by Sheila Joy on Unsplash

Photo by Sheila Joy on Unsplash

*Design patterns are reusable solutions to commonly occurring problems in software design*

What we had so far (in previous demo1 and demo2) was basically just a bunch of function declarations one after another. Something like this:

(function () {
    // some global variables here

    function drawTreemap() {...}

    function drawLineChart() {...}

    function updateLineChartCols(elem, firstClick) {...}

    function setColor(data, perc) {...}

    // and more functions
})(jQuery);

Nothing wrong with it, but we might face some problems with sharing some parts of the code due to function scope. We can organize the code better using modules for example. There are several ways of implementing modules in JS:

  • The Module pattern

  • Object literal notation

  • AMD modules

  • CommonJS modules

  • native ES modules

Nowadays modern browsers support native modules, when you use import and export keywords, but back in 2016 using jQuery I opted for the revealing module pattern (modified version of the module pattern).

With the module pattern*, only a public API is returned, keeping everything else within the closure private. The pattern utilizes an* immediately-invoked function expression (IIFE) where an object is returned*.*

To read more about the module pattern I recommend this section from Addy’s Osmani book Learning JavaScript Design Patterns. Let’s clarify the jargon before we get to the specific example.

What is IIEF?

An immediately invoked function expression is a function that is immediately executing itself as the name suggests. It can have 2 forms:

(function(){...})()

or

(function(){...}())

We can pass in any argument in the ‘invocation part’ of the code and use it as a parameter with a different name within the function:

(function IIFE($){...})(jQuery)

In this example, we pass in jQuery object and use it as a *$ *inside the function. IIFE allows us to hide the enclosed variables or functions from the outside scope and thus avoid collisions between different identifiers.

The Revealing Module Pattern

Let’s first see what our code looks like after implementation. **Demo on Stackblitz**

(function () {

    function drawTreemap() {
        ...
        var cellColor = api.setColor(tableData,false);
    }

    function drawLineChart() {
        ...
        var data = api.formatDataForLineChart(json);
    }

    // the revealing module pattern starts here with IIEF
    var api = (function () {

        function updateLineChartCols(elem, firstClick) {...}

        function setColor(data, perc) {...}

        function formatDataForLineChart(data) {...}

        return{
            updateLineChartCols: updateLineChartCols,
            setColor: setColor,
            formatDataForLineChart: formatDataForLineChart
        }

    })();

})(jQuery);   // this is another IIEF

We define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.

The code is more organized, maintainable, and readable. Notice how we can define the functions in one place and call them outside of that private scope where we need them, thus solving also the scope issue. We access them as object properties so we could also name them differently in the return statement.

Conclusion

There are modern frameworks that use native ES modules and a component-based approach is a way to go now. This is awesome, but if you still write or maintain Vanilla JS or jQuery code, this pattern might come in handy. And not only this pattern and in those scenarios. In every app development, there comes a day when something doesn’t work as expected, and you don’t know why. Understanding JS helps and the design patterns are part of it.

Thank you for reading!