GUISA
Entra
|
Registrati
|
Aiuto
Home
Chi siamo
Blog
Forum
Media
Caffetteria
Architettura e design
Metodologia e processo
Forum
»
GUISA
»
Architettura e design
»
Design di una applicazione desktop
Design di una applicazione desktop
rated by 0 users
This post has 5 Replies | 1 Follower
Post
268
Punteggio 4.907
Rispondi
petrux
Posted: 12-10-2009 12.05
rated by 0 users
Ciao a tutti,
mi trovo davanti alla necessità di sviluppare una applicazione desktop,
una sorta di editor WYSIWYG, sulla falsa riga di Lexi, quello descritto
nel libro "Design Patterns" della GoF. In particolare riflettevo sulla
possibilità di implementare le operazioni di UNDO (o CTRL-Z, se
preferite o 'C-x u' se siete Emacs-maniacs :-)). Il manuale in questione
propone l'utilizzo di un Command Pattern. E fin qui, nulla di strano.
Ora, mi pongo un problema in termini di estendibilità/pluggabilità
dell'applicativo.
Supponiamo che la struttura del mio documento sia rappresentabile con un
object-model assimilabile ad un grafo:
interface IGraph {
...
List NodeSet;
}
interface INode {
List Paretns;
List Children;
string Label { get; set; }
int Seed { get; set; }
}
e che abbia definito il mio generico comando come:
interface ICommand {
void Execute();
void Undo();
boo IsUndoable { get; }
}
Il problema che mi sto ponendo è: dove metto la generazione dei comandi?
Nel senso: se io intercetto un evento che si scatena a livello di GUI
posso fare due cose:
1. richiamo uno snippet del genere:
INode n = ...; //nodo affetto dalla modifica;
string label = ...; //il nuovo valore della label;
ChangeLabelCommanf c = new ChangeLabelCommand();
c.Node = n
c.OldLabelValue = n.Label;
c.NewLabelValue = label;
Graph.CommandList.Enqueue(c);
2. faccio una cosa del genere (con 'n' e 'label' dal punto precedente):
n.Label = label;
e utilizzo una implementazione delle interfacce che "mascherino" la
generazione del comando e via dicendo.
Nel caso 1 ho in pratica un layer di meno (e la layerizzazione è un
costo), ho il problema che un eventuale plugin che operi *direttamente*
sul modello (a meno di non renderlo in pratica read-only... ma non mi
parrebbe proprio il caso), faccia delle modifiche che non siano
passibili di revert.
Consigli? ;-)
Grazie,
Giulio
--
| Punteggio Post: 20
Post
143
Punteggio 2.560
Rispondi
Mauro Servienti [MVP]
In risposta a
12-10-2009 20.36
rated by 0 users
Ciao Giulio,
You wrote on 10/12/2009 :
> Nel caso 1 ho in pratica un layer di meno (e la layerizzazione è un
> costo), ho il problema che un eventuale plugin che operi *direttamente*
> sul modello (a meno di non renderlo in pratica read-only... ma non mi
> parrebbe proprio il caso), faccia delle modifiche che non siano
> passibili di revert.
> Consigli? ;-)
certo che tu le domande semplici le hai finite da piccolino :-D
io, nel mio piccolo faccio fare ad un mediatore che sta tra l'editor e
il modello, una cosa del tipo:
EditorView
PersonViewModel
Person
l'editor, e quindi i plugin, conoscono in fase di edit solo
PersonViewModel il quale fa tutta la gestione della parte del Memento,
nel mio caso sia indietro che avanti. Hai poi un problema di cui devi
tenere conto:
EditorView
PersonViewModel
Person
Addresses
che naturalmente diventa:
EditorView
PersonViewModel
Person
AddressesViewModel
AddressViewModel
Address
Nel caso di editor master-detail il supporto per il memento deve essere
"mixed"? ergo deve essere possibile fare questo:
* cambio Person.FirstName;
* cancello un Address;
* cambio Person.LastName;
* aggiungo un nuovo Address;
* cambio Address.Street del 3� indirizzo;
e poi fare ctrl+z per 5 volte tornando all'inizio? e paggio ancora fare
ctrl+y per altrettante volte e tornare alla fine?
Se si allora il servizio che traccia la lista delle modifiche deve
essere noto a livello di "editor" e iniettato nel vari *ViewModel
..m
--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCP
http://mvp.support.microsoft.com
http://blogs.ugidotnet.org/topics
whynot [ at ] topics [ dot ] it
| Punteggio Post: 20
Post
268
Punteggio 4.907
Rispondi
petrux
In risposta a
12-11-2009 9.25
rated by 0 users
Ciao Mauro,
mauroservienti wrote:
> certo che tu le domande semplici le hai finite da piccolino :-D
Già... :-)
> io, nel mio piccolo faccio fare ad un mediatore che sta tra l'editor e
> il modello, una cosa del tipo:
[cut]
> Nel caso di editor master-detail il supporto per il memento deve essere
> "mixed"? ergo deve essere possibile fare questo:
>
> * cambio Person.FirstName;
> * cancello un Address;
> * cambio Person.LastName;
> * aggiungo un nuovo Address;
> * cambio Address.Street del 3� indirizzo;
>
> e poi fare ctrl+z per 5 volte tornando all'inizio? e paggio ancora fare
> ctrl+y per altrettante volte e tornare alla fine?
Ebbene si.
> Se si allora il servizio che traccia la lista delle modifiche deve
> essere noto a livello di "editor" e iniettato nel vari *ViewModel
Per "a livello di editor", si intende che l'editor conosce il servizio
che traccia le modifiche, ma non i plugin, giusto?
Per il resto... l'enigma è il seguente: Memento o Command? :-)
Ciao,
Giulio
--
| Punteggio Post: 20
Post
143
Punteggio 2.560
Rispondi
Mauro Servienti [MVP]
In risposta a
12-12-2009 9.08
rated by 0 users
Ciao Giulio,
You wrote on 11/12/2009 :
> Per "a livello di editor", si intende che l'editor conosce il servizio
> che traccia le modifiche, ma non i plugin, giusto?
si intende che l'editor inietta nella gerarchia che sta editando il
Memento quindi tutti hanno a disposizione il memento per
aggiunggere/rimuovere "azioni" e per capire lo stato del grafo
> Per il resto... l'enigma è il seguente: Memento o Command? :-)
Memento condito da command :-), ho una chilometrica serie di post al
riguardo ma il blog non va pi� :-(
per� qualcosa c'�:
http://blogs.ugidotnet.org/topics/archive/0001/01/01/ichangetrackingservice.aspx
http://blogs.ugidotnet.org/topics/archive/0001/01/01/memento-non-ti-scordar-mai-di-mehellip.aspx
..m
--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCP
http://mvp.support.microsoft.com
http://blogs.ugidotnet.org/topics
whynot [ at ] topics [ dot ] it
| Punteggio Post: 20
Post
268
Punteggio 4.907
Rispondi
petrux
In risposta a
12-14-2009 10.42
rated by 0 users
Ciao Mauro,
mauroservienti wrote:
> si intende che l'editor inietta nella gerarchia che sta editando il
> Memento quindi tutti hanno a disposizione il memento per
> aggiunggere/rimuovere "azioni" e per capire lo stato del grafo
Ok, credo di aver capito.
> Memento condito da command :-), ho una chilometrica serie di post al
> riguardo ma il blog non va pi� :-(
Uhm... comunque anche nel libro della Gang of Four, alla fine propone un
Memento+Command per implementare meccanismi di Undo/Redo. A tal
proposito c'è qualcosa che mi sfugge.
Secondo quanto esposto dalla GoF, l'oggetto Memento espone *due*
interfacce, una più "stretta" che viene usata dal Caretaker (che
sarebbe, se non ho capito male, il "motore" che gestisce la
creazione/caricamento del memento) ed una più "larga", che viene usata
dall'Originator per salvare/caricare lo stato.
Ora, mi chiedo: come è possibile realizzare "praticamente" questa specie
di segregazione delle interfacce (nel codice C++ presentato in "Design
Patterns" te la cavi con un "friend" :-))? In pratica per ogni classe
che gioca un ruolo di Originator devo costruirmi una "specializzazione"
del Memento?
Ciao,
petrux
--
| Punteggio Post: 20
Post
143
Punteggio 2.560
Rispondi
Mauro Servienti [MVP]
In risposta a
12-14-2009 10.55
rated by 0 users
Ciao Giulio,
You wrote on 14/12/2009 :
> Ora, mi chiedo: come è possibile realizzare "praticamente" questa specie
> di segregazione delle interfacce (nel codice C++ presentato in "Design
> Patterns" te la cavi con un "friend" :-)? In pratica per ogni classe
> che gioca un ruolo di Originator devo costruirmi una "specializzazione"
> del Memento?
l'ho letto ma non mi ricordo come viene implementato sul GoF, io alla
fine dopo anni di rimaneggiamenti sono giunto a questa conclusione:
un grafo � sempre e solo fatto ti oggetti e liste di oggetti, le
*modifiche* che possono essere apportate su un grafo sono di 2
macro-tipi:
- modifiche alle *propriet�*;
- modifiche alle relazioni che intercorrono tra un oggetto e
l'eventuale *lista* che lo contiene in quel momento;
quindi:
abstract Change
PropertyChange
CollectionChange
l'engine � sempre lo stesso, sia quello che vedono i client che quello
che vede il grafo internamente
..m
--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCP
http://mvp.support.microsoft.com
http://blogs.ugidotnet.org/topics
whynot [ at ] topics [ dot ] it
| Punteggio Post: 5
Precedente
|
Successivo
Pagina 1 di 1 (6 elementi) |
RSS