Miglioriamo lo stile di programmazione: i setter funzionali in Java



Ho lavorato per anni allo sviluppo di software gestionale in Java, e vorrei qui trascrivere qualche piccolo trucco imparato con il tempo.

Il modo di organizzare il software che presenterò oggi è oramai molto diffuso, ma forse è utile battezzarlo in qualche modo. Molti chiamano questo stile fluid interface, io preferisco il termine “setter funzionali” per indicare un particolare uso di questo idioma nella fase di inizializzazione degli oggetti. Vediamo.

In Java non ci sono parametri per nome, cioè parametri che possano essere passati ad un metodo in ordine arbitrario essendo identificati in base al loro nome. Per esempio in Visual Basic for Applications possiamo ordinare alcune celle in un foglio Excel in questo modo:

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

Si noti che l’ordine con il quale i parametri vengono impostati è del tutto ininfluente, ed alcuni di essi possono essere omessi, nel qual caso assumeranno un valore predefinito.

Supponiamo ora di aver bisogno di creare un oggetto con una lunga serie di parametri (OK, so che non è una buona pratica di programmazione, ma chiudete un occhio per cortesia):

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

Accidenti, non è certo un gran bel codice! In modo particolare la sequenza di parametri booleani è di difficile comprensione. Inoltre, in alcuni casi potrei voler costruire il mio oggetto con meno parametri, lasciando che gli altri assumano un valore predefinito. Potrei creare diversi costruttori, ma questo aumenterebbe la complessità del codice.

Potrei risolvere il problema introducendo dei setters:

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

Uhmm, va già meglio, ma cosa succederebbe se dovessi assegnare il mio oggetto ad una costante, cioè ad un campo dichiarato final static? Dovrei scrivere:

 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, questo codice fa schifo! Forse potrei migliorarlo un poco usando dei setter funzionali cioè dei setter che hanno un valore di ritorno, esattamente come se fossero delle funzioni. Nella classe PrintType dovrei scrivere:

 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;
}

Il che trasforma l’inizializzazione delle mie costanti in questo modo:

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

Molto meglio, cosa ne pensate?

Annunci sponsorizzati:
Condividi su Facebook Condividi su Twitter!
Pinterest