Friday, December 27, 2019

Python : SOLID Principles


SOLID principles:


  • S Single Responsibility - Should have single reason to change and should be related to its primary objective.
  • O Open Closed - add features by extension, not by modification
  • L Liskov Substitution
  • I Interface Segregation
  • D Dependecny Inversion

AntiPattern:
    God Object : Reverse of Single Responsibility ie., 1 class doing everything

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Single Responsibility : A class should have only one job
Example :
class User:
def __init__(self, name: str): self.name = name
def get_name(self) :pass
def save(self, user: User): pass

Problem: User class is taking responsibility of Saving as well .
Solution :
class User:
def __init__(self, name: str): self.name = name
def get_name(self): pass

class UserDB:
def save(self, user: User):pass
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Open Closed : Classes should be open for extension, not for modification.
Example :
class bottle:
def __init__(self, season, price):
self.season = season
self.price = price

def give_discount(self):
if self.season == 'normal': return self.price
if self.season == 'festival': return self.price * 0.1

Problem : Let’s imagine you have a store, and you give a discount of 20% to your favorite customers using this class:
When you decide to offer double the 20% discount to VIP customers. You may modify the class

Solution:
class bottle:
def __init__(self, season, price):
self.season = season
self.price = price
def give_discount(self):return self.price

class Festival_bottle_price(bottle):
def give_discount(self): return self.price * 0.1
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Liskov Substitution Principle:  A sub-class can assume the place of its super-class without errors.
Example :
class Bird():
def fly(self):pass

class Duck(Bird):
def fly(self):pass

class penguin(Bird):
def fly(self):pass

Problem : This breaks LSP.As penguin cannot fly hence this causes error
Solution :
class Bird():pass
class FlyingBirds(Bird) :
def fly(self):pass

class Duck ( FlyingBirds):pass
class Ostrich ( Bird): pass
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Interface Segregation:Make interfaces that are client specific Clients should not be forced to depend upon interfaces that they do not use
Example :
class Machine:
def print(self):raise NotImplementedError()
def call(self):raise NotImplementedError()

class Printer(Machine):
def print(self, document): pass

Problem : Printer object throws exception when Printer().call() is performed as it should not have been exposed in the first place.
Solution:
class Machine:
def perform_operation(self):raise NotImplementedError()

class Printer(Machine):
def perform_operation(self, document): pass
class call_phone(Machine):
def perform_operation(self, document): pass
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dependency Inversion  :A: High-level modules should not depend on low-level level modules. It should depend upon its abstraction.
Example :
class Http:
def __init__(self, xml_http_service: XMLHttpService):self.xml_http_service = xml_http_service

def get(self, url: str, options: dict):self.xml_http_service.request(url, 'GET')

def post(self, url, options: dict):self.xml_http_service.request(url, 'POST')

class XMLHttpService(XMLHttpRequestService):pass

Problem:Http =high-level component , XMLHttpService= low-level component.
The Http class should care less the type of Http service you are using

Solution:
class Connection:
def request(self, url: str, options: dict):
raise NotImplementedError

class Http:
def __init__(self, http_connection: Connection):
self.http_connection = http_connection

def get(self, url: str, options: dict):self.http_connection.request(url, 'GET')

def post(self, url, options: dict):self.http_connection.request(url, 'POST')

class NodeHttpService(Connection):def request(self, url: str, options:dict):pass

class MockHttpService(Connection):def request(self, url: str, options:dict):pass






Python : Interface Segregation

Python : Interface Segregation


class Printer:
    @abstractmethod    def print(self, document): pass
class Scanner:
    @abstractmethod    def scan(self, document): pass


class MyPrinter(Printer):
    def print(self, document):
        print(document)

class Photocopier(Printer, Scanner):
    def print(self, document):
        print(document)

    def scan(self, document):
        pass  # something meaningful

Python :open Closed principle



"""OCP - Open Closed PrincipleOpen for expansion but closed for modification 
Goal : Instead of modifing existing class , your are encouraged to create a new class to solve the problem
Summary : To select object from a list of objects based on the properties
Description :Assume you have a box containing objects .You job is to select an object based on the properties like size and color . Here number of objects , size and color can be of any number .You have to printTrue for object which satisfies all the properties mentioned using Open Closed Principle.
Solution:1. you can select an object by size or color .Eg: small2. You can select object by both size and color . Eg: small and red
Steps:1. Start by creating classes which selects an object based on 1 property2. If u have 2 property create 2 classes3. For combination create last class which takes above 2 class objects as input  
"""
from enum import Enum
class COLOR(Enum):
    black="BLACK"    white="WHITE"
class SIZE(Enum):
    big="BIG"    small="small"
