DEV Community

viyashdoss
viyashdoss

Posted on

Solid Principles - Python

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())
```
Enter fullscreen mode Exit fullscreen mode

References

Top comments (0)