Caruceru Cristian Constantin (1) [308504]

[anonimizat]

2015

Tehnologii folosite

C#

C# [anonimizat], [anonimizat]. [anonimizat] .NET, acest limbaj a fost standardizat de către Ecma (European Computer Manufacturers Association) și de către ISO (International Organization of Standardization) și reprezintă unul dintre limbajele de programare ce folosesc CLI (Common Language Infrastructure) din .NET.

CLI este o [anonimizat], fără a schimba codul limbajului inițial. Framework-ul .NET, Mono și Portable.NET conțin astfel de implementări ale CLI.

Pe lângă C#, printre limbajele ce produc cod CLI se numără Visual Basic.NET, F#, J#, C++/CLI, JScript.NET și altele.

Deoarece și C# [anonimizat] (Intermediate Language), echivalentul unui limbaj de asamblare în mediul CLI. În final codul scris în IL este transmis către un compilator JIT (just-in-time) ce îl transformă în cod binar înțeles de procesor.

Avantajele folosirii unei astfel de tehnici pentru compilare sunt acomodarea codului produs de JIT la rulare pentru diferite platforme și procesoare și compilarea și refolosirea doar a codului necesar în fluxul execuției programului.

Compilarea codului de nivel înalt în .NET (sursa)

XAML

XAML vine de la eXtensible Application Markup Language și este limbajul declarativ al Microsoft pentru definirea interfețelor grafice. Acesta oferă o [anonimizat]-obiect pentru dezvoltarea de aplicații cu arhitectura MVC.

[anonimizat], cum ar fi C#, pentru a completa funcționalitatea unui software scris cu XAML.

[anonimizat], Windows Phone și aplicațiile ce folosesc Silveright (tehnologie similară Adobe Flash).

Tot ceea ce se poate scrie cu XAML se poate exprima folosind C#, dar cu o dificultate mult mai mare deoarece codul este mai lung și dificil de înțeles. [anonimizat], C# [anonimizat]-Behind: [anonimizat] C# atașat celui XAML.

Pe același principiu de lucru (un limbaj de definire a interfeței și unul gestionare a logicii) au fost construite și alte limbaje de programare folosite pentru a [anonimizat]:

ASP.NET (Active Server Pages): [anonimizat] C# sau VisualBasic.NET.

JSP (Java Server Pages): o tehnologie dezvoltată de Sun și întreținută de Oracle folosit cu limbajul Java.

Python Server Pages: o [anonimizat].

PL/SQL Server Pages: o extensie a PL/SQL Web Toolkit utilizată pentru a scrie aplicații ce interacționează cu baza de date.

Limbajele prezentate mai sus sunt toate de tipul XML la fel ca XAML (ceea ce duce la o sintaxă asemănătoare între ele) și au fost create special pentru a facilita ușurința programatorului în a scrie aplicații. Diferența majora între XAML și restul limbajelor de mai sus este scopul pentru care sunt create aplicațiile: desktop și mobil pentru XAML și Web pentru restul.

Import.IO

Import.IO este o platformă Web folosită pentru extragerea datelor de pe site-uri web, fără a mai fi necesară scrierea de cod. Punând la dispoziția utilizatorului un tool, acesta poate fi folosit pentru crearea de API-uri (Application Programming Interface – un set de rutine și protocoale) din câteva click-uri. Utilizatorul navighează către pagina de unde dorește să extragă date și, prin evidențierea lor pe pagină, algoritmii de învățare sunt particularizați pe exemplele subliniate de utilizator pentru a colecta date de pe site. Pe urmă, informațiile sunt adunate în serverele puse la dispoziție de Import.IO și pot fi descărcate sub diverse forme, cum ar fi JSON, CSV, Excel.

Un avantaj major al acestei platforme este disponibilitatea ridicată chiar și pentru utilizarea datelor cu un volum mare, pe lângă integrarea ușoară cu alte limbaje de programare.

Principala lor modalitate de preluare a datelor este prin intermediul unui apel HTTP de tipul GET la o adresa generată de ei, odată cu crearea datelor. De exemplu, pentru a afla profesorii din departamentul de informatică, se face un apel la următoarea adresă ce returnează un JSON cu profesorul și email-ul acestuia.

https://api.import.io/store/connector/9437d0b6-d55e-4741-a16c-39dc47d4410b/_query?_user=a7cce6a1-a995-41bd-9149-2b38a6ff07de&_apikey=sFc2s1rAHHuO1LsIbzNSqngYjSo8J0fc8lSdl68Y3KLUz8nkv5OjLP8bBB7VYmxJz1t6lbFdAgu%2BDKE%2Fz%2FW0eQ%3D%3D

XPath

Specificația XPath a fost promulgată de World Wide Web Consortium cu scopul de a simplifica regăsirea datelor într-un conținut bazat pe XML. Cu un software pe baza acestor specificații, XPath oferă un instrument standard și puternic pentru localizarea de informații în documentele XML pe baza structurii arborescente pe care o ele o prezintă.

Deoarece HTML este derivat din XML, XPath se poate aplica și pe paginile scrise în HTML, acționând ca un selector CSS. În cadrul platformei Import.IO, utilizatorul poate opta pentru introducerea manuală a unei expresii XPath pentru selecția datelor, în cazul în care algoritmii de extragere nu sunt destul de preciși.

RSS / Atom

Utilizarea originală, și încă cea mai frecventă, pentru RSS și Atom este de a oferi un flux de conținut sindicalizat (content syndication feed): un fișier consistent, înțeles de calculator, ce permite site-urilor web de a partaja conținutul acestora cu alte aplicații într-un mod standard. Inițial acesta a fost utilizat pentru a partaja date între site-uri web, dar acum este cel mai frecvent utilizat între un site și o aplicație desktop (numită cititor).

Aceste tipuri de feed-uri permit editorilor să publice datele automat. Un format standard de fișier XML este folosit pentru a asigura compatibilitatea pentru mai multe calculatoare și programe. Abonarea la un site ce emite RSS sau Atom elimină necesitatea unui utilizator de a verifica manual un site pentru conținut nou.

Atom este un web feed mai complex decât RSS, fiind creat după apariția lui tocmai pentru a suplini neajunsurile lăsate de RSS:

conținutul unui RSS poate avea text simplu sau HTML având cuvintele cheie eliberate (escaped) fără a exista vre-o indicație care dintre cele două variante este folosit. Atom prevede un mecanism clar de etichetare a conținutului.

RSS comunică informațiile cu privire la data apariției / actualizării după un standard învechit (RFC 822 – 1982) în timp ce Atom folosește unul mai nou (RFC 3339 – 2002).

Atom permite specificarea limbii folosite pentru fiecare fracțiune de conținut lizibil, în timp ce RSS redă o singură limbă folosită în întreg conținutul.

Windows Phone 8.1 SDK

Un SDK (software development kit) este un set de tool-uri de dezvoltare software ce permite crearea unei aplicații pentru un anumit pachet software, un anumit framework, platformă hardware, sistem de operare sau pe o altă platformă software.

Windows Phone 8.1 SDK este un mediu de dezvoltare cu caracteristici complete pentru construirea unei aplicații destinată platformei mobile Windows Phone 8 și 8.1. Acest SDK este construit pe baza CLI, ceea ce înseamnă că aplicațiile pot fi scrise folosind C# și VisualBasic.NET împreună cu XAML.

Printre altele, acest SDK aduce dezvoltatorului un emulator de Windows Phone ce suportă aproape toate modalitățile de interacțiune cu un telefon normal prin acțiuni de tipul multi-touch, rotirea ecranului, simularea conexiunii de date, diverși senzori, etc. Un alt tool foarte important este cel de monitorizare a performanței aplicației, cum ar fi memoria folosită, procentul de utilizare al procesorului, impactul asupra bateriei telefonului.

Newtonsoft Json.NET

Acesta este cea mai populară librărie de manipulare a fișierelor JSON disponibil pentru .NET. Este folosit nu numai pentru citirea și scrierea de fișiere JSON, ci și pentru serializarea obiectelor unei clase (chiar și a cu complexitate structurală mare) în format JSON și invers, crearea unui obiect complex citit dintr-un JSON.

Printre principalele motive pentru popularitatea acestei librării sunt: posibilitatea de a converti între JSON și XML, rapiditatea mare, memoria scăzută în utilizare și timpul alocat de garbage collector-ul din .NET pentru curățarea obiectelor din Json.NET este ameliorat.

Cimbalino Phone Toolkit

Acesta este un set de instrumente ce ajută dezvoltatorii de aplicații Windows Phone să implementeze șablonul de design MVVM (Model, View, ViewModel) plus alte utilități ce facilitează gestionarea unei aplicații Windows Phone. Printre acestea se număra clasa NavigationServices ce aduce o ușurință navigării între paginile aplicației, clasa ViewModelBase folosită drept clasa de bază în MVVM, și diverse metode, clase ajutătoare și convertoare de obiecte.

Rest Sharp

Rest Sharp este un client REST (Representational State Transfer – stil de arhitectură software pentru crearea de servicii web) și API HTTP pentru .NET. Suportă toate tipurile de metode HTTP, autentificare prin diverse protocoale (Basic, OAuth, etc.), deserializarea obiectelor XML și JSON (deși nu este folosită în mod special), detectarea automată a tipului răspunsului, etc.

Motivul pentru care dezvoltatorii integrează această librărie în aplicațiile lor este pentru ușurința sa în crearea unui apel către un serviciu REST / API, față de clasele puse la dispoziție de .NET.

Html Agility Pack

Html Agility Pack este o librărie ce analizează și implementează citirea și scrierea în DOM (Document Object Model – o convenție pentru reprezentarea și interacționarea cu obiecte HTML și XML organizate sub formă de arbore) ce suportă XPath și permite dezvoltatorului să analizeze fișiere HTML "înafara browser-ului". Clasele folosite de această librărie sunt apropiate de cele existente în .NET pentru manipularea XML-ului (din Sytem.Xml) dar adaptate la obiecte HTML.

Ca într-un browser normal, acest produs are implementat un grad de toleranță a erorilor apărute într-un HTML malformat, fiind capabil să rezolve tag-urile nepotrivite, care nu au fost închise corect, atribute scrise greșit, etc. Datorită puterii sale de procesare a fișierelor HTML, mai este folosit și pentru dezvoltarea scrapper-elor, softuri utilizate pentru extragerea automată de date de pe site-uri web.

My Toolkit

La fel ca Cimbalino Phone Toolkit, este o librărie utilă pentru implementarea MVVM și vine cu un set de clase folosite pentru a suprima lipsa sau înlocuirea claselor existente din .NET cu scopul de a ușura munca dezvoltatorului în crearea aplicațiilor de calitate pentru Windows Phone sau Windows Store. Ce aduce în plus față de toolkit-ul prezentat anterior este existența controalelor noi de interfață, mai robuste față de cele existente în .NET.

SharpGIS GZIP Web Client

GZIP Web Client, așa cum îi sugerează și numele, este un mic client web ce suportă comprimarea GZIP(Gnu ZIP – o metodă de compresie a datelor), aceasta nefiind suportată până acum un an pe terminalele Windows Phone, venind în ajutorul multor dezvoltatori ce doreau să transmită date în rețea comprimate conform algoritmului GZIP pentru a salva din pachetele transmise și din timpul de comunicare.

WP Toolkit

Windows Phone Toolkit este un alt toolkit, dar de data aceasta creat special de Microsoft, ce vine în ajutorul dezvoltatorului cu soluții noi de implementare a interfeței unei aplicații folosind XAML, cum ar fi controale pentru selectarea unei date calendaristice, controale pentru manipularea unei hărți, efecte de tranziție noi, etc.

SharpZipLib Portable

Aceasta este o librărie de manipulare a obiectelor compresate Zip (și nu numai) pentru .NET, scrisă de la zero în C#, ceea ce o face portabilă pe orice platformă ce folosește CLI. Pe lângă acest fapt, un alt avantaj în utilizarea ei îl constituie ușurința în utilizare față de clasele ce se află în .NET (System.IO.Compression) concepute pentru același scop.

Openshift

Openshift este o platformă PaaS (Platform as a Service) venită din partea celor de la RedHat și pusă la dispoziția dezvoltatorilor ce doresc să scrie aplicații fără a administra servere pentru ele. Doar cu câteva schimbări în modul în care se dezvoltă aplicația, dezvoltatorul poate pune în picioare un server și o bază de date folosind o comandă de la terminal, ceea ce înseamnă că nu mai este necesară menținerea sistemului de operare la zi, aplicarea de patch-uri aplicației server, menținerea DNS-ului și alte sarcini ce împiedică dezvoltarea codului aplicației.

Pentru a urca aplicațiile pe server, dezvoltatorii folosesc Git, iar acestea pot fi scrise într-o varietate mare de limbaje puse la dispoziție de către Openshift (Java, Python, JavaScript, Ruby, PHP, Perl, etc.). Pe lângă acestea mai sunt tolerate orice fel de aplicație web, atâta timp cât ele pot fi rulate pe RedHat Enterprise Linux, sistemul de operare folosit pe serverele lor.

Openshift se preocupă de menținerea automată serviciilor de care aplicația web depinde, actualizări de securitate, și de scalarea ei dacă este necesară. Printre acestea, o aplicație web poate avea asociată și o bază de date relațională (PostgreSQL, MySql) sau nerelațională (MongoDB).

Git

O unealtă care gestionează și depistează diferite versiuni de software sau orice fel de conținut este referit în mod generic drept un sistem de versionare. Git este un instrument de control al versiunii deosebit de puternic, flexibil, cu costuri mici, care face dezvoltarea în colaborare cu alți dezvoltatori mai ușoară. Git a fost inventat pentru a susține dezvoltarea kernel-ului de Linux, și de atunci s-a dovedit a fi o unealtă utilă în dezvoltarea proiectelor de diferite tipuri.

Un proiect gestionat cu Git este organizat sub formă de repertoriu (repository – o structură de date ce stochează metadate despre istoricul fișierelor) cu istoricul menținut complet de la prima creare a unui fișier și capacitate de a depista o versiune/schimbare a fișierelor, fără a fi dependent de rețeaua în care se află calculatorul, sau de un server central.

