ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 148
Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 77
Abonament PDF

Aplicații deconectate ocazional

Florin Nicolae Cristea
Technical Lead @ Yonder



PROGRAMARE


Trăim într-o eră a internetului, în care suntem conectați aproape în permanență, fie la job, acasă sau când ne plimbăm prin oraș. Cu toate acestea, mai sunt momente în care conexiunea cu online-ul ne poate crea probleme. Cât de des am văzut cu toții mesajul: "Fără conexiune la internet. Asigurați-vă că WI-FI sau datele mobile sunt pornite, apoi reîncercați." Astfel de situații sunt evident neplăcute, dar ce putem face ca dezvoltatori software în cazul în care atât operatorul de date cât și rețeaua WI-FI nu sunt în favoarea noastră?

În principiu, avem întotdeauna de ales între a afișa un mesaj prietenos (n.r. aplicație web sau mobile) în care precizăm că această aplicație funcționează doar cu internet, și a dezvolta o aplicație care să ofere utilizatorului o funcționalitate limitată. Așadar, provocarea principală este cum să gândim arhitectura unei aplicații, astfel încât chiar și atunci când conectivitatea este scăzută sau inexistentă, situațiile neplăcute pentru utilizator să fie reduse la minim, iar consistența datelor să fie asigurată la revenirea în online. Astfel de aplicații mai sunt cunoscute și ca aplicații deconectate ocazional.

Să presupunem că avem o aplicație care facilitează realizarea a diverse servicii la domiciliul clientului pe baza unui sistem centralizat de cereri. Informațiile despre locația (adresa, client, etc.) la care trebuie realizat serviciul pot fi schimbate fie din sistemul central, fie de către alt operator de pe teren. Cum ar fi ca pentru perioade scurte de timp, în timpul intervenției la domiciliul clientului, operatorul companiei de servicii să nu poată beneficia de informațiile necesare din sistem, din cauza lipsei internetului? Dar dacă se constată că cererea nu mai este validă sau e necesară înregistrarea unui nou serviciu în sistem?

O abordare tradițională ar fi folosirea unei arhitecturi clasice de tip MVC (n.r. Model View Controller), prin care avem o interfață (View) în aplicație, care prin intermediul unui Controller va gestiona Modelul pentru realizarea operațiilor de citire/scriere (CRUD) solicitate de utilizator. De asemenea, Viewul va fi actualizat de către controller ori de câte ori apare o schimbare în Model. De altfel, arhitectura MVC este un șablon arhitectural foarte utilizat, în special pentru crearea aplicațiilor cu interfață grafică pentru utilizator, având acest avantaj major al separării părții vizuale de partea de business.

În cazul în care decidem să valorificăm o astfel de arhitectură pentru aplicațiile deconectate ocazional, având în vedere că partea de business trebuie să funcționeze și fără internet, se poate păstra același View, dar trebuie luate în calcul următoarele aspecte suplimentare, pe lângă cele clasice de MVC:

Modelul de date

Același model de citire/scriere a datelor care în general rulează pe server, va trebui să fie replicat și pe client (pentru modul offline). Așadar, vor exista multiple structuri de date, una principală pe server și mai multe instanțe pe fiecare client.

Confidențialitatea și securitatea datelor pe client

Se va impune ca datele sensibile care vor fi stocate în structurile de date (de exemplu: Local Storage, IndexDB), să fie criptate la stocare și decriptate la afișare.

Sincronizarea datelor

Chiar și atunci când există conexiune la internet, aplicația va trebui să decidă momentul oportun în care își va sincroniza datele pentru suportul offline. Sincronizarea o putem realiza automat la revenirea conexiunii, la logarea utilizatorului în aplicație, sau on request de către utilizator. Totuși, în toate cele trei variante menționate anterior, se recomandă blocarea Viewului până la terminarea procesului de sincronizare pentru evitarea unor eventuale conflicte.

Consistența datelor

Pentru asigurarea consistenței datelor între serverul central și diverși clienți deconectați, este necesară folosirea unor indicatori de timp pentru fiecare entitate în parte. Pe baza acestor indicatori care ar putea fi folosiți pentru operațiile de creare, editare sau ștergere, sistemul va decide ce schimbări să aplice pe o anumită entitate. În cazul detectării unei coliziuni pe aceeași entitate, există două opțiuni:

De cele mai multe ori, dacă se ține cont cu seriozitate de aspectele menționate mai sus, arhitectura MVC clasică este o arhitectură de succes și în cazul aplicațiilor deconectate ocazional. Cu toate acestea, un inconvenient major al acestui tip de arhitectură este adăugarea de complexitate și mentenanță suplimentară aplicațiilor pe care le dezvoltăm.

Cum ar fi însă dacă am încerca să privim această problemă dintr-o altă perspectivă? Complexitatea folosirii unei arhitecturi MVC clasice în această situație e dată de duplicarea modelului sau a structurii de date, sincronizarea entităților și asigurarea consistenței datelor. Prin urmare, dacă am reuși doar să separăm modelul de date în două modele independente de citire, respectiv scriere a datelor, situația unei aplicații fără conexiune la internet s-ar simplifica. Din fericire, există un șablon arhitectural în acest sens, care ne ajută să schimbăm puțin paradigma de separare a operațiilor de citire cu cele de scriere. Denumit CQRS (Command Query Responsibility Segregation), conceptul a fost prima dată introdus de Greg Young în Februarie 2010. Fiind un concept sau șablon arhitectural, se poate folosi în continuare o arhitectură clasică de tip MVC, dar de această dată îmbunătățită prin CQRS în modul de manipulare a datelor.

