Newsgroup: it.comp.java
Titolo: comunicazione (socket) e gestione eventi associati

ciao, ho fatto un progetto che usa una classe che gestisce tutto il
meccanismo di comunicazione, e che dovrebbe interagire con altre
classi "avvisandole" di eventi e dando la possibilita' a quest'ultime
di lanciare messaggi al server.
Ho pensato di fare in modo che, quando leggo un certo comando da
socket, la classe di I/O vada a richiamare un particolare metodo di
una certa classe, che NON e' nota a priori, nel senso che sarebbe
meglio NON cablare questa caratteristica nel codice, ma dare la
possibilita' di specificare a run-time il metodo da richiamare.
Insomma, io posso passare come variabile una funzione?
ciao e grazie
as

 wrote in message
hOInOH0Yc2hIJn...@4ax.com...


Insomma, io posso passare come variabile una funzione?
Ci sono due (tre) strade:
- usare la reflection per invocare il metodo basandosi sul suo nome, dove 
il 
nome e' specificato dinamicamente.
- definire un'interfaccia che vada implementata. Il metodo va definito 
ovviamente ad usage-time e non a run-time, ma quasi sempre questo e' 
accettabilissimo. Questo e' il metodo migliore, e piu' pulito di norma.
public interface Callable {
 public void receive(Object target);
}
ad esempio puoi dare un'occhiata al framework di comunicazione asincrona 
tra 
thread a 
http://space.tin.it/computer/csadun/software/lf
- usare un pattern di incapsulamento appropriato. Questo dal punto di vista 
del 
design ha senso solo quando non e' *strutturalmente* possibile (o voluto, 
come 
nel tuo caso) usare direttamente un'interfaccia. Definisci un'interfaccia 
"Azione" che incapsula la tua funzione:
public interface Action {
 public Object execute(java.lang.Vector parameters);
}
e la tua classe, invece di esporre direttamente metodi, espone oggetti 
"Action" 
che contengono il codice appropriato. 
Un'eventuale implmenentazione "standard" di Action puo' avvalersi della 
reflection per invocare un metodo per nome. Oppure, piu' comunemente, il 
tuo 
oggetto Action contiene direttamente il codice. Una Action e' un "oggetto-
funzione", in altri termini.
Ovviamente andra' "registrato" presso la tua classe di I/O insieme alla 
classe 
che lo "espone", in modo che la tua classe sappia quando chiamarlo.
Un modo per avere velocemente un meccanismo di registrazione e' ereditare 
da 
una classe tipo "com.deltax.util.ListenerSupport" nel software che ti 
nominavo 
sopra.
Una nota di design. Usare un'approccio del genere va fatto solo quando c'e' 
poca o nulla alternativa.. se appena appena puoi definire un'interfaccia 
comune, *quella* e' la strada migliore. 
Personalmente ideai il metodo delle "Action" (anche se probabilmente 
esisteva 
gia' ;-) un due/tre anni fa, quando mi trovai a fare il primo wrapping in 
Java 
di un software legacy.. la situazione ci imponeva di cominciare ad 
implementare 
senza *conoscere* esattamente quali caratteristiche comuni ci fossero nelle 
funzionalita' del core software - mi trovavo quindi nell'impossibilita' di 
definire un'interfaccia precisa. 
Dato che le interfacce sono - per come disegno io il software - il perno di 
tutto il design, non mi posso quasi mai permettere di cambiarle a meta' 
strada. 
La tecnica delle Action permise di rendere anche l'interfaccia del tutto 
dinamica e adattabile alle oltre 200 funzioni del prodotto finale. 
Il prezzo, pero', e' abbastanza elevato: piu' complessita', un meccanismo 
di 
framework che emula una funzionalita' di base del linguaggio (le 
interfacce) e 
che - come sempre accade - non puo' avere la stessa qualita' in termini di 
compile-time check e prevenzione degli errori, etc. Quindi, come idea 
generale, 
ci *deve* essere un motivo piu' che serio per usarlo. Se e' giusto perche' 
"vuoi".. ripensaci. :)
-- 
God is Real, unless declared Integer.
ObjectZone - 
http://space.tin.it/computer/csadun/

del  design ha senso solo quando non e' *strutturalmente* possibile (o voluto, 
umh... dunque, se permetti ti spiego megli i problema partendo dalla
radice: vedi io sono ancora uno studente e mi piace MOLTO affrontare
questi problemi di design (da grande voglio fare il capo...!).
scherzi a parte ecco una brevissima spiegazione di quello che devo
fare (e perche'):
specifiche in linguaggio naturale:
l'applicazione deve mettere a disposizione una carta geografica che
riporta il mondo diviso in n regioni. Ciascuna di queste ha un nome e
un paio di dati che vanno riportati sulla cartina stessa. Gli utenti
(ciasuno dal proprio pc collegati al server) devono poter interagire
con la cartina, ed effettuare un certo numero di azioni che prevedono
l'interazione con i valori riportati sulla cartina. Senza entrare nel
dettaglio, ipotizziamo che ci siano 4 azioni diverse che devono
cumunicare al server alcuni dati E la regione scelta sulla cartina.
Spero di aver dato una spiegazione sufficientemente dettagliata per
farti capire piu' o meno come gira la cosa.
Io solitamente parto cosi': mi disegno su un foglio dei pallini che
sono le classi e ci aggiungo i metodi e le relazioni fra le varie
classi. Inoltre costruisco un nucleo di classi abstarct che vanno e
definire le funzioni principali, lasciando pero' il compito ad altre
classi derivate di implementare effettivamente il lavoro, per il
seguente motivo:
io sono contrario ad inserire cose tipo l'interfaccia grafica nel
codice dell'applicazione (amo molto visual basic immaginerai). Insomma
volgio che l'applicazione necessiti di una sola piccola modifica nel
caso io volgia usare una cartina basata su un disegno vettoriale
realizzato con i polygons piuttosto che con una gif piuttosto che con
una schermata basata su testo. Stessa cosa per l'interfaccia di
comunicazione, ora ne volevo scriveer una basata su socket, ma vorrei
poterne fare una basata su corba piuttosto che RMI o con metodi nativi
che sfruttino IPX (questa me la sono inventata adesso). Ora uso i
socket perche' l'applicazione dovrebbe girare su un canale condiviso
da tutti i pc a 2400bps (CP/IP over AX.25 via radio), e voglio contare
i bit che mi passano...
insomma, tornando al discorso principale, io faccio abbondante uso di
classi astratte e poi nella classe principale (quella che poi eseguo)
istanzio il giusto insieme di classi specifiche. Va da se che questo
approccio deve consentirmi di specificare alle varie classi come
comunicare fra loro...
la classe che gestisce il servizio A, cosa richiama quando viene
premuto il suo bottone? Dato che opero una totale dissociazione
dall'interfaccia grafica, non so assolutamente chi e' preposto a
gestire l'input (la tastiera o una classe che gestisce la mappa in
modo grafico col mouse?)
Insomma, che ne dici di questo metodo di design? E' in qualche modo
usato male?
Grazie e ciao!
as
P.S. da poco uso togetherJ per il design, perche' permette di generare
automagicamente il codice in tempo reale, e' di una comodita'
estrema!!!

usato male?
LOL Le motivazioni mi sembrano quelle giuste, e credo che condividiamo 
l'opinione su visual basic. :) Sul processo di analisi/design vero e proprio, 
non so, ognuno ha il suo ;-). L'unica cosa che posso dire e' che io evito di 
introdurre specializzazioni (distinzioni tra classi base e derivate) da subito, 
a meno che non siano proprio evidenti, e preferisco ragionare per ruoli&classi, 
invece che per classi soltanto. 
Inoltre, sviluppo allo stesso tempo (in testa e/o in diagrammi) sia la parte 
statica (classi e relazioni) che quella dinamica (interazioni tra oggetti e/o 
ruoli). Trascurare la seconda e' - nella mia esperienza - un errore tipico di 
team di design "principianti"... se vedi qualcuno che come documentazione ti 
propina due chili di diagrammi di classi, ma nemmeno una velina che specifichi 
l'interazione runtime degli oggetti di quelle classi, nove su dieci sei in 
presenza di un team al suo primo/secondo progetto OO. :)
Mi par di capire comunque che le tue "classi abstract" altro non siano che 
interfacce ("ruoli") - che mettono a disposizione servizi prescindendo 
dall'implementazione, quindi mi par di condividere l'impostazione. 
Un'altra cosa importante imho e' il fatto che - contrariamente a quanto a volte 
si sente dire - non e' che progettando OO ci si dimentica delle 
implementazioni.. al contrario, si tiene conto *contemporaneamente* di tutte le 
possibili implementazioni! Quello che non si fa (compatibilmente coi requisiti) 
e' la *scelta* a priori tra esse. 
E' per questo che un buon analista/designer *deve* imho avere un'ottima 
competenza tecnologica.. perche' deve tener conto di tutti i possibili modi 
(passati, presenti, e possibilmente futuri ;-) di implementare l'analisi/design 
che produce.
Tieni presente che tutto questo (ad esempio nel sistema che descrivi) non 
significa non poter imporre *staticamente* requisiti a tali interfacce.. ma 
vuol dire semplicemente che e' necessario astrarre *tutto* quanto serve. :)
Ad esempio, se vuoi astrarre la comunicazione per renderla indipendente 
dall'uso di socket, corba, rmi etc, ci sono due passi da fare. Il primo e' 
quello di definire l'architettura, identificando attori e ruoli: ad esempio, il 
fatto che esiste un oggetto 'canale', c'e' il ruolo di 'coordinatore della 
comunicazione', che tale coordinatore gestisce uno o piu' canali, e che li 
richiede al sistema operativo all'inizio dell'escuzione. 
Poi passi a definire le caratteristiche specifiche - che ti porta ai metodi 
dell'interfaccia 'coordinatore'.. per definire i quali dovrai definire 
(astrattamente) nuove altre interfacce, ad esempio 'richiedente', 
'osservatore', etc. E cosi' via.
In ogni momento valuti quanto sia l'architettura che le caratteristiche 
specifiche siano rigide o flessibili, e quanto ti costa questa rigidita' o 
flessibilita', note tutte le possibili implementazioni che ragionevolmente puoi 
farne. Alla fine ti trovi con un set di interfacce di cui hai gia' in mente le 
possibili implementazioni e i possibili costi.
Oppure, per le tue mappe, puoi definire un ruolo specifico per un oggetto che 
debba interagire con una mappa.. ad esempio [Selezionatore = qualcuno che 
seleziona sottoinsiemi di una mappa (che a loro volta sono mappe)], che ti 
porta a 
 interface Selector {
   public Map select(Map m);
 }
se un particolare modo di selezionare su una mappa e' usare il mouse 
oppure la tastiera avrai
class MouseSelector implements Selector { ... }
class KeyboardSelector implements Selector { ... }
Costruendo (o immaginando) le implementazioni, ti renderai conto che tutte 
quante avranno bisogno di alcune operazioni di base, indipendenti dalla 
specifica.. ecco quindi che costruisci una classe astratta da usare con 
l'interfaccia:
 abstract class BaseSelector implements Selector {
  protected void servizioComune();
  ...
 }
la quale probabilmente *non* implementera' nemmeno Selector. Eccetera.
Tutti i tuoi client dovranno (staticamente) aderire a tale interfaccia. Ma, 
dato che suono *tuoi* client, e' una cosa che gli puoi chiedere in 
tranquillita'. :)


e' la *scelta* a priori tra esse. 
certo. Alla fine io avevo chiaro dall'inizio che avrei fatto una prima
implementazione in AWT, alla quale poteva facilmente seguire una
raffinazione modulo per modulo in swing, e parallelamente il mio amico
avrebbe potuto farsi il client in modo testo dato che non ha una
macchina potente.
Insomma: mi sapresti consigliare un testo e dei validi riferimenti che
mi diano un'ampia veduta teorica su questi concetti? Ne sono propio
affascinato. Credi che i vari libri sull'UML (O'reilly etc etc) siano
una buona partenza???
Tu tieni corsi privati per email per caso?!?!??!
ciao e grazie!!!
as

 Tu tieni corsi privati per email per caso?!?!??!
LOL Ho paura di no. :)
Ciao,
 -cris

 macchina potente.
Mi hai fatto venire in mente una serie di articoli che ho letto sul sito
JavaWorld, che trattano l'argomento della separazione interfaccia
utente/logica dell'applicazione nei sistemi OO in modo piuttosto efficace e
per niente scontato (non manca qualche frecciatina ai vari RAD che non
manterrebbero affatto le promesse).
 
Ecco il riferimento:
"Building user interfaces for object-oriented systems", in tre parti
http://www.javaworld.com/javaworld/jw-07-1999/jw-07-toolbox_p.html
Mi piacerebbe sentire un'opinione dei piu' esperti del gruppo, ovviamente
se hanno la voglia e il tempo di leggersi gli articoli :)

 manterrebbero affatto le promesse).