Din punctul de vedere al salvării informațiilor, există o asemănare majoră între Git și un sistem de gestiune al bazei de date, și anume noțiunea de commit. În ambele cazuri, commit-ul marchează permanentizarea unui set de tentative de schimbări.

Printre funcționalitățile sale, se numără și posibilitatea divizării codului în versiuni diferite (branch) pe care dezvoltatorii pot să lucreze separat la o caracteristică nouă, ca mai apoi să integreze munca obținută sub același fișier (operație numită merge).

Bineînțeles, există și opțiunea de revenire la o anumită versiune, în cazul în care dezvoltatorul a făcut greșeli sau se renunță la o funcționalitate a softului, dezvoltarea a mers într-o direcție greșită, etc. Această operație se cheamă reset și este asemănătoare celei de rollback dintr-un sistem de gestiune al bazei de date cu diferența că un reset poate avea loc pentru orice versiune a fișierului în cauză până la versiunea sa inițială.

Diferite versiuni ale unui fisier ale atat local cat si pe server (sursa Ronald Wihda)

SWFTools

SWFTools este o suită de software open-source creată pentru manipularea fișierelor SWF. Un fișier SWF (small web format) este un fișier de tip Adobe Flash (platformă software folosită la crearea de animații, grafică vectorială și aplicații pentru Internet complexe) ce poate avea conținut multimedia, toate acestea fiind gestionate de un cod scris în ActionScript (limbaj de programare asemănător JavaScript, dezvoltat de Adobe).

Un tool important adus de acest pachet îl constituie swfrender, un software scris în C, folosit pentru a reda sub formă de imagine PNG (Portable Network Graphics) un cadru (frame) dintr-un fișier SWF.

Tesseract

Considerat cel mai bun software open-source din domeniul său, Tesseract este un motor de recunoaștere a caracterelor folosit pe diverse sisteme de operare și dispozitive hardware cu suport pentru recunoașterea caracterelor din diferite limbi, printre care și română.

Fiind open-source, acest software nu are o dezvoltare concretă, el fiind în continuare menținut datorită sponsorizărilor din partea firmei Google, în principal datorită folosirii acestuia în motorul lor de căutare a imaginilor.

Acest software nu are o interfață cu utilizatorul, comenzile cu acesta având loc de la consolă. Pe baza acestuia, s-au scris multe alte softuri de recunoaștere a caracterelor precum FreeOCR, OCRFeeder, VietOCR, gImageReader, etc.

Diferite înăltimi și linii ale unui text(sursa Wikipedia)

Față de alte motoare de tip OCR (optical character recognition) comerciale (ABBY FineReader, OmniPage, AspriseOCR, etc.) acesta are nevoie ca imaginea dată la intrare să fie preprocesată astfel încât luminozitatea imaginii să fie uniformă, umbrele foarte închise la culoare să dispară deoarece pot fi interpretate greșit ca și caractere, iar înălțimea x (x-height) să fie de minim 20 de pixeli (în tipografie, x-height reprezintă înălțimea dintre baza literelor și marginea superioară a literei mici).

Python

Este un limbaj de programare de uz general ce îmbină paradigmele procedural, funcțional, și orientat pe obiect și este și un limbaj de scriptare, ceea ce înseamnă că are nevoie de un interpretor pentru rularea codului. Pe lângă acestea, este open-source și beneficiază de o dezvoltare continuă din partea comunității ce susține limbajul prin rezolvarea problemelor și evoluarea lui.

Python aduce un sistem de tipuri dinamic foarte bine definit (în Python nu se declară tipul unei variabile) astfel încât, în comparație cu JavaScript, acesta nu permite rularea codului ce implică operații între două obiecte de tipuri diferite fără a semnala o eroare la execuție. De exemplu, dacă se încearcă evaluarea următorului cod: 3+"x" în JavaScript, va rezulta un string "3x", în timp ce în Python această operație va rezulta printr-o excepție deoarece nu este definită adunarea între string și număr întreg.

Diferența majora dintre un sistem de tipuri dinamic și unul static este că în cel dinamic variabilele sunt doar niște nume asociate unor valori de un anumit tip (valorile au un tip), iar în cel din urmă variabilele au tipul lor și nu pot fi reasignate valori cu tip diferit. Un alt aspect important de discutat este momentul în care se decide că un tip nu este bine folosit în contextul unui program. Python aruncă o excepție de tipuri în momentul rulării programului, în timp ce C#/Java detectează eroarea în momentul compilării, nefiind necesară execuția programului pentru verificarea corectitudinii.

Ca orice alt limbaj din ziua de zi, Python aduce și un sistem de gestiune a memoriei automat, un avantaj față de C/C++ unde memoria este gestionată de dezvoltator. Codul scris în acest limbaj este unul interpretat, ceea ce duce la necesitatea instalării unui interpretor dar, datorită existenței unor tool-uri terțe părți, se poate exporta codul scris în Python ca executabile de sine stătătoare pentru diverse sisteme de operare și arhitecturi hardware.

Principala implementare a limbajului Python este CPython, un interpretor scris în C conform standardului C90. Acesta este distribuit cu un număr mare de librării scrise în C sau Python și este disponibil pe mai multe platforme (inclusiv Windows și UNIX) fiind gândit să fie multi-platformă (cross-platform).

Wand for Python

Este o librărie de Python scrisă în CPython ce se ocupă de manipularea imaginilor folosind drept suport cunoscutul software de editare/conversie de imagini ImageMagick.

Ceea ce aduce în plus față de alte librării de imagistica (ce au sau nu la bază ImageMagick) este documentația din partea dezvoltatorului bine structurată, suportul pentru noile versiuni de Python și ușurința în utilizare.

Java

Java este un limbaj de programare de nivel înalt, orientat pe obiecte, cu o sintaxă similară cu cea a limbajului C. Scriitorii limbajului Java sau străduit să creeze un mediu de dezvoltare puternic și în același timp fără particularități prea complexe împrumutate din alte limbaje ce le erau greu de implementat în practică, cum ar fi C++. Având o sintaxă simplă cu caracteristici de ultimă generație, dezvoltatorii scriu ușor cod robust și fără erori, ceea ce îl face foarte popular în rândul programatorilor.

O aplicație Java este compilată într-un cod de asamblare (bytecode) ce se poate rula doar pe mașina virtuala Java, așa cum un program scris în C poate fi compilat în cod de asamblare pentru procesorul mașinii. O instrucțiune JVM (Java virtual machine) are de obicei un opcode (codul operației) format dintr-un singur byte, iar din cele 256 de instrucțiuni posibile 198 sunt folosite în prezent, iar restul sunt rezervate pentru implementări ale unor instrucțiuni viitoare.

În ziua de azi, Java este cel mai răspândit limbaj de programare când vine vorba de aplicații client-server, multe framework-uri de aplicații web fiind făcute în Java (Spring, JSF – Java Sever Faces, Google Web Toolkit, Apache Struts, etc.). Pe lângă acestea, au fost scrise și multe aplicații server folosind Java EE (Enterprise Edition) ce înglobează un set de pachete Java care facilitează crearea de servicii web, cum ar fi Tomcat, JBoss, Jetty, iPlanet Web Server, etc..

Principalul limbaj competitor pentru Java este C# deoarece ele sunt foarte asemănătoare ca sintaxă. Diferențele dintre cele două limbaje înclin în favoarea C# (existența pointerilor, programarea funcțională, existența referințelor, legarea târzie – late-binding -, etc…) dar datorită interoperabilității pe mai multe platforme, Java a câștigat teren în favoarea C#.

Compilarea codului Java (sursa Stack Overflow)

JBoss

JBoss este o aplicație server scrisă în Java ce se axează pe nivelul scăzut de memorie folosită, cu un impact minor asupra garbage collector-ului și a aplicației și cu o pornire rapidă a serverului de la zero. Acesta suportă scalabilitatea aplicației, distribuirea ei, punând la dispoziție întreg API-ul Java EE (Enterprise Edition), printre care și suport pentru librării cunoscute precum Hibernate (folosit pentru asocierea obiectelor unei clase cu un tabel al unei baze de date relaționale), Infinispan (lucru asemănător Hibernate, numai că folosește baze de date nerelaționale).

O trăsătură importantă a acestei aplicații este ascunderea implementării serverului față codul scris de dezvoltator și astfel, softul este dezvoltat în izolare față de clasele scrise pentru funcționarea serverului. Pe lângă acestea, JBoss are un sistem de gestiune a pachetelor jar (Java archive) mai optimizat față de competitorii lui, fiind încărcate în memorie doar strictul necesar folosit de aplicația scrisă de programator.

Joda Time

Joda Time este o librărie Java ce aduce un înlocuitor superior a claselor predefinite Java în legătură cu gestionarea timpului și calculele/aritmetica pentru datele calendaristice.

Din cauza inexactității și a metodelor marcate drept învechite din clasele Date și Calendar din pachetul java.util, această librărie a devenit principala modalitate folosită de dezvoltatori pentru a lucra cu date calendaristice atunci când dezvoltă aplicații pentru Java 7. Odată cu apariția Java 8, Oracle a inclus un pachet nou (java.time) ce definește corect regulile de manipulare a datelor calendaristice și calculele pe unități de timp.

Maven

Convenția înaintea configurării este un concept simplu în care sistemele, librăriile și framework-urile asumă niște setări implicite rezonabile fără a mai solicita configurări inutile pentru funcționarea corectă a lor. Maven este un software de gestionare a proiectelor ce încorporează acest concept și înglobează mai multe unelte de build pentru a ușura munca dezvoltatorului în crearea proiectului, testarea și livrarea lui. Pe lângă acestea, Maven este capabil de a gestiona dependințele mai multor proiecte între ele, dar și dependințe externe cum ar fi librării produse de terțe părți.

Acest software folosește un server central (numit Maven Central Repository) de unde fiecare proiect existent își ia dependințele (librării Java având orice versiune) și le instalează pe calculator, astfel eliminând necesitatea dezvoltatorului de a configura manual proiectele și a include diverse jar-uri / clase în procesul de building.

Orice dezvoltator poate contribui la Maven Central Repository cu proiecte făcute de aceștia, cu condiția să treacă de cerințele impuse pentru asigurarea calității. Maven oferă informații utile pentru proiect care sunt în mare parte luate din POM (Project Object Model), un fișier XML ce conține informațiile de configurare a unui proiect, cum ar fi numele, proprietarul, dependințele. Tot în acest fișier sunt scriși diverși pași ai procesului de build, pași ce sunt implementați de către plugin-uri pentru Maven (de exemplu există plugin pentru compilare, unul pentru testare, altul pentru instalare, etc.).

Structura unui proiect Maven (sursa Wikipedia)

Apache Commons Codec

Commons Codec este o librărie Java produsă sub tutela Apache ce are conține implementarea a diverși algoritmi de codare și decodare a string-urilor cum sunt Base32, Base64, Hex, Soundex, Metaphone, etc.

Această librărie este folosită în special pentru implementarea făcută a algoritmului Base64, un algoritm de codare a unui șir binar sub formă de caractere text. Necesitatea apariției ei a fost impusă de faptul că într-un timp existau aproximativ 34 de clase Java ce se ocupau de acest lucru, fiecare abordând diferit problema codării și a decodării cu o ușoară abatere de la standard.

JAX-RS

Scrierea serviciilor REST (Representational State Transfer) în Java a fost posibilă de multă vreme folosind API-ul servleților deoarece aceștia sunt apropiați de protocolul HTTP, folosit de obicei în tandem cu REST, dar aceștia necesitau foarte mult cod pentru a manipula informațiile cu cereri HTTP. În 2008 a apărut JAX-RS, un framework creat pentru a simplifica scrierea acestor tipuri de servicii.

JAX-RS este livrat separat ca o librărie sau vine la pachet odată cu instalarea Java 6 / 7 EE (Enterprise Edition) și se folosește de adnotări, o modalitate de a adăuga unor clase și metode metadate introdusă în Java 5, pentru a simplifica dezvoltarea și lansarea serviciilor web. În final, pentru a face un serviciu web de tip REST, tot ce are un dezvoltator nevoie este de includerea pachetului JAX-RS în proiect și crearea unei clase ce conține diverse metode pentru manipularea metodelor HTTP GET, POST, ș.a., nemaifiind necesară crearea (instanțierea) ei, aceasta făcându-se automat de către serverul Java pe care rulează aplicația.

Quartz Scheduler

Quartz este o librărie open-source cu multe caracteristici menită să gestioneze taskuri (joburi – în sensul de acțiune repetitivă) prin crearea de planificatoare, capabilă de a fi integrată de la cea mai mică aplicație Java de sine stătătoare până la un sistem business mare.

Poate fi folosit pentru a crea planificatoare simple sau complexe unde se pot executa de la una până la câteva sute de joburi a cărui conținut pot realiza orice se poate în Java, fără a se impune restricții asupra conținutului codului.

Quartz este folosit în special de programatori când aceștia au nevoie ca în aplicația lor să se execute un task după un anumit timp sau la intervale fixe de timp. Diferența dintre Quartz și interfața ScheduledExecutorService (standard Java) constă într-o gestionare mai bună resurselor și eficacitate mare în cazul executării mai multor joburi în același timp.

GZIPOutputStream

Aceasta este o clasă regăsită în pachetul java.util.zip apărută pentru prima oara în Java 6 ce implementează un flux (stream) de octeți pentru scrierea datelor compresate sub formatul GZIP (Gnu ZIP). Formatul GZIP este utilizat mai ales în cazul transmiterii datelor compresate în rețea pentru a economisi cât mai multe din pachetele transmise și pentru a crește viteza transmiterii unei informații.

Uptime Robot

