Solid principles are a set of instructions on how to write code for production-ready software. Every software developer has to know these crucial principles to develop any application, Solid stands for
- S - Single responsibility principle
- O - Open/Closed principle
- L - Liskov’s substitution principle
- I - Interface segregation principle
- D - Dependency inversion principle
Single Responsibility Principle :
A class should have a single responsibility for handling processes, and if there is anything to change, it should not affect the other classes. The main objective of the single responsibility principle is to design a software component with attributes and methods that are related to each other, and it should not handle more stuff; the smaller the class, the better.
-
It can have any number of methods if all are coupled with each other; otherwise, we need to separate those methods into separate classes.
Class Game: def initializer_method(self): pass def draw_method(self): pass def running_method(self): pass def endCond_method(self): pass
In the above example, we have to decouple all of the methods in the game class since some of them (draw, running) are not related to each other.
Open-Closed Principle :
-
Open/closed principle is all about open for extension but closed for modification.
It is co-related to the single responsibility principle. The code which we are writing should be capable of adding extra features without breaking the existing code.
def read_file(file): return open(file, "r").read() def get_text_from_url(URL): return text def count_word_occurrences(word, content): counter = 0 for e in content.split(): if word.lower() == e.lower(): counter += 1 return counter def csv_reader(file): return text
In the above example, we are counting the number of words in a file by reading through the file as well as from the web. What happens when we want to read a file from another resource, like a CSV file? We can create a function to read CSV data and return the text as above to the count_word function.
Liskov’s Substitution Principle :
It states that objects of a parent class should be replaceable with objects of its subclasses without breaking the existing code/application.
-
For example, Consider the below one mixer class is inheriting the kitchen parent class, what if we want to add another class Owen which has to inherit from the Kitchen class, then we can call those methods alone will work but we have to use all the methods from the parent class.
class kitchen(): def on(): pass def off(): pass def set_level(): pass class mixer(Kitchen): def on(): pass def off(): pass def set_level(): pass class mixer(Kitchen): def on(): pass def off(): pass
-
So to overcome this we can create another class to set the level of the mixer and we can inherit that class and use its methods of it.
class kitchen(): def on(): pass def off(): pass class mixer_level(kitchen): def set_level(): pass class mixer(mixer_level): def on(): pass def off(): pass def set_level(): pass class mixer(Kitchen): def on(): pass def off(): pass
Interface Segregation Principle :
A class or function should not have all the functionalities in a single method; instead, they should be separated.
-
In the example below, we force the function to read data from both the URL and the file; however, what if the class that invokes this function does not need to fetch data from the URL? In that case, we must create a separate class for that functionality. If the class needs to read data from both, they can initialise objects for both classes and invoke the main function.
def get_text_from_url(URL): pass def count_word_occurrences(word, content): file_data=open(file, "r").read() url_data = get_text_from_url(URL) counter = 0 for e in content.split(): if word.lower() == e.lower(): counter += 1 return counter
Dependency Inversion :
This principle states that higher-level modules should not depend on lower-level modules. Instead, both should depend on abstractions.
In the below example, Food, production is like the base class and if we want to add another food we can create another class and inherit from the food class without breaking it. In this way low and high level classes is depending on the abstract class FOOD.
```
class FOOD:
def bake(self):
pass
def eat(self):
pass
class Bread(FOOD):
def bake(self):
print("Bread was baked")
def eat(self):
print("Bread was eaten")
class Production:
def __init__(self, food):
self.food = food
def produce(self):
self. food.bake()
def consume(self):
self. food.eat()
ProduceBread = Production(Bread())
```
Top comments (0)