DEV Community

Sadel Fortunato
Sadel Fortunato

Posted on

Dia 3: 🧩 Principio Abierto/Cerrado (Open/Closed Principle) en C#

¿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!
    }
}

Enter fullscreen mode Exit fullscreen mode

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

  1. Interfaz base (cerrada para modificación)
public interface INotificador
{
    void Enviar(string mensaje);
}

Enter fullscreen mode Exit fullscreen mode
  1. 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}");
    }
}



Enter fullscreen mode Exit fullscreen mode
  1. Agregar una nueva notificación (ejemplo: Slack)
public class NotificadorSlack : INotificador
{
    public void Enviar(string mensaje)
    {
        Console.WriteLine($"Slack: {mensaje}");
    }
}

Enter fullscreen mode Exit fullscreen mode
  1. *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);
    }
}

Enter fullscreen mode Exit fullscreen mode
  1. Uso del código
class Program
{
    static void Main()
    {
        INotificador notificador = new NotificadorSlack();
        var gestor = new GestorNotificaciones(notificador);

        gestor.Notificar("¡Hola desde Slack!");
    }
}

Enter fullscreen mode Exit fullscreen mode

¿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)