¿Qué es el Principio Abierto/Cerrado?
El Principio Abierto/Cerrado (Open/Closed Principle) establece que:
Las clases deben estar abiertas para su extensión, pero cerradas para su modificación.
Esto significa que deberíamos poder agregar nuevas funcionalidades sin modificar el código existente.
El objetivo es evitar romper el comportamiento actual del sistema cuando se introducen cambios.
Ejemplo de la vida real
Piensa en un enchufe eléctrico.
No cambiamos el enchufe de la pared cada vez que aparece un nuevo dispositivo.
Simplemente los dispositivos se adaptan al enchufe.
De igual forma, nuestro código debe estar diseñado para adaptar nuevas extensiones sin tocar el código ya probado y estable.
Ejemplo que viola el principio
Veamos una clase Notificador que no cumple el principio:
public class Notificador
{
public void Enviar(string tipo, string mensaje)
{
if (tipo == "email")
{
Console.WriteLine($"Email: {mensaje}");
}
else if (tipo == "sms")
{
Console.WriteLine($"SMS: {mensaje}");
}
else if (tipo == "push") // ← MODIFICAMOS la clase
{
Console.WriteLine($"Push: {mensaje}");
}
else if (tipo == "slack") // ← MODIFICAMOS nuevamente
{
Console.WriteLine($"Slack: {mensaje}");
}
// ¿WhatsApp? ¿Discord? ¿Telegram?
// ¡Seguiremos modificando esta clase!
}
}
Problemas con este enfoque
- Cada vez que se agrega un nuevo tipo de notificación, tenemos que modificar la clase.
- Difícil de testear y mantener.
- Rompe el Principio de Responsabilidad Única (SRP).
- El código puede crecer fácilmente hasta tener cientos de líneas solo en un método.
Solución aplicando el Principio Abierto/Cerrado
- Interfaz base (cerrada para modificación)
public interface INotificador
{
void Enviar(string mensaje);
}
- Implementaciones (abiertas para extensión)
public class NotificadorEmail : INotificador
{
public void Enviar(string mensaje)
{
Console.WriteLine($"Email: {mensaje}");
}
}
public class NotificadorSMS : INotificador
{
public void Enviar(string mensaje)
{
Console.WriteLine($"SMS: {mensaje}");
}
}
public class NotificadorPush : INotificador
{
public void Enviar(string mensaje)
{
Console.WriteLine($"Push: {mensaje}");
}
}
- Agregar una nueva notificación (ejemplo: Slack)
public class NotificadorSlack : INotificador
{
public void Enviar(string mensaje)
{
Console.WriteLine($"Slack: {mensaje}");
}
}
- *Clase gestora que usa la interfaz *
public class GestorNotificaciones
{
private readonly INotificador _notificador;
public GestorNotificaciones(INotificador notificador)
{
_notificador = notificador;
}
public void Notificar(string mensaje)
{
_notificador.Enviar(mensaje);
}
}
- Uso del código
class Program
{
static void Main()
{
INotificador notificador = new NotificadorSlack();
var gestor = new GestorNotificaciones(notificador);
gestor.Notificar("¡Hola desde Slack!");
}
}
¿Qué logramos con esto?
Ahora cada tipo de notificación es independiente.
Si queremos agregar un nuevo canal, como WhatsApp o Telegram, solo creamos una nueva clase que implemente INotificador
.
No necesitamos modificar las clases existentes
Beneficios
- Fácil de testear: cada clase puede probarse de forma aislada.
- Cumple el Principio de Responsabilidad Única (SRP).
- Código limpio, legible y mantenible.
- Escalable: agregar nuevas notificaciones es sencillo.
Conclusión
El Principio Abierto/Cerrado es una pieza fundamental de SOLID.
Te permite construir software flexible, mantenible y escalable a largo plazo.
Diseña tu código para extenderse, no para reescribirse.
Top comments (0)