In our last article of the series, we refactor a single object using the Module Design pattern: Refactoring using the Module Design Pattern
Now, we are going to improve our code design a bit. A small change will deal with some of the issues created by the Module design pattern while keeping our enclosure protected from global scope and able to use public and private variables and methods.
This is our example of JavaScript code refactored using the Module design pattern:
<script type="text/javascript"> var stockModule = (function () { // private variables var stockApples = 0; // Private functions function addToStock(count) { stockApples += count; }; function reduceStock(count) { stockApples -= count; } function currentStock() { return stockApples; }; return { // Public functions displayCurrentStock: function () { $("#customerFeedback").text("Current number of apples in stock: " + currentStock()); }, addApples: function () { var number = parseInt($("#numberOfAddApples").val()); addToStock(number); }, sellApples: function () { var numberSold = parseInt($("#numberOfSoldApples").val()); reduceStock(numberSold); } }; })(); // Use console to test your functions exposure. // console.log(stockModule.); </script>
The problem with the Module pattern is that as you can see, we are treating the private and public functions in a different way by separating the private functions (under the root of the object enclosure) and public functions (within the “return” enclosure). This differentiation adds complexity and can cause naming issues when calling private variables or functions from public functions for example.
The goal of the Module Reveal is to fix those issues and simplify our code. Let’s take a look:
<script type="text/javascript"> var stockModule = (function () { // private variables var _stockApples = 0; // Private functions function _addToStock(count) { _stockApples += count; }; function _reduceStock(count) { _stockApples -= count; } function _currentStock() { return _stockApples; }; // Public functions (will be paired below) function displayCurrentStock() { $("#customerFeedback").text("Current number of apples in stock: " + _currentStock()); } function addApples() { var number = parseInt($("#numberOfAddApples").val()); _addToStock(number); } function sellApples() { var numberSold = parseInt($("#numberOfSoldApples").val()); _reduceStock(numberSold); } return { displayCurrentStock: displayCurrentStock, addApples: addApples, sellApples: sellApples }; })(); // Use console to test your functions exposure. //console.log(stockModule.); </script>
Now all the functions are located under the same enclosure making communication between public and private much easier. The RETURN enclosure is the one in charge of making those private functions public by assigning similar public functions to its corresponding private functions.
Couple of things about the MODULE and MODULE REVEAL design patterns:
First, it all starts with a single JavaScript structure:
var stockModule = (function () { /* code goes here */ })();
Second, a function “init” might be required when using this kind of design pattern and while the example didn’t need one, is not difficult to create either:
<script type="text/javascript"> var stockModule = (function () { // private variables var _stockApples = 0; // init function init(numberofApples) { _stockApples = numberofApples; } // Private functions function _addToStock(count) { _stockApples += count; }; function _reduceStock(count) { _stockApples -= count; } function _currentStock() { return _stockApples; }; // Public functions (will be paired below) function displayCurrentStock() { $("#customerFeedback").text("Current number of apples in stock: " + _currentStock()); } function addApples() { var number = parseInt($("#numberOfAddApples").val()); _addToStock(number); } function sellApples() { var numberSold = parseInt($("#numberOfSoldApples").val()); _reduceStock(numberSold); } return { init: init, displayCurrentStock: displayCurrentStock, addApples: addApples, sellApples: sellApples }; })(); // Use console to test your functions exposure. //console.log(stockModule.); </script>
Hope you enjoy our journey to refactor a single object using modern design patterns. Please send me your comments or questions and don’t forget to share this article with your friends.