OOP - O princípio Open-Closed (OCP)


Neste artigo vou tratar de um dos assuntos que é um dos pilares da programação orientada a objetos: O princípio Open-Closed.

Obs: Os conceitos e exemplos usados neste artigo foram obtidos das referências com algumas alterações e adaptações minhas.

De maneira simples e objetiva o princípio Open-Closed afirma que :

"Classes deverão ser abertas para extensão mas fechadas para modificação" Bertrand Meyer (1988)

Como é que é ????

Abertas para extensão mas fechadas para modificação ????

Posso abrir para estender mas não posso modificar ????

Me explica isso ai....

Em outras palavras:

"O principio Open Close afirma que a concepção e escrita do código deve ser feita de uma forma que uma nova funcionalidade deve ser adicionada com mudanças mínimas no código existente e que o projeto deve ser feito de forma a permitir a adição de novas funcionalidades como as novas classes, mantendo tanto quanto possível, o código existente inalterado. "

Me mostra como fazer isso.

O exemplo a seguir foi criado no Visual C# 2010 Express Edition é um código usado apenas para ilustrar a aplicação do princípio Open-Closed:

O programa EditorGrafico foi concebido para desenhar formas geométricas e temos implementado os seguinte métodos:

  1. Forma - Define uma forma geométrica
  2. Circulo - Define um circulo e estende de Forma;
  3. Quadrado - Define um quadrado e estende de Forma;
  4. DesenharFormas - Desenha uma forma geométrica;
  5. DesenharCirculo - Desenha um círculo;
  6. DesenharQuadrado - Desenha um quadrado;
using System;
using System.Collections.Generic;

namespace Principio_Open_Closed
{
    public class EditorGrafico
    {
           public class Forma
            {
                int m_tipo;
            }

            public class Quadrado : Forma
            { 
                Quadrado(){
                }
            }

            public class Circulo : Forma
            {
                Circulo(){
                }
            }

            public void DesenharFormas(List<Forma> listaFormas)
            {
                for (int i = 0; i < listaFormas.Count; i++)
                {
                
   Forma formaAtual = listaFormas[i];
                 
  if (formaAtual is Quadrado)
                        DesenharQuadrado();
                    else if (formaAtual is Circulo)
                        DesenharCirculo();

                }
            }

            public void DesenharCirculo()
            {
                Console.WriteLine("Desenhar circulo");
            }

            public void DesenharQuadrado()
            {
                Console.WriteLine("Desenhar quadrado");
            }
    }
}

Aparentemente tudo esta correto no código da classe EditorGrafico, mas essa.
classe VIOLA o princípio Open-Closed.(OCP)

Mas como ???

Simplesmente pelo fato de que a inclusão de uma nova forma geométrica vai
exigir que a classe EditorGrafico sofra alterações o que traz as seguintes
implicações:

  • Para cada nova forma incluída os testes unitários da classe EditorGrafico
    terão que ser refeitos;
  • A inclusão de uma nova forma pode afetar as funcionalidades existentes;
  • Para incluir uma nova forma é necessário entender o funcionamento da
    classe EditorGrafico;

Para ter um efeito mais dramático, basta imaginar que a classe EditorGrafico é uma
classe grande, com um monte de funcionalidade dentro, escrito e alterado por muitos
desenvolvedores, ao passo que a classe forma pode ser uma classe implementada por um
único desenvolvedor.

Quantas vezes você já violou este princípio ???

Eu mesmo já fiz isso tantas vezes que já perdi a conta.

Aplicando princípio Open-Closed

Vamos alterar o código da classe EditorGrafico levando em conta o princípio Open-Closed.(OCP)

Vamos criar uma nova classe EditorGraficoOC e definir nesta classe o seguinte código:

namespace Principio_Open_Closed
{
    public class EditorGraficoOC
    {
        public void DesenharForma(Forma f)
        {
            f.desenhar();
        }
    }

    public abstract class Forma
    {
        public abstract void desenhar();
    }

    public class Quadrado : Forma
    {
        public override void desenhar()
        { }
    }

    public class Circulo : Forma
    {
        public override void desenhar()
        { }
    }
}
A nova concepção da classe EditorGraficoOC traz duas alterações importantes:

1- O método abstract desenhar() na classe para desenhar formas geométricas;

2- A implementação de cada forma geométrica foi movida para fora da classe;

Dessa forma, aplicando o princípio Open-Closed, os problemas do código anterior
são evitados, porque a classe EditorGraficoOC não precisa mais ser alterada
quando uma nova forma geométrica for incluída.

Para incluir uma nova forma não será mais preciso refazer o teste unitário da
classe EditorGraficoOC nem conhecer detalhes dessa classe , basta criar uma nova
classe concreta e assim os riscos de ter que alterar a classe EditorGraficoOC são
eliminados.

 

Dessa forma a nossa nova classe EditorGraficoOC esta aberta para extensão pois podemos incluir tantas formas quanto desejarmos, mas esta fechada para modificação pois podemos fazer isso sem ter que alterar praticamente nada na classe.

Tudo isso graças ao princípio Open-Closed.(OCP)

Deu para entender agora ????

Procure aplicar este princípio ao seu código e ele ganhará muito mais qualidade e terá menos trabalho.

A aplicação deste princípio leva você a se divertir mais e a sofrer menos.

Agindo desta forma, as suas classes serão mais simples, sem ter uma sobrecarga de atribuições;  e quando houver a necessidade de incluir novos comportamentos nas suas  classe, isso não irá desencadear uma série de modificações nas classes dependentes e nas unidades de teste; além disso, não vai precisar também que a equipe de teste valide todo o sistema novamente.

Aguarde mais artigos sobre os princípios S.O.L.I.D.: SRP , OCP, LSP, ISP e DIP.

Eu sei é apenas OOP , mas eu gosto...

"Falou-lhes pois Jesus outra vez, dizendo: Eu sou a luz do mundo; quem me segue não andará em trevas, mas terá a luz da vida." (João 8:12)

Referências:
  • Padrões de Projeto
  • Padrões de Projeto - O modelo MVC - Model View Controller
  • O padrão Singleton
  • VB.NET - Permitindo uma única instância da sua aplicação
  • Design Patterns - o padrão Factory
  • Conceitos sobre projetos - Decomposição
  • Usando o padrão Strategy
  • SRP - O princípio da responsabilidade única - Macoratti.net
  • Boas Práticas - O padrão inversão de controle (IoC) - Macoratti.net
  • http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
  • Conceitos sobre projetos - Decomposição
  • Seção Padrões de Projeto do site Macoratti.net
  • Super DVD .NET - A sua porta de entrada na plataforma .NET
  • Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#

  • José Carlos Macoratti