Joel's Thoughts

Modular Code Structure In Javascript

September 02, 2016

Imagine you inherited a legacy code that calculates and displays a new annual balance for an investment given a fixed rate and an initial amount:

//global variables
var balance = 1500,
interest_rate = 4.3;

//calculate new balance per year by adding the new interest from the old balance
function calculateAnnualBalance(){    
    balance = balance * (1 + (interest_rate/100));    
}

function getBalance(n){
    var label = "Balance On Year " + n + " is $";
    balance =  label + balance;    
    return balance;
}

function printBalance(){   
   calculateNewBalance(); //increment balance
   console.log(getBalance(1));
}

printBalance(); // will output "Balance On Year 1 is $1564.5";

Running the code on the console will output like this:

Life is great and wonderful until a new requirement comes in. The new requirement is to support multiple years of balances and print them individually.

To support the new requirement, your new co-worker modified the printBalance function like this:


   .... more code before

   function printBalance(years){
        for (var i = 1; i <= years; i++){
            calculateNewBalance(); //increment balance
            console.log(getBalance(i));
        }
   }

   printBalance(10); //print all balances in 10 years

Running the code, the output will now contain a lot of “NaN” values.

This is because of the balance variable being exposed globally. The getBalance function has a direct access to the balance value
consequently changing the variable’s type from number to string.

This is just a trivial example and we can fix the bug easily. However, imagine this in a real world application and there are tons of spaghetti code in here. Also to make the matter worst, what if the new co-worker went home without telling you the problem. I think you got my point here.

One solid and long term solution is to modularize the code. Modularly structuring a code can protect data integrity. To illustrate, let’s rewrite the code above.

var Balance = (function(){

    //these are now private variables thus cannot be accessed outside the module
    var balance = 1500,
    interest_rate = 4.3;


    function calculateNewBalance(){  
       balance = balance * (1 + (interest_rate/100));    
    }

    function getBalance(){
        return balance;
    }

    //expose the functions outside the module
    return {
        calculateNewBalance: calculateNewBalance,
        getBalance: getBalance
    }

})();

We start by declaring a new Balance module. The functions and variables are the same except we added a new getBalance function.

Take note that getBalance function does not modify the balance value but only gets it. Also balance variable isn’t accessible outside the module assuring us that the data type for this variable isn’t modified anywhere else.

Given that there’s a new developer on the team, the only way he/she can access the balance variable outside the module is to call the getBalance function.

Next is to create a submodule for displaying output.


    Balance.displayUtility = (function(){

        function getBalance(n){
            var label = "Balance On Year " + n + " is $",
            balance =  label + Balance.getBalance(); //call the getBalance function from the main module     
            return balance;
        }        

        function printBalance(years){
                for (var i = 1; i <= years; i++){
                    Balance.calculateNewBalance(); //increment balance using the module's function
                    console.log(getBalance(i));
                }
        }

        return {            
            printBalance: printBalance
        }

    })();

A new submodule for Balance called displayUtility is created. Since balance isn’t global anymore, we call the main module’s getBalance function instead on this line.

 ...more code 

  var label = "Balance On Year " + n + " is $",
  balance =  label + Balance.getBalance();  

  ... more code

To print the balances in 10 years, we call the printBalance function w/c calls the getBalance function as well:


Balance.displayUtility.printBalance(10);

The console’s output as expected is now:

Here’s our whole Balance module:


var Balance = (function(){
    var balance = 1500,
    interest_rate = 4.3;


    function calculateNewBalance(){  
       balance = balance * (1 + (interest_rate/100));    
    }

    function getBalance(){
        return balance;
    }

    return {
        calculateNewBalance: calculateNewBalance,
        getBalance: getBalance
    }
})();

Balance.displayUtility = (function(){

        //private function
        function getBalance(n){
            var label = "Balance On Year " + n + " is $",
            balance =  label + Balance.getBalance();    
            return balance;
        }        

        function printBalance(years){
            for (var i = 1; i <= years; i++){
                Balance.calculateNewBalance(); //increment balance
                console.log(getBalance(i));
            }
        }

        return {            
            printBalance: printBalance
        }

})();

Balance.displayUtility.printBalance(10);









  • About
  • Search
  • Resume
  • Powered by Jekyll using the Trio theme