Uptime Robot este un serviciu web gratuit ce permite utilizatorilor să monitorizeze starea de funcționare a unui server prin trimiterea de cereri HTTP, verificarea existenței IP-ului sau verificarea existenței unui port deschis. În momentul în care se află că serverul este oprit (din diverse motive precum erori de cod, fenomene fizice sau rețeaua nu mai funcționează / nu mai e conectată la internet) se notifică utilizatorul prin trimiterea unui email ce conține informații precum codul de eroare trimis ca răspuns și de cât timp se află serverul în stare nefuncțională.

Utilizatorul poate seta intervalul de monitorizare, de la o frecvență de 5 minute până la 2 ore. În momentul în care se detectează un cod de eroare primit, serviciul retrimite cereri către server în următoarele 30 de secunde, dar de data aceasta într-un mod distribuit (din mai multe locații) pentru a diminua șansele unor răspunsuri fals-pozitive.

Funcționarea serviciului UptimeRobot

Teorie

Structuri de date

O structură de date este o organizare de informații, de obicei în memorie, pentru o mai bună eficiență în utilizarea algoritmilor, cum ar fi coada, stiva, lista liniară, heap-ul, dicționarul și arborele, sau o unitate conceptuală, cum ar fi numele și adresa unei persoane. Aceasta poate include informații redundante, cum ar fi lungimea listei sau numărul de noduri în subarbore.

Lista

O listă este o structură de date în care obiectele sunt aranjate într-o ordine liniară. Spre deosebire de o matrice, în care ordinea liniară este determinată de indicii matricei, ordinea într-o listă este determinată de un pointer la fiecare obiect. Listele oferă o reprezentare simplă, flexibilă pentru seturi dinamice de date.

Cele mai răspândite structuri de tip listă sunt listele circulare dublu înlănțuite și vectori listă (ArrayList). O listă circulară dublu înlănțuită memorează trei elemente pe o poziție a ei; una este valoarea ce a fost inserată, iar celelalte două sunt pointeri (adrese de memorie) către elementul următor și precedent al listei. În lista circulară dublu înlănțuită ultimul element are drept succesor pe primul și invers, primul element are drept predecesor pe ultimul. Acest tip de listă mai conține câte un pointer ce adresează începutul și un unul ce adresează sfârșitul listei.

Lista circulară dublu înlănțuită (sursa Yaldex)

Vector listă

Un vector listă este o implementare diferită a conceptului de listă cu diferențe majore față de lista liniară simplu înlănțuită. Ea are în spate un vector (o zonă de memorie contiguă) ce conține pointeri către fiecare element al listei.

Asemănarea dintre cele două concepte de liste este faptul că elementele sale nu se află neapărat într-o zonă de memorie contiguă, ceea ce duce la o mai bună organizare a memoriei prin diminuarea fenomenului de fragmentare a acesteia.

Din punct de vedere al performanței, ambele tipuri de structură de date se compensează una pe alta când vine vorba de cele trei tipuri de operații primordiale: ștergere, adăugare și acces.

Din tabelul de mai jos, se deduce că lista circulară se comporta mai bine la inserarea repetată de date, în timp ce un vector listă este gândit pentru accesarea repetată a datelor.

Tabel performanțe vector listă și lista circulară dublu înlănțuită

Tabele de dispersie

O funcție hash este o funcție a cărui domeniu conține date de dimensiune oarecare și a cărui codomeniu conține date de dimensiune fixată. O astfel de funcție face o asociere a unei date din calculator cu un element din codomeniul ei, numit hash.

O funcție de hashing bună satisface (aproximativ) prezumpția de funcție hashing uniformă, unde fiecare cheie are aceeași probabilitate să indice către oricare dintre cele n poziții ale unui vector, independent de pozițiile la care celelalte chei au marcat.

Un tabel de dispersie este o generalizare a noțiunii de vector simplu, cu diferența că se folosește de o funcție de hashing pentru calcularea indexului unui element din vector pornind de la cheie, ce poate fi un număr, un șir de caractere sau un obiect de nivel înalt.

În general costul mediu pentru operațiile elementare (inserare, acces, ștergere) aplicate asupra unui element într-un tabel asociativ este independent de numărul de elemente din el, și este de aproximativ O(1).

La acest tip de structură de date apare un fenomen neconvenabil numit coliziune, ce constă în faptul că pornind de la două chei distincte se poate calcula prin intermediul funcției de hash același index. De aceea tabelele de dispersie pot avea în componență structuri de tip liste pentru a adăuga mai multe valori cu același hash pe aceeași poziție în vector.

Exemplu de tablou de dispersie(sursa Wikipedia)

Modelul OSI

Acest este un model conceptual ce definește modul în care un sistem ar trebui să comunice cu altul, prin intermediul a mai multor straturi de comunicare, folosind diferite protocoale definite în fiecare strat al său. Fiecare strat are desemnată o parte bine definită a sistemului de comunicare, de exemplu stratul fizic definește toate componentele de natură fizică (fire, frecvențe, coduri de impulsuri, tensiunea transmiterii, etc.) a unui sistem de comunicație.

Modelul OSI (Open Systems Interconnection) are următoarele nivele (straturi) dispuse în următoarea ordine: fizic, legătură de date, rețea, transport, sesiune, prezentare, aplicație. Nivelul aplicație este locul unde aplicația utilizatorului se află și care are nevoie de transferul datelor între calculatoare sau printre ele. Stratul prezentare ajută să fie înțeleasă reprezentarea datelor într-o formă de pe o mașină pe alta mașină într-o reprezentare nativă a ei.

În sesiune, sunt definite capabilități de gestionare a sesiunii între calculatoare (de menținere a conexiunii pe baza unui cod de acces), iar în nivelul transport este asigurată transmiterea datelor între calculatoare de la un capăt la celălalt. Cât despre stratul rețea, acesta ajută la identificarea în mod unic a calculatoarelor din subrețele și definește calea pe care pachetele o vor urma sau vor fi dirijate pentru a ajunge la destinație.

Nivelul legătură de rețea preia datele de transmisie și alcătuiește cadre de octeți pe care le transmite nivelului fizic. Acest strat verifică și rezolvă orice erori de transmisie apărute. Ultimul strat, cel fizic, se ocupă de tehnologia hardware și mecanismul real de comunicare, cum ar fi semnalizarea, tensiunea, cablul și lungimea lui, etc.

Comunicarea între straturi se face după următoarea regulă: la primirea unei informații, stratul inferior raportează celui superior următor datele primite și eventualele erori apărute în comunicare (de la nivelul fizic către cel aplicație), iar în cazul transmiterii de date se procedează în sens invers, stratul superior transmite pe rând informații celui imediat inferior până se ajunge la cel fizic unde are loc transmiterea efectivă.

Protocolul HTTP

HTTP (Hypertext Transfer Protocol) este un protocol de tip cerere–răspuns simplu care rulează în mod normal peste TCP (Transmission Control Protocol). Aceasta specifică ce mesaje pot trimite clienții către servere și ce răspunsuri se întorc în schimb. Anteturile unei cereri și a unui răspuns sunt alcătuite din caractere ASCII, iar conținutul este dat într-un format MIME (o extensie a protocolului de email ce definește diferite tipuri de conținut). Acest model simplu a accelerat succesul Web-ului, deoarece a făcut dezvoltarea și implementarea lui mai simplă.

De exemplu, un browser web poate acționa drept client și o aplicație care rulează pe un calculator ce găzduiește un site web poate fi drept server. Serverul oferă resurse cum ar fi fișierele HTML și nu numai, iar clientul transmite o cerere HTTP către server și el îi returnează un mesaj de răspuns către client. Răspunsul conține un status informativ despre cerere și poate conține, de asemenea, conținutul solicitat în corpul mesajului.

HTTP definește câteva metode pentru a indica acțiunea dorită a fi aplicată asupra unei resurse. Principalele metode sunt GET, PUT, POST și DELETE, iar mai puțin cunoscute sunt PATCH, TRACE, CONNECT, HEAD și OPTIONS.

Metodele GET, HEAD, TRACE și OPTIONS sunt convenite a fi sigure din punctul de vedere al stării serverului deoarece acestea sunt concepute doar pentru a regăsi informații și nu îi alterează starea internă, spre deosebire de restul metodelor ce sunt destinate producerii unor acțiuni ce au un efect secundar (cum ar fi o tranzacție bancară sau trimiterea unui email).

Modelul OSI împreună cu protocoalele HTTP și TCP/IP (sursa programming notes)

REST

REST (Representational State Transfer) este un set de reguli și practici rentabile ce desemnează o cale simplă, interoperabilă și flexibilă în scrierea unui serviciu web și proiectării componentelor unui sistem de comunicare distribuit, ce poate duce la o arhitectură mai performantă, ușor de întreținut și scalabilă. Scalabilitatea este abilitatea unui sistem de ași crește capacitatea de lucru odată cu creșterea cererilor supuse sistemului.

Sistemele de tip REST de obicei comunică prin protocolul HTTP folosind tipurile de cerere puse la dispoziție de HTTP (GET, POST, PUT, etc.) utilizate de browser-e web pentru comunicarea cu pagini web și trimiterea de date către servere la distanță.

Stilul arhitectural REST a fost dezvoltat de către World Wide Web Consortium (W3C) odată cu versiunea 1.1 a protocolului HTTP. Internetul (world wide web), așa cum îl știm în ziua de azi, reprezintă cel mai mare sistem ce respectă principiile impuse de REST.

Administrarea datelor prin REST (sursa Sales Force)

SSH

SSH, Secure Shell, este o abordare populară, puternică, bazată pe software în cadrul securității în rețea. Ori de câte ori datele sunt trimise de un computer în rețea, SSH le criptează automat iar atunci când datele ajung la destinatarul propus, SSH le decriptează automat. Rezultatul este o criptare transparentă: utilizatorii pot lucra în mod normal, fără să știe că transmisiile sunt criptate în siguranță pe rețea. În plus, SSH folosește algoritmi de criptare moderni și siguri și este suficient de eficient pentru a fi găsit în aplicațiile critice din cadrul marilor corporații.

Acest protocol se plasează pe stratul 7 în structura modelului OSI (nivelul aplicație) și permite unui utilizator să ruleze comenzi la o linie de comandă pe o mașină fără a fi prezent fizic sau în apropierea mașinii și de asemenea, este capabil de a stabili un canal securizat de comunicare într-o rețea nesigură.

Criptografia asimetrică stă la baza principiului de funcționare al SSH, unde sunt nevoie de două chei pentru transmiterea datelor, una publică pentru criptare și alta privată pentru decriptare. Cheia publică este folosită pentru a cripta mesajul clar sau pentru a verifica o semnătură digitală iar cheia privată este utilizată pentru a decripta textul criptat sau pentru a crea o semnătură digitală.

SSH este un protocol care poate fi utilizat pentru multe aplicații pe diverse platforme, în sisteme de tip Unix precum și Microsoft Windows. Cele Unix conțin preinstalate programul ce poartă același nume ca și protocolul, folosit pentru conectarea la un calculator aflat la distanță pentru a executa comenzi pe el. În cadrul sistemelor de tip Windows, este necesară instalarea unei aplicații dedicate (precum Putty), întrucât ele nu livrează un utilitar pentru utilizarea protocolului.

Cloud Computing

Cloud Computing este un model ce permite accesul convenabil omniprezent și instant la rețea către o colecție partajată a resurselor de calcul configurabile (de exemplu rețele, servere, medii de stocare, aplicații și servicii), care pot fi prevăzute și lansate rapid cu un efort minim de administrare fără a fi necesară interacțiunea cu furnizorul de servicii cloud.

Principalele caracteristici pe care o platformă cloud le expune sunt: scalabilitate, securitatea, integritatea datelor, eficiența, întreținerea ușoară, disponibilitate și costul redus. Furnizorii de cloud computing își oferă serviciile sub forma a mai multor modele fundamentale: IaaS, PaaS, SaaS.

IaaS (infrastructure as a service) oferă calculatoare fizice, sau cel mai des mașini virtuale și alte resurse. Pentru ași implementa aplicațiile lor, dezvoltatorii vor instala sistemul de operare dorit și aplicațiile lor software pe infrastructura cloud, acesta fiind nivelul cel mai fundamental de serviciu de tip cloud.

PaaS (platform as a service) livrează în platforma cloud de obicei un sistem de operare, un mediu de execuție pentru un limbaj de programare gata instalat, bază de date și serverul web, lăsând dezvoltatorul doar să-și creeze și să ruleze aplicațiile lui pe o platformă de cloud fără a avea grija cumpărării și gestionării a deferitelor materii hardware și software care stau la bază.

SaaS (software as a service) furnizează utilizatorilor acces la software gata făcut și baze de date fără a fi necesară administrarea infrastructurii cloud și platforma unde rulează aplicația. Aceasta simplifică mult întreținerea și suportul față de celelalte tipuri de mai sus și elimină necesitatea de a instala și rula aplicația pe calculatoarele utilizatorilor, la fel ca IaaS și PaaS.

Organizarea modelelor fundamentale de cloud (sursa qarea)

Virtualizare

În informatică, un emulator este o componenta hardware sau software ce permite unei mașini (numită gazdă) să se comporte ca o altă mașină (numită vizitator). Un emulator în general permite sistemului gazdă să ruleze software sau să folosească dispozitive periferice destinate pentru sistemul vizitator. O mașină virtuală reprezintă instanță a unei astfel de emulări a unui calculator și funcționează ca și cum ar avea arhitectura și funcțiile unui calculator real.

În funcție de gradul de virtualizare (cât de bine sunt implementate caracteristicile unei mașini reale), mașinile virtuale pot fi complete sau sub formă de proces. Mașinile virtual complete asigură un substitut complet pentru mașina reală vizată și un nivel de funcționalitate total pentru executarea unui sistem de operare complet. Pe de altă parte, procesele virtuale sunt concepute pentru a executa un singur program de calculator prin asigurarea unui mediu de execuție abstract și independent de platformă.

Există diferite tehnici de virtualizare folosite, în funcție de utilizarea dorită. Acestea sunt execuția nativă, emularea sau virtualizarea la nivel de sistem de operare. Execuția nativă se bazează pe virtualizarea directă a hardware-ului de la bază, asigurând astfel mai multe "instanțe" ale aceleași arhitecturi pe care mașina se bazează, capabile să ruleze un sistem de operare complet.

