MokaByte 64 - Giugno 2002 
Design Patterns
di
Giancarlo Crocetti
Uno dei soggetti piu' caldi del momento nella comunita' di sviluppatori object oriented. Vediamo come e' nato questo movimento e le finalita' che vuole raggiungere

Introduzione
I Patterns per lo sviluppo del software non sono semplicemente suggerimenti per risolvere particolari problemi, ma una vera e propria disciplina scientifica che ha lo scopo di aiutare gli sviluppatori del software a risolvere problemi ricorrenti che si incontrano nella fase di analisi e codifica del software.
Al fine di raggiungere questo scopo, e' necessario definire formalmente un linguaggio comune per comunicare esperienze, per definire problemi e la loro soluzione. Questo approccio formale permette, quindi, di acquisire quella conoscenza profonda del problema e giustificare una soluzione piuttosto che un'altra.
Altro punto importante, quindi, e' dire che questa disciplina non fornisce semplicemente una soluzione al problema, ma fornisce quella "ottima". I Design Patterns non si focalizzeranno, quindi, sulla tecnologia, quanto sulla creazione di una cultura per la documentazione ed il supporto di un solido approccio alle architetture ed al design.

Ognuno di noi puo' definire un suo patterns, l'importante e' seguire delle linee guida che sono accettate dalla comunita' scientifica "Pattern Community" e di cui parleremo successivamente.


L'origine dei Patterns
Il termine Pattern fu coniato da alcuni lavori dell'architetto Christopher Alexander ed applicato allo sviluppo di piani urbani ed alle architetture di costruzioni urbane. Un esempio di lavoro di Alexander e' "A Pattern Language: Towns, Buildings, Constructions (Oxford University Press, 1977).

Lo studio di Alexander sui patterns aveva lo scopo di dimostrare che l'archittettura del tempo era inadeguata per incontrare la reale domanda del momento e i requisiti degli utenti, della societa' e degli individui, e falliva nel realizzare lo scopo ultimo di ogni attivita' ingenieristica e di design: migliorare le condizioni umane.
Anche se il lavoro di Alexander e' esclusivamente un lavoro di architettura e di pianificazione urbana, I concetti da lui sviluppati possono essere applicabili ad altre discipline, come lo sviluppo del software.

Alexander propose un paradigma per l'architettura che venne poi ripreso ed adattato da Ward Cunningham e Kent Beck nel 1987, mentre si trovavano a lavorare con Smalltalk nel creare interfacce utenti. Cunningham e Kent svilupparono cinque pattern per comunicare concetti a programmatori che si avvicinavano per la prima volta allo sviluppo con Smalltalk. Il loro lavoro venne presentato a OOPSLA '87 nel documento: "Using Pattern Languages for Object-Oriented Programs".

Successivamente il concetto di Pattern nel mondo dello sviluppo del software si e' consolidato e con l'uscita del lavoro della "Gang of Four" dal titolo "Design Patterns: Elements of Reusable Object-Oriented Software" il termine Patterns e' entrato ufficialmente nella letteratura della Computer Science con un proprio significato.

Cos'e' quindi un Pattern?
Dopo questa introduzione non voglio dimenticare di dare una definizione formale al Pattern:

"Un Pattern e' la descrizione chiara e formale di un problema (o una famiglia di problemi) ricorrenti, e della sua risoluzione. Questa descrizione ha lo scopo di catturare l'essenza stessa del problema all'interno di certi contesti. La comprensione di tali problemi e' necessaria per la apprezzare la soluzione proposta. Tale soluzione puo' essere non-ottimale se il problema viene estrapolato dal contesto considerato."

I problemi descritti nei Patterns sono ricorrenti, nel senso che ogni sviluppatore ha incontrato lo stesso problema nel passato e lo incontrera' nuovamente nel futuro.
E' la stessa natura "ricorrente" del problema che fa del Pattern un formidabile strumento di design e di architettura: creare un Pattern significa riutilizzare e condividere l'esperienza di qualche altro sviluppatore che ha dovuto affrontare gli stessi ostacoli logici e architetturali.
Punto fondamentale del Pattern e', quindi, la capacita' di documentare tali problemi e le relative soluzioni. Questo viene ottenuto attraverso una serie ben definita di passi che possiamo riassumere nel seguente schema:

  1. La motivazione o contesto in cui il pattern viene applicato
  2. Prerequisiti che devono essere soddisfatti per l'applicazione del pattern
  3. Una descrizione della struttura del programma che il pattern andra' a definire
  4. Una lista di partecipanti necessari alla completezza del pattern
  5. Conseguenze nell'uso del pattern sia dal punto di vista di vantaggi che svantaggi
  6. Fornire almeno un esempio nell'uso del pattern.

