Platforma online pentru învățare [304346]
Platforma online pentru învățare
PROIECT DE DIPLOMĂ
Autor: Darius Ovidiu CUPȘA
Conducător științific: S.I.dr.ing. Mihai HULEA
Autor: Darius Ovidiu CUPȘA
Platforma online pentru învățare
Enunțul temei: Proiectul își propune implementarea unei aplicații web pentru accesarea de materiale didactice online.
Conținutul proiectului:
Pagina de prezentare
Declarație privind autenticitatea proiectului
Sinteza proiectului
Cuprins
1. Introducere
2. Obiective și specificația proiectului
3. Studiu bibliografic
4. Analiză și proiectare
5. Implementare
6. Testare și validare
7. Concluzii
Bibliografie
Acronime
În primul capitol se prezintă contextul proiectului cât și tema lucrării.
În capitolul doi se prezintă obiectivele proiectului și cele două tipuri de specificații: [anonimizat].
În capitolul trei se prezintă un scurt studiu bibliografic despre arhitecturile utilizate: REST, Three-Tier și Flux.
Capitolul patru prezintă partea de analiză și fundamentare teoretică.
În capitolul cinci sunt prezentate detalii legate de proiectarea și implementarea sistemului: [anonimizat], [anonimizat].
În capitolul șase se prezintă modalitățile de testare și validare a componentelor aplicației.
Capitolul șapte prezintă concluziile proiectului cât și sugestii pentru dezvoltări ulterioare.
Locul documentației: [anonimizat]: S.I.dr.ing. Mihai HULEA
Data emiterii temei:
Data predării:
Semnătura autorului
Semnătura conducătorului științific
Declarație pe proprie răspundere privind
autenticitatea proiectului de diplomă
Subsemnatul(a) [anonimizat](ă) cu CI/BI seria CJ nr. 201337 , CNP [anonimizat] ,
autorul lucrării:
Platforma online pentru învățare
elaborată în vederea susținerii examenului de finalizare a [anonimizat] ,
[anonimizat],
sesiunea a anului universitar 2016-2017,
[anonimizat], [anonimizat], și în bibliografie.
Declar, [anonimizat] a convențiilor internaționale privind drepturile de autor.
Declar, [anonimizat] a mai fost prezentată în fața unei alte comisii de examen de licență.
In cazul constatării ulterioare a [anonimizat], respectiv, anularea examenului de licență.
Data Prenume NUME
(semnătura)
SINTEZA
proiectului de diplomă cu titlul:
Platforma online pentru învățare
Autor: Darius Ovidiu CUPȘA
Conducător științific: S.I.dr.ing. Mihai HULEA
1. Cerințele temei:
Implementarea unei aplicații web pentru accesarea de materiale didactice online.
2. Soluții alese:
Sistemul este format din trei aplicații cu funcții specifice dezvoltate independent. [anonimizat], [anonimizat] a sistemului.
[anonimizat]irii sistemului fiind create câteva scripturi.
3. Rezultate obținute:
Printre principalele specificații realizate reamintim: managementul utilizatorilor, adăugarea și modificarea categoriilor de materiale cât și a lecțiilor apartenente acestora, posibilitatea creării de sesiuni de predare în cadrul clasei virtuale unde participanții au acces la câteva unelte de desen cât și un chat în timp real.
4. Testări și verificări:
Pentru testarea aplicațiilor server s-a folosit Postman, pentru testarea proxy-ului și a load-balancer-ului s-a utilizat Apache Benchmark, iar pentru testarea componentei web s-a folosit BrowserStack.
5. Contribuții personale:
Implementarea celor trei componente ale sistemului cât și proiectarea infrastructurii pe care rulează.
6. Surse de documentare:
Cursuri, internet.
Semnătura autorului
Semnătura conducătorului științific
Introducere
Contextul proiectului
Privind în jur nu putem să nu realizăm că trăim într-o lume din ce în ce mai tehnologizată. Activitățile în mediul online cresc exponențial de la o zi la alta, ridicând gradul de confort al consumatorului, iar împreună cu această creștere și percepția noastră cu privire la trecerea timpului se schimbă.
Astfel, privim cu o mai mare rigoare pierderea fără de folos a timpului în trafic și în alte conjuncturi alegând de cele mai multe ori să căutăm materiale informative în spațiul online. Cu această schimbare de percepție, în ultimul deceniu au apărut într-un ritm constant platforme noi cu materiale didactice facilitând dezvoltarea personală și profesională a consumatorului.
Printre avantajele acestei abordări asupra educației se numără:
Posibilitatea învățării continue
Alegerea ritmului de studiu
Oferta de materiale didactice este mult mai diversificată în comparație cu educația tradițională
Costuri mult mai reduse
Tema lucrării
Principalul obiectiv al acestui sistem este de a facilita accesul la materiale didactice, cât și la sesiuni de predare cu profesori acreditați într-un mediu virtual.
Pentru îndeplinirea acestui scop, sistemul pune la dispoziția utilizatorilor o aplicație web ce rulează în majoritatea browserelor moderne. În momentul în care un utilizator accesează aplicația, acestuia îi va fi prezentat un formular de autentificare. Pe baza informațiilor primite după autorizarea utilizatorului în aplicație acesta va avea acces la materiale didactice bine pregătite cât și la sesiuni de predare în timp real cu profesori acreditați.
Trăind într-o lume digitalizată, educația online prezintă una dintre opțiunile principale ale tinerilor și nu numai din întreaga lume, oameni care muncesc, care se pot implica în alte proiecte profesionale și personale, privilegiind astfel și educația în același timp.
Condiția necesară utilizării acestui sistem este deținerea unor dispozitive care să poată susține infrastructura necesară rulării componentelor principale, fiind indicat un server care să ruleze Linux și să fie conectat la internet. Fiecare utilizator va avea nevoie de un calculator cu acces la internet, un browser relativ modern și url-ul unde serverul este hostat.
Obiectivele și specificațiile proiectului
Obiectivele proiectului
Scopul acestei aplicații este acela de a facilita comunicarea dintre profesor și elevi cât și oferirea unei platforme pentru susținere a cursurilor în mediul online.
Principalele funcționalități implementate sunt următoarele:
Funcționalități generale
Logarea în aplicație folosind adresa de email și parola
Vizualizarea claselor în care aparții și a sesiunile aferente acestora
Accesarea clasei virtuale
Listă cu participanții care au accesat aceeași clasă virtuală
Chat în timp real cu participanții din sesiunea curentă
Vizualizarea unei lecții în cadrul clasei virtuale
Utilizarea diferitelor unelte de desen (creion, dreptunghi, linie, marker, radieră)
Funcționalități specifice profesorilor
Adăugare de noi studenți și asignarea acestora în clase virtuale
Adăugarea și modificarea claselor virtuale
Adăugarea și modificarea sesiunilor aferente
Adăugarea de categorii de materiale
Adăugarea de materiale in diferite categorii
Funcționalități specifice administratorilor
Adăugare de noi profesori
Specificațiile proiectului
Specificații funcționale
Logarea în aplicație folosind adresa de email și parola
Mecanismul de logare se va realiza în felul următor: când utilizatorul va accesa platforma, acestuia i se va prezenta un formular de logare cu email și parolă. După completarea acestor informații, ele vor fi transmise serverului care le va verifica și va genera un token (JSON Web Token) valid pe baza datelor de autentificare primite, token ce va fi utilizat mai apoi de platformă pentru toate request-urile ce vor urma.
Vizualizarea claselor în care aparții și a sesiunilor aferente acestora
După autentificare, utilizatorul (fie el elev, profesor sau administrator) va fi redirecționat către un panou de control unde va putea vedea trei tabele:
Clase virtuale din care faci parte (la care predai)
Sesiuni precedente
Sesiuni viitoare
Accesarea clasei virtuale
Din panoul de control, utilizatorul va putea accesa clasa virtuală, pentru sesiunile precedente și pentru cele viitoare doar dacă data de început a sesiunii este mai mică sau egală cu data curentă, printr-un simplu click pe linkul aferent sesiunii.
Lista cu participanții care au accesat aceeași clasă virtuală
Când o sesiune este deschisă în clasa virtuală, aceasta se conectează la un server de tip socket (timp real), trimite token-ul primit la autentificare si id-ul sesiunii creând astfel un canal de comunicare in timp real între toți participanții cu același id de sesiune. La conectare, fiecare participant trimite un eveniment de tip “participant-joined”, eveniment ce va fi distribuit către restul instanțelor ce ascultă pe acest canal, astfel fiecare primește lista actualizată a participanților la sesiune.
Chat în timp real cu participanții din aceeași clasă virtuală
Utilizând același canal ca și mai sus, pentru chat instant, după scrierea unui mesaj in căsuța de chat, acesta va fi transmis printr-un eveniment de tip ”chat-message” care va fi distribuit celorlalți participanți.
Vizualizarea unei lecții în cadrul clasei virtuale
În interiorul clasei virtuale pot fi prezentate lecții având posibilitatea de a naviga printre paginile acesteia.
Utilizarea diferitelor unelte de desen (creion, dreptunghi, linie, marker, radieră)
Asupra materialelor afișate în interiorul sesiunii se pot face modificări cu ajutorul uneltelor de desen, utilizatorul poate astfel desena liber cu creionul, adăuga dreptunghiuri, linii și chiar poate folosi markerul pentru evidențierea unor elemente din pagină.
Adăugarea de studenți noi și asignarea acestora în clase virtuale
Profesorul, din panoul de administrare, poate crea conturi noi de studenți, poate actualiza și modifica informațiile acestora cât și să îi adauge in clase virtuale deja existente.
Adăugarea și modificarea claselor virtuale
Ca și profesor, acesta poate crea clase noi, poate modifica și șterge clase existente, poate adăuga studenți si profesori.
Adăugarea și modificarea sesiunilor aferente
In panoul de administrare, profesorul poate adăuga, șterge și programa sesiuni în clasa virtuală, poate modifica datele la care o sesiune va fi disponibilă.
Adăugarea și modificarea categoriilor de materiale
În secțiunea ”categorii” din panoul de administrare, profesorul poate adăuga, modifica și șterge categoriile în care vor fi grupate materialele disponibile atât profesorilor cât și studenților în cadrul clasei virtuale.
Adăugarea de materiale in diferite categorii
După adăugarea unei categorii, în aceasta se pot crea, modifica și șterge diferite lecții.
Adăugare de profesori noi
Ca și administrator, pe lângă toate funcționalitățile descrise mai sus, acesta poate crea, modifica și șterge conturile profesorilor, cât și crea alte conturi pentru administratori.
Specificații non-funcționale
Interfața prietenoasă
Dat fiind faptul că aplicația va fi folosită in special de persoane în folosul dezvoltării personale, platforma trebuie să fie ușor de utilizat, oferind astfel o experiență cât mai plăcută.
Utilizabilitate
Datorită interfeței prietenoase, platforma oferă o interfață grafică intuitivă, astfel încât utilizarea acesteia poate deveni o plăcere pentru utilizatorii acesteia, realizând într-un mod mai plăcut interacțiunea dintre utilizatori.
Securitatea
Securitatea este un aspect foarte important al sistemului, platforma permițând doar utilizatorilor autentificați să acceseze materialele existente, permite doar profesorilor să creeze materiale și conturi pentru studenți, conturi ce pot fi folosite doar pentru consumarea de materiale nu și ștergerea acestora și permite doar administratorilor să creeze conturi pentru profesori. Fiecare request făcut către api și socket server este însoțit de un token unic care se generează la autentificarea utilizatorului în platformă.
Performanța
Când vorbim de performanțele sistemului, vorbim despre timpul de răspuns al acestuia, executarea interogărilor și afișarea rezultatelor. Acesta trebuie să fie optim indiferent de numărul utilizatorilor care accesează concomitent platformă, indiferent de complexitatea interogărilor si a executării acestora pe o bază de date ce va crește în timp. Executarea interogărilor trebuie să fi realizate într-un timp optim pentru ca activitatea utilizatorului să nu fie întreruptă de blocarea sistemului sau de așteptarea după informații din partea acestuia.
Scalabilitatea
Prin scalabilitatea sistemului ne referim la abilitatea acestuia de a suporta un volum de încărcare sau de a permite extinderea sa. Vorbim de un sistem de stocare și prelucrare a datelor scalabil dacă se comportă similar chiar dacă volumul de date pe care îl prelucrează continuă să crească. Acesta fiind unul dintre motivele pentru folosirea unei baze de date NoSQL, fapt ce permite scalarea acesteia atât pe orizontală ( pe mai multe servere ) precum și abilitatea acesteia de a replica și distribui datele pe mai multe servere. Din dorința de scalabilitate a platformei s-a folosit și o infrastructură bazată pe containere Docker, având astfel posibilitatea de a porni mai multe instanțe din fiecare serviciu, traficul fiind balansat între ele folosind un load balancer.
Robustețe
Platforma trebuie să nu fie vulnerabilă la erori produse de introducerea de date invalide de către utilizatorii acesteia, aceasta trebuie să se comporte rezonabil, returnând un mesaj în care să informeze utilizatorul asupra datelor introduse greșit.
Studiu bibliografic
Arhitectura REST
Serviciul REST (Representantional State Transfer) reprezintă un stil arhitectural pentru sisteme hypermedia distribuite cum ar fi aplicațiile web. În cadrul acestora, nu se pune accent pe implementarea acestora cât pe rolul fiecărei componente și pe un set de interacțiunile dintre acestea.
Scopul acestei arhitecturi este de a crește performanța, scalabilitatea, simplicitatea, portabilitatea respectiv vizibilitatea sistemelor distribuite, conform [1]. Astfel, într-un context mai larg, serviciul descrie o interfață care transmite și consumă date prin HTTP, evitând utilizarea sesiunilor prin folosirea cookie-urilor HTTP.
În cadrul acestuia, transmiterea datelor nu este restrânsă doar la HTTP. Se pot astfel dezvolta aplicații software care să respecte arhitectura REST dar fără utilizarea protocolului HTTP. Printre principalele exemple de implementare putem enumera transmiterea datelor utilizând fișiere XML sau prin reprezentarea acestora in format JSON (JavaScript Object Notation).
Arhitectura REST (Representational State Transfer) a fost introdusă și definită de către Roy Fielding în teza acestuia de doctorat când studia la Universitatea Irvine California. Acesta introduce conceptul că în REST totul este o resursă, astfel orice poate fi stocat poate fi considerat o resursă. Posibile resurse ar fi:
o listă de utilizatori
statistici asupra unui produs
un nou material încărcat în platformă
Astfel, în cele mai multe cazuri, metodele folosite pentru implementarea serviciilor REST sunt așa numitele HTTP verbs:
GET – citirea unei resurse fără modificarea acesteia. Executarea repetată a acestei metode va returna același set de date, având același efect ca și o singură execuție.
POST – utilizată pentru crearea unei noi resurse. (adesea folosită și la modificarea unei resurse existente datorită unor limitări in implementarea HTTP verbs care nu permit de exemplu încărcarea de fișiere prin metoda PUT). Execuția acestei metode va avea efecte distincte.
PUT – modificarea unei resurse existente, astfel execuția repetată a acesteia va avea același efect ca și execuția singulară.
DELETE – folosită în ștergerea unei resurse existente. Execuția repetată a acesteia va avea același efect ca și execuția singulară a acesteia.
Caracteristici ale arhitecturii REST:
este o arhitectură client-server bazată pe resurse
este un stil arhitectural bazat pe standardele Web
adresa resurselor unei aplicații ce implementează servicii REST sunt adesea de forma http://{server}:{port}/{resursa}/{id} de exemplu un request la endpointul http://localhost:80/user/1 ar returna resursa de tip user cu id-ul 1
tratarea erorilor se realizează conform standardului HTTP
arhitectura REST nu este limitată în reprezentarea datelor, acestea putând fi reprezentate în diferite forme precum XML, JSON, TEXT, JPEG, OCTET- STREAM cât timp acestea respectă standardele protocolului în care sunt implementate.
Utilizând metode de caching, clienții pot crește performanța și scalabilitatea aplicației.
Arhitectura Three-Tier
Arhitectura Three-Tier, dezvoltată de către J. Donovan, reprezintă o arhitectură tip client – server în care interfața cu utilizatorul (layer-ul de prezentare), logica funcțională (layer-ul de business) și layer-ul de date sunt dezvoltate și menținute ca și module independente, adesea fiind separate pe diferite platforme.
Datorită separării între module, cu interfețe bine definite, arhitectura 3-tier intenționează să permită dezvoltatorului posibilitatea de a actualiza oricare dintre nivele fără a avea implicații asupra celorlalte. De exemplu, dacă se dorește schimbarea modalității de stocare a datelor, de la o bază de date NoSql la o bază de date relațională, singurul modul care va fi modificat va fi cel de stocare a datelor.
Arhitectura Three-Tier prezintă 3 mari module:
Nivelul de prezentare
Nivelul logic
Nivelul de stocare a datelor
Nivelul de prezentare
Reprezintă nivelul superior al aplicației, prezentând informații legate de anumite servicii cum ar fi căutarea și achiziționarea de produse, gestionarea resurselor . Acest nivel transmite informații și anumite resurse spre client respectiv comunică cu celelalte nivele din interiorul aplicației. Datorită separării și ierarhiei dintre nivele, nivelul de prezentare va comunica exclusiv cu nivelul logic.
Nivelul logic
Reprezintă legătura dintre nivelul superior al aplicației și nivelul de stocare a datelor. Fiind nivelul de mijloc, doar acesta are o conexiune directă cu nivelul de stocare, astfel pentru utilizator acesta reprezintă o abstractizare a bazei de date . La acest nivel se execută operații asupra datelor înainte de a fi transmise către stocare. Exemple de operații pot fi: validarea informațiilor primite de la client, procesarea fișierelor încărcate, eliminarea informațiilor confidențiale din resursele cerute de client.
Nivelul de stocare a datelor
Conține atât mecanismele de stocare a datelor ( servere de baze de date ) cât și cele de căutare și retragere a acestora . Nivelul de stocare trebuie să expună un API accesibil nivelului logic care să permită accesul la baza de date cât și executarea unor operații pe baza de date, dar fără să creeze dependințe în mecanismul de stocare. Astfel o modificare a arhitecturii bazei de date nu va afecta nivelul logic.
În figura următoare pot fi vizualizate cele 3 nivele, respectiv modalitatea de comunicare dintre acestea:
Arhitectura Flux (Unidirectional Data Flow)
Arhitectura Flux a fost dezvoltată de către Facebook pentru implementarea de aplicații web pe partea de client (client-side). Aceasta complementează framework-ul (React), framework bazat pe componente prin utilizarea unui flux de date unidirecțional, astfel, când un utilizator interacționează cu o componentă React, aceasta propagă printr-un dispatcher central informații către diferitele data store-uri care, după prelucrarea și stocarea acestora le trimit mai apoi copiilor lor.
Arhitectura flux are 3 mari componente:
Dispatcher-ul
Data store-uri
View-uri (de cele mai multe ori fiind reprezentate de componente React)
Fluxul de date
Informațiile într-o aplicație ce implementează arhitectura flux se propagă într-o singură direcție:
Un flux de date unidirecțional este central arhitecturii flux, iar diagrama de mai sus ar trebui să reprezinte principalul model mental asupra arhitecturii în mintea unui programator ce o implementează. Dispatcherul, store-urile și view-urile sunt noduri independente cu interfețe de intrare și ieșire bine definite. Acțiunile sunt obiecte simple ce conțin noile informații și o proprietate tip ce le identifică.
View-urile pot cauza o nouă acțiune în sistem în urma interacțiunii utilizatorilor cu acestea:
Acțiunile, care de cele mai multe ori își au originea în interacțiunea utilizatorilor cu aplicația, sunt trimise către dispatcher. Acesta mai apoi invocă callback-urile pe care store-urile le înregistrează în dispatcher la inițializare, trimițând astfel acțiunea către toate store-urile. După ce store-urile își modifică starea internă în raport cu acțiunea primită, vor emite un event de tip change care va altera controllerele view-urilor că există o modificare în layer-ul de date. Acestea mai apoi vor prelua noul set de date actualizându-și astfel starea, fapt care va forța o re-randare a view-urilor.
Starea aplicației este menținută doar în store-uri fapt care permite independența și decuplarea diferitelor componente ale aplicației. În cazurile în care apar dependințe intre store-uri, acestea sunt păstrate într-o ierarhie strictă, dispatcher-ul ocupându-se de actualizarea sincronă a acestora.
Structură
Dispatcher
Dispatcherul este punctul central care controlează fluxul de date în aplicație. În fundal acesta se comportă ca un registru de callback-uri pe care store-urile le înregistrează neavând o inteligență reală, fiind doar un mecanism simplu de a propaga action-urile în store-uri.
Pe măsură ce aplicația crește, dispatcher-ul devine din ce în ce mai vital, deoarece poate controla dependințele dintre store-uri prin invocarea callback-urilor aferente într-o anumită ordine. Astfel store-urile pot aștepta unul după altul să își termine de actualizat starea și mai apoi să se actualizeze ele însăși.
Data Store
Data store-urile conțin starea și logica aplicației. Rolul acestora este puțin similar cu cel al model-urilor în arhitectura MVC (Model-View-Controller) însă acestea păstrează starea mai multor obiecte de diferite tipuri, nu reprezintă doar un singur obiect cum o fac modelele ORM sau o colecție de obiecte de un singur tip cum o fac colecțiile din Backbone. Astfel data store-urile controlează starea unui domeniu din aplicație.
Cum am menționat mai sus, store-urile își înregistrează un callback în dispatcher. Acest callback primește acțiunea din dispatcher ca și parametru. În cadrul acestui callback există o instrucțiune de tip switch pe tipul acțiunii, aceasta fiind folosită pentru interpretarea și procesarea acesteia. Astfel o acțiune produce o actualizare a state-ului interior.
View
Sunt componente organizate într-o ierarhie care primesc starea store-ului și se actualizează pe baza acesteia. Pe nivelele de sus ale ierarhiei avem așa numitele controller-views, acestea sunt componente smart care, când primesc un event de tip update, iau noul state al store-ului, își setează propriul state și se rerandează, fapt care forțează toate componentele pe nivelele inferioare ale ierarhiei să se actualizeze.
Action
Action-urile sunt event-uri ce conțin seturi de date care vor afecta starea următoare a aplicației.
Analiză și fundamentare teoretică
Docker
Arhitectura Docker
Potrivit Docker este o platformă folosită pentru dezvoltarea, livrarea și rularea aplicațiilor. Scopul acestei platforme este de a îmbunătății portabilitatea și viteza de lansare a aplicațiilor scurtând durata procesului dintre scrierea codului și rularea acestuia în producție. În plus Docker aduce o separare a aplicației și a infrastructurii pe care rulează.
Docker funcționează pe un sistem bazat pe containere. Ca deosebire față de mașinile virtuale, containerele vor fi independente de infrastructura și sistemul de operare pe care rulează.
Figura 4.1 Arhitectura Docker
Docker folosește o arhitectură tip client-server. Clientul docker comunică în mod direct cu Docker daemon care efectiv rulează operațiile de build, rulare și livrare a containerelor. Docker client si docker daemon pot să ruleze pe același sistem sau se pot fi distribuite pe sisteme diferite utilizând o conexiune TCP. Comunicarea dintre client si server se realizează prin sockets sau prin intermediul unui API pus la dispoziție.
Docker images
Imaginile docker sunt fișiere de sistem predefinite ce vor fi utilizate de către Docker. De exemplu, o imagine docker poate conține un sistem de operare cu o bază de date relațională, sau un server web. Aceste imagini se construiesc aplicând modificări asupra unei imagini de bază.
Exemplu de imagini existente: “ubuntu:16.04”, “node:7.5-slim”, “mysql: latest”.
Conform , o imagine este formată din mai multe layere. Astfel fiecare instrucțiune RUN dintr-un fișier Dockerfile creează un nou layer peste cele existente ale imaginii. Imaginile, de cele mai multe ori tind să fie cât mai minimaliste, oferind doar ceea ce este strict necesar rulării unui singur proces. Toate layerele inferioare sunt read-only, doar layer-ul superior fiind writable.
Exemplu de fișier dockerfile:
FROM node:7.5-slim
MAINTAINER Darius Cupsa <cupsadarius@gmail.com>
RUN apt-get update
RUN apt-get upgrade
RUN npm install –g generaptr
ENTRYPOINT /bin/node
Pentru crearea unei imagini se folosește comanda ”build”. Exemplu ”docker build –d imagine-noua:tag .”. Această comandă creează o imagine nouă cu numele ”imagine-noua” cu tag-ul ”tag” bazată pe imaginea ”node:7.5-slim” și executând comenzile de update / upgrade. Dacă la rularea imaginii nu se folosește nici un parametru. Se va executa comanda de la ENTRYPOINT.
Docker containers
Docker container este o instanță a unei imagini Docker. Pentru a rula un container se utilizează comanda ”run”. Ca exemplu vom starta un container pornind de la imaginea creată anterior. Exemplu: ”docker run –d –name container-nou imagine-noua:tag”.
Un container trebuie să ruleze o singură aplicație sau un singur proces, containerul rămânând activ până la finalizarea execuției. Odată cu terminarea procesului, containerul se va opri automat.
Să presupunem că avem o aplicație scrisă în node js care este conectată la o bază de date mongo. Pentru rularea acesteia vom avea nevoie de două containere: un container de mongo care să ruleze serverul mongo al bazei de date, respectiv un container care să ruleze aplicația node. Pentru conectarea celor două containere, la rularea containerului node se va folosi comanda ”– link”. Exemplu: ”docker run –d –p 80:80 –name node –link=mongo:mongo node:7.5”.
Datorită separării față de infrastructura pe care rulează, fiecare container docker poate rula propria distribuție Linux. În cazul de mai sus prezentat imaginea de mongo poate să conțină un sistem de operare Ubuntu 16.04 pe care rulează instanța de mongo iar imaginea de nodejs poate conține un sistem de operare Ubuntu 17.10 pe care să ruleze serverul de node.
NodeJs
Conform , Node.js este o platformă construită pe motorul V8 al Chrome și se bazează pe un model event-driven și non-blocking I/O, folosind callback-uri utilizat în construcția de aplicații scalabile.
În exemplul următor mai multe conexiuni pot fi rezolvate concomitent, astfel când un request este primit calback-ul este apelat, dar dacă nu există nici un request în stack serverul va intra în sleep.
Figura 4.3 Exemplu node.js Hello World
Exemple de utilizări ale Node.js:
API-uri lightweight REST / JSON
Aplicații în timp real – aplicații web, rețele de socializare și instant messaging, software de chat, dashboard-uri pentru monitorizare în timp real
Aplicații single-page
Aplicații event-driven
Aplicații care trebuie să proceseze mii de conexiuni
Dispozitive IoT – tehnologie ”wearable”, dispozitive embeded și robotică
Avantaje ale folosirii Node.Js:
scalabil, datorită arhitecturii asincrone
rapid, atât din punct de vedere al executării cât și a timpului de dezvoltare
cod scris într-un singur limbaj, poate fi rulat pe mai multe platforme
oferă posibilitatea de a proiecta pe partea de client cât și pe cea de server într-un fel care nu necesită oscilarea între multiple tehnologii
foarte mare plaja de extensii și module open source
datorită operării pe un singur thread, abordării event-driven și a modelului non-blocking I/O, Node.Js practic acceptă în permanență requesturi.
Figura 4.4 Comparație număr requesturi procesate
Figura 4.5 Cerințe HTTP + CPU
Baze de date NoSQL
În ultimii 20 de ani, bazele de date relaționale sunt una din modalitățile de stocare preferate ale arhitecților în proiectarea aplicațiilor. Deși, în ultima perioadă bazele de date NoSQL au început să câștige din ce în ce mai mult teren. Aceste baze de date au apărut din necesitatea unor companii mari precum Amazon, Google sau Facebook de a manipula și organiza cantități uriașe de date, date cărora bazele de date relaționale nu le-ar putea face față. De aceea, bazele de date NoSQL au fost proiectate pentru stocarea unor volume uriașe de informații, în general distribuite pe mai multe servere.
Stocarea informațiilor în baze de date NoSQL poate lua mai multe forme precum: colecții cheie-valoare, implementări BigTable, colecții de documente și baze de date orientate pe grafuri.
Bazele de date NoSQL prezintă câteva caracteristici unice:
abilitatea de a scala orizontal pe mai multe servere
abilitatea de a replica și distribuii pe mai multe servere
abilitatea de a adăuga dinamic noi atribute la înregistrările existente
utilizare eficientă a indexării distribuite și a memoriei RAM pentru o stocare eficientă
O altă caracteristică importantă a sistemelor NoSQL este arhitectura ”share nothing”. În această arhitectură, fiecare nod este independent, niciunul nu partajează spațiu sau memorie. Datorită acestei arhitecturi bazele de date NoSQL pot efectua un număr foarte mare de operații de scriere și citire. O simplă operație asupra bazei de date se numește OLTP (online transaction processing).
Chiar dacă bazele de date NoSQL vin cu avantajele prezentate mai sus, au și dezavantaje. Una dintre cele mai importate fiind faptul că baza de date este formată dintr-un număr foarte mare de relații (colecții), iar modificare acestei scheme poate duce la modificarea aplicației ce depinde de aceasta. Totodată, dimensiunea colecțiilor poate crește foarte mult. Un alt dezavantaj al acestora este lipsa de maturitate, bazele de date fiind la primele versiuni sau chiar in faze incipiente.
RethinkDB
RethinkDB este prima bază de date JSON, scalabilă, open-source proiectată în special pentru aplicații web în timp real. Se diferențiază față de bazele de date NoSQL tradiționale prin modul în care datele pot fi accesate, astfel developer-ul nu trebuie să ceară constant noi seturi de date, poate doar să ceară bazei de date să trimită în continuu noi seturi de date pentru aplicații în timp real.
Baza de date RethinkDB este extrem de utilă când aplicația dezvoltată are nevoie de un flux constant de date. Tipurile convenționale de interogare funcționează bine în aplicațiile web deoarece se mapează direct pe modelul HTTP request-response. Totuși aplicațiile moderne necesită ca datele să fie trimise direct în timp real către client.
Tipuri de aplicații în care se pretează utilizarea RethinkDB:
aplicații web și mobile colaborative
aplicații pentru streaming
jocuri multiplayer
marketplace în timp real
Principalele tipuri de date suportate pentru câmpurile unui document sunt:
tipuri scalare: integer, double, float, boolean
tipuri șir de caractere: string, expresii regulate, cod
obiecte similare cu JSON
Datorită acestei flexibilități, developerul poate să modifice rapid structura obiectelor salvate în baza de date. Acest lucru este foarte util într-o aplicație în care apar constant modificarea cerințelor existente.
Exemplu de document salvat într-o bază de date RethinkDB:
{
“nume”: “Cupsa”,
“prenume”: “Darius”,
“email”: [
“cupsadarius@gmail.com”,
],
“adresa”: {
“strada”: “Bucegi”,
“numar”: “2A”,
“localitate”: “Cluj-Napoca”,
“cod”: 400667,
}
}
TypeScript
TypeScript este un superset peste ECMAScript 2015 (ES2015). Fiecare program scris in JavaScript este și un program TypeScript valid. Compilatorul pentru TypeScript face doar operații asupra fișierelor locale acestea fiind convertite în JavaScript și mai apoi rulate.
Sintaxa utilizată de TypeScript include toate funcționalitățile din ECMAScript 2015 incluzând clasele și modulele, iar pe lângă acestea oferă posibilitatea de a transpila aceste funcționalități în cod valid pentru ECMAScript 3 și 5.
Utilizând TypeScript oferă developerilor posibilitatea de a scrie cod într-un mod orientat pe obiecte, făcând posibilă utilizarea paradigmelor ce devin posibile o dată cu aceasta.
Conform , pe lângă toate avantajele prezentate mai sus, TypeScript oferă și posibilitatea de a scrie cod într-un mod strongly-typed punând la dispoziția programatorilor un set de adnotări asemănătoare cu comentariile JSDoc găsite in sistemele Clojure însă în TypeScript acestea sunt integrate direct în sintaxă, făcând codul mult mai ușor de citit și înțeles, reducând astfel necesitatea de mentenanță.
Figura 4.6 Exemplu TypeScript
Express.js
Express.js sau simplu Express este un framework pentru aplicații web ce rulează pe Node.js publicat ca și software open source sub licența MIT. A fost proiectat pentru dezvoltarea de aplicații web și API-uri, devenind în scurt timp de la lansare cel mai răspândit framework în ecosistemul Node.js.
Autorul original, TJ Holowaychuk, descrie Express ca și un server minimal cu multe facilități și un ecosistem bogat de module și pluginuri.
Express face parte din suita MEAN împreună cu MongoDB ca și bază de date, Express ca și backend server și AngularJs ca și framework pe frontend.
Socket.io
Socket.io este o librărie JavaScript pentru aplicații în timp real. Aceasta pune la dispoziție un canal de comunicare bidirecțional între clienți web și server. Librăria pune la dispoziție două părți, una pentru client ce rulează în browser și una pentru server ce rulează pe NodeJs. Amândouă pun la dispoziție un API foarte similar și funcționează ca și Node.js pe un sistem bazat pe eventuri.
Socket.io folosește în principiu WebSockets ca și protocol de comunicare. Deși de multe ori este folosită doar ca și un wrapper peste WebSockets, socket.io permite cu mult mai mult, cum ar fi posibilitatea de a emite către mai multe socketuri o data, stocare de date asociate cu fiecare client, operații I/O asincrone, etc.
ReactJs
React este o librărie JavaScript open source utilizată în crearea de interfețe pentru utilizatori. Este menținută de Facebook, Instagram și o mare comunitate de dezvoltatori. După ultimele statistici librăria este folosită de către site-uri precum: Netflix, Imgur, Feedly, Airbnb și alții.
Facilități
Flux de date unidirecțional
Seturi de date sunt trimise către componente pe baza cărora acestea randează content HTML. Totuși o componentă nu poate să modifice direct proprietățile primite, emite un action care va avea ca și consecință modificarea state-ului.
Virtual DOM
React creează un cache în memorie pe care execută toate operațiile, calculează diferențele și apoi actualizează DOM-ul browserului . Fapt ce permite programatorului să scrie cod ca și cum întreaga pagină ar fi randată o dată, React ocupându-se de actualizarea fiecărei componente când există o schimbare.
JSX
Componentele React sunt de cele mai multe ori scrise în JSX, acesta fiind o extensie a sintaxei JavaScript ce permite utilizarea de cod HTML ca și string-uri.
Proiectare și implementare
Detalii de proiectare
Cazuri de utilizare
În această secțiune vor fi prezentate principalele funcționalități ale aplicației sub forma unor cazuri de utilizare.
Considerăm un caz de utilizare, o colecție de scenarii de succes și eșec care descriu setul de acțiuni realizate de sistem pentru obținerea unui rezultat de către actor. Actorul este o entitate cu un comportament specific, spre exemplu o persoană, un alt sistem, etc. În sistemul proiectat se pot identifica trei actori principali:
Student: orice utilizator al aplicației are și rolul de student. După logarea în sistem, acesta poate realiza o multitudine de activități precum vizualizarea claselor virtuale din care face parte, vizualizarea și accesarea sesiunilor precedente cât și vizualizarea sesiunilor viitoare.
Profesor: adiacent acțiunilor posibile studenților, profesorii pot face cu mult mai mult, cum ar fi adăugarea și modificarea conturilor studenților, a claselor virtuale, a categoriilor de materiale și a materialelor cât și crearea de sesiuni virtuale și modificarea acestora.
Administrator: pe lângă acțiunile moștenite de la tipurile de actori prezentați antecedent, administratorul are abilitatea de a crea, modifica și șterge conturi de tip profesor.
Diagramă cazuri de utilizare student
Cazul principal de utilizare constă în accesarea clasei virtuale de către actor, în contextul unei sesiuni.
Posibile cazuri de utilizare pentru un utilizator tip student:
Login în aplicație
Vizualizarea claselor virtuale din care face parte
Vizualizarea sesiunilor precedente
Vizualizarea sesiunilor viitoare
Accesarea unei sesiuni în clasa virtuală
Figura 5.1 Diagramă cazuri utilizare pentru un student
În continuare vom prezenta unul dintre aceste cazuri de utilizare:
Nume caz de utilizare: Accesarea unei sesiuni în clasa virtuală
Actorul principal: Utilizatorul tip student
Scurtă descriere: De fiecare dată când un student dorește să acceseze o sesiune în cadrul clasei virtuale, aplicația va prelua id-ul sesiunii, va cere informațiile necesare accesării materialului de la api, va autentifica utilizatorul într-un socket room-ul asignat sesiunii fapt ce va permite comunicarea în timp real între participanții aceleiași sesiuni.
Succesiunea evenimentelor:
START caz de utilizare
Studentul accesează linkul aferent sesiunii pe care dorește să o deschidă
Se efectuează un HTTP request către API cu id-ul sesiunii
După primirea răspunsului ce conține informații despre participanții la sesiune cât și materialul aferent acesteia, aplicația va autentifica utilizatorul către serverul socket
După autentificarea cu succes, un event tip ParticipantJoin va fi emis către ceilalți participanți în sesiune
FINALIZARE caz de utilizare
Momentul în care utilizatorul student este anunțat despre succesul sau eșecul acțiunii sale, cazul de utilizare ia sfârșit.
Cerințe speciale:
Sistemul nu trebuie să permită accesul persoanelor neautentificate, asigurând astfel integritatea și securitatea datelor utilizatorilor deja existenți.
Precondiții:
Linkul aferent sesiunii trebuie să conțină id-ul sesiunii cât și id-ul materialului ce urmează a fi afișat, iar acesta trebuie să fie accesat de către un utilizator tip student.
Postcondiții:
API-ul returnează un răspuns ce conține informații cu privire la participanții aferenți sesiunii cât și date referitoare la lecția ce va fi susținută.
Serverul de socket trebuie să accepte conexiunea utilizatorului cât și să distribuie eventurile primite de la acesta.
Dacă a existat un schimb de informații, acestea sunt stocate și trebuie să rămână persistente.
Prioritate: Este obligatoriu ca sistemul să execute acești pași când linkul către sesiune este accesat.
Disponibilitate: disponibil tot timpul.
Frecvența de utilizare: este variabilă, aceasta depinde de numărul de utilizatori activi în aplicație cât și de numărul de sesiuni programate în momentul accesării.
Diagramă cazuri de utilizare profesor
Cazul principal de utilizare constă în efectuarea următoarelor activități de către actor, în cazul de față actorul estre un utilizator tip profesor. Un profesor este orice utilizator care are rolul de profesor în sistem.
Posibile cazuri de utilizare ale unui utilizator tip profesor, pe lângă cele moștenite de la utilizatorii tip studenți:
Adăugare conturi studenți
Modificare conturi studenți
Ștergere conturi studenți
Adăugare clase virtuale
Modificare clase virtuale
Ștergere clase virtuale
Adăugare sesiuni
Modificare sesiuni
Ștergere sesiuni
Adăugare categorii materiale
Modificare categorii materiale
Ștergere categorii materiale
Adăugare lecții
Modificare lecții
Ștergere lecții
Figura 5.2 Diagramă cazuri utilizare profesor
În continuare vom prezenta în detaliu unul dintre aceste cazuri de utilizare.
Nume caz de utilizare: Adăugare lecție
Actorul principal: Utilizatorul profesor
Scurtă descriere: După autentificare, un profesor are opțiunea de a adăuga un nou material didactic, pe lângă alte opțiuni disponibile.
Succesiunea evenimentelor:
START caz de utilizare
Utilizatorul accesează aplicația și se autentifică în aceasta
După logare, acesta va fi redirecționat către pagina de administrare a platformei unde acesta are opțiunea de a adăuga un nou material didactic
Utilizatorul inserează titlul lecției
Utilizatorul inserează descrierea acesteia
Utilizatorul alege din dropdown categoria din care materialul face parte
Utilizatorul adaugă fiecare pagină din material ca imagine ce urmează a fi încărcată
Utilizatorul apasă butonul ”SAVE”
Lecția apare în tabelul adiacent formularului de inserare
FINALIZARE caz de utilizare
Cazul de utilizare a luat sfârșit atunci când noua lecție adăugată apare în tabelul cu lecții existente în sistem.
Excepții:
Utilizatorul nu se poate autentifica în aplicație deoarece acesta nu are un cont valid
Această problemă poate fi remediată doar de către un administrator al sistemului.
Utilizatorul apasă butonul ”SAVE” fără a completa unul din câmpurile titlu, categorie, pagina
Aplicația va afișa un mesaj de eroare prin care avertizează starea invalidă a formularului de adăugare
Se va continua de la pasul 3
Cerințe speciale:
Sistemul nu trebuie să permită accesul persoanelor neautentificate, asigurând astfel integritatea și securitatea datelor utilizatorilor deja existenți.
Precondiții:
Utilizatorul trebuie să fie autentificat în sistem
Utilizatorul trebuie să fie de tip profesor
Postcondiții:
Datele sunt trimise către API unde vor fi stocate
Noua lecție apare în tabelul cu materialele existente
Prioritate: rămâne la latitudinea utilizatorul dacă dorește sau nu să folosească această funcționalitate.
Frecvența de utilizare: relativă, rămâne la latitudinea utilizatorului.
Diagramă cazuri de utilizare administrator
Cazul principal de utilizare a acestui tip de actor constă în adăugarea de noi conturi de tip profesor. Un administrator este un utilizator ce a fost creat la prima inițializare a aplicației.
Adăugare conturi profesori
Modificare conturi profesori
Ștergere conturi profesori
Figura 5.3 Diagramă cazuri de utilizare administrator
În continuare se va prezenta în detaliu unul dintre aceste cazuri de utilizare.
Nume caz de utilizare: Adăugare cont profesor
Actor principal: Utilizator administrator
Scurtă descriere: După autentificare, utilizatorul va fi redirecționat către pagina de administrare a platformei unde acesta are posibilitatea de a adăuga noi conturi de tip profesor, pe lângă celelalte opțiuni disponibile moștenite de la tipurile inferioare de utilizatori (profesor, student).
Succesiunea evenimentelor:
START caz de utilizare
Utilizatorul accesează aplicația și se autentifică în aceasta
După logare, acesta va fi redirecționat către pagina de administrare a platformei unde acesta are opțiunea de a adăuga un nou cont de tip profesor
Utilizatorul inserează numele profesorului
Utilizatorul inserează prenumele profesorului
Utilizatorul inserează adresa de email a profesorului
Utilizatorul inserează numărul de telefon al profesorului
Utilizatorul inserează o parolă pentru contul profesorului
Utilizatorul apasă butonul ”SAVE”
Noul cont al profesorului apare în tabelul adiacent formularului de adăugare
FINALIZARE caz de utilizare
Cazul de utilizare ia sfârșit când contul profesorului apare în lista cu conturi existente în sistem.
Excepții:
Utilizatorul nu se poate autentifica în aplicație deoarece acesta nu are un cont valid
Această problemă poate fi remediată doar de către un administrator al sistemului.
Utilizatorul apasă butonul ”SAVE” fără a completa unul din câmpurile nume, prenume, email, telefon, parolă
Aplicația va afișa un mesaj de eroare prin care avertizează starea invalidă a formularului de adăugare
Se va continua de la pasul 3
Cerințe speciale:
Sistemul nu trebuie să permită accesul persoanelor neautentificate, asigurând astfel integritatea și securitatea datelor utilizatorilor deja existenți.
Precondiții:
Utilizatorul trebuie să fie autentificat în sistem
Utilizatorul trebuie să fie de tip administrator
Postcondiții:
Datele sunt trimise către API unde vor fi stocate
Nou cont apare în tabelul cu profesori existenți
Prioritate: rămâne la latitudinea utilizatorul dacă dorește sau nu să folosească această funcționalitate.
Frecvența de utilizare: relativă, rămâne la latitudinea utilizatorului.
Diagrame de secvență
Diagrama de secvență descrie interacțiunea dintre două sau mai multe entități și ordinea mesajelor ce sunt transmise între acestea. Totodată arată modul în care instanțele comunică într-un anumit caz de utilizare.
În continuare vor fi prezentate diagramele de secvență pentru trei dintre cele mai importante funcționalități ale aplicației:
Autentificarea în cadrul aplicației
Adăugarea unei lecții noi
Accesarea unei sesiuni în cadrul clasei virtuale
Diagrama de secvență pentru autentificarea în aplicație
Diagrama de secvență este ilustrată în Figura 5.4 Diagrama de secvență a autentificării în aplicație.
Figura 5.4 Diagrama de secvență a autentificării în aplicație
Componenta Login afișează un dialog prin care oferă utilizatorului posibilitatea de autentificare prin introducerea unei adrese de email și o parolă validă. După inserarea acestora, componenta trimite un event de tip LoginEvent în Dispatcher, event ce apoi este propagat de către acesta în Auth Api de unde un request HTTP va fi transmis către API.
Când request-ul ajunge la API, acesta va fi tratat de către Auth Controller în handler-ul rutei ”/authentificate”. Aici un obiect ce conține emailul utilizatorului si parola acestuia va fi construit din body-ul requestului primit, obiect ce mai apoi va fi transmis serviciului de autentificare care, folosind emailul va apela metoda getByEmail din User Service, metodă ce va transmite cererea mai departe către User Repository.
Dacă nu există un utilizator în baza de date cu același email o excepție va fi aruncată, excepție ce va fi mapată pe un obiect de tip response si transmisă aplicației de frontend unde un mesaj corespunzător va fi afișat. Totuși dacă există un utilizator în baza de date, informațiile referitoare la acesta vor fi returnate user service-ului și mai apoi auth service-ului unde validarea parolei va avea parte.
Dacă parola nu este validă o excepție va fi aruncată și tratată ca în cazul precedent, dar dacă parola este validă un JWToken va fi generat pe baza informațiilor primite, acesta fiind mai apoi returnat aplicației de frontend care, la primirea acestuia el va fi stocat și utilizat pentru toate request-urile viitoare.
În urma primirii token-ului, un nou request va fi făcut către API, request ce va fi trată tot în Auth Controller în handler-ul rutei ”/current-user”. Aici token-ul primit va fi decodificat și validat de către metoda validate din auth service. Dacă token-ul este valid, informațiile din acesta vor fi returnate către frontend fiind salvate pentru utilizări viitoare.
Dacă autentificarea a fost executată cu succes putem afirma că aplicația de frontend are la dispoziție un JWToken valid și un obiect ce conține informațiile utilizatorului logat, cât și faptul că utilizatorul a fost redirecționat către pagina de administrare unde poate vizualiza informațiile referitoare la clasele virtuale din care aparține cât și sesiunile precedente și viitoare din care poate face parte.
Diagramă de secvență pentru adăugarea unui material didactic nou
Diagrama secvențială este ilustrată în Figura 5.5 Diagrama de secvență pentru adăugarea unui nou material didactic.
Componenta lesson form pune la dispoziția utilizatorului un formular pentru adăugarea de materiale didactice noi. Acesta conține câmpuri pentru titlu, descriere, categoria din care face parte, cât și oricâte câmpuri de upload pentru paginile materialului. După completarea acestora și trimiterea formularului, componenta apelează un callback primit din Lesson Page numit saveLesson trimițând ca parametru noul obiect format din datele luate din formular, care mai apoi este transformat într-un event de tip NewLessonEvent ce cu ajutorul Dispatcherului global ajunge în Lesson Api.
Handler-ul eventului NewLessonEvent din Lesson API va face un request HTTP cu informațiile primite de la dispatcher către API. Când request-ul este primit de către API, acesta este procesat de către câteva middleware care pe lângă autorizare va procesa fiecare fișier încărcat ca și pagină în material apoi va permite requestului să ajungă în controller.
Când request-ul a ajuns în Lesson Controller putem asuma că fișierele încărcate există deja pe server astfel putem trece la procesarea requestului. În controller un obiect ce conține toate informațiile de pe request va fi creat și transmis serviciului lesson service împreună cu array-ul ce conține informațiile referitoare la fișierele încărcate. După maparea acestora pe o instanță a clasei Lesson, obiectul va fi validat utilizând un set de validatori. Dacă după validare există erori acestea vor fi mapate pe un obiect de tip response și transmise către frontend unde un mesaj de eroare corespunzător va fi afișat, iar dacă obiectul este valid acesta va fi salvat în baza de date cu ajutorul unei instanțe a clasei Lesson Repository, clasă ce facilitează operațiile asupra bazei de date. Dacă salvarea în baza de date s-a efectuat cu succes, un id va fi returnat aplicației de frontend.
La primirea id-ului noului material didactic creat, un nou request va fi făcut către API pentru preluarea unei noi liste cu materialele disponibile. După primirea acesteia, un nou event ce conține noua lecție va fi trimis dispatcherului, care îl va propaga în Lesson Store unde acesta își va actualiza starea internă. Bazat pe noua stare a store-ului, componentele Lesson Page și Lesson Form se vor actualiza reprezentând modificările față de starea precedentă.
Diagrama de secvență pentru accesarea unei sesiuni în cadrul clasei virtuale
Diagrama secvențială este ilustrată în Figura 5.6 Diagrama secvențială pentru accesarea unei sesiuni în cadrul clasei virtuale.
Figura 5.6 Diagrama secvențială pentru accesarea unei sesiuni în cadrul clasei virtuale
Când o sesiune este deschisă în cadrul clasei virtuale aceasta trimite ca parametrii constructorului acesteia id-ul sesiunii și pe cel al materialului didactic ce va fi susținut. Având acces la aceste informații, clasa virtuală va emite un event în dispatcher de tip GetLessonEvent, event ce va fi propagat către Lesson API unde un request HTTP va fi făcut către API, acesta fiind tratat ca în cazurile exemplificate anterior.
Astfel, când clasa virtuală primește instanța materialului de la API, va continua la conectarea către serverul de socket. Va emite un event de tip SocketConnect ce va conține id-ul sesiunii, id-ul utilizatorului și token-ul primit la autentificare. Pe baza acestor informații socket serverul va autentifica utilizatorul folosind aceeași secvență descrisă la 5.1.2.1. După autentificarea utilizatorului, un room specific sesiunii va fi creat, room la care toți viitorii participanți vor fi adăugați, menținând astfel integritatea datelor.
După conectarea cu succes la serverul socket se emite un event de tip ParticipantJoined, când acest event ajunge în room-ul sesiunii, pe lângă faptul că acest mesaj va fi distribuit celorlalți participanți, utilizatorul care a transmis eventul va primi toate eventurile persistate în trecut în cadrul sesiunii sortate după un revision id, aducând astfel utilizatorul la starea curentă a sesiunii în desfășurare.
Detalii de implementare
Sistemul proiectat în lucrarea de față este compus din trei componente majore, fiecare având un rol bine definit: partea de server sau backend-ul aplicației, partea de socket server sau serverul pentru comunicarea în timp real și partea de client sau frontend-ul aplicației.
Toate aceste module sunt dezvoltate pe o infrastructură bazată pe containere Docker, fiecare modul fiind un container expunând doar un reverse proxy, fapt ce permite scalarea aplicației în funcție de necesitate cât și balansarea sarcinii pe componente.
Partea de API este reprezentată de o aplicație Node.js și frameworkul Express.js dezvoltată utilizând mediul de dezvoltare WebStorm 2016.1.
Partea de comunicare în timp real sau socket serverul este tot o aplicație Node.js și frameworkul Socket.io dezvoltată în același IDE.
Clientul este reprezentat de către o aplicație web disponibilă în toate browserele moderne scrisă pe baza framework-ului React și implementând printre altele arhitectura flux.
După cum se poate observa în diagrama de deployment, comunicarea dintre module se realizează folosind protocolul HTTP și arhitectura REST pentru comunicarea dintre client si API, respectiv protocolul RFC 6455 pentru comunicarea dintre client si serverul de socket. Conținutul cererilor și răspunsurilor vor fi transmise în format JSON fiind astfel ușor de parsat de către client.
Prin alegerea arhitecturii REST și a celei client-server se realizează cu adevărat o separare uniformă a componentelor și a atribuțiilor fiecăreia. Astfel, stocarea și procesarea datelor este principala atribuție a serverului, menținerea informațiilor referitoare la comunicarea în timp real cât și procesarea si stocarea evenimentelor transmise printre acestea este principala funcționalitate a socket serverului, iar interfațarea acestora cu utilizatorul intră în atribuția clientului. Astfel componentele pot fi dezvoltate independent și ar putea fi înlocuită cu ușurință, atât timp cât interfața dintre componente și modul de comunicare rămâne același, fapt care determină astfel simplitatea și scalabilitatea sistemului.
În Figura 5.7 Diagrama de deployment a sistemuluieste prezentată diagrama de deployment a întregului sistem, evidențiind astfel principalele componente prezentate anterior.
Figura 5.7 Diagrama de deployment a sistemului
În continuare, se vor prezenta în detaliu fiecare componentă din diagrama de deployment, evidențiind modul de comunicare dintre componente în interiorul sistemului.
Arhitectura bazei de date
Pentru stocarea și organizarea datelor transmise în interiorul sistemului se folosește RethinkDb, o implementare a bazelor de date NoSQL. Este o bază de date ușor de manipulat și înțeles având posibilitatea de a lucra cu volume mari de date, astfel fiind utilizată atât în proiecte mari cât și în proiecte mici.
În figura următoare este prezentată arhitectura bazei de date, evidențiind legăturile dintre colecții.
După cum se poate observa în figura precedentă, avem 7 colecții: Users, Blacklist, Events, Categories, Lessons, Sessions și Classrooms.
Colecția Users
În această colecție sunt stocate principalele date de identificare a unui utilizator, printre care se regăsesc: informații personale precum nume, prenume, email, număr de telefon.
Principalele câmpuri ale colecției sunt:
id – id-ul utilizatorului
firstName – prenumele utilizatorului
lastName – numele utilizatorului
email – adresa de email a utilizatorului
phoneNumber – numărul de telefon
salt – hash generat utilizat în criptarea parolei
password – parola criptată utilizând algoritmul bcrypt
roles – array de roluri pe care le deține utilizatorul, roluri ce regulează accesul la anumite funcționalități din aplicație
Unele informații sunt completate direct de către client: firstName, lastName, email, phoneNumber iar restul sunt completate de către server. De exemplu, salt, pasword și roles sunt completate de către sistem la crearea utilizatorului în sistem.
Colecția Blacklist
În această colecție sunt stocate doar JSONWebtokens precedente pe care utilizatorul a ales să le invalideze chiar dacă acestea nu au expirat încă. Este utilizată în procesul de autorizare, iar un nou token este adăugat doar când un utilizator alege să se delogheze din aplicație.
Principalele câmpuri ale colecției sunt:
id
token
Colecția Categories
Colecția categories conține informațiile ce descriu categoriile de materiale din sistem. Acestea pot fi create de către administrator și profesori.
Principalele câmpuri ale colecției sunt:
id
name – numele categoriei
description – o scurtă descriere asupra categoriei
Colecția Lessons
În această colecție sunt păstrate informații cu referire la materialele didactice disponibile în sistem cât și informații despre slide-urile ce aparțin acestora.
Principalele câmpuri ale colecției sunt:
id
categoryId – id-ul categoriei din care face parte
title – titlul materialului didactic
description – o scurtă descriere a acestuia
slides – un array de elemente de tip slide ce descriu fiecare pagină a materialului
Principalele câmpuri ale unui slide sunt:
id
name – numele fisierului
order – ordinea în material
path – calea către fișier
type – mimeType-ul fisierului
Colecția Sessions
În această colecție sunt persistate informațiile despre sesiunile precedente cât și cele viitoare ce au luat parte în cadrul sistemului.
Principalele câmpuri ale colecției sunt:
id
lessonId – id-ul materialului susținut în sesiune
startDate – data de început a sesiunii
endDate – momentul în care sesiunea intră in review
Colecția Classrooms
În cadrul acestei colecții sunt stocate informații referitoare la clasele virtuale adăugate în sistem. Printre alte informații acestea conțin un set de sesiuni precedente cât și viitoare, un array de studenți și unul de profesori,
Principalele câmpuri ale colecției sunt:
id
name – numele clasei virtuale
lastSessionId – id-ul ultimei sesiuni deschise în cadrul clasei virtuale
sessions – un array de sesiuni
students – o listă cu studenții ce aparțin clasei virtuale
teachers – o listă cu profesorii ce susțin materiale în cadrul clasei
Colecția Events
În colecția events vor fi păstrate toate eventurile trimise prin intermediul serverului de comunicare în timp real care au un nivel de persistență indefinită. Aceste eventuri păstrează pe lângă informații necesare identificării sesiunii și a utilizatorului ce le-a emis date referitoare la acțiunile efectuate de către participanți în cadrul unei sesiuni cum ar fi un nou desen adăugat sau un nou mesaj transmis în chat.
Principalele câmpuri ale colecției sunt:
id
sesssionId – id-ul sesiunii în cadrul căreia eventul a fost transmis
slideId – id-ul slide-ului asupra căreia acțiunea descrisă în event trebuie aplicată
userId – id-ul user-ului ce a emis eventul
type – tipul eventului
revision – conține numărul de ordine al eventului în contextul întregii sesiuni, câmp ce va fi utilizat în ordonarea cronologică a eventurilor
persistenceLevel – nivelul de persistență al eventurilor
data – obiect ce va conține orice informație necesară pentru descrierea unei acțiuni în cadrul clasei virtuale.
Aplicația server principală
API-ul aplicației folosește se bazează pe paradigma programării orientată pe obiecte utilizând NodeJs precum utilizarea suprasetului TypeScript cât și a framework-ului ExpressJs.
Soluția acestui modul al sistemului este alcătuită din trei mari pachete, fiecare din ele reprezentând o parte din arhitectura three-tier.
În figura următoare este prezentat modul de comunicare dintre cele trei pachete.
În continuare vom prezenta fiecare pachet mai în detaliu.
Pachetul database layer
Acest pachet reprezintă fundația arhitecturii three-tier. Conține mecanisme de stocare și acces asupra datelor. La rândul lui pachetul conține câteva subpachete: models, repositories, mappers, validators.
Pachetul models conține modelele necesare în cadrul aplicației. Fiecare clasă în acest pachet extinde clasa BaseModel, clasă ce implementează câteva metode utile.
Pachetul repositories conține clasele necesare conectării la baza de date precum și interfața de comunicare cu implementările de rigoare necesare interacționării cu aceasta.
Pachetul mappers conține logica necesară conversiei datelor înspre și dinspre baza de date, logică ce permite utilizarea entităților în cadrul aplicației și maparea automată către acestea.
Pachetul validators conține logica de validare a datelor stocate într-o entitate, validare ce se execută de fiecare dată când o modificare a datelor din baza de date este efectuată.
Figura 5.10 diagrama de clase apartenente modulului modelsprezintă succint diagrama de clase din cadrul submodulului models.
Figura 5.11 diagrama de clase a pachetului repositoriesreprezintă diagrama de clase apartenente modulului repositories.
În cadrul acestui pachet se poate observa metodele de bază în interfațarea cu baza de date clasă ce va fi extinsă de către fiecare repository specific entității. Repository-urile acestea mai apoi vor implementa metode specifice entităților ce le deservesc.
După cum am specificat în capitolele anterioare, ca suport pentru baza de date s-a ales o bază de date NoSql și anume RethinkDb. Pentru implementarea interogărilor s-a folosit driverul acestora pentru NodeJs cu o interfață custom dezvoltată în cadrul acestei aplicații.
Figura 5.12 diagrama claselor în pachetul mappersreprezintă diagrama claselor în pachetul mappers.
Figura 5.12 diagrama claselor în pachetul mappers
Pachetul mappers pune la dispoziția programatorului logica necesară mapării documentelor din baza de date asupra modelelor definite în cadrul aplicației, mapare ce se face automat în interiorul repository-ului specific entității.
Modulul pune la dispoziție un factory public, care pe baza clasei entității returnează o instanță a mapper-ului necesar entității. Fiecare mapper implementează o interfață generică ce forțează clasa să expună două metode bine definite.
Astfel la apelarea funcției hydrate cu o instanță a entității ce urmează a fi mapată și un obiect cu datele necesare, mapper-ul va popula instanța cu datele pertinente din obiect. La fel, când funcție dehydrate este apelată cu o instanță a entității, mapper-ul va returna un simplu obiect JSON cu informațiile stocate în entitate.
Figura 5.14 diagrama claselor din pachetul validatorsprezintă în detaliu diagrama claselor în pachetul validators cât și dependințele dintre acestea.
Figura 5.14 diagrama claselor din pachetul validators
Astfel modulul validators pune la dispoziție o serie de validatori simplii care mai apoi vor fi utilizați în validarea informațiilor înainte de salvarea acestora.
Pachetul pune la dispoziția programatorului un factory public prin care, pe baza entității se poate accesa o instanță a validatorului specific entității.
Pachetul service layer
Acest pachet reprezintă layer-ul de mijloc în cadrul arhitecturii three-tier. Conține logica de business a aplicației precum și interacțiunile dintre modele cât și procesarea datelor primite de la utilizator.
Modulul conține câteva clase principale și anume:
authService – serviciul responsabil de autentificarea și autorizarea utilizatorului
userService – serviciu ce implementează logica necesară entității de tip User
attendeeService – acest serviciu extinde logica din userService și adaugă unele metode specifice diferitelor tipuri de utilizatori din cadrul sistemului
categoryService – serviciu responsabil de procesarea informațiilor referitoare la categoriile de materiale
lessonService – conține partea de business ce permite manipularea entităților de tip lesson
sessionServie – serviciu ce agregă metodele necesare lucrului cu entități de tip session
classroomService – implementează logica de business utilizată în procesarea informațiilor referitoare la entități de tip classroom.
În figura următoare se pot observa interacțiunile dintre clasele ce fac parte din acest pachet.
Pachetul presentation layer
Acest pachet reprezintă nivelul superior din arhitectura three-tier. În cadrul acestui pachet se definesc resursele cu care utilizatorul va avea posibilitatea de a interacționa. Conține diferite subpachete: controllers, utils și middleware.
În figurile următoare vor fi prezentate clasele ce fac parte din pachetele menționate anterior.
În pachetul middlewares sunt implementate câteva funcții ajutătoare layer-ului de prezentare. Aceste funcții sunt metode ce au acces atât la informațiile din request cât și la obiectul ce urmează a fi transmis ca și response.
Aceste funcții middleware pot executa următoarele operațiuni:
pot executa orice cod
pot modifica informațiile din request sau response
pot încheia ciclul request-ului returnând prematur un response
pot apela următorul middleware din stack
Dacă middleware-ul curent nu încheie ciclul request-ului acesta este obligat să apeleze la sfârșitul executării următorul middleware din stack.
În cazul aplicației noastre sunt implementate patru astfel de middleware și anume: cors, authentificated, authorizedWithRole și uploader.
Middleware-ul prezentat mai sus realizează mecanismul CORS (Cross-origin resource sharing). Acest mecanism permite aplicațiilor aparținătoare altor domenii să acceseze serviciile REST implementate în acest modul. Acest lucru fiind realizat prin adăugarea unor headere în răspunsul trimis clientului.
Middleware-ul authenticated realizează validarea fiecărui request făcut către API. Acesta preia JWToken-ul de pe request și cu ajutorul serviciului de autentificare îl validează, îl decodifică, iar informația este adăugată request-ului acesta fiind mai apoi trimis ca parametru următoarelor metode ce așteaptă în stack. În caz contrar, fie când tokenul nu există sau e invalid, ciclul request-ului este întrerupt returnându-se un răspuns de eroare cu mesajul ”Invalid token”.
Funcția lambda prezentată în figura anterioară prezintă implementarea middleware-ului authorizedWithRole, middleware ce realizează verificarea accesului utilizatorului la resursele din sistem. Astfel după autentificare, dacă aceasta sa realizat cu succes, această metodă primește rolul necesar accesări resursei ca parametru și verifică dacă acesta apare în rolurile utilizatorului. Dacă autorizarea s-a efectuat și utilizatorul autentificat are rolul necesar accesării resursei, ciclul request-ului va continua în mod natural, iar în caz contrar un răspuns de eroare cu mesajul ”Unauthorized access” va fi returnat, request-ul încheindu-se aici.
Middleware-ul prezentat anterior utilizează o bine cunoscută librărie pentru upload pe NodeJs și anume multer , iar în funcția precedentă este afișată configurarea acesteia. Sunt configurate astfel modul de numire a fișierelor cât și destinația acestora. De altfel aici sunt setate și limitele acestora: maxim 100 de fișiere încărcate pe un request și o dimensiune maximă de 10MB.
Aplicația de comunicație în timp real (server-ul socket)
Aplicația de comunicare în timp real este implementată utilizând engine-ul v8 pe baza căruia funcționează NodeJs și framework-urile Express.Js și Socket.Io, librării ce facilitează realizarea acesteia.
La fel ca și aplicația precedentă aceasta implementează tot arhitectura three-tier având astfel un database layer, un business logic layer și un presentation layer.
Pachetul database layer
Acest pachet reprezintă layer-ul cel mai de jos din arhitectura three-tier. Conține mecanismele de acces și stocare a informațiilor în baza de date. La rândul lui pachetul conține câteva subpachete: models, repositories și mappers.
Figura următoare prezintă succint diagrama de clase din pachetele amintite mai sus.
Figura 5.23 diagrama claselor din pachetul mappers
Pachetul de business logic
Logica de business în contextul acestei aplicații este cuprinsă în trei clase fiecare cu funcționalitate specifică. În continuare se vor prezenta câteva funcționalități ale server-ului socket.
Similar middleware-ului de autentificare prezentat în cadrul aplicației server principală, un proces de autentificare este necesar și aici, acesta funcționând astfel: după ce un socket se conectează la server acesta va emite către server un eveniment de tip authentication ce conține JWToken-ul primit la logare. Cu ajutorul serviciului de autentificare token-ul este validat, astfel dacă acesta este corect se va continua la crearea sesiunii în cadrul server-ului, iar în caz contrar clientul va fi deconectat păstrând astfel integritatea informațiilor transmise între utilizatorii autentificați.
În figura prezentată anterior este implementat managerul de sesiuni active în sistem. Managerul utilizează design patern-ul singleton , iar instanța acestuia este creată la startarea server-ului și expune doar două metode publice, createSession și addParticipant, metode ce vor fi utilizate astfel: după autentificare utilizatorului pe baza id-ului sesiunii se va crea o sesiune în cadrul sistemului dacă aceasta nu există, după crearea sesiunii, pe baza id-ului acesteia cât și cel al participantului socket-ul aferent acestuia este adăugat în sesiune, socket ce va fi folosit pentru primirea și emiterea de evenimente pe parcursul sesiunii. De menționat aici este faptul că atunci când toți participanții părăsesc sesiunea managerul va șterge instanța acesteia eliberând astfel memoria alocată.
Dată fiind arhitectura și natura aplicației, aceasta fiind orientată pe evenimente, pentru fiecare sesiune existentă se păstrează doar starea inițială și fiecare eveniment care este emis în cadrul acesteia. Astfel după ce un utilizator este autentificat și adăugat în sesiune este apelată funcția descrisă în figura anterioară, funcție ce ia din baza de date toate evenimentele precedente momentului apelării le combină cu evenimentele ce au un nivel de persistență efemeră le sortează după id-ul reviziei și le emite utilizatorului autentificat, rezultând astfel în aducerea stării sesiunii utilizatorului la starea finală aplicând toate evenimentele emise vreodată în ordinea emiteri acestora.
Pachetul presentation layer
Dat fiind faptul că utilizatorul nu are interacțiune directă cu această aplicație, comunicarea cu aceasta și utilizarea ei este strict implementată în aplicația de front-end, pachetul acesta conține doar un endpoint folosit pentru handshake la deschiderea sesiunii.
Aplicația de frontend
Interfața sistemului cu care utilizatorul interacționează este la rândul ei o aplicație web de sine stătătoare ce implementează arhitectura flux pe baza framework-ului ReactJs utilizând JSX pentru view-uri și LESS pentru design.
Datorită arhitecturii implementate, aplicația se împarte în mai multe pachete cu funcționalități specifice și anume: actions, api, components, dispatcher, events, helpers, models, pages și stores, pachete ce vor fi prezentate mai în detaliu în rândurile următoare.
Pachetul api
Pachetul api conține logica necesară comunicării cu aplicațiile prezentate anterior. Acesta implementează metodele necesare consumării resurselor primite de la API cât și transmiterea datelor către acesta, astfel fiecare clasă din acest pachet primește event-uri de la dispatcher pe baza cărora trimite sau cere informații de la API, răspunsul acestor request-uri fiind mai apoi emis ca și alte eventuri către dispatcher.
Pachetul actions
În pachetul actions sunt implementează toate callback-urile prin care orice event va fi emis către dispatcher, astfel implementând fluxul de date unidirecțional care afirmă ca într-o aplicație flux doar prin cadrul unui action un event poate fi emis în dispatcher.
În continuare este prezentată diagrama claselor apartenente pachetului actions.
Pachetul dispatcher
Pachetul dispatcher conține o singură clasă ce implementează dispatcher-ul unic utilizat în contextul aplicației, fiind punctul central al arhitecturii, prin care sunt emise toate event-urile în aplicație, event-uri ce descriu orice acțiune efectuată.
Pachetul helpers
În pachetul helpers sunt agregate câteva clase care permite programatorului o mai ușoară implementare a unor funcționalități în sistem.
Acesta conține următoarele clase:
Base64 – librărie utilă în codificarea și decodificarea mesajelor în baza 64
DateFormatter – librărie utilizată în formatarea timestamp-urilor
LocalStorage – clasă ce implementează câteva metode utile în lucrul cu spațiul de stocare local
MD5 – librărie utilizată în codificarea stringurilor în format md5
Pachetul components
În pachetul components sunt implementate toate fragmentele ce pot fi afișate în aplicație formând astfel layer-ul de view-uri ale acesteia.
Prezentat anterior este arborele de dependințe dintre componentele vizuale ale aplicației, astfel pentru afișarea oricărei element toate componentele adiacente acestuia pe nivelele superioare ale arborelui trebuie să fie deja randate.
Spre exemplu: ca să afișăm componenta whiteboard trebuie să încărcăm componenta page care la rândul ei afișează componentele navigation, sidebar și content. În cadrul componentei content, pe baza rutei accesate, se va randa elementul classroom care va afișa în spațiul sidebar-ului o listă cu participanți și un chat, iar în container-ul principal se va încărca componenta whiteboard.
Pachetul events
Pachetul events conține toate clasele ce descriu fiecare eveniment din aplicație. Acestea se pot grupa în două categorii: specifice procesului de autentificare, specifice unei entități și evenimente specifice acțiunilor din clasa virtuală.
Evenimente specifice procesului de autentificare
LoginEvent
LoginSuccessfulEvent
LoginUnsuccessfulEvent
LogoutEvent
GetCurrentUserEvent
GetCurrentUserSuccessfullyEvent
GetCurrentUserUnsuccessfullyEvent
Evenimente specifice unei entități
LoadEvent
LoadedSuccessfullyEvent
SelectEvent
SaveEvent
DeleteEvent
FormErrorsEvent
Evenimente specifice clasei virtuale
ParticipantJoin
ChatMessage
SlideChange
PencilDrawing
EraserDrawing
LineDrawing
RectangleDrawing
HighlighterDrawing
Pachetul models
Pachetul models conține o agregare a pachetelor cu același nume din aplicațiile de server și comunicare în timp real, dat fiind faptul ca aplicația frontend comunică cu ambele, păstrându-se astfel structura datelor constantă între frontend și backend.
Pachetul pages
În cadrul acestuia sunt stocate componentele ce descriu nivelul superior al arborelui de dependințe prezentat anterior. Elementele apartenente acestui pachet sunt randate pe baza rutei accesate în sistem, astfel în nici un moment al execuției aplicației două astfel de componente nu pot coexista.
Pachetul stores
Modulul stores conține ultima parte majoră din arhitectura flux și anume data stores. Conform 3.3 store-urile sunt clase care păstrează starea aplicației si care înregistrează callback-uri în dispatcher prin care primește eventuri ce vor altera starea acestuia în iterația următoare.
Rularea sistemului
Pentru rularea aplicației sunt necesare pornirea containerelor docker în ordinea corectă a dependințelor: proxy, monitoring, baza de date, api, socket și frontend. Pentru facilitarea acestui proces sa folosit docker compose , tehnologie ce orchestrează aplicații ce necesită mai multe containere pentru rulare.
Astfel pentru facilitarea rulării sistemul câteva scripturi au fost implementate cum ar fi build.sh, install.sh, start.sh și scale.sh, scripturi ce rulează comenzi asupra infrastructurii docker.
Dacă startarea aplicațiilor server s-a realizat cu succes, terminalele sistemelor ar trebui să arate precum în figurile următoare:
După rularea scripturilor prezentate anterior, sistemul pune la dispoziție câteva intefețe pentru fiecare din sisteme:
classroom.dkr – interfața aplicației implementate
classroom.dkr:8080 – interfața proxy-ului și a load balancer-ului
monitoring.classroom.dkr – interfața serviciului de monitorizare
db.classroom.dkr – panoul de administrare al bazei de date
În figura următoare este prezentată interfața proxy-ului precum și instanțele container-ului api acesta fiind load-balanced de către proxy.
Conform 5.1.1 în sistem sunt implementate funcționalitățile necesare management-ului de clase virtuale, studenți, profesori și materiale didactice. În continuare vor fi prezentate grafic câteva dintre aceste funcționalități.
Figura precedentă reprezintă pagina principală a aplicației. Pentru accesarea acesteia utilizatorul trebuie să fie autentificat, pagina afișând informații senzitive utilizatorului sub forma tabelelor afișate ce conțin date referitoare claselor virtuale în care aparține cât și sesiunile precedente și viitoare împreună cu materialele didactice aferente acestora.
În Figura 5.42 se poate vizualiza pagina de administrare a materialelor didactice în sistem. Această pagină necesită cel puțin rolul de profesor pentru accesare datorită acțiunilor posibile în această situație.
Prezentat în Figura 5.43 vizualizarea materialului didactic și a chat-ului în clasa virtuală este o sesiune deschisă în clasa virtuală cât și funcționalitățile acesteia cum ar fi lista participanților, chatul în timp real, uneltele de desen cât și o demonstrație a acestora în figura următoare.
Testare și validare
Testarea aplicațiilor server
Testarea conexiunii cu baza de date s-a realizat atât în timpul implementării serviciilor cât și la executarea finală a testelor și rularea aplicației. Metoda principală de testare a serverului api și socket s-a realizat utilizând plugin-ul Postman.
Testarea serviciului de load-balancing și monitorizare
Pentru testarea scalabilității sistemului s-a folosit Apache Benchmarking . Cu ajutorul acestui tool se pot executa automat mii de requesturi către un endpoint testând astfel reziliența acestuia cât și timpul de răspuns al acestuia.
Un astfel de test se execută utilizând comanda: ab –n [număr total de requesturi] –c [număr requesturi concomitente] [endpoint]
Testarea aplicației ca întreg
Testarea acesteia sa realizat atât în timpul dezvoltării cât și la final. Fiecare funcționalitate a acesteia fiind executată repetat cu fiecare tip de utilizator. La rândul ei, aplicația în sine a fost testată pe mai multe sisteme de operare cum ar fi Windows, Ubuntu și Mac Os X confirmând astfel abilitatea platformei de a rula în orice tip de environment.
Concluzii
Concluzii
Obiectivul principal al acestui sistem este de a facilita accesul la materiale didactice, cât și la sesiuni de predare cu profesori acreditați într-un mediu virtual. În acest scop s-a încercat utilizarea tehnologiilor emergente. Proiectarea sistemului de față a inclus în componența sa o aplicație web accesibilă din orice browser modern.
Funcționalitățile sistemului au fost implementate în totalitate, aplicația îndeplinind cu succes următoarele activități:
Logarea în aplicatie folosind adresa de email și parola
Vizualizarea claselor în care aparții și a sesiunile aferente acestora
Accesarea clasei virtuale
Listă cu participanții care au accesat aceeași clasă virtuală
Chat în timp real cu participanții în sesiunea curentă
Vizualizarea unui material didactic în clasa virtuală
Utilizarea diferitelor unelte de desen
Adăugarea de noi studenți și gruparea acestora în clase
Adăugarea și modificarea claselor virtuale
Adăugarea și modificarea sesiunilor aferente acestora
Adăugarea de categorii de materiale
Adăugarea de materiale didactice și gruparea acestora în categorii
Adăugarea de noi profesori
Sistemul este format din trei componente majore: două componente de server și o aplicație web. Aceste aplicații au fost implementate individual, ulterior fiind testată integritatea acestora în contextul întregului sistem. Testarea acestora s-a realizat atât manual prin parcurgerea diferitelor flow-uri în aplicație cât și prin rularea de teste automate utilizând Postman si Apache benchmark.
Așadar, proiectul este un sistem distribuit ce facilitează accesul la materiale didactice, singura condiție fiind deținerea unui calculator cu acces la internet și un browser relativ modern.
Dezvoltări ulterioare
Pentru o viitoare versiune a sistemului se pot aduce îmbunătățiri atât în privința aplicațiilor de server cât și în componenta de web.
În cazul aplicației server principale se pot aduce următoarele îmbunătățiri:
Implementarea unui serviciu de notificări prin email când o sesiune urmează să devină disponibilă
Rafinarea sistemului de autorizare, permițând o granulare mai atentă a accesului la informațiile din sistem
Încărcarea slide-urilor în Cloud facilitând astfel scalabilitatea sistemului
În cazul serverului de comunicare în timp real se pot aduce îmbunătățiri la managementul sesiunilor mutând această funcționalitate din memorie într-un sistem de sine stătător.
De asemenea, o nouă versiune a aplicației web ar putea aduce câteva funcționalități noi în forma:
Implementării unei unelte de adăugare de text
Implementării unui sistem de comunicare audio / video utilizând WebRTC
Îmbunătățirii rezilienței funcționalităților existente
Datorită contextului căruia sistemul este destinat, îmbunătățirea aplicației este o necesitare continuă, printre actualizările obligatorii fiind creșterea performanței sistemului, reziliența acestuia la erori și rezolvarea acestora îmbunătățind astfel utilizabilitatea acestuia.
Acronime
JSON – JavaScript Object Notation
API – Application Programming Interface
HTTP – HyperText Transfer Protocol
URI – Union Resource Identifier
REST – Representational State Transfer
NoSQL – Not Only SQL
JWT – Json Web Token
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Platforma online pentru învățare [304346] (ID: 304346)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
