Monday, May 25, 2020

Design Pattern - Design and Implement Snake and Ladders Game

Design and Implement Snake and Ladders Game 

I will write the code and tell you the thought process of how one should proceed in Design and implement the code. Snake and Ladder show how various objects like a game board, snack, ladders, etc come together to produce a program. Snack and ladder game is a very famous interview question to check your design pattern concept. I think we all know about the Snack and Ladder Game how we play it So I will jump to design pattern.

In the Snake and Ladder game, there are some objects that will need to be created like below:
  • GameBoard
  • PlayerPiece
  • BoardSquare
  • Snake
  • Ladder
  • Die
And one more thing we need an object of the game itself. the main design decisions we have to take based on their responsibilities of Objects.

So Die should be rolled this is the Die object responsibility. What about BoardSquare or even the Game itself? So we could keep track of which piece is on which square using the BoardSquare or even the game itself. What about PlayerPiece?It should have a useful role in the application like it will be responsible for knowing which BoardSquare it currently occupies. There is an association between PlayerPiece and BoardSquare.

This is just one way of designing the solution. Just give a thought about the Snake and Ladder classes?
Why because they are very similar in fact could be modeled as a single class that links two squares together whether they take the player up or down on the board does not really make any difference to the implementation but we will keep them apart.

What do we do about the relationship between the Snack and ladders and the BoardSquares?
A BoardSquare needs to know if it contains the head of a snake or the foot of ladder though it does not need to know if it has the tail of a snake or the head of a ladder because these do not cause the PlyerPiece to move again. We cannot have both a snake and a ladder on any one square.

The main logic:

Finally, the SnakeAndLadders class acts as the program entry point and creates the GameBoard and the PlyerPieces. it has the main method that creates an instance of the class and triggers the play method. This handles the main game loop that iterates until the game is over.

Implementation :

So the Snake and Ladder objects need to be positioned on the board so they can be referenced by the BoardSquare that they are placed on and reference the other BoardSquare that they point to. Now to set a position of a Snake, a parameterized constructor is provided that takes the head of and tail positions as parameters.


Snake(BoardSquare head, BoardSquare tail){
 setTail(tail);
head.addSnake(this);
}

Similarly the Ladder constructor stores the top of the ladder and passes itself back to the BoardSquare that contains its foot.

Ladder(BoardSquare top, BoardSquare foot)
{
   setTop(top);
   foot.addLadder(this)
}

in both the case we omit the public prefix because the class itself is not public.

class Snake
{
  private BoardSquare tail;
  Snake(BoardSquare head,BoardSquare tail)  
  {
    setTail(top);
head.addSnake(this);
  }
  private void setTail(BoardSquare tail)
  {
    this.tail=tail;
  }
  private BoardSquare getTail()
  {
    return tail;
  }
  
  void movePlayerPiece(PlayerPiece counter)
  {
    System.out.println("Down the Snake to " + getTail().getPosition());
counter.setCurrentPostion(getTail());
  }
}

class Ladder
{
  private BoardSquare top;
  Ladder(BoardSquare top,BoardSquare foot)  
  {
    setTail(top);
head.addLadder(this);
  }
  private void setTop(BoardSquare top)
  {
    this.top=top;
  }
  private BoardSquare getTop()
  {
    return top;
  }
  void movePlayerPiece(PlayerPiece counter)
  {
    System.out.println("Up the Ladder to " + getTop().getPosition());
counter.setCurrentPostion(getTop());
  }
}

class PlayerPiece
{
 private BoardSquare currentPosition; 
 private String color;
 PlayerPiece(String color)
 {
   setColor(color);
 }
  private void setColor(String color)
  {
    this.color=color;
  }
  String getColor()()
  {
    return color;
  }
  BoardSquare getCurrentPosition()
  {
    return currentPosition;
  }
  void setCurrentPostion(BoardSquare newPosition)
  {
   currentPosition = newPosition
  }
}

class BoardSquare
{
 private Snake aSnake = null;
 private Ladder aLadder = null;
 private int position;
 BoardSquare(int position)
 {
   setPosition(position);
 }
 int getPosition()
 {
   return position;
 }
 private void setPosition(int position)
 {
  this.position = position;
 }
 void addSnake(Snake s)
 {
   aSnake = s
 }
 public void addLadder(Ladder l)
 {
  aLadder = l;
 }
 private boolean hasSnake()
 {
  return null!=aSnake;
 }
 private boolean hasLadder()
 {
   return null!=aLadder;
 }
 
 public void movePlayerPiece(PlayerPiece counter)
  {
counter.setCurrentPostion(this);
if(hasSnake())
{
  aSnake.movePlayerPiece(counter);
}
if(hasLadder())
{
  aLadder.movePlayerPiece(counter);
}
  }
}



private BoardSquare[] squares;
private Die die;
static final int MAX_SQUARES = 100;
class Gameboard
{
  static final int START_SQUARE =1;
  Gameboard()
  {
    die = new Die();
squares = new BoardSquare[START_SQUARE + MAX_SQUARES];
for(int i=START_SQUARE;i<=MAX_SQUARES;i++)
{
  squares[i]=new BoardSquare[i];
}
  }
  
  // add the Ladders
  new Ladder(squares[38],squares[1]);
  new Ladder(squares[14],squares[4]);
  new Ladder(squares[31],squares[9]);
  new Ladder(squares[42],squares[21]);
  new Ladder(squares[84],squares[28]);
  new Ladder(squares[44],squares[36]);
  new Ladder(squares[67],squares[51]);
  new Ladder(squares[91],squares[71]);
  new Ladder(squares[100],squares[80]);
  
  //add the Snakes
  
  new Snake(squares[16],squares[6]);
  new Snake(squares[47],squares[26]);
  new Snake(squares[49],squares[11]);
  new Snake(squares[56],squares[53]);
  new Snake(squares[62],squares[19]);
  new Snake(squares[64],squares[60]);
  new Snake(squares[87],squares[24]);
  new Snake(squares[93],squares[73]);
  new Snake(squares[95],squares[75]);
  new Snake(squares[98],squares[78]);
  
  // constructor creates the square and adds the 
  
  BoardSquare getStartSquare()
  {
    return square[START_SQUARE];
  }
  
  public void movePlayerPiece(PlayerPiece counter)
  {
BoardSquare current = counter.getCurrentPosition();
int nextPosition = current.getPosition() + die.getRoll();
if(nextPosition > MAX_SQUARES)
{
  System.out.println("you need to land  exactly on the last suquare to win!");
}
else
{
  counter.moveTo(squares[nextPosition]);
}
System.out.println(counter.getColor + "counter on " + counter.getCurrentPosition().getPosition());
  }
}

