Category: programming

  • Java: come scrivere un build.xml di ant per compilare e pacchettizzare (WAR/EAR)

    Come sapete, tutti i Java application server (come ad es. Tomcat) richiedono il deploy di un applicativo sottoforma di un pacchetto EAR. Ma come è composto un pacchetto EAR?

    Un pacchetto EAR non è altro che un file jar (che a sua volta è un file zip) che contiene al suo interno:

    • un descrittore di deploy, sotto la directory META-INF (application.xml) che contiene informazioni di gestione riguardo all’applicazione in corso di deploy, come il nome, il contextpath, etc.
    • generalmente, contiene un file WAR che contiene, al suo interno, il modulo web J2EE dell’applicazioni.

    A sua volta, un file WAR è un file JAR composto da:

    • il file web.xml sotto la directory WEB-INF che definisce la struttura dell’applicazione web.
    • i file compilati (.class) dell’applicazione posti sotto WEB-INF/classes

    Risalendo a ritroso, per creare un EAR è necessario:

    1. Compilare i files dell’applicazione;
    2. Spostarli sotto WEB-INF/classes insieme ai files della webapp (jsp, files statici, etc.)
    3. Creare un WAR (jar)
    4. Creare un EAR inglobando anche il meta-descrittore del deploy

    Per fare tutto questo è sufficiente usare ant (o meglio maven, ma questo ve lo spiegherò in un altro post!) con diversi target. Vediamo un esempio che ho realizzato:

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="prjTest" default="main" basedir="./">
    
    <property name="component-name" value="prjTest" />
    <dirname property="workspace.path" file="${ant.file.prjTest}/.." />
    <dirname property="ear.dir" file="${ant.file.prjTest}" />
    <property name="target.dir" value="${ear.dir}/target" />
    <property name="deploy.dir" value="${ear.dir}/deploy" />
    <property name="deploy.file" value="prjTest.ear" />
    
    <target name="init">
    <mkdir dir="${target.dir}/classes" />
    <mkdir dir="${deploy.dir}" />
    </target>
    <target name="clean">
    <delete dir="${target.dir}" />
    <delete dir="${deploy.dir}" />
    <delete dir="${workspace.path}/prjTest/WebContent/WEB-INF/classes" />
    </target>
    
    <path id="myclasspath">
    <fileset dir="${workspace.path}/prjTest/WebContent/WEB-INF/lib">
    <include name="**/*.jar" />
    </fileset>
    </path>
    
    <target name="main" depends="clean,init">
    <javac srcdir="${workspace.path}/prjTest/JavaSource" destdir="${target.dir}/classes" includes="**/*.java"
    source="${source}" target="${target}"
    classpathref="myclasspath">
    </javac>
    
    <copy todir="${workspace.path}/prjTest/WebContent/WEB-INF">
    <fileset dir="${target.dir}">
    <include name="**/*" />
    <exclude name="**/.metadata/*" />
    </fileset>
    </copy>
    <copy todir="${workspace.path}/prjTest/WebContent/WEB-INF/classes">
    <fileset dir="${workspace.path}/prjTest/JavaSource">
    <include name="**/*.properties" />
    </fileset>
    </copy>
    
    <war destfile="${target.dir}/prjTest.war" webxml="${workspace.path}/prjTest/WebContent/WEB-INF/web.xml">
    <fileset dir="${workspace.path}/prjTest/WebContent" />
    </war>
    
    <ear destfile="${deploy.dir}/prjTest.ear" appxml="${workspace.path}/prjTest/META-INF/application.xml">
    <fileset dir="${target.dir}" includes="*.jar,*.war" excludes="**/.metadata/*" />
    </ear>
    </target>
    </project>
    

    Come potete vedere il target chiamato “main” si occupa di:

    • compilare tutte le classi del progetto (javac) usando il classpath di riferimento
    • copiare i files di configurazione (come il già menzionato web.xml) sotto /WEB-INF (copy)
    • copiare i compilati delle classi sotto /WEB-INF/classes (copy)
    • creare un archivio WAR (war) usando i files specificati in fileset e usando il web.xml specificato sotto webxml
    • creare un archivio EAR (ear) usando i files specificati in fileset usando il meta-application specificato in appxml e copiando i files da fileset.

    Questo è lo scheletro di build.xml che uso per pacchettizzare velocemente un’applicazione J2EE (infatti basta lanciare ant build.xml main) da linea di comando per compilare, copiare tutti i files necessari e creare WAR ed EAR!).

  • Pressman – “Principi di Ingegneria del Software” – quarta edizione: la mia recensione

    Ad un paio di anni di distanza dal corso di “Ingegneria del Software” frequentato all’università, ho deciso di rileggere il libro di Roger Pressman, “Principi di Ingegneria del Software”, che nel frattempo era avanzato fino alla quarta edizione.

    Il libro è voluminoso (circa 700 pagine) e piuttosto costoso (49 euro), ma rappresenta una pietra miliare nel campo del software engineering. Mettiamo subito in chiaro che su questo libro non si impara a programmare. È un libro che illustra le metodologie, gli strumenti e la teoria dell’ingegneria del software.

    Il libro è diviso in tre parti:

    1. nella prima parte vengono illustrati i modelli di sviluppo del software (il vetusto modello a cascata, il modello iterativo, e gli sviluppi agili);
    2. nella seconda parte vengono presentati gli approcci pratici a tutto il ciclo di vita del software, come la modellazione dei requisiti, gli strumenti per la progettazione del software (come UML) fino alla tecniche di testing (es. black-box e white-box);
    3. nell’ultima parte, infine, vengono presentate le metriche per la stima e per la valutazione della qualità del software

    Il libro non è di facile comprensione, ed è corredato da un esempio di progetto che viene sviluppato dall’inizio alla fine. Pressman presenta in modo completo ed accurato tutti i temi relativi all’ingegneria del software; a mio avviso, considero il libro come una sorta di manuale a cui fare riferimento in ogni momento e ad una lettura basata sullo specifico concetto, più che un libro da una lettura streamlined dall’inizio alla fine (in questo senso l’unico progetto di esempio sviluppato dall’inizio alla fine non aiuta).

    In definitiva: un libro che è una pietra miliare da avere nella propria collezione di libri tecnici. È vero, non è di facile comprensione (soprattutto a chi non ha molta dimestichezza con diversi temi dell’ingegneria del software), ma di sicuro un libro a cui si deve poter fare riferimento in ogni momento.

  • Online JavaScript Deminifier

    Se vi trovate a dover debuggare del codice JavaScript che è minified (per ottimizzare il trasferimento viene applicato il minifying, ovvero vengono tolti tutti gli spazi inutili nel codice), dovete passare per un deminifier/unminified (o beautifier). In ogni caso, un tool che vi permetta di leggere il codice JavaScript senza “incrociare gli occhi“.

    A tal proposito ho provato JSBeautifier e ne sono rimasto soddisfatto. Segnalo anche Javascript Deminifier (per Firefox).

  • Python: scriviamo un HTTPS downloader simile a wget (con urllib2, optparse e getpass)

    Per ragioni di semplicità di utilizzo e immediatezza (e anche per imparare qualcosa di nuovo), la settimana scorsa ho dovuto scrivere un downloader da linea di comando simile a GNU wget, ma con alcuni requisiti personalizzati:

    • l’accesso alla pagina di download è protetto da userid e password (autenticazione HTTPDigestAuth);
    • il protocollo di accesso è HTTPS;
    • una volta ottenuto l’accesso, è necessario fare il GET di alcuni files ben particolari e crearli su hard disk.

    Per realizzare questo wget-like in Python, usiamo il modulo urllib2 che ci permette di accedere a risorse esterne tramite i protocolli più svariati. Per aprire una connessione HTTPS e autenticarci correttamente usiamo i seguenti statement:

        passman.add_password(None, url, username, password)
        authhandler = urllib2.HTTPDigestAuthHandler(passman)
        opener = urllib2.build_opener(authhandler)
    

    Affinché la gestione delle varie opzioni sia più semplice possibile, usiamo anche il modulo optparse (che permette di passare le opzioni al programma in modo simile alle utility GNU):

    parser = optparse.OptionParser()
    parser.add_option("-u", "–username")
    parser.add_option("-d", "–date")
    parser.add_option("-t", "–target", default="logs")
    options, arguments = parser.parse_args()
    

    Visto che dovremo gestire anche l’autenticazione tramite username e password, la scelta di passare la password come argomento del programma è una scelta non ottimale: una semplice ricerca nella history della shell utilizzata potrebbe permettere ad un attaccante di risalire alla password. Per questo ci viene incontro il pacchetto getpass che, in modo simile ai programmi UNIX che si rispettino, chiede interattivamente la password (senza stamparla, ovviamente!). Per richiedere l’inserimento della password all’utente è sufficiente:

    password = getpass.getpass()
    

    Torniamo ora all’inizio: abbiamo ottenuto dall’utente username (passato come argomento) e password (richiesta interattivamente): ora possiamo aprire una connessione verso l’hostname di riferimento e richiedere il download del file (salvando su file lo stream del file in ricezione tramite i metodi standard di Python):

    passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
    passman.add_password(None, url, options.username, password)
    authhandler = urllib2.HTTPDigestAuthHandler(passman)
    opener = urllib2.build_opener(authhandler)
    download = opener.open(file)
    logging.debug('downloading %s ...' % file)
    fo = open(options.target + os.sep + targetFileName, 'w')
    fo.write(download.read())
    fo.close()
    

    Abbiamo quindi ottenuto un semplice downloader di file scritto in Python, molto più semplice di wget ma al tempo stesso molto più customizzabile.

  • Misurare la quantità di codice di un progetto

    In questo post affronto un argomento abbastanza delicato: come si misura la quantità di codice di un progetto?

    La soluzione più immediata è quella di contare le linee di codice (Source Lines of Code, SLOC). Un esempio che ho personalmente applicato per contare le righe di codice di un progetto Java a partire dalla root del progetto, usando gli strumenti che Linux ci mette a disposizione:
    find . -type f -name *.java | xargs wc -l

    Un tool che svolge lo stesso compito, più raffinato e con un supporto ad un numero maggiore di linguaggi, è sloccount [sicuramente consigliato].

    Ma quanto è indicativo il numero delle righe di codice per indicare un progetto? A mio avviso dipende da molti fattori, come:

    1. lo stile con cui si programma (un’istruzione condizionale, tipo if può occupare 3 righe come ne può occupare una, a discrezione del programmatore).
    2. l’utilizzo di librerie esterne e framework (il codice è effettivamente utilizzato ma le righe di codice non vengono conteggiate)
    3. il conteggio deve includere i test?

    In definitiva, il conteggio delle righe di codice (e/o di altre metriche relative al codice) è una grandezza che non riesce ad esprimere in modo chiaro ed esauriente la grandezza di un progetto software.
    Esistono altre metriche che ci possono aiutare nella stima della dimensione di un progetto? Voi cosa ne pensate?

  • QR Codes e la Google Chart API

    Piccola intro: i QR Codes sono analoghi ai “normali” codici a barre, ma rappresentano un’evoluzione: possono contenere più dati (a parità di dimensione) e possono essere letti da una serie più ampia di dispositivi, come gli smartphone (su iOS segnalo l’ottima e gratuita QR Reader for iPhone). Dopo aver scaricato un lettore di QR Codes per il vostro smartphone, fate una fotografia all’oggetto qui accanto: il browser del vostro telefonino vi porterà nella pagina più visitata di questo sito…

    Fatto! Avete utilizzato il vostro primo QR Code. Ma come si generano?

    A questo proposito, segnalo quest’utilissima API di Google per generare QR Codes: è molto semplice da utilizzare e in modalità RESTful (specificate i parametri direttamente nell’URL della chiamata); la tabella di documentazione di Google è estremamente chiara a riguardo. Consigliatissima!

  • Scambiare il contenuto di due variabili int senza utilizzare una variabile temporanea: XOR swap

    Una domanda interessante che mi è stata posta è: “com’è possibile scambiare il contenuto di due variabili senza utilizzare una variabile temporanea?”.

    Infatti, per scambiare il contenuto di due variabili, di solito si utilizza una variabile temporanea (vediamo un esempio in Python):

    a = 13
    b = 17
    c = a
    a = b
    b = c
    >>> a
    17
    >>> b
    13
    

    Ora, per scambiare due variabili senza una variabile temporanea (nel nostro caso l’abbiamo chiamata ‘c’), ho pensato di utilizzare un procedimento di questo tipo:

    a = 13
    b = 17
    a = a+b
    b = a-b
    a = a-b
    >>> a
    17
    >>> b
    13
    

    La soluzione a cui sono arrivato viene classificata come una variante del più diffuso XOR swap algorithm, che, in forma più generale, permette di scambiare due variabili semplicemente usando l’operazione di XOR:

    a = 13
    b = 17
    a = a ^ b
    b = a ^ b
    a = a ^ b
    >>> a
    17
    >>> b
    13
    

    Lo XOR swap può essere utile in casi molto particolari, come ad esempio quando la memoria disponibile è notevolmente limitata.
    Bonus point: in Python non c’è bisogno di utilizzare l’algoritmo di XOR swap:

    a = 13
    b = 17
    a, b = b, a
    >>> a
    17
    >>> b
    13
    

    E c’è di più: questo “trucco” funziona anche per i tipi di dato non intero!

    a = 'homer'
    b = 'marge'
    a, b = b, a
    >>> a
    'marge'
    >>> b
    'homer'
    
  • Python e il metodo setdefault

    Note to self (pun intended): questo post rappresenta una sorta di appunto mentale per ricordarmi il funzionamento di setdefault in Python, visto che puntualmente mi trovo ad utilizzarlo.

    setdefault è utilizzato sui dizionari (dict) e permette di impostare una chiave di default durante una set. Mi spiego meglio con un esempio:

    >>> D
    {1: 'leonard', 2: 'sheldon', 3: 'wolowitz', 4: 'rajesh'}
    

    Vediamo come funziona il metodo setdefault:

    >>> D.setdefault(1, 'penny')
    'leonard'
    >>> D
    {1: 'leonard', 2: 'sheldon', 3: 'wolowitz', 4: 'rajesh'}
    >>> D.setdefault(5, 'penny')
    'penny'
    >>> D
    {1: 'leonard', 2: 'sheldon', 3: 'wolowitz', 4: 'rajesh', 5: 'penny'}
    

    Ovvero, setdefault valuta la chiave passata come primo argomento:

    • se è già presente nel dizionario, viene ritornato il valore della chiave presente nel dizionario;
    • altrimenti viene aggiunta al dizionario con il valore specificato come argomento.

    in termini pythonici:

    def setdefault(d, key, val):
        if key in d:
            return d[key]
        else:
            d[key] = val
    
  • Python: scriviamo un quine

    Una sfida che intriga molti programmatori è quella di scrivere un quine, ovvero quello di scrivere un programma che stampi il proprio sorgente.

    Partiamo con la definizione più semplice, e man mano aggiungiamo i vincoli necessari. Un programmatore furbo potrebbe stampare il contenuto del sorgente semplicemente aprendolo e stampando il contenuto:

    import sys
    print open(sys.argv[0],'r').read()
    

    Per agevolare il compito di confronto, usiamo diff (in modalità unified), e quindi inseriamo il Python hashbang e modifichiamo il print in modo che non vada a capo:

    #! /usr/bin/env python
    import sys
    print ''.join(open(sys.argv[0],'r').readlines()),
    

    Il confronto è presto fatto:

    $ ./quine.py | diff  -u - quine.py
    $
    

    (D’ora in poi, avendo inserito un alias nel .bashrc, assumerò di usare sempre diff unified).

    Abbiamo creato il nostro primo quine, ma abbiamo imbrogliato: leggere il file di input è considerato come barare; dobbiamo quindi ideare un metodo alternativo.

    Consideriamo quindi un programma che, data una stringa hardcoded, la stampi. Il problema non è banale, infatti ci potremmo addentrare in una ricorsione infinita se non studiamo un modo “furbo” per stampare il sorgente del programma:

    #! /usr/bin/env python
    import sys
    source = [
    "import sys" ,
    source = [ ... ] , # ricorsione infinita!
    "if __name__ == ‘__main__’:" ,
    "for i in source:" ,
    "print i"
    ]
    
    if __name__ == ‘__main__’:
    for i in source:
    print i
    

    Studiamo un metodo alternativo per stampare il sorgente: nella stringa che rappresenta il sorgente (source); il segreto è che usare un carattere speciale (es. $$) per dire al programma di stampare la stringa stessa!

    #! /usr/bin/env python
    import sys
    source = [
    "import sys" ,
    source = $$
    "if __name__ == '__main__':" ,
    "for i in source:" ,
    "print i"
    ]
    
    if __name__ == ‘__main__’:
    for i in source:
    if ‘$$’ in i:
    # stampiamo la rappresentazione della stringa che rappresenta il codice sorgente
    else:
    print i
    

    Per terminare il quine, dobbiamo espandere la sezione che manca; è importante prestare attenzione agli string literal (lettura consigliatissima!) per effettuare una stampa corretta delle stringhe nel programma (con i caratteri di escape corretti).
    Dopo aver ottenuto un primo esempio, armati di diff e di pazienza, dovremo correggere eventuali piccoli problemi (ad esempio: le “,” a fine riga per gli elementi della lista sourcecode — la virgola c’è per tutti gli elementi, tranne che per l’ultimo!).
    Volete la soluzione?

    #!/usr/bin/env python
    import string
    source = [
    '#!/usr/bin/env python' ,
    'import string' ,
    'source = $$' ,
    'if __name__ == "__main__":' ,
    'for i in source:' ,
    'if i == "source = $$":' ,
    'print i[0:i.find("$")] + "["' ,
    'for i in source:' ,
    '''if string.count(i,"'") != 0:''' ,
    '''print "'"*3 + i + "'"*3,''' ,
    'else:' ,
    '''print "'" + i + "'",''' ,
    'if source.index(i) < len(source)-1:' ,
    'print ","' ,
    'else:' ,
    'print ""' ,
    'print "]"’ ,
    ‘else:’ ,
    ‘print i’
    ]
    if __name__ == "__main__":
    for i in source:
    if i == "source = $$":
    print i[0:i.find("$")] + "["
    for i in source:
    if string.count(i,"'") != 0:
    print "'"*3 + i + "'"*3,
    else:
    print "'" + i + "'",
    if source.index(i) < len(source)-1:
    print ","
    else:
    print ""
    print "]"
    else:
    print i
    

    [notate come ho evitato alcuni problemi degli string literals tramite triple quoting (”’) e il costrutto di ripetizione (“”*3)].

    Da un rapido confronto tra l’output del programma e il sorgente, a meno di indentazioni del codice sorgente (richieste da Python), possiamo dire che dopo tanta fatica, abbiamo creato il nostro primo quine!

    Il prossimo passo sarebbe quello di ottimizzare il codice: short is better. Ma io non mi dilungherò oltre: aprite un editor e datevi da fare!

  • Eclipse: impostare un template per l’inserimento di un Logger log4j

    Mi capita spesso, in Eclipse, di inserire il codice per abilitare il logging di una classe tramite log4j:

    private static Logger logger = Logger.getLogger(Klass.class);
    

    Utilizzano i templates, una funzionalità di Eclipse, possiamo evitare di riscrivere tutte le volte questa semplice istruzione. Per impostare un template, in Eclipse, è sufficiente recarsi su: Window > Preferences > Java > Editor > Templates e creiamo un nuovo template.

    Nel campo pattern inseriamo:

    private static Logger logger = Logger.getLogger( ${enclosing_type}.class );
    ${:import(org.apache.log4j.Logger)}
    

    A questo punto, per inserire il logger, è sufficiente utilizzare lo shortcut CTRL+Space per visualizzare gli autocompletamenti, e selezionare “logger” dal menu.