Design di una applicazione desktop

rated by 0 users
This post has 5 Replies | 1 Follower

Top 10 Partecipanti
Post 92
Punteggio 1.705
petrux Posted: 12-10-2009 12.05
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
Top 10 Partecipanti
Post 67
Punteggio 1.190
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
Top 10 Partecipanti
Post 92
Punteggio 1.705
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
Top 10 Partecipanti
Post 67
Punteggio 1.190
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
Top 10 Partecipanti
Post 92
Punteggio 1.705
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
Top 10 Partecipanti
Post 67
Punteggio 1.190
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
Pagina 1 di 1 (6 elementi) | RSS
Powered by Community Server (Commercial Edition), by Telligent Systems