public class SnakesAndladders
{
  private Gameboard board;
  public SnakesAndladders()
  {
    board = new Gameboard();
  }
  public void play()
  {
    PlayerPiece counter = new PlayerPiece("RED")
counter.setCurrentPostion(board.getStartSquare());
while(counter.getCurrentPosition(),getPosition() < Gameboard.MAX_SQUARES)
{
  board.movePlayerPiece(counter)
}
System.out.println(counter.getColor + "counter finished on  " + counter.getCurrentPosition().getPosition());
  }
  public static void main(String[] args)
  {
     SnakesAndladders myGame = new SnakesAndladders();
myGame.play()
  }
}


Output : 

up the ladder tp 14
RED counter on 14
RED counter on 15
...........................
.............................
.............................
RED counter on 100
RED counter finished on 100








Peeling Concept of Dynamic Programming , Data-Structures and Algorithm

Peeling Concept of Dynamic Programming Data-Structures and Algorithm

Dynamic Programming(DP): Dp is a very simple technique but at the same time very difficult to master. The problem is how to identify and solve DP problems.

Another thing just keep in mind that DP and memorization(Means maintaining a table of subproblems already solved) work together. So what is the main difference between the 
Divide and Conquer and DP? Divide-Conquer,subproblems are independent whereas in DP the overlap of subproblems occur. This is the main difference.

So now why memoization? because it reduces the exponential complexity to polynomial complexity O(n2), O(n3) for many subproblems.

The major components of DP :

a)Recursion: Solves subproblems recursively.
b)Memorization: Stores already computed values in the table

Dynamic Programming = Recursion + Memorization

So how to identify that this problem will be solved by DP. Keep in mind.
a)Optimal substructure - So an optimal solution to a problem contains the given subproblems.
b)Overlapping subproblems- a recursive solution of subproblems.

So another question can we solve every problem using Dynamic programming?
The answer is no like greedy and divide and conquer not able to solve everything it is that same way. You have to understand one thing the difference between the DP and straightforward recursion is in the memorization of recursive calls.

If subproblems are independent and there is no repetition then memorization does not help so DP is not a solution to such problems.

Dynamic Programming Approaches

to solve any DP problem we have two approaches

1)Bottom-up dynamic programming
2)Top-down dynamic programming


Bottom-up Dynamic Programming : 

So here we start with smallest possible input argument value and then slowly increase input argument value and while doing this we store values in a table(memory).

Top-down Dynamic Programming:

So here we broke the problem in subproblems and these subproblems are solved and the solutions remembered in case they need to be solved. Also we save each computed value as a final action of a recursive function and at the same, we also check if pre-computed values exist.

Algorithms of Dynamic Programming : 

These are a few algorithms of DP.

1)String Algorithms include the longest common subsequence, longest increasing subsequence, longest common substring, edit distance.

2)Bellman-Ford Algorithm, Floyd's All pair shortest path algorithm.

3)Chain Matrix multiplication

4)Subset Sum

5)0/1 Knapsack

6)Travelling salesman problem 

Let's understand the Dynamic Programming in more depth:

Fibonacci Series(Current number is the sum of two previous number).Remember it.

Fib(n) = 0      for n =0
Fib(1) = 1      for n=1
           =  Fib(n-1) + Fib(n-2) ........ for n  > 1

So now think of its recursive solution which is very simple.

int RecursiveFibonacci(int n)
{
   if(n==0) return 0;
   if(n==1) return 1;

   return RecursiveFibonacci(n-1) + RecursiveFibonacci(n-2);
}

Above we discuss about Memorization So how Memorization helps here?
Ans: It helps like it produces a call tree that calls the function on the same value many times.

Fib(5) 
Fib(4) + Fib(3)
(Fib(3) + Fib(2))  + (Fib(2) + Fib(1))
...............

(((Fib(1) + Fib(0)) + Fib(1)) + (Fib(1) + Fib(0) + Fib(0))) + Fib(0) + Fib(1))

So here Fib(2) was calculated 3 times(overlapping of subproblems) this leads to an exponential time. Instead of solving the same subproblems again and again just keep track of it store the previously calculated values then it reduces the complexity. 

Bottom-up Approach:

int fib[n];
int fib(int n)
{
   if(n==0 || n==1)
   retun 1
   
   fib[0] =1;
   fib[1] =1;
   for(int i =2 ; i<n; i++)
   {
     fib[i] = fib[i -1] + fib[i-2]
   }
   
   return fib[n -1]
}

Top-down Approach :

int fib[n];
int fibonacci(int n)
{
   if(n==1) retun 1;
   if(n==2) retun 1;
   if(fib[n]!=0)
    {
  return fib[n];
}  
   return fib[n] = fibonacci(n -1) + fibonacci(n -2);
}

So both of them reduces the problem of complexity to O(n) this is because if a value is already computed then we are not calling the subproblems again. We are directly taking it from
table.

Time Complexity O(n) 
Space Complexity: O(n) for table.

We can further improve the space complexity by O(1)

So the question is How?
Ans: So just think about Fibonacci series is basically the current value is the sum of two previous calculations only. So we do not have to store all the previous values right? we just have two store last two values we can calculate the current value. 


















Sunday, May 24, 2020

Send Email in Python Example

Email Send in Python :

So for this first, you have to install the flask-mail library. make sure you are in the same virtual environment.use the following command to install the same.

(venv)$ pip install Flask-Mail

Once installed you have to initiate and configure flask mail.


Code :

cuurent_appp.config - this is just a configuration.

MAIL_DEFAULT_SENDER = 'your_email_address'
MAIL_SERVER = 'email_providers_smtp_address'
MAIL_PORT='mail_server_port'
MAIL_USERNAME='your username'
MAIL_PASSWORD='your password'
MAIL_USE_TLS=False
MAIL_USE_SSL=True


from flask_mail import Message,Mail
mail = Mail()

 for the initiate, it just calls below
 
mail.init(app) 

def send_email(to,subject,template):
    msg = Message(
       subject,
   receipts=[to],
   html=template,
   sender=cuurent_app.config['MAIL_DEFAULT_SENDER']
                   )
   mail.send(msg)
 
Use the above code to send the email. Thanks!



Building REST APIs with FLASK Python Web Services- CRUD Application with User Authentication

User Authentication 

So once we have all our routes in place and we need to add in user authentication to ame sure only logged-in users can access certain routes. So now we will add in user login
and signup routes but before we need to add schema.

Create users.py:

In schema add two static methods to encrypt the password and verify password and for the same we will need a python library called "passlib".

just install this library by using the below command.

(venv)$ pip install passlib

Let's write the required code.

from api.database import db
from passlib.hash import pbkdf2_sha256 as sha256
from marshmallow_sqlalchemy import ModelSchema
from marshmallow import fields

class User(db.Model):
     _tablename_ = 'users'
 
  id = db.Column(db.Integer,primary_key=True)
  username = db.Column(db.String(120),unique = True,nullable = False) 
  password= db.Column(db.String(120),nullable=False)
  
   
def create(self):
        db.session.add(self)
db.session.commit()
return self
    @classmethod
def find_by_username(cls,username):
    return cls.query.filter_by(username=username).first()
@staticmethod
    def generate_hash(password):
    return sha256.hash(password)
