Monday, May 29, 2023

Design Patterns

 Creational Patterns:

Singleton Pattern:

Scenario: Ensure that only one instance of a class is created throughout the application, and provide a global access point to that instance.

Example: Database connection manager, where you want to ensure there is only one connection to the database throughout the application.

Factory Pattern:

Scenario: Delegate the responsibility of object creation to a factory class, allowing subclasses to decide which class to instantiate.

Example: Abstract factory pattern for creating different types of shapes (e.g., creating instances of Circle, Square, Triangle) based on the input provided.

Prototype Pattern:

Scenario: Create new objects by cloning existing objects, avoiding the need for explicit instantiation.

Example: Prototypical object creation in JavaScript, where you clone an existing object to create a new object with the same properties and behaviors.

Builder Pattern:

Scenario: Separate the construction of complex objects from their representation, allowing the same construction process to create different representations.

Example: Building a complex document (e.g., a report) where you have different builders for constructing the header, body, and footer sections. The same construction process can create different types of reports.

Abstract Factory Pattern:

Scenario: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Example: Creating furniture objects (e.g., chair, table) in different styles (e.g., Victorian, Modern) using an abstract factory. The concrete factories create furniture objects that belong to a specific style.


Structural Patterns:

Adapter Pattern:

Scenario: Convert the interface of a class into another interface that clients expect, enabling classes with incompatible interfaces to work together.

Example: Adapting a legacy API to a new system by creating an adapter class that translates the new system's expected interface to the one provided by the legacy API.

Decorator Pattern:

Scenario: Dynamically add additional responsibilities to an object by wrapping it with a decorator class, without modifying its underlying structure.

Example: Adding features to a text editor, such as spell checking or text formatting, by creating decorator classes that wrap the base text editor class.

Proxy Pattern:

Scenario: Provide a surrogate or placeholder object to control access to another object, allowing additional actions to be performed before or after accessing the original object.

Example: Remote proxy for accessing objects over a network, where the proxy handles network communication and forwards requests to the remote object.

Composite Pattern:

Scenario: Compose objects into tree structures to represent part-whole hierarchies. Clients can treat individual objects and compositions uniformly.

Example: Representing a file system hierarchy, where files and folders are treated uniformly as components, and a folder can contain both files and subfolders.


Behavioral Patterns:

Observer Pattern:

Scenario: Establish a one-to-many dependency between objects, where changes in one object (subject) trigger updates in its dependent objects (observers).

Example: Event handling system, where multiple event listeners (observers) are registered to an event source (subject), and when an event occurs, all registered listeners are notified and updated.

Strategy Pattern:

Scenario: Define a family of algorithms, encapsulate each one, and make them interchangeable. Clients can use and switch between algorithms dynamically.

Example: Sorting algorithms, where different strategies (e.g., bubble sort, merge sort, quicksort) can be encapsulated and selected dynamically based on the specific sorting requirements.

Command Pattern:

Scenario: Encapsulate a request as an object, allowing clients to parameterize clients with queueable requests and support undoable operations.

Example: Implementing an undo/redo functionality, where commands representing user actions are encapsulated as objects, allowing the execution and reversal of those actions.

Iterator Pattern:

Scenario: Provide a way to access elements of an aggregate object sequentially without exposing its underlying representation.

Example: Iterating over elements in a collection (e.g., list, array) using an iterator object that provides methods to retrieve elements one by one, abstracting the specific structure of the collection.

Template Method Pattern:

Scenario: Define the skeleton of an algorithm in a base class, allowing subclasses to override certain steps of the algorithm without changing its structure.

Example: Defining a template for different types of reports, where a base report class defines the overall structure and common steps, while subclasses provide specific implementations for individual report sections.

State Pattern:

Scenario: Allow an object to alter its behavior when its internal state changes, by encapsulating state-specific logic into separate state objects.

Example: Implementing a vending machine, where the behavior of the machine (e.g., accepting coins, dispensing products) depends on its current state (e.g., idle, selecting product, accepting payment).

Chain of Responsibility Pattern:

Scenario: Create a chain of objects, each of which has the ability to process a request and pass it to the next object in the chain. The request is processed by the first object that can handle it.

Example: Handling requests in an application, where each handler object checks if it can process the request and either handles it or passes it to the next handler in the chain.

Interpreter Pattern:

Scenario: Define a grammar for a language and interpret sentences in the language by creating objects representing expressions in the grammar.

Example: Implementing a calculator, where mathematical expressions are parsed and evaluated using interpreter objects representing different types of expressions (e.g., addition, subtraction).

These behavioral patterns provide solutions for managing interactions and behaviors between objects in a flexible and decoupled manner, allowing for easier extensibility and maintainability of the software system.







Friday, March 17, 2017

Zonejs Overview with Example


Zonejs is one of the core library used in Angularjs 2. Zonejs is to maintain contextual execution for single or multi-leveled asynchronous methods. So, it means it helps to keep track of the parent context of currently executing asynchronous method.

Example-

Zone.current.fork({}).run(function(){
 Zone.current.myZoneVar = true;
 console.log('Assigned myZoneVar');
 setTimeout(()=>{
   console.log('In timeout', Zone.current.myZoneVar);
 },1000);
});
console.log('Out side', Zone.current.myZoneVar);


Here we created a fork of our current Zone and run is invoking the method under the Zone. The method has an asynchronous call (setTimeout). But as it is under zone we have the access of Zone variable. In last line we can see out of zone we are trying to access same variable, but it will have undefined in it.

Forking a zone will basically inheriting an existing context and you can override it if required.

Example-

function main(){
 console.log('Start ' );
 setTimeout(function(){
 throw new Error('Oops End- Error');},1000);
 console.log('In Progress ');
}

Zone.current.fork({
  onHandleError: (parentZoneDelegate, currentZone, targetZone, error) =>{
    console.log('error handler ->',error)
  }
}).run(main);


Here, we are overriding current zone error handler using onHandleError.

State changes tracking of context using interception very easy using zone events handlers.

List of events-

/**
* Allows the interception of zone forking.
*
* When the zone is being forked, the request is forwarded to this method for interception.
*
* @param parentZoneDelegate Delegate which performs the parent [ZoneSpec] operation.
* @param currentZone The current [Zone] where the current interceptor has beed declared.
* @param targetZone The [Zone] which originally received the request.
* @param zoneSpec The argument passed into the `fork` method.
*/
onFork?: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, zoneSpec: ZoneSpec) => Zone;
/**
* Allows interception of the wrapping of the callback.
*
* @param parentZoneDelegate Delegate which performs the parent [ZoneSpec] operation.
* @param currentZone The current [Zone] where the current interceptor has beed declared.
* @param targetZone The [Zone] which originally received the request.
* @param delegate The argument passed into the `warp` method.
* @param source The argument passed into the `warp` method.
*/
onIntercept?: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, source: string) => Function;
/**
* Allows interception of the callback invocation.
*
* @param parentZoneDelegate Delegate which performs the parent [ZoneSpec] operation.
* @param currentZone The current [Zone] where the current interceptor has beed declared.
* @param targetZone The [Zone] which originally received the request.
* @param delegate The argument passed into the `run` method.
* @param applyThis The argument passed into the `run` method.
* @param applyArgs The argument passed into the `run` method.
* @param source The argument passed into the `run` method.
*/
onInvoke?: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, applyThis: any, applyArgs: any[], source: string) => any;
/**
* Allows interception of the error handling.
*
* @param parentZoneDelegate Delegate which performs the parent [ZoneSpec] operation.
* @param currentZone The current [Zone] where the current interceptor has beed declared.
* @param targetZone The [Zone] which originally received the request.
* @param error The argument passed into the `handleError` method.
*/
onHandleError?: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any) => boolean;
/**
* Allows interception of task scheduling.
*
* @param parentZoneDelegate Delegate which performs the parent [ZoneSpec] operation.
* @param currentZone The current [Zone] where the current interceptor has beed declared.
* @param targetZone The [Zone] which originally received the request.
* @param task The argument passed into the `scheduleTask` method.
*/
onScheduleTask?: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => Task;
onInvokeTask?: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, applyThis: any, applyArgs: any) => any;
/**
* Allows interception of task cancelation.
*
* @param parentZoneDelegate Delegate which performs the parent [ZoneSpec] operation.
* @param currentZone The current [Zone] where the current interceptor has beed declared.
* @param targetZone The [Zone] which originally received the request.
* @param task The argument passed into the `cancelTask` method.
*/
onCancelTask?: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => any;
/**
* Notifies of changes to the task queue empty status.
*
* @param parentZoneDelegate Delegate which performs the parent [ZoneSpec] operation.
* @param currentZone The current [Zone] where the current interceptor has beed declared.
* @param targetZone The [Zone] which originally received the request.
* @param isEmpty
*/
onHasTask?: (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) => void;

Zone js can be used for any js app. It's just a helper library for implementing contextual execution for asynchronous methods. Bellow we can see, we can implement error stack trace using Zone.
Handler details created in longStackTraceZoneSpec custom property of Zone. See the running example code.

Example-

function grandChild(){
 console.log('set grandchild');
 setTimeout(function(){ throw new Error('Error--');},1000);
}

function child(){
 console.log('set child');
 grandChild();
}

function parent(){
 console.log('set parent');
 child();
}

function start(){
 parent();
}
var forkVal = Zone.longStackTraceZoneSpec;
/*forkVal.onHandleError= function (parentZoneDelegate, currentZone, targetZone, error) {
console.log('error handler ->',error)
};*/
//Uncomment upper section to see default error with out longStackTraceZoneSpec---|
Zone.current.fork(forkVal).run(start);

// see the console... You will see full error stack trace with method name ref...


The last example is to get the total time count for nested asynchronous call using zone. As the bootstrap method is under zone context, Zone variables and functions will be accessible to all asynchronous call under parent /root zone. This is the core flavor of Zone.



To conclude, we can say " Zone is an execution context that persists across async tasks. You can think of it as thread-local storage for JavaScript VMs." 
Angular 2 is utilizing Zonejs for change detection. Whenever any change happens, it is detected by following code in Angular 2 - 
ObservableWrapper.subscribe(this.zone.onTurnDone, () => {
  this.zone.run(() => {
    this.tick();
  });
});

tick() {
  // perform change detection
  this.changeDetectorRefs.forEach((detector) => {
    detector.detectChanges();
  });
}
Angular zone emits onTrunDone event to start change detection in the app.

Ref to Angular2 Repo- Zone_Start

Further study -



Saturday, February 25, 2017

RxJs Quick start

Reactive Programming is a pattern of development that works with asynchronous data stream created of UI Events, HTTP Requests, File System, cache etc. So data stream is an ongoing event sequence in time orderly manner. Stream can emit value, error, and status signal.

Observables are to watch these streams and trigger function on anything occurs in the stream. Observers can subscribe to observables.

RxJs is the library which helps us to do the exact same implementation in our project.

As per MSDN -
Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators. Reactive Extensions represents all these data sequences as observable sequences. An application can subscribe to these observable sequences to receive asynchronous notifications as new data arrive. 

Great let’s see some RxJs Code and see how it works -

Example 1 –

import Rx from 'rxjs/Rx'; //import Rxjs
  
const src$ = new Rx.Observable.create(function (observer) {  //Create observable  
// Each next inside Observable will trigger subscribed function.
 observer.next('hi'); 
    observer.next('hello');
    setTimeout(function () {
        observer.next('bye');
        observer.complete();// Will end the observer
    }, 3000);
    //observer.error(new Error('Error'));// <-- uncomment the throw error
});

src$.subscribe(
    function (e) {
        console.log(e);// will execute when any change in Observable
    },
    function (er) {
        console.log(er);// will be called when error
    }, function () {
        console.log('completed'); // will be called when done
    }
 );
See comments for detail understanding.

Few more examples.

Example 2 – (Event Observable)

import $ from 'jquery';  //import jquery
import Rx from 'rxjs/Rx'; //import Rxjs
const btn = $('#btn'); // get element
const input = $('#inp');
    
const btnStream$ = Rx.Observable.fromEvent(btn, 'click'); // set observable event
btnStream$.scbscribe( // Subscribe to the event, to call function when event occurs
    function (e) {
        console.log(e);
    },
    function (er) { // error handling
        console.log(err);
    }, function () { // called when completed
        //completed
    });

