Oct 28, 2018

Angular - Best Practices

Using Immutability

Generally speaking, immutability is a good practice in JavaScript whether we are using Angular or not, so the recommendation to prefer immutability is a good recommendation in all JavaScript code. In general, do not mutate existing objects in memory, but rather create new objects. Using immutability can help you avoid certain classes of bugs, such as bugs that occur when a value is unexpectedly changed from somewhere else in the code. Using immutability can also help with certain types of change detection in Angular. Refer following for safe way of deep copying an object.
function cloneObject(obj) {
    var clone = {};
    for(var i in obj) {
        if(obj[i] != null &&  typeof(obj[i])=="object")
            clone[i] = cloneObject(obj[i]);
        else
            clone[i] = obj[i];
    }
    return clone;
}
let newObj = JSON.parse(JSON.stringify(obj));

copy via object assign

Following will do shallow copy, left most is target. value in right will override argument in left.
Object.assign({},employee,{name:'New Name'}, {age:10})

copy via spread

const copyObject = {...objtobecloned, {name:'New Name'}}
const copyArray = [...arrayToBeCopied, ]

map, filter, reduce, concat, spread mutate the array where as push, pop, reverse are immutable.

You can also use library like Immer.

Callback hell

When writing callback keep an eye on a number of curly braces as it gets difficult to manage if you have deeply nested callback. It's sometimes neat to put callback (if it's getting bigger) in a separate function.

Prefixing Component Selectors

Prefixing your component selectors will avoid conflicts if you happen to import a module that has a component selector that conflicts with one of your own.

Delegating Complex Logic to Services

Inside component, you mostly initialize form controls, add validators, redirect logic, event handler, etc, any business logic or complex processing should be in service. On the other hand, service should not have to deal with form controls objects.

Code Organization

Properties at the top followed by the constructor, followed by interface implementation, followed by the component public method and at the end private method. Implement Life Cycle Hook Interfaces like OnInit, OnChange.

Service Injector Best Practices


For every Angular app, Angular creates a root injector, which is responsible for injecting services wherever they're needed. If you provide a service in the eagerly loaded module, then angular register that with the root injector which makes it (singleton) available to the entire application. On the other hand, if you provide a service in a lazily-loaded feature module, Angular creates a new injector for that module and registers it there. So the instance of the service is only available to that lazily-loaded feature module. This behavior of creating a second instance is unique to lazily-loaded feature modules. Just remember that if you provide a service in a lazily-loaded module, it is only available to that module, and if you need a single instance of a service to be available everywhere, define it in your core module.

Ahead-of-time Compilation and tree shaking CLI

Use cli to build

Lazy Loading Feature Modules

Modules are not downloaded at the launch of the application rather only eagerly loaded module is downloaded. There are three type -
 Lazy Loading - Module is downloaded only when the user navigates to lazily loaded feature.
 Preloading - At the launch of application only eagerly loaded module is downloaded and hence user is severed quickly. Once downloaded and template appears, router checks for preloaded module and download them. This way
 application launch becomes fast as at that time user is downloading only eagerly loaded module and once user is served, angular downloads feature module, so its available for user when user try's to navigate to it.
 Custome Preloading - You can put custom rule to defined preloading behavior.

Monitoring Bundle Sizes


It's very important to keep an eye on the bundle size of all the chunks which gets created during build. You can use source-map-explorer to peek into your bundle to see whats taking most of the space. Ultimately user will be downloading these bundles and smaller the bundle size faster it would be to download
 ng build --prod --source-map

Improving Performance with OnPush Change Detection

Application state change can be caused by three things - Events (click, submit, ), XHR (http call), Timer (setTimeout, setInterval). These are the asynchronous operations which triggers change detection. So when change detection is triggered each of bindings will be evaluated, which can cause performance concern on a page which has lots of binding. So if you don't expect any of your binding to get impacted then you may add OnPush so that bindings are not re-evaluated on events, xhr or timer. To test add following <div>{{callMethod()}}</div> to your template and you will notice that callMethod will be called everytime an event is fired on the component or http call happens.