@staticmethod
    def verify_hash(password,hash):
    return sha256.verify(password,hash)
class UserSchema(ModelSchema):
     class Meta(ModelSchema.Meta):
       model = User
   sqla_session = db.session
id = fields.Number(dump_only=True)    
username = fields.String(required=True)
 
Next create users.py in routes directory and we will add user login and signup routes.

For user authentication across the application we will use JWT(JSON WEB TOKENS) authentication. In a flask, there is an opensource extension called Flask-JWT-Extended which
provides JWT support and other helpful methods.

Now install flask-JWT-Extended by using the following command.
(venv)$ pip install flask-JWT-Extended

@user_routes.route('/',methods=['POST'])
def create_user():
    try: 
    data = request.get_json()
data['password'] = User.generate_hash(data['password'])
user_schema = UserSchema()
user,error = user_schema.load(data)
result = user_schema.dump(user.create()).data
return response_with(resp.SUCCESS_201)
except Eception as e:
        print e
        return response_with(resp.INVALID_INPUT_422)
Now we will add a method for the signed-up users to login.

@user_routes.route('/login',methods=['POST'])
def authenticate_user():
    try: 
    data = request.get_json()
current_user = User.find_by_username(data['username'])
if not current_user:
     return response_with(resp.SERVER_ERROR_404)
 
if User.verify_hash(data['password'],current_user.password):
     access_token = create_access_token(identity=data['user_name'])
return response_with(resp.SUCCESS_201,value={'message':'Logged in as {}.format(current_user.username)'})
else:

             return response_with(resp.UNAUTHORIZED_401)
except Exception as e:
      print e
      return response_with(resp.INVALID_INPUT_422)   
  
The following code will take the username and password as input and verifies it. We have created a successful REST application with user authentication.









Building REST APIs with FLASK Python Web Services- CRUD Application with FLASK Part-2


So this part will contain the other methods which I mentioned in the first 1st part.let's see GET author endpoint.

@author_routes.route('/',methods=['GET'])
def get_author_list():
    fetched = Author.query.all()
author_schema=AuthorSchema(many=True,only=['first_name','last_name','id'])
authors,error=author_schema.load(fetched)
result=author_schema.dump(fetched)
return response_with(resp.SUCCESS_200,value={"authors": authors})
 
This will GET all authors route and here we will respond with an array of authors only containing their ID, First Name, and Last Name.

So just hit the URL with POSTMAN.

https://localhost:5000/api/authors/


Now lets add another GET route to fetch a specified author using their ID and add the follwiiong code to it add the route:

@author_routes.route('/<int:author_id>',methods=['GET'])
def get_author_detail():
    fetched = Author.query.get_or_404(author_id)
author_schema=AuthorSchema()
author,error=author_schema.load(fetched)
result=author_schema.dump(fetched)
return response_with(resp.SUCCESS_200,value={"author": author})
 
So hit the URL with POSTMAN like 
https://localhost:5000/api/authors/1

Before we move on to creating PUT and DELETE endpoints for author object. let's initiate book routes. Create books.py in the same folder and add the following code to initiate the route.

from flask import Blueprint
from flask import request
from api.responses import response_with
from api import responses as resp
from api.models.authors import Author ,AuthorSchema
from api.databases import db

author_routes = Blueprint("author_routes",_name_)

from api.routes.books import book_routes
app.register_blueprint(book_routes,url_prefix='/api/books')

now to create book use below methods:

@book_routes.route('/',methods=[POST])
def create_book():
    try: 
    data = request.get_json()
book_schema = BookSchema()
book,error = book_schema.load(data)
result = book_schema.dump(book.create()).data
return response_with(resp.SUCCESS_201,value={"book":result})
except Eception as e:
        print e
        return response_with(resp.INVALID_INPUT_422)

To test the method hit the URL with POSTMAN
http://localhost:5000/api/books/

Ans also use below JSON formate to hit.

{
  "title":"Android Book",
  "year":2007,
  "author_id":1
}

So this way you will able to create all the methods that I mentioned in the 1st part. Let me know if any problems.
 

Saturday, May 23, 2020

Building REST APIs with FLASK Python Web Services- CRUD Application with FLASK Part-1


CRUD Application with FLASK

So in my last blog, I told you how to write SQL based applications.here I will tell you the RESTful Flask application from scratch. Here I will maintain a database of
Author objects and it will also have the user authentication mechanism to only allow logged-in users to use certain functions.

I will create the following endpoints for our REST applications:

1) GET/authors: get lists of books
2)GET/authors/<id>: This gets author with the certain ID .
3)POST/authors: This creates a new author object.
4)PUT/authors/<id>: This will edit autor object with the given ID.
5)DELETE/authors/<id>: This will delete the author with given ID.
6)GET/books : this will return all the books.
7)GET/books/<id>: this gets the book with specified ID.
8)POST/books: This creates a new book object.
9)PUT/books/<id>: This will edit book object with specified ID.
10)DELETE/book/<id>: This will delete the book with given ID.

Now let's create it. Create a new project and name it author-manager.
So create new virtual environment.
$ mkdir author-manager && cd author-manger
$ virtualenv venv

Now install the following dependencies.
(venv) $ pip install flask flask-sqlalchemy marshmallow-sqlalchemy

Just an info FLASK uses concept of blueprints to make application components and support common patterns across the application. The blueprint helps create smaller modules for
larger application and simplifies how large application works.

So we will structure the application small modules and keep all our application code in the /src folder inside our app folder.
Now we will create an src folder inside our current directory and then create run.py files inside it.

(venv) $ mkdir src && cd src

We will initiate our FLASK app in main.py file inside the src and then create another file run.py which will import main.py, config file, and run the application.

main.py : 

import os
from flask import Flask
from flask import jsonify

app = Flask(_name_)

if os.environ.get('WORK_ENV') == 'PROD'
     app_config = ProductionConfig
 
elif os.environ.get('WORK_ENV') == 'TEST'  
     app_config = TestingConfig

else: 

     app_config = DevelopmentConfig

app.config.from_object(app_config)  

if _name_ == "_main_":
   app.run(port=5000,host="0.0.0.0",use_reloader=False) 
   
This is how our main.py will look like and next we will create our run.py to call app and run the application.

run.py:

from main import app as application

if _name_ == "_main_":

   application.run()
   
   
Here we defined the config, improve create_app, and initialized the application. Now we will create another directory/API inside src and export config, models, and routes from API directory.
so now create a directory inside src called API and then create another directory called config inside API.

config.py:

class Config(object):
      DEBUG = False
  TESTING = False
  SQLALCHEMY_TRACK_MODIFICATIONS = False
  
class ProductionConfig(Config):
  
  SQLALCHEMY_DATABASE_URI = <Production DB URL>
  
class DevelopmentConfig(Config):
      DEBUG = True
  SQLALCHEMY_DATABASE_URI = <Development DB URL>
  SQLALCHEMY_ECHO = False
  

class TestingConfig(Config):
      DEBUG = True
  SQLALCHEMY_DATABASE_URI = <Testing DB URL>
  SQLALCHEMY_ECHO = False

Now create a database.py:

from flask-sqlalchemy import SQLAlchemy
db = SQLAlchemy()

And this shall initiate to create our db object.now will import the main.py and initialize it.

from api.database import db

def create_app(config):
    app = Flask(_name_)
app.config.from_object(config) 
db.init_app(app)
with app.app_context():
     db.create_all()
    return app

And update create_app to initialize the db object.

So till now, we have an structure like below:

venv/
src
   api/
       _init_.py
   database.py
   
   config/
          _init_.py
          database.py

run.py
main.py
requirements.txt

Now let's define our db schema. So we will deal with two resources author and book. Let's create book models.

books.py:

from api.database import db  
from marshmallow-sqlalchemy import ModelSchema
from marshmallow import fields

class Book(db.Model):
      _tablename_ = 'books'
  
  id = db.Column(db.Integer,primary_key=True,autoincrement=True)
  title = db.Column(db.String(50)) 
  year= db.Column(db.Integer)
  author_id = db.Column(db.Integer,db.ForeignKey('authors.id'))
  
  
def _init_(self,title,year,author_id=None):
     self.title= title
self.year= year
self.author_id = author_id
 
def create(self):
        db.session.add(self)
db.session.commit()
return self
class BookSchema(ModelSchema) :
     class Meta(ModelSchema.Meta) :
       model = Book
   sqla_session = db.session
   
  id = feilds.Number(dump-only=True)
  title = feilds.String(required=True) 
  year= feilds.integer(required=True)
  author_id = feilds.Integer()
  
Here we are importing db module marshmallow-like we did in our last blog and return JSON objects.

authors.py:

from api.database import db  
from marshmallow-sqlalchemy import ModelSchema
from marshmallow import fields
from api.models.books import BookSchema

class Author(db.Model):
      _tablename_ = 'authors'

       id = db.Column(db.Integer,primary_key=True,autoincrement=True)
  first_name = db.Column(db.String(50)) 
  last_name= db.Column(db.String(50))
  created = db.Column(db.DateTime,server_default=db.func.noe())   
  books = db.relationship('Books',backref='Author',cascade="all, delete-orphan")
  
  
  
def _init_(self,first_name,last_name,books=[]):
     self.first_name= first_name
self.last_name= last_name
self.books = books

     
def create(self):
        db.session.add(self)
db.session.commit()
return self  
 
class AuthorSchema(ModelSchema):
     class Meta(ModelSchema.Meta) :
       model = Author
   sqla_session = db.session
   
  id = feilds.Number(dump_only=True)
  first_name = feilds.String(required=True) 
  last_name= feilds.String(required=True)
  created = feilds.String(dump_only=True)
  books = feilds.Nested(BookSchema,many=True,only=['title','year','id'])
  
So after all this, we have to write global HTTP configurations in main.py
Now create responses.py inside the api and use jsonify and make_response from Flask library to create standard responses for our APIs.

responses.py:


from flask import make_response,jsonify

def resposnes_with(response,value=None,message=None,error=None,headers={},pagination=None):

    result= {}
    if value is not None:
        result.update(value)
if response.get('message',None) is not None:
        result.update({'message:' response['message']})
result.update({'code': response['code'] })
if error is not None:
   result.update({'errors':error})
   
    if pagination is not None:
        result.update('pagination':pagination)
headers.update({'Access-Control-Allow-Orgin': '*'})
headers.update({'server': 'Flask REST API'})
return make_response(jsonify(result),response['http_code'],headers)
This exposes a function reponse_with for our API endpoints to use and respond back.

HTTP responses :

200 200 Ok - Standard response to HTTP requests
201 201 Created - A new resource has been created

204 204 No Content - No data returned a successful request.
400 400 Bad Request - Server cant process the error due to client error

403 403 Not Authorized - not authorized to obtain the resources
404 404-Not Found - Resource does not exist on the server
422 422 Unprocessable Entity - Due to semantic error
500 500 Internal Server Error - Unexpected condition in server.

INVALID_FEILD_NAME_SENT_422 = {
 "http_code" : 422,
 "code":"InvalidDeild",
 "message":"Invalid Feilds Found"
}

INVALID_INPUT_422 = {
 "http_code" : 422,
 "code":"InvalidInput",
 "message":"Invalid Input"
}

MISSING_PARAMETERS_422 = {
 "http_code" : 422,
 "code":"missingParameters",
 "message":"Missing parameters"
}

BAD_REQUEST_400 = {
 "http_code" : 400,
 "code":"badRequest",
 "message":"Bad request"
}

SERVER_ERROR_500 = {
 "http_code" : 500,
 "code":"notFound",
 "message":"Server Error!"
}

SERVER_ERROR_404 = {
 "http_code" : 404,
 "code":"notFound",
 "message":"Resource not found!"
}

UNAUTHORIZED_403 = {
 "http_code" : 403,
 "code":"notAuthorized",
 "message":"you are not authorized to execute this!"
}

SUCCESS_200 = {
 "http_code" : 200,
 "code":"success",
}

SUCCESS_201 = {
 "http_code" : 201,
 "code":"success",
}
SUCCESS_204 = {
 "http_code" : 204,
 "code":"success",
}
Now we have our working respose.py model ready but we have to add some to our main.py

from api.responses import response_with
import api.responses as resp

just add above db.init_app function.

@app.after_request
def add_header(response):
    return response
@app.errorhandler(400)
def bad_request(e):
    logging.error(e)
return response_with(resp.BAD_REQUEST_400)
@app.errorhandler(500)
def server_error(e):
    logging.error(e)
return response_with(resp.SERVER_ERROR_500)
@app.errorhandler(404)
def server_error(e):
    logging.error(e)
return response_with(resp.SERVER_ERROR_404)

Now we need to create our api endpoints and include them in our main.py

from flask import Blueprint
from flask import request
from api.responses import response_with
from api import responses as resp
from api.models.authors import Author ,AuthorSchema
from api.databases import db

author_routes = Blueprint("author_routes",_name_)

@author_routes.route('/',methods=['POST'])
def create_author():
    try:
     data = reuest.get_json()
author_schema= AuthorSchema
author,error=author_schema.load(data)
result=author_schema.dump(author.create()).data
return response_with(resp.SUCCESS_201,value={"author": result})
except Exception as e:  
print e
return response_with(resp.INVALID_INPUT_422)
 
 
So it will take JSON data from the request and execute create method on the Author schema and then return the response using response_with method.
So in our main.py import the author routes and the registers the blueprint.

from api.routes.authors import author_routes
app.register_blueprint(author_routes,url_prefix='/api/authors')

Now run the application using Python command run.py and our flask server should be up and running.
Now let's try with POSTMAN with the below URL.

https://localhost:5000/api/authors/ with following JSON data.
{
   "first_name": "Abhinav",
    "last_name": "Tripathi"
}

