Doing something you intrinsically are enthusiastic with.

2017年1月17日 星期二

SOLID Principles of objected programming

晚上11:07 Posted by Unknown No comments

What is SOLID principle ?

SOLID stands for five basic principles of object-oriented programming and design. The intention is that these principles, when applied together, will make it more likely that a programmer will create a system that is easy to maintain and extend over time.The principles of SOLID are guidelines that can be applied while working on software to remove code smells by providing a framework through which the programmer may refactor the software's source code until it is both legible and extensible.

SOLID stands for:

SINGLE-RESPONSIBILITY PRINCIPLE

Definition: A class should have only one reason to change.

擷取.PNG

This principle echoes with the encapsulation concept. The encapsulation concept suggests that the details not necessary for external references should be hidden, those unnecessary methods also shouldn't exist within the class.

In the code above, we can see that the save_page method deals with the file saving of the page.
This violates the single responsibility principle since the Book itself should not operate on this task.
We should let each object focus on what they should do.

In the code below, the save method has been moved to another class called BookData_maniputlation.

擷取2.PNG



OPEN-CLOSED PRINCIPLE

Definition: Objects or entities should be open for extension, but closed for modification. If the OCP is applied well, then further changes are achieved by adding new code, not by changing old code that already works. This can avoid that a single change to a program will result in a cascade of changes to dependent modules.

擷取3.PNG

In the code above we can notice that in method drawShape, the m_type is used to check the objects and determine which part of code should be run. However, it violates the Open-Closed principle, for example, if we want to add one more shape to the code, we inevitably change the code.



So instead, we move the detail to Rectangle class itself. And the drawCircle and drawRectangle
method become useless in the GraphicEditor class. This can help us not to change the logic inside GraphicEditor while adding new shape.


LISKOV SUBSITITUTION PRINCIPLE

Definition: Subtypes must be replaceable for their base types. Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.


For example, when implementing the draw method in the subclass of Shape, Circle and Square, the methods both abide by the behavior definition of draw (draw themselves on the canvas). If the subclasses hasn't follow the definition of their base class, the demand of  Liskov substitution principle is not met.

If the program does not meet the demand of LSP, then the behavior of the program is going to be unpredictable. In other words, it's possible that the bugs are unpredictable and unnoticeable.
For instance, if the draw method in Circle does not draw itself on the canvas but save it as a file or output to the printer. There's nothing wrong when programmers simply read the code, but when in the runtime, the behavior of the program won't work as expected.

Let us take a look at the example below to clarify the concept.



In the code above, we have two classes, Square and Rectangle, they seem to work fine. Whatever you do on the Square, it will conform to the definition of Square,so does the Rectangle. Even when you pass a Square to a function that accepts the Rectangle object or pointer, Square still keeps its property and consistency.

Noted that the _width and _height parameter in class Square are nonsense while a Square won't keep different width or height. This inherently violates the Open-closed principle which also means there is a design issue in the base class.

But what's more than that is in the func function, there will be error in the assert function when we pass a square to it. The functions designed in the Rectangle class has violated the Liskov substitution principle.

From the point of view of the behavior, a Square is not a Rectangle. And what we actually care about in software development is the behavior. The Liskov Principle let us know the IS-A in object-oriented design is relevant with the behavior. It's not about the interior, private behaviors but those become public that the users rely on. To meet the demand of both LSP and OCP, all the derived class should conform to the behavior of the base class that user expect.


INTERFACE-SEGREGATION PRINCIPLE

Definition: A client should never be forced to implement an interface that it doesn't use or clients shouldn't be forced to depend on methods they do not use.



In the code above, SomeController which handles clicks from two SomeButton objects and window events from a SomeWindow object. The problem with this design is that SomeButton and SomeWindow both have a SomeController pointer. SomeButton does need to call the onButton[X]methods of the controller object, but it also has access to the onWindow[X] methods which are useless to the button. The presence of useless onWindow[X] methods is a violation of the Interface Segregation Principle. There is also a cyclic dependency.



The improved design above uses abstract base classes and multiple inheritance. SomeButton now only has access to button related controller methods, and SomeWindow only has access to window related controller methods, yet SomeController objects can be plugged into both.


