25 cosas que amamos de Java

Publicado el por luiz.dibella

¡A JetBrains le encantan todos los lenguajes de programación y todo tipo de desarrolladores! En mayo de 2020 ¡Java cumple 25 años! Por eso queremos hacerle un homenaje y hablar de 25 cosas que adoramos de Java y la JVM.

25-Things-We-Love-About-Java

Compatibilidad con versiones anteriores

Java es casi el único lenguaje capaz de ejecutar código de hace 25 años en una versión moderna. Los desarrolladores de este lenguaje toman muy en serio la compatibilidad con versiones anteriores y, debido a esto, muchas organizaciones están felices de hacer de Java su plataforma de desarrollo principal, con la tranquilidad de que su código seguirá funcionando en la JVM durante años.

Madurez

Existir desde hace mucho tiempo tiene una gran cantidad de ventajas. Durante los últimos 25 años, los desarrolladores han escrito aplicaciones en Java para una amplia variedad de sectores y tipos de negocios, así como para plataformas distintas. Mientras tanto, durante 25 años los desarrolladores han aprendido Java en las escuelas, universidades, talleres y en su trabajo. De este modo se ha creado un gran ecosistema que ha tenido tiempo de aprender de la experiencia y continúa creciendo. Java y los problemas que puede resolver están bien documentados y cuentan con un buen apoyo por parte de proveedores y organizaciones sin fines de lucro, así como usuarios individuales. Otro aspecto muy importante para desarrolladores como nosotros es que la madurez y el uso tan extendido de Java significan que existen muchos puestos de trabajo para desarrolladores que desean codificar en este lenguaje.

Mejora constante

En contraposición con la compatibilidad con versiones anteriores y la madurez tenemos la evolución de la plataforma y del lenguaje. Desde 2017 (Java 9) hemos visto un nuevo lanzamiento cada seis meses, lo cual ha permitido un flujo constante de cambios y mejoras en el lenguaje. En combinación con Funciones de vista previa, este lenguaje es capaz de experimentar con sintaxis nueva, obtener feedback de desarrolladores y estandarizar nuevas funcionalidades que de verdad resultan útiles a quienes usan Java.

Equilibrio

Java debe encontrar el difícil equilibrio entre la compatibilidad con versiones anteriores y la visión de futuro. El enfoque actual de dar valor a la compatibilidad con versiones anteriores y lanzar cada seis meses, pero con un lanzamiento de una versión LTS (Asistencia a largo plazo) cada tres años, parece estar logrando el equilibrio perfecto. El lenguaje es capaz de evolucionar enviando advertencias acerca de funcionalidades obsoletas que se eliminarán, y disponiendo de alternativas para todo aquello que vaya a desaparecer.

Quienes busquen una estabilidad adicional pueden quedarse con los lanzamientos de versiones LTS (Asistencia a largo plazo). Para reducir su riesgo en cuanto a tiempo de actualización, podrían testear con regularidad frente a las versiones semestrales.  Los que están satisfechos con actualizar cada seis meses pueden descargar la versión más reciente de Java cada vez que se lance una. Los desarrolladores que deseen probar sintaxis nueva incluso antes de que se estandarice, pueden habilitar las funcionalidades de vista previa, y los que deseen hacerlo lo antes posible, pueden incluso utilizar el lanzamiento de acceso anticipado de una versión que todavía no esté en el mercado.  Los equipos que usen versiones modernas de Java realmente pueden disfrutar de lo mejor de todos los mundos.

Estándares

Los estándares pueden no resultar tan interesantes para un desarrollador como las funcionalidades del lenguaje, pero disponer de estándares para Java, para Java EE y Jakarta EE, así como para casos de uso común con los que los desarrolladores se van encontrando, les hace la vida más fácil.  Aprender a utilizar JDBC para que se comunique con una base de datos significa que no tenemos que preocuparnos por cómo se implementa el controlador de la base de datos, puesto que nuestro modo de interactuar con él será siempre el mismo.  El JCP es uno de los procesos utilizados para determinar estándares para Java.

La especificación de lenguaje Java (JLS) explica la apariencia del lenguaje Java y cómo debería funcionar el compilador. Incluye el Java Memory Model, que puede ayudarnos a predecir cómo podría comportarse una aplicación, independientemente de la JVM o del hardware. La Especificación de Java Virtual Machine aborda los detalles de nivel inferior de la JVM. Estas especificaciones permiten a los JDK, distribuidos por distintos proveedores y que se ejecuten en diferentes plataformas, comportarse de modos específicos y predecibles. Lo cual nos lleva a…

Write Once Run Anywhere

WORA (el acrónimo en inglés de “Se escribe una vez, se ejecuta en cualquier lugar) fue una de las ideas originales de Java, que hoy en día parece algo tan obvio que puede que no nos demos cuenta de lo revolucionario que fue en su día. Recuerdo cuando trabajaba para una muy, muy gran organización en 2002. Esta organización cambió su tecnología anterior por Java simplemente porque tenían una gran cantidad de hardware diverso, y poder ejecutar las nuevas aplicaciones de Java en él en lugar de tener que comprar hardware específico para aplicaciones es uno de los principales motivos por los que trasladaron todo su desarrollo a Java. Hoy en día, en la era de la nube, esto podría parecer menos relevante, pero solo porque no veamos siempre WORA en acción no significa que no nos esté resultando útil todavía. Y, por supuesto, si usamos IntelliJ IDEA (o NetBeans) estamos disfrutando de WORA en el escritorio.

Rendimiento

A menudo les resulta sorprendente a quienes están menos familiarizados con Java, pero Java es un lenguaje de muy alto rendimiento. Cuenta con una plataforma madura con 25 años de mejoras en el rendimiento, numerosos recolectores de memoria con distintos perfiles de rendimiento, y la JVM optimiza nuestro código en tiempo de ejecución para nuestro uso real en la producción mucho mejor de lo que lo haría la mayoría de los desarrolladores humanos. Java se usa mucho en el mundo financiero, por ejemplo, que depende de transacciones de baja latencia y rendimiento predecible.

Garbage Collection

La Garbage Collection (limpieza de memoria) automática es otra de las cosas que, 25 años después, damos por supuestas. Ya no tenemos que pensar en cómo se asigna la memoria en nuestras aplicaciones, ni en cómo liberarla. Cada JVM cuenta con uno o más algoritmos distintos de recolección de memoria, para que podamos escoger el que funcione bien con nuestra aplicación; sin tener que preocuparnos demasiado por el funcionamiento interno podemos continuar dedicándonos a escribir la lógica de negocio para nuestras aplicaciones.

Observabilidad y gestión

Si nos interesa saber qué sucede durante la ejecución de nuestra aplicación, disponemos de una gran cantidad de herramientas para ello. Muchas de ellas incluso son gratuitas, especialmente desde que Java Flight Recorder y Mission Control forman parte de OpenJDK (desde Java 11). Herramientas como JMX incluso nos permiten gestionar dinámicamente nuestras aplicaciones.

Java Virtual Machine (JVM)

Muchas de las funcionalidades que acabamos de mencionar son características de la JVM, pero queremos hacer mención por separado a la JVM y al hecho de que es independiente del lenguaje Java. Existen muchos motivos para adorar la JVM, incluidos algunos de los que ya hemos mencionado: WORA, optimizaciones de tiempo de ejecución, rendimiento, elección de proveedor, etc., muchos de los cuales son posibles gracias a los estándares y especificaciones. También es importante que la JVM sea independiente del lenguaje Java, puesto que significa que pueden crearse lenguajes diferentes en la plataforma, aprovechando así todas las grandes funcionalidades de la JVM que acabamos de explicar y ofreciendo a la vez distintos tipos de sintaxis y funcionalidades de lenguaje.

Otros lenguajes de la JVM

Uno de los motivos por los que Java sobrevivió, e incluso prosperó en los años más tranquilos entre Java 6 y Java 8 (Java 7 tiene grandes funcionalidades, pero a los desarrolladores Java no les pareció un gran lanzamiento), es por los otros lenguajes de la JVM. El favorito de JetBrains, por supuesto, es Kotlin, pero la JVM es una plataforma para otros lenguajes populares como Groovy, Scala, Clojure y JRuby, así como muchos otros lenguajes nuevos y reimplementados. En muchos casos, la interoperabilidad entre estos lenguajes y el Java clásico nos ayuda a adoptar y sacar partido de esta variedad.

Bibliotecas y marcos de trabajo

Uno de los argumentos de más peso es la ingente cantidad de bibliotecas y marcos de trabajo entre los que podemos elegir, muchos de ellos de código abierto y gratuitos. En particular, marcos de trabajo populares como Spring y Spring Boot facilitan la creación de cualquier cosa, desde pequeños servicios a grandes y complejas aplicaciones para empresas. Gracias a los estándares, a menudo no resulta difícil comprender y utilizar una biblioteca cuando hemos usado algo similar en otro contexto. La madurez de Java y la adopción temprana del código abierto por parte de la comunidad significan que a menudo ya existe una solución para problemas estándar, no es necesario volver a inventar la rueda. También significa que, dado que muchas de estas soluciones existen y se usan desde hace mucho tiempo, ya se han probado, se comprenden y se han documentado bien.

Herramientas de build y gestión de dependencias

Atrás quedaron los días en los que un pobre desarrollador (como yo) tenía que buscar en Internet algún archivo JAR desconocido que contuviese alguna clase que parecía ser necesaria para el código que intentaba ejecutar. Maven y Gradle, en particular, han facilitado no solo crear e implementar una aplicación, sino configurar un proyecto de forma estándar con todas las dependencias necesarias. Es fácil comenzar a escribir código ya sea en un proyecto nuevo o en uno existente. Los repositorios públicos como Maven Central y Bintray agilizan la búsqueda (y publicación) de bibliotecas.

JUnit y testeo automatizado

JUnit se creó en 1997, así que ¡es casi tan antiguo como el propio Java!  Es, de lejos, el marco de trabajo de pruebas automatizado más habitual en el mundo Java, y tanto JUnit como TestNG se incluyen con IntelliJ IDEA, puesto que se presupone que se necesitará un marco de trabajo de pruebas con cualquier nuevo proyecto de Java. Es probable que los marcos de trabajo de pruebas modernos de una gran cantidad de lenguajes estén basados en ideas de JUnit que ahora damos por supuestas. La cultura del testeo automatizado de la comunidad Java debe mucho a esta biblioteca.

IDE

Este es el blog de IntelliJ IDEA, ¡no íbamos a olvidarnos de esta! Tanto si creen que la verbosidad de Java requiere un IDE, como si piensan que Java puede sacar partido realmente de un IDE debido a su tecleo estático, el hecho es que los desarrolladores de Java adoran sus IDE (¡y nosotros adoramos a los desarrolladores!). Aprender a utilizar un IDE con eficacia (ya sea IntelliJ IDEA, Eclipse o NetBeans) puede mejorar significativamente la productividad de un desarrollador gracias a: finalización y generación de código, ejecución de pruebas, depuración, navegación y una gran cantidad de funcionalidades adicionales. A los desarrolladores de Java suelen encantarles las ventajas de un IDE.

Comunidad

La comunidad Java es grande, madura, dinámica y acogedora. Existen grupos de usuarios de Java en muchas ciudades del mundo, y un grupo de usuarios virtual de Java si no puede asistir a un meetup en persona. Los Java Champions son líderes técnicos reconocidos en el mundo Java que cobraron fama por compartir cosas útiles o interesantes para los desarrolladores de Java y JVM. Java cuenta con una enorme comunidad de código abierto, incluyendo el propio JDK a través de OpenJDK. La comunidad Java valora el aprendizaje, la enseñanza y la mejora constante, se interesa por los estándares y las “buenas prácticas”, y es pragmática en su uso en un entorno real.

Personas

La comunidad está formada por personas, por supuesto, pero cuando pregunté qué es lo que los desarrolladores más valoran de Java, muchos de ellos mencionaron especialmente a la gente del mundo Java que había influido en ellos. Estos incluyen desde colegas a profesores, a gente como Brian Goetz, Angie Jones, Georges Saab, Mala Gupta, Venkat Subramaniam. Algunos incluso me mencionaron a . Personalmente, yo llegué a Java porque lo había estudiado en la universidad y había mucho empleo, pero me quedé porque me encantan las personas y la ayuda que he recibido de ellos.

Javadoc y documentación

Java convierte la documentación de la API en una parte clave del lenguaje a través de Javadoc. Los tres tipos distintos de comentarios (Javadoc, bloque y línea) indican claramente qué tipo de comentario está dejando el desarrollador. Javadoc anima especialmente a los desarrolladores a dejar documentación útil para otros desarrolladores que llamen a un método o utilicen una clase o paquete. Si un desarrollador no encuentra información de ayuda detallada en una biblioteca o trozo de código, normalmente Javadoc puede ayudarle a orientarse en la dirección correcta.

Además, el ecosistema de Java en general parece esperar (y proporcionar) documentación de calidad a los desarrolladores. Se anima a los potenciales participantes en proyectos de código abierto a enviar solicitudes de incorporación de cambios en los comentarios de Javadoc u otra documentación, y desarrolladores de todo el mundo preguntan y responden preguntas en StackOverflow, o escriben artículos en blogs acerca de soluciones para problemas específicos.

Código abierto

La comunidad de Java no solo adoptó el código abierto desde bien temprano, sino que ahora el propio JDK también es de código abierto a través de OpenJDK. El código abierto facilita que participen y colaboren varios proveedores o individuos. También es fascinante poder ver el código Java en sí mismo. El código abierto ofrece a los desarrolladores como nosotros una gran oportunidad de aprender de personas que ya han hecho todo el trabajo duro de pensar acerca de problemas complicados y resolverlos.

Gratis

La plataforma Java y muchas de las herramientas más populares utilizadas en el ecosistema Java no necesitan que un desarrollador (o incluso una organización con fines de lucro) paguen por usarlas. Incluso después de que Oracle cambiase sus licencias y asistencia en Java 11, él y muchos otros proveedores todavía ofrecieron un modo de usar el lenguaje de forma gratuita en la producción. Los proyectos de código abierto, herramientas de build e IDE ya mencionados en este artículo, son todos gratuitos o disponen de una opción gratis. Por eso, Java resulta atractivo para desarrolladores que están empezando a escribir código, así como para organizaciones de todos los tamaños que necesitan crear software pero respetando el presupuesto.

Orientación a objetos

La programación orientada a objetos no es la única opción, claro, y cada paradigma tiene sus ventajas y sus desventajas. Java se diseñó como lenguaje orientado a objetos desde el principio, y en él se demuestran muchos ejemplos de patrones de diseño y otras buenas prácticas de codificación para orientación a objetos. Si busca un lenguaje de programación orientado a objetos, Java debería ser uno de los primeros de su lista de lenguajes por probar.

Evolución y adaptación

Java era, y continúa siendo, un lenguaje de programación orientado a objetos. Pero ha adoptado con éxito algunos conceptos de la programación funcional (como las expresiones lambda y las estructuras de datos inmutables), y ha hecho que funcionen bien dentro del paradigma de orientación a objetos. La inferencia de tipo (por ejemplo, var) nos permite continuar disfrutando de las ventajas de un lenguaje de tipo estático, pero con menos código estereotipado. La informática sigue siendo una disciplina relativamente joven, pero a medida que aprendemos cosas nuevas podemos ir aplicándolas a nuestras herramientas existentes. Java (el lenguaje y todo el ecosistema) evoluciona constantemente según nuevas tendencias y nuevas “buenas prácticas”, y también como resultado de observar cómo funcionan las cosas en el mundo real.

También saca partido de la sintaxis y las ideas de otros lenguajes de JVM, para ver qué funciona y qué podría no encajar en un mundo Java clásico. Incluso los procesos y herramimentas que Java utiliza para evolucionar y crecer, como el JCP y OpenJDK, también se adaptan para continuar siendo relevantes en esta constante evolución. Esta evolución y adaptación forma parte del delicado equilibrio que Java tiene que mantener.

Enfocado en la legibilidad