So first is ready to use check it.

  


      


   













Building REST APIs with FLASK Python Web Services -Database Modeling in FLASK

Database Modeling in FLASK

So now let's have a look at Database's most important aspect of REST application development.FLASK being a microframework provides facility to connect with different types of
databases like SQL and NoSql based database in FLASK. You can also connect with ORM types.

Creating a FLASK Application with SQLAlchemy

FLASK-SQLAlchemy is an extension for FLASK which adds support for SQLAlchemy to the application.SQLAlchemy is a python toolkit and ORM that provides access to the SQL database
using Python.FLASK-SQLAlchemy provides support for the following SQL based database engines gives the appropriate DBAPI driver is installed:

1) PostgreSQL
2)MYSQL
3)ORACLE
4)SQLite
5)Microsoft SQL Server
6)Firebird Sybase 

Anyways we will use MySql so let's create a new directory called flask-MySQL, create a virtual environment and then install flask-sqlalchemy.
  
  $mdir flask-mysql && cd flask-mysql
  
Now create a virtual environment inside the directory using the following commands
  
   $virtualenv venv
   
Once the virtualenv is activated.lets install flask-sqlalchemy.FLASK and FLASK-SQLAlchemy can be installed using PIP commands.

   (venv)$ pip install flask-sqlalchemy

Now let's install PyMySQl to enable MySQL connection with FLASK-SQLAlchemy.

   (venv)$ pip install pymysql

   
 Now we have everything we need to create our sample flask-mysql application. Let's name the file as app.py which will contain the code for our application.

Code :

from flask import Flask
from flask-sqlalchemy import SQLAlchemy


app = FLASK(_name_) 
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql:<mysql_username>:<mysql_password>@<mysql_host>:<mysql_port>/<mysql_db>'
db = SQLAlchemy(app)

if _name_ == "_name_":
    app.run(debug=True)
Creating an Author Database

 class Author(db.Model):
      id = db.Column(db.Integer,primary_key=True)
  name = db.Column(db.String(20))
  specelisation = db.Column(db.String(50))
  
  def _init_(self,name,specelisation):
      self.name=name
  self.specelisation = specelisation
  
      def _repr_(self):
     return '<product %d>' % self.id
 
  db.create_all()

With this code we have created a model titled "Author" which has three fields. Okay now there import thing before move ahead like in order to serve JSON response from our API using 
the data returned by SQLAlchemy we need another library called marshmallow which is an addon to SQLAlchemy to serialize SQLAlchemy-returned data objects to JSON.

  (venv)$ pip install flask-marshmallow

We will define our schema from the Author model using marshmallow.

from marshmallow_sqlalchemy import ModelSchema
from marshmallow import fields

After db.create_all() define your output schema using the following code:

   class Author(ModelSchema):
      class Meta(ModelSchema.Meta):
           model = Author
           sql_session = db.session
   
      id = feilds.Number(dump_only=True)
  name = feilds.String(required=True)
  specelisation = feilds.String(required=True)
  
So this maps the fields to the variables attribute to feild objects and in Meta we define the Model to relate to our schema. So this will help us return JSON from SQLAlchemy.

Before writing the endpoints edit the first import line to the following to import jsonify, make_response, and request from FLASK.

from flask import Flask, request,jsonify,make_response

And after the AuthorSchema write your first endpoint/authors with follwoing code:

@app.route('/authors' , methods = ['GET'])
def index():
    get_authors = Author.query.all()
author_schema = AuthorSchema(many=true)
authors,error = author_schema.dump(get_authors)
return make_response(jsonify({"authors: authors"}))
In this method we are fetching all the authors in the DB dumping it in the AuthorSchema and returning the result in JSON.
Run the application using Python app.py and then query the endpoint using your preferred REST client. I will be using POSTMAN to request the endpoint.
So just open your POSTMAN and the http://localhost:5000/authors to query the endpoint.











Sunday, May 17, 2020

Building REST APIs with FLASK Python Web Services


Creating Python Webservices with MySql

Beginning with Flask: Flask is a BSD licensed, Python microframework based on Werkzeuge and Jinja2. Flask is a very simple, highly extensible framework. Flask has two major components Werkzeuge and Jinja2 are responsible for providing routing, debugging and web server Gateway Interface(WSGI), Falsk uses Werkzeuge and Jinja2 as a template engine but Flask does not support database access under user authentication or any other high-level utility. Flask is actually a Production-ready framework for developing web applications and services.

Starting Flask: You can install Flask by using the Python Package Index (PPI) and is ready to set up and start developing with and it only takes a few minutes to getting started with Flask.

Installing Flask: With a virtual environment activated, execute the following command to install the latest version of Flask.

$pip install flask
;

This command will install the Flask in your virtual environment. You can use any ide and i am using PyCharm.

Using Virtual Environments: In python 3 the venv module comes pre-shipped as part of the standard library.

To install virtualebv type the following command in your terminal

$ pip install virtualenv


Let me give one simple basic Falsk application example

from flask import Falsk
app = Flask(_name_)

@app.route('/')
def hellow_world():
      return 'Hellow , from Flask'

if _name_ =='_main_':
       app.run()

And this much code is enough to start your first Flask application. So first you have to install Flask library using PIP command.

And will run and open the browser localhost:5000 and print Hellow from Flask.

to run the app type this command in terminal
$ app.py



RESTful Services: REST is a software architectural style for web services that provide a standard for data communication between different kinds of systems. In simple terms, REST is standard for exchanging data over the web for the sake of Interoperability between computer systems. So REStful web services which allow requesting systems to access and manipulate the data using a uniform and predefined set of stateless operations.REST principles are what make is it popular and heavily used.
REST is stateless which simply means that neither the client nor the server has to know the state of each other.
SOAP(Simple Object Access Protocol) is another web service communication protocol which has been overtaken by RST in recent years.SOAP, however, exposes components of application logic as services rather than data.SOAP is a legacy protocol and also lots of other constraints when compares with REST.
SOAP only exchanges data over XML and REST provides the ability to exchange data over a variety of data formats.RESTful services are faster than SOAP.SOAP is preferred when robust security is essential as it provides support for web services security(WS-Security) which is specification security measures are implemented in web services to protect them from external attacks.SOAP is highly extensible with other technologies and protocols like WS_Security, WS-addressing, WS-coordination, and many more.

REST protocol and the following features:

1)Uniform Interface
2)Representations
3)Messages
4)Links between resources
5)Caching
6)Stateless

1) Uniform Interface: it should have a uniform interface to access resources.A logical URI system with Uniform across the system. So it provides a set of methods.

GET - Fetch single or multiple resources and it is safe.
POST- Insert a new resource and it is not safe.
PUT - Insert a new resource or update an existing and it is also not safe.
DELETE - Delete single or multiple resources and it is not safe.
OPTIONS - List allowed operations on a resource and it is safe.
HEAD - return only resource headers and nobody and it is safe.
PATCH - Only update the provided changes to the resource and not safe.

