Newsgroup: it.comp.java
Titolo: La mia applicazione è strutturata correttamente?

Ciao a tutti, sto partecipando allo sviluppo di un progetto client-server
in cui io mi occupo del client. L'applicazione in se non è nulla di
eccezionalmente complicato, dopo aver superato una fase di login, si tratta
essenzialmente di ricevere dati dal server ed elaborarli. In sostanza le
comunicazioni avvengono solamente server ==> client tranne che per qualche
messaggio di servizio (login, logout, query iniziale).
Dopo aver stabilito
la connessione con il server, la classe principale lancia un thread che si
occupa solamente di quanto arriva dal server. Per ogni messaggio (ed una
sua prima elaborazione) genero un evento che viene inviato alla classe
principale la quale poi si occupa di trattarlo.
Pero' ho dei dubbi di
carattere "strutturale" sulla mia applicazione:
- come faccio a sapere
dalla classe principale se si è verificata un'eccezione nella classe "in
ascolto" che è quindi terminata? L'unica soluzione "elegante" che mi è
venuta in mente è di creare un nuovo evento "InputDefunto" che la classe
principale è in grado di recepire, e quindi reinizializzare gli oggetti per
ritornare allo stato di partenza ed essere quindi pronta per una successiva
connessione.
- a parte qualche prova che fanno tutti con le chat, questo è
il mio primo vero progetto client-server: l'idea del thread separato che
ascolta i messaggi in arrivo e li inoltri alla classe principale tramite un
evento come vi sembra? Ci sono soluzioni migliori o più efficenti? Tenete
presente che il client deve continuamente analizzare i msg in arrivo per
poi mostrarli su delle finestre figlie
Avete qualche consiglio da darmi?
Grazie per l'attenzione
Lis
--------------------------------
Inviato via 
http://usenet.iol.it

 i msg in arrivo per poi mostrarli su delle finestre figlie
L'unica cosa a cui devi fare attenzione e' tener sempre presente in che
thread vengono eseguite le chiamate. Qualunque metodo (anche della classe
watchdog) invocato da run() dell'oggetto working thread e' eseguito nel
relativo thread di s/o, quindi spesso e' necessario un disaccoppiamento.
In tal caso, ti puo venire utile il framework che scrissi anni fa proprio
per questo - 
http://space.tin.it/computer/csadun/software/lf
. Ad esempio,
un'applicazione che ne fa uso di cui sto per mettere i sorgenti su
sourceforge e' un package per fare polling su directory. 
In quel tipo di applicazioni, e' importante discriminare eccezioni
applicative (che il thread operativo sa di poter subire, e per cui e'
possibile definire un sottosistema di exception handling), eccezioni non
applicative ma "previste", ed eccezioni del tutto inattese
(unrecoverable). Una buona gerarchia di eccezioni ti semplifica la vita
notevolmente e fa la differenza per l'affidabilita' del sistema. 
Il sottosistema di exception handling puo' implementare policy di
retry/failure, restart/failure, count/retry or fail eccetera. 
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

notevolmente e fa la differenza per
l'affidabilita' del sistema.
Esatto, infatti il mio thread generara
eventi per segnalare errori bloccanti, warning oppure semplici
informazioni.
Grazie



Dai un'occhiata a questo precedente thread...
http://groups.google.com/groups?hl=en&th=543b216a7aee138f&rnum=1
... e in particolare a questo articolo:
http://groups.google.com/groups?hl=en&selm=3c4705d6.24949946%40news.inet.it
Ciao,
    Bruno.
---
| Bruno Bossola
| A Java Software Engineer :-)
| 
http://members.xoom.it/bbruno
| 
http://digilander.iol.it/bbossola

 informazioni.
Occhio che sto parlando di eccezioni a livello di linguaggio. Ad esempio,
un'eccezione di I/O puo' essere dovuta al fatto che qualcuno ha
inciampato nel cavo di rete :-) (una politica di wait/retry ha senso)
oppure nel fatto che il server sia down (il client in genere dovra'
semplicemente terminare gracefully) eccetera. Modellare i vari casi con
opportuni oggetti-eccezione e' qualcosa che, nella mia esperienza, va
fatto anche se a prima vista pare poco importante, perche' salva un bel
po' di casini dopo. 
Poi, ovviamente, le eccezioni "previste" saranno incapsulate in eventi e
notificate col meccanismo di dispatching scelto, ma e' un altro discorso. 


semplicemente terminare gracefully) eccetera.
Esatto, siamo allineati ;-)
Ciao


pratica :)
Dopo aver letto la tua documentazione ho capito che.... sto
già applicando questo metodo, e in effetti funziona molto bene e 
imho è
anche molto elegante :))



http://groups.google.com/groups?hl=en&selm=3c4705d6.24949946%40news.inet.it
Grazie per l'interesse, ma la mia non è un'applicazione web, per cui non mi
scontro con i problemi di quel thread
Ciao


> generico strato di comunicazione
Quello che cercavo di suggerirti e' che stavi spendendo forse troppo tempo sul "come"
risolvere il problema da un punto di vista puramente tecnico tralasciando il design del
sistema stesso (lo so, suona male detto da me che sono un XPer ma qui stiamo facendo BDUF,
Big Design Up Front).
Il fatto che ci sia un thread a gestire *tecnicamente* il colloquio non ti deve guidare
piu' di tanto nel design che fai: questo e' un dettaglio implementativo interno, e non e'
certo quello che ti guida nella strutturazione della tua applicazione. Certo, puo' essere
un ottimo punto di partenza ma quando ti chiedi se la tua applicazione e' "strutturata
correttamente", devi sicuramente farlo anche osservando il sistema da un punto di vista di
puro design. E il thread ne e' un dettaglio implementativo che si trova ad un livello
molto basso.
Suggerendoti di usare il suo framework Cristiano penso stia forse cercando anche lui di
guidarti, beh, in un modo un po' piu' esplicito :-D, ad osservare la tua applicazione da
un punto di vista di design, non di implementazione.
Se non sono stato chiaro o hai dubbi, posta.


molto basso.
Forse ho sbagliato a dire thread e non classe, che forse
sarebbe piu' corretto, ma la mia domanda era capire appunto se dal punto di
vista logico l'applicazione era organizzata correttamente oppure se,
dall'alto della mia inesperienza, c'era qualche grava problema che me
l'avrebbe fatta zoppicare perchè non pensata correttamente.
Cmq, come ho
già risposto a Cristiano, avevo già implementato un framework simile al suo
come struttura e logica, quindi penso di essere sulla buona strada: ho la
mia classe principale (il client vero e proprio) che è un listener e riceve
in questo modo i messaggi che gli vengono mandati dal server. Per il
momento è una classe separata che lavora con i socket e mi genera tali
eventi ma, ritornando al tuo suggerimento, basterebbe cambiare quella
classe (o aggiungerne delle altre specialzzate filtrate da una piu'
generica) per cambiare la tipologia di comunicazione client-server senza
che la parte del client di alto livello ne risenta. Dico giusto o non ho
capito una mazza? :))
Grazie



Giusto! Come vedi stai parlando e descrivendo il tuo sistema ad un livello di astrazione
piu' alto: devi solo + eliminare i termini "classe" e "socket", e poi ci sei  :-D
Davvero, e' molto importante farsi capire.


 Davvero,
e' molto importante farsi capire.
Prima o poi grazie alle vostre
correzioni arrivero' anche io ad usare i termini corretti, nel prossimo
post (che arrivera', non temete :)) cerchero' di utilizzare una
terminologia piu' corretta. Adesso vado avanti felice nell'implementazione
dei miei thre... ehm... oggetti  :)))))
Ciao


 anche molto elegante :))
Ottimo! :-) 


 nella strutturazione della tua applicazione. 
Giusto una nota, per bilanciare. :-)
Imho, il threading e' una delle cose che attaccare come "ripensamento",
dopo il design, e' certamente possibile ma estremamente costoso (e
pericoloso per la qualita' dell'applicazione). 
'nsomma, se una certa parte del sistema e' concorrente o meno e' qualcosa
che s'ha da decidere quanto prima. Poi, ovviamente, puoi scrivere
"thread" o scrivere "pincopallo", ma essere concorrente o meno e' una
proprieta' strutturale di un sottosistema, e i linguaggi d'oggidi' (anche
Java, che qui fa meglio di molti altri) non permettono di modificarla a
basso costo, a meno di casi molto semplici. 
Insomma, di certo non ti guida il nome "thread"  - ma l'idea di
concorrenza eccome. 


>
La mia posizione e' che la probabilita' che questo succeda quando si lavora ad un livello
di astrazione molto alto (come diceva il post originale: "La mia applicazione e'
strutturata correttamente?") e' decisamente bassa, e quando ci si trova a farsi guidare
nello design da questo, beh, secondo me bisogna decisamente dubitare.
E nel caso in oggetto, ha decisamente da dubitare :-D


 punta delle dita. 
Be', se nel tuo codice usi, ad esempio, chiamate a metodi esposti da
un'interfaccia (che e' ormai, vivaddio, prassi quasi comune :), traslare
le cose in due flussi di controllo concorrenti implica o riscrivere
*tutte* le invocazioni come notifiche di eventi, e fornire un dispatcher
che traduca gli eventi in method calls (aggiungi eccezioni checked e hai
un ginepraio, perche' per quello che prima facevi automaticamente con lo
stack unwinding devi farlo a mano con notifiche di eccezioni e un
exception handler; aggiungi eccezioni unchecked e devi scrivere codice
per evitare morti premature e poco chiare del thread in cui sono
sollevate :); oppure reimplementre l'interfaccia in modo che sia lei a
fare la notifica - in genere ad un receiver che controlla
un'implementazione client dell'interfaccia e fa il demarshalling
evento-invocazione (ottenendo in pratica stubs/skeletons, alla RMI o
CORBA per intenderci). 
Insomma, fattibile si', ma prima ci si pensa meglio e'. :)
Non e' un caso, ad esempio, che proprio per questi motivi quando in Sun
progettarono RMI decisero che RemoteException era *checked*.. 