const inputStream$ = Rx.Observable.fromEvent(input, 'keyup');

btnStream$.scbscribe(
    function (e) {
        console.log(e);
    },
    function (er) {
        console.log(err);
    }, function () {
        //completed
    });

Example 3- (Observable Array)

import Rx from 'rxjs/Rx';
   
const numbers = [1, 2, 3, 4, 5];
const numberStream$ = Rx.Observable.from(numbers);// Make array Observable
numberStream$.subscribe( // Subscribe to the array observable
    function (e) {
        console.log(e);
    },
    function (er) {
        console.log(err);
    }, function () {
        //completed
    });
   
Further study - https://xgrommx.github.io/rx-book/why_rx.html

Friday, February 17, 2017

TypeScript Intro


TypeScript is a typed superset of Javascript. “  

Let’s see what does this line means.  TypeScript is typed; it has the ability to define typed variables. In core javascript, we use “var” to initialize a variable or function. But in TypeScript, we can specify the type (Like- string, number, Boolean, etc.) of it while initializing. TypeScript is also a superset of javascript, that means any javascript code should work properly inside TypeScript. In other words, all Javascript is valid inside TypeScript.  So we can say, it is javascript with some more advanced features.

Ok, now let’s think, we created a web application using TypeScript. If we try to run that in our browser, it will not work as it is not core javascript, so it is not compilable by our browser engine. So to overcome we have something called transpiler, which will compile TypeScript code to core javascript which can get executed in a browser.
Microsoft has created this TypeScript transpiler. It comes with typescript package. So it install TypeScript, open your terminal and run-

>npm install –g typescript

So now typescript is installed. If you now run following, you should see the typescript transpiler version.

>tsc  --version

Now use VSCode editor for coding. It has inbuilt .ts type support.
Well, open your working folder in VSCode and create a file, name it Employee.ts. Yes , the extension will be .ts not .js.  Put the following code in the file-

//Interface
interface IEmployee { //defining interface
    yearOfJoin: number;// interface  property
    loyality : () => number;// interface function
}
//Base Class
class Company { //create class
    constructor(public name: string, public country: string) { //define constructor
                this.name = name;
                this.country = country;
    }
    public Details(details: string) {            
        return ('Company Name:' + this.name + ' Country: ' + this. country + ' Details: ' + details);
    }
}
//Child Class implements IEmployee and inherits from Company
class Employee extends Company implements IEmployee { //create class extend company and implement IEmployee
    firstName: string; // typed variable
    lastName: string;
    yearOfJoin: number;
    //private _company: Company;
    //Constructor           
    constructor(firstName: string, lastName: string, companyName: string, country: string, yearOfJoin: number) {
        super(companyName, country);
        this.firstName = firstName;
        this.lastName = lastName;
        this. yearOfJoin = yearOfJoin;
    }
    loyality () {
        return 2017 - this. yearOfJoin;  // as 2017 is current year
    }
    CompanyDetails() {
        var y = super. Details (' Software Company with CMMI lavel');
        console.log(y);
    }
    printDetails(): void {
        alert(this.firstName + ' ' + this.lastName + ' Company is: ' + this.name);
    }
}

Save the file and run-

>tsc Employee.ts --target ES5 --outDir js --watch

Here we are running typescript transpiler with following arguments –

1.       Typescript files to be compiled.
2.       Compiled to which js version.(ES5/ES6)
3.       What should be the output directory.(js)
4.       Watch the files as mentions in the first argument, and whenever any changes, compile it to js.

Note: for more options execute-  
> tsc –help

After the execution you should see a js folder inside your current folder. And the js folder will contain your compiled .js files form provided .ts files.


See code comments for clear understanding.

Friday, February 3, 2017

Express With MongoDB - Quick start

Let's access MongoDB from Nodejs using Express. 

What is Express? 
As per Express site, it's a minimal and flexible Node.js web application framework that provides a robust set of features for the web and mobile applications.

