SOLID is an acronym for the five design principles.These design principles help create more maintainable and bug free applications.The five design principles in SOLID are:
- S stands for the Single Responsibility Principle
- O stands for the Open Closed Principle
- L stands for the Liskov Substitution Principle
- I stands for the Interface Segregation Principle
- D stands for the Dependency Inversion Principle
For other design priciples please refer
- Single responsibility principle
- Liskov substitution principle
- Interface segregation principle
- Dependency Inversion Principle
Here we will look into the Open closed principle.According to the open closed principle we are allowed to add behaviour to a class but not able to modify it.In other words whatever functionality is already implemented by a class we should be able to extend that functionality through inheritance but not allowed to change its existing implementation.
Lets understand this with an example.Suppose we are developing a software application for a college.A college have lots of students in different standards.Different Standards have different subjects,a student in class 10th will have different subjects then the one in class 1st.So to calculate the percentage of marks for students different criteria can be used.For example a subject such as maths can carry more weightage than a subject such as craft.
In the following example we have defined two classes
- Student Represents the Student
- Subject Represents a subject such as Maths.
The Student class declares a method called score which will calculate the average score of the student.In this method we are using a different logic for score calculation of students in Category1 and students in Category2 which are based on the class such as High school.
class Student { public string Name { get; set; } public string Address { get; set; } public string RollNo { get; set; } public int Class { get; set; } public float Score { get;set;} public List<Subject> Subjects { get; set; } public float CalculateScore() { float totalScore=0; //calculation logic for students in Category 1 if(Category==1) { //calcualte percentage float sum=Subjects.Sum(x => x.Score); int total=Subjects.Count(); totalScore=sum / total * 100; } ////calculation logic for students in Category 2 else if (Category==2) { //calcualte percentage based on weightage float sum = Subjects.Sum(x => (x.Score * x.weightage) ); int total = Subjects.Count(); totalScore = sum / total * 100; } return totalScore; } } class Subject { public string Name { get; set; } public float Score { get; set; } public float weightage { get; set; } }
So our application works fine now and is able to calculate the score of students based on his class or standard.
But if the score calculation logic changes tomorrow for students between class 6 to class 8th ,called Category 3,to include only the top 5 scoring subjects,then we may again have to modify the Student class.
else if (Category==3) { //calcualte percentage based on weightage and top 5 scoring subjects float sum = student.Subjects.OrderBy(x=>x.Score).Take(5).Sum(x => (x.Score * x.weightage)); int total = student.Subjects.Count(); totalScore = sum / total * 100; }
Every time there is change in score calculation logic our Student class needs to be modified.
Not only we have to modify the Student class we need to retest all the existing functionality and also have to redeploy the entire application.This doesn’t sound very logical.After all we should only test and deploy the new functionality and not all the existing functionality.The solution to this problem is the Open closed principle.
Instead of defining the functionality for all the Students in the common Student class we will add a new abstract class called BaseStudent .Every time we need to add a new category of Students we add a new class instead of modifying the existing Student class.The class for students in Category1 can be defined as:
public abstract class BaseStudent { public abstract float Score(); } class StudentCategory1 : BaseStudent { public string Name { get; set; } public string Address { get; set; } public string RollNo { get; set; } public int Class { get; set; } public float Score { get;set;} public List<Subject> Subjects { get; set; } //calculation logic for students in standards less than 8th public float CalculateScore() { float totalScore=0; //calcualte percentage float sum=Subjects.Sum(x => x.Score); int total=Subjects.Count(); totalScore=sum / total * 100; return totalScore; } }
Each time there is a requirement to add a new category of students we add a new StudentCategory class deriving from BaseStudent class which defines the abstract method CalculateScore.
So we have applied the open closed principle in our existing design and have got the following advantages:
- We don’t need to modify the existing Student class ,which has already been tested.
- There is less chance of breaking the existing functionality because of change in requirement.
- The new requirement can easily be accommodated as we don’t have to struggle to modify an already existing class.
Leave a Reply