Exemplu de virtualizare la nivel de Sistem de Operare (sursa Right Scale)

Mașinile virtuale pot efectua, de asemenea, rolul de emulator care permite unei aplicații software sau a unui sistem de operare să fie rulat chiar dacă a fost scris pentru o altă arhitectură de procesor față de mașina gazda.

Virtualizarea la nivelul sistemului de operare este o tehnologie de virtualizare folosită pentru servere, care virtualizează unul sau mai multe servere pe un sistem de operare. Aceasta poate fi gândită ca o partiționare a unui server fizic în mai multe partiții mici și fiecare astfel de partiție acționează ca un server unitar din punctul de vedere al utilizatorilor săi.

Concurență

Scrierea unei aplicații ce utilizează nuclee adiționale ale unui procesor pentru a executa porțiuni de cod (cu scopul de a efectua multe sarcini) a căror calcule sunt independente unele față de celelalte este cunoscută drept programare concurentă. O aplicație concurentă are una sau mai multe fire de execuție în progres la un moment dat ce accesează mai multe resurse comune, în comparație cu o aplicație paralelă ce suportă mai multe acțiuni executate în același timp simultan, nedepinzând unele de altele.

Deoarece procesele într-un sistem concurent pot interacționa unele cu altele în timp ce acestea sunt de executare, numărul de posibile căi de execuție poate fi extrem de mare, iar un rezultat exact se află doar în mod nedeterminist. Utilizarea concomitentă a resurselor partajate de mai multe procese poate fi o sursă de nedeterminism care duce la probleme precum blocajul (deadlock-ul).

Un deadlock este o situație în care două sau mai multe acțiuni concurente se așteaptă unul pe altul să se termine, și astfel niciunul nu se încheie vreodată. De exemplu, într-un sistem de operare, un deadlock apare atunci când un proces intră într-o stare de așteptare deoarece o resursă solicitată (fișier, zonă de memorie, etc.) este deținută de un alt proces, care la rândul său este în așteptare pentru o altă resursă deținută de un alt proces, și tot așa. În cazul detectării unui astfel de fenomen, sistemul de operare poate alege să închidă unul dintre procesele blocante și să îl repornească pentru a nu împiedica funcționarea proceselor utilizatorului.

Cel mai simplu și ușor de implementat algoritm pentru evitarea blocajelor este Round-Robin. Acesta este unul dintre algoritmii utilizați pentru planificarea proceselor unde intervale de timp egale sunt atribuite pentru fiecare operațiune în parte, în mod circular, astfel încât fiecare proces are aceeași prioritate.

Procese executate în mod Round-Robin cu o perioadă maximă de execuție de 2 ms (sursa University of Edinburgh)

Automate finite deterministe

Computerele sunt de fapt mașini deterministe, adică pentru o anumită intrare se ajunge sigur la o ieșire, fie dorită sau nedorită. Un automat este un model abstract de calculator digital ce are capacitatea de a-și citi intrările de la o bandă de intrare. Un automat poate recunoaște anumite limbaje, și prin urmare aceste modele sunt de fapt acceptori de limbaje sau identificatori de limbaje.

Automatul finit lucrează cu stări și tranziții. O stare este o descriere a situației unui sistem care așteaptă să execute o tranziție, iar o tranziție este un set de acțiuni executate atunci când o condiție este îndeplinită sau un eveniment este primit. Automatul poate avea la un moment dat o singură stare și din acea stare cu ajutorul unei tranziții, se poate trece în alta asigurând o funcționare continuă a întreg sistemului. Acest mecanism se numește finit deoarece execuția acestuia se desfășoară pe o perioadă determinată de timp, în funcție lungimea intrării lui.

O particularitate a automatului finit o reprezintă automatul finit determinist care dintr-o pereche de stare și tranziție poate să își schimbe starea într-una singură și numai una.

Pe lângă stări și tranziții, un automat finit determinist conține o mulțime de simboluri numit alfabetul automatului, o stare inițială de unde se începe execuția și o mulțime de stări finale în care automatul își poate încheia execuția cu succes. Elementele alfabetului reprezintă modalitatea prin care se poate trece de la o stare la alta pe baza celei curente. De aceea tranzițiile sunt reprezentate ca o funcție de la mulțimea perechilor stare – simbol către o nouă stare.

Pentru recunoașterea unui fișier de tip JSON, este necesar un automat care să îi recunoască limbajul cu ajutorul stărilor finale prin care se ajunge, procesând pe rând câte un caracter din sursa de date. Automatul este necesar, dar nu și suficient, însă constituie o bază bună pentru implementarea unui analizor lexical și semantic ce returnează informațiile cuprinse într-un fișier JSON.

Set de automate finite deterministe pentru recunoașterea unui JSON (sursa json.org)

Expresii regulate

O expresie regulată este o modalitate eficace și naturală de a reprezenta un limbaj, iar orice limbaj ce este acceptat de o expresie regulată sau automat finit poartă denumirea de limbaj regulat. Un astfel de mijloc de reprezentare a unui limbaj este foarte util în a demonstra dacă un anumit șir de caractere se regăsește într-un limbaj.

Expresiile regulate sunt foarte utile în informatică iar diferite sisteme (programe) pentru specificarea expresiilor regulate au evoluat pentru a oferi atât standardul de bază cât și o extindere a lor pentru gramatică și sintaxă. Procesoare de expresii regulate se găsesc în multe editoare de text, motoare de căutare și dialoguri ale aplicațiilor de căutare și înlocuire text.

Pentru construirea unei expresii regulate, este necesară definirea următoarelor constante: mulțimea vidă (Â), caracterul vid (λ) și caracterele peste un alfabet Σ. Acestea se consideră a fi pentru început expresii regulate și, cu ajutorul acestora, se definesc următoarele operații peste o expresie regulată ce returnează altă expresie regulată: concatenarea (), reuniunea () și iterația Kleene ().

În modelarea unei expresii regulate, cea mai bună soluție este folosirea unui automat ce recunoaște același limbaj ca și expresia regulată. De exemplu, pentru recunoașterea limbajului , următorul automat finit poate fi folosit:

Limbaje interpretate

Un limbaj interpretat este un limbaj de programare pentru care cele mai multe dintre instrucțiunile sale sunt executate direct, fără a compila în prealabil un program cu instrucțiuni scrise în limbaj cod-mașină. Un interpretor este folosit pentru a executa programul direct, translatând fiecare linie de cod într-o secvență de unul sau mai multe subrutine deja compilate.

Un limbaj interpretat are drept avantaje independența platformei hardware, cod sursă mult mai mic (din moment ce se poate decide setul de instrucțiuni pentru procesor la compilare), tipuri dinamice (abilitatea de a verifica la execuția programului tipul unui obiect – RTTI) și reflecție (abilitatea de a modifica la execuția programului structura unui obiect – reflection).

O alternativă mai bună pentru astfel de limbaje le constituie cele ce folosesc un compilator hibrid, care combină compilarea și interpretarea. În acest caz, un compilator pentru un astfel de limbaj produce la ieșire o formă de limbaj intermediar ce poate fi compilat ulterior de interpretorul limbajului intermediar. Astfel de limbaje existente ce se bazează pe acest procedeu sunt Java, Python și C#.

Tabel performanțe pentru diferite limbaje compilate, hibride și interpretate (sursa AtractiveChaos)

Principalul dezavantaj al limbajelor interpretate o reprezintă o viteză mult mai scăzută a execuției programului, comparativ cu executarea de cod-mașină direct pe procesorul calculatorului. O tehnică folosită pentru a îmbunătăți performanța folosită de compilatoarele hibride este compilarea imediată (just-in-time) care, în principiu, convertește instrucțiuni interpretate întâlnite frecvent în secvențe de instrucțiuni ale procesorului.

GZip

Algoritmi de compresie a datelor sunt folosiți pentru a reduce numărul de biți necesari pentru a reprezenta o imagine, video, text sau alte formate de fișiere într-o formă compactă. Aceste reprezentări sunt create prin identificarea și utilizarea unor structuri predefinite care există în date. Motivul pentru care este necesară compresia datelor este că din ce în ce mai multe din informațiile pe care le generăm și utilizăm sunt în formă digitală și pot deveni foarte mari. De exemplu, pentru a reprezenta digital o secundă de film, fără compresie, este nevoie între 20 și 160 MB.

Compresia este utilă în reducerea utilizării resurselor, cum ar fi spațiul de stocare a datelor sau capacitatea de transport în rețea. Deoarece datele comprimate trebuie să fie decomprimate pentru a fi utilizabile, această prelucrare suplimentară impune putere de calcul în plus și probabil costuri mai mari, de aceea algoritmii folosiți în compresie trebuie să fie eficienți.

GZIP este un algoritm de compresie generic ce se aplica pe un flux de octeți, și are la bază algoritmul DEFLATE (care la rândul lui este o variație a LZ77) si codificarea Huffman. El ține minte o parte din conținutul tratat anterior și încearcă să găsească și să înlocuiască fragmente de date duplicate într-un mod eficient.

Un șir de biți codificați DEFLATE constau dintr-o serie de blocuri, fiecare bloc fiind precedat de un antet de 3 biți astfel:

primul bit semnifică marcajul pentru sfârșitul fluxului. 1 dacă aceasta este ultimul bloc din informația finală, 0 dacă există mai multe blocuri după acesta;

biții doi și trei reprezintă metoda de codificare folosită în acel bloc:

00: o secțiune stocată în mod brut de maxim 65535 de octeți lungime;

01: un bloc comprimat cu Huffman, folosind un arbore Huffman prestabilit;

10: un bloc comprimat cu Huffman în mod dinamic cu tabelul Huffman furnizat;

11: rezervat (nu se utilizează).

Cele mai multe blocuri se sfârșesc de obicei prin a fi codificate folosind metoda "10" (codificarea Huffman dinamică) ce produce un arbore Huffman optimizat, particularizat pentru fiecare bloc de date individual. Instrucțiunile pentru a regenera arborele Huffman necesar la decodare sunt scrise imediat în antetul blocului.

Comparații de performanță generală între GZip și DEFLATE simplu la compresie și decompresie (sursa typepad)

Pe lângă algoritmul de compresie, dacă o serie de octeți este duplicată în informația originală, se introduce o referință către blocul unde s-a găsit șirul identic. Această operație face parte din algoritmul LZ77 care, pe lângă poziție, se introduce și lungimea blocului repetat ce poate fi mai mare decât blocul în sine pentru a marca repetițiile neîntrerupte.

Imagini digitale

O imagine digitală este un șir de biți a căror semnificație reprezintă liniarizarea unei matrice de pixeli folosiți în constituirea unei imagini reale în mod bidimensional, captate cu ajutorul unui aparat digital precum camera digitală, scanner sau senzori pentru diferite spectre, sau create în mod artificial cu un software specializat pe calculator. Un pixel reprezintă cea mai mică unitate logică ce poate fi reprezentată pe un dispozitiv de redare a imaginilor digitale, cum ar fi monitorul. Există două noțiuni în tipologia imaginilor digitale: vector și raster (bitmap).

Imaginile raster au un set fix de valori digitale, numite pixeli, și conțin un număr fix de rânduri și coloane (sub formă matriceală). Pixelii reprezintă cel mai mic element individual al imaginii ce au drept conținut valori discrete ce reprezintă luminozitatea și culoarea unui anumit punct.

Grafica vectorială utilizează primitive geometrice pentru reprezentarea imaginii în grafica pe calculator, cum ar fi puncte, linii, curbe sau poligoane. Aceasta permite operații complexe făcute ușor prin formule matematice, față de grafica raster, cum ar fi rotație, mișcarea (fără rotație), oglindire, întindere, îndoire, transformări afine, schimbarea ordinei de redare (ceea ce este în față și în spate).

PNG

Portable Network Graphics (PNG) este un format de fișier imagine de tip raster ce suportă compresia fără pierdere a datelor. Acest format a fost conceput pentru a înlocui formatul GIF (Graphics Interchange Format) mai vechi și cu o structură mai simplă ce nu a mai fost îndeajuns pentru implementarea unei imagini, și ca alternativă pentru formatul mult mai complex TIFF (Tagged Image Format) unde e necesară mai multă putere de calcul pentru manipularea lui. PNG a fost creat pentru a servi drept formatul de imagine universal folosit îndeosebi pe Internet.

Pentru web, PNG aduce trei avantaje principale față de GIF: canale alfa (transparență variabilă), corecția gamma (controlul cross-platform a luminozității imaginii), și îmbinare bidimensionala (o metodă de afișare progresivă a conținutului imaginii).

Un canal alfa este mod de a asocia transparență variabilă într-o imagine. Față de GIF ce suportă transparență binară – orice pixel poate fi complet transparent sau opac – PNG permite până la 254 de nivele de transparență parțială.

Corecția gamma se referă practic la capacitatea de a corecta diferențele de luminozitate în modul în care calculatoarele (mai ales monitoarele) interpretează valorile culorilor. De exemplu o imagine generată pe Mac devine prea întunecată pe un PC și invers, imagini generate de un PC tind să se arate prea luminoase pe Mac-uri.

Algoritmul pentru îmbinarea bidimensională se numește Adam7 și o imagine căruia i-a fost aplicat Adam7 este împărțită în șapte sub-imagini definite prin replicarea unui model de 8×8 pixeli peste imaginea completă. Cele 7 faze ale încărcării imaginii sunt reprezentate în figura 1, unde numerele reprezintă pixelii din etapa în care s-a încărcat sub-imaginea.

Fig. 1 – Tiparul folosit pentru interpretarea imaginilor PNG

Datorită acestui mecanism de încărcare a imaginii, PNG-ul este capabil de a reda informație distinctivă de om mult mai devreme față de GIF și JPEG, iar textul încorporat într-o imagine PNG devine lizibil până la de două ori mai repede.

Rețele neuronale

Învățarea automată este intersecția dintre informatica cu aspect teoretic și de datele reale, practic perturbate. În esență, este vorba de calculatoare care fac sens din date în aceeași manieră în care o fac oamenii. Învățarea automată este un tip de inteligență artificială prin care un algoritm sau metodă extrage modele din date (pattern-uri).

În funcție de natura învățării disponibilă unui sistem de învățare (intrările și evaluările oferite algoritmului), învățarea automată este clasificată în:

învățare supervizată: calculatorului (algoritmului) îi sunt prezentate exemple de intrări și ieșiri dorite, date de un "supraveghetor / profesor", iar scopul este de a învăța o regulă generală ce leagă intrările de ieșiri.

învățare nesupervizată: nu sunt date algoritmului de învățare și ieșirile (etichetele) lăsând-ul pe cont propriu să găsească structura intrărilor lui. Învățarea nesupervizată poate avea ca scop descoperirea unor structuri ascunse în date.

Învățare împuternicită (reinforcement learning): un program de calculator interacționează cu un mediu dinamic în care trebuie să ajungă într-un anumit punct final, fără ca un "supraveghetor" să spună explicit dacă a ajuns aproape de obiectivul său sau nu.

O modalitate prin care se poate implementa învățarea pe un calculator este prin intermediul unei rețele neuronale. O rețea neuronală este o funcție robustă care ia un set arbitrar de intrări și le încadrează în alt set arbitrar de ieșiri. Este excelent la potriviri dificile și construirea de funcții robuste pentru a potrivi aproape orice. În practică rețelele neuronale sunt utilizate în domeniul cercetării cu învățare profundă (deep learning) pentru a potrivi imagini cu anumite caracteristici, a recunoaște scrisul de mană și multe altele. O astfel de metodă de învățare este formată din unul sau mai mulți perceptroni (sau neuroni) care reprezintă cea mai mică unitate capabilă de a învață o funcție liniară.

Cel mai simplu exemplu de rețea neuronală este cea care învață funcția XOR. În figura 2 se observă cum o rețea neuronală reușește să împartă valorile 0 și 1 în semiplane diferite calculând mai întâi hiperplanele corespunzătoare din dreapta lui P1 și stânga lui P2, apoi prin intersecția lor se obține regiunea convexă corespunzătoare valorii 1.

Fig. 2 : Funcția XOR și ceea ce a învățat o rețea neuronală (sursa Celebi)

Fig. 3 : O rețea neuronală multistrat antrenată pentru recunoașterea funcției XOR (sursa Celebi)

Rețeaua care a reușit să învețe acest lucru este una multistrat, pe două nivele, a cărei structură și parametri au fost calculați folosind modalitatea de implementare cu funcții booleene. Ea este reprezentată în figura 3 unde pe primul strat se află doi perceptroni ce recunosc pe și iar pe ultimul strat (cel de ieșire) se află un perceptron ce calculează funcția "și logic" între ieșirile celorlalți doi din urmă. Toți perceptronii folosesc drept funcție de transfer (modificarea ieșirii perceptronului) funcția hardlim (ce returnează 0 dacă numărul e negativ, altfel 1).

Model, View, ViewModel

Prezentare

Pattern-ul Model-View-ViewModel (MVVM) ajută separarea într-un mod îngrijit a activității și logicii de prezentare față de interfața cu utilizatorul (UI). Menținerea unei separări definitorii între logica aplicației și UI ajută la abordarea a numeroase probleme de dezvoltare și proiectare, și pot face aplicația mult mai ușor de testat, menținut, și evoluat. De asemenea, poate îmbunătăți foarte mult oportunitățile de reutilizare a codului și permite dezvoltatorilor și designerilor UI o colaborare mai ușoară în a dezvolta părțile lor respective din aplicație.

Folosind modelul MVVM, UI-ul aplicației și logica împreună cu activitățile care stau la bază sunt separate în trei clase distincte: View-ul, care încapsulează UI-ul și logica UI; ViewModel, ce încapsulează logica de prezentare și de stare a aplicației; și Model, ce încapsulează logica de activitate a aplicației și a datelor.

Caracteristicile și funcțiile fiecărei clase

View-ul interacționează cu ViewModel prin intermediul procedeului data binding (legare a datelor), comenzi, și evenimente ce notifică schimbări. ViewModel interoghează, observă, și coordonează actualizări ale Model-ului, convertește, validează, și agreghează datele necesare pentru afișare în View.

Clasa View

Responsabilitatea View-ului este de a defini structura și aspectul pentru ceea ce utilizatorul vede pe ecran. În mod ideal, code-behind-ul unui View conține doar un constructor care apelează metoda InitializeComponent, ce creează elementele de UI definite în XAML. În unele cazuri, code-behind poate conține logică UI ce implementează comportament vizual complex sau ineficient pentru a fi exprimat în XAML, cum ar fi animații complexe sau codul ce trebuie să manipuleze direct elemente vizuale care sunt parte din View.

În MVVM, contextul de date (DataContext) al View-ului (locul de unde își ia datele pe care să le prezinte) este setat de către ViewModel. ViewModel-ul pune la dispoziție proprietăți și comenzi la care View-ul se poate lega (bind) și notifică View-ul cu privire la orice modificări în starea programului prin evenimente ce declanșează notificările. De obicei există o relație unu-la-unu între un View și ViewModel-ul său.

Un View-urile este de multe ori derivat din clasa Page sau UserControl (principalele modalități de a crea o pagină). Cu toate acestea, în unele cazuri, View-ul poate fi reprezentat de un șablon de date (DataTemplate), ce specifică elementele UI care trebuie utilizate pentru a reprezenta vizual un obiect atunci când este afișat. Folosind template-uri de date, un designer poate defini cu ușurință modul în care un ViewModel va fi redat sau poate modifica reprezentarea vizuală fără a schimba obiectele de bază sau comportamentul de control utilizat pentru a afișare.

Modul de comunicare a părților în MVVM (sursa MSDN)

Template-urile de date (DataTemplates) pot fi considerate ca View-uri ce nu au code-behind. Acestea sunt concepute pentru a se lega de un ViewModel ori de câte ori o este necesar să fie afișat UI-ul. În momentul rulării, View-ul, așa cum este definit de șablonul de date, va fi instanțiat automat și contextul său de date setat pentru ViewModel-ul corespunzător.

Rezumând, View-ul are următoarele caracteristici cheie:

Este un element vizual, cum ar fi o fereastră, pagină (Page), UserControl, sau șablon de date (DataTemplate).

Definește controalele folosite și aspectul lor vizual.

Referențiază ViewModel-ul prin proprietatea de DataContext. Controalele din View sunt legate (data bound) de proprietățile și comenzile expuse de ViewModel.

Poate personaliza comportamentul de data binding dintre View și ViewModel. De exemplu, View-ul poate folosi clase convertoare (Converters) pentru a formata datele ce urmează să fie afișate în interfața, sau poate folosi reguli de validare pentru a furniza date de intrare suplimentare pentru utilizator.

Definește și se ocupă de comportamentul vizual al UI-ului, cum ar fi animații sau tranziții ce pot fi declanșate de o schimbare de stare în ViewModel sau prin interacțiunea utilizatorului cu UI-ul.

Code-behind-ul poate defini logica UI ce implementează un comportament vizual dificil de exprimat în XAML sau care necesită referiri directe la controale UI specifice, definite în View.

Clasa ViewModel

ViewModel-ul în pattern-ul MVVM încapsulează logica de prezentare și datele destinate View-ului. Acesta nu are nici o referire directă la View sau orice cunoștințe despre implementarea specifică a View-ului sau tipul lui. ViewModel-ul implementează proprietăți și comenzi la care View-ul poate lega date (data bind) și îl notifică cu privire la orice modificări de stare prin crearea de evenimente ce notifică schimbările. Proprietățile și comenzile pe care ViewModel le furnizează definesc funcționalitatea oferită de către UI, dar View-ul determină cum va fi redată acea funcționalitate.

ViewModel-ul este responsabil de coordonarea interacțiunii View-ului cu orice clasă Model care e necesară. De obicei, există o relație unu-la mai mulți între ViewModel și clasele Model. ViewModel poate alege expunerea claselor Model direct către View, astfel încât controalele din View să poată face data bind direct la ele. În acest caz, clasele Model vor trebui concepute pentru a suporta data bind și evenimentele de notificare a schimbărilor relevante.

Tot ViewModel-ul poate converti sau manipula datele Model-ului astfel încât să poată fi ușor consumate de View. Acesta poate defini proprietăți suplimentare pentru a sprijini în mod specific View-ul; aceste proprietăți nu ar face în mod normal parte din (sau nu pot fi adăugate la) Model. De exemplu, VewModel poate combina valoarea a două câmpuri pentru a face mai ușor de prezentat informația pentru View, sau poate calcula numărul maxim de caractere ce poate fi afișat de View și să returneze șirul de caractere trunchiat. ViewModel-ul poate pune în aplicare, de asemenea, logica de validare a datelor pentru a asigura coerența lor.

ViewModel-ul poate defini, de asemenea, stări logice pe care View-ului le poate utiliza pentru a oferi schimbări în interfață. View-ul poate defini schimbări în paginare sau un stil vizual care să reflecte starea ViewModel-ului. De exemplu, ViewModel poate defini o stare care indică faptul că datele sunt obținute asincron de la un serviciu web, iar View-ul poate afișa o animație în această stare pentru a oferi feedback vizual utilizatorului.

De obicei, un ViewModel definește comenzi sau acțiuni ce pot fi reprezentate în UI pe care utilizatorul le va putea invoca. Un exemplu comun este atunci când ViewModel oferă o comandă pentru o casetă de căutare, ce permite utilizatorului să caute datele din View. View poate alege să reprezinte acea comanda cu un buton și un câmp de introducere a textului, astfel încât utilizatorul poate face clic pe buton pentru a trimite cererea. În mod tipic, în cazul în care comanda devine indisponibilă, reprezentarea UI asociată devine dezactivată. Comenzile oferă o modalitate de a încapsula acțiunile utilizatorului și a le separa în mod corect de reprezentarea lor vizuală din interfață.

Sintetizând, un ViewModel are următoarele caracteristici:

Este o clasa non-vizuală și nu derivă dintr-o clasă destinată creării interfeței. Acesta încapsulează logica de prezentare necesara pentru a susține un caz de utilizare sau sarcină cerută de utilizator. Testarea acestuia este independentă de View și Model.

De obicei nu face referire în mod direct la View. El implementează proprietăți și comenzi la care View-ul poate face data bind. Totodată notifică View-ul cu privire la orice modificări de stare, prin intermediul evenimentelor de notificare a schimbărilor și prin intermediul interfețelor INotifyPropertyChanged și INotifyCollectionChanged.

Coordonează interacțiunea View-ului cu Modelul. Poate converti sau manipula datele, astfel încât să poată fi ușor consumate de View și poate implementa proprietăți suplimentare care nu pot fi prezente în Model.

Poate defini stări logice pe care View-ul le poate reprezenta vizual pentru utilizator.

Clasa Model

Model-ul în pattern-ul MVVM încapsulează logica de activitate și a datelor. Logica activităților (business logic) este definită ca orice logică a unei aplicații ce se preocupă de recuperarea și gestionarea datelor aplicației și pentru a asigura că sunt aplicate toate regulile activității care asigură coerența și valabilitatea datelor. Pentru a maximiza oportunitățile de re-utilizare, Model-ele nu trebuie să conțină nici un caz de utilizare specific, comportament specific sarcinii de utilizator sau logică pentru aplicație.

El poate defini structuri de date, pe baza tipului de date al aplicației și orice activități susținute și de validare logică. Model-ul poate include, de asemenea, codul pentru suportul accesului la date și caching, deși de obicei un depozit de date (data repository) sau serviciu separat se ocupă de acest lucru. De multe ori, Model-ul și accesul la date sunt auto-generate ca parte a unui serviciu de date, cum ar fi ADO.NET Entity Framework.

De obicei Model-ul implementează facilitățile ce fac ușor data bind la View. Uzual, acest lucru înseamnă că suportă notificări a schimbării unei proprietăți sau colecții prin intermediul interfețelor INotifyPropertyChanged și INotifyCollectionChanged. Clasele Model ce reprezintă colecții de obiecte de obicei moștenesc clasa ObservableCollection<T>, care oferă o implementare a interfeței INotifyCollectionChanged.

Model-ul poate suporta, de asemenea, validarea datelor și raportarea erorilor prin intermediul interfețelor IDataErrorInfo (sau INotifyDataErrorInfo). Interfețele IDataErrorInfo și INotifyDataErrorInfo permit ca data binding-ul XAML să fie notificat când valorile se schimbă astfel încât UI-ul să fie actualizat. De asemenea acestea permit sprijin pentru validarea datelor și raportarea erorilor în UI.

Modelul are următoarele caracteristici esențiale:

Clase de Model sunt clase non-vizuale care încapsulează datele aplicației și logica acțiunilor. Ele sunt responsabile pentru gestionarea datelor aplicației și pentru asigurarea consistenței și valabilității prin încapsularea regulilor de activitate (business rules) necesare și logica de validare a datelor.

Nu face referire în mod direct la View sau ViewModel și nu are nicio dependență de modul în care acestea sunt implementate.

Oferă de obicei notificări pentru schimbarea proprietăților cu prin evenimentelor din interfețele INotifyPropertyChanged și INotifyCollectionChanged. Acest lucru le permite datelor să fie ușor legate de View. Clase Model ce reprezintă colecții de obiecte de obicei moștenesc clasa ObservableCollection<T>.

Pune la dispoziție de obicei validarea datelor și raportarea erorilor prin oricare din interfețele IDataErrorInfo sau INotifyDataErrorInfo.

Aplicația Mobilă

Context

Aplicația FMI UniBuc a fost concepută pentru studenții Facultății de Matematică și Informatică și le oferă informații regăsite pe site-ul oficial al facultății direct pe telefonul lor mobil (ce are ca sistem de operare Windows Phone), fără a fi necesară o conexiune permanentă la internet.

Aceștia pot urmări ultimele noutăți și anunțuri postate atât pe site-ul facultății cât și pe pagina de Facebook a acesteia. De asemenea studenții au posibilitatea să-și consulte orarul pe telefonul mobil, fapt ce nu se poate întâmpla dintr-un browser al unui terminal mobil.

Pe lângă acestea mai sunt puse la dispoziție legături către programarea examenelor fiecărui an, emailurile profesorilor din toate departamentele, calendarul privind activitatea didactică și vacanțele, detaliile de contact și câte o hartă a fiecărui etaj al facultății.

Caracteristici

Anunțuri de la secretariat

Actualizări de pe pagina de Facebook

Examene

Profesorii și emailurile lor

Structura an universitar

Date de contact

Schițele facultății

Orarul pentru studenți

Partajarea anunțurilor

Notificări cu privire la anunțuri noi

Live tile cu imagini din facultate

Schimbare imagine fundal lockscreen

Evoluție

În primele sale versiuni, aplicația descărca imaginile cu orarul de pe server codate sub formă de șir de caractere Base64. Acestea aveau în medie dimensiunea de 70 de KB iar avantajul folosirii acestei abordări este ușurința scrierii codului pentru manipularea șirurilor de caractere codate Base64, atât în Java cât și C#.

Durata descărcării unei imagini codate Base64 – 284 330 ms

Principalul dezavantaj al acestei codări este faptul că dimensiunea mesajului transmis este semnificativ mai mare decât imaginea originală (aproximativ 50 KB). Pentru tratarea acestui inconvenient, s-a părăsit acest procedeu în favoarea folosirii comprimării GZip. Prin acest lucru, s-a obținut un câștig de 10 KB per imagine, ajungându-se la o dimensiune medie a mesajului de 40 de KB.

Durata descărcării unei imagini comprimate GZip – 145 410 ms

În cazul transmiterii cu GZip, header-ul mesajului conține "Accept-Encoding" setat pentru "gzip", iar "Content-Type" este fixat "application/octet-stream". Față de transmiterea prin Base64 care avea "Content-Type" setat "application/json", aceasta se întâmplă mult mai repede datorită faptului că transmiterea nu se face în mod text, ci ca un flux de octeți.

Aplicația de față a trecut prin următoarele faze de dezvoltare până la versiunea finală din prezent:

Prima versiune: Atunci când utilizatorul se afla în pagina cu Departamente, la navigarea înapoi să nu apară pagina cu Facebook, ci să rămână la pagina cu Departamente.

A doua versiune: Notificarea în caz de anunțuri noi pe prima pagina a site-ului facultății să apară de la toate categoriile de anunțuri (nu doar pentru Anunțuri de la secretariat și Noutăți) și să arate de la ce categorie a venit notificarea.

A treia versiune: Introducerea orarului în aplicație.

A patra versiune: Soluționarea problemelor din versiunea precedentă. Prima problemă apăruta a fost faptul că dura foarte mult să se descarce imaginile. Soluția a fost modificarea aplicației server astfel încât să trimită pozele sub formă de GZip și numele lor separat.
A doua problemă apărea atunci când utilizatorul derula printre poze și interfața nu ținea pasul; moment în care dispăreau de pe ecran imaginile. A fost rezolvată în atunci când s-a reușit OCR-ul pe imagini pentru a scoate denumirile lor și arătând utilizatorului doar butoane cu numele imaginii fără o previzualizare pentru ele (90 de poze, chiar și micșorate, sunt prea multe pentru a fi redate pe mobil).

A cincea versiune: Un utilizator a observat că aplicația nu descărca orarul cel nou pentru semestrul II. Dar ceea nu știa este de existența unui buton pentru refresh, doar că era ascuns în meniul de jos al aplicației. Problema a fost rezolvată prin afișarea permanentă pe prima pagină a butoanelor, doar pe celelalte pagini ele rămânând ascunse.

Implementare

Aplicația

Prima clasă încărcată în memorie este clasa App (anexa 7.2.1). Aceasta conține diverse metode ce ajută aplicația să reacționeze în diverse scenarii pe care un utilizator o poate folosi (scenarii ce au legătură cu utilizarea în general a dispozitivului): deschiderea pentru prima oară, punerea în background, închiderea, revenirea din background în prim plan.

Cele trei stări ale unei aplicații pe Windows Phone (sursa MSDN)

Pe lângă acestea, tot aici sunt manipulate și alte motive de lansare în execuție a aplicației, cum ar fi de la un tile (scurtătură) pus de utilizator pentru a vedea orarul sau altul pentru a vedea o anume categorie de anunțuri. Aceste evenimente sunt tratate astfel încât prima pagină ce urmează a fi afișată să nu fie MainPage, ci aceea pe care utilizatorul dorea să o vadă în momentul în care acesta a apăsat pe tile. Această navigare este posibilă prin precizarea paginii și a elementului ce va fi încărcat în loc de MainPage.

Alte activități ce se întâmplă la deschiderea aplicației sunt încărcarea în memorie a string-urilor folosite de diverse butoane și controale UI pentru redare text, a câtorva setări ale aplicației, înregistrarea execuției unei activități de fundal (background task – despre care se va discuta mai jos) și eventual afișarea paginii MainPage.

MainPage pe lângă actualizarea tile-ului aplicației principale (folosind MainAppTileHelper), apelează MainViewModel ce încarcă fiecare View cu informațiile necesare prin intermediul celorlalte ViewModel-uri (ce vor fi discutate mai jos). Ele la rândul lor încorporează diverse funcții cum ar fi Share (ShareServices), crearea de tile-uri (TileServices) și diverse comenzi ale controalelor dintr-un View, date printr-un DelegateCommand sau RelayCommand. Ultimele două clase diferă prin faptul că prima primește ca parametru o funcție ce trebuie executată și nu întoarce nimic, iar a doua primește ca parametru tot o funcție, dar aceasta la rândul ei primește și o valoare de un anume tip.

În ceea ce privește background task-ul existent (ScheduledAgent), acesta se ocupă cu două lucruri: notifică utilizatorul cu privire la anunțuri noi apărute pe site-ul facultății și actualizează imaginea de background a ecranului de lockscreen. Ambele acțiuni sunt determinate de acordul utilizatorului prin activarea unei setări declanșate de apăsarea unui buton în ContactView.

Partea de schimbare a imaginii de fundal se face ușor, printr-un apel pus la dispoziție de Windows Phone 8.1 SDK, iar partea de notificare se întâmplă astfel: se instanțiază clasa AnunturiDataSource folosită pentru a descărca cele mai recente anunțuri și se compară cu cele existente în cache-ul aplicației; dacă există diferențe, se afișează o notificare cu privire la categoriile schimbate (actualizate).

Pagina principală

Din punctul de vedere al pattern-ului MVVM, se întâmplă următoarele lucruri: clasa MainViewModels (vezi anexa 7.2.2) încapsulează toate ViewModel-urile folosite de aplicație și după instanțierea ei, se apelează metoda LoadData ce determină apelarea metodei LoadItems asociată fiecărui ViewModel (metodă moștenită din ViewModelBase).

În timp ce se așteaptă datele de la fiecare Model în parte (fiecare pe alt fir de execuție), se instanțiază MainPage ce conține câte un View pentru fiecare pagină. OrarView și EtajeView au ca dependență o altă pagină separată (ImageViewer), capabilă să redea imagini și să manipuleze imaginea după gesturile făcute de utilizator (zoom și mișcare).

Pentru a naviga de la o pagină la alta, în MainPage și toate celelalte View-uri se folosește NavigationServices, ce ajută la navigarea și transmiterea de argumente între pagini pentru a adăuga un plus de funcționalitate aplicației. De exemplu, când utilizatorul apasă pe un feed de Facebook, acestuia să-i apară detaliile despre acel feed, și nu despre primul din listă.

În MainViewModel se găsesc trei comenzi importante: una care setează imaginea de la lockscreen, una care anunță background task-ul să afișeze notificări pentru utilizator și una care deschide pagina AboutThisAppPage. Aceasta din urmă are ViewModel-ul făcut ca un singleton, pentru a nu se încărca a doua oară în memorie) și este oarecum separată de restul logicii aplicației deoarece ea se nu se instanțiază automat, ci depinde de acțiunile utilizatorului.

Anunțuri

În cadrul majorității paginilor, pattern-ul MVVM respectă aceeași idee de implementare: Modelul este alcătuit în principal dintr-un DataSource ce implementează interfața IDataSource și clasă Schema ce implementează BindableSchemaBase. ModelView-ul este format dintr-o singură clasă ce implementează ViewModelBase<T> iar la rândul ei implementează ViewModelBase (vezi anexa 7.2.3). Această despărțire a fost necesară deoarece unele metode și câmpuri depindeau de tipul dat clasei șablon/template. Și în final, View-ul este alcătuit dintr-o singură clasă (a cărui conține ceea ce se afișează urmat de 'Detail').

În cazul de față, AnunturiDataSource se folosește de AnunturiDoarText și AnunturiDoarTitlu pentru a crea obiectele primite de pe serverul ImportIO (sub formă de json) și a le utiliza pentru crearea unei liste de AnunturiSchema folosită ca data binding pentru View (AnunturiDetail).

Un aspect important de discutat este faptul că atât ViewModelBase cât și BidableSchemaBase moștenesc aceeași clasă BindableBase. Ea la rândul ei implementează interfața INotifyPropertyChanged, despre care s-a discutat în partea de MVVM și rolul ei în data binding.

Dacă nu exista o conexiune la internet, se încearcă citirea datelor din cache-ul aplicației (AppCache) iar dacă aceasta metoda nu returnează nimic (aplicația a fost deschisă pentru prima oara) atunci View-urile nu mai sunt populate cu date și funcționalitatea aplicației se rezumă afișarea unor pagini goale.

Calendar, Examene, Profesori

Aceste trei concepte structurale (a căror diagrame se află în anexa 7.2.4) sunt foarte asemănătoare (moștenesc aceleași clase și funcționează la fel), singurul aspect ce le deosebește este scopul pentru care au fost create. Ce apare nou aici este clasa ImportIOCall ce face apel către serverul ImportIO folosind API-ul lor, și returnează fișierul json cu informațiile necesare pentru a fi prelucrate de către DataSource.

La categoria Profesori, View-ul este împărțit cu cel pentru Departamente deoarece departamentele au un aspect atât static cât și dinamic:

static deoarece sunt patru departamente: Matematică, Informatică, Profesori Asociați și Profesori Consultanți.

dinamic deoarece fiecare departament are un număr variabil de profesori.

De aceea DepartamenteDetail este folosit atât pentru afișarea celor patru categorii, cât și pentru afișarea profesorilor unui departament.

Contact, Etaje, Departamente

Aceste trei clase (cu diagramele prezentate în anexa 7.2.5) nu au nevoie de conexiunea la internet întrucât datele sunt stocate în memoria dispozitivului, odată cu instalarea aplicației. Datorită simplității View-ului pentru pagina de ContactDetail, acesta nu mai are atașată o clasă C# în code-behind ci pur și simplu este alcătuit doar din cod XAML ce are definită interfață și data binding-ul necesar.

Pagina de Etaje nu are nimic ieșit din comun, însă de observat este relația de unu la patru dintre DepartamenteDetail și ProfesoriViewModel. Pagina cu Departamente are atașate două ViewModel principale, deoarece primul (DepartamenteViewModel) afișează doar denumirile departamentelor iar al doilea (ProfesoriViewModel) afișează profesorii din departamentul pe care utilizatorul l-a selectat.

Pagina cu Orar-ul și cea în care se găsesc news feed-urile de Facebook sunt amintite împreună cu diagramele lor UML de clase în anexele 7.2.6 și 7.2.7.

Acțiuni desfășurate în aplicație

Încărcarea datelor de pe Facebook

Când se descărcă news feed-ul de pe Facebook (vezi anexa 7.4.1) se petrec următoarele acțiuni:

se creează un obiect din clasa RssDataProvider, ce primește ca parametru link-ul paginii de Facebook. Acesta apelează metoda Load ce se va ocupa de descărcarea feed-ul sub forma de XML.

după ce se verifică integritatea XML-ului descărcat, se creează un obiect din clasa RssReader ce apelează metoda LoadFeed cu XML-ul dat ca parametru.

se verifică tipul de RSS returnat și în funcție de aceasta, se creează lista de RssSchema cu primele informații căpătate.

dintre feed-uri returnate, se păstrează doar primele 20 și se creează o listă simplă de FacebookSchema pe baza informațiilor din RssSchema, ca mai apoi în final să se creeze o listă de ObservableCollection<T> parametrizată după FacebookSchema folosită pentru data binding, cu feed-urile sortate după data publicării.

Încărcarea datelor de pe Import.IO

Acțiunea de a descărca informațiile de pe serverul Import.IO presupune următorii pași (vezi anexa 7.4.2):

inițializarea unui obiect static (o singură dată) de tipul RestClient în a cărui constructor se pasează ca argument adresa unde se găsesc resursele de pe ImportIO.

crearea unei solicitări (request) cu parametrii id-ul, user id-ul și api key.

executarea request-ului și primirea răspunsului (sub formă de fișier json).

dacă răspunsul nu este OK, returnează null.

altfel, se intră în blocul switch unde fiecare caz returnează o noua listă de un tip dat ca parametru cu informațiile obținute prin deserializarea json-ului.

Execuție background task

În cadrul sistemului de operare Windows Phone, un background task permite unei aplicații să execute cod în fundal, chiar și atunci când aplicația nu se execută în prim-plan. Există două tipuri de background task: PeriodicTask și ResourceIntensiveTask. Al doilea rulează pe o perioada lungă de timp pentru a executa instrucțiuni cu durată mare de timp și resurse multe, dar doar atunci când dispozitivul permite acest lucru (baterie, conexiune la internet, utilizare scăzută a procesorului). Primul tip (Periodic Task) rulează pe perioade scurte de timp și la intervale recurente regulate, folosite în special pentru a manipula cantități mici de date.

