Friday, June 16, 2017

Iteration vs. Recursion

Code

def factorial_iter(n):
    num = 1
    while n >= 1:
        num = num * n
        n = n - 1
    return num
   
def factorial_recur(n):
    if n == 1:
        # base case that stops recursion
        print ('  return 1 (this is the top of the stack)')
        return 1
    else:
        print ('  return ' + str(n) + '*' + 'factorial_recur(' + str(n-1) + ')')
        # the function is calling ITSELF
        return n * factorial_recur(n-1)
       
number = 5

print ('-' * 20)
print ('Using Iteration. Factorial of ' + str(number))
print ('-' * 20)
print (str(factorial_iter(number)))

print (' ' * 20)

print ('-' * 20)
print ('Using Recursion. Factorial of ' + str(number))
print ('-' * 20)
print ("factorial_recur: stack trace")
print ("Note how the function calls itself. This is no different than calling another function")
print ("It is called RECURSION because the function is calling ITSELF")
print ("When it reaches the BASE CASE (n==1), it stops calling itself")
print ("The function MUST stop calling itself at some point, otherwise it will never end (likely run of out memory)")
print ("The innermost function call is evaluated first, where n=1 and then return 2 * 1, then return 3 * 2, and so on")
print ("This is called unwinding of the stack. Start from the BOTTOM and evaluate upwards. Think of a function evaluation as follows.")
print ("(5 * (4 * (3 * 2) * (1)))")
print ("Stack trace")
print (str(factorial_recur(number)))

Output

--------------------
Using Iteration. Factorial of 5
--------------------
120
                   
--------------------
Using Recursion. Factorial of 5
--------------------
factorial_recur: stack trace
Note how the function calls itself. This is no different than calling another function
It is called RECURSION because the function is calling ITSELF
When it reaches the BASE CASE (n==1), it stops calling itself
The function MUST stop calling itself at some point, otherwise it will never end (likely run of out memory)
The innermost function call is evaluated first, where n=1 and then return 2 * 1, then return 3 * 2, and so on
This is called unwinding of the stack. Start from the BOTTOM and evaluate upwards. Think of a function evaluation as follows.
(5 * (4 * (3 * 2) * (1)))
Stack trace
  return 5*factorial_recur(4)
  return 4*factorial_recur(3)
  return 3*factorial_recur(2)
  return 2*factorial_recur(1)
  return 1 (this is the top of the stack)
120

Thursday, June 15, 2017

Why use async/await pattern?

While code execution is waiting for an IO bound operation, such as SQL or HTTP operation, to complete, the thread that is waiting can be used by other code operations. Basically, mark the method as async and await the results of an IO bound operation. While waiting, the awaited thread can be utilized for other operations.

Wednesday, April 26, 2017

Immediately Invoked Function Expressions (IIFE) aka Self-executing Anonymous Functions

In the following html page, a heading shown. The color of the heading is changed to red by JavaScript. The scope of elem variable is global. If there is another global variable by the same name in any JavaScript included on this page, the elem will be destroyed and the script is not going to change the color of heading to red.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>IIFE</title>
</head>
<body>
<h1 id="heading">IIFE</h1>

<script>
var elem = document.getElementById("heading");
elem.style.color = "red";
</script>
</body>
</html>

In JavaScript, variables are either scoped globally (like above) or at function level. By wrapping the JavaScript on a page in an Immediately Invoked Function Expression (IIFE) (aka Self-executing Anonymous Function), we can limit the scope of elem variable to the function and avoid a name collision with an identically named variable in the global scope.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>IIFE</title>
</head>
<body>
<h1 id="heading">IIFE</h1>

<script>
(function (color){
var elem = document.getElementById("heading");
elem.style.color = color;
})("red");
</script>
</body>
</html>

Saturday, February 11, 2017

Creating a Google Chrome Extension

Google Chrome Extensions are created using ubiquitous HTML, JavaScript and CSS. Third-party JavaScript can be included and leveraged in building Chrome Extensions.

There are two types of Chrome extensions.

1) Browser Extension - Available at all times, with its icon displayed in the toolbar.

2) Page Extension - Applies to one or more pages. The icon is displayed in the address bar. Performs operations on the content of the page.

General Development Steps

1. Create an empty directory

2. Add the following files to the empty directory.

Manifest.json - Information about the extensions, permissions requested by the extension (for example, to access storage), and names of all the content files of the extension (html, javascript files).

3. Html files
May not include embedded javascript.

popup.html - file that is displayed when the extension icon is clicked, page title becomes the tooltip text for the extension icon
options.html (optional) - file for setting options for the extension

