The open-closed principle is the second principle of the SOLID design principles, namely:
The open-closed principle states that “the software entities should be open for extension but closed for modification”.
The idea of the principle is to design the code in a way such that new entities or functionalities can be added without modifying the existing code.
Consider a simple example of finding the index of a value in an array. The code will be as follows:
#include <iostream>using namespace std;int find(int key, int arr[], int arrsize){for(int i=0; i<arrsize; i++){if(arr[i] == key){return i;}}return -1;}int main() {int arr[4] = {1, 2, 5, 7};int key = 5;cout<<key<<" found at index: "<<find(key, arr, 4);return 0;}
The find
function returns the index of key
in the array arr
of having arrsize
number of elements. If key
is not present in arr
, it returns -1.
Now consider that we also want to find a word in an array of words. We will have to modify the above code as follows:
#include <cstring>#include <iostream>using namespace std;int find(int key, int arr[], int arrsize){for(int i=0; i<arrsize; i++){if(arr[i] == key){return i;}}return -1;}int find(const char* key, const char* arr[], int arrsize){for(int i=0; i<arrsize; i++){if(strcmp(arr[i], key) == 0){return i;}}return -1;}int main() {int arr[4] = {1, 2, 5, 7};int key = 5;cout<<key<<" found at index: "<<find(key, arr, 4)<<endl;const char* arr2[] = {"abc", "edf", "fwet", "zc"};const char* key2="edf";cout<<key2<<" found at index: "<<find(key2, arr2, 4);return 0;}
Notice that the only difference between the functions is in the data types of input parameters of the
find
function and inif
statements in lines 7 and 16, where the key and an array index are compared to see if they are equal.
If we want to define the find
function of another data type, the input parameters and the comparison of the find
function will be modified and we will write another find
function. This violates the open-closed principle, because a new function is written for each data type, which means the code is not open for extension.
The open-closed principle proposes a solution to the aforementioned problem.
We can write a single find
function that can be extended to as many data types as required without any modification in already written code.
#include <cstring>#include <iostream>using namespace std;bool cmp(int k1, int k2){if(k1==k2){return true;}else{return false;}}bool cmp(const char* k1, const char* k2){if(strcmp(k1, k2) == 0){return true;}else{return false;}}template <typename T>int find(const T key, const T arr[], int arrsize){for(int i=0; i<arrsize; i++){if(cmp(arr[i],key)){return i;}}return -1;}int main() {int arr[4] = {1, 2, 5, 7};int key = 5;cout<<key<<" found at index: "<<find<int>(key, arr, 4)<<endl;const char* arr2[] = {"abc", "edf", "fwet", "zc"};const char* key2="edf";cout<<key2<<" found at index: "<<find<const char*>(key2, arr2, 4);return 0;}
The above find
function is a template-based solution. Each data type implements its own cmp
function that compares if two values are equal. To implement the find
function of another data type, no modification is required. We only need to write the cmp
function of that data type. Thus, the code above follows the open-closed principle.
Free Resources