In this Article we will learn
· Open Closed Principle
· Implementation guidelines of Open closed Principle
· And will implement this Principle with a simple example
O in the SOLID is acronym for "Open/Closed Principle" also known as OCP.
Definition : In object-oriented programming, the open/closed principle states that "software entities such as classes, modules, functions, etc. should be open for extension, but closed for modification"
Definition : In object-oriented programming, the open/closed principle states that "software entities such as classes, modules, functions, etc. should be open for extension, but closed for modification"
· Which means, any new functionality should be implemented by adding new classes, attributes and methods, instead of changing the current ones or existing ones.
· Bertrand Meyer is generally credited for having originated the term open/closed principle and This Principle is considered by Bob Martin as "the most important principle of object-oriented design".
Implementation guidelines
· 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 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.
Pit falls of Not following OCP : What if I do not follow Open closed principle during a requirement enhancement in the development process. In that case, we end up with the following disadvantages
1. If a class or a function always allows the addition of new logic, as a developer we end up testing the entire functionality along with the requirement.
2. Also, as a developer we need to ensure to communicate the scope of the changes to the Quality Assurance team in advance so that they can gear up for enhanced regression testing along with the feature testing.
3. Step 2 above is a costly process to adapt for any organization
4. Not following the Open Closed Principle breaks the SRP since the class or function might end up doing multiple tasks.
5. Also, if the changes are implemented on the same class, Maintenance of the class becomes difficult since the code of the class increases by thousands of unorganised lines.
Hope the above counter facts help in understanding on why we need to follow the open closed principle.
Below code demonstrates how we can achieve Open Closed Principle
Code before Open Closed Principle
Below code demonstrates how we can achieve Open Closed Principle
Code before Open Closed Principle
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenClosedDemo
{
public class Employee
{
Employee() { }
public Employee(int id, string name, string type)
{
this.ID = id;
this.Name = name;
this.EmployeeType = type;
}
public int ID { get; set; }
public string EmployeeType { get; set; }
public string Name { get; set; }
public decimal CalculateBonus(decimal salary)
{
if (this.EmployeeType == "Permanent")
return salary * .1M;
else
return salary * .05M;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenClosedDemo
{
class Program
{
static void Main(string[] args)
{
Employee empJohn = new Employee(1, "John", "Permanent" );
Employee empJason = new Employee(2, "Jason", "Temp");
Console.WriteLine(string.Format("Employee {0} Bonus: {1}",
empJohn.ToString(),
empJohn.CalculateBonus(100000).ToString()));
Console.ReadLine();
}
}
}
|
Code after Open Closed Principle Implementation
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenClosedDemo
{
public abstract class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public Employee()
{
}
public Employee(int id, string name )
{
this.ID = id; this.Name = name;
}
public abstract decimal CalculateBonus(decimal salary);
public override string ToString()
{
return string.Format("ID : {0} Name : {1}", this.ID, this.Name);
}
}
public class PermanentEmployee : Employee
{
public PermanentEmployee()
{ }
public PermanentEmployee(int id, string name) : base(id, name)
{ }
public override decimal CalculateBonus(decimal salary)
{
return salary * .1M;
}
}
public class TemporaryEmployee : Employee
{
public TemporaryEmployee()
{ }
public TemporaryEmployee(int id, string name) : base(id, name)
{ }
public override decimal CalculateBonus(decimal salary)
{
return salary * .05M;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenClosedDemo
{
class Program
{
static void Main(string[] args)
{
Employee empJohn = new PermanentEmployee(1, "John" );
Employee empJason = new TemporaryEmployee(2, "Jason" );
Console.WriteLine(string.Format("Employee {0} Bonus: {1}",
empJohn.ToString(),
empJohn.CalculateBonus(100000).ToString()));
Console.WriteLine(string.Format("Employee {0} Bonus: {1}",
empJason.ToString(),
empJason.CalculateBonus(150000).ToString()));
Console.ReadLine();
}
}
}
|
EmoticonEmoticon