Wednesday, January 8, 2020

Using design patterns

What are Design Pattern

Design patterns provide standard approach to create class instances, organize classes and communicate among classes. Fully supported by object oriented programming languages. Functional programming languages are not fully supported.

Advantages of Design Patterns

1. Simplify the system architecture
2. Enhance the re-usability of components
3. Not depends on programming languages and world wide adoptions
4. Enhance system performances and communications


1. Factory method design pattern ( Not the abstract factory method )

Usage : When it found different implementation for a given method


Basically we define classes and methods in abstract level first. These  classes can be an interfaces or an abstract classes or a normal java class. Then we can implement or override abstract methods in implementation classes which are based on different implementations of abstract methods.


public abstract class Loan {

    private double loanAmount;
    public double getLoanAmount() {
        return loanAmount;
    }
    public void setLoanAmount(double loanAmount) {
        this.loanAmount = loanAmount;
    }

    public abstract void processLoan();
}



public class PersonalLoan extends Loan {

    @Override
    public void processLoan() {
        // Backend processing for personal loan
        setLoanAmount(50);
    }

}

public class HousingLoan extends Loan {

    @Override
    public void processLoan() {
        // Backend processing for housing loan   
        setLoanAmount(100);
    }

}


public abstract class BaseLoanFactory {

    public abstract Loan placeLoanFactory(String loanType);

}


public class LoanFactory extends BaseLoanFactory {

    @Override
    public Loan placeLoanFactory(String loanType) {
        Loan loan=null;
        if (loanType != null && loanType.equalsIgnoreCase("personal loan")) {
            loan = new PersonalLoan();
        } else if (loanType != null && loanType.equalsIgnoreCase("housing loan")) {
            loan = new HousingLoan();           
        }
        loan.processLoan();
        return loan;
    }


}


public class Main {

    public static void main(String[] args) {

       LoanFactory lf = new LoanFactory();
        double pLoanAmount = lf.placeLoanFactory("personal loan").getLoanAmount();
        double hLoanAmount = lf.placeLoanFactory("housing loan").getLoanAmount();
       System.out.println("pLoanAmount->" + pLoanAmount + "|hLoanAmount->" + hLoanAmount);

    }

}


OUTPUT

pLoanAmount=50.0|hLoanAmount=100.0


Ex in JDK : valueOf() of Integer, Float, Boolean and etc..
Ex in Spring : Can use Autowired and Qualifier annotations

@Autowired @Qualifier("personalLoan")
private Loan loan;


2. Abstract factory method

Usage : When it required to create instances of different classes without mentioning class names. It provides factory of classes. It is an another layer of abstraction to abstract method pattern.



public interface Bank {

    public String doBankProcess();
}

public class BankA implements Bank{

    @Override
    public String doBankProcess() {
        return "Bank-A-DONE";
    }

}

public class BankB implements Bank{

    @Override
    public String doBankProcess() {
        return "Bank-B-DONE";
    }

}

public abstract class Loan {

    public abstract String processLoan();
}


public class PersonalLoan extends Loan {

    @Override
    public String processLoan() {
        return "personal loan processed";
    }

}


public class HouseLoan extends Loan {

    @Override
    public String processLoan() {
        return "house loan processed";  
    }

}


 public abstract class AbstractFinanceFactory {

    public abstract Loan getLoan(String loanType);

    public abstract Bank getBank(String bankName);
}


public class BankFactory extends AbstractFinanceFactory {

    @Override
    public Loan getLoan(String loanType) {
        Loan loan = null;
        if (loanType != null && loanType.equalsIgnoreCase("personal")) {
            loan = new PersonalLoan();
        }
        if (loanType != null && loanType.equalsIgnoreCase("housing")) {
            loan = new HouseLoan();
        }
        loan.processLoan();
        return loan;
    }

    @Override
    public Bank getBank(String bankName) {
        Bank bank = null;
        if (bankName != null && bankName.equalsIgnoreCase("BankA")) {
            bank = new BankA();
        }
        if (bankName != null && bankName.equalsIgnoreCase("BankB")) {
            bank = new BankB();
        }
        bank.doBankProcess();
        return bank;
    }

}



 public class Main {

    public static void main(String[] args) {
        BankFactory bf = new BankFactory();
        String bankStatus = bf.getBank("BankA").doBankProcess();
        String loanStatus = bf.getLoan("housing").processLoan();
          System.out.println("bankStatus->"+bankStatus+"|loanStatus="+loanStatus);
    }

}


OUTPUT

bankStatus->Bank-A-DONE|loanStatus=house loan processed



2. Singleton Pattern

This pattern restricts creating new instances and it will return same instance again and again. Ensures one instance of a particular class per class loader. Restriction of creating a new object can be done by private constructor in the class. The instance will be created and assigned to a static variable. 



public class Singleton {
    private static Singleton singletonObj = null;

    private Singleton() {

    }

    public static Singleton readInstance() {
        if (singletonObj == null) {
            singletonObj = new Singleton();
        }
        return singletonObj;
    }
}

public class Main {

    public static void main(String[] args) {
        Singleton obj1 =Singleton.readInstance();
    }

}


Improved version of singleton pattern to avoid instantiation by two parallel threads at once


public class Singleton {
    private static Singleton singletonObj = null;

    private Singleton() {

    }

    public static Singleton readInstance() {
        if (singletonObj == null) {
            synchronized (Singleton.class) {
                if (singletonObj == null) {
                    singletonObj = new Singleton();
                }
            }

        }
        return singletonObj;
    }
}