I Rad... la prima volta che vidi il codice generato da visualcafe' quasi mi
venne una sincope! :)

venne una sincope! :)
Hehe..
Ci terrei ad avere una tua opinione sugli articoli... fai in tempo?
Ciao,  
 P.    === Replace "punto" with "." to get my email address.

Anche se lo hai chiesto a Cristiano, mi permetto di commentare io.
Ho letto i tre articoli e ora li sto rileggendo. Ho fatto così tante volte
SI con la testa che quasi mi si sloga il collo, soprattutto quando parla
della dbgrid come il massimo dell'abominazione del RAD. E' inutile e
frustrante cercare di creare oggetto quando hai una porta sempre aperta sul
database.
Ho fatto un programma con un'interfaccia stile Outlook e una grid sempre in
primo piano ma è stato un bagno di sangue: sincronizzare la grid con le
strutture dati è stato sempre un mal di testa gigante.
Anche io ho provato sempre di più nel corso del tempo l'idea che il RAD
finiva sempre per scontrarsi con la struttura della mia applicazione e che
tutti gli widget della toolbar (un terreno di scontro fra gli ambienti RAD
fra chi ne ha di più, chi ha i più potenti) alla fine erano più nemici del
progetto che altro.
Tutto sommato credo che Holub mi vendichi di tante frustrazioni nel corso
degli anni (ho dodicimila righe di codice VB da portare al museo degli
orrori, un progetto nel quale i pochi oggetti presenti sono stati
sopraffatti dal resto del codice).
Sono d'accordo sul fatto che se non si procede in maniera corretta si fa
molto prima a finire un lavoro in C che non a pensarlo in C++, un altro
incubo del passato. La mia produttività in C era molto maggiore e anche
l'affidabilità del codice non era così male.
In conclusione penso che uno sguardo a questi articoli sia praticamente
obbligatorio per tutti quelli che iniziano un progetto adesso e sono stanchi
di ritrovarsi aggrovigliati nel loro stesso codice verso il 70% del lavoro.
Hai presente quando il progetto è quasi finito e il codice di un qualcosa,
quello che appare in quasi tutte le form, cambia formato e regola di
validazione per qualche ragione?
Ah, e per quello che riguarda i tool come la mettiamo?
Io personalmente uso TextPad (o quello che c'è sulla macchina) e il JDK. Il
codice prodotto dai RAD ha sempre qualcosa che non mi va e non voglio
nemmeno avere decine di copie disallineate fra loro del JDK sulla stessa
macchina (quella dentro JBuilder, quella dentro Café e, naturalmente, quella
di Microsoft che è già nel sistema). L'unico RAD che installo è Visual J++
perché é piccolo e leggero e dovrebbe consentirmi di rivedere Visual Basic
quando serve un oggetto COM per qualche ragione.
Adesso la mia scelta come editor è together 3 whiteboard edition, un
ambiente in cui puoi ragionare in UML o Java con aggiornamento reciproco
delle due viste. Peccato che la versione completa di TogetherJ costi una
follia, ma per fortuna quella standard è gratis (
www.together.com
). La
versione 3 è veramente bella e, stranamente, non è lenta come tutti gli
ambienti di sviluppo scritti in Java. Un altro plus è che ti danno gnumake,
jikes e cvs che fanno sempre comodo.
Quanto al debugging, l'unico momento in cui un IDE può far comodo, ho usato
adb, sdb, dbx e gdb per parecchi anni e jdb non è peggio di nessuno di
questi, quindi mi contento di jdb. Java fa fare anche un'infinità di errori
stupidi rispetto al C, quindi il debugger serve di meno.

:
Ho letto (velocemente :( ) il primo articolo e devo dire che mi pare 
ottimo: che e' un'altro modo per dire che io avrei detto le stesse cose, 
non che sia giusto! LOL
In particolare mi piace lo stress sull'interfaccia piuttosto che sui dati e 
l'enfasi sull'idea di oggetto invece che di classe.
L'esempio con l'ATM (bancomat) mi pare simile a quello di Rambaugh nel 
libro su OMT, che di certo non va a disonore del lettore.
Per quanto riguarda i RAD, VC (nella versione che usavo tempo fa) 
implementava il View/Controller con difetti *ancora peggiori* che quelli - 
generici - descritti la'.


 validazione per qualche ragione?
In pratica mi sembra di aver capito che, per quanto riguarda la
realizzazione dell'interfaccia utente nei sistemi ad oggetti, Holub
sostenga la necessita' di considerare la gui come parte dell'oggetto
stesso. Secondo lui, la separazione tra oggetto e relativa gui e' un errore
in una "vera" impostazione ad oggetti, e i motivi che portano a pensare al
contrario (come 
p.es
. il fatto che potrebbe essere utile accedere alle
variabili di un oggetto tramite diversi tipi di interfacce utente) sono in
realta' trascurabili rispetto ai vantaggi derivati dal suo modello.
Holub dice che bisogna concentrarsi sul fatto che un oggetto deve fornire
dei servizi. Es. oggetto pippo, sei un'istanza della classe Impiegati, ora
fammi inserire i tuoi dati con la gui che mi metti a disposizione. E non..
pippo, sei il mio Impiegato; pippoGui, sei la mia interfaccia utente per
gli Impiegati, ora valorizziamo le variabili di pippo leggendo i dati dai
campi di pippoGui. Insomma Holub dice che in un ottica object-oriented,
quando si sente dire "passaggio di dati tra oggetti", vuol dire che c'e'
qualcosa che non va.
Ho letto e testato i suoi esempi, ma devo ancora capirli a fondo. Pero' ho
la sensazione che la sua traccia sia giusta, e non vorrei perdere tempo in
futuro scrivendo programmi in modo piu' "tradizionale" e magari
controproducente. Per questo ci tenevo a sentire altri pareri.
Ah, e' notevole l'esempio del terzo articolo, che e' un po' un corollario
dei precedenti. Viene presentata una gui di un oggetto, che cambia a
seconda dello "spazio" disponibile. Quando viene rimpicciolita, diventa un
pulsante; un po' piu' grande, ed e' un combo-box, se c'e' abbastanza
spazio, e' una lista scorrevole. Non avevo mai visto nulla del genere - e'
il concetto della gui che si adatta al dispositivo fisico portato veramente
agli estremi :)

stesso. 
Questa idea funziona, e bene. E' imho importante mantenere *sganciate* comunque 
le due cose: un oggetto *e'* qualcosa - un'incapsulazione di un fornitore di 
servizi. Tra i servizi forniti, ci sara' quello di provvedere una GUI per 
l'accesso dall'esterno! 
Ora, e' del tutto vero che la GUI deve conoscere i dettagli dell'oggetto logico 
per potervi operare.. quindi e' cattivo design costruirla come classe esterna, 
dato che si devono poi esporre accessors inutili nell'interaccia per accedervi 
(o peggio usare accesso package level).
Tuttavia Java mette a disposizione le classi inner (mai parlato tanto delle 
inner come in questi giorni :), la classe GUI diventa semplicemente una classe 
interna ad un classe "logica": ad esempio
interface PluggableGUIObject {
  public Component getGUI();
}
class Persona implements PluggableGUIObject {
  ..servizi logici..
  private class GUI extends Component {
    ...GUI che agisce su Persona...
  }
  public Component getGUI() { 
    	... ritorna  un'istanza di Persona.GUI su Persona.this.. 
  }
}
(L'interfaccia PluggableGUIObject non e' strettamente necessaria ai fini 
dell'esempio)
In questo modo un oggetto ha una (o piu' d'una) vista come GUI, ed e' 
inseribile semplicemente in un qualunque Container.
Usai l'anno scorso questo approccio per un sistema di cui non si sapeva bene il 
tipo di gui definitiva desiderata e devo dire che sono rimasto parecchio 
soddisfatto. 


 database.
Anche io li ho letti. Sono MOLTO interssanti, soprattutto quando finalmente
l'autore spiega chiaramente che i metodi set e get sono comunque una violazione
della legge di Demeter e non incapsulano un bel niente. Solo pochi altri autori
lo hanno fatto, ed ormai credevo di essermelo inventato io a forza di
ripeterlo... ;)
Ciao
--
Ugo
°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
Enterprise Java Consulting
@mail: Ugo.L...@Flashnet.it
Home URL: 
http://www.ugolandini.net
Mentoring: 
http://www.projectoo.com
Sample Work: 
http://www.sirena.lomb.cgil.it
Work Phone: 02/61860647-6-4
Cell Phone: 0347/6310749 - 0347/4783580
°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°