martedì 29 gennaio 2013

Moduli Mancanti

Vorrei dire ai più pessimisti e ai tecnici più radicali nell'adesione alle regole, che in informatica c'è ancora molto spazio per un po' di fantasia, ma ancora di più ci dovrebbe essere spazio per un ritorno alla semplicità.

E' passato troppo tempo dall'ultimo post, tempo che ho impiegato nella mia attività di programmatore indipendente, ma adesso sento il bisogno di esprimere qui un concetto, che non mi sembra banale, purtroppo però pare che chi crea strumenti non ne abbia ancora preso coscienza:
quando si sviluppa un programma modulare, bisogna tenere presente sempre che un modulo potrebbe NON ESISTERE al momento della chiamata.

Non è un dettaglio da poco.

Ritenere che un modulo sia sempre installato, quindi che la presenza sia sempre certa è a mio avviso un grave errore progettuale, che inficia lo stesso vantaggio della modularità. Non basta sapere che posso sostituire un modulo con un altro, che ha un'implementazione diversa, mantenendo la stessa interfaccia, perché nel momento in cui si toglie un modulo necessario, per sostituirlo, l'applicazione deve essere FERMA. Questo non è sempre tollerato e tollerabile in tutte le situazioni.
Se l'alternativa è usare un cluster di server, francamente non mi sembra una soluzione, bensì una pezza costosa necessaria per la mancanza di un software moderno.

Non mi sembra sensato che, perché si cambia un logger, un sito con migliaia di visite si debba bloccare.
Ma anche nel momento in cui la modifica sia più importante, penso ad esempio ad un componente di back end per comunicare con web service, la sostituzione dovrebbe portare ad un messaggio di errore, oppure all'accodamento dell'invio dei dati in un sistema di bus.

Il tema della mancanza del modulo chiamato è affrontato malissimo in Java enterprise. Non esiste a livello di linguaggio qualcosa che si avvicini ad un'architettura modulare.

Se si usano le chiamate JNDI,  si può gestire la mancanza della parte chiamata, ma JNDI usa delle stringhe non standard tra un application server e un altro, perciò è un modo orribile per mantenere il progetto. Un diverso application server può usare parole diverse e una stringa non ha aiuti dal compilatore, quindi sbagliando a scrivere una parola, si ottiene un errore a runtime.

Le injection delle ultime specifiche hanno risolto il problema delle stringhe, ma ne hanno introdotto uno più grave: una risorsa iniettata può mancare e si ottiene una bella NullPointerException, chiamandola.

Il sistema modulare migliore ad oggi tra quelli disponibili, è OSGi. Purtroppo il supporto degli strumenti di sviluppo sotto questo punto di vista è scandaloso. Un oggetto esposto come servizio ha un'interfaccia, come best practice. Ora, la specifica suggerisce che il modulo chiamante crei un wrapper dell'oggetto esportato, implementando la sua stessa interfaccia, in modo che quando il client chiama un metodo, non sappia se sta chiamando il wrapper o il servizio vero e proprio, in modo che la mancanza del modulo chiamato sia gestita dentro al wrapper, magari con un messaggio per l'utente o per per accodare i dati. Tutto questo a mano ? Ma è ridicolo !  Non tutti lavorano per grosse multinazionali con budget enormi ! Non ho trovato aiuti in giro per questo punto, così importante.

La spiegazione che mi do su questa mancanza è che, soprattutto nei progetti piccoli,  la realtà è che ciò che si sviluppa non è un vero progetto software, ma un prototipo da vendere ! Chi fa moduli in un prototipo ? Nessuno.

Possibile che i pattern, la programmazione a oggetti, il buon senso siano tutti lussi ? No.

Non conosco Objective C, però ho letto che si possono passare messaggi (chiamare metodi) che non esistono e che possono trovarsi a runtime. Questo non è sempre ideale, anzi, ma forse negli anni 80 qualcuno si poneva il problema di chiamare un modulo che non c'è? Le shared object di mac os x si possono scaricare dinamicamente come i bundle di OSGi. Forse la soluzione esiste se la si cerca ?

Possibile che Java, il linguaggio dell' ubiquitous computing, non tenga conto minimamente di questa problematica ? Lasciare il problema a OSGi e rimandare continuamente il progetto Jigsaw non è una buona notizia, soprattutto se si vede a cosa si è dato priorità, come i generics, orribili.

A me viene da dire che il mondo Java, che uso da sempre, si concentri troppo sul linguaggio e troppo poco sugli strumenti ! Invece che cercare novità nelle annotation, sarebbe meglio spingere sullo sviluppo di generatori di codice che lascino al programmatore la scrittura di interfacce e implementazioni, queste ultime comunicanti con un sistema a bus, con una gestione della mancanza dell'oggetto chiamato, direttamente nel codice generato.

Il boiler plate necessario per un sistema moderno a volte è lo stesso che si usava 20 anni fa sui vecchi programmi legacy in c++.

Non abbiamo imparato niente da allora? Con tutti i problemi di memoria condivisa dei programmi multithread, non sarebbe il caso di rivalutare i vecchi task singoli, con un sistema (cross platform, please) che faccia comunicare i vari task, gestendo la mancanza del chiamato con un bus o un'altra forma che si possa decidere al momento della generazione del codice "collante" ?

Con finalmente un sistema standardizzato e semplice per aggiornare i moduli obsoleti ? Incredibilmente, OSGi ne è privo !

OSGi è sinceramente una buona idea, ma è stato concepito per girare su macchine con risorse scarsissime, in team con budget abbondantissimi ! Il core ha pochissime funzionalità. Oggi ci vuole un core che incorpori già un web server, un sistema di log moderno e standard e che non faccia impazzire con i classloader, che sono un delirio sotto OSGi, soprattutto quando si vuole usare librerie che non sono nate per OSGi e che usano internamente i classloader, perché chi le ha sviluppate, pensava a un sistema modulare, ma non ne aveva uno buono...