2) Representations: RESTful services focus on resources and providing access to resources. You can think of it as an OBJECT in OOP. here is small example of representations.

1)
<?xml version="1.0" encoding="UTF-8"?>
<Book>
<ID>1</ID>
<Name>Abhinav</Name>
<Author>Abhinav</Author>
</Book>

2)
{
   "ID" : 1,
   "NAME" : "Abhinaw"
   "Author": "Abhinaw"
}

In REST systems you can use either of the methods or both the methods depending on the requesting client to represent the data.

3) Messages: The client and server talk with each other via messages in which the client sends a message to server which is often called as request and the server sends a response.
 The actual data exchange between the client and server in the form of request and response body.there is some metadata exchange by the client and the server both in the form of request and response headers.

Sample Response:

{"result":{"alias":"bcpartner1_key.p12","creationDate":null, "dn":"cn=Trading Partner One,ou=BusinessConnect Server (only for TEST purposes),o=TIBCO Software Inc.,l=Palo Alto, st=California,c=US serial #7a3ed2ea20", "encryptionAlgorithm":0,"encryptionKeyFingerprint":"","encryptionKeyID":"","encryptionKeyLength":0, "expiryDate":{"date":31,"day":2,"hours":10,"minutes":52,"month":11,"seconds":13,"time":1735671133000, "timezoneOffset":480,"year":124}, "password":"IRbb9HE1NlLhs+HyIQ1jQ8Fg9FfC+hxnAgSCfUKB7xPe1xNUDKF/w==", "priCredContent":"MIIOQQIBAzCCDgcGCSqGSIb3DQEHAaCCDfgEgg30MIIN8DCCAukGCSqGSIb3DQEHAaCCAtoEggLWMIIC0jCCAs4GCyqGSIb3DQEM CgECoIICpjCCAqIwHAYKKoZIhvcNAQwBAzAOBAh/g3eJa5dMVQICB9AEggKAmwKc9/j/bZjAkGauBJo1yYeWOYsbB2iq6FDe0o+/HitTzIiWPJyLfOnO4G Y6me2qtcXF6d7Yx6qN3W3xkGbLiUeYQtnnxMFtnkD1+DRqWKIXmo1r8loTZntyKPdenVPkmFri06Nmdc7zDyRIkncz9nmZT/+iJHkGvQsdtbDT+hrLz1yD zeyqX7YUdCavkToQ5W9S57lVxn4ajKup8Xr+=", "pubCredContent":"","shadowExpiryDate":null,"shadowName":"","signingAlgorithm":0,"signingKeyFingerprint":"", "signingKeyID":"","signingKeyLength":0,"type":"KCRED","updatedFileName":"bcpartner1_key.p12","userID":""}}

4) Links Between Resources: A resource is an object with a type of associated data. and relationships to other resources alongside a set of methods that can be executed on it. The resources in REST API can contain link to other resources which should drive the process flow.

5)Caching: Caching is a technique that stores a copy of the given resource and serves it back when requested again. Saving extra DB calls and processing time. It can be done at different levels like client-server or middleware proxy server. Caching is important for API to increase its performance and scaling. Caching in REST APIs is controlled using HTTP headers. In REST specification when a safe method is used on a resource URL, usually the reverse proxy caches the results to use the cached data when the same resource is requested the next time.

6)Stateless: Each request from the client to the server must contain all of the information necessary to understand the request and can not take advantage of any stored context on the server.
Session state is therefore kept entirely on the client Statelessness here means that every HTTP responses is a complete entity in itself and enough to serve the purpose. The point of statelessness is to defeat the purpose of accord with the server allowing intended flexibility in the infrastructure. Statelessness is an essential part of being able to scale the infrastructure enabling us to deploy multiple servers to serve millions of concurrent users given there is no server session state dependency.






Conclusion 

Once you have Flask installed in your virtual environment you are ready to go the next step of the development phase. In the next part, I will discuss the Database because it is an essential part of the REST application.






Difference Between Data Scientist and Data Analyst for Students


This is dedicated to Students who want to pursue their careers in DataScience, ML, and AI.

There is again the most demanding question that I am getting actual students does not able to differentiate between the Data Scientist and Data Analyst. Let me just give you my point of view on this. I understood correctly while I was getting training from an institute.

Difference Between Data Scientist and Data Analyst

Data Scientist :

  • Data scientists actually formulate the questions that will help a business organization and then proceed in solving them.
  • Data scientists will have strong data visualization skills and the ability to convert data into a business story.
  • So Data scientists should know programming in Python and R along with Perfection in mathematics, statistics.
  • Data scientists can also estimate the unknown information from the known data.

Data Analyst : 

  • Data Analyst receives questions from the business team and provides answers to them.
  • Data Analyst simply analyzes the data and provides information requested by the team.
  • Data Analysts should know the following things like Perfection in data warehousing, big data concepts, SQL and Business intelligence, etc.
  • Data Analyst looks at the known data from a new perspective.

I hope I am clearly able to differentiate the difference in the real world. Let me share a picture which will tell you more.







Interview Questions related to Networking in Python and and Basic concepts to remember


I am trying to capture all possible questions that can be asked during python networking questions for core-python developers. It is very basic but very important. Good product based companies ask these types of questions in good interviews and I think we all should at least aware of these things.

  • The interconnection of computer is called Network.
  • The advantage of a network is sharing resources like data, files, software, and hardware.
  • The computers which receive data from a network are called clients and computers which provide services are called severs.
  • A protocol represents a set of rules to be followed by every computer on the network. So there are two protocol models are TCP/IP and UDP. All other protocols are developed based on these two protocols.
  • TCP/IP is a connection-oriented protocol that transmits data safely.
  • UDP is a connectionless protocol and may not transmits data safely.
  • An IP address is a unique identification number given to every computer on the network. It contains four integers numbers in the range of 0 to 255 and separated by a dot. 
  • A socket is a logical point of connection between a server and a client. Data is transmitted through sockets only.
  • Every socket is identified with a unique number called port number.
  • Port number is a 2byte number and ranges from 0 to 65535.
  • A socket with a constant socket.SOCKET_STREAM is created to work with TCP/IP protocol.
  • A socket with a constant socket.SOCK_DGRAM is created to transmit data on UDP protocol.
  • The gethostbyname() function of a socket module is used to find the IP Address of any website.
  • The messages are transmitted between the server and the client in the form of binary strings.
  • The encode() method converts a normal string into a binary string and decodes () method converts a byte stream into a normal string.
  • SMTP class of smtplib module and MIMEText class of email.mimime.text module are provided in python to send emails on the internet.
Sample program to Send an Email:

import smtplib

body = ''' This is my text mail.this is sent to you because I am teaching Python.'''

msg=MIMEText(body)

fromaddr="abhinawtripathi34@gmail.com"
toaddr="abhinawtripathi@ymail.com"

msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "hi friend!"