Ex : In spring use @Scope("singleton") , this will create single instance in spring container.















Friday, January 3, 2020

Containerizing your apps 1 - Pros and Cons of Containerization against Virtualization and Monolithic Model



Pros
Cons
Example
Containerization
Platform independence. Containers will grab all dependencies at the creation time. No need to set up dependencies in the staging or production environment.

Avoid multiple deployments runs on a single server that makes bottlenecks. Best way to avoid monolithic applications


Containers will start very quickly and can be shut down very quickly

Can deploy multiple containers on the given operating system. Each container has a very low CPU and memory usages. The same user space of the operating system can be shared by multiple containers.


Can deploy services as highly scalable lightweight services with the support of Container orchestrations.

Reduce infrastructure costs and operational simplicity. Can upgrade services without affecting rest of services

Container echo-system is complicated

Centralized log mechanism  and service monitoring mechanism required

Data persistence among multiple schemas

Separate deployment required for each container

Not suitable for simple and non-complicated application
Docker

Kubernetes

AWS Fargate

AWS Kubernetes

Google 
Kubernetes

and etc...

Server
Virtualization
Can test the software under different Operating Systems

Dedicated hardware resource can be arranged
Required high disk spaces to install virtual machines

Takes time to start and shutdown

High CPU and memory usage

High infrastructure setup and maintenance cost

High cost on system backups
Set of virtual machines in one physical server.
Monolithic Model
Simple deployments

Simplifies loggers, security implementations and data persistence


Performance issues as multiple services deployed in a single server

Not suitable for multi tire complicated applications

Tightly coupled and not easy to maintain

Multiple war files deployed in single tomcat server which are interdependent

Wednesday, January 1, 2020

GIT in command lines

Cloning Master and check available branches

First download the repository and then list branches


Step 1 :   Run bellow command to set console configurations and change your directory to download location
               Command : git config --global user.email "you@example.com"
               Command : git config --global user.name "Your Name"
               Command : cd ~/Desktop

Step 2 : Enter git command. Make sure to put .git at the end of your repository
           
              Command : git clone https://your-git-server/your-project/testrepository.git

              Output : Cloning into 'testrepository'...

Step 3 : Enter username and password of your git account

Step 4 : Check console output

remote: Enumerating objects: 273, done.
remote: Counting objects: 100% (273/273), done.
remote: Compressing objects: 100% (120/120), done.
remote: Total 273 (delta 79), reused 233 (delta 60)
Receiving objects: 100% (273/273), 89.99 KiB | 415.00 KiB/s, done.
Resolving deltas: 100% (79/79), done.

Step 5 : Check the download directory

Step 6 : Change your directory to downloaded repository location
               Command : cd testrepository

Step 7 : List branches
               Command : git branch -al

Step 8 : Check output for if branches are available

* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/testrepository

           

Updating Master Branch

 Step 1:  Run bellow command to set console configurations and change directory to the downloaded directory
               Command : git config --global user.email "you@example.com"
               Command : git config --global user.name "Your Name"
               Command : cd ~/Desktop/testrepository

 Step 2 : Change some file contents, add or delete files.

 Step 3:  Update changes by bellow command.
                Command git add .

 Step 4:  Commit the code with proper comment.
                Command : git commit -m "Updated properties"

 Step 5:  Check console output
                [master 5ca1aa2] Updated properties
                1 file changed, 1 deletion(-)

 Step 6: Push changes to remote repository
               Command : git push -u origin

 Step 7: Enter username and password and check console output

Username :
Password :
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 322 bytes | 322.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://your-git-server/your-project/testrepository.git
   371609a..5ca1aa2  master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.


Cloning a branch


 Step 1:  Run bellow command to set console configurations and change directory to the downloaded directory
             Command :  git config --global user.email "you@example.com"
             Command : git config --global user.name "Your Name"
             Command : cd ~/Desktop

Step 2 : Clone the branch
             Command : git clone -b 

             Example     : git clone -b testbarnchname https://your-git-server/your-project/testrepository.git

Step 3: Enter username and password of your git repository

Cloning into 'testbranch'...
Username :
Password  :

Step 4: Check output


remote: Enumerating objects: 290, done.
remote: Counting objects: 100% (290/290), done.
remote: Compressing objects: 100% (125/125), done.
remote: Total 290 (delta 71), reused 227 (delta 53)
Receiving objects: 100% (290/290), 87.84 KiB | 1022.00 KiB/s, done.
Resolving deltas: 100% (71/71), done.



Updating a branch


 Step 1:  Run bellow command to set console configurations and change directory to the downloaded directory
               Command : git config --global user.email "you@example.com"
               Command : git config --global user.name "Your Name"
               Command : cd ~/Desktop/testbranch

 Step 2 : Change some file contents, add or delete files.

 Step 3:  Update changes by bellow command.
                Command git add .

 Step 4:  Commit the code with proper comment.
                Command : git commit -m "Updated properties"

 Step 5:  Check console output
                [master 5ca1aa2] Updated properties
                1 file changed, 1 deletion(-)

 Step 6: Push changes to remote repository
               Command : git push -u origin testbarnchname

 Step 7: Enter username and password and check console output

Username :
Password :

Step 8 : Check console output

Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 319 bytes | 319.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote:
remote: To create a merge request for testbranch, visit:
remote:
To https://your-git-server/your-project/testrepository.git
   1524205..cd1eb7b  testbranch -> testbranch
Branch 'testbranch' set up to track remote branch 'testbranch' from 'origin'.