- These are five principles of object oriented programming, helps in writing clean code and build good architecture.
- These are first introduced by Robert J. Martin (a.k.a Uncle Bob).
- SOLID stands for :
- Single Responsibility Principle
- The Open-Closed Principle
- The Liskov Substitution Principle
- Interface Segregation Principle
- The Dependency Inversion Principle
Single Responsibility Principle
- Simple definition is that a Class should be responsible for only one function
class Invoice:
def calculate(self):
# calculates total amount
def print_invoice(self):
# Prints invoice in given format
def save_invoice(self):
# Saves to file
Explanation:
- In the above example, let's say Invoice class will calculate and prints the invoice slip
- So, here SRP is voilating.
- Because, SRP states that there should be only one reason to change or modify a class
- But in the above example, If you want to change the format of invoice printing you will have to change invoice class.
- If you want to change some business logic in calculate method again you have to change the invoice class
- So, here same class is responsible for two things Soluton:
class InvoiceCalculate:
def calculate(self):
# calculates total amount
class PrintInvoice:
def print_invoice(self):
# Prints invoice in given format
class SaveInvoice:
def save_invoice(self):
# Saves to file
- Here we are transporting three methods to three different class, as they have different functionalities
The Open-Closed Principle
- This principle states that class should be closed for modification and open for extension
- Meaning, If you want to add fuctionality to the class you don't want to change the existing code as this will arise bugs
- Let's say if you want to save the invoice to both database and file
- You can do as follows Example:
class SaveInvoice:
def save_invoice(self):
# Saves to file
def save_invoice_database(self):
# Saves to database
- In the above code Open-Closed principle has been violated
- Because, we are changing or modifying the existing class for adding a new functionality
- So, to solve the above problem we can use abstraction Solution:
- we will create SaveInvoice as a abstract class instead of concrete class and we will inherit the class to impliment the required function
from abc import ABC,abstractmethod
# Base class
class SaveInvoice(ABC):
@abstractmethod
def save(self):
pass
# class to imliment save function to save invoice to file
class SaveToFile(SaveInvoice):
def save(self):
# Save to file
# class to impliment save function to save invoice to database
class SaveToDatabase(SaveInvoice):
def save(self):
# Save to database
- In the above example we have used abstraction to overcome the problem of modifying the existing class
- Even in future if we want to save invice to someother source we can always create a class corresponding to that and impliment save method from base class
The Liskov Substitution Principle
- This principle states that Subclasses should be substitutable for their base classes
- In other words, person who is using our code should not know which object he is implimenting or using
example:
- This is closly related to the open closed priciple
from abc import ABC,abstractmethod
class polygone(ABC):
def area(self):
pass
class rectangle(polygone):
def __init__(self,a,b):
self.a = a
self.b = b
def area(self):
return self.a*self.b
class square(polygone):
def __init__(self,l):
self.l = l
def area(self):
return self.l * self.l
rect = rectangle(a,b)
print(rect.area())
print(isinstance(rect,polygone))
- The above example is similar to open-close principle
- Here, we can replace rect object with parent object polygone
- So, Lisko Substitution principle is followed
Interface Segregation Principle
- The Interface Segregation Principle is about separating the interfaces.
- Keep multiple interfaces for multiple use cases
from abc import ABC,abstractmethod
class sim(ABC):
def call(self):
pass
def message(self):
pass
def network(self):
pass
- In the above example although the functionalities of these methods are different they are in same abstract class.
- This will create obligation to impliment all the methods even though you want only call method
Solution
from abc import ABC,abstractmethod
class sim_call(ABC):
@abstractmethod
def call(self):
pass
class sim_message(ABC):
@abstractmethod
def message(self):
pass
class sim_network(ABC):
@abstractmethod
def network(self):
pass
- Here, we have used three seperate abstract classes for all these different functions
The Dependency Inversion Principle
- The Dependency Inversion principle states that our classes should depend upon interfaces or abstract classes instead of concrete classes and functions.
- This is related to the open-close principle
- we can use the same example as in Open-close principle
- If we observe the given example, we have removed the SaveInvoice class which is concrete class and replaced them with abstract class to achieve DI principle
Top comments (0)