Prin aplicarea conceptului CQRS peste o arhitectură de tip MVC, practic vom folosi întotdeauna același model de date pentru citire, prin queries, respectiv un model diferit pentru scriere, prin comenzi, ceea ce ne va facilita sincronizarea și optimizarea separată a celor două modele în funcție de necesități.

Cu toate acestea, să vedem cum s-ar modifica aspectele anterioare care trebuiau luate în calcul la adaptarea unui model arhitectural MVC pentru aplicațiile deconectate ocazional:

Modelul de date

E important să menționăm că nu există neapărat constrângeri de modelare și că un model încărcat ar putea crea aceleași probleme ca și în abordarea cu un MVC clasic. Din acest punct de vedere, pentru a evita potențialele conflicte, noi am optat pentru un model atomic de comenzi, astfel încât, în esență, fiecare comandă să modifice maxim o proprietate dintr-o entitate.

Așadar, dacă pentru expunerea datelor către utilizator, ne putem folosi de simple servicii REST cu repository-uri pentru interogarea directă a bazei de date, pentru modificarea, crearea sau ștergerea datelor, vom folosi comenzi atomice. Prin folosirea unui hub de comenzi și printr-o versionare corectă a fiecărei comenzi, se vor putea sincroniza comenzi și nu entități, iar posibilele conflicte pot fi foarte bine gestionate, observate și tratate automat sau cu intervenția utilizatorului.

Ce se întâmplă însă cu expunerea datelor către utilizator în cazul în care acesta rămâne fără conexiune la internet? În această situație, ultimele informații citite de la server vor fi folosite de către aplicație cât este deconectată, iar partea interesantă este că exact același set de comenzi va fi generat, atât online, cât și offline. Acest lucru înseamnă că la revenirea conexiunii de internet, clientul va prelua rezultatele comenzilor executate de către alți clienți sau de către un operator central și le va aplica pe setul personal de date.

Confidențialitatea și securitatea datelor pe client

Am ales ca atât entitățile aplicației, cât și înlănțuirea de comenzi să fie stocate în structuri de date din memoria internă a aplicației. Pe de altă parte, va fi necesară stocarea informațiilor într-o bază de date locală, în cazul în care e necesară și logarea în aplicație fără conexiune la internet. În această situație, este obligatoriu ca datele să fie criptate la stocare și decriptate la afișare.

Sincronizarea datelor

Indiferent de conexiunea la internet, am ales să folosim câte un eveniment pentru fiecare comandă executată. Conceptul CQRS se pretează foarte bine la folosirea de evenimente asincrone, care ne ajută să confirmăm dacă o comandă a fost aplicată cu succes sau nu. De exemplu, în cazul unui eveniment pozitiv, operația de modificare inițiată de către utilizator va fi păstrată în aplicație, dar în cazul unui eveniment negativ, utilizatorul va putea să decidă rezoluția unui posibil conflict.

Putem face sincronizarea și propagarea de evenimente, ca rezultat al unor comenzi, prin metode ca long-polling, server-sent-events sau chiar conexiuni de tip websocket. Avantajul folosirii unei conexiuni de tip websocket este comunicarea în timp real între aplicația client și server, având întotdeauna un canal de comunicare deschis care interceptează evenimentele generate de server. De asemenea, în cazul în care conexiunea websocket este închisă, serverul va putea determina cu exactitate momentul din care utilizatorul de pe teren a rămas fără conexiune la internet, respectiv locația acestuia, dacă folosește un dispozitiv mobil.

Consistența datelor

Prin sistemul central de comenzi și notificări, conflictele vor fi rezolvate fie automat de către aplicație, fără intervenția utilizatorului, fie prin notificarea utilizatorului în vederea luării unei decizii. Consistența datelor poate fi realizată prin folosirea unei versiuni la nivel de proprietate din root-aggregate. Indicatorii de timp nu mai sunt necesari, în schimb este esențială trimiterea în ordine cronologică a comenzilor și implicit a evenimentelor.

Soluționarea conflictelor continuă să reprezinte un aspect critic și în această abordare. Totuși există avantajul că acestea pot fi rezolvate consistent și indiferent de modul de lucru: cu sau fără conexiune la internet. Folosirea unui hub de comenzi ne permite de altfel și gruparea/executarea comenzilor în grupuri tranzacționale acolo unde este cazul.

Concluzie

Chiar dacă uneori ne este greu să ne decidem asupra unui model arhitectural atunci când dorim dezvoltarea unei aplicații deconectate ocazional, un aspect important e identificarea problemelor care trebuie rezolvate, apoi scalabilitatea și mentenanța soluției alese. În cazul CQRS, schimbarea paradigmei unui CRUD clasic cu izolarea operațiilor de citire/scriere și menținerea unui singur model, poate fi benefică pe termen mediu/lung.

Conferință TSM

NUMĂRUL 147 - Automotive

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects