Vai al contenuto

Design pattern

Da Wikipedia, l'enciclopedia libera.
Image Disambiguazione – "Design patterns" rimanda qui. Se stai cercando il libro, vedi Design Patterns (saggio).
Image
Un diagramma UML che descrive l'Abstract Factory pattern

Nell'ingegneria del software, un design pattern (o schema di progettazione) è una soluzione progettuale di carattere generale e riutilizzabile a un problema ricorrente che si presenta comunemente durante le fasi di progettazione e sviluppo del software.

Da un punto di vista pratico un design pattern può essere espresso sotto forma di modello logico o insieme di linee guida che possono essere adattati a diversi contesti, piattaforme e linguaggi di programmazione. Essi sono cristallizzazioni dell'esperienza dei progettisti, e rappresentano buone pratiche che facilitano la definizione dell'architettura software e offrono un vocabolario comune tra sviluppatori. Sebbene nel paradigma orientato agli oggetti mostrino tipicamente le relazioni e le interazioni tra componenti senza specificarne i dettagli finali, la loro applicazione può variare o risultare superflua a seconda delle caratteristiche o del supporto nativo del linguaggio utilizzato. Negli ultimi decenni, l'efficacia di questo modello di risoluzione ne ha esteso l'adozione anche ad altri ambiti, come l'interazione uomo-macchina, il web design e l'apprendimento online.

Il concetto di design pattern nasce originariamente in ambito architettonico per iniziativa dell'architetto Christopher Alexander. Un primo approccio a questo tema viene presentato da Alexander già nel 1964 all'interno del saggio "Notes on the synthesis of form", seguito nel settembre del 1966 dall'articolo "The Pattern of Streets", pubblicato sul Journal of the AIP.[1][2]

Tra il 1977 e il 1979, richiamandosi alla tradizione classica di Vitruvio, Alexander raccoglie e formalizza una collezione di pattern di progettazione, culminata nelle pubblicazioni "A Pattern Language" (1977) e "The Timeless Way of Building" (1979). Nelle parole dello stesso autore, «ogni pattern descrive un problema che si presenta innumerevoli volte nel nostro ambiente, così come la sua soluzione, in modo tale che possiamo utilizzare questa soluzione un milione di volte in futuro senza doverla ripensare da capo».[3][4]

I pattern proposti spaziavano dalla pianificazione urbanistica delle città fino al corretto posizionamento dei pomelli delle porte. L'obiettivo primario di Alexander era quello di coinvolgere direttamente gli abitanti nel processo di progettazione, cercando di recuperare una connessione con il concetto di qualità tipico dell'architettura antica, andato in parte perduto con la rottura operata dalla modernità. Nonostante il valore teorico della proposta, nel settore dell'architettura questa idea non ha riscontrato una diffusione paragonabile a quella che avrebbe successivamente ottenuto in campo informatico.[3][4]

Il trasferimento del concetto di pattern al mondo della programmazione si deve a Kent Beck e Ward Cunningham. Nel 1987, spinti dalla necessità di formare i programmatori ancora poco esperti nei concetti di ereditarietà e polimorfismo, i due individuarono un parallelismo tra la "buona architettura" descritta da Alexander e una progettazione orientata agli oggetti (OO). Sulla base di queste intuizioni, svilupparono cinque pattern per la creazione di interfacce grafiche (HCI) in Smalltalk e presentarono i loro risultati alla conferenza OOPSLA dello stesso anno con l'articolo "Using Pattern Languages for OO Programs".[5]

L'interesse attorno a questa metodologia crebbe rapidamente. Nel 1988, Erich Gamma avviò un dottorato di ricerca presso l'Università di Zurigo incentrato proprio sull'applicazione di questo approccio allo sviluppo del software generale.[senza fonte] Negli stessi anni, tra il 1989 e il 1991, James Coplien lavorò su costrutti simili a pattern per il linguaggio C++, pubblicando nel 1991 il testo "Advanced C++ Idioms".[6] Nello stesso anno, Gamma completò il proprio dottorato per poi trasferirsi negli Stati Uniti.[senza fonte]

Sebbene l'applicazione pratica dei design pattern fosse in corso già da tempo, la loro formalizzazione definitiva giunse a metà degli anni '90. Nel 1994 (con alcune edizioni e traduzioni pubblicate nel 1995), Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides pubblicarono il celebre testo "Design Patterns: Elements of Reusable Object-Oriented Software".[7] Il volume descriveva nel dettaglio 23 design pattern. A differenza dei modelli originari di Alexander, pensati soprattutto per i non addetti ai lavori, i pattern descritti nel libro si rivolgevano esplicitamente agli sviluppatori software. Grazie alla risonanza di quest'opera, i quattro autori vennero indicati collettivamente dalla comunità scientifica con il soprannome di "Gang of Four" (abbreviato in GoF), un acronimo spesso utilizzato per identificare anche lo stesso libro.[8]

