forked from mouredev/roadmap-retos-programacion
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request mouredev#7197 from mrodara/mrodara/main
#29-Python
- Loading branch information
Showing
2 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
### Principio de Segregación de Interfaces (Interface Segregation Principle, ISP) | ||
|
||
''' | ||
Este principio establece que: | ||
"Ningún cliente debería depender de métodos que no utiliza." | ||
Esto significa que las interfaces (o clases abstractas en Python) deben diseñarse de manera que los clientes que | ||
las implementan no se vean forzados a definir métodos innecesarios o irrelevantes. | ||
Ventajas: | ||
+ Reduce el acoplamiento | ||
+ Hace el código más modular | ||
+ Facilitan la implementación | ||
''' | ||
|
||
# Ejemplo que viola el principio | ||
|
||
from abc import ABC, abstractmethod | ||
|
||
class Vehicle(ABC): | ||
|
||
@abstractmethod | ||
def drive(self): | ||
pass | ||
|
||
@abstractmethod | ||
def pilot(self): | ||
pass | ||
|
||
@abstractmethod | ||
def navigate(self): | ||
pass | ||
|
||
class Car(Vehicle): | ||
|
||
def drive(): | ||
print("El coche está en marcha") | ||
|
||
def pilot(self): | ||
raise NotImplementedError("Un coche no puede volar") | ||
|
||
def navigate(self): | ||
raise NotImplementedError("Un coche no puede navegar por el mar") | ||
|
||
''' | ||
En este ejemplo los principales problemas son: | ||
- El cliente (Car) debe implementar métodos que no utiliza (pilot y navigate) | ||
- El cliente debe manejar excepciones innecesarias | ||
''' | ||
|
||
# Fin Ejemplo que viola el principio | ||
|
||
# Rediseño para no violar el ISP | ||
|
||
class Driveable(ABC): | ||
|
||
@abstractmethod | ||
def drive(self): | ||
pass | ||
|
||
class Pilotable(ABC): | ||
|
||
@abstractmethod | ||
def pilot(self): | ||
pass | ||
|
||
class Navigateable(ABC): | ||
|
||
@abstractmethod | ||
def navigate(self): | ||
pass | ||
|
||
|
||
class Car(Driveable): | ||
|
||
def drive(self): | ||
print("El cocche está en marcha") | ||
|
||
class Plane(Pilotable): | ||
|
||
def pilot(self): | ||
print("El avión está volando") | ||
|
||
class Ship(Navigateable): | ||
|
||
def navigate(self): | ||
print("El barco se encuentra navegando en alta mar") | ||
|
||
|
||
# Fin Rediseño para no violar el ISP | ||
|
||
## EJERCICIO EXTRA | ||
|
||
class PrinterBW(ABC): | ||
|
||
@abstractmethod | ||
def print_bn(self): | ||
pass | ||
|
||
class PrinterColor(ABC): | ||
|
||
@abstractmethod | ||
def print_color(self): | ||
pass | ||
|
||
class Maileable(ABC): | ||
|
||
@abstractmethod | ||
def send_mail(self): | ||
pass | ||
|
||
class Faxeable(ABC): | ||
|
||
@abstractmethod | ||
def send_fax(self): | ||
pass | ||
|
||
class BwPrinter(PrinterBW): | ||
|
||
def print_bn(self): | ||
print("Imprimiendo documento en Blanco/Negro") | ||
|
||
class ColorPrinter(PrinterColor): | ||
|
||
def print_color(self): | ||
print("Imprimiendo documento en Color") | ||
|
||
class MultiFunction(PrinterBW, PrinterColor, Maileable, Faxeable): | ||
|
||
def print_bn(self): | ||
print("Imprimiendo documento en Blanco/Negro") | ||
|
||
def print_color(self): | ||
print("Imprimiendo documento en Color") | ||
|
||
def send_mail(self, to="[email protected]", subject="Test", body="This is a mail test"): | ||
print(f"Enviando correo electrónico a {to} con asunto {subject} y mensaje {body}") | ||
|
||
def send_fax(self, destination_number="+345557890", content="This is a fax test"): | ||
print(f"Enviando fax a {destination_number} con contenido {content}") | ||
|
||
|
||
# Batería de pruebas | ||
|
||
def test_bw_printer(): | ||
printer = BwPrinter() | ||
printer.print_bn() # Debería imprimir en blanco y negro | ||
|
||
def test_color_printer(): | ||
printer = ColorPrinter() | ||
printer.print_color() # Debería imprimir en color | ||
|
||
def test_multi_function_print_bn(): | ||
printer = MultiFunction() | ||
printer.print_bn() # Debería imprimir en blanco y negro | ||
|
||
def test_multi_function_print_color(): | ||
printer = MultiFunction() | ||
printer.print_color() # Debería imprimir en color | ||
|
||
def test_multi_function_send_mail(): | ||
printer = MultiFunction() | ||
printer.send_mail(to="[email protected]", subject="Prueba", body="Esto es una prueba") | ||
|
||
def test_multi_function_send_fax(): | ||
printer = MultiFunction() | ||
printer.send_fax(destination_number="+123456789", content="Esto es una prueba de fax") | ||
|
||
def test_no_extra_methods_bw_printer(): | ||
printer = BwPrinter() | ||
try: | ||
printer.print_color() | ||
except AttributeError: | ||
print("Error esperado: 'BwPrinter' no tiene método 'print_color'") | ||
|
||
def test_no_extra_methods_color_printer(): | ||
printer = ColorPrinter() | ||
try: | ||
printer.print_bn() | ||
except AttributeError: | ||
print("Error esperado: 'ColorPrinter' no tiene método 'print_bn'") | ||
|
||
|
||
print("Pruebas de BwPrinter:") | ||
test_bw_printer() | ||
test_no_extra_methods_bw_printer() | ||
|
||
print("\nPruebas de ColorPrinter:") | ||
test_color_printer() | ||
test_no_extra_methods_color_printer() | ||
|
||
print("\nPruebas de MultiFunction:") | ||
test_multi_function_print_bn() | ||
test_multi_function_print_color() | ||
test_multi_function_send_mail() | ||
test_multi_function_send_fax() | ||
|
||
|
||
## FIN EJERCICIO EXTRA | ||
|
||
|
||
|
||
|
||
|
||
### FIN Principio de Segregación de Interfaces (Interface Segregation Principle, ISP) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
### Principio de Inversión de Dependencias (Dependency Inversion Principle, DIP) | ||
|
||
''' | ||
Este principio establece que: | ||
Los módulos de alto nivel NO deben depender de los módulos de bajo nivel. Ambos deben depender de abstracciones. | ||
Las abstracciones NO deben depender de los detalles. Los detalles DEBEN depender de las abstracciones. | ||
En resumen, el DIP promueve que las clases principales (alto nivel) dependan de interfaces o abstracciones, | ||
en lugar de depender directamente de clases concretas (bajo nivel). | ||
''' | ||
|
||
''' | ||
Ventajas: | ||
+ Reduce el acoplamiento: | ||
Los módulos de alto nivel no dependen de los detalles específicos de implementación. | ||
+ Facilita el mantenimiento: | ||
Los detalles de implementación pueden cambiar sin afectar a las clases principales. | ||
+ Aumenta la flexibilidad y la extensibilidad: | ||
Es más sencillo sustituir o añadir implementaciones concretas al depender de abstracciones. | ||
''' | ||
|
||
# EJEMPLO QUE VIOLA EL PRINCIPIO | ||
|
||
class CreditCardPayment(): | ||
|
||
def proccess_payment(self, amount): | ||
print(f"Procesando pago con tarjeta de crédito: {amount} €") | ||
|
||
class OrderProccesor(): | ||
|
||
def __init__(self): | ||
self.payment_proccessor = CreditCardPayment() | ||
|
||
def proccess_order(self, amount): | ||
self.payment_proccessor.proccess_payment(amount=amount) | ||
|
||
''' | ||
Problemas detectados: | ||
+ Dependencia directa: | ||
OrderProcessor está acoplada directamente a CreditCardPayment. | ||
No se puede usar otro método de pago sin modificar OrderProcessor. | ||
+ Falta de flexibilidad: | ||
Si necesitas añadir PayPalPayment o CryptoPayment, tendrás que modificar el código de OrderProcessor. | ||
''' | ||
|
||
# FIN EJEMPLO QUE VIOLA EL PRINCIPIO | ||
|
||
# REDISEÑO PARA CUMPLIR CON EL PRINCIPIO | ||
from abc import ABC, abstractmethod | ||
|
||
class PaymentProccessor(ABC): | ||
|
||
@abstractmethod | ||
def proccess_payment(self, amount): | ||
pass | ||
|
||
class CreditCardPayment(PaymentProccessor): | ||
|
||
def proccess_payment(self, amount): | ||
print(f"Procesando pago con tarjeta de crédito: {amount} €") | ||
|
||
class PayPalPayment(PaymentProccessor): | ||
|
||
def proccess_payment(self, amount): | ||
print(f"Procesando el pago mediante Paypal: {amount} €") | ||
|
||
class BizumPayment(PaymentProccessor): | ||
|
||
def proccess_payment(self, amount): | ||
print(f"Procesando el pago mediante Bizum: {amount} €") | ||
|
||
|
||
# Clase de Alto nivel | ||
class OrderProccessor(): | ||
|
||
def __init__(self, payment_proccessor): | ||
self.payment_proccessor = payment_proccessor | ||
|
||
def proccess_order(self, amount): | ||
self.payment_proccessor.proccess_payment(amount=amount) | ||
|
||
order = OrderProccessor(CreditCardPayment()) | ||
order.proccess_order(amount=100) | ||
|
||
order = OrderProccessor(PayPalPayment()) | ||
order.proccess_order(amount=200) | ||
|
||
order = OrderProccessor(BizumPayment()) | ||
order.proccess_order(amount=300) | ||
|
||
# FIN REDISEÑO PARA CUMPLIR CON EL PRINCIPIO | ||
|
||
## EJERCICIO EXTRA | ||
|
||
# CLASE ABSTRACTA | ||
class Notifier(ABC): | ||
|
||
@abstractmethod | ||
def send_notification(self, message): | ||
pass | ||
|
||
#Específicas | ||
class EmailNotifier(Notifier): | ||
|
||
def send_notification(self, message): | ||
print(f"Enviando eamil con el mensaje {message}") | ||
|
||
class PushNotifier(Notifier): | ||
|
||
def send_notification(self, message): | ||
print(f"Enviando mensaje Push con texto: {message}") | ||
|
||
class SmsNotifier(Notifier): | ||
def send_notification(self, message): | ||
print(f"Enviando mensaje SMS con texto: {message}") | ||
|
||
# Alto nivel | ||
class NotificationSender(): | ||
|
||
def __init__(self, notifier: Notifier): | ||
self.notifier = notifier | ||
|
||
def send_notification(self, message): | ||
self.notifier.send_notification(message) | ||
|
||
|
||
# Batería de pruebas | ||
email_sender = NotificationSender(EmailNotifier()) | ||
email_sender.send_notification("Hola soy un Email") | ||
|
||
push_sender = NotificationSender(PushNotifier()) | ||
push_sender.send_notification("Hola soy un Push") | ||
|
||
sms_sender = NotificationSender(SmsNotifier()) | ||
sms_sender.send_notification("Hola soy un SMS") | ||
|
||
|
||
## FIN EJERCICIO EXTRA | ||
|
||
### FIN Principio de Inversión de Dependencias (Dependency Inversion Principle, DIP) |