Nos pretenden insuflar Java por webos [1]: “Simple, orientado-a-objetos, distribuido, interpretado, robusto, seguro, de arquitectura neutra, alta eficacia, multi-hilo y dinámico” es la descripción que Sun procura del lenguaje, y multitud de notas y artículos en el web, así como en revistas y libros, afianzan tal detalle. Y es que la unión de C++, Objective-C, Smalltalk, Internet y Sun ha generado un poutpurri de gran fuerza atractiva. Pero el caso es que internet se ha convertido en el punto de referencia de lo que se anuncia como un lenguaje completo de propósito general, cual parece ser Java. Precisamente el propósito de este artículo es determinar hasta qué punto es Java tal lenguaje de programación, con independencia del visor “Hot Java” (una aplicación al fin y al cabo), de los applets (programillas [2] para internet, cortos para ser fácilmente cargados y distribuidos) y de Internet misma. Como quiera que la euforia reina por doquier, en este artículo me centraré precisamente en los problemas del lenguaje, en esas porciones del mismo no bien definidas o discutibles, así como en sus características más oscuras o pendientes de definición precisa: a fin de cuentas Java necesita de cierta discusión y enfoque crítico, de manera que dejaremos los elogios para un próximo artículo. LA LEYENDA DEL ORIGEN Y EL ORIGEN DE LA LEYENDA La niebla de la leyenda ha difuminado en muy poco tiempo el origen de Java, de forma que yo he podido leer más de 10 versiones matizadamente distintas sobre la génesis, concepción y desarrollo de Java. Claro que aparte de los cuentos de Perrault también he oído (de boca de ingenieros de Sun) cómo este fue un proyecto que rebotó durante mucho tiempo por distintos departamentos sin que nadie le prestara ninguna atención, hasta que finalmente encontró su nicho de mercado en la “aldea global” macluhana. Lo mejor es, de cualquier manera, hacer caso omiso de historias que, independientemente de la bondad intelectual de sus protagonistas, pretenden dar carta de naturaleza a la clarividencia industrial y al pasmo volitivo. Porque, ¿qué demonios importa si en realidad Java ha sido generado aleatoriamente por un equipo de monos, extraterrestres o científicos mal pagados? ¿O es que habremos de desechar la penicilina por su origen? La cuestión es si, independientemente de su origen y entorno comercial cuidadosamente medidos, Java nos ofrece soluciones ajustadas a nuestras expectativas. OTROS LENGUAJES, OTROS ÁMBITOS Dícese que Java es entre 10 y 30 veces más lento que C, mientras que Jeff Sutherland afirma que “La belleza de Java es que es Smalltalk para programadores de C++”. No existen aún, por otro lado, proyectos en Java de la misma gran magnitud que en Smalltalk, ni realmente Java está preparado para este tipo de proyectos, según expresamente reconoce. La verdad es que empiezan a aparecer comparaciones interesadas entre Java y el resto de lenguajes de cierta extensión: Smalltalk, C++, C, Visual Basic, Object Pascal, etc. Las partes afectadas con insuficiente presencia comercial generan, por otro lado, sus propias comparaciones ventajosas (cual es el caso, por ejemplo, de Eiffel, cuya comparación entre C++, Smalltalk, Eiffel y Java puede revisar el lector en la dirección web “http://www.eiffel.com/doc/manuals/technology/oo_comparison/index.html”). Chris Laffra (“http://members.aol.com/laffra”) es el autor de un traductor gratuito de C++ a Java llamado C2J que los forofos de C++ debieran probar. Y esto sin contar el aluvión de documentación de Sun y la ingente cantidad de folletos electrónicos mayormente tendenciosos que supuran fanatismo en favor y en contra de distintos lenguajes contendientes con Java. Lo que se suele obviar en todo esto es que habría que decidir primero hasta que punto Java está maduro como lenguaje de programación para ser comparado con otros, como Smalltalk, con una antiguedad de más de 20 años. HELLO WORLD El inevitable ejemplo de saludo ha de servir para explicar algo de lo que Java supone: // La clase es la unidad operativa de Java, así que todo son clases class HolaA {
} HERRAMIENTAS El JDK (o Java Developer’s Kit), disponible para Windows 95, NT y Solaris 2.X [3], y de nada inituitiva instalación, consta de diversas y muy rudimentarias herramientas: un compilador un tanto ineficiente (javac), un depurador de línea de comandos de escasa practicidad (jdb), un visor de applets (appletviewer), un desensamblador (javap) que vuelca el contenido de clases compiladas, un generador de cabeceras (javah), un constructor elemental de documentación (javadoc) a partir de comentarios señalados (//* */), el intérprete (java) y las versiones no optimizadas de tales herramientas. Nada, pues, de IDEs, compositores visuales o sutilezas amaneradas. ÁMBITO INTERNO, ÁMBITO EXTERNO Como vimos en el ejemplo anterior, una variable declarada y definida en una expresión de control de flujo (“for” en ese caso) posee un ámbito interior al bloque que tal supone. Esto es, si en un “for” se define una variable “n”, ésta no podrá ser utilizada después de terminar el bucle “for”. “Oh, esto parece muy razonable”, exclamará aquí el irreflexivo lector, quejoso de la extensión en C++ de tal ámbito hasta el fin del bloque inmediatamente exterior al bucle. Pero piénsese que en C++ esta facilidad equivale a definir la variable en la línea inmediatamente anterior al bucle, de forma que el estilo de codificación que define todas las variables al principio de un módulo, tan típico en C, se troque más legible. El problema con Java es que tal código no podrá ser reconvertido, pues un acercamiento de la definición de una variable a su primer uso originará errores de compilación si la misma había sido usada tras el bloque. Que una facilidad sintáctica de “decoración” pueda generar errores de compilación (y otros más graves de solapamiento de identificadores) resulta absurdamente lesivo. Naturalmente ninguna de las soluciones es inatacable, pero es precisamente por esto que ninguna de ellas ha de presentarse como exclusiva solución ante la dolosa maldad de la otra. GOTOS, ETIQUETAS Y EXCEPCIONES Resulta curioso que Java proporciona las expresiones de control de flujo “break” y “continue” que, seguidas opcionalmente de una etiqueta, significan “gotos” puros y duros, por poner una etiqueta que en este caso no es en absoluto opcional, mientras que la palabra reservada “goto” anda pendiente de definición precisa. Pero si esto no se le antoja lesivo al lector, ¿qué decir de la construcción “finally”, que al término de un bloque de manejadores “catch” asegura que pase lo que pase con el código sujeto al “try”, se genere o no una excepción (manejada o no), un cierto código se ejecutará siempre?: se trata, sin ambages, de un goto incondicional a prueba de excepciones. Naturalmente que podría afirmarse que lo que pretende Java es afianzar su carácter multiparadigma, pero esto resulta especialmente contradictorio con el ánimo de sus diseñadores, que conscientemente han eliminado “sobrecarga de operadores” y “herencia múltiple general”, entre otras características no triviales de extensión lingüística, por considerar que aportaban al lenguaje una complejidad difícil de manejar. Una buena cuestión es si el uso de los “gotos”, expresos o no, se ajusta a este prejuicio contra la complejidad aparente. MÚLTIPLES FINALES La palabra reservada “final” es un cualificador de clase que denota que tal clase no podrá tener subclases directas. Se trata, en definitiva, de que cuando se utiliza la expresión “extend”, el compilador comprueba que la clase base no es una clase “final”. Bien, esto resulta claro y legible, aunque el uso de esta característica puede necesitar de lo que un colega llama “el principio de la clarividencia”, pues no sólo de jerarquías de subtipación vive el programador. Lo que no resulta tan claro es la sorprendente reutilización del mismo identificador “final” para indicar que un método no puede ser redefinido (y esto todavía semeja lo anterior), como también para señalar variables que, siendo inicializadas y definidas a la vez, no pueden cambiar su valor (variables constantes, vaya). Parece que con “final” se pretende indicar la inmutabilidad futura de un componente, pero ¿por qué mancillar la pretendida sencillez del lenguaje con tal reutilización? Y es que el término “const” anda pendiente de concreción en Java. SOBRECARGAS Y LIGEREZAS Java, tomando como referencia absoluta la sintaxis de C++, aparentemente decide eliminar las sobrecargas de operadores por considerarlas demasiado difíciles de manejar (piense el lector que hacer coexistir constructores, operadores sobrecargados y operadores de conversión sin que sea posible generar situaciones de ambigüedad es en algunos casos imposible y en otros una muy ardua tarea). El lenguaje predefine, sin embargo, una sobrecarga “intuitiva” del operador + para la concatenación de “strings”, y es que precisamente la sobrecarga de operadores sirve, bien usada, para favorecer la legibilidad del código. Así que me resulta un cierto arcaicismo codificar la clase “Complejo” sin usar los mismos operadores que utilizo para operar con “floats”. En C++ la sobrecarga de operadores es una consecuencia más de la decisión de que clases y tipos predefinidos son de la misma categoría, circunstancia que evidentemente no se da en Java. CADENAS INMUTABLES Y COMPARACIONES ODIOSAS Java provee la clase “String” para el manejo de cadenas de caracteres, con la particularidad de que los objetos de ese tipo no pueden ser cambiados. Esto es, una variable puede apuntar a una cadena dada (verbigracia: “hola”), pero a través de esa variable la cadena no puede ser cambiada (en Java no existe el equivalente del operador [] para Strings [4]), de forma que lo único que puede hacerse es que la variable apunte a otra cadena distinta:
La idea es que se reutilicen las cadenas de caracteres de un modo parecido al idioma de sobre/carta en C++ bien explicitado por Coplien. El lector habrá también advertido, ante estas decisiones, por qué Java ha necesitado sobrecargar el operador + para Strings, ya que todas las funciones deben ser funciones-miembro de alguna clase y otra solución complicaría enormemente la legibilidad del código. Resulta así que una cadena será independiente de las variables que la “apunten”, por lo que parece que las operaciones con Strings mantendrán un esquema semántico basado en el valor de las cadenas apuntadas. Desafortunadamente la coherencia no se mantiene respecto del operador de comparación:
pues éste verifica la igualdad de los objetos implicados (su identidad referencial) en lugar de comparar el valor de la cadena en cada caso referenciada. Ciertamente se trata de una mezcolanza de difícil explicación y sorprendente comportamiento. ESTRATEGIA CÓSMICA Siguiendo el tentador ejemplo de Smalltalk, todas las clases en Java son extensiones, directas o no, de la clase Object. También al igual que en Smalltalk, las variables son punteros no visibles (no manejables directamente) con semántica de referencias. Se trata, pues, de un lenguaje monoparadigmático, que obliga a una programación forzada a la derivación de clases. Como por otro lado Java no cuenta con tipos parametrizables (las plantillas de C++, soporte de la muy efectiva y elegante Standard Template Library), todos sus contenedores admiten derivados de Object, de forma que para recuperar un determinado elemento hay que aplicar un “cast” que será validado en tiempo de ejecución. La recolección automática de basura ayuda, afortunadamente, a superar algunos de los problemas de gestión de memoria que se notan en mi anterior artículo “Contenedores y Plantillas en C++”. El problema es que el estilo de codificacion Smalltalk es preferible precisamente embebido en un entorno Smalltalk, que fue diseñado a tal fin con precisión. DESTRUCTORES OCASIONALES Los constructores son muy parecidos a los de C++, con la particularidad que Java asegura la inicialización de todas las variables, expresamente codificadas o no, anteponiendo la seguridad a la eficiencia. Al contar con recolector automático de basura (o de residuos), no se da la necesidad de codificar destructores. Sin embargo Java procura una función miembro de destrucción con signatura “void finalize()” en cuyo interior pueden codificarse rutinas de desasignación y limpieza. El problema es que Java no garantiza que tal método vaya a ser finalmente llamado, de forma que ninguna porcion de código debiera depender del mismo. Si se observa, por otro lado, como una posible optimización, el impacto real en la aplicación será, cuando menos, impredecible. Lo cierto es que no conozco ejemplos concretos de uso adecuado de esta palabra clave, así que habrá que esperar a la experiencia. MODELO-VISTA-CONTROLADOR ¿Qué pasa con el MVC [5]? ¿Hay que reinventarlo para Java? Bueno, el lenguaje provee algunas clases como “Observer” y “Observable” que pudieran parecer suficientes para soportar el estilo de programación MVC. El problema es que Smalltalk dispone de un método que hace corresponder un String con una llamada a un método en tiempo de ejecución:
mientras que en Java no existen estructuras de tipo diccionario que contengan los métodos, como en Smalltalk, de forma que al faltar las capacidades de metainterpretación el esquema MVC no puede hacerse funcionar. Naturalmente una solución (insoportablemente tediosa pero finalmente funcional) sería pasar como argumentos objetos cuyo sólo propósito fuera permitir la invocación de un único método. AWT Éste es el acrónimo de X Window Toolkit, donde X puede ser Abstract, Alternative, Awkward o Another, aunque finalmente Sun está promoviendo la abstracción (seriedad ante todo). Bueno, en breve se trata de una biblioteca de clases Java para el desarrollo de interfaces gráficos de usuario. En el momento de escribir este artículo la versión 1.0 del AWT, que se desarrolló en sólo dos meses (de octubre a diciembre de 1.995), es la parte más débil del conjunto que representa Java como lenguaje: no sólo no se han tenido en cuenta las ideas de entornos gráficos novedosos (como Fresco), sino que se ha ahondado (y la presión del time-to-market ha tenido mucho que ver) en estructuraciones dolosas orientadas-a-eventos, plenas de callbacks y sin ningún soporte del entorno para la construcción gráfica. Amy Fowler, jefa del proyecto AWT en Javasoft, que actualmente consta de 6,5 personas (cosas de la informática), ha asegurado, sin embargo, que todo esto pronto pertenecerá al pasado, y el AWT será multi-idioma (en la actual versión los recursos no se almacenan externamente), constará de herramientas visuales, etc. En fin, seguro que el futuro nos depara muchas sorpresas, suelen amenazar los astrólogos. En tanto, he aquí la versión revisitada de nuestro saludo electrónico:
Claro que ejemplo tan sencillo poco puede ilustrar. En realidad la estructura básica del AWT se basa en Componentes y Contenedores. Estos últimos contienen componentes posicionados a su respecto y son componentes a su vez (recuerde el lector la estructura de glyphs típica de los procesadores de texto), de forma que los eventos pueden tratarse tanto en contenedores como en componentes (siempre mediante la herencia, claro), corriendo por cuenta del programador (pues aún no existen herramientas de composición visual) el encaje entre todas las piezas, así como la seguridad de tratamiento de los eventos adecuados. En fin, nada trivial. REFERENCIAS El lector podrá encontrar en internet papeles, índices, métodos, referencias e incluso manuales completos, libros en pre-edición y comentarios diversos a los distintos aspectos del lenguaje/entorno Java. Lo que ocurre es que la naturaleza volátil de internet sigue aconsejando fiar el conocimiento de la seguridad de las hojas impresas. He aquí algunas de ellas:
[1] Seguro que el leído lector sabe que el antiguo término castellano “(h)uebos” significa “necesidad”. Por webos vendría a querer decir, así, “por e-necesidad”. [2] El diminutivo no encierra ningún ánimo despectivo, sino más bien práctico: ¿Imagina el lector un applet del tamaño de WinWord con las actuales conexiones a Internet mediante una conexión telefónica a 9.600 bps o aún a 28.800 bps? [3] IBM ya dispone de sus propias versiones del JDK para AIX (1.01) y OS/2 Warp (1.0), ambas producidas en base a un acuerdo del 6-12-95 con Sun Microsystems Inc. [4] Para cambiar caracteres individuales Java proporciona la clase “StringBuffer”, de parecida funcionalidad y nombre autoexplicativo. [5] MVC (Model-View-Controller) es un esquema/patrón soporte de interfaces gráficos desarrollado por Trygve Reenskaug y Adele Goldberg y embebido en la arquitectura del lenguaje Smalltalk. [6] Recapacite el lector que Nietzsche admiró profundamente a Wagner antes de denostarlo por su decadencia insoportable, así que la comparación musical con el C++ quizás no resulte desafortunada. |
||
| Pº. Castellana 188, 14º e · 28046 - Madrid · info@a4devis.com |
||