4. Icon
19x19 icon for the toolbar icon for the extension

5. JavaScript files
Normal javascript file referenced from the html pages

Event javascript page that is executed when an extension is loaded. Provides an opportunity to hook up handlers to various events (Event js is just background script with persistent set to false in manifest).
Background javascript file that keeps running in the background for the extension (persistent set to true).
Can have one or the other. 

Simply copy thirdparty libraries to the folder and reference in HTML file. Make reference to these files in the head tag of html using the script tag.

6. Css
Style files referenced from HTML pages.

For example, use popup.css in HTML page using the link tag. 

7. Images
Images referenced in HTML pages.

8. Content scripts 
Javascript that runs on the  page being browsed. Tacked on the page being viewed.
Cannot use chrome extensions API directly.
Must use messaging to communicate with chrome extension code.

9. Testing extension
In Google settings, go to Extensions tab.
Enable developer mode.
Load unpacked extension from the directory
Can do "Inspect Element" on the extension to debug.

Thursday, February 9, 2017

Creating Class Objects in JavaScript

Object Factory Pattern


  • A function that creates and returns a new object (o in code below) after it sets data and function members.
  • Members can be data values (e.g. radius) or functions (e.g. area(), circumference(), print()).
  • Members have access to other members using the this keyword (e.g. area() function accesses this.radius).
Source:

var CircleFactory = function(radius){
    var o = {};
    o.radius = radius;
    o.area = function(){
        return 22/7 * this.radius * this.radius;
    }
    o.circumference = function(){
        return 2 * 22/7 * this.radius;
    }
    o.print = function(){
        console.log("radius: " + this.radius + 
        " area: " + this.area() 
        + " circumference: " + this.circumference());
    }
    return o;
}

// Usage
var circle1 = CircleFactory(10);
circle1.print();
var circle2 = CircleFactory(15);
circle2.print();

Output:

radius: 10 area: 314.2857142857143 circumference: 62.857142857142854
radius: 15 area: 707.1428571428571 circumference: 94.28571428571428

Constructor Function Pattern

  • A normal function is defined. This can serve as the Constructor function (i.e. Circle). 
  • Members are defined using the this keyword. These members are publicly available. One member can access another member using the this keyword (e.g. area() function accesses this.radius).
  • Members can be data values (e.g. radius) or functions (e.g. area(), circumference(), print()).
  • An instance of a function (aka function object) is created using the new keyword.
  • Members are invoked on the function object (not on the Constructor function).
Source:
var Circle = function(radius) {
    this.radius = radius;

    this.area = function() {
        return 22 / 7 * this.radius * this.radius;
    }
    this.circumference = function() {
        return 2 * 22 / 7 * this.radius;
    }

    this.print = function() {
        console.log("radius: " + this.radius 
        + " area: " + this.area() 
        + " circumference: " + this.circumference());
    }
}

// Usage
var circle1 = new Circle(10);
circle1.print();
var circle2 = new Circle(15);
circle2.print();

Output:
radius: 10 area: 314.2857142857143 circumference: 62.857142857142854
radius: 15 area: 707.1428571428571 circumference: 94.28571428571428

Constructor Function using Prototype Pattern

  • First, see description of Constructor Function Pattern above. Constructor Function using Prototype Pattern is just a more efficient implementation of the Constructor Function Pattern.
  • Every new object constructed has it's own copy of radius, area(), circumference(), print() functions. The radius is going to vary from one function object to another so it makes sense that every new function object maintain it's own copy of radius. But the implementation of area(), circumference(), print() functions does not differ from one function object to another! When a large number of function objects are created, this duplication of member function code adds unnecessary memory overhead.
  • The prototype property on the function allows us to set a member of the function once and have it available for all new function objects.
  • Both data (PI) and functions (area(), circumference(), print()) can be defined on the prototype of a function object.
Source:
var Circle = function(radius) {
    this.radius = radius;
}

Circle.prototype.PI = 22/7;

Circle.prototype.area = function() {
    return this.PI * this.radius * this.radius;
}
Circle.prototype.circumference = function() {
    return 2 * this.PI * this.radius;
}
Circle.prototype.print = function() {
    console.log("radius: " + this.radius 
    + " area: " + this.area() 
    + " circumference: " + this.circumference());
}

// Usage
var circle1 = new Circle(10);
circle1.print();
var circle2 = new Circle(15);
circle2.print();

Output:
radius: 10 area: 314.2857142857143 circumference: 62.857142857142854
radius: 15 area: 707.1428571428571 circumference: 94.28571428571428

Monday, January 23, 2017

How to use GROUP BY and JOIN in LINQ

Demonstrates how to use GROUP BY and JOIN in LINQ

Please see comments inline with the code.

GitHub Repository: https://github.com/sal-razzaq/linq_groupby_join

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;

namespace LINQGroupByExample
{
    // Demonstrates GROUP BY and JOIN in LINQ
    [TestClass]
    public class LINQGroupByExampleTest
    {
        // ENTITY: Represents a Web Page Url
        class WebPage
        {
            public int Id { get; set; }
            public string Url { get; set; }
        }

        // ENTITY: Records an access of a Web Page by Url 
        class WebPageAccess
        {
            public int Id { get; set; }
            public string Url { get; set; }
            public DateTime AccessedAt { get; set; }
        }

        // ENTITY: Records latency experienced in accessing a
        // Web Page represented by Url
        class WebPageLatency
        {
            public int Id { get; set; }
            public string Url { get; set; }
            public int LoadTimeMs { get; set; }
        }

        // Test Data - These could be Entity Framework DbSets
        List<WebPage> WebPages = new List<WebPage>();
        List<WebPageAccess> WebPageAccesses = new List<WebPageAccess>();
        List<WebPageLatency> WebPageLatencies = new List<WebPageLatency>();

        // Test Urls
        const string URL1 = "abc.com";
        const string URL2 = "def.com";
        const string URL3 = "xyz.com";

        // Populate data for testing
        void SeedData()
        {
            // We are tracking three web pages represented
            // by their respective Urls
            this.WebPages.Add(new WebPage() { Url = URL1 });
            this.WebPages.Add(new WebPage() { Url = URL2 });
            this.WebPages.Add(new WebPage() { Url = URL3 });

            for (int i = 0; i < 10; i++)
            {
                // record 10 accesses for URL1
                this.WebPageAccesses.Add(new WebPageAccess() { Url = URL1 });
                // record 5 accesses for URL2
                if (i % 2 == 0)
                {
                    this.WebPageAccesses.Add(new WebPageAccess() { Url = URL2 });
                }

                // record a latency of 2 for URL1
                this.WebPageLatencies.Add(new WebPageLatency() { Url = URL1, LoadTimeMs = 2 });
                // record a latency of 4 for URL2
                if (i % 2 == 0)
                {
                    this.WebPageLatencies.Add(new WebPageLatency() { Url = URL2, LoadTimeMs = 4 });
                }
            }
            // no data recorded for URL3
        }

        const int ASSERT_URL1_TOTAL_VIEWS = 10;
        const int ASSERT_URL2_TOTAL_VIEWS = 5;
        const int ASSERT_URL1_AVG_LATENCY_MS = 2;
        const int ASSERT_URL2_AVG_LATENCY_MS = 4;

        [TestMethod]
        public void Test()
        {
            SeedData();

            // Group web page accesses by Url, count accesses by Url
            var webPageAccessGroups = from row in this.WebPageAccesses
                                      // we can group by multiple fields, if needed
                                      group row by new { row.Url } into urlAccessGroup
                                      select new                        // group projection
                                      {
                                          Url = urlAccessGroup.Key.Url,
                                          TotalViews = urlAccessGroup.Count()
                                      };

            // Group web page latency by Url, average latency by Url
            var webPageLatencyGroups = from row in this.WebPageLatencies
                                       group row by new { row.Url } into urlLatencyGroup
                                       select new                       // group projection
                                       {
                                           Url = urlLatencyGroup.Key.Url,
                                           AvgLatencyMs = urlLatencyGroup.Average(g => g.LoadTimeMs)
                                       };

            // Join the main table of Urls (WebPages) with their respective
            // access (view) counts and latencies
            var webPagesStatsByUrl = from webpage in this.WebPages
                                     join webPageAccessGroup in webPageAccessGroups on new { Url = webpage.Url }
                                     equals new { Url = webPageAccessGroup.Url } into webPageAccesses
                                     join webPageLatencyGroup in webPageLatencyGroups on new { Url = webpage.Url }
                                     equals new { Url = webPageLatencyGroup.Url } into webPageLatencies
                                     from webPageAccess in webPageAccesses.DefaultIfEmpty() // used below for projection
                                     from webPageLatency in webPageLatencies.DefaultIfEmpty() // used below for projection
                                     select new     // new projection
                                     {
                                         Url = webpage.Url,
                                         TotalViews = webPageAccess == null ? 0 : webPageAccess.TotalViews,
                                         AvgLatencyMs = webPageLatency == null ? 0 : webPageLatency.AvgLatencyMs
                                     };
            Debug.WriteLine("== Results ==");
            Debug.WriteLine("Url\t\t\tTotalViews\tAvgLatencyMs");
            foreach (var row in webPagesStatsByUrl)
            {
                Debug.WriteLine($"{row.Url}\t\t{row.TotalViews}\t\t\t{row.AvgLatencyMs}");
            }

            Assert.AreEqual(ASSERT_URL1_TOTAL_VIEWS, webPagesStatsByUrl.Where(w => w.Url == URL1).FirstOrDefault().TotalViews);
            Assert.AreEqual(ASSERT_URL2_TOTAL_VIEWS, webPagesStatsByUrl.Where(w => w.Url == URL2).FirstOrDefault().TotalViews);
            Assert.AreEqual(0, webPagesStatsByUrl.Where(w => w.Url == URL3).FirstOrDefault().TotalViews);

            Assert.AreEqual(ASSERT_URL1_AVG_LATENCY_MS, webPagesStatsByUrl.Where(w => w.Url == URL1).FirstOrDefault().AvgLatencyMs);
            Assert.AreEqual(ASSERT_URL2_AVG_LATENCY_MS, webPagesStatsByUrl.Where(w => w.Url == URL2).FirstOrDefault().AvgLatencyMs);
            Assert.AreEqual(0, webPagesStatsByUrl.Where(w => w.Url == URL3).FirstOrDefault().AvgLatencyMs);
        }
    }
}

