Archive for the ‘Java’ Category.

Tomcat on AS400 (aka i-series, Systemi, IBM i, bla, bla…)

I know that AS400 gives its own native support to Tomcat and other application servers, but it does it in the IBM style: intricate and rigid. What if, for example, I need to use a version of Tomcat that it is not shipped with my operating system?
Here is one possible answer:

1) Download a copy of Apache Tomcat and unzip it in a directory of the Integrated File System of AS400.

2) In another directory of the Integrated File System Create a text file named tomcat with a simple script like this:

#The path of the JDK you want to use
export JAVA_HOME=/QIBM/ProdData/Java400/jdk14  

#The JVM option you want to use
#In this example -opt0 means 'no optimization'
export JAVA_OPTS='-opt0 -Djava.awt.headless=true'  

cd /path/to/my/tomcatdir/bin
catalina.sh %1

3) In a 5250 session (or in a batch job) execute this command

QSH CMD('/path/to/my/script/tomcat run')

Your Tomcat should be alive and kicking :-)

4) In order to shut down Tomcat, use this command

QSH CMD('/path/to/my/script/tomcat stop')

Enjoy with Tomcat and AS400!!!

Functional setter Java idiom

The way of organizing the code I will show in this post is very common, but, perhaps, it's useful to give it a name, and I will call it the "functional setter java idiom". Let's see.

In java there are no named parameters, i.e. parameters that I can pass to a method in the order I like calling them with their name. For example in Visual Basic for Applications we can sort some Excel cells this way:

 
SelectedSheets.PrintOut Copies:=1, _
    Preview:=True, _
    PrintToFile:=True, _
    Collate:= True
 

Note that the order in which I set the parameters is arbitrary, and that some parameters can be omitted, having it assigned with default values.

Now let's suppose we need to create an object with a long series of parameters (OK, I know, it's a code smell, but, please, close your nose for a while):

 
PrintType printType = new PrintType(1, true, true, true);
 

Well, not a good piece of code! Especially the sequence of boolean parameters is a mess. Moreover, sometimes I'd like to create my object with less parameters, having the others set with default values. I could create many constructors, but this would increase the complexity of my program.

I could solve the problem using some setters:

 
PrintType printType = new PrintType();
printType.setCopies(1);
printType.setPreview(true);
printType.setPrintToFile(true);
printType.setCollate(true);
 

Uhmm, better enough, but what if I need to assign my object to a constant, i.e. a final static field? I should write:

 
public final static PrintType DEFAULT_PRINT = new PrintType();
 
static {
	DEFAULT_PRINT.setCopies(1);
	DEFAULT_PRINT.setPreview(true);
	DEFAULT_PRINT.setPrintToFile(true);
	DEFAULT_PRINT.setCollate(true);
}
 

Mamma mia, this code is ugly! Maybe I could improve it just a bit using some functional setters, i.e. setters that have a return value, as a function. In the PrintType class I should write:

 
public PrintType setCopies(int copies) {
	this.copies = copies;
	return this;
}
 
public PrintType setPreview(boolean value) {
	this.preview = value;
	return this;
}
 
public PrintType setPrintToFile(boolean value) {
	this.printToFile = value;
	return this;
}
 
public PrintType setCollate(boolean value) {
	this.collate = value;
	return this;
}
 

Now the initialization of my static field becomes:

 
public final static PrintType DEFAULT_PRINT = new PrintType()
	.setCopies(1)
	.setPreview(true)
	.setPrintToFile(true)
	.setCollate(true);
 

This is not so bad, don't you think?

RDS Kata

In questo post mostrerò la mia discutibilissima soluzione all’RDS Kata proposto sul blog di SI-Agile, il vivace gruppo che raccoglie gli agilisti della Svizzera Italiana. Il codice è presente in questo file zip, spero a breve di creare un progetto su Google Code per ulteriori sviluppi.

Funzioni di utilità

