experiencia
Servicios - Sepa lo que Ricardo Devis & Asociados pueden hacer por ustedPublicaciones - Consulte los documentos que ponemos a su disposiciónContacto - Conozca como ponerse en contacto con Ricardo Devis & Asociados
 


RPP enero 1996

Objetos: Mitos, Hitos y Ritos


Ricardo Devis
Botella

En torno a ciertos popularmente entendidos hitos se han conjugado una larga serie de inexactitudes conformando lo que, con la adición de fantasía tecnológica, se han convertido rápidamente en mitos, alrededor de los cuales ha surgido un cúmulo de ritos, a cual más atroz, ridículo o profano. Hablo, naturalmente, de la Tecnología de Objetos y la parafernalia que la rodea. En el presente artículo me ocuparé de algunos de ellos, a los que trataré de imponer la luz de la razón o, cuando menos, del pragmatismo sentido.

 

No hay que subestimar la fuerza de la repetición y la estulticia de los medios de comunicación: si una barbaridad se repite con insistencia en los lugares adecuados, en breve pasará a ser considerada como una realidad incontestable. Les pondré un ejemplo: cuando se habla de objetos mucha gente perpetra con demasiada facilidad vocablos como “paradigma”, “entorno/marco” (por framework), etc. Pero, ¿cuál es su significado preciso? Humm, mejor no preguntar. Pregunten sin miedo, empero, sobre la orientación a objetos y obtendrán: tal, tal ... y “polimorfismo”. ¡Demonios! La traducción literal del griego, “muchas-formas”, no genera excesivas luces, la verdad, así que la mayoría de los encuestados tiende a suplir sus carencias formales con su autoexaltado sentido común, de forma que los resultados vienen a ser como la traducción al castellano de las películas extranjeras: un dislate sin sentido. ¿Es polimórfico Felipe González? ¿Es polimórfica la plastilina? En fin, como el lector puede apreciar el panorama es agotadoramente desolador. En lo que sigue intentaré reseñar algunas de las supersticiones más extendidas, pero el tema en absoluto queda completamente cubierto, así que es posible que vuelva sobre el mismo en un futuro artículo.

Un lenguaje orientado-a-objetos “puro” es mejor que otro “híbrido”.

Esto es lo mismo que decir que un veneno puro es más beneficioso para el cuerpo que otro convenientemente rebajado. Cualquier mente no enferma entiende que la idoneidad de un lenguaje, en cualquier ámbito, se basa en las facilidades que provee para acometer las tareas a que se destina. Parece, además, prudente suponer que, como bien afirma Stroustrup, “un lenguaje de propósito general ha de soportar más de un estilo (paradigma) de programación”. Oh, naturalmente esto no es sólo una defensa de C++ frente a Smalltalk (que lo es, por cierto), sino una llamada al sentido común: si preguntamos a diez dentistas cuáles son los pilares de la orientación-a-objetos, al menos nueve de ellos responderán “encapsulación, herencia y polimorfismo”, para después añadir “y no provoca caries”. Ah, pero esto no es cierto. La verdad es que todavía no hay consenso respecto de las características esenciales de la orientación-a-objetos. Y no digamos de otras características: En los lenguajes orientados-a-objetos ¿todo son objetos? ¿Las clases han de ser por fuerza objetos? ¿Son los sistemas orientados-a-objetos en realidad sistemas de objetos, para los objetos y con los objetos? ¿La herencia múltiple es una bendición o más bien un artefacto del infierno que requiere vender primero el alma para ser manejado con acierto? ¿El chequeo estático de tipos es una herejía? Vaya, demasiadas incertidumbres. Así que si Smalltalk o Eiffel son químicamente puros, C++ podría ser físicamente híbrido. Bah, ¡tonterías!

Para aprender a usar adecuadamente C++ hay que empezar por Smalltalk.

En más de una ocasión Stroustrup oportunamente ha señalado: “C++ no es un buen Smalltalk; nunca se pretendió que lo fuera. De igual manera Smalltalk no es un buen C++, pues evidentemente nunca se pretendió tal”. El mensaje es claro: Smalltalk conduce a una particular forma de diseñar y codificar, basada esencialmente en la estructuración mediante herencia de clases en jerarquías cósmicas (derivadas de Objeto), que trasladada a C++ usualmente genera un estilo particularmente ineficiente e inseguro. ¿Quién en su sano juicio usaría en C++ de forma masiva, a no ser por imperativos físicos, las colecciones de Smalltalk pudiendo hacer uso de la Biblioteca Estándar de Plantillas de C++ (que obvia completamente la herencia, dicho sea de paso)? Mi experiencia en dirección de proyectos y formación me señala, en contrapartida, que la realidad es exactamente la inversa: un buen programador de C++ se convierte con mucha facilidad, y normalmente a su pesar, en un buen programador de Smalltalk. Pero, claro, ésta es una broma práctica.

C++ es más fácil de asimilar para los programadores de C.

Este lugar común casa perfectamente con aquel otro que afirma “Para estudiar C++ hay que empezar estudiando C”. En general habría que decir, con Stroustrup, que “si vas a usar C++, estudia C++”. Desmond D’Souza acertadamente expone que el hecho que la enseñanza de C++ no sea trivial en absoluto implica que C++ sea difícil de aprender (o al menos un cierto subconjunto de uso del lenguaje): otra cuestión es que lo parezca, y esto se debe más a lo que se adivina no saber que a lo que en realidad se ha aprendido (C++ es un lenguaje ciertamente prolijo). En general el segmento de C++ que intersecta con C no posee el mismo comportamiento en ambos lenguajes: esto es, C enseña a codificar estructuras de código preparadas para utilizar los recursos del lenguaje, bien distintos a los de C++; y a la inversa. Así una buena parte de las técnicas que se enseñan en excelentes textos de C resultan inservibles o inadecuadas en C, mientras que el uso de ciertas características del subconjunto C de C++ no es en absoluto trasladable al puro C. Resulta, pues, que en la práctica los programadores que arrostran un cierto estilo C tienden a observar un lapso de tiempo más prolongado para el aprendizaje de C++ que los que, sin bagaje previo de C, empiezan por C++.

Las herramientas OOCASE integradas generan código orientado-a-objetos fiable.

Bueno, hay que distinguir dos vertientes: la generación de código de implementación o la generación de cabeceras, frecuentemente llamadas esqueletos de la aplicación y que usualmente adquieren en la práctica su sentido más mórbido. En cuanto a las cabeceras, refiriéndose al código de descripción de clases, bueno, como la mayoría de las herramientas OOCASE requieren una completa información de nombres y tipos de métodos y atributos, la generación de tales protocolos, unidos a lo sumo por una relación de herencia, resulta aparentemente trivial; en lo referido al código de los métodos, bueno, esta es otra historia: cualquier programador de C++ sabe que tras una simple línea de código pueden esconderse cientos de líneas en absoluto triviales o evidentes. Y es que ¿cómo asume una herramienta CASE idiomas y estilos estrictos de codificación para cada lenguaje particular? Pues como murio mi abuela: con mucho dolor y dificultad. Si el detalle no excesivamente prolijo del uso del operador de asignación en C++ puede llevar más de 20 páginas, ¿podría permitirse una herramienta CASE su particularización hasta tal extremo, teniendo en cuenta, además, que muchas decisiones de implementación dependen de la arquitectura y patrones del diseño a codificar? Naturalmente no estoy hablando de generación de código para la construcción de interfaces gráficos, pues existen entornos/marcos y bibliotecas de clases perfectamente estables y fiables sobre los que construir con facilidad y seguridad clases concretas de uso.

La herencia es una cualidad esencial de los sistemas orientados-a-objetos.

¿Cuáles son los pilares de la Orientación-a-Objetos? Henderson-Sellers los estableció en un triángulo: abstracción, encapsulación y polimorfismo. ¿Y la herencia? Bueno, parece que hay poco patrimonio que transmitir. Y es que, pese a lo que se pueda pensar, la herencia es básicamente un mecanismo que utilizan los lenguajes de programación orientados-a-objetos para implementar el polimorfismo, y como tal mecanismo puede ser perfectamente sustituido por otro que procure la misma suerte de funcionalidad, siempre a nivel de lenguaje. Oh, ya veo temblar al lector, que atónito observa como desdigo y mortifico a multitud de gurus (un barbarismo, aunque no lo crea) y expertos que basan la construcción de sistemas software fundamentalmente en la herencia. Bien, Alan Davis afirma que hay que seguir a los lemmings con cuidado: la herencia, en tales sistemas, pertrecha causa común con los tipos abstractos de datos, jerarquías de subtipado y con algunos aspectos de simplificación del diseño, para terminar con cuestiones de reutilización: todo un completo panorama que parece trocar a la herencia en piedra angular. Nada más lejos de lo deseable, empero: ¿por qué distinguir la herencia, como relación entre clases, de las relaciones de agregación, composición o uso que también se dan en tales sistemas? ¿Por qué la herencia suele aplicarse a clases y no a objetos/instancias? Pues porque es una componenda esencialmente estática que procura una estructura lógica recorrible sobre la que basar bien la un esquema de reutilización bien la resolución de operadores (por métodos) en tiempo de ejecución. Pero componenda no es panacea, así que nos quedaremos con que la herencia es una cualidad accesoria de los sistemas orientados-a-objetos.

La herencia es un mecanismo indispensable en los lenguajes de programación orientados-a-objetos

Oh, este es un mito especialmente peligroso. Ciertamente la aplicación de la herencia en los lenguajes de programación constituyó, en su día, un importante hito en el dominio de la modularidad software. La herencia, o derivación, ha incurrido, empero, en generar una larga serie de despropósitos que la acompañan dondequiera va. Resultaría, de acuerdo con lo expuesto, que un lenguaje orientado-a-objetos prototípico y basado en delegación, como es Self, no estaría realmente orientado-a-objetos. Se oye frecuentemente, también, que una buena codificación ha de hacer uso intensivo de la herencia, y se obvian otras características como contenedores parametrizables, algoritmos reutilizables, etc. Con todo cuando en alguna mesa redonda yo afirmo que en algunos proyectos prohibo la herencia (y por prohibir indico que cualquier relación de herencia necesitará la aprobación de un arquitecto), mis colegas me miran con sospecha. Y es que realmente la herencia es un mecanismo poderoso, pero también peligroso y difícil de controlar en grandes equipos humanos.

La herencia únicamente se puede aplicar cuando se da una relación “ES-UN”.

La dictadura de las jerarquías de subtipación se ha convertido, en muy breve tiempo, en una absurda tecnocracia. En el mundo Smalltalk (universo, le llaman sus postulantes) es frecuente, por ejemplo, usar la derivación de clases como método puro de reutilización, haciendo caso omiso de consideraciones estrictas de subtipado. Y es que si se piensa que los lenguajes son herramientas imperfectas de modelado en el dominio software de problemas reales, ¿cómo no se ha de ser esencialmente pragmático tanto en el diseño como en la codificación? Los “mixins”, por ejemplo, son clases resultantes de la aplicación de la herencia múltiple que se usan como componentes de implementación de otras clases, bien mediante herencia bien mediante composición (layering). Tiende a olvidarse con facilidad que la finalidad de las actividades de desarrollo es la construcción de sistemas software, y no la aplicación de métodos o técnicas en sí.

Existen demasiadas metodologías de análisis y diseño Orientadas-a-Objetos.

Bien al contrario, prácticamente no existen en la actualidad metodologías orientadas-a-objetos. Observe el lector que metodología es “ciencia de los métodos”, y con lo que mayormente contamos es con métodos: OMT, Coad/Yourdon, Wirfs-Brock, Jacobson, Booch, etc. son, pura y simplemente, métodos en el mejor de los casos, aderezados con algunos heurísticos y bastantes trucos, varios ejemplos y un demasiado de filosofía genérica. Claro que en informática se soluciona todo con rapidez, de forma que se ha redefinido “metodología” para ajustar el vocablo a las carencias del área: así que en informática “metodología” significa “método” (y si el lector se sorprende, ríase de la locución “ingeniería de software”). Con todo, no existen tantos métodos orientados-a-objetos: casi todos ellos se basan en alguna extensión del modelo entidad-relación de Chen, sobre la base de clases/objetos, a la que se adicionan notaciones sospechosamente parecidas entre sí y algunos componentes de comportamiento sustanciados en el modelado de escenarios arbitrarios y en el control y gestión de estados de las entidades/clases/objetos. Realmente con los métodos OO se sustancia la vox populi sobre los políticos: conocido uno, conocidos todos. Bueno, casi todos: sí existe alguna metodología orientada-a-objetos (y seguro que no es la que el lector pueda pensar), pero eso es materia de un próximo articulo completo.

Cada empresa debe adaptar a su manera los métodos existentes para construirse uno “a medida”.

Piense el lector, en primer lugar, si no es ridículo pensar que un método dado pueda manejar cualquier problema de la realidad, sobre todo teniendo en cuenta que la mayoría de los métodos observa una estructuración secuencial a la vez breve y establecida en fases inamovibles. Oh, esto no es sino mirar la realidad, como hizo Freud respecto del sexo, por un tubito tan pequeño como el método usado. Examine el lector seguidamente la desafortunadamente extendida suposición que una conjunción particular de varios métodos, encajados en razón del discutible criterio de una empresa, pudiera modelar todos los problemas. Es como si, una vez desechado el esperanto, la solución viniera de la mano de un refrito de lenguas: I t’aime mucho! Y lo curioso es que este enfoque se ha convertido en una de esas verdades difusas que casi nadie cuestiona: ahora cojo OMT de Rumbaugh, le añado un tanto de casos de uso (use cases) de Jacobson, lo aderezo con algo de fichas CRC y Diseño Orientado-a-Responsabilidades de Wirfs-Brock, lo agito en la coctelera, le doy un nombre nuevo, fabrico una herramienta pseudo-CASE que lo soporta y ... voilà el método universal. Es como si se anunciara: sobre gustos no hay nada escrito. ¡Mentira! Hay muchísimo escrito, pero seguramente usted no lo ha leído, cabría contestar. La solución, a mi entender, no pasa por el refrito de métodos, ni tampoco por la solución que proponen los auto-denominados métodos de segunda generación, abanderados por Fusion, de Coleman y otros, y que se basa en la utilización de un método cualquiera (OMT, Jacobson, Wirfs-Brock, etc.) como información de entrada para un marco formal que regule y distribuya adecuadamente los resultados. El modelado genérico de sistemas de información habría más bien de pasar, según mi opinión, por lo que se conocen como “marcos referenciales metodológicos”: esto es, un adecuado conjunto de herramientas metodológicas y de métodos que conforman un arsenal de vistas aplicables de forma segmentada y no necesariamente completa sobre el dominio de los problemas a modelar. ¿Existen tales marcos? Por supuesto, pero esto es otra historia.

Lo primero que hay que hacer es crear una biblioteca de clases reutilizables.

Esta frase se oye mucho en cursillos y se lee por doquier en las revistas del ramo. La cuestión es: ¿cómo puede crearse de la nada una clase reutilizable? Esto es, ¿puede reutilizarse una clase que todavía no ha sido utilizada? ¡Naturalmente que no! Primero hay que generar a la vez política y ambiente de reutilización en la empresa, de forma que cuando se creen clases con un diseño prudente tales clases sean utilizadas por el equipo humano y la información que se desprenda de tal uso pueda revertir en la mejora de tales clases, que volverán a ser utilizadas de nuevo en un ciclo involutivo. Se entiende por reutilización no el uso (una clase “Ventana” se usará por varias aplicaciones, pero tal no es reuso), sino los usos distintos en distintos contextos. Por supuesto que el (re)uso se da tanto a nivel de aplicativos como de las propias bibliotecas de clases, pero aquí, como ya se expresó anteriormente, la herencia juega un papel usualmente desdichado: si nos dedicamos a insertar las clases a reutilizar en jerarquías no-triviales de herencia, cuando queremos hacer uso de una determinada clase arrastraremos con ellas buena parte del arbol de derivación, con lo que el nivel de aprovechamiento, si posible, dejará mucho que desear.

REFERENCIAS BIBLIOGRÁFICAS

Los siguientes textos no se ciñen al ámbito estricto de la Tecnología de Objetos, sino que exponen de forma afortunadamente acertada un cúmulo de criterios y principios, explícitos o no, subyacentes en el diseño de sistemas software de calidad. La selección, como siempre, es absolutamente personal y medida: por cada libro interesante que estudio he de leer otros cuatro lesivos, triviales o ridículos. Naturalmente yo intento leer únicamente los buenos, pero es difícil (y poco educado) juzgar en voz alta sin conocer, así que tras conocer y desechar, he aquí mi selección, mascada ya para que el lector trabaje menos:

201 Principles of Software Development , por Alan M. Davis, 1995, McGraw-Hill, 0-07-015840-1.
Davis plantea en este texto una completa conjunción de principios/mandamientos/patrones que, aplicados, debieran procurar sistemas software más raciones, sólidos y mantenibles: en resumen, de calidad. Los principios son cortos y no tienen desperdicio: (34) Todo documento software necesita un índice, (82) Los grandes diseños vienen de grandes diseñadores, (30) Sigue a los lemmings con cuidado, (22) Técnica antes que herramientas, (170) Sé pesimista sobre la evolución del software, ... y muchos otros. Cada principio se acompaña de una corta justificación, sirviendo así el texto de guia referencial a ingenieros (sic) software, directivos y estudiantes. Conviene recordar que los seres humanos tienden a trivializar rápidamente lo que les parece obvio en un contexto dado, así que a más de uno le resultará tremendamente instructivo repasar algunos conceptos que tenía por asimilados pero que nunca realmente ha aplicado con claridad.

