Skip to content

Commit f97c13e

Browse files
authored
Merge pull request #8290 from raynerpv2022/main
#30 - Python
2 parents 18f9283 + 6283e3a commit f97c13e

File tree

1 file changed

+365
-0
lines changed

1 file changed

+365
-0
lines changed
Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
# /*
2+
# * EJERCICIO:
3+
# * Explora el "Principio SOLID de Inversión de Dependencias (Dependency Inversion
4+
# * Principle, DIP)" y crea un ejemplo simple donde se muestre su funcionamiento
5+
# * de forma correcta e incorrecta.
6+
from abc import ABC, abstractmethod
7+
8+
9+
10+
11+
# * DIFICULTAD EXTRA (opcional):
12+
# * Crea un sistema de notificaciones.
13+
# * Requisitos:
14+
# * 1. El sistema puede enviar Email, PUSH y SMS (implementaciones específicas).
15+
# * 2. El sistema de notificaciones no puede depender de las implementaciones específicas.
16+
# * Instrucciones:
17+
# * 1. Crea la interfaz o clase abstracta.
18+
# * 2. Desarrolla las implementaciones específicas.
19+
# * 3. Crea el sistema de notificaciones usando el DIP.
20+
# * 4. Desarrolla un código que compruebe que se cumple el principio.
21+
# */
22+
23+
24+
# Sistema de Notificaciones
25+
# DIP incorrecto
26+
27+
28+
29+
class PostNotification:
30+
def SendMessage(self):
31+
print("Sended Notificacion per Post")
32+
33+
# addicionando clase para enviar por email, necesitamos modificar la clase Notificacion
34+
35+
class EmailNotification:
36+
def SendMessage(self):
37+
print("Sended Notificacion per Email ")
38+
39+
40+
class Notification:
41+
def __init__(self, m : PostNotification, e : EmailNotification):
42+
self.Message = m
43+
self.email = e
44+
45+
def PostMessage(self):
46+
self.Message.SendMessage()
47+
48+
def EmailMessage(self):
49+
self.email.SendMessage()
50+
51+
e = EmailNotification()
52+
p = PostNotification()
53+
Mess1 = Notification(p,e)
54+
Mess1.PostMessage()
55+
Mess1.EmailMessage()
56+
57+
# Correcto
58+
59+
60+
class GenericNotification(ABC):
61+
@abstractmethod
62+
def SendMessage(self ):
63+
pass
64+
65+
class PostNotification(GenericNotification):
66+
def __init__(self, message):
67+
self.message = message
68+
69+
def SendMessage(self):
70+
print(f"Message {self.message} was sent via POst")
71+
72+
class EmailNotification(GenericNotification):
73+
def __init__(self, message):
74+
self.message = message
75+
76+
def SendMessage(self ):
77+
print(f"Message {self.message} was sent via Email")
78+
79+
class WhatsAPPNotification(GenericNotification):
80+
def __init__(self, message):
81+
self.message = message
82+
83+
def SendMessage(self):
84+
print(f"Message {self.message} was sent via WhatsAPP")
85+
86+
class TelegramNotification(GenericNotification):
87+
def __init__(self, message):
88+
self.message = message
89+
90+
def SendMessage(self):
91+
print(f"Message {self.message} was sent via Telegram")
92+
93+
94+
class Notification:
95+
def __init__(self, Noti: GenericNotification):
96+
self.notification = Noti
97+
98+
# aqui almaceno el mensaje directo en la la instancia de la clase a enviar sea, sms, email, etc.
99+
def Send(self):
100+
self.notification.SendMessage()
101+
102+
103+
104+
w = WhatsAPPNotification("Hallo")
105+
p = PostNotification("Hola")
106+
e = EmailNotification("HI")
107+
t = TelegramNotification("Telegram")
108+
109+
n = Notification(w)
110+
n.Send()
111+
n = Notification(p)
112+
n.Send()
113+
n = Notification(e)
114+
n.Send()
115+
n = Notification(t)
116+
n.Send()
117+
118+
119+
120+
121+
122+
123+
# Respuesta de CHatGPT
124+
# Has implementado correctamente el Principio de Inversión de Dependencias (DIP)! Ahora, si deseas seguir aplicando los demás principios SOLID a este ejemplo, podemos revisar cómo mejorar el diseño con cada uno de ellos. Vamos a hacer un breve repaso de cada uno:
125+
# 1. Single Responsibility Principle (SRP):
126+
127+
# Cada clase tiene una única responsabilidad.
128+
129+
# PostNotification, EmailNotification, y WhatsAPPNotification son responsables de enviar un tipo específico de notificación.
130+
131+
# Notification es responsable de recibir una notificación y enviarla.
132+
# Cumple con SRP.
133+
134+
# 2. Open/Closed Principle (OCP):
135+
136+
# El sistema está abierto para su extensión, pero cerrado para su modificación.
137+
138+
# Si quisieras agregar otro tipo de notificación (como SMS, Push, etc.), simplemente crearías una nueva clase que implemente GenericNotification, sin necesidad de modificar las clases existentes.
139+
# Cumple con OCP.
140+
141+
# 3. Liskov Substitution Principle (LSP):
142+
143+
# Las subclases deben poder sustituir a sus clases base sin afectar la funcionalidad del sistema.
144+
145+
# PostNotification, EmailNotification, y WhatsAPPNotification son clases que implementan GenericNotification, lo que asegura que todas se comporten de manera esperada al ser usadas de forma intercambiable.
146+
# Cumple con LSP.
147+
148+
# 4. Interface Segregation Principle (ISP):
149+
150+
# Las interfaces deben ser específicas y no imponer métodos innecesarios.
151+
152+
# La interfaz GenericNotification tiene solo el método necesario SendMessage. Si alguna notificación requiere más métodos (como establecer una prioridad, por ejemplo), puedes agregar una nueva interfaz sin hacer cambios innecesarios en las demás.
153+
# Cumple con ISP.
154+
155+
# 5. Dependency Inversion Principle (DIP):
156+
157+
# Ya lo has implementado correctamente. La clase Notification depende de la interfaz GenericNotification, no de clases concretas, lo que permite que cualquier tipo de notificación sea inyectada sin modificar el comportamiento de Notification.
158+
# Cumple con DIP.
159+
# Resumen:
160+
161+
# Tu diseño sigue correctamente los 5 principios SOLID. Las clases están bien estructuradas y mantienen una separación clara de responsabilidades, haciendo que el código sea extensible, mantenible y fácil de probar.
162+
163+
# Si quieres explorar más sobre estos principios o tienes alguna duda en particular, no dudes en preguntar. ¡Buen trabajo!
164+
165+
166+
167+
# ¡Perfecto! Vamos a revisar tu código en Python paso a paso para ver cómo se alinean (o no) con los 5 principios SOLID. Aquí te dejo el análisis detallado:
168+
# ✅ 1. Single Responsibility Principle (SRP)
169+
170+
# Una clase debe tener una sola responsabilidad.
171+
172+
# ✔️ Cumplido:
173+
174+
# Cada clase tiene una única responsabilidad clara:
175+
176+
# PostNotification, EmailNotification y WhatsAPPNotification solo envían mensajes por un canal específico.
177+
178+
# Notification solo coordina el envío.
179+
180+
# No hay mezcla de lógicas adicionales.
181+
182+
# ✅ 2. Open/Closed Principle (OCP)
183+
184+
# Abierto para extensión, cerrado para modificación.
185+
186+
# ✔️ Cumplido:
187+
188+
# Si mañana agregas un nuevo canal (por ejemplo, TelegramNotification), puedes extender el sistema sin modificar las clases existentes.
189+
190+
# Solo necesitas crear una nueva subclase de GenericNotification.
191+
192+
# class TelegramNotification(GenericNotification):
193+
# def __init__(self, message):
194+
# self.message = message
195+
196+
# def SendMessage(self):
197+
# print(f"Message {self.message} was sent via Telegram")
198+
199+
# ✅ 3. Liskov Substitution Principle (LSP)
200+
201+
# Las subclases deben poder sustituir a sus clases base sin problemas.
202+
203+
# ✔️ Cumplido:
204+
205+
# Todas las clases (PostNotification, EmailNotification, WhatsAPPNotification) pueden reemplazar a GenericNotification en Notification sin romper nada.
206+
207+
# n = Notification(EmailNotification("Hi")) # funciona igual con cualquier clase hija
208+
# n.Send()
209+
210+
# ✅ 4. Interface Segregation Principle (ISP)
211+
212+
# Los clientes no deben depender de interfaces que no usan.
213+
214+
# ✔️ Cumplido:
215+
216+
# GenericNotification tiene una única función abstracta, SendMessage(), y todas las subclases la implementan.
217+
218+
# No estás forzando a las subclases a implementar métodos que no necesitan.
219+
220+
# ✅ 5. Dependency Inversion Principle (DIP)
221+
222+
# Depender de abstracciones, no de implementaciones concretas.
223+
224+
# ✔️ Cumplido:
225+
226+
# La clase Notification depende de GenericNotification (una abstracción), no de clases concretas como EmailNotification.
227+
228+
# Esto permite intercambiar implementaciones sin tocar Notification.
229+
230+
# class Notification:
231+
# def __init__(self, Noti: GenericNotification): # <- buena práctica
232+
# self.notification = Noti
233+
234+
235+
236+
# EXTRA EXTAR
237+
238+
# Crear un sistema que permita ejecutar comandos (Start, Shutdown, Login, Logout, Reset, etc.)
239+
# en distintos sistemas operativos (Windows, Ubuntu, etc.) siguiendo los 5 principios SOLID.
240+
241+
# Requisitos:
242+
243+
# SRP – Principio de Responsabilidad Única:
244+
245+
# Cada clase debe encargarse de una sola cosa: enviar un comando, representar un sistema operativo, o coordinar la ejecución.
246+
247+
# OCP – Abierto para extensión, cerrado para modificación:
248+
249+
# Debes poder agregar nuevos comandos o nuevos sistemas operativos sin modificar las clases existentes.
250+
251+
# LSP – Sustitución de Liskov:
252+
253+
# Las clases hijas (Windows, Ubuntu, etc.) deben poder sustituir a la clase base del sistema operativo sin alterar el comportamiento del programa.
254+
255+
# ISP – Principio de Segregación de Interfaces:
256+
257+
# Divide los comandos en interfaces específicas (por ejemplo, ILogin, IShutdown) en lugar de una sola interfaz gigante.
258+
259+
# DIP – Principio de Inversión de Dependencias:
260+
261+
# Las clases de alto nivel (como CommandExecutor) deben depender de interfaces abstractas, no de implementaciones concretas.
262+
263+
264+
class VirtualCommand(ABC):
265+
@abstractmethod
266+
def Execute(self):
267+
pass
268+
269+
270+
271+
class iStart(VirtualCommand):
272+
def Execute(self):
273+
return "Start"
274+
275+
class iShutDown(VirtualCommand):
276+
def Execute(self):
277+
return " ShutDown"
278+
279+
280+
class VirtualSO(ABC):
281+
@abstractmethod
282+
def Command(self, command : VirtualCommand):
283+
pass
284+
285+
class iWindows(VirtualSO):
286+
def Command(self, command: VirtualCommand):
287+
print(f" Command {command.Execute()} in Windows")
288+
289+
class iUbuntu(VirtualSO):
290+
def Command(self, command : VirtualCommand):
291+
print(f" Command {command.Execute()} in Ubuntu")
292+
293+
294+
class ExecutTerminal:
295+
def __init__(self,command: VirtualCommand, so: VirtualSO):
296+
self.command = command
297+
self.so = so
298+
299+
def Execute(self):
300+
self.so.Command(self.command)
301+
302+
start = iStart()
303+
shutdown = iShutDown()
304+
so_w = iWindows()
305+
so_u = iUbuntu()
306+
ex = ExecutTerminal(start,so_w)
307+
ex.Execute()
308+
ex = ExecutTerminal(shutdown, so_u)
309+
ex.Execute()
310+
311+
312+
313+
314+
315+
316+
# ✅ 1. SRP – Principio de Responsabilidad Única
317+
318+
# Cada clase tiene una responsabilidad única:
319+
320+
# VirtualCommand define una interfaz para comandos.
321+
322+
# iStart e iShutDown implementan comandos concretos.
323+
324+
# VirtualSO es la abstracción para los sistemas operativos.
325+
326+
# iWindows e iUbuntu ejecutan comandos específicos en su SO.
327+
328+
# ExecutTerminal orquesta la ejecución, pero no se encarga de los detalles internos de comandos ni SO.
329+
330+
# ✅ Cumplido.
331+
# ✅ 2. OCP – Principio de Abierto/Cerrado
332+
333+
# Tu código está abierto a extensión (puedes crear nuevos comandos o SOs), pero cerrado a modificación (no necesitas tocar las clases existentes para extender).
334+
335+
# Por ejemplo:
336+
337+
# Puedes agregar iRestart() sin tocar ExecutTerminal.
338+
339+
# Puedes crear un nuevo SO como iMacOS.
340+
341+
# ✅ Cumplido.
342+
# ✅ 3. LSP – Principio de Sustitución de Liskov
343+
344+
# Las instancias de VirtualCommand (iStart, iShutDown) pueden reemplazar sin problema a su clase base VirtualCommand en cualquier parte del código sin romper nada.
345+
346+
# ✅ Cumplido.
347+
# ✅ 4. ISP – Principio de Segregación de Interfaces
348+
349+
# Estás usando interfaces (VirtualCommand, VirtualSO) con métodos mínimos y necesarios. No obligas a las clases a implementar métodos que no necesitan.
350+
351+
# ✅ Cumplido.
352+
# ✅ 5. DIP – Principio de Inversión de Dependencias
353+
354+
# ExecutTerminal depende de abstracciones, no de clases concretas:
355+
356+
# def __init__(self, command: VirtualCommand, so: VirtualSO)
357+
358+
# Eso te da flexibilidad total para cambiar implementaciones sin afectar la lógica de ExecutTerminal.
359+
360+
# ✅ Cumplido.
361+
# 🔧 Sugerencias mínimas (opcional):
362+
363+
# Los nombres como iStart e iShutDown podrían cambiarse a StartCommand y ShutDownCommand para ser más claros (prefijo "i" se usa a veces para interfaces, lo cual puede llevar a confusión).
364+
365+
# Si más adelante quieres ejecutar múltiples comandos en fila, podrías añadir una lista de comandos o un patrón Command más completo (con undo, etc.).

0 commit comments

Comments
 (0)