E' chiaro, quindi, che un pattern include una descrizione generale della descrizione di un problema ricorrente con vari vincoli ed obiettivi. In ogni caso un pattern non si limita ad identificare una soluzione, ma anche a spiegare perche' questa soluzione e' necessaria.
Ultimamente il termine "Pattern" e' un po' alla moda, e sembra che tutto debba essere legato ad essi. Questo ha generato molte delusioni in molte persone che vedevano in essi la soluzione di ogni problema ed, in qualche modo, delegittimato coloro che, nella patterns community, stanno facendo uno sforzo reale nel documentare patterns "veri".
Detto questo e' importante dire che non tutte le soluzioni, algoritmi o best practice sono descritte nei patterns. Anche se il problema che si sta studiando sembra avere tutti I requisiti per essere identificato come pattern, non dovrebbe essere considerato tale, fino a quando possa essere verificata la sua natura ricorrente.
L'azione di documentare un pattern valido puo' essere incredibilmente difficile. Un pattern per essere valido deve soddisfare queste linee guida:

  1. Risolvere un problema: Patterns identificano soluzioni, non principi astratti o strategie.
  2. E' un concetto solido: La soluzione indicata nel pattern deve essere solida e ben dimostrata: non teorie o speculazioni.
  3. La soluzione non e' ovvia: Molte tecniche di problem-solving tendono a derivare soluzioni da principi. Nei pattern la soluzione e' generata indirettamente, attraverso un approccio formale.
  4. Un Pattern descrive relazioni: Un pattern non descrive semplicemente dei moduli, quanto profonde strutture e funzionalita' di un sistema.

Ricordate inoltre che il fatto di avere una soluzione che non sia un pattern, non significa che questa sia una soluzione non valida o banale. Il fatto di avere un pattern implica una soluzione ottima, ma il contrario non e' vero, cioe' si puo' avere una soluzione ottima senza che questa sia un pattern. Quindi e' bene considerare con grande rispetto I patterns, ma non cosiderarli come una legge assoluta.
Se un pattern descrive una "Best Practice" allora un "Anti-Pattern" descrive una "Bad Practice". Gli anti-pattern proposti da Andrew Koening non saranno soggetto di questo articolo e lascio a voi ogni giudizio a riguardo.
Nella letteratura, sono stati sviluppati patterns in diversi settori. Abbiamo cosi Design Patterns, Analysis Patterns ed anche Organizational Patterns.
Probabilmente i Design Patterns sono quelli che vi sono piu' a cuore, e che vengono definiti come "la descrizione di oggetti e classi comunicanti che hanno lo scopo di risolvere generali problemi di design in un particolare contesto".
In questo tipo di patterns vengono identificate tutte le classi partecipanti, le loro istanze, i loro ruoli e la distribuzione delle loro responsabilita'. Ognuno dei pattern si concentrera' su particolari problemi di design Object-Oriented. Verra' descritto quando questo pattern viene applicato oppure quando non e' assolutamente il caso di farlo.

 

Elementi di un Pattern
Per quanto riguarda il formato utilizzato nella descrizione un pattern, potrete trovare alcune differenze tra i diversi autori. In ogni caso, c'e' un consenso comune sugli elementi che devono essere presenti nella presentazione formale di un pattern:

  • Nome: deve essere un nome che abbia senso. Questo permette agli sviluppatori di utilizzare un nome come riferimento al pattern e al concetto e struttura che esso descrive. Puo' accadere che uno spesso pattern possa essere conosciuto con nomi diversi ed in questo caso e' bene riportare anche una lista di nomi sotto cui il pattern e' conosciuto.
  • Problema: Una chiara descrizione del problema che il pattern si trova ad affrontare: gli obiettivi che si vogliono raggiungere all'interno di un particolare contesto (se presente).
  • Contesto: Le precondizioni sotto le quali il problema e la sua soluzione sembrano ricorrere, e per le quali la soluzione e' desiderabile. Il contesto puo' essere pensato come la configurazione iniziale del sistema prima dell'applicazione del pattern.
  • Vincoli: Una descrizione dei vincoli presenti nel contesto e di come questi interagiscono tra loro. I vincoli rivelano le scelte che dobbiamo considerare nello scenario che essi descrivono.
  • Soluzione: Questo spesso equivale a dare istruzioni su come ottenere il risultato finale. Nell'offrire la soluzione e' possibile utilizzare qualsiasi media, come figure e diagrammi, che identificano la struttura del pattern, gli attori e la collaborazione tra le parti, allo scopo di visualizzare come il problema e' risolto. La soluzione non dovrebbe contenere soltanto strutture statiche, ma anche comportamenti dinamici.
  • Esempi: Uno o piu' esempi devono accompagnare la descrizione del pattern. In questi esempi deve essere chiaro qualche contesto iniziale viene utilizzato, come il pattern viene utilizzato ed, eventualmente, come il contesto viene modificato dal pattern stesso. Gli esempi aiutano il lettore a comprendere, in modo profondo, l'uso del pattern e la sua applicabilita'.
  • Contesto Finale: Lo stato o configurazione del sistema dopo che il pattern e' stato applicato, includendo le conseguenze (sia positive che negative) nell'applicazione del pattern, oppure eventuali problemi che possono crearsi nel nuovo contesto.
  • Referimenti ad altri pattern: Relazioni tra il pattern che si sta descrivendo ed altri pattern utilizzati nel sistema. Se esistono relazioni tra diversi pattern e' possibile che questi condividano lo stesso gruppo di vincoli oppure il contesto di applicabilita'.
  • Usi conosciuti: descrivere sistemi che utilizzano questo pattern e come esso e' stato applicato per risolvere il problema iniziale. Questo aspetto e' molto importante perche' aiuta a dimostrare la soluzione del pattern e a provarne la sua natura ricorrente.

