home >> mb130
di

Alberto Brandolini

Nella stessa sezione>
processing-3
soylatte
grails-1
genetics-1
programmatore-4
Nella stessa serie
grails-1
grails-2
grails-3
grails-4
grails-5
News on Feed


Bookmarking
bookmark on Delicious bookmark on Digg bookmark on Furl bookmark on Reddit bookmark on Slashdot bookmark on Technorati
 
 


MokaByte 130 - Giugno 2008

Sviluppo rapido di applicazioni con Groovy & Grails

I parte: Cominciamo subito!

Ruby on Rails ha creato un terremoto nel campo della programmazione web, introducendo un nuovo termine di riferimento per la produttività individuale e la realizzazione di applicazioni. Ma sul fronte Java non si è rimasti a guardare: Grails è una soluzione decisamente interessante che sta riscuotendo notevoli consensi, anche in ambito enterprise. Vediamo perché.

Java, "gli altri" e le web application

Fino a qualche tempo fa, per noi programmatori Java, gli "altri" erano rappresentati principalmente dai colleghi che lavoravano sui piattaforma Microsoft. Ogni tanto si vantavano alla macchinetta del caffè delle possibilità offerte dal loro ambiente di sviluppo, a volte a ragione, a volte a torto, ma in generale non scalfivano la nostra sicurezza. Java era qualcos’altro: era multipiattaforma, poteva girare su Linux, sul mainframe e sull’AS 400, potevo scegliere l’IDE e fare un sacco di cose. C# non era altro che una copia di Java, a dimostrazione del fatto che SUN fosse più avanti e che Microsoft fosse costretta a copiare per inseguire. Poi, però, a poco a poco, la situazione ha cominciato a mutare. Sempre più spesso nuovi colleghi, provenienti da ambiti più "poveri" come il PHP, hanno iniziato a dileggiarci per la bassa produttività nella costruzione delle applicazioni web, vantandosi della semplicità e della rapidità del loro linguaggio. Infine è arrivata la mazzata di Ruby on Rails: chiunque abbia visto il video in cui in 15 minuti viene creata una web application per gestire un blog ha provato un senso di meraviglia e frustrazione, perche’ con tutti i nostri framework, il pattern MVC, le tag libraries, Hibernate, le annotations... col cavolo che riuscivamo a creare una web application in 15 minuti.

 

Poi è arrivato Grails

E con Grails, Groovy. Di Groovy ne avevamo sentito parlare prima, ma eravamo distratti, impegnati a controllare che nel file di configurazione di Struts non ci fosse qualche minuscola, e non avevamo compreso la reale importanza del suo arrivo. Grails e Groovy permettono di essere produttivi come mai prima, sia pure restando sulla JVM e senza buttare a mare anni e anni di codice legacy, se non altro per il valore affettivo che riveste.

Cos’è Grails?

Grails [2] è un framework per lo sviluppo rapido di applicazioni web sulla piattaforma Java. Il termine "piattaforma" è più esteso di "linguaggio" e in effetti Grails si appoggia a Groovy [3] come linguaggio di programmazione principale. Groovy è uno fra i linguaggi di programmazione che possono essere eseguiti sulla JVM (tra gli altri possiamo citare JRuby, Scala, Rhino, Jython), ma è anche il primo ad avere ottenuto l’investitura ufficiale da parte di SUN con la JSR-241 [4]. L’infrastruttura applicativa si basa su una serie di tecnologie che dovrebbero essere ben note ai lettori (in particolare Spring e Hibernate), il cui uso e la cui configurazione restano però "dietro le quinte", gestite dai principi di convention over configuration di Grails.

 
Figura 1 - Una visione d’insieme delle principali tecnologie su cui si basa Grails.



Se Spring e Hibernate ci mettono la robustezza e l’affidabilità, Groovy da parte sua ci mette la "magia". La presenza di un linguaggio dinamico è infatti fondamentale - e pesantemente sfruttata - per rendere lo slviluppo rapido e minimale al tempo stesso.
Trattandosi di un linguaggio dinamico, Groovy permette di effettuare molte operazioni "a cuore aperto", velocizzando le operazioni di sviluppo, in maniera simile ai linguaggi interpretati. In comune con Java c’è la struttura base della grammatica (sia pure con qualche rilevante differenza), ma soprattutto il fatto che il byte code prodotto sia assolutamente simile a quello delle classi Java, caratteristica che permette di chiamare classi Java da Groovy e viceversa.

Figura 2 - Classi Java e Groovy sono assolutamente compatibili a livello di bytecode.



In realtà c’è molto di più, ma piuttosto che addentrarci nei dettagli del "come funziona" è probabilmente meglio iniziare a "smanettare" con il codice.

Pronti a partire

La prima cosa da fare è scaricare l’ultima versione di Grails, dal sito [2]: in questo momento la versione di riferimento è la 1.0.2. Quindi dobbiamo scompattare l’archivio nella nostra directory di destinazione e registrare questa dir come variabile di sistema GRAILS_HOME. Molto probabilmente avete già settato la variabile JAVA_HOME nel vostro PC (e se state leggendo questo articolo, su questa rivista, in effetti la probabilità di tutto ciò è abbastanza alta...); in caso contrario è necessario farlo, perche’ Grails si aspetta di trovare un JDK (dalla versione 1.4 in poi) installato sulla vostra macchina. Per poter eseguire Grails a riga di comando è necessario inoltre aggiungere la nostra GRAILS_HOME seguita dal /bin al PATH.

Figura 3 - La nostra checklist d’installazione.



A questo punto proviamo a digitare

grails


al prompt della riga di comando; se otteniamo un messaggio di help abbiamo completato l’installazione.

Figura 4 - Il messaggio di risposta di Grails: a quanto pare è tutto OK.

 

La nostra prima applicazione

Le dita prudono, dobbiamo iniziare il nostro primo progetto! Da dove cominciamo? Qualcuno avrà già aperto l’IDE, o più probabilmente non l’ha mai chiuso. In realtà la cosa migliore è quella di partire con la buona vecchia riga di comando (anche perche’ non tutti gli IDE supportano Grails e Groovy alla stessa maniera). Grails ci permette di creare un’intera applicazione con un solo comando

grails create-app


che come parametro accetta il nome della nostra applicazione. Cosa di più "classico" di un’agenda per mettere alla prova le conclamate abilità di Grails? E agenda sia!

:>grails create-app agenda


Grails inizia a macinare, a copiare files e creare directory. Al termine delle operazioni, ci troviamo con una struttura di directory già bell’e pronta sul disco.

Figura 5 - L’alberatura delle directory generata da Grails.



A prima vista, si tratta di un approccio che ricorda Maven [5]. In realtà Grails, dietro le quinte, fa uso del buon vecchio Ant [6], sia pure facendo propri alcuni concetti cari a Maven quali la convention-over-configuration. In ogni caso ci troviamo con una struttura di directory standard (e quindi non perdiamo tempo a decidere o, peggio, a "metterci d’accordo" su dove mettere le cose), indipendente dall’IDE (e quindi portabile da un IDE all’altro) e decisamente ordinata. Notiamo inoltre che viene impostata una prima organizzazione del progetto (le sottodirectory confcontrollersdomaini18nservicestaglibutilsviews), e che è già presente una directory test, tra l’altro già divisa in integration  e unit.

Creiamo una classe di dominio

Il passo successivo è definire la nostra prima classe di dominio. L’interfaccia a riga di comando di Grails ci semplifica il compito con il comando

:>grails create-domain-class contatto

 

che provvede a creare un file Contatto.groovy nella directory  grails-app/domain. Apriamo il file con un editor di testo (parleremo dell’IDE più avanti); per il momento non c’è granche’:

class Contatto {
}

In realtà c’è più di quello che sembra: innanzitutto è una classe Groovy. In effetti potrebbe anche essere una classe Java, iniziamo a costruirla un po’ più seriamente. 

class Contatto {
    String nome
    String cognome
    String azienda
    String email
    Date dataNascita
}


