SOLID were introduced by Robert C. Martin, with intention that
When these principles are applied together , a programmer will create a system which is easy to maintain and extend over time.
Can avoid:
Rigidity, Fragility, Immobility, Viscosity
Lets move the promotion determination logic from Employee class to the HRPromotions class like this
Open Closed Principle by Bertrand Meyer
Software entities should be open for extension but closed for modification.
It can be achieved by interfaces or abstract classes, rather than using concrete classes. Functionality can be added by creating new classes that implement the interfaces.
Your classes should be designed such a way that whenever fellow developers wants to change the flow of control in specific conditions in application, all they need to extend your class and override some functions and that’s it.
“extending the AreaCalculator class to also calculate the area of triangles isn’t very hard, is it?”. Of course in this very basic scenario it isn’t but it does require us to modify the code. That is, AreaCalculator isn’t closed for modification as we need to change it in order to extend it. Or in other words: it isn’t open for extension.
When these principles are applied together , a programmer will create a system which is easy to maintain and extend over time.
Can avoid:
Rigidity, Fragility, Immobility, Viscosity
Single Responsibility Principle
Open Closed Principle
Liskov Substitution Principle
Interface Segregation Principle (separation)
Dependency Inversion Principle
Single Responsibility:
A class should have one and only one responsibility. There cannot be more than one reason to change for a class. A class should have only one job to do. It should be cohesive (integrated) i.e. everything in class should be related to one purpose.
Similarly, lets move the income tax calculation logic from
Employee class to FinITCalculations class –
Our
Employee class now remains with a single responsibility of maintaining core employee attributes –Open Closed Principle by Bertrand Meyer
Software entities should be open for extension but closed for modification.
It can be achieved by interfaces or abstract classes, rather than using concrete classes. Functionality can be added by creating new classes that implement the interfaces.
Your classes should be designed such a way that whenever fellow developers wants to change the flow of control in specific conditions in application, all they need to extend your class and override some functions and that’s it.
public class Rectangle { public double Width { get; set; } public double Height { get; set; } }public class AreaCalculator
{ public double Area(Rectangle[] shapes) { double area = 0; foreach (var shape in shapes) { area += shape.Width*shape.Height; } return area; } }public double Area(object[] shapes)
{ double area = 0; foreach (var shape in shapes) { if (shape is Rectangle) { Rectangle rectangle = (Rectangle) shape; area += rectangle.Width*rectangle.Height; } else { Circle circle = (Circle)shape; area += circle.Radius * circle.Radius * Math.PI; } } return area; }
“extending the AreaCalculator class to also calculate the area of triangles isn’t very hard, is it?”. Of course in this very basic scenario it isn’t but it does require us to modify the code. That is, AreaCalculator isn’t closed for modification as we need to change it in order to extend it. Or in other words: it isn’t open for extension.
A solution that abides by the Open/Closed Principle
public abstract class Shape { public abstract double Area(); }public class Rectangle : Shape
{ public double Width { get; set; } public double Height { get; set; } public override double Area() { return Width*Height; } }public class Circle : Shape
{ public double Radius { get; set; } public override double Area() { return Radius*Radius*Math.PI; } }public double Area(Shape[] shapes)
{ double area = 0; foreach (var shape in shapes) { area += shape.Area(); } return area; }
Liskov Substitution Principle
objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.
If the subtype is not replaceable for the supertype reference, then in order to support the subtype instances as well we go ahead and make changes to the existing code and add the support. This is a clear violation of OCP.
class Bird {
public void fly(){}
public void eat(){}
}
class Crow extends Bird {}
class Ostrich extends Bird{
fly(){
throw new UnsupportedOperationException();
}
}
public BirdTest{
public static void main(String[] args){
List<Bird> birdList = new ArrayList<Bird>();
birdList.add(new Bird());
birdList.add(new Crow());
birdList.add(new Ostrich());
letTheBirdsFly ( birdList );
}
static void letTheBirdsFly ( List<Bird> birdList ){
for ( Bird b : birdList ) {
b.fly();
}
}
}
As soon as an Ostrich instance is passed, it blows up!!! Here the sub type is not replaceable for the super type.
In the above scenario we can factor out the fly feature into- Flight and NonFlight birds.
class Bird{
public void eat(){}
}
class FlightBird extends Bird{
public void fly()()
}
class NonFlight extends Bird{}
Integration Segregation Principle
Many client specific interfaces are better than one general purpose interface
No comments:
Post a Comment