Entendendo o open/closed principle

Leonardo Golfeto
3 min readDec 8, 2021

--

1. Introdução

Se você é um programador(a) e trabalha com alguma linguagem orientada a objetos muito provavelmente já ouviu falar no acrônimo SOLID (criado pelo Michael Feathers ele representa os cinco principais conceitos identificados por Robert C. Martin na programação orientação a objetos).

Neste conjunto importantíssimos de conceitos o OCP(Open/Closed Principle) é representado pela letra O.

2. O que é

Este princípio consiste em sempre programar entidades de um sistema (classes, módulos, funções) abertas para extensões mas fechadas para modificações, de forma que seja possível adicionar novos comportamentos a funcionalidade criando novas classes ao invés de modificar as antigas.

Isso parece ser um pouco difícil de ser aplicado, porém, no decorrer desse artigo vamos observar como é simples e a importância de programar voltado a esse padrão.

3. Vantagens

Considerado o conceito com maior importância dentre os cinco por Robert C. Martin, porém, negligenciado pela maioria dos desenvolvedores esse principio traz inúmeras vantagens para qualquer sistema OO, algumas delas são:

  1. Reduz a complexidade ciclomática
  2. Facilita a manutenção
  3. Aumenta a escalabilidade
  4. Diminui o acoplamento

4. Caso de uso

Como podemos ver, nesse trecho de código existe um serviço de e-mails onde são feitas algumas verificações baseadas no tipo passado como parâmetro para definir o comportamento do método EnviarEmail.

public enum TipoEmail {
Texto,
Html,
Criptografado
}
public class EmailService { public void enviarEmail(String mensagem, TipoEmail tipo) { if (tipo == TipoEmail.Texto) { removerFormatacao(mensagem); } else if (tipo == TipoEmail.Html) { inserirHtml(mensagem); } else if (tipo == TipoEmail.Criptografado) { criptografarMensagem(mensagem);
}
send(mensagem);
}
}

Vamos imaginar o seguinte cenário:

Nosso P.O solicita a adição de XML como tipo de e-mail, oque faremos?

A solução que vem a mente é:

public enum TipoEmail {
Texto,
Html,
Criptografado,
Xml
}
public class EmailService { public void enviarEmail(String mensagem, TipoEmail tipo) { if (tipo == TipoEmail.Texto) { removerFormatacao(mensagem); } else if (tipo == TipoEmail.Html) { inserirHtml(mensagem); } else if (tipo == TipoEmail.Criptografado) { criptografarMensagem(mensagem);
}
else if (tipo == TipoEmail.Xml) {
mapearParXml(mensagem);
}
send(mensagem);
}
}

Nesta abordagem sempre que houver necessidade de novas alterações (e você sabe que não são poucas vezes) será necessário a adição de um novo item no enum acompanhado do encadeamento de um novo if no método de envio.

Desta forma nosso serviço de e-mail tem um potencial enorme de crescimento e com isso o aumento exponencial da complexidade do código comprometendo os testes, a semântica do código e escalabilidade do sistema.

Para aplicar o Open/closed principle vamos utilizar a seguinte abordagem:

public interface Email {
void tratar();
}
public class EmailCriptografado implements Email { @Override
public void tratar() {
criptografarMensagem(mensagem);
}
}
public class EmailHtml implements Email {

@Override
public void tratar() {
inserirHtml(mensagem);
}
}public class EmailTexto implements Email { @Override
public void tratar() {
removerFormatacao(mensagem);
}
}
public class EmailXml implements Email { @Override
public void tratar() {
mapearParXml(mensagem);
}
}

Como existem vários tipos de e-mail e obrigatoriamente eles terão estratégias diferentes para tratar a mensagem, criamos uma interface chamada “Email” que terá um método chamado tratar, assim para cada tipo será criado uma classe que implementa Email e sobrescreve o método tratar.

E nossa classe de serviço fica assim:

public class EmailService {    public void enviarEmail(Email email) {          email.tratar();            send(email.getMensagem());      }    
}

Como podemos observar cada classe e-mail tem sua própria maneira de tratar a mensagem, removendo todos os if’s que existiam no nosso serviço, e o melhor de tudo, quando for necessário a adição de outro tipo só precisamos criar outra classe que implementa Email, promovendo um código realmente aberto a novas implementações e fechado para modificações.

5. Considerações finais

O mais importante é não se apegar a implementações e sim a conceitos e sempre se esforçar para aplicá-los no dia a dia. Caso não tenha ficado claro, segue alguns artigos que abordam o mesmo tema de outra forma:

  1. https://www.devmedia.com.br/open-closed-principle/18970
  2. https://www.eduardopires.net.br/2013/05/open-closed-principle-ocp/
  3. https://stackify.com/solid-design-open-closed-principle/
  4. http://www.andrecelestino.com/solid-open-closed-principle-ocp/
  5. http://joelabrahamsson.com/a-simple-example-of-the-openclosed-principle/
  6. https://medium.com/@gabriellamedas/ocp-the-open-closed-principle-b994922bed94

--

--

No responses yet