MokaHints
Fattorie Remote
di 
Giovanni Puliti
Grazie all'utilizzo del pattern Factory, è possibile implementare architeture distribuite basate su RMI in modo molto più flessibile

RMI è un modello di programmazione distribuita molto semplice ma anche molto potente. La sua estrema semplicità pero' in certi casi si paga con una certa rigidità che invece altri modelli (vedi ad esempio CORBA) non hanno. Vediamo in questo articolo come sia possibile aggirare alcune limitazioni di RMI, senza modificare il modello teorico.

RMI e la programmazione per pattern 
L’estrema semplicità con cui è possibile realizzare applicazioni distribuite in Java, permette sicuramente di semplificare enormemente il lavoro, ma spesso si dimostra essere anche la sua principale limitazione. 
Alcune delle limitazioni imposte dal modello alla base di RMI possono essere superate in maniera piuttosto brillante grazie ad una opportuna progettazione della struttura delle classi che compongono lo scheletro dell’applicazione. In particolare la programmazione per pattern ([GOF] [java pattern] [mokabyte pattern]), permette di dar vita ad interessanti soluzioni, e proprio per questo saranno presi in esame due pattern particolarmente utili, il Factory Method ed il Command.
 
 
 

RMI ed il Pattern Factory
Se si ripensa per un momento alla modalità di pubblicazione di un oggetto remoto da parte del server RMI, si potrà osservare come la funzione di creazione e registrazione è un compito totalmente a carico del server
Per una precisa scelta progettuale quindi, visto che la registrazione dell’oggetto avviene una volta sola, l’istanza dell’oggetto remoto sarà l’unica disponibile e quindi condivisa fra tutti i client possibili. 
Pensata per la massima semplicità possibile, in molti casi però questa soluzione risulta essere troppo rigida e non sufficiente per creare strutture distribuite complesse.
Si pensi ad esempio a tali oggetti come a veri e propri servizi messi a disposizione dal server, accessibili dal client proprio perché oggetti remoti,  e per questo per brevità verranno qui chiamati “oggetti remoti di servizio”.
Per  rendere tali oggetti pubblici ed invocabili da un client RMI, si potrebbe pensare di crearne un certo numero, e successivamente di  registrarli nel registro remoto con nomi differenti.
Ovviamente tale soluzione non risolve il problema della condivisione fra i vari client, dato che  per tanti che possano essere gli oggetti remoti di servizio registrati, i client potrebbero essere in numero maggiore;  inoltre tale organizzazione non risolve il problema della creazione on-demand da parte del client.
Sebbene il modello teorico di RMI non prevede, almeno per il momento, una soluzione a tale limitazione,  grazie all’utilizzo di un particolare schema progettuale, il pattern factory appunto,  vi si può ovviare in modo piuttosto semplice.
Si supponga ad esempio di avere una insieme base di oggetti strutturati come riportato in figura  1. 
Si tratta di una semplice gerarchia di classi per la gestione dei messaggi di log all’interno di una applicazione: per semplicità verrà preso in considerazione il caso in cui sia presente il solo metodo log(String messaggio) per la produzione di tali messaggi.
La classe base (Logger) quindi serve per gestire messaggi di tipo generico, mentre le due derivate potrebbero implementare tecniche particolari per la gestione di messaggi verso file (classe FileLogger) e verso uno stream generico (classe StreamLogger)
 



Figura 1  struttura gerarchica di base per la gestione di messaggi di log

A tal punto si può immaginare che un ipotetico client possa aver bisogno di utilizzare i servizi di un oggetto di tipo  FileLogger  oppure StreamLogger,  ad esempio per memorizzare alcune informazioni relative al suo funzionamento.
Si potrebbe quindi ipotizzare che ogni client debba o voglia poter produrre messaggi propri indipendentemente dagli altri, e che tali messaggi siano gestiti da un server centrale.
Utilizzando RMI allora si dovrà per prima cosa creare n oggetti remoti (in teoria uno per ogni client che desideri fare log da remoto)  e successivamente registrarli.
Per rendere remoti gli oggetti visti in precedenza è necessario modificare leggermente la gerarchia di classi, cosa che può portare ad una organizzazione delle classi come quella riportata in figura 2
 
 


Figura 2 Versione remota delle classi per la 
gestione dei messaggi da client RMI




Come si può notare, la classe base è stata sostituita dalla interfaccia remota RemoteLogger, la quale, oltre a sopperire alla funzione di interfaccia standard, permette alle sotto classi di essere oggetti remoti a tutti gli effetti.
Si è predisposta in tal modo la base per permettere l’utilizzo da client RMI di oggetti remoti. 
A questo punto si deve predisporre un qualche meccanismo  che permetta la creazione di tali oggetti anche da parte di client RMI.

La classe LoggerFactory che implementa il cosiddetto pattern factory, è a tutti gli effetti un oggetto remoto come quelli visti in precedenza: tramite la sua registrazione nel registro RMI, ogni client potrà ottenerne lo stub ed invocarne il metodo remoto getLogger(), la cui implementazione è riportata di seguito
 
 
 
 

public RemoteLogger getLogger(int type) throws RemoteException{
    RemoteLogger ret=null;

    if (type == 1){
      ret= new RemoteFileLogger();
    }

    if (type == 2){
      ret= new RemoteStreamLogger();
    }
  return ret;
}
 
 

Come si può notare tale metodo controllando il valore del parametro passato, è in grado di restituire un oggetto (remoto) di tipo FileLogger  e StreamLogger; più precisamente viene restituita una interfaccia remota Logger, cosa che permette di mantenere la massima genericità possibile.
Da un punto di vista organizzativo le classi remote che implementano il factory sono strutturate secondo lo schema UML riportato in figura 3
 
 


Figura 6 Il factory remoto




Il client invocando il metodo remoto getLogger() riceverà lo stub dell’oggetto remoto, il quale verrà eseguito sul server remoto, in perfetto accordo con il modello teorico di RMI.
 
 
 

Conclusioni
Come si è potuto vedere, grazie all'utilizzo di un semplice patter come il Factory, si è potuto implementare una soluzione molto semplice per superare alcune limitazioni imposte dalla architettura di RMI. Si tenga presente che pur senza effettuare nessuna modifica al modello teorico di RMI, si è ottenuto un comportamento fortemente diverso da quello base. Per chi volesse approfondire ulteriormente la programmazione dei pattern si consiglia la lettura di [1], e sopratutto del corso iniziato su MB nel numero 26, di Gennaio 1999.
 
 
 

Bibliografia
[1] - "Java Design Patterns  A Tutorial"  di James William Cooper, James W. Cooper 
Ed. Addison-Wesley Pub CoI  ISBN 0201485397
[2] - "Distributed Programming With Java " di Qusay H. Mahmoud - Ed. Manning Publications Company  ISBN: 1884777651 
 

Chi volesse mettersi in contatto con la redazione può farlo scrivendo a mokainfo@mokabyte.it