Entendo a intenção do princípio aberto-fechado. Ele visa reduzir o risco de quebrar algo que já funciona ao modificá-lo, solicitando que você tente estender sem modificar.
No entanto, tive alguns problemas para entender como esse princípio é aplicado na prática. No meu entender, existem duas maneiras de aplicá-lo. Antes e depois de uma possível mudança:
Antes: programe para abstrações e 'preveja o futuro' o máximo que puder. Por exemplo, um método
drive(Car car)
precisará ser alterado seMotorcycle
s forem adicionados ao sistema no futuro, portanto, provavelmente viola o OCP. Masdrive(MotorVehicle vehicle)
é menos provável que o método precise mudar no futuro, por isso adere ao OCP.No entanto, é bastante difícil prever o futuro e saber com antecedência quais mudanças serão feitas no sistema.
Depois: quando uma alteração for necessária, estenda uma classe em vez de modificar o código atual.
A prática nº 1 não é difícil de entender. No entanto, é a prática número 2 que estou tendo problemas para entender como me inscrever.
Por exemplo (a tirei de um vídeo no YouTube): vamos dizer que temos um método em uma classe que aceita CreditCard
objetos: makePayment(CraditCard card)
. Um dia Voucher
s são adicionados ao sistema. Este método não os suporta, portanto, ele deve ser modificado.
Ao implementar o método em primeiro lugar, falhamos em prever o futuro e o programa em termos mais abstratos (por exemplo makePayment(Payment pay)
, agora precisamos alterar o código existente.
A prática nº 2 diz que devemos adicionar a funcionalidade estendendo ao invés de modificar. O que isso significa? Devo subclassificar a classe existente em vez de simplesmente alterar o código existente? Devo fazer algum tipo de wrapper para evitar a reescrita do código?
Ou o princípio nem mesmo se refere a 'como modificar / adicionar corretamente a funcionalidade', mas se refere a 'como evitar a necessidade de fazer alterações em primeiro lugar (isto é, programa para abstrações)?