Thursday, May 7, 2015

Modular Pattern & OOP in JS

Factory pattern

Factory pattern is one great creational pattern. In the sample I have 2 different classes - Fulltime and Contractual employees. Based on the parameters passes, appropriate class is created and used

/** * Created by krishnan on 5/7/15. */function FullTimeEmployee(employeeOptions) {
    this.employeeName = employeeOptions.empName;
    this.employeeID = employeeOptions.empID;
    this.designation = employeeOptions.designation;
}

FullTimeEmployee.prototype.printDetails = function printDetails() {
        console.log('Employee Name: ' + this.employeeName + ', Employee ID: ' + this.employeeID +
        ', Designation: ' + this.designation);
    }

function ContractEmployee(employeeOptions) {
    this.employeeName = employeeOptions.empName;
    this.employeeID = employeeOptions.empID;
    this.designation = 'Consultant';
    this.hourlyRate = employeeOptions.hourlyRate;
}

ContractEmployee.prototype.printDetails = function printDetails() {
    console.log('Employee Name: ' + this.employeeName + ', Employee ID: ' + this.employeeID +
    ', Designation: ' + this.designation + ', Hourly Rate: ' + this.hourlyRate);
}

function EmployeeFactory() {
    return {
        employeeClass : FullTimeEmployee,
        createEmployee: function createEmployee(employeeOptions) {
            switch(employeeOptions.employeeType) {
                case "full-time":
                    this.employeeClass = FullTimeEmployee;
                    console.log('Employee is full-time');
                    break;
                case "part-time":
                    this.employeeClass = ContractEmployee;
                    console.log('Employee is part-time');
                    break;
            }
            return new this.employeeClass(employeeOptions);
        }
    };
}

var employeeOptions = {employeeType:'full-time', empName:'Sriram', empID:10, 'designation':'VP'}
var currEmployee = EmployeeFactory().createEmployee(employeeOptions);
currEmployee.printDetails();

var contEmployeeOptions = {employeeType:'part-time', empName:'Krishnan', empID:11, 'designation':'Contract',
    hourlyRate:90};
var currEmployee2 = EmployeeFactory().createEmployee(contEmployeeOptions);
currEmployee2.printDetails();

A simple Singleton in JS

/** * Created by krishnan on 5/7/15. */
var empSingleton = (function(empName, empId) {
    var instance;

    function init(empName, empId) {

        var employeeName, employeeID;
        var employeeSalary;

        function printEmpDetails() {
            employeeName = empName;
            employeeID = empId;
            console.log('Emp Name: ' + employeeName + ', Emp ID: ' + employeeID + ' his salary: ' + employeeSalary);
        }

        function calculateSalaryFor(experience, designation) {
            if(experience <= 1) {
                employeeSalary = 5000;
            } else if(experience <= 5) {
                employeeSalary = 10000;
            } else if(experience <= 10) {
                employeeSalary = 15000;
            } else if(experience <= 15) {
                employeeSalary = 20000;
            } else {
                employeeSalary = 30000;
            }
        }

        return {
            calculateSalary: calculateSalaryFor,
            empDetails: printEmpDetails        }
    }

    return {
        getInstance: function(empName, empID) {
          if(!instance) {
              instance = init(empName, empID);
          }
          return instance;
        }
    };
})();

var singletonInstance = empSingleton.getInstance('Krishnan', 20);
singletonInstance.calculateSalary(14, 'VP');
singletonInstance.empDetails();

var singletonInstance2 = empSingleton.getInstance('Shyam', 20);
singletonInstance2.calculateSalary(19, 'VP');
singletonInstance2.empDetails();

Modular Pattern and OOP in JS

Using classes in Javascript is tricky from reusability perspective. Especially if you want to use inheritance ideologies. I have had my fair bit of struggle with the concept.

To start with lets do a simple class using Modular pattern followed by conventional approach. I had issues with inheritance when I take Modular pattern route, but that could just be because of the code sample I had. I am working on it. As soon as I crack open that box, I'll add sample here.

Modular Pattern


Modular pattern provides a great way to encapsulate and abstract class objects. You can have private methods that will not be exposed. Conversely, you just let the caller invoke/look at what you want him to look at.

Here's the sample of the same

Employee.js

/** * Created by krishnan on 5/6/15. */
function Employee() {
    var empName;
    var empID;

    function login(empName, empId) {
        this.empName = empName;
        this.empID = empId;
        console.log('EMPLOYEE logged in');
    }

    function logoff() {
        console.log('EMPLOYEE signed off');
    }

    function hoursOfWork() {
        console.log('Employees need to work 8 hours a day');
    }

    function printEmployee() {
        console.log('EmpName: ' + this.empName + ' Emp ID: ' + this.empID);
    }

    return {
        login: login,
        logoff: logoff,
        hoursOfWork:hoursOfWork,
        printDetails:printEmployee    }
}

module.exports = Employee;

Consumer.js

/** * Created by krishnan on 5/7/15. */
var Employee = require('./Employee');
emp = Employee();
emp.login('Krishnan', 30);
emp.hoursOfWork();
emp.printDetails();
emp.logoff();

If you notice the Employee.js, although we have variables like empName and empID, they are not exposed to consumer classes. They only get to see the functions that operate on private properties of Employee class.

