SOLID Design Principles (OCP)
In the previous article, we talked about the first Principle of SOLID Principles series. we demonstrated an example to make everything clear and obvious.
Today, we are going to talk about the second principle…
Open-Closed Principle (OCP)
Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.
Which means, an entity shall allow its behavior to be extended without modifying its source code. In other words, High-level policy doesn’t know about low-level details.
So, How we can apply the OCP?
The simplest way to apply OCP is to implement the new functionality on new derived (sub) classes that inherit the original class implementation. Another way is to allow the client to access the original class with an abstract interface.
So, at any given point of time when there is a requirement change instead of touching the existing functionality, it’s always suggested to create new classes and leave the original implementation untouched.
Let’s have an example to demonstrate the OCP,…
The below class creates an instance of Employee with some properties like name, id, salary and type which indicates contract employee, permanent employee. freelance one, etc...
Here is the implementation
class Employee(private var name: String, private var id: Int, private var type: String) {
private var employeeSalary: Double = 0.0
fun setName(name: String) {
this.name = name
}
fun getName(): String {
return name
}
fun setId(id: Int) {
this.id = id
}
fun setType(type: String) {
this.type = type
}
fun getType(): String {
return type
}
fun setSalary(salary: Double) {
employeeSalary = salary
}
fun calculateBonous(type: String): Double {
when (type) {
"Permanent" -> return employeeSalary * 1.5
"Contract" -> return employeeSalary * 1.25
else -> return employeeSalary * 1.3
}
}
}
Now, If we need to add a new employee type (sponsor) and calculate the bonus for him it will require to touch the Employee class and do some modifications especially for the calculateBonous method which violate the OCP.
So, to avoid such mistake we MUST refactor the Employee class to be like...
abstract class Employee(private var name: String, private var id: Int, private var type: String) {
private var employeeSalary: Double = 0.0
fun setName(name: String) {
this.name = name
}
fun getName(): String {
return name;
}
fun setId(id: Int) {
this.id = id
}
fun setType(type: String) {
this.type = type
}
fun getType(): String {
return type
}
fun setSalary(salary: Double) {
employeeSalary = salary
}
fun getSalary(): Double {
return employeeSalary
}
abstract fun calculateBonus(): Double
}
for type permanent…
class PermanentEmployee(name: String, id: Int, type: String) : Employee(name, id, type) {
override fun calculateBonus(): Double {
return getSalary() * 1.5
}
}
for type contract…
class ContractEmployee(name: String, id: Int, type: String) : Employee(name, id, type) {
override fun calculateBonus(): Double {
return getSalary() * 1.25
}
}
for type sponsor…
class SponsorEmployee(name: String, id: Int, type: String) : Employee(name, id, type) {
override fun calculateBonus(): Double {
return getSalary() * 1.25
}
}
And so on…
The implementation will be like...
fun main() {
var employee1 = ContractEmployee("Irshad", 120, "Permanent")
employee1.setSalary(500.0)
var employee2 = PermanentEmployee("Nirag", 130, "Contract")
employee2.setSalary(800.0)
var employees: Array<Employee> = arrayOf(employee1, employee2)
for (item in employees) {
System.out.println(
"Employee with name: ${item.getName()} with type: ${item.getType()} has bonus: ${item.calculateBonus()}"
)
}
}
After changing the implementation of Employee class it becomes untouchable any more and every time we create a new employee type we just create a new class and extend the parent one.
Summary
We have seen how it's simple for avoiding falling in mistakes and its better to think twice rather than hit the code multiple times for every change. you may think it's easy to do so but, if you are working on a huge team it will be hard to track all these changes and will become a fragile project!
Remember always you are a Programmer, not Plumper! Thanks for continuing the article. If you like it just clap and share!
see you at the third principle!