Sei sulla pagina 1di 86

Enterprise-class DSLs in Groovy & Grails

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 1

About me
Strategic IT consultant Trainer
- Skills Matter, ...

Articoli
- Mokabyte,

Blogger
- Ziobrandos Lair

animatore di Community
- Grails-IT - DDD-IT
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009 2

A cosa serve un DSL?


Un DSL uno strumento per la condivisione di informazioni specializzato per uno specifico contesto
- dominio del problema - ruoli coinvolti - ambito di applicazione
Mettere la foto di un addetto allatterraggio

- Facilita la condivisione di informazioni (precise e prive di ambiguit) allinterno di un gruppo - si tratta di uno strumento per migliorare lefficienza della comunicazione
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009 3

un classico esempio di DSL

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 4

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un Domain Specic Language nasce per coprire unesigenza di comunicazione in un contesto5specico indirizzando alcuni elementi della comunicazione: limpossibilit di utilizzare determinati canali (in questo caso laudio), la necessit di comunicare con maggiore rapidit e precisione, la necessit di essere sintetici

Ecosistema di progetto

Domain Expert

Analyst

Specication

Architect

Tester

Code

Developer

DBA

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un DSL comunque uno strumento di comunicazione: perch sia efficace la comunicazione deve 6 coinvolgere almeno due soggetti che condividano informazioni. In un classico contesto di progetto sono presenti diversi ruoli che fanno uso d diversi linguaggi. Esistono DSL specicati per determinati compiti, ma ci che pu avere impatto sul nostro modo di produrre software rappresentato dal DSL specico del dominio applicativo, ovvero della lingua parlata dallesperto di dominio.

Ecosistema di progetto
DSL

Domain Expert

Analyst

Specication

Architect

Tester

Code

Developer

DBA

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un DSL comunque uno strumento di comunicazione: perch sia efficace la comunicazione deve 6 coinvolgere almeno due soggetti che condividano informazioni. In un classico contesto di progetto sono presenti diversi ruoli che fanno uso d diversi linguaggi. Esistono DSL specicati per determinati compiti, ma ci che pu avere impatto sul nostro modo di produrre software rappresentato dal DSL specico del dominio applicativo, ovvero della lingua parlata dallesperto di dominio.

Ecosistema di progetto
DSL ?

Domain Expert

Analyst

Specication

Architect

Tester

Code

Developer

DBA

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un DSL comunque uno strumento di comunicazione: perch sia efficace la comunicazione deve 6 coinvolgere almeno due soggetti che condividano informazioni. In un classico contesto di progetto sono presenti diversi ruoli che fanno uso d diversi linguaggi. Esistono DSL specicati per determinati compiti, ma ci che pu avere impatto sul nostro modo di produrre software rappresentato dal DSL specico del dominio applicativo, ovvero della lingua parlata dallesperto di dominio.

Ecosistema di progetto
DSL ?

Domain Expert

Analyst

UML

Specication

Architect

Tester

Code

Developer

DBA

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un DSL comunque uno strumento di comunicazione: perch sia efficace la comunicazione deve 6 coinvolgere almeno due soggetti che condividano informazioni. In un classico contesto di progetto sono presenti diversi ruoli che fanno uso d diversi linguaggi. Esistono DSL specicati per determinati compiti, ma ci che pu avere impatto sul nostro modo di produrre software rappresentato dal DSL specico del dominio applicativo, ovvero della lingua parlata dallesperto di dominio.

Ecosistema di progetto
DSL ?

Domain Expert

Analyst

UML

Specication

Architect

Tester

Java

Code

Developer

DBA

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un DSL comunque uno strumento di comunicazione: perch sia efficace la comunicazione deve 6 coinvolgere almeno due soggetti che condividano informazioni. In un classico contesto di progetto sono presenti diversi ruoli che fanno uso d diversi linguaggi. Esistono DSL specicati per determinati compiti, ma ci che pu avere impatto sul nostro modo di produrre software rappresentato dal DSL specico del dominio applicativo, ovvero della lingua parlata dallesperto di dominio.

Ecosistema di progetto
DSL ?

Domain Expert

Analyst

UML

Specication

Java

Architect

Tester

Java

Code

Developer

DBA

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un DSL comunque uno strumento di comunicazione: perch sia efficace la comunicazione deve 6 coinvolgere almeno due soggetti che condividano informazioni. In un classico contesto di progetto sono presenti diversi ruoli che fanno uso d diversi linguaggi. Esistono DSL specicati per determinati compiti, ma ci che pu avere impatto sul nostro modo di produrre software rappresentato dal DSL specico del dominio applicativo, ovvero della lingua parlata dallesperto di dominio.

Ecosistema di progetto
DSL ?

Domain Expert

Analyst

UML

Specication

Java

Architect

Tester

Java

SQL

Code

Developer

DBA

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un DSL comunque uno strumento di comunicazione: perch sia efficace la comunicazione deve 6 coinvolgere almeno due soggetti che condividano informazioni. In un classico contesto di progetto sono presenti diversi ruoli che fanno uso d diversi linguaggi. Esistono DSL specicati per determinati compiti, ma ci che pu avere impatto sul nostro modo di produrre software rappresentato dal DSL specico del dominio applicativo, ovvero della lingua parlata dallesperto di dominio.

Avviciniamo i contesti

Domain Expert

Analyst

Specication

Architect

Tester

Code

Developer

DBA
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

Potendo intervenire sulla forma dellapplicazione e sulla lingua utilizzata al suo interno, possiamo 7 avvicinare mondi diversi. Possiamo avere maggiore controllo sulla corrispondenza tra il codice applicativo e le speciche e ridurre molto del fardello di overhead e sincronizzazione legato alla presenza di due viste sulla stessa applicazione.

Avviciniamo i contesti

Domain Expert

Analyst

Specication

qui pu succedere qualcosa di interessante


Architect Tester

Code

Developer

DBA
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

Potendo intervenire sulla forma dellapplicazione e sulla lingua utilizzata al suo interno, possiamo 7 avvicinare mondi diversi. Possiamo avere maggiore controllo sulla corrispondenza tra il codice applicativo e le speciche e ridurre molto del fardello di overhead e sincronizzazione legato alla presenza di due viste sulla stessa applicazione.

DSL in Enterprise Application


...scrivere codice che si possa leggere e capire a colpo docchio. A chi giova? - codice applicativo pi conciso e self-explaining - possibilit di controllare la pi rapidamente la correttezza e/o la corrispondenza alle specifiche - scrittura di test pi veloce - scrittura di test allargata a ruoli tradizionalmente esclusi
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

Quindi interessante notare che il focus si sposta sul codice di test: abbiamo qualche vantaggio 8 signicativo a livello di codice applicativo, che risulta pi leggibile e privo di fronzoli (basti pensare alle acrobazie necessarie per gestire i BigDecimal o le Date.

Different approcci ali DSL


Vari approcci al problema:
Parser/interpreti interni allapplicazione Scrittura di codice self-explaining
Domain Driven Design, fluent interfaces

Generazione specializzata di codice applicativo


Intentional Software, MDA,

Espansione delle possibilit espressive del linguaggio


C++, Groovy, ...
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

Dove lesigenza di conformarsi ad un SL gi esistente era particolarmente forte, si fatto ricorso ad 9 interpreti/parser dedicati, che permettessero luso del DSL nelle applicazioni. Altri tentativi sono stati legati alla possibilit di rendere il codice pi accessibile, ma la verbosit tecnologica di Java ha ostacolato questa direzione. Unaltra strada quella legata alla generazione di codice a partire da una specica espressa in una sorta di DSL (quindi realizzando lapplicazione in due fasi) separate. Inne (ed la zona in cui si colloca Groovy) c la possibilit di allargare le possibilit espressive del linguaggio stesso, sfruttandone le possibilit di espansione.

DSL in Groovy
Groovy introduce nuovi strumenti che aprono scenari sulla JVM:
- overloading degli operatori - object orientation completa - coercition dei tipi numerici - risoluzione dinamica dei metodi - strumenti di metaprogrammazione - piccole chicche sparse qua e la.

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Groovy in questo senso rappresenta un passo in avanti notevole rispetto a Java, la cui struttura non era 10 sufficientemente essibile. Matte infatti a disposizione una serie di strumenti legati alle sue caratteristiche di linguaggio dinamico che permettono di raggiungere risultati interessanti, senza arrivare alla complicazione di un parser dedicato.

Money: obiettivi
- Domain Class in Groovy - Value Object riutilizzabile - Aritmetica Domain Specific Vogliamo esplorare le possibilit di scrittura di queste componenti offerte da Groovy Approccio white-box, partendo dal foglio bianco (?)

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Come primo esempio delle possibilit offerte da Groovy, esaminiamo la possibilit di denire11 un piccolo dialetto legato alle operazioni nanziarie, gestendo quindi una tipica classe Money

DDD Value Object


In Domain Driven Design un Value Object un oggetto caratteristico del dominio applicativo:
immutabile condivisibile privo di identit specifica

La presenza dei Value Object un elemento caratterizzante dei Rich Domain Model

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Money, rappresenta un classico esempio di Value Object, secondo la classicazione di DDD. 12 Non c una corrispondenza precisa tra VO e DSL, i due concetti sono in larga parte ortogonali, tuttavia buona parte dei DSL general purpose quindi legati a pi domini applicativi sono basati su concetti che ricadono in questa categoria. Gli strumenti offerti da Groovy al riguardo, rendono estremamente conveniente affrontare il problema in questottica.

Time and Money


Libreria Java open source emanazione di Domain Driven Design Tipi di dato riutilizzabili in svariati dominii
alcuni problemi ricorrenti gi affrontati:
precisione del calcolo finanziario, usabilit delle date persistenza dei tipi di dato

Maggiore espressivit e chiarezza

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Come esempio di riferimento prendiamo quindi limplementazione di Money, denita dalla libreria 13 Time and Money, con lobiettivo di vericare costi e beneci di una riscrittura in Groovy

Java blocca la strada


BigDecimal non un tipo numerico primitivo
Operatori aritmetici da ridefinire Cambiamento di tipo tuttaltro che fluido Comportamento non sempre user friendly
Come sono arrivato a questa situazione?

java.lang.AssertionError:expected:<EUR4>butwas: <EUR4.0000000000000002220446049250313080847263336181640625>

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

La scrittura di una componente relativamente semplice, ha per in Java qualche complicazione in pi 14 del previsto, legata al fatto che BigDecimal NON un tipo primitivo, quindi anche lautoboxing di java 5 non ci aiuta pi di tanto. In particolare va rimarcato che BigDecimal ha un comportamento diverso nel caso sia invocato come new BigDecimal(...) rispetto a BigDecimal.valueOf(...) con lo stesso argomento!

...una buona notizia


La scrittura della classe, a parit di test superati, ha richiesto circa la met del codice:
Sintassi pi concisa gestione dei BigDecimal molto smooth (via coercition) Alcuni metodi di utilit non pi necessari Zucchero sintattico decisamente demod

Non solo
loverloading degli operatori permette di scrivere: Money tenEuros = Money.euros(10) Money twentyEuros = Money.euros(20) assert twentyEuros == tenEuros + tenEuros assert twentyEuros == tenEuros * 2

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Tenendo ferme le caratteristiche denite dalla suite di test la scrittura del codice si rivelata 15 molto pi agevole, tanto in lunghezza, che in complessit. Molti metodi erano relativi a problematiche che in Groovy sono assolte direttamente dalla piattaforma, altre risultano obsolete dalle possibilit offerte dalla meta programmazione. Loverloading degli operatori premette gi di trattare Money come un tipo primitivo.

The comparable bug


junit.framework.AssertionFailedError: expected:<EUR10>butwas:<EUR10.00>

Scompaiono anche i problemi nella gestione della precisione (sembra troppo facile) ... in effetti era un bug Groovy usa compareTo() dietro le quinte se si invoca == su un Comparable

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Qualche piccola sorpresa legata ad un problema atteso ma non presentatosi. Si tratta in realt di 16 unanomalia benigna di Groovy, ma che sar corretta prima o poi. Nel nostro caso limplementazione corrente fa al caso nostro, ma dovremo vericare il comportamento con le prossime versioni del linguaggio.

Money - continued
- Creazione delle istanze di Money - reversibilit delle operazioni E necessario intervenire pi in profondit per rendere la cosa pi interessante Entra in gioco la ExpandoMetaClass

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Quanto fato no adesso gi piuttosto interessante, ma possiamo fare di meglio. la 17 metaprogrammazione in Grovy ci permette di manipolare le classi Java e Groovy, spingendole oltre limmaginazione dei progettisti originari.

Expando Meta Class


EMC permette di aggiungere nuovi comportamenti alle classi gi esistenti, a run time, senza modificarne il codice

Currency currency BigDecimal amount plus(...) minus(...) ...

Currency currency BigDecimal amount multiply(..) getReference()

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In particolare ci interesser loperatore . corrispondente al metodo getReference, che simula 18 linvocazione di un metodo getter su una property che non esiste nella classe originaria ma che abbiamo denito nella corrispondente MetaClass

I soldi iniziano a girare...


assert 20.EUR == 10.EUR + 10.EUR assertEquals 45.EUR, 9.EUR * 5 assertEquals 45.EUR, 5 * 9.EUR assertEquals 4.EUR, 36.EUR / 9 assertEquals 4, 36.EUR / 9.EUR assert 4.EUR == 1.60.EUR * 2.5 assertEquals 4.EUR, 1.60.EUR * 2.5 assertEquals assertEquals assertEquals assertEquals 250.EUR, (10.EUR + 15.EUR) * 10 25.EUR, (100.EUR + 150.EUR) / 10 2.5.EUR, (10.EUR + 15.EUR) / 10 250.EUR, 10 * (10.EUR + 15.EUR)

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In Groovy tutto un oggetto, quindi anche gli interi ed i decimali lo sono. 19 Fornendo una Closure di valutazione innescata dalla ricerca di una property sulle classi numeriche, ed associandola alla MetaClass dele classi numeriche possiamo intercettare la valutazione della notazione postssa e piegarla alle nostre esigenze.

...proviamo a spingerci oltre...

assertEquals 250.,

10. * 25

Funziona! :-)
assertEquals 250., 10. * 25

Errore di compilazione :-(


assertEquals 250.$, 10.$ * 25

...Pure peggio :-(


Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

E abbastanza interessante notare che lipotetico passo successivo ci viene per sbarrato dalla 20 struttura del linguaggio, in maniera asimmetrica rispetto ala valuta utilizzata. In particolar modo per il tradizionale ruolo del simbolo $ come operatore. non resta che passare alla moneta unica!

Per, cos facendo, finisco per attribuire alla classe Number responsabilit che non le competono, violando uno dei principi della OOP

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Stiamo denendo nuovi modi per creare istanze della classe Money, ma stiamo distribuendo il codice 21 di pertinenza nelle gerarchie della classi numeriche che dovrebbero restare agnostiche rispetto a Money. Le classi della famiglia Number non vengono toccate direttamente, per non stiamo lavorando in modalit OOP canonica

Legacy e Black Bok


- maggiore espressivit su librerie Java - reversibilit delle operazioni Il foglio bianco il sogno di ogni programmatore. La dura realt ... il legacy. Vorremmo avere le stesse possibilit espressive, senza operare in modalit white-box

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

La prova effetuata su Money, interessante, ma non forse realistica. In un contesto reale non sempre 22 godiamo del privilegio di poter riscrivere tutto in groovy, vediamo che si pu fare in modalit:

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 23

non vedo, non sento, non parlo.

Joda Time
Libreria con funzionalit avanzate per Date e Time Candidata alla sostituzione di java.util.Date nelle prossime versioni di Java Supporto out-of-the box per Hibernate supporto out-of-the box per JSP

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 24

Black Box approach


Prendendo in esame qualcosa di pi complesso, ha senso rivolgersi allesistente. In ambito DSL alcune aree di maggior complessit risultano gi coperte:
- Date ed Intervalli con Time and Money - Date ed Intervalli con Groovy (Duration, etc.) - Joda Time - JScience

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 25

JScience
Libreria con supporto per: - unit di misura (SI) - quantit - calcoli type-safe

Amount m3 = Amount.valueOf(3, KILO(GRAM)); Amount m2 = Amount.valueOf(2 Kg);

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 26

Il punto della situazione

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Ho molti potenziali candidati a diventare DSL utili allinterno del mio contesto applicativo, in 27 particolare per le aree dove la sintassi del inguaggo java si dimostra particolarmente infelice (le date sono un esempio lampante). Ci spingerebbe verso una modularizzazione ed un uso estensivo dei DSL. Daltra parte limplementazione dei DSL semplice in termini di righe di codice, ma decisamente complicata in termini di debugging, per cui sarabbe bene che fosse il pi possibile disaccoppiata dal codice applicativo.

Il punto della situazione


Molti DSL gi disponibili off the shelf :-)

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Ho molti potenziali candidati a diventare DSL utili allinterno del mio contesto applicativo, in 27 particolare per le aree dove la sintassi del inguaggo java si dimostra particolarmente infelice (le date sono un esempio lampante). Ci spingerebbe verso una modularizzazione ed un uso estensivo dei DSL. Daltra parte limplementazione dei DSL semplice in termini di righe di codice, ma decisamente complicata in termini di debugging, per cui sarabbe bene che fosse il pi possibile disaccoppiata dal codice applicativo.

Il punto della situazione


Molti DSL gi disponibili off the shelf :-)

possibilit espressive interessanti :-)

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Ho molti potenziali candidati a diventare DSL utili allinterno del mio contesto applicativo, in 27 particolare per le aree dove la sintassi del inguaggo java si dimostra particolarmente infelice (le date sono un esempio lampante). Ci spingerebbe verso una modularizzazione ed un uso estensivo dei DSL. Daltra parte limplementazione dei DSL semplice in termini di righe di codice, ma decisamente complicata in termini di debugging, per cui sarabbe bene che fosse il pi possibile disaccoppiata dal codice applicativo.

Il punto della situazione


Molti DSL gi disponibili off the shelf :-) Debugging dei DSL :-(

possibilit espressive interessanti :-)

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Ho molti potenziali candidati a diventare DSL utili allinterno del mio contesto applicativo, in 27 particolare per le aree dove la sintassi del inguaggo java si dimostra particolarmente infelice (le date sono un esempio lampante). Ci spingerebbe verso una modularizzazione ed un uso estensivo dei DSL. Daltra parte limplementazione dei DSL semplice in termini di righe di codice, ma decisamente complicata in termini di debugging, per cui sarabbe bene che fosse il pi possibile disaccoppiata dal codice applicativo.

Il punto della situazione


Molti DSL gi disponibili off the shelf :-)

possibilit espressive interessanti :-)

Debugging dei DSL :-( I DSL agiscono sulle stesse Classi chiave :-/

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Ho molti potenziali candidati a diventare DSL utili allinterno del mio contesto applicativo, in 27 particolare per le aree dove la sintassi del inguaggo java si dimostra particolarmente infelice (le date sono un esempio lampante). Ci spingerebbe verso una modularizzazione ed un uso estensivo dei DSL. Daltra parte limplementazione dei DSL semplice in termini di righe di codice, ma decisamente complicata in termini di debugging, per cui sarabbe bene che fosse il pi possibile disaccoppiata dal codice applicativo.

Il punto della situazione


Molti DSL gi disponibili off the shelf :-)

possibilit espressive interessanti :-) Sovrapposizioni fra i differenti dialetti :-/

Debugging dei DSL :-( I DSL agiscono sulle stesse Classi chiave :-/

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Ho molti potenziali candidati a diventare DSL utili allinterno del mio contesto applicativo, in 27 particolare per le aree dove la sintassi del inguaggo java si dimostra particolarmente infelice (le date sono un esempio lampante). Ci spingerebbe verso una modularizzazione ed un uso estensivo dei DSL. Daltra parte limplementazione dei DSL semplice in termini di righe di codice, ma decisamente complicata in termini di debugging, per cui sarabbe bene che fosse il pi possibile disaccoppiata dal codice applicativo.

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Gli effetti della sovrapposizione degli interventi sulle stesse classi chiave possono infatti essere 28 sorprendenti e presentarsi in aree applicative molto lontane da dove il problema stato effettivamente introdotto.

Groovy bestiale, posso scrivere i miei DSL!!

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Gli effetti della sovrapposizione degli interventi sulle stesse classi chiave possono infatti essere 28 sorprendenti e presentarsi in aree applicative molto lontane da dove il problema stato effettivamente introdotto.

Groovy bestiale, posso scrivere i miei DSL!!

Fico! ...quasi quasi me ne faccio uno anche io...

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Gli effetti della sovrapposizione degli interventi sulle stesse classi chiave possono infatti essere 28 sorprendenti e presentarsi in aree applicative molto lontane da dove il problema stato effettivamente introdotto.

Groovy bestiale, posso scrivere i miei DSL!! Grande! posso riscrivere la grammatica del linguaggio!!!

Fico! ...quasi quasi me ne faccio uno anche io...

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Gli effetti della sovrapposizione degli interventi sulle stesse classi chiave possono infatti essere 28 sorprendenti e presentarsi in aree applicative molto lontane da dove il problema stato effettivamente introdotto.

Groovy bestiale, posso scrivere i miei DSL!! Grande! posso riscrivere la grammatica del linguaggio!!!

Fico! ...quasi quasi me ne faccio uno anche io... Credono di essere capaci solo loro? Mo gli faccio vedere...

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Gli effetti della sovrapposizione degli interventi sulle stesse classi chiave possono infatti essere 28 sorprendenti e presentarsi in aree applicative molto lontane da dove il problema stato effettivamente introdotto.

Groovy bestiale, posso scrivere i miei DSL!! Grande! posso riscrivere la grammatica del linguaggio!!! Hey!

Fico! ...quasi quasi me ne faccio uno anche io...

Credono di essere capaci solo loro? Mo gli ho questerrore faccio vedere... strano...

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Gli effetti della sovrapposizione degli interventi sulle stesse classi chiave possono infatti essere 28 sorprendenti e presentarsi in aree applicative molto lontane da dove il problema stato effettivamente introdotto.

Multiple DSL
- Fare convivere Un unico punto di innesco configurabile per pi DSL pi DSL nello stesso contesto DSL Modulari e componibili applicativo - Separazione netta delle responsabilit

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Vorremmo quindi la possibilit di disporre di un punto di controllo centralizzato per coordinare pi 29 DSL a granularit ne. Ovviamente supponendo che questo siano adeguatamente testati e supportati cos da poterci effettivamente concentrare solo sul codice applicativo con in pi le nuove potenzialit espressive.

DSL Descriptor

Repository di delle caratteristiche specifiche del nostro DSL


parole chiave operatori operazioni di setUp

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Un primo elemento di questo nuovo approccio la denizione d un descrittore del DSL che esponga le 30 caratteristiche speciche del nostro DSL in formato standard.

Scenario Money
<<Interface>> DSLDescriptor getPostx Operation

Corretta allocazione delle responsabilit tra la classe ed il descrittore


Money Currency currency BigDecimal amount plus(...) minus(...) ...

MoneyDSLDescriptor Attribute Attribute Operation Operation

Riscruttura del codice Interazione con i tipi primitivi

ExpandoMetaClass

Number Currency currency BigDecimal amount multiply(..) getReference()

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In uno scenario come quello di money, il descrittore si limita a coordinare le operazioni sulle 31 classi esterne al subdominio (nel nostro caso la classe Number), mentre le classi caratteristiche del DSL (Money) sono in grado di denire da sole il proprio comportamento.

Scenario Time and Money


Libreria complessa e gi testata Maggiore ricorso alla EMC

<<Interface>> DSLDescriptor getPostx Operation

CalendarDate plus(...) minus(...) ...

TimeAndMoneyDSLDescriptor Attribute Attribute Operation Operation

TimeInterval plus(...) minus(...) ... String getReference

ExpandoMetaClass

Number Currency currency BigDecimal amount multiply(..) getReference()

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Nel caso Time & Money, il nostro descrittore contiene una logica pi complessa, e funge anche da 32 repository delle closure di valutazione delle classi del sottodominio delle date, per i metodi non direttamente esposti da queste.

DSLEngine
Un ruolo di coordinatore centralizzato per lattivazione simultanea di pi DSL Si aprono nuovi problemi: - priorit nellordine della risoluzione - sovrapposizione degli operatori - registrazione e de-registrazione dei DSL

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Al centro di questo scenario si collocher il nostro coordinatore. 33 Dotato di risoluzione della priorit di valutazione, di gestione dei conitti tra operatori utilizzati da pi dialetti, e delle funzionalit di registrazione e de-registrazione dei DSL

<<Interface>> DSLEngine Operation Operation

<<Interface>> DSLDescriptor getPostx Operation

Separazione delle responsabilit: Engine come punto di coordinamento Descriptor come componente pluggabile

AbstractDSLDescriptor priority Operation Operation

MoneyDSLDescriptor Attribute Attribute Operation Operation

TimeDSLDescriptor Attribute Attribute Operation Operation

QuantityDSLDescriptor Attribute Attribute Operation Operation

JodaTimeDSLDescriptor Attribute Attribute Operation Operation

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 34

DSL Multipli
...perch limitarci ad uno solo quando possiamo combinarne pi di uno?
<<Interface>> DSLEngine Operation Operation <<Interface>> DSLDescriptor getPostx Operation

EUR, USD, GBP

k, M, ...
MoneyDSLDescriptor Attribute Attribute Operation Operation QuantityDSLDescriptor Attribute Attribute Operation Operation
Javaday Roma III Edizione 24 gennaio 2009

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT Perch interessante combinare pi DSL? 35 Perch in determinate circostanze, lunione di pi componenti semplici pu risultare signicativa. in questo caso combinando Money e Quantity abbiamo una grammatica abbastanza signicativa.

DSL Compositi
A volte, la maggiore espressivit si raggiunge componendo frammenti di DSL separati
assert 20.k.EUR == 10.EUR * 2000

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Che permette una notazione sintetica dei grandi numeri combinando due grammatiche denite 36 indipendentemente luna dallaltra.

DSL Compositi
A volte, la maggiore espressivit si raggiunge componendo frammenti di DSL separati
assert 20.k.EUR == 10.EUR * 2000

Qu
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

Che permette una notazione sintetica dei grandi numeri combinando due grammatiche denite 36 indipendentemente luna dallaltra.

an tit

yD

SL

DSL Compositi
A volte, la maggiore espressivit si raggiunge componendo frammenti di DSL separati
assert 20.k.EUR == 10.EUR * 2000

yD an tit Qu
Mo

SL
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

Che permette una notazione sintetica dei grandi numeri combinando due grammatiche denite 36 indipendentemente luna dallaltra.

ne yD S

Grails
Framework per lo sviluppo rapido di applicazioni Web (ma non solo)
- basato su Groovy - si appoggia su librerie Java note e provate (Spring, Hibernate, Quartz, etc.) - integrabile con svariate tecnologie

- La risposta a Ruby on Rails sulla JVM


- migliore curva di apprendimento dal mondo Java - infrastruttura spesso gi installata
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009 37

Grails

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
te n-c ea ai cr om d as l s

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
te n-c ea ai cr om d
class Persona { String nome String cognome String e-mail Date dataNascita }

as l

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
te n-c ea ai cr om d
class Persona { String nome String cognome String e-mail Date dataNascita }

as l

createcontroller

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
te n-c ea ai cr om d
class Persona { String nome String cognome String e-mail Date dataNascita }

as l

createcontroller

class PersonaController { def list = { } def create = { } }

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
te n-c ea ai cr om d
class Persona { String nome String cognome String e-mail Date dataNascita }

as l

createcontroller

class PersonaController { def list = { } def create = { } }

Persone Id nome cognome eMail dataNascita

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
te n-c ea ai cr om d
class Persona { String nome String cognome String e-mail Date dataNascita }

as l

cr

e e-vi eat

createcontroller

class PersonaController { def list = { } def create = { } }

Persone Id nome cognome eMail dataNascita

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
te n-c ea ai cr om d
class Persona { String nome String cognome String e-mail Date dataNascita }

as l

cr

e e-vi eat

createcontroller

class PersonaController { def list = { } def create = { } }

Persone Id nome cognome eMail dataNascita

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
Entity
class Persona { String nome String cognome String e-mail Date dataNascita }

te n-c ea ai cr om d

as l

cr

e e-vi eat

createcontroller

class PersonaController { def list = { } def create = { } }

Persone Id nome cognome eMail dataNascita

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
Entity
class Persona { String nome String cognome String e-mail Date dataNascita }

te n-c ea ai cr om d

as l

cr

e e-vi eat

createcontroller

class PersonaController { def list = { } def create = { } }

Value Object
class Money { Currency currency BigDecimal amount }
Id nome

Persone cognome eMail dataNascita

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
Entity
class Persona { String nome String cognome String e-mail Date dataNascita }

te n-c ea ai cr om d

as l

cr

e e-vi eat

createcontroller

class PersonaController { def list = { } def create = { } }

Value Object
class Money { Currency currency BigDecimal amount }
Id nome

Persone cognome eMail dataNascita

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Grails
Entity
class Persona { String nome String cognome String e-mail Date dataNascita }

te n-c ea ai cr om d

as l

cr

e e-vi eat

createcontroller

class PersonaController { def list = { } def create = { } }

Value Object
class Money { Currency currency BigDecimal amount }

?
Id nome

Persone eMail dataNascita

cognome

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

In 2 parole: Grails permette di partire da una denizione estremamente sintetica delle classi di 38 dominio, per generare lo strato di presentation (con navigazione e validazione del dato sulla base dei constraints deniti dallutente) e tutto il codice di gestione della persistenza (comprese del DDL di popolamento del database) che permettono la realizzazione di una CRUD application in tempi brevissimi

Value Object in Grails


Grails nasce privo del concetto di Value Object: - il dominio applicativo nasce in corrispondenza 1-1 con il database sottostante - localizzazione della logica applicativa nelle classi di dominio - La gestione di eventuali tipi di dato ricorrenti delegata a Hibernate via Gorm

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 39

Ed il nostro DSL?
Il supporto ai tipi di dato definiti dallutente passa attraverso: - Grails Scaffolding
- che per riconosce e gestisce di default solo i tipi primitivi

- GORM
- che delega la gestione agli User Type di Hibernate

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 40

Grails Scaffolding

Cos com Grails non ci permette di trarre il meglio dal DSL e dai tipi di dato che lo caratterizzano. La generazione delle pagine e dello strato di persistenza non ha infatti le informazioni necessarie per generare pagine e database cos come avviene per le classi di dominio basate sui dati primitivi.

Obiettivi

- Widget riutilizzabile - integrato nel processo di scaffolding

Componente di presentation che mirato sulle caratteristiche specifiche del nostro oggetto Grails deve essere in grado di riconoscere le istanze del nostro oggetto ed integrarle nel proprio processo di creazione della view

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Il nostro obiettivo ora quello di vericare i punti di espansione e customizzazione offerti dalla 42 piattaforma per allargare le potenzialit di Grails anche al nostro DSL.

Tag Libraries in Java


La scrittura di una tag library in Java unoperazione abbastanza punitiva
- sintassi ed API di basso livello - integrazione conlambiente di sviluppo non eccelsa - processo di registrazione delle taglibraries - varie ed eventuali

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 43

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 44

Fortunatamente abbiamo scoperto chi lautore delle speciche :-)

Tag Libraries
>grails create-taglib

grailscreailsorgentedella

nostraTagLibrarynellacartella taglib corrispondentetestnella cartella/test/integration


Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

contestualmentecreaancheil

In grails la gestione delle tag libraries largamente semplicata: 45 - si tratta di unoperazione gestita diretamente dal framework, che provvede anche a creare i test.

Tag Libraries in Grails


-Illusione di un unico spazio condiviso: -possibile referenziare altri tags direttamente allinterno del nostro codice -sintassi estremamente semplice -tag gi registrati
def money = { attrs -> ... out << currencySelect(name:"${attrs.name}.currency", value:attrs.value.currency) out << textField(name:"${attrs.name}.amount", value:attrs.value.amount) }

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Inoltre la gestione dei namespaces opzionale: di default il namespace condiviso con le tag di 46 sistema, permettendo di referenziarle direttamente da codice.

Extending Grails Scaffolding

<<Interface>> GrailsTemplateGenerator setResourceLoader(ResourceLoader) generateViews(GrailsDomainClass, String) generateController(GrailsDomainClass, String) setOverwrite(boolean) generateView(GrailsDomainClass, String, Writer) generateController(GrailsDomainClass, Writer)

RenderEditor.template contiene le direttive di Grails per lo Scaffolding