server = smtplib.SMTP('smtp.gmail.com',587)
server.starttls()

server.login(fromaddr,"MyPassword")
sever.send_message(msg)
print('Mail sent...')
server.quit()

Output: 
      
   C\:>python mail.python
   Mail sent...

While running this program we should be connected with the internet. This program is sending the mail through gmail.com sever





Saturday, May 16, 2020

Simple ORACLE Database Connection with Python


How to work with Oracle through Python?

Installation of Oracle latest version 19c.

Go to oracle.com website at the following link:

http://www.oracle.com/technetwork.datbases.database-technologies/express-edition/downlaods/index.html

So after this you able to download and install on your system but you need another thing Oracle Database Driver.

Installing Oracle Database Driver

We have to install a driver or connector software that connects the Oracle database with our Python programs.

The name of the driver needed is 'ex_Oracle' and it can be installed using pip command that comes with python by default. Just go to system prompt and type the command like below:

C:\>pip install cx_Oracle

Now let me give you a simple program to understand.

Program # 1 : 

import cx_Oracle

conn = cx_Oracle.connect('SYSTEM/ABHINAW@localhost')
cursor = conn.cursor()
cursor.execute("select * from table")
row = cursor.fetchone()

while row is not None:
    print(row)
    row = cursor.fetchone()

cursor.close()
conn.close()

Output: 

C:>python ora.python

(1001,'ABHINAW',100000)
(1002,'JAYANTA',100000)
(1003,'PRITAM',100000)
(1004,'BIPRADIP',100000)

Now since we are discussing ORACLE so let me also tell you about "Stored Procedures"

Stored Procedures

So a stored procedure is a set of statements written using PL/SQL(Procedural  Language / Structured Query Language). To perform some calculations on tables of a database, we can use stored procedures. Stored procedures are written and stored at the database server. So when a client contacts the server, the stored procedures are executed and results are sent to the client.

Stored Procedures are compiled once and stored in the executable form at the server-side. The memory for stored procedures is not allocated every time they are called. Stored Procedures are stored in cache memory at the server-side and they are immediately available to clients. This is one of the main advantages of Stored Procedures

let me give you an example of how to write the stored procedures program:

-- myproc.sql
-- to increase number in my table
create or replace provider myproc(no in int,isal out float) as
salary float;
begin 
         select sal into salary from table where someid=no
         isal := Salary+1000;
end;
/

Note: atlast line you see '/' indicates to execute the procedure at server side.

Now Points to Remember:

  • A database management system(DBMS) represents software that stores and manage data.
  • After installing the ORACLE driver we can see a new module by name 'cx_Oracle' in the Python library.
  • The SQL commands are almost the same for all databases like MYSQL or ORACLE.







Python Program to retrieve a row from a MYSQL database table using GUI

 
So another example this time with GUI retrieves a row using GUI -- Python a GUI application

#Program: 

import MySQLdb
from tkinter import *

root = TK() # create root window

def retrieve_rows(eno): # takes employee number and display
    conn = MYSQLdb.connect(host = 'localhost' , database = 'Anything' , user = 'root' , password ='Pass123')
cursor = conn.cursor()

     str = "select * from table where eno = '%d'"
args = (eno)
cursor.execute(str % args)
row = cursor.fetchone()
 
if row is not None:
     lbl = Label(text=row,font=('Arial' , 14)).place(x=50, y=200)
 
cursor.close()
     conn.close()