Partiamo subito con la prima sequenza di test.
Leggendo tutti i requisiti del Kata, ho pensato fosse necessario avere in primo luogo una funzione che centrasse le stringhe secondo le specifiche. Ho pertanto creato dei test per un metodo statico center da inserire nella mitica classe di utilità StringUtils, che non può mancare in qualsiasi progetto Java. Il primo banale test, testCenterDoesNotChangeTooLongStrings, mi è servito per disegnare l’interfaccia del metodo. Per scrivere i test successivi mi è sorta la necessità di avere una funzione blanks, che, guarda caso, mi è poi tornata utile anche nel codice di produzione. Ho deciso di non scrivere un test specifico per blanks, avendo fiducia che, una volta creata correttamente la funzione stringOf, la sua specializzazione che creasse stringhe di spazi fosse banale.
Uso qui volutamente il termine di funzione, in quanto questi metodi hanno la proprietà di trasparenza referenziale, ovvero restituiscono sempre gli stessi valori a fronte dei medesimi ingressi, indipendentemente da un qualsiasi concetto di “stato” del sistema; inoltre non hanno alcun effetto collaterale. Se ci fosse la possibilità di utilizzare i metodi statici come parametri di altre funzioni… ;-)
Concludendo le divagazioni, vorrei solo annotare che, per migliorare la leggibilità del codice e ridurre le duplicazioni, ho fatto un po’ di refactoring sui test estraendo il metodo assertCenterReturnsAStringOfFixedLength.

Le classi principali

Sono poi passato al disegno principale della mini applicazione tramite i test di RDSGeneratorTest che ho cercato di rendere indipendenti dal numero di caratteri del display.
Leggendo le specifiche del Kata ho cercato di elaborare una metafora: le varie parti da mostrare sul display (autore, data, titolo) sono gruppi distinti di parole, ovvero delle frasi. Ho quindi stilato i test di RDSSentenceTest, facendo anche in questo caso attenzione a rendermi indipendente dalla lunghezza del display. La prima stesura della classe RDSSentence, che comunque supera tutti i test, è stata la seguente:

 
public class RDSSentence {
 
  private final String sentence;
  private final int displaySize;
 
  public RDSSentence(String sentence, int displaySize) {
    this.sentence = sentence;
    this.displaySize = displaySize;
  }
 
  public String[] tokens() {
    if ("".equals(sentence.trim())) {
      return new String[]{};
    }
 
    String[] tokens = sentence.trim().split("\\s+");
    if (tokens.length == 0) {
      return new String[]{};
    }
 
    Collection<String> result = new ArrayList<String>();
    StringBuffer accumulator = new StringBuffer();
    for (int i = 0; i < tokens.length; i++) {
       if (accumulator.length() + tokens[i].length() + 1 <= displaySize) {
         if (accumulator.length() > 0)  {
           accumulator.append(" ");
         }
         accumulator.append(tokens[i]);
       } else {
         if (accumulator.length() > 0) {
           result.add(accumulator.toString());
         }
         accumulator = new StringBuffer(tokens[i]);
       }
       if (i == tokens.length -1) {
         result.add(accumulator.toString());
       }
    }
 
    return result.toArray(new String[]{});
  }
 
}
 

Come potete vedere, il codice è troppo complesso, con un numero ciclomatico molto elevato. Per un buon refactoring occorreva un’altra metafora: il display che accumula parole fino ad una certa lunghezza può essere appunto visto come un accumulatore elettrico, o, se vogliamo, idraulico che, raggiunta la capienza, si svuota in un tubo di scarico. Sono nate così le classi Accumulator e StringWharehouse, che non hanno test autonomi, ma vengono esercitate indirettamente dai test di RDSSentenceTest. La classe StringWharehouse, con una leggera modifica, mi è poi stata utile per migliorare il MockRadioStation, che in un primo tempo accumulava i dati in un semplice StringBuffer.

Conclusioni

Cosa ho cercato di esercitare con questo Kata?

Sicuramente non ho raggiunto completamente i miei obiettivi, spero comunque di aver fatto un piccolo passo in questa direzione.

Pleasures of boilerplate code

In a very interesting interview, Martin Odersky said that Scala could be a little more difficult than Java for newcomers because in it you have not to write boilerplate code, but you have to think at your problem just from the first line of code. In some way, boilerplate code could be a kind of "warming up" for beginners. Writing some code, even if it's only syntactic noise, could give confidence to the programmer, generating a feeling of accomplishment.