Output:
== Results ==
Url TotalViews AvgLatencyMs
abc.com 10 2
def.com 5 4
xyz.com 0 0

Monday, January 16, 2017

Amazon API Gateway Velocity Template to Pass All Data to AWS Lambda

Lambda Integration Velocity Template

## See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
## This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload


## allParams contains three members ($type below): path, querystring, header
## each member in turn is object with 0..n members

## stage-variables can defined for a particular "stage" of API Gateway

#set($allParams = $input.params())
{


"body-json" : $input.json('$'),

"params" : {
#foreach($type in $allParams.keySet())
#set($params = $allParams.get($type))
"$type" : {
#foreach($paramName in $params.keySet())
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
},


"stage-variables" : {
#foreach($key in $stageVariables.keySet())
"$key" : "$util.escapeJavaScript($stageVariables.get($key))"
#if($foreach.hasNext),#end
#end
},


"context" : {
"account-id" : "$context.identity.accountId",
"api-id" : "$context.apiId",
"api-key" : "$context.identity.apiKey",
"authorizer-principal-id" : "$context.authorizer.principalId",
"caller" : "$context.identity.caller",
"cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
"cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
"cognito-identity-id" : "$context.identity.cognitoIdentityId",
"cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
"http-method" : "$context.httpMethod",
"stage" : "$context.stage",
"source-ip" : "$context.identity.sourceIp",
"user" : "$context.identity.user",
"user-agent" : "$context.identity.userAgent",
"user-arn" : "$context.identity.userArn",
"request-id" : "$context.requestId",
"resource-id" : "$context.resourceId",
"resource-path" : "$context.resourcePath"
}
}

Data Received by AWS Lambda

{
"body-json": {
"appid": "myapp",
"eventtime": "2017-01-16",
"eventtype": "init",
"key1": "k1",
"key2": "k2",
"json": {
"astr": "str",
"anum": 123,
"bool": true
}
},
"params": {
"path": {},
"querystring": {},
"header": {
"Accept": "application/json",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.8",
"Cache-Control": "no-cache",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Content-Type": "application/json",
"Host": "5tt5f8xji6.execute-api.eu-west-1.amazonaws.com",
"Origin": "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop",
"Postman-Token": "bb496633-fe87-142d-95ea-31d1ee34ebca",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Via": "1.1 64184371bdc0c4545cde799b5949d17c.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "k9f8O0GfedOrKH2UUI10lt0QHBMbsPGyz-0GdwJpTWasNB_n9fMdgA==",
"X-Forwarded-For": "23.120.xx.xxx, 54.240.xxx.xx",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
}
},
"stage-variables": {},
"context": {
"account-id": "",
"api-id": "5tt5f8xji6",
"api-key": "",
"authorizer-principal-id": "",
"caller": "",
"cognito-authentication-provider": "",
"cognito-authentication-type": "",
"cognito-identity-id": "",
"cognito-identity-pool-id": "",
"http-method": "POST",
"stage": "prod",
"source-ip": "23.120.xx.xxx",
"user": "",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"user-arn": "",
"request-id": "f5ab9082-dc73-11e6-8ca5-15a998eb4e77",
"resource-id": "kmtrw2",
"resource-path": "/trace"

}
}