class Product():
    def __init__(self,color,size):
        self.color=color
        self.size=size

class match():
    def test(self,obj1,obj2):
        pass
class color_match(match):
    def __init__(self,color):
        self.color=color

    def test(self,target):
        return self.color==target.color

class size_match(match):
    def __init__(self,size):
        self.size=size

    def test(self,target):
        return self.size==target.size

class And_operation():
    def __init__(self,match1,match2):
        self.match1=match1
        self.match2=match2

    def test(self,target):
        return self.match1.test(target) and self.match2.test(target)

pen=Product(COLOR.black.value, SIZE.small.value)
paper=Product(COLOR.white.value,SIZE.small.value)
book=Product(COLOR.white.value,SIZE.big.value)

Products=[pen,paper,book]
Color_match=color_match(COLOR.white.value)
Size_match=size_match(SIZE.small.value)

combination=And_operation(Color_match,Size_match)
for product in Products:
    print(combination.test(product))
Output :
False
True
False

Enum vs Named tuple in Python

Enum vs Named tuple

  1. enums are a way of aliasing values, 
  2. namedtuple is a way of encapsulating data by name. 
  3. The two are not really interchangeable, 
 Example :

from collections import namedtuple
from enum import Enum

class HairColor(Enum):
    blonde = 1
    brown = 2
    black = 3
    red = 4

Person = namedtuple('Person', ['name','age','hair_color'])
bert = Person('Bert', 5, HairColor.black)

 you can use enums as values in  namedtuple.


Python Setter and getter :

Python Setter and Getter :

Without Setter and getter , in the below example when the users first name or last name is changed individually his full name is not getting changed : 

Method 1 : Without Decorator

class  a():
   _value=0
    def __init__(self,value):
         self._value = value
    
    def get_value(self):
        return self._value
     
    def set_value(self, x):
        self._value = x


