• Non ci sono risultati.

5.4 Gli aspetti collaborativi della piattaforma

5.4.1 Collaborazione asincrona

Con collaborazione asincrona identichiamo tutti quegli strumenti che permetto di collaborare in istanti dierenti da parte degli utenti, non permettono perciò di collaborare nello stesso momento allo sviluppo di un prodotto.

5.4 Gli aspetti collaborativi della piattaforma 83 5.4.1.1 Notiche

Come è stato illustrato nella parte precedente, tra gli strumenti che permettono la collaborazione asincrona abbiamo previsto la presenza di notiche, che avvisino l'utente in maniera istantanea all'accadere di alcuni eventi.

Tali notiche devono essere visibili in tutti gli ambienti della piattaforma, perché non riguardano un solo ambiente. Infatti il pensiero che ha guidato l'im- plemetazione di tali notiche non è: devo andare nella pagina inerente ai gruppi per ricevere le notiche che riguardano i gruppi, ma: sono in un altro ambiente e mi arriva una notica che mi dice di dirigermi alla pagina dei gruppi perché ho delle azioni da compiere. Ancora meglio se poi la notica stessa, oltre ad avvisarmi che ci sono delle novità per me in una determinata pagina, mi per- mettesse di prendere le decisioni inerenti, ed eseguire le possibili azioni previste per quell'evento, direttamente dal menù delle notiche, senza dover cambiare ambiente!

Per rendere questo possibile è necessaria la presenza dell'istanza di un og- getto che sia unica, in tutte le parti della piattaforma e che funga da centro di notiche. Visto che tale oggetto dev'essere dinamico e si deve aggiornare, modi- cando le informazioni che mostra, non soltanto al caricamento della pagina, ma anche a pagina già aperta, dev'essere per forza un componente client-side, e di conseguenza implementato in Javascript. Infatti all'interno della piattaforma c'è un oggetto di questo tipo, presente in ogni pagina dell'applicazione, che presenta all'interno le funzionalità per la gestione delle notiche.

Per quanto riguarda la visualizzazione delle notiche ci siamo ispirati ad uno dei social network di maggior successo: Facebook. In questa applicazione, le notiche sono composte da un piccolo messaggio di testo che descrive l'even- to accaduto. L'utente coinvolto nella notica, può visualizzarla solo all'interno dell'elenco delle notiche, insieme a tutte le altre, oppure può decidere di visua- lizzarla in maniera più estesa cliccando sulla notica stessa. In entrambi i casi la notica risulterà letta, e perciò non comparirà più tra quelle in primo priano.

In maniera analoga abbiamo pensato impostare il comportamento del nostro gestore delle notiche. Infatti, abbiamo posizionato nella barra in alto della piattaforma un'icona a forma di busta (Figura 5.6), per far capire all'utente che quelli saranno l'equivalente di messaggi che è possibile ricevere.

Possiamo distinguere due fondamentali tipologie di notiche diverse: quelle temporizzate e quelle permanenti.Le notiche temporizzate decadono dopo una nestra temporale denita e vengono perciò cancellate, anche se non sono state ancora lette. Ad esempio se mando un invito ad un utente per un'attività da fare insieme e l'utente invitato non è online, la mia richiesta non potrà rimanere pendente no a quando l'utente non si connette e la visualizza, perché quando questo accadrà, potrebbe essere l'utente che ha mandato l'invito a non essere online. Questo tipo di notiche ha bisogno di un time-out, una nestra temporale che denisca il tempo limite entro cui la notica sia ancora valida. Le notiche

Figura 5.6: Lettura di una nuova notica.

permanenti e rimangono valide a prescindere dal tempo, no a che l'utente non esgua una delle azioni previste, se ve ne sono associate a quel tipo di notica, o non decida di nasconderle. Ad esempio sono notiche di questo tipo gli inviti di adesione che un utente può ricevere da parte del fondatore di un gruppo. In questo caso la notica, quando viene visualizzata presenta due bottoni: Accept e Deny, per poter accettare o riutare la richiesta (Figura 5.6). Questo tipo di notica rimane, naturalmente non in primo piano, no a quando l'utente non decide di intraprendere una delle due azioni.

Per poter gestire questi diversi tipi di notiche è stato realizzato un centro notiche client-side e uno server-side. Quest'ultimo si occupa di comunicare con il database, e inviare le informazioni al client. Tale versione server-side è imple- mentata in PHP e rispetta i paradigmi di modularità e versatilità descritti in precedenza.

L'oggetto che gestisce le notiche, il noticationManager, dal lato PHP, è sta- to implementato per poter elaborare indierentemente qualsiasi tipo di notica, e soprattutto per poter estendere e aggiungere in maniera modulare un tipologie dierenti di notiche. Per otttenere ciò abbiamo implementato tale oggetto se- guendo un pattern implementativo ormai molto famoso e consolidato: il pattern Plug-In.

Questo pattern, che altrimenti si chiama Extensibility Pattern, prevede che ci sia un framework centrale, implementato in modo che, anche in un momento successivo, vi si possa aggiungere una qualche funzionalità che al momento dello sviluppo non era stata prevista. Per esempio un applicazione che lavora con dei protocolli di rete che rispetta questo pattern permetterà di aggiungere un nuovo protocollo prima non supportato dall'applicazione. Allo stesso modo abbiamo

5.4 Gli aspetti collaborativi della piattaforma 85 implementato il noticationManager in modo che anche in un secondo momen- to sia possibile gestire un nuovo tipo di notiche che non erano state ancora implementate.

Per poter implementare tale meccanismo ci si è rifatto ad un altro pattern molto utilizzato, appunto per poter implementare un'applicazione a plug-in, il Factory Pattern. Quest'ultimo permette di implementare un interfaccia comune a tutte le classi, così che al momento dell'istanziamento dell'oggetto, sia possibile crearne uno senza ancora sapere che tipo di oggetto sia, permettendo alle sot- to classi di determinarlo e istanziarlo correttamente. Naturalmente non è stato possibile seguire il pattern alla lettera per motivi implementativi, ma abbiamo sfruttato tale metodo nell'implementazione di un'interfaccia comune, che tutte le varie classi di oggetti devono rispettare (Figura 5.8). Il PHP, linguaggio in cui è stato implementato questo sistema, non è un linguaggio orientato alla pro- grammazione ad oggetti, perciò non è stato possibile creare una vera e propria interfaccia che sia implementata da tutte le classi, ma è stato denito un insieme di metodi e attributi che tutte le classi devono avere, che poi vengono richiamati dal noticationManager. Inoltre abbiamo sfruttato un altro pattern implementa- tivo: la Lazy Initialization, che combinato con il Factory Pattern da luogo al Lazy Facotory. Questo pattern prevede che una classe venga istanziata solo quando ce ne sia realmente bisogno, istanziando tale classe non all'apertura della pagina, o al caricamento dell'oggetto che potrebbe utilizzarne i metodi, ma solo nel mo- mento in cui l'oggetto debba realmente richiamarne i metodi. Questo pattern si combina perfettamente con la nostra idea di un gestore di notiche plug-in, per- ché non introduce le criticità dovute a un eccessivo numero di moduli da caricare da parte del gestore, perché dei moduli, per tanti che siano, verranno istanziati solo quelli necessari e al momento necessario. In questo modo abbiamo imple- mentato un gestore delle notiche che possa venire esteso in maniera semplice ed agile.

Abbiamo infatti implementato il noticationManager come un oggetto PHP semplice, che però prevede delle chiamate di funzioni che corrispondono ai metodi implementati nelle classi che sono poi i moduli delle notiche. In altre parole il noticationManager fa la parte della nostra interfaccia, ma in più si occupa di instanziare le classi opportune all'occorrenza e di invocarne i metodi. Per i moduli abbiamo sfruttato le classi di PHP che. seppur prive di un supporto completo, permettono di istanziare un oggetto all'occorrenza. Tali classi devono implementare gli stessi metodi previsti nel noticationManager, e i vari metodi devono restituire delle strutture dati che siano conformi a quelle previste.

I metodi necessari, implementati dai singoli moduli, sono quelli per la gestione delle notiche, che sono in qualche misura specici per quel tipo di notica:

• aggiunta di una notica all'interno del database

Figura 5.7: Schema database per la gestione delle notiche getNotifications() checkInterval() addNotification() handleReplay() username databaseConnector arrayNotification Notification Interface NotificationSharing NotificationGroup getNotifications() setNotificationRead() replyNotification() addNotification() deleteNotification() NotificationType: Array[] databaseConnector <<Singleton>> NotificationManager 1..* 1 <<implements>> <<implements>> ...

5.4 Gli aspetti collaborativi della piattaforma 87 • un metodo per gestire le azioni, se previste, per una certa notica

I metodi che invece sono comuni a tutte le notiche, sono invece implementati direttamente nel noticationManager, così da renderne immediata l'esecuzione e sono:

• un metodo per noticare che l'utente ha visionato i messaggi, e perciò questi non sono più in primo piano

• un metodo per eliminare la notica dal database

Per poter implementare in maniera eciente tale sistema, abbiamo dovuto im- porre anche al database un pattern simile, per quanto riguarda le tabelle che gestiscono le notiche come mostra la gura 5.7. Infatti, visto che ogni tipo di notica presenta degli attributi che sono propri di quella tipologia e non sono condivisi con le altre, è stato necessario creare una tabella per ogni tipologia di notica. Questa scelta ovviamente, non facilita l'aggiunta di nuovi tipi di noti- ca, ma si è rivelata necessaria per via della diversità degli attributi delle stesse, basti pensare alle dierenze tra notiche temporizzate e permanenti, o quelle che necessitano di una risposta e quelle che hanno il solo compito di noticare.

Le due parti, server-side in PHP e client-side in Javascript, che compongono il sistema delle notiche, devono comunicare tra loro in maniera eciente e veloce. Questo implica che la richiesta di aggiornamento delle notiche deve restituire una certa struttura dati, proveniente dal linguaggio PHP, comprensibile e facilmente consultabile da Javascript. Abbiamo deciso di usare per il trasporto dei dati il formato JSON. È una notazione molto diusa che si basa su Javascript, e perciò è estremamente agile da utilizzare una volta che il client la riceve dal server. Il server, dalla sua parte, non ha un supporto per il JSON, ma data la grandissima diusione del formato, sono disponibili delle librerie per la conversione di variabili da PHP a JSON e viceversa. La variabile codicata in JSON poi non è nient'altro che una stringa che rispetta una certa sintassi, perciò risulta particolarmente eciente restituirla come risultato di una chiamata al server. Inoltre gli stessi meccanismi AJAX, per le chiamate dinamiche al server, presentano delle opzioni che permettono di fare il parsing automatico della risposta del server, se questa è in JSON. È perciò ovvio che la soluzione migliore è quella di appoggiarsi a questo formato per la comunicazione client-server. È comunque utile visualizzare un esempio di risposta del server alla chiamata per aggiornare le notiche (Figura 5.9), in modo anche da vericare le grosse dierenze, dal punto di vista dei parametri salvati, che vi sono tra i vari tipi di notiche; dierenze che sono state citate prima per giusticare il coinvolgimento del database per l'estensione delle notiche.

Le notiche, per avere senso e non essere dei messaggi inecaci, devono es- sere in qualche modo aggiornate in tempo reale. Non si può fare adamento su un'azione dell'utente per eettuare la chiamata al server per aggiornare le noti- che; un utente potrebbe non fare quell'azione per ore e una notica in ritardo

{

group :[{ id :1,

type :" group ", read :0,

description : "Mik invited you to join Colleghi with this message : hi join our group !",

needReply :1,

replyOption :[" accept ", " deny "],

replyAction :[" action = reply & type = group & param = accept ,1" , " action = reply & type = group & param =deny ,1"] }], sharing :[{ id :4, type :" sharing ", read :0,

description : " Luca shared with you a composition with name : myConcerts throw group amici "

needReply :0 }, { id :7, type :" sharing ", read :1,

description : " Marco shared with you a composition with name : restaurants in Chicago ",

needReply :0 }]

}

5.4 Gli aspetti collaborativi della piattaforma 89 di ore, specialmente se un invito ad un'attivita, non ha senso che sia mostrata. Le notiche devono essere aggiornate non appena ci sia qualcosa da noticare, con un ritardo non eccessivamente lungo, nell'ordine dei minuti: serve perciò un meccanismo che autonomamente recuperi le informazioni dal server e le mostri all'utente, senza che questo abbia intrapreso delle particolari azioni.

Questa problematica viene illustrata e arontata in maniera molto più appro- fondita nella sezione che riguarda la collaborazione sincrona; perciò rimandiamo a quella sezione la spiegazione del problema, in maniera che possa essere arontato e spiegato in maniera molto più esaustiva che in questo paragrafo.

5.4.1.2 Annotazioni

Un altro strumento asincrono della collaborazione sono le annotazioni. In ta- le direzione il maggiore problema di sviluppo riscontrato riguarda la necessità di avere le annotazioni sempre a portata di mano e contestuali all'elemento al quale si riferiscono, ma allo stesso tempo di evitare che la loro presenza possa intralciare l'uso del mashup ed in generale le azioni eettuate dall'utente. Infatti da un lato è necessario che l'utente sia n grado a colpo d'occhio di valutare la presenza di annotazioni all'interno della composizione. Questo permette di met- tere a fuoco quali siano i principali elementi sui quali la collaborazione sia attiva, nonché di dare la possibilità ad un utente di leggere il contenuto della nota e po- tervi rispondere contestualmente attraverso dinamiche di interazione pressoché istantanee.

Contemporaneamente sussiste il problema di dove collocare all'interno dello spazio di lavoro tali annotazioni. Il massimo grado di contestualizzazione può es- sere raggiunto solamente appendendo ai singoli componenti tali commenti. Ogni annotazione è come un piccolo bigliettino adesivo che può essere incollato al- l'interno del componente di propria scelta. Questo permette di avere sempre localizzate, all'interno dell'elemento cui si riferiscono, le informazioni rilevanti circa lo specico oggetto.

Il problema che nasce da una simile scelta è relativo al limitato spazio che un componente possa avere dedicato all'interno dello spazio di lavoro. Infatti, so- prattutto nel caso di composizioni particolarmente aollate, la presenza di una o più annotazioni, posizionate sopra al componente stesso, nirebbero per nascon- derne il contenuto, rendendo di fatto inutilizzabile il componente. Una simile situazione si presenta anche nel caso in cui il numero di componenti sia limita- to, mentre sia cospicuo il numero delle annotazioni, ovvero quando il numero di interazioni su uno stesso componente sia elevato.

Per disciplinare tale comportamento si potrebbe pensare di visualizzare solo le annotazioni più recenti, in modo così da recuperare spazio vitale da dedicare ai contenuti dei componenti. Tale scelta si dimostra estremamente svantaggiosa: gran parte delle speculazioni possibili a partire dalle annotazioni traggono forza dalle prolungate interazioni tra più utenti nel tempo e non è quindi accettabile

l'idea di nascondere le note meno recenti. Aggravante è la caratteristica asincrona delle annotazioni: in caso di interazioni su intervalli di tempo prolungati, non è pensabile che l'utente possa ricordarsi tutte le precedenti fasi dell'interazione. La soluzione messa in pratica in tale senso è quella di mostrare contestualmente al singolo componente solo l'annotazione più recente, con la possibilità di visualiz- zare lo storico delle note precedenti tramite un apposito pulsante, che mostri in una nuova nestra, non più contestuale al componente, l'elenco di tutti i mes- saggi scambiati dagli utenti. Per quanto riguarda l'implementazione specica delle annotazioni, ciascuna è costituita da una parte di meta-dati, contenenti le informazioni di base circa l'utente che ha aggiunto tale nota, data e ora dell'inte- razione, e da una parte di contenuto, eettivo testo inserito nella nota. Inoltre la gestione delle annotazioni è mantenuta indipendente dal salvataggio dello stato della composizione: questo permette di gestire le note su un canale dedicato e parallelo, nonché segue il preciso volere di mantenere un approccio modulare, con la possibilità di sfruttare in futuro un simile meccanismo per annotare altri og- getti presenti in Peudom o addirittura implementare delle meta-annotazioni che si riferiscano direttamente all'ambiente di lavoro utilizzato e non più al mashup in fase di sviluppo.

5.4.1.3 Controllo di versione

Uno degli strumenti più utili a supporto della collaborazione asincrona è il con- trollo di versione. L'abbiamo collocato nella collaborazione asincrona, perché di fatto permette e aiuta questo tipo di collaborazione, anche se è disponibile e at- tivo su composizioni e componenti personali, su cui, non essendo condivisi, non c'è collaborazione. Abbiamo deciso di rendere questo strumento disponibile per qualsiasi tipo di composizione e componente, condiviso e non, per il fatto che rap- presenta uno strumento utilissimo sia per lo sviluppo collaborato che per quello personale. È infatti estremamente utile poter ripristinare una versione precedente di un oggetto.

Un vero e proprio controllo di versione prevede che vi siano una copia remota del documento, contenuta sul server, una copia locale, contenuta sul client, e una serie di azioni che l'utente può intraprendere. Tali azioni sono comuni a molti, visto che il controllo di versione è un sistema estremamente diuso e conosciuto nell'ambito informatico.

Update: L'utente eettua l'aggiornamento della propria copia locale, sincroniz- zandola con quella del server: in questo caso le modiche presenti sul server, se ve ne sono, sono applicate alla copia locale.

Commit: Vengono inviate le modiche, eettuate in locale, al server, provocan- do di fatto un avanzamento di versione.

5.4 Gli aspetti collaborativi della piattaforma 91 Revert: Vengono annullate le modiche eettuate dall'utente sulla sua copia locale, eseguendo di fatto un reset dell'oggetto riportandolo allo stato in cui si trova sul server

Update to version: La copia locale dell'utente viene riportata alla versione indicata presente sul server.

Branch: Viene creata una nuova versione di partenza, creata a partire dalla versione attuale, ma che evolve in maniera indipendente. Di fatto si crea un nuovo repository, scollegato dal precedente.

Queste sono solo le azioni di base, poi vi sono una serie di altre possibilità per la gestione dei conitti e dei repository, ma non accenniamo a queste funzioni dato che l'implementazione del nostro controllo di versione è piuttosto minimale. In- fatti non è prevista una vera e propria azione di aggiornamento della copia locale perché di fatto non esiste una copia locale che l'utente può modicare. Trovando- ci di fronte a un'applcazione web, tutti i dati dell'applicazione sono conservati sul server in remoto, e di conseguenza ogni volta che l'utente apre una composizione o un componente precedentemente salvati, sta di fatto eseguendo un aggiorna- mento per ricevere l'ultima versione dell'oggetto aperto. Infatti al caricamento dell'oggetto il server controlla l'ultima versione disponibile e la invia all'utente. In questo l'azione di Commit si riduce al semplice salvataggio dell'oggetto mo- dicato, in qusto caso il server controlla quale è l'ultima versione salvata e salva l'oggetto ricevuto dall'utente come nuova versione, tenendo in memoria le ver-