En Meyer's Object-Oriented Software Construction (1988) define el principio abierto / cerrado de la siguiente manera:
- Se dirá que un módulo está abierto si todavía está disponible para la extensión. Por ejemplo, debería ser posible agregar campos a las estructuras de datos que contiene, o nuevos elementos al conjunto de funciones que realiza.
- Se dirá que un módulo está cerrado si está disponible para su uso por otros módulos. Esto supone que el módulo ha recibido una descripción estable y bien definida (la interfaz en el sentido de ocultar información).
Él continúa diciendo:
Si vuelve a abrir un módulo, también debe volver a abrir todos sus clientes para actualizarlos, ya que dependen de la versión anterior. ... [Este problema] surge cada vez que un módulo debe extenderse por una nueva función o elemento de datos, lo que desencadena cambios en clientes directos e indirectos. ... Con los enfoques clásicos de diseño y programación, no hay forma de escribir módulos abiertos y cerrados.
La solución de Meyer a este dilema es: nunca amplíe un módulo de biblioteca modificando las clases existentes; en su lugar, escriba un nuevo módulo que subclasifique las clases existentes y haga que los nuevos clientes dependan de ese nuevo módulo.
Ahora, en 1988, estaba escribiendo programas de juguete (de procedimiento) en Turbo Pascal y Blankenship Basic, y mi experiencia profesional del siglo XXI es en JVM, CLR y en lenguajes dinámicos, así que no sé qué quería decir Meyer por "enfoques clásicos de diseño y programación".
El ejemplo concreto de Meyer de por qué los módulos del cliente deben volver a abrirse (una declaración de cambio en una enumeración que ahora tiene más miembros, que requiere más casos) parece bastante razonable, pero no justifica la afirmación de que cada vez que agrega funcionalidad a una biblioteca módulo, necesita actualizar todos sus clientes .
¿Hay alguna razón histórica de que esta afirmación pareciera evidente en 1988? Por ejemplo, ¿agregar funciones o estructuras de datos a una biblioteca estática en C cambió el diseño de tal manera que incluso con API compatibles con versiones anteriores, los clientes tuvieran que volver a compilarse? ¿O Meyer realmente está hablando de un mecanismo para hacer cumplir la compatibilidad con API hacia atrás?
Respuestas:
Por lo que puedo decir, esta pregunta ha sido respondida por el propio Bertrand Meyer, y la respuesta es que esta afirmación no es precisa. Con los enfoques clásicos de diseño y programación, de hecho, puede haber una manera de escribir módulos abiertos y cerrados.
Para descubrir esto, debe estudiar la segunda edición de este libro (publicado nueve años después, en 1997). Según el Prólogo de la segunda edición , es
En particular, la declaración que te confunde ha desaparecido. Todavía hay un capítulo de principio abierto-cerrado en "§3.3 Cinco principios", y hay una discusión más a fondo de este tema en "§14.7 Introducción a la herencia", pero la declaración de la primera edición ya no está allí.
En cambio, lo que hay allí se centra en cómo es más conveniente e idiomático en el enfoque OO en lugar de las formas anteriores,
Ya que también parece preguntarse qué significa "enfoques clásicos" Meyer aquí, puede encontrar una explicación de estos en §4.7 Estructuras modulares tradicionales . Esta sección explica que esto significa "bibliotecas de rutinas" y "paquetes" (para este último, el autor dice que el término se toma de Ada y menciona otros idiomas que tienen esta característica: clústeres en CLU y módulos en Modula).
Si lo piensa, ninguno de estos enfoques fue originalmente diseñado para ayudar a escribir código que se adhiera al principio abierto-cerrado. Esto podría llevar al autor a su evaluación algo prematura que luego se corrigió en la segunda edición.
En cuanto a lo que específicamente hizo que el autor cambiara de opinión sobre esa afirmación entre la primera y la segunda edición, creo que uno puede encontrar una respuesta, nuevamente, en el libro mismo, es decir, en la Parte F: Aplicación del método en varios idiomas y entornos " . En este capítulo, el autor analiza cómo los métodos orientados a objetos se pueden usar en idiomas más antiguos:
En particular, en esta parte, Meyer explica en detalle cómo sería posible implementar la herencia (con algunas advertencias y limitaciones, pero aún así) en C e incluso en Fortran.
Verá, esto realmente requiere revisar esa declaración de la primera edición. Parece prácticamente imposible explicar cómo conciliar "con los enfoques clásicos ... no hay forma" con ejemplos realistas sobre cómo exactamente se puede hacer.
fuente