---------------------------------------------------------------------------------
Method 2  : With Decorator 
class a():
    _value=0
    def __init__(self,value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter       # should match the method name of @property
    def value(self, a):
        self._value = a


A=a("hi")
A.value=10
print(A.value)




Thursday, December 26, 2019

Python Refactor

Python Refactor :


Rules:

    General :
  1.         Follow PEP8 Standard
  2.         DRY - Dont Repeat Yourself ie., not more than 2 times
  3.         1 Function / method should perform only 1 thing
  4.         Use helper functions (small functions)
  5.         Simplicity (logic , naming etc )
    Functions/Method:
  1.         big functions are bad
  2.         group related methods / variables in a file
  3.         split or merge methods / functions using refactor feature in IDE
    Classes/Objects:
  1.         Hide/Expose logic using middeleman classes
  2.         Separate general and specific code in a class
  3.         objects should not talk to strangers
  4.         Use parent-child class whenever method/variables is repeated across different classes
    Others:
  1.         breaking 1 big expression in conditional statements into simple statments
  2.         Use named tuple to mini classes for data segregation
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Tools:

  1.     Linters (Quality Checker):             Pylint , PEP8 and McCabe
  2.     Formatters (Formatter):                 Autopep8
  3.     Style Checkers(recommendations):    pycodestyle , pydocstyle Eg: pycodestyle file.py
  4.     Pycharm(Refactor):                    In Editor > Rt ck >refactor

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Anti Patterns :    

    1. Too much code in a function/method
    2. Implementation of OOP / Not correct application of OOP /Too much OOP
    3. Duplicate Code
    4. Avoiding intertwine code
    5. Rename variables ie., do not use v1 ,v2 etc.,
    6. Avoid useless /non-operational code
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Design Patterns in OOP:

    1. If subclasses need not be modifiedby others , than instantion of child object inside parent class and make parent method static.
     2. Instead of having checks to returm certain value , you can create a null class which returns null /empty/relavent value and instantiate that instead.Instead of actual classs.
    3.Replace conditional with subclasses
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Law of Demeter

 the Law of Demeter for functions requires that a method m of an object O may only invoke the methods of the following kinds of objects:

    O itself
        public class ClassOne {
            public void method1() {method2();}
            public void method2() {}
        }


    m's parameters
        public class ClassOne {
            public void method1(ClassTwo classTwo) {
                classTwo.method2();
            }
        }
        class ClassTwo {
            public void method2() {   }
        }


    Any objects created/instantiated within m
        public class ClassOne {       
            public void method1() {
                ClassTwo classTwo = new ClassTwo();
                classTwo.method2();
            }
        }
        class ClassTwo {       
            public void method2() {  }
        }


    O's direct component objects
        public class ClassOne {
            private ClassTwo classTwo;   
            public void method1() {
                classTwo = new ClassTwo();
                classTwo.method2();
            }
        }
        class ClassTwo {
            public void method2() { }
        }

    A global variable, accessible by O, in the scope of m
        public class ClassOne {
            public void method1() {
                classTwo.STATIC_INSTANCE.method2();
            }
        }
        class ClassTwo {
            public static final ClassTwo STATIC_INSTANCE = ...;
            public void method2() { }
        }

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1. OOP is mainly used to organize your business logic while  
  2. AOP helps to organize your non-functional things like Auditing, Logging, Transaction Management , Security etc. This way you can decouple your business logic with non-fictional logic that makes code cleaner.







Monday, December 23, 2019

Installing lubuntu OS

Installing lubuntu


Pre-Req:
  • 4GB pen Drive
  • Linux OS 
Steps :
  1. Download lubuntu iso- https://lubuntu.net/
  2. Insert USB 
  3. if you are using Linux  than use - Gparted to format the device.
    1. If you dont than run - sudo apt-get install gparted # to install
  4. $df -hT #to show the filesystem and size
  5. notedown the device name eg:/dev/sdb1
  6. unmount the device $sudo umount /dev/sdb1
  7.  sudo dd bs=4M if=/path/lubuntu.iso of=/dev/sdb1 status=progress oflag=sync
  8. Start > System Tools >Software updater 
  9. Restart after update
  10.  Open Terminal 
  11. $sudo apt install python3-pip


Tuesday, October 1, 2019

GIT : Commands and Operation

 Commands and Operation



Remote Master-------------------------------------Remote branch
|                                                                         |
|                                                                         |
|                                                                         |
|                                                                         |
Local Master ---------------------------------------Local branch


Usual Operations :

  1. Usually project will be made available in Git
  2. User clones the repository into local (once you clone master you get all the branches in the repository)
  3. creates a story branch locally if not available / if available checkout that branch
  4. Works on development work  
  5. commits the Changes to local branch
  6. Pushes the changes to remote branch
  7. Then the code pushed code is merged to master in remote.

Scenario 1: Developer wants to use the new code his colleague merged recently to master.
  1. Saves current changes in his current branch
  2. Developer switches to local master
  3. Perform PULL request to update his local master with latest changes.
  4. checkout the story branch
  5. Merges the updated the master to local branch
Scenario 2: Developer completed his coding while merging his code to remote master , he faces merge conflicts.
  1. checkout master
  2. pull all the changes from remote master to local master
  3. checkout story branch
  4. perform merge 
  5. Solve all the conflicts 
    1. Git shows "AUTO CONFLICT merge xxxx"
    2. Files turn red (Eg :intelliJ)
    3. rt ck > Git > resolve conflicts
    4. click Merge button
    5. Window with 3 screens open : middle screen - Current code , left and right screen shows the code in local staging and code in master
    6. Make required selection
    7. Save
  6. Commit changes
  7. Push to story branch
  8. Raise PR (merge to master) 
Sample Code :
git checkout master
git pull
git checkout my_branch
git merge master
(now use above conflict resolution to solve the issue )

Clone-Remote Master into local:
Usually any user will either clone the remote repository into his computer or create a local master repository.
git clone git_ssh_link #clone from git
git init #new repository without cloning

Check status: 
git branch

Result:
*master

Create / Use already existing branch 
once user has cloned / create a local repository
git checkout - b branch_new #Create a new branch in local and switch
git  branch branch_new #Just create a new branch in local

Message display / status
git branch #display all branches
git branch -vv #display all branches with their upstream branch
git status #display status of project wrt git
git log

Change branch 
git checkout branch_new #switch branch

Commit changes to staging whenever developer has reached a checkpoint
git add file #add file to local staging
git commit -m "description" #commit added file in staging

Push changes to story branch in remote (cloud)
git add file #add file to local staging
git commit -m "description" #commit added file in staging
git push -u origin branch_new #Create new story branch in remote and put changes there

Update the current branch if new changes are available in remote

git pull origin branch_name #1st time only
git pull #get latest updates from remote branch whichever is made upstream else same branch which we are currenlty

Remove the file from local git
git rm -rf file_name #delete file from local git

Reset
git checkout file #reset changes of the current file
git reset #save and reset changes of all the files to last commit
git reset --hard #reset to last commit without commiting

Delete branch
git branch -D branch-name

To Create a upstream
git branch -u masterbranchname # from where u want to pull latest code


Example to create a new project locally and push it to remote :
  • git init
  • git add README.md
  • git commit -m "first commit"
  • git remote add origin git@github.xxx.com:username/scala_protobuf.git
  • git push -u origin master

…or push an existing repository from the command line

  • git remote add origin git@github.xxx.com:username/scala_protobuf.git
  • git push -u origin master

Git Remove File from Face of the earth (all history included)
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch path_to_file" HEAD
git push --all

Git delete remote branch
git push origin --delete branch_name


Wednesday, September 18, 2019

Linux / Mac : Get latest of chromeDriver

Linux / Mac : Get latest of chromeDriver



LINUX
currdir=$(pwd)/misc
latest_version=$(wget https://chromedriver.storage.googleapis.com/LATEST_RELEASE -O -) && wget https://chromedriver.storage.googleapis.com/${latest_version}/chromedriver_linux64.zip -P $currdir
unzip -q $(pwd)/misc/chromedriver_mac64.zip && /bin/rm $(pwd)/misc/chromedriver_linux64.zip


MAC
#mac make sure "wget" is installed
#brew install wget
currdir=$(pwd)/misc
latest_version=$(wget https://chromedriver.storage.googleapis.com/LATEST_RELEASE -O -) && wget https://chromedriver.storage.googleapis.com/${latest_version}/chromedriver_mac64.zip -P $currdir
unzip -q $(pwd)/misc/chromedriver_mac64.zip && /bin/rm $(pwd)/misc/chromedriver_mac64.zip

Tuesday, September 17, 2019

scala : Perform basic test using MOCK


Scala : Perform basic test using MOCK and scalatest


Note :
  1. If you already have scala installed in your system do not add in your scalaVersion := "2.13.0" build file.
  2. Always add code in the test folder to use mock and scalatest.

build.sbt (I already have scala in my PC hence did not add scalaversion)

name := "sbt_test" version := "0.1"
//scalaVersion := "2.13.1"

libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.0" libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test" libraryDependencies += "org.mockito" % "mockito-all" % "1.8.4" libraryDependencies += "org.scalamock" %% "scalamock" % "4.3.0" % "test" libraryDependencies += "org.testng" % "testng" % "6.10" 

 Under Project > src > test > scala > test1 > test_class.scala
package test1
import org.scalatest.{BeforeAndAfter, FunSpec, FunSuite}
import org.scalamock.scalatest.MockFactory

object test_class extends App with MockFactory{
 val x=mock[Point]
}

class Point(xc: Int, yc: Int) {
  var x: Int = xc
  var y: Int = yc

  def start(x:Int,y:Int): Unit ={
    println("start")
  }

  def move(dx: Int, dy: Int) {
    println("move")
  }

  def end(dx: Int) {
    println("end")
  }
}

Bazel : Debugging / JVM debugging using JDB for Scala - Bazel


Debugging / JVM debugging using JDB


Follow steps to perform debugging in Bazel / Any JVMs :

Steps :
1.cd path
2. Open new Terminal Window
3. bazel run build_name --java_debug
4. Open another Terminal Window
5. jdb -attach localhost:5005 -sourcepath ~/dev/remote/src/main/java/

Note :Breakpoint can only be set in Dev Code not on scalatest .

Eg:
#stop in Dev code
stop in dev_package.class_name.method

#stop at Dev Code
stop at dev_package.class_name:130

#Clear BreakPoint
clear dev_package.class_name:line_number
clear dev_package.class_name.method

Commands :
run
cont
step over
next
locals
print resultdf.show()


Ref : http://pages.cs.wisc.edu/~horwitz/jdb/jdb.html

Friday, September 13, 2019

Git : Setting up a clone project


Git Pre- Req

Computer Authentication :


Pre- Req:

Windows:

                         i.         Open https://git-scm.com/download/win
                       ii.         Install (Next > next >…)
                      iii.         Right click on select git bash option

Mac :

·       Open Terminal

Steps :


1.     Enter ssh-keygen -t rsa in your git bash prompt / terminal (type “yes” when asked and press enter key otherwise)
2.     Note down location of the file created or usually file gets created in below locations
3.     Open id_rsa.pub file
a.     For Windows :   C:\User_name\.ssh\id_rsa.pub or  C:\xxx_USER \.ssh\id_rsa.pub
b.     For Mac :          /Users/User_name/.ssh/id_rsa.pub

4.     Copy entire Contents
Eg :
ssh-rsa sadfasfldfllflamflamsflWWQEW;as
--------
--------
---------------------------------@in.xxx.com
5.    Create a new git hub account
6.     Goto Settings
7.     Click on SSH and GPG keys
8.     Click on New SSH Keys
9.     Paste the contents inside
10.  Click on Add button
11.  Create a new folder in your system with name git_test (any location)
12.  Navigate inside the folder
13.   
a.     For windows : Open git bash by right click
b.     For mac : use terminal to navigate inside the new folder using “cd command”

14.  In your terminal / git bash run command (copy link below from the git project online)
15.  Run command “cd” into the cloned folder