#takes input from Entry widget
def display(self): 
    str =e1.get()
    lbl =Label(text='You entered: '+str,font=('Arial' , 14)).place(x=50, y=150) 
    retrieve_rows(int(str)
# create a frame as child to root window
f = Frame(root, hegight=350,width=600)
f.propagete(0)
f.pack()

l1=Label(text='Enter employee number : ',font=('Arial' , 14))

e1 = Entry(f,width=15 , fg='blue' , bg='yellow',font=('Arial',14))
e1.bind(("<Return>" , display)
l1.place(x=50,y=100)
e1.place(x=300,y=100)

root.mainloop()

Output: 








Python Database Connectivity with MySQL


So again another most demanded topic this week is Python's Database Connection

I am going to cover everything in a peeling way. I will tell you exactly how to do it without any crap.

DBMS

To store data we need a database. A database represents a collection of data. We can also perform some operations on data. for example modifying the existing data, deleting the unwanted data, or retrieving the data from the database. To perform such operations a database comes with the software. This is called a database management system(DBMS).

DBMS = database + software to manage the data

Examples for DBMS are MYSQL, ORACLE, SYBASE, SQL SERVER, etc.

Types of Databases Used with Python

So here I will certainly talk about Python and Databases for a better understanding of how it works with Python.

To work with any database we should have the database installed in our computer system. And to connect to that database we need a driver or connector program that connects the database with Python program.

So now let's use MYSQL very commonly used database. In order to install it open the mysql.com website and download the installer.

https://dev.mysql.com/downloads/windows/installer/

Just click next - next and install it after this how to verify that MYSQL is installed properly.

Verifying MySQL in the Windows Operating System

So for this just go to the Start -> your computer and you will find the MYSQL option. but you have to do one more thing after this is like

Installing MYSQLdb Module

Why this? because To communicate with MYSQL database from Python we need a program that becomes an interface to the MySQL database server. So MYSQLdb is an interface between the MySQL server and Python programs. To install it you have to do this way.

https://pypi.python.org/pypi/mysqlclient

So after this, you are ready to use the MySQL database with Python certainly. Whatever  I have mentioned is for the core-python developer.

So let me give you some examples of simple programs that you can directly execute on your systems.

#Program : 

Retrieve and Display all rows from a any table.

import MySQLdb

# connect to Mysql database

conn = MYSQLdb.connect(host = 'localhost' , database = 'Anything' , user = 'root' , password ='Pass123')

# prepare a cursor object using cursor() method

cursor = conn.cursor()

# execute the query

cursor.execute("select * from table")

# fetch only one row

row = cursor.fetchone()

#if the rows exists

while row is not None:
        print(row)
         row = cursor.fetchone()

# close the connection
cursor.close()
conn.close()

Output: In My case, it is like below

Connected to MySQL database
(1001 ,  'Abhinav', '10000')
(1002 ,  'Pritam' , '10000')
(1003 ,  'Jayanta' , '10000')
(1004 ,  'Arindam' , '10000')

So we can also use the fetchall() method that retrieved all the rows from my table like 

rows = cursor.fetchall()

This is a simple database connection program for Python Developer.












Sunday, May 10, 2020

Best Practice for Handling Back Hard/Soft Navigation for Fragments - Kotlin/Java Android

So I was getting this question from my viewers for handling the back/soft press on Android App. See there are many ways to handle this but every app has nowadays followed a Design-Patterns like MVC, MVP, MVVM, REDUX, etc. So how to implement the back navigations which work smoothly. I will try to give you a complex use-case So that you can relate to it. But let's assume you have created an Android Project with 2 Activities and Say 20 fragments in it.

So suppose it is like below

Activity1 hosting 10 fragments and then Another Activity2 hosting another 10 fragments So now how to design you back navigation for this use case.

For Fragments and Back Navigation Google App Developer site have a well-defined article but you have to understand it in order to implement below is the URL of it in case you wish to see.



So suppose you have Designed your app code structure like you know you have BaseActivity and BaseFragment and you are defining all the functions withing it and obviously implementing those in your Activity1 and Activity2 right So far with me?

The same goes for Fragments to Since you have Base Fragments So you must be doing like below I am giving example.

This is pretty basic Java/Kotlin but actually quite essential for any fragment-heavy application. I find this leads to less code complexity but more extensibility for me. I have a standard container layout in XML, and call the following to the swap fragments in it:

Fragment myNiceFragment = MyNiceFragment.instantiate(mContext, MyNiceFragment.class.getName(), args);

getSupportFragmentManager().beginTransaction()
        .replace(R.id.content_container, myNiceFragment, myNiceFragment.getClass().getSimpleName())
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        .addToBackStack(null)
        .commit();

For committing fragments you must be doing like above this is just a code snippet to make you understand how to do it? Do not confuse between Add/Replace/Remove of fragments right?
Of course, by adding it to the back stack it pops when we press back by default, which is just lovely.  user hits back, and not just have the hosting activity know that we pressed back. He should share that info with anyone that would like to know!.

Solution

To tell fragments when the back button has been pressed, first of all, you need a base fragment which all of your other fragments inherit from. This base fragment implements the following:

BaseFragment.Java/BaseFragment.kt: whichever way you prefer.

public interface OnBackPressed {
    void onBackPressed();
}

public class BaseFragment extends Fragment implements OnBackPressed {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    public void onBackPressed() {//Leave it empty}
}

Now in your hosting Activity, call any implementations of the interface before any fragments are popped:

Just do this in your Hosting Activit1 and Activity2 and You are good to go.No problem at all.

@Override
public void onBackPressed() {
    tellFragments();
    super.onBackPressed();
}

private void tellFragments(){
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for(Fragment f : fragments){
        if(f != null && f instanceof BaseFragment)
            ((BaseFragment)f).onBackPressed();
    }
}

That’s it! Any fragments which implement our onBackPressed() can do so and will be told as soon as the Activity is.

In Your Respective Fragments:

@Override
public void onBackPressed(){
    getActivity().getSupportFragmentManager().popBackStack();
}


So what are the Pros and Cons implementing this way if you see Suppose you have a requirement like when press back from Fragment 10 and I should Navigate to Fragment 2 Right? So it is just easy like in you on the BackPress method write a while loop and put a condition and just make a fragment Pop call and you are good. This type of requirement you will find in almost all your project So I find this way you are more controlled and maintained and once you leave the company your fellow Developer can understand it too :). I saw many people end up doing it in Activiting making switch cases and handling there believe me at some point in time the code becomes impossible to understand for a big project. So this one is the best way to do it. let me know your thoughts on it.

Note Just little tweak to make it compatible with Kotlin is just do it like below:

interface OnBackPressed {
    fun onBackPressed();
}

I hope you understand it and if you are not able to d to it just copy and paste this code and Android Studio will do it for you.

Thanks.





Sunday, May 3, 2020

Kotlin - Extension Functions



Extensions - Extensions let you add new functions and properties to an existing type without you having to create a whole new subtype.

Before getting deep into it lest understand some points about Design Patterns.

Object declarations provide a way of implementing the Singleton patterns as each declaration creates a single instance of that object.

Extensions may be used in place of the Decorator patterns as they allow you to extend the behaviour of classes and objects And if you are interested in using the Delegation patterns as an alternative to the inheritance.

For example: 

// Defines a function named toDollar() which extends Double.
fun Double.toDollar() : String
{
   return "$$this" // returns the current value prefixed with $.
}








Kotlin - Modifiers , Enum classes ,Sealed classes


Visibility Modifiers 

It lets you set the visibility of any code that you create such as classes and functions. For example, a member function can only be used inside its class.

So Kotlin has four visibility modifiers : 

1) public
2)private
3)protected
4)internal

Modifiers:  What it does:

public        It makes the declaration visible everywhere.This is applied by default so it can be omitted.

private       It makes the declaration visible to code inside its source file but invisible elsewhere.

internal      It makes the declaration visible inside the same module but invisible elsewhere.

Lets take an example :

open class Parent
{
  var a = 1

   private var b =2

   protected open var c = 3

   internal var d =4
 
}         

class Child : Parent()
{
  override var c = 6
}

Note that if you override a protected member as in the above code, the subclass version of that member will also be protected by default.you can however
change its visibility as in this example,

class Child : Parent()
{
 public override var c = 6
}

Enum classes :

An enum class lets you create a set of values that represent the only valid values for a variable.

for example:

enum class BandMember { AVI,KUNAL,PRASHANT} // the enum class has 3 values.

fun main(args : Arrays<String>)
{
   var selectedBandMember : BandMember // The variable's type is BandMember
   selectedBandMember = BandMember.AVI  // So we can assign one of BandMembers value to it.
}

Note : 


  • Each value in an enum class is constant.
  • Each enum constant exists as a single instance of that enum class.
enum properties and functions example:


enum class BandMember(val instrument : String) { AVI("Lead Guitar"),KUNAL("Rythm guitar"),PRASHANT("bass");

fun sings() = "occasionally"  // Each enum value has a function named sings which return the String
}

enum class BandMember(val instrument : String)
{
  AVI("Lead Guitar")
  {
    override fun sings() = "plaintively"
  },
  KUNAL("Rythm Gutar")
  {
    override fun signs() = "hoarsely"
  },
  PRASHANT("Bass")
  {
  };

  open fun signs() = "occasionally"

}

fun main(args : Array<String>)
{
   var selectedBandMember : BandMember

   selectedBandMember = BandMember.AVI
 
   println(selectedBandMember.instrument)
 
   println(selectedBandMember.sings())
}

Sealed classes 

Suppose that you want to be able to use two different message types in your application: one for success and another for failure.

How to do this?

enum class Message Type(var msg: String)
{
  SUCCESS("YAH!!"),
  FAILURE("Failed!!")
}

But there is a problem with this approach:

1) Each value is a constant which only exists as a single instance.
2)Each value must have the same properties and functions.

So what's the solution?

Sealed classes to the rescue!:

So a sealed class is like a souped-up version of an enum class.it lets restrict your class hierarchy to a specific set of subtypes each one of which can be defined as its own properties and functions.

You can create a sealed class by prefixing the class name with sealed.

for example;

 sealed class Message Type
 class MessageSuccess(var msg: String) : MessageType()
 class MessageFailure(var msg: String) : MessageType()

fun main(args : Array<String>)
{
   var messageSucc : MessageSuccess ("Successful")
   var messageSucc2 : MessageSuccess ("It worked Successful")
   var messageFail : MessageSuccess ("Failed")
}