MokaByte Numero 24  -  Novembre 98
La qualità senza nome
di 
Graziano Lo Russo
In questo numero vediamo  cosa rende un pattern un buon pattern, e del riuso del software

 



 
 


Nella scorsa puntata abbiamo visto come i pattern siano "una soluzione a un problema in un contesto". Ma ogni pattern è un buon pattern? No, certo. Un buon pattern deve risolvere il problema più importante di un contesto. Quale è il problema più importante del software? Il riuso. Quindi il requisito fondamentale a cui deve rispondere un pattern è: produrre codice riusabile.



 
 

Sui Pattern

Abbiamo detto che un pattern è una soluzione assodata a un problema in un contesto. Ciò vuol dire che i pattern limitano la creatività individuale? Affatto! Dice Alexander:

"Un pattern è allo stesso tempo una cosa che accade nel mondo, la regola che ci dice come creare quella cosa, quando crearla. È insieme un processo e una cosa; insieme la descrizione di una cosa che è viva e la descrizione del processo che genera quella cosa". Questa frase esprime pienamente l’aspetto dinamico, generativo dei pattern.

"Ci saranno sempre variazioni e unicità nel modo in cui un pattern manifesta se stesso [sottolineato nell’originale]. Ogni pattern è una soluzione generica a un qualche sistema di forze nel mondo. Ma le forze non sono mai le stesse. Siccome l’esatta configurazione dei dintorni in un certo posto e in un certo momento è sempre unica, la configurazione delle forze cui è sottoposto il sistema è anche unica... ne segue che anche il sistema deve essere unico; non può essere esattamente uguale a nessun altro, anche se è approssimativamente simile. Questa non è una conseguenza accidentale: è un aspetto essenziale della vita e dell’essere ogni parte in rapporto con il tutto (wholeness)" [Alex79, p. 147].

La qualità senza nome

Prosegue Alexander: "In breve, c’è una caratteristica nelle cose naturali che è creata dal fatto che sono riconciliate con le loro forze interne". Più avanti Alexander la chiama "qualità senza nome" (the quality without a name), per sottolineare che la si può vivere (come nel concetto tedesco di erlebniss), ma non la si può definire. La qualità senza nome è quella qualità "negli edifici e nelle città che non può essere fatta, ma solo generata, indirettamente, dalle ordinarie azioni delle persone, come un fiore non può essere fatto, ma solo generato dal seme". La qualità senza nome è insieme brutale utilitarismo, piacevolezza, robustezza al cambiamento e olismo (integrazione della parte nel tutto). Ma, come nota Alexander, che ogni tentativo di definire o misurare la Qualità è futile, perché "le parole confondono più di quanto spieghino".
L’accenno al seme ricorda due cose: una buona architettura non nasce già fatta, ma è frutto del lento adattamento di un’idea embrionale al contesto e ai suoi problemi; inoltre, una buona architettura ha la "qualità della natura", è una "cosa viva", cresce quasi da sola. Uno dei segni più indicativi del fatto che si è trovata l’architettura giusta per un problema è quando l’architettura stessa suggerisce le soluzioni ai problemi prima ancora che si presentino. Come dice Coplien [Cope97], "un buon progetto anticipa ciò che cambierà e ciò che resterà lo stesso nel tempo". 
Un pattern non è solo la descrizione di una soluzione ricorrente. "I pattern nel mondo meramente esistono. Ma gli stessi pattern nella nostra mente sono dinamici. Hanno forza. Sono generativi. Ci dicono che cosa fare; ci dicono come potremmo, o dovremmo, generarli; ci dicono anche che, in determinate circostanze, dobbiamo crearli" [Cope96]. 
Dire che un pattern è composto da un contesto, un problema e una soluzione non dice solo che si può usare quel pattern come soluzione a un problema. Dice anche che è desiderabile farlo [Alex79, pag. 183]: il pattern dice che in quel contesto è naturale che si presenti un certo problema. Anche per questo un buon pattern genera le soluzioni ai problemi che si presentano. 
Se voglio sapere quali sono i problemi tipici nel progetto di software real-time il testo migliore è un libro di pattern per real-time; un libro sul real-time non impostato a pattern fornirà una libreria di astute ottimizzazioni e sapienti tecniche di sincronizzazione, lasciando nell’imbarazzo di capire cosa convenga usare per questo specifico problema (per inciso: un libro può essere impostato a pattern anche senza dirlo esplicitamente, e un libro non è ottimo solo perché nel titolo c’è scritto "Pattern").
Se non si può definire la qualità senza nome, si può almeno capire che domande porsi, che cammino seguire per perseguirla? Sì, si può. Un pattern è la soluzione di un problema. Per definire un pattern bisogna sapere quale è il problema, il vero problema. 
Poiché i pattern sono soluzioni a problemi ricorrenti, dobbiamo domandarci quale siano i veri problemi ricorrenti del software.

Pattern e riuso

Quali sono i problemi più ricorrenti del software? Il problema più lamentato da chi scrive il software è che ne scrive troppo. Fine ultimo del programmatore è di scrivere meno software. Non tutti sono d’accordo con questa definizione; chi vi propone un tool mirabolante che "aumenta la produttività" evidentemente la pensa diversamente.  Scherzi a parte (ma non troppo: si legga il gustoso saggio di Tom De Marco Why Does Software Cost So Much [Dorset House 1995]), esistono e quali sono i veri problemi nella produzione del software?
Frederick Brooks, l’architetto di sistema di OS/360, ha affermato in un articolo memorabile [Brooks87] che il software differisce per aspetti essenziali (ineliminabili) da altri prodotti manifatturieri. Uno degli aspetti essenziali è la complessità; i programmi software sono quanto di più complesso sia mai stato costruito dall’uomo. Neanche le CPU sono così complesse. Per questo ci sono programmi che progettano CPU, ma non programmi che progettano altri programmi (di dimensioni realistiche). Un altro aspetto essenziale è che il software è sottoposto in continuazione a cambiamenti dopo che è già stato consegnato, anzi più un software ha successo più sarà sottoposto a cambiamenti; pensate a quanto diversa è la situazione nella produzione di autovetture, dove una vettura di successo come la vecchia 500 o il Maggiolino può restare in produzione senza troppe variazioni per decine di anni. 
La vita del software è molto più simile alla vita di un edificio o di una città, solo con ritmi più rapidi, che alla vita di un’automobile: anche una città o un edificio hanno una vita e, a meno che li si imbalsami in un monumento, saranno diversi quando termineranno da come erano al momento della loro costruzione. 
Non è un caso se le idee dei pattern sono nate per prime nella mente di un architetto. Prendiamo un libro di Object Oriented Design pre-pattern (Booch, Jacobson, Coad, Rumbaugh, fate voi): troveremo scritto che scopo del design è "trasformare i concetti dell’analisi in modo che siano implementabili". Se l’analisi è ad oggetti e il linguaggio di programmazione è ad oggetti, non c’è poi molto da trasformare: avanzano sì e no le relazioni, che più o meno tutti implementano con puntatori. Tutto lì? Ah no: fa parte del design anche occuparsi della persistenza, del multitasking (se c’è) e del disegno dell’interfaccia utente. 
Non c’è da stupirsi se, con queste premesse, le discussioni sul design si ingolfano sul formalismo dei diagrammi di classi, o se qualcuno a buon diritto non presenta un CASE tool che deriva automaticamente il codice dai diagrammi dell’analisi, in barba a qualunque sforzo di Design, salvo l’interfaccia utente che si disegna con pochi colpi di mouse. Devo ancora trovare un CASE tool che sia stato costruito lui stesso in questo modo. Il riuso? Sì, di quello qualcuno fra i metodologi ne parla, per dire che è una cosa difficile da ottenere, che ci riesce solo gente molto brava e impiegando tanto tempo in più che per fare codice non riusabile: ma che cosa mai facciano i guru del riuso in tutto questo tempo in più non si sa bene, i guru delle metodologie non lo dicono. 
Un merito del movimento dei Pattern è di avere richiamato all’attenzione che i problemi veri di Design non sono come implementare le associazioni o la persistenza in C++, o se rappresentare le classi usando scatole, nuvolette o esagoni, ma come scrivere codice facile da estendere e contrarre. La domanda cruciale del design è quindi: "che cosa cambia se questo cambia?". I pattern di design sono risposte a questa domanda. Costruire un sistema software attorno alle risposte a questa domanda ha due benefici: manutenzione più facile e componenti più facili da riusare. Questa non è un’invenzione dei Pattern, anzi ne parlava già Parnas più di 15 anni fa [Parnas79], ma fino a tempi recenti i principi sull’information hiding di Parnas erano rimasti pressoché lettera morta [McConnell96]: quegli stessi principi, rivisitati a oggetti e concretizzati, sono ora espressi come pattern. Per esempio, [GoF] espone diversi modi di disaccoppiare la creazione di un oggetto dal suo uso (pattern creazionali), oppure diversi modi di disaccoppiare l’interfaccia di un oggetto dalla sua implementazione (pattern di comportamento), o ancora modi di disaccoppiare il comportamento di un oggetto dalla sua struttura (pattern strutturali). I pattern sono riuso visto dalla parte dell’implementatore. 
Il riuso di cui parlano i pattern non è l’assemblaggio di parti software prefabbricate, ma l’adattamento intelligente di una parte al tutto.

"Ciascun pattern descrive un problema ricorrente e la sua soluzione, in un modo tale che potrà riusare questa soluzione un milione di volte, senza mai farlo allo stesso modo due volte" dice Alexander.

I pattern rispondono anche al problema della manutenzione del software, che assorbe in media la maggior parte del costo globale del software, cioè di adattare un’implementazione al cambiamento delle specifiche e al conseguente cambiamento delle interfacce (riuso dell’implementazione). 
Distinguere l’interfaccia dall’implementazione per cambiare l’implementazione mantenendo fissa l’interfaccia (riuso dell’interfaccia), o costruire il software tramite composizione di mattoncini modulari come nel Lego, senza mai doverci mettere le mani dentro, in sostanza disinteressarsi dell’implementazione per curare solo l’interfaccia, non è nello stile dei pattern: come dice Coplien in WhyPatternsAreDifferent, "quando la tecnologia o la comprensione maturano al punto che possiamo catturare formalmente un’idea, essa cessa di avere la qualità generativa, letteraria che distingue i pattern da altri metodi". 
Un pattern è un modo di trovare una soluzione con caratteristiche di adattabilità e generatività che una libreria non può dare. Naturalmente ci sono dei campi, come la costruzione di GUI, in cui i pattern non sono più necessari e si può ricorrere a un Wizard: ma, come ci ricorda Dino Esposito [Esposito96], un conto è fare 100 programmi di 1000 righe, un conto è farne uno da 100,000 righe.

I pattern e la qualità del software

Abbiamo detto che il problema principale del software è il riuso. Quale è la qualità senza nome delle soluzioni a questo problema?

Risponde Gabriel: "Credo che sia il codice stesso. Molti parlano dei benefici di avere eccellenti interfacce e del beneficio di separare l’interfaccia dall’implementazione in modo che l’implementazione possa variare. Ma pochi parlano seriamente della qualità del codice stesso. Molti teorici lo lasciano nella categoria delle cose di cui è meglio non discutere, qualcosa che deve essere nascosto dalla vista così che possa essere cambiato in privato. Ma Alexander dice che la qualità viene in parti uguali dall’artista e dal costruttore che con le sue mani plasma la geometria che dà all’edificio la sua qualità e il suo carattere. E il costruttore del software non è il programmatore?".

I programmatori sono visti in molte organizzazioni come il più basso livello di manovalanza nella "fabbrica software", secondo un modello tayloriano della fabbrica che è già datato persino nelle fabbriche vere. È vero che la programmazione incide solo per il 10-15% sul costo di produzione del software. Ma la produzione è solo il 30% del costo complessivo del software: il restante 70% è manutenzione, che è principalmente riprogrammazione del software e dipende in modo determinante dalla leggibilità del codice già fatto. 
Avere finalmente riconosciuto ed esaltato l’importanza della qualità della codifica nella qualità del software è ciò che ha reso i pattern popolari anche nella comunità dei programmatori, generalmente scettici sui discorsi teorici; Coplien si spinge a consigliare il pattern ArchitectAlsoImplements nel ciclo di produzione del software. Va da sé che nell’ottica dei pattern non basta che "il software funzioni", cioè che implementi correttamente la specifica e sia conformante alle interfacce, perché sia considerato valido.
Qualsiasi programma può essere fatto funzionare da chi l’ha scritto, sappia il suo mestiere e abbia una buona provvista di caffè. Anche i programmi WORN (Write Once, Read Never), cioè gli usa-e-getta funzionano, ci vuole pochissimo a scriverli e magari funzionano pure così bene che non li gettiamo più via. In certi contesti va benissimo così. Io ne ho scritti tanti. Il problema è cosa succederà se lo stesso programma dovrà essere modificato da qualcun altro, o magari dallo stesso che l’ha scritto ma a distanza di tempo. Io ho tanti nemici fra quelli cui è capitato di mantenere i miei WORN. Nota per chi non avesse mai sentito l’acronimo WORN, arcaismo dei tempi dei linguaggi di shell Unix: sostituite WORN con RAD, o con Wizard-generated, e rileggete. 
Vedrete che non cambia niente.

Framework

L’approccio tradizionale all’architettura del software è di vedere il tutto come la somma della parti (componentware): il software come una specie di Lego.  Ma "è impossibile formare qualcosa che abbia il carattere della natura sommando parti preformate. Quando le parti sono modulari e sono fatte prima del tutto, per definizione sono identiche, ed è impossibile per ogni parte essere unica e in accordo alla sua posizione con il tutto" [Alex79, pag. 368]. 
Il primo approccio al riuso del software sono state le librerie, librerie di funzioni o librerie di classi o di "componenti".  Come nota Booch, "le librerie sono una cosa strana: tutti vogliono aggiungerci qualcosa e nessuno ne vuole prendere niente".  Quel che è peggio, più una libreria è orientata al riuso più chiede di buttare via tutto il resto perché non è abbastanza orientato al riuso. Più fornisce componenti riusabili più è incompatibile con le componenti riusabili di altre librerie. Certe volte, le librerie di componenti riusabili hanno persino la biasimevole proprietà di tendere ad alzare il costo del software e a diminuire la qualità complessiva.
Perché? Se un modulo costa M lire e viene riusato N volte, si risparmiano M(N-1) lire.
Va bene? Niente affatto: primo, il risparmio è direttamente proporzionale al costo iniziale, per cui i moduli riusabili tendono a diventare spaventosamente grossi e cari per aumentare il risparmio; spesso, un modulo per essere riusabile in N posti diversi diventa oltremodo "flessibile" (cioè grosso e lento), quindi caro, il che contribuisce ad aumentare il risparmio complessivo. 
Secondo, era veramente necessario riusare N volte quel modulo?  Ciò ha veramente contribuito a migliorare il sistema software complessivo? Fantasie? Conosco fior di progetti dal costo astronomico e con prestazioni deludenti perché qualcuno aveva deciso di risparmiare riusando dappertutto un certo modulo dal costo spropositato (più il costo è astronomico più si cerca di riusarlo per aumentare il risparmio!) e, tutto sommato, inappropriato in ognuno dei posti in cui era stato inserito.

I framework cercano di superare i limiti dell’approccio a librerie componenti ponendo l’accento sul tutto (il framework) piuttosto che sulle parti.

Un framework è un insieme di classi che collaborano per fornire servizi al cliente di un’applicazione; il meccanismo di invocazione fra framework e classi è ribaltato rispetto a una normale libreria di classi: è il framework che chiama l’applicazione attraverso qualche meccanismo di callback, non viceversa.  Un framework è prima di tutto un’architettura applicativa piuttosto che un’architettura di componenti. Il principio ispiratore del progetto di un framework è (o dovrebbe essere) il "Principio di Hollywood" ("don’t call us, we’ll call you").  Il framework provvede il "main", l’applicazione i "dettagli" dei metodi.  Si potrebbe parafrasare un framework dicendo "non chiederti cosa fa il framework per te: chiediti cosa devi fare tu per il framework". In pratica le cose non sono mai così semplici perché qualunque framework include anche qualche routine di libreria, il che fa sentire qualcuno autorizzato a chiamare framework qualsiasi pacchetto software ci sia da vendere. 
I framework possono usare i pattern per disaccoppiare l’applicazione dal framework, ma non sono essi stessi pattern né linguaggi di pattern. Un framework è una specifica realizzazione di uno o più pattern in un contesto ben delimitato. Un pattern è una cosa logica; un framework è una cosa fisica. Un pattern è riusabile perché lo si può applicare a problemi diversi per generare ogni volta la soluzione. Un framework è riusabile perché incorpora tecniche specifiche (a loro volta pattern) per rendersi flessibile e disaccoppiato dall’applicazione.

Attualmente molti progetti cercano di costruire framework in nome del riuso. I framework e le componenti che ne derivano sembrano attraenti dall’esterno, e rispecchiano le note proprietà di astrazione e la separazione di interfaccia da implementazione. Ma molti di questi framework risultano essere al 90% librerie di soluzioni specifiche, con solo un 10% di parti comuni. "Il diavolo sta in quel 10%" dice [Cope97]: proprio la struttura interna spesso si rivela il punto debole e deve essere rifatta per ottenere flessibilità, efficienza o affidabilità. In questi casi il sedicente "framework" ha piuttosto l’aspetto di un "patchwork" e non ispira affatto la "qualità senza nome".

La struttura di un buon framework deve catturare la struttura del problema; esemplari sono i pattern di sistema studiati da [Buschmann96].

Un problema non trascurabile dei pattern è che il principio di Hollywood è tanto bello e tanto in ma ha un piccolo inconveniente: per documentare un framework non serve a niente dire cosa fa il framework per l’applicazione, bisogna dire che cosa il framework si aspetta che l’applicazione faccia per lui. Documentare in modo tradizionale una cosa di questo genere è praticamente impossibile. 
Basti pensare che tutti i metodi di Object Oriented Analisys e Design suppongono che l’applicazione possa liberamente definire il main del flusso di controllo e le radici delle gerarchie di classi; sono palesemente inadeguati a descrivere un’applicazione fatta solo di callback e di classi derivate. 
La soluzione "a pattern" consiste in primo luogo nel rendere espliciti i pattern su cui si basa il framework, in secondo luogo nel descrivere come scrivere l’applicazione che fa uso di un framework piuttosto che descrivere il framework stesso. Infatti la parte più importante della documentazione di una libreria è il Reference Manual, mentre la parte più importante della documentazione di un framework è lo User Manual. I pattern sono particolarmente efficaci nel descrivere i framework [Johnson92], perché evidenziano come usare il software anziché il software stesso. Descrivere il software serve a implementarlo, non a usarlo. Descrivere come usare un framework è descrivere come costruire l’applicazione (che non c’è ancora) in modo che si possa inserire nel framework. 
Prendiamo ad esempio il JDK di Java: la documentazione delle routine che ci sono nel JDK, per quanto sia eccellente e ben presentata, è meno importante della documentazione sulle routine che il JDK si aspetta che siano fornite dall’applicazione (le interfacce astratte), e questo a sua volta è meno importante che capire come avverrà l’interazione fra delle routine dell’applicazione fra di loro e quelle di AWT. Sapere che la gestione degli stream in Java avviene secondo il pattern Chain Of Responsibility, o che l’AWT nel JDK 1.1 usa il pattern dell’Observer è molto più importante per il progettista che ricordarsi a memoria le interfacce.