Fatto! In teoria potremmo già passare allo step successivo, ma probabilmente è meglio spendere qualche parola in più su questo listato, apparentemente incompleto.

  • mancano i punti e virgola: in Groovy sono opzionali;
  • mancano i modificatori di visibilità sugli attributi: in Groovy non esiste la visibilità package (che, a dire il vero, non era proprio "gettonatissima" in Java) e un attributo senza modificatore è interpretato come una property;
  • mancano getters e setters: in Groovy le properties dispongono di getters e setters impliciti; sono presenti nel byte code, ma non è necessario scriverli nel codice: in altre parole, scrivere  String nome  in Groovy equivale a dichiarare un attributo nome privato, ed esporre metodi pubblici  getNome()  e  setNome(...)  in Java;
  • manca la clausola import relativa a Date: la Date che vediamo sopra è la buona vecchia Java.util.Date; Groovy importa implicitamente i package Java di uso più frequente, e li rende disponibili in ogni nostra classe.



Questo è un primo assaggio dell’approccio adottato dai progettisti di Groovy (e di Grails): pragmatismo (quante volte abbiamo realmente avuto bisogno della visibilità package?), convention over configuration, e il famigerato DRY: Don’t Repeat Yourself. Piccole cose, per ora, ma vedremo che questi principi, applicati sistematicamente al linguaggio di programmazione e al framework, producono un effetto combinato tutt’altro che trascurabile.

Creiamo il nostro controller

Il passo successivo è la definizione di un Controller, che gestisca le operazioni relative alla nostra classe di dominio. Grails è un framework applicativo, che nasce orientato al web: la struttura di riferimento è il classico pattern Model-View-Controller. Il Model è rappresentato dalla nostra domain-class appena implementata, la View dalle pagine di visualizzazione, al Controller spetta il compito di coordinare il tutto.
Ovviamente, Grails ci viene in aiuto. Dalla riga di comando è sufficiente digitare:

:>grails create-controller

Grails ci chiede il nome della domain-class cui ci stiamo riferendo. Avremo potuto passarlo come parametro, in effetti, ma il fatto che Grails ci venga incontro chiedendoci di specificare solo il nome della classe (senza fare lo schizzinoso con le maiuscole), anziche’ chiederci di ri-digitare l’intero comando è un altro sintomo dell’approccio che sta dietro all’intera faccenda: rendere le cose facili per il programmatore (senza farlo sentire stupido). Il risultato dell’invocazione, è la classe ContattoController.groovy, situata nella directory /controllers.

class ContattoController {
    def index = { }
}

Grails si è premurato di definire l’azione di default per il nostro controller, lasciandone vuota l’implementazione. def è una parola chiave propria di Groovy che serve per definire variabili senza specificarne il tipo. In questo caso si tratta di una closure (altro costrutto caratteristico di Groovy), con un’implementazione vuota. C’è molto altro dietro, ma per il momento è meglio non mettere troppa carne al fuoco.

Il modo più rapido per arrivare a un prototipo funzionante (e per apprezzare le potenzialità di Grails) è quello di attivare il Dynamic Scaffolding. Il termine "scaffolding" (letteralmente "impalcatura") è stato portato alla ribalta da Ruby on Rails, e sta ad indicare tutto quel codice che in se’ per se’ non "fa" nulla, ma è necessario per interpretare i campi del form di una pagina web, ad esempio, e di trasformarli in attributi di un oggetto di dominio. Grails permette sia di generare staticamente tutto il codice di scaffolding del controller o delle pagine (tramite l’apposito comando ant), ma permette anche di generare lo stesso codice direttamente a run-time. Per attivare questa funzionalità, è sufficiente definire una property chiamata scaffold nel nostro controller, come segue

class ContattoController {
    def scaffold = Contatto
}

 

Lanciamo la nostra applicazione

Tutto qui. Ora siamo pronti per fare girare la nostra applicazione. Torniamo alla riga di comando:

:>grails run-app


La console inizia a "movimentarsi" quindi ci informa che all’indirizzo