But, is there a way to warm up without writing silly code? The best way of doing this is with unit testing. In TDD by example , Kent Beck describes "Starting tests": Start by testing a variant of an operation that doesn't do anything. Using these tests, not only you can start exploring your design, but you can also break the "white sheet syndrome".

Agile day 2008 - appunti di viaggio


Agile day

Sì, va bene, avrei voluto commentare in diretta l'Agile day 2008, ma non ci sono riuscito per merito degli organizzatori: troppe le cose interessanti da seguire per poterle riportare immediatamente!
Cercherò quindi di dare il mio personalissimo riassunto a posteriori, che intende essere più un taccuino di viaggio che un'analisi accurata dei tantissimi stimoli ricevuti nella manifestazione. I protagonisti dei vari incontri non me ne vogliano se non sono riuscito a recepire esattamente quanto volevano esprimere :-)

Agile e pragmatic: sinonimi o contrari?

La giornata è iniziata discutendo su "Agile e pragmatic: sinonimi o contrari?". Stimolo per il dibattito è stato un comune sentire che si sta facendo strada nell'ambiente Agile, emergente anche dagli ultimi thread della mailing list XP-it (e su cui mi sono permesso di scrivere un breve post). La sensazione è che nelle pratiche agili ci sia qualcosa da rivedere, pur non essendoci accordo sul cosa. Qualcuno pone l'accento sul dogmatismo con il quale esse sono a volte presentate. Altri sul fatto che, come in tutti i fenomeni diventati di massa, ci siano state delle cattive interpretazioni. Un altro dubbio riguarda la possibiltà di applicare solo in parte queste tecniche, senza che la mancata introduzione di una renda inutili tutte le altre. I più maligni (che però non hanno preso parte all'Agile Day ;-) ) arrivano a supporre che qualcuno abbia sfruttato la moda per interesse personali. La mia modestissima opinione è che effettivamente alcuni punti cardine dello Sviluppo Agile possano generare dei dubbi. In primo luogo mi chiedo se il design emergente sia in ogni situazione un valido sostituto del design preventivo, termine con cui non intendo la produzione di valanghe di documentazione e grafi UML che descrivono ogni metodo del progetto, ma una fase di analisi del "cosa fare" e "come farlo" proporzionale all'entità dell'impresa, analisi che potrebbe richiedere anche la generazione di documentazione di corredo. Mi domando inoltre se la programmazione agile sia veramente alla portata del programmatore medio, o richieda delle capacità fuori dal comune.
La maggiore prova a sostegno della bontà dell'approccio agile penso comunque sia stata portata da Simone Genini. Se un imprenditore come lui, che non fonda il proprio business sulla evangelizzazione dell'agilismo, bensì sulla consegna al cliente di codice funzionate, continua a scommettere da anni, pare anche con successo, su questi metodi di lavoro, allora si potrebbe financo pensare che funzionino veramente! ;-)

Refactoring di codice Legacy

La mia seconda tappa è stata il bellissimo workshop di Tommaso Torti e Fabiana Romagnoli su "Refactoring di codice Legacy". Cosa ho imparato? Che anche il refactoring deve misurarsi con il tempo e le risorse a disposizione. Il codice proposto presentava infatti diversi aspetti suscettibili di miglioramento, ma un limite insuperabile era costituito dai venti minuti a disposizione. Ci si poteva concentrare sull'eliminazione di numerosi "if" tramite l'utilizzo del polimorfismo, oppure lavorare sulla chiarezza del codice cancellando duplicazioni, rinominando variabili ed assegnando correttamente le responsabilità alle classi. Il primo refactoring sarebbe stato sicuramente più pirotecnico, ma probabilmente non avremmo avuto né il tempo, né le energie (ci siamo alzati alle cinque) per portarlo a termine. Il secondo, molto più banale, aveva invece il vantaggio di riuscire comunque a consegnare valore al cliente (nel nostro caso Tommaso e Fabiana) nel tempo stabilito.

Tool for agile planning and estimation

Altro workshop molto interessante è stato quello condotto da Simone Casciaroli. Lo strumento per la pianificazione agile proposto, chiamato ora Stuffplanner, pur essendo in versione alpha, ci è sembrato molto potente. Cosa ho imparato? Tutto, dato che sono assolutamente un novizio della pianificazione agile. Ecco i miei appunti ad uso principianti.

- E' importante suddividere il progetto in "storie" quanto più indipendenti fra loro al fine di evitare che una di esse costituisca un collo di bottiglia per lo sviluppo delle altre. Esse dovrebbero inoltre essere "verticali", ovverosia comprendere una funzionalità completa, dalla GUI al DB, per rappresentare una unità atomica di valore rilasciabile al cliente. In tal modo questi potrà valutarne correttamente la priorità all'interno della fase di pianificazione ed avremo sempre dei rilasci che aggiungono valore al prodotto.

- Un formato standard per le storie è: As a....I want...so that.....
As a... indica lo scenario di utilizzo che si immagina per la storia, per esempio Come utente esperto.
I want... indica il contenuto vero e proprio della storia, per esempio io voglio cercare un libro per ISBN.
Nella clausola so that.. si dovrebbe rendere esplicito il valore che la storia possiede per il cliente, al fine di aiutarlo nell'attribuzione del giusto peso durante la fase di pianificazione. Nel nostro esempio avremmo così da poter comprare un libro in brevissimo tempo.

- Una storia non dovrebbe occupare il team per più di due giorni, per evitare che il grafico di avanzamento lavoro (burndown chart) rimanga stabile per troppo tempo, abbassando il morale degli sviluppatori.

- La stima di una storia dovrebbe essere svolta preferibilmente in "story point", una misura di difficoltà relativa. Per esempio, "se si indica con 1 la difficoltà di sviluppo della storia più semplice, allora la storia X avrà peso 7". Il passaggio dagli "story points" al tempo reale dovrebbe essere realizzato analizzando lo storico delle iterazioni precedenti. Alla prima iterazione occorre solo confidare nell'esperienza dei membri del team. :-)

- La stima di una storia non è un valore singolo, ma una curva di probabilità di consegna: suppongo che non ci sia alcuna probabilità di realizzare la storia in meno di x story point (valore minimo), mi aspetto che ne serviranno y (valore atteso), penso di essere certo di consegnarla dopo z story point (valore massimo). Tutti gli elementi del team esprimono queste tre valutazioni. Per determinare il peso da assegnare alla storia, che è un singolo numero, si possono scegliere diverse funzioni di interpolazione di questi dati, fissando inoltre una soglia di rischio: ad esempio potrei scegliere il valore della curva di probabilità che mi garantisca una affidabilità dell'80%. Uno strumento come Stuffplanner è di ausilio in questa fase.

- Se è ovviamente importante non sottostimare le storie, è altrettanto pericoloso sovrastimarle. Il team, infatti, vedendo che la propria velocità è molto maggiore del previsto potrebbe rilassarsi troppo e perdere concentrazione.

Processo al database server relazionale

Purtroppo ho potuto assistere solo ai momenti finali di questa divertente presentazione/rappresentazione, svolta con notevole capacità teatrale. Due brevi note da innocentista.
Come prova a carico del DB relazionale è stata portata una stored procedure, realmente messa in produzione, che occupava diverse pagine. A mio avviso le stored procedure non hanno un legame essenziale, oserei dire ontologico, con la struttura di un DB relazionale. Sono solo un posto, quasi sempre sbagliato, dove mettere del codice che lavora sui dati relazionali. La loro esistenza non è strutturalmente legata a tale modello. Il fatto che molti programmatori poco avveduti ne abbiano abusato non è sufficiente a dire che il modello relazionale sia negativo.
Un'altra critica mossa al DB è quella che lo vorrebbe d'impiccio nella fase di stesura dei test. Se da un lato questo è sicuramente vero, dall'altro occorre forse ristabilre una giusta proporzione tra le cose. Ricordiamo sempre che i test non sono un fine, ma solo un mezzo. Dobbiamo trovare il modo per testare meglio l'uso del DB, cercando di evitare che la parte di accesso ai dati contenga troppa logica, ma ciò non può scalfire la validità dell'approccio relazionale nella grande maggioranza dei casi.
Quando qualcuno parla male dei database, io ricordo sempre che lavoro da anni su un DB che è stato alimentato, interrogato e spippolato da programmi scritti in una decina di linguaggi diversi. I linguaggi sono cambiati, i programmi sono stati riscritti, ma la struttura del DB, ben congegnata, è rimasta. Diceva Cicerone Programmata volant, Datarum Basae manent :-D

Uso dei Kanban, ovvero quando stimare è impossibile

Questo è stato il titolo di un open space fuori programma tenuto da Gabriele Lana.
Se non ho inteso male, il punto di vista di Gabriele è il seguente. In particolari situazioni, dove ad esempio il dominio del problema sia particolarmente difficile o inusuale, oppure dove vi sia una grossa dipendenza da programmi o prodotti sviluppati da terzi fuori dal nostro controllo, effettuare delle stime dei tempi di realizzazione è semplicemente impossibile. Non solo, ma la stima potrebbe risultare controproducente rispetto all'affidabilità del software. I programmatori potrebbero infatti cercare di abbassare la qualità (copia e incolla selvaggio, mancata stesura di test, design approssimativo e mancanza di refactoring) pur di rimanere all'interno dei tempi previsti. In questi casi l'approccio migliore sarebbe quello di stendere delle user story, che potremmo ora definire Kanban, che avrebbero solo la funzione di ordinare i lavori in base alla priorità e determinare lo stato di avanzamento degli stessi.
E la stima di tempi e costi? Visto che in ogni caso in queste situazioni una qualsiasi stima sarebbe solo una bugia, meglio concordare con il cliente un tipo di contratto flessibile, con punti di verifica frequenti ove poter eventualmente cambiare direzione.

Conclusioni

L'agile day si è confermato un grande evento. Un grosso ringraziamento a chi si è preso l'onere dell'organizzazione ed un arrivederci all'anno prossimo!!!

Design Object Oriented: Factory method

Spesso ci accontentiamo di scrivere programmi funzionanti e questo sarebbe già un successo, direbbe qualcuno. ;-) A volte però non ci accorgiamo che i nostri programmi, anche se svolgono il loro compito, non contengono un codice elegante, non hanno cioè un buon design. La ricerca dell'eleganza del codice non è un mero esercizio estetico. Scrivere bel codice significa avere programmi facili da comprendere, quindi facili da cambiare e da correggere.
Vedremo qui e nei prossimi post alcune tecniche che, se bene applicate, possono aiutarci a raggiungere questi obiettivi.
Continue reading ‘Design Object Oriented: Factory method’ »

Un diverso application server su AS400

Forse non tutti sanno che, a partire dal V5R4, è disponibile su AS400 - iSeries un application server diveso da Tomcat e dal tristemente noto Websphere (per gli amici WebPallaAlPiede).
Si chiama "IBM Integrated Web Application Server for i5/OS", ed è l'application server sfruttato da IBM web query.
In attesa di provarlo, vi rinvio alla documentazione ufficiale IBM.

Incomincia la collaborazione con mondoinformatico.info

Con un articoletto su Java inizia la mia collaborazione con mondoinformatico.info. Ho intenzione di pubblicare su questa giovane testata on-line una serie di piccoli suggerimenti su Java e Scala. Restate connessi ;-)

Questo articolo partecipa al link contest di mondoinformatico.info.

Come eseguire un comando AS400 tramite JDBC/ODBC

In un precedente post abbiamo visto come eseguire un programma AS400 tramite JDBC/ODBC. Occupiamoci ora di come eseguire un comando tramite questa interfaccia.
Continue reading ‘Come eseguire un comando AS400 tramite JDBC/ODBC’ »

Come richiamare un programma AS400 da Java o Access

E’ possibile richiamare un qualsiasi programma AS400 da una connessione JDBC utilizzando lo statement SQL CALL. Questo non solo dal Toolbox for Java, ma, teoricamente, da una qualsiasi connessione ODBC/JDBC.
Se non si devono ricevere dei parametri di ritorno dal programma, non è necessario creare anticipatamente una definizione di Stored procedure, altrimenti occorre prima definire la procedura con lo statement SQL CREATE PROCEDURE.
Continue reading ‘Come richiamare un programma AS400 da Java o Access’ »