Pure and Impure Pipe Performance

A pure pipe is only called when Angular detects a change in the value or the parameters passed to a pipe. An impure pipe is called for every change detection cycle no matter whether the value or parameters changes. So in case of pure pipe, when you pass an array and one of the element of array changes, the pure pipe will not be called as the instance remain the same. So if you have sort custom pipe (pure) which takes an array, the pipe will not be executed if you update one of the element of the array

Oct 12, 2018

Angular - Router Guard

Angular router provides several types of guards. Guard is an angular injectable service which you register as a provider and use it when you configure a route. You also have an option to create it just like a function, but typically in production code, you will have a service. Following is the order in which guards are executed and if any guard returns false, all pending guards are canceled, and the requested navigation is canceled.
  • canDeactivate - The router first executes the canDeactivate guards for the current route to determine whether the user can leave that route.
  • canLoad - If a feature module is loaded asynchronously, the canLoad route guard is checked before the module is loaded; it won't even be downloaded unless the guard requirements are met. Unlike the canActivate, the canLoad method cannot access the ActivatedRouteSnapshot or RouterStateSnapshot because the module defining the route is not yet loaded.
  • canActivateChild - This is to guard activation to a child route to protect child route
  • canActivate - Guard to protect the route.
  • resolve - After all other route guards are checked, the resolvers are executed, so you resolve only when you have access to the route. This is typically used to fetches data before the component is activated. This way component doesn't have to show partial data or put special logic to work around that while data is being downloaded from the server.

The router extracts any route parameters from the URL and supplies them to the component through its ActivatedRoute service. It provides access to URL segments, route parameters, query parameters, route data and even access to the parent route. These are exposed as observables so you can subscribe which will notify of any parameter change. A controller onInit is only called once when a component is initialized, meaning route parameter change (navigating from app/1 to app/2 in cased of route like app/:id) will not call onInit, so to make sure you update your component based on id in the browser, you get hold of the ActivatedRoute and then subscribe to param change. On the other hand routeguard will be called every time, even when route parameter change and it will be passed with ActivatedRouteSnapshot, which has same properties as ActivatedRouty as plain values, while ActivatedRoute exposes them as observables.

Oct 5, 2018

Angular 2 - Show spinner using Router Resolvers and Event before activating route

The idea here is that we will create a route resolver and then we will subscribe to the router event and on NavigationStart event we will start the spinner and on NavigationEnd and other related events we will stop the spinner. This way new component is not activated until data is fetched to render that component, and until data is being fetched user will be displayed with the spinner.

Route resolver is a service which imports Resolve interface from ‘@angular/router’. Here you implement the resolve method which has two parameters - ActivatedRouteSnapshot and RouterStateSnapshot. This method returns observable of an object which you want to return. In your route configuration, you activate this by adding resolve. Through ActivatedRouteSnapshot, you can get hold of all route-related data for the route being activated, like parameters, query string, etc. Now at this place, you can call your service to interact with the server, before the new component is activated. This way you can handle any error which server may return as well your component is not partially displayed.

