Design Pattern :
There are certain problems which seem to be occurring from time to time and the programmers have come up with a way to solve these problems and classified the solutions as various patterns.
Patterns are not a completely implemented solution but a description or template to solve the problem. It tries to prevent the programmer from making a bad code.The general principles suggested to be followed are,
OPEN CLOSE PRINCIPLE :
" Software entities like classes, modules and functions should be open for extension but closed for modifications. "
If you add a new functionality to a class make the changes without affecting the previously existing code. Consider the following example,
class Car {
public:
..........
Petrol P;
Car(){P=0;}
Fill_tank(Petrol litres){P+=litres;}
Run(){run using the petrol;}
...........
}
The above mentioned Car class will be handling only petrol cars. If a new diesel car comes we need to change the code inside the Car and add new methods. If the Car class is a highly complex class and edited by many people it will be better if we implement the new functionality outside the Car class.So its better to write a generic car code which can be made to run using any fuel.
class Car{
public:
Fuel f;
Car(){f.content=0;}
Fill_tank(Fuel temp){f.content+=temp.content;}
Run(){run using the fuel;}
}
class Fuel{
int content;
}
class Petrol : public Fuel{
}
class Diesel: public Fuel{
}
DEPENDENCY INVERSION PRINCIPLE :
Dependency Inversion Principle states that when you go for designing , design the complex classes first and then go for designing the simple classes. This is because the complex classes will be difficult to modify in future, rather than changing the simple classes.
For example: consider a ATM machine which is using a button type input interface. Even If the button type is replaced by a touch screen type the underlying working of the ATM machine should not be changed for changing the input interface. This comes by following the DIP principle.
INTERFACE SEGREGATION PRINCIPLE :
This Principle concentrates on the design of the interfaces. Interfaces should be able to accommodate the changes in future. If a bad interface is designed you will have the problem of unnecessarily implementing the methods of the interface in the class inheriting it.
If you are designing an interface for Power Generator. Control_pollution() is a method to be implemented. But if the Power Generator is using a renewable resource you need not implement the Control_pollution() method.
So its better you go for two interfaces of Power_Generator_Renewable and Power_Generator_non-Renewable.This will segregate the interfaces. Caution: Be careful while following the principle because you may end using way too many interfaces.
To apply the principle have a balance between complicating the code using new interfaces and avoiding unnecessary implementation of methods in the class using interfaces.
SINGLE RESPONSIBILITY PRINCIPLE :
According to the principle assign a class with only one responsibility. If you are trying to assign more than one responsibility you better break down the code into two different classes.
Many people may find this principle annoying as i personally do. But it will be better if you don't put too much methods into a single class. Because it will spoil the use of object oriented approach as you are not properly identifying the objects...!!!
LISKOV'S SUBSTITUTION PRINCIPLE :
This means that the if a parent class has a method and a child class inherits it. The way the child class execute the methods should not be different from the way the child executes the method.
If Light is a class and turn_on() is a method in it. The turn_on() method should return the same function of giving light for Light class or any other class derived from it eg. Tube light or neon light.
eg. Consider a Point_2d class and a Point_3d class inherited from the Point_2d class.
Point_2d {
int x,y;
2d(int a,int b){x=a,y=b;}
same_points(Point_2d p)
{
if(this.x==p.x && this.y==p.y) return true;
return false;
}
}
Point_3d: public Point_2d{
int z;
3d(int a,int b,){x=a,y=b;z=random()%1000;}
3d(int a,int b,int c) {x=a,y=b,z=c;}
same_points(Point_3d p)
{
if(this.x==p.x && this.y==p.y && this.z==p.z) return true;
return false;
}
}
The same_points() in the parent class works differently from that of the same_points() in the derived class.This is a violation of LSP.
This may make you feel that LSP doesn't allow method over riding right.?? Yeah its a violation of LSP to use method over riding. Not all principles can be followed all the time as they are general guidelines for a better code.
REFACTORING :
Refactoring the code means making the code which you wrote to follow the above mentioned principles. Your code may be functional but it will be a better code if you change your code to follow these principles.
DESIGN PATTERNS:
There are a lot of design pattern to discuss. And people may want to know which pattern should one go for to solve the problem. To these people i might suggest you may not always get solution from the classified patterns. There may be some situations where you might have coded according to a pattern without knowing that it is a pattern design.
Example : Singleton class.
Singleton class is a design pattern. In this pattern there should be only one copy of object of the singleton class. These can be like the init process in the system. The system can contain any number of other processes but only one init process.
The implementation requires use of a private constructor to prevent any object from creating the object directly. A static member which is to mark the creation of the first and only object for the entire program. And a method to call the private constructor.
Similarly any non-sharable resources like printer can be quoted as examples. These should be implemented in such a way that they work well in multi-threaded environments too.
Usually they are implemented by mechanisms similar to that of semaphores or using a static member of the class.
Disadvantages of patterns :
Pattern are not always advantageous as they might lead to unnecessary complication of the code. Don't use pattern unless they are really necessary and don't overuse the design patterns.
Anti Pattens:
These refer to the patterns that exist in the real world and they are counter productive and often lead to bad consequences. For example : Hard coding and not rechecking the code having a blind faith in the code .
There are certain problems which seem to be occurring from time to time and the programmers have come up with a way to solve these problems and classified the solutions as various patterns.
Patterns are not a completely implemented solution but a description or template to solve the problem. It tries to prevent the programmer from making a bad code.The general principles suggested to be followed are,
OPEN CLOSE PRINCIPLE :
" Software entities like classes, modules and functions should be open for extension but closed for modifications. "
If you add a new functionality to a class make the changes without affecting the previously existing code. Consider the following example,
class Car {
public:
..........
Petrol P;
Car(){P=0;}
Fill_tank(Petrol litres){P+=litres;}
Run(){run using the petrol;}
...........
}
The above mentioned Car class will be handling only petrol cars. If a new diesel car comes we need to change the code inside the Car and add new methods. If the Car class is a highly complex class and edited by many people it will be better if we implement the new functionality outside the Car class.So its better to write a generic car code which can be made to run using any fuel.
class Car{
public:
Fuel f;
Car(){f.content=0;}
Fill_tank(Fuel temp){f.content+=temp.content;}
Run(){run using the fuel;}
}
class Fuel{
int content;
}
class Petrol : public Fuel{
}
class Diesel: public Fuel{
}
DEPENDENCY INVERSION PRINCIPLE :
Dependency Inversion Principle states that when you go for designing , design the complex classes first and then go for designing the simple classes. This is because the complex classes will be difficult to modify in future, rather than changing the simple classes.
For example: consider a ATM machine which is using a button type input interface. Even If the button type is replaced by a touch screen type the underlying working of the ATM machine should not be changed for changing the input interface. This comes by following the DIP principle.
INTERFACE SEGREGATION PRINCIPLE :
This Principle concentrates on the design of the interfaces. Interfaces should be able to accommodate the changes in future. If a bad interface is designed you will have the problem of unnecessarily implementing the methods of the interface in the class inheriting it.
If you are designing an interface for Power Generator. Control_pollution() is a method to be implemented. But if the Power Generator is using a renewable resource you need not implement the Control_pollution() method.
So its better you go for two interfaces of Power_Generator_Renewable and Power_Generator_non-Renewable.This will segregate the interfaces. Caution: Be careful while following the principle because you may end using way too many interfaces.
To apply the principle have a balance between complicating the code using new interfaces and avoiding unnecessary implementation of methods in the class using interfaces.
SINGLE RESPONSIBILITY PRINCIPLE :
According to the principle assign a class with only one responsibility. If you are trying to assign more than one responsibility you better break down the code into two different classes.
Many people may find this principle annoying as i personally do. But it will be better if you don't put too much methods into a single class. Because it will spoil the use of object oriented approach as you are not properly identifying the objects...!!!
LISKOV'S SUBSTITUTION PRINCIPLE :
This means that the if a parent class has a method and a child class inherits it. The way the child class execute the methods should not be different from the way the child executes the method.
If Light is a class and turn_on() is a method in it. The turn_on() method should return the same function of giving light for Light class or any other class derived from it eg. Tube light or neon light.
eg. Consider a Point_2d class and a Point_3d class inherited from the Point_2d class.
Point_2d {
int x,y;
2d(int a,int b){x=a,y=b;}
same_points(Point_2d p)
{
if(this.x==p.x && this.y==p.y) return true;
return false;
}
}
Point_3d: public Point_2d{
int z;
3d(int a,int b,){x=a,y=b;z=random()%1000;}
3d(int a,int b,int c) {x=a,y=b,z=c;}
same_points(Point_3d p)
{
if(this.x==p.x && this.y==p.y && this.z==p.z) return true;
return false;
}
}
The same_points() in the parent class works differently from that of the same_points() in the derived class.This is a violation of LSP.
This may make you feel that LSP doesn't allow method over riding right.?? Yeah its a violation of LSP to use method over riding. Not all principles can be followed all the time as they are general guidelines for a better code.
REFACTORING :
Refactoring the code means making the code which you wrote to follow the above mentioned principles. Your code may be functional but it will be a better code if you change your code to follow these principles.
DESIGN PATTERNS:
There are a lot of design pattern to discuss. And people may want to know which pattern should one go for to solve the problem. To these people i might suggest you may not always get solution from the classified patterns. There may be some situations where you might have coded according to a pattern without knowing that it is a pattern design.
Example : Singleton class.
Singleton class is a design pattern. In this pattern there should be only one copy of object of the singleton class. These can be like the init process in the system. The system can contain any number of other processes but only one init process.
The implementation requires use of a private constructor to prevent any object from creating the object directly. A static member which is to mark the creation of the first and only object for the entire program. And a method to call the private constructor.
Similarly any non-sharable resources like printer can be quoted as examples. These should be implemented in such a way that they work well in multi-threaded environments too.
Usually they are implemented by mechanisms similar to that of semaphores or using a static member of the class.
Disadvantages of patterns :
Pattern are not always advantageous as they might lead to unnecessary complication of the code. Don't use pattern unless they are really necessary and don't overuse the design patterns.
Anti Pattens:
These refer to the patterns that exist in the real world and they are counter productive and often lead to bad consequences. For example : Hard coding and not rechecking the code having a blind faith in the code .
No comments:
Post a Comment