http://localhost:8080/agenda


è disponibile la nostra applicazione. Digitiamo l’indirizzo nel browser ed ecco la schermata iniziale della nostra applicazione. Wow!

Figura 6 - La home page della nostra prima applicazione Grails.



Clicchiamo su ContattoController (non che avessimo molta scelta...) e ci viene mostrata una nuova pagina:

Figura 7 - la pagina di default associata a ContattoController.



Notiamo che il nome della pagina nella barra indirizzi del browser è

http://localhost:8080/agenda/contatto/list


valore, che Grails ottiene ancora una volta con il principio di convention over configuration.
In altre parole: i metodi dei controller corrispondono automaticamente ad URL parlanti nella nostra applicazione Grails (chiunque abbia sbattuto contro la gestione della barra degli indirizzi con Java Server Faces sta tirando un sospiro di sollievo in questo momento).
Clicchiamo su New Contatto e l’applicazione ci porta a un’un’altra pagina che non ricordiamo di avere scritto:

Figura 8 - La schermata di editing del contatto creata con il Dynamic Scaffolding.



I campi sono "disordinati", o meglio: sono ordinati in ordine alfabetico. Però Grails ha riconosciuto il tipo Date della data di nascita e ha cambiato il formato di input di conseguenza. C’è di che correre alla macchina del caffè, per vantarsi con i colleghi, ma c’è ancora qualcosa che merita di essere sperimentato: torniamo alla nostra classe di dominio, Contatto.groovy, e aggiungiamo qualche riga di codice:

    static constraints = {
        nome(blank:false)
        cognome(blank:false)
        email(email:true)
    }


Grails interpreta il contenuto della variabile statica constraints, e applica le regole di validazione definite nei campi. C’è un sottoinsieme di regole standard (Domain Constrains) tra cui scegliere, con la possibilità di applicare meccanismi più flessibili basati sulle espressioni regolari.
Inseriamo un nuovo contatto... la pagina di edit è diversa.

Figura 9 - La schermata di edit dopo avere definito i constraints.


L’ordine dei campi è cambiato. In effetti prima di definire i constraints, Grails non aveva alcuna idea di quale potesse essere l’ordine di visualizzazione, per cui si appoggiava all’ordine alfabetico. Definendo i constraints abbiamo indirettamente fornito informazioni anche sulla struttura statica della pagina.
Ma soprattutto, la modifica alla domain-class è stata recepita dinamicamente. Non c’è stato bisogno di rilanciare l’applicazione, o di effettuarne nuovamente il deploy. Una classe è stata modificata, (ovviamente salvata...) e Grails ne ha caricato la versione più recente (e cominciamo a capire l’utilità di un linguaggio dinamico...). L’intera pagina è stata ri-generata dinamicamente con il dynamic scaffolding. Dimenticavo: la validazione è funzionante. Se proviamo a inserire un valore non corretto per il campo Email, o a lasciare indefinito un campo obbligatorio, l’applicazione risponde così:

Figura 10 - Visualizzazione degli errori di validazione.



Forse potrà sembrare normale che l’applicazione parli italiano... Grails nasce già internazionalizzato. La lingua è reperita dal Locale, e i messaggi di validazione sono gestiti con il classico meccanismo dei resource bundle. Troviamo il file messages_it.properties nella cartella /i18n, nel caso ci interessi personalizzarlo.

Cosa abbiamo fatto

Abbiamo impostato un CRUD relativo ad una classe di dominio, completo di validazione e internazionalizzazione. In circa 10 minuti. Le pagine sono indubbiamente da personalizzare, ma sono già meglio di un sacco di roba che si vede in giro. E soprattutto funzionano! Dobbiamo ovviamente lavorare per arrivare a una configurazione di sviluppo condivisa, ma siamo già operativi (e Grails prevede dei meccanismi built-in per la gestione delle configurazioni nei vari ambienti).

Cosa NON abbiamo fatto

  1. Non abbiamo impostato l’application server. In effetti non l’abbiamo nemmeno esplicitamente installato. Grails lancia automaticamente Jetty (che ha un’impiego di risorse inferiore a Tomcat) e rende disponibile la nostra applicazione, senza dover manualmente lanciare l’application server. Ovviamente è possibile utilizzare application server differenti, ma questo approccio permette di essere produttivi in modalità zero-configuration.
  2. Non abbiamo lanciato il database, ne’ lo abbiamo inizializzato. In realtà, la configurazione di sviluppo prevede l’impiego di un in-memory-database (Hypersonic) e - pur non avendo scritto una riga di codice SQL o definito una classe DAO - stiamo effettivamente andando su un DB in memoria, creato on-the-fly.
  3. Non abbiamo scritto le pagine web, ci siamo appoggiati al dynamic scaffolding. Si tratta della soluzione più comoda in sede di prototipazione. Una volta chiarite meglio le caratteristiche della pagina, possiamo delegare a Grails la scrittura del codice di base e applicare le nostre personalizzazioni sulle pagine.
  4. Non abbiamo scritto i DAO: Grails si fa carico di un gran numero di operazioni, che vanno ben oltre il semplice CRUD visto in questo semplice evento. È possibile ricorrere ai DAO, ma è sensato farlo solo in casi particolari.
  5. Non abbiamo configurato Spring (eppure, guardando l’output della console sappiamo che è partito...).
  6. Non abbiamo mappato Hibernate: a questo ci ha pensato Grails, o meglio GORM (Grails - Object Relational Mapping). GORM applica a Hibernate i principi di Convention Over Configuration, rendendo superfluo definire il mapping tra attributi delle classi e campi delle tabelle del DB, se queste seguono la convention.
  7. Non abbiamo configurato Log4J, eppure funziona.

 

Conclusioni

C’è qualche punto oscuro, la sintassi di Groovy può lasciarci disorientati: è relativamente facile da leggere (per quel poco che abbiamo visto) ma si tratta comunque di un linguaggio diverso, le cui potenzialità abbiamo a malapena intravisto. Abbiamo messo molta carne al fuoco: un framework applicativo e un linguaggio di programmazione in un colpo solo! Tuttavia, la semplicità con cui siamo riusciti a "portare a casa" un risultato è abbastanza sconcertante; del resto l’attenzione che sta riscuotendo Grails da parte della comunità Java internazionale ci fa supporre che ci siano validi motivi per continuare a investigare. Nei prossimi articoli faremo luce sui "misteri" che stanno dietro a quanto abbiamo visto in questa breve presentazione.
Non so voi, ma io dopo avere scritto queste poche righe di codice mi sono sentito meglio. Come se qualcuno mi avesse tolto un peso dallo stomaco. Un sacco di domande che per anni hanno riecheggiato nella mia testa, come coda di un generico "perche’ non va?":

  • "Hai dichiarato gli import?"
  • "Hai messo getters e setters?"
  • "Hai configurato log4J?"
  • "Hai dichiarato il Bean?"
  • "Hai scritto il mapping file di Hibernate?"
  • "Hai configurato l’application server?"
  • "Hai chiuso le finestre?"
  • "Hai messo la canottiera?"

... con Grails non hanno più senso. Grails è una canottiera che ho già indosso, senza saperlo. E non devo pensarci più.

Riferimenti 

[1] http://www.youtube.com/watch?v=Gzj723LkRJY
[2] http://grails.org/
[3] http://groovy.codehaus.org/
[4] http://jcp.org/en/jsr/detail?id=241
[5] http://maven.apache.org/
[6] http://ant.apache.org/
[7] Il Grails User Group italiano

 

Invia un messaggio alla redazione su questo articolo

Mittente (facoltativo - immetti una email valida se desideri ricevere una risposta)

Come hai trovato questo articolo?

 

Mi sono addormentato

Interessante con il giusto taglio

Argomento non interessante

Molto interessante

Argomento interessante, ma non approfondito

Efficace, ha risolto i miei problemi

Interessante

Mi sono commosso

 

Lascia un commento su questo articolo