Il 1994 segnò inoltre lo svolgimento della prima conferenza "Pattern Languages of Programming", mentre l'anno successivo nacque il "Portland Pattern Repository", istituito con lo scopo di documentare in modo continuo i design pattern emergenti.

Oggi, l'espressione "design pattern" viene impiegata quasi esclusivamente in riferimento all'ingegneria del software, dove rappresenta una delle principali linee di sviluppo metodologico. I pattern trovano applicazione in molteplici ambiti industriali, come lo sviluppo basato su componenti, la progettazione di sistemi aperti e la creazione di framework. L'influenza di questo approccio è tale che la maggior parte dei linguaggi di programmazione moderni e delle tecnologie correlate è stata concepita o modificata con l'intento di supportare in modo coerente i principi emersi da questo movimento.

In astratto un design pattern è costituito da pochi elementi fondamentali, quali:

  • il nome: costituito da una o due parole che siano il più possibile rappresentative del pattern stesso;
  • la descrizione del problema: ovvero la descrizione della situazione alla quale si può applicare il pattern. Può comprendere la descrizione di classi o di problemi di progettazione specifici, come anche una lista di condizioni perché sia necessario l'utilizzo del pattern;
  • la descrizione della soluzione: ovvero una disamina degli elementi costitutivi della soluzione, delle relative relazioni interne e implicazioni, senza però addentrarsi in una specifica implementazione;
  • la descrizione di eventuali corollari: ovvero degli effetti secondari dell'applicazione del pattern. Essi possono comprendere considerazioni in materia di prestazioni nel tempo e nello spazio, implicazioni specifiche a determinati ambienti di programmazione, e l'impatto con il resto del progetto.

Vantaggi principali

[modifica | modifica wikitesto]

I principali vantaggi nell'uso dei design pattern sono qui delineati.

  • Aiutano a identificare e prevenire bug o criticità, riducendo il rischio di complicazioni future.
  • Accelerano il processo di programmazione fornendo paradigmi già testati, evitando di dover ricercare soluzioni a problemi già noti e risolti in passato.
  • Formalizzano un linguaggio condiviso tra architetti del software e programmatori. Fare riferimento a un pattern specifico infatti evita di dover scendere in lunghe spiegazioni.
  • Standardizzano l'approccio alla progettazione e migliorano notevolmente la leggibilità e la comprensibilità del codice per chiunque abbia familiarità con i pattern utilizzati.
  • Facilitano l'apprendimento e la crescita professionale dei progettisti meno esperti, condensando l'esperienza accumulata nel tempo dalla comunità di sviluppo in un formato accessibile e strutturato.

Classificazione

[modifica | modifica wikitesto]

I design pattern possono essere classificati con diversi criteri, i più comuni dei quali sono quelli che evidenziano il tipo di problema che si cerca di risolvere. Il tipo di problema può essere legato ad uno specifico dominio progettuale (telecomunicazioni, reti, software) oppure, più comunemente, al problema progettuale in senso più ampio (nell'ingegneria del software, ad esempio, si può parlare di creazione, comportamento, navigazione di oggetti o strutture dati).

Nel suo libro la GoF identificò 23 tipi di design pattern, suddivisi in tre categorie: strutturali, creazionali e comportamentali.[8]

Pattern creazionali

[modifica | modifica wikitesto]

I pattern creazionali risolvono problematiche inerenti alla creazione degli oggetti

  • Abstract factory – fornisce un'interfaccia per creare famiglie di oggetti connessi o dipendenti tra loro, in modo che non ci sia necessità da parte degli utilizzatori di specificare i nomi delle classi concrete all'interno del proprio codice
  • Builder – separa la costruzione di un oggetto complesso dalla sua rappresentazione, in modo che il processo di costruzione stesso possa creare diverse rappresentazioni
  • Factory method – fornisce un'interfaccia per creare un oggetto, ma lascia che le sottoclassi decidano quale oggetto istanziare
  • Lazy initialization – permette di ritardare la creazione di un oggetto al momento precedente al primo utilizzo
  • Prototype – permette di creare nuovi oggetti clonando un oggetto iniziale, o prototipo
  • Singleton – ha lo scopo di assicurare che di una classe possa essere creata una sola istanza in sistemi con un unico thread
  • Double-checked locking – ha lo scopo di assicurare che di una classe possa essere creata una sola istanza in sistemi multithread

Pattern strutturali

[modifica | modifica wikitesto]

I pattern strutturali risolvono problematiche inerenti alla struttura delle classi e degli oggetti.

  • Adapter – converte l'interfaccia di una classe in una interfaccia diversa
  • Bridge ("ponte") permette di separare l'astrazione di una classe dalla sua implementazione, per permettere loro di variare indipendentemente
  • Composite – organizza gli oggetti in una struttura ad albero, dando la possibilità all'utilizzatore di manipolare gli oggetti in modo uniforme
  • container – offre una soluzione alla rottura dell'incapsulamento per via dell'uso dell'ereditarietà
  • decorator – consente di aggiungere metodi a classi esistenti a tempo di esecuzione
  • Extensibility
  • Façade – implementa un'interfaccia semplificata per un sistema complesso
  • Flyweight – permette di separare la parte variabile di una classe dalla parte che può essere riutilizzata
  • Proxy – media l'accesso ad un oggetto, applicando logiche personalizzate
  • Pipe and filter – permette di definire un sistema in termini di filtri (trasformazioni) e flussi dati tra essi
  • Private class data

Pattern comportamentali

[modifica | modifica wikitesto]

I pattern comportamentali forniscono soluzioni ai più comuni problemi di interazione tra oggetti.

  • Chain of responsibility – rende meno stringente l'accoppiamento fra l'entità che effettua una richiesta e quella che la soddisfa, dando a più entità la possibilità di soddisfarla
  • Command – permette di isolare la porzione di codice che effettua un'azione dal codice che ne richiede l'esecuzione.
  • Event listener – permette a un'entità di reagire ad eventi
  • Hierarchical visitor
  • Interpreter – dato un linguaggio, definisce una rappresentazione della sua grammatica insieme ad un interprete per essa
  • Iterator – permette la navigazione e l'accesso agli elementi di una struttura dati celandone i dettagli implementativi
  • Mediator – media le comunicazioni tra entità di un sistema, allo scopo di aggiornare lo stato globale del sistema quando una sua parte notifica un cambiamento di stato
  • Memento – permette di memorizzare una copia dello stato interno di un oggetto, senza violare il principio di incapsulamento, per poterlo ripristinare in un momento successivo.
  • Observer – permette di monitorare lo stato di uno o più entità e di notificarne i cambiamenti ad altrettante entità
  • Single-serving visitor
  • State – permette ad un oggetto di cambiare il comportamento in funzione di un suo stato interno
  • strategy – permette all'utilizzatore di un oggetto di selezionare dinamicamente l'algoritmo da usare internamente per la risoluzione di un problema
  • Template method – permette di definire la struttura di un algoritmo incapsulato in una classe delegando la definizione di alcuni aspetti alle relative sottoclassi.
  • Visitor – permette di separare un algoritmo dalla definizione della struttura dati a cui è applicato
  • Null object – permette di sostituire un riferimento nullo con un oggetto che non fa nulla

Pattern architetturali

[modifica | modifica wikitesto]

I pattern architetturali operano ad un livello diverso (e più ampio) rispetto ai design pattern, ed esprimono schemi di base per impostare l'organizzazione strutturale di un sistema software. In questi schemi si descrivono sottosistemi predefiniti insieme con i ruoli che essi assumono e le relazioni reciproche.

Pattern di metodologia

[modifica | modifica wikitesto]

Pattern di concorrenza

[modifica | modifica wikitesto]

Nel caso di processi che eseguono contemporaneamente delle attività su dati condivisi si parla di concorrenza. Alcuni design pattern sono stati sviluppati per mantenere sincronizzato lo stato dei dati in tali situazioni:

  1. Alexander 1964.
  2. Alexander 1966.
  3. 1 2 Alexander 1977.
  4. 1 2 Alexander 1979.
  5. Beck Cunningham 1987.
  6. Coplien 1991.
  7. tradotto in italiano come "Design Patterns: Elementi per il riuso di software ad oggetti"
  8. 1 2 GoF 1995.

Voci correlate

[modifica | modifica wikitesto]

Altri progetti

[modifica | modifica wikitesto]

Collegamenti esterni

[modifica | modifica wikitesto]
Controllo di autoritàLCCN (EN) sh98003823 · GND (DE) 4546895-3 · BNE (ES) XX550686 (data) · J9U (EN, HE) 987007532683705171
  Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica