PDA

View Full Version : [Design] Qual è un design adatto per...


tomminno
24-06-2008, 13:26
Non riesco a trovare un design "corretto" per gestire un protocollo di comunicazione con una cinquantina di comandi.
Ad ogni comando corrisponde un'azione, una modifica dello stato di qualche altro oggetto e una risposta.

Al momento c'è un Mediator in che si occupa di smistare le operazioni e di tenere uno stato centralizzato. La classe però è decisamente grossa ed ha almeno un metodo per ogni comando.

Ad esempio ho varie classi che singolarmente monitorano aspetti differenti del sistema, adesso sono istanziate dal Mediator che ne modifica i parametri a seconda del comando ricevuto.

Ho provato ad effettuare il refactoring usando il Factory, che sembra l'ideale in questo caso, la creazione dei comandi è alquanto agevole è ci vuole un attimo ad aggiungerne di nuovi.
Il mio problema è che con il factory non ho più un'entità che gestisca l'interscambio di informazioni e dovrei fare ricorso massivo ai singleton.
Se il singleton può andare bene per la classe che gestisce la comunicazione (tanto ce ne deve essere una sola), non mi piace assolutamente per tutto il resto.
E in alternativa dovrei modificare l'interfaccia per passare tutti i riferimenti di tutti i possibili oggetti manipolabili da un comando, che lo vedo come un obrobrio.

Insomma non riesco più a riunire ciò che il Factory ha diviso.

Qual è il design corretto da applicare in questi casi?

^TiGeRShArK^
24-06-2008, 13:34
mmmm...
non ho capito bene se è il tuo caso..
ma hai già provato ad applicare il Command Patern (http://en.wikipedia.org/wiki/Command_pattern)?

tomminno
24-06-2008, 14:19
mmmm...
non ho capito bene se è il tuo caso..
ma hai già provato ad applicare il Command Patern (http://en.wikipedia.org/wiki/Command_pattern)?

Beh tramite il Factory creo un Command.
Poi però mi manca il modo con cui fare interagire i Command tra di loro e con altri oggetti.

cionci
24-06-2008, 15:09
Scusa, ma i command li dovresti istanziare una sola volta per tutta l'applicazione ed in base ad un valore intero ricevuto (l'azione indicata nel pacchetto) dovresti scegliere un command da eseguire. I command dovrebbero essere implementati come method object.

tomminno
24-06-2008, 16:11
Scusa, ma i command li dovresti istanziare una sola volta per tutta l'applicazione ed in base ad un valore intero ricevuto (l'azione indicata nel pacchetto) dovresti scegliere un command da eseguire. I command dovrebbero essere implementati come method object.

Il mio problema è fare interagire i command non istanziarli.
Il Factory istanzia già il command appropriato in base all'id messaggio.
Ma l'interfaccia non consente il passaggio dei riferimenti a tutti i possibili oggetti manipolati dai singoli command.
E oltretutto il Factory isola la classe che conosce le istanze dei vari oggetti dai command che li devono usare.

^TiGeRShArK^
24-06-2008, 16:56
Il mio problema è fare interagire i command non istanziarli.
Il Factory istanzia già il command appropriato in base all'id messaggio.
Ma l'interfaccia non consente il passaggio dei riferimenti a tutti i possibili oggetti manipolati dai singoli command.
E oltretutto il Factory isola la classe che conosce le istanze dei vari oggetti dai command che li devono usare.

ecco, questa parte mi sfugge...
i command devono interagire tra loro o con oggetti esterni?
E comunque con il factory non hai a disposizione tutti i riferimenti dei vari command?
In quel modo, magari implementando un observer pattern, dovresti riuscire a instradare gli eventi ai vari oggetti coinvolti che poi potranno reagire opportunamente..
..o mi sfugge ancora qualcosa? :fagiano:

certo che in effetti discutere di quale design pattern sia migliore senza conoscere pienamente l'architettura è un pò un casino..:stordita:
infatti io ti sto suggerendo solo quelli che mi vengono in mente in base a quello che io ho capito che ti serve..
ma se non ho capito un cazz allora i miei suggerimenti sono praticamente inutili :asd:

cionci
24-06-2008, 17:48
Il mio problema è fare interagire i command non istanziarli.
Il Factory istanzia già il command appropriato in base all'id messaggio.
Ma l'interfaccia non consente il passaggio dei riferimenti a tutti i possibili oggetti manipolati dai singoli command.
E oltretutto il Factory isola la classe che conosce le istanze dei vari oggetti dai command che li devono usare.
Non capisco cosa intendi sinceramente. Non capisco nemmeno a cosa serva un factory. Basta un map che associa l'id al command da allocare al momento dell'instaurazione della connessione o al cambio di stato del protocollo.
Per far interagire i command con l'esterno dovrai passare i riferimenti agli altri oggetti o al costruttore del command o al metodo che esegue il comando stesso.

^TiGeRShArK^
24-06-2008, 17:50
Non capisco cosa intendi sinceramente. Non capisco nemmeno a cosa serva un factory. Basta un map che associa l'id al command da allocare al momento dell'instaurazione della connessione o al cambio di stato del protocollo.
Per far interagire i command con l'esterno dovrai passare i riferimenti alla altri oggetti o al costruttore del command o al metodo che esegue il comando stesso.
è questo pure il mio problema...:stordita:

marco.r
24-06-2008, 21:30
E in alternativa dovrei modificare l'interfaccia per passare tutti i riferimenti di tutti i possibili oggetti manipolabili da un comando, che lo vedo come un obrobrio.

Come viene specificato quali oggetti un comando modifica ? Se dipende solo dal comando in se' probabilmente e' solo una questione di trovare un modo opportuno di istanziare i comandi. In caso contrario probabilmente il messaggio passato contiene un qualche ID dell'oggetto su cui operare, al che ti basta una classe che mappi ID -> oggetti. O forse la sto facendo troppo semplice ? :confused:

tomminno
25-06-2008, 15:44
Come viene specificato quali oggetti un comando modifica ?


E' il comando a sapere cosa deve modificare.
Il comando ImpostaSogliaXSensoreY sa di dover usare l'oggetto SensoreY, il problema è fargli conoscere l'istanza del SensoreY.


Se dipende solo dal comando in se' probabilmente e' solo una questione di trovare un modo opportuno di istanziare i comandi. In caso contrario probabilmente il messaggio passato contiene un qualche ID dell'oggetto su cui operare, al che ti basta una classe che mappi ID -> oggetti. O forse la sto facendo troppo semplice ? :confused:

Se non fosse che tutti i comandi implementano la stessa interfaccia e un comando può usare più oggetti che non hanno la stessa interfaccia...

tomminno
25-06-2008, 15:45
Non capisco cosa intendi sinceramente. Non capisco nemmeno a cosa serva un factory. Basta un map che associa l'id al command da allocare al momento dell'instaurazione della connessione o al cambio di stato del protocollo.
Per far interagire i command con l'esterno dovrai passare i riferimenti agli altri oggetti o al costruttore del command o al metodo che esegue il comando stesso.

Factory o meno, usando una interfaccia comune per i comandi, ci vorrebbero decine di parametri, ovvero tutti quelli manipolabili dall'insieme di tutti i comandi e se c'è da aggiungere una nuova funzionalità con un nuova classe con relativi comandi per il controllo vanno modificati tutti.
E non è nemmeno detto che un comando agisca su un solo oggetto per cui non posso nemmeno usare i template/generics

Forse è il caso di esemplificare la struttura del programma:
Al momento c'è una classe Manager che istanzia praticamente tutto, il client per la connessione, le classi che rappresentano dei sensori, il GPS, il GSM (tutti questi hanno interfacce completamente differenti e non unificabili).
Poi ci sono tanti messaggi che controllano le singole funzioni, alcuni esempi:
ImpostaSogliaXSensoreY
ImpostaSogliaTemperatura
ResettaTuttiSensori
ImpostaStringaNMEA
ImpostaNumeroTelefonoServer

All'arrivo di un messaggio dal socket una map associa il messaggio ad un metodo che esegue il lavoro e risponde al server con il risultato dell'operazione. Insomma scarsamente OO.

Quello che volevo fare (e che in parte ho già fatto), già che devo rimettere mano al caos attuale, era creare una classe Command per ogni comando tipico del pattern command, una classe Factory per istanziare il comando appropriato in base al messaggio, dopotutto serve a questo il Factory no?

A questo punto nasce il problema di come fare per far si che il Command che gestisce il messaggio ImpostaSogliaXSensoreY abbia un riferimento alla classe SensoreY, che quello per ImpostaSogliaTemperatura abbia un riferimento alla classe SondaTemperatura, che quello per ResettaTuttiSensori abbia un riferimento a tutti i sensori, che ImpostaStringaNMEA abbia un riferimento al GPS e ImpostaNumeroTelefonoServer al GSM.

O comunque un modo per far si che all'arrivo del messaggio venga modificata la classe opportuna, anche rivedendo completamente la struttura che avevo pensato di usare.

Spero che adesso sia più chiaro.

cionci
25-06-2008, 16:01
A questo punto nasce il problema di come fare per far si che il Command che gestisce il messaggio ImpostaSogliaXSensoreY abbia un riferimento alla classe SensoreY, che quello per ImpostaSogliaTemperatura abbia un riferimento alla classe SondaTemperatura, che quello per ResettaTuttiSensori abbia un riferimento a tutti i sensori, che ImpostaStringaNMEA abbia un riferimento al GPS e ImpostaNumeroTelefonoServer al GSM.
La prima soluzione che mi viene in mente è appunto istanziare una sola volta i Command e passare al costruttore i vari riferimenti alle classi necessarie.
Mi sembra anche la soluzione più semplice. L'interfaccia per il metodo che implementa il comando resterà la stessa.

La seconda soluzione che mi viene in mente è delegare la modifica dei sensori (e delle altri oggetti) agli oggetti stessi, i quali si registreranno su un observer in attesa di processare uno o più tipi di messaggi.
Alla ricezione un pacchetto verrà fatto un dispatch di un messaggio sull'observer. L'observer lo inoltrerà agli oggetti registrati per quel tipo di messaggio che si occuperanno di fare il parsing dei dati restanti per riconoscere se è diretto a loro oppure no (a seconda del messaggio puoi far arrestare l'inoltro del messaggio agli altri oggetti).
E' una soluzione abbastanza valida, ma anche computazionalmente più costosa.