DEPENDENCY INVERSION PRINCIPLE

Definition: The dependency inversion principle refers to a specific form of decoupling software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details.The principle states:

A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions.


Here we have one PC with one HDD. In this example, the HDD depends on the details rather than on the abstractions. If one day I want to add functions to the HDD or replace it with another one, then we must modify the HDD class to achieve it.


In this modified version, if there is a new HDD for update in the future. We can just add a new class called MyHDD or something else rather than modify the original HDD class .

This is the end of this post.
If there is anything wrong, please kindly let me know. I appreciate your help.

2016年10月28日 星期五

Abstract class v.s. Interface in Java

凌晨12:06 Posted by Unknown No comments

The difference between abstract class and interface is frequently asked in interviews.

Characteristics of abstract class 

1.Both abstract class and abstract method needs to be declared with 「abstract」

2.Using「new」to generate object on abstract class is not allowed.

3.Abstract class needs declaration but not necessary to be implemented.

4.The derived class needs to implement the abstract method in the base class. 

Otherwise it's merely another abstract class.

 abstract class Shape{
      String name;
      double length, width, heigh;
      double radius;

      abstract double area();            // calculate area
      abstract double perimeter();    // calculate perimeter

      // In abstract class, constructor is allowed. For quardrangle
      public Shape(double length, double width, String name){
            this.length = length;
            this.width = width;
            this.name = name;
      }
      
      // For triangle
      public Shape(String name, double width, double height){
            this.height = height;
            this.width = width;
            this.name = name;
      }
}


class Rectangular extends Shape{      
     public Rectangular(double length, double width, String name){
            super(length, width, name);     //use super to call constructor of base class
     } 

     //Area and perimeter functions need to be implemented.
     double area(){     
            return length * width;
     } 
    
     double perimeter(){
            return (length + width) * 2; 
     }
} 

class EqualTriangle extends Shape{      //Triangle
      public EqualTrangle(String name, double width, double height){
              super(name, width, height);
      } 

      double area(){
            return (width * height) / 2 ;
     } 
    
     double perimeter(){
            return 3 * width; 
     }
}

Characteristics of interface

1.No constructor in the interface.


2.All the data members need to be initiated

3.The parameters need to be declared  as public and final,or static.

4.Abstract methods need to be public or abstract.




interface Shape {
    public double Shape_PI = 3.14;
     
    public double area();
    public double perimeter();
}
 
class Circle implements Shape {
    private double radius;
     
    public Circle(double r) {
        setRadius(r);
    }
     
    public Circle() {
        this(10.0);
    }
     
    public double getRadius() {
        return radius;
    }
     
    public void setRadius(double r) {
        if (r > 0.0) {
            radius = r;
        }
        else {
            radius = 1;
        }
    }
     
    public double area() {
        return radius * radius * Shape_PI;
    }
     
    public double perimeter() {
        return 2 * radius * Shape_PI;
    } 
}
 
class Rectangle implements Shape {
    private double length;
    private double width;
     
    public Rectangle(double l, double w) {
        setLength(l);
        setWidth(w);
    }
     
    public Rectangle(double a) {
        this(a, 10.0);
    }
     
    public Rectangle() {
        this(10.0, 10.0);
    }
     
    public double getLength() {
        return length;
    }
     
    public double getWidth() {
        return width;
    }
     
    public void setLength(double l) {
        if (l > 0) {
            length = l;
        }
        else {
            length = 1.0;
        }
    }
     
    public void setWidth(double w) {
        if (w > 0) {
            width = w;
        }
        else {
            width = 1.0;
        }
    }
     
    public double area() {
        return length * width;
    }
     
    public double perimeter() {
        return 2 * (length + width);
    }
}

Note to avoid confusion 1. Class in java can only inherit one base class. (While in C++, multi-inheritance of class is supported but not recommended) 2. Interface can do multi-inheritance on interfaces. 3. Class can implements multiple interfaces.  When to use abstract class or interface ?
It's been widely discussed for long time about when to user abstract class or interface.As for me, I will intend to use abstract class and inheritance to describe the characteristic of the class.And I will use interface to define functions that can represent the capability or behavior of it. That's my principle,depending on the project,developers can have their own style or principles to use abstract class and interface flexibly.

