Groovy: Ruby per i programmatori Java
Vai alla fonteIeri, avevo pubblicato un post riguardo NetBeans e la beta della versione 6.5 in cui citavo le varie novità di questa versione, tra tutte queste una che meritava attenzione a mio modo di vedere era Groovy. Già lo hanno definito “Java 2.0″, ma cos’è pochi lo sanno. Cercherò in questo articolo di spiegare cosa sia Groovy, confrontandolo con Java e cercando gli aspetti positivi. Lo sviluppo iniziale di Groovy risale al lontano 2003, quando James Strachan gettò le basi del progetto con un post sul suo blog. Successivamente, nel 2004, diventò una Java Specification Request, con id 241, questo è il motivo per cui a volte viene menzionato come JSR241. La versione 1.0 è stata rilasciata il 2 Gennaio 2007. L’ultima versione stabile è la 1.5.6 rilasciata il 25 Aprile 2008. Ma cos’è Groovy?
Groovy è un linguaggio di programmazione orientato agli oggetti nato con la pretesa di far avvicinare la robustezza di Java alla semplicità ed alla velocità di sviluppo dei linguaggi più moderni come Python, Ruby e i meno moderni Perl e SmallTalk. La particolarità è che stavolta non ci troviamo dinanzi all’ennesimo linguaggio di programmazione così come siamo abituati a considerare, bensì un linguaggio di programmazione per l’ambiente Java, ad esso alternativo e completamente interoperabile (o quasi). Possiamo includere codice Java in codice Groovy, di seguito entrambi verranno semi-compilati in bytecode per poi essere eseguito da qualsiasi JVM. Gli sviluppatori Groovy affermano che la curva di apprendimento per passare da Java a Groovy è prossima allo zero. Vediamo se è vero e vediamo se davvero lo sviluppo in Groovy è più agile. Quella che segue è una lista delle principali differenze, spero sia quanto più completa possibile, se mi è sfuggito qualcosa di interessante basta un commento:
Import di default
A differenza di Java, vengono importate di default una serie di librerie che sono:
java.io.*
java.lang.*
java.math.BigDecimal
java.math.BigInteger
java.net.*
java.util.*
groovy.lang.*
groovy.util.*
Array
Sebbene la sintassi sia molto simile a Java, non useremo le parentesi graffe per dichiarare un array, bensì le quadre:
int[] a = {1,2,3}; // Sintassi Java
int[] a = [1,2,3]; // Sintassi Groovy
Ciclo for
Il ciclo for non può essere scritto come siamo abituati a fare, ma abbiamo delle sintassi alternative:
// Sintassi Java
for (int i=0; i < len; i++) {...}
// Alternative Groovy
for (i in 0..len-1) {...}
for (i in 0..<len) {...}
len.times {...}
Per ora, non so se sia una scelta voluta, o dovuta a problemi di sviluppo, nella testata del for può essere aggiunta una sola variabile di incremento.
Liste
In Java una list è una collezione ordinata, come l’array ha un indice per ogni elemento ed ammette duplicati. Le principali implementazioni di list sono ArrayList, Vector e LinkedList. Qualsiasi implementazione vogliamo usare, in Java, va per l’appunto istanziata:
ArrayList list = new ArrayList(3); list.add(5); list.add(6); list.add(7); list.add(8);
In Groovy non abbiamo bisogno di crearle con new:
def list = [5, 6, 7, 8]
Supporto ai linguaggi di Markup
import groovy.xml.MarkupBuilder
def myXMLDoc = new MarkupBuilder()
myXMLDoc.workbook {
worksheet(caption:"Employees") {
row(fname:"John", lname:"McDoe")
row(fname:"Nancy", lname:"Davolio")
}
worksheet(caption:"Products") {
row(name:"Veeblefeetzer", id:"sku34510")
row(name:"Prune Unit Zappa", id:"sku3a550")
}
}
println myXMLDoc
produce in output:
<workbook>
<worksheet caption='Employees'>
<row fname="John" lname="McDoe" />
<row fname="Nancy" lname="Davolio" />
</worksheet>
<worksheet caption='Products'>
<row name="Veeblefeetzer" id="sku34510" />
<row name="Prune Unit Zappa" id="sku3a550" />
</worksheet>
</workbook>
Se avessimo voluto farlo in Java:
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class XMLFun {
public static void main(String[] args) throws Exception {
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute("indent-number", 2);
Transformer trans = factory.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
trans.setOutputProperty(OutputKeys.INDENT, "yes");
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element workbook = doc.createElement("workbook");
doc.appendChild(workbook);
Element worksheet = doc.createElement("worksheet");
worksheet.setAttribute("caption", "Employees");
workbook.appendChild(worksheet);
Element row = doc.createElement("row");
row.setAttribute("fname", "John");
row.setAttribute("lname", "McDoe");
worksheet.appendChild(row);
row = doc.createElement("row");
row.setAttribute("fname", "Nancy");
row.setAttribute("lname", "Davolio");
worksheet.appendChild(row);
worksheet = doc.createElement("worksheet");
worksheet.setAttribute("caption", "Products");
workbook.appendChild(worksheet);
row = doc.createElement("row");
row.setAttribute("name", "Veeblefeetzer");
row.setAttribute("id", "sku34510");
worksheet.appendChild(row);
row = doc.createElement("row");
row.setAttribute("name", "Prune Unit Zappa");
row.setAttribute("id", "sku3a550");
worksheet.appendChild(row);
StringWriter writer = new StringWriter();
StreamResult out = new StreamResult(writer);
DOMSource dsource = new DOMSource(doc);
trans.transform(dsource, out);
System.out.println(writer.toString());
}
}
Altre differenze altrettanto importanti sono: la possibilità di non terminare le istruzioni con un punto e virgola, questo va fatto solo se scriviamo più istruzioni su una stessa riga; l’istruzione return non è obbligatoria; metodi e classi sono public di default; non c’è differenza tra eccezioni checked e unchecked; supporto nativo alle espressioni regolari; possibilità di tipizzazione statica o dinamica per variabili e metodi. Per maggiori informazioni consiglio di dare un’occhiata al sito ufficiale del progetto, http://groovy.codehaus.org/, dove possiamo trovare preziose informazioni e documenti che ho usato per creare questo articolo. Detto questo non resta che mostrare il classico “Hello World”.
class Greet {
def name
Greet(who) { name = who[0].toUpperCase() + who[1..-1] }
def salute() { println "Hello $name!" }
}
g = new Greet('world') // create object
g.salute() // Output "Hello World!"
Sebbene le somiglianze con Java siano evidenti, è anche vero che per un programmatore esperto abituato con la sintassi Java è noiso per i primi tempi capire come scrivere il codice e magari fare continuamente riferimento alla documentazione per creare una classe, un metodo o un ciclo for. Nonostante tutto, penso che questo “spreco” di tempo iniziale sarà ben ripagato nel futuro. L’esempio del documento XML è quello più lampante di quanto può essere veloce programmare con Groovy.
Intanto la comunità sta apprezzando il progetto, tant’è che a corredo sono nati anche vari framework, Grails è il primo che mi viene in mente. Non resta dunque che iniziare a provare…