Skip to content

Commit d0c785e

Browse files
committed
#27 - Python
1 parent 8ea492f commit d0c785e

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
"""
2+
EJERCICIO:
3+
Explora el "Principio SOLID Abierto-Cerrado (Open-Close Principle,
4+
OCP)" y crea un ejemplo simple donde se muestre su funcionamiento de
5+
forma correcta e incorrecta.
6+
7+
DIFICULTAD EXTRA(opcional):
8+
Desarrolla una calculadora que necesita realizar diversas operaciones
9+
matemáticas.
10+
Requisitos:
11+
- Debes diseñar un sistema que permita agregar nuevas operaciones
12+
utilizando el OCP.
13+
14+
Instrucciones:
15+
1. Implementa las operaciones de suma, resta, multiplicación y
16+
división.
17+
2. Comprueba que el sistema funciona.
18+
3. Agrega una quinta operación para calcular potencias.
19+
4. Comprueba que se cumple el OCP.
20+
21+
by adra-dev
22+
"""
23+
24+
"""
25+
Open-Closed Principle (OCP):
26+
El principio open closed para el diseño orientado a objetos fue
27+
introducido por Bertran Meyer en 1988 y este declara:
28+
29+
"Las entidades del software(clases, módulos, funciones. etc.)
30+
deberían estar abiertas para extender su funcionalidad pero
31+
cerradas para su modificación."
32+
33+
documentacion:"https://realpython.com/solid-principles-python/"
34+
35+
Para entender a que se refiere el principio open-closed considera el
36+
siguiente ejemplo.
37+
"""
38+
39+
40+
from math import pi
41+
42+
class Shape:
43+
def __init__(self, shape_type, **kwargs):
44+
self.shape_type = shape_type
45+
if self.shape_type == "rectangle":
46+
self.width = kwargs["width"]
47+
self.height = kwargs["height"]
48+
elif self.shape_type == "circle":
49+
self.radius = kwargs["radius"]
50+
51+
def calculate_area(self):
52+
if self.shape_type == "rectangle":
53+
return self.width * self.height
54+
elif self.shape_type == "circle":
55+
return pi * self.radius**2
56+
57+
58+
rectangle = Shape("rectangle", width=10, height=5)
59+
print(rectangle.calculate_area())
60+
61+
circle = Shape("circle", radius=5)
62+
print(circle.calculate_area())
63+
64+
"""
65+
La clase shape funciona. Tu puedes crear circulos y rectangulos,
66+
calcular su área, etc. a pesar de eso la clase luce muy mal. algo se
67+
ve mal a primera vista.
68+
69+
Imagina que necesitas agregar una nueva figura cuadrado, ¿cómo sería?
70+
Bueno, la opcion aqui seria agregar más cláusulas elif al método .__
71+
init__() y al método .calculate_area(), para que así puedas agregar
72+
los requerimientos a la figura cuadrado.
73+
74+
Tener que realizar estos cambias para agregar una nueva figura
75+
significa que tu clase está abierta a modificación lo cual viola el
76+
principio open-closed. aquí hay una posible corrección del código
77+
78+
79+
"""
80+
81+
from abc import ABC, abstractmethod
82+
83+
class Shape(ABC):
84+
def __init__(self, shape_type):
85+
self.shape_type = shape_type
86+
87+
@abstractmethod
88+
def calculate_area(self):
89+
pass
90+
91+
92+
class Circle(Shape):
93+
def __init__(self, radius):
94+
super().__init__("Circle")
95+
self.radius = radius
96+
97+
def calculate_area(self):
98+
return pi * self.radius**2
99+
100+
101+
class Rectangle(Shape):
102+
def __init__(self, width, height):
103+
super().__init__("rectangle")
104+
self.width = width
105+
self.height = height
106+
107+
def calculate_area(self):
108+
return self.width * self.height
109+
110+
111+
class Square(Shape):
112+
def __init__(self, side):
113+
super().__init__("square")
114+
self.side = side
115+
116+
def calculate_area(self):
117+
return self.side **2
118+
119+
120+
"""
121+
En este código, se le ha realizado un refactor a la clase Shape,
122+
convirtiéndola en una clase de base abstracta(ABC). Esta clase provee
123+
de una interfaz api para cualquier tipo de forma que se quiera
124+
definir. Esta interfaz consiste del atributo .shape_type y del método
125+
.calculate_area() que se pueden sobrescribir en todas las subclases.
126+
127+
Este refactor cierra la clase a modificaciones. Ahora puedes agregar
128+
nuevas figuras al diseño de tu clase sin la necesidad de modificar la
129+
clase shape en. En cualquier caso, tendrías que modificar la interfaz
130+
necesario, lo cual también convierte la clase a un tipo polimórfica.
131+
132+
"""
133+
134+
"""
135+
Extra
136+
"""
137+
138+
class Operation(ABC):
139+
@abstractmethod
140+
def execute(self, a, b):
141+
pass
142+
143+
144+
class Addition(Operation):
145+
def execute(self, a,b):
146+
return a + b
147+
148+
149+
class Substract(Operation):
150+
def execute(self, a, b):
151+
return a - b
152+
153+
154+
class Multiply(Operation):
155+
def execute(self, a, b):
156+
return a * b
157+
158+
159+
class Division(Operation):
160+
def execute(self, a, b):
161+
return a / b
162+
163+
164+
class Power(Operation):
165+
def execute(self, a, b):
166+
return a ** b
167+
168+
169+
class Calculator:
170+
def __init__(self) -> None:
171+
self.operations = {}
172+
173+
def add_operation(self, name, operation):
174+
self.operations[name] = operation
175+
176+
def calculate(self, name, a, b):
177+
if name not in self.operations:
178+
raise ValueError(f"La operacion {name} no esta soportada.")
179+
return self.operations[name].execute(a,b)
180+
181+
182+
calculator = Calculator()
183+
calculator.add_operation("addition", Addition())
184+
calculator.add_operation("substract", Substract())
185+
calculator.add_operation("multiply", Multiply())
186+
calculator.add_operation("division", Division())
187+
calculator.add_operation("power", Power())
188+
189+
print(calculator.calculate("addition", 10,2))
190+
print(calculator.calculate("substract", 10,5))
191+
print(calculator.calculate("multiply", 10,5))
192+
print(calculator.calculate("division", 10,5))
193+
print(calculator.calculate("power", 10,5))

0 commit comments

Comments
 (0)