OCP: Open Closed Principle // Principio Abierto/Cerrado

Open / Closed Principle
Principio abierto/cerrado

"Software entities (classes, modules, functions, etc.) should be open for extension, but closed  for modification." - Robert C. Martin parafraseando a Bertrand Meyer

Traducción literal: "Las entidades de software (clases, módulos, funciones, etcétera) deberían estar abiertas a la extensión pero cerradas a la modificación."

Mi traducción: Cambia el comportamiento de una clase mediante herencia y composición.

Empecemos con un ejemplo sencillo y típico:

public interface IForma
{
    int GetTipo();
}
public class Rectangulo : IForma
{
    public int GetTipo()
    {
        return 1;
    }
}

public class Circulo : IForma
{
    public int GetTipo()
    {
        return 2;
    }
}
public class EditorGrafico
{
    public void DibujarForma(IForma forma)
    {
        switch (forma.GetTipo())
        {
            case 1:
                DibujaUnRectangulo((Rectangulo)forma);
                break;
            case 2:
                DibujaUnCirculo((Circulo)forma);
                break;
        }
    }

    public void DibujaUnCirculo(Circulo c)
    {
        //pinta un círculo...
    }

    public void DibujaUnRectangulo(Rectangulo r)
    {
        //pinta un rectángulo
    }    
}
¿Por qué éste es un mal ejemplo? Porque si quisiéramos añadir una nueva forma, es decir, extender la clase, tendríamos que modificar ésta clase, es decir, no está abierta a la extensión. ¿Cómo solucionamos ésto? Muy fácil:
public abstract class Forma
{
    public abstract void Dibujar();
}
public class Rectangulo : Forma
{
    public override void Dibujar()
    {
        // Dibuja un Rectangulo
    }
}
public class Circulo : Forma
{
    public override void Dibujar()
    {
        // Dibuja un círculo
    }
}
public class EditorGrafico
{
    public void DibujarForma(Forma forma)
    {
        forma.Dibujar();
    }
}
¿No es genial? De una forma elegante hemos ganado en simplicidad, sólo hemos utilizado una clase abstracta con un método abstracto que será implementado por cada clase hija. Voy a insistir en mi propia traducción de éste principio, si has de cambiar una clase hazlo usando herencia y polimorfismo. No debes temer el uso de clases abstractas ni interfaces sino al revés ya que son una ayuda contra el acoplamiento de tu software que te protegen frente a cambios.

Juan García Carmona

Comentarios

Entradas populares