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?
Respostas:
Até onde eu sei, essa pergunta foi respondida pelo próprio Bertrand Meyer, e a resposta é que essa afirmação não é precisa. Com abordagens clássicas de design e programação, de fato pode haver uma maneira de escrever módulos abertos e fechados.
Para descobrir isso, você precisa estudar a segunda edição deste livro (publicada nove anos depois, em 1997). De acordo com o Prefácio da segunda edição , é
Em particular, a declaração que confunde você se foi. Ainda existe um capítulo de princípio Aberto-Fechado em "§3.3 Cinco Princípios", e há uma discussão mais aprofundada sobre esse tópico em "§14.7 Introdução à herança", mas a declaração da primeira edição não existe mais.
Em vez disso, o que está focado é como é mais conveniente e idiomático na abordagem OO, em oposição às formas anteriores,
Como você também parece se perguntar sobre o que "abordagens clássicas" Meyer quis dizer aqui, você pode encontrar uma explicação delas em §4.7 Estruturas modulares tradicionais . Esta seção explica que essas significam "bibliotecas de rotinas" e "pacotes" (para o último, o autor diz que o termo é retirado do Ada e menciona outras línguas com esse recurso - clusters no CLU e módulos no Modula).
Se você pensar bem, nenhuma dessas abordagens foi originalmente planejada para ajudar na escrita de código que adere ao princípio de aberto-fechado. Isso poderia levar o autor a uma avaliação um tanto prematura que foi corrigida posteriormente na segunda edição.
Quanto ao que especificamente fez o autor mudar de idéia sobre essa afirmação entre a primeira e a segunda edição, acho que podemos encontrar uma resposta, novamente, no próprio livro, ou seja, na Parte F: Aplicação do método em vários idiomas e ambientes " . Neste capítulo, o autor discute como métodos orientados a objetos podem ser usados em idiomas mais antigos:
Em particular, nesta parte, Meyer explica em detalhes como seria possível implementar a herança (com algumas ressalvas e limitações, mas ainda) em C e até em Fortran.
Veja bem, isso realmente exige uma revisão dessa declaração da primeira edição. Parece praticamente impossível explicar como conciliar "com abordagens clássicas ... não há como" com exemplos realistas de como exatamente isso pode ser feito.
fonte