Anche se non obbligatorio, molti pattern iniziano con un Abstract utilizzato come un'introduzione o come sintesi del problema che ci stiamo accingendo a descrivere. Inoltre un pattern dovrebbe esplicitamente descrivere il suo audience e le conoscenze di base che il lettore deve avere.
Concludo questo articolo con la descrizione di un pattern molto semplice, ma molto importante nelle architetture di sistemi: il Singleton.

 

Singleton
Problema
Questo pattern si applica in tutte quelle situazioni in cui esiste la necessita' di avere una singola istanza di una determinata classe.
Spesso viene lasciata al programmatore la responsabilita' di assicurare l'esistenza di una sola istanza di una classe con la conseguente possibilita' di errori e bug di sistema.
Un importante aspetto di questo pattern e' il modo in cui questa singola instanza viene messa a disposizione di ogni oggetto che ne faccia richiesta. Dalla responsabilita' del programmatore si passa al comportamento di una classe: e' la classe stessa (behaviour) che garantisce l'esistenza di una singola istanza.

Classi
Questo pattern viene implementato attraverso una sola classe. Di seguito viene riportato il diagramma di come il singleton e' stato concepito:


Figura 1 - Singleton Cloud

Caratteristica principale e' l'uso di un costruttore privato (e' questo che garantisce la singola istanza) e di un metodo publico e statico getIstance(). La singola istanza viene mantenuto attraverso l'uso di una variable privata e statica istance.

Vantaggi
Assoluto controllo sull'istanza singola della classe. Quando questo pattern viene implementato come raccomandato, la class singleton controllera' direttamente la creazione delle sue istanze, attraverso il costruttore privato. Questo solleva il programmatore dalla responsabilita' di assicurare l'esistenza di una sola istanza.

Esempi
Ecco un esempio di singleton scritto in Java:

public class Singleton{
private static Singleton instance=null;

private Singleton()
{
… inizializzazioni
}

public static Singleton getInstance()
{
if (instance==null)
{
instance=new Singleton();
}
return instance;
}

… Altri metodi
}

Usi Conosciuti
Esempi d'uso di questo pattern possono essere:

  1. Connecion Pooling
  2. Generazione di SID globali
  3. DesktopView

Pattern Relativi
Instance Creation

 


Conclusioni
Come abbiamo visto I Patterns sono catalogabili per aree di interesse. Possiamo trovare patterns per sistemi real time, o come nel nostro caso, pattern applicabili allo sviluppo di applicazioni basate su tecnologia J2EE.
Conoscere I patterns significa avere una profonda conoscenza sulle problematiche legate all'architettura di sistemi e di design; conoscere I patterns significa conoscere la soluzione a problemi ricorrenti, che sicuramente incontreremo nella nostra vita professionale.
Avere un'esposizione ai pattern e' fondamentale per gli architetti di sistemi e designers e aggiungo di avere sempre un aspetto critico verso I patterns perche', come abbiamo visto, essi offrono una soluzione ottima che dipende dal contesto. Se il contesto cambia, anche la soluzione puo' cambiare, invalidando il pattern stesso.
Se questo e' il caso, invito tutti ad offrire una soluzione valida e di sottoporla alla Patterns Community come momento di accettazione formale, e dare, cosi', il vostro contributo al mondo degli sviluppatori di software e degli architetti di sistemi.


Reference
[A Pattern Language] - Oxford University Press, 1977.
[Patterns] - Richard Helm e Ralph Johnson, 1998
[Essential Concept and Terminology] - Brad Appleton, 2000
[Singleton] - Erich Gamma, 1995

Giancarlo Crocetti si e' laureato in Scienze dell'informazione all'universita' "La Sapienza" di Roma per poi conquistare il Master in Computer Science alla Rutgers University del New Jersey nel 1998. Dal 1996 vive a New York dove lavora come consulente per importanti aziende ed enti governativi come: Computer Science Corporation, United Nations, Merrill Lynch, Lockheed Martin e per il governo degli Stati Uniti.
Da piu' di quattro anni il 60% dei sistemi da lui architettati e sviluppati vengono implementati utilizzando tecnologie Java. Nel 2000 ha creato la propria azienda Nous USA inc., che offre servizi di consulenza e di training concentrate soprattutto su tecnologie Java.

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it