O aplicație este restricționată la a avea un singur tip de background task, dezvoltatorul luând decizia pe care să o implementeze și având grijă ca acesta să respecte constrângerile impuse de sistemul de operare. Ambele tipuri de task-uri implementează interfața BackgorundAgent ce conține metodele OnInvoke, NotifyComplete și Abort. Sistemul de operare, când dorește să ruleze task-ul, apelează metoda OnInvoke, se executa codul acestuia și când ajunge într-un punct în care s-a terminat de efectuat task-ul, trebuie apelată fie metoda NotifyComplete, fie Abort.

Când se apelează NotifyComplete, se comunică sistemului de operare faptul că execuția background task-ului a fost cu succes. Când task-ul este incapabil de a-și efectua acțiunile, acesta trebuie să apeleze Abort iar sistemul de operare nu îl va mai porni până când aplicația nu va fi deschisă și va remedia problemele pe care le-a întâmpinat.

În cazul aplicației de față, background task-ul este unul de tip Periodic Task ce executa două acțiuni principale: actualizează imaginea de fundal de pe ecranul lockscreen și verifică dacă au apărut anunțuri noi pe site-ul facultății (vezi anexa 7.4.3). Realizarea lor se face astfel:

în prima parte se apelează metoda SetNewLockScreenImage care verifică două lucruri: dacă aplicația curentă este furnizor de imagini pentru lockscreen și dacă trebuie să ceară permisiunea utilizatorului pentru aceasta. În funcție de cele două variabile primite ca argument, se schimbă sau nu imaginea și diverse coduri de succes/eroare sunt returnate.

execuția celei dea doua părți este condiționată de existența unei setări făcute de utilizator din aplicație (dacă dorește sau nu să primească notificări). Aici este creat un AnunturiDataSource (o parte a Model-ului pentru anunțuri) ce se ocupă cu logica pentru obținerea informațiilor.

se execută metoda LoadData ce descarcă anunțurile de pe Import.IO separat (titlurile și textul) după care într-un ciclu le adaugă la o listă unde vor fi ușor de manipulat.

dacă rezultatul returnat este null, execuția se oprește și se apelează NotifyComplete.

altfel, se citește dintr-un fișier ultimele anunțuri salvate. Dacă acestea nu există, se scriu cele noi și se termină execuția în aceeași manieră ca cea de mai sus.

În final, dacă există anunțurile noi și vechi, se compara fiecare element pentru a vedea dacă există diferențe între ele și dacă da, se scriu în fișier cele noi, se creează o notificare ce conține categoriile noi unde au apărut anunțurile și se apelează metoda NotifyComplete.

Partajare informații

Utilizatorul când dorește să facă share la o informație conținută în aplicație, prin acțiunile lui este apelată în fundal metoda Share (vezi anexa 7.4.4) ce execută următoarele operații:

se curăță titlul și mesajul (daca este text) de eventualul cod HTML în metoda CleanHtml.

se află posibilitățile de share ale informației, pe baza existenței câmpurilor link, title, image, message și a tipurilor lor. Modalitățile prin care se poate face share sunt prin imagine, NFC (near field communication – dacă dispozitivul este dotat cu acestă tehnologie), status (pentru Facebook sau alte aplicații de social networking) sau prin email (fiind mereu o opțiune validă).

după ce se alcătuiește o listă cu posibilitățile enumerate mai sus, aceasta este pasată metodei OpenShareTypeSelector ce arată vizual pentru utilizator metodele posibile de share de unde utilizatorul o alege pe care o dorește. De aici sistemul de operare apelează aplicația țintă pentru share.

Încărcarea datelor în aplicație

Metoda LoadData din ViewModelBase (vezi anexa 7.4.5) reprezintă punctul de comunicare dintre Model și ViewModel, luând decizia dacă datele vor fi preluate din cache, internet sau static din memoria dispozitivului. Aceste decizii au loc în următoarea ordine:

se verifică dacă datele ce urmează a fi extrase sunt statice sau nu prin evaluarea unui câmp boolean. Dacă nu sunt statice, se încearcă recuperarea lor din memoria cache a aplicației (apelând metoda GetItems<T>). Procesul include și deserializarea lor într-o formă înțeleasă de ViewModel.

în cazul în care există o conexiune la internet, datele sunt preluate folosind Model-ul corespunzător ViewModel-ului. Dacă există informație returnată, aceasta este mai întâi scrisă în cache (AddItems<T>) și apoi câmpului Items al ViewModelBase i se atribuie un ObservableCollection<T> ce conține datele returnate.

în cazul în care datele sunt statice (venite odată cu instalarea aplicației) se apelează doar metoda Load al Model-ului.

dacă pe parcursul procedeului de mai sus este întâmpinată o eroare, pentru date nestatice, în blocul catch se scrie în cache null pentru ViewModel-ul curent.

Crearea unei scurtături pe ecranul principal

Pentru ca utilizatorul să adauge la ecranul principal o scurtătură a aplicației către o categorie de anunțuri, o grupă din orar sau o schiță a unui etaj, se executa metoda PinToStart (vezi anexa 7.4.6) a clasei ViewModelBase, în felul următor:

se preia elementul curent vizibil în View (câmpul SelectedItem din ViewModel) prin apel la metoda GetCurrentItem.

elementului curent, fiind de tipul interfeței BindableSchemaBase, i se extrag informațiile din câmpurile lui apelând pe rând metoda GetBindingValue pentru fiecare câmp în parte.

cu informațiile extrase, se creează un TileInfo ce va fi pasat ca argument (pe lângă altele) metodei statice PinToStart a clasei TileServices. Aici, se salvează în cache-ul aplicației informațiile despre acel tile și se verifică dacă el există deja sau nu.

dacă nu există, atunci se apelează CreateTile care salvează imaginea folosită la o dimensiune mai mică și informațiile legate de tile. Imaginea poate fi transmisă ori printr-un șir de octeți, ori printr-un link către aceasta.

dacă tile-ul există, atunci, preluând tile-ul curent al aplicației prin apeluri ale sistemului de operare, se face actualizarea acestuia (popularea cu informații și imagini, la fel ca mai sus) și se încheie execuția metodei.

Aplicația server

De ce Openshift

Platforma celor de la RedHat, în comparație cu platforma Heroku, este mai ușor de utilizat din punctul de vedere al unui dezvoltator nou ce are nevoie să-și creeze o aplicație web imediat.

Acesta nu necesită un tool dedicat pentru a pune în producție o aplicație (deploy), aceasta făcându-se automat în momentul în care se folosește Git pentru a face upload noului cod pe server. Deși serviciul OpenShift pune la dispoziția dezvoltatorilor un tool pentru gestionarea aplicației, utilitatea lui nu este neapărat justificată, iar spre deosebire de Heroku utilizatorul poate să între direct pe server folosind SSH (Secure Shell) pentru a executa diverse comenzi, să repornească aplicația sau pentru a vedea log-urile.

Pe lângă acestea, OpenShift pune la dispoziția dezvoltatorilor mai multe tipuri de baze de date, relaționale (MySql) și nerelaționale (MongoBD), printre care și PosgreSQL (singura disponibilă pe Heroku).

Implementare

Existența unui server pentru aplicația de față este necesară întrucât acesta se ocupă cu extragerea orarului de pe site-ul facultății, activitate pe care dispozitivul utilizatorului nu o poate face datorită resurselor limitate impuse de sistemul de operare.

Serverul se ocupă cu următoarele activități:

descărcarea orarului curent de pe site-ul facultății (actualmente sub formă de fișier .swf – Adobe Flash).

pentru acest lucru se folosește un script scris în bash (limbajul de scriptare folosit pe sistemele UNIX) capabil de a se adapta de la un semestru la altul.

extragerea informațiilor din orar.

pentru a transforma orarul într-un set de imagini, este folosită o componentă a unui set de tool-uri (SWFTools) și anume swfrender. Aceasta este o aplicație scrisă în C, sub formă de utilitar la consolă, ce primește la intrare calea către un fișier .swf și produce la ieșire câte o imagine corespunzătoare fiecărui cadru (frame).

după ce se termină execuția pasului precedent, se începe extragerea titlului imaginii (grupa) realizând OCR (optical character recognition) cu un software specializat (Tesseract) pentru fiecare poza.

popularea memoriei cache cu informațiile scoase.

aplicația server (scrisă în Java) citește informațiile lăsate la pasul 2 și populează cache-ul cu noile date.

punerea lor la dispoziția utilizatorilor sub formă de apel REST.

repetarea întregului procesului pentru a fi asigurată actualitatea informațiilor.

pașii 1 și 2 se repetă din oră în oră iar pasul 3 se repetă la interval de jumătate de oră. Asta înseamnă că, teoretic, o actualizare a orarului pe site-ul facultății duce la o actualizare a celui de pe server în maxim o oră.

Diagrama UML de clase

La pornirea serverului, se încarcă clasa ApplicationActivator ce inițializează framework-ul JAX-RS și crearea taskului ce se execută din jumătate în jumătate de oră pentru actualizarea informațiilor din memoria aplicației.

Taskul este alcătuit din metoda 'execute' a clasei ReloadImageCacheJob care apelează updateCache din clasa ImageCache. Aici se verifică existența fișierelor pe disc, se citesc din ele lista cu grupele și imaginile cu orarul, după care se creează un HashMap cu numerele de ordine ale imaginilor și denumirile grupelor, și o listă ce conține imaginile sub formă de sir de biți comprimate folosind gzip.

Cât despre clasa ImageService, ea implementează caracteristicile JAX-RS pentru a pune la dispoziția clientului următoarele informații printr-un serviciu de tip REST: numărul total de imagini, denumirile lor și imaginile. În cazul apariției unei excepții pe server, un mesaj informativ este trimis înapoi la client cu ajutorul clasei ResponseException ce reprezintă un template pentru alcătuirea unui mesaj de eroare cu un cod HTTP de eroare asociat. În plus, pentru depanare mai există implementată și o metodă REST ce returnează un text cu informații despre memoria serverului și eventualele excepții aruncate.

Diagrama de clase a serverului

Testare

Testare unitară și funcțională

Aplicația mobilă beneficiază de zece teste unitare și funcționale, patru dintre ele fiind funcționale. Toate se axează în principal pe testarea diferitelor metode ajutătoare folosite deseori în aplicație.

Două dintre testele unitare au drept scop testarea unor metode de extragere a textului vizibil dintr-un text HTML și trunchierea unui text HTML la un număr limitat de caractere, dar care returnează HTML valid prin închiderea tag-urilor lăsate deschise în urma trunchierii.

[TestMethod()]

public void CleanHtmlTest()

