Università degli studi di Padova DIPARTIMENTO DI MATEMATICA CORSO DI LAUREA IN INFORMATICA Rating, statistiche e dashboard per un’applicazione mobile di coaching Tesi di laurea triennale Relatore Prof. Gilberto Filè Laureanda Chiara Bigarella Anno Accademico 2015-2016 Sommario Il presente documento descrive l’attività di stage svolta presso l’azienda TeddyApp BV con sede legale ad Amsterdam. Durante lo svolgimento dello stage l’azienda è locata presso H-Farm Ventures. Il lavoro si è inizialmente concentrato sulla realizzazione di un sistema di rating per un’applicazione mobile di coaching on demand. In seguito è stata realizzata un’interfaccia che permette agli utenti dell’app di visualizzare le proprie statistiche di utilizzo. Per finire è stata realizzata una dashboard per le aziende, col fine di mostrare a queste ultime le statistiche di utilizzo complessive dei propri utenti. III IV Ringraziamenti Innanzitutto, vorrei esprimere la mia gratitudine al Prof. Gilberto Filè, relatore della mia tesi, per l’aiuto fornitomi e per la sua disponibilità durante la stesura del lavoro. Desidero ringraziare con affetto i miei cari per il sostegno, il grande aiuto e per essermi stati vicini in ogni momento durante gli anni di studio. Ringrazio poi i miei amici per tutti i bellissimi anni passati insieme e le mille avventure vissute. Dicembre 2015, Padova Chiara Bigarella V VI Indice 1 Introduzione 1.1 Struttura del documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 2 Progetto di stage 2.1 Motivazioni dello stage . . . . . . . . . . . . . 2.2 Descrizione del prodotto . . . . . . . . . . . . 2.2.1 App per gli Utenti . . . . . . . . . . . 2.2.2 App per i Coach . . . . . . . . . . . . 2.2.3 Backend . . . . . . . . . . . . . . . . . 2.2.4 Interazioni tra applicazioni e backend 2.3 Obiettivi dello stage . . . . . . . . . . . . . . 2.3.1 Obiettivi minimi . . . . . . . . . . . . 2.3.2 Obiettivi opzionali . . . . . . . . . . . 2.4 Vincoli tecnologici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 4 4 4 5 5 6 6 7 7 3 Tecnologie utilizzate 3.1 Node.js . . . . . . . . 3.1.1 Vantaggi . . . . 3.1.2 Svantaggi . . . 3.2 MongoDB . . . . . . . 3.2.1 Vantaggi . . . . 3.2.2 Svantaggi . . . 3.3 Mongoose.js . . . . . . 3.3.1 Vantaggi . . . . 3.3.2 Svantaggi . . . 3.4 Express.js . . . . . . . 3.4.1 Vantaggi . . . . 3.4.2 Svantaggi . . . 3.5 Norris . . . . . . . . . 3.5.1 Vantaggi . . . . 3.5.2 Svantaggi . . . 3.6 Objective-C . . . . . . 3.6.1 Vantaggi . . . . 3.6.2 Svantaggi . . . 3.7 Socket.io Swift Client 3.7.1 Vantaggi . . . . 3.7.2 Svantaggi . . . 3.8 Parse . . . . . . . . . . 3.8.1 Vantaggi . . . . 3.8.2 Svantaggi . . . 3.9 Layer . . . . . . . . . 3.9.1 Vantaggi . . . . 3.9.2 Svantaggi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 9 9 9 9 10 10 10 10 10 11 11 11 11 12 12 12 12 12 12 12 13 13 13 13 13 14 4 Lo stage: punti salienti dello sviluppo 4.1 Sintesi delle attività svolte . . . . . . . . . . . . 4.1.1 Apprendimento delle tecnologie . . . . . 4.1.2 Sistema di rating . . . . . . . . . . . . . 4.1.3 Analisi delle statistiche di utilizzo . . . 4.1.4 Dashboard per le aziende . . . . . . . . 4.2 Criticità incontrate . . . . . . . . . . . . . . . . 4.2.1 Autenticazione al server . . . . . . . . . 4.2.2 Rating dopo una conversazione via chat 4.2.3 Socket.IO Swift Client . . . . . . . . . . 4.3 Altre scelte implementative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 15 15 16 17 17 19 19 19 20 20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . VII 4.3.1 4.3.2 Scelta del driver per MongoDB . . . . . . . . . . . . . . . . . . . . . . . . . Scelta del design pattern MVP per la Dashboard . . . . . . . . . . . . . . . 20 21 5 Verifica e validazione 5.1 Strategia di verifica . . . . . . . . 5.1.1 Obiettivi di qualità . . . . 5.1.2 Metriche . . . . . . . . . . 5.1.3 Esiti delle misurazioni . . 5.2 Testing del backend . . . . . . . 5.3 Testing delle applicazioni mobile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 23 23 24 25 28 29 6 Conclusioni 6.1 Obiettivi raggiunti . 6.2 Conoscenze acquisite 6.2.1 MongoDB . . 6.2.2 Node.js . . . 6.2.3 iOS . . . . . 6.3 Sviluppi futuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 31 31 31 31 31 32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Database B Backend B.1 RequestManager . . . . . . . . . . . . . . . . B.2 DBManager . . . . . . . . . . . . . . . . . . . B.3 Controller . . . . . . . . . . . . . . . . . . . . B.4 Dashboard . . . . . . . . . . . . . . . . . . . . B.4.1 Dashboard:Model . . . . . . . . . . . . B.4.2 Dashboard:Presenter . . . . . . . . . . B.4.3 Dashboard:View . . . . . . . . . . . . B.5 Descrizione delle interazioni tra le componenti B.5.1 Controller-DBManager . . . . . . . . . B.5.2 Controller-RequestManager . . . . . . B.5.3 Dashboard-Controller . . . . . . . . . Glossario VIII 33 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 36 37 37 39 41 41 42 42 42 42 43 45 Elenco delle figure 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Alcune schermate dell’app per gli utenti . . . . . . . . . . . . Schermata iniziale dell’app per i coach . . . . . . . . . . . . . Dashboard di Parse . . . . . . . . . . . . . . . . . . . . . . . . Logo di Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . Logo di MongoDB . . . . . . . . . . . . . . . . . . . . . . . . Logo di Mongoose . . . . . . . . . . . . . . . . . . . . . . . . Logo di Express.js . . . . . . . . . . . . . . . . . . . . . . . . Logo di Norris . . . . . . . . . . . . . . . . . . . . . . . . . . Logo di Socket.io . . . . . . . . . . . . . . . . . . . . . . . . . Logo di Parse . . . . . . . . . . . . . . . . . . . . . . . . . . . Logo di Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . Diagramma di Gantt . . . . . . . . . . . . . . . . . . . . . . . Mokup della dashboard per le aziende . . . . . . . . . . . . . Esiti seconda fase: parametri per metodo . . . . . . . . . . . Esiti terza fase: parametri per metodo . . . . . . . . . . . . . Esiti quarta fase: parametri per metodo . . . . . . . . . . . . Schema del Database . . . . . . . . . . . . . . . . . . . . . . . Diagramma delle componenti . . . . . . . . . . . . . . . . . . Diagramma delle classi di DBManager . . . . . . . . . . . . . Diagramma delle classi di Controller . . . . . . . . . . . . . . Diagramma delle sottocomponenti della Dashboard . . . . . . Diagramma delle classi di Dashboard:Model . . . . . . . . . . Diagramma delle classi di Dashboard:Presenter . . . . . . . . Diagramma delle interazioni tra Controller e DBManager . . Diagramma delle interazioni tra Controller e RequestManager Diagramma delle interazioni tra Dashboard e Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 5 5 9 10 10 11 11 12 13 13 15 18 25 26 27 33 36 37 38 40 40 41 42 42 43 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 27 28 28 Elenco delle tabelle 1 2 3 4 Esiti Esiti Esiti Esiti seconda fase: grado di accoppiamento terza fase: grado di accoppiamento . . quarta fase: grado di accoppiamento . delle misurazioni effettuate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IX X 1 Introduzione TeddyApp B.V. nasce in un contesto in cui lo stress lavorativo è un fattore rilevante nell’insorgere di esaurimento e depressione. Questo porta non solo al malessere psicofisico della persona, ma anche a notevoli danni economici per le aziende i cui dipendenti stressati rendono di meno o si assentano dal lavoro per ricevere le adeguate cure mediche. TeddyApp B.V. vuole prevenire tutto ciò, fornendo alle aziende uno strumento concreto: un’applicazione mobile che permetta al lavoratore di contattare in ogni momento esperti che lavorano nell’ambito del benessere, quali psicologi o coach, in modo da prevenire lo stress lavorativo. È proprio in questo contesto che si inserice l’esperienza di stage da me svolta, che questo documento si prefigge di descrivere. Al momento del mio arrivo in azienda, sono già presenti due applicazioni iOS: una per gli utenti e una per i coach. È inoltre presente un backend in Parse, il quale comunica con le due app e salva sul proprio database i dati provenienti da esse. Il progetto di stage prevede l’aggiunta di nuove funzionalità all’applicazione per gli utenti. In particolare è richiesto di creare: • un sistema di rating che permetta all’utente di valutare il coach con il quale ha intrattenuto una conversazione; • un’interfaccia che permetta agli utenti di vedere le proprie statistiche di utilizzo dell’applicazione. La parte più corposa dello stage è tuttavia costituita dall’implementazione delle funzionalità fornite dal backend in Parse, presente prima dell’inizio dello stage, in un nuovo backend implementato utilizzando il framework Node.js. Per fare ciò si deve infatti progettare un nuovo database e implementare la logica di comunicazione tra le applicazioni e il nuovo server. In particolare l’autenticazione al server costituisce un punto critico del progetto di stage. Le motivazioni della scelta di spostare il backend da Parse a Node.js sono essenzialmente due: 1. l’azienda vuole rendere il servizio maggiormente scalabile; 2. Parse è un servizio a pagamento. Oltre all’implementazione delle principali funzionalità già presenti, viene implementata una dashboard per le aziende. In questo modo le aziende possono visualizzare tramite un’interfaccia web le statistiche di utilizzo del servizio da parte dei propri dipendenti. Le informazioni visibili alle aziende non sono, ovviamente, informazioni sensibili. Le aziende possono infatti visualizzare: • il numero di dipendenti che si sono registrati al servizio; • il numero di dipendenti che hanno utilizzato l’applicazione di recente; • il numero di conversazioni recenti avvenute tra i propri dipendenti e i coach; • il numero di conversazioni totali avvenute tra i propri dipendenti e i coach; • i coach maggiormente contattati dai propri dipendenti. Non possono inceve avere accesso alle seguenti informazioni: • quali dipendenti si sono registrati al servizio; • quali dipendenti utilizzano l’applicazione; • il numero di conversazioni di un determinato dipendente; • quali coach ha contattato un determinato dipendente; • le conversazioni stesse. Al fine di garantire una maggiore privacy degli utenti, i coach sono persone esterne alle aziende che utilizzano il servizio. Inoltre, per poter lavorare nel ruolo di coach si deve essere iscritti ad un albo professionale. In questo modo TeddyApp B.V. garantisce la qualità del servizio offerto. 1 1.1 Struttura del documento Viene riportata di seguito la struttura del documento. Ogni capitolo è accompagnato da una breve descrizione dei contenuti: 1. Introduzione: in questo capitolo vengono introdotti lo scopo e i contenuti del presente documento; 2. Progetto di stage: in questo capitolo vengono descritte le motivazioni dello stage e gli obiettivi che con esso si vogliono raggiungere. Viene inoltre descritto il prodotto già esistente prima della stesura del piano di lavoro e i vincoli tecnologici che ne derivano; 3. Tecnologie utilizzate: in questo capitolo vengono descritte le principali tecnologie utilizzate durante lo svolgimento del progetto di stage. In particolare ci si sofferma su vantaggi e svantaggi che derivano dall’utilizzo di tali tecnologie; 4. Lo stage: punti salienti dello sviluppo: in questo capitolo vengono descritte le attività svolte durante lo stage. Ci si sofferma in particolare sulle criticità incontrate, descrivendo ciò che è stato fatto per risolvere le problematiche emerse. Infine si pone l’attenzione sulle più importanti scelte implementative effettuate; 5. Verifica e validazione: in questo capitolo vengono descritte le tecniche di verifica e le metriche utilizzate per verificare che il prodotto realizzato soddisfi i requisiti; 6. Conclusioni: in questo capitolo si riassumono gli obiettivi raggiunti, le conoscenze acquisite e i possibili sviluppi futuri del progetto di stage; 7. Appendici: nelle appendici sono presenti informazioni di carattere tecnico riguardo il progetto di stage. In particolare sono riportate in appendice le progettazioni del database e del backend; 8. Glossario: nel glossario sono riportate le spiegazioni dei termini tecnici utilizzati nel presente documento, in modo tale da agevolarne la lettura rendendo il testo più facilmente comprensibile. 2 2 Progetto di stage 2.1 Motivazioni dello stage TeddyApp B.V. è una startup che si occupa dello sviluppo di un servizio di coaching on demand. In seguito al rilascio della prima versione dell’applicazione mobile, sono sorte all’interno dell’azienda alcune necessità. Vengono riportate di seguito le più importanti, che hanno portato alla definizione del progetto di stage: 1. Innanzitutto c’è il crescente bisogno di ricevere feedback inerenti l’utilizzo dell’applicazione da parte degli utenti. Questo aspetto è molto importante in questa prima fase di sviluppo dell’applicazione, in quanto può permettere all’azienda di capire le esigenze degli utenti, la frequenza di utilizzo dell’app, le funzionalità più utilizzate. Di grande importanza è inoltre il livello di gradimento delle conversazioni che gli utenti hanno con i coach. Per questi motivi, oltre alla volontà di integrare all’interno dell’applicazione sistemi di analisi come Google Analytics e Intercom, l’azienda ha espresso enorme interesse nella realizzazione di un sistema di rating, in modo da permettere all’utente di valutare un coach al termine di una chiamata o dopo una conversazione avvenuta tramite chat. 2. In secondo luogo, l’azienda ha espresso la volontà di ampliare le statistiche di utilizzo fornite all’utente. La dashboard che è attualmente a disposizione dell’utente mostra i dati relativi all’intero periodo di utilizzo dell’applicazione (ovvero a partire dalla registrazione dell’utente al servizio). Si vorrebbe, invece, permettere all’utente di consultare separatamente le statistiche di utilizzo settimanali, mensili e annuali. In particolare si vorrebbe suddividere la dashboard attuale in tre view: • Week : visualizza le statistiche di utilizzo relative alla settimana corrente, ovvero: – il numero di coach contattati dall’utente durante la settimana; – il numero di chiamate effettuate dall’utente durante la settimana; – la durata totale delle chiamate effettuate dall’utente durante la settimana; – la percentuale delle chiamate della settimana che sono state effettuate durante i giorni lavorativi; – la percentuale delle chiamate della settimana che sono state effettuate durante il weekend. • Month: visualizza le statistiche di utilizzo relative al mese corrente, ovvero: – il numero di coach contattati dall’utente durante il mese corrente; – il numero di chiamate effettuate dall’utente durante il mese corrente; – la durata totale delle chiamate effettuate dall’utente durante il mese corrente; – la percentuale delle chiamate del mese corrente che sono state effettuate durante i giorni lavorativi; – la percentuale delle chiamate del mese corrente che sono state effettuate durante il weekend. • Year : visualizza le statistiche di utilizzo relative all’anno corrente, ovvero: – il numero di coach contattati dall’utente durante l’anno corrente; – il numero di chiamate effettuate dall’utente durante l’anno corrente; – la durata totale delle chiamate effettuate dall’utente durante l’anno corrente; – la percentuale delle chiamate dell’anno corrente che sono state effettuate durante i giorni lavorativi; – la percentuale delle chiamate dell’anno corrente che sono state effettuate durante il weekend. È dunque necessario raffinare l’analisi dei dati raccolti durante l’utilizzo dell’applicazione ed integrare nella dashboard personale dell’utente i nuovi dati, mostrandoli sotto forma di grafici. 3. Infine, l’azienda vuole pian piano implementare in Node.js le funzionalità dell’attuale backend. 3 2.2 Descrizione del prodotto TeddyApp consiste di due applicazioni mobile native iOS, una per gli utenti ed una per psicologi e professionisti che lavorano nell’ambito del benessere. Per semplicità ci riferiremo a questi ultimi con il termine più generico di ’coach’. 2.2.1 App per gli Utenti Attraverso l’applicazione, gli utenti sono in grado di contattare coach, psicologi e professionisti nell’ambito del benessere, in modo da prevenire lo stress lavorativo. Quando l’utente sente di aver bisogno di un parere, un consiglio, o anche solamente per sfogarsi, può scegliere il professionista che più si presta al suo caso dalla lista dei coach che sono on-line in quel determinato momento. La scelta dell’utente è facilitata dalla presenza di una breve descrizione, nella quale vengono indicate le competenze di ciascun coach. Una volta scelto il professionista a cui rivolgersi, l’utente può procedere a contattarlo tramite chiamata oppure tramite messaggio. L’utente ha inoltre a disposizione una dashboard personale, nella quale vengono visualizzate le statistiche relative alle chiamate effettuate e ai coach contattati. In particolare vengono visualizzati: • il numero di coach contattati dall’utente; • il numero di chiamate effettuate dall’utente; • la durata totale delle chiamate effettuate dall’utente; • la percentuale delle chiamate che sono state effettuate durante i giorni lavorativi; • la percentuale delle chiamate che sono state effettuate durante il weekend. Figura 1: Alcune schermate dell’app per gli utenti 2.2.2 App per i Coach Questa applicazione permette ai coach di decidere se rendersi disponibili o meno per essere contattati dagli utenti. Inoltre permette loro di rispondere alle chiamate e ai messaggi degli utenti che li contattano. 4 Figura 2: Schermata iniziale dell’app per i coach 2.2.3 Backend Infine, le due applicazioni sopra ciatate condividono il backend in Parse. Dalla dashboard di Parse è possibile gestire il database con le informazioni relative ad utenti e coach in modo semplice anche per chi non sa programmare. Sono inoltre fornite delle API per effettuare query più complesse ed accedere ai dati direttamente da codice. Figura 3: Dashboard di Parse 2.2.4 Interazioni tra applicazioni e backend Sono riportate di seguito le principali tipologie di interazioni che avvengono tra le due app e il backend: 5 • autenticazione: le applicazioni inviano al backend username e password rispettivamente dell’utente o del coach; il backend controlla che tali dati siano corretti e, in caso affermativo, effettua l’autenticazione; • registrazione: quando un nuovo utente si registrata utilizzando una delle due applicazioni, il backend si occupa di salvare i dati del nuovo utente nel database; • chiamate: quando l’utente effettua una chiamata, il backend si occupa di salvare nel database i dati relativi alla sessione (per esempio la durata della chiamata, l’orario in cui è stata effettuata, ecc); • notifiche push: il backend controlla periodicamente per quanto tempo i coach on-line sono rimasti inattivi. Se lo sono da più di un’ora, manda loro una notifica e li fa diventare off-line; • il backend raccoglie inoltre alcune semplici statistiche di utilizzo, come per esempio quante persone hanno installato l’app, quanti utenti si sono registrati, ecc. 2.3 Obiettivi dello stage Gli obiettivi dello stage sono stati individuati durante la stesura del piano di lavoro, assieme al tutor aziendale Michelle Franke. Si è scelto di suddividerli in: • obiettivi minimi, ovvero obiettivi che devono necessariamente essere soddisfatti al termine dello stage; • obiettivi opzionali. 2.3.1 Obiettivi minimi Sono riportati di seguito gli obiettivi minimi previsti dal piano di lavoro: 1. apprendimento delle tecnologie utilizzate dall’azienda, necessarie per lo svolgimento del progetto; 2. progettazione e sviluppo dell’elaborazione dei dati provenienti da Parse: i dati inerenti le statistiche di utilizzo dell’applicazione, provenienti dal backend in Parse, devono essere elaborati con Node.js. Dopodichè il server deve provvedere all’invio dei dati elaborati all’applicazione iOS, che si occuperà di visualizzarli; 3. progettazione, sviluppo e integrazione della visualizzazione dei dati sottoforma di grafici nell’applicazione iOS: si vogliono mostrare all’utente statistiche più precise riguado alle conversazioni con i coach. È necessario quindi sviluppare ed ampliare la dashboard attuale dell’utente, aggiungendovi i nuovi dati elaborati nel backend, sottoforma di grafici; 4. progettazione, sviluppo e integrazione di un sistema di rating nell’applicazione iOS: è necessario sviluppare (e integrare nell’applicazione esistente) un sistema di rating in modo da permettere agli utenti di valutare le conversazioni avute con i coach. È dunque necessario sviluppare: (a) un database per la memorizzare dei dati inerenti le valutazioni degli utenti; (b) un backend che permetta di elaborare i dati provenienti dall’app e di salvarli nel database; (c) una view all’interno dell’applicazione che consenta all’utente di valutare il coach. La view deve comunicare con il backend per inviargli i dati relativi alla valutazione. Inoltre, l’azienda deve poter visualizzare in modo semplice i dati relativi alle valutazioni degli utenti; 5. stesura della documentazione del codice prodotto. 6 2.3.2 Obiettivi opzionali Sono riportati di seguito gli obiettivi opzionali previsti dal piano di lavoro: 1. realizzazione della visualizzazione web dei grafici: si vuole permettere all’utente di visualizzare le statistiche inerenti le proprie conversazioni anche dal web; 2. implementazione in Node.js delle funzionalità presenti nel backend attuale (o di una parte di esse). 2.4 Vincoli tecnologici La struttura del prodotto esistente impone alcuni vincoli riguardo le tecnologie che dovranno essere utilizzate durante lo svolgimento dello stage. In particolare è fondamentale l’utilizzo delle seguenti tecnologie: • Objective-C, in quanto le due applicazioni mobile sono scritte in tale linguaggio; • Parse, in quanto costituisce l’attuale backend; • Layer, in quanto è il servizio di instant messaging utilizzato dalle due applicazioni. Inoltre, è stato richiesto dall’azienda l’utilizzo delle seguenti tecnologie per lo sviluppo del backend: • Node.js • MongoDB Per un’analisi più approfondita delle tecnologie sopra citate si rimanda alla sezione Tecnologie utilizzate. 7 8 3 Tecnologie utilizzate In questa sezione sono elencate le principali tecnologie utilizzate per lo sviluppo del progetto. Per ognuna di esse viene descritto lo scopo per il quale viene usata ed i vantaggi che se ne ricavano. 3.1 Node.js Node.js è un framework che utilizza V8, il motore JavaScript di Google, per permettere lo sviluppo di applicazioni JavaScript lato server. Si basa su un sistema di I/O asincrono, non bloccante, basato sugli eventi; utilizza inoltre un unico thread e un event loop per la gestione delle callback. In questo modo vi è un uso ottimale delle risorse. L’azienda ha richiesto il suo utilizzo per la realizzazione del nuovo backend. Figura 4: Logo di Node.js 3.1.1 Vantaggi I vantaggi nell’utilizzo di Node.js sono i seguenti: • fornisce una semplice soluzione per lo sviluppo di programmi scalabili; • essendo single thread, non presenta problemi legati all’utilizzo della concorrenza; • basandosi su un sistema di I/O asincrono, risulta molto efficiente nelle applicazioni con un utilizzo intensivo di I/O; • è particolarmente indicato per lo sviluppo di sistemi responsivi. 3.1.2 Svantaggi Seguono gli svantaggi rilevati nell’utilizzo di Node.js: • essendo di recente creazione, alcuni moduli risultano instabili; • essendo single-threaded, non è performante in caso di applicazioni con uso intensivo di CPU; • utilizzando un sistema I/O asincrono, è possibile che l’uso di callback risulti eccessivo. 3.2 MongoDB MongoDB è un DBMS non relazionale, orientato ai documenti. Viene classificato come un database di tipo NoSQL, in quanto si allontana dalla struttura basata su tabelle dei database relazionali, in favore di documenti in stile JSON con schema dinamico. Ciò rende l’integrazione di dati di alcuni tipi di applicazioni più facile e veloce. L’azienda ha richiesto il suo utilizzo per la realizzazione del nuovo database. 3.2.1 Vantaggi Essendo un DBMS di tipo NoSQL, MongoDB presenta i seguenti vantaggi: • tipi di dati più flessibili; • migliori performance di lettura/scrittura; • scalabilità in orizzontale. 9 Figura 5: Logo di MongoDB 3.2.2 Svantaggi Seguono gli svantaggi rilevati nell’utilizzo di MongoDB: • non ci sono controlli sull’integrità dei dati; • non supporta le transazioni. 3.3 Mongoose.js Mongoose è un modulo di Node.js che si interfaccia con MongoDB. Permette di accedere in modo semplice alle operazioni di CRUD messe a disposizione da MongoDB e consente la costruzione ed esecuzione di query. Permette inoltre di modellare i dati utilizzando uno schema. In questo modo è possibile controllare che i dati inseriti nel database si attengano ai vincoli definiti dallo schema. All’interno del progetto di stage Mongoose è utilizzato dalle classi del backend che si interfacciano con il database. Figura 6: Logo di Mongoose 3.3.1 Vantaggi I vantaggi nell’utilizzo di Mongoose.js sono i seguenti: • consente di dare uno schema ai documenti che verranno salvati su MongoDB; • permette di controllare l’integrità dei dati prima che vengano salvati sul database; • utilizza una sintassi molto simile a quella di MongoDB. 3.3.2 Svantaggi Il principale svantaggio dovuto all’utilizzo di Mongoose consiste nel rischio di un uso eccessivo di callback, in quanto le operazioni di CRUD messe a disposizione sono asincrone. 3.4 Express.js Express.js è un framework di Node.js che forisce un livello di astrazione maggiore alle operazioni messe a disposizione dal modulo http di Node.js. Tra le varie funzionalità di Express.js, le più importanti sono le seguenti: • permette la creazione di un server web; • permette di gestire in modo semplice le route; • permette di gestire le richieste HTTP; 10 • permette l’utilizzo di middleware; • permette l’utilizzo di template engine per la creazione di pagine web a partire da un template. All’interno del progetto questo framework è stato utilizzato per i seguenti scopi: • gestire le richieste POST HTTP provenienti dalle due applicazioni mobile; • creare il server. Figura 7: Logo di Express.js 3.4.1 Vantaggi I vantaggi nell’utilizzo di Express.js sono i seguenti: • permette l’utilizzo di middleware; • la gestione delle route è molto semplice; • in generale rende più semplice l’utilizzo delle funzionalià del modulo http. 3.4.2 Svantaggi Non sono stati rilevati grossi svantaggi nell’uso di Express.js, il quale risulta essere un buon framework che fornisce molti metodi per estendere il modulo http di Node.js. 3.5 Norris Norris, acronimo di Node Real-time Intelligence, è un framework basato su Node.js che permette di creare grafici lato server in modo semplice e veloce. I grafici creati con Norris possono essere visualizzati all’interno di una pagina web automaticamente generata dal framework, oppure possono essere inseriti all’interno del proprio sito web tramite l’utilizzo di CHUCK, una libreria lato client creata appositamente per questo scopo. Norris permette inoltre di aggiornare dal server i dati dei grafici. Ogni aggiornamento verrà visualizzato dai client in tempo reale. Figura 8: Logo di Norris 3.5.1 Vantaggi I vantaggi dovuti all’utilizzo di Norris sono i seguenti: • semplicità di utilizzo; • permette l’aggiornamento in tempo reale dei grafici; • crea in automatico la pagina web per visualizzare i grafici creati. 11 3.5.2 Svantaggi Gli svantaggi dovuti all’utilizzo di Norris sono i seguenti: • non è presente una libreria lato client per iOS. 3.6 Objective-C Objective-C è un linguaggio di programmazione orientato agli oggetti, derivato dal C. Il modello di programmazione object-oriented utilizzato da questo linguaggio si basa sullo scambio di messaggi tra le istanze. Objective-C viene utilizzato per scrivere software per OS X e iOS ed è il linguaggio in cui sono state scritte le due applicazioni iOS precedentemente descritte. 3.6.1 Vantaggi I vantaggi nell’utilizzo di Objective-C sono i seguenti: • permette di scrivere applicazioni iOS native; • è compatibile con Swift, il nuovo linguaggio di Apple. 3.6.2 Svantaggi Seguono gli svantaggi rilevati nell’utilizzo di Objective-C: • il codice non è di facile lettura; • l’Automatic Reference Counting è supportato solo per le API Cocoa, ma non per i costrutti derivati da C. 3.7 Socket.io Swift Client Socket.io Swift Client è una libreria scritta in Swift che permette comunicazioni real-time bidirezionali e basate su eventi. Si basa sulla tecnologia websocket e costituisce la libreria lato client di Socket.io. All’interno del progetto viene utilizzata per implementare la trasmissione degli aggiornamenti dei grafici che vengono mostati nell’applicazione degli utenti. Figura 9: Logo di Socket.io 3.7.1 Vantaggi L’utilizzo di Socket.io Swift Client fornisce i seguenti vantaggi: • permette di creare comunicazioni bi-direzionali tra client e server; • gestisce la connessione in modo trasparente; • è compatibile con Objective-C. 3.7.2 Svantaggi L’utilizzo di Socket.io Swift Client porta anche ad alcuni svantaggi: • richiede che anche il server utilizzi la libreria Socket.io; • non è presente una documentazione dettagliata di come utilizzare la libreria con Objective-C. 12 3.8 Parse Parse è una piattaforma che fornisce i seguenti servizi, utili per lo sviluppo di applicazioni web e mobile: • permette di salvare dati ed effettuare query su di essi; • permette di gestire job in backgrond per l’esecuzione di task; • permette di integrare Parse con il proprio server tramite API; • permette di gestire le notifiche push; • fornisce alcune statistiche riguardo l’utilizzo della propria applicazione. Figura 10: Logo di Parse 3.8.1 Vantaggi I vantaggi nell’utilizzo di Parse sono i seguenti: • la documentazione delle API è ben fatta e ricca di esempi; • è facile da usare anche per chi non sa programmare. 3.8.2 Svantaggi Seguono gli svantaggi rilevati nell’utilizzo di Parse: • è un software a pagamento; • la gestione delle notifiche push è limitata. 3.9 Layer Layer è una piattaforma che permette di creare un sistema di messaggistica istantanea all’interno della propria applicazione mobile. È utilizzato per implementare il sistema di istant messaging all’interno di TeddyApp. Figura 11: Logo di Layer 3.9.1 Vantaggi I vantaggi nell’utilizzo di Layer sono i seguenti: • è un sistema veloce e sicuro; • essendo un software a pagamento, fornisce un efficiente servizio di supporto. 13 3.9.2 Svantaggi Il principale svantaggio nell’utilizzo di Layer è costituito dal fatto che non c’è molta documentazione e quella che c’è è piuttosto sommaria e povera di esempi. 14 4 Lo stage: punti salienti dello sviluppo 4.1 Sintesi delle attività svolte Durante la stesura del piano di lavoro, sono state identificate le attività da svolgere durante lo stage per il raggiungimento degli obiettivi precedentemente descritti. In seguito si è deciso di ripartire queste attività all’interno di 4 fasi: 1. Apprendimento delle tecnologie 2. Progettazione e sviluppo del sistema di rating 3. Progettazione e sviluppo delle analisi delle statistiche di utilizzo 4. Progettazione e sviluppo di una dashboard per le aziende Dal diagramma di Gantt in Figura 12 si può vedere la durata temporale di ogni fase. Di seguito sono inoltre riportate, per ogni fase, le descrizioni delle principali attività svolte. Figura 12: Diagramma di Gantt 4.1.1 Apprendimento delle tecnologie Questa prima fase è stata dedicata all’apprendimento delle tecnologie utilizzate dall’azienda per lo sviluppo del prodotto descritto nella sezione Descrizione del prodotto. In particolare sono state studiate le seguenti tecnologie, fondamentali per la comprensione del prodotto e per lo sviluppo delle funzionalità previste dagli obiettivi dello stage: • Objective-C, linguaggio con cui sono state scritte le due applicazioni mobile; • Parse, piattaforma con la quale è stato creato il backend; • Layer, piattaforma con la quale è stato creato il sistema di messaggistica delle app. Si è reso quindi necessario familiarizzare con gli strumenti utilizzati dall’azienda per la gestione e lo sviluppo del progetto. Tra questi i principali sono: • Bitbucket e Git per la gestione del versionamento del codice; • CocoaPods per la gestione delle dipendenze delle due applicazioni; • Slack per le comunicazioni tra i membri dell’azienda; • Trello per la gestione dei task; • Xcode come ambiente di sviluppo. Infine è iniziato lo studio delle due applicazioni esistenti, soffermandosi dapprima sui servizi da esse forniti, per proseguire poi con l’analisi del codice. 15 4.1.2 Sistema di rating Questa fase è cominciata con l’analisi dei requisiti del sistema di rating. In contemporanea all’analisi dei requisiti, sono stati svolti alcuni esercizi assegnati dall’azienda. Lo scopo degli esercizi è di familiarizzare con il linguaggio Objective-C e con il codice delle due app. Sono riportati di seguito gli esercizi più significativi: • inserire Google Analytics nelle app; • rendere obbligatori i campi dei form di registrazione degli utenti e dei coach, in modo tale che non ci si possa registrare se non sono stati compilati tutti i campi; • automatizzare l’inserimento del codice del gruppo di apparenenza nell’app degli utenti: ogni utente appartiene ad un gruppo. Il gruppo è generalmente determinato dalla lingua parlata o dall’appartenza dell’utente ad un’azienda. La suddivisione degli utenti in gruppi consente agli utenti stessi di contattare solamente i coach della propria lingua o che lavorano per la propria azienda. Al momento dell’inizio dello stage sono presenti solamente gruppi che corrispondono alle lingue Italiano, Inglese e Olandese. Inoltre, l’utente deve inserire manualmente il codice del gruppo a cui appartiene, dopo averlo ricevuto per email. L’esercizio prevede che l’utente, scegliendo la lingua in cui vuole utilizzare l’app da un’apposita lista, venga automaticamente inserito all’interno del gruppo corrispondente; • permettere di modificare il codice del gruppo di appartenenza dalle impostazioni. Dopodichè si è proceduto con l’attività di progettazione: 1. Per prima cosa è stato progettato il database necessario al salvataggio di tutti i dati che interessano per lo sviluppo del sistema di rating, ovvero: • chiamate effettuate dagli utenti; • messaggi inviati e ricevuti dagli utenti; • valutazioni dei coach effettuate dagli utenti; • rating medio di ogni coach. Per maggiori dettagli riguardo la struttura del database, si rimanda all’appendice Database. 2. In secondo luogo è stato progettato il backend. Si è scelto di suddividerlo in 3 componenti: • DBManager: questa componente ha la responsabilità sulla gestione del database. In particolare si occupa della creazione delle varie collections, con i rispettivi schemi e fornisce un’interfaccia alle operazioni di CRUD. Contiene le uniche classi che hanno accesso diretto al DB, create utilizzando il design pattern DAO (Data Access Object). Ogni altra classe del backend può accedere al database solo tramite il DBManager. • RequestManager: questa componente si occupa della gestione delle richieste HTTP provenienti dall’applicazione; si occupa inoltre di gestire le comunicazioni con Parse. Si occupa quindi di gestire tutte le comunicazioni che avvengono tra il backend e gli altri sistemi che costituiscono il prodotto. • Controller: racchiude al suo interno le principali funzionalità del backend e coordina le classi di DBManager e RequestManager. Per maggiori dettagli riguardo la struttura del backend, si rimanda all’appendice Backend. 3. Si è dunque proceduto alla progettazione dell’integrazione del sistema di rating con l’applicazione degli utenti esistente. 4. Infine sono stati progettati i test di integrazione e di sistema da eseguire sul backend e sull’app. 16 Una volta conclusa l’attività di progettazione, si è proceduto con l’attività di sviluppo. Durante questa attività sono state implementate le funzionalità del sistema di rating seguendo l’ordine con cui le varie parti sono state progettate. In parallelo all’attività di sviluppo, è stata stesa la documentazione del codice prodotto per il backend utilizzando lo strumento JSdoc. Una volta sviluppato il backend, si è proceduto con l’integrazione nell’app delle nuove funzionalità. È stata quindi creata una view che permette all’utente di valutare il coach. È stato inoltre realizzato un apposito meccanismo di comunicazione tra l’app e il nuovo backend. Questo meccanismo si basa su richieste POST HTTP tramite le quali l’applicazione si autentica al server e gli invia i dati. Terminata l’attività di integrazione delle funzionalità del nuovo backend con l’applicazione, sono stati effettuati i test di integrazione e di sistema. Infine si è proceduto con la configurazione di un server Amazon, nel quale è stato installato e configurato il software necessario, ovvero MongoDB e Node.js. È stato quindi avviato il nuovo backend. 4.1.3 Analisi delle statistiche di utilizzo Questa fase è cominciata con l’analisi dei requisiti delle analisi delle statistiche di utilizzo dell’applicazione che si vogliono fornire agli utenti. Dopodichè si è proceduto con l’attività di progettazione: 1. Per prima cosa sono state progettate le nuove classi e funzionalità da aggiungere al backend. Sono riportate di seguito le principali modifiche effettuate: • Controller: a questa componente sono state aggiunte le classi che permettono di creare i grafici delle statistiche di utilizzo a partire dai dati presenti nel database. Queste nuove classi si occupano inoltre di mantenere i dati dei grafici aggiornati, tramite l’utilizzo della tecnologia websocket. • È stato intoltre creato il modello dei dati che si vogliono mostrare agli utenti sottoforma di grafici. Per maggiori dettagli riguardo la struttura del backend in seguito all’aggiunta delle nuove funzionalità, si rimanda all’appendice Backend. 2. In secodo luogo è stata progettatta la comunicazione tra il backend e l’applicazione tramite l’utilizzo della tecnologia websocket. Questa tecnologia viene utilizzata per permettere l’aggiornamento in tempo reale dei dati dei grafici. 3. È stata poi progettata la view che permette agli utenti di visualizzare le nuove statistiche di utilizzo. 4. Infine sono stati progettati i test di integrazione e di sistema. Terminata l’attività di progettazione, si è proceduto con l’attività di sviluppo. Durante questa attività sono state implementate le classi del backend che si occupano di effettuare le analisi delle statistiche di utilizzo dell’applicazione. In parallelo all’attività di sviluppo, è stata stesa la documentazione del codice prodotto per il backend utilizzando lo strumento JSdoc. Una volta sviluppato il backend, si è proceduto allo sviluppo della comunicazione tra backend e applicazione. Si è poi passati allo sviluppo della view delle statistiche di utilizzo. Infine è stata effettuata l’integrazione nell’app delle nuove funzionalità e i vari test. 4.1.4 Dashboard per le aziende Questa fase è cominciata con l’analisi dei requisiti della dashboard, a partire dal mokup in Figura 13 creato dal grafico dell’azienda. Si è proceduto dunque con la progettazione: 1. Per prima cosa sono state progettate le nuove collections da aggiungere al database, in modo da poter salvare le informazioni inerenti a: • le aziende che usufruiscono del servizio; 17 Figura 13: Mokup della dashboard per le aziende • gli utenti di ogni azienda; • i coach. Per maggiori dettagli riguardo la struttura del database in seguito all’aggiunta delle nuove collections, si rimanda all’appendice Database. 2. In secondo luogo sono state progettate le nuove classi e funzionalità da aggiungere al backend. Sono riportate di seguito le principali modifiche effettuate alle componenti del backend: • DBManager: a questa componente sono state aggiunte le classi per la gestione delle nuove collections; • RequestManager: alle classi di questa componente sono stati aggiunti alcuni metodi, utili per lo sviluppo delle nuove funzionalità richieste; • Controller: a questa componente sono state aggiunte le classi per il coordinamento delle nuove classi del DBManager. Inoltre, vista la mole delle nuove funzionalità richieste, è stata creata la componente Dashboard. Al suo interno sono state raggruppare le classi che si occupano di definire la struttura e le funzionalità della dashboard. Questa componente è stata a sua volta suddivisa in tre sottocomponenti, utilizzando il Design Pattern MVP: • Model: questa componente contiene il modello dei dati della dashboard; • View: questa componente contiene i template HTML dai quali vengono generate le varie dashboard; • Presenter: questa componente racchiude l’intera logica di creazione di una dashboard: dalla creazione dei grafici, all’aggiornamento in tempo reale dei dati in essi contenuti. Per maggiori dettagli riguardo la struttura del backend in seguito all’aggiunta delle nuove funzionalità, si rimanda all’appendice Backend. 3. Infine sono stati progettati i test di unità, di integrazione e di sistema per la dashboard. 18 Terminata l’attività di progettazione, si è proceduto con l’attività di sviluppo. Durante questa attività sono state create le nuove collections nel database e sono state implementate le principali funzionalità della dashboard. Non è stato possibile sviluppare tutte le funzionalità a causa della limitata disponibilità di tempo, ma è stato comunque creato un primo prototipo funzionante. In parallelo all’attività di sviluppo, è stata stesa la documentazione del codice prodotto per il backend utilizzando lo strumento JSdoc. Infine sono stati eseguiti alcuni test sul prototipo creato. 4.2 Criticità incontrate In questa sezione vengono presentate le criticità riscontrate durante lo stage e come queste sono state risolte. 4.2.1 Autenticazione al server La prima criticità incontrata nel corso dello stage è data dalla necessità di inviare dati dalle applicazioni mobile al nuovo server. Per fare ciò in modo sicuro si ha infatti bisogno di un efficacie sistema di autenticazione. È stato dunque necessario soffermarsi sulla progettazione di quest’ultimo. Inizialmente si è pensato alla classica autenticazione tramite invio di username e password. Tuttavia, non essendo ancora attivo sul server Amazon un certificato SSL, questa opzione è stata scartata. Infatti, nel caso in cui un utente malevolo intercettasse queste informazioni, potrebbe utilizzarle per autenticarsi al server al posto dell’utente a cui appartengono. Questo avverrebbe anche se le informazioni venissero criptate prima di essere inviate al server. Sì è dunque pensato di generare un token a partire dall’ID dell’utente e da una chiave privata, condivisa da applicazioni e server. Ogni app avrebbe inviato questo token al server, assieme all’ID dell’utente. Il server avrebbe provveduto a controllare l’autenticità del token confrontandolo con un token creato utilizzando lo stesso procedimento. Tuttavia anche questa soluzione non è sicura. Anche in questo caso, infatti, se un utente malevolo intercettasse il token e l’ID dell’utente, potrebbe utilizzarli per autenticarsi al server. Dopo aver capito di avere la necessità di un token diverso per ogni autenticazione, si è pensato di strutturare l’autenticazione delle app al server nel seguente modo: 1. Per prima cosa l’applicazione invia al server l’ID dell’utente; 2. Il server genera una chiave casuale e la salva nel database, associata all’ID dell’utente; 3. Il server invia all’app la chiave appena generata; 4. L’app crea un token a partire dall’ID dell’app, dalla chiave casuale ricevuta dal server e da una chiave privata, condivisa con il server; 5. L’app cripta il token con algoritmo SHA-1 ; 6. L’app invia al server il token criptato, assieme ai dati che dovranno essere salvati nel database; 7. Il server controlla che il token inviato dall’app sia corretto e, in caso affermativo, salva i dati nel database; 8. Il server elimina dal database la chiave casuale precedentemente generata. In questo modo, anche se un utente malevolo intercettasse un token, non potrebbe utilizzarlo poichè non sarebbe più valido. 4.2.2 Rating dopo una conversazione via chat Oltre alla possibilità di valutare un coach al termine di una chiamata, si vuole dare la possibilità ad un utente di valutare un coach anche dopo una conversazione avvenuta tramite messaggi. È stata definita come conversazione uno scambio di messaggi di cui almeno 7 sono stati inviati dal coach all’utente. Il problema che si pone riguarda il come presentare all’utente la possibilità di 19 valutare il coach. Fin dall’inizio è stata esclusa l’opzione di mostrare la schermata di rating dopo aver raggiunto i 7 messaggi inviati dal coach. Infatti, non è detto che una volta raggiunti i 7 messaggi, la conversazione sia giunta al termine. E se la conversazione non fosse ancora conclusa, il sopraggiungere della schermata di rating sarebbe invasivo e di disturbo per l’utente. Non essendo possibile sapere con esattezza quando una conversazione via messaggi sia conclusa, si è dovuto pensare a delle alternative. La prima opzione consiste nell’invio di una notifica all’utente subito dopo la ricezione del settimo messaggio. Quando l’utente clicca sul messaggio della notifica, viene mostrata la schermata del rating e l’utente può valutare il coach. Le problematiche emerse da questa possibile soluzione sono le seguenti: 1. Innanzitutto bisognerebbe fare in modo che la notifica sia sempre visibile durante la conversazione; bisognerebbe dunque trovare una posizione in cui non sia di disturbo alla chat. Questo è un problema soprattutto per i dispositivi con schermi piccoli. 2. Inoltre questa soluzione è di difficile realizzazione. Per questi motivi si è deciso di abbandonare questa possibilità, a favore di una seconda opzione: la creazione di un pulsante Rate. L’utente può trovare questo pulsante nella schermata in cui vengono visualizzati i coach on-line. Quando l’utente preme questo pulsante, viene mostrata la schermata del rating. Una volta che l’utente ha valutato il coach, il pulsante Rate viene nascosto. Questa soluzione è stata ritenuta la migliore per le ragioni seguenti: • non interrompe la conversazione; • non è un possibile elemento di disturbo; • non è difficile da implementare. 4.2.3 Socket.IO Swift Client Socket.IO Swift Client è la libreria utilizzata nell’app per ricevere i dati dei grafici provenienti dal server. Utilizzando la tecnologia websocket, questa libreria permette di avere i dati aggiornati in tempo reale, senza necessità di refresh. La versione per iOS di questa libreria è però scritta in Swift. La compatibilità con Objective-C non ha costituito un problema, in quanto X-Code genera in automatico un’interfaccia che permette di utilizzare in Objective-C codice scritto in Swift. I problemi sono sorti però nel capire come utilizzare le funzionalità offerte dalla libreria. La documentazione a riguardo è infatti molto scarsa. Inoltre, essendo il codice scritto in Swift, è stato particolarmente difficile capire in che modo richiamare le funzioni in Objective-C, in quanto la sintassi dei due linguaggi è completamente differente. Sempre a causa della mancanza di documentazione, è stato particolarmente difficile capire quale fosse il formato corretto dei parametri da passare alle funzioni della libreria. Analizzando il codice Swift e facendo alcune analogie con la versione lato server della libreria, si è alla fine riusciti a capire il funzionamento della libreria stessa. 4.3 4.3.1 Altre scelte implementative Scelta del driver per MongoDB Per lo svolgimento del progetto di stage si è reso necessario scegliere quale driver utilizzare per interfacciarsi a MongoDB con Node.js. Node.js mette a disposizione due moduli per svolgere questa funzione: 1. mongodb, il driver ufficiale per MongoDB; 2. Mongoose, il quale si basa su mongodb per offrire un’interfaccia più ad alto livello. Sebbene l’utilizzo di mongodb sia molto semplice, Mongoose offre maggiori funzionalità, quali: • la possibilità di creare uno schema per i dati da salvare nel database; 20 • la possibilità di validare i dati secondo gli schemi definiti; • la possibilità di verificare l’integrità dei dati prima che vengano salvati nel database. Queste funzionalità si aggiungono alle funzioni di CRUD offerte da entrambi i moduli. Le funzionalità aggiuntive che offre Mongoose sono molto utili, in quanto suppliscono alla mancanza di controlli sull’integrità dei dati da parte di MongoDB. È stato dunque scelto di utilizzare proprio questo modulo, del quale si può vedere un’analisi dettagliata nella sezione Tecnologie utilizzate. 4.3.2 Scelta del design pattern MVP per la Dashboard Durante la progettazione della dashboard è emersa la complessità di questa componente. È stato dunque necessario renderla più modulare, in modo da poterla suddividere in sottocomponenti più semplici, con compiti più specifici. Si è deciso quindi di utilizzare il Design Pattern Model View Presenter. A differenza del pattern Model View Controller, MVP racchiude all’interno del Presenter anche la logica presentazionale, rendendo la View un semplice template e disaccopiando il Model dalla View stessa. Questa caratteristica ben si adatta alla dashboard, in quanto i dati presenti nella View vengono aggiornati in tempo reale dal framework Norris ogniqualvolta i dati presenti nel Model subiscono delle variazioni. Non è dunque necessaria alcuna interazione tra le componenti View e Model. Inolte, il fatto che la View sia un template permette al Presenter di gestire facilmente la logica di presentazione tramite l’utilizzo di EJS, un template engine messo a disposizione dal framework Express.js. 21 22 5 Verifica e validazione Al termine di ogni fase del progetto si è proceduto con l’attività di verifica per assicurarsi che il codice prodotto fosse privo di bug e conforme a quanto richiesto dai requisiti. In questa sezione vengono riportate: • la strategia di verifica, ovvero l’insieme degli obiettivi di qualità che si vogliono soddisfare, associati alle metriche utilizzate per quantificare tali obiettivi; • le modalità di testing con le quali è stato verificato il codice prodotto. 5.1 5.1.1 Strategia di verifica Obiettivi di qualità Prima di iniziare l’attività di progettazione, sono stati definiti gli obiettivi di qualità da perseguire. Ad ogni obiettivo sono state poi associate una o più metriche, in modo da rendere tale obiettivo quantificabile. Inoltre, sono stati fissati un range di accettazione e un range di ottimalità, affinchè sia possibile determinare se un obiettivo sia stato raggiunto o meno. Vengono riportati di seguito gli obiettivi perseguiti durante il progetto di stage. 5.1.1.1 Funzionalità Questo obiettivo indica se il prodotto realizzato soddisfa o meno le richieste degli utenti. Per misurare il grado di funzionalità si è scelto di utilizzare come metrica la percentuale dei requisiti funzionali (ovvero i requisiti che si riferiscono a funzionalità) realizzati. Metrica utilizzata per quantificare l’obiettivo : percentuale di requisiti funzionali realizzati; Soglia di accettabilità : 100% obbligatori, 98% desiderabili, 90% opzionali; Soglia di ottimalità : 100% obbligatori, 100% desiderabili, 95% opzionali. Al termine dello svolgimento del progetto di stage si vuole raggiungere un esito almeno accettabile. 5.1.1.2 Semplicità Questo obiettivo indica se il codice prodotto risulta essere di semplice utilizzo o meno. Un codice più semplice è anche più facile da comprendere e la sua manutenzione risulta meno difficile. Per misurare il grado di semplicità del codice, si è scelto di utilizzare come metrica il numero di parametri di un metodo. Metrica utilizzata per quantificare l’obiettivo : numero di parametri per metodo Soglia di accettabilità : tutti i metodi hanno al più 5 parametri; Soglia di ottimalità : tutti i metodi hanno al più 3 parametri. Al termine dello svolgimento del progetto di stage si vuole raggiungere un esito ottimale. 5.1.1.3 Manutenibilità e comprensibilità del codice Questo obiettivo indica se il codice prodotto risulta essere facilmente comprensibile, e dunque manutenibile, o meno. Vengono riportate di seguito le metriche utilizzate per misurare il grado di comprensibilità e manutenibilità del codice, assieme alle rispettive soglie di accettazione e ottimalità: • numero di statement di un metodo: Soglia di accettabilità : tutti i metodi hanno al più 60 statement; Soglia di ottimalità : tutti i metodi hanno al più 30 statement. • numero di campi dati per classe: 23 Soglia di accettabilità : tutte le classi hanno al più 8 campi dati; Soglia di ottimalità : tutte le classi hanno al più 5 campi dati. • grado di accoppiamento: Soglia di accettabilità : massimo 7 classi dipendenti per ogni package; Soglia di ottimalità : massimo 5 classi dipendenti per ogni package. Al termine dello svolgimento del progetto di stage si vuole raggiungere un esito almeno accettabile. Per una descrizione più dettagliata delle metriche utilizzate, si rimanda alla sezione Metriche. 5.1.2 Metriche Percentuale di requisiti funzionali realizzati Questa metrica serve a misurare la funzionalità del prodotto. È fondamentale per determinare se a fine progetto sono stati realizzati tutti i requisiti funzionali richiesti. I range di accettazione per questa metrica sono: • meno del 100% dei requsiti obbligatori, meno del 98% dei requsiti desiderabili e meno del 90% dei requsiti opzionali è considerato negativo; • il 100% dei requsiti obbligatori, almeno il 98% dei requsiti desiderabili, almeno il 90% dei requsiti opzionali è considerato acettabile; • il 100% dei requsiti obbligatori, il 100% dei requsiti desiderabili, almeno il 95% dei requsiti opzionali è considerato ottimale. Numero di parametri per metodo Un metodo con un numero troppo elevato di parametri formali in input risulta essere complesso e poco manutenibile rispetto ad un metodo con un basso numero di parametri formali. È dunque necessario, per garantire un discreto livello di manutenibilità, che il numero di parametri di ogni metodo sia al più pari a 5. Il numero di parametri di un metodo può considerarsi ottimale quando assume valori al più uguali a 3. Numero di statement di un metodo Un metodo con una grande quantità di statement risulta essere complesso e meno manutenibile rispetto a metodi più compatti. Se un metodo deve svolgere diverse azioni complesse, è buona norma che queste azioni vengano incapsulate all’interno di altri metodi. In questo modo si evita di appesantire il codice di un singolo metodo, favorendone la comprensibilità e la manutenibilità. I range di accettazione per questa metrica sono: • valori maggiori di 60 sono considerati negativi; • valori compresi tra 30 e 60 sono considerati accettabili; • valori minori di 30 sono considerati ottimali. Numero di campi dati di una classe Una classe con un elevato numero di campi dati risulta essere complessa, difficilmente riutilizzabile e poco manutenibile. Nel caso di classi che necessitano di molti campi dati, sarebbe opportuno incapsulare una parte di essi all’interno di una nuova classe. I range di accettazione per questa metrica sono: • valori maggiori di 8 sono considerati negativi; • valori compresi tra 5 e 8 sono considerati accettabili; • valori minori di 5 sono considerati ottimali. 24 Grado di accoppiamento Il grado di accoppiamento di un programma è il grado con cui ciascuna componente di un programma dipende da ciascuna delle altre componenti. In presenza di un basso grado di accoppiamento, eventuali modifiche apportate ad una classe hanno poche ripercussioni (o nessuna) sulle altre classi del sistema. Il codice risulta quindi facilmente manutenibile. Un basso accoppiamento è anche indice di maggiore comprensibilità del codice e di alta coesione all’interno delle componenti. Viceversa, un alto grado di accoppiamento comporta una difficile manutenibilità del codice, il quale risulta più complesso e poco coeso. Per valutare il grado di accoppiamento del codice, si devono calcolare due diverse tipologie di indici: • Accoppiamento Afferente (CA): indica il numero di classi esterne ad un package che dipendono da classi interne ad esso. Un alto valore di CA è indice di un alto grado di dipendenza del resto del software dal package. • Accoppiamento Efferente (CE): indica il numero di classi interne al package che dipendono da classi esterne ad esso. Un basso valore di CE indica che la maggior parte delle funzionalità fornite dal package sono indipendenti dal resto del sistema. I range di accettazione per questa metrica sono: • valori maggiori di 8 sono considerati negativi; • valori compresi tra 5 e 7 sono considerati accettabili; • valori minori o uguali a 5 sono considerati ottimali. 5.1.3 Esiti delle misurazioni Vengono riportati di seguito gli esiti delle misurazioni effettuate durante le attività di verifica previste per le ultime tre fasi del progetto. Per quanto riguarda le applicazioni mobile, le metriche sono state calcolate solamente sulle classi create interamente durante il progetto di stage. Le classi già presenti all’inzio dello stage non sono state considerante. Sistema di rating • Percentuale di requisiti funzionali realizzati: al termine di questa fase sono stati soddisfatti tutti i requisiti previsti per il sistema di rating. Si ha dunque raggiunto un esito ottimale; • Numero di parametri di un metodo: come si può vedere dal grafico in Figura 14, la maggiorparte dei metodi ha un numero di parametri inferiore a 3; solo una piccola parte ha esattamente 3 parametri, mentre nessun metodo ha un numero di parametri maggiore di 3. Si può dunque ritenere di aver raggiunto un risultato ottimale. Figura 14: Esiti seconda fase: parametri per metodo 25 • Numero di statement di un metodo: la maggiorparte dei metodi ha un numero di statement inferiore a 30. Solo pochi metodi della componente Controller arrivano ad avere quasi 60 statement, mentre nessun metodo supera i 60 statement. Nel complesso si è quindi raggiunto un risultato ottimale. • Numero di campi dati di una classe: quasi tutte le classi realizzate in questa fase hanno un numero di campi dati inferiore a 5. Fa eccezione la classe RatingViewController dell’applicazione degli utenti, la quale arriva ad avere un numero di campi dati pari a 10. Il motivo di un così elevato numero di campi dati è dovuto al fatto che si tratta per lo più di componenti grafiche che costituiscono la schermata per effettuare il rating. Nel complesso si può dunque ritenere di aver ottenuto un esito accettabile. • Grado di accoppiamento: al termine dell’attività di progettazione è stato misurato il grado di accoppiamento delle componenti Controller, DBManager e RequestManager, ottenendo i seguenti risultati: Componente Controller DBManager RequestManager Accoppiamento afferente 1 5 3 Accoppiamento efferente 5 0 1 Tabella 1: Esiti seconda fase: grado di accoppiamento Analisi delle statistiche di utilizzo • Percentuale di requisiti funzionali realizzati: al termine di questa fase sono stati soddisfatti tutti i requisiti previsti per l’analisi delle statistiche di utilizzo dell’app. Si ha dunque raggiunto un esito ottimale; • Numero di parametri di un metodo: come si può vedere dal grafico in Figura 15, la maggiorparte dei metodi ha un numero di parametri inferiore a 3; solo una piccola parte ha esattamente 3 parametri, mentre nessun metodo ha un numero di parametri maggiore di 3. Si può dunque ritenere di aver raggiunto un risultato ottimale. Figura 15: Esiti terza fase: parametri per metodo • Numero di statement di un metodo: la maggiorparte dei metodi implementati durante questa fase ha un numero di statement inferiore a 30. Solo pochi metodi della componente Controller arrivano ad avere quasi 60 statement, mentre nessun metodo supera i 60 statement. Nel complesso si è quindi raggiunto un risultato ottimale. • Numero di campi dati di una classe: quasi tutte le classi realizzate o modificate in questa fase hanno un numero di campi dati inferiore a 5. Fa eccezione la classe AnalysisViewController dell’applicazione degli utenti, la quale arriva ad avere un numero di campi dati pari 26 a 10. Il motivo di un così elevato numero di campi dati è dovuto al fatto che si tratta per lo più di componenti grafiche che costituiscono la schermata delle statistiche di utilizzo del servizio. Nel complesso si può dunque ritenere di aver ottenuto un esito accettabile. • Grado di accoppiamento: al termine dell’attività di progettazione è stato misurato il grado di accoppiamento delle componenti Controller, DBManager e RequestManager, ottenendo i seguenti risultati: Componente Controller DBManager RequestManager Accoppiamento afferente 1 6 3 Accoppiamento efferente 6 0 1 Tabella 2: Esiti terza fase: grado di accoppiamento Dashboard per le aziende • Percentuale di requisiti funzionali realizzati: al termine di questa fase non sono stati soddisfatti i requisiti desiderabili che prevedono l’utilizzo della libreria grafica AMCharts per la visualizzazione dei grafici lato client. Inoltre la struttura della View è ancora approssimativa e molto lontana dal risultato a cui si mira, nonostante contenga tutte le informazioni richieste. Si ritiene dunque che per questa fase l’esito di questa metrica non sia del tutto accettabile. Nonostante ciò, la creazione della dashboard costituisce un obiettivo opzionale del progetto di stage. Non era prevista dunque la sua completa realizzazione. Il fatto di essere riusciti a produrre un prototipo funzionante può quindi considerarsi accettabile ai fini dello stage. • Numero di parametri di un metodo: come si può vedere dal grafico in Figura 16, la maggiorparte dei metodi ha un numero di parametri inferiore a 3; solo una piccola parte ha esattamente 3 parametri, mentre nessun metodo ha un numero di parametri maggiore di 3. Si può dunque ritenere di aver raggiunto un risultato ottimale. Figura 16: Esiti quarta fase: parametri per metodo • Numero di statement di un metodo: la maggiorparte dei metodi implementati durante questa fase ha un numero di statement inferiore a 30. Solo un metodo della componente Model arriva ad avere quasi 60 statement, mentre nessun metodo supera i 60 statement. Nel complesso si è quindi raggiunto un risultato ottimale. • Numero di campi dati di una classe: tutte le classi della Dashboard hanno un numero di campi dati al più pari a 3. Si può dunque ritenere di aver ottenuto un esito ottimale. • Grado di accoppiamento: al termine dell’attività di progettazione è stato misurato il grado di accoppiamento delle componenti Controller, Dashboard, DBManager e RequestManager, ottenendo i seguenti risultati: 27 Componente Controller Dashboard DBManager RequestManager Accoppiamento afferente 8 0 9 3 Accoppiamento efferente 9 7 0 1 Tabella 3: Esiti quarta fase: grado di accoppiamento Nonostante la presenza di valori negativi (evidenziati in rosso), si può ritenere che l’esito di questa metrica sia comunque accettabile. Infatti, per quanto riguarda il DBManager si ha un alto grado di accoppiamento afferente. Ciò non è una cosa del tutto negativa, poichè significa che questa componente ha un’importanza fondamentale all’interno del progetto. Per quanto riguarda il Controller, si può notare che l’alto grado di accoppiamento efferente è dovuto al fatto che ogni tipologia di controller dipende dalla classe DBManager:CollectionDAO. Questo è inevitabile, in quanto ogni controller deve essere in grado di effettuare operazioni sul database. Viene riportata di seguito una tabella che riassume i risultati ottenuti per ogni metrica. Gli esiti riportati sono stati ottenuti facendo la media dei risultati di ogni misurazione effettuata. Metrica Percentuale di requisiti funzionali realizzati Numero di parametri per metodo Numero di statement di un metodo Numero di campi dati di una classe Accoppiamento afferente Accoppiamento efferente Esito accettabile ottimale ottimale accettabile accettabile accettabile Tabella 4: Esiti delle misurazioni effettuate Si ritiene dunque di aver raggiunto gli obiettivi prefissati. 5.2 Testing del backend Il backend è stato testato dinamicamente tramite l’esecuzione di test, che hanno permesso di rilevare in modo efficace eventuali errori presenti nel codice. I test effettuati sul backend sono di varie tipologie: • test di unità; • test di integrazione; • test di sistema. I test di unità sono stati effettuati su ogni classe del backend, utilizzando Mocha, uno strumento che permette di effettuare test di unità e integrazione in Node.js. Questo ha permesso di rilevare fin da subito la maggior parte degli errori presenti nel codice. Al termine di ogni fase sono stati effettuati i test di integrazione, in modo tale da verificare che le varie classi e componenti interagissero correttamente tra di loro. Dopo aver testato il software in locale, sono stati effettuati i medesimi test anche sul server Amazon, utilizzando un database appositamente creato per i test, ma con le stesse caratteristiche del database che si sarebbe poi utilizzato. I test effettuati hanno permesso di rilevare alcune problematiche legate alla comunicazione tra il backend e le due applicazioni mobile, che sono state adeguatamente risolte. Infine, sono stati effettuati i test di sistema, tramite i quali la stagista ha verificato assieme all’azienda che il prodotto funzionasse correttamente e soddisfasse i requisiti precedentemente stabiliti. 28 5.3 Testing delle applicazioni mobile L’attività di testing delle due applicazioni mobile si è svolta in modo leggermente diverso rispetto a quella effettuata sul backend. Infatti, la maggiorparte delle operazioni effettuate sulle due app sono costituite da modifiche o aggiunte a classi e metodi già esistenti. Essendo poche le classi create da zero, si è proceduto direttamente con i test di integrazione. Sono poi stati effettuati anche per le due app i test di sistema, in modo da poter verificare assieme all’azienda il corretto soddisfacimento dei requisiti. 29 30 6 Conclusioni 6.1 Obiettivi raggiunti In riferimento agli obiettivi riportati nella sezione Obiettivi dello stage, si possono trarre le seguenti conclusioni: 1. sono stati soddisfatti tutti gli obiettivi minimi previsti dal piano di lavoro; 2. sono stati parzialmente soddisfatti gli obiettivi opzionali previsti. In particolare non è stata soddisfatta la richiesta di realizzazione di un’interfaccia web che permettesse la visualizzazione delle statistiche d’uso degli utenti agli utenti stessi. Sono state invece implementate nel nuovo backend molte delle funzionalità presenti in Parse. È stato inoltre creato un prototipo funzionante di una dashboard per le aziende. Si può dunque ritenere di aver soddisfatto una buona parte degli obiettivi opzionali. 6.2 Conoscenze acquisite Durante il progetto di stage sono state utilizzate numerose tecnologie, molte delle quali inizialmente sconosciute. Si riportano di seguito le principali conoscenze e competenze acquisite. 6.2.1 MongoDB L’utilizzo di MongoDB costituisce il mio primo approcio ad un database non relazionale. Di questo DBMS sono state approfondite le principali differenze rispetto ad un database relazionale e ne è stata appresa la struttura document-oriented. Al termine dello stage si ritiene di aver acquisito una buona padronanza della shell di MongoDB e delle operazioni di CRUD effettuabili sulle collections. Non sono state invece approfondite operazioni più avanzate quali Aggregation Pipeline e Map Reduce, in quanto non necessarie per lo svolgimento del progetto. 6.2.2 Node.js Sebbene avessi già una conoscenza di base di questo framework, il suo ampio utilizzo all’interno del progetto di stage mi ha permesso di consolidare le conoscenze pregresse e acquisirne di nuove. In particolare sono state consolidate le seguenti conoscenze: • costrutti del linguaggio JavaScript; • utilizzo del framework Express.js; • utilizzo del template engine EJS. Sono state inoltre acquisite le seguenti competenze: • buona padronanza del modulo Mongoose; • comprensione del meccanismo delle promises e loro utilizzo; • conoscenza e utilizzo di vari moduli di Node.js, quali q, sha-1, generate-key. 6.2.3 iOS Questo progetto di stage costituisce per me il primo approcio alle tecnologie mobile. Da questa esperienza sono state apprese, in modo più o meno approfondito, svariate tecnologie legate allo sviluppo di applicazioni iOS. In particolare sono state acquisite le seguenti competenze: • conoscenza della struttura di un’applicazione iOS; • utilizzo del linguaggio di programmazione Objective-C nel contesto dello sviluppo di un’applicazione iOS; 31 • invio e ricezione di dati tramite richieste POST HTTP; • ricezione di dati in tempo reale tramite l’utilizzo della libreria SocketIO Swift Client; • sviluppo di semplici interfacce grafiche; • integrazione dell’applicazione con Parse; • gestione delle dipendenze del codice di un’applicazione tramite l’utilizzo di CocoaPods; • utilizzo di alcune funzionalità dell’IDE Xcode. 6.3 Sviluppi futuri Al termine del progetto di stage rimangono ancora parecchie prospettive di miglioramento per il prodotto che sta realizzando l’azienda: • Finitura dell’interfaccia della dashboard: l’interfaccia della dashboard non è ancora nella sua versione definitiva. Sono infatti da apportare le segenti modifiche: – modificare la libreria grafica per la visualizzazione dei grafici lato client. Attualmente la libreria utilizzata è Google Charts, ma si vorrebbe passare all’utilizzo di AMCharts; – rifinire il template, in modo da renderlo conforme al mokup progettato (vedi Figura 13 per maggiori dettagli). • Sviluppo di un sistema di autenticazione per le aziende: per permettere ad ogni azienda di accedere alla propria dashboard personale è necessaria la realizzazione di un sistema di autenticazione tramite il quale le aziende potranno effettuare il login. • Sviluppo di un’applicazione Android per ampliare il bacino di utenza: al momento il servizio offerto dall’azienda è disponibile solamente per utenti iOS. Questa scelta costituisce un buon punto di partenza, ma si rischia di perdere un’ampia fascia di mercato se all’applicazione iOS non si affianca un’analoga applicazione per gli utenti Android. • Sviluppo di un’interfaccia web per rendere il servizio ancora più accessibile: permettere agli utenti di utilizzare il servizio non solo da telefono, ma anche da computer costituirebbe un enorme valore aggiunto al prodotto. 32 A Database Il database è stato realizzato con MongoDB, un DBMS non relazionale. Per definizione, questo tipo di database è privo di schema. Si è quindi voluto dare una struttura al database utilizzando il modulo di Node.js, Mongoose. Viene riportato in Figura 17 lo schema implementato con Mongoose. In giallo sono evidenziati i campi che si riferiscono a campi presenti in altre collections, delle quali sono chiavi primarie. Nonostante in un database non relazionale non esista il concetto di chiave esterna, si è ritenuto utile per la comprensione della struttura del database mettere in evidenza questi campi. Figura 17: Schema del Database Segue la descrizione di ogni collection del DB: • Call: è la collection che contine le informazioni inerenti le chiamate effettuate dagli utenti ai coach. Di ogni chiamata vengono salvati: – lo username dell’utente che ha effettuato la chiamata; – lo username del coach che ha ricevuto la chiamata; – la durata della chiamata; – la data in cui è stata effettuata. MongoDB associa automaticamente un codice identificativo ad ogni chiamata. • Message: è la collection che contine le informazioni inerenti i messaggi inviati dagli utenti ai coach, e viceversa. Di ogni messaggio vengono salvati: – lo username del mittente; 33 – lo username del destinatario; – il testo del messaggio; – la data in cui il messaggio è stata inviato. Inoltre, se il mittente è un coach, viene salvato il tempo di risposta, ovvero il tempo che intercorre tra l’ultimo messaggio ricevuto dal coach da parte dell’utente a cui sta rispondendo e il momento in cui il messaggio corrente viene inviato. MongoDB associa automaticamente un codice identificativo ad ogni messaggio. • Rating: è la collection che contine le informazioni inerenti le valutazioni dei coach effettuate dagli utenti. Di ogni valutazione vengono salvati: – lo username dell’utente che l’ha effettuata; – lo username del coach valutato; – il valore numerico della valutazione (da 1 a 5); – la data in cui è stata effettuata. MongoDB associa automaticamente un codice identificativo ad ogni valutazione. • Average: è la collection che contiene le informazioni inerenti la media delle valutazioni di ogni coach. Inoltre sono presenti altre informazioni riassuntive quali: – il numero di chiamate ricevute da ogni coach; – il numero di messaggi inviati da ogni coach; – il tempo di risposta medio di ogni coach. La chiave primaria di ogni documento di questa collection è costituita dallo username dei coach. • Session: è la collection che contine le informazioni inerenti le sessioni. Di ogni sessione vengono salvati: – l’ID dell’utente che si vuole autenticare al server; – una chiave casuale generata dal server; – la data in cui la sessione è stata creata. MongoDB associa automaticamente un codice identificativo ad ogni sessione. • Company: è la collection che contine le informazioni inerenti le aziende. Di ogni azienda vengono salvati: – il nome; – la password crittata; – il numero totale degli utenti dell’azienda registrati al servizio; – il numero totale delle conversazioni che questi utenti hanno avuto con i coach; – il numero di conversazioni che si sono tenute tra le 5 e le 10 del mattino; – il numero di conversazioni che si sono tenute tra le 11 e le 17; – il numero di conversazioni che si sono tenute tra le 18 e le 2 di notte; – il fuso orario della sede dell’azienda; – il numero di utenti attivi per ogni giorno della settimana; – il numero di conversazioni effettuate dagli utenti dell’azienda per ogni giorno della settimana. La chiave primaria di ogni documento di questa collection è costituita dal nome dell’azienda. 34 • User: è la collection che contiene le informazioni inerenti gli utenti. Di ogni utente vengono salvati: – lo username; – l’azienda a cui appartiene; – la data in cui si è registrato al servizio; – il momento in cui è stato attivo per l’ultima volta, ovvero l’ultima volta in cui ha avuto una conversazione con un coach. La chiave primaria di ogni documento di questa collection è costituita dallo username degli utenti. • Coach: è la collection che contiene le informazioni inerenti i coach. Di ogni coach vengono salvati: – lo username; – il nome; – il congnome; – le aziende per le quali svolge il lavoro di coach; – il numero totale di conversazioni effettuate con gli utenti di ciascuna azienda per cui lavora. La chiave primaria di ogni documento di questa collection è costituita dallo username dei coach. Le collections Call, Message, Rating, Average e Session sono state create durante la fase Sistema di rating. Le rimanenti collections, ovvero Company, User, Coach, sono state aggiunte in seguito, durante la fase Dashboard per le aziende per la necessità di memorizzare nuove tipologie di informazioni. 35 B Backend Il backend è stato realizzato utilizzando il framework Node.js, il quale permette lo sviluppo di applicazioni JavaScript lato server. In questa appendice si vuole descrivere la struttura del backend e le interazioni tra le sue componenti. Per le componenti più complesse viene riportato il diagramma delle classi, nel quale sono evidenziate in rosa le classi factory e in grigio i moduli esterni utilizzati. Viene riportato in Figura 18 il diagramma delle componenti in cui è stato suddiviso il backend. Figura 18: Diagramma delle componenti B.1 RequestManager La componente RequestManager si occupa della gestione delle comunicazioni del backend con i sistemi esterni ad esso, ovvero Parse e le due applicazioni iOS. Per la diversa natura dei due sistemi, questa componente è stata suddivisa ulteriormente in due sottocomponenti: • AppRequestManager: si occupa di gestire le richieste POST HTTP provenienti dalle due applicazioni mobile utilizzando il meccanismo di gestione delle route messo a disposizione dal framework Express.js. In particolare, si occupa di: 1. controllare che le informazioni ricevute siano nel formato corretto; 2. avviare la procedura per l’autenticazione; 3. nel caso in cui l’autenticazione sia andata a buon fine, inviare al controller corretto le informazioni ricevute. • ParseRequestManager: si occupa di gestire la comunicazione con Parse attraverso l’utilizzo delle API di quest’ultimo. In particolare, si occupa di: 1. effettuare l’autenticazione a Parse; 2. effettuare delle query al database di Parse; 3. salvare nuovi oggetti sul database di Parse; 4. aggiornare le informazioni di oggetti già esistenti. 36 Figura 19: Diagramma delle classi di DBManager B.2 DBManager La componente DBManager si occupa della gestione delle comunicazioni delle classi del backend con il database ed è stata progettata utilizzando il Design Pattern DAO (Data Access Object). Ogni classe di questa componente che deriva dalla classe astratta CollectionDAO, rappresenta una collection del database. Per ogni collection vengono definiti il modello dei dati e le operazioni di CRUD tramite l’utilizzo di Mongoose. Come si può vedere dal diagramma in Figura 19, ogni classe DAO contiene al suo interno la propria classe factory (classi in rosa). Al caricamento di ogni classe DAO, la rispettiva classe factory viene registrata in un hashmap all’interno di CollectionDAO. In questo modo vengono memorizzate in CollectionDAO tutte le dipendenze necessarie alla creazione di una qualsiasi classe DAO. Ciò consente di fornire all’esterno un’unica interfaccia tramite la quale interagire con la componente DBManager. B.3 Controller La componente Controller si occupa di racchiudere le principali funzionalità del backend e coordinare le attività delle altre componenti. Come si può vedere dal diagramma in Figura 20, ogni classe controller contiene al suo interno la propria classe factory (classi in rosa). Al caricamento di ogni classe controller, la rispettiva classe factory viene registrata nella classe astratta Controller. In questo modo vengono memorizzate in Controller tutte le dipendenze necessarie alla creazione di un qualsiasi controller. Viene riportata di seguito la descrizione delle funzionalità di ogni controller: • AuthenticationController: si occupa di gestire l’autenticazione al server. In particolare si occupa di: 1. generare una chiave casuale tramite l’utilizzo del modulo generate-key di Node.js; 2. salvare nel database una nuova Session contenente la chiave casuale generata e l’ID dell’utente che l’ha richiesta, tramite l’utilizzo delle funzionalità messe a disposizione da CollectionDAO; 37 Figura 20: Diagramma delle classi di Controller 3. recuperare dal database la chiave casuale associata ad un certo ID; 4. effettuare l’autenticazione al server, controllando che il token inviato dall’app sia corretto; 5. eliminare la Session creata in precedenza. • CallController: si occupa di gestire le operazioni legate alle chiamate effettuate dagli utenti. In particolare si occupa di: 1. controllare che l’utente che ha effettuato la chiamata e il coach siano effettivamente degli utenti registrati al servizio, tramite l’utilizzo dei metodi messi a disposizione da ParseRequestManager ; 2. salvare nel database le informazioni relative ad una nuova chiamata, tramite l’utilizzo delle funzionalità messe a disposizione da CollectionDAO; 3. aggiornare i dati delle collections correlate alla nuova chiamata, ovvero Company, User e Coach, richiamando i metodi dei rispettivi controller. • MessageController: si occupa di gestire le operazioni legate ai messaggi inviati e ricevuti da utenti e coach. In particolare si occupa di: 1. controllare che il mittente e il destinatario di un messaggio siano effettivamente degli utenti registrati al servizio, tramite l’utilizzo dei metodi messi a disposizione da ParseRequestManager ; 2. salvare nel database le informazioni relative ad un nuovo messaggio, tramite l’utilizzo delle funzionalità messe a disposizione da CollectionDAO; 3. calcolare il tempo di risposta nel caso in cui il mittente sia un coach; 4. aggiornare i dati delle collections correlate al nuovo messaggio, ovvero Company, User e Coach, richiamando i metodi dei rispettivi controller. • RatingController: si occupa di gestire le operazioni legate al rating. In particolare si occupa di: 1. controllare che l’utente che ha inviato il rating e il coach valutato siano effettivamente degli utenti registrati al servizio, tramite l’utilizzo dei metodi messi a disposizione da ParseRequestManager ; 38 2. controllare che la valutazione dell’utente sia nel range corretto, ovvero tra 1 e 5 compresi; 3. salvare nel database le informazioni relative alla nuova valutazione, tramite l’utilizzo delle funzionalità messe a disposizione da CollectionDAO; 4. calcolare il rating medio del coach valutato; 5. calcolare il tempo di risposta medio del coach valutato; 6. aggiornare le informazioni contenute nel documento della collection Average relativo al coach valutato, tramite l’utilizzo dei metodi messi a disposizione da CollectionDAO; 7. inviare le informazioni aggiornate a Parse, tramite l’utilizzo delle funzionalità messe a disposizione da ParseRequestManager. • AnalyticsController: si occupa di gestire le operazioni legate alle statistiche di utilizzzo da mostrare nell’app agli utenti. In particolare si occupa di: 1. creare la struttura dei grafici da mostrare all’utente, tramite l’utilizzo del framework Norris; 2. mantere aggiornate le informazioni presenti nei grafici. • CompanyController: si occupa di gestire le informazioni legate alle aziende che utilizzano il servizio. In particolare si occupa di: 1. salvare nel database le informazioni relative ad un’azienda; 2. aggiornare correttamente le informazioni relative ad un’azienda; 3. ottenere alcune informazioni di interesse inerenti un’azienda. Per fare tutto ciò si serve delle funzionalità messe a disposizione da CollectionDAO. • UserController: si occupa di gestire le informazioni legate agli utenti che utilizzano il servizio. In particolare si occupa di: 1. salvare nel database le informazioni relative ad un utente; 2. aggiornare correttamente le informazioni relative ad un utente; 3. ottenere alcune informazioni di interesse inerenti un utente, come per esempio l’azienda per cui lavora. Per fare tutto ciò si serve delle funzionalità messe a disposizione da CollectionDAO. • CoachController: si occupa di gestire le informazioni legate ai coach. In particolare si occupa di: 1. salvare nel database le informazioni relative ad un coach; 2. aggiornare correttamente le informazioni relative ad un coach; 3. ottenere alcune informazioni di interesse inerenti un coach, come per esempio le aziende per le quali è disponibile come coach. Per fare tutto ciò si serve delle funzionalità messe a disposizione da CollectionDAO. B.4 Dashboard La componente Dashboard racchiude al suo interno le classi necessarie alla creazione e gestione di una dashboard per le aziende. Data la complessità di questa componente, si è deciso di suddividerla in tre sottocomponenti utilizzando il Design Pattern MVP (Model View Presenter). Viene riportato in Figura 21 il diagramma delle sottocomponenti in cui è stata suddivisa la Dashboard. 39 Figura 21: Diagramma delle sottocomponenti della Dashboard Figura 22: Diagramma delle classi di Dashboard:Model 40 B.4.1 Dashboard:Model Questa sottocomponente contiene al suo interno le classi che costituiscono il modello dei dati di una dashboard. In particolare contiene le classi che rappresentano la struttura dei grafici presenti nella dashboard e la classe che rappresenta il modello della dashboard stessa. Le classi che rappresentano i grafici derivano dalla classe astratta Chart e utilizzano il framework Norris per creare grafici che possano essere aggiornati in tempo reale. Ognuna di queste classi contiene al suo interno la propria classe factory (classi in rosa in Figura 22). Al caricamento di ogni classe che rappresenta un grafico, la rispettiva classe factory viene registrata in Chart. In questo modo vengono memorizzate in Chart tutte le dipendenze necessarie alla creazione e all’aggiornamento di una qualsiasi tipologia di grafico. Ciò consente di fornire alla classe Dashboard un’unica interfaccia tramite la quale creare i grafici, diminuendo le dipendenze e aumentando la manutenibilità del codice. Inoltre, permette di estendere facilmente il modello dei dati nel caso in cui si vogliano aggiungere nuove tipologie di grafici. B.4.2 Dashboard:Presenter Figura 23: Diagramma delle classi di Dashboard:Presenter Questa sottocomponente contiene al suo interno la classe StandardDashboardPresenter che si occupa della creazione e gestione di una dashboard utilizzando un template standard. In particolare questa classe si occupa di: 1. creare un’istanza di una dashboard a partire dal modello dei dati; 2. mantenere aggiornati i grafici della dashboard creata, tramite l’utilizzo dell’apposito metodo della classe Chart; 3. gestire le richieste delle pagine web contenenti le varie dashboard, tramite la gestione delle route messa a disposizione dal framework Express.js; 4. effettuare il render del template tramite l’utilizzo del template engine EJS di Express.js. La classe StandardDashboardPresenter deriva dalla classe astratta Presenter e contiene al suo interno la propria classe factory (classe in rosa in Figura 23). Al caricamento della classe, la propria classe factory viene registrata in Presenter. Analogamente a quanto avviene per le altre componenti del backend, la memorizzazione delle dipendenze nella classe Presenter consente di avere un unico punto di accesso a questa componente e la rende più facilmente manutenibile ed estendibile. 41 B.4.3 Dashboard:View Questa sottocomponente contiene il template HTML della dashboard, il quale verrà popolato dal Presenter con i dati corretti. B.5 B.5.1 Descrizione delle interazioni tra le componenti Controller-DBManager Figura 24: Diagramma delle interazioni tra Controller e DBManager Ogni controller possiede un oggetto di tipo DBManager:collectionDAO, tramite il quale effettua le operazioni di CRUD sulla rispettiva collection del database. Grazie all’utilizzo della dependency injection, le dipendenze delle varie tipologie di DAO sono state iniettate all’interno della classe base. In questo modo, sebbene ogni controller sia in possesso di un’istanza di una classe derivata da DBManager:collectionDAO, l’unica dipendenza della componente Controller rispetto a DBManager è proprio la dipendenza verso la classe base DBManager:collectionDAO. B.5.2 Controller-RequestManager Figura 25: Diagramma delle interazioni tra Controller e RequestManager Come si può vedere dalla Figura 25, alcune tipologie di controller, ovvero Controller:CallController, Controller:MessageController e Controller:RatingController, possiedono un oggetto di tipo RequestManager:ParseRequestManager, tramite il quale effettuano operazioni di lettura/scrittura sul 42 database di Parse. La classe RequestManager:AppRequestManager utilizza le funzionalità della classe Controller:AuthenticationController per inviare ad un utente una chiave casuale e per effettuare l’autenticazione dell’utente stesso. Inoltre, ogni volta che riceve delle informazioni da parte di un utente autenticato, richiama il metodo che effettua il salvataggio delle informazioni sul database, utilizzando il controller adeguato. In quest’ultimo caso la sola dipendenza necessaria è quella verso la classe Controller, la quale contiene al suo interno tutte le dipendenze delle diverse tipologie di controller. B.5.3 Dashboard-Controller Figura 26: Diagramma delle interazioni tra Dashboard e Controller Ogni classe che rappresenta un grafico possiede un oggetto di tipo Controller, tramite il quale ottiene i dati di cui ha bisogno nel formato corretto. 43 44 Glossario AMCharts Libreria JavaScript che permette la creazione lato client di mappe e grafici. API Acronimo di "Application Programming Interface". Si tratta di procedure disponibili al programmatore, utili per l’implementazione di un certo compito all’interno di un programma. Bitbucket Servizio web di hosting per lo sviluppo di progetti software che usa i sistemi di controllo di versione Git e Mercurial. CocoaPods Gestore delle dipendenze per i progetti il cui codice è scritto in Swift e Objective-C. collection in MongoDB rappresenta un insieme correlato di oggetti, chiamati documenti. CRUD Acronimo di Create Read Update Delete, indica le quattro operazioni di creazione, lettura, modifica ed eliminazione disponibili per i dati salvati su un database. DAO Acronimo di Data Access Object, è un design pattern architetturale che ha la funzione di stratificare e isolare l’accesso ad un’entità del database tramite query. Questo design pattern prevede la creazione di una classe per ogni entità (tabella o collection) presente nel database. Ogni classe DAO mette a disposizione un’interfaccia per le operazioni di CRUD effettuabili sull’entità rappresentata. Design Pattern Soluzione progettuale generale ad un problema ricorrente. EJS Template engine di Express.js che permette di effettuare in modo semplice il render di una pagina web a partire da un template HTML. Git Sistema software di controllo di versione distribuito, utilizzabile da riga di comando. Google Analytics Servizio di analisi dei dati di Google che traccia il trafico di siti web e applicazioni mobile. JSdoc Linguaggio di markup utilizzato per produrre in modo semplice e veloce la documentazione di codice JavaScript. Viene utilizzato all’interno dei commenti nei file contenenti il codice e da essi prende le informazioni necessarie per generare automaticamente la documentazione in formato HTML. JSON Acronimo di JavaScript Object Notation, è un formato per lo scambio dei dati in applicazioni client-server basato sul linguaggio JavaScript. Mocha Framework per testare codice JavaScript su Node.js. Supporta i test asincroni e l’utilizzo di una qualsiasi libreria per le asserzioni. Mongoose Modulo di Node.js che si interfaccia con MongoDB, permettendo di accedere in modo facile e veloce alle operazioni di CRUD di MongoDB. Node.js Framework che permette l’utilizzo di JavaScript lato server su piattaforme UNIX like. Si basa sul motore JavaScript V8 e la sua caratterstica principale è il fatto di essere event-driven e non bloccante per operazioni di I/O. Objective-C Linguaggio di programmazione derivato dal C. È orientato agli oggetti e viene utilizzato per scrivere software per OS X e iOS. Slack Strumento di messaggistica istantanea multipiattaforma che permette raggruppare in un unico software tutte le comunicazioni del team. 45 Socket.io Libreria JavaScript per applicazioni web real-time. Utilizza il protocollo WebSocket per implementare una comunicazione bidirezionale orientata agli eventi. SSL Acronimo di Secure Sockets Layer, è un protocollo progettato per consentire alle applicazioni di trasmettere informazioni in modo sicuro e protetto. Le applicazioni che utilizzano i certificati SSL sono in grado di gestire l’invio e la ricezione di chiavi di protezione e di criptare/decriptare le informazioni trasmesse utilizzando le stesse chiavi. Swift Linguaggio di programmazione creato da Apple per facilitare lo sviluppo di app per iOS e Mac. È progettato per dare agli sviluppatori più esperti tutta la libertà e le funzioni necessarie a creare app di nuova generazione, ma è facile da imparare e intuitivo da usare anche ai principianti. Trello Strumento di supporto alla gestione dei task, che permette di organizzare le attività in varie board per mantenere traccia dello stato di avanzamento di ciascuna di esse. Xcode Ambiente di sviluppo integrato di Apple che permette di sviluppare software per iOS e OS X. 46