El código Java suele ser legible incluso para programadores de otros lenguajes. El lenguaje tiende a ser más extenso que extremadamente conciso, lo cual facilita su comprensión al leer. Los desarrolladores del lenguaje no han implementado funciones como la sobrecarga de operadores, puesto que creen que es importante no verse sorprendido por comportamiento personalizado inesperado. Se tiende a evitar la “magia” en el lenguaje y en los marcos de trabajo. Aunque algunos marcos de trabajo usan aspectos como la Convención sobre configuración para hacer cosas sin que un desarrollador tenga que ocuparse de ello imperativamente, sin duda se ha producido un alejamiento de (por ejemplo) hacer mucha programación orientada a aspectos con anotaciones, y un acercamiento a usar anotaciones para documentación y comprobaciones de análisis estáticos. A la comunidad y al ecosistema tienden a gustarles los estándares y las “buenas prácticas”, de modo que el código Java suele respetar reglas similares incluso en proyectos muy distintos.

Funcionalidades del lenguaje

¡Hemos hablado de 23 cosas que nos gustan de Java sin citar ni una sola funcionalidad! Para ser sinceros, es porque limitarnos a solo 25 funcionalidades parecía muy difícil, y también porque muchas de las cosas que nos encantan de Java no siempre están relacionadas con la sintaxis o las funcionalidades. Nos gustaría hacer un homenaje a algunas de las funcionalidades favoritas de los desarrolladores:

  • API Collections: ¡lleva mucho tiempo con nosotros y nos ha dado un buen servicio!
  • Métodos de fábrica prácticos para las colecciones: facilita muchísimo la creación de colecciones no modificables.
  • API Streams: una estupenda adición a la API para colecciones, y es genial verla evolucionar desde Java 8. Los flujos paralelos supusieron un nuevo modo de utilizar el hardware moderno.
  • Expresiones lambda: especialmente útiles con la API Streams, pero muy prácticas por sí mismas.
  • Optional: un buen modo de expresar que un método podría no darle algo (y evitar que tengamos que proteger frente a NullPointerExceptions). También es genial ver cada mejora en Opcional desde Java 8.
  • java.time: la última API para trabajar con fecha y hora es una mejora muy bienvenida
  • Excepciones comprobadas: la gente está dividida entre excepciones comprobadas vs. de tiempo de ejecución, pero al menos las excepciones marcadas están ahí para quienes deseen usarlas.
  • Anotaciones: las anotaciones (entre otras cosas) son como documentación que el compilador puede comprobar, o notas para que un marco de trabajo haga trabajo duro.
  • JShell: ahora podemos jugar con Java en un REPL
  • var: la inferencia de tipo ayuda a reducir el ruido de código si se usa de forma sensata
  • Modificadores de acceso y modularidad: Java facilita (incluso más desde Java 9) el ser explícito acerca de qué código puede acceder a qué campos, métodos, clases y módulos.
  • Expresiones Switch: ¡ahora ya no es tan feo usar Switch!
  • Prácticas NullPointerExceptions: ¿a quién no le encanta una NullPointerException? Ahora las excepciones dan a los desarrolladores información mucho más útil acerca de lo que era nulo.
  • Funcionalidades de vista previa: ¡nos encantan las funciones de vista previa! Nos entusiasman las Registros; Reconocimiento de patrones para instanceof; y bloques de texto.

El futuro

Obtenemos nuevas funcionalidades cada seis meses, y cada uno de los lanzamientos de LTS suele suponer un mejor rendimiento desde el principio para cualquier aplicación que ejecute. Java 15 (septiembre de 2020) debería contar con: clases ocultas, bloques de texto (ya no en vista previa); vistas previas actualizadas par registros, reconocimiento de patrones para instanceof y una vista previa de clases selladas.

Y ya en un futuro más lejano también esperamos ver: concurrencia ligera y fácil de usar con Project Loom; Inline Types de Project Valhalla; más cambios de lenguaje desde Project Amber, como restos de lambda; Project Panama facilitará a los programadores el acceso a API extranjeras, tiempos de inicialización más breves gracias a Project Leydon; más mejoras en varios recopiladores de memoria, y muchísimo más.

¡Java tiene un futuro brillante!