Skip to content

Commit 3517aad

Browse files
committed
#27 - java, javascript, php, c# y typescript
1 parent c4ffec9 commit 3517aad

File tree

5 files changed

+1060
-0
lines changed

5 files changed

+1060
-0
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
/*
6+
* PRINCIPIO ABIERTO-CERRADO (OCP)
7+
*
8+
* El principio establece que las entidades de software (clases, módulos, funciones, etc.)
9+
* deberían estar:
10+
* - ABIERTAS para la extensión: Podemos agregar nuevo comportamiento
11+
* - CERRADAS para la modificación: No debemos modificar el código existente
12+
*
13+
* Beneficios:
14+
* 1. Código más mantenible y escalable
15+
* 2. Reduce el riesgo de bugs en código existente
16+
* 3. Facilita la adición de nuevas funcionalidades
17+
*/
18+
19+
namespace OCP.Calculator
20+
{
21+
// EJEMPLO INCORRECTO (Violando OCP)
22+
// ❌ Cada vez que queremos agregar una nueva operación, debemos modificar la clase existente
23+
public class BadCalculator
24+
{
25+
public decimal Calculate(decimal a, decimal b, string operation)
26+
{
27+
switch (operation)
28+
{
29+
case "sum":
30+
return a + b;
31+
case "subtract":
32+
return a - b;
33+
case "multiply":
34+
return a * b;
35+
case "divide":
36+
return a / b;
37+
// Si queremos agregar una nueva operación, debemos modificar esta clase
38+
// violando el principio OCP
39+
default:
40+
throw new ArgumentException("Operación no soportada");
41+
}
42+
}
43+
}
44+
45+
// EJEMPLO CORRECTO (Siguiendo OCP)
46+
// Definimos una interfaz para las operaciones
47+
public interface IOperation
48+
{
49+
decimal Execute(decimal a, decimal b);
50+
string Symbol { get; }
51+
string Name { get; }
52+
}
53+
54+
// Implementamos cada operación como una clase separada
55+
public class Addition : IOperation
56+
{
57+
public decimal Execute(decimal a, decimal b) => a + b;
58+
public string Symbol => "+";
59+
public string Name => "Suma";
60+
}
61+
62+
public class Subtraction : IOperation
63+
{
64+
public decimal Execute(decimal a, decimal b) => a - b;
65+
public string Symbol => "-";
66+
public string Name => "Resta";
67+
}
68+
69+
public class Multiplication : IOperation
70+
{
71+
public decimal Execute(decimal a, decimal b) => a * b;
72+
public string Symbol => "*";
73+
public string Name => "Multiplicación";
74+
}
75+
76+
public class Division : IOperation
77+
{
78+
public decimal Execute(decimal a, decimal b)
79+
{
80+
if (b == 0)
81+
throw new DivideByZeroException("No se puede dividir por cero");
82+
return a / b;
83+
}
84+
public string Symbol => "/";
85+
public string Name => "División";
86+
}
87+
88+
// Podemos agregar nuevas operaciones sin modificar el código existente
89+
public class Power : IOperation
90+
{
91+
public decimal Execute(decimal a, decimal b)
92+
{
93+
return (decimal)Math.Pow((double)a, (double)b);
94+
}
95+
public string Symbol => "^";
96+
public string Name => "Potencia";
97+
}
98+
99+
// Clase para resultados de operaciones
100+
public class OperationResult
101+
{
102+
public decimal Value { get; set; }
103+
public string Operation { get; set; }
104+
public decimal FirstOperand { get; set; }
105+
public decimal SecondOperand { get; set; }
106+
public bool IsSuccess { get; set; }
107+
public string ErrorMessage { get; set; }
108+
109+
public override string ToString() =>
110+
IsSuccess
111+
? $"{FirstOperand} {Operation} {SecondOperand} = {Value}"
112+
: $"Error: {ErrorMessage}";
113+
}
114+
115+
// La calculadora que cumple con OCP
116+
public class Calculator
117+
{
118+
private readonly Dictionary<string, IOperation> _operations;
119+
120+
public Calculator()
121+
{
122+
_operations = new Dictionary<string, IOperation>();
123+
}
124+
125+
// Método para registrar nuevas operaciones
126+
public void RegisterOperation(IOperation operation)
127+
{
128+
_operations[operation.Symbol] = operation;
129+
}
130+
131+
// Método para realizar cálculos con manejo de errores
132+
public OperationResult Calculate(decimal a, decimal b, string symbol)
133+
{
134+
try
135+
{
136+
if (!_operations.TryGetValue(symbol, out var operation))
137+
{
138+
return new OperationResult
139+
{
140+
IsSuccess = false,
141+
ErrorMessage = $"Operación {symbol} no soportada"
142+
};
143+
}
144+
145+
return new OperationResult
146+
{
147+
IsSuccess = true,
148+
Value = operation.Execute(a, b),
149+
Operation = symbol,
150+
FirstOperand = a,
151+
SecondOperand = b
152+
};
153+
}
154+
catch (Exception ex)
155+
{
156+
return new OperationResult
157+
{
158+
IsSuccess = false,
159+
ErrorMessage = ex.Message,
160+
Operation = symbol,
161+
FirstOperand = a,
162+
SecondOperand = b
163+
};
164+
}
165+
}
166+
167+
// Método para obtener operaciones disponibles
168+
public IEnumerable<(string Symbol, string Name)> GetAvailableOperations()
169+
{
170+
return _operations.Values.Select(op => (op.Symbol, op.Name));
171+
}
172+
}
173+
174+
// Clase principal para demostración
175+
public class Program
176+
{
177+
public static void Main()
178+
{
179+
// Creamos una instancia de la calculadora
180+
var calculator = new Calculator();
181+
182+
// Registramos las operaciones básicas
183+
calculator.RegisterOperation(new Addition());
184+
calculator.RegisterOperation(new Subtraction());
185+
calculator.RegisterOperation(new Multiplication());
186+
calculator.RegisterOperation(new Division());
187+
188+
// Mostramos las operaciones disponibles
189+
Console.WriteLine("Operaciones disponibles:");
190+
foreach (var (symbol, name) in calculator.GetAvailableOperations())
191+
{
192+
Console.WriteLine($"- {name} ({symbol})");
193+
}
194+
195+
// Probamos las operaciones básicas
196+
var testCases = new[]
197+
{
198+
(a: 10m, b: 5m, symbol: "+"),
199+
(a: 10m, b: 5m, symbol: "-"),
200+
(a: 10m, b: 5m, symbol: "*"),
201+
(a: 10m, b: 5m, symbol: "/")
202+
};
203+
204+
Console.WriteLine("\nProbando operaciones básicas:");
205+
foreach (var (a, b, symbol) in testCases)
206+
{
207+
var result = calculator.Calculate(a, b, symbol);
208+
Console.WriteLine(result);
209+
}
210+
211+
// Agregamos una nueva operación (potencia) sin modificar el código existente
212+
calculator.RegisterOperation(new Power());
213+
214+
Console.WriteLine("\nProbando nueva operación (potencia):");
215+
var powerResult = calculator.Calculate(2, 3, "^");
216+
Console.WriteLine(powerResult);
217+
218+
// Probamos el manejo de errores
219+
Console.WriteLine("\nProbando manejo de errores:");
220+
221+
// División por cero
222+
var divByZeroResult = calculator.Calculate(5, 0, "/");
223+
Console.WriteLine(divByZeroResult);
224+
225+
// Operación no existente
226+
var invalidOpResult = calculator.Calculate(5, 2, "%");
227+
Console.WriteLine(invalidOpResult);
228+
}
229+
}
230+
}
231+
232+
/*
233+
* EXPLICACIÓN DE POR QUÉ ESTE DISEÑO CUMPLE CON OCP:
234+
*
235+
* 1. ABIERTO PARA EXTENSIÓN:
236+
* - Podemos agregar nuevas operaciones implementando la interfaz IOperation
237+
* - No necesitamos modificar ninguna clase existente
238+
* - Cada operación está encapsulada en su propia clase
239+
*
240+
* 2. CERRADO PARA MODIFICACIÓN:
241+
* - La clase Calculator no necesita ser modificada para agregar nuevas operaciones
242+
* - El código existente permanece intacto cuando agregamos nuevas funcionalidades
243+
* - La interfaz IOperation define un contrato claro que no cambia
244+
*
245+
* 3. VENTAJAS DE ESTE DISEÑO:
246+
* - Fácil de mantener y extender
247+
* - Cada operación está aislada y puede ser probada independientemente
248+
* - Reduce el acoplamiento entre componentes
249+
* - Facilita la adición de nuevas operaciones sin riesgo de afectar las existentes
250+
*
251+
* 4. CARACTERÍSTICAS ESPECÍFICAS DE LA IMPLEMENTACIÓN EN C#:
252+
* - Uso de interfaces y genéricos
253+
* - Manejo de errores con try-catch y tipos específicos de excepciones
254+
* - Uso de tipos decimales para precisión en cálculos
255+
* - Clase específica para resultados con estado de éxito/error
256+
* - Uso de características modernas de C# como tuplas y expression-bodied members
257+
* - Organización en namespace
258+
* - Uso de LINQ para consultas
259+
*/

0 commit comments

Comments
 (0)