Dando continuidade à série sobre os princípios SOLID em Go, hoje vamos falar sobre o Open/Closed Principle (OCP). Para ler o primeiro artigo acesse:
A definição formal do OCP diz que "um artefato de software deve estar aberto para extensão, mas fechado para modificações".
Este é provavelmente o princípio mais polêmico e difícil de assimilar logo de cara, afinal de contas, software é evolutivo, é incomum que um programa seja desenvolvido uma vez e nunca mais modificado. Então onde esse princípio tenta chegar?
Se uma nova funcionalidade precisa ser adicionada, deve ser possível implementá-la criando uma nova classe, módulo ou função, sem precisar modificar o código de outras partes do sistema. Isso significa que as entidades de software devem ser projetadas de forma modular e coesa, com interfaces claras e contratos bem definidos.
Em resumo, o "fechado para modificações" do OCP não significa que o software nunca pode ser modificado, mas sim que as modificações devem ser realizadas de forma consciente e planejada, sem gerar impactos negativos.
Agora vamos sair da teoria e ver como isso funciona na prática com GoLang. Vejamos primeiro um exemplo mais lúdico. Observem o código abaixo:
A struct Calculator possui um método sumAreas que define como parâmetro a variável shapes, que pode ser qualquer coisa. Linhas a frente podemos encontrar um switch-case para mapear cada tipo possível.
O que aconteceria se definíssemos uma forma Triangle e quiséssemos que a área dela fosse somada também? Teríamos que modificar a função sumAreas para mapeá-la e realizar o cálculo, certo? Por esse motivo, o código acima quebra o Open/Closed Principle; para cada nova forma, uma modificação é necessária em sumAreas. Isso pode afetar negativamente a manutenibilidade do código, aumentando a complexidade, o risco de erros e a dificuldade de alterações futuras.
Então como resolver?
Podemos delegar a responsabilidade do cálculo das áreas às suas respectivas formas geométricas (alô SRP) e fechar um contrato através de uma interface chamada Shape com um método Area(). Vejamos:
Neste exemplo, a função sumAreas está aberta para extensão porque podemos adicionar novas formas que implementam a interface Shape sem modificá-la. Ela também está fechada para modificação porque não precisamos alterar seu código interno para lidar com novas formas.
Mas e no mundo real, onde podemos aplicar o Open/Closed Principle?
Vamos supor que você esteja desenvolvendo um sistema de e-commerce e precisa calcular o frete para entrega dos produtos. A função que faz esse cálculo poderia facilmente ser escrita assim:
O problema com essa implementação é da mesma natureza do que vimos no caso das formas geométricas: sempre que uma nova transportadora for adicionada, será necessário modificar a função CalculateShipping.
Para corrigir essa violação do OCP, podemos criar uma interface ShippingProvider que define um método CalculateShipping e, em seguida, implementar uma struct para cada transportadora. A função CalculateShipping pode receber uma instância da struct correspondente e delegar o cálculo do frete para ela.
Formas práticas de seguir o OCP
Do meu ponto de vista, o Open/Closed Principle é o mais complicado e consequentemente incompreendido dentre os 5 princípios SOLID. Nesse artigo eu trouxe exemplos onde fica claro quando aplicá-lo, mas no dia a dia nem sempre vai ser assim. Precisamos ser capazes de identificar corretamente áreas no código que precisam ser isoladas para que possam ser modificadas sem afetar outras partes do sistema (pontos de variação). Ao mesmo tempo, não queremos desenvolver software com muita complexidade inicial. Tendo isso em mente, aqui estão maneiras práticas de seguir OCP:
- Se você ainda não consegue identificar os pontos de variação em seu código, comece de um jeito simples, mas não simplório. Então, à medida que o sistema evolui, faça sua refatoração e construa a abstração correta em torno desses pontos.
- Se você conhece seus pontos de variação antecipadamente, tente identificar o nível certo de abstração que seu software precisa sem complicar demais as coisas.
Isso é tudo, pessoal! Até a próxima!
Referências:
Top comments (0)