2016年10月26日 星期三

Leetcode-Balanced Binary Tree

晚上9:34 Posted by Unknown No comments
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary tree 
in which the depth of the two subtrees of every node never differ by more than 1.
=======================================================================
Solution :
The Top-down solution is to check all the sub tress from the root whether
the difference of the two sub tress more than 1.

class solution {
public:
    int depth (TreeNode *root) {
        if (root == NULL) return 0;
        return max (depth(root -> left), depth (root -> right)) + 1;
    }

    bool isBalanced (TreeNode *root) {
        if (root == NULL) return true;
        
        int left=depth(root->left);
        int right=depth(root->right);
        
        return abs(left - right) <= 1 && isBalanced(root->left) && isBalanced(root->right);
    }
};

2016年10月14日 星期五

Quicksort-instant reveiw

晚上8:36 Posted by Unknown No comments
You may checked this video to see how quicksort is working.

There are many similar forms of quicksort.

You can randomly choose one pivot or two pivot to go while the code below only

deals with the single pivot case. Like the video, we burn the the candle from one side.






1. Candle burned from one side


  1. void quick_sort(int array[], int leftint right)
  2. {
  3.     if (left < right)
  4.     {
  5.         // divide (partition)
  6.         int pivot = array[(left+right)/2];  
  7.       // Can choose any number you want
  8.         swap(array[right], array[(left+right)/2]);
  9.       // to the rightmost
  10.         int i = leftj = left;
  11.         for (; j < right; ++j)
  12.             if (array[j] <= pivot)
  13.             {
  14.                 if (i < jswap(array[i], array[j]);    
  15.                 i = i + 1;
  16.             }
  17.         if (i < rightswap(array[i], array[right]);   
  18.  
  19.         // then conquer
  20.         quick_sort(arraylefti-1);
  21.         quick_sort(arrayi+1right);
  22.  
  23.         // no need to combine sub-solutions
  24.     }
  25. }

2016年10月1日 星期六

Leetcode-Swap nodes in pair

下午1:40 Posted by Unknown No comments
Given a linked list, swap every two adjacent nodes and return its head.
For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.
Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.
Subscribe to see which companies asked this question
----------------------------------------------------------------------------------------
Solution:
The dummy node is used to keep the swap_pair function work in consistent way at the 
very beginning. In other words, to satisfy the function at the very first initialization state.

Noted that we need to pass the pointer by reference so that the structure 
of the list will actually change.

class Solution {
public:
    ListNode *swapPairs(ListNode *head) {
        ListNode *dummy = new ListNode(0);
        dummy->next = head;
        head = dummy;
        while(head) head = swapNodes(head->next);
        head = dummy->next;
        delete dummy;
        return head;
    }
    
    ListNode *swapNodes(ListNode *&head) {
        if(!head || !head->next) return NULL;
        ListNode *tail = head;
        ListNode *nextHead = head->next->next;
        head = head->next;
        head->next = tail;
        tail->next = nextHead;
        return tail;
    }
};



2016年8月30日 星期二

2016年8月25日 星期四

Leetcode--Excel Sheet Column Title

中午12:39 Posted by Unknown No comments
Given a positive integer, return its corresponding column title as appear in an Excel sheet.
For example:
    1 -> A
    2 -> B
    3 -> C
    ...
    26 -> Z
    27 -> AA
    28 -> AB 

Solution:

This is a 26-ary system. However if we use 1-26. 26 can not be consistent with other numbers ahead.

For example: 25/26=0, but 26/26=1. So we need to apply 0-based policy in this problem.

Each number from 1-26 minuses 1 to conform A-Z. But new problems occur, AA should be 27

orginally, 27-1=26, 26%26=0. This is incorrect. So every number should minus 1 in each loop to

make sure it's 0-based.

  1. class Solution {
  2. public:
  3.     string convertToTitle(int n) {
  4.        
  5.         string ans;
  6.         while (n--!= 0) {
  7.             ans = char(int('A') + n % 26) + ans;
  8.             n /= 26;
  9.         }
  10.         return ans;
  11.  
  12.     }
  13. };