vineri, mai 18, 2012

JavaScript <= Java (Web)

Cu mirare asistam la o evolutie spectaculuoasa pentru Java Script. Ce este foarte clar este ca merita sa fie urat in trecut pentru incompatibilitatile dintre browsere - si l-am evitat pe cat am putut pentru asta. Dar in ziua de azi capata din ce in ce mai multa insemnatate, mai ales odata cu HTML5 (HTML 5 nu e doar o inbunatatire adusa pentru HTML ci e un intreg runtime independend de browser care ofera aplicatiilor capabilitati nebanuite) si aplicatiile pentru mobile.

Intre timp problemele de incompatibilitate intre browsere s-au rezolvat prin aparitia framework-urilor JS precum JQuery, Dojo, etc. Acestea permit aces spre DOM indiferent de browser, apeluri de AJAX transparente fata de browser, etc. Lucrand cu un framework precum JQuery spre exemplu, ai senzatia ca e o reactualizare a paradigei "Scrie o data ruleaza oriunde", acum nu la nivel de OS ci la nivel de browser. Un API standat, un fel de SDK care e independent de browser - si cum browserul sta pe un OS - e independent si de sitem de operare.

Pe langa aceasta asemanare intre framework-uri JS si Java mai sunt si altele. Ani de zile am programat "on the server side" respectand paradigma MVC (patternul MVC) cu framework-uri precum Struts 2 (1), Spring MVC sau implementari de JSF. Supriza cea mai mare este ca se poate si fara MVC on the server side, si refresh pe toata pagina - ceea ce circula intre client si server trebuie sa fie numai datele sub forma de JSON sau XML (text). De fapt de ce nu am folosi MVC in client iar serverul sa fie accesat doar via Web Services? BlackboneJS este chiar un astfel de framework (dar nu e singurul). E un MVC la nivel de JS, frumos implementat, care aduce claritate aplicatiei tale prin folosire si care separa clar partea de View, de partea de Contoller si cea de Model. Modelul se populeaza din partea de server folosindu-se apeluri REST/AJAX transportant JSON peste HTTP - transformarea mesajelor in obiecte JS este instantanee.

Apelurile asincrone/sincrone se pot face explicit cu JQuery sau direct in Blackbone.js (doar apeluri REST, partea de server nu mai genereaza markup HTML). Securizarea pe partea de server pentru WS REST se poate face cu OAuth sau prin REST API key. La nivel de view se pot folosi template-uri statice in care se se injecteaza modelul dinamic adus de pe server. Se pot folosi si alte librarii pentru templating - precum Mustache. Submit-ul de form-uri se face la fel cu AJAX.Validari se fac on the client side cu JQuery validation plugin spre exemplu. Rutarea paginilor se poate face cu un router intern Blackbone.js sau cu unul extern: JQuery Mobile Router spre exemplu. Localizarea se poate face cu pluginuri de JQuery. Pentru sintaxa simplificata (ca un fel de Groovy pentru Java) exista CoffeeScript.

Ce lipseste in JavaScript este modularitatea. In Javascript nu exista ca in Java includere de pachete in unitatea de compilare  (fisierul .java), nu exista modificatori de acces pentru a limita vizibilitatea intre pachete. Dar si pentru acestea exista solutii: RequireJS. Si ca tabloul sa fie complet trebuie sa enumeram si framewor-uri pentru TDD: QUnit, BDD: Jasmine si altele care fac posibila testarea la nivel de JavaScript.

Nu am vorbit despre partea de mobile - am spus doar ca o mare parte din importanta pe care o capata JavaScript vine de aici (browserele integrate in mobile sunt mai avansate in ce priveste implementarea noilor standarde). Ei bine pentru mobile avem o serie de framework-uri (combinate cu CSS) specifice: Dojo Mobile, JQuery Mobile si Sencha Tauch. Aceste framework-uri aduc seturi de componente specializate pentru mobile, care se randeaza perfect pe aceste dispozitive adaptandu-se chiar din look-and feel-ul nativ - spre deosebre de o pagina standard HTML care se afiseaza (si doar atat). La fel se randeaza pe o gama larga de dispozitive adaptandu-se la un set mare de browsere. Responsive web design este un principiu care sta la baza acestor framework-uri si implica randarea automata a paginii in mod corect la dimensiunile display-ului dispozitivului.

Tot in lumea mobila, este de remarcat PhoneGap, tot o librarie Javascript care ofera transparenta fara de tipul de mobil utilizat (iOS, Android, BlackBerry, webOS, Symbian) oferind un API standard apelabil JavaScript prin care se pot accesa functii native ale dispozitivelor - spre exemplu acces la agenda de contacte din telefon, la pozitia GPS, etc. PhoneGap aduce de asemenea local storage astfel incat aplicatia poate rula in izolare urmand a sincroniza datele cu partea de server.

Unelte utile:


vineri, mai 11, 2012

A/B Tests (Lean)

Testele A/B (Split Tests) sunt foarte putin cunoscute. Pentru mine a fost o mare mirare cand am auzit de ele. Ca o recapitulare. Exista teste unitare (in izolare). Exista mocks, stubs, dummy objects. Exista teste de integrare (integration tests). Teste functionale (automate sau nu). Exista TDD. Exista BDD. Exista acoperire cu teste. Existe test case-uri. Exista teste de regresie. Exista UAT -  user acceptance tests. Exista teste de performanta si load. Exista biblioteci Java: JUnit, TestNG | JMock,Mockito | DBUnit, HTTPUnit | JBehave | JMeter, etc.

De unde vin A/B Tests? Din alta lume! Daca setul de practici enumerat mai sus vin din metodologiile agile (incluzand Scrum si XP) in care testatea unitara/automata constituia o practica de baza, A/B tests vin din lean, metodologia la baza careia sta eliminarea pierderii de timp (en. eliminate waste). Ce e WASTE intr-un proiect, orice consuma resurse si nu aduce valoare. Unul din principalele motive de pierdere de timp este implementarea de functionalitati pe care nu le foloseste nimeni. Cazul extrem este cel al unui intreg produs pe care nu il foloseste nimeni.

Cum e posibil sa creezi un produs pe care nu il foloseste nimeni? Una din cele mai comune situatii este aceea in care clientul este necunoscut - adica nu iti cunosti inca cllientii (alta posibilitate este ca cel ce reprezinta clientul in agile, sa nu il reprezinte de fapt). Te adresezi unei piete in care tu crezi ca exista o problema care merita rezolvata - care ti-ar putea  permite sa construiesti ceea ce se cheama un "self sustenable business". In acest caz nu are cine sa-ti mai spuna care din story-uri aduc valoare, nu are cine sa mai vada demo-urile, etc. Practic esti gata sa construiesti un  produs pe care nimeni nu il vrea.

Deci suntem gata sa implementam o noua functionalitate (feature) in aplicatia noastra (incremental - o adaugam unui set de functionalitati pe care le-am implementat deja - toate legate incontinuu prin integrate continua). Daca folosim Agile, reprezentantul clientului care sta on site cu tine ar trebui sa aleaga dintr-un backlog of features pe cea mai valoroasa. In stil agile se implementeaza si se livreaza clientului la demo pentru a o valida - UAT. Dar ce se intampla in cazul in care nu-ti stii clientii? Ar trebui facut acelasi lucru - ar trebui validata intr-un fel.  Iar validarea in acest caz o faci cu A/B tests - pentru ca acestea iti ofera posibilitatea de a vedea daca festure-ul tau aduce valoare sau nu clientilor.

Putem spune in acest caz ca nu avem o functionalitate de implementat ci o ipoteza de testat = experiment de facut (daca o ipoteza cade la teste se elimina functionalitatea din spate). Avem deci un experiment care are mai multe ipoteze (una din ipoteze este aplicatia ta fara noua functionalitate) - fiecare ipoteza cu un procent de  utilizatori/vizitatori care iau parte la el. Se urmaresc in site o serie de metrici care spun clar cum a influentat acel experiment experienta utilizatorilor/vizitatorilor cu aplicatia.

Deci se ia functionalitatea si se face asa (un exemplu in care se experimenteaza o a doua pagina de landing cu un alt continut:  UVP schimbat, design, etc.):
String[] firstHypothesis = { "landing_1", "50" };
String[] secondHypothesis = { "landing_2", "50" };

Hypothesis hypothesis = cohortsManager.setupVisitorsExperiment("LANDING PAGE",
getRequest().getRemoteHost(), firstHypothesis, secondHypothesis);

Se creaza pe loc experimentul daca nu exista (se salveza in baza de date cu tot cu ipoteze asociate si si cu procentele lor). Se returneaza ipoteza in care e utilizatorul curent - daca face deja parte din experiment se returneaza ipoteza pe care o avea. Daca e nou i se asociaza o ipoteza astfel incat sa se respecte procentele stabilite per experiment. Ipoteza se foloseste in redirectarea vizitatorului spre o pagina de landing sau alta.

Mergand la extrem in a compara/deosebi Agile cu Lean: story-urile se transforma in experimente (ipoteze care trebuie testate). Testele de acceptanta clientului se transforma in split (A/B) teste. Integrarea continua se tranforma in livrare continua (continous delivery) - functionalitatile implementate se expun repede in fata clientului pentru a fi validate. Scrum Board se transforma in Kanban - limitare clare de task-uri care se implementeaza la un moment dat pentru a nu creea functionalitati pe care nu le folosesc nimeni = maximixare de pierdere de timp. Deci daca se infunda pe undeva board-ul, trebuie desfundat pentru a merge mai departe - nu continuam sa il infundam. Dezvoltatorul este implicat de la un capat la altul in dezvoltarea task-ului - incluzand validarea care e o interactiune indirecta cu clientii.

Actionable Metrics