Features
·         Robust routing
·         Focus on high performance
·         Super-high test coverage
·         HTTP helpers (redirection, caching, etc)
·         View system supporting 14+ template engines
·         Content negotiation
·         Executable for generating applications quickly

Great.Lets start. (Assumed you have Nodejs and MongoDB installed, if not ,check Nodejs MongoDb)

Create a folder and run following command on your terminal-

 > npm init

It will ask you few questions (Like- Name for the project, author, version). For now, you can keep all the default values. This will give you your package.json inside the same folder.

Greate execute this now-

> npm install --save express
mongoose morgan body-parser

So here, we actually installed Express along with mongoose which is a Node.js library that provides MongoDB object mapping similar to ORM with a familiar interface within Node.js and Morgan which is basically used for logging request details. And body-parser parses incoming request bodies in a middleware before your handlers, available under the req.body property.

Now you should see a folder named node_modules inside your current folder. Inside node_modules all your installed node packages reside. We are now ready to go further.

Let's create a file and name it server.js. Put the following code and save it.

var express = require('express'); // load express module in your project

var morgan = require('morgan'); // load morgan module 

var mongoose = require('mongoose'); //load mongoose module 

var bodyParser = require('body-parser'); // load body-parser module 

var app = express(); //init express
var port = process.env.PORT || 6064; //allocate the port for your server
app.use(express.static('./public')); // set folder for public items , such as - image , css, html, client side js
app.use(morgan('dev')); // init morgan for logging request details
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

mongoose.connect('mongodb://localhost/mongodbtest'); // mongodb connection

routesetup(app);// set your route details with path and its handlers 
app.listen(port);// start your server
console.log("App listening on port " + port); 


function routesetup(app) { // function for route setup
   app.use( function (req, res, next) {  // will be executed for all request
        console.log(req.url);
        next();
    });
    app.use( function (err, req, res, next) { // will be executed for all error
        console.log(err);
        next();
    });    
// REST API to access from client side js--> 
    app.get('/api/todos', function (req, res) { // get method route
       todo.find(function (err, todos) { // used mongoose model to get data
            if (err) {
                res.send(err);
            }

            res.json(todos);
        });
    });
app.post('/api/todos', function (req, res) { //post method route
 var td = new todo({
 val: req.body.val
        });

        td.save(function (err, td) { // use mongoose model to dave data
            if (err) {
                return res.status(500).json({
                    message: 'Error when creating todo',
                    error: err
                });
            }
            return res.status(201).json(todo);
        });
});
    app.get('*', function (req, res) { // get method for html
        //throw new Error('err');
        res.sendFile(__dirname + '/public/index.html');
    });
}

var todo = mongoose.model('Todo', { //mongoose model
    val: {
        type: String,
        default: ''
    }
});

Now create a folder public and inside it create a file index.html  and add following -

<html>

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <script>
    $(document).ready(function () {
        $("#btn").click(function () {
            $.post("/api/todos",
                {
                    val: $("#txttask").val()
                },
                function (data, status) {
                    console.log("Data: " + data + "\nStatus: " + status);
                });

            $("#txttask").val('');
            getData();
        });
        function getData() {
            $.get("/api/todos", function (data, status) {
                var listVal = "";
                $.each(data, function (index, val) {
                    listVal += val.val + "<br>";
                })
                $("#listtask").html(listVal);
            });
        }
        getData();
    });
</script>
</head>

<body>
    <div>
        <b>Express Running</b></div>
    <div>
        <label> Task:</label><input type="text" id="txttask" /><button id="btn">Save</button>
    </div>
    <div>
        <b>Task List</b>
    </div>
    <div id="listtask"></div>
</body>

</html>

Save both the files.

Note: Please read all the inline comments carefully for better understanding.

Greate . Now we are ready to run our first Express application with MongoDB.

Run you mongoDB, before going further.(go to your mongo installation folder and then ./bin folder using a new terminal window)

mongod --directoryperdb --dbpath <folder path>


To Run the application, execute following in your terminal-

> node server.js

Now Try to open - http://localhost:6064/

If you have done it properly, you should see your HTML page with heading Express Running. Using the api created in server.js you can save and see the saved list of items in the page.

That's it.

Feel free to ask if you have any queries.