{

string html = "<body>\r\n\t<div class=\"topbar-inner\">\r\n\t\t<div class=\"container-fluid\">\r\n\t\t\t<a class=\"brand\" href=\"http://www.freeformatter.com\">FreeFormatter.com</a>\r\n\t\t\t<ul class=\"nav\">\r\n\t\t\t\t<li><a href=\"https://www.freeformatter.com\"><strong>HTTPS</strong></a></li>\r\n\t\t\t\t<li><a href=\"http://www.freedatagenerator.com\"><strong>FreeDataGenerator.com</strong></a></li>\r\n\t\t\t\t<li><a href=\"mailto:freeformatter@gmail.com\">Contact</a></li>\r\n\t\t\t</ul>\r\n\t\t\t<div class=\"social\" style=\"float:right;\">\r\n\t\t\t\t<div class=\"fb-like\" data-href=\"http://www.freeformatter.com\" data-send=\"false\" data-layout=\"button_count\" data-width=\"50\" data-show-faces=\"true\" data-font=\"arial\"></div>\r\n\t\t\t\t<!– Place this tag where you want the +1 button to render –>\r\n\t\t\t\t<div style=\"float: left; padding: 8px 5px 5px;\">\r\n\t\t\t\t\t<g:plusone></g:plusone>\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t</div>\r\n</body>\r\n<script type=\"text/javascript\">\r\n\t$(document).ready(\r\n\t\tfunction() {;}\r\n }\r\n</script>\r\n";

string cleaned = HtmlUtil.CleanHtml(html);

Assert.AreEqual(cleaned, @"FreeFormatter.com

HTTPS

FreeDataGenerator.com

Contact");

}

[TestMethod()]

public void TruncateHtmlTest()

{

string html = "<body>\r\n\t<div class=\"topbar-inner\">\r\n\t\t<div class=\"container-fluid\">\r\n\t\t\t<a class=\"brand\" href=\"http://www.freeformatter.com\">FreeFormatter.com</a>\r\n\t\t\t<ul class=\"nav\">\r\n\t\t\t\t<li><a href=\"https://www.freeformatter.com\"><strong>HTTPS</strong></a></li>\r\n\t\t\t\t<li><a href=\"http://www.freedatagenerator.com\"><strong>FreeDataGenerator.com</strong></a></li>\r\n\t\t\t\t<li><a href=\"mailto:freeformatter@gmail.com\">Contact</a></li>\r\n\t\t\t</ul>\r\n\t\t\t<div class=\"social\" style=\"float:right;\">\r\n\t\t\t\t<div class=\"fb-like\" data-href=\"http://www.freeformatter.com\" data-send=\"false\" data-layout=\"button_count\" data-width=\"50\" data-show-faces=\"true\" data-font=\"arial\"></div>\r\n\t\t\t\t<!– Place this tag where you want the +1 button to render –>\r\n\t\t\t\t<div style=\"float: left; padding: 8px 5px 5px;\">\r\n\t\t\t\t\t<g:plusone></g:plusone>\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t</div>\r\n</body>\r\n<script type=\"text/javascript\">\r\n\t$(document).ready(\r\n\t\tfunction() {;}\r\n }\r\n</script>\r\n";

string truncated = HtmlUtil.TruncateHtml(html, 100, "puncte puncte");

Assert.AreEqual(truncated, @"<body>

<div class=""topbar-inner"">

<div class=""container-fluid"">

<a class=""brand"" href=""http://www.freeformatter.com"">FreeFormatter.com</a>

<ul class=""nav"">

<li><a href=""https://www.freeformatter.com""><strong>HTTPS</strong></a></li>

<li><a href=""http://www.freedatagenerator.com""><strong>FreeDataGenerator.com</strong></a></li>

<li><a href=""mailto:freeformatter@gmail.com"">Contact</a></li>

</ul>

<div class=""social"" style=""float:right;"">

puncte puncte</div></div></div></body>");

}

Un alt test important este acela de a testa funcționalitatea metodei ce returnează o listă de partajări (share) posibile a unei informații selectate de utilizator, pe baza conținutului acesteia (text, imagine, link). Acesta este conceput într-un mod mai special deoarece a fost nevoie de accesul la membri privați ai unei clase, ceea ce a dus la folosirea reflecției (reflection) în C#, mecanism-ul de a obține informații despre clase și obiecte în momentul execuției programului.

În fluxul său, testul creează în mod dinamic tipul unei liste generice de enumerații (enum) folosită pentru a compara rezultatul returnat de apelarea metodei testate prin diverși parametri ce conțin elemente unei liste alcătuite în prealabil.

[TestMethod()]

public void GetAvailableShareTypesTest()

{

Type[] search = typeof(ShareServices).GetNestedTypes (BindingFlags.NonPublic);

Type shareTypeEnum = null;

foreach (Type type in search)

{

if (type.Name == "ShareEnumType")

{

shareTypeEnum = type;

break;

}

}

if(shareTypeEnum == null)

{

Assert.Fail("Could not find ShareTypeEnum!");

}

Type genericList = typeof(List<>);

Type genericListOfShareEnumType = genericList.MakeGenericType (shareTypeEnum);

String[] enumValues = System.Enum.GetNames(shareTypeEnum);

ShareServices aux = new ShareServices();

PrivateObject services = new PrivateObject(aux);

var list = services.Invoke("GetAvailableShareTypes", "title", "message", false, "", ""); // args: string title, string message, bool isRawImage, string link = "", string image = ""

Assert.IsInstanceOfType(list, genericListOfShareEnumType);

dynamic listOfShareEnumType = Convert.ChangeType(list, genericListOfShareEnumType);

Assert.IsTrue(listOfShareEnumType.Count == 2);

Assert.AreEqual(listOfShareEnumType[0], shareTypeEnum.GetField(enumValues[3], BindingFlags.Static | BindingFlags.Public)); // ShareStatus

Assert.AreEqual(listOfShareEnumType[1], shareTypeEnum.GetField(enumValues[4], BindingFlags.Static | BindingFlags.Public)); // ShareByEmail

list = services.Invoke("GetAvailableShareTypes", "", "message", false, "", "");

listOfShareEnumType = Convert.ChangeType(list, genericListOfShareEnumType);

Assert.IsTrue(listOfShareEnumType.Count == 1);

Assert.AreEqual(listOfShareEnumType[0], shareTypeEnum.GetField(enumValues[3], BindingFlags.Static | BindingFlags.Public)); // ShareStatus

list = services.Invoke("GetAvailableShareTypes", "", "", false, "", "");

listOfShareEnumType = Convert.ChangeType(list, genericListOfShareEnumType);

Assert.IsTrue(listOfShareEnumType.Count == 0);

list = services.Invoke("GetAvailableShareTypes", "title", "message", true, "", "");

listOfShareEnumType = Convert.ChangeType(list, genericListOfShareEnumType);

Assert.IsTrue(listOfShareEnumType.Count == 3);

Assert.AreEqual(listOfShareEnumType[0], shareTypeEnum.GetField(enumValues[2], BindingFlags.Static | BindingFlags.Public)); // ShareImage

Assert.AreEqual(listOfShareEnumType[1], shareTypeEnum.GetField(enumValues[3], BindingFlags.Static | BindingFlags.Public)); // ShareStatus

Assert.AreEqual(listOfShareEnumType[2], shareTypeEnum.GetField(enumValues[4], BindingFlags.Static | BindingFlags.Public)); // ShareByEmail

list = services.Invoke("GetAvailableShareTypes", "title", "message", false, "http://fmi.unibuc.ro/ro", "");

listOfShareEnumType = Convert.ChangeType(list, genericListOfShareEnumType);

Assert.IsTrue(listOfShareEnumType.Count == 3);

Assert.AreEqual(listOfShareEnumType[0], shareTypeEnum.GetField(enumValues[1], BindingFlags.Static | BindingFlags.Public)); // ShareLink

Assert.AreEqual(listOfShareEnumType[1], shareTypeEnum.GetField(enumValues[3], BindingFlags.Static | BindingFlags.Public)); // ShareStatus

Assert.AreEqual(listOfShareEnumType[2], shareTypeEnum.GetField(enumValues[4], BindingFlags.Static | BindingFlags.Public)); // ShareByEmail

list = services.Invoke("GetAvailableShareTypes", "", "", false, "", "http://www.joomlaworks.net/images/demos/galleries/abstract/7.jpg");

listOfShareEnumType = Convert.ChangeType(list, genericListOfShareEnumType);

Assert.IsTrue(listOfShareEnumType.Count == 1);

Assert.AreEqual(listOfShareEnumType[0], shareTypeEnum.GetField(enumValues[2], BindingFlags.Static | BindingFlags.Public)); // ShareStatus

}

Scenariile care au mai fost testate sunt:

descărcarea news feed-ului de pe Facebook;

convertirea corectă a datelor prin testarea unui convertor pentru imagini comprimate, și a altuia ce transformă un string cu niște ani într-unul cu sens pentru utilizator.

asigurarea funcționalității clasei RelayCommand

Testare destructivă

Testarea destructivă se referă la teste neconvenționale ce implică factori externi în utilizarea aplicației. Singurul astfel de factor ce poate periclita funcționalitatea aplicației este conexiunea la internet pentru descărcarea datelor.

Ceea ce s-a testat a fost schimbarea pachetelor trimise pe rețea către aplicație, iar rezultatele au fost următoarele:

la pachete transmise de multiple ori aplicația se comporta normal, nu se manifesta nicio eroare.

pachetele ce aveau modificat conținutul informației implicau închiderea cu eroare a aplicației.

la o conexiune slabă de date aplicația aștepta prea mult pentru primirea datelor și se închidea cu eroare.

Ultimele două cazuri în care apăreau erori grave au fost rezolvate în versiunea următoare a aplicației, prin tratarea excepțiilor apărute și afișarea utilizatorului doar a informațiilor existente în memoria cache, dacă existau.

Testarea clasei GZip Java

Pentru fluxurile de obiecte în Java (ObjectInput/OutputStream), se constată că înfășurarea fluxul de octeți în jurul celui gzip atât pentru intrare cât și ieșire este mult mai rapidă aproape întotdeauna la compresie și decompresie. Cu cât obiectele ce vor a fi compresate sunt mai mici, cu atât mai bine acest lucru este făcut.

ois = new ObjectInputStream(new BufferedInputStream(new GZIPInputStream(fis)));

oos = new ObjectOutputStream(new BufferedOutputStream(new GZIPOutputStream(fos)));

Cu toate acestea, pentru text și fluxuri de octeți simple (șir de biți), se remarcă faptul că fluxul gzip jurul fluxul de octeți se comportă mai bine față de configurația folosită mai sus, dar nu cu un impact al performanței semnificativ.

reader = new InputStreamReader(new GZIPInputStream(new BufferedInputStream(fis)));

writer = new OutputStreamWriter(new GZIPOutputStream(new BufferedOutputStream(fos)));

Fiecare dintre cele două metode a fost rulată de 20 de ori, dar primul test nu a fost luat în considerare (deoarece în această fază se procesează codul intermediar – bytecode – de către JIT) și s-a făcut media celorlalte 19.

Pentru fluxurile de obiecte (prima metodă) s-au testat pe două fișiere ce conțineau obiecte serializate (unul mare și unul mic). Pentru cel cu conținut bogat în fișier (38MB), citirea a fost cu 85% mai rapidă (0,7 față de 5.6 secunde) dar scrierea a fost ceva mai lentă (5,9 față de 5.7 secunde), totul comparat cu a doua modalitate propusă pentru folosirea gzip în Java.

În cazul fișierului mai mic (18MB), citirea a fost cu 75% mai rapidă (1,6 față de 6.1 secunde) și scrierea cu 40% mai rapidă (2.8 față de 4.7 secunde).

În ceea ce privește citirea / scrierea fișierelor text, folosind un fișier csv de 64MB, fluxul gzip jurul celui de octeți (a doua variantă) a fost cu 11% mai rapidă la citire (950 față de 1070 milisecunde) și puțin mai rapid atunci când se scrie (7,9 față de 8.1 secunde).

Concluzia testelor a fost că, pentru imaginile cu orarul facultății, este necesară folosirea celei de-a doua modalități de utilizare a clasei gzip, adică înfășurarea octeților imaginii cu un flux de octeți gzip deoarece imaginile, în memorie, reprezintă un șir de octeți simpli și nu un obiect complex.

Anexă

Manual de utilizare

Instalarea

De pe ecranul principal, utilizatorul deschide magazinul Store și folosind butonul de căutare, acesta caută aplicația după cuvintele cheie "fmi unibuc".

Odată găsită aplicația, se selectează rezultatul căutării pentru a vedea mai multe detalii despre aplicație, printre care și butonul de instalare.

În timp ce aplicația se instalează, utilizatorul poate continua să-și folosească dispozitivul în continuare sau poate urmări progresul instalării din meniul principal care listează toate aplicațiile.

Odată instalat, utilizatorul poate avea posibilitatea să adauge aplicația pe ecranul principal, apăsând pe ea și selectând opțiunea "pin to start". Prin această acțiune este creată o scurtătură pe ecranul principal și se poate vedea un live tile ce conține diferite imagini ale facultății.

Utilizarea

Odată deschisă, prima pagină ce va fi afișată va fi cea cu noutățile de pe pagina de Facebook a facultății. De aici, utilizatorul va face swipe către stânga sau dreapta pentru a naviga la diversele pagini sau poate selecta una din informațiile afișate pe ecran pentru a vedea mai multe detalii.

În următoarea secțiune se găsesc informații de pe prima pagină a facultății, și anume din următoarele categorii: Noutăți, Conferințe & Seminarii, Cercetare / Concursuri, Evaluare Instituțională, Anunțuri de la secretariat, Licență/Disertație, Stagii și locuri de muncă recomandate, Anunțuri despre cursuri și seminarii și Realizări studențești.

După selectarea unei categorii, în pagina ce va apărea, se pot lua următoarele acțiuni: pune la pagina principală o scurtătură la categoria respectivă, deschide browser-ul și a naviga către site-ul facultății, sau de a partaja (share) la informații folosind diverse aplicații instalate pe dispozitiv.

Pagina următoare conține informații ce sunt mai mult folositoare înainte și în timpul unei sesiuni de examene, și anume programa examenelor, expusă sub formă de link-uri către pdf-urile cu grila de examene de pe site-ul facultății. Se poate face și aici share la informațiile de pe pagină, și, în general, tot ce se regăsește în această aplicație se poate partaja de către utilizator.

Secțiunea următoare constituie un alt punct de informare important al unui student, și anume email-urile profesorilor. Acestea sunt împărțite pe departamente, la fel cum se regăsesc pe site-ul facultății. Dacă profesorul are asociat un email, prin apăsarea pe numele acestuia se lansează clientul de email, având ca destinatar email-ul profesorului. De asemenea, este pusă la dispoziția utilizatorului o casetă de căutare în care se poate căuta după nume sau prenume profesorul.

În pagina ce urmează se află calendarul cu structura anului universitar curent, așa cum se găsește pe site-ul universității.

Următoarea parte include schițele facultății (un plan al fiecărui etaj) și este destinată în special studenților nou veniți, ce nu știu să se orienteze în facultate. Tot aici, pentru un acces mai rapid, utilizatorul poate să creeze o scurtătură pe ecranul principal al dispozitivului către imaginea selectată.

Ca în orice altă aplicație ce prezintă date despre o instituție, și aici este prezentă pagină de contact, cu numere de telefon, email și link ce deschide harta și afișează locația facultății.

În ultima secțiune a aplicației se află cel mai important punct de informare al acestei aplicații, și anume orarul studentului. La fel ca și în alte locuri de până acum, utilizatorul poate să-și creeze o scurtătură către orarul grupei sale pe ecranul principal al dispozitivului.

În fiecare secțiune ce conține informații descărcate de pe internet, utilizatorul are posibilitatea de a face o reîmprospătare (refresh) a conținutului, accesând meniul de jos al paginii.

Pe pagina de Contact, în meniul din josul paginii, se afla trei butoane cu următoarele funcționalități: setează imagini de fundal cu facultatea la lockscreen, obține notificări cu privire la anunțuri noi și afișează informații despre versiunea aplicației.

Diagrame UML de clase

Diagrama de clase generală

1/2

2/2

MainViewModels

1/2

2/2

Anunțuri

Calendar, Examene, Profesori

Contact, Etaje, Departamente

Facebook

1/2

2/2

Pattern-ul folosit pentru a reda feed-ul de pe pagina de Facebook a facultății este mai bogat față ceea ce s-a folosit până acum, în sensul că Model-ul este alcătuit din mai multe clase ce ajută la descărcarea informației sub forma de feed RSS în mod sigur și în întregime.

Orar

Chiar dacă acest pattern se aseamănă cu cele ce folosesc date statice, în OrarDataSource este folosită aceeași logică pe care o folosește clasa ImportIOCall, doar adaptată pentru rezultatul returnat de către serverul de pe OpenShift.

Diagrame UML cazuri de utilizare

Diagrame de secvențe

Încărcarea datelor de pe Facebook

1/2

2/2

Încărcarea datelor de pe Import.IO

Execuție background task

1/2

2/2

Partajare informații

1/2

2/2

Încărcarea datelor în aplicație

1/2

2/2

Crearea unei scurtături pe ecranul principal

1/2

2/2

Diagrame de stări

Încărcarea aplicației

Scrierea în fișier

Citirea din fișier

Actualizare iconiță aplicația principală

Schimbarea imaginii lockscreen

Similar Posts