¿Por qué los desarrolladores de Java deberían darle una oportunidad a Grails?
Publicado: 2022-03-11Java tiene un ecosistema que ha madurado a través de años de desarrollo, estableciéndolo como una de las plataformas más confiables que existen. Sin embargo, carece de los medios necesarios para hacer el trabajo rápidamente, especialmente para cosas como las aplicaciones web. En un intento por evitar frustraciones con este tipo de problemas, los desarrolladores a menudo optan por lenguajes de implementación y sus marcos web modernos, como Ruby con Ruby on Rails, Python con Django, etc. A diferencia de Java, estos proporcionan un camino mucho más simplificado para construir una aplicación web.
Afortunadamente, para los desarrolladores de Java que desean crear aplicaciones web, hay una mejor manera e involucra a Grails. En este artículo, veremos cómo Grails with Groovy es una alternativa viable en el ámbito de JVM. Veremos algunos ejemplos en los que Grails nos atrae a nosotros como desarrolladores de Java y podría tentar a alguien más a intentarlo también.
La historia
En una startup para la que trabajé, tuvimos exactamente este problema. Teníamos una aplicación de Spring que se estaba convirtiendo en un fastidio para trabajar. A medida que crecía más y más, pronto descubrimos que la refactorización y la adición de funciones nos llevaban más tiempo del que debería. La combinación de eso con algunas otras motivaciones nos llevó a decidir reescribir nuestra aplicación principal. También estábamos abiertos a cambiar o reemplazar la pila de tecnología existente. Grails parecía una opción viable, ya que se ejecuta en JVM y se basa en tecnologías que ya conocíamos. Utiliza el lenguaje de programación Groovy pero al mismo tiempo te permite mezclarlo con Java. Así que dimos el paso.
Máxima velocidad adelante
Una cosa en la que Grails realmente se destaca es en facilitar el inicio de un nuevo proyecto. Es tan simple como ejecutar un comando que crea la estructura del proyecto con todas las carpetas necesarias para las clases que agregará más adelante. Agregar clases de modelo, controladores, servicios y páginas web requiere un esfuerzo mínimo similar. Lo único que debe cuidar es nombrar y colocar las cosas correctamente. A diferencia de Java, prácticamente no hay código repetitivo que deba estar allí solo porque necesita estarlo. Esto es parcialmente posible gracias al uso de Spring e Hibernate, que son dos de los pilares de Grails, así como el concepto de codificación por convención. Para ejecutar el proyecto, Grails viene incluido con Apache Tomcat como servidor de desarrollo. Todo lo que tenemos que hacer es ejecutar el proyecto en nuestro IDE y el servidor se activará con nuestro código implementado. Además, el Mapeo Relacional de Objetos de Grails (GORM) con Hibernate se encargará de crear la base de datos por nosotros. Para usar una base de datos existente, debemos configurar las propiedades de la conexión JDBC o simplemente dejarlo por defecto para usar una instancia en memoria. Una vez que el servidor con Grails se está ejecutando (toma un poco más que una aplicación Spring MVC), podemos modificar el código y la funcionalidad de implementación en caliente mantendrá nuestra sesión de depuración equipada con la última versión. Las únicas clases que no se pueden recargar de esta manera son las clases de entidad.
El llenado de la base de datos se puede realizar mediante secuencias de comandos SQL, pero puede volverse tedioso. Todos los proyectos de Grails contienen una clase Bootstrap que se ejecutará cuando se ejecute nuestra aplicación. En esta clase podemos almacenar o modificar datos y así inicializar el estado de nuestra aplicación. Esto resultó muy útil para nosotros, por lo que tenemos algunos casos de prueba en la versión de desarrollo de inmediato.
Manipulación de datos
Una de las cosas que llamó nuestra atención de inmediato con Grails fue la facilidad de trabajar con datos. La lectura de la base de datos es una tarea que debe hacerse una y otra vez. Y muchas veces es simple. Como buscar una o más entidades que cumplan con ciertos criterios y luego agregarlas. ¿Por qué no usar un buscador dinámico para eso? Es una forma de consultar datos donde los métodos se crean dinámicamente en tiempo de ejecución. Todo lo que tiene que hacer es seguir una convención de nomenclatura.
def users = User.findAllByLastNameLikeOrAgeGreaterThan('Doe%', 30)
La línea anterior obtendrá todos los objetos de usuario con apellido que comience con "Doe" o una edad superior a 30. Sí, no es un caso muy sofisticado, pero entiende la esencia.
¿Qué pasaría si quisiéramos filtrar esta lista adicionalmente por aquellos que tienen la propiedad “failedLogins” mayor a 10? ¿Y si quisiéramos ordenarlos por su fecha de creación? ¿Y si quisiéramos concatenar sus nombres o encontrar la edad máxima de los usuarios devueltos?
users = users.findAll() { it.failedLogins > 10 } users = users.sort { it.dateCreated } def firstNamesString = users.firstName.join(', ') def maximumAge = users.age.max()
Los ejemplos anteriores pueden parecer simples, pero muestran lo poderoso que puede ser Grails para consultar, filtrar y manipular datos. En Java 8, puede lograr resultados similares para algunos de estos casos, pero aún requerirá más código que Grails.
A veces quiero crear de manera diferente
Un constructor dinámico o un constructor de argumentos con nombre es una característica que muchos de nosotros queríamos tener en Java. Es bueno definir qué constructores permite una determinada clase, pero en muchos casos solo desea establecer algunas propiedades y obtener la maldita instancia. Groovy agrega un constructor especial para cada entidad que básicamente toma la elegancia de un mapa como entrada y establece las propiedades con las entradas del mapa.
def Person = new Person(name: 'Batman', age: 57)
Este enfoque conduce a un código que es mucho más expresivo y evita la necesidad de todo el código repetitivo del constructor.
Y, por cierto, aquí hay algunos ejemplos de la genialidad y la elegancia de los mapas de Groovy:
def emptyMap = [:] def map = [bread:3, milk:5, butter:2] map['bread'] = 4 map.milk = 6
Este es otro ejemplo de cómo el código puede ser corto y simple, pero poderoso. Muestra cómo se puede utilizar la inicialización en línea y cómo se pueden manipular los valores del mapa de forma similar a las propiedades de los objetos. No es necesario llamar a los métodos tradicionales de Java para la manipulación básica, a menos que realmente lo desee.
¡Necesitamos más poder!
Por supuesto, no existe un marco que pueda hacer todo, pero cuando estemos llenando los vacíos, deberíamos ver qué más podría estar disponible antes de intentar implementar nuestra propia solución. Para expandir nuestro arsenal de funcionalidades basadas en Grails, podemos usar Grails Plugins. La instalación de un complemento se realiza simplemente agregando otra línea en la clase BuildConfig
que está presente en cada proyecto de Grails (¡la convención de código ataca de nuevo!).

compile ':spring-security-core:2.0-RC4'
La línea anterior agrega el núcleo de seguridad Spring a nuestra aplicación y prácticamente no se necesita más configuración para incorporar esta funcionalidad.
Dicho esto, déjame contarte un caso que tuvimos que tratar. Necesitábamos implementar una búsqueda que abarcara varias entidades de datos. Grails tiene un complemento de Elasticsearch que es muy fácil de usar. Como se mencionó anteriormente, solo necesitamos hacer referencia al complemento en el archivo de configuración y estamos listos para comenzar. Si queremos buscar entidades de una determinada clase, solo necesitamos agregar una propiedad estática "buscable" a esa clase. Y si queremos, podemos incluso limitar las propiedades que se permitirán buscar.
class User { static searchable = { only = name } String name Double salary }
Es un código muy pequeño, pero bajo el capó, Grails y el complemento Elasticsearch indexarán automáticamente a todos los usuarios por nombre y nos permitirán buscar por nombre. La llamada de búsqueda real también es muy concisa:
User.search("${params.query}")
Si no queremos, nunca tendremos que tocar el índice de Lucene. Todo se hará automáticamente por arte de magia para nosotros. El complemento incluso tiene una API para mostrar los resultados de la búsqueda: puede resaltar la coincidencia que se encuentra dentro del texto buscado. Este es solo un ejemplo de cómo un complemento puede proporcionar una gran cantidad de funcionalidades que pueden hacernos mucho más eficientes al evitar la necesidad de que lo implementemos nosotros mismos.
Todavía necesitamos más poder
Los complementos son geniales, pero a veces no necesitamos un complemento completo, solo queremos algo extra. ¿Recuerdas la última vez que quisiste tener un método adicional en una clase de Java existente pero no querías (o no podías) extenderlos/anularlos? En Groovy, puede agregar métodos y propiedades a las clases existentes, o incluso solo a ciertas instancias de ellas. Por ejemplo, puede agregar un método de formatting
a la clase java.util.Date
que es increíble cuando desea formatear fechas de manera consistente y simplemente no desea escribir clases de utilidad estáticas o definir varios filtros.
Date.metaClass.formatDate = { delegate.format("dd.MM.yyyy") }
¿Qué sucede si desea ordenar una lista de usuarios por un valor calculado y solo necesita esto en un caso (es decir, agregar un nuevo método en la clase Usuario sería contaminante)? Puede agregar una propiedad en cada una de esas instancias y luego ordenar o filtrar la colección por esa propiedad:
user.metaClass.computedProp = 312 * 32 * 3
Los autores de Groovy ya han agregado muchas mejoras a algunas de las clases principales de Java, por lo que no tenemos que hacerlo. A continuación se muestran algunos ejemplos.
Usar "menos" para eliminar todos los elementos de una colección que están presentes en otra colección.
assert [1, 2, 3, 4, 4, 5] - [2, 4] == [1, 3, 5]
Métodos adicionales para manipular objetos java.util.Date
que son útiles muchas veces, como agregar/restar días de fechas u obtener/establecer un determinado campo de la fecha sin convertirlo a Calendar
o usar bibliotecas adicionales.
def yesterdayAllMyTroublesSeemedSoFarAway = new Date() - 1 def myAwesomeAnniversaryYear = myAwesomeDate[Calendar.YEAR] + 1 myAwesomeDate.set(year: myAwesomeAnniversaryYear, second: 0)
Cuando quiera ser realmente descriptivo con la manipulación de fechas, simplemente puede usar la clase TimeCategory
agregada por Groovy:
use (TimeCategory) { println 1.minute.from.now println 10.hours.ago def someDate = new Date() println someDate - 3.months }
Un martillo y un clavo
Luego están los IDE. GGTS basado en Eclipse e IntelliJ IDEA están configurados para trabajar con Grails. Comprenden la estructura del proyecto (y lo ayudarán a navegar por las carpetas y los recursos) y tienen accesos directos para los comandos que usará con mayor frecuencia (por ejemplo, agregar un controlador, agregar una página, ejecutar un proyecto, etc.). Con Grails, ejecutará comandos (para ejecutar un proyecto o configurar una nueva funcionalidad de complemento) y necesitará diferentes configuraciones, que también están cubiertas por los IDE. La finalización de código funciona muy bien en las páginas de plantillas web de Grails donde a menudo hará referencia a controladores y acciones. También hay otros IDE que se pueden usar con Grails como Netbeans, TextMate, Emacs y otros.
¿Qué pasa con el lado oscuro?
Al igual que con todo en la vida, también hay advertencias con Griales. Se está haciendo mucha magia debajo del capó, lo que a menudo puede ser algo bueno, pero a veces el resultado no será el esperado. Los errores ocurrirán solo por no usar la escritura (sí, los tipos son opcionales en Groovy) y no tener el cuidado suficiente. Y tal vez no notará un error hasta que sea demasiado tarde. Además, es muy tentador escribir frases ingeniosas para impresionar a tus compañeros de trabajo. Y usted mismo. Pero estas poderosas líneas de código pueden no ser tan claras para sus compañeros de trabajo. O incluso a ti mismo en un par de meses. Por eso creo que Grails exige más disciplina de programación que algunos de los marcos más tradicionales.
El tiempo es dinero
La codificación no debería tomar más tiempo solo porque su marco actual lo exige. Especialmente con la cantidad cada vez mayor de nuevas empresas en estos días, es importante concentrarse en las tareas que realmente importan y ser lo más eficiente posible. De hecho, el tiempo es dinero y el tiempo de comercialización es crítico. Debe ser capaz de actuar rápidamente e implementar la solución antes de que se agote el tiempo y su competencia se le adelante.
Mis amigos que trabajan con Ruby on Rails o Python/Django me han dicho durante mucho tiempo lo geniales que son esas tecnologías. Y me pareció una tontería pensar cuánto tiempo más me tomó en Java escribir código que almacena algo en la base de datos y lo muestra en una página web. De hecho, los griales pueden ser una respuesta útil. No es que no puedas hacer esto con Java puro, Spring MVC e Hibernate. Tú podrías. Su aplicación podría incluso ejecutarse un poco más rápido. Pero hará el trabajo más rápido con Grails.