!"#$"%&$'()%*("+,-.("

DefaultGrailsTemplateGenerator ... ...

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Una volta denito il nostro componente graco per il rendering, il nostro obiettivo quello di renderlo 47 parte del processo di scaffolding di Grails. sufficiente andare a modicare il template offerto da Grails.

GORM
Tipi persistenti riutilizzabili

Integrati nel processo di scaffolding

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Per quanto riguarda la gestione della persistenza gestita da GORM, di fatto stiamo interagendo quasi 48 direttamente con Hibernate.

Scrittura degli User Type semplificata dalle caratteristiche dei Value Object Discriminazione delle strategie di persistenza sulla base della classe

class BankingAccount { String name String bank String iban Money currentBalance Currency currency static hasMany = [operations:BankingOperation, statements:Statement] static embedded = ['currentBalance'] static mapping = { columns { currentBalance type:MoneyCurrencyUserType } }

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009

Sar necessario disporre di Hibernate User Type corrispondenti ai tipi di dato caratteristici del nostro 49 DSL. Si tratta di unoperazione inizialmente tediosa che pu essere notevolmente semplicata ricordando che si tratta generalmente di Value Object con la caratteristica dellimmutabilit.

...considerazioni finali
Non reinventare la ruota:
Alcuni dialetti gi disponibili off-the shelf I linguaggi interessanti esistono gi, non dobbiamo inventarli

Lutente ha (quasi) sempre ragione Keep it Simple Stupid:


Non aggiungiamo nulla che non serva

Test, Test ed ancora Test:


e magari se rimane tempo, qualche altro test
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009

Groovy offre una soluzione di compromesso interessante sul panorama dei DSL e Grails ne permette 50 lintegrazione in maniera tutto sommato agevole.

Domande?

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 51

Riferimenti

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 52

Riferimenti
http://groovy.codehaus.org/

http://grails.org

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 53

Riferimenti
JScience: http://jscience.org/ Joda Time: http://www.joda.org/ Time and Money: http:// timeandmoney.sourceforge.net/ http://glaforge.free.fr/weblog/ http://www.warneronstine.com/blog/articles/ 2008/04/24/groovy-dsl-roundup http://peterbacklund.blogspot.com/ http://www.jakusys.de
Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT
Javaday Roma III Edizione 24 gennaio 2009 54

Riferimenti
Grails-IT: http://it.groups.yahoo.com/group/Grails-IT/ Mokabyte: http://www.mokabyte.it http://ziobrando.blogspot.com http://albertobrandolini.wikidot.com

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 55

Open Source it!


Sorgenti presto su: http://code.google.com/p/diesel/

Alberto Brandolini - alberto.brandolini@avanscoperta.it Grails-IT


Javaday Roma III Edizione 24 gennaio 2009 56

Potrebbero piacerti anche