O que o princípio aberto-fechado significa para refatoração?
Resolva a tensão entre proteger os clientes contra alterações indesejadas e ampliar as capacidades dos serviços.
Em seu livro de 1988, Construção de Software Orientado a Objetos, o professor Bertrand Meyer definiu o Princípio Aberto-Fechado como:
“Um módulo será considerado aberto se ainda estiver disponível para extensão. Por exemplo, deveria ser possível adicionar campos às estruturas de dados que contém ou novos elementos ao conjunto de funções que executa.
"Um módulo será considerado fechado se estiver disponível para uso por outros módulos. Isso pressupõe que o módulo recebeu uma descrição estável e bem definida (a interface no sentido de ocultação de informações)."
Uma maneira mais sucinta de colocar isso seria:
As entidades de software (classes, módulos, funções, etc.) devem estar abertas para extensão, mas fechadas para modificação.
Da mesma forma (e paralelamente às descobertas de Meyer), Alistair Cockburn definiu o padrão de Variação Protegida:
"Identifique pontos de variação previstos e crie uma interface estável em torno deles."
Ambos lidam com a volatilidade do software. Quando, como sempre acontece, você precisa fazer alguma alteração em um módulo de software, os efeitos em cascata podem ser desastrosos. A causa raiz dos efeitos de ondulação desastrosos é o acoplamento rígido, portanto, o Princípio Aberto-Fechado e o Padrão de Variação Protegida nos ensinam como desacoplar adequadamente vários módulos, componentes, funções e assim por diante.
O Princípio Aberto-Fechado impede a refatoração?
Se um módulo (ou seja, um bloco de código nomeado) deve permanecer fechado para qualquer modificação, isso significa que você não tem permissão para tocá-lo depois de implantado? E se sim, isso não eliminaria qualquer possibilidade de refatoração?
Sem a capacidade de refatorar o código, você é forçado a adotar o Princípio da Finalidade. Isso sustenta que o retrabalho não é permitido (por que as partes interessadas concordariam em pagar você para trabalhar novamente em algo pelo qual já pagaram?) e você deve elaborar seu código com cuidado, porque terá apenas uma chance de fazê-lo corretamente. Isso está em total contradição com a disciplina de refatoração.
Se você tiver permissão para estender o código implantado, mas não alterá-lo, você estará fadado a nadar para sempre nos rios das cachoeiras? Ter apenas uma chance de fazer qualquer coisa é uma receita para o desastre.
Vamos revisar a abordagem para resolver esse enigma.
Como proteger os clientes de alterações indesejadas
Os clientes (ou seja, módulos ou funções que usam algum bloco de código) utilizam algumas funcionalidades aderindo ao protocolo originalmente implementado no componente ou serviço. Contudo, à medida que o componente ou serviço muda inevitavelmente, a “parceria” original entre o serviço ou componente e vários clientes se desfaz. Os clientes “descobrem” a mudança pela quebra, o que é sempre uma surpresa desagradável que muitas vezes arruína a confiança inicial.
Os clientes devem ser protegidos dessas quebras. A única maneira de fazer isso é introduzindo uma camada de abstração entre os clientes e o serviço ou componente. No jargão da engenharia de software, chamamos essa camada de abstração de “interface” (ou API).
Interfaces e APIs ocultam a implementação. Depois de providenciar a entrega de um serviço por meio de uma interface ou API, você se liberta das preocupações de alterar o código de implementação. Não importa o quanto você mude a implementação do serviço, seus clientes permanecerão felizmente inalterados.
Dessa forma, você está de volta ao seu mundo confortável de iterações. Agora você está completamente livre para refatorar, reorganizar o código e continuar reorganizando-o em busca de uma solução mais ideal.
O que neste arranjo permanece fechado para modificação é a interface ou API. A volatilidade de uma interface ou API é o que ameaça quebrar a confiança estabelecida entre o serviço e seus clientes. Interfaces e APIs devem permanecer abertas para extensão. E essa extensão acontece nos bastidores – refatorando e adicionando novos recursos, garantindo ao mesmo tempo a não volatilidade do protocolo voltado ao público.
Como estender os recursos dos serviços
Embora os serviços permaneçam não voláteis do ponto de vista do cliente, eles também permanecem abertos aos negócios quando se trata de melhorar as suas capacidades. Este princípio aberto-fechado é implementado por meio de refatoração.
Por exemplo, se o primeiro incremento do serviço OrderPayment
oferece meros recursos básicos (por exemplo, capaz de processar o total do pedido e calcular o imposto sobre vendas), o próximo incremento pode ser adicionado com segurança respeitando o Open -Princípio Fechado. Sem quebrar o handshake entre os clientes e o serviço OrderPayment
, você pode refatorar a implementação por trás da API OrderPayment
adicionando novos blocos de código.
Portanto, o segundo incremento poderia conter a capacidade de calcular custos de envio. E assim por diante, você entendeu; você realiza o Padrão de Variação Protegida observando o Princípio Aberto-Fechado. É tudo uma questão de modelar cuidadosamente abstrações de negócios.