Conventional approach


Traditionally, we can achieve the same behavior by doing something like this. you can still create private variables by prefixing variables with "__". But that's not easy on eyes or bound to go wrong in one place or other. On the flip side. This mechanism is a lot more easier for inheritance over module pattern.

But that's for another day and another time

Here's a quick look on the code

Employee.js


/** * Created by krishnan on 5/6/15. */
function Employee(name, empId) {
    console.log('EMPLOYEE constructor invoked');
    this.empName = name;
    this.empId = empId;
}

Employee.prototype.login = function login() {
    console.log('Employee logged into office');
}

Employee.prototype.logoff = function logoff() {
    console.log('Employee signed off for the day');
}

Employee.prototype.hoursOfWork = function() {
    console.log('Employees should work for 8 hours a day');
}

module.exports = Employee;


ContractEmployee.js

/** * Created by krishnan on 5/6/15. */var Employee = require('./Employee'),
    inherits = require('util').inherits;

function ContractEmployee(name, empId) {
    console.log('ContractEmployee constructor invoked');
    Employee.call(this, name, empId);
}

inherits(ContractEmployee, Employee);

ContractEmployee.prototype.hourlyRate = function hourlyRate() {
    console.log('Hourly rate for contract employee is $20');
}

module.exports = ContractEmployee;

Consumer.js

/** * Created by krishnan on 5/6/15. */
var ContractEmployee = require('./ContractEmployee');

var cEmployee = new ContractEmployee('Krishnan', 30);
console.log('Class name: ' + cEmployee.constructor.name);
cEmployee.login();
cEmployee.logoff();
cEmployee.hoursOfWork();
cEmployee.hourlyRate();

Monday, May 4, 2015

NodeJS - Asynchronous and Events programming

Async Series in NodeJS


When you need to do something in series with no dependency on carry over response from one to another NodeJS provides a wonderful asynchronous solution
/** * Created by krishnan on 5/4/15. */

var fs = require('fs');
var async = require('async');

var readFileCB = function(err, fileContent) {
    if(err) {
        console.log('Failed to read file');
    } else {
        console.log('Contents of file\n');
        console.log(fileContent);
    }
}

var readTextFile1 = function(fileName, cb) {
    fs.readFile(fileName, 'utf8', cb);
}

var readTextFile2 = function(fileName, cb) {
    fs.readFile(fileName, 'utf8', cb);
}

var readFile1Text = function(cb) {
    fs.readFile("file1.txt", 'utf8', cb);
}

var readFile2Text = function(cb) {
    fs.readFile("file2.txt", 'utf8', cb);
}

var workerReadFiles = [readFile1Text, readFile2Text];

async.series(workerReadFiles, readFileCB);
//readTextFile("file1.txt", readFileCB);


Imagine a situation where results are dependent, like you need to read contents of a JSON file, load an object successfully, before you process to process JSON. That's where waterfall is extremely useful. One thing that you need to be aware here is, if any of the intermediate step fails, we do not move forward. In the following example, readJSONContent reads the local JSON file, if successfull, moves onto processJSON method.
/** * Created by krishnan on 5/4/15. */

var fs = require('fs');
var async = require('async')

var readJSONContent = function(readCallBack) {
    console.log('Read invoked');
    fs.readFile("customerForm.json", "utf8", function(err, fileContent){
        if(err) {
            readCallBack(err, null);
        } else {
            readCallBack(null, fileContent);
        }
    });
}

var processJSONContent = function(fileContent, processCallBack) {
    var customerContent = JSON.parse(fileContent);
    if(customerContent.firstName == "John") {
        processCallBack(null);
    } else {
        throw new Error("Wrong values in JSON");
        processCallBack(null);
    }
}

var workflow = [readJSONContent, processJSONContent];

async.waterfall(workflow, function(error) {
   if(error) {
       console.log("Failed with error :" + error);
   } else {
       console.log('Finished reading ')
   }
});

Event Emitters

Building a loosely coupled system with emitter. Emitters can be very useful as much as it can be abused to the core. (Concept is parallel to Notifications in iOS, if you have done some iOS programming). As much as the code is loosely coupled, I'd advice you take care when you do anything with events. Here's the sample code for the same
/** * Created by krishnan on 5/4/15. */

var events = require('events');

var eventEmitter = new events.EventEmitter();

var startConnection = function() {
    console.log('Started connection to DB');
    eventEmitter.emit('connection_success');
}

var readData = function() {
    console.log('Read data from remote connection');
    eventEmitter.emit('read_success');
}

var connectionClosed = function() {
    console.log('Connection closed');
    eventEmitter.emit('connection_closed');
}

var allDone = function() {
    console.log('All done!!!');
}

eventEmitter.on('connection', startConnection);
eventEmitter.on('connection_success', readData);
eventEmitter.on('read_success', connectionClosed);
eventEmitter.on('connection_closed', allDone);

eventEmitter.emit('connection');

We will be able to add more than one listener to an event through 'addListener' method of EventEmitter class. So can you remove one and all listeners through removeListener and removeAllListeners. You can set a upper limit on the number of listeners you can have on events through the method setMaxListeners