viernes, 21 de mayo de 2010

El legado positivo de C++ y Java

Artículo original por Bruce Eckel (ingles)
14 de Marzo, 2009


Resumen
En una discusión reciente, he oído afirmaciones de que C++ fue un lenguaje pobremente diseñado. Yo he estado en el Comité de Normas de C++ por 8 años, y he visto tomar decisiones en este tiempo. Pienso que es útil entender las opciones C++ y Java con el fin de tener una mejor perspectiva.

Yo no uso casi nunca C++. Cuando lo hago es para examinar un código en un sistema heredado o para escribir pequeñas partes de código crítico, para ser llamado por otro código (mi preferencia es escribir código rápidamente en Python entonces si es necesario mejorar el rendimiento, llamo pequeñas partes de código en C++ usando la librería ctypes de Python).

Debido a que estuve el Comité de Normas de C++, he visto como se toman las decisiones. Lo cual es de una forma extremadamente cuidadosa y analizada, mucho más que como son tomadas en Java.

Sin embargo, las personas señalan acertadamente, que el lenguaje resultante es complicado y doloroso de usar, y lleno de reglas extrañas que he olvidado en cuanto me he distanciado por poco tiempo de él – y yo había deducido estas reglas mientras escribía mis libros (No memorizándolas).

Para entender como un lenguaje puede ser al mismo tiempo desagradable, complicado y bien diseñado, debemos mantener en mente la decisión inicial de diseño sobre la cual todo C++ se basó: compatibilidad con C. Stroustrup decidió – y correctamente, parecería – que la forma de obtener masas de programadores de C y moverlos hacia los objetos eras hacer la migración transparente: permitirles compilar su código en C sin cambios bajo C++. Esto era una inmensa restricción, y fue siempre la gran fortaleza de C++… y su perdición. Hizo a C++ exitoso y complejo al mismo tiempo.

También engañó a los diseñadores de Java que no entendían suficientemente C++. Por ejemplo el operador sobrecargado era demasiado complejo de usar correctamente por parte de los programadores. Lo cual es básicamente cierto en C++, ya que C++ tiene dos lugares de almacenamiento en el stack y el heap y usted debe sobrecargar sus operadores para manipular todas las situaciones y no causar lagunas de memoria. Trabajoso realmente. Java, sin embargo, tiene un único mecanismo de almacenamiento y un recogedor de basura, lo cuál hace al operador de sobrecarga trivial – como fue mostrado en C# (Pero antes en Python, el cual precedió al Java). Pero por muchos años, la línea particular del equipo de Java fue “El operado de sobre carga es muy complejo.” Esta y muchas otras decisiones fueron de alguien que claramente no hizo su tarea, es el porque tengo la reputación de estar en desacuerdo con muchas de las decisiones tomadas por Gosling y el equipo Java.

Existen muchos ejemplos. Primitivas “tuvieron que ser incluidas para lograr eficiencia.” La respuesta acertada sería decir “Todo es un objeto” y proveer una puerta trasera para actividades de bajo nivel cuando la eficiencia fuera requerida (esto también hubiera permitido tecnologías para hacer transparente hacer cosas con más eficiencia, cuando eventualmente las tendrían). Oh, y el hecho de que usted no puede usar el procesador de punto flotante directamente para calcular (de hecho es por software). He escrito acerca de problemas como estos tanto como mi entendimiento y razonamiento me lo han permitido, y la respuesta que siempre he obtenido ha sido algo automático “Esta es la forma de hacer del Java”.

Cuando escribí sobre lo mal que los genéricos estaban diseñados, obtuve la misma respuesta, “nosotros debemos mantener compatibilidad con las anteriores malas decisiones hechas en Java.” Con el tiempo más y más personas han ganado experiencia suficiente con Genéricos para ver que realmente son difíciles de usar – de hecho, templates en C++ son mucho mas poderosos y consistentes (y más fáciles de usar en estos momentos, que los mensajes de error en la compilación que son tolerados en Java). Las personas toman la rectificación seriamente – algo que sería provechoso pero no una mella en el diseño que está cojo por restricciones auto impuestas.

La lista continua hasta un punto en que se hace simplemente tediosa.¿ Esto implica el fracaso de Java? Absolutamente no. Java trajo la al mundo el recolector de basura, maquinas virtuales y un modelo consistente de manejo de errores (especialmente con la substracción del chequeo de excepciones, lo cual es posible usando técnicas que muestro en Thinking in Java, 4e). Con todas las fallas, nos ha movido a un nivel superior, al punto en el cual estamos listos para lenguajes de más alto nivel.

En un tiempo, C++ fue un lenguaje líder y las personas pensaron que siempre sería así. Muchos piensan lo mismo de Java, pero Java ha hecho aun más fácil sustituirse así mismo, debido a la JVM. Es posible para alguien crear un nuevo lenguaje y tenerlo corriendo eficientemente como Java en un corto tiempo. Previamente obtener un compilador eficiente tomaba la mayor parte del tiempo de desarrollo para el nuevo lenguaje.

Hemos visto esto  pasar – con nuevos lenguajes estáticos y dinámicos como: Scala, y Groovy, Jroby y Jython, respectivamente. Este es el futuro, y la transición es muy suave debido a que es fácil usar estos nuevos lenguajes en conjunto con el código Java existente, y usted puede reescribir los cuellos de botella en Java si es necesario.

El mismo Java va a ir quedando atrás de la misma forma que lo hizo C++, solo será usado en casos especiales (o quizás para soporte técnico de código heredado, debido a que no tiene la misma conexión con el hardware que C++) . Pero el beneficio no intencional, la brillantes accidental de Java esta en que creó un camino muy bueno para su propio reemplazo, aun cuando el mismo Java ha llevado a un punto en el cual no puede evolucionar. Todos los lenguajes futuros deben aprender de esto: crear una cultura donde sea posible refactorizar el lenguaje (como Python y Ruby han hecho) o permitir a las especies competitivas crecer.

No hay comentarios:

Publicar un comentario