The Design and Evolution of C++ , por Bjarne Stroustrup, 1994, Addison-Wesley, 0-201-54330-3.
El lector podría aquí objetar: “Pero ... ¡este es un libro de C++!”. ¡Pues claro! Estamos hablando de software y, guste o no, C++ es el OOPL actualmente más extendido: si quisiera hablar de mitos cosmogónicos o de ritos humanos básicos acudiría a las sesiones del congreso de los diputados. Este libro, con todo, no versa sobre C++ sino sobre las decisiones de diseño que han conducido al lenguaje, en lo esencial, a su actual configuración. Stroustrup posee un tono exacto y pragmático que convierte su texto en un alegato contra la tontería, más allá de consideraciones beligerantes entre lenguajes. Yo diría que su antecedente más cercano es el inteligente libro de Bertrand Meyer “Object Oriented Software Construction”, 1988, donde se explicitaban también las decisiones de diseño del lenguaje Eiffel. Así que ... ¡alto! ¿Oigo las quejas de algun lector? Humm, las comparaciones no son odiosas: la estupidez y la banalidad, en contrapartida, sí son odiosas. Considero que aunque C++ se pervertiera y sólo se usara en el BOE, el libro seguiría siendo absolutamente recomendable.

Pitfalls of Object-Oriented Development , por Bruce F. Webster, 1995, M&T Books, 1-55851-397-3.
He de confesar que este libro no colmó las expectativas que el título y su publicidad me habían sugerido. Claro que satisfacerme a mí es azarosamente prolijo. Con todo el texto es buen material para los efectivos practicantes, novicios o no, de la Tecnología de Objetos. Cada “pitfall” consta de una descripción primera, seguida de un detalle de los síntomas, más las posibles consecuencias de su aplicación, técnicas de detección, consejos para su eliminación/extracción y, para finalizar, algunas pistas encaminadas a su prevención. Webster divide los problemas en: conceptuales, políticos, de gestión, de análisis y diseño, de entornos, lenguajes y herramientas, de implementación, de clases y objetos, de codificación, de calidad y de reuso: un ambicioso conjunto que pretende abarcar el ciclo de vida completo del software y su redención mediante la penitencia constructiva. Atiendan a algunas de las trampas: (5.4) Usar C++, (5.5) No usar C++, (3.5) Intentar demasiadas cosas, demasiado pronto, demasiado rápido, (1.1) Adoptar la Orientación-a-Objetos por razones equivocadas, (6.8) Ser seducido por el lado oscuro, etc. etc. En fin, con esta obra (que se supone complementaria del magnífico texto de Goldberg y Rubin, Succeeding with Objects) se pretende conseguir algo parecido a lo que con los patrones de diseño: comunicar la experiencia contrastada en diseño real de sistemas a los postulantes, aunque aquí por el lado morboso del castigo y el didactismo. Muy entretenido, al fin.

Software Requirements & Specifications: A Lexicon of Practice, Principles and Prejudices , por Michael Jackson, 1995, Addison-Wesley, 0-201-87712-0.
Este libro, aunque liviano, me ha encantado hasta la sonrisa: su estructura es la de un diccionario, de forma que las distintas secciones están ordenadas por orden alfabético, y aun así puede leerse de corrido. Jackson aporta aquí importantes dosis de sentido común y claridad distribuidas en pequeñas porciones repletas de inteligencia y solidez. La traslación, por ejemplo, del problema de los puentes de Königsberg al terreno de los escenarios en especificaciones es particularmente afortunada; el planteamiento, bajo el epígrafe “Brillantez”, de los analistas insustituibles que generan diseños que ni ellos mismos alcanzan a comprender es, por otro lado, grandemente instructivo (Oh Sancta Simplicitas). La incomprensión, por ejemplo, de los menús por parte de los comensales, en el apartado “Restaurantes”, resulta intelectualmente punzante. En fin, Jackson se despacha con sorpresas página tras página y desarrolla temas tan interesantes como El Marco JSP, Dekker (sobre el Problema de la Mutua Exclusión), Eventos e Intervalos, etc. En el sentido más cercano al espíritu de D’Alembert, este diccionario es una buena herramienta contra la estupidez y el fanatismo.

 
 
 
volver a la página de publicaciones
 
 
 Pº. Castellana 188, 14º e · 28046 - Madrid · info@a4devis.com