To implement spinner, in your application component (app's root component), subscribe to router event method and initialize some variable based on which you can show spinner on the page (using css you can place spinner at the center of the page)

 router.events.subscribe(
  (event: Event) => {
   if (event instanceof NavigationStart) {
     this.loading = true;
   } else if (
     event instanceof NavigationStart ||
     event instanceof NavigationEnd ||
     event instanceof NavigationCancel ||
     event instanceof NavigationError ) {
     this.loading = false;
   }
  });

Sep 28, 2018

Docker Bridge Network

Docker Bridge (user defined) network allows containers connected to the same bridge network to communicate with each other. This is single host networking, meaning it applies to containers running on the same Docker daemon host. Even if we create bridge network with same name on another host, we will have two distinct network and container on one host will not be able to talk to container on other host. For communication among containers running on different Docker daemon hosts, you can use an overlay network. 

When you start Docker, a default bridge network (also called bridge) is created automatically, and newly-started containers connect to it unless otherwise specified. Run following command to get all the networks 
docker network ls

You can create an user defined network with the following command and then create containers on that bridge network. The container will get IP from the subnet specified while creating bridge network
docker network create -d bridge --subnet 10.0.0.1/24 my-bridge
If you create any container on this bridge network, it will get IP from the subnet you specified above
docker run -dt --name c1 --network my-bridge alpine sleep 1d
docker run -dt --name c2 --network my-bridge alpine sleep 1d

In the above example I am creating two containers on my user defined network. Now run following command to inspect the network
docker network inspect my-bridge

Output of above command will show details of my-bridge, some of them are subnet ip, containers in the network and its ip.

Now since the two containers are running on the same user defined network, it will automatically exposes all ports to each other and no port to the outside work. This makes containerized applications to communicate with each other easily. So now try the following command, which will execute sh command on the container c1

docker exec -it c1 sh

Now from c1 you should be able to ping c2, try following
ping c2

So the user defined bridge provides automatic DNS resolution between the container, as in case above, we were able to ping c2 with its name without IP. Every docker engine has embedded DNS service, meaning anytime we create container with name flag, an entry for that container will get added to DNS server, then any other container on the same network can talk to it by its name. Every container gets a DNS resolver, not a full blown DNS server, just a small resolver that can trap and forward name based query. It listens on standard DNS port 53 at 127.0.0.11 on every container. The resolver intercepts all DNS requests from the container and it forwards them to a DNS server service running on the local Docker host. Then the DNS server on the Docker host either resolves the name or sends it off to the big wide world public DNS.

On the other hand if we want a container on bridge network to be accessible from outside that network (container from another host or network, client outside host ), you need to publish container service on a host port. In the following command we are publishing container's port 8091-8094 through host port 8091-8094

docker run -d --name couchbase -p 8091-8094:8091-8094 -p 11210:11210 couchbase

Jul 17, 2018

Introduction to docker

Docker is a way to simplify the process of building applications, shipping them, and then running them in different environments.

Image

Image is a file that's essentially a snapshot of a container. Images are created with the build command. 

docker build -t rraj/nodeexpress .

The above command will create a image using Dockerfile and tag that image as rraj/nodeexpress. When you build a new image, Docker does this for each instruction (RUN, COPY etc.) in your Dockerfile:
  • create a intermediate (temporary) container from the previous image layer (or the base FROM image for the first command.
  • run the Dockerfile instruction in the temporary "intermediate" container;
  • save the temporary container as a new image layer.
  • remove intermediate container
The final image layer is tagged with whatever you name the image. Once the image is built, you can view all the layers that make up the image with the docker history command.

docker history rraj/nodeexpress

The intermediate image will not show when you run docker images, but these are cached, so if you build it again it will use cache until it find new instruction after which it will create intermediate contain and follow the same step for subsequent instruction. Try this by changing one of the instruction.


Pull
Because image can become quite large, images are designed to be composed of layers of other images, allowing a minimal amount of data to be sent when transferring images over the network. Layers can be reused by images. Run docker pull node:6.14.3 and then run docker pull node:8.11.3, you will notice that some of the layer already exist and it will not pull them and it will show them as Already exists.  

Container

Image is like a blue print which isn't very useful of it own, so you use them to create running instance of container. Container are actually where the live application run. So image is a read only template with layering, for example you will have a layer specific to your linux (or windows) OS and then you will have layer for your application framework like asp.net core or nodejs and so on. Once you have an image you can build an isolated container. Image and file system they have is read only and can be shared across multiple containers, whereas container has thin read/write layer



Benefits of Using Docker

Build it once and run it anywhere

You develop an application using programming run-time (like nodejs, .net) on you dev box and then you add some dependencies to it like angularjs, newtonsoft, entityframework etc. The instruction on how to do this will differ depending on what OS you are using MacOS, Linux or Windows or may be even between different version of same OS. This raises a big complexity in developing application and sharing and deploying it to different environments. With docker you create a docker file which you  can think of it as a recipe for how to set up your application. You only need to define this file once and then build it. Once that Docker image is built, all you have to do is move it to another machine and run it.

Resource efficiency and density

Since docker does not require guest OS as compared to VM, you can run many more containers than VMs on a single server.

Effective isolation and resource sharing

By default, a container is relatively well isolated from other containers and its host machine. You can control how isolated a container’s network, storage, or other underlying subsystems are from other containers or from the host machine. Docker uses a technology called namespaces to provide the isolated workspace called the container. When you run a container, Docker creates a set of namespaces for that container. These namespaces provide a layer of isolation. Each aspect of a container runs in a separate namespace and its access is limited to that namespace.

Speed

Starting, creating, replicating or destroying containers is very fast. Run following command and you will have sql server instance. Also if you have image already on your m/c running a container will be in seconds
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=mysecurepwd' -p 1433:1433 -d microsoft/mssql-server-linux

Handy Command

List Images
docker images

Remove Image
docker rmi <few character of images id>

Launch docker container
docker run <image name>
Options
 -d  - detached mode 
 -name - name container
 --rm - automatically clean up container and remove file system when container exists
 -it  - For interactive processes like a shell (docker run -it ubuntu /bin/bash)
 -p hostport:containerport  - Expose container port to host post
 -e  - To set environment variable refer this for automatically set environment variable in Linux
 --memory=27m Max amount of memory a container can use
 --cpus=".1"  Specify how much of the available CPU resources a container can use.

Other container command
docker ps -a
docker ps -as #with container size
docker stop <container>
docker rm <container>
docker inspect <container>
docker container logs -f  <container> # follow documentation for more options
docker stats <container name>

Start a shell in a container
docker exec -it <containername> /bin/bash

Remove unused data
docker system prune -a

Common Collection Methods in Javascript and C#

Transform each element of collection into a new form and return new array 
javascript  
[1, 2, 3].map(x => x * 2);
c#
(new int[] {1, 2, 3}).Select(x => x * 2)

var students1 = new[] {
 new { Id = 1, FirstName = "John", LastName = "Singh", Addresss=new []{ new {City = "Boston" }, new { City = "Quincy" } } } ,
 new { Id = 2, FirstName = "Json", LastName = "Jha", Addresss=new []{ new {City = "Cambridge" } } }
 };
foreach ( var item in students1.SelectMany(y=>y.Addresss,(a,b)=> new { a, b} ) ) {
 Console.WriteLine($"{item.a.FirstName}-{item.b.City}");
}
Filters collection 
javascript
[1, 2, 3].filter(x => x > 2)
c#  
(new int[] {1, 2, 3}).Where(x=>x>1)
Accumulator function over a collection 
javascript  
[1, 2, 3].reduce((accumulate, currentValue, index) => accumulate + currentValue, 10)
c#
(new int[] {1, 2, 3}).Aggregate(10, (accumulate, currentValue) => accumulate + currentValue)
Determines whether a collection contains any elements which pass the test 
javascript
[1, 2, 3].some(x=>x>2) //true
[1, 2, 3].some(x=>x>3) //false 
c#
(new int[] {1, 2, 3}).Any(x=>x>2) 
Determines whether all elements of collection pass the test 
javascript
[1, 2, 3].every(x=>x>0) //true
[1, 2, 3].some(x=>x>1) //false 
c#   

(new int[] {1, 2, 3}).Any(x=>x>2) 
(new int[] {1, 2, 3}).All(x=>x>2)
Find first element of collection that pass the test 
javascript  
[1, 2, 3].find(x=>x>1) //2
[1, 2, 3].find(x=>x>7) //undefined
[1, 2, 3].findIndex(x=>x>0) //0
[1, 2, 3].findIndex(x=>x>7) //-1
c#  
(new int[] {1, 2, 3}).First(x=>x>1) //2
(new int[] {1, 2, 3}).First(x=>x > 7) //InvalidOperationException 
(new int[] {1, 2, 3}).FirstOrDefault(x=>x3) //0

(new int[] { 1, 2, 3 }).ToList().Find( x => x > 0 ) //0
(new int[] { 1, 2, 3 }).ToList().Find( x => x > 7 ) //0
(new int[] { 1, 2, 3 }).ToList().FindIndex( x => x > 7 ) // -1
Concatenates two Collections 
javascript
[1, 2, 3].concat([4, 5, 6])
[...[1, 2, 3],...[4, 5, 6]]
c#
(new int[] {1, 2, 3}).Concat(new int[] {4, 5, 6})
GroupBy 
javascript
[{name:'John', city:'Quincy'},{name:'Sam', city:'Boston'} ,{name:'Json', city:'Boston'}]
  .reduce((a,c,i)=>{
    let element = a.find(x=>x.key === c.city);
    element ? element.item.push({name:c.name}): a.push({key:c.city, item:[{name:c.name}]});
    return a;
  }, [])  
c#
var students = new[] { new { Id=1, FirstName = "John", LastName = "Singh" }, new { Id = 2, FirstName = "Json", LastName="Jha"} };
var address = new[] { new {StudentID =1, City = "Boston" }, new { StudentID = 1, City = "Quincy" }, new { StudentID = 2, City = "Quincy" } };
var query1 = students.
 Join( address, s => new { s.Id }, a => new { Id = a.StudentID }, ( s, a ) => { return new { Name = s.LastName + "," + s.FirstName, a.City }; } ).
 GroupBy( x => x.Name );
foreach ( var item in query1 ) {
 Console.WriteLine($"{item.Key}-{item.Count()}");
}
Sorting 
javascript  
console.log([{name:'John', age:42},{name:'Sam', age:25}].sort((x,y)=>x.age-y.age))
c#  
var a = new int[] { 1, 2, 3, 5 };
a.OrderBy(x=>x) //here x should implement ICampare
Slicing 
javascript
var number = [ 1, 2, 3];  
console.log(number.slice(0,2,))//1,2 (will not include end index), number object is not modified
console.log(number.splice(1,2,4)) //[2,3] starting from index 1 take out two and add 4 at the end  
console.log(number) //1,4

number = [ 1, 2, 3];  
console.log(number.shift());//1
console.log(number) //2,3
number = [ 1, 2, 3];  
console.log(number.pop());//3
console.log(number) //1,2

c#
var a = new int[] { 1, 2, 3, 5 };
a.Skip( 1 ).Take(2); //[2,3]
a.Take(1).Concat(a.Skip(3)) //[1,5]
a.Take(1).Concat(new int[]{4}).Concat(a.Skip(3)) //[1,4,5]
var b = new List<int>(){ 1, 2, 3, 5 };
b.RemoveAt(2);//remove 2nd item
b.Remove(5);//remove item with value as 5

Add New Item
javascript
[1,2,3].push(4)// add 2 to end
[1,2,3].upshift(0)//add 0 to starting

c#
stIndex(x=>x=
(new List<int>(){1,2,3,2,5}).Add(6) (new List<int>(){1,2,3,2,5}).Insert(0,0)
Index Of Item 
javascript
[1,2,3,1].indexOf(1,2)///eturn 3
c#
Array.IndexOf( [1,2,3,1], 1, 2 ) //return 3
(new List<int>(){1,2,3,2,5}).FindIndex(x=>x==2);
(new List<int>(){1,2,3,2,5}).FindLastIndex(x=>x==2);


String to Character Array 
javascript  
'this is string'.split('');
'this is string'.split('').join('');
c# 
"this is string".ToCharArray();
new String("this is string".ToCharArray());
String Split 
javascript  
'this is string'.split('is');
c# 
"this is string".Split(new char[]{'i', 't'}, StringSplitOptions.RemoveEmptyEntries);
"this is string".Split(new string[]{is, str},StringSplitOptions.RemoveEmptyEntries );
Substring 
javascript  
'abcdef'.substring('0,3');//abc start index and end index not include end index
c#
"abcd".Substring(1,2);bd//start index and length

Join Collection of String
javascript  
'this is string'.split(' ').join(',');
c# 
string.Join(",","this is string".Split(" "))
https://javascript.info/string