Version 11 (modified by 18 years ago) (diff) | ,
---|
Variante 2: Operazioni estendibili
Note preliminari sul documento
Questo documento intende essere punto di riferimento in fase di sviluppo e germe della documentazione che accompagnera' il progetto.
Questo documento e' presente in duplice copia: fra i sorgenti in modo da essere facilmente editabile e leggibile in fase di sviluppo, e sul wiki [src:/branches/var2/doc/Appunti] e nel wiki Variante2 per aumentarne la facilita' di utilizzo. Dal momento che i commenti sul wiki possono essere lasciati anche da chi non segue direttamente lo sviluppo, l'utilizzo del file presente nei sorgenti e' da ritenersi una copia della pagina wiki; pertanto chi effettua modifiche al primo si dovra` preoccupare di sincronizzarlo tempestivamente con il secondo.
In caso di divergenze di opinioni su una sezione e' preferibile il commento pittosto della brutale modifica, in modo da tenere traccia delle considerazioni fatte. Convenzioni utili per i commenti:
- posporli alla sezione a cui fanno riferimento;
- usare il carattere corsivo per indivduarli facilmente;
- premettere il nome dell'autore accompagnato dalla data.
Specifiche
Si assuma che il numero e la struttura dei costrutti del linguaggio MiniScheme sia dato e non soggetto a cambiamenti:
- Si fornisca l'implementazione di tutti i costrutti originali
Si assuma che il numero delle operazioni polimorfe sia destinato ad evolvere rapidamente
- Si fornisca un interprete e una prettyPrint modulari
Il modello deve supportare la definizione modulare di operazioni.
- Si vuole supportare la definizione di operazioni modulari sia sotto forma di visitors che di iteratori
- Il modello deve fornire API di manipolazione specifiche e generiche
- L'aggiunta di una operazione non deve richiedere nessun
cambiamento al modello
20060819-1310 [SoujaK] Le operazioni non devono perrtanto risiedere all'interno del modello, ma all'esterno, negli specifici visitor/iterator. Il modello esporra' nella sua interfaccia la classicaaccept(AbstractVisitor)
. Raggruppare l'interfaccia dei visitor permette al modello di essere totalmente indipendente dall'aggiunta di nuove operazioni.
20060819-1617 [SoujaK]
E per quanto riguarda gli iteratori?
Le scelte di design devono essere imposte al cliente.
- Si vuole imporre al cliente l'uso dei pattern stabiliti (in particolare quelli creazionali)
- Il codice e i pattern non conformi a questa specifica non
devono fare parte del sistema fornito
20060818-1501 [SoujaK] Quali pattern creazionali? E' necessario il redesign di questa sezione, oppure la vecchia Factory adempie gia' a questo compito? Volendo si potrebbe pensare a soluzioni alternative, ma reputo la cosa a bassa priorita'.
Diaro di bordo: dubbi, problemi e conseguenti scelte
20060725-1758 [gnappo]
Le API di manipolazione generiche sono dei getter e setter che agiscono
sull'intero modello. Per approfondire seguite il
link.
Se non bastasse vi rimando all'
esempio
del prof. Solmi: prestate attenzione alle classi LanguageEntity e alle varie
Abstract* (sono particolarmente chiarificatrici).
20060818-1918 [SoujaK]
Le API di manipolazione generica sul modello possono essere implementate in un
genitore comune che fornira' l'operazione di default (verosimilmente il
sollevamento di un eccezione).
20060820-1238 [SoujaK]
Natura del modello: la struttura solitamente pensata come un albero di
espressioni e' rappresentata grazie a campi interni degli oggetti che compongono
l'aggregato. Si tratta di List
o ArrayList
nel caso di nodi non terminali,
altrimenti tipi specifici (bool, String, int) a seconda del caso. Il problema
che sorge e' come riuscire a far attraversare un aggregato cosi' eterogeneo da
un Visitor o da un Iterator.
Forse potrebbe avere senso fare come e' stato fatto per Variante 1, cioe'
far diventare i campi interni degli SchemeValue.
20060820-1332 [SoujaK]
Le API di manipolazione specifica (getter
e/o setter
) diventano piu' che mai
necessari in questa variante, perche' le operazioni sul modello devono essere
effettuate all'esterno di esso. Affinche' i Visitor
riescano nel loro intento
hanno ovviamente bisogno di conoscere l'oggetto che intendono visitare.
20060820-1817 [SoujaK]
Durante l'implementazione dei Visitor si pone un problema di natura progettuale:
chi e` responsabile dell'attraversamento della struttura a oggetti?
La possibilita' di utilizzare un Iterator esterno e` stata discussa da tutta la
squadra e non verra' realizzata sebbene si lasci tale facolta' al cliente.
Rimane pertanto da chiedersi se chi si fa carico dell'iterazione e' la stessa
struttura ad oggetti (come accade sovente a detta della GoF) oppure i Visitor
(si veda "GoF - Design Pattern - pagg 340-1).
Il dott. Solmi, nel suo esempio sui Visitor
snatura il significato di
Visitor
declassandoli a miseri proxy
usati per evitare di esporre
pubblicamente le operazioni come evaluate
o prettyPrint
. La richiesta di
chiarimenti, inoltrata al professore esattamente un mese fa (20060720-1854), non
ha ancora avuto risposte.
A mio avviso demandare l'attraversamento della struttura a oggetti Visitor
e'
la soluzione migliore in termini di eleganza e chiarezza dell'algoritmo di
visita, dal momento che la sua implementazione risiede, in tutte le sue
componenti, proprio fra i metodi di visita degli oggetti.
Faro' cosi'.
Appunti vari
- Gli iterator sono da intendersi come esterni.
- I nostri due visitor (PrettyPrintVisitor e InterpreterVisitor) conoscono direttamente la natura dell'albero di espressioni su cui lavorano. Al cliente e' chiaramente lasciata la possibilita' di usare un iterator.
- Le Expression$NAME vanno arricchite con API di manipolazione specifica (i.e.
getter
esetter
) per permettere all'iteratore di accedere in maniera indiretta ai campi di istanza.
Operazioni aggiunte
Questo e' il posto in cui rendere note le proprie scelte.