Open-Closed Principle is a coding principle where our code will be Open for Extension but Closed for Modification. This means we will not modify the existing code that might break its correctness but we will add new code to extend the functionality of the application.
For example, if I want to evaluate and rank any student based on the score, I can write the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.huongdankotlin.designpattern.ocp class Student { fun classify(score: Int): Classification { if (score > 9) { return Classification.EXCELLENCE } if (score > 8) { return Classification.GOOD } if (score > 6) { return Classification.NORMAL } return Classification.MEDIUM } } |
With enum Classification with the following content:
1 2 3 4 5 6 7 8 |
package com.huongdankotlin.designpattern.ocp enum class Classification { NORMAL, MEDIUM, GOOD, EXCELLENCE } |
Students with a score greater than 9 will be graded excellence, greater than 8 will be good, greater than 6 will be normal, and the remaining will be medium. I will run the following example:
1 2 3 4 5 6 7 |
package com.huongdankotlin.designpattern.ocp fun main() { val student = Student() println(student.classify(7)) } |
Result:
It doesn’t matter if in the future I want to add another rating criterion, if the score is less than 5, it will be classified as weak. At this point, if I don’t apply Open-Closed Principal, I will have to modify the clarify() method in the Student class to achieve my wish. Maybe for simple applications, you will see no big deal if we modify the clarify() method directly, but imagine you are working with complex applications, every time you modify existing classes, it is possible to break previously worked features of the application.
The better way to write in this case with Open-Closed Principal is that we will add a class that takes care of ranking students with scores less than 5 as follows:
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.huongdankotlin.designpattern.ocp class WeakStudent: Student() { override fun classify(score: Int): Classification { if (score < 5) { return Classification.WEAK } return super.classify(score); } } |
Enum Classification also needs to be updated as follows:
1 2 3 4 5 6 7 8 9 |
package com.huongdankotlin.designpattern.ocp enum class Classification { WEAK, NORMAL, MEDIUM, GOOD, EXCELLENCE } |
Now, modify the example application using the WeakStudent class:
1 2 3 4 5 6 7 |
package com.huongdankotlin.designpattern.ocp fun main() { val student = WeakStudent() println(student.classify(7)) } |
You will see the following result:
The result is still the same as above, but if you change the score to 4:
1 2 3 4 5 6 7 |
package com.huongdankotlin.designpattern.ocp fun main() { val student = WeakStudent() println(student.classify(4)) } |
you will see the WEAK rating returned:
We have added the feature to the application, but there is no need to modify the existing Student class.