Elementary Pattern, Pattern, GRASP e Design Pattern GoF Object Oriented Rosario Turco
Introduzione
Nel lavoro precedente [DR18] sono stati presentati gli Elementary Pattern (EP), gli Anti Elementary Pattern (AEP), i GRASP (General Responsibility Assignment Software Patterns).. Gli EP esaminati sono stati:
Elementary Pattern Complessità e Riusabilità di una c lasse
Anti Elementary Pattern di Coesione (istanza, dominio misto, ruolo misto)
Elementary Pattern Conformita di tipo
Elementary Pattern dell’Invariante
Elementary Pattern della precondizione
Elementary Pattern della postcondizione
Elementary Pattern - Principio del comportamento chiuso alle modifiche
Elementary Pattern della classe Astratta o dell’Interfaccia
Elementary Pattern Classe Mista
Elementary Pattern Descrittore di Classe
Elementary Pattern Separation of concerns
Elementary Pattern Lazy initialization
Vedremo che esistono molti altri EP. I GRASP esaminati sono stati:
Information Expert
Creator
Low Coupling
High Cohesion
Controller
Polimorfismo
Pure Fabrication
Indirection
Procted Variations
Testo rigoroso e storico sui Design Pattern è quello in [DR6]. Una trattazione in chiave di classificazione dei Design Pattern GoF, il loro scopo e una loro modellazione è stata prodotta dall’autore in *DR5+. In questo lavoro vogliamo, invece, vedere i Design Pattern GoF (DP) attraverso gli EP e i GRASP. Arrivando a sottolineare ulteriori Elementary Pattern e Pattern Architetturali.
1
La trattazione non è da ritenersi esaustiva, ma serve a sottolineare il metodo per comprendere cosa possa servire nella progettazione o come validare la propria progettazione. Gli EP e I GRASP sono principalmente concetti, principi e regole di buon senso Object Oriented, adottate nel tempo. I Design Pattern e i Pattern Architetturali cerano di risolvere problemi ricorrenti, dando flessibilità e solidità al progetto, individuando i punti di variazioni futuri possibili ( Variability Analysis) e i punti progettuali fragili (Commonality Analysis ). Esiste, quindi, una granularità diversa che ci porta a trovarli frequentemente in determinati ambiti. Ad esempio solo se facciamo un sistema di Persistenza dati, troveremo altri Elementary Pattern come:
Object Identifier (OID chiave tra oggetto e riga di una tabella),
Materialization (come rendere una riga di tabella un oggetto)
Dematerialization (come rendere un oggetto una riga di tabella, detto anche passivazione)
Cache
Etc. Se lavoriamo con framework o prodotti di persistenza questi EP non saranno aspetti progettuali che ci interesseranno, ma saremo concentrati rispetto al nostro dominio. Il lavoro mostrerà in prima battuta come alcuni DP discendono in modo semplice dagli EP e/o dai GRASP; poi ogni DP, per ragioni di flessibilità, attraverso considerazioni GRASP, comporta quasi quasi sempre la presenza anche di altri DP che si rendono necessari nella progettazione, insieme a nuovi EP non esaminati nel lavoro precedente. Infine si descriveranno anche dei P attern Architetturali. DP Adapter Problema: Come risolvere il problema di conciliare interfacce differenti da usare o fornire una stabile interfaccia (nel senso che non si modifica di continuo) a c omponenti simili ma che hanno interfacce diverse? Soluzione: Soluzione: Convertire l’interfaccia di un oggetto in quella di un altro attraverso un oggetto mediatore o adattatore.
Esempio Supponiamo che un nostro dispositivo deve usare calcolatori di tassa esterni, che possono essere sia cambiati o aggiunti ma hanno comportamento diverso.
In pratica qui usiamo almeno in prima battuta l’idea del GRASP Polimorfismo, del GRASP Procted Variation e l’EP della classe astratta o dell’interfaccia dell’interfaccia (basata sul Partizionamento completo).
Il progettino in prima battuta si presenta come nella figura successiva.
2
Le classi Adapter sono classi locali che poi chiameranno eventuali API dei calcolatori esterni. Quindi fanno da GRASP Indirection. Il template ci permette di avere il partizionamento completo e usare la interfaccia. L’interfaccia ci permette di incapsulare un punto di variazione potenziale e qu indi è applicato anche il GRASP Procted Variations. Infine è il minor ingombro diretto e indiretto possibile ottenendo Low Coupling e High Cohesion. Adesso usiamo ancora i GRASP, in senso generale . I GRASP ci suggeriscono “chi ha la responsabilità per …”. Qui nasce subito il problema: chi crea l’Adapter?
Sicuramente è vero l’EP Lazy inizialization , nel senso che in fase di sviluppo è difficile che si inizializzino e si creino attraverso i costruttori tutte le classi e poi si usano dopo. Semmai le classi si creano c reano quando servono, perché è un dispendio di risorse. Quindi è evidente che l’Adapter è associato ad una Factory (quella Concrete come vedremo) e anche a qualche altro DP.
La Factory in termini GRASP ci risolve la responsabililtà del Creator per l’Adapter, del Pure Fabrication (è un Helper) e l’EP di Separation of concerns. La Factory deve decidere anche quale calcolatore mettere su, ad esempio in modalità DATA-DRIVEN o da configurazione. E’ possibile cioè progettare una ServiceFactory come in figura, che ritorna oggetti di tipo dell’interfaccia.
Questo tipo è una “Concrete Factory”, perché provvede direttamente a creare l’oggetto di interesse, in questo caso l’Adapter. La Factory permette anche strategie non funzionali e di indirezione come il Caching, riduce la complessità della parte di logic che dovrebbe essere concentrata solo sul dominio aziendale. Molti framework (es: Spring) usano una factory per caricare oggetti o bean a partire da un file di configurazione XML.
3
DP Factory Problema: A chi dare la responsabilità per risolvere il problema di creazione di un oggetto ma semplificando la complessità della parte logica, in modo da avere basso accoppiamento con altri elementi di dominio diverso e la separazione dei concetti? Soluzione: Dare la responsabilità ad un Pure Fabrication Object denominato Factory che gestisce la creazione dell’oggetto.
Fin qua siamo soddisfatti, ma la GRASP ci pone un altro paio di domande: chi crea la Factory? quante factory devono esistere?
Sicuramente nel caso di un Adapter ci servirà una sola istanza di Factory per volta. Quindi La factory deve essere anche un Singleton. Possiamo Possiamo usare un attributo di istanza statico a sé sé stesso e un metodo statico. In UML sia gli attributi statici che i metodi statici sono sottolineati, ma non tutti i tool lo visualizzano in tal modo, alcuni come StarUML permette di marcare l’attributo e il metodo con TARGETSCOPE = INSTANCE e Owner Scope = INSTANCE.
Il synchronized va valutato se inserirlo in dipendenza se ci sono problemi di multi-thread oppure no. Nella pratica un oggetto Register potrebbe avere nel codice la seguente parte: public class Register { …. Etc …. taxCalculatorAdapter = ServiceFactory.getInstance(). ServiceFactory.getInstance().getTaxCalculatorAdapter(); getTaxCalculatorAdapter();
}
Sui diagrammi UML di un sequence il passaggio intermedio a getInstance() potrebbe non essere visibile, cioè viene ritenuto implicito , ma nell’implementazione è necessario .
4
Se si vuole esplicitare che ci deve essere il Singleton allora è meglio esplicitare il tutto almeno nel nome delal ServiceFactory, trasformandolo in ServiceFactorySingleton e mettendo un commento. In ogni caso c’è una condizione sul create(). Ci si chiede: perché in ServiceFactory non facciamo tutti attributi e metodi statici? Le risposte sono: Intanto per non violare la concetto di incapsulamento e di data-hiding, caro all’OO che risolve i problemi di co-nascenza dei linguaggi procedurali I metodi statici non sono soggetti apolimorfis mo e non permettono l’overriding Nelle comunicazioni di rete remote (come RMI) sono possibili solo metodi di istanza e non metodi statici
DP Singleton Problema: Come ottenere che ci sia il controllo sul fatto che esista una sola i stanza di una classe, a causa del fatto che la continua creazione di istanze è un fatto costoso in termine di tempo e risorse? Soluzione: Dare la responsabilità ad un Singleton.
Passiamo ad un altro problema che ci può capitare: spesso si hanno problematiche di logica complessa, ad esempio di stabilire in una vendita (Sale), in base al totale da pagare da un tipo di cliente (normale, gold, etc), lo sconto e il prezzo che gli si può applicare. Tipicamente sono problemi dove si applicano regole diverse o algoritmi diversi a seconda di determinate situazioni. Il DP Strategy è utile proprio a questo. DP Strategy Problema: Come progettare/disegnare/modellare per contenere le variazioni di algoritmi, regole, policy? Soluzione: Dare la responsabilità ad uno Strategy.
GRASP e EP sui cui si basa anche lo Strategy sono: GRASP Polimorfismo GRASP Procted Variation EP della classe astratta astratta o dell’interfaccia (basata sul Partizionamento Partizionamento completo). allo Strategy è sempre associato ad un Context Object (nell’esempio la vendita Sale).
Un primo progettino è, quindi, quello in figura. 5
La classe PercentDiscount chiede a Sale (Expert) quanto era il conto totale senza sconto. Mentre AbsoluteDiscount chiede a PercentDiscount (Expert) il conto scontato (se è scontabile). Il metodo getPreDiscountTotal() è ovviamente di Sale. Entrambi le classi usano Sale ( Context Object). In sostanza c’è una collaborazione.
I GRASP pongono adesso il seguente quesito: chi la responsabilità di creare lo Strategy? Ovvero sono da applicare di nuovo il GRASP Creator e EP Lazy Initialization. La risposta è una Factory . Altra domanda GRASP: ma quante quante istanze di strategy sono permesse? Nel caso una, per cui il Singleton diventerebbe d’obbligo. Per cui la Factory dovrebbe avere anche un attributo di istanza e un metodo statico. In figura la soluzione col Singleton.
6
In ultima analisi se serve uno DP Strategy, allora lo troveremo accoppiato quasi certamente ad una Factory, ad un Context Object, ed eventualmente ad un Singleton . Ma potrebbero essere utili anche altri DP a seconda della complessità del problema come vedremo. Facciamo qualche altra osservazione, prima. La percentuale di sconto potrebbe dipende dal giorno (es.: lunedì 10%, martedì 20% etc.) o dal tipo di cliente. In tal caso queste percentuali saranno configurate su un properties o su un database relazionale. Chi dovrebbe leggere questi dati per passarli allo Strategy? Una scelta ragionevole è la PricingStrategyFactory stessa. Essa conosce i dati che legge, conosce la strategia di pricing e quindi costituisce l’Expert. Supponiamo adesso che però le policy di pricing ce ne sono molte e sono in conflitto. Ad esempio le policy in gioco sono oggi lunedì: 20% di sconto ai clienti gold 15% di sconto alle vendite che superano i 400 euro Il lunedì ci sono almeno 50 euro fuori acquisto sul totale di 500 euro Acquistando il prodotto X si ottiene uno sconto del 15% su ogni altro pr odotto
Almeno tre delle situazioni di sopra comportano sconto.
7
Alcuni store potrebbero applicare lo sconto migliore a partire da un totale più basso (a favore del cliente), oppure la vendita ha sconti diversi per prodotto etc. In ogni caso questo evidenzia un chiaro conflitto di strategia. Intanto che il cliente sia gold è qualcosa che deve leggere la PricingStrategyFactory al tempo di creazione dello Strategy. Se lo sconto va fatto per prodotto acquistato significa che abbiamo dietro un EP Descrittore di classe, un ProductDescription, che deve leggere la PricingStrategyFactory per determinare per ognuno lo sconto. Rimane ora un problema. C’è un modo affinché l’oggetto Sale non conosca a priori se esiste un legame con uno o più strategie di prezzo? Esiste anche un modo per risolvere i conflitti di strategie? Occorre introdurre il DP Composite.
8
DP Composite Problema: Come trattare un gruppo di oggetti o composizione di oggetti come oggetti non atomici? Soluzione: Usare il Composite, cioè definire classi per oggetti composti e atomici così che essi implementino la stessa interfaccia.
Supponiamo una nuova classe che definisce la miglior strategia per il cliente gold: CompositeBestForCustomerPricingStrategy che implementa iSalePricingStrategy e contiene altri oggetti sempre di tipo ISalePricingStrategy. Riprendiamo una figura precedente, quella senza Factory, e cerchiamo di arricchirla.
In figura il Composite superclasse ha una lista di strategie: CompositePricingStrategy punta alla interfaccia a tale scopo per disporre di una lista. E’ una caratteristica del Composite. Come si vede dalla superclasse si hanno due sottoclassi, una per la migliore strategia del cliente e l’altra per lo Store. La figura fa vedere che a Sale è possibile collegare oggetti semplici o compositi per far uso o di una strategia puntuale come PercentDiscount o una particolare CompositeBestForCustomerStrategy che serve a determinare il più basso totale a cui fare lo sconto. IL Sale in questo caso non sa né le regole atomiche né quelle complesse. Nella figura non abbiamo riportato la Factory, che andrebbe però riportata. Il problema difatti è capire come creare con la Factory per i diversi Strategy. Finora abbiamo supposto che ci sono almeno tre sconti (dovremmo saperlo dagli Use case): Definiti per lo Store e che vengono aggiunti quando Sale è creata (le percentuali di partenza definite in PercentDiscount). Definiti per il tipo di cliente, aggiunti quando il cliente arriva al POS che legge dalla sua carta che è gold Definiti in base al prodotto
Nel primo use case la class name della strategy da far partire è letto da system properties, così pure le percentuali vengono lette da DB, dalla Factory. 9
Questo primo use case ha il sequence della figura successiva.
Il secondo use case è rappresentato nella figura successiva. Ovviamente poiché il cliente può essere gold o normal, allora bisogna individuare da DB c on l’IDCustomer prelevato dalla scheda se è gold o meno.
Perché un IDClient si è poi trasformato in un oggetto Customer. E’ una pratica comune, è un Elementary Pattern IDs to Objects. Spesso serve prelevarsi dall’ID le informazioni dell’intero oggetto. E’ un esempio. Se non serve si passa solo l’ID. Anche trasformare un ID in ProductSpecification è simile come pattern.
Un altro fatto che mette in mostra la figura è che addCustomerPricingStrategy(s:Sale) passa l’oggetto Sale alla factory e la factory torna indietro da Sale a chiedere Customer e il PricingStrategy. Perché non passare direttamente alla Factory Customer e il PricingStrategy ? Questo è un comune metodo OO consigliato: per aumentare la flessibilità progettuale evitare di passare sottooggetti di oggetti padri o di aggregati, meglio passare l’oggetto padre o l’aggregato! Inolte si ritarda il fatto che la factory debba sapere prima del tempo quello che gli serve. Questo viene chiamato Elementary Pattern Aggregate Object as Parameter .
10
DP FACADE Problema: Come disporre di un unico punto di ingresso al sottosistema, con un’unica interfaccia, che permette di nascondere quello che c’è dietro e che potrebbe variare? Soluzione: Usare un Facade object , che offre un’unica interfaccia e collabora con le varie parti del sottosistema (ma senza logica di business).
Il Facade è un front-end di accesso ai servizi del sotto-sistema, ne wrappa dietro le classi e le interfacce offerte, non rendendoli visibili all’esterno (sono privati al sistema). Quindi rispetta il GRASP Procted Variations, rispetto alle variazioni. Nasconde sia la complessità del sottosistema, che eventuali interfacce non implementate ancora. In sostanza c’è anche il GRASP Indirection o al contrario l’Elementary Pattern Delegate; infatti l’esperto è il sottosistema a cui il Facade delega la competenza. In tal modo si supporta il GRASP Low Coupling. Supponiamo ad esempio un sottosistema che è un motore di regole, di cui non è stata fatta l’implementazione, e sicuramente il client non deve conoscere la singola classe da chiamare. E’ da considerarsi spesso un Front Controller, quindi esiste dietro anche l’ Elementary Pattern Controller , perché fa da coordinatore della varie parti del sottosistema da coinvolgere.
Si insiste molto sui termini Front-end, sottosistema. Quindi il Facade è un tipico DP architetturale o come nella classificazione GoF è un DP strutturale. In J2EE il Facade è un compito svolto da un EJB Session Bean stateless; in rari casi da un EJB Session Bean Stateful. Il Facade può portarsi appresso anche un DP Adapter, che a sua volta può richiederne altri o un Singleton. In figura mostriamo l’organizzazione a package e delle classi su StarUML.
11
DP OBSERVER (Publish-Subscribe o anche Delegation Event Model) Problema: Differenti oggetti devono svolgere il proprio lavoro ma nello stesso tempo sono interessati al verificarsi di un evento su cui devono svolgere particolari task. Come fare? Soluzione: Usare l’Observer. In esso differenti tipi di oggetti denominati “Listener interface” o Subscriber (Sottoscrittore) sono interessati ad un evento, che è costituito dalla variazione di stato di un attributo. Per tale motivo ogni Subscriber si sottoscrivono (registrano) in modalità asincrona ad un Publisher per un evento. Il Publisher avverte i Subscriber registrati all’evento solo al verificarsi dell’evento stesso. Si chiama Observer perché il Subscriber tiene d’occhio l’evento, come un o sservatore.
Esempio Supponiamo che vogliamo realizzare una GUI che quando l’istanza della classe Sale cambia il valore del totale della vendita fa refresh del valore a video. Per le User Interface, Web e non, si utilizza il pattern Model-View-Controller . Il Model (Sale in questo caso, ovvero il modello del dominio) non deve avere alcuna conoscenza della View. Questo concetto incoraggia i GRASP Low Coupling e Procted Variation. Per poter ottenere questo serve realizzare un DP Observer. Il Model Sale è il Publisher (co lui che pubblica la variazione di stato), mentre il Subscriber o Listener Interface è la View che deve fare refresh. Il Subscriber però si deve registrare al Publisher per l’evento. 12
In figura l’Observer che serve realizzare. Supponiamo che usiamo classi di Swing per la UI. Anche qua si può lavorare tra due package, uno Domain contenente Sale e l’altro UserInterface contenente il Listener Interface. Ovviamente il package Domain <> il package UserInterface.
Nel seguito abbiamo preferito di mostrare le classi insieme. Sale ha almeno: Il metodo che setta il nuovo valore del totale: setTotal(Money) Il metodo che consente ai Subscriber di sottoscriversi a Sale: addListener(Listener lis) Il metodo per pubblicare ai Subscriber la variazione del valore: publishEvent(name, value)
Il Listener Interface deve avere almeno: Il metodo che riconoscendo l’evento a cui si è sottoscri tti effettua il refresh: onEvent(source, name, value). Tale metodo è chiamato dal Publisher e costituisce la callback. Un metodo add per tener conto dei listener sottoscritti
source è s, cioè Sale. Name è “sale.total”, value è total. Nel seguito il sequence dà ulteriori chiarimenti. addListener() farà qualcosa come: propertyListeners.add(lis); Il publishEvent() farà qualcosa come: { for each IListener pl in propertyListeners pl.onEvent(this,name, value); 13
}
L’esempio non deve far pensare che l’Observer serva solo per le User Interface. Spesso è utile anche per la parte server. Ad esempio per ricaricare una cache.
Esempio di Failover di una cache ad un local service Dobbiamo trovare una descrizione di un prodotto. Essa è presente attraverso un servizio su un database. Per efficienza ci serve una cache che li legge da locale se ce li ha se no va verso il servizio remoto.
Pensiamo di usare un Adapter (che verrà creato da un ServiceFactory). Anche se realmente non è un Adapter, è a due livelli. In realtà è un Proxy (Remote Proxy, Virtual Proxy o Failure Proxy). Qua non abbiamo riportato il ServiceFactory che riportiamo nel sequence.
14
Il Proxy inizialmente fornisce un riferimento temporaneo; esempi sono: Gestione dei failover di connessioni, cache etc Nel Web per visualizzare subito il contenuto testuale delle pagine HTML, fornendo un segnaposto iniziale per le immagini, che c he vengono caricate successivamente nel Java RMI fornendo un oggetto locale per poi comunicare successivamente con l’oggetto remoto
Per le eccezioni alzate vale un Elementary Pattern Convert Exceptions [Brown01]: se si è a livello di sottosistema non alzare eccezioni di più basso livello non coerenti col sottosistema ma convertirle. Per il logging vale un Elementary Pattern Centralized Error Logging [Renzel97]: definire un oggetto acceduto in modo centralizzato e Singleton e riportare ad esso tutte le eccezioni. Vale per le UI un analogo un Elementary Pattern Error Dialog [Renzel97]: definire un oggetto acceduto in modo centralizzato e Singleton con cui notificare agli utenti gli errori. DP ABSTRACT FACTORY Problema: Come creare una famiglia di classi legate che implementano una interfacce comuni? Soluzione: Definire una factory interface, con tutti i metodi.
15
16
DP Template Method E’ di enorme importanza nei framework (vedi *DR19+ per esempi e principi sui framework) . Consiste nel fatto che in una classe due metodi di cui uno implementato e che richiama un secondo non implementato, mentre la sottoclasse implementa il secondo metodo e ne fa l’overriding polimorfico.
Nella superclasse il primo metodo, che NON VARIA e che richiama il secondo metodo non implementato, si chiama per questo template; mentre il secondo metodo è detto hook (uncino d’aggancio). Il principio su cu si basa il Template Method è un Elementary Pattern Principio di Hollywood: “ Non chiamateci, vi chiamiamo noi (tramite l’hook)!” Ad esempio si possono fare framework per giochi che hanno una stessa base d’infrastruttura (*DR19+) oppure dei Mapper diversi (da file, DB, da JMS, etc) In figura quanto detto sopra.
Il DP Template Method esalta l’EP Pro tected Variations.
DP State Pattern
Problema: Il comportamento di un oggetto dipende dal suo stato e i suoi metodi contengono logica che è legata a questi stati Soluzione: Usare lo State Pattern. Esempio Gli oggetti di un sistema persistente possono essere inseriti, cancellati o modificati. Supponiamo però che lavorare su un oggetto persistente non provoca subito la modifica dell’oggetto sul database ma una esplicita commit deve essere effettuata. Un diagramma di stato per un PersistentObject potrebbe essere quello in figura.
17
Come gestirlo con un modello di classi? Vediamo la figura successiva.
Sulle classi che esprimono lo stato troveremo i metodi che fanno uscire dallo stato in questione. L’esempio qui visto è solo didattico, per trasportarlo in situazioni simili ma non di persistenza; per la persistenza è meglio usare un framework come Hibernate, MyBatis etc.
DP Command Pattern
Problema: Come gestire richieste, comandi o task che necessitano di applicazioni di funzionalità come sorting, queuing, logging, undoing, etc. Soluzione: Usare il Command Pattern, facendo ogni task una classe che implementa una interfaccia
18
Esempio Supponiamo di avere un oggetto Transaction che deve far eseguire una lista di comandi. Può delegare ad un esperto (il Command)
19
Abbiamo, quindi, finora esaminato i seguenti Design Pattern sotto “una lente EP e GRASP”:
Adapter Factory Strategy Composite Facade Observer Proxy Abstract Factory Template Method State Pattern Command Pattern
Abbiamo poi incontrato degli EP ulteriori: Context Object (sono utili non solo nello Strategy, sono dei particolari Data Transfer Object) Lazy Initialization IDs to Objects Aggregate Object as Parameter Convert Exceptions Centralized Error Logging Error Dialog Principio di Hollywood MVC (Model View Controller)
L’MVC è un pattern architetturale. Per una UI desktop con Swing l’Observer proposto può andar bene. Per UI web si usano framework che gestiscono l’MVC come Spring, Struts2 (lato server) o JavascriptMVC (lato client).
Lo standars POSA (Pattern-Oriented Software Architecture) indica che esistono almeno tre tipologie: Pattern architetturali (PA) Design Pattern, alcuni visti primi Idiomi, che indirizzano problemi di linguaggio o di basso livello. Anche il Singleton è di questo tipo, oltre che essere un DP.
Un altro Pattern Architetturale importante è il Layer. PA Layers
Problema: 1. Il sw cambia spesso creando instabilità, m olte parti sono fortemente accoppiate 2. L’application logic è troppo connessa e intrecciata alla UI 3. Servizi tecnici e di business sono intrecciati 4. Forte connessione tra area diverse Soluzione: organizzare il sistema a strati (layer), ognuno dei quali risolve una serie di sotto problemi e collabora con gli altri Nel sw di un sistema tipicamente si ritrovano ad esempio i seguenti package che seguono il PA Layers: 20
Presentation Application (Workflow, Process, Mediation, Controller) Domain (dominio di business) Business Infrastructure (opzionale: servizi di business di basso livello) Technical Services (Infrastruttura tecnica, servizi tecnici) Foundation (opzionale: Infrastruttura di basso livello, servizi tecnici di basso livello)
Per i rimanenti DP qui non trattati si consiglia di esaminare [DR5][DR6].
Riferimenti [DR1] Rosario Turco – Concetti di base Object Oriented [DR2] Rosario Turco – Principi di Disegno [DR3] Rosario Turco – Usabilità e ripetibilità dei processi produttivi software [DR4] Rosario Turco – Modellare con l’UML ed i colori [DR5] Rosario Turco – Design Pattern – Pattern e-book: una guida nella jungla dell’OO [DR6] Gamma, Helm, Johnson,Vlissides – Design Patterns – Elementi per il riuso di software a oggetti – Prima edizione italiana [DR7] Rosario Turco – Risoluzione di problemi con UML [DR8] Rosario Turco – Tradurre le relazioni UML in C++ [DR9] Rosario Turco - Refactoring: la teoria in pratica [DR10] Rosario Turco – Disegno per il riuso e con il riuso [DR11] Rosario Turco – Framework e UML [DR12] Rosario Turco – Il Business AS IS Modeling con UML [DR13] Rosario Turco – Extreme Programming [DR14] Rosario Turco – Rational Unified Process [DR15] Rosario Turco – BPM, SOA e Business Rules Engine, l’ultima frontiera [DR16] Rosario Turco – Progettazione a componenti [DR17] Rosario Turco - Metodologia Agile [DR18] Rosario Turco – Elementary Pattern, Anti Elementary Pattern e GRASP [DR19] Rosario Turco – Principi sui framework software
21