L’approccio formale ai pattern

L’approccio di Alexander e di Coplien, che sottolinea l’aspetto generativo dei pattern e l’organizzazione dei pattern in linguaggi, non è l’unico. Lo stesso Vlissides, che fa parte della Gang of Four e che condivide con Coplien l’incarico di chairman dei PLoP, si è occupato attivamente di formalizzazione e generazione automatica di codice a partire dai pattern [Budinsky96]. Coplien ha replicato sul C++ Report [Cope96] che un pattern destinato a generare codice non è più un pattern, e che comunque la scrittura del codice non impegna più del 5-10% del costo di sviluppo di un software. Però ha sottolineato che un pattern di oggi può diventare il codice generato automaticamente di domani. Personalmente ho visto il lavoro di Vlissides e non mi sembra che la sua notazione sia un passo avanti nella leggibilità del Design, anche se posso ammettere che un tool lo trovi molto significativo. Come notato da Doug Lea [Lea95], è una buona idea sviluppare formalismi per catturare meglio la descrizione di microarchitetture e idiomi ed è anche una buona idea costruire tool per facilitare l’uso dei pattern. Ma rappresentare un progetto con qualche formalismo o tool non è lo stesso che scrivere un pattern. Un pattern deve essere utile alla gente: deve descrivere quando è applicabile, che problemi risolve e quanto bene li risolve, quali altri genera, come si correla ad altri pattern. Le categorie di pattern private del contesto sono tanto utili quanto elencare i 17 modi diversi di implementare un iteratore: meglio di niente, certo, ma poco utilizzabile. Un pattern deve stimolare la riflessione e aiutare a migliorare la consapevolezza del problema che il software è chiamato a rispondere. Né una notazione formale, né tool di catalogazione o di generazione automatica possono dare questi aiuti. La dualità fra chi sottolinea quanto i pattern e i linguaggi di pattern siano generativi, e chi sottolinea quanto i pattern e i cataloghi di pattern siano riusabili, è vecchia come il movimento dei pattern. Il primo articolo di Coplien sui pattern aveva il sottotitolo "a generative pattern"; il primo articolo di Kent Beck affermava "patterns are a way of developing and packaging reusable software". La comunità dei pattern si distingue per tolleranza e pluralità di opinioni.

Non per niente KindsOfPatterns è un (meta)pattern sul Wiki Wiki WEB (c2.com): ogni modo di intendere i pattern non è altro che una fra le soluzioni possibili a un problema in un contesto.

Altri pattern

