Issuu on Google+

No. 5 / 2012 • www.todaysoftmag.ro

TSM

T O D A Y S O F T WA R E MAG A Z I NE

Propriul start-up

Social networks

Tehnici SEO interne - partea I

Core Data – În spatele scenei

Google Guice

5 practici Java pe care le folosesc

Agile & Testing & Mobile - trei concepte convergente

Microsoft Kinect - Ghid de programare

Cum sa crești o mentalitate agilă în contextul dezvoltării software?

Testarea ca știință exactă

Joacă „Hard Choices” în fiecare sprint și rascumpără-ți datoriile! Designul experienței utilizatorului și moduri de aplicare în dezvoltarea produsului Construirea interfețelor web dinamice folosind MVVM și ASP.NET UseTogether. Ce? Cum? şi De ce? Planificator Ecologic pentru OpenNebula

Noutăți în Windows Communication Foundation 4.5 Service Bus Topics din Windows Azure Design-ul aplicaţiilor Android pentru toate platformele Malware pe Android statistici, comportament, identificare și neutralizare Gogu


6 Propriul start-up Călin Biriș

34 Construirea interfetelor web dinamice folosind MVVM si ASP.NET Csaba Porkoláb

10 UseTogether. Ce? Cum? şi De ce?

36 Social networks Andreea Pârvu

Echipa UseTogether

10 Tehnici SEO interne Radu Popescu

13 Google Guice Mădălin Ilie

16 Agile & Testing & Mobile 3 concepte convergente Rares Irimies

20 Design-ul aplicaţiilor Android pentru toate platformele Claudia Dumitraș

23 Cum sa cresti o mentalitate agila in contextul dezvoltarii software? Andrei Chirilă

26 Joacă „Hard Choices” în fiecare sprint si rascumpără-ti datoriile! Adrian Lupei

26 Planificator Ecologic pentru OpenNebula Ionut Anghel si Tudor Cioara

38 Core Data – În spatele scenei Zoltán, Pap-Dávid

41 5 practici Java pe care le folosesc Tavi Bolog

44 Microsoft Kinect - Ghid de programare Echipa Simplex

46 Testarea ca stiintă exactă Andrei Contan

47 Noutăti în Windows Communication Foundation 4.5 Leonard Abu-Saa

49 Service Bus Topics din Windows Azure Radu Vunvulea

52 Malware pe Android statistici, comportament, identificare si neutralizare Andrei Avădănei

31 Designul experientei utilizatorului si moduri de aplicare în dezvoltarea produsului Sveatoslav Vizitiu

54 Gogu Simona Bonghez


editorial

Editorial

Z

Ovidiu Măţan, PMP

ovidiu.matan@todaysoftmag.com Fondator și CEO Today Software Magazine

ilele acestea Apple a lansat iPhone 5, iar această informație probabile că este mai populară decât un campionat de fotbal întreg. Nu voi lua în considerare dacă partea de hardware este mai interesantă decât a concurenței, cert este că sunt asemănătoare, iar factorul major de diferențiere va fi sistemul de operare și diversitatea din App Store. Din acest punct de vedere iOS 6 a schimbat un pic regulile generale ale jocului prin introducerea suportului de hărți proprii, prin renunțarea la aplicatia YouTube, printr-o mai bună integrare cu rețelele sociale și o îmbunătățire a sincronizării datelor între device-uri aproape în timp real. Paradoxal, aceasta îl aproprie mai mult de strategia celor de la Microsoft unde vedem cam același lucru: sistemul propriu de hărți prin Nokia folosind Navteq, o foarte bună integrare a rețelelor sociale în OS și suportul de sincronizare. Android continuă trend-ul de disruptive business, prin oferirea sa gratuită, dar multitudinea de device-uri care pot fi suportate face uneori destul de provocatoare dezvoltarea de aplicații. În funcție de device experiența utilizatorului variază mult. Dacă acum zece ani, tot ceea ce conta era platforma hardware și implicit producătorul dispozitivului cum ar fi Nokia sau Sony Erricson în zilele noastre luăm in considerare mai mult ceea ce oferă sistemul de operare în sine. Ecosistemul la care se primește acces devine mai valoros decât hardware-ul achiziționat. Din toate acestea, un dezvoltator de software ar trebui să înțeleagă că un singur produs poate avea un succes pe term scurt și că pe termen lung contează crearea acelui ecosistem care conține o experiență cât mai completă a utilizatorilor pentru domeniul țintă. Pentru programatori lecția s-ar traduce prin punerea accentului pe diversitate și pe preocuparea de a înțelege toate nivelele unui astfel de ecosistem, de a se implica activ în dezvoltarea sa începând cu aplicația ce rulează pe device și terminând cu backend-ul. Numărul curent al revistei contine cu 40% mai multe articole decât în numărul precedent și poate fi considerat o expresie a acestei diversități. Accentul pus pe metodologia Agile și multitudinea de articole care pornesc de la definirea layout-ului aplicației pe dispozitivele Android, tehnici de optimizare SEO, Goolge Guice, Core Data iOS, best practice-uri Java, noutăți WCF 4.5, Service Bus din Windows Azure, design-ul experienței utilizatorului, statistici și comportament al virușilor Android și multe altele pe care le puteți găsi în paginile revistei oferă cititorilor o gamă variată de subiecte. Importanța ecosistemului poate fi extinsă și la nivel local iar aici revista TSM sprijnă comunitatea pentru o mai bună comunicare și împărtășire a experienței tehnice a programatorilor și nu numai. Implicarea mediului academic pentru o colaborare cu firmele de IT din Cluj și accentuarea importantanței research-ului va fi dezbătută într-un eveniment special, vom reveni cu detalii. Colaborarea cu cercetătorii locali poate fi de asemenea un prilej bun de pornire a unor startup-uri locale care s-ar dovedi astfel cu adevărat inovatoare. Închei prin a mulțumi tuturor colaboratorilor, sponsorilor revistei și nu în ultimul rând vouă cititorilor. Mulţumesc,

Ovidiu Măţan 4

nr. 5/2012 | www.todaysoftmag.ro

Fondator și CEO Today Software Magazine


TODAY SOFTWARE MAGAZINE Redacţie

Lista autorilor Călin Biriș

Fondator / Editor in chief: Ovidiu Mățan ovidiu.matan@todaysoftmag.com Editor (startups și interviuri): Marius Mornea marius.mornea@todaysoftmag.com

calin.biris@gmail.com

Sveatoslav Vizitiu info@sveatoslav.com

Călin Biriş este Crocodilul de Marketing la Trilulilu şi Preşedinte al IAA Young Professionals Cluj.

User Experience and User interface Senior Designer

Mădălin Ilie

Graphic designer: Dan Hădărău dan.hadarau@todaysoftmag.com

madalin.ilie@endava.com

Andreea Pârvu

Cluj Java Discipline Lead @ Endava

andreea.parvu@endava.com

Colaborator marketing: Ioana Fane ioana.fane@todaysoftmag.com Radu Popescu

Reviewer: Romulus Pașca romulus.pasca@todaysoftmag.com Reviewer: Tavi Bolog tavi.bolog@todaysoftmag.com Produs de

Today Software Solutions SRL str. Plopilor, nr. 75/77 Cluj-Napoca, Cluj, Romania contact@todaysoftmag.com www.todaysoftmag.ro www.facebook.com/todaysoftmag twitter.com/todaysoftmag ISSN 2284 – 6352

rpopescu@smallfootprint.com QA şi Web designer @ Small Footprint

Radu Vunvulea

Rareș Irimieș

Senior Software Engineer @iQuest

Senior QA @ 3Pillar Global Romania

Zoltán, Pap-Dávid

Claudia Dumitraș claudia.dumitras@skobbler.ro

zpap@macadamian.com Software Engineer @ Macadamian

Android Developer @ Skobbler

Simona Bonghez, Ph.D. Tavi Bolog tavi.bolog@nokia.com

Andrei Chirilă Andrei.Chirila@isdc.eu Team Leader Technical Architect @ ISDC

Reproducerea parțială sau totală a articolelor din revista Today Software Magazine fără acordul redacției este strict interzisă.

Radu.Vunvulea@iquestgroup.com

rares.irimies@threepillarglobal. com

Development lead @Nokia

Copyright Today Software Magazine

Recruiter în cadrul Endava și trainer specializat în dezvoltarea abilităților si competenețelor de leadership

Simona.bonghez@confucius.ro Speaker, trainer şi consultant în managementul proiectelor, Owner al Confucius Consulting

Echipa Simplex

simplex@todaysoftmag.com

Adrian Lupei alupei@bitdefender.com

Ionuț Anghel, Ph. D

Project Manager și Software Engineering Manager @ Bitdefender

Asistent Doctor Inginer Departamentul Calculatoare Facultatea de Automatica si Calculatoare

Leonard Abu-Saa

Andrei Conțan

System Architect @ Arobs

Principle QA @ Betfair Co-Founder Romanian Testing Community

leonard.abu-saa@arobs.com

ionut.anghel@cs.utcluj.ro

andreicontan@hotmail.com

Tudor Cioară, Ph. D

www.todaysoftmag.ro www.todaysoftmag.com

tudor.cioara@cs.utcluj.ro Asistent Doctor Inginer Departamentul Calculatoare Facultatea de Automatica si Calculatoare

Andrei Avădănei andrei@worldit.info Fondator si CEO DefCamp CEO worldit.info

www.todaysoftmag.ro | nr. 5/2012

5


startups

Propriul startup

G

ândește-te la trei branduri locale de online, care au pornit din Cluj și au ajuns să aibă succes la nivel național sau internațional. Nu-i așa că este greu să le găsești? Deși, dacă te gândești la principalele centre IT din România, Clujul este în primele trei. Avem mulți practicieni în IT, dar care sunt absorbiți de companiile de outsourcing. Prea puține sunt companiile care si-au dezvoltat produse proprii.

Călin Biriș

calin.biris@trilulilu.ro Călin Biriş este Crocodilul de Marketing la Trilulilu şi Preşedinte al IAA Young Professionals Cluj. Pasionat fiind de mediul online şi de marketing, a ţinut zeci de prezentări despre publicitate online şi marketing, atât pentru studenţi cât şi pentru mediul de business. Este o persoană activă în mediul online pe blogul personal www.calinbiris.ro şi pe reţelele sociale.

6

nr. 5/2012 | www.todaysoftmag.ro

Am auzit că piața din Cluj se va schimba. Salariile din domeniu cresc și au ajuns la un nivel mare, comparabil cu nivelul salariilor din țările vestice. Companiile de outsourcing vor începe să sufere din acest motiv iar clienții lor vor începe să își îndrepte proiectele către alte piețe mai ieftine. O direcție sănătoasă pentru orice companie locală de outsourcing ar fi să înceapă să construiască produse proprii care să se adreseze la mai multe piețe de clienți. Astfel, difersificând portofoliul, nu vor ține toate ouăle în același coș iar riscurile vor fi împărțite. Dar de ce să aștepți după compania în care lucrezi să te pună într-o echipă pe un produs nou, când poți chiar tu să pornești un start-up în afara orelor de birou și să lucrezi și pentru tine? Avantajul tău în acest moment este că lucrezi pe un salar bun și că în timpul liber te poți concentra pe proiecte proprii de viitor. Dacă te gândești la un start-up lucrurile

cele mai importante pe care ar trebui să le iei în considerare: echipa, banii și ideea.

Echipa

Cea mai importantă resursă într-un start-up este cea de capital uman, adică specialiștii. Mulți care se gândesc să pornească un start-up cad în capcana banilor, crezând că fără bani de investiție nu pot realiza un produs de succes pe piață și din acest motiv nu se mai apucă de nimic. Eu cred că dacă vei reuși să faci o echipă bună, care să livreze un produs de valoare, cu un model de business sănătos, banii vor veni. Problema echipei este că aceasta trebuie să fie formată din membri cu aptitudini complementare. Când a pornit Trilulilu, proiectul a avut o echipă inițială formată din buni specialiști în design, programare, administrare de server, management, branding și legal. O mână de oameni care s-au completat unii pe ceilalți și care au lucrat pentru același scop de a lansa pe piață un serviciu de impact. Gândește-te la competențele de care vei


management

TODAY SOFTWARE MAGAZINE

avea nevoie în start-up-ul tău și găsește cei odată cu creșterea numărului de clienți Cel mai ușor mod de a testa o idee este mai buni oameni care să se implice alături plătitori. să încerci să vinzi produsul înainte să îl de tine. realizezi efectiv. S-ar putea să găsești clienți Ideea dispuși să plătească acum pentru o soluție Banii Am avut mai multe ocazii să stau de pe care să o livrezi doar peste un anumit Dacă ai pornit un start-up care crezi vorbă cu dezvoltatori care doreau să se timp. Din același test vei putea descoperi că are potențial, este mai ușor decât te-ai implice în proiecte proprii, dar care nu nevoi la care nici nu te-ai gândit inițial că aștepta să ajungi la persoane dispuse să îți aveau o idee în care să creadă că va avea vor putea fi acoperite de serviciul sau proofere feedback sau chiar să investească în succes pe piață. Pe lângă acest lucru, din dusul tău. ideea echipei tale. cauza inerției de a lucra pentru proiectele Dar totuși de ce să începi să lucrezi la Am scris recent pe blogul propriu des- altor clienți, nu aveau timpul să se gân- un start-up și să nu te mulțumești cu ce ai pre evenimentele dedicate start-up-urilor, dească la propiectele proprii. Cel mai bun acum? unde se întâlnesc învestitorii de tip Angel lucru care ar putea să îl facă este să încerce Pentru că ai posibilitatea: cu echipe care au nevoie de bani pentru să găsească idei prin networking. • Să lucrezi la propriile idei, un produs pe care îl dezvoltă. Sunt deja Participând la mai multe competiții de • Să câștigi mai bine, o mână de astfel de evenimente care se start-up-uri am realizat că cele mai bune • Să fii mai apreciat pentru ceea ce întâmplă anual. idei vin de la oameni care poate nu sunt creezi, Însă nu toți investitorii doresc să pro- atât de orientați către partea de IT ci mai • Să cunoști mai mulți oameni și să moveze că au bani de dat. Am aflat și de mult către partea de business. Poate din călătorești mai mult, persoane care au bani puși deoparte și care acest motiv ar trebui organizate tot mai • Să nu ai toate ouăle în același coș, în așteaptă echipa potrivită în care să inves- multe întâlniri între specialiști din busicaz că se întâmplă ceva. tească, chiar dacă nu participă la astfel de ness cu specialiști în IT, care să încerce să evenimente. găsească acele idei de start-up care ar avea Degeaba Clujul este în topul centrelor De asemenea, te poți gândi și la alte șanse de reușită. IT din țară, dacă nu ne putem lăuda cu surse de finanțare precum împrumuturile Dacă nu ai o idee de start-up, încearcă propriile realizări. Depinde numai de tine bancare, fondurile nerambursabile sau cei să te întâlnești tot mai mult cu oameni să încerci ceva nou, să faci o echipă și să 3F – friends, family and fools. din domenii diferite de al tău și descoperă începi ceva, orice. Ai mai multe de câștigat Însă mai important decât ”cum vei face oportunități pe care le-au văzut în diferite decât de pierdut. Gândește-te. rost de investiție pentru start-up” este să te piețe. Poate împreună veți găsi soluții care gândești care va fi modelul de business pe ar putea avea succes. care îl vei urma și cum vei face bani. Dacă Dar cum îți dai seama că o idee este ai un răspuns bun la asta, investiția va veni bună?

www.todaysoftmag.ro | nr. 5/2012

7


startups

UseTogether. Ce? Cum? şi De ce?

T

otul a început în urmă cu aproximativ șase luni la Startup Weekend Cluj, unde, doisprezece persoane care se întâlneau atunci pentru prima dată au hotărât să îşi unească forţele în jurul unei idei simple dar puternice: de ce să cumperi când poţi împrumuta? Planul părea destul de simplu: trebuia să punem cap la cap cele mai bune idei pe care le aveam şi să construim un proof of concept pentru o platformă online dedicată schimbului de obiecte. Din fericire, întreaga experienţă a fost printre site-urile populare implementate wiki, CLI precum și un API. Ca sisteme de una mai mult decât pozitivă. Am plecat în Django se numără Pinterest, Instagram, versionare, Phabricator poate lucra cu Git, de acolo cu sfaturi, idei şi perspective noi Mozilla, The Washington Times și Public Subversion și Mercurial și poate fi rulat de şi, poate cel mai important, am primit Broadcasting Service. pe Linux, Mac și chiar Windows. validarea conceptului de la care a pornit Problema cu tehnologiile fiind rezolPentru noi, code review-urile s-au proiectul. vată, mai aveam nevoie doar de un sistem dovedit a fi o adevărată mană cerească. Au urmat o mulţime de şedinţe, pla- de project management și issue tracking. Dacă atunci când ai de scris cod ești disnuri, schiţe şi mâzgălituri şi, lucrând în Ne-am decis inițial să folosim Trac. După pus să te înduri de propria-ți persoană și timpul rămas liber dintre locul de muncă, cum e descris și pe http://trac.edgewall. să renunți la calitatea codului în favoarea facultate, familie, prieteni şi tot felul de alte org/, Trac e un sistem minimalist ce com- soluțiilor quick and dirty, din fericire, noi îndatoriri, astăzi putem spune cu bucurie bină un wiki și un issue tracker. E ideal oamenii suntem destul de neiertători cu cei că UseTogether.ro se află în final în beta şi pentru proiectele în cadrul cărora se știe din jurul nostru. Și dacă de cele mai multe merge (sperăm) pe drumul cel bun. ce e de făcut și comunicarea față în față ori nu ești dispus să vezi bârna din propriul Acest articol va descrie aventurile se produce ușor și frecvent. Din păcate, ochi, vă asigur că până și cele mai mici paie developmentului din cadrul UseTogether noi nu îndeplineam nici măcar una din- din ochiul celuilalt au fost scoase la iveală precum şi suita de tehnologii pe care tre condițiile de mai sus. Nu aveam o idee în modul ăsta. Nu pot să subliniez îndealucrăm şi care ne fac viaţa mai uşoară. Deși perfect închegată vizavi de modul în care juns importanța code review-urilor într-un am câștigat Startup Weekend Cluj cu o arhi- vom aborda proiectul și fiind și angajați / proiect ca UseTogether, cu o echipă mică de tectură clasică PHP, MySQL și JavaScript, studenți, reușeam să ne întâlnim toți patru devi, în care oricare dintre membri trebuie am ajuns destul de rapid la concluzia că mai mult în weekend-uri. să fie în stare să înțeleagă și să modifice aveam nevoie de ceva mai puternic si mai Așa că ne-am reorientat spre ceva mai orice parte din cod. flexibil dacă aveam de gând să oferim ideii complex, care să ne permită să fim mai Și nu în ultimul rând, trusa noastră de de UseTogether o implementare pe măsură. bine conectați la întregul proces de deve- tool-uri a fost completată de Git. De ce Git? După lungi discuții asupra tehnologiilor pe lopment. Din fericire, cei de la Facebook Pentru că e distribuit, foarte ușor de folosit care urma să le folosim, ne-am oprit în cele au avut probleme similare cu mult înain- și foarte rapid. din urmă asupra framework-ului Django tea noastră și, ca răspuns la ele, s-a născut Pe final, vă urăm cât mai puține bugca piatră de temelie pentru proiect. Django Phabricator. Phabricator este o suită de uri critice și vă lăsăm cu o fărâmă de e un framework web MVC scris în Python aplicații web menite să facă viața devilor înțelepciune: “Python is a drop-in replacecare pune accent pe development rapid și mai ușoară și deși seamănă destul de mult ment for BASIC in the sense that Optimus design simplu și pragmatic. cu sisteme precum Trac sau Redmine, o Prime is a drop-in replacement for a truck.” Apărut în jurul anului 2005 din frus- scurtă vizită pe http://phabricator.org/ - Cory Dodt. trarea autorilor săi de a întreține site-uri va dezvălui că acesta din urmă se ia ceva complexe scrise în PHP, Django și-a înce- mai puțin în serios: Facebook engineers put viața ca un layer de abstractizare între rave about Phabricator, describing it with codul Python propriu zis și mod_python. glowing terms like „okay” and „mandaDeși intenția nu a fost de a crea un fra- tory”. De la descrieri precum “Shows code mework web, sătui să mai copieze cod de so you can look at it”, până la Close a ticket la un proiect la altul, autorii au reușit să “out of spite” sau butonul de Submit care a abstractizeze și să dezvolte layer-ul inițial fost redenumit în “Clowncopterize” (becasuficient de mult încât experiența de a lucra use clowns and helicopters are awesome), în Django să devină una mai mult decât Phabricator este ca o lungă plimbare prin plăcută. Nerdtown, pe Geek street. Un tool scris de Totuși de ce Django și nu, spre exem- programatori pentru programatori. plu, Ruby on Rails? Pentru noi, motivația Dincolo de interfața hazlie, foarte ase- Echipa UseTogether a fost destul de simplă: toți patru lucrasem mănătoare cu Facebook, Phabricator îți De la stanga la dreapta, pe randul de sus: deja mai mult sau mai puțin în Python și, oferă tot ce ți-ai putea dori de la un sis- Daniel Rusu, Mircea Vădan, Alex Țiff, Cătălin Pintea, Gabi Nagy, Paul în plus, Django a fost numit după un chita- tem de project management modern: code Călin, Adriana Valendorfean, Victor Miron; iar pe randul de jos: Larisa Anghel, Ioana Hrițcu, Sorina Andreșan, Alina Borbely rist și anume - Django Reinhardt. Ca idee, review, issue tracking, source browsing,

8

nr. 5/2012 | www.todaysoftmag.ro


TODAY SOFTWARE MAGAZINE

Comunităţi IT Cluj-Napoca

S

ecţiunea comunitate îşi propune să ţină evidenţa grupurilor de profesionişti relevante pentru industria IT, dar şi un calendar de evenimente şi întâlniri din acest sector. Pentru început prezentăm principalele iniţiative din mediul local, în timp intenţionând să creştem acest index până ce va conţine toate comunităţile locale, dar şi cele naţionale cu prezenţă şi activitate pe plan local. Criteriul ales pentru ordonare este în funcţie de numărul de membri şi de activitatea grupurilor (evenimente locale) raportate la durata lor de viață astfel sperăm să obţinem o ierarhie a gradul de implicare, al organizatorilor şi al membrilor.

Transylvania Java User Group Comunitate dedicată tehnologiilor Java. Website: http://www.transylvania-jug.org/ Data înfiinţării: 15.05.2008 / Nr. Membri: 493 / Nr. Evenimente: 38 Romanian Testing Community Comunitate dedicată QA. Website: http://www.romaniatesting.ro Data înfiinţării: 10.05.2011 / Nr. Membri: 520 / Nr. Evenimente: 1 Cluj.rb Comunitate dedicată tehnologiilor Ruby. Website: http://www.meetup.com/cluj-rb/ Data înfiinţării: 25.08.2010 / Nr. Membri: 112 / Nr. Evenimente: 27

Calendar Septembrie 25

Technical Days C++ C o nt a c t : ht t p : / / b l o g . p e o p l e - c e nt r i c . r o / n e w s / un-nou-eveniment-technical-days-c-la-cluj

Septembrie 26

Open Coffee Meetup - #HaSH - Hack a Server Hackathon Contact: http://www.facebook.com/opencoffeecluj/events

Septembrie 29

Windows 8 Dev Camp Contact: http://codecamp-cluj-sept2012.eventbrite.com

The Cluj Napoca Agile Software Meetup Group Comunitate dedicată metodelor Agile de dezvoltare software. Website: http://www.agileworks.ro Data înfiinţării: 04.10.2010 / Nr. Membri: 234 / Nr. Evenimente: 13

Octombrie 2

Cluj Semantic WEB Meetup Comunitate dedicată tehnologiilor semantice. Website: http://www.meetup.com/Cluj-Semantic-WEB/ Data înfiinţării: 08.05.2010 / Nr. Membri: 125 / Nr. Evenimente: 18

HTML5 and Problem solving in Web Design Contact: http://www.meetup.com/Cluj-Semantic-WEB

Romanian Association for Better Software Comunitate dedicata oamenilor cu experienta din IT indiferent de tehnologie sau specializare. Website: http://www.rabs.ro Data înfiinţării: 10.02.2011 / Nr. Membri: 173 / Nr. Evenimente: 9

Patterns for Parallel Programming Contact: http://www.rabs.ro

Octombrie 17

Noiembrie 9

Artificial Intelligence, Computational Game Theory, and Decision Theory - Unifying paths Contact: workshop2012@rist.ro

Google Technology User Group Cluj-Napoca Comunitate dedicată tehnologiilor Google. Website: http://cluj-napoca.gtug.ro/ Data înfiinţării: 10.12.2011 / Nr. Membri: 25 / Nr. Evenimente: 7 Cluj Mobile Developers Comunitate dedicată tehnologiilor mobile. Website: http://www.meetup.com/Cluj-Mobile-Developers/ Data înfiinţării: 08.05.2011 / Nr. Membri: 45 / Nr. Evenimente: 2

www.todaysoftmag.ro | nr. 5/2012

9


programare

Tehnici SEO interne partea I

D

acă în numărul precedent am putut vedea care au fost cele mai importante modificări ale algoritmilor de căutare ai Google, în acest număr am decis să realizăm un articol în care să prezentăm unele dintre cele importante tehnici de optimizare pentru motoarele de căutare, aplicabile zonei de SEO intern. Aceste tehnici, deşi uşor de aplicat, oferă rezultate foarte bune pe termen lung, în privinţa creşterii traficului organic. În cele ce urmează vă propunem spre informare aceste câteva tehnici.

Radu Popescu

rpopescu@smallfootprint.com QA şi Web designer @ Small Footprint

10

nr. 5/2012 | www.todaysoftmag.ro

Meta tags

Rolul tagului <title> este identic cu al tagului <meta description>, adică de a creşte rata de click în pagina de rezultate. Folosirea unor titluri interesante sau cuvinte cheie în interiorul tagului, pe cât posibil în primele cuvinte, va creşte această rată de click. În cazul în care se doreşte folosirea unui nume de brand în tagul <title> avem parte de două abordări diferite. Dacă brandul e unul cunoscut, este recomandat ca acesta să se regăsească aproape de începutul tagului (exemplu: Nume Brand | Nume Pagina). În cazul brandurilor mici sau noi, trebuie să adăugăm numele brandului spre finalul tagului (exemplu: Nume Pagina | Nume Brand). Aceste abordări pornesc de la ideea că numele unui brand important are un impact foarte puternic în decizia de a da click pe respectivul rezultat, pe când un brand necunoscut nu va atrage clickuri. Lungimea tagului <title> trebuie să fie în intervalul 10-64 caractere, astfel că trebuie evitate cuvintele fără valoare descriptivă, care doar ocupă spaţiul, precum “de”, “pe”, “în”, “pentru” etc. E x i st ă u n m it l e g at d e < Me t a

Keyword>, şi anume că trebuie să avem cât mai multe cuvinte cheie într-o pagină, acestea fiind importante în SERPS. Nimic mai fals. Încă din septembrie 2009, Matt Cutts (care ocupa la vremea respectivă poziţia de Search Quality Manager) anunţa, pe unul din blogurile Google, că celebrul motor de căutare nu va mai ţine cont de <Meta Keywords>. Adăugarea şi folosirea acestui tag nu este dăunatoare, dar totuşi ne răpeşte din timpul necesar altor sarcini, având în vedere că tagul nu este folosit. Încă un mit ar fi acela că <meta description> ar ajuta la apariţia unei pagini cât mai sus în rezultatele Google. De fapt, rolul acestui meta tag este acela de a convinge cât mai multe persoane să dea click pe rezultatul nostru. <Meta description> este o unealtă care ajută foarte mult în creşterea ratei de click în SERPS. Toate persoanele care văd o pagină cu rezultate (în urma unei căutari Google) vor trebui să decidă pe care din linkurile afişate vor intra. Descrierea care oferă un sumar foarte bun sau interesant al conţinutului va determina majoritatea oamenilor să dea click pe linkul respectiv. O abordare mai controversată în


TODAY SOFTWARE MAGAZINE

cazul acestui meta tag este folosirea unor descrieri foarte interesante, dar incomplete (terminate în mijlocul unei idei cu trei puncte de suspensie). Aceasta va face ca persoana care e pusă în faţa respectivului rezultat să dorească foarte mult să afle mai multe detalii despre descriere, astfel încât va da click. Legat de lungimea descrierii, trebuie menţionat că aceasta ar trebui să fie între 50-150 de caractere, pentru cele mai bune rezultate.

Fişierul Sitemap.xml şi rolul său

Sitemap-ul este un fişier de tip XML, care ajută motoarele de căutare să găsească mai uşor paginile pe care le va indexa, oferind o listă care conţine toate URL-urile site-ului. Acest fişier a fost folosit pentru prima dată de către Google în 2005, iar în 2006 motoarele de căutare MSN şi Yahoo au anunţat că vor utiliza şi ele sitemapul pentru indexare. Formatul fişierului Sitemap.xml este unul foarte simplu, astfel încât oricine îl poate crea. Există totuşi generatoare online gratuite care pot face acest lucru într-un timp mult mai scurt. Dintre acestea, cel mai bun şi rapid este www.xml-sitemaps.com. În cazul în care acest fişier va conţine peste 50.000 de URLuri sau va avea o dimensiune mai mare de 10 Mb, trebuie comprimat în format gzip. <?xml version=”1.0” encoding=”utf-8”?> <urlset xmlns=”http://www.sitemaps.org/schemas/ sitemap/0.9”> <url> <!-- această secţiune se va repeta pentru fiecare pagină în parte --> <loc>http://example.com/</loc> <!-- adresa paginii --> <lastmod>2006-11-18</lastmod> <!--data ultimei modificări a conţinutului --> <changefreq>daily</changefreq> <!--intervalul de schimbare al conţinutului--> <priority>0.8</priority> <!-- prioritatea paginii (poate varia de la 0.0 pana la 1.0) --> </url> </urlset>

Odată creat, fişierul Sitemap.xml va trebui adăugat în directorul de bază al sitului (root), fiind accesibil prin adresa www. exemplu.ro/sitemap.xml.

Validarea codului HTML şi importanţa sa

Un lucru de foarte multe ori uitat sau dat la o parte din cauza timpului redus de dezvoltare este validarea codului HTML. Ne amintim cu toţii de vremurile în care pe majoritatea site-urilor erau prezente, în zona inferioară, etichete sau mici logo-uri pe care scria că acel site conţine cod HTML

şi CSS valid. De fapt, ele nu erau doar un • Lipsa artibutului ALT din interiorul motiv de laudă, ci ajutau în principiu la tagului pentru imagini SEO. Motoarele de căutare trebuie să par• Imbricarea incorectă a tagurilor. seze codul HTML, pentru a găsi conţinutul. Iată un mod greşit de imbricare În momentul în care există anumite erori, <div><b>TEXT</div></b>. Modul este posibil ca unele părţi din site să nu corect este: <div><b>TEXT</b></ poată fi luate în considerare, astfel că toată div> munca de optimizare a conţinutului va fi în • Convertirea caracterelor speciale zadar. în simboluri de tip Entity. În cazul Printre cele mai comune erori de valicaracterului “©” în codul HTML dare HTML amintim următoarele: vom folosi “&copy;” • Închiderea unor taguri. Tagul <div> se va închide prin </div>, în timp ce Verificarea validităţii codului HTML se tagul <img> se va închide într-un poate realiza folosind unealta gratuită pusă singur format <img /> la dispoziţia oricui pe site-ul www.valida• Folosirea unui DOCTYPE incorect tor.w3.org. Deşi nu toate erorile HTML pot www.todaysoftmag.ro | nr. 5/2012

11


programare

avea consecinţe asupra SEO, este recomandat să avem un cod valid şi curat, măcar din considerente legate de profesionalism şi calitate.

<Bold> vs. <strong> şi <i> vs. <em>

Trebuie să întelegem că motoarele de căutare, în momentul în care se uită la o pagina web, nu văd acelaşi lucru ca o persoană reală. Ele văd codul sursă şi îl analizează. Din această cauză, deşi pentru noi un text cuprins în tagul <b> (bold) arată la fel ca un text cuprins în tagul <strong>, motoarele de căutare văd două lucruri total diferite. Tagul <b> este perceput ca un tag de design, oferind un stil mai pronunţat cuvintelor asupra cărora este folosit, pe când tagul <strong> oferă o informaţie semantică, prin care se evidenţiază conţinutul. În general, tagul <em> va fi folosit pentru conţinutul generat de către utilizatori (testimoniale sau recenzii), tagul <strong> pentru a marca diferite cuvinte cheie în interiorul conţinutului iar pentru stilizarea textului se vor evita pe cât posibil tagurile <b> şi <i>, folosind proprietăţile CSS <font-weight> şi <font-style>.

Redirectarea adresei non-www către adresa www

Tehnici SEO interne - partea I

SEO ale domeniului redirectat către noul domeniu. În general, se va folosi acest tip de redirectare în cazul mutării unui site pe un alt domeniu, fără a pierde foarte mult din traficul organic venit de pe Google. De foarte multe ori, se trece cu vederea faptul că adresa www.exemplu.ro şi exemplu.ro sunt văzute ca fiind diferite de către motoarele de căutare, iar puterea SEO a linkurilor externe poate să fie înjumătăţită. Redirectarea de tip 301 a adresei exemplu. ro, către www.exemplu.ro ne va ajuta să avem un rank mai bun. Pentru a înţelege mai bine acest lucru, ne putem gândi că avem 50 de linkuri de pe blogurile unor prieteni către exemplu.ro şi 50 de linkuri de pe diferite alte site-uri către www.exemplu.ro. Cele 100 de linkuri se împart între două adrese diferite, dar printr-un simplu 301 redirect, putem avea 100 de linkuri către aceeaşi adresă, dublând astfel autoritatea sitului nostru. Acest tip de redirectare se poate realiza prin intermediul panoului de control al contului de hosting, prin folosirea unui fişier .htaccess în cazul siturilor construite folosind PHP sau prin fişierul webconfig în cazul siturilor care folosesc tehnologii Microsoft.

Concluzii

Redirectarea 301 este un tip de redirecUn lucru foarte important de ştiut tare permanentă care va permite trecerea este că optimizarea excesivă poate avea a peste 90% din optimizarea şi beneficiile un impact negativ asupra site-ului, după

12

nr. 5/2012 | www.todaysoftmag.ro

introducerea actualizării Pinguin, despre care am vorbit în numărul precedent. Folosirea exactă a aceluiaşi cuvânt sau grup de cuvinte în tagurile meta, în titlul paginii, în tagul <h1> dar şi în interiorul conţinutului poate duce la o penalizare. Este recomandat să folosim mai multe variaţii ale unui cuvânt cheie sau construcţii modificate ale unui anumit grup de cuvinte. Deşi majoritatea acestor tehnici par, la o primă vedere, a fi simple, ele oferă un mare plus în optimizarea pentru motoarele de căutare. Ramura internă a SEO ţine în principal de acţiunile persoanelor care construiesc sau deţin un site, nu de factori externi, iar acest lucru ne face să le acordăm o atenţie sporită şi ne oferă încrederea că rezultatele vor fi reale. În numărul viitor, vom veni în completarea acestui articol cu o serie de tehnici de optimizare internă.


programare

TODAY SOFTWARE MAGAZINE

Google Guice

A

șa cum am promis în articolul trecut, voi continua prezetarea containerului Google Guice și pentru aplicații web. Pentru aceasta aveți nevoie de extensia de Servlet – parte din distribuția standard, alături de alte extensii precum JMX, JNDI, Persist, Struts sau Spring. Folosind Guice web.xml-ul se reduce doar la punerea containerului Guice în ”mișcare”, restul configurarilor făcându-se simplu în codul Java în maniera type-safe prezentată în articolul trecut.

Mădălin Ilie

madalin.ilie@endava.com Cluj Java Discipline Lead @ Endava

Servleții vor ”beneficia” de următoarele avantaje: • Injectare la nivel de constructor, • Configurare Type-safe, • Modularizare, • AOP. Voi prezinta în acest articol două scenarii: • Dezvoltarea de la 0 a unei aplicații web, • Intergrarea într-o aplicație existentă.

Start-ul unei aplicatii web folosind Google Guice

Aveți în dreapta un snapshop din Eclipse cu structura proiectului. Pe lângă librăriile Guice core prezentate în articolul trecut, classpath-ul trebuie să conțină și librăria guice-servlet.jar (Verificați sfârșitul aritcolului pentru dependința de Maven). După ce classpath-ul este configurat, primul pas îl reprezintă definirea filtrului de Guice în web.xml. Aceasta va fi de altfel și singura configurare pe care o va conține acest fisier. Web.xml: <?xml version=”1.0” encoding=”UTF-8”?> <web-app xmlns=”http://java.sun.com/xml/ns/javaee” xmlns:xsi= ”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation= ”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee /web-app_3_0.xsd” version=”3.0”> <display-name>Guice Web</display-name> <filter> <filter-name>guiceFilter</filter-name> <filter-class> com.google.inject.serv let.GuiceFilter </filter-class>

</filter> <filter-mapping> <filter-name>guiceFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>

Ne-am asigurat astfel că toate requesturile vor fi procesate de Guice. Următorul pas îl reprezintă construirea Injector-ului și definirea modulelor. Pe lângă modulele „obișnuite” care pot fi prezente în aplicație - descrise în articolul trecut , pentru a folosi într-adevar modulul de Guice Servlet trebuie să instalăm o instanță de com.google.inject. servlet.ServletModule. Acest modul este www.todaysoftmag.ro | nr. 5/2012

13


programare Google Guice

responsabil pentru setarea scopurilor de import com.google.inject.Singleton; Request si Session și este locul unde vom @Singleton class MyServlet extends HttpServlet { configura servleții si filtrele folosite în public private static final long serialVersionUID = 1861227452784320290L; aplicație. Având în ve dere ca de zvolt ăm @Inject private MyService myService; void service( o aplicație web, cel mai logic loc în protected HttpServletRequest request, HttpServletResponse response) care putem crea Injector-ul îl repre- throws ServletException, IOException { z i n t ă u n S e r v l e t C o n t e x t L i s t e n e r . response.getWriter().println( „Service: „ + myService.doStuff()); ServletContextListener-ul este o compo} } nentă care actionează imediat ce aplicația a fost instalată și înainte de orice request Haideți să analizăm puțin codul de mai către server. Guice vine cu o clasă pro- sus: prie ce trebuie extinsă pentru a putea crea 1. Un servlet trebuie să fie singleton un Injector valid. Vom folosi Servlet 3.0 – marcat corespunzător prin adnoAPI așa că vom adnota această clasă cu tarea @Singleton – altfel aplicația va @WebListener – astfel nu va mai fie nevoie arunca o excepție. să o declarăm în web.xml. 2. Folosim injectare la nivel de câmp Spuneam că ServletModule este locul pentru a obține o instanță de în care configurăm servleții aplicației. Iată MyService care este apelată mai jos mai jos conținutul clasei care va extinde în metoda service(). acest modul și configurează un servlet sim3. Clasa extinde HttpServlet, ca orice plu mapat pe toate request-urile .html: alt servlet.

GuiceServletContextListener. Toate aceste configurări nu vor avea momentan nici o influență asupra aplicației – totul va functiona la fel ca înainte, fără nici o problemă. În continuare putem avea două abordări: • Folosim Guice doar pentru ce este nou adăugat – bineînțeles, nu este un best practice, dar este un caz destul de întâlnit în aplicațiile mari care au foarte mult legacy code, • „Guice-ficăm” toata aplicația – cazul ideal. Pentru cazul 2, abordarea va fi identică cu prima parte a articolului. În primul caz vom ajunge în situații în care vrem să folosim DI în servleți sau clase care nu sunt instrumentate de Guice. Putem avea acces la Injector-ul de Guice foarte simplu prin accesarea ServletContext-ului:

package endava.guice.modules; import endava.guice.servlet.MyServlet;

Pentru injectarea dependințelor, folosind injectorul de mai sus, avem două posibilități: • U n c a l l c ă t r e i n j e c t o r . injectMembers(this) – care va injecta toate dependințele, • U n c a l l c ă t r e i n j e c t o r . getInstance(clazz) pentru fiecare instanță injectată.

import com.google.inject.servlet.ServletModule; public class MyServletModule extends ServletModule { @Override protected void configureServlets() { serve(„*.html”).with(MyServlet.class); } }

ServletContextListener-ul va avea următorul conținut:

Interfața MyService: package endava.guice. service; import com.google.inject.ImplementedBy; @ImplementedBy(MyServiceImpl.class) public interface MyService { String doStuff(); }

Implementarea MyServiceImpl: package endava.guice.service; public class MyServiceImpl implements MyService {

Injector injector = (Injector) request.getServletContext(). getAttribute(Injector.class.getName());

Request and Session Scope

Extensia de Servlet introduce două scopuri noi: Request și Session. Voi arăta mai import com.google.inject.Guice; jos un exemplu despre folosirea scopului import com.google.inject.Injector; import com.google.inject.servlet. În acest moment aplicația este gata Session. GuiceServletContextListener; pentru a fi deployată. Iată rezultatul unui Vom modifica foarte puțin câteva din @WebListener public class MyGuiceConfig request către index.html clasele prezentate mai sus. Având în vedere extends GuiceServletContextListener { că în acest exemplu vom mixa și com @Override protected Injector getInjector() { accesa un obiect cu un scop mai restrâns return Guice.createInjector(new MyServletModule()); dintr-unul cu un scop mai larg (accesăm } un obiect cu scopul Session dintr-un sinObservați în metoda getInjector() cregleton), vom folosi Provideri (vezi Note). area Injector-ului pe baza modulului de Modulul de servleți va arăta astfel: servlet de mai sus. Dacă aplicația are mai Integrarea Google Guice într-o package endava.guice.modules; multe module, toate trebuiesc declarate aici aplicație web existentă import endava.guice.provider.PojoProvider; – acesta e singurul loc în care trebuie creat Pentru a integra Google Guice într-o import endava.guice.servlet.MyServlet; import endava.guice.servlet.PojoClass; un Injector. De asemenea, observați cât de aplicație existentă vom începe prin a ne import com.google.inject.servlet.ServletModule; intuitivă este și declararea Servlet-ului si a asigura că avem totul ”in place”. Pentru import com.google.inject.servlet.ServletScopes; mapării aferente. Iată și conținutul clasei aceasta facem exact aceleași setări ca mai public class MyServletModule extends ServletModule { MyServlet: sus: @Override • Adăugăm în classpath librăriile de protected void configureServlets() { package endava.guice.servlet; serve(„*.html”).with(MyServlet.class); import java.io.IOException; google guice import javax.servlet.ServletException; bind(PojoClass.class). import javax.servlet.http.HttpServlet; • Definim filtrul în web.xml toProvider(PojoProvider.class). import javax.servlet.http.HttpServletRequest; in(ServletScopes.SESSION); import javax.servlet.http.HttpServletResponse; • Definim ServletContextListener-ul } import endava.guice.service.MyService; } import com.google.inject.Inject; prin sub-clasarea clasei package endava.guice.listener; import javax.servlet.annotation.WebListener; import endava.guice.modules.MyServletModule;

14

nr. 5/2012 | www.todaysoftmag.ro

@Override public String doStuff() { return „doing stuff!”; } }


programare O b s e r v aț i m a i s u s b i n d i n g - u l ServletScopes.SESSION. Clasa PojoProvider: package endava.guice.provider; import endava.guice.servlet.PojoClass; import com.google.inject.Provider; public class PojoProvider implements Provider<PojoClass> {

TODAY SOFTWARE MAGAZINE pojoClass.get().setName(„existing name”); } response.getWriter(). println(pojoClass.get(). getName()); } }

Pentru demonstrație o să accesăm aplicația de două ori. Prima dată ar trebui sa aveți rezultatul de mai jos:

public PojoClass get() { return new PojoClass(); } }

public class PojoClass {

• •

Clasa PojoClass: package endava.guice.servlet;

Iar a doua oară următorul rezultat:

private String name;

instanțe ale unei dependințe per injection, Un client vrea să obțină dependința efectivă doar atunci când se face injectarea (lazy loading), Injectăm un obiect cu scop mai restrâns într-un obiect cu scop mai larg, Avem logică adițională necesară pentru crearea unui obiect care va fi apoi injectat, Vrem să controlăm modul în care sunt create instanțele pentru binding.

public void setName(String s) { this.name = s; }

După cum am văzut mai sus, este foarte simplu să scriem un Provider. Trebuie doar să implementăm interfața Provider<T>, unde T este tipul concret pentru care vrem Pentru a demonstra că aplicația Exemplul poate fi foarte ușor schim- să construim provider-ul. chiar functionează, vom modfica și clasa bat pentru a folosi Request Scope in loc de MyServlet să afișeze informații adiționale: Session Scope. Așa arată o aplicație didactică în care package endava.guice.servlet; import java.io.IOException; am încercat să ating cele mai importante import javax.servlet.ServletException; puncte din modulul de Guice Servlet. La import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; fel cum am menționat și în articolul trecut, import javax.servlet.http.HttpServletResponse; import endava.guice.service.MyService; aceasta e doar o introducere. Puteți contiimport com.google.inject.Inject; nua să experimentați diverse situații. Cel import com.google.inject.Provider; import com.google.inject.Singleton; mai mult veți învăța însă folosind Guice @Singleton într-un proiect ”pe bune”. public String getName() { return this.name; } }

public class MyServlet extends HttpServlet { private static final long serialVersionUID = 1861227452784320290L; @Inject private Provider<PojoClass> pojoClass; @Inject private MyService myService; protected void service( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.getWriter().println( „Service: „ + myService.doStuff() + „ with „); if (pojoClass.get().getName() == null) { pojoClass.get().setName(„name”); } else {

Guice ca și Maven dependency <dependency> <groupId>com.google.inject</ groupId> <artifactId>guice</artifactId> <version>3.0</version> </dependency>

Provideri

Providerii adresează următoarele situații: • Un client are nevoie de mai multe

www.todaysoftmag.ro | nr. 5/2012

15


testare

Agile & Testing & Mobile trei concepte convergente

O

privire de ansamblu asupra universului IT al zilelor noastre ne arată că tehnologia mobilă este un domeniu deosebit de dinamic. Bătălia principală de pe acest sector de piață se desfășoară între trei mari competitori: Apple, Nokia și marea familie a dispozitivelor cu Android (Samsung, Motorola, Sony-Ericsson etc.). Dacă până nu demult pe un dispozitiv mobil aveam la dispoziţie doar aplicații de bază (clienți de e-mail, navigatoare, calculator de buzunar sau jocuri rudimentare) astăzi suntem bombardați din toate direcțiile de aplicații financiare, sănătate și asigurări, jocuri cu grafică avansată, calendare și agende avansate, asistent personal. Rareș Irimieș

rares.irimies@threepillarglobal.com Senior QA @ 3Pillar Global Romania

16

nr. 5/2012 | www.todaysoftmag.ro

Într-un timp relativ scurt, apariția acestor aplicații ne-a determinat să folosim telefonul mobil sau tableta până și în cele mai puţin importante activități pe care le desfăşurăm de-a lungul zilei. Pe măsură ce nevoile clienților au evoluat, dezvoltatorii de aplicații mobile au început să se axeze foarte mult pe complexitatea aplicației, neglijând oarecum calitatea acesteia. Datorită cerințelor prea mari ale clienților, multe proiecte au început să aibă probleme în ceea ce privește alocarea timpului necesar dezvoltării și testării aplicațiilor. Ca o soluție pentru această problemă putem discuta despre alegerea unei metodologii de dezvoltare care să cuprindă cât mai bine cerințele clienților și să protejeze timpul și munca echipei de dezvoltare. Stabilirea unor standarde care trebuie urmate se face la nivel de companie și trebuie aplicate sau modificate asfel încât să se adapteze cât mai bine cerințelor clientului și a produsului care urmează să fie livrat. Folosind metodologia “Agile”, compania pentru care lucrez a reușit să definească câteva reguli sau principii de bază care trebuie urmate pentru a livra un produs cât mai apropiat cerințelor clientului și a pieței. Aceste principii de bază ar fi: • Definirea strategiei de testare, • Definirea scopului testării, • Adaptarea continuă la schimbarea scopului, • Identificarea riscurilor şi stabilirea strategiei de prevenire, • Feedback-ul continuu.

În cele ce urmează vom detalia fiecare dintre aceste reguli având în vizor lumea aplicaţiilor mobile şi analizând impactul fiecăreia în dezvoltarea produsului.

Definirea strategiei de testare

Chiar dacă nu avem cum să știm ce “surprize” sau impedimente vom întâlni pe parcursul testării unei aplicații, este esențial să stabilim de la bun început o bază a strategiei de testare. Aceasta bază are ca principale componente: • Stabilirea ariei testării, • Determinarea mediului de testare, • Definirea tipurilor de teste ce se vor aplica.

Aria de testare

Clientul joacă un rol foarte important în stabilirea ariei de testare (dispozitive, sisteme de operare, combinații ale platformelor, browsere etc.). Echipa responsabilă de Quality Assurance (QA) trebuie să prezinte clientului riscurile unei arii de testare reduse sau posibilele riscuri care vor apărea în momentul în care aplicația se află deja în dezvoltare. Pentru a putea prezenta aceste date, echipa trebuie să efectueze câteva cercetări pe piață pentru a stabili care sunt cele mai folosite dispozitive și sisteme de operare. În urma unor discuții client- echipă se pot stabili următoarele: • Care sunt platformele pe care se va face dezvoltarea; • C a r e s u n t d i s p o z i t i v e l e ș i combinațiile de sisteme de operare pe care se va axa testarea;


management

Care este posibilitatea ca operatorii de telefonie sau fabricanții de dispozitive să fi implementat functionalități comune de care ar depinde aplicația care urmează să fie dezvoltată.

Datorită timpului sau bugetului limitat, testarea efectivă nu va putea acoperi suficiente dispozitive și versiuni de sisteme de operare pentru a putea reduce considerabil numărul defectelor. În acest caz, este indicat ca testarea să se desfăşoare pe combinațiile de dispozitiv - sistem de operare cele mai folosite și pe dispozitivele la care s-au semnalat cele mai multe probleme. Un alt pas important în stabilirea ariei de testare este poziționarea aplicației pe piață: jocuri, social, banking, sănătate etc. Bazându-ne pe segmentul de piață pentru care este adresată aplicația, putem stabili câteva dispozitive care vor fi folosite în testare. Astfel, pentru banking vom fi nevoiți să acoperim cât mai multe dispozitive pentru ca orice fel de utilizator să aibă accces la ea, iar pentru jocuri ne vom orienta spre dispozitivele cele mai utilizate de către copii (iPod, iPad , Android tablet). O altă problemă care ar putea apărea în momentul în care dezvoltăm o aplicație complexă este folosirea unor API-uri furizate de aplicaţii deja existente (Facebook, Twitter, etc) sau a unor librării third-party (TapJoy, iAD etc). Clientul trebuie să știe că integrarea acestor componente poate dura mai mult sau poate avea un impact major asupra stabilităţii aplicației (bug-uri third-party care nu pot fi rezolvate în timp

TODAY SOFTWARE MAGAZINE

util sau a caror soluţii de evitare pot afecta într-un mod neplăcut funcționalitatea aplicației).

Mediul de testare

Sunt intens utilizate în testarea automată.

Infrastructură partajată

Această modalitate are câteva caracteOdată ce aria de testare a fost stabilită, ristici ce merită menţionate: urmează definirea mediului testării. În • Eficiente în: Exhaustive testing, cadrul aceste activități trebuie să avem în Compatibility testing, Interruption vedere următoarele aspecte: testing, Functional testing, Regression • Ce tip de testare vom folosi? testing; • Care sunt costurile pentru procura• Nu este free (DeviceAnywhere, rea acestui mediu? PerfectoMobile); • Cât de eficientă este testarea pe un • Testarea poate acoperi o gamă largă astfel de mediu? de combinaţii dispozitiv – sistem de • Odată mediul creat, putem să îl folooperare; sim și pentru testarea altor aplicații? • Foarte încete din cauza utilizării conexiunii la internet pe întreaga Astfel putem face o comparație între perioadă a testării; urmatoarele medii de testare: emulatoare – • Eficiente în reproducerea unui scedispozitive fizice – infrastructură partajată. nariu de zi cu zi. – Shared infrastructure

Emulatoare

Fiind cele mai la îndemână, testarea pe emulatoare are nişte caracteristici ce trebuie luate în seamă atunci când se aleg ca mediu principal de testare: • Emulatoarele sunt eficiente în: Sanity testing, Compatibility testing, Functional testing, Smoke testing; • Sunt gratuite (download free) ; • 40% din testarea aplicației poate fi executată pe emulator; • Se pot obține combinații dorite de dispozitiv - sistem de operare ; • Nu sunt 100% eficiente în crearea unui scenariu de zi cu zi; • Sunt medii de testare relativ încete;

Dispozitive fizice

Testarea într-un astfel de mediu poate fi considerată cea mai aproape de adevăr având în vedere faptul că poate fi simulat perfect comportamentul uman în folosirea dispozitivelor. Caracteristicile importante sunt în acest caz următoarele: • Eficiente în: Functional testing, Smoke testing, Acceptance testing, Regression testing, Bug fix testing; • Foarte bune pentru reproducerea problemelor apărute în timpul utilizării; • 50% din testarea trebuie facută pe un dispozitiv fizic; • Eficiente în testarea automată; • Oferă rezultate rapide și precise.

www.todaysoftmag.ro | nr. 5/2012

17


testare Agile & Testing & Mobile - 3 concepte convergente

Tipul testării

După definirea mediului de testare, Principalele metode de testare pentru echipa trebuie să decidă tipul de testare uti- testarea manuală sunt Functional testing și lizat. Fie ea manuală sau automată, testarea Bug-fix testing. Punctele urmărite în testatrebuie adaptată complexității proiectului, rea manuală ar fi: bugetului alocat pentru resurse precum și a. Testarea interfeţei cu utilizatorul, timpului de testare disponibil. care implică fonturi, culori, navigaAstfel, făcând o comparație între aceste rea de pe un ecran pe altul; tipuri de testare manuală sau automată, b. Testarea functionalităților de bază trebuie să luăm în considerare următoarele ale aplicației; aspecte. c. Usability testing – implică testarea butonalor gen “Home” sau “Back” Care este cea mai bună metodă de din fiecare ecran al aplicației; testare? d. Testarea download-ului, instalării Testarea manuală are o eficiență de sau dezinstalării aplicației; 100%, deoarece comportamentul utilie. Interruption testing – Felul în care zatorului poate fi reprodus cel mai uşor. se comporta aplicația în momentul Testarea automată are o eficiență de doar când primești un mesaj sau un apel, 60-70%, deoarece script-urile folosite nu iar aplicația rulează in foreground; pot fi 100% corecte sau complete. Totodată, f. Monkey testing – inserarea de caractestarea manuală ar trebui efectuată în tere sau imagini într-un mod haotic procent de minim 70% pe întregul propentru a vedea care este rezistenţa iect. Pe marginea subiectului Manual vs aplicației la stres; Automation au loc în prezent o serie de dezbateri care au drept concluzie, în mare Pe lângă testarea manuală sau autoparte, faptul că testarea automată nu poate mată, din ce în ce mai multe companii înlocui testarea manuală. apelează la servicii de gen “Crowd sourcing”. Folosindu-ne de aceste servicii Care sunt costurile fiecărei metode? putem stabili dacă am construit produsul Pentru a răspunde scurt la această corect, transferându-l spre testare unui întrebare, trebuie să avem în vedere com- grup de oameni care fac parte din viitorii plexitatea aplicației și timpul acordat utilizatori (alfa testing). pentru testare. Testarea automată costă mai mult în faza iniţială în care se inves- Strategia de testare teşte timp şi resurse pentru dezvoltarea Având clarificate cele trei componente script-urilor automate, setarea şi utiliza- ale testării detaliate anterior (aria testării, rea unui mediu de Continuous Integration, mediul de testare şi tipul testării) se poate însă în timp această metodă îşi va dovedi defini o strategie de testare a unei aplicații eficienţa în etapele de testare de regresie. Pe mobile în patru paşi: de altă parte, testarea manuală este capa1. Plan bilă de a descoperi defectele încă din fazele a. Înţelegerea documentaţiei şi a incipiente ale produsului; în schimb este cerinţelorș costisitoare din punctul de vedere al dispob. Stabilirea dispozitivelor si a comzitivelor fizice pe care aceasta se desfăşoară. binaţiilor cu sistemele de operare; c. Descrierea emulatoarelor sau disCare sunt beneficiile acestui tip de pozitive reale de testarii; testare? d. Descriere tipului de testare (autoTestarea automată poate fi foarte folosimat sau manual) folosit. toare în faza de testare de regresie, salvând 2. Design mult timp de execuție a testelor. Cu toate a. Găsire a uneltelor ade c vate acestea, joacă un rol foarte important în (pentru Automation, Test Case load testing sau performance testing pe Management, C ontinuou s întreaga durată a proiectului. Bineînteles, Integration); dupa cum am spus anterior, în cazul tesb. Rezolvarea problemei dispozitivetării automate trebuie luată în considerare lor (procurarea acestora); posibilitatea integrării într-un sistem c. Stabilirea scenariilor de test; de Continuous Integration (ex. Bamboo, 3. Dezvoltare Jenkins/Hudson etc). a. Crearea datelor de test;

18

nr. 5/2012 | www.todaysoftmag.ro

b. Crearea scenariilor de test; 4. Executare a. Configurarea mediului de testare; b. Testarea efectivă; c. Reportarea defectelor; d. Extragerea de rapoarte (Execution Matrix).

Definirea scopului testării

În metodologia Agile-Scrum, procesul de QA se desfăşoară pe întreg parcursul proiectului, în fiecare sprint. La sfârșitul fiecărui sprint, fiecare aplicație trebuie să aibă un cod compilabil care poate fi testat. Dat fiind că în majoritatea cazurilor timpul alocat pentru QA este de 2-4 zile, planul de testare trebuie să fie foarte clar și să definescă gradul de calitate pe care îl va avea codul în momentul Demo-ului. În primele sprint-uri (în care se implementează în general functionalități noi) testerul va putea valida doar “happy flow”ul. Pe măsură ce codul devine tot mai stabil, vor apărea și posibilitățile de testare automată, testare a performanței și a scenariilor negative. În funcție de complexitatea produsului, managerul trebuie să aloce 1-2 sprint-uri pentru testare și bug-fixing înainte ca produsul să fie instalat pe mediul de producţie şi să ajungă public.

Adaptarea continuă la schimbarea scopului

Această regulă este una destul de incomodă pentru majoritatea testerilor. Deoarece în “Agile” prioritățile sau funcţionalitatea aplicației se pot schimba, planul de testare trebuie actualizat cât mai des pentru a reflecta schimbările petrecute. De exemplu, se ia decizia ca anumiţi utilizatori să poată avea acces la partea de backend a aplicației pentru a adăuga sau șterge conturile altor utilizatori, acest lucru nefiind prezentat în documentația inițială a aplicației. În acest caz, în planul de testare vor trebui introduse noi metode de testare: • Security testing (în funcție de rolul utilizatorului, acesta are sau nu acces la întreaga baza de date); • Load testing (verificarea comportamentului în condițiile în care mai mulți utilizatori alterează baza de date în același timp). Acesta este doar un exemplu, însă deschiderea pentru schimbarea permanentă a scopului şi a metodologiei trebuie să fie prezentă constant.


TODAY SOFTWARE MAGAZINE Identificarea riscurilor si stabilirea strategiei de abordare

Este foarte important ca planul de testare să surprindă și să prevadă cât se poate de bine riscurile care pot apărea pe parcursul dezvoltării și testării produsului. D e e xe mplu, p e nt r u a te st a o funcționalitate mai complexă este necesar să alocăm mai mult timp pentru testare. Strategia de abordare şi prevenire a riscurilor ar putea consta în alocarea mai multor resurse pe o perioadă scurtă de timp pentru a testa cat mai multe scenarii de risc care ar putea fi executate de către un utilizator, sau poate însemna în acelaşi timp reducerea numărului de teste şi prioritizarea acestora în funcţie de impactul asupra aplicaţiei.

Feedback-ul continuu

Poate cel mai important lucru şi nu în ultimul rând, trebuie avută o discuție

deschisă și continuă pentru a obține feedback. Este foarte important ca noile functionalități sau schimbări majore aduse aplicației să fie discutate de către toate persoanele implicate în proiect pentru a obține calitatea dorită. Aceste modificări au un impact foarte mare asupra planului de testare și a calității produsului existent. Pentru aceasta, persoanele din departamentul de testare trebuie să fie implicate în luarea decizilor de acest tip de către client sau de către echipa de dezvoltare. În sprijinul acestei reguli poate fi adusă şi ideea testării încă din primele faze ale proiectului şi implicarea cât mai mare nu doar a testerilor dar şi a managerului de produs în procesul de calitate. Calitatea produsului trebuie să fie asigurată în mod colaborativ şi fiecare persoană implicată în dezvoltare trebuie să fie conştientă de calitatea pe care o produce.

Concluzii

Testarea aplicațiilor mobile devine din ce în ce mai dificilă odată cu trecerea timpului, creșterea nivelului de complexitate al aplicației și pretențiile tot mai mari ale clienților. Alegerea strategiei corecte atât în ceea ce priveşte tipurile de testare cât şi mediul pe care aceasta se desfăşoară ne ușureaza munca, reduce costurile şi poate ajuta în anticiparea problemelor ce ar putea să apară. Poate cel mai important lucru este deschiderea permanentă către schimbare şi adaptarea continuă la scopul mereu ajustabil. Testarea aplicaţiilor mobile este o provocare în sine, mediul mobil fiind cel mai dinamic în zilele noastre.

www.todaysoftmag.ro | nr. 5/2012

19


programare

Design-ul aplicaţiilor Android pentru toate platformele

C

hiar de la inceput aş vrea să subliniez faptul că acest articol nu aduce ceva nou la modul de programare în Android, ci este mai degrabă o sinteză a informaţiei pe care sistemul Android o pune la dispoziţie.

Claudia Dumitraș

claudia.dumitras@skobbler.ro Android Developer @ Skobbler

20

nr. 5/2012 | www.todaysoftmag.ro

Una dintre problemele, cu care se confruntă programatorii aplicaţiilor Android este lansarea unei aplicaţii care să funcţioneze corect pe toate platformele suportate. Ceea ce merge perfect pe unele telefoane ar putea să nu funcţioneze deloc pe altele, acest lucru făcându-i pe unii să renunţe la încercarea de a acoperi o categorie cât mai largă de telefoane Android, inclusiv tablete. Principalele constrângeri care trebuie luate în considerare atunci când se scrie o aplicație sunt: • versiunea de SDK suportată, • opţiunile de configurare la rulare cum ar fi: limba, orientarea telefonului (portret sau landscape), operatori, etc, • versiunile de hardware diferite, fiecare cu constrâgerea sa, • dimensiunea telefonului sau a tabletei.

aşteptările şi nevoile utilizatorilor; limbajul vizual trebuie să fie dus dincolo de ecranele statice pentru o utilizare cât mai flexibilă a elementelor vizuale. Nu este suficientă crearea de aplicaţii cu un UI performant - care reacţionează rapid la acţiunea utilizatorului - ci şi intuitiv, astfel încât toate elementele să fie clare şi complet vizibile. Din fericire, framework-ul Android se dezvoltă continuu în această direcţie, şi anume în a oferi suport în dezvoltarea aplicaţiilor pentru mai multe tipuri de telefoane. Toate modelele grafice pe care fiecare versiune de SDK le aduce nu trebuie considerate restricţii, ci moduri de dezvoltare în această direcţie. Încă de la început, framework-ul de UI a fost proiectat pentru a putea fi ajustat în funcţie de spaţiul ecranului care există la dispoziţie. Un exemplu la îndemână ar fi componenta ListView care poate să îşi schimbe înălţimea în concordanța de dimeConstrângeri grafice nisunea ecranului, care variază în funcție Un loc aparte în proiectarea și dezvolta- de QVGA HVGA şi WVG. rea unei aplicații îl ocupă arhitectura părţii grafice cu scopul de a acoperi cât mai multe Design grafic pentru telefoane tipuri de telefoane. Partea grafică este construită cu ajutoInterfaţa grafică trebuie construită rul fisierelor .xml, numite layout-uri. dinamic, pentru a fi schimbată în funcţie de În c e p â n d c u A n d r o i d 1 . 6 s - a


management

TODAY SOFTWARE MAGAZINE

introdus un nou concept, acela de densitate a ecranului, făcând astfel mult mai uşoară scalarea pe mai multe rezoluţii, chiar şi când telefoanele aveau aproximativ aceeaşi dimensiune fizică (spre exemplu această opţiune a fost extrem de utilă pentru telefoanele gen Droid, cu rezoluţii mari, ce au apărut pe piaţă). Prin densitatea ecranului se înțelege numărul de pixeli pe o anumită suprafaţă a ecranului fizic, sau altfel spus, puncte per inch (dots per inch). Astfel, partea grafică (layouts) poate fi clasificată în: „small” pentru QVGA, „normal” pentru HVGA și „large” pentru WVGA, în acest fel putându-se folosi diferite resurse în concordanța cu dimensiunea ecranului. În funcție de aceste calificative de configurare prezente în aplicaţie, sistemul ştie să aleagă resursele potrivite în funcţie de caracteristicile specifice ecranului telefonului. Un calificativ de configurare reprezintă stringul adăugat fişierelor de resurse. Exemplul de mai jos prezintă o listă cu nume de fişiere pentru resurse, în funcție de diferite layout-uri precum şi exemple de fişiere diferite de imagini pentru densități de ecran „small”, „normal” şi „high”:

mai multe directoare de resurse, este bine a se folosi anumite standarde în toate layout-urile existente şi anume, este indicat a se folosi dps ca unitate de măsurare (densitatea independentă de pixeli). Un dp este o unitate virtuală, care descrie dimenisunea, precum și poziţionarea elementelor grafice, într-o manieră independentă de densitate. Un dp este egal cu un pixel fizic pe un ecran de 160 dpi (dots per Figura 1 Strategii de a trata design-ul layoutinch), aceasta fiind densitaurilor pentru tablete portet şi landscape. tea de referinţă presupusă Sursa: http://static.googleusercontent.com/external_content/ de sistem pentru o densiuntrusted_dlcp/www.google.com/en//events/io/2011/static/presofiles/ tate de ecran „medium”. La designing_and_implementing_android_uis_for_phones_and_tablets.pdf runtime, dacă este necesar, sistemul decide scalarea unităţilor dp, bazat încercarea de a face ca layout-urile să fie pe densitatea actuală a ecranului utilizat. generalizate pe grupuri de dimensiuni (cum ar fi large sau xlarge) . Chiar dacă Design grafic pentru tablete cele două tipuri de tablete par a fi apropiate // layout pentru dimensiunea ecranului „normal” Pentru prima generaţie de tablete cu în dimensiuni, separarea tabletelor de 7” de res/layout/my_layout.xml Android 3.0, modul potrivit de a declara cele de 5” a fost necesară, mai ales pen// layout pentru dimensiunea ecranului „small” res/layout-small/my_layout.xml partea grafică este folosind calificativul tru că acestea două se încadrau în grupul // layout pentru dimensiunea ecranului „large” de configurare „xlarge” (de exemplu res/ „telefoanelor mari” (large). Spaţiul ecranures/layout-large/my_layout.xml layout-xlarge/). lui utilizat la aceste două tipuri de tablete // fisier imagini pentru densitatea mică „low” res/drawable-ldpi/my_icon.png Cu scopul de a suporta şi alte tipuri de este diferit, la fel este şi stilul cu care sunt // fisier imagini pentru densitatea medie tablete cu alte dimensiuni, de genul celor obişnuiţi utilizatorii. // „medium” res/drawable-mdpi/my_icon.png de 7” – Android 3.2 a introdus o nouă Pentru ca diferenţierea părţii grafice să // fisier imagini pentru densitatea mare „heigh” modalitate de a împărţi resursele. Această fie şi mai bine proiectată pe diferite dimenres/drawable-hdpi/my_icon.png nouă tehnică se bazează mai degrabă pe siuni, platforma Android permite acum Chiar dacă aplicaţia va dispune de raţionalizarea spaţiului necesar, decât pe gruparea resurselor specificate în dp, bazat

WE WANT YOU & T O A P P LY ! A N

A W E S O M E

C + +

D E V E L O P E R

NOW IT’S TIME

to work with the latest kick-ass technologies to do some serious rocket science with more than 3 mio customers, who drive 2 mio km/week

to rock the Romanian IT industry to change the LBS community worldwide

www.skobbler.com/careers apply@skobbler.com

www.todaysoftmag.ro | nr. 5/2012

21


programare Design-ul aplicaţiilor Android pentru toate platformele

Figura 2. Exemplu de definere a modulelor grafice care conțin fragmente, ce pot fi combinate într-o activitate pentru tablete, dar separate petru telefoane Sursa http://developer.android.com/guide/components/fragments.html)

pe lăţimea şi/sau înălţimea care sunt cu adevărat disponibile pentru aplicaţie. De exemplu, după proiectarea layout-urilor pentru tablete, se poate determina limita pentru care acest layout nu se mai potriveşte, de exemplu 600dp. Această limită, astfel setată, devine dimensiunea minimă necesară pentru layout-ul tabletelor sau, altfel spus, acest tip de resurse este specificat atunci când există cel puţin o lăţime de 600dp pentru UI-ul aplicaţiei. // pentru tablete de 7” (laţime mai mare sau // egală cu 600dp) res/layout-sw600dp/main_activity.xml // pentru tablete de 10” (laţime mai mare sau // egală cu 720dp) res/layout-sw720dp/main_activity.xml

De obicei, pentru tablete se doreşte folosirea întregului spaţiu aflat la dispoziţie şi extinderea elementelor grafice pe toată lungimea ecranului, ceea ce nu duce întotdeauna la un rezultat plăcut. O soluţie la îndemână constă în împărţirea layout-ului

Fragmente

general în panouri mai mici, tehnică numită şi multipane. Această separare trebuie făcută într-un mod ordonat şi clar, astfel încât conţinutul să devină mai detaliat, dar această împărţire trebuie să fie păstrată indiferent de orientarea tabletei. În figura următoare sunt câteva strategii pe care cei de la Android le propun pentru a rezolva eventualele probleme care apar în portret sau landscape.

Implementarea panourilor multiple se realizează cel mai uşor folosind fragmente (Fragment API). Un fragment poate reprezenta o funcţionalitate aparte, sau o parte din interfaţa grafică. Se pot combina mai multe fragmente într-o singură activitate, cu scopul de a construi astfel o interfaţă cu panouri multiple. Acest lucru constituie un avantaj, pentru că se pot refolosi în diferite activitaţi. Fiecare sub-layout poate fi împărţit pe fragmente. O clasă Fragment poate fi considerată ca mini-Activity (Activity clasa specifică Android ca suport al părţii grafice), dar nu poate funcţioana independent, ci trebuie să fie inclusă în cadrul unei clase Activity. Un Fragment este o componentă cu UI şi cu durată de viaţă proprie, dar acest lucru este direct afectat de succesiunea de stări a activităţii. De exemplu,

atunci când activitatea este terminată la fel vor fi şi fragmentele componente. Cu toate acestea, fragmentele pot fi adăugate sau şterse în timp ce activitatea rulează.

Versiunea minimă de SDK

Versiunea minimă a SDK este un atribut care se declară în fișierul manifest al aplicației (android:targetSdkVersion). De obicei acesta se alege în funcţie de numărul cel mai mare al telefoanelor existente pe piaţă. Acest număr reperezintă limita superioară a API-ului folosit și este foarte important pentru că ar putea influența anumite funcționalități. Cu cât numărul versiunii este mai mic cu atât mai mult pot apărea neplăceri legate de limitările date de API. De asemenea, multe din widget-urile native ar putea avea o imagine învechită.

Concluzie

Este important ca design-ul aplicației să fie compatibil cu toate platformele existente, în acest fel crescând numărul utilizatorilor. Acest lucru, însă, nu este suficient. Fiecare dimensiune a ecranului oferă diferite posibilități și provocări pentru interacțiunea cu utilizatorul, așa încât pentru a impresiona cu adevărat, trebuie mers mai departe, și anume, trebuie optimizată această experiență pentru fiecare tip de configurare. Chiar dacă nu veţi putea cumpăra toate device-urile existente pe piaţă la ora actuală, pentru a vă testa aplicaţia, sistemul Android pune la dispoziţie multiple metode pentru a testa rezultatul final pe mai multe platforme. Dar înainte de aceasta, fiecare aplicaţie trebuie să respecte toate standardele impuse de acest sistem de operare.

Referinţe http://developer.android.com/guide/practices/screens_support.html http://android-developers.blogspot.ro/2011/02/android-30-fragments-api.html http://developer.android.com/guide/components/fragments.html http://www.google.com/events/io/2011/sessions/designing-and-implementing-android-uis-for-phones-and-tablets.html http://static.googleusercontent.com/external_content/untrusted_dlcp/www.google.com/en//events/io/2011/static/presofiles/designing_and_implementing_android_uis_for_phones_and_tablets.pdf http://www.youtube.com/watch?v=2jCVmfCse1E&feature=relmfu http://developer.android.com/guide/topics/manifest/uses-sdk-element.html http://developer.android.com/training/multiscreen/index.html

22

nr. 5/2012 | www.todaysoftmag.ro


management

TODAY SOFTWARE MAGAZINE

Cum să crești o mentalitate agilă în contextul dezvoltarii software?

N

u există o modalitate mai bună de a descrie chintesența mentalității agile decât pornind de la principiile Manifestului pentru dezvoltare agilă de software:

„Noi scoatem la iveală modalități mai bune de dezvoltare software prin experiență proprie și ajutându-i pe ceilalți. Prin această activitate am ajuns să apreciem:

Andrei Chirilă Andrei.Chirila@isdc.eu Team Leader Technical Architect @ ISDC cu peste 5 ani de experienta, Andrei sustine ca motivatia si pasiunea sunt valori-nucleu pentru o echipa. Acesta este unul dintre motivele pentru care el considera ca, daca este interesant sa iti doresti a fi inspirat, este cu mult mai valoros sa tintesti sa ii inspiri pe ceilalti din jurul tau pentru ca asta ii ajuta pe acestia sa se dezvolte si pe tine sa te autodepasesti.”

• • • •

Indivizii şi interacţiunea înaintea proceselor şi tool-urilor, Software-ul funcţional înaintea documentaţiei vaste, Colaborarea cu clientul înaintea negocierii contractuale, Receptivitatea la schimbare înaintea urmăririi unui plan.

Cu alte cuvinte, desi există valoare in elementele din dreapta, le apreciem mai mult pe cele din stânga.” agilemanifesto.org

Formarea unei echipe

Este ușor de conchis din principiile Manifestului Agil că mișcarea agilă consideră oamenii ca fiind indivizi unici și nu resurse înlocuibile și că cea mai mare valoare adusă nu este în performanța individuală (chiar dacă ea joacă un rol important), ci rezultă din puterea interacțiunilor și colaborării între indivizi. Practicile agile recomandă formarea de echipe coezive, cu roluri bine definite, care se autoorganizează și care au ca scop ultim obținerea valorii. Acest lucru presupune, desigur, că membrii unei echipe sunt împuterniciți să facă lucrurile așa cum consideră ei cel mai bine, conform principiilor și ‚Crezului’ lor, fără să li se fi impus un anumit model de lucru. În egală măsură, aceasta înseamnă că aceștia sunt și responsabili pentru rezultatele si performanțele

lor.

Formarea unei echipe agile, modul cum sunt alocați oamenii într-o anumită echipă (în funcție de competențe, compatibilitate etc.), este crucial pentru succesul acesteia. Extrapolând, clădirea de echipe agile este foarte importantă pentru a dezvolta un mediu agil, deci o companie agilă și având ca ultim scop cultivarea unei mentalități agile. Voi detalia această perspectivă mai încolo. Dar legat de chipă, contează foarte mult configurația acesteia, responsabilitățile membrilor ei și cum aceștia colaborează pentru a dezvolta relații de succes. Compatibilitatea membrilor unei echipe, modul cum ei interacționează sunt esențiale pentru a forma o echipă de succes. Ideea de influențare și imitare a performanței este cea mai evidentă atunci când echipa nu a atins un anumit nivel de maturitate și când individul cu cea mai www.todaysoftmag.ro | nr. 5/2012

23


management Cum sa cresti o mentalitate agila in contextul dezvoltarii software?

multă experiență este un model pentru toți ceilalți membri ai echipei. Puterea exemplului este mult mai mare decât ne putem închipui. Atitudinea este foarte ușor imitabilă pentru indivizi. Oamenii au tendința de a împrumuta comportamente de la cei cu care empatizează, de a copia atitudinea superiorilor sau de o respinge total, și de aceea, sunt foarte importante anturajul, echipa și contextul în care un individ interacționează și, în consecință, cum se ”crește” o echipă și o viziune colectivă. Un citat anonim spune: ”Să fii inspirat este bine, dar să îi inspiri pe ceilalți este incredibil”. Un adevărat lider va fi recunoscut de către ceilalți și îi va determina pe aceștia să își depășească limitele. Rolul acestui lider (eventual Scrum Masterul într-o implementare SCRUM) este critic pentru că acesta își poate motiva oamenii să performeze, dar trebuie să știe și să ii protejeze atunci când ceilalți au nevoie de asta.

Împuternicire și responsabilitate

Adesea atitudinea oamenilor dintr-o companie face diferența între o companie matură de una cu mai puțină experiență. O echipă devine mai productivă cu cât este mai responsabilă pentru ceea ce face și cu cât membrii ei sunt împuterniciți să hotărască ceea ce este cel mai bine pentru produsul lor și contextul în care lucrează. Într-un cadru de lucru clasic, puterea pe care un manager o are asupra celorlalți, cunoașterea proiectelor și controlul asupra

24

nr. 5/2012 | www.todaysoftmag.ro

deciziilor legate de proiecte sunt doar o iluzie pentru că acestea pot fi privite de către ceilalți ca o modalitate de a pasa responsabilitatea de la un nivel la altul. Managerul este informat, iar omul din echipă este indirect ”eliberat” de responsabilitatea de a hotărî. Schimbarea de perspectivă este că, într-un mediu agile, motivul pentru a împuternici indivizii nu este pentru a motiva ci pentru a îmbunătăți managementul decizional. Distribuirea informației și a responsabilității în cadrul unei rețele (de exemplu o echipă) este mult mai eficientă decât menținerea acestora la un singur individ. O echipă care consideră că are ca singur țel dezvoltarea de linii de cod fără a se implica activ în procesul decizional și fără a-și atribui responsabilitate nu poate fi considerată o echipă matură. Oamenii ar trebui să fie încurajați și împuterniciți să ia decizii cu informațiile la care au acces și motivați să clădească povești de succes, nu să se aștepte să fie călăuziți de oamenii de pe alte nivele către povești de succes. Responsabilitatea și împuternicirea nu apar de la o zi la alta, însă pot fi ”cultivate”. Dacă a iniția acest proces de creștere este mai greoi, odată început, lucurile vor evolua de la sine până când un anumit nivel de maturitate este atins. Echipele mature nu au nevoie de foarte multă mentenanță. Ele au suficientă experiență și informații contextuale pentru a fixa majoritatea problemelor cu care se confruntă. În egală măsură, ele trebuie

să își cunoască foarte bine limitele cercului de influență și să ceară ajutorul atunci cand au nevoie. De aceea, un adevărat lider de echipă trebuie să își încurajeze echipa să vrea mai mult, să îndrăznească, să provoace schimbări și să se autodepășească, dar trebuie să ii protejeze în egală măsură de presiunea exterioară și de pericolul care poate apărea dacă aceștia își supraestimează forțele.

Oamenii înaintea Proceselor

Este important de remarcat că, în ciuda faptului că manifestul agile sugerează pradigma ‚oamenii înaintea proceselor’, acest fapt nu înseamnă că procesele nu aduc valoare în cadrul dezvoltării software. Dimpotrivă. Acestea ar trebui să complementeze Modelul Agil pentru că, deși diversele implementări de ‚Process Improvement’ (de exemplu CMMi etc.) vorbesc despre zonele care pot fi adresate pentru a eficientiza, ele nu dau o rețetă despre abordarea pe care o poți folosi în a le implementa. Aici poate interveni cu succes modelul agil pentru că, în filosofia sa, este adresată tocmai nevoia de schimbare și perfecționare a modului de lucru prin pricipiul ‚inspectează și adaptează’. Conform acestui principiu, echipa este atentă la lucrurile care nu sunt optime pentru ea și își setează ca țintă perfecționarea acestora prin dezvoltarea unor microprocese, procese care sunt relevante în echipă. În timp, acestea pot deveni macroprocese pentru că, dacă sunt împărtășite, pot aduc


TODAY SOFTWARE MAGAZINE

management

O mentalitate agilă înseamnă mult mai mult decât a fi agil

valoare altor echipe și organizației. Cu cât acest lucru este făcut mai des de către echipe, cu atât comunitatea și organizația pot beneficia de pe urma acestora pentru că promovează învățarea din greșeli, împărtășirea de practici și formarea unei identități colective.

Cum ? Ce ? De ce ?

Membrii unei echipe agile vor întâmpina provocări peste care vor trece, vor învăța și vor evolua. În urma acestor experiențe, își vor dezvolta noi procese, reguli și proceduri care îi vor ajuta să fie mai eficienți în modul de lucru, în calitatea pe care o livrează, în modul în care învață unii de la alții. Astfel, oamenii vor investi timp și efort pentru a perfecționa ”Cum-ul”. Unele echipe doar își vor îndeplini sarcinile, altele vor excela la acesta. Dar aici intervine partea interesantă. Cu cât o echipă agilă este mai matură, cu atât își va schimba focusul de pe definirea funționalităților pe care trebuie să le livreze (”Ce-ul”) și de pe modalitatea în care face aceasta într-un mod eficient (”Cum-ul”), pe

Oricât de simplist sau contradictoriu ar suna, a avea o mentalitate agilă înseamnă mult mai mult decât a fi sau a te comporta agil. A fi agil înseamnă să ai un comportament agil, iar acesta este influențat de caracterul individului, de experiența acestuia în proiecte agile, de cum acționează și interacționează într-o echipă. Mentalitatea agilă nu se naște în indivizi. Ea apare mai degrabă din împărtășirea unor experiențe, opinii, practici, comportamente între echipe și are ca rezultat construirea unui ”inventar” de cunoștințe și experiențe. Cu motivul pentru care trebuie să construiască alte cuvinte, nu poate exista o mentalitate aceste funcționalități, pe valoarea adusă în agilă acolo unde nu au existat deja echipe final Businessului (”De Ce-ul”). Pe scurt, o agile. echipă matură va dori să cunoască mai mult nevoile Business-ului, va pune la încercare O mentalitate agilă are impact la mai propunerile invalide, va da suport, se va multe nivele. La început echipele agile axa pe a aduce valoare și nu pe a construi promovează un mediu agil care, evoluând, funcționalitate. duce la cultivarea unei mentalități agile. Asemenea unui bulgăre de zăpadă, o menDar de ce ar fi o echipă suprasolici- talitate agilă clădește o companie agilă și tată, care deja luptă pe mai multe fronturi, asta duce la alte echipe agile ș.a.m.d. interesată să cunoască și ”De Ce-ul” și Mentalitatea agilă este cea care promodedesubturile acestuia? Răspunsul este vează schimbări vizibile la toate nivelele relativ simplu: cu cât pui la încercare moti- unei companii și care susține scalabilitatea vul, cu atât te pui pe tine și pe clientul cu și dezvoltarea. Cu cât oamenii și echipele care lucrezi la încercare și cu atât dezvolți împărtășesc o viziune agilă comună, deci o relație mai strânsă cu acesta. Există o o mentalitate agilă, cu atât organizația este tehnică interesantă , Tehnica celor cinci capabilă să facă față schimbării și să evolu”De Ce” (5 Whys Technique), care a prins eze. Lumea IT în care trăim astăzi a devenit popularitate în domeniul IT pentru aflarea un sistem complex, haotic. Companiile nu cauzei problemelor, dar care a început să fie sunt capabile să inoveze, să aducă valoare utilizată și pentru a pune la încercare ade- fără să evolueze și să se adapteze. A avea o văratele nevoi ale clientului. Prin această mentalitate agilă înseamnă a avea o deschischimbare de perspectivă, echipa nu mai dere pentru schimbare și pentru inovație este considerată a se ocupa doar cu dezvol- și de aceea viziunea pe care oamenii o au tarea de soft, ci are un rol mult mai mare despre inovație este importantă. Un citat pentru că îndeplinește și pune la încercare anonim spune că ”Inovația este abilitatea de nevoile clientului, este implicată proactiv în a vedea schimbarea ca o oportunitate și nu procesul decizional. ca o amenințare” pentru că prin inovație ne putem schimba pe noi și tot prin inovație Un model similar poate fi întâlnit avem puterea de a schimba lumea din jurul in Cercul de Aur al lui Simon Sinek, un nostru. model simplu dar puternic pentru leadership-ul inspirațional, care pune foarte mult accent pe rolul întrebării „De ce?” și modul în care, răspunzând la această întrebare, problemele pot fi abordate într-o manieră convențională sau într-o manieră exceptională. www.todaysoftmag.ro | nr. 5/2012

25


management

Joacă „Hard Choices” în fiecare sprint și rascumpără-ți datoriile!

B

un venit în era datoriilor! America are datorii de aproape 16 trilioane de dolari și dacă nu ai ajuns la New York în Times Square poți vedea această datorie direct online pe site-uri precum http://www.usdebtclock.org/. Nu mai este o surpriză pentru nimeni că Europa e într-o criza a datoriilor iar țările care excelează la acest capitol sunt Grecia, Spania, Italia, Irlanda și Portugalia cu aproximativ 120 bilioane de euro împrumutate. În mod cert și Romania este afectată de această criză sau participă la ea prin diverse acțiuni politice sau economice. Adrian Lupei alupei@bitdefender.com Project Manager și Software Engineering Manager Bitdefender IT-ist prin excelenţă, Adrian şi-a construit o carieră urmând paşii clasici, pornind de la Junior Software Developer, fiind apoi Senior Software Developer, Team Leader iar, în prezent, Project Manager și Software Engineering Manager. Cu o experiență de 4 ani în management de proiect, Adrian deține o certificare PMIACP și două certificări SCRUM (Certified Scrum Master și Certified Scrum Product Owner) oferite de ScrumAlliance.org, de asemenea este pasionat de aplicarea metodologiilor Agile în proiecte şi de instrumentele software care pot facilita implementarea lor în diverse companii.

26

nr. 5/2012 | www.todaysoftmag.ro

Așadar, datorii peste tot! Trebuie să le care te duc cu gândul că echipa acumuleaza plătim? Când trebuie să le plătim? datorii: • Nu avem timp acum, dar vom aloca Dar ce relevanță au datoriile țărilor timp mai tarziu, în povestea datoriei software? Sigur • Nu avem nevoie de asta acum, dar putem face o analogie, vorbim tot despre o să facem când o să avem nevoie, organizații mai mari sau mai mici, despre • Pe unde am mai lucrat nu am facut posibilitatea lor de a fi competitive sau nu, dintr-astea și treaba mergea bine, de puterea de a se dezvolta mai rapid sau • Nu știm cum se face sau nu am mai mai greu, de a putea răspunde mai rapid facut așa ceva, sau mai greu la nevoile clienților lor. • Nu avem timp să facem asta acum, Metodologiile de dezvoltare agile ne dar daca se întampla ceva nasol o să spun că poți să te adaptezi rapid la nevogăsim noi o solutie. ile pieței daca ești agile. Dar ce se întâmplă dacă tu știi că ești agile dar din nevoia de a Iar dacă datoriile sunt extrem de mari răspunde rapid mai bagi niște mizerie sub pe alocuri vedem exprimări de genul “la preș? De câte ori poți să faci asta? Dacă ești mine merge”, “la noi nu se reproduce” sau project manager de câte ori poți să spui ca ”trebuia să fie gata ieri”. spui că echipa tehnică nu a livrat la timp? Este clar că pe termen scurt echipa nu Dacă esti dezvoltator de câte ori poti să are nici o problemă. Dar ce se întâmplă pe reestimezi și să întârzii un task? Poți cere termen lung? Poti să ai probleme mari la un de fiecare dată să reimplementezi totul de demo și atunci ai nevoie de unul sau mai la zero? Dacă ești inginer la testare de câte multe sprint-uri în care să platești datoria ori poți să spui că nu dai release-ul pentru tehnică. Poți să mai ai probleme mari la că ai primit binarele ieri și nu ai avut timp clienți și nu ai cum să creezi un fix rapid să testezi? Daca ești manager de release de care să nu strice altceva. Oare nu cumva se câte ori poți să spui că trebuia să dai rele- poate întampla ca produsul sau serviciul la ase-ul ieri dar nu ai avut ok-ul de la echipa care lucrezi sa își piardă din clienti și pur de QA? De unde vin toate aceste probleme? și simplu să devină falimentar ca business? Cred ca v-ați prins că datoria în Sunt absolut convins că unii dinsoftware se rezumă la toate deciziile de a tre cititorii acestui articol se asteaptă la amâna sau chiar ignora activitați de valoare metodologii, rețete, tool-uri, practici de în dezvoltarea software. Există exprimări dezvoltare software sau agile dar pentru că


management

totul depinde tine și de organizația pe care o transformi zilnic o sa vorbim un pic despre un joc de societate inventat de Software Engineering Institute (de ai nostri). Jocul Hard Choices simulează ciclul de dezvoltare software cu ajutorul conceptelor precum incertitudinea, riscul, opțiunile și datoria tehnică. Din dorința de a deveni lideri de piață în dezvoltarea de software, jucătorii se întrec în a lansa produse de calitate. Până la finalul unui joc toți experimentează implicațiile efortului investit în “a face treaba ca lumea”, pentru a câștiga avantaj competitv, dar și în prețul plătit pentru a apela la scurtături. Jucătorii pot apela sau chiar combina cele două strategii pentru a face față incertitudinii și acesta se aseamănă cu alegerea echipei de a folosi o anumită metodologie pentru dezvoltarea de software. Jocul are câteva reguli simple pentru a fi jucat destul de usor, exact cum Scrum-ul sau Kanban-ul are foarte puține reguli. De asemenea tururile de masă pot fi asemănate cu sprint-urile sau iterațiile cu care echipele agile sunt deja obișnuite. Din regulile jocului observăm că nu contează doar cine termina primul, ci și numărul de puncte adunate pe parcursul jocului, pentru că fiecare unealtă adunată înseamnă un punct valoros care ajută la stabilirea clasamentului final. Cel mai interesant aspect din jocul Hard Choices este faptul că atunci când decizi să alegi o scurtătură vei fi penalizat până când îți platești datoria, similar cu sprint-urile pentru ”technical debt”. Cât de mult ne întârzie lipsa unit testelor? Cu cât suntem penalizați atunci când nu avem teste automate care să ne valideze un build? Cât plătim când întârziem livrarea softului sau a unor fixuri? Oare cât plătim atunci când clienții nu regăsesc aceeași experiență după o actualizare a soft-ului? De asemenea, atunci când jucătorii au în mână o carte unealtă și ajung într-o casuță care conține o nouă unealtă pot s-o folosească imediat aruncând încă o dată cu zarul sau pot să strângă cartea pentru a acumula puncte finale. Această regulă este asemănătoare deciziilor luate în interiorul sprintului, de exemplu în cadrul retrospectivei, decizii luate pentru a îmbunătăți o anumită componentă sau un anumit proces, îmbunătățire care se vede imediat în următorul sprint, poți să mai arunci o dată cu zarul, sau la final când ajunge produsul în piață, se termina jocul.

TODAY SOFTWARE MAGAZINE

Pentru a explica mai bine ce înseamnă datoria software, câțiva ingineri au testat jocul folosind următoarele trei strategii: 1. jucătorul alege tot timpul scurt ătura și pl ătește tot j o c u l scăzându-se un punct la fiecare aruncare de zar, 2. jucatorul alege scurtătura dar plătește imediat stând o tură fară să joace, 3. jucatorul nu alege niciodata scurtătura.

câștigă mai multe puncte, dar contează și câte puncte reușești să aduni pe traseu din colecționarea uneltelor.

În concluzie, acumularea de datorii este strâns legată de amânarea unor decizii și de ignorarea unor practici care pot să aibă rezultate pe termen lung. Poate că este simplu să îți spui că nu te implici în echipă pentru că oricum vrei sa înveți altă tehnologie sau să schimbi proiectul. Dar oare nu există riscul ca în alta parte sa gasești o datorie și mai mare? Ce faci dacă alte Strategia 2 este cea câștigătoare, iar echipe sau companii nu te acceptă în echipă strategiile 1 și 3 sunt aproximativ la fel de dacă nu ești deschis pentru a face pair proeficiente pentru regulile simple ale acestui gramming sau Test Driven Development? joc. Dar dacă am sta două ture sau sprinturi pentru a ne plăti datoria? Dar dacă am fi penalizați cu două puncte la fiecare aruncare de zar? În mod cert strategiile 1 și 3 s-ar diferenția din punct de vedere al eficienței. Totuși scopul jocului nu este să ajungi la final cât mai repede ci să aduni puncte, cum s-ar zice în agile ”livrezi valoare”. Contează cine ajunge la final primul, www.todaysoftmag.ro | nr. 5/2012

27


programare

Planificator Ecologic pentru OpenNebula

Ionuț Anghel, Ph. D

ionut.anghel@cs.utcluj.ro Asistent Doctor Inginer Departamentul Calculatoare Facultatea de Automatica si Calculatoare Universitatea Tehnica din Cluj-Napoca

Tudor Cioară, Ph. D

tudor.cioara@cs.utcluj.ro Asistent Doctor Inginer Departamentul Calculatoare Facultatea de Automatica si Calculatoare Universitatea Tehnica din Cluj-Napoca

28

nr. 5/2012 | www.todaysoftmag.ro

În ultimul timp, consumul de energie datorat proceselor de IT și centrelor de date și servicii, a crescut până la a deveni o adevărată provocare ecologică. Agenția de Protecție a Mediului din Statele Unite (U.S. Environmental Protection Agency [EPA]) a cuantificat acest consum, pentru anul 2006, la suma de 61 miliarde de kilowați-oră, ceea ce înseamnă un cost de peste 4,5 miliarde de dolari. În același raport, este prezentată o dublare a consumului de electricitate necesar centrelor de servicii și date în perioada 2006-2011 și în următorii ani se estimează o accelerare a acestei creșteri datorită adoptării paradigmei „cloud computing”. La nivel mondial, emisiile de CO2 asociate centrelor de date sunt echivalente cu jumătate din emisiile transportului aerian, consumul total de energie fiind estimat la aproape 2% din producția mondială de electricitate [Metha, 2007]. Din raportul Kalyvianaki [Kalyvianaki, 2009] aflăm că pentru fiecare 1.00$ (cheltuieli de capital) cheltuit pentru achiziția de echipamente noi, se cheltuie încă 0.50$ pentru curent și răcire. Având în vedere că atât cererea de servicii, cât și prețul energiei electrice, sunt în creștere, menținerea consumului de energie și a costurilor aferente la un nivel cât mai scăzut este una din prioritățile industriei. O posibilă soluție este scoasă în evidență de studii asupra centrelor de dimensiuni mari (mii de servere), care arată că rata de utilizare medie a resurselor computaționale este de maxim 6% [Kaplan, 2008]. Explicația provine de la concentrarea pe performanță în detrimentul consumului de energie în politicile de management al centrelor. Adaptarea acestor politici pentru reducerea consumului și aplicarea lor dinamică în condițiile unei variații foarte mari a cererii constituie o provocare ce presupune atât complexitate cât și costuri care nu sunt de obicei asumate de către manageri. În aceste circumstanțe, viziunea noastră este să considerăm consumul de energie ca o informație de context relevantă și să

dezvoltăm un sistem adaptiv la context (Green Cloud Scheduler) capabil să gestioneze dinamic consumul de energie și să ia decizii de management și adaptare care încearcă tot timpul să minimizeze acest consum, fără pierderi semnificative de performanță. Pentru început se impune o definire mai exactă a conceptului de “sistem adaptiv la context”. Acestă denumire este dat�� unei anumite clase de sisteme distribuite capabile să detecteze și să înțeleagă schimbările din mediul de execuție și să își adapteze comportamentul în consecință. Spre deosebire de sistemele tradiționale, care nu se folosesc de context pentru a le influența comportamentul, cele adaptive la context, folosesc datele din mediul de execuție, atât cele interne, cât și cele externe, pentru a înțelege și mai ales pentru a se adapta la schimbări, ele dispunând de mecanisme senzoriale pentru a percepe mediul, de raționament pentru a îl înțelege și de un set de acțiuni posibile pentru a se adapta în timp real. Ideea principală din spatele Green Cloud Scheduler (un planificator ecologic de resurse computaționale) este de a modela problema consumului ridicat de energie, ca o problemă de context și adaptare, în care utilizarea resurselor din centrul


TODAY SOFTWARE MAGAZINE

Figura 1. Arhitectura Green Cloud Scheduler de calcul este adaptată dinamic la variațiile nivelului de încărcare, astfel încât eficiența energetică să fie maximizată. În general, în centrele de servicii virtualizate, resursele computaționale sunt supradimensionate pentru a face față încărcării maxime, iar Green Cloud Scheduler va monitoriza schimbările în nivelul de încărcare și va lua măsuri de adaptare, cum ar fi: (i) acțiuni de configurare și consolidare a resurselor (ex. alocarea de resurse către VM (Mașina Virtuală), activarea VM), și (ii) acțiuni de management dinamic al energiei (ex. punerea unui server în hibernare sau trezirea la viață, etc.) Green Cloud Scheduler respectă una din cele mai folosite arhitecturi în domeniul sistemelor adaptive la context: MAPE-K (Monitorizare, Analiză, Planificare, Execuție – Cunoștințe (eng. Knowledge) având în centrul său datele/ informațiile/cunoștințele de context. Faza de monitorizare este responsabilă cu colectarea informațiilor de context legate de consumul de energie și cerințele de performantă din întreg centrul de date și reprezentarea acestor date într-o formă uniformă și pretabilă procesării ulterioare folosind ontologii. Această abordare permite analiza automată a consumului de energie și inferarea de noi cunoștințe folosind tehnici de raționare. Faza de analiză evaluează Service Center Greenness Level (Nivelul Ecologic al Centrului de Servicii) prin compararea valorilor unui set de GPI/KPI (Green Performance Indicators/Key Performance Indicators - eng. Indicatori de Performanță Ecologici/Indicatori Cheie de Performanță) evaluate în faza de monitorizare cu un set de valori de referință stabilite în faza de design a centrului de date. Acești indicatori sunt reprezentați în XML și convertiți în SWRL, pentru a permite evaluarea prin raționare, fiind clasificați după cum urmează: (i) indicatori

de nivel aplicație, cum ar fi: timpul de răspuns și performanta, (ii) indicatori de nivel virtualizare, cum ar fi: alocarea VM CPU și memorie VM și (iii) indicatori de infrastructură, cum ar fi: MHz/Watt, Deployed Hardware Utilization Ratio (DH-UR – Rata de Utilizare a Hardware-ului), Power Usage Effectiveness (PUE – Eficiența Utilizării Puterii energetice). Dacă nivelul Service Centre Greenness Level este sub un prag predefinit și toți indicatorii sunt îndepliniți, considerăm centrul într-o stare verde din punct de vedere al consumului și nu este nevoie de acțiuni de adaptare. În caz contrar este inițiată o fază de planificare și aceasta va lua deciziile necesare pentru selectarea celei mai bune acțiuni de adaptare care va aduce centrul într-o stare verde. Faza de planificare are ca scop principal luarea automată a unei decizii, fără intervenție umană, privind secvența corectă de acțiuni de adaptare care trebuie executată pentru a impune valorile minime ale GPI/KPI și a aduce centrul într-o stare verde. Procesul decizional are în centru său un proces de analiză “whatif ” implementat folosind tehnici specifice de învățare automată (eng. reinforcement learning). Acest proces construiește un arbore decizional prin simularea tuturor acțiunilor ce ar putea îmbunătății eficiența energetică a centrului (ex. pornirea sau migrarea unei mașini virtuale, pornirea/ oprirea unui server fizic), iar apoi selectează secvența optimă folosind un sistem de penalizări/recompense. Faza de execuție are ca scop execuția dinamică, în timp real, a acțiunilor determinate în faza de planificare. Un Modul de Acces la Infrastructură ii oferă Green Cloud Scheduler mijloacele necesare accesării resurselor hardware și software din centrul de date pentru a impune acțiunile din planul de adaptare. Acest modul (vezi Figura 2 - Infrastructure Access Module)

este format din: • CentOS 5.5 Linux sistemul de operare folosit de serverele din centrul de servicii. Implementarea Green Cloud Scheduler este generică, deci poate fi folosită cu orice altă distribuție de Linux. O acțiune adaptivă posibilă la nivelul sistemului de operare fiind oprirea unui server, exemplificata în codul de mai jos, unde Global Control Loop (Bucla Globală de Control) execută codul necesar pentru realizarea acțiunii. // connect through ssh to the target server // IP = host.getHostname() and issue a // shutdown command String cmd = “/usr/bin/ssh” + host.getHostname() + “sudo /sbin/shutdown -h now”; Process proc = Runtime.getRuntime(). exec(cmd); // wait until the server does not respond to // ping anymore waitUntilTargetIsOff(host.getHostname()); proc.getInputStream().close(); proc.getOutputStream().close(); proc.getErrorStream().close(); proc.destroy();

K V M ( Ke r n el - b a s e d Vir tu al Machine) este un hypervisor (supervizor) care are rol în virtualizarea resurselor hardware și se instalează peste CentOS. Principalele funcții folosite sunt cele de monitorizare și management ale mașinilor virtuale. OpenNebula este un middleware pentru managementul norilor (eng. clouds). A fost ales datorită popularității, dar Green Cloud Scheduler poate fi ușor adaptat oricărei alte platforme de management infrastructură. OpenNebula oferă funcționalități de management ale tuturor mașinilor virtuale din centru, cum ar fi: crearea, instalarea, migrarea, etc. Middleware-ul OpenNebula implementează două tipuri diferite de migrare (vezi codul de mai jos): (i) migrare live (liveMigrate) – serverele migrează mașina virtuală fără a o opri și (ii) migrare off-line (migrate) – cu oprirea mașinii virtuale pe perioada copierii pe un server nou.

PhysicalHost destination; // get a reference to an existing virtual // machine having the // OpenNebula ID = taskinfo.getID() VirtualMachine machine = new VirtualMachine(taskInfo.getId(), client); // issue a live migration or an offline // migration depending on the configuration // of the GCL OneResponse response = (GeneralConfigrationManager. getVMMigrationMechanism().quals(„live”)) ? machine.liveMigrate(destination.getId()) : machine.migrate(destination.getId()); if (response.isError()) { throw new ServiceCenterAccessExcepti on(response.getErrorMessage()); }

www.todaysoftmag.ro | nr. 5/2012

29


programare

Open SSH este folosit pentru comunicarea în rețea, atât cu serverele cât și cu mașinile virtuale. Wake on LAN este un instrument folosit pentru a porni un server folosind o conexiune la rețea. De exemplu comanda >wol serverMAC din codul de mai jos.

// GeneralConfigurationManager. // getNodesWakeUpMechanism() returns // „wakeonlan”(Ubuntu) or // „wol” (CentOS/Scientific Linux) String cmd = GeneralConfigurationManager. getNodesWakeUpMechanism() + „ „ + physicalHost.getMac(); //execute the wakeonlancommand Process proc = Runtime.getRuntime().exec(cmd); OutputStream outputStream = proc.getOutputStream(); InputStream stdin = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(stdin); //log the wakeonlan output BufferedReader br = new BufferedReader(isr); String line = br.readLine(); if (line != null) { GlobalLoopLogger.getLogger().debug(line); } //wait until server responds to ping GlobalLoopLogger.getLogger(). info(„Waiting for” + physicalHost.getHostname() + „ to respond to ping”); waitUntilTargetIsAlive( physicalHost.getHostname()); // wait until server responds to SSH // connection request needed because SSH is // used by OpenNebula to deploy/migrate // virtual machines GlobalLoopLogger.getLogger().info( „Waiting for” + physicalHost.getHostname() + „ to respond to SSH”); waitUntilSSHAvailable( physicalHost.getHostname());

Pentru implementarea arhitecturii MAPE-K s-a folosit stiva de software prezentată în Figura 2. Pe scurt: s-a folosit JaDE (Java Agent DEvelopment

Figura 2. Stiva Green Cloud Scheduler si Infrastructure Access Module

Figura 3. Eficientizarea Consumului de Energie. Rezultate comparative Framework) pentru agenții inteligenți ce ajută la luarea deciziilor în fazele MAPE; Java RMI (Java Remote Method Invocation) pentru comunicarea între module; Apache Log4J pentru logare; AspectJ permite monitorizarea codului în timpul rulării și îmbunătățește nivelul de detaliu în faza de monitorizare; Java WS (Java Web Services) pentru comunicarea gradului de încărcare; JAXB (Java Architecture for XML Binding) folosit pentru transmiterea parametrilor intre module. Odată definită arhitectura de bază și implementarea unui prototip funcțional, echipa a cercetat și diferite metode de îmbunatățire a managementului resurselor prin folosirea unor algoritmi inspirați din biologie (un exemplu ar fi folosirea unei analogii între grupări de servere și formațiunile V ale păsărilor migratoare, pentru a determina când un server este considerat aglomerat, când poate accepta încărcare suplimentară și când poate fi oprit, nefiind folosit). Dar cel mai important pas a fost aplicarea practică a cercetării în cadrul a două proiecte: 1. Poiectul GAMES (Green Active Management of Energy in IT Service centers), proiect european în care un consorțiu de opt entități din mediul academic și industrie au aplicat cunoștințele acumulate în două implementări: HLRS în Stuttgart (Germania) și centru de servicii Engineering Pont SaintMartin (Italia); obținându-se creșteri ale eficienței energetice cu până la 25-30%, fără scăderi ale

performanței sau calității serviciilor. 2. Green Could Scheduler pentru OpenNebula, este inițiativa prin care încercăm să diseminăm tehnologia în cadrul comunității OpenSource și s-a materializat prin trimiterea modulului către OpenNebula Community Manager, i ar î n u r m a u nu i Au d it d e performanță acesta a fost acceptat și inclus în oferta OpenNebula Ecosystem, putând fi descărcat de la adresa http://opennebula.org/ software:ecosystem:green_cloud_ scheduler, instalat și folosit. În încheiere am dori să prezentăm rezultate comparative între OpenNebula Scheduler și Green Cloud Scheduler. După cum se vede în cazul folosirii algoritmului Fit-First al Open Nebula consumul energetic este de 1032 Wh, pe când folosind Green Cloud Scheduler avem un consum de 871 Wh, rezultând o reducere a consumului de energie cu 15.6%. Aceste rezultate confirmă faptul că prin folosirea unor strategii de alocare mai bună a resurselor se pot obține rezultate care să aibă un real impact asupra mediului și a costurilor energetice impuse de creșterea consumului de servicii IT, practic fără nici un fel de costuri suplimentare, doar instalarea unui modul software. Suntem siguri ca prin relaxarea criteriilor de performanță și prin investigarea altor strategii de reducere a consumului, putem să împingem eficiența energetică și mai mult.

Bibliografie [EPA] U.S. Environmental Protection Agency - ENERGY STAR Program, Report to Congress on Server and Data Center Energy Efficiency - Public Law 109-431, 2007. [Metha, 2007] V. Metha - A Holistic Solution to the IT Energy Crisis - 2007. [Kalyvianaki, 2009] E. Kalyvianaki - Resource provisioning for virtualized server applications - University of Cambridge Tech. Report, Number 762, ISSN 1476-2986, 2009. [Kaplan, 2008] J. M. Kaplan, W. Forrest and N. Kindler - Revolutionizing data center energy efficiency - McKinsey & Company, 2008.

30

nr. 5/2012 | www.todaysoftmag.ro


UIX

TODAY SOFTWARE MAGAZINE

Designul experienței utilizatorului și moduri de aplicare în dezvoltarea produsului

D

Sveatoslav Vizitiu info@sveatoslav.com User Experience and User interface Senior Designer Designer și consultant independent din România, cu vastă experieță în UI, UX, Interaction design, Information design, Visual design, Web Design, Web 2.0 și Web development.

esign-ul experienței utilizatorului și al interfeței (UX) se referă la un concept care plasează utilizatorul final în centrul eforturilor de design și de dezvoltare, spre deosebire de sistem, de aplicațiile sale sau doar valoarea sa estetică . Cerința pentru un UX exemplar este satisfacerea nevoilor exacte ale clientului. Eleganța și simplitatea conferite de designer garantează un bun grad de utilizare și convingere utilizatorului de a cumpăra. Unul din principalele scopuri ale oricărui bun designer este comunicarea mesajului într-un mod care duce la o experiența bună pentru utilizator. Prezentul articol oferă un insight în acest proces. Design-ul înseamnă din ce în ce mai puțin rezolvarea problemelor și eliminarea frustrărilor. Totul se învârte, din ce în ce mai mult, în jurul îmbunătățirii experienței utilizatorului. Acum nu mai e de ajuns utilizabilitatea. Design-ul trebuie să se integreze în viața oamenilor. Chiar trebuie să aducă fericire în viața oamenilor și să anticipeze nevoile lor. U X - u l i n c lu d e t o at e a s p e c t e l e interacțiunilor dintre utilizatorul final și companie, servicii și produse. Un bun UX înseamnă satisfacerea nevoilor exacte ale clientului. Pentru a obține calitate înaltă, UX-ul trebuie să fie o îmbinare perfectă de mai multe servicii, inclusiv designul interfaței, industrial, de inginerie și marketing. Unul din principalele scopuri ale oricărui bun designer este comunicarea mesajului într-un mod care duce la o experiență bună pentru utilizator. Culoarea textului, aliniamentul paginii, imaginile, modelul de design – toate sunt parte a acestei comunicări, indicii care deseori rămân neobservate sau neexprimate, dar care au un rol decisiv în UX. Aceasta poate include interacțiunile cu un software, o pagina web, un call center, o reclamă, un sticker pe calculatorul cuiva, o aplicație pe mobil, un cont Twitter, prin e-mail, poate chiar față în față. Suma totala a acestor interacțiuni alcătuiesc UX-ul .

și reconfortant. Ne permite să trăim și să functionăm cu o anumită ușurință care nu necesită gândire activă permanentă. Construirea unui produs de succes rareori se face copiind produsele altora. Produsele de succes se creează schimbând, în mod fundamental, percepția oamenilor despre ce le va satisfice nevoile și asigurând o tranziție ușoară către noul produs.

Experiențele bune sunt simple

“Simplitatea este sofisticarea extremă” – Leonardo da Vinci Când produsul este atât de complet încât nu mai este nimic de adăugat sau de înlăturat. Când lucrurile sunt ințelese perfect și reprezentate de statutul și aspectul lor, să le privești înseamnă să le înțelegi și să le cunoști. Dacă oamenii pot ințelege și folosi ceva cu mică dificultate, atunci s-a creat ceva simplu. Dar simplitatea nu e ușor de creat, doar pare astfel.

Ciclu de viață

Pe masură ce utilizatorii interacționează cu produsul sau serviciul tău, ei trec printro serie de pași numită ciclu de viață . Ca orice alt ciclu de viață, ciclul de viață de utilizare are un început, un mijloc și un sfârșit. Etapele ciclului de viață: • Primul contact – oamenii află despre produs, • Prima utilizare – prima utilizare a produsului și momentul în care utiPrincipiile UX lizatorul reflectă asupra obligațiilor Pentru cei mai mulți oameni, schimpe termen lung; este prima reală barea înseamnă frică și stres și impune impresie despre produs, familiarizarea cu produsul, însă poate fi • Utlizarea continuă – folosirea www.todaysoftmag.ro | nr. 5/2012

31


UIX Designul experienței utilizatorului și moduri de aplicare în

regulată a produsului, Utlizarea entuziasmată – utilizatorul devine imersat în produs, Moarte – oamenii încetează sa mai folosească produsul.

• •

Conversație

UX înseamnă, de fapt, un bun marketing. Înseamnă să cunoști piața și orientarea pieței și să faci un design corespunzător. Mai înseamnă și să colectezi feedback și să faci schimbările în funcție de orientarea pieței, îmbunătățind experiența elementelor pieței, luând în considerarea semnul de egal dintre utilizatori și piața. Utilizatorii înseamnă piața pentru care faci design. UX-ul, ca și marketing-ul, creează un dialog cu utilizatorii, al cărui scop este învățarea și îmbunătățirea experienței lor.

Invisibilitate

Când utilizatorul se bucură de un bun UX, nu se gândește la munca depusă pentru a crea acel design. Un bun UX înseamnă că nimeni nu vorbește despre designeri.

Context

Nu există un răspuns corect pentru o problemă de design. Există doar răspunsuri bune, proaste și mai bune pentru situația actuală. Fiecare soluție potențială se află într-un context anume. Pentru a obține un răspuns optim, trebuie să știi contextul în care se află. Trebuie avut în vedere scopul și resursele necesare atingerii acestuia. Un designer trebuie să știe care sunt țelurile aplicației sau ale problemei tratate, ce doresc utilizatorii, ce știu aceștia și conținutul.

Social

Un designer tinde să se gândească la ce încearcă să obțină, ce a construit în trecut, și deci, în termeni de ce face sau ce ar trebui să facă. Aceasta duce la încercarea de a controla totul, de a ajusta caracteristici. Socialul se petrece în lume și utilizatorii nu te au pe tine sau produsul tău în minte, ci propriile experiențe și cei cu care le împărtășesc. Schimbă cadrul în care lucrezi. Nu mai avem de-a face cu oameni ci cu vieți sociale. Trebuie să facem față atât comportamentului individual cât și mediului veșnic schimbător al cărui nuanțe influențează comportamentul.

Strategia UX

Strategia de design e în serviciul

32

nr. 5/2012 | www.todaysoftmag.ro

utilizatorului. Adevărata provocare este rezolvarea problemei umane. Înseamnă înțelegerea nevoilor și aspirațiilor lor și satisfacerea lor, deci servirea utilizatorului. Uneori, nevoile lor sunt de a fi suprinși și încântați, însă nu ne pot spune cum să îi surprindem sau să îi încântăm. Acest lucru e datoria designer-ului, de profesie creativi. Designer-ul de UX trebuie să poată răspunde clar la cinci întrebări pentru a crea un produs ce rezonează imediat cu clientul. Pentru a dobândi această viziune și strategie, un expert UX trebuie inclus în proiect de la începutul acestuia, având o pozitie unică pentru a răspunde la aceste întrebări : Ce problemă încercăm să rezolvăm? Înainte să începem construcția unui produs, trebuie să identificăm problema pe care încercăm să o rezolvăm. Problema trebuie prezentată cât se poate de clar și concis. Odată formulată astfel, avem o lentilă prin care putem răspunde la restul întrebărilor, clarificând scopul și elaborând strategia. Cine este clientul? Este una din cele mai importante întrebări pentru fiecare produs nou. Fără a înțelege clar cine este publicul țintă, există riscul să construim un produs ce nu satisface sau nu se potrivește cu așteptările clientului. Cercetările legate de utilizatori, etnografia și personajul, sunt toate componente ale instrumentelor UX care pot răspunde la această întrebare. Cum putem îmbunătăți structura și soluțiile existente? E foarte valoros să înțelegem cum au încercat alții să rezolve o problemă similară pentru a putea evita greșelile lor, pentru a identifica structurile eșuate sau care au nevoie de îmbunătățiri și pentru a identifica momentele călătoriei clientului care îl pot surpinde și încânta. Această întrebare ne-o vom pune de nenumărate ori în timpului procesului de design. Când ar trebuie să începem să primim feedback de la utilizatori? Devreme și des e răspunsul comun la această întrebare, însă nu e întotdeauna adevărat. Dacă îl prezentăm prea devreme, riscăm ca dezvoltarea produsului sa fie dirijată de utilizator. Dacă îl prezentăm prea târziu pierdem feedback valoros care ar putea evita excesul. Înțelegând cine sunt clienții țintă și cum se pot îmbunătăți soluțiile existente ne ajută la identificarea momentului în care se poate incorpora

feedback-ul în dezvoltarea produsului. De ce rezolvă produsul nostru problema? După identificarea problemei pe care încercăm sa o rezolvăm, cine este publicul țintă și unde se pot aduce îmbunătățiri, ar trebuie sa putem explica de ce soluția noastră e bună. Aceasta ar trebui să fie baza scopurilor pe termen scurt în cadrul unei strategii pe termen lung. Cum pot informațiile ajuta la înțelegerea produsului pe c are îl construiești? Există numeroase analize care pot fi folosite pentru a confirma presupuneri, decizii de design și pentru a clarifica modul în care produsul se potrivește pe piață. Tehnici precum: data mining, eyetracking, testare A/B, user flow, cercetări etnografice, benchmarking și multe altele pot fi folosite pentru o mai bună înțelegere. Niciun detaliu nu e prea mic pentru a fi testat. Copy, layout și interacțiune – în toate aceste cazuri, informații bune pot ajuta la înțelegerea rezultatelor și ajustarea lor. Companiile care încep prin a răspunde la aceste întrebări și se implică în procesul de UX design au șanse mai bune de a crea produse viabile, longevive decât companiile care le construiesc fără aceste răspunsuri. În lumea mereu în creștere a start-up-urilor, cei care apreciază și aplică UX-ul de la început vor fi cei de succes. Un instrument obiectiv pentru măsurare și analiză ajută să oferim clienților recomandări bazate pe fapte, și nu doar opinii și presupuneri. Metodologia prezentată în acesta articol va ajuta să : • Elimine preferințele personale (subiectivitatea) cât de mult posibil, • Permită persoanelor de profesii diferite (designer, developer, client) sa înțeleagă la fel produsul, • Ofere clienților o prezentare faptică a beneficiilor și limitărilor produsului lor, • UX-ul este format din patru factori principali: • Branding, • Gradul de utilizare, • Funcționalitate, • Conținut. De unul singur, niciunul din acești factori nu oferă o bună experiență; totuși, împreună, acești factori constituie principalele ingrediente ale succesului unui produs. Mai jos se pot găsi explicații pentru


TODAY SOFTWARE MAGAZINE fiecare element și parametrii de bază folosiți într-un model de analiză.

Branding

Se referă la frecvența și gravitatea erorilor, cât de des utilizatorul face greșeli în timp ce utilizează sistemul, cât de grave sunt aceste erori și cum reactionează utilizatorul la ele. Memorabilitate: dacă a folosit sistemul înainte utilizatorul poate să iși amintească suficient de acea experiență pentru a-l utiliza în mod eficient data următoare sau trebuie să reînvețe totul de la început?

Branding-ul include toate elementele legate de estetică și design ale unui produs. • Implică proiectarea mesajului și imaginii dorite pentru un produs. Moduri de a măsura branding-ul includ: • Impactul vizual al produsului e în concordanță cu identitatea brand-ului. • Grafica, elementele specifice și mul- Conținut timedia imbunătățesc experiența. Conținutul se referă la adevăratul conținut al produsului (text, multimedia, imagini etc.) dar și structura sau arhitectura acestuia. E important modul în care informația și conținutul sunt structurate în moduri definite de nevoile utilizatorului dar și de client. Moduri de a măsura conținutul includ: • Conținutul este structurat într-un mod care facilitează atingerea scopului utilizatorului. • Conținutul este conform nevoilor și scopurilor utilizatorului și clientului. • Conținutul este comprehensiv în mai multe limbi. Figura 1. UX-ul este format din 4 eleMăsurarea eficacității design-ului este mente interdependente un lucru nou pentru mulți designeri. Și, într-adevăr, suntem la început și încă mai • Produsul este în conformitate cu avem de învățat până să ajungem să o imaginea percepută a brand-ului. facem bine. Există mai multe motive pen• Produsul se bazează pe mediu pen- tru care design-ul nu se măsoară, inclusiv tru a extinde brand-ul. datorită faptului că nu s-a stabilit un sistem de evaluare comun, nefiind clar cum Funcționalitate se măsoară experiența utilizatorului legat Funcționalitatea include toate procesele de un produs/serviciu și nu se poate statehnice, „din spatele scenei”, livrarea de bili o metodologie. Niciunul din aceste servicii interactive destinate utilizatorilor lucruri nu e ușor: e nevoie de o întreagă finali, atât publicul cât și administratorii. cultură dedicată colectării de feedback și Moduri de a măsura funcționalitatea sunt: îmbunătățirea sa, abilitatea de a accesa date • Utilizatorul primește răspunsuri legate de utilizatori și website, dar și abilirapide la întrebări. tatea de a programa și porni o inițiativă de • Progresul unui task e comunicat rectificare a unui feedback negativ. clar. Fiecare proiect are nevoie de anumite instrumente în funcție de provocarea pe Grad de utilizare care o are în față. Cele care pot ajuta cel mai Gradul de utilizare înseamnă ușurința mult în ceea ce privește claritatea datelor și de utilizare a componentelor și feature-uri- creșterea productivității sunt : lor produsului. Moduri de a măsura gradul Schițele sunt grafice trasate de mână de utilizare sunt : care conțin idei de ecran sau grafice de • Eficacitate: abilitatea utilizatorului explicații a celei mai importante probleme de a folosi cu succes un Website sau soluții. Sunt foarte importante înainte pentru a găsi informații și a înde- de formarea, explorarea sau realizarea plini sarcini. ideilor. Schițele vor ajuta la clarificarea ele• Eficiența: abilitatea unui utilizator mentelor necesare îndeplinirii scopurilor. de a îndeplini sarcini rapid, ușor și Wire-frames sunt grafice generate fără frustrări. pe calculator ce ilustrează organizarea de • Satisfacție: cât de mult un utiliza- conținut, feature-uri și funcționalitate. tor folosește Website-ul cu plăcere. Prioritizarea elementelor de design și

determinarea planului general poate fi foarte haotică. Un wire-frame bine construit va evidenția piesele individuale și se va asigura că aparțin de pagina corespunzătoare. Mock-ups sunt grafice bogate ce simulează aspectul și atmosfera proiectului pentru o mai bună înțelegere a impactului vizual asupra brand-ului. Un mock-up poate prezenta adevărată impresie și poate comunica adevăratele sentimente și personalitate ale unui proiect. Fără a construi cu adevărat site-ul (ceea e o mulțime de oameni fac), nu există altă metodă de a defini în mod concret cum ar trebui să arate produsul final. Prototipurile HTML sunt versiuni parțial complete ale website-ului folosite pentru a înțelege cum vor interacționa paginile între ele dar și fluxul de la o zonă la alta. Interacțiunile mai complicate ale unor componente mai sofisticate necesită prototipuri funcționale pentru a le putea înțelege. Când există multe elemente mișcătoare și țeluri cu mai multe etape, prototipurile HTML sunt utile pentru a acoperi golurile dintr-un plan. Pentru cei mai mulți dinte noi, majoritatea muncii înseamnă perfecționarea, actualizarea și îmbunătățirea sistemelor existente. Noile cadre de design apar cu scopul de a le face reutilizabile, designuri elastice și ca un drum spre inovație. Pe măsură ce aplicațiile și produsele devin din ce în ce mai complexe, cu siguranță nu dorim să ne petrecem timpul reinventând roata. Dar aceste sisteme, cadre și „bune practici” ne pot împiedica să ieșim din tipar și să cream ceva cu totul nou.

Concluzii

Testarea gradului de utilizare e unul dintre cele mai bune lucruri care se poate face pentru a înțelege dacă utilizatorii pot folosi produsul așa cum a fost menit. Mulți oameni susțin că această testare este dificilă, neconcludentă și chiar o pierdere de timp. Credem că multe din aceste noțiuni sunt consecințe ale neînțelegerii procesului sau cerințelor pentru testare. Da, testele cantitative, calitative și cele de dezvoltare comparativă pot fi copleșitoare. Adevărul e că ceva testare e mai bine decât deloc. Poate încă te gandești că acest lucru nu va funcționa pentru tine. Stilul „doit-yourself ” pentru testarea gradului de utilizare a început să rezoneze cu designeri, ingineri și manageri de produs. Poate ajuta la îmbunătățirea produsului, ceea ce va duce la clienți fericiți și satisfăcuți. www.todaysoftmag.ro | nr. 5/2012

33


programare

Construirea interfețelor web dinamice folosind MVVM și ASP.NET

K

nockout este o librărie Javascript care ne ajută la crearea paginilor web „desktop like”, care au un data model clar stabilit și ne permite ca UI ul să fie perfect sincronizat cu data model. Knockout este un proiect open-source creat de Steve Sanderson, programator la Microsoft. Este proiectul lui personal, nu este proprietatea companiei Microsoft. Codul sursă poate fi descărcat de pe GitHub, iar documentația relevantă, precum și ultimele notificări de pe siteul: http://www.knockoutjs.com Csaba Porkoláb

cporkolab@macadamian.com Software developer @ Macademian

Codul sursă este javascript nativ, nu se folosește de alte librării javascript. Se integrează foarte bine cu ASP.NET și cu alte limbaje server-side. În pagina HTML trebuie să inserăm referința către librăria Knockout.

De ce Knockout? •

mai ușoare testarea și suportul aplicației. Istoric vorbind, MVVM se trage din MVP (Model-View-Presenter). În acest pattern Modelul reprezintă efectiv datele din aplicație, View-ul reprezinta UI-ul, iar Presenter-ul face legătura dintre cele două. Practic Presenter-ul ține referințe atât către Modele, cât către View-uri.

Elegant dependency tracking - face update la UI în mod automat ori de Caracteristici ale lui MVVM: câte ori Data Model se schimbă. • Modelul reprezintă partea de date • Folosește Declarative Bindings din aplicație. Toate clasele de busicu o sintaxă specifică, Knockout ne ness (domain objects) fac parte din permite să ne conectăm din UI la Model. Data Model. • Între View-uri și ViewModel-uri • Este extensibil – au apărut o serie de există o relație de unu la unu, fieplugin-uri după release. Knockout care View are propria instanță de are deja o comunitate activă bine ViewModel. Pentru a realiza o formată. separare clară între logică și UI, DOM-ul poate fi foarte ușor manipulat funcționalitatea se implementează cu JQuery, dar JQuery nu oferă o decuplare în ViewModel. ViewModel-ul apeperfectă a funcționalității de UI. Rezultatul lează clasa de business, dacă este folosirii librăriei Knockout va fi un cod cazul. mult mai structurat. Knockout se folosește • Decuplând total partea de UI de de patternul MVVM. Folosind Knockout partea de logică, putem foarte ușor putem renunța la event-handlerele masive, aplica Unit testing pe core. În cazul care se intersectau. În Knockout totul este unei aplicații cu procese complexe, declarativ. acest lucru este de o importanță crucială.

Despre patternul MVVM (Model View ViewModel)

Patternul Model-View-ViewModel (MVVM) ne ajută la separarea nivelului de business de interfața grafică (UI). Această separare ne ajută la evitarea multor probleme de development și de design, făcând

Figura 1. - Paternul MVVM

34

nr. 5/2012 | www.todaysoftmag.ro

Dacă folosim ASP.NET / MVC, Business Logic and Data va fi o clasă de tip controller care returnează JSON. Folosind rutarea MVC, fiecare funcție din controller are popriul ei URL, care poate fi ușor apelată din templateul razor (View). Presentation Logic va fi o clasă javascript cu aceeași structură ca și clasa C#, iar logica UI va fi definită în templateul Razor. ViewModel-ul poate fi generat din JSON folosind plugin-ul de knockout mapping.


TODAY SOFTWARE MAGAZINE var viewModel = ko.mapping. fromJS(jsonString); <div id=”PatientForm”> <p><label>Firstname: </label> <span data-bind=”text: firstName”> </span></p> <p><label>Lastname: </label> <span data-bind=”text: lastName”> </span></p> <p><label>Fullname: </label> <span data-bind=”text: fullName”> </span></p> </div> <script language=”javascript” type=”text/javascript”> var viewModel = { firstName: ko.observable(‘John’), lastName: ko.observable(‘Harlid’), fullName: ko.computed(function() { return this.firstName() + “ “ + this.lastName(); }, this) } ko.applyBindings(viewModel, $(‘#PatientForm’)); </script>

În exemplul de mai sus avem un viewModel definit și un HTML template. Legătura dintre viewModel și un DOM element se realizează cu applyBindings. Dacă nu specificăm DOM element și scriem doar ko.applyBindings(viewModel), legătura se va face cu HTML body. Proprietățile firstName și lastName sunt observables, adică sunt supervizate. Dacă se schimbă valoarea lor, UI-ul va fi updatat. FullName e o proprietate de tip computed și va fi updatat dacă firstName sau lastName se va schimba. Un observable este o funcție care ne returnează the latestValue dacă este apelată fără vreun parametru. Putem superviza și obiecte de tip array utilizând observableArrays, Knockout punându-ne la dispoziție o gamă largă de funcții pentru manipularea lor, cum ar fi. push, remove, removeAll. Legăturile (bindings) predefinite de knockout dintre care nu le vom enumera decât pe cele importante se împart în trei categorii: 1. Legături care controlează textul și aparența sunt: a. Visible binding: Ascunde sau arată un element DOM

d. Css binding: Adaugă sau șterge o clasă sau mai multe clase CSS asociate elementului DOM în funcție de o condiție; errorCount este un observable și returnează int <span data-bind=”css: {errorWarning: errorCount() > 0, hide: errorCount () ==0}”>

Style binding: Adaugă sau șterge un style CSS asociat elementului DOM în funcție de o condiție; errorCount este un observable și returnează int <span data-bind=” css: { color: errorCount() > 0 ? ‚red’ : black’}”>

e. Attr binding: Adaugă sau șterge atribute asociate unui element DOM <a data-bind=”attr: { href: url, title: details }”> 2. Control flow bindings: a. Foreach binding: Ne permite afișarea unui template de mai multe ori bazat pe un observableArray <ul data-bind=”foreach: students”> $index<li data-bind=”text: name”> </ul>

În exemplul de mai sus am afișat numele studenților. $index afișează indexul curent al elementului iterat. $parent este obiectul părinte. b. If binding: Cu ajutorul lui putem adăuga sau șterge elemente DOM pe baza unui observable de tip boolean. Dacă displayMessage e false atunci div-ul va fi scos din DOM. În loc de un observable de tip boolean putem folosi expresii logice complexe. <div data-bind=”if: displayMessage”> Here is a message. </div>

3. Event bindings: a. Click binding: Va executa o funcție definită în viewModel în caz de click <button data-bind=”click: doSomething”>

b. Event binding: Permite atașarea unui event javascript la obiectul DOM.

<div data-bind=”event: { mouseover: enableDetails, mouseout: disableDetails }”>

<div data-bind=”visible: isVisible”>

(isVisible este un observable și returnează boolean) b. Text binding: Setează proprietatea innerText al unui element DOM <span data-bind=”text: myMessage”> (myMessage este un observable și returnează string) c. Html binding: Setează proprietatea innerHTML al unui element DOM <span data-bind=”text: myHtml”> (myHtml este un observable și returnează string)

Figura 2. - Clasele KO

Legături virtuale

Legăturile de tip “Control flow” pot fi aplicate și elementelor DOM virtuale. <ul> <li class=”heading”>My heading</li> <!-- ko foreach: items --> <li data-bind=”text: $data”> </li> <!-- /ko --> </ul>

Custom Mappings

Nu suntem limitați numai la folosirea legăturilor definite în librăria Knockout, ci putem crea unele noi. Primul pas în procesul de creare este înregistrarea legăturii ca o subproprietate a clasei ko.bindingHandlers: Parametrii de intrare celor două funcții coincid: ko.bindingHandlers.legaturaNoua = { init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { // Va fi apelată atunci când legătura se // realizează cu un element DOM. }, update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { // Va fi apelată atunci când legătura se // realizează cu elementul DOM sau // când se schimbă valoarea unui observable // în model } };

• •

• •

element – elementul DOM cu care se realizează legătura valueAccessor – este o funcție Javascript, care returnează proprietatea din model, care e invocat în legătura curentă allBindingsAccessor – este o funcție Javascript, care returnează toate proprietățile legate de elementul DOM. viewModel – obiectul viewModel, care a fost folosit la inițializarea legăturii în funcția applyBindings. bindingContext – obiectul care conține datele de context al legăturii. Conține proprietăți ca $parent, $root, care pointează spre o legătură părinte, precum la legătura de rădăcină.

Concluzii

Knockout este o librărie compactă. Merită folosită în cazul paginilor mai complexe, care au multe apeluri Ajax. Un dezavantaj al librăriei ar fi viteza în cazul paginilor supra-aglomerate cu legături. Durata procesului de generare a legăturilor unei pagini are aproximativ 30 de secțiuni legate de câte un observableArray poate fi de o secundă și astfel sunt cazuri când tranziția devine vizibilă.

www.todaysoftmag.ro | nr. 5/2012

35


HR

Social networks

T

oată lumea a auzit, cu siguranță, despre ”Social Networks”, sau mai pe românește despre ”Rețele de socializare online”. Nenumărate articole pe această temă au fost scrise, care mai de care mai detaliate despre istoricul conceptului, despre plusuri și minusuri, despre confidențialitatea informației. Acest articol are ca scop indentificarea impactului pe care prezența pe aceste site-uri de socializare îl are asupra procesului de recrutare. ”Rețele de socializare” sunt destul de numeroase, dar pentru că spațiul este limitat, articolul va face referire doar la două dintre ele: Facebook și LinkedIn.

Andreea Pârvu

andreea.parvu@endava.com Recruiter în cadrul Endava și trainer specializat în dezvoltarea abilităților si competenețelor de leadership, comunicare și muncă în echipă

36

nr. 5/2012 | www.todaysoftmag.ro

Circula vorba prin ”târg” dacă nu ești pe Facebook, nu exiști?! Prima dată când am auzit această expresie mi s-a părut amuzantă și de neluat în serios. Facebook a ajuns la 1mld. de utilizatori și acum pot spune că afirmația de mai sus nu este deloc de neglijat. Totul se întâmplă pe Facebook, de la campanii de recrutare, la recrutarea efectivă a candidaților. Facebook-ul are avantajele și dezavantajele lui. Înainte de orice este considerat ca fiind un spațiu personal, însă orice apariție pe internet este publică și devine vizibilă și pentru alții. Sunt recruiteri care utilizează Facebook-ul ca o sursă de identificare a candidaților. Mi s-a întamplat să găsesc informații actualizate în comparație cu clasicele site-uri de recrutare. Pe Facebook toată lumea are profilul actualizat: de la compania unde lucrează la activitățile extra pe care le întreprinde. Scopul nu este de a scrie un articol despre cum se utilizează Facebook-ul pentru că mai mult ca sigur fiecare din noi știe acest lucru, dar cu siguranță mulți dintre noi nu luăm în considerare impactul pe care îl poate avea ceea ce se publică pe profilul personal, motiv pentru care voi lua fiecare secțiune care mi se pare relevantă în procesul de recrutare și o voi analiza din perspectiva ”Așa îmi doresc să văd un profil”. Secțiunea About you – o consider ca fiind extrem de relevantă în culegerea unor informații cât mai relevante despre candidatul cu care urmează să interacționez. Cu cât este mai detaliată, cu atât poate constitui un mare plus. Ce fel de informații caut eu ca și recruiter? Cred că cel mai simplu mi-ar fi să exemplific: o persoană care are ca motto ”Nothing is impossible”, mă gândesc că este o persoană orientată spre obținerea rezultatelor și identificarea soluțiilor indiferent de circumstanțele în care se află.

Secțiunea Work and Education vă recomand să o lăsați vizibilă publicului larg. Marele plus este adus de actualizarea constantă a acesteia și dacă este posibil atașați un link către companiile în care lucrați sau ați lucrat.

Secțiunea Contact Info – aici rămâne la latidutinea fiecăruia dacă dorește să facă publice datele de contact. Pentru mine ca recruiter situația ideală ar fi cea în care să găsesc public numărul de telefon  , dar fiind vorba de confidențialitate, fiecare poate alege ce să publice și ce nu. În schimb vă recomand să puneți link-uri către proiecte personale sau profesionale în care ați fost implicați, site-uri personale sau blog-uri.


TODAY SOFTWARE MAGAZINE Secțiunea Events – participați activ la evenimente pe Facebook și conectați-vă cu persoane din domeniul vostru de activitate, cu persoane care au interese comune și folosiți aceste conexiuni pentru proiectele pe care le dezvoltați, pentru că am ajuns într-un moment în care cu cât cunoști mai multe persoane cu atât vizibilitatea ta este mai ridicată în mediul în care interacționezi. Și acum intrăm în subiectul mult controversat ”Pictures”. Am întâlnit deseori întrebarea: ”Ce fel de poze îmi recomanzi să public pe Facebook?”. Mereu la această întrebare am răspuns foarte personal, iar din punctul meu de vedere orice fel de poze în care nu ești pus în situații stânjenitoare sunt potrivite. Cu siguranță în contexul prieteni, poate produce bună dispoziției, dar pentru un recruiter nu este cel mai plăcut lucru pe care dorește să îl vadă. Dar, pe de altă parte am primit contra-argumente la această opinie a mea, repet strict personală, referitoare la faptul că la urma urmei este alegerea mea dacă mă uit la pozele respective sau nu.  Am început cu Facebook-ul, deoarece este cea mai utilizată ”rețea de socializare” și care din punct de vedere profesional încă nu este utilizat la potențial maxim. Facebook-ul va deveni cu siguranță sursa care poate oferi cele mai importante informații despre noi ca persoane. Sunt sigură că există companii care ar plăti sume mari de bani pentru a avea acces la informații cât mai detaliate. Așa că vă recomand să vă gândiți de două ori ce publicați pe această rețea de socializare. Un alt site de socializare pe care aș vrea să îl prezint este LinkedIn-ul, care este o rețea mult mai profesională și care nu este utilizat astfel încât să aducă beneficii maxime. Mai mult decât atât, există nenumărate persoane care încă nu au auzit despre acest site. Avantajele LinkedIn sunt și mai mari decât cele pe care Facebook-ul le oferă, pentru că site-ul în sine este structurat mai profesionist. Secțiunele pe care LinkedIn-ul le are permit crearea unui CV online mult mai relevant decât cel care apare pe Facebook. Statistic vorbind, LinkedIn-ul a ajuns deja la peste 100 mil de utilizatori. Ca scop, LinkedIn-ul poate fi utilizat pentru găsirea unui job sau pentru a conecta persoane din lumea businessului, prin facilitatea de a crea evenimente și de a le promova online. Secțiunea Profile – oferă posibilitatea creării unui CV electronic. • În categoria Summary, așa cum îi

spune și titlul, se notează ce consideri că este relevant, fie un rezumat al evoluției în carieră, fie punctele forte sau cunoștințele pe care consideri că le ai, fie rezultatele pe care le-ai avut de-a lungul carierei. Mai simplu spus, ce te face pe tine unic în comparație cu ceilalți utilizatori care doresc același job ca și tine. Specialties recomand să te lauzi cu ce știi să faci cel mai bine.

Experience descrie cât mai clar și concis responsabilitățile pe care le-ai avut la locurile de muncă, inclusiv voluntariat. Plusul pe care îl aduce LinkedIn-ul este că pentru fiecare post, poți solicita o recomandare. Un profil care are un CV bun și are și recomandări, este imposibil să nu atragă atenția recruterilor sau head-hunterilor. Te sfătuiesc să ceri recomandări și fă-le cât mai diversificate pentru a avea un feedback din toate mediile

în care ai interacționat. Education se referă la educația formală.Sugestie: pentru cei care au deja facultate și master să nu mai menționeze liceu în profil. Ultima parte din această secțiune se referă la interesele pe care fiecare le are și la diferite informații personale.

Secțiunea Groups – recomand să te înscrii în grupurile de interes pentru tine. Scopul lor este mult mai bine definit d e c ât p e Facebook, d e o are c e poți avea acces la resurse sau la opinii pe baza discuțiilor pe care le poți i n iț i a c a membru al grupulu i , p oț i afla părerea unor specialiști în domeniu într-un mod foarte simplu și util. Secțiunea Jobs – cu utilitate maximă pentru cei interesați de un job nou, este una dintre resursele cele mai importante pe care LinkedIn-ul le pune la dispoziția utilizatorilor. Recitind articolul mi-am dat seama că nu am făcut o observație chiar relevantă. În momentul în care dorești să adaugi o persoană în listă, personalizează invitația prin a explica motivele pentru care vrei să devină parte a rețelei tale profesionale. Impactul crescut al celor două ”rețele de socializare” este demonstrat prin creșterea numărului utilizatorilor. Comparativ cu anul 2011, LinkedIn-ul a crescut cu 4 mil de utilizatori, iar Facebook-ul cu 300.000.000 de utilizatori. Cele două rețele oferă numeroase oportunități atât în ceea ce privește găsirea unui job nou, dar în același timp facilitează interacțiunea în lumea business-ului. Pentru cei care încă nu au un profil pe LinkedIn, recomand să nu mai amânați si să-l faceți, iar ceilalți care aveți unul, dar nu este complet, vă sfătuiesc să începeți să îl actualizați și să deveniți din ce în ce mai vizibili. Succes!

www.todaysoftmag.ro | nr. 5/2012

37


programare

Core Data – În spatele scenei

C

ore Data este un graf de obiecte și un framework pentru persistența datelor oferit de Apple. Este un framework relativ mic, dar foarte robust, oferă soluții pentru multe probleme generale și se potrivește perfect cu Cocoa si alte API-uri furnizate de Apple. (În MVC pattern ține loc de model).

Zoltán, Pap-Dávid

zpap@macadamian.com Software Engineer @ Macadamian

Core Data API poate fi descompus în următoarele trei componente: Persistent Store Coordinator (NSPersistentStoreCoordinator), Managed Object Model (NSManagedObjectModel) și Managed Object Context (NSManagedObjectContext). Toate cele trei părți lucrează împreună pentru stocarea/încărcarea obiectelor persistente stivei, și interacționează cu obiectele per(NSManagedObject). sistente prin acest context. (Orice obiect persistent creat trebuie sa fie legat de un context). De asemenea, nu este threadsafe, prin urmare, toate thread-urile cu care vrem să accesăm obiecte persistente trebuie să aibă un context separat. Este important să se țină cont de faptul că, la fel ca și în cazul UI-ului, instanțele de NSManagedObjectContext trebui să fie accesate doar de pe threadul pe care au fost create.

Persistent Store Coordinator Managed Object Model (NSManagedObjectModel)

Încapsulează schema bazei de date, care conține entități și relațiile dintre ele descriind graful de obiecte. Îl putem crea cu ajutorul instrumentului vizual oferit de Xcode (care va fi compilat într-o resursă binară) sau chiar din cod. De obicei, nu e nevoie să-l accesăm după ce stiva Core Data (Core Data stack) a fost inițializată, dar pentru scenarii complexe – deoarece conține descrierea tuturor entităților care compun modelul – este posibil să-l folosim pentru a interoga dinamic modelul pentru descoperire/afișare.

Managed Object Context (NSManagedObjectContext)

Instanța NSManagedObjectContext este obiectul pe care îl accesăm atunci când vrem să salvăm, citim, creăm și să ștergem obiecte persistente. Este pe ultimul nivel al

38

nr. 5/2012 | www.todaysoftmag.ro

Se află la baza stivei Core Data și este responsabil pentru serializarea/deserializarea obiectelor persistente. Locul în care se depozitează datele (Persistent Store) poate fi pe disc sau în memorie. Trei tipuri de depozite sunt incluse în Core Data API: SQLite, XML și binar. Toate acestea pot fi serializate pe disc sau în memorie (stocarea în memorie fiind doar un storage temporar). XML și binar sunt depozite atomice (întregul fișier de date este rescris la fiecare salvare). Deși depozitele atomice au avantajele lor, ele nu sunt scalabile. Un alt dezavantaj al lor este faptul că sunt încărcate complet în memorie, astfel încât amprenta pe memorie este mult mai mare în cazul lor decât în cazul SQLite. Totuși pentru un set mic de date pot reprezenta varianta optima. SQLite este o bibliotecă de software care implementează un motor de bază de dată SQL de sine stătător, fără server, preconfigurat, tranzacțională. Este cel mai des


TODAY SOFTWARE MAGAZINE folosit motor de bază de date SQL. Prin folosirea unei baze de date relaționale ca depozit persistent, nu avem nevoie de încărcarea tuturor datelor în memorie. De asemenea baza de date poate fi scalată la dimensiuni foarte mari. SQLite în sine a fost testat cu seturi de date măsurate în terabytes. Datele de pe disc sunt organizate eficient, doar datele pe care le folosim la un moment dat, sunt încărcate în memorie. Pentru că avem o bază de date în loc de un fișier plaintext, avem acces la mai multe opțiuni pentru creșterea performanței. Putem controla, de asemenea, modul în care obiectele sunt încărcate în memorie. Pentru cele mai multe scenarii Core Data oferă un acces transparent, dar pentru a scrie aplicații scalabile, eficiente, bazate pe Core Data, trebuie să cunoaștem ce se petrece în spate scenei, altfel riscăm să ne confruntăm cu situații neplăcute.

Faulting

Faulting este una dintre cele mai sensibile subiecte legate de Core Data. Se desfășoară în mod transparent, prin urmare aplicațiile simple pot fi dezvoltate fără a cunoaște detaliile de funcționare. În ceea ce urmează, voi folosi un exemplu simplu, pentru demonstrarea impactului asupra performanței. Să considerăm un model nou, în care creăm o singură entitate (Person) cu trei atribute (age, gender, name), fără nici o relație. Luăm în considerare o bază de date, cu 5000 de instanțe ale acestui obiect. Dorim să iterăm prin toate obiectele și să verificăm un atribut al obiectului (Desigur, putem face mult mai eficient, cu definirea unui predicat, însă dorim să ne asigurăm că toate obiectele vor fi încărcate în memorie) NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@”Person” inManagedObjectContext:context]; [fetchRequest setEntity:entity]; NSArray * result = [context executeFetchRequest: fetchRequest error:&error];

//timp de execuție 0.552 s for (Person * person in result) { if ([person.age intValue] < 25) value++; }

//timp de execuție 0.083s

Se observă că putem inspecta toate obiectele într-un timp decent. Acum vrem să extindem modelul cu o altă entitate, precum și o relație între cele două entități. Creăm o entitate nouă: Car cu trei atribute (engine, manualTransmission, name), precum și o relație între Person și enitatea Car. Folosim o bază de date, care conține 5000 de obiecte Person, și fiecare persoană are un obiect Car (în total avem 10000 obiecte). De asemenea, dorim să extindem următoarea interogare, iterăm în continuare toate obiectele Person, dar acum inspectăm un atribut din obiectului referit de relația între cele două entiați. NSFetchRequest *fetchRequest= [[NSFetchRequest alloc] init];

căreia se poate verifica dacă obiectul este încărcat în memorie, sau nu. Când accesăm primul atribut, dar în memorie avem doar un placeholder, o notificare este inițiată (Fault is fired) pentru a încărca obiectul în intregime în memorie. Să analizăm mai detaliat. A. După executarea requestului (NSFetchRequest), vom avea o listă de faulted NSManagedObject,

B. Când începem să iterăm peste lista rezultată și accesăm un atribut al primului obiect, un mesaj va fi trimis automat nivelelor inferioare Core Data,

NSEntityDescription *entity = [NSEntityDescription entityForName:@”Person” inManagedObjectContext:context]; [fetchRequest setEntity:entity]; NSArray *result=[context executeFetchRequest :fetchRequest error:&error];

//timp de execuție 0.351 secunde

for (Person * person in result) { if (person.car.manualTransmission) { value += [person.age intValue]; } }

//timp de execuție 21.201 secunde

După executarea codului, putem obser va o degradare accentuată a performanței. Dar ce s-a întâmplat? Dacă verificăm un obiect Person înainte de parcurgere, în debugger, putem observa că este marcat ca și Fault. Înainte de accesare obiectul nu se află încărcat în memorie! În continuare vom studia procesul de încărcare a datelor.

Încărcarea (Fetching) obiectelor

Pentru a optimiza utilizarea memoriei, Core Data folosește lazy loading la încărcarea datelor. „Fetching” este termenul folosit pentru a adresa pașii care sunt urmați pentru a crea un obiect în memorie pornind de la conținutul din storage (câmpurile obiectului sunt stocate în tabelele bazei de date relaționale). Când folosim SQLite ca storage, după executarea unei cereri, este foarte posibil ca un obiect pe care-l credem în memorie, este de fapt pe disc și trebuie să fie încărcat în memorie ulterior. În mod similar, obiectele despre care credem că sunt gata pregătite, de fapt se află încă într-un cache. Atu nc i c ând e ste e xe c ut at u n NSFetchRequest, vom prelua o listă de NSManagedObject, dar în spatele acestor obiecte, în memorie, vom avea doar obiecte substituente (Faulting objects). Singurul atribut care este încărcat în memorie este NSManagedObjectID. Deasmenea obiectele au o proprietate (isFault) cu ajutorul

C. Core Data verifică conținutul cacheului intern. Pentru că obiectul respective nu face parte din cache, Core Data apelează la repository, pentru deserializarea obiectului,

D. Cu un singur acces la baza de date, toate obiectele din lista respectivă sunt încărcate în cache. Când primul obiect este încărcat în memorie, conținutul lui se poate accesa. (isFault va fi NO pentru primul, si YES pentru următoarele obiecte),

E. Iterarea peste listă va fi rapidă, deoarece obiectele se află în cache. Deoarece accesul multiplu la baza de date pentru a încărca lista obiect cu obiect, nu este eficient, datele sunt încărcate în bucăți (chunks). Acest comportament poate fi reglat prin setarea proprietății FetchBatchSize al NSFetchRequest -lui. Valoarea implicită este 0, ceea ce corespunde la ∞ (toate elementele listei vor fi încărcate în cache la prima accesare). În www.todaysoftmag.ro | nr. 5/2012

39


programare

cazul în care lista rezultat are multe elemente, am putea lua în calcul modificarea acestei valori, care va duce la un consum mai mic de memorie, pentru început, însă vor fi mai multe accesări ale bazei de date fizice. Prin urmare, trebuie să considerăm fiecare caz în parte, atunci când vrem să schimbăm acest comportament implicit. De asemenea, putem opri acest comportament prin

Core Data – În spatele scenei

„Pre-Fetching” - anticiparea nevoilor viitoare, pentru a evita încărcarea obiectelor prin accesări separate la disc. Acest lucru poate fi realizat doar enumerând relațiile, pe care le vom folosi pentru obiectele aduse. Astfel Core Data va ști dacă obiectele respective vor fi folosite și va asigura un acces optim la ele. NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@”Person” inManagedObjectContext:context]; [fetchRequest setEntity:entity];

înainte de a executa query-ul. Astfel după executarea request-ului toate câmpurile obiectelor vor fi în cache. Prin introducerea Faulting, Core Data încearcă să optimizeze consumul de memorie, astfel că pănă la prima accesare obiectele nu sunt încărcate în memorie. Trebuie să observăm, că nu toate proprietatile și metodele din NSManagedObject cauzează trimiterea notificării de încărcare a datelor. Există o listă lungă de metode din NSManagedObject care nu cauzează pornirea procedurii de încărcare a obiectelor: isEqual:, hash, superclass, class, self, zone, isProxy, isKindOfClass:, isMemberOfClass:, conformsToProtocol:, respondsToSelector:, retain, release, autorelease, retainCount, description, managedObjectContext, entity, objectID, isInserted, isUpdated, isDeleted, isFault

Grafuri de obiecte

Primul exemplu a fost bazat pe entitați simple fără utilizarea relațiilor. Următorul pas de extindere a structurii de date este introducerea relațiilor între entități. Acest pas poate avea un impact semnificativ asupra performanței unei aplicații Core Data. În al doilea exemplu, putem observa degradarea performanței. Motivul pentru aceasta este faptul că relațiile sunt accesate și încărcate una câte una. În primul caz, accesarea primului element Persoana din lista, rezultă încărcarea tuturor celor 5000 de obiecte în cache printr-un singur acces la disk, în cazul al doilea când accesăm obiectul referință Car, Core Data încarcă în cache doar obiectul respectiv. Prin urmare, în al doilea caz în total 5001 de accese la disc vor fi folosite, comparativ cu primul caz în care toate datele sunt aduse în cache printr-un singur acces la disc. 5001 comparativ cu 1. Acesta este motivul pentru ruinarea performanței. Soluția pentru această problemă este

40

nr. 5/2012 | www.todaysoftmag.ro

[fetchRequest setRelationshipKeyPathsForPrefetching: [NSArray arrayWithObject:@”car”]]; NSArray * result = [context executeFetchRequest:fetchRequest error:&error]; //timp de execuție 4.006 secunde for (Person * person in result) { if (person.car.manualTransmission) { value += [person.age intValue]; } }

//timp de execuție 0.974 secunde

Acest truc rezolvă problema noastră pentru moment, dar tehnica este destul de fragilă, pentru că trebuie să păstrăm codul sincronizat cu modelul, deoarece avem o relație hardcodată. Cănd modificăm relațiile din model, trebuie să propagăm modificările și în cod, altfel riscăm să ajungem la accesul ineficient pe care l-am subliniat anterior.

Concluzii

După cum am văzut, încărcarea obiectelor cu accesări independente este una dintre cele mai comune cauze pentru performanțele slabe ale aplicațiilor Core Data. Mecanismul de „Faulting” este o sabie cu două tăișuri, care poate aduce îmbunătățiri mari pentru viteza si performanța aplicațiilor sau poate trage în jos performanța foarte mult. Trebuie să cunoaștem acest comportament al framework-ului Core Data și trebuie să păstrăm un echilibru între numărul de accesări de disc și consumul de memorie, și să aducem numai datele de care avem nevoie și numai la momentul potrivit. De asemenea e important să creăm schema modelului nostru ținând cont de aceste proprietăți. Atunci când încărcăm datele, în cazul în care aducem prea puțin, aplicația va părea blocată, din cauza numărului mare de accese la disc. Pe de altă parte, dacă vom încărca cantitatea prea mare de date în memorie, vom avea acces rapid la datele noastre încărcate, dar vom avea probleme de memorie scăzută pe device-uri (să nu

uităm că iPad2 are o memorie internă de 512MB). De asemenea, trebuie să fim conștienți de faptul că, neavând virtualizare de memorie în iOS, Core Data încearcă să reducă consumul din memorie prin eliminarea datelor nefolosite pe parcurs, astfel eliberând obiecte din cache atunci când acestea nu sunt folosite. Acest lucru ar putea cauza un acces suplimentar la disc chiar pentru obiectele care au fost anterior în memorie și au fost accesate. Pentru îmbunătățirea performanței putem folosi următoarele: • Pre-inițializarea cache-ului (Cache waming up). Putem preîncărca datele în cache pentru a fi siguri că datele vor fi disponibile, atunci când va fi nevoie de ele. Atunci când pornește aplicația, într-un thread separat pornim încărcarea datelor, care în mod sigur vor fi folosite în momentele ulterioare. Practic timpul de încărcare îl mutăm în faza de inițializare. În acest caz, nu contează dacă folosim mai multe thread-uri, deoarece toate operațiunile vor fi direcționate către NSPersistentCoordinator, care are un cache unic. • Optimizarea accesului la disc. Având în vedere că accesul la disc este mult mai lent decât accesul la memorie, putem reduce numărul de accese la disc pentru a optimiza încărcarea datelor. Am văzut cum putem optimiza accesul la disc prin cunoașterea modului de încărcare a datelor. Aceeași problemă ar putea fi extins și la salvarea datelor. Este mult mai eficient a salva în bucăți mai mari în loc de a salva obiect cu obiect. Ștergerea obiectelor este, de asemenea, un subiect sensibil, care necesită o atenție specială. Chiar dacă ștergem un singur obiect, acest lucru ar putea implica eliminarea mai multor obiecte în cascadă datorită relațiilor dintre obiecte.


programare

TODAY SOFTWARE MAGAZINE

5 practici Java pe care le folosesc

A

rticolul prezintă cinci practici Java pe care le folosesc în scrierea codului meu. Este interesant că lucrurile simple îți fac viața de developer (și a colegilor) mai ușoară. Lista de mai jos nu este un top, doar ilustrează lucruri pe care le consider folositoare.

Implementarea metodelor equals, hashCode și toString moștenite din java.lang.Object Tavi Bolog tavi.bolog@nokia.com Development lead @ Nokia

Toate cele trei metode sunt parte din java.lang.Object din versiunea JDK 1.0. Mai jos este o listă a beneficilor folosirii acestor metode: Object#equals(Object obj): determină dacă obiectul curent este egal cu obiectul trimis ca parametru. Implementarea lui Object#equals verifică doar dacă referințele celor două obiecte sunt egale (this == obj), dar această verificare nu este întodeuana suficientă. De obicei, o implementare completă a lui equals verifică: a. Dacă (obj == null) returnează false; b. Dacă (this == obj) returnează true; c. D acă (!getClass().equals(obj. getClass()) returnează false; d. Se execută un type cast a lui obj la tipul lui this; e. Se verifică egalitatea attributelor lui this și obj și în funcție de aceasta se returnează true sau false. Suprascrierea lui equals este benefică dacă egalitatea stării obiectelor este importantă pentru un program să ruleze corect De exemplu, obiectele sunt parte ale unor colecții și trebuie să fie găsite în cazul unor operații de citire. Altă situație este legată de scrierea testelor automate, unde, de obicei, se verifică egalitatea obiectelor ca parte a validării unui test. Object#hashCode este altă metodă care poate fi folositoare în situații similare cu

Object#equals. Contractul general al lui hashCode este: a. Equals este suprascrisă, b. Dacă două obiecte sunt egale, ele vor genera același hash cod, c. Calcularea hash codului se va face folosind aceleași atribute folosite pentru verificarea egalității, d. Dacă nu se schimbă starea unui obiect, apeluri ale metodei hashCode trebuie să returneze aceeași valoare; totuși acest lucru nu este valabil pentru diferite rulări ale aplicației. Colecțiile și mapele de tip hash sunt implemetate folosind structuri bazate pe hash (“buckets”). O implementare improprie a hash codului, ar putea produce rezultate neașteptate in cazul operațiilor de citire asupra colecților și mapelor hash (căutarea in structura greșită de hash). Din cauza punctului d). de deasupra, codul client poate să nu găsească un obiect dacă starea obiectului a fost schimbată între timp (și această stare este folosită în determinarea egalității). Cea mai bună cale pentru evitarea unor astfel de situații este folosirea obiectelor imutabile (starea lor nu se va schimba pe durata vieții lor). De asemenea, dacă obiectele sunt imutabile, implementarea hashCode va putea folosi tehnici de caching pentru o eventuală imbunătățire a performanței (hash codul trebuie să fie același dacă starea obiectului nu se schimbă). De câte ori ne-am uitat la niște www.todaysoftmag.ro | nr. 5/2012

41


programare

loguri și am văzut ceva de genul: “value is: Car@29edc073”? Da, foarte enervant și nefolositor și totul pentru că Object#toString() nu a fost suprascrisă în clasa respectivă. Această metodă este foarte folositoare când vrem să logăm starea obiectelor. Dacă logul ar arăta ceva de genul: “value is: Car[type=BMW,number of doors=5,isAllWheelDrive=false]” ar avea sens mai mult decât exemplul anterior. O sugestie în apelarea lui toString ar fi să nu se apeleze explicit în concatenarea cu alte stringuri: “value is “ + car, în locul “value is “ + car.toString(), deoarece, în acest context, “car” este oricum evaluat folosind toString() (ca urmare a concatenării cu un string) și am putea evita un NullPointerException, dacă “car” este null. Pentru cele trei metode, Apache Commons Lang 3 (http://commons.apache.org/lang/) pune la dispoziție utilități care fac viața developerilor mai ușoară. Vezi https://github.com/tavibolog/ TodaySoftMag/blob/master/src/main/ java/com/todaysoftmag/examples/objectmethods/Car.java și testul asociat.

Evitarea comenzilor imbricate

În general, îmi place să scriu code simplu si ușor de înteles. Bineînțeles, acest lucru nu se întâmplă întotdeauna. Ca o regulă de bază, prefer să ies dintro metodă/flow cât mai repede posibil. Făcând asta, se limitează complexitatea de a citi comenzi imbricate. Tehnicile de realizare a acestei ieșiri bruște dintr-un flow implică folosirea comenzilor: return, break, continue sau throw. În opinia mea, folosind: If (a == null) {return;} // și apoi continua flowul aplicație pe o urm

este preferabil:

5 practici Java pe care le folosesc

Verifică validitatea parametrilor unei metode

Ni m ă nu i nu î i p l a c e c a N P E (NullPointerException) să apară in stacktrace-ul codului său. Nici mie. Iată câteva tehnici de a evita acest lucru: a. Folosește JavaDoc pentru documentarea parametrilor de intrare. Problema ar fi că majoritatea developerilor nu citesc JavaDoc-ul. /** @throws NullPointerException in case argument is null */

b. Folosește assert-uri. Acestea sunt comenzi care permit developerilor să verifice anumite presupuneri asupra codului care se execută. Deci folosirea assert-urilor nu este pentru utilizatori. Când un assert eșuează, de obicei librăria care conține assert-ul are un bug. Cele mai commune cazuri de folosire ale asert-urilor sunt legate de paradigma “design-by-contract”: • Pre-condiții: Verifică ce trebuie să fie adevărat când o metodă este apelată. Aceasta poate fi o soluție pentru metodele private, dar nu și pentru cele publice, pentru că aplicația poate rula și făra ca assert-urile să fie active și, deasemenea, aserturile aruncă doar AssertionError si nu o excepție specifică., Deci metodele publice ar trebui să verifice validitatea parametrilor. Totuși, metodele private pot folosi assert-uri înainte de a executa orice operație. private void divide(int a, int b) { ….. }

If (a != null) {//fă ceva} // și apoi continuă flowul între paranteze

O modalitate de a impune această practică este limitarea numărului de caractere pe o linie la 120 în IDE-ul pe care îl folosești. Vezi https://github.com/tavibolog/ TodaySoftMag/blob/master/src/main/ java/com/todaysoftmag/examples/nested/ Utility.java pentru două versiuni ale aceleiași metode, una folosind comenzi imbricate și celaltă încercând să le evite. Apoi alege-o pe cea care arată mai simplu.

42

nr. 5/2012 | www.todaysoftmag.ro

assert (b != 0);

Post-condiții: verifică ce trebuie să fie true înainte de terminarea unei metode. Aici, assert-urile sunt premise și pentru metodele publice pentru că anumite probleme apărute pot fi rezolvate în codul client (de exemplu, obiectul account care este null mai jos)

private Account createAccount() { Account account = null; // create the account … assert (account != null); return account; }

Invarianți ai unei clase: verifică ceea ce trebuie să fie adevărat tot timpul pe durata de viață a unui obiect. În această situație, orice contructor sau metodă publică trebuie să apeleze invariantul

înainte de a se termina, pentru a se asigura că starea obiectului este consistentă relativ la invariant. Public class Account { String name = null; private boolean checkNameForNull() { // class invariant return name != null; } public Account(String name) { … assert checkNameForNull(); } }

De reținut că nu este nici un mecanism de recuperare dintr-un assert, pentru că scopul asset-urilor este de a ajuta scrierea de cod testabil și de a proteja împotriva unor execuții care pot corupe starea aplicației. Implicit, assert-urile nu sunt active. Pentru activare, se poate folosi: java –ea MyClaass sau java –enableassertions MyClass c.

Verificarea validității parametrilor de intrare și aruncarea de excepții după cum este necesar. Dacă codul se poate recupera dintr-o stare generate de intrări invalide, atunci ar trebui să folosești “checked exception”, dacă nu ar trebui să folosești “un-checked exception”. Vezi aici mai multe detalii despre folosirea excepțiilor: http:// docs.oracle.com/javase/tutorial/ essential/exceptions/runtime.html. De obicei, constructorii nu pot instanția obiectele adecvat în cazul intrărilor invalide, așa că prefer să arunc IllegalArgumentException. De asemenea, este o practică bună se specificăm aruncarea de excepții în JavaDoc. Vezi https://github.com/tavibolog/ TodaySoftMag/blob/master/src/main/ java/com/todaysoftmag/examples/check/ Dog.java și testul asociat. NOTA: Verificarea validității parametrilor de intrare poate fi problematică în așa numita “fereastră de vulnerabilitate” În perioada dintre verificarea parametrului și atribuirea parametrului, alt thread ar putea modifica valoarea parametrului de intrare făcând verificarea parametrilor nefolositoare. Pentru evitarea unor astfel de situații, verificarea validității ar putea fi făcută pe operandul din stânga al unei atribuiri, după ce atribuirea s-a făcut.


HR

Evită zgomotul inutil

TODAY SOFTWARE MAGAZINE

în special când se definește o constantă, dar nu ar trebui folosit din abundență în alte circumstanțe decât dacă este absolut necesar.

Este întotdeauna bine să îți menții public int add(final int a, final int b) { codul cât mai curat. Uni developeri pot final int c = a + b; return c; avea intenții bune în a urma cele mai bune } practice, dar rezultatul muncii lor nu aduce Metoda de mai sus este corectă, dar ar fi întotdeuna beneficii, doar zgomot inutil. mai simplu să o scriem ca mai jos: Comentariile sunt folositoare doar dacă spun mai mult decât codul în sine. Dacă codul este foarte clar, atunci comentariile de mai jos nu prea au valoare: a. /** seteaza persoana */ public void setPerson(Person p){}

b. … // citește fișierul

readFile(new File(“…”));

… Ca regulă, mai bine îți denumești variabilele și metodele cât mai clar cu putință pentru a evita comentarii zgomotoase. De asemenea, să nu uităm că și comentariile trebuie menținute în caz de refactorizare a codului, ceea ce înseamna din nou lucru în plus. Următorul topic de discutat ar fi folosirea lui this. Aceasta are sens dacă: a. Este folosit pentru apelarea unul constructor în cadrul unui alt constructor pentru a evita duplicarea de cod de inițializare public Person(String name, int age) {this(name);}

b. Când numele unui atribut este identic cu numele unui parametru

public setPerson(Person person){this. person = person;}

public int add(int a, int b) { return a + b; }

Ai grijă să îți cureți resursele folosite

Este important ca resursele unei aplicații să fie bine administrate. În caz contrar, aplicația poate avea un comportament neașteptat și eventual să necesite restarturi. Una dintre cele mai clasice greșeli făcute de developeri este aceea de a uita să închidă stream-urile pe care le-au deschis. O secvență a folosirii unui stream ar fi: a. Deschide stream, b. Lucrează cu streamul de date, c. Închide streamul. Ultimul pas trebuie să se execute neapărat chiar dacă apar excepții în aplicație. Până la Java 6, folosirea finally ne ajuta să fim siguri că un stream se închide întotdeauna. Iată cum ar arăta de obicei codul: FileInputStream fis = null; try { fis = new FileInputStream(new File(„README”)); // Lucrează cu streamul aici } catch(IOException ioexp) { // administrează eventuale excepții } finally { // asigură-te că streamul se închide if (fis != null) { fis.close(); } }

În alte cazuri, folosirea lui this nu aduce Ce se poate întâmpla aici este că blocul prea mare valoare. Mai jos sunt câteva finally să arunce o excepție și codul trebuie contra-exemple: să o prindă, ceea ce înseamnă cod aditional System.out.println(this.name); care trebuie scris și menținut și care are o System.out.println( tendință repetitivă. this.COUNT_OF_MESSAGES); Începând cu Java 7, syntax lui try a fost Ultimul topic de discutat în acest capi- extinsă pentru a defini scopul pentru streatol ar fi folosirea lui final. Acesta are sens murile folosite, numit try-with-statements: dacă o variabilă va fi folosită într-o clasă try (FileInputStream fis = new FileInputStream(new File(„README”))) inner sau dacă developerul vrea să atragă { //lucrează cu streamul aici atenția că variabila respective nu ar trebui } re-inițializată. Am folosit primul caz desAceasta înseamnă că la sfârșitul blotul de des, în timp ce al doilea caz are sens cului try, resursele care implementează

interfața AutoCloseable vor fi automat închise. Se pot chiar specifica mai multe resurse pe aceeași linie. Pentru a suporta acest concept nou, o mulțime de clase din JDK implementează începând cu Java 7 interfață AutoCloseable, incluzând pachetele: java.io.*, java.nio.*, java.net.*, etc. De asemenea codul generat de compilator știe să administreze resurse nule. Vezi https://github.com/tavibolog/ TodaySoftMag/blob/master/src/main/ java/com/todaysoftmag/examples/resources/ResourceCleaner.java și testul asociat pentru a ilustra ambele situații (închiderea stream-urilor – incluzând un exemplu cu JDK 1.7 – și lipsa închiderii stream-urilor). În special pe sistemele Linux/Unix, neînchiderea streamurilor generează “FileNotFoundException” cu mesajul “too many open files” după ce numarul de stream-uri deschise depășește limita sistemului. Un alt concept interesant în Java 7 este legat de administrarea excepțiilor mascate. Mascarea unei excepții este situația în care o excepție o maschează pe alta și nu este legată de situația în care codul client încadrează o excepție venită de la un API de nivel jos. Dar în cazul în care o excepție este aruncată în blocul try și altă exceptie este aruncată in blocul finally, iar codul client va observa doar exceptia din blocul finally. Java 7 administrează automat această situație (în cazuri specifice se poate folosi Throwable.addSuppress(...)), mașina virtuală suprimând excepția din finally pentru a se administra excepția din try. Este recomandat să lăsăm compilatorul să genereze codul de administrare pentru cazul de mascare a excepțiilor, pentru că va adauga codul minimal, iar developerul poate să se focuseze pe logica aplicației. Alte situații care se află în aceeași categorie de curățare a resurselor sunt: • Eșuarea închiderii conexiunilor la bazele de date, • Eșuarea închiderii sockeților. NOTA: Exemplele de cod au fost testate folosind Ubuntu 12.04, rulând open JDK 7 și Maven 3.

www.todaysoftmag.ro | nr. 5/2012

43


programare

Microsoft Kinect - Ghid de programare Partea a II-a – Afișarea scheletului întreg al utilizatorului

Î

n numerele precedente, am introdus o secvență de cod cu rol în inițializarea Kinectului și am construit o scurtă aplicație de tip Hello World. În cele ce urmează, vom continua dezvoltarea aplicației printr-o funcționalitate nouă: afișarea scheletului întreg al utilizatorului. Echipa Simplex

simplex@todaysoftmag.com

void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e) { if (closing) { return; } Skeleton first = GetFirstSkeleton(e); if (first == null) { return; } ContainerSkeleton.Children.Clear(); Dictionary<JointType, Joint> jointsDictionary = new Dictionary<JointType, Joint>(); foreach (Joint joint in first.Joints) jointsDictionary.Add(joint.JointType, getScaledJoint(joint, e)); drawJoints(jointsDictionary); drawBones(jointsDictionary); }

Odată ce am primit un Frame de la Kinect, verificăm mai întâi daca este nul, iar apoi extragem încheieturile din primul schelet descoperit și le reținem într-un dicționar. void drawJoints(Dictionary<JointType, Joint> jointsDictionary) { foreach (KeyValuePair<JointType, Joint> joint in jointsDictionary) { drawJointEllipse(30, Brushes.LightGreen, joint.Value); } } private void drawJointEllipse(int diameter, Brush color, Joint joint) { Ellipse el = new Ellipse(); el.Width = diameter; el.Height = diameter; el.Fill = color; Canvas.SetLeft(el, joint.Position.X - diameter / 2); Canvas.SetTop(el, joint.Position.Y - diameter / 2); }

main.ContainerSkeleton.Children.Add(el); el.Cursor = Cursors.Hand;

Metoda drawJointEllipse desenează câte o încheietură din corpul utilizatorului în elementul de tip Canvas, ContainerSkeleton. Fiecare încheietură este reprezentată grafic de o elipsă. void drawBones(Dictionary<JointType, Joint> jointsDictionary) { Brush brush = new SolidColorBrush(Colors.LightGray); ContainerSkeleton.Children.Add(getBodySegment(new PointCollection() { new Point(jointsDictionary[JointType.ShoulderCenter].Position.X, jointsDictionary[JointType.ShoulderCenter].Position.Y), new Point(jointsDictionary[JointType.Head].Position.X,

44

nr. 5/2012 | www.todaysoftmag.ro


TODAY SOFTWARE MAGAZINE jointsDictionary[JointType.Head].Position.Y) }, brush, 9)); ContainerSkeleton.Children.Add(getBodySegment(new PointCollection() { new Point(jointsDictionary[JointType.ShoulderCenter].Position.X, jointsDictionary[JointType.ShoulderCenter].Position.Y), new Point(jointsDictionary[JointType.ShoulderLeft].Position.X, jointsDictionary[JointType.ShoulderLeft].Position.Y), new Point(jointsDictionary[JointType.ElbowLeft].Position.X, jointsDictionary[JointType.ElbowLeft].Position.Y), new Point(jointsDictionary[JointType.WristLeft].Position.X, jointsDictionary[JointType.WristLeft].Position.Y), new Point(jointsDictionary[JointType.HandLeft].Position.X, jointsDictionary[JointType.HandLeft].Position.Y)}, brush, 9)); ContainerSkeleton.Children.Add(getBodySegment(new PointCollection() { new Point(jointsDictionary[JointType.ShoulderCenter].Position.X, jointsDictionary[JointType.ShoulderCenter]. Position.Y), new Point(jointsDictionary[JointType.ShoulderRight].Position.X, jointsDictionary[JointType.ShoulderRight]. Position.Y), new Point(jointsDictionary[JointType.ElbowRight].Position.X, jointsDictionary[JointType.ElbowRight].Position.Y), new Point(jointsDictionary[JointType.WristRight].Position.X, jointsDictionary[JointType.WristRight].Position.Y), new Point(jointsDictionary[JointType.HandRight].Position.X, jointsDictionary[JointType.HandRight].Position.Y)}, brush, 9)); ContainerSkeleton.Children.Add(getBodySegment(new PointCollection() { new Point(jointsDictionary[JointType.ShoulderCenter].Position.X, jointsDictionary[JointType.ShoulderCenter]. Position.Y), new Point(jointsDictionary[JointType.Spine].Position.X, jointsDictionary[JointType.Spine].Position.Y), new Point(jointsDictionary[JointType.HipCenter].Position.X, jointsDictionary[JointType.HipCenter].Position.Y)}, brush, 9)); ContainerSkeleton.Children.Add(getBodySegment(new PointCollection() { new Point(jointsDictionary[JointType.HipCenter]. Position.X, jointsDictionary[JointType.HipCenter].Position.Y), new Point(jointsDictionary[JointType.HipLeft].Position.X, jointsDictionary[JointType.HipLeft].Position.Y), new Point(jointsDictionary[JointType.KneeLeft].Position.X, jointsDictionary[JointType.KneeLeft].Position.Y), new Point(jointsDictionary[JointType.AnkleLeft].Position.X, jointsDictionary[JointType.AnkleLeft].Position.Y), new Point(jointsDictionary[JointType.FootLeft].Position.X, jointsDictionary[JointType.FootLeft].Position.Y)}, brush, 9)); ContainerSkeleton.Children.Add(getBodySegment(new PointCollection() { new Point(jointsDictionary[JointType.HipCenter]. Position.X, jointsDictionary[JointType.HipCenter].Position.Y), new Point(jointsDictionary[JointType.HipRight].Position.X, jointsDictionary[JointType.HipRight].Position.Y), new Point(jointsDictionary[JointType.KneeRight].Position.X, jointsDictionary[JointType.KneeRight].Position.Y), new Point(jointsDictionary[JointType.AnkleRight].Position.X, jointsDictionary[JointType.AnkleRight].Position.Y), new Point(jointsDictionary[JointType.FootRight].Position.X, jointsDictionary[JointType.FootRight].Position.Y)}, brush, 9)); }

Metoda drawBones trasează un segment pentru fiecare dintre oasele cele mai importante din scheletul utilizatorului. Segmentele sunt adăugate în containerul ce conține și elipsele reprezentând încheieturile identificate anterior. private Polyline getBodySegment(PointCollection points, Brush brush, int thickness) { Polyline polyline = new Polyline(); polyline.Points = points; polyline.Stroke = brush; polyline.StrokeThickness = thickness; return polyline; } private Joint getScaledJoint(Joint joint, AllFramesReadyEventArgs e) { var posX = (float)GetCameraPoint(joint, e).X; var posY = (float)GetCameraPoint(joint, e).Y; joint.Position = new Microsoft.Kinect.SkeletonPoint { X = posX, Y = posY, Z = joint.Position.Z }; }

return joint;

Un mod de a afișa încheieturile pe ecran ar fi prin folosirea metodei ScaleTo. Totuși, ScaleTo tinde să deformeze corpul utilizatorului, astfel încât acesta să ocupe întreg spațiul disponibil pe display. Pentru a păstra proporțiile anatomice, vom converti manual coordonatele fiecărei încheieturi din sistemul metric în pixeli, prin intermediul funcției GetCameraPoint. Point GetCameraPoint(Joint joint, AllFramesReadyEventArgs e) { using (DepthImageFrame depth = e.OpenDepthImageFrame()) { if (depth == null || sensor == null) { return new Point(0, 0); } DepthImagePoint jointDepthPoint = depth.MapFromSkeletonPoint(joint.Position); ColorImagePoint jointColorPoint = depth.MapToColorImagePoint(jointDepthPoint.X, jointDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30); return new Point((int)(ContainerSkeleton.ActualWidth * jointColorPoint.X / 640.0), (int)(ContainerSkeleton.ActualHeight * jointColorPoint.Y / 480));

} }

Concluzii

Afișarea scheletui complet e utilă în special pentru debugging (putem afla cu ușurință cât de precis sunt poziționate încheieturile pe corpul utilizatorului), sau pentru unele aplicații grafice sau jocuri.

www.todaysoftmag.ro | nr. 5/2012

45


testare

Testarea ca știință exactă

D

omeniul testării software a devenit din ce în ce mai dinamic, noi metode de testare sunt introduse, multe concepte redefinite sau reinventate. Celebra sintagmă “oricine poate să testeze” incepe să fie din ce în ce mai greu de confirmat, datorită nivelului tehnic ridicat și al tehnologiilor folosite în dezvoltarea aplicațiilor.

Se dă un scenariu simplu: student sau proaspăt absolvent se angajează pe o poziție de “Software Testing Engineer”, generic denumit QA. În primele zile se familiarizează cu compania, colegii, aplicația pe care urmează să o testeze. Mai mult, i se sugerează să studieze pentru certificarea de ISTQB Foundation Level, pentru o mai bună înțelegere a procesului de testare. Conștiincios, QA-ul nostru învață și în final obține diploma de certificare pentru primul nivel de testare software. La un moment dat unele concepte sunt uitate, că doar suntem oameni, și apelează la prietenul Google pentru a reîmprospăta memoria. Inevitabil găsește pentru același concept, mai multe definiții, apropiate ca explicație, dar cu mici diferențe interpretabile (e.g “Test Automation”). Întrebarea ce urmează: Care e definiția cea mai potrivită, există acel “single source of truth” la care visăm ? Da, s-ar putea să fie puțini cei care își aleg ca metodă de documentare studiile sau articolele stiințifice publicate pe această temă și majoritatea va opta pentru o căutare rapidă pe internet. Voi incerca, în exemplul ce urmează, să vă arăt că testarea automată e mai mult decât rulare de teste, iar structura unui proces automat e muncă laborioasă ce implică mulți factori, nu doar ce găsim la o simplă căutare pe net. ISTQB e o certificare recunoscută la nivel mondial, dar totuși nu e singura. Nu toată lumea acordă o importanță majoră acestui tip de certificare și totuși un QA și un cercetator în domeniul testării software, pot vorbi aceeași limbă. Testarea software tinde să fie o știință exactă, o știință studiată și bine definită. E un domeniu în care un concept primește o definiție în urma unui proces de evaluare și feedback, laborios și exercitat între persoane academice, pe baza unor date reale. Să dăm un exemplu concret: la o simplă cautare pe Google: “Test Automation”, accesați articolul din Wikipedia1, unde veți găsi următoarea definiție:

46

nr. 5/2012 | www.todaysoftmag.ro

“In software testing, test automation is the use of special software (separate from the software being tested) to control the execution of tests, the comparison of actual outcomes to predicted outcomes, the setting up of test preconditions, and other test control and test reporting functions. Commonly, test automation involves automating a manual process already in place that uses a formalized testing process.” În schimb, dacă veți căuta același concept în studii și articole de cercetare, veți da peste principiul Parasuraman2, care definește testarea automată de forma: “We propose that automation can be applied to four broad classes of functions: a) information acquisition; b) information analysis; c) decision and action selection; and d) action implementation. Within each of these types, automation can be applied across a continuum of levels from low to high, i.e., from fully manual to fully automatic.[…] We therefore use a definition that emphasizes human-machine comparison and define automation as a device or system that accomplishes (partially or fully) a function that was previously, or conceivably could be, carried out (partially or fully) by a human operator [8].” Se poate observa ca varianta Wikipedia se referă doar la partea de rulare a scenariilor de test, care, din perspectiva principiului academic, e doar un nivel intermediar unde automatizarea completă e definită prin lipsa oricărei intervenții umane. Pe o scală de la 1 la 10 (1- sistemul nu oferă deloc asistență, toate deciziile și acțiunile sunt umane; 10 – sistemul decide tot, acționează autonom, ignoră intervenția umană) Testarea Automată așa cum am invățat-o eu în primele zile de QA, se află la nivelul 5, nivel ce presupune doar execuția testelor, orice altă decizie fiind luată de om (definirea datelor de test, selecția testelor, analiza rezultatelor, etc). Există o multitudine de modele de automatizare, care implică mai mult sau mai puțin intervenția umană, exemplul

oferit este doar un punct de pornire pentru o înțelegere mai bună a ce-și doreste fiecare echipă în momentul în care folosește testarea automată. În final, un proces eficient și de succes al automatizării software se rezumă la factori gen productivitate/ costuri/calitate. În concluzie, aș vrea doar să menționez, că fiecare își alege documentația și sursele de informare de unde crede de cuviință, fie online, fie offline, în final e irelevant. Ce este relevant e informatia cu care rămîne și acuratețea acelei informații. Testarea software, în special cea automată nu face parte din categoria artă creativă unde fiecare poate să vină cu o definiție proprie a ce inseamnă automatizare sau testare sau orice al termen. Și că tot vorbim de artă, automatizarea poate să devină o artă, în măsura în care procesele folosite, bine definite și demonstrate științific, vor aduce admirația oamenilor din domeniul software și nu numai.

Bibliografie 1. http://en.wikipedia.org/wiki/ Test_automation 2. Raja Parasuraman, Thomas B. Sheridan, Fellow, IEEE, and Christopher D. Wickens – “A Model for Types and Levels of Human Interaction with Automation” in IEEE transactions on systems, man, and cybernetics—part a: systems and humans, vol. 30, no. 3, may 2000

Andrei Conțan

andrei.contan@betfair.com Principle QA @ Betfair Co-Founder Romanian Testing Community


programare

TODAY SOFTWARE MAGAZINE

Noutăți în Windows Communication Foundation 4.5

N

oile funcţionalităţi din WCF 4.5 tind să se încadreze în două aspecte: simplitate şi scalabilitate. Cea mai mare problemă care există când vine vorba de WCF este configurarea. Ceea ce s-a dorit de la noua versiune a fost un mod mai uşor şi mai simplu de configurare. Ştim cu toţii că nu este uşor să configurezi un serviciu WCF. Într-adevăr, după ce este configurat și merge, devine un mare atuu in orice sistem de aplicații distribuite.

Leonard Abu-Saa

leonard.abu-saa@arobs.com System Architect @ Arobs

Modernizarea şi scalabilitatea au fost obţinute prin implementarea de noi funcţionalităţi gen: web sockets, suport pentru protocolul UDP, suport pentru noul async programming model “awayt/assync”. Să începem cu fişierul de configurare. Vi se pare cunoscut scenariul în care aţi creat un serviciu pe care îl expuneţi printrun endpoint http/tcp, iar când aţi adăugat o referinţă din aplicaţia client aţi găsit o tonă de configurări pentru un binding? Din fericire acest aspect s-a schimbat şi lucrurile vor arăta altfel. Aşa arată configurarea default a unui binding într-o aplicaţie client, în WCF 4.0

Aşa va arăta in WCF 4.5 !

Frumos. Nu? Un alt aspect legat de simplitate este faptul că s-au modificat şi valorile unor setări pentru ca serviciile să fie “production ready”. În acest sens au fost modifiate Reader Quotas, Throttles, Timeouts tocmai pentru a evita multitudinea de excepţii ce se generau din setările default anterioare.

www.todaysoftmag.ro | nr. 5/2012

47


tehnologii

Un feature nou introdus este suportul pentru moduri de autentificare multiplă per endpoint. Dacă acest lucru înainte era posibil doar prin crearea mai multor endpoint-uri, acum este posibil prin configurarea unui singur endpoint care să suporte de exemplu autentificare Windows si Basic simultan. Definirea unui endpoint și a unui serviciu se face mai ușor în fișierul de configurare prin suportul nou de inllisense, care acum ne oferă o listă de contracte sau

denumiri de clase care pot fi folosite. În cazul în care un element nu a fost configurat bine, în fereastra de warnings vom fi atenționați despre acest fapt. Acest feature se numește “Validation over configuration”. WCF 4.5 mai vine cu o noutate în zona de bindings. A fost introdus un nou binding, basicHttpsBinding. Acesta este asemanator cu basicHttpBinding, și are umătoarele setări default: SecurityMode=Transport și ClientCredentialType=None. Configurările acum se pot face în serviciu din cod printr-un nou tip, numit ServiceConfiguration. În cazul în care în serviciu se găsește o metodă statică void Configure(ServiceConfiguration config), aceasta va fi apelată by default. Prin acest tip nou de date se pot adăuga behavior-uri noi, endpoint-uri noi, si alte setări uzuale. Configurările se pot încărca acum și

dintr-un fișier aflat la o locație diferită pe disc. Acest lucru era posibil înainte doar prin work-around-uri care aduceau overhead și dificultate în mentenanță. Acest feature s-a numit în mod evident Codebased configuration. Toate aceste feature-uri au fost introduse pentru a simplica si ușura lucrul cu WCF. În continuare vom vorbi despre ce anume s-a adus în plus pe partea de modernizare si scalabilitate a acestui framework. Vom începe cu noul mod în care se pot scrie metode asincrone, Task-based model . Acest feature permite scrierea de cod asincron atât pe server cât si apelarea lui de pe client tot în mod asincron. Ca și principiu orice metodă care returnează Task sau Task<T> reprezintă o metodă asincronă pe server. Aceste metode pot fi invocate folosind noile keyword-uri: await și async. Să considerăm urmatorul exemplu: public static async void CopyToAsync (Stream source, Stream destination) { byte[] buffer = new byte[0x1000]; int numRead; while((numRead = await source. ReadAsync(buffer, 0, buffer.Length)) > 0) { await destination.WriteAsync(buffer, 0, numRead); } }

Practic avem o copiere asincronă de stream-uri. Metoda are nevoie de modificatorul async deoarece în interiorul ei folosim operatorul await. În acest fel compilatorul știe că este vorba de cod asincron iar când execuția codului va fi gata va continua cu orice alte instrucțiuni mai rămân de executat. În cazul in care folosim await

public static IAsyncResult BeginCopyTo(Stream source, Stream destination) { var tcs = new TaskCompletionSource(); byte[] buffer = new byte[0x1000]; Action<IAsyncResult> readWriteLoop = null; readWriteLoop = iar => { try { for (bool isRead = iar == null; ; isRead = !isRead) { switch (isRead) { case true: iar = source.BeginRead(buffer, 0, buffer.Length, readResult => { if (readResult.CompletedSynchronously) return; readWriteLoop(readResult); }, null); if (!iar.CompletedSynchronously) return; break; case false: int numRead = source.EndRead(iar); if (numRead == 0) { tcs.TrySetResult(true); return; } iar = destination.BeginWrite(buffer, 0, numRead, writeResult => { try

48

nr. 5/2012 | www.todaysoftmag.ro

{

}

}

}

dar nu punem async în semnătura metodei vom avem o eroare de compilare. Pe nt r u c omp ar aț i e voi a d ău g a același exemplu folosind APM (Async Programming Model), cel uzual cu care am fost obişnuiţi până acum. Este evident faptul că lucrurile au fost simplificate major. Folosind noul task based model, este aproape la fel de uşor scrierea metodelor asincrone ca şi cele sincrone. Trebuie doar ca return type-ul metodei să fie de tip Task<T> şi să adăugaţi keyword-urile await şi async. Revin la partea de bindigs unde a fost introdus UdpBinding. Acesta este folositor în cazul în care se doreşte transmiterea datelor către mai mulţi receive-ri, scenarii gen broadcast şi multicast . În acest caz nu este atât de important conţinutul mesajelor cât timpul de trimitere. Limitarea este faptul că nu are WAS suport. Un alt feature foarte important este suportul pentru WebSockets. Acestea permit comunicarea bi-direcţională, full duplex, într-un mod mai uşor decât se făcea până acum. Ca o concluzie, în WCF 4.5 s-a încercat simplificarea si modernizarea platformei de development prin setări “production ready”, intellisense si validare pe fişierele de configurare, support pentru WebSockets, UDP, Task-based model și alte feature-uri. Considerăm că aceste feature-uri sunt utile şi bine venite raportându-ne la versiunile anterioare și abia așteptăm să le punem în practică.

if (writeResult.CompletedSynchronously) return; destination.EndWrite(writeResult); readWriteLoop(null);

} catch(Exception e) { tcs.TrySetException(e); } }, null); if (!iar.CompletedSynchronously) return; destination.EndWrite(iar); break;

} catch(Exception e) { tcs.TrySetException(e); } }; readWriteLoop(null); }

return tcs.Task;

public static void EndCopyTo(IAsyncResult asyncResult) { ((Task)asyncResult).Wait(); }


tehnologii

TODAY SOFTWARE MAGAZINE

Service Bus Topics din Windows Azure

P

Radu Vunvulea

Radu.Vunvulea@iquestgroup.com Senior Software Engineer @iQuest, proiectele pe care lucrează sunt de tip LoB, în general folosind ultimele tehnologii Microsoft. Face parte din grupul entuziaștilor, motiv pentru care ii place să fie la curent cu tot ce apare nou in domeniul IT, in special din punct de vedere software.

rimul CTP de Windows Azure a fost anunţat în 2008, iar după doi ani a fost lansată şi versiunea comercială. De atunci şi până astăzi, fiecare nouă versiune de Windows Azure a adus noi funcţionalităţi. Dacă în 2010 web role-ul şi worker role-ul erau principalele puncte forte, astăzi Windows Azure este mult mai complex şi ne permite să facem lucruri pe care nici nu ni le puteam imagina. Windows Azure Service Bus ne oferă infrastructura pentru a putea comunica într-un sistem distribuit fără nici o problemă. Toate găzduite pe servere on-premises prin interproblemele legate de scalabilitate, securi- mediul la Windows Azure. tate, load-balancing sunt rezolvate de către Service Bus Queue este un serviciu care acesta. O proprietate foarte importantă a ne permite comunicarea între două module acestei infrastructuri este că garantează că prin intermediul unei cozi de mesaje. nici un mesaj nu este pierdut, fiecare mesaj Această operaţie se desfăşoară în totaliajungând la destinaţie odată ce a fost recep- tate asincron, modulele nefiind obligate să ţionat de Service Bus. aştepte după alte module. Orice mesaj care În acest moment când vorbim de a fost trimis cu succes la această coadă de Service Bus vorbim de trei componente mesaje nu o să fie pierdut, acest lucru fiind foarte importante: garantat de către Windows Azure. Chiar şi • Service Bus Queues, în momentele când nu există un consuma• Service Bus Topics, tor de mesaje, acestea o să fie păstrate de • Service Bus Relay. către Service Bus Queue. Service Bus Queue, despre care o să vorNumărul de mesaje dintr-un queue nu bim în acest articol, este un serviciu care este limitat. Limita există doar la capacitane permite să lucrăm cu cozi de mesaje în tea maximă pe care o poate avea un queue, cadrul Service Bus-ului. Service Bus Topics aceasta fiind de 5GB. Fiecare mesaj poate este destul de asemănător cu Service Bus avea o dimensiune maximă de 256KB. Queues, diferenţa principală este că un În interiorul acestuia putem să adaugăm mesaj poate să ajungă la mai mulţi ascul- informaţii sub forma de (cheie, valoare) tători (subscribers), nu doar la unul singur. sau orice obiect serializabil. Putem să Service Bus Relay ne permite să integrăm adaugăm chiar şi stream-uri de date, atâta şi să expunem servicii WCF care sunt timp cât dimensiunea lor nu depăşeşte

www.todaysoftmag.ro | nr. 5/2012

49


tehnologii

capacitatea maximă a unui mesaj. Fiecare mesaj adăugat în Service Bus Queue are un TTL (time-to-live), valoarea maximă acceptată este infinit. În momentul în care TTL expiră, un mesaj este automat eliminat din coadă. Pe lânga această proprietate avem disponibilă şi o proprietate prin care putem specifica când un mesaj să devină activ în coadă şi poate să fie consumat. În acest mod putem trimite un mesaj în coadă care să poată fi procesat doar începând la o dată prestabilită de către noi. Service Bus Queue, este un serviciu care ne permite să avem un număr nelimitat de producători şi consumatori de mesaje. Acest servciu include şi un mecanism de detectare automată a duplicatelor. Din punct de vedere a securităţii şi a accesului la o coadă de mesaje din Service Bus, acesta poate fi făcut prin intermediul: • Claim-urilor de tip ACS, • Acces pe bază de rol, • Identify provider federation. La ora actuală Shared Access Signature nu poate fi folosit pentru a accesa o coadă din Service Bus sau orice altă resursă din cadrul Service Bus-ului. Pentru a putea folosi o coadă sau orice alt serviciu disponibil prin intermediul la Service Bus este necesar să ne creăm un namespace. Un namespace reprezintă un nume unic prin care putem identifica resursele şi serviciile pe care le avem disponibile în Service Bus. Acesta poate fi creat de pe portalul Windows Azure, în cadrul secţiunii “Service Bus, Access Control & Caching”. Odată ce avem un namespace ,o coadă poate fi creată prin diferite moduri, începând de la portal până la fişiere de configurare sau din cod. Putem să dăm orice nume la o coadă atâta timp cât respectăm următoarele reguli: • Conţine doar cifre, litere mari şi mici, • Conţine doar caractere precum ‘-‘, ‘_’, ‘.’ • Nu depăşeşte 256 de caractere. Aplicaţiile care doresc să acceseze Service Bus Queues trebuie să ştie trei informaţii: • Endpoint – adresa url prin interme d iu l c ăre i a pute m a c c e s a serviciile din cadrul Service Bus. Această adresă are în general forma următoare:

issuer (proprietarul namespace-ului) SharedSecretValue – cheia secretă pe baza căreia un namespace poate fi accesat. Aceasta se poate regenera în orice moment prin intermediul portalului. Toate aceste informaţii şi locaţia unde trebuie să fie adăugate într-un proiect pot fi găsite pe portalul Windows Azure. Acesta ne poate genera automat XML-ul care trebuie adăugat. Tot ce ne mai rămâne nouă de făcut este să adăugăm printr-un simplu copy/paste această informaţie. Următoarele exemple o să fie în C#, dar asta nu înseamnă că nu puteţi să folosiţi Service Bus Queues din PHP, Node.js sau orice alt limbaj de programare. Acest serviciu este expus în format REST, iar orice librărie pe care o folosiţi este de fapt un wrapper peste acesta. Înainte să creăm un queue este recomandat să verificăm dacă acesta nu există deja. În cazul în care dorim să creăm un queue cu un nume care deja există va fi aruncată o excepţie. NamespaceManager ne permite să accesăm orice serviciu din cadrul Service Bus-ului. •

NamespaceManager namespaceManager = NamespaceManager.CreateFromConnectionString( CloudConfigurationManager.GetSetting( “ServiceBusConnectionString”)); QueueDescription queueDescription = new QueueDescription(„FooQueue”);

BrokeredMessage message = new BrokeredMessage(); message.Properties[„key”] = „value”;

queueDescription.DefaultMessageTimeToLive = new TimeSpan(0, 10, 30); if(!namespaceManager.QueueExists(„FooQueue”)) {

QueueClient queueClient = QueueClient.CreateFromConnectionString( connectionString, „FooQueue”);

namespaceManager. CreateQueue(queueDescription); //sau namespaceManager.CreateQueue(“FooQueue”); }

BrokeredMessage messageReceiveAndDelete = queueClient.ReceiveAndDelete();

După cum se poate observa, o coadă se poate crea specificând doar numele. În cazul în care dorim să setăm anumiţi parametri cu alte valori faţă de valorile default putem apela la QueueDescription. Orice mesaj pe care îl adaugăm în sb://[namespace].servicebus.windows. queue este de tip BrokeredMessage. În net/ cadrul acestui obiect este necesar să punem • SharedSecretIssuer – numele la toată informaţia care trebuie să ajungă la

50

nr. 5/2012 | www.todaysoftmag.ro

consumator. Un mesaj este format din două părţi: • Header –conţine configuraţia mesajului şi toate proprietăţile pe care noi vrem să le adaugăm • Body – conţinutul mesajului. Acesta poate să fie un obiect serializat sau un stream. Operaţiile pe o coadă se pot desfăşura atât sincron cât şi asincron. Mecanismul de adăugare a unui mesaj în coada este destul de simplu. În schimb când dorim să extragem un mesaj din coadă avem la dispoziţie două mecanisme: • Receive and delete – un mesaj este luat din coadă şi imediat şters • Peek and lock – un mesaj este luat din coadă şi blocat. Acesta urmează să fie şters doar în momentul în care consumatorul specifică acest lucru. Dacă într-un interval predefinit de timp consumatorul nu confirmă că mesajul a fost procesat, Service Bus Queue va face mesajul din nou disponibil pe coadă (valoarea default este de 60 de secunde). Toate aceste operaţii pot fi făcute prin intermediul unui obiect de tip QueueClient.

queueClient.Send(message);

try { BrokeredMessage messagePeekAndLock = queueClient.Receive(); // ... messagePeekAndLock.Complete(); } catch() { messagePeekAndLock.Abandon(); }

Operaţiile pe coada de mesaje sunt tranzacţionale, iar atât producătorul cât şi consumatorul pot să lucreze cu batch-uri de mesaje. În cazul în care ajungeţi să adăugaţi foarte multe date într-un mesaj sau


TODAY SOFTWARE MAGAZINE

Service Bus Topics din Windows Azure

doriţi să adăugaţi conţinutul unui stream într-un mesaj încercaţi să vă gândiţi de două ori dacă aveţi nevoie de această informaţie şi dacă nu o puteţi pune într-un loc unde atât producătorul cât şi consumatorul să o poată accesa (de exemplu în Windows Azure Tables, Windows Azure Blobs). byte[] currentMessageContent = new byte[100]; //... BrokeredMessage messageToSend = new BrokeredMessage(new MemoryStream( currentMessageContent)); queueClient.Send(messageToSend); BrokeredMessage messageToReceive = queueClient.Receive(); Stream stream = messageToReceive. GetBody<Stream>();

După ce se apelează metoda Receive() trebuie să avem grijă dacă obiectul returnat este null. Totodată, thread-ul o să rămână blocat la apelul metodei ReceiveAndDelete până când un mesaj din coadă este disponibil. Fiecare mesaj adăugat în coadă poate să avea ataşat un id unic de sesiune (SessionId). Prin intermediul acestei sesiuni, se poate configura ca un consumator să primească mesajele care au doar un anumit id de sesiune. Aceasta este o modalitate de a trimite date către un consumator care în mod normal nu ar încăpea într-un singur mesaj. Pe partea de producător trebuie setată doar proprietatea SessionId a mesajului, iar consumatorul trebuie să se folosească de MessageSession, instanţă ce poate fi obţinută apelând metoda “AcceptMessageSession([sessionId])” a QueueClient-ului. MemoryStream finalStream = new MemoryStream(); MessageSession messageSession = queueClient. AcceptMessageSession(mySessionId); while(true) { BrokeredMessage message = session. Receive(TimeSpan.FromSeconds(20)); if(message != null) { ... message.Complete(); continue; } break;

//

}

}

O coadă de mesaje din Service Bus Queues, nu conţine doar un singur queue. Putem spune că un queue conţine mai multe queue-uri. Toate mesajele care nu au putut fi procesate (de exemplu mesajele care au expirat sau când coada a ajuns la capacitate maximă) ajung într-o coadă de mesaje de tip “Death Letters”. Această coadă poate fi accesată, fiind foarte utilă când se face debug sau când avem nevoie să logăm mesajele care nu au putut să fie procesate. În această coadă nu ajung doar mesajele adăugate de către sistem. Aceste mesaje se pot adăuga şi din cod prin intermediul metodei DeathLetter a unui BrokeredMessage. Există un scenariu când această funcţionalitate ne poate fi foarte utilă. Imaginaţi-vă că un consumator de mesaje încearcă să consume un mesaj care nu poate să fie procesat. Consumatorul va încerca la infinit să proceseze acest mesaj. Acest tip de mesaj este denumit “Poison Message”, iar un sistem gândit greşit poate să fie dat peste cap din cauza acestei cozi. În următorul exemplu încercăm să procesăm un mesaj de trei ori. Dacă nu reuşim cu succes, acesta este automat marcat ca şi “Poison Message”. while(true) { BrokeredMessage message = queueClient. Receive(); if(message == null) { Thread.Sleep(1000); continue; } try {

... message.Complete() } catch(Exception ex) { if( message.DeliveryCount > 3 ) { message.DeadLetter(); } message.Abandon(); }

O referinţă la o coadă de mesaje pentru death letters poate fi obţinută în felul următor: QueueClient deathLeterQueue= QueueClient. CreateFromConnectionString( myFooConnectionString, QueueClient.FormatDeadLetterPath( „FooQueue”) );

O funcţionalitate aparte a Service Bus Queues este integrarea cu WCF. Un serviciu WCF poate fi configurat să folosească cozile de mesaje pentru a putem comunica. Prin acest mod serviciul nostru devine flexibil şi scalabil. Toate problemele de tip load balancing se rezolvă aproape singure în acest fel. Iar în cazul în care serviciul este căzut, consumatorul va putea trimite în continuare mesaje fără să aibă parte de erori sau aceste mesaje să se piardă. În unele cazuri acest lucru ne poate fi de folos. Totodată prin acest mod putem să expunem servicii WCF din reţele private fără să avem probleme de securitate. Din unele puncte de vedere Service Bus Queues este destul de asemănător cu Windows Azure Queues. Ne putem imagina Service Bus Queues ca şi un Windows Azure Queues cu steroizi. Când avem nevoie de features precum garantarea ordinii mesajelor, operaţii tranzacţionale, TTL mai mare ca șapte zile sau integrarea cu WCF, atunci Service Bus Queues este soluţia noastră. Sunt însă cazuri când Windows Azure Queues este o soluţie mult mai bună. Din această cauză trebuie să comparaţi cele două tipuri de cozi de mesaje oferite de Windows Azure şi să vedeţi care este cea mai bună pentru aplicaţia voastră. În concluzie Service Bus Queues este extrem de puternic şi are patru puncte forte care nu trebuie neglijate: • Loose coupling (consumatorul şi producătorul nu trebuie să ştie unul de celălalt) • Load leveling (consumatorul nu trebuie să funcţioneze non-stop) • Load balancing (putem să înregistrăm consumatori şi producători foarte uşor) • Temporary decoupling (producătorul sau consumatorul poate să fie offline)

www.todaysoftmag.ro | nr. 5/2012

51


tehnologii

Malware pe Android statistici, comportament, identificare și neutralizare Android, sistemul de operare pentru telefoanele mobile de tip Smartphone, cel mai popular mobile OS din SUA și poate cel mai popular de pe planetă se bucură de o atenție tot mai categorică la nivel mondial și aceasta datorită diversității gadget-urilor pe care este instalat.

Andrei Avădănei andrei@worldit.info Fondator si CEO DefCamp CEO worldit.info

Din păcate, nici Android nu scapă de atenția hackerilor și a criminalilor cibernetici care abia așteaptă noile tehnologii să ajungă populare pentru a obține câștiguri informaționale, tehnologice și financiare ilegale. Totuși, cum stă Android în acest moment? Conform unui studiu realizat de TrendLabs, în primele 3 luni ale acestui an au fost descoperite 5 000 de aplicații malware ca apoi în luna aprilie să se descopere aproape 15 000 de aplicații malware, aceștia așteptându-se ca până la sfârșitul anului să se ajungă la aproape 130 000 de aplicații malware mobile. Îngrijorător e că doar 20% dintre aplicațiile mobile au o aplicație dedicată securității, iar drept dovadă, 17 aplicații malware din Google Play au fost descărcate de 700 000 de ori până ca acestea să ajungă să fie eliminate. Clasamentul comportamental al malware-ului pe Android arată că în top se află aplicațiile de tip Premium Service Abuser cu 48%, urmate de Adware cu 22% și la mică distanță, cu 21%, furtul de date. Uneltele de spionaj ocupă în acest moment doar un procent de 4% ceea ce demonstrează că până acum sunt folosite în scop targetat. Un exemplu de aplicație malware a fost SMSZombie, nu prea populară în Europa și SUA pentru că se adresa unui serviciu folosit predominant de chinezi

– Mobile SMS Payment Service. Aplicația a infectat 500,000 de device-uri și au trimis bani în conturile unor profile de jocuri online.

Ce opțiuni are o aplicație de spionaj publică?

Pentru aproape 16$ pe lună sau chiar mai puțin, există aplicații de spionaj ale telefoanelor cu Android (atenție, și nu numai) extrem de complexe ��i de bine puse la punct ce se adresează în mod public părinților ce vor să fie mai aproape de copiii lor, managerilor firmelor ce suspectează spionajul industrial dar și organelor guvernamentale. Controlul aplicațiilor se face atât prin SMS cât și prin Internet, atunci când este posibil. Poți înregistra convorbirile și vizualiza istoricul apelurilor, poți citi SMS-urile primite și trimise, poți defini cuvinte cheie pentru aceste SMS-uri, poți înregistra zgomotul din jur până la peste 10 metri, poți citi email-urile de pe GMail sau de pe vreun serviciu definit în mod explicit în aplicația de email default de la Android, poți accesa toate contactele stocate pe telefon, toate activitățile din calendar, poți vedea fotografiile, videoclipurile, muzica; există acces la istoricul browserelor, monitorizarea locației cu sau fără GPS și lista continuă. Mă repet, aceasta poate face doar o aplicație de spionaj publică. Monitorizarea rețelelor Wifi, obținerea controlului asupra rețelelor, instalarea de exploit-uri 0-day pe computerele din rețea, monitorizarea bluethoot ar putea completa lista.

Ce opțiuni ar putea avea un botnet pentru Android?

Deși situațiile de acest gen au fost puține până acum, ne putem aștepta în

52

nr. 5/2012 | www.todaysoftmag.ro


tehnologii

orice clipă la un adevărat botnet popularizat prin intermediul Google Play + ceva magic. Să ne imaginăm următorul scenariu – o aplicație nouă, aparent ce rezolvă o nevoie a publicului larg a fost încărcată în Google Play. După ce este descărcată, această dă automat Like, +1 și un punctaj bun aplicației din market, eventual lasă un comentariu random dintr-o listă predefinită, poate chiar încearcă să lege un dialog între doi “clienți”. Aplicația malware exploatează o vulnerabilitate ce permite obținerea dreptului de root pe telefonul mobil. Printre altele face un ping la un website hijacked, ce are un serviciu de comunicare special instalat pentru malware. Acesta îi comunică o listă cu website-uri hijacked descentralizate. Bun, face un fingerprinting pe tot mobilul (operațiunea se poate face și înainte de a obține root acces și implicit backdoor-ul), se decide dacă e necesară vreo unealtă suplimentară de la unul din servere. Dacă nu, se colectează informații precum – adrese de email, numere de telefon, conversații, istoric, cookie-uri, conturi, s-ar putea infecta telefoane până în momentul în care ajunge la țintă, se realizează operațiunea pentru care a fost creat, apoi se diluează. Restul e variabil. Problema rămâne totuși răspândirea – prin rețele wifi, pe alte telefoane oferind mesaje personalizate prietenilor în funcție de țara și orașul unde sunt, prin 0-day-uri, prin construirea permanentă a unor aplicații infectate.

TODAY SOFTWARE MAGAZINE

configurabil. Fiecare facilitate majoră a platformei este revizuită de ingineri. Pe parcursul dezvoltării componentele sunt revizuite de Android Security Team, Google Information Security Engineering Team și consultanți independenți în securitate. Scopul acestor analize este identificarea slăbiciunilor și posibilelor vulnerabilități cu mult înainte ca acestea să fie publicate Open Source. În momentul publicării, Android Open Source Project permite întreținerea și revizuirea codului de un număr nedefinit de entuziaști și voluntari. După momentul în care a fost publicat codul sursă, echipa Android reacționează rapid la orice raport cu privire la o potențială vulnerabilitate pentru a se asigura că riscul ca utilizatorii să fie afectați este minimalizat în cel mai scurt timp posibil. Aceste reacții includ updateuri rapide, eliminarea unor aplicații din Google Play sau eliminarea unor aplicații din device-uri.

Arhitectura platformei de securitate Android

Android urmărește să fie cel mai sigur sistem de operare pentru platformele mobile, încercând să garanteze: • protejarea datelor de la utilizatori, • protejarea resurselor sistemului (include și rețeaua), • izolarea aplicațiilor. Pentru a atinge aceste puncte, trebuie atinse niște puncte cheie în arhitectura platformei : O introducere în securitatea pe • securitate robustă la nivel de OS Android prin kernelul de Linux, Android este o platformă mobilă • Sandbox pentru aplicații, modernă ce a fost dezvoltată cu gândul la • comunicare securizată între procese, deschidere. Aplicațiile de pe Android se • semnarea aplicațiilor, folosesc de tehnologia hardware și software pentru a oferi utilizatorilor experiența ideală. Pentru a proteja valoarea creată de sistemul de operare, platforma oferă un mediu ce asigură securitatea utilizatorilor, a datelor, a aplicațiilor, a device-ului și a rețelei. Securizarea unei platforme Open Source necesită o arhitectură robustă de securitate dar și de un proces de securitate riguros. Android a fost gândit astfel încât securitatea sa fie împărțită în mai multe straturi, oferind astfel o flexibilitate sporită și protejând utilizatorii platformei.

definirea unor permisiuni pentru aplicații și utilizatori. Mai multe detalii despre arhitectură Android se găsesc pe source.android.com.

Ce aplicații Anti-Virus pentru Android există?

Conform rezultatelor AV-Comparatives din septembrie 2012, cele mai eficiente aplicații mobile de securitate sunt: avast! Mobile Security, BitDefender Mobile Security, ESET Mobile Security, F-Secure Mobile Protection, IKARUS mobile.security, Kaspersky Mobile Security, Lookout Premium, McAfee Mobile Security, Qihoo 360 Mobilesafe, SOPHOS Mobile Security, WEBROOT, eficiență fiind de peste 93% în ordine descrescătoare.

Concluzii

Deși statisticile arată îngrijorător, realitatea e că majoritatea aplicațiilor malware de până acum nu au un comportament foarte periculos. În același timp, tehnologiile anti-virus moderne se mută și pe mobile cu o viteză surprinzătoare, majoritatea jucătorilor de pe piață având o soluție de securitate pentru smartphone deja pregătită. Mai mult decât atât, echipa de dezvoltare Android susține că ultima versiune a sistemului de operare aduce un plus de siguranță, după cum o confirmă și unii specialiști în securitate independenți. Din experiență, tind să cred că problema virușilor pe telefoanele mobile va fi la fel de sensibilă ca pe computere în scurt timp și că va trebui să fim din ce în ce mai atenți la ce instalăm. Stay safe, stay open!

Programul Android de securitate

Procesul Android de securitate începe în primele etape ale dezvoltării prin crearea unui model de securitate complet și www.todaysoftmag.ro | nr. 5/2012

53


diverse

Gogu Şefu’ întredeschise uşa de la birou, iar Gogu văzu imediat pe faţa lui că ceva nu e în regulă. Adevărul e că, dacă s-ar fi uitat în jur, ar fi văzut că întreg biroul era stupefiat: încă nu le venea să creadă, nimeni nu-i auzise până acum pe Gogu şi pe Mişu certându-se şi ţipând unul la altul. Păi dacă e căpos?! îşi zise Gogu. Dar stai aşa, că ne lămurim noi acum… - Şefu’, bine c-ai venit. Ai două minute să ne clarifici o problemă? - O problemă?! Păi la ce scandal se aude la voi, mira-m-aş să fie vorba despre o singură problemă! S-aud şi eu, care e mărul discordiei? - Ce măr, Şefu’, crezi ca ne arde de joacă? se băgă şi Mişu în discuţie, roşu în obraji, cu ochii sticlind şi cu respiraţia întretăiată de parcă ar fi alergat la maraton. Lămureşte-l mata pe colegul Gogu, că eu argumente nu mai am! - N-ai, că n-ai de unde! De-aia te şi enervezi şi ridici tonul! nu se putu abţine Gogu. Şefu’ se prinse că discuţia probabil dura déjà de o bună bucată de vreme, era evident – pentru cine îl cunoştea, desigur - că Gogu făcea eforturi să pară calm, dar era la fel de “prins” ca Mişu (doar că nu era la fel de roşu). Erau necesare măsuri imediate aşa că Şefu’ îşi luă aerul sfătos şi vocea joasă, se îndreptă de spate şi lăsă cuvintele să iasă clar şi răspicat: - Cred că e cazul să vă calmaţi amândoi şi să îmi explicaţi – calm, fără să ridicaţi tonul şi fără să vorbiţi deodată – despre ce e vorba. Evident se lansaseră imediat amândoi în explicaţii aşa că Şefu’ se văzu nevoit să repete: - Calm, fără să ridicaţi tonul şi fără să vorbiţi deodată, am spus. Gogule, explică tu. Gogu încercă să se abţină şi să nu dea drumul la zâmbetul victorios (era clar că eu explic, sunt mai vechi şi clar mai priceput) şi, după ce luă – uşor teatral - aer în piept, începu să explice: - Uite Şefu’ despre ce e vorba: piramidele din Egipt au fost construite acum vreo cinci mii de ani, corect până aici? - Corect, Gogule. - Marele zid chinezesc e mai recent, are probabil in jur de 2200 de ani, nu? - Aşa e, Gogule. - Piramidele mayaşe sunt si mai recente, dar tot au 1500 de ani.

54

nr. 5/2012 | www.todaysoftmag.ro

- Ce e asta, Gogule, lecţie de istorie?! îşi pierdu Şefu’ răbdarea. Mişu vru să intervină, dar privirea lui Şefu’ îl opri. Gogu continuă, neabătut: - Construcţia Taj Mahal-ului a durat 22 de ani şi s-a finalizat în secolul 17. Turnul Eiffel a fost realizat mult mai recent şi este şi el o capodoperă arhitectonică. - Ajungem şi noi undeva cu toate aceste afirmaţii? - Se înscriu toate aceste realizări extraordinare în categoria “proiecte”? continuă neabătut Gogu. - Da, măi Gogule, da… - Şi-atunci – încheie el victorios – este că există managementul de proiect de 5000 de ani?! Mişu – care trecuse de la roşu la vişiniu – era în pragul unui infarct aşa că explodă: - Managementul de proiect – mai citeşte şi tu o carte, căpos megalitic! – a apărut în anii 1950. E suficient să te uiţi pe net, cu un minim de efort găseşti informaţia… Şi dacă nu era management de proiect, nu erau nici proiecte, recalcitrant perimat! Pe Şefu’ îl pufni râsul şi nu se stăpâni, începu să râdă tare, sănătos şi cu poftă, fără să dea semn că ar vrea să se oprească. Încet, încet, cei din biroul se molipsiră şi începură să râdă şi ei. Cei doi eroi ai noştri se uitau la el sideraţi, dar era imposibil să nu te molipseşti de râsul lui aşa că se treziră şi ei zâmbind întâi, iar apoi îşi dădură drumul şi ei la râs. Hohotind, Gogu remarcă în sinea sa: numai Şefu’ poate face comedie dintr-un scandal de proporţii. După ce se mai liniştiră puţin, Şefu’ se aşeză comod pe un birou, cu picioarele atârnând, pregătindu-se de explicaţie. Se vedea clar că îi făcea plăcere: - Măi, frumoasă temă mi-aţi ridicat la fileu, dar tot nu merita să vă agitaţi în halul ăsta. Hai să vă spun cum stă treaba cu proiectele şi managementul lor. Prin definiţie, proiectele sunt procese complexe, relativ unice pentru compania care le execută. Ţineţi minte când am lansat ultimul nostru produs, acum două luni? Realizarea şi lansarea lui a fost – pentru noi – un proiect. Acum realizăm acelaşi produs în serie iar activitatea aceasta se desfăşoară prin procese. Adică odată ce ştim cum se face, putem să executăm totul prin procese pe care le cunoaştem şi le conducem aplicând conceptele managementului operaţional.

Pentru proiecte aplicăm managementul proiectelor. Dar am acum o întrebare pentru voi: ce se întâmplă dacă eu n-am idée despre ce înseamnă proiect şi managementul proiectelor, aş putea totuşi să realizez şi să lansez un produs nou? - Păi, ce, acu’ cinci ani aveam noi habar de management de proiect – se băgă în vorbă Zoli – şi tot aveam câte un produs nou pe an. Ceilalţi aprobară în tăcere. Se pare ca “povestea” Şefului îi prinse pe toţi. Acesta continuă: - Corect. Sigur că făceam. Doar că nu ne ieşea intotdeauna exact cum ne închipuiam, costurile nu erau urmărite iar termenele se lungeau mai mereu. Lucram după metodele noastre, exact cum lucrau şi egiptenii şi chinezii la construcţiile lor. Nu erau ei pasionaţi de a face economie sau de a respecta cu stricteţe nişte termene. Exemplele tale, Gogule, sunt exemple de reuşite din istoria omenirii, dar sunt şi alte exemple, sute, mii de iniţiative care au fost începute dar niciodată finalizate, tocmai din cauza complexităţii lor. - Sagrada Familia, murmură Mişu, iar Şefu’ dădu din cap a aprobare: - Şi mai sunt multe altele. Ideea de proiect a apărut atunci când s-a încercat aplicarea unor metode noi care să asigure succesul proceselor complexe, riscante, cu investiţii considerabile. Managementul proiectelor înseamnă, de fapt, acordarea unei atenţii manageriale sporite, concretizată prin numirea unui manager de proiect şi a unei echipe care să fie responsabile de realizarea procesului complex şi unic – acum numit proiect. Voi certăreţilor, aveaţi fiecare şi dreptate şi v-aţi şi înselat amândoi: exemplele lui Gogu sunt într-adevăr proiecte, aşa cum le înţelegem noi azi, dar cei care au participat la realizarea lor nu ştiau asta şi nici n-aveau cum să aplice managementul de proiect. Şi gata pauza, hai înapoi la muncă, auzi la ei: “căpos megalitic”... Simona Bonghez, Ph.D.

simona.bonghez@confucius.ro Speaker, trainer şi consultant în managementul proiectelor, Owner al Confucius Consulting


sponsori

powered by


Tsm 5 2012 ro