Created
July 13, 2021 12:57
-
-
Save janaki-sasidhar/685ab5a4348b71aff1ace6b24e1dad0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
SOLID DESIGN PRINCIPLES | |
[S]INGLE RESPONSIBILITY | |
[O]PEN / CLOSED | |
[L]ISKOV SUBSTITUTION | |
[I]NTERFACE SEGREGATION | |
[D]EPENDENCY INVERSION | |
''' | |
# CODE CONTENT FROM ARJAN CODE (https://www.youtube.com/watch?v=pTB30aXS77U) | |
# DO SUBSCRIBE TO HIS CHANNEL. GREAT CONTENT OVER THERE | |
# INITIAL CODE OF SALE SYSTEM (ORDDER AND PAYMENT HANDLING) | |
from typing import List | |
class Order: | |
items : List = [] | |
quantities : List = [] | |
prices : List = [] | |
status : str = 'open' | |
def add_item(self,name,quantity,price) -> None: | |
self.items.append(name) | |
self.quantities.append(quantity) | |
self.price.append(price) | |
def total_price(self) -> float: | |
total = 0 | |
for i in range(len(self.prices)): | |
total += self.quantities[i] * self.total | |
return total | |
def pay(self,payment_type,security_code) -> None: | |
if payment_type == 'debit': | |
print('PROCESSING DEBIT PAYMENT TYPE') | |
print(f'VERIFYING SECURITY CODE {security_code}') | |
self.status = 'paid' | |
elif payment_type == 'credit': | |
print('PROCESSING CREDIT PAYMENT TYPE') | |
print(f'VERIFYING SECURITY CODE {security_code}') | |
self.status = 'paid' | |
else: | |
raise Exception(f'Unknown payment type : {payment_type}') | |
''' | |
USING THE CLASS ABOVE | |
order = Order() | |
order.add_item('keyboard',1,50) | |
order.add_item('SSD',1,150) | |
order.add_item('USB CABLE',2,5) | |
print(order.total_price()) | |
order.pay('debit','055050') | |
''' | |
############# SINGLE RESPONSIBILITY #################### | |
''' | |
CLASSES AND METHODS SHOULD HAVE SINGLE RESPONSIBILITY SO THAT THEY CAN BE RESUSED. | |
IN ABOVE CASE ORDER CAN HAVE add_item AND total_price BUT pay METHOD IS NOT NEEDED IN THERE . | |
ORDER HAS TOO MANY RESPONSIBILITIES | |
WE CAN MOVE THE pay METHOD TO A NEW CLASS SO IT CAN BE REUSED | |
''' | |
from typing import List | |
class Order: | |
items : List = [] | |
quantities : List = [] | |
prices : List = [] | |
status : str = 'open' | |
def add_item(self,name,quantity,price) -> None: | |
self.items.append(name) | |
self.quantities.append(quantity) | |
self.price.append(price) | |
def total_price(self) -> float: | |
total = 0 | |
for i in range(len(self.prices)): | |
total += self.quantities[i] * self.total | |
return total | |
class PaymentProcessor: | |
def pay_debit(self,order,security_code) -> None: | |
print('PROCESSING DEBIT PAYMENT TYPE') | |
print(f'VERIFYING SECURITY CODE {security_code}') | |
order.status = 'paid' | |
def pay_credit(self,order,security_code) -> None: | |
print('PROCESSING DEBIT PAYMENT TYPE') | |
print(f'VERIFYING SECURITY CODE {security_code}') | |
order.status = 'paid' | |
''' | |
USING THE CLASS ABOVE | |
order = Order() | |
order.add_item('keyboard',1,50) | |
order.add_item('SSD',1,150) | |
order.add_item('USB CABLE',2,5) | |
print(order.total_price()) | |
payment_process = PaymentProcessor() | |
payment_process.pay_debit(order,'055050') | |
SWEET !!! | |
''' | |
################### OPEN / CLOSED ############################# | |
''' | |
CODE WRITTEN SHOULD BE OPEN FOR EXTENSIBILITY LIKE INHERITING | |
BUT CLOSED FOR MODIFICATION SO WE SHOULDNT NEED TO MODIFY THE ORIGINAL CODE INI ORDER TO MODIFY | |
''' | |
''' | |
IN THE ABOVE EXAMPLE , IF WE WANT TO ADD ANOTHER PAYMENT METHOD , WE WANT TO MODIFY THE EXISTING PaymentProcessor Code. | |
''' | |
from abc import ABC ,abstractmethod | |
class Order: | |
items : List = [] | |
quantities : List = [] | |
prices : List = [] | |
status : str = 'open' | |
def add_item(self,name,quantity,price) -> None: | |
self.items.append(name) | |
self.quantities.append(quantity) | |
self.price.append(price) | |
def total_price(self) -> float: | |
total = 0 | |
for i in range(len(self.prices)): | |
total += self.quantities[i] * self.total | |
return total | |
class PaymentProcessor(ABC): | |
@abstractmethod | |
def pay(self,order,security_code): | |
pass | |
class DebitPaymentProcessor(PaymentProcessor): | |
def pay(self,order,security_code): | |
print('PROCESSING Debit type') | |
print(f'Verifying security code {security_code}') | |
order.status = 'paid' | |
class CreditPaymentProcessor(PaymentProcessor): | |
def pay(self,order,security_code): | |
print('PROCESSING Credit type') | |
print(f'Verifying security code {security_code}') | |
order.status = 'paid' | |
class PayPalPaymentProcessor(PaymentProcessor): | |
def pay(self,order,security_code): | |
print('PROCESSING PayPal type') | |
print(f'Verifying security code {security_code}') | |
order.status = 'paid' | |
''' | |
USING THE CLASS ABOVE | |
order = Order() | |
order.add_item('keyboard',1,50) | |
order.add_item('SSD',1,150) | |
order.add_item('USB CABLE',2,5) | |
print(order.total_price()) | |
payment_process = DebitPaymentProcessor() | |
payment_process.pay_debit(order,'055050') | |
SWEET !!! | |
''' | |
################## LISKOV SUBSTITUTION ###################### | |
''' | |
If there are any objects in the code , we should be able to replace those objects with the instances of the subtypes or subclasses without altering the correctness of program. | |
The thing is the paypal doesnt work with security codes but email. | |
''' | |
from abc import ABC ,abstractmethod | |
class Order: | |
items : List = [] | |
quantities : List = [] | |
prices : List = [] | |
status : str = 'open' | |
def add_item(self,name,quantity,price) -> None: | |
self.items.append(name) | |
self.quantities.append(quantity) | |
self.price.append(price) | |
def total_price(self) -> float: | |
total = 0 | |
for i in range(len(self.prices)): | |
total += self.quantities[i] * self.total | |
return total | |
class PaymentProcessor(ABC): | |
@abstractmethod | |
def pay(self,order): | |
pass | |
class DebitPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code): | |
self.security_code = security_code | |
def pay(self,order): | |
print('PROCESSING Debit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class CreditPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code): | |
self.security_code = security_code | |
def pay(self,order): | |
print('PROCESSING Credit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class PayPalPaymentProcessor(PaymentProcessor): | |
def __init__(self,email): | |
self.email = email | |
def pay(self,order): | |
print('PROCESSING PayPal type') | |
print(f'Verifying security code {self.email}') | |
order.status = 'paid' | |
''' | |
USING THE CLASS ABOVE | |
order = Order() | |
order.add_item('keyboard',1,50) | |
order.add_item('SSD',1,150) | |
order.add_item('USB CABLE',2,5) | |
print(order.total_price()) | |
payment_process = PayPalPaymentProcessor('[email protected]') | |
payment_process.pay_debit(order) | |
SWEET !!! | |
''' | |
##################### INTERFACE SEGGREGATION ########################## | |
''' | |
SEVERAL SPECIFIC INTERFACES INSTEAD OF ONE GENERAL INTERACE | |
''' | |
# modifying original code to add sms verification and then working on seggregation | |
from abc import ABC ,abstractmethod | |
class Order: | |
items : List = [] | |
quantities : List = [] | |
prices : List = [] | |
status : str = 'open' | |
def add_item(self,name,quantity,price) -> None: | |
self.items.append(name) | |
self.quantities.append(quantity) | |
self.price.append(price) | |
def total_price(self) -> float: | |
total = 0 | |
for i in range(len(self.prices)): | |
total += self.quantities[i] * self.total | |
return total | |
class PaymentProcessor(ABC): | |
@abstractmethod | |
def pay(self,order): | |
pass | |
@abstractmethod | |
def auth_sms(self): | |
pass | |
class DebitPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code): | |
self.security_code = security_code | |
self.verified = False | |
def auth_sms(self,code): | |
print('VERIFYING SMS CODE {code}') | |
self.verified=True | |
def pay(self,order): | |
print('PROCESSING Debit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class CreditPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code): | |
self.security_code = security_code | |
def auth_sms(self,code): | |
raise Exception('CREDIT CARD PAYMNETS DOESNT SUPPORT SMS CODE AUTHORIZATION') | |
def pay(self,order): | |
print('PROCESSING Credit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class PayPalPaymentProcessor(PaymentProcessor): | |
def __init__(self,email): | |
self.email = email | |
self.verified = False | |
def auth_sms(self,code): | |
print('VERIFYING SMS CODE {code}') | |
self.verified=True | |
def pay(self,order): | |
print('PROCESSING PayPal type') | |
print(f'Verifying security code {self.email}') | |
order.status = 'paid' | |
''' | |
NOW WE DONT WANT TO RAISE EXCEPTION FOR CREDITCARD BUT GRACEFULLY DO THINGS . | |
IN BELOW WE MODIFIED SO WE BEAUTIFULLY SEGGREGATED DEBIT , PAYPAL WITH CREDIT WITH EXTENDING FROM MULTIPLE SUBCLASSES | |
''' | |
from abc import ABC ,abstractmethod | |
class Order: | |
items : List = [] | |
quantities : List = [] | |
prices : List = [] | |
status : str = 'open' | |
def add_item(self,name,quantity,price) -> None: | |
self.items.append(name) | |
self.quantities.append(quantity) | |
self.price.append(price) | |
def total_price(self) -> float: | |
total = 0 | |
for i in range(len(self.prices)): | |
total += self.quantities[i] * self.total | |
return total | |
# auth_sms not needed here | |
class PaymentProcessor(ABC): | |
@abstractmethod | |
def pay(self,order): | |
pass | |
# we used auth_sms here but not pay because its inherited by default | |
class PaymentProcessor_SMS(PaymentProcessor): | |
@abstractmethod | |
def auth_sms(self): | |
pass | |
class DebitPaymentProcessor(PaymentProcessor_SMS): | |
def __init__(self,security_code): | |
self.security_code = security_code | |
self.verified = False | |
def auth_sms(self,code): | |
print('VERIFYING SMS CODE {code}') | |
self.verified=True | |
def pay(self,order): | |
print('PROCESSING Debit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class CreditPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code): | |
self.security_code = security_code | |
def pay(self,order): | |
print('PROCESSING Credit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class PayPalPaymentProcessor(PaymentProcessor_SMS): | |
def __init__(self,email): | |
self.email = email | |
self.verified = False | |
def auth_sms(self,code): | |
print('VERIFYING SMS CODE {code}') | |
self.verified=True | |
def pay(self,order): | |
print('PROCESSING PayPal type') | |
print(f'Verifying security code {self.email}') | |
order.status = 'paid' | |
''' | |
USING COMPOSITION INSTEAD OF MULTIPLE SUBCLASSES. LEARN ABOUT COMPOSITION AND WHY ITS BETTER THAN INHERITANCE | |
''' | |
from abc import ABC ,abstractmethod | |
class Order: | |
items : List = [] | |
quantities : List = [] | |
prices : List = [] | |
status : str = 'open' | |
def add_item(self,name,quantity,price) -> None: | |
self.items.append(name) | |
self.quantities.append(quantity) | |
self.price.append(price) | |
def total_price(self) -> float: | |
total = 0 | |
for i in range(len(self.prices)): | |
total += self.quantities[i] * self.total | |
return total | |
class SMSAuth: | |
authorized = False | |
def verify_code(self,code): | |
print(f'verifying code {code}') | |
self.authorized = True | |
def is_authorized(self) -> bool: | |
return self.authorized | |
class PaymentProcessor(ABC): | |
@abstractmethod | |
def pay(self,order): | |
pass | |
class DebitPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code , authorizer: SMSAuth): | |
self.authorizer = authorizer | |
self.security_code = security_code | |
def pay(self,order): | |
if not self.authorizer.is_authorized(): | |
raise Exception('not authorized') | |
print('PROCESSING Debit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class CreditPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code): | |
self.security_code = security_code | |
def pay(self,order): | |
print('PROCESSING Credit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class PayPalPaymentProcessor(PaymentProcessor): | |
def __init__(self,email,authorizer: SMSAuth): | |
self.email = email | |
self.authorizer = authorizer | |
def pay(self,order): | |
if not self.authorizer.is_authorized(): | |
raise Exception('not authorized') | |
print('PROCESSING PayPal type') | |
print(f'Verifying security code {self.email}') | |
order.status = 'paid' | |
''' | |
USING THE CLASS ABOVE | |
order = Order() | |
order.add_item('keyboard',1,50) | |
order.add_item('SSD',1,150) | |
order.add_item('USB CABLE',2,5) | |
print(order.total_price()) | |
authorizer = SMSAuth() | |
processor = DebitPaymentProcessor('002020',authorizer) | |
authorizer.verify_code(465389) | |
processor.pay(order) | |
SWEET !!! | |
''' | |
############ DEPENDENCY INVERSION ############# | |
from abc import ABC ,abstractmethod | |
class Order: | |
items : List = [] | |
quantities : List = [] | |
prices : List = [] | |
status : str = 'open' | |
def add_item(self,name,quantity,price) -> None: | |
self.items.append(name) | |
self.quantities.append(quantity) | |
self.price.append(price) | |
def total_price(self) -> float: | |
total = 0 | |
for i in range(len(self.prices)): | |
total += self.quantities[i] * self.total | |
return total | |
class Authorizer(ABC): | |
@abstractmethod | |
def is_authorized(self) -> bool: | |
return self.authorized | |
class SMSAuth(Authorizer): | |
authorized = False | |
def verify_code(self,code): | |
print(f'verifying code {code}') | |
self.authorized = True | |
def is_authorized(self) -> bool: | |
return self.authorized | |
class ROBOTAuth(Authorizer): | |
authorized = False | |
def not_a_robot(self): | |
print('ARE YOU A ROBOT ? NO') | |
self.authorized =True | |
def is_authorized(self) -> bool: | |
return self.authorized | |
class PaymentProcessor(ABC): | |
@abstractmethod | |
def pay(self,order): | |
pass | |
class DebitPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code , authorizer: Authorizer): | |
self.authorizer = authorizer | |
self.security_code = security_code | |
def pay(self,order): | |
if not self.authorizer.is_authorized(): | |
raise Exception('not authorized') | |
print('PROCESSING Debit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class CreditPaymentProcessor(PaymentProcessor): | |
def __init__(self,security_code): | |
self.security_code = security_code | |
def pay(self,order): | |
print('PROCESSING Credit type') | |
print(f'Verifying security code {self.security_code}') | |
order.status = 'paid' | |
class PayPalPaymentProcessor(PaymentProcessor): | |
def __init__(self,email,authorizer: Authorizer): | |
self.email = email | |
self.authorizer = authorizer | |
def pay(self,order): | |
if not self.authorizer.is_authorized(): | |
raise Exception('not authorized') | |
print('PROCESSING PayPal type') | |
print(f'Verifying security code {self.email}') | |
order.status = 'paid' | |
''' | |
USING THE CLASS ABOVE | |
order = Order() | |
order.add_item('keyboard',1,50) | |
order.add_item('SSD',1,150) | |
order.add_item('USB CABLE',2,5) | |
print(order.total_price()) | |
authorizer = ROBOTAuth() | |
processor = DebitPaymentProcessor('002020',authorizer) | |
authorizer.not_a_robot() | |
processor.pay(order) | |
SWEET !!! | |
''' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment