Na Construção de Software Orientada a Objetos de Meyer (1988), ele define o princípio aberto / fechado da seguinte forma:
- Um módulo será considerado aberto se ainda estiver disponível para extensão. Por exemplo, deve ser possível adicionar campos às estruturas de dados que ele contém ou novos elementos ao conjunto de funções que ele executa.
- Diz-se que um módulo está fechado se estiver disponível para uso por outros módulos. Isso pressupõe que o módulo tenha recebido uma descrição estável e bem definida (a interface no sentido de ocultar informações).
Ele continua dizendo:
Se você reabrir um módulo, também deverá reabrir todos os seus clientes para atualizá-los, pois eles dependem da versão antiga. … [Este problema] surge sempre que um módulo deve ser estendido por uma nova função ou elemento de dados, provocando alterações em clientes diretos e indiretos. ... Com abordagens clássicas de design e programação, não há como escrever módulos abertos e fechados.
A solução de Meyer para esse dilema é: nunca estenda um módulo de biblioteca modificando as classes existentes; em vez disso, escreva um novo módulo que subclasse as classes existentes e faça com que novos clientes dependam desse novo módulo.
Agora, em 1988, eu estava escrevendo programas de brinquedo (processuais) no Turbo Pascal e Blankenship Basic, e minha experiência profissional do século XXI é na JVM, no CLR e em linguagens dinâmicas, então não sei o que Meyer quis dizer por "abordagens clássicas de design e programação".
O exemplo concreto de Meyer de por que os módulos clientes devem ser reabertos (uma instrução switch em uma enumeração que agora possui mais membros, exigindo mais casos) parece bastante razoável, mas ele quase não justifica a afirmação de que toda vez que você adiciona funcionalidade a uma biblioteca módulo, você precisa atualizar todos os seus clientes .
Existe uma razão histórica para que essa afirmação parecesse evidente em 1988? Por exemplo, adicionar funções ou estruturas de dados a uma biblioteca estática C alterou o layout de forma que, mesmo com APIs compatíveis com versões anteriores, os clientes precisavam ser recompilados? Ou Meyer está realmente apenas falando de um mecanismo para reforçar a compatibilidade com versões anteriores da API?