SOLID principles:
- S Single Responsibility - Should have single reason to change and should be related to its primary objective.
- O Open Closed - add features by extension, not by modification
- L Liskov Substitution
- I Interface Segregation
- D Dependecny Inversion
AntiPattern:
God Object : Reverse of Single Responsibility ie., 1 class doing everything
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Single Responsibility : A class should have only one job
Example :
class User:def __init__(self, name: str): self.name = namedef get_name(self) :passdef save(self, user: User): pass
Problem: User class is taking responsibility of Saving as well .
Solution :
class User:def __init__(self, name: str): self.name = namedef get_name(self): passclass UserDB:def save(self, user: User):pass
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Open Closed : Classes should be open for extension, not for modification.
Example :
Open Closed : Classes should be open for extension, not for modification.
Example :
class bottle:def __init__(self, season, price):self.season = seasonself.price = pricedef give_discount(self):if self.season == 'normal': return self.priceif self.season == 'festival': return self.price * 0.1
Problem : Let’s imagine you have a store, and you give a discount of 20% to your favorite customers using this class:
When you decide to offer double the 20% discount to VIP customers. You may modify the class
Solution:
class bottle:def __init__(self, season, price):self.season = seasonself.price = pricedef give_discount(self):return self.price
class Festival_bottle_price(bottle):def give_discount(self): return self.price * 0.1
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Liskov Substitution Principle: A sub-class can assume the place of its super-class without errors.
Example :
Liskov Substitution Principle: A sub-class can assume the place of its super-class without errors.
Example :
class Bird():def fly(self):pass
class Duck(Bird):def fly(self):passclass penguin(Bird):def fly(self):pass
Problem : This breaks LSP.As penguin cannot fly hence this causes error
Solution :
class Bird():passclass FlyingBirds(Bird) :def fly(self):passclass Duck ( FlyingBirds):passclass Ostrich ( Bird): pass
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Interface Segregation:Make interfaces that are client specific Clients should not be forced to depend upon interfaces that they do not use
Example :
Interface Segregation:Make interfaces that are client specific Clients should not be forced to depend upon interfaces that they do not use
Example :
class Machine:def print(self):raise NotImplementedError()def call(self):raise NotImplementedError()
class Printer(Machine):def print(self, document): pass
Problem : Printer object throws exception when Printer().call() is performed as it should not have been exposed in the first place.
Solution:
class Machine:def perform_operation(self):raise NotImplementedError()
class Printer(Machine):def perform_operation(self, document): passclass call_phone(Machine):def perform_operation(self, document): pass
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dependency Inversion :A: High-level modules should not depend on low-level level modules. It should depend upon its abstraction.
Example :
Dependency Inversion :A: High-level modules should not depend on low-level level modules. It should depend upon its abstraction.
Example :
class Http:def __init__(self, xml_http_service: XMLHttpService):self.xml_http_service = xml_http_service
def get(self, url: str, options: dict):self.xml_http_service.request(url, 'GET')
def post(self, url, options: dict):self.xml_http_service.request(url, 'POST')
class XMLHttpService(XMLHttpRequestService):pass
Problem:Http =high-level component , XMLHttpService= low-level component.
The Http class should care less the type of Http service you are using
Solution:
class Connection:def request(self, url: str, options: dict):raise NotImplementedError
class Http:def __init__(self, http_connection: Connection):self.http_connection = http_connection
def get(self, url: str, options: dict):self.http_connection.request(url, 'GET')
def post(self, url, options: dict):self.http_connection.request(url, 'POST')
class NodeHttpService(Connection):def request(self, url: str, options:dict):pass
class MockHttpService(Connection):def request(self, url: str, options:dict):pass