From 4151e184748856cbb3ea32ff8ef1bcca448e6a68 Mon Sep 17 00:00:00 2001 From: Arjan Egges Date: Mon, 3 May 2021 17:14:19 +0200 Subject: [PATCH 01/18] Simplified calling singleton super() --- 10 - object creation/singleton.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/10 - object creation/singleton.py b/10 - object creation/singleton.py index ccf245c..54370fb 100644 --- a/10 - object creation/singleton.py +++ b/10 - object creation/singleton.py @@ -2,7 +2,7 @@ class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: - cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class Logger(metaclass=Singleton): From 984975d5d6e7d8f980588f1cea7a05ee8f97f9b3 Mon Sep 17 00:00:00 2001 From: Ujesh Date: Thu, 22 Jul 2021 06:35:41 +0530 Subject: [PATCH 02/18] used default dict in api_v2/event instead of normal dict --- 4 - observer pattern/api_v2/event.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/4 - observer pattern/api_v2/event.py b/4 - observer pattern/api_v2/event.py index 8c4d1bf..254afcd 100644 --- a/4 - observer pattern/api_v2/event.py +++ b/4 - observer pattern/api_v2/event.py @@ -1,8 +1,9 @@ -subscribers = dict() +from collections import defaultdict + +# Default value of the dictionary will be list +subscribers = defaultdict(list) def subscribe(event_type: str, fn): - if not event_type in subscribers: - subscribers[event_type] = [] subscribers[event_type].append(fn) def post_event(event_type: str, data): From f4922e93439993f731366e43e0128446caa61b6a Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 26 Jul 2021 20:04:56 +0200 Subject: [PATCH 03/18] Enable pip install -r requirements.txt --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3e1e305 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +flask +returns From 91e4bd85d54a06f847468275961ba69149c071c0 Mon Sep 17 00:00:00 2001 From: Mickey Beurskens Date: Tue, 30 Nov 2021 10:05:56 +0100 Subject: [PATCH 04/18] Fix spacing in solid examples --- 9 - solid/dependency-inversion-after.py | 10 ++++++++-- 9 - solid/dependency-inversion-before.py | 8 ++++++-- 9 - solid/interface-segregation-after-comp.py | 8 ++++++-- 9 - solid/interface-segregation-after.py | 9 +++++++-- 9 - solid/interface-segregation-before.py | 8 ++++++-- 9 - solid/liskov-substitution-after.py | 8 ++++++-- 9 - solid/liskov-substitution-before.py | 7 +++++-- 9 - solid/open-closed-after.py | 6 ++++-- 9 - solid/open-closed-before.py | 3 ++- 9 - solid/single-responsibility-after.py | 3 ++- 9 - solid/single-responsibility-before.py | 3 ++- 11 files changed, 54 insertions(+), 19 deletions(-) diff --git a/9 - solid/dependency-inversion-after.py b/9 - solid/dependency-inversion-after.py index c8a8eef..b0162aa 100644 --- a/9 - solid/dependency-inversion-after.py +++ b/9 - solid/dependency-inversion-after.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class Order: def __init__(self): @@ -19,6 +20,7 @@ def total_price(self): total += self.quantities[i] * self.prices[i] return total + class Authorizer(ABC): @abstractmethod def is_authorized(self) -> bool: @@ -37,6 +39,7 @@ def verify_code(self, code): def is_authorized(self) -> bool: return self.authorized + class Authorizer_Google(Authorizer): def __init__(self): @@ -49,6 +52,7 @@ def verify_code(self, code): def is_authorized(self) -> bool: return self.authorized + class Authorizer_Robot(Authorizer): def __init__(self): @@ -73,7 +77,7 @@ class DebitPaymentProcessor(PaymentProcessor): def __init__(self, security_code, authorizer: Authorizer): self.security_code = security_code self.authorizer = authorizer - + def pay(self, order): if not self.authorizer.is_authorized(): raise Exception("Not authorized") @@ -81,6 +85,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class CreditPaymentProcessor(PaymentProcessor): def __init__(self, security_code): @@ -91,6 +96,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class PaypalPaymentProcessor(PaymentProcessor): def __init__(self, email_address, authorizer: Authorizer): @@ -115,4 +121,4 @@ def pay(self, order): # authorizer.verify_code(465839) authorizer.not_a_robot() processor = PaypalPaymentProcessor("hi@arjancodes.com", authorizer) -processor.pay(order) \ No newline at end of file +processor.pay(order) diff --git a/9 - solid/dependency-inversion-before.py b/9 - solid/dependency-inversion-before.py index 17778ff..3244130 100644 --- a/9 - solid/dependency-inversion-before.py +++ b/9 - solid/dependency-inversion-before.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class Order: def __init__(self): @@ -19,6 +20,7 @@ def total_price(self): total += self.quantities[i] * self.prices[i] return total + class SMSAuthorizer: def __init__(self): @@ -44,7 +46,7 @@ class DebitPaymentProcessor(PaymentProcessor): def __init__(self, security_code, authorizer: SMSAuthorizer): self.security_code = security_code self.authorizer = authorizer - + def pay(self, order): if not self.authorizer.is_authorized(): raise Exception("Not authorized") @@ -52,6 +54,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class CreditPaymentProcessor(PaymentProcessor): def __init__(self, security_code): @@ -62,6 +65,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class PaypalPaymentProcessor(PaymentProcessor): def __init__(self, email_address, authorizer: SMSAuthorizer): @@ -85,4 +89,4 @@ def pay(self, order): authorizer = SMSAuthorizer() # authorizer.verify_code(465839) processor = PaypalPaymentProcessor("hi@arjancodes.com", authorizer) -processor.pay(order) \ No newline at end of file +processor.pay(order) diff --git a/9 - solid/interface-segregation-after-comp.py b/9 - solid/interface-segregation-after-comp.py index 17778ff..3244130 100644 --- a/9 - solid/interface-segregation-after-comp.py +++ b/9 - solid/interface-segregation-after-comp.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class Order: def __init__(self): @@ -19,6 +20,7 @@ def total_price(self): total += self.quantities[i] * self.prices[i] return total + class SMSAuthorizer: def __init__(self): @@ -44,7 +46,7 @@ class DebitPaymentProcessor(PaymentProcessor): def __init__(self, security_code, authorizer: SMSAuthorizer): self.security_code = security_code self.authorizer = authorizer - + def pay(self, order): if not self.authorizer.is_authorized(): raise Exception("Not authorized") @@ -52,6 +54,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class CreditPaymentProcessor(PaymentProcessor): def __init__(self, security_code): @@ -62,6 +65,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class PaypalPaymentProcessor(PaymentProcessor): def __init__(self, email_address, authorizer: SMSAuthorizer): @@ -85,4 +89,4 @@ def pay(self, order): authorizer = SMSAuthorizer() # authorizer.verify_code(465839) processor = PaypalPaymentProcessor("hi@arjancodes.com", authorizer) -processor.pay(order) \ No newline at end of file +processor.pay(order) diff --git a/9 - solid/interface-segregation-after.py b/9 - solid/interface-segregation-after.py index 50dc15d..71decd2 100644 --- a/9 - solid/interface-segregation-after.py +++ b/9 - solid/interface-segregation-after.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class Order: def __init__(self): @@ -26,6 +27,7 @@ class PaymentProcessor(ABC): def pay(self, order): pass + class PaymentProcessor_SMS(PaymentProcessor): @abstractmethod @@ -36,6 +38,7 @@ def auth_sms(self, code): def pay(self, order): pass + class DebitPaymentProcessor(PaymentProcessor_SMS): def __init__(self, security_code): @@ -45,7 +48,7 @@ def __init__(self, security_code): def auth_sms(self, code): print(f"Verifying SMS code {code}") self.verified = True - + def pay(self, order): if not self.verified: raise Exception("Not authorized") @@ -53,6 +56,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class CreditPaymentProcessor(PaymentProcessor): def __init__(self, security_code): @@ -63,6 +67,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class PaypalPaymentProcessor(PaymentProcessor_SMS): def __init__(self, email_address): @@ -89,4 +94,4 @@ def pay(self, order): print(order.total_price()) processor = PaypalPaymentProcessor("hi@arjancodes.com") processor.auth_sms(465839) -processor.pay(order) \ No newline at end of file +processor.pay(order) diff --git a/9 - solid/interface-segregation-before.py b/9 - solid/interface-segregation-before.py index fceb703..c9cdf22 100644 --- a/9 - solid/interface-segregation-before.py +++ b/9 - solid/interface-segregation-before.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class Order: def __init__(self): @@ -30,6 +31,7 @@ def auth_sms(self, code): def pay(self, order): pass + class DebitPaymentProcessor(PaymentProcessor): def __init__(self, security_code): @@ -39,7 +41,7 @@ def __init__(self, security_code): def auth_sms(self, code): print(f"Verifying SMS code {code}") self.verified = True - + def pay(self, order): if not self.verified: raise Exception("Not authorized") @@ -47,6 +49,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class CreditPaymentProcessor(PaymentProcessor): def __init__(self, security_code): @@ -60,6 +63,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class PaypalPaymentProcessor(PaymentProcessor): def __init__(self, email_address): @@ -86,4 +90,4 @@ def pay(self, order): print(order.total_price()) processor = DebitPaymentProcessor("2349875") processor.auth_sms(465839) -processor.pay(order) \ No newline at end of file +processor.pay(order) diff --git a/9 - solid/liskov-substitution-after.py b/9 - solid/liskov-substitution-after.py index a1e89d6..5bf63c4 100644 --- a/9 - solid/liskov-substitution-after.py +++ b/9 - solid/liskov-substitution-after.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class Order: def __init__(self): @@ -26,16 +27,18 @@ class PaymentProcessor(ABC): 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 payment type") print(f"Verifying security code: {self.security_code}") order.status = "paid" + class CreditPaymentProcessor(PaymentProcessor): def __init__(self, security_code): @@ -46,6 +49,7 @@ def pay(self, order): print(f"Verifying security code: {self.security_code}") order.status = "paid" + class PaypalPaymentProcessor(PaymentProcessor): def __init__(self, email_address): @@ -64,4 +68,4 @@ def pay(self, order): print(order.total_price()) processor = PaypalPaymentProcessor("hi@arjancodes.com") -processor.pay(order) \ No newline at end of file +processor.pay(order) diff --git a/9 - solid/liskov-substitution-before.py b/9 - solid/liskov-substitution-before.py index d8da03b..46fb51a 100644 --- a/9 - solid/liskov-substitution-before.py +++ b/9 - solid/liskov-substitution-before.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class Order: def __init__(self): @@ -20,25 +21,27 @@ def total_price(self): 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 payment type") print(f"Verifying security code: {security_code}") order.status = "paid" + class CreditPaymentProcessor(PaymentProcessor): def pay(self, order, security_code): print("Processing credit payment type") print(f"Verifying security code: {security_code}") order.status = "paid" + class PaypalPaymentProcessor(PaymentProcessor): def pay(self, order, security_code): print("Processing paypal payment type") @@ -53,4 +56,4 @@ def pay(self, order, security_code): print(order.total_price()) processor = PaypalPaymentProcessor() -processor.pay(order, "hi@arjancodes.com") \ No newline at end of file +processor.pay(order, "hi@arjancodes.com") diff --git a/9 - solid/open-closed-after.py b/9 - solid/open-closed-after.py index 47e1d6f..9103aa3 100644 --- a/9 - solid/open-closed-after.py +++ b/9 - solid/open-closed-after.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod + class Order: def __init__(self): @@ -20,19 +21,20 @@ def total_price(self): 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 payment type") print(f"Verifying security code: {security_code}") order.status = "paid" + class CreditPaymentProcessor(PaymentProcessor): def pay(self, order, security_code): print("Processing credit payment type") @@ -47,4 +49,4 @@ def pay(self, order, security_code): print(order.total_price()) processor = DebitPaymentProcessor() -processor.pay(order, "0372846") \ No newline at end of file +processor.pay(order, "0372846") diff --git a/9 - solid/open-closed-before.py b/9 - solid/open-closed-before.py index 70d0193..13bb60e 100644 --- a/9 - solid/open-closed-before.py +++ b/9 - solid/open-closed-before.py @@ -17,6 +17,7 @@ def total_price(self): total += self.quantities[i] * self.prices[i] return total + class PaymentProcessor: def pay_debit(self, order, security_code): print("Processing debit payment type") @@ -36,4 +37,4 @@ def pay_credit(self, order, security_code): print(order.total_price()) processor = PaymentProcessor() -processor.pay_debit(order, "0372846") \ No newline at end of file +processor.pay_debit(order, "0372846") diff --git a/9 - solid/single-responsibility-after.py b/9 - solid/single-responsibility-after.py index 70d0193..13bb60e 100644 --- a/9 - solid/single-responsibility-after.py +++ b/9 - solid/single-responsibility-after.py @@ -17,6 +17,7 @@ def total_price(self): total += self.quantities[i] * self.prices[i] return total + class PaymentProcessor: def pay_debit(self, order, security_code): print("Processing debit payment type") @@ -36,4 +37,4 @@ def pay_credit(self, order, security_code): print(order.total_price()) processor = PaymentProcessor() -processor.pay_debit(order, "0372846") \ No newline at end of file +processor.pay_debit(order, "0372846") diff --git a/9 - solid/single-responsibility-before.py b/9 - solid/single-responsibility-before.py index 6496d52..696a5d1 100644 --- a/9 - solid/single-responsibility-before.py +++ b/9 - solid/single-responsibility-before.py @@ -29,10 +29,11 @@ def pay(self, payment_type, security_code): else: raise Exception(f"Unknown payment type: {payment_type}") + 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", "0372846") \ No newline at end of file +order.pay("debit", "0372846") From 1b095061b4c11bba39ba4723a23bce495b5ea06a Mon Sep 17 00:00:00 2001 From: Mickey Beurskens Date: Tue, 30 Nov 2021 10:07:41 +0100 Subject: [PATCH 05/18] Fix naming to be consistent with pep8 --- 9 - solid/dependency-inversion-after.py | 8 ++++---- 9 - solid/interface-segregation-after.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/9 - solid/dependency-inversion-after.py b/9 - solid/dependency-inversion-after.py index b0162aa..f1ccfe1 100644 --- a/9 - solid/dependency-inversion-after.py +++ b/9 - solid/dependency-inversion-after.py @@ -27,7 +27,7 @@ def is_authorized(self) -> bool: pass -class Authorizer_SMS(Authorizer): +class AuthorizerSMS(Authorizer): def __init__(self): self.authorized = False @@ -40,7 +40,7 @@ def is_authorized(self) -> bool: return self.authorized -class Authorizer_Google(Authorizer): +class AuthorizerGoogle(Authorizer): def __init__(self): self.authorized = False @@ -53,7 +53,7 @@ def is_authorized(self) -> bool: return self.authorized -class Authorizer_Robot(Authorizer): +class AuthorizerRobot(Authorizer): def __init__(self): self.authorized = False @@ -117,7 +117,7 @@ def pay(self, order): order.add_item("USB cable", 2, 5) print(order.total_price()) -authorizer = Authorizer_Robot() +authorizer = AuthorizerRobot() # authorizer.verify_code(465839) authorizer.not_a_robot() processor = PaypalPaymentProcessor("hi@arjancodes.com", authorizer) diff --git a/9 - solid/interface-segregation-after.py b/9 - solid/interface-segregation-after.py index 71decd2..c60aa18 100644 --- a/9 - solid/interface-segregation-after.py +++ b/9 - solid/interface-segregation-after.py @@ -28,7 +28,7 @@ def pay(self, order): pass -class PaymentProcessor_SMS(PaymentProcessor): +class PaymentProcessorSMS(PaymentProcessor): @abstractmethod def auth_sms(self, code): @@ -39,7 +39,7 @@ def pay(self, order): pass -class DebitPaymentProcessor(PaymentProcessor_SMS): +class DebitPaymentProcessor(PaymentProcessorSMS): def __init__(self, security_code): self.security_code = security_code @@ -68,7 +68,7 @@ def pay(self, order): order.status = "paid" -class PaypalPaymentProcessor(PaymentProcessor_SMS): +class PaypalPaymentProcessor(PaymentProcessorSMS): def __init__(self, email_address): self.email_address = email_address From 814b24573421f57871e794247c1a5c45146cd939 Mon Sep 17 00:00:00 2001 From: trolzen Date: Thu, 30 Jun 2022 02:28:47 +0300 Subject: [PATCH 06/18] remove unnecessary import Since it's functions only, importing from `abc` is not needed. --- 3 - strategy pattern/strategy-after-fn.py | 1 - 1 file changed, 1 deletion(-) diff --git a/3 - strategy pattern/strategy-after-fn.py b/3 - strategy pattern/strategy-after-fn.py index 892a284..83f4bc7 100644 --- a/3 - strategy pattern/strategy-after-fn.py +++ b/3 - strategy pattern/strategy-after-fn.py @@ -1,7 +1,6 @@ import string import random from typing import List, Callable -from abc import ABC, abstractmethod def generate_id(length=8): From 36a202a735a47c43229a0664ee4ee2b09ec09172 Mon Sep 17 00:00:00 2001 From: Eduardo Cancino Date: Wed, 25 Jan 2023 19:10:34 -0500 Subject: [PATCH 07/18] Update strategy-after-fn.py --- 3 - strategy pattern/strategy-after-fn.py | 50 ++++++++++++++--------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/3 - strategy pattern/strategy-after-fn.py b/3 - strategy pattern/strategy-after-fn.py index 83f4bc7..ad1cc40 100644 --- a/3 - strategy pattern/strategy-after-fn.py +++ b/3 - strategy pattern/strategy-after-fn.py @@ -1,50 +1,55 @@ +from dataclasses import dataclass, field import string import random from typing import List, Callable -def generate_id(length=8): +def generate_id(length: int = 8) -> str: # helper function for generating an id return ''.join(random.choices(string.ascii_uppercase, k=length)) +@dataclass class SupportTicket: + id: str = field(init=False, default_factory=generate_id) + customer: str + issue: str - def __init__(self, customer, issue): - self.id = generate_id() - self.customer = customer - self.issue = issue +SupportTickets = List[SupportTicket] -def fifoOrdering(list: List[SupportTicket]) -> List[SupportTicket]: +Ordering = Callable[[SupportTickets], SupportTickets] + + +def fifo_ordering(list: SupportTickets) -> SupportTickets: return list.copy() -def filoOrdering(list: List[SupportTicket]) -> List[SupportTicket]: +def filo_ordering(list: SupportTickets) -> SupportTickets: list_copy = list.copy() list_copy.reverse() return list_copy -def randomOrdering(list: List[SupportTicket]) -> List[SupportTicket]: +def random_ordering(list: SupportTickets) -> SupportTickets: list_copy = list.copy() random.shuffle(list_copy) return list_copy -def blackHoleOrdering(list: List[SupportTicket]) -> List[SupportTicket]: +def black_hole_ordering(_: SupportTickets) -> SupportTickets: return [] class CustomerSupport: def __init__(self): - self.tickets = [] + self.tickets: SupportTickets = [] def create_ticket(self, customer, issue): self.tickets.append(SupportTicket(customer, issue)) - def process_tickets(self, ordering: Callable[[List[SupportTicket]], List[SupportTicket]]): + def process_tickets(self, ordering: Ordering): # create the ordered list ticket_list = ordering(self.tickets) @@ -65,13 +70,20 @@ def process_ticket(self, ticket: SupportTicket): print("==================================") -# create the application -app = CustomerSupport() +def main() -> None: + # create the application + app = CustomerSupport() + + # register a few tickets + app.create_ticket("John Smith", "My computer makes strange sounds!") + app.create_ticket("Linus Sebastian", + "I can't upload any videos, please help.") + app.create_ticket( + "Arjan Egges", "VSCode doesn't automatically solve my bugs.") + + # process the tickets + app.process_tickets(random_ordering) -# register a few tickets -app.create_ticket("John Smith", "My computer makes strange sounds!") -app.create_ticket("Linus Sebastian", "I can't upload any videos, please help.") -app.create_ticket("Arjan Egges", "VSCode doesn't automatically solve my bugs.") -# process the tickets -app.process_tickets(blackHoleOrdering) +if __name__ == '__main__': + main() From 76a492a597fc1ee0ee7ae45cdd2e40ec8fc1b530 Mon Sep 17 00:00:00 2001 From: Eduardo Cancino Date: Wed, 25 Jan 2023 19:12:59 -0500 Subject: [PATCH 08/18] Update strategy-after-fn.py --- 3 - strategy pattern/strategy-after-fn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3 - strategy pattern/strategy-after-fn.py b/3 - strategy pattern/strategy-after-fn.py index ad1cc40..be51f17 100644 --- a/3 - strategy pattern/strategy-after-fn.py +++ b/3 - strategy pattern/strategy-after-fn.py @@ -37,7 +37,7 @@ def random_ordering(list: SupportTickets) -> SupportTickets: return list_copy -def black_hole_ordering(_: SupportTickets) -> SupportTickets: +def blackhole_ordering(_: SupportTickets) -> SupportTickets: return [] From 559794d83ba2cd6bbef6c62e09076d3f97aa17d7 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 26 Jan 2023 13:04:32 +0100 Subject: [PATCH 09/18] .DS_Store is a macOS file that should be gitignored --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 80d15dff7be3f502a3438b1294cba2e2f7dda17f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!Ab)$5KY>uS&Fy^LA~YTtwO67^&l*@9=r)FdQfS1X=xYgZs~4av{v>z^pE@j zf5(|5EtV>t6e=??d6Q%&Y2K8~hB3x#!&Zecn=vLp5pxzaUkJ{l&PmRUAab?FkcBK@ z36r2Ci@*Tp&Sq7}*beCD{IyvOSqvbf9Y2lxelPOD_s#G3f;cIc-+3-ySXy2YLKMZS zxOKZx>Ly+?jBDQD8hhtn()Epf5kfwm%d&*ku(w8|ql5jD+^v?!B{`~8tI#>zI~tEIv9Vn_K5O1RJdU2m&o7#O z4*yIgYX&Fq3dWBozjp^=FA6*0J6UHEPe=?91H{1MGGJ~rQC!?3&@U$jh=E^X0PhD0 zis%^3G^(ou8vK03`2r#e*!Y$}lm;DxnMRla;W`vhhjR18;5r<}rSWqNW*T)k<7#JE z$L!3_3x%uQVO%PA#vP5+5(C7*ECYGnwXy!6e*gZT4Wb?~Kn(mV26&;0YjBy@WoQR391CfB^rQ^!Av8JfY674qJbJ>;7=L&0AG4m-2eap From 2eba63712d495c30bb2d577dafb330d268147b27 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 26 Jan 2023 13:09:46 +0100 Subject: [PATCH 10/18] Fix typo discovered by codespell https://pypi.org/project/codespell --- 7 - dealing with errors/advanced/logging-decorator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7 - dealing with errors/advanced/logging-decorator.py b/7 - dealing with errors/advanced/logging-decorator.py index 2627ccf..d0e99f2 100644 --- a/7 - dealing with errors/advanced/logging-decorator.py +++ b/7 - dealing with errors/advanced/logging-decorator.py @@ -9,7 +9,7 @@ def create_logger(): logger = logging.getLogger('exc_logger') logger.setLevel(logging.INFO) - #c reate a file to store all the + # create a file to store all the # logged exceptions logfile = logging.FileHandler('exc_logger.log') From c39da38a85c7b7a27185fb108a7da65c8272a826 Mon Sep 17 00:00:00 2001 From: Diego Viniegra Date: Tue, 23 Apr 2024 10:39:12 -0500 Subject: [PATCH 11/18] Add single_responsibility --- .gitignore | 3 +- better-rust/Cargo.lock | 11 +++++ better-rust/Cargo.toml | 9 ++++ better-rust/solid/Cargo.toml | 8 ++++ better-rust/solid/src/lib.rs | 2 + better-rust/solid/src/main.rs | 43 ++++++++++++++++++ .../solid/src/single_responsibility_after.rs | 45 +++++++++++++++++++ .../solid/src/single_responsibility_before.rs | 43 ++++++++++++++++++ better-rust/src/main.rs | 4 ++ 9 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 better-rust/Cargo.lock create mode 100644 better-rust/Cargo.toml create mode 100644 better-rust/solid/Cargo.toml create mode 100644 better-rust/solid/src/lib.rs create mode 100644 better-rust/solid/src/main.rs create mode 100644 better-rust/solid/src/single_responsibility_after.rs create mode 100644 better-rust/solid/src/single_responsibility_before.rs create mode 100644 better-rust/src/main.rs diff --git a/.gitignore b/.gitignore index 6d294de..ef427c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ # misc .DS_Store -*.pyc \ No newline at end of file +*.pyc +/better-rust/target diff --git a/better-rust/Cargo.lock b/better-rust/Cargo.lock new file mode 100644 index 0000000..26f91b6 --- /dev/null +++ b/better-rust/Cargo.lock @@ -0,0 +1,11 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "better-rust" +version = "0.1.0" + +[[package]] +name = "solid" +version = "0.1.0" diff --git a/better-rust/Cargo.toml b/better-rust/Cargo.toml new file mode 100644 index 0000000..8d9cfec --- /dev/null +++ b/better-rust/Cargo.toml @@ -0,0 +1,9 @@ +workspace = { members = ["solid"] } +[package] +name = "better-rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/better-rust/solid/Cargo.toml b/better-rust/solid/Cargo.toml new file mode 100644 index 0000000..a1ca2ef --- /dev/null +++ b/better-rust/solid/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "solid" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/better-rust/solid/src/lib.rs b/better-rust/solid/src/lib.rs new file mode 100644 index 0000000..df43f4e --- /dev/null +++ b/better-rust/solid/src/lib.rs @@ -0,0 +1,2 @@ +pub mod single_responsibility_before; +pub mod single_responsibility_after; diff --git a/better-rust/solid/src/main.rs b/better-rust/solid/src/main.rs new file mode 100644 index 0000000..91f9041 --- /dev/null +++ b/better-rust/solid/src/main.rs @@ -0,0 +1,43 @@ + +fn main() { + run_single_responsibility_before(); + + run_single_responsibility_after(); +} + +fn run_single_responsibility_before() { + println!("running `run_single_responsibility_before`:\n"); + + use solid::single_responsibility_before::*; + + let mut order = Order::new(); + + order.add_item("Keyboard", 1, 50.0); + order.add_item("SSD", 1, 150.0); + order.add_item("USB cable", 2, 5.0); + + println!("{}", order.total_price()); + order.pay("debit", "0372846"); + + println!("------------"); +} + +fn run_single_responsibility_after() { + println!("running `run_single_responsibility_after`:\n"); + + use solid::single_responsibility_after::*; + + let mut order = Order::new(); + + order.add_item("Keyboard", 1, 50.0); + order.add_item("SSD", 1, 150.0); + order.add_item("USB cable", 2, 5.0); + + println!("{}", order.total_price()); + + let processor = PaymentProcessor {}; + + processor.pay_debit(&mut order, "0372846"); + + println!("------------"); +} \ No newline at end of file diff --git a/better-rust/solid/src/single_responsibility_after.rs b/better-rust/solid/src/single_responsibility_after.rs new file mode 100644 index 0000000..fb3cfe7 --- /dev/null +++ b/better-rust/solid/src/single_responsibility_after.rs @@ -0,0 +1,45 @@ + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub struct PaymentProcessor; + +impl PaymentProcessor { + pub fn pay_debit(&self, order: &mut Order, security_code: &str) { + println!("Processing debit payment type"); + println!("Verifying security code: {security_code}"); + order.status = "paid"; + } + + pub fn pay_credit(&self, order: &mut Order, security_code: &str) { + println!("Processing credit payment type"); + println!("Verifying security code: {security_code}"); + order.status = "paid"; + } +} \ No newline at end of file diff --git a/better-rust/solid/src/single_responsibility_before.rs b/better-rust/solid/src/single_responsibility_before.rs new file mode 100644 index 0000000..9c7f91f --- /dev/null +++ b/better-rust/solid/src/single_responsibility_before.rs @@ -0,0 +1,43 @@ + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } + + pub fn pay(&mut self, payment_type: &str, security_code: &str) { + if payment_type == "debit" { + println!("Processing debit payment type"); + println!("Verifying security code: {security_code}"); + self.status = "paid"; + } else if payment_type == "credit" { + println!("Processing credit payment type"); + println!("Verifying security code: {security_code}"); + self.status = "paid"; + } else { + panic!("Unknown payment type: {payment_type}"); + } + } +} \ No newline at end of file diff --git a/better-rust/src/main.rs b/better-rust/src/main.rs new file mode 100644 index 0000000..7da3a48 --- /dev/null +++ b/better-rust/src/main.rs @@ -0,0 +1,4 @@ + +fn main() { + println!("Hello, world!"); +} From 9827e54bffd361b95ad14faf9a862c0dab7a0383 Mon Sep 17 00:00:00 2001 From: Diego Viniegra Date: Tue, 23 Apr 2024 11:00:06 -0500 Subject: [PATCH 12/18] Add open-closed --- better-rust/solid/src/lib.rs | 2 + better-rust/solid/src/main.rs | 22 +++++++++ better-rust/solid/src/open_closed_after.rs | 53 +++++++++++++++++++++ better-rust/solid/src/open_closed_before.rs | 45 +++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 better-rust/solid/src/open_closed_after.rs create mode 100644 better-rust/solid/src/open_closed_before.rs diff --git a/better-rust/solid/src/lib.rs b/better-rust/solid/src/lib.rs index df43f4e..389e4bd 100644 --- a/better-rust/solid/src/lib.rs +++ b/better-rust/solid/src/lib.rs @@ -1,2 +1,4 @@ pub mod single_responsibility_before; pub mod single_responsibility_after; +pub mod open_closed_before; +pub mod open_closed_after; diff --git a/better-rust/solid/src/main.rs b/better-rust/solid/src/main.rs index 91f9041..b5611b8 100644 --- a/better-rust/solid/src/main.rs +++ b/better-rust/solid/src/main.rs @@ -3,6 +3,8 @@ fn main() { run_single_responsibility_before(); run_single_responsibility_after(); + + run_open_closed(); } fn run_single_responsibility_before() { @@ -40,4 +42,24 @@ fn run_single_responsibility_after() { processor.pay_debit(&mut order, "0372846"); println!("------------"); +} + +fn run_open_closed() { + println!("running `run_open_closed`:\n"); + + use solid::open_closed_after::*; + + let mut order = Order::new(); + + order.add_item("Keyboard", 1, 50.0); + order.add_item("SSD", 1, 150.0); + order.add_item("USB cable", 2, 5.0); + + println!("{}", order.total_price()); + + let processor = DebitPaymentProcessor {}; + + processor.pay(&mut order, "0372846"); + + println!("------------"); } \ No newline at end of file diff --git a/better-rust/solid/src/open_closed_after.rs b/better-rust/solid/src/open_closed_after.rs new file mode 100644 index 0000000..8929db1 --- /dev/null +++ b/better-rust/solid/src/open_closed_after.rs @@ -0,0 +1,53 @@ + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub trait PaymentProcessor { + fn pay(&self, order: &mut Order, security_code: &str); +} + +pub struct DebitPaymentProcessor; + +impl PaymentProcessor for DebitPaymentProcessor { + fn pay(&self, order: &mut Order, security_code: &str) { + println!("Processing debit payment type"); + println!("Verifying security code: {security_code}"); + order.status = "paid"; + } +} + +pub struct CreditPaymentProcessor; + +impl PaymentProcessor for CreditPaymentProcessor { + fn pay(&self, order: &mut Order, security_code: &str) { + println!("Processing credit payment type"); + println!("Verifying security code: {security_code}"); + order.status = "paid"; + } +} diff --git a/better-rust/solid/src/open_closed_before.rs b/better-rust/solid/src/open_closed_before.rs new file mode 100644 index 0000000..fb3cfe7 --- /dev/null +++ b/better-rust/solid/src/open_closed_before.rs @@ -0,0 +1,45 @@ + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub struct PaymentProcessor; + +impl PaymentProcessor { + pub fn pay_debit(&self, order: &mut Order, security_code: &str) { + println!("Processing debit payment type"); + println!("Verifying security code: {security_code}"); + order.status = "paid"; + } + + pub fn pay_credit(&self, order: &mut Order, security_code: &str) { + println!("Processing credit payment type"); + println!("Verifying security code: {security_code}"); + order.status = "paid"; + } +} \ No newline at end of file From 30c956c54529fbfbc423071c897ae4fe65b16bfa Mon Sep 17 00:00:00 2001 From: Diego Viniegra Date: Tue, 23 Apr 2024 12:28:34 -0500 Subject: [PATCH 13/18] Add liskov substitution --- .vscode/settings.json | 23 ++--- better-rust/solid/src/lib.rs | 2 + .../solid/src/liskov_substitution_after.rs | 87 +++++++++++++++++++ .../solid/src/liskov_substitution_before.rs | 63 ++++++++++++++ better-rust/solid/src/main.rs | 22 +++++ 5 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 better-rust/solid/src/liskov_substitution_after.rs create mode 100644 better-rust/solid/src/liskov_substitution_before.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index 776675a..0c1637e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,12 +1,13 @@ { - "python.testing.unittestArgs": [ - "-v", - "-s", - "./5 - unit testing", - "-p", - "*_test.py" - ], - "python.testing.pytestEnabled": false, - "python.testing.nosetestsEnabled": false, - "python.testing.unittestEnabled": true -} \ No newline at end of file + "python.testing.unittestArgs": [ + "-v", + "-s", + "./5 - unit testing", + "-p", + "*_test.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.nosetestsEnabled": false, + "python.testing.unittestEnabled": true, + "cSpell.words": ["liskov"] +} diff --git a/better-rust/solid/src/lib.rs b/better-rust/solid/src/lib.rs index 389e4bd..04dbbac 100644 --- a/better-rust/solid/src/lib.rs +++ b/better-rust/solid/src/lib.rs @@ -2,3 +2,5 @@ pub mod single_responsibility_before; pub mod single_responsibility_after; pub mod open_closed_before; pub mod open_closed_after; +pub mod liskov_substitution_before; +pub mod liskov_substitution_after; diff --git a/better-rust/solid/src/liskov_substitution_after.rs b/better-rust/solid/src/liskov_substitution_after.rs new file mode 100644 index 0000000..907ba08 --- /dev/null +++ b/better-rust/solid/src/liskov_substitution_after.rs @@ -0,0 +1,87 @@ + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub trait PaymentProcessor { + fn pay(&self, order: &mut Order); +} + +pub struct DebitPaymentProcessor<'a> { + pub security_code: &'a str, +} + +impl<'a> DebitPaymentProcessor<'a> { + pub fn new(security_code: &'a str) -> Self { + Self { security_code } + } +} + +impl PaymentProcessor for DebitPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + println!("Processing debit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct CreditPaymentProcessor<'a> { + pub security_code: &'a str, +} + +impl<'a> CreditPaymentProcessor<'a> { + pub fn new(security_code: &'a str) -> Self { + Self { security_code } + } +} + +impl PaymentProcessor for CreditPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + println!("Processing credit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct PaypalPaymentProcessor<'a> { + pub email_address: &'a str, +} + +impl<'a> PaypalPaymentProcessor<'a> { + pub fn new(email_address: &'a str) -> Self { + Self { email_address } + } +} + +impl PaymentProcessor for PaypalPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + println!("Processing paypal payment type"); + println!("Using email address: {}", {self.email_address}); + order.status = "paid"; + } +} diff --git a/better-rust/solid/src/liskov_substitution_before.rs b/better-rust/solid/src/liskov_substitution_before.rs new file mode 100644 index 0000000..133f647 --- /dev/null +++ b/better-rust/solid/src/liskov_substitution_before.rs @@ -0,0 +1,63 @@ + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub trait PaymentProcessor { + fn pay(&self, order: &mut Order, security_code: &str); +} + +pub struct DebitPaymentProcessor; + +impl PaymentProcessor for DebitPaymentProcessor { + fn pay(&self, order: &mut Order, security_code: &str) { + println!("Processing debit payment type"); + println!("Verifying security code: {security_code}"); + order.status = "paid"; + } +} + +pub struct CreditPaymentProcessor; + +impl PaymentProcessor for CreditPaymentProcessor { + fn pay(&self, order: &mut Order, security_code: &str) { + println!("Processing credit payment type"); + println!("Verifying security code: {security_code}"); + order.status = "paid"; + } +} + +pub struct PaypalPaymentProcessor; + +impl PaymentProcessor for PaypalPaymentProcessor { + fn pay(&self, order: &mut Order, security_code: &str) { + println!("Processing paypal payment type"); + println!("Using email address: {security_code}"); + order.status = "paid"; + } +} diff --git a/better-rust/solid/src/main.rs b/better-rust/solid/src/main.rs index b5611b8..41c04cd 100644 --- a/better-rust/solid/src/main.rs +++ b/better-rust/solid/src/main.rs @@ -5,6 +5,8 @@ fn main() { run_single_responsibility_after(); run_open_closed(); + + run_liskov_substitution(); } fn run_single_responsibility_before() { @@ -61,5 +63,25 @@ fn run_open_closed() { processor.pay(&mut order, "0372846"); + println!("------------"); +} + +fn run_liskov_substitution() { + println!("running `run_liskov_substitution`:\n"); + + use solid::liskov_substitution_after::*; + + let mut order = Order::new(); + + order.add_item("Keyboard", 1, 50.0); + order.add_item("SSD", 1, 150.0); + order.add_item("USB cable", 2, 5.0); + + println!("{}", order.total_price()); + + let processor = PaypalPaymentProcessor::new("hi@arjancodes.com"); + + processor.pay(&mut order); + println!("------------"); } \ No newline at end of file From d64bd277379145e5ec2dda7a88749a0d18e859db Mon Sep 17 00:00:00 2001 From: Diego Viniegra Date: Tue, 23 Apr 2024 15:14:12 -0500 Subject: [PATCH 14/18] Add macro example --- better-rust/Cargo.lock | 46 +++++++++++++++++++++++++++++++++++ better-rust/Cargo.toml | 2 +- better-rust/macros/Cargo.toml | 13 ++++++++++ better-rust/macros/src/lib.rs | 21 ++++++++++++++++ better-rust/solid/Cargo.toml | 1 + better-rust/solid/src/main.rs | 37 +++++++++------------------- 6 files changed, 94 insertions(+), 26 deletions(-) create mode 100644 better-rust/macros/Cargo.toml create mode 100644 better-rust/macros/src/lib.rs diff --git a/better-rust/Cargo.lock b/better-rust/Cargo.lock index 26f91b6..d96eaa1 100644 --- a/better-rust/Cargo.lock +++ b/better-rust/Cargo.lock @@ -6,6 +6,52 @@ version = 3 name = "better-rust" version = "0.1.0" +[[package]] +name = "macros" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + [[package]] name = "solid" version = "0.1.0" +dependencies = [ + "macros", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/better-rust/Cargo.toml b/better-rust/Cargo.toml index 8d9cfec..740087c 100644 --- a/better-rust/Cargo.toml +++ b/better-rust/Cargo.toml @@ -1,4 +1,4 @@ -workspace = { members = ["solid"] } +workspace = { members = ["solid", "macros"] } [package] name = "better-rust" version = "0.1.0" diff --git a/better-rust/macros/Cargo.toml b/better-rust/macros/Cargo.toml new file mode 100644 index 0000000..a907c20 --- /dev/null +++ b/better-rust/macros/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "macros" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "*", features = ["full"]} +quote = "1.0" \ No newline at end of file diff --git a/better-rust/macros/src/lib.rs b/better-rust/macros/src/lib.rs new file mode 100644 index 0000000..b1ac13e --- /dev/null +++ b/better-rust/macros/src/lib.rs @@ -0,0 +1,21 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn; + +#[proc_macro_attribute] +pub fn example(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input = syn::parse_macro_input!(item as syn::ItemFn); + let ident = input.sig.ident; + let name = ident.clone().to_string(); + let block = input.block; + + let gen = quote! { + fn #ident() { + println!("running `{}`:\n", #name); + #block; + println!("-------------\n"); + } + }; + + gen.into() +} \ No newline at end of file diff --git a/better-rust/solid/Cargo.toml b/better-rust/solid/Cargo.toml index a1ca2ef..d9f9dd6 100644 --- a/better-rust/solid/Cargo.toml +++ b/better-rust/solid/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +macros ={ path = "../macros" } \ No newline at end of file diff --git a/better-rust/solid/src/main.rs b/better-rust/solid/src/main.rs index 41c04cd..7d0267a 100644 --- a/better-rust/solid/src/main.rs +++ b/better-rust/solid/src/main.rs @@ -1,17 +1,15 @@ - fn main() { - run_single_responsibility_before(); + single_responsibility_before(); - run_single_responsibility_after(); + single_responsibility_after(); - run_open_closed(); + open_closed(); - run_liskov_substitution(); + liskov_substitution(); } -fn run_single_responsibility_before() { - println!("running `run_single_responsibility_before`:\n"); - +#[macros::example] +fn single_responsibility_before() { use solid::single_responsibility_before::*; let mut order = Order::new(); @@ -22,13 +20,10 @@ fn run_single_responsibility_before() { println!("{}", order.total_price()); order.pay("debit", "0372846"); - - println!("------------"); } -fn run_single_responsibility_after() { - println!("running `run_single_responsibility_after`:\n"); - +#[macros::example] +fn single_responsibility_after() { use solid::single_responsibility_after::*; let mut order = Order::new(); @@ -42,13 +37,10 @@ fn run_single_responsibility_after() { let processor = PaymentProcessor {}; processor.pay_debit(&mut order, "0372846"); - - println!("------------"); } -fn run_open_closed() { - println!("running `run_open_closed`:\n"); - +#[macros::example] +fn open_closed() { use solid::open_closed_after::*; let mut order = Order::new(); @@ -62,13 +54,10 @@ fn run_open_closed() { let processor = DebitPaymentProcessor {}; processor.pay(&mut order, "0372846"); - - println!("------------"); } -fn run_liskov_substitution() { - println!("running `run_liskov_substitution`:\n"); - +#[macros::example] +fn liskov_substitution() { use solid::liskov_substitution_after::*; let mut order = Order::new(); @@ -82,6 +71,4 @@ fn run_liskov_substitution() { let processor = PaypalPaymentProcessor::new("hi@arjancodes.com"); processor.pay(&mut order); - - println!("------------"); } \ No newline at end of file From 6e2aaa199aff3f99d9fa78631dcce0ec129116dc Mon Sep 17 00:00:00 2001 From: Diego Viniegra Date: Thu, 25 Apr 2024 09:26:02 -0500 Subject: [PATCH 15/18] Add interface segregation --- .../solid/src/interface_segregation_after.rs | 117 ++++++++++++++++++ .../solid/src/interface_segregation_before.rs | 105 ++++++++++++++++ better-rust/solid/src/lib.rs | 2 + better-rust/solid/src/main.rs | 42 +++++++ 4 files changed, 266 insertions(+) create mode 100644 better-rust/solid/src/interface_segregation_after.rs create mode 100644 better-rust/solid/src/interface_segregation_before.rs diff --git a/better-rust/solid/src/interface_segregation_after.rs b/better-rust/solid/src/interface_segregation_after.rs new file mode 100644 index 0000000..38de58c --- /dev/null +++ b/better-rust/solid/src/interface_segregation_after.rs @@ -0,0 +1,117 @@ +use std::cell::RefCell; + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub struct SMSAuthorizer { + pub authorized: bool, +} + +impl SMSAuthorizer { + pub fn new() -> Self { + Self { authorized: false } + } + + pub fn verify_code(&mut self, code: u32) { + println!("Verifying SMS code {code}"); + self.authorized = true; + } + + fn is_authorized(&self) -> bool { + self.authorized + } +} + +pub trait PaymentProcessor { + fn pay(&self, order: &mut Order); +} + +pub struct DebitPaymentProcessor<'a> { + pub security_code: &'a str, + pub authorizer: &'a RefCell, +} + +impl<'a> DebitPaymentProcessor<'a> { + pub fn new(security_code: &'a str, authorizer: &'a RefCell) -> Self { + Self { security_code, authorizer } + } +} + +impl PaymentProcessor for DebitPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + if !self.authorizer.borrow().is_authorized() { + panic!("Not authorized"); + } + + println!("Processing debit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct CreditPaymentProcessor<'a> { + pub security_code: &'a str, +} + +impl<'a> CreditPaymentProcessor<'a> { + pub fn new(security_code: &'a str) -> Self { + Self { security_code } + } +} + +impl PaymentProcessor for CreditPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + println!("Processing credit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct PaypalPaymentProcessor<'a> { + pub email_address: &'a str, + pub authorizer: &'a RefCell, +} + +impl<'a> PaypalPaymentProcessor<'a> { + pub fn new(email_address: &'a str, authorizer: &'a RefCell) -> Self { + Self { email_address, authorizer } + } +} + +impl PaymentProcessor for PaypalPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + if !self.authorizer.borrow().is_authorized() { + panic!("Not authorized"); + } + + println!("Processing paypal payment type"); + println!("Using email address: {}", {self.email_address}); + order.status = "paid"; + } +} diff --git a/better-rust/solid/src/interface_segregation_before.rs b/better-rust/solid/src/interface_segregation_before.rs new file mode 100644 index 0000000..f3a503c --- /dev/null +++ b/better-rust/solid/src/interface_segregation_before.rs @@ -0,0 +1,105 @@ + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub trait PaymentProcessor { + fn auth_sms(&mut self, code: u32); + + fn pay(&self, order: &mut Order); +} + +pub struct DebitPaymentProcessor<'a> { + pub security_code: &'a str, + pub verified: bool, +} + +impl<'a> DebitPaymentProcessor<'a> { + pub fn new(security_code: &'a str) -> Self { + Self { security_code, verified: false } + } +} + +impl PaymentProcessor for DebitPaymentProcessor<'_> { + fn auth_sms(&mut self, code: u32) { + println!("Verifying SMS code {code}"); + self.verified = true; + } + + fn pay(&self, order: &mut Order) { + println!("Processing debit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct CreditPaymentProcessor<'a> { + pub security_code: &'a str, +} + +impl<'a> CreditPaymentProcessor<'a> { + pub fn new(security_code: &'a str) -> Self { + Self { security_code } + } +} + +impl PaymentProcessor for CreditPaymentProcessor<'_> { + fn auth_sms(&mut self, _code: u32) { + panic!("Credit card payments don't support SMS code authorization."); + } + + fn pay(&self, order: &mut Order) { + println!("Processing credit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct PaypalPaymentProcessor<'a> { + pub email_address: &'a str, + pub verified: bool, +} + +impl<'a> PaypalPaymentProcessor<'a> { + pub fn new(email_address: &'a str) -> Self { + Self { email_address, verified: false } + } +} + +impl PaymentProcessor for PaypalPaymentProcessor<'_> { + fn auth_sms(&mut self, code: u32) { + println!("Verifying SMS code {code}"); + self.verified = true; + } + + fn pay(&self, order: &mut Order) { + println!("Processing paypal payment type"); + println!("Using email address: {}", {self.email_address}); + order.status = "paid"; + } +} diff --git a/better-rust/solid/src/lib.rs b/better-rust/solid/src/lib.rs index 04dbbac..6a49eb1 100644 --- a/better-rust/solid/src/lib.rs +++ b/better-rust/solid/src/lib.rs @@ -4,3 +4,5 @@ pub mod open_closed_before; pub mod open_closed_after; pub mod liskov_substitution_before; pub mod liskov_substitution_after; +pub mod interface_segregation_before; +pub mod interface_segregation_after; \ No newline at end of file diff --git a/better-rust/solid/src/main.rs b/better-rust/solid/src/main.rs index 7d0267a..a0bc1d4 100644 --- a/better-rust/solid/src/main.rs +++ b/better-rust/solid/src/main.rs @@ -1,3 +1,5 @@ +use std::cell::RefCell; + fn main() { single_responsibility_before(); @@ -6,6 +8,10 @@ fn main() { open_closed(); liskov_substitution(); + + interface_segregation_before(); + + interface_segregation_after(); } #[macros::example] @@ -70,5 +76,41 @@ fn liskov_substitution() { let processor = PaypalPaymentProcessor::new("hi@arjancodes.com"); + processor.pay(&mut order); +} + +#[macros::example] +fn interface_segregation_before() { + use solid::interface_segregation_before::*; + + let mut order = Order::new(); + + order.add_item("Keyboard", 1, 50.0); + order.add_item("SSD", 1, 150.0); + order.add_item("USB cable", 2, 5.0); + + println!("{}", order.total_price()); + + let mut processor = DebitPaymentProcessor::new("2349875"); + processor.auth_sms(465839); + processor.pay(&mut order); +} + +#[macros::example] +fn interface_segregation_after() { + use solid::interface_segregation_after::*; + + let mut order = Order::new(); + + order.add_item("Keyboard", 1, 50.0); + order.add_item("SSD", 1, 150.0); + order.add_item("USB cable", 2, 5.0); + + println!("{}", order.total_price()); + + let authorizer = RefCell::new(SMSAuthorizer::new()); + + let processor = PaypalPaymentProcessor::new("hi@arjancodes.com", &authorizer); + authorizer.borrow_mut().verify_code(465839); processor.pay(&mut order); } \ No newline at end of file From 16b6e086d3eae97c7b483d8935058bf361ddf460 Mon Sep 17 00:00:00 2001 From: Diego Viniegra Date: Thu, 25 Apr 2024 12:29:03 -0500 Subject: [PATCH 16/18] Add dependency inversion --- .../solid/src/dependency_inversion_after.rs | 144 ++++++++++++++++++ .../solid/src/dependency_inversion_before.rs | 117 ++++++++++++++ better-rust/solid/src/lib.rs | 4 +- better-rust/solid/src/main.rs | 23 +++ 4 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 better-rust/solid/src/dependency_inversion_after.rs create mode 100644 better-rust/solid/src/dependency_inversion_before.rs diff --git a/better-rust/solid/src/dependency_inversion_after.rs b/better-rust/solid/src/dependency_inversion_after.rs new file mode 100644 index 0000000..1ad88e6 --- /dev/null +++ b/better-rust/solid/src/dependency_inversion_after.rs @@ -0,0 +1,144 @@ +use std::cell::RefCell; + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub trait Authorizer { + fn is_authorized(&self) -> bool; +} + +pub struct SMSAuthorizer { + pub authorized: bool, +} + +impl SMSAuthorizer { + pub fn new() -> Self { + Self { authorized: false } + } + + pub fn verify_code(&mut self, code: u32) { + println!("Verifying SMS code {code}"); + self.authorized = true; + } +} + +impl Authorizer for SMSAuthorizer { + fn is_authorized(&self) -> bool { + self.authorized + } +} + +pub struct AuthorizerRobot { + pub authorized: bool, +} + +impl AuthorizerRobot { + pub fn new() -> Self { + Self { authorized: false } + } + + pub fn not_a_robot(&mut self) { + println!("Are you a robot?"); + self.authorized = true; + } +} + +impl Authorizer for AuthorizerRobot { + fn is_authorized(&self) -> bool { + self.authorized + } +} + +pub trait PaymentProcessor { + fn pay(&self, order: &mut Order); +} + +pub struct DebitPaymentProcessor<'a> { + pub security_code: &'a str, + pub authorizer: &'a RefCell, +} + +impl<'a> DebitPaymentProcessor<'a> { + pub fn new(security_code: &'a str, authorizer: &'a RefCell) -> Self { + Self { security_code, authorizer } + } +} + +impl PaymentProcessor for DebitPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + if !self.authorizer.borrow().is_authorized() { + panic!("Not authorized"); + } + + println!("Processing debit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct CreditPaymentProcessor<'a> { + pub security_code: &'a str, +} + +impl<'a> CreditPaymentProcessor<'a> { + pub fn new(security_code: &'a str) -> Self { + Self { security_code } + } +} + +impl PaymentProcessor for CreditPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + println!("Processing credit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct PaypalPaymentProcessor<'a> { + pub email_address: &'a str, + pub authorizer: &'a RefCell, +} + +impl<'a> PaypalPaymentProcessor<'a> { + pub fn new(email_address: &'a str, authorizer: &'a RefCell) -> Self { + Self { email_address, authorizer } + } +} + +impl PaymentProcessor for PaypalPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + if !self.authorizer.borrow().is_authorized() { + panic!("Not authorized"); + } + + println!("Processing paypal payment type"); + println!("Using email address: {}", {self.email_address}); + order.status = "paid"; + } +} diff --git a/better-rust/solid/src/dependency_inversion_before.rs b/better-rust/solid/src/dependency_inversion_before.rs new file mode 100644 index 0000000..38de58c --- /dev/null +++ b/better-rust/solid/src/dependency_inversion_before.rs @@ -0,0 +1,117 @@ +use std::cell::RefCell; + +pub struct Order<'a> { + pub items: Vec<&'a str>, + pub quantities: Vec, + pub prices: Vec, + pub status: &'a str, +} + +impl<'a> Order<'a> { + pub fn new() -> Self { + Self { items: vec![], quantities: vec![], prices: vec![], status: "open" } + } + + pub fn add_item(&mut self, name: &'a str, quantity: u32, price: f32) { + self.items.push(name); + self.quantities.push(quantity); + self.prices.push(price); + } + + pub fn total_price(&self) -> f32 { + let mut total: f32 = 0.0; + + for (i, price) in self.prices.iter().enumerate() { + total += self.quantities[i] as f32 * price; + } + + total + } +} + +pub struct SMSAuthorizer { + pub authorized: bool, +} + +impl SMSAuthorizer { + pub fn new() -> Self { + Self { authorized: false } + } + + pub fn verify_code(&mut self, code: u32) { + println!("Verifying SMS code {code}"); + self.authorized = true; + } + + fn is_authorized(&self) -> bool { + self.authorized + } +} + +pub trait PaymentProcessor { + fn pay(&self, order: &mut Order); +} + +pub struct DebitPaymentProcessor<'a> { + pub security_code: &'a str, + pub authorizer: &'a RefCell, +} + +impl<'a> DebitPaymentProcessor<'a> { + pub fn new(security_code: &'a str, authorizer: &'a RefCell) -> Self { + Self { security_code, authorizer } + } +} + +impl PaymentProcessor for DebitPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + if !self.authorizer.borrow().is_authorized() { + panic!("Not authorized"); + } + + println!("Processing debit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct CreditPaymentProcessor<'a> { + pub security_code: &'a str, +} + +impl<'a> CreditPaymentProcessor<'a> { + pub fn new(security_code: &'a str) -> Self { + Self { security_code } + } +} + +impl PaymentProcessor for CreditPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + println!("Processing credit payment type"); + println!("Verifying security code: {}", {self.security_code}); + order.status = "paid"; + } +} + +pub struct PaypalPaymentProcessor<'a> { + pub email_address: &'a str, + pub authorizer: &'a RefCell, +} + +impl<'a> PaypalPaymentProcessor<'a> { + pub fn new(email_address: &'a str, authorizer: &'a RefCell) -> Self { + Self { email_address, authorizer } + } +} + +impl PaymentProcessor for PaypalPaymentProcessor<'_> { + fn pay(&self, order: &mut Order) { + if !self.authorizer.borrow().is_authorized() { + panic!("Not authorized"); + } + + println!("Processing paypal payment type"); + println!("Using email address: {}", {self.email_address}); + order.status = "paid"; + } +} diff --git a/better-rust/solid/src/lib.rs b/better-rust/solid/src/lib.rs index 6a49eb1..768e5b8 100644 --- a/better-rust/solid/src/lib.rs +++ b/better-rust/solid/src/lib.rs @@ -5,4 +5,6 @@ pub mod open_closed_after; pub mod liskov_substitution_before; pub mod liskov_substitution_after; pub mod interface_segregation_before; -pub mod interface_segregation_after; \ No newline at end of file +pub mod interface_segregation_after; +pub mod dependency_inversion_before; +pub mod dependency_inversion_after; \ No newline at end of file diff --git a/better-rust/solid/src/main.rs b/better-rust/solid/src/main.rs index a0bc1d4..d6719f3 100644 --- a/better-rust/solid/src/main.rs +++ b/better-rust/solid/src/main.rs @@ -12,6 +12,8 @@ fn main() { interface_segregation_before(); interface_segregation_after(); + + dependency_inversion(); } #[macros::example] @@ -113,4 +115,25 @@ fn interface_segregation_after() { let processor = PaypalPaymentProcessor::new("hi@arjancodes.com", &authorizer); authorizer.borrow_mut().verify_code(465839); processor.pay(&mut order); +} + +#[macros::example] +fn dependency_inversion() { + use solid::dependency_inversion_after::*; + + let mut order = Order::new(); + + order.add_item("Keyboard", 1, 50.0); + order.add_item("SSD", 1, 150.0); + order.add_item("USB cable", 2, 5.0); + + println!("{}", order.total_price()); + + // let authorizer = RefCell::new(SMSAuthorizer::new()); + let authorizer = RefCell::new(AuthorizerRobot::new()); + + let processor = PaypalPaymentProcessor::new("hi@arjancodes.com", &authorizer); + // authorizer.borrow_mut().verify_code(465839); + authorizer.borrow_mut().not_a_robot(); + processor.pay(&mut order); } \ No newline at end of file From a323495b26289494e04efc18e85560e11721ba22 Mon Sep 17 00:00:00 2001 From: Diego Viniegra Date: Mon, 29 Apr 2024 14:24:35 -0500 Subject: [PATCH 17/18] coupling cohesion before --- better-rust/Cargo.lock | 72 +++++++++++++++++++ better-rust/Cargo.toml | 2 +- better-rust/coupling_and_cohesion/Cargo.toml | 9 +++ .../src/coupling_cohesion_after.rs | 71 ++++++++++++++++++ .../src/coupling_cohesion_before.rs | 71 ++++++++++++++++++ better-rust/coupling_and_cohesion/src/main.rs | 7 ++ 6 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 better-rust/coupling_and_cohesion/Cargo.toml create mode 100644 better-rust/coupling_and_cohesion/src/coupling_cohesion_after.rs create mode 100644 better-rust/coupling_and_cohesion/src/coupling_cohesion_before.rs create mode 100644 better-rust/coupling_and_cohesion/src/main.rs diff --git a/better-rust/Cargo.lock b/better-rust/Cargo.lock index d96eaa1..acfd705 100644 --- a/better-rust/Cargo.lock +++ b/better-rust/Cargo.lock @@ -6,6 +6,36 @@ version = 3 name = "better-rust" version = "0.1.0" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "coupling_and_cohesion" +version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + [[package]] name = "macros" version = "0.1.0" @@ -14,6 +44,12 @@ dependencies = [ "syn", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.81" @@ -32,6 +68,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "solid" version = "0.1.0" @@ -55,3 +121,9 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/better-rust/Cargo.toml b/better-rust/Cargo.toml index 740087c..1ba3465 100644 --- a/better-rust/Cargo.toml +++ b/better-rust/Cargo.toml @@ -1,4 +1,4 @@ -workspace = { members = ["solid", "macros"] } +workspace = { members = ["solid", "macros", "coupling_and_cohesion"] } [package] name = "better-rust" version = "0.1.0" diff --git a/better-rust/coupling_and_cohesion/Cargo.toml b/better-rust/coupling_and_cohesion/Cargo.toml new file mode 100644 index 0000000..08dabf0 --- /dev/null +++ b/better-rust/coupling_and_cohesion/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "coupling_and_cohesion" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.5" diff --git a/better-rust/coupling_and_cohesion/src/coupling_cohesion_after.rs b/better-rust/coupling_and_cohesion/src/coupling_cohesion_after.rs new file mode 100644 index 0000000..0abc32c --- /dev/null +++ b/better-rust/coupling_and_cohesion/src/coupling_cohesion_after.rs @@ -0,0 +1,71 @@ +use rand::{self, Rng}; + +fn generate_random_string(length: usize, digits: bool) -> String { + rand::thread_rng() + .sample_iter(rand::distributions::Alphanumeric) + .map(char::from) + .filter(|c| if digits { c.is_digit(10) } else { !c.is_digit(10) }) + .map(|c| c.to_ascii_uppercase()) + .take(length) + .collect() +} + +pub struct VehicleRegistry; + +impl VehicleRegistry { + pub fn generate_vehicle_id(&self, length: usize) -> String { + generate_random_string(length, false) + } + + pub fn generate_vehicle_license(&self, id: &str) -> String { + let front = &id[0..2]; + let middle = generate_random_string(2, true); + let last = generate_random_string(2, false); + + format!("{front}-{middle}-{last}") + } +} + +pub struct Application; + +impl Application { + pub fn register_vehicle(&self, brand: &str) { + // create a registry instance + let registry = VehicleRegistry; + + // generate a vehicle id of length 12 + let vehicle_id = registry.generate_vehicle_id(12); + + // now generate a license plate for the vehicle + // using the first two characters of the vehicle id + let license_plate = registry.generate_vehicle_license(&vehicle_id); + + // compute the catalogue price + let mut catalogue_price = 0; + + if brand == "Tesla Model 3" { + catalogue_price = 60000; + } else if brand == "Volkswagen ID3" { + catalogue_price = 35000; + } else if brand == "BMW 5" { + catalogue_price = 45000; + } + + // compute the tax percentage (default 5% of the catalogue price, except for electric cars where it is 2%) + let mut tax_percentage = 0.05; + + if brand == "Tesla Model 3" || brand == "Volkswagen ID3" { + tax_percentage = 0.02; + } + + // compute the payable tax + let payable_tax = tax_percentage * catalogue_price as f32; + + // print out the vehicle registration information + println!("Registration complete. Vehicle information:"); + println!("Brand: {brand}"); + println!("Id: {vehicle_id}"); + println!("License plate: {license_plate}"); + println!("Payable tax: {payable_tax:?}"); + } +} \ No newline at end of file diff --git a/better-rust/coupling_and_cohesion/src/coupling_cohesion_before.rs b/better-rust/coupling_and_cohesion/src/coupling_cohesion_before.rs new file mode 100644 index 0000000..0abc32c --- /dev/null +++ b/better-rust/coupling_and_cohesion/src/coupling_cohesion_before.rs @@ -0,0 +1,71 @@ +use rand::{self, Rng}; + +fn generate_random_string(length: usize, digits: bool) -> String { + rand::thread_rng() + .sample_iter(rand::distributions::Alphanumeric) + .map(char::from) + .filter(|c| if digits { c.is_digit(10) } else { !c.is_digit(10) }) + .map(|c| c.to_ascii_uppercase()) + .take(length) + .collect() +} + +pub struct VehicleRegistry; + +impl VehicleRegistry { + pub fn generate_vehicle_id(&self, length: usize) -> String { + generate_random_string(length, false) + } + + pub fn generate_vehicle_license(&self, id: &str) -> String { + let front = &id[0..2]; + let middle = generate_random_string(2, true); + let last = generate_random_string(2, false); + + format!("{front}-{middle}-{last}") + } +} + +pub struct Application; + +impl Application { + pub fn register_vehicle(&self, brand: &str) { + // create a registry instance + let registry = VehicleRegistry; + + // generate a vehicle id of length 12 + let vehicle_id = registry.generate_vehicle_id(12); + + // now generate a license plate for the vehicle + // using the first two characters of the vehicle id + let license_plate = registry.generate_vehicle_license(&vehicle_id); + + // compute the catalogue price + let mut catalogue_price = 0; + + if brand == "Tesla Model 3" { + catalogue_price = 60000; + } else if brand == "Volkswagen ID3" { + catalogue_price = 35000; + } else if brand == "BMW 5" { + catalogue_price = 45000; + } + + // compute the tax percentage (default 5% of the catalogue price, except for electric cars where it is 2%) + let mut tax_percentage = 0.05; + + if brand == "Tesla Model 3" || brand == "Volkswagen ID3" { + tax_percentage = 0.02; + } + + // compute the payable tax + let payable_tax = tax_percentage * catalogue_price as f32; + + // print out the vehicle registration information + println!("Registration complete. Vehicle information:"); + println!("Brand: {brand}"); + println!("Id: {vehicle_id}"); + println!("License plate: {license_plate}"); + println!("Payable tax: {payable_tax:?}"); + } +} \ No newline at end of file diff --git a/better-rust/coupling_and_cohesion/src/main.rs b/better-rust/coupling_and_cohesion/src/main.rs new file mode 100644 index 0000000..6c3d870 --- /dev/null +++ b/better-rust/coupling_and_cohesion/src/main.rs @@ -0,0 +1,7 @@ +mod coupling_cohesion_before; + +fn main() { + let app = coupling_cohesion_before::Application; + + app.register_vehicle("Volkswagen ID3"); +} From 1c98122da9dfc80d75c23f7355b8bd12b61441a5 Mon Sep 17 00:00:00 2001 From: Diego Viniegra Date: Mon, 29 Apr 2024 15:11:28 -0500 Subject: [PATCH 18/18] Add coupling cohesion after --- better-rust/Cargo.lock | 1 + better-rust/coupling_and_cohesion/Cargo.toml | 1 + .../src/coupling_cohesion_after.rs | 112 ++++++++++++------ better-rust/coupling_and_cohesion/src/main.rs | 21 +++- 4 files changed, 98 insertions(+), 37 deletions(-) diff --git a/better-rust/Cargo.lock b/better-rust/Cargo.lock index acfd705..a5c57b9 100644 --- a/better-rust/Cargo.lock +++ b/better-rust/Cargo.lock @@ -16,6 +16,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" name = "coupling_and_cohesion" version = "0.1.0" dependencies = [ + "macros", "rand", ] diff --git a/better-rust/coupling_and_cohesion/Cargo.toml b/better-rust/coupling_and_cohesion/Cargo.toml index 08dabf0..7d0bc68 100644 --- a/better-rust/coupling_and_cohesion/Cargo.toml +++ b/better-rust/coupling_and_cohesion/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] rand = "0.8.5" +macros = { path = "../macros" } diff --git a/better-rust/coupling_and_cohesion/src/coupling_cohesion_after.rs b/better-rust/coupling_and_cohesion/src/coupling_cohesion_after.rs index 0abc32c..7106028 100644 --- a/better-rust/coupling_and_cohesion/src/coupling_cohesion_after.rs +++ b/better-rust/coupling_and_cohesion/src/coupling_cohesion_after.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use rand::{self, Rng}; fn generate_random_string(length: usize, digits: bool) -> String { @@ -10,9 +11,71 @@ fn generate_random_string(length: usize, digits: bool) -> String { .collect() } -pub struct VehicleRegistry; +#[derive(Clone)] +pub struct VehicleInfo { + pub brand: String, + pub electric: bool, + pub catalogue_price: u32, +} + +impl VehicleInfo { + pub fn new(brand: &str, electric: bool, catalogue_price: u32) -> Self { + Self { brand: brand.to_string(), electric, catalogue_price } + } + + pub fn compute_tax(&self) -> f32 { + let mut tax_percentage = 0.05; + if self.electric { + tax_percentage = 0.02; + } + + tax_percentage * self.catalogue_price as f32 + } + + pub fn print(&self) { + println!("Brand: {}", self.brand); + println!("Payable tax: {:#?}", self.compute_tax()); + } +} + +pub struct Vehicle { + pub id: String, + pub license_plate: String, + pub info: VehicleInfo, +} + +impl Vehicle { + pub fn new(id: &str, license_plate: String, info: VehicleInfo) -> Self { + Self { id: id.to_string(), license_plate, info } + } + + pub fn print(&self) { + println!("Registration complete. Vehicle information:"); + println!("Id: {}", self.id); + println!("License plate: {}", self.license_plate); + self.info.print(); + } +} +pub struct VehicleRegistry { + pub vehicle_info: HashMap, +} impl VehicleRegistry { + pub fn new() -> Self { + let mut vehicle_registry = Self { vehicle_info: HashMap::new() }; + + vehicle_registry.add_vehicle_info("Tesla Model 3", true, 60000); + vehicle_registry.add_vehicle_info("Volkswagen ID3", true, 35000); + vehicle_registry.add_vehicle_info("BMW 5", false, 45000); + vehicle_registry.add_vehicle_info("Tesla Model Y", true, 75000); + + vehicle_registry + } + + fn add_vehicle_info(&mut self, brand: &str, electric: bool, catalogue_price: u32) { + self.vehicle_info.insert(brand.to_string(), VehicleInfo::new(brand, electric, catalogue_price)); + } + pub fn generate_vehicle_id(&self, length: usize) -> String { generate_random_string(length, false) } @@ -24,48 +87,25 @@ impl VehicleRegistry { format!("{front}-{middle}-{last}") } + + pub fn create_vehicle(&self, brand: &str) -> Vehicle { + let id = self.generate_vehicle_id(12); + let license_plate = self.generate_vehicle_license(&id); + + Vehicle::new(&id, license_plate, self.vehicle_info.get(brand).unwrap().clone()) + } } pub struct Application; impl Application { pub fn register_vehicle(&self, brand: &str) { - // create a registry instance - let registry = VehicleRegistry; - - // generate a vehicle id of length 12 - let vehicle_id = registry.generate_vehicle_id(12); + // create a registry instance + let registry = VehicleRegistry::new(); - // now generate a license plate for the vehicle - // using the first two characters of the vehicle id - let license_plate = registry.generate_vehicle_license(&vehicle_id); + let vehicle = registry.create_vehicle(brand); - // compute the catalogue price - let mut catalogue_price = 0; - - if brand == "Tesla Model 3" { - catalogue_price = 60000; - } else if brand == "Volkswagen ID3" { - catalogue_price = 35000; - } else if brand == "BMW 5" { - catalogue_price = 45000; - } - - // compute the tax percentage (default 5% of the catalogue price, except for electric cars where it is 2%) - let mut tax_percentage = 0.05; - - if brand == "Tesla Model 3" || brand == "Volkswagen ID3" { - tax_percentage = 0.02; - } - - // compute the payable tax - let payable_tax = tax_percentage * catalogue_price as f32; - - // print out the vehicle registration information - println!("Registration complete. Vehicle information:"); - println!("Brand: {brand}"); - println!("Id: {vehicle_id}"); - println!("License plate: {license_plate}"); - println!("Payable tax: {payable_tax:?}"); + // print out the vehicle information + vehicle.print(); } } \ No newline at end of file diff --git a/better-rust/coupling_and_cohesion/src/main.rs b/better-rust/coupling_and_cohesion/src/main.rs index 6c3d870..f735133 100644 --- a/better-rust/coupling_and_cohesion/src/main.rs +++ b/better-rust/coupling_and_cohesion/src/main.rs @@ -1,7 +1,26 @@ mod coupling_cohesion_before; +mod coupling_cohesion_after; fn main() { - let app = coupling_cohesion_before::Application; + coupling_cohesion_before(); + + coupling_cohesion_after(); +} + +#[macros::example] +fn coupling_cohesion_before() { + use coupling_cohesion_before::*; + + let app = Application; + + app.register_vehicle("Volkswagen ID3"); +} + +#[macros::example] +fn coupling_cohesion_after() { + use coupling_cohesion_after::*; + + let app = Application; app.register_vehicle("Volkswagen ID3"); }