[Pubblichiamo un estratto da un classico della letteratura informatica, tradotto in dieci lingue e con oltre centomila copie vendute, che più di ogni altro nel suo settore potrebbe favorire il vero salto di qualità nel lavoro del programmatore].
Di solito non si associa la parola eleganza ai detective della polizia, che invece richiamano magari alla mente il luogo comune delle ciambelle con il caffè. Pensiamo però come i detective possano usare una lavagna per coordinare le indagini su un omicidio e risolverlo.
Supponiamo che l’ispettore capo cominci con il far installare una grande lavagna nella sala riunioni. Sulla lavagna, poi, scrive un’unica domanda:
H. DUMPTY (MASCHIO, UOVO): INCIDENTE O OMICIDIO?
Humpty è davvero caduto, o è stato spinto? Ogni detective può contribuire a questo potenziale caso di omicidio aggiungendo fatti, dichiarazioni dei testimoni, ogni prova forense che si scopra e così via. Mentre i dati si accumulano, un detective può notare un collegamento e scrivere sulla lavagna la sua osservazione o la sua ipotesi. Il processo continua, un turno dopo l’altro, con persone e agenti diversi, finché il caso non viene chiuso. (Un esempio di lavagna è in questa figura.)
Ecco alcune caratteristiche fondamentali del metodo della lavagna.
- Nessuno dei detective deve sapere dell’esistenza di altri detective; ciascuno guarda la lavagna per scoprire le nuove informazioni e vi aggiunge quanto ha scoperto.
- I detective possono essere addestrati in campi diversi, possono avere livelli diversi di istruzione e di esperienza, possono non lavorare nello stesso distretto. Hanno in comune il desiderio di risolvere il caso, ma niente altro.
- Nel corso delle indagini possono andare e venire detective diversi, e possono lavorare in turni diversi.
- Non ci sono limitazioni su quello che può essere messo sulla lavagna. Possono essere foto, frasi, prove fisiche e così via.
Abbiamo lavorato a molti progetti che comportavano un flusso di lavoro o un processo di raccolta di dati distribuiti. In tutti i casi, progettare una soluzione sulla base di un semplice modello a lavagna ci ha fornito una metafora concreta su cui lavorare: tutte le caratteristiche elencate sopra parlando di detective sono applicabili a oggetti e moduli di codice.
Un sistema a lavagna permette di disaccoppiare completamente gli oggetti, gli uni dagli altri, mettendo a disposizione una “piazza” in cui consumatori e produttori di conoscenza possono scambiarsi dati in forma anonima e asincrona. Si riduce anche la quantità di codice da scrivere.
Implementazioni a lavagna
I sistemi a lavagna basati su computer sono stati inventati per l’uso in applicazioni di intelligenza artificiale dove i problemi da risolvere erano grandi e complessi: riconoscimento del parlato, sistemi di ragionamento basati sulla conoscenza e così via.
Sistemi distribuiti moderni simili a lavagne, come JavaSpaces e T Spaces si basano su un modello a coppie chiave/valore, presente per la prima volta in Linda, dove l’idea si chiamava tuple space (spazio di ennuple).
Con questi sistemi, si possono memorizzare oggetti Java attivi (e non solo dati) sulla lavagna, e li si può poi recuperare per corrispondenza parziale di campi (attraverso schemi e jolly) o per sottotipi. Supponiamo per esempio di avere un tipo Author, con un sottotipo Person. Si potrebbe effettuare una ricerca in una lavagna contenente oggetti Person utilizzando uno schema Author con il valore “Shakespeare” per lastName. Si otterrà Bill Shakespeare l’autore ma non Fred Shakespeare il giardiniere.
Le operazioni principali in JavaSpaces sono:
Nome | Funzione |
---|---|
read | Cerca e recupera dati dallo spazio. |
write | Inserisce un elemento nello spazio. |
take | Simile a read, ma quando trova un elemento lo elimina anche dallo spazio. |
notify | Imposta il verificarsi di una notifica ogni volta che viene scritto un oggetto corrispondente allo schema. |
T Spaces ha un insieme simile di operazioni, ma con nomi diversi e una semantica leggermente diversa. Entrambi i sistemi sono costruiti come un prodotto database: mettono a disposizione operazioni atomiche e transazioni distribuite per garantire l’integrità dei dati.
Poiché possiamo memorizzare oggetti, possiamo usare una lavagna per progettare algoritmi sulla base di un flusso di oggetti e non solo di dati. È come se i nostri detective potessero appendere alla lavagna persone in carne e ossa, i testimoni e non solo le loro dichiarazioni. Chiunque può fare domande a un testimone nell’ambito del caso, appendere la trascrizione e spostare il testimone in un’altra area della lavagna, dove potrebbe rispondere in modo diverso (se si consente anche al testimone di leggere la lavagna).
Un grande vantaggio di sistemi come questi è che si ha un’unica interfaccia coerente verso la lavagna. Quando si costruisce un’applicazione distribuita convenzionale, si può dedicare molto tempo a mettere a punto specifiche chiamate API per ogni transazione e interazione distribuita nel sistema. Con l’esplosione combinatoria di interfacce e interazioni, il progetto può diventare rapidamente un incubo.
Lo stile di programmazione a lavagna elimina il bisogno di molte interfacce e permette di ottenere un sistema più elegante e coerente, purché la lavagna sia organizzata: quando i detective lavorano su grandi casi, può diventare molto ingombra, e può risultare difficile trovare i singoli dati. La soluzione è suddividere in parti la lavagna e iniziare in qualche modo a organizzare i dati.
Sistemi software diversi gestiscono questo partizionamento in modi diversi: qualcuno usa strutture piatte a zone o gruppi di interesse, altri adottano una struttura più gerarchica, ad albero.
Un esempio applicativo
Supponiamo di dover scrivere un programma che accetti ed elabori domande di mutuo o di prestito. Le norme che governano il settore negli Stati Uniti sono orrendamente complesse: le amministrazioni federali, statali e locali hanno tutte qualcosa da dire in merito. Il prestatore deve dimostrare di aver comunicato certe cose e deve chiedere certe informazioni, ma non deve fare certe altre domande e così via.
Al di là del marasma di leggi di cui tener conto, abbiamo da affrontare anche i problemi seguenti.
- Non c’è alcuna certezza sull’ordine in cui arriveranno i dati. Per esempio, le interrogazioni per una verifica del credito o per una ricerca catastale possono richiedere quantità di tempo sostanziose, mentre informazioni come nome e indirizzo possono essere subito disponibili.
- La raccolta dei dati può essere fatta da persone diverse, distribuite in uffici diversi, in fusi orari diversi.
- In parte la raccolta dei dati può essere effettuata automaticamente da altri sistemi. Anche questi dati possono arrivare in modo asincrono.
- Ciononostante, certi dati possono essere comunque dipendenti da altri dati. Per esempio, magari non si può iniziare la ricerca di un’auto finché non si ha un documento di proprietà o di assicurazione.
- L’arrivo di nuovi dati può sollevare nuove domande e determinare nuove politiche. Supponiamo che la verifica del credito restituisca indicazioni tutt’altro che entusiasmanti: a questo punto serviranno altri cinque moduli e magari anche un campione di sangue.
Possiamo cercare di gestire ogni possibile combinazione e ogni possibile circostanza utilizzando un sistema a flusso di lavoro. Esistono molti sistemi del genere, ma possono essere complessi e richiedere molto lavoro di programmazione. Al variare dei regolamenti, il flusso di lavoro deve essere riorganizzato: le persone devono magari modificare le loro procedure e se il codice è troppo rigido deve essere riscritto.
Una lavagna, insieme con un motore di regole che incapsuli le norme legali, è una soluzione elegante a queste difficoltà. L’ordine di arrivo dei dati non è rilevante: quando viene comunicato un fatto, può attivare le regole appropriate. È facile anche gestire il feedback: l’output di qualsiasi insieme di regole può finire sulla lavagna e provocare l’attivazione altre regole pertinenti.
Possiamo usare la lavagna per coordinare fatti e agenti diversi, mantenendo però l’indipendenza e anche l’isolamento dei partecipanti, uno rispetto all’altro.
Si possono ottenere gli stessi risultati con metodi più basati sulla forza bruta, ovviamente, ma i sistemi che si otterrebbero sarebbero più fragili. Se si rompono, c’è il rischio che nessuno sia più in grado di far funzionare di nuovo il programma.
Prima di qualche esercizio, riflettere: usate dei sistemi a lavagna nel mondo reale, per esempio la bacheca per i messaggi vicino al frigorifero o una grande lavagna bianca al lavoro? Che cosa li rende efficaci? I messaggi vengono inseriti con un formato coerente? È importante?
Esercizi
Per ciascuna delle applicazioni seguenti, un sistema a lavagna sarebbe appropriato oppure no? Perché?
- Elaborazione di immagini. Vorreste avere una serie di processi in parallelo che prendono parti di un’immagine, le elaborano e poi rimettono a posto i pezzi completati.
- Calendari di gruppo. Avete persone sparse per il pianeta, sotto fusi orari diversi e che parlano lingue diverse, e una riunione da pianificare.
- Strumento di monitoraggio della rete. Il sistema raccoglie statistiche sulle prestazioni e segnalazioni di gusti. Vorreste implementare qualche agente che le usi per verificare i problemi nel sistema.