Una categorizzazione utile, anche se un po’ forzata, è basata sulla granularità dei pattern: ci sono pattern di codifica, di design, di analisi e di architettura. I pattern di design sono storicamente quelli più sviluppati e famosi: il [GoF] è il capostipite indiscusso dei pattern di design. I pattern di design studiano le relazioni fra i componenti elementari dell’OOD: oggetti, interfacce, implementazioni. Alcuni tipici pattern di design sono Proxy, Visitor, Iterator e Observer.  In generale i pattern di design sono indipendenti sia dalla semantica dell’applicazione che dal linguaggio di programmazione, anche se il linguaggio condiziona la forma della soluzione, perché ogni linguaggio ha i suoi pattern e i suoi idiomi. 
I pattern di codifica sono pattern specifici di un linguaggio di programmazione. Essi insegnano come usare gli elementi del linguaggio per risolvere un problema di implementazione. 
I pattern di design si collegano in modo naturale con i pattern di codifica: in C++, il Proxy si implementa bene usando gli smart pointer, il Visitor con il polimorfismo; il pattern di codifica del counted pointer implementa alcuni tipi di pattern di Life Cycle. Coplien con [Cope94b], Scott Meyers e Andrew Koenig sono i punti di riferimento per i pattern di codifica in C++. 
I pattern di codifica non sono la stessa cosa che gli idiomi. Un pattern di codifica dice quando usare un idioma, non solo come funziona; un idioma è orientato alla soluzione, un pattern di codifica al problema. Parte della confusione nasce dal fatto che il punto di riferimento per i pattern di codifica in C++ è il libro di Coplien intitolato "Advanced C++ Idioms", perché era stato pubblicato quando i pattern non erano ancora cultura comune. È comunque evidente che i pattern di codifica parlano degli stessi pezzi di codice che siamo abituati a conoscere come idiomi di programmazione: cambia solo la prospettiva. 
I pattern di analisi [Coad95] insegnano a usare la notazione dell’OOA per modellare un dominio applicativo: per esempio, come trovare le relazioni e le collaborazioni fra gli oggetti. Riconoscere le strutture ricorrenti di oggetti è più importante in fase di analisi che non trovare gli oggetti stessi, con i loro attributi e relazioni. 
Un esempio è: quando compare un insieme di istanze di oggetti della stessa classe, inserire sempre una classe che li contenga e li gestisca (ContainerAsManager). In un primo momento magari il contenitore sembra inutile, non si sa quale semantica assegnargli né quali operazioni abbia, le operazioni "vere" le hanno gli oggetti contenuti. 
Eppure, tutte le volte che lo ho usato, ho scoperto che più avanti nel design emergevano delle funzionalità che si applicavano naturalmente al contenitore, anzi spesso era la stessa presenza di un contenitore a suggerirle. Questo esempio mostra anche il carattere anticipatorio e generativo dei pattern. I pattern di architettura [Buschmann96] si occupano dei pattern che danno forma a un intero sistema software. 
Un pattern di architettura non è riducibile a un’architettura né a un framework, sebbene per brevità si usi il nome dell’architettura anche per indicare il pattern corrispondente (p.e. [Buschmann96] parla di pattern Broker, pattern MVC eccetera): il pattern dice come costruire un’architettura per risolvere un dato problema in un contesto. 
Un framework e un’architettura sono concetti statici, punti di partenza; un pattern è dinamico, è generativo. 
Ogni pattern di architettura comprende anche un linguaggio di pattern; per esempio MVC (Model View Controller) usa fortemente il pattern dell’Observer, così come il Broker si fonda sul pattern del Proxy: ma un pattern di architettura non solo un accostamento di pattern di design. 
Il tutto è più della somma delle parti. Il fatto che certe architetture sembrino proprio un’accozzaglia di pattern e di idiomi affiancati non fa che esaltare l’importanza dei pattern architetturali.

Conclusione

A che cosa servono i pattern? Come si usano? Un programmatore deve davvero sapere a memoria tutti i 23 pattern del [GoF]? E che dire poi dei libri dei convegni sui pattern, PLoP, dato che ogni anno ne esce uno nuovo? Dobbiamo usare il registratore sotto il cuscino per impararli tutti?
Evidentemente, no. Certo è utile conoscere i pattern del [GoF] e anche avere letto i PLoP non guasta, ma lo scopo dei pattern non è di essere recitati la sera e la mattina a mo’ di rosario del programmatore. Non funziona così. Raramente capita di trovare la soluzione a un problema già bella impacchettata in un pattern. 
Più spesso mi è successo di scoprire una soluzione (a un problema in un contesto), e solo dopo di accorgermi di un pattern che gli assomigliava. Allora a cosa mi sono serviti i pattern? Prima di tutto nel metodo di indagine: problema + contesto = soluzione. Poi, a rinfrancarmi sul fatto che la mia soluzione "esistesse davvero", per quanto bizzarra mi fosse sembrata, e che valeva la pena di provarla. 
Infine, ma non ultimo, la razionalizzazione in pattern della mia soluzione che aveva fatto qualcun altro metteva spesso in luce vantaggi e svantaggi, requisiti e conseguenze a cui non avevo pensato. I linguaggi di pattern evidenziano una cosa ancora più importante, cioè quanto due pattern messi assieme "vadano d’accordo". In fondo, trovare una soluzione a un problema è facile; il difficile è fare sì che tutte le soluzioni che mettiamo dentro a un’applicazione convivano felicemente. 
La cosa peggiore che può capitare a un progetto (e a un progettista) è scoprire di avere messo assieme due pattern incompatibili. 
Di solito lo si scopre un bel po’ di tempo dopo, quando non ci resta che scegliere fra la ristrutturazione totale del sistema, con conseguente odio di tutti quelli cui facciamo rifare del codice che già funziona, o una famigerata patch, per cui saremo odiati da tutti coloro che ci seguiranno. 
Mi sono appassionato ai pattern in seguito a un progetto di cui sono stato responsabile e che, alla fine, ha pure prodotto una discreta quantità di software, ma a costo di una serie inenarrabile di ripensamenti e ristrutturazioni. Leggendo il [GoF] quello che veniva in mente più spesso era "...se l’avessi saputo prima!". 
Spero che almeno ai pattern risparmino la mia esperienza.
 

Bibliografia

[Alex79] C. Alexander, "The Timeless Way of Building", Oxford Press, 1979.
[Brooks87] F. P. Brooks, "No Silver Bullet", IEEE Computer, April 1987, 10-19.
[Budinsky96] Budinsky, Finie e Vlissides, "Automatic Code Generation from Design Patterns", IBM Technical Journal 35(2), 1996; Anche su http://www. almaden.ibm.com/journal/sj/budin/dudinsky.html).
[Buschmann96] F. Buschmann et al., "A System of Patterns", J.Wiley 1996.
[Cope96] J. O. Coplien, "Software Patterns", SIGS Management Briefings, 1996.
[Cope97] J. O. Coplien, "Pattern Languages", C++ Report, Jan. 1997, 15-21.
[Esposito96] D.Esposito, "Te lo do io il Wizard", Computer Programming N. 53, Dic. 96, 129.
[Garlan95] D. Garlan et al., "Architectural Mismatch: Why Reuse is So Hard", IEEE Software, Nov. 1995, 17-26.
[GoF] E. Gamma, R. Helm, R. Johnson, J. Vlissides, "Design Patterns", Addison Wesley 1995.
[Johnson92] R. E. Johnson, "Documenting Frameworks Using Patterns", Proc. OOPSLA ’92, 63-76.
[Lea95] http://iamwww.unibe.ch/~fcglib/WWW/OnlineDoku/archive/DesignPatterns/0513.hml.
[McConnell96] S. McConnell (ed.), "Missing in Action: Information Hiding", IEEE Software, March 1996, 128-127.
[Parnas79] D. L. Parnas, "Designing Software for Ease of Extension and Contraction", IEEE Tr. On Software Eng., SE-5, No. 2, March 1979, 128-137.
[PLoP2] Vlissides Coplien Kerth (eds.), "Pattern Languages of Program Design 2", Addison Wesley, 1996.
 

Graziano Lo Russo è laureato in Ingegneria Elettronica; è uno specialista in analisi e sviluppo Object Oriented. Può essere contattato tramite e-mail all’indirizzo: lorusso@programmers.net
 

 

 
 

MokaByte Web  1998 - www.mokabyte.it 
MokaByte ricerca nuovi collaboratori. 
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it