Procesul de Dezvoltare Software

Cuprins

Cuprins

Introducere

Motivatia

Definirea problemei

Cerintele Economice

Cerintele Tehnologice

Problematica Proiectului

Drepturi

Tehnologii Open Source folosite

PHP

Mysql

Apache

LAMP

VMWare

Script.aculo.us

SWFUpload

OpenID

EBay API

PayPal API

GoogleCheckout API

Integrarea componentelor

Alegerea platformei de dezvoltare

Alegerea componentelor

Dezvoltare de module (Integrarea cu MyPIXBusiness)

Softlinks

Points

Multipleupload

EBay

OpenID

Moderate

Dezvoltare interfetei grafice (Integrarea temei Mypix)

Dezvoltari ulterioare

Concluzii

Introducere

Aceasta lucrare a aparut ca o evolutie normala a modului meu de analiza asupra procesului de dezvoltare software si a mediului in care acesta se realizeaza – Internetul.

Internetul sta la baza definirii modului cum noi comunicam in acest secol, iar acesta a dus la explozia tehnologica la care asistam. El a facilitat crearea unei colectii imense de informatie si mijloace de interactiune ce nu apartine unui grup restrans de persoane sau companii, ci apartine intregii umanitati. S-au dezvoltat astfel proiecte Open Source, in jurul carora se formeaza comunitati care au ca scop evolutia, scop dezinteresat, lipsit de caracterul economic.

Comunitatiile Open Source sunt promotorul evolutiei pentru ca ofera mijlocul de transfer si acumulare de experienta profesionala asemeni comunitatiilor stiintifice, cu mentiunea ca, se organizeaza in jurul unei idei concrete, cu aplicabilitate practica.

Motivatia

Am dorit sa experimentez complexitatea metodelor de dezvoltare bazate pe componente CoTS. Multe proiecte Opem Source, daca au fost dezvoltate generic, pot fi intrebuintate ca parti integrante ale unor sisteme mai mari, sau in sisteme cu aplicabilitate intr-o alta ramura decat contextul dezvoltarii lor. Am vrut sa incerc si sa testez prin prisma experientei proprii o astfel de metoda de dezvoltare software, metoda in care problema principala este integrarea si poate mai putin dezvoltarea componentelor. O astfel de metoda atrage dupa sine si o serie intreaga de consecinte, consecinte care am dorit sa le evaluez. Am vrut sa stiu cat de pertinente sunt aceste teorii, curente de dezvoltare si cum se aplica in productie.

Dezvoltarea produsului se doreste sa dureze mai putin;

Mentenanta componentelor (rezolvarea bug-urilor sau extinderea lor) este suportata de catre comunitatea care o dezvolta;

Prin faptul ca dezvoltarea componentelor este facuta de catre o comunitate (una sau mai multe echipe) matura (dezvoltata pe o perioda de timp relativ mare), ne asiguram de calitatatea implementarii, alegerea unor algoritmi optimi etc, prin faptul ca asupra respectivei componente s-a alocat o perioada de timp indelungata si a fost supusa unor numeroase analize si dezbateri;

Standardele Open ofera componentelor o interfata comuna, o metoda de a interactiona, astfel s-a dorit ca orice comoponenta sa fie usor schimbata in cazul in care cerintele se schimba, sau contextul sistemului software.

Am fost constient ca pentru alegerea unei componente trebuie alocat timp. Componenta va trebui analizata din perspectiva mai multor factori: usurinta in integrarea sa, sa aibe o comunitate dezvoltata (receptiva si operativa la raportarea bug-urilor, cu utilizatori dornica sa se ajute reciproc), o documentatie clara si detaliata,sa rezolve problema in termenii definiti (aici incluzand si factori ca: fiabillitate,disponibiliatae etc)

Am dorit sa evaluez aceste consecinte prin prisma experientei proprii, sa imi formez o perspectiva asupra dezvoltarii software bazate pe integrare si mentenanta.

In cadrul comunitatilor Open Source se gasesc oameni cu o bogata experienta in dezvoltarea de sisteme informatice, precum si proiecte de o maturitate deplina. Aceasta a dus la dorinta mea de a-mi imbunatatii cunostintele referitoare la dezvoltarea de sisteme software colaborand cu acesti oameni. Materializarea cunostiintelor tehnice teoretice acumulte in anii studiu trebuia astfel sa se realizeze in productie, in lumea reala, prin acest proiect.

Un alt scop propus a fost acela de a invata de la persoane cu  experienta in domeniul dezvoltarii software. De a contribui, cu experienta mea, la evolutia componentelor ce le voi folosi in cadrul sistemului. Iar toate aceasta, din mai multe motive.

ca si arhitect, sa invat cum alte echipe trec prin procesul de design.

ca si testor am incercat sa raportez probleme existente in componente.

ca si dezvoltator am incercat sa repar eventuale bug-uri, astfel, respectivul produs sa devina mai bun din punct de vedere calitativ, sa obtina o notorietate mai mare.

sa pot face o comparartie intre diferite echipe referitor la modul cum acestea se organizeaza si comunica. (multe echipe din comunitatiile OS sunt formate din indivizi ce sunt raspinditi pe o arie geografica deosebit de mare – modul de colaborare si dezvoltare fiind complet diferit fata de o companie cu profil software, unde toti dezvoltatorii se afla la un loc). In functie de aceasta am putut lua decizii referitoare la modul cum proiectul va evolua, speranta lui de viata, dar si existenta suportului (a mentenantei) din partea comunitatii.

sa ofer si altora suportul meu in repararea bug-urilor, sau pentru documentatie sau indrumari.

pentru a ma asigura ca respectiva componenta evolueaza intr-o directie ce convine sistemului meu.

pentru ca procesul de dezvoltare software nu poate fi facut individual, ci este un proces colaborativ.

Un sistem software ce are aplicabilitate, este cu atat mai valoros. Provocarea mea a fost dezvoltarea unei applicatii web, folosita in comertul online,  folosind unelte, standarde si componente Open Source. O aplicatie care nu si-ar fi avut radaciniile in realitatea economica ar fi avut doar un scop academic. O aplicatie ce va fi folosita de zeci de mii de utilizatori reprezinta o adevarata provocare inginereasca.

Am folosit ca si pretext pentru dezvoltarea mea ca si inginer software, implementarea unei aplicatii de partajare poze in vederea comercializarii accesului la acestea. Concluziile obtinute din dezvoltarea acestui proiect sunt necesare pentru a avea o perspectiva realista asupra domeniului Stiintei Calculatoarelor, referitoare la dezvoltarea sistemelor informatice. Am incercat sa combin astfel scopul economic al proiectului meu cu ideologia si practicile open source.

Definirea problemei

Acest proiect a aparut din necesitatea mai multor magazine online de a-si automatiza procesele de procurare, gestiune, hosting si de a-si amortizara costurile referitor la producerea pozelor. MyPIXbusiness (http://www.mypixbusiness.com) este numele proiectul care a luat nastere.

Cerintele Economice

Fiecare magazin de pe eBay pune inspre vanzare mai multe produse. Calitatea prezentarii unui produs determina si vendabilitatea produslui respectiv. Astfel, in primul rand un produs trebuie sa se prezinte cu una sau mai multe poze, cu o cat mai buna calitate. Cu cat poza este mai realista si ofera clientului o mai buna perspectiva asupra prodului respectiv, cu atat produsul se va vinde mai bine. Astfel, cerinta principala a fost ca aplicatia sa ofere moduri de a vizualiza poze la o rezolutie cat mai buna.

EBay ofera hosting-ul pozelor, dar la un pret pe care aceste magazine il considera ridicat. In plus, rezolutia la care aceste poze sunt afisate este limitata. eBay nu ofera gestiunea pozelor decat in cadrul produsului oferit spre vanzare. S-a definit astfel nevoia ca applicatia sa permita gestionarea pozelor:

sa pastreze pozele centralizat si localizat

accesul la poze sa fie cat mai rapid

sa se poata face upload de poze prin diferite modalitati: http (fisiere sau directoare de poze), ftp, import automat din eBay

sa se poata organiza ca o strructura de fisiere si directoare

sa se poata crea categorii de poze

sa se poata defini cuvinte chei

sa ofere multiple modalitati de cautare a pozelor.

sa gestioneze detalii referitoare la rezolutie, descriere, note.

Costul pentru crearea pozei fiecarui produs este suportat de catre fiecare magazin in parte. De cele mai multe ori, exista numeroase magazine care vand acelasi produs. Astfel producerea unor poze a aceluiasi produs reprezinta un cost pentru fiecare magazin. Costul implica angajarea unui fotograf, angajarea unui designer care sa prelucreze electronic poza (inlaturarea fundalului sau crearea unuia special in functie de produs, retusarea defectelor, paletei culoriilor etc). Acest cost ajungand pana la zeci (x10$) de dolari. Participand cat mai multe magazine la partajarea accesului la poze, se doreste reducerea costurilor. Cumpararea de catre un magazin a astfel de poze reprezentand un cost considerabil mai mic decat producerea lor.

S-a dorit ca aplicatia sa ofere o modalicate prin care artisti (persoane care se ofereau sa produca astfel de poze) sa isi poata pune inspre vanzare pozele. De multe ori, artistii puteau fi reprezentati de insasi magazinele. Deoarece un produs se afla pe rafturi o perioada limitata, nu exista necesitatea detinerii pozei efective, ci doar un acces temporar, pentru perioda in care respectivul produs se afla inspre vanzare. Cerinta a fost definita ca un mod prin care un utlizator sa poata share-ui poze pentru o perioada definita, cu un pret in functie de rezolutie, si la un pret definit de catre producatorul acesteia. Astfel aplicatia trebuie sa puna la dispozitie un mod prin care un utilizator sa poate defini un pachet de preturi in functie de diferite criterii.

Achitarea costurilor pozelor sa fie facute prin mijloace traditionale de plata online: Google Checkout sau PayPal. Aplicatia trebuie sa ofere si un istoric si rapoarte referitoare la operatiile financiare facute.

Pozele gestionate de catre aplicatie trebuie sa fie usor accesibile. Pagina de prezentare a produsului din cadrul aplicatie web eBay va trebui sa contina o legatura catre pozele din cadrul aplicatiei MyPIXBusiness. Aceste poze vor trebui sa se incarce rapid in brwserele utilizatorilor clienti. Deoarece aplicatia este destinata unei piete si utilizatori deja existenti, cei ai site-ului eBay, aceastaa trebuie gandita a se adresa unui numar foarte mare de utilizatori, de ordinul milioanelor (x106). MyPIXBusiness va trebui sa gaseasca si o solutie legata de utilizarea aplicatie in cazuri de trafic extrem.

Deoarece aplicatia este destinata unui numar foarte mare de utilizatori, a aparut necesitatea controlului si verificarii continutului pozelor. S-a impus ca si cerinta verficarea si excluderii pozelor cu continut neadecvat sau care nu corespundeau drepturilor de autor.

Aplicatia trebuie sa fie dezvoltata pana intr-o stare Beta si sa ofere functionallitatea de baza. Scopul este prezentarea sa intr-o conferinta eBay la finele anului 2008. Dezvoltarea sa trebuie sa se limiteze in bugetul prevazut.

Cerintele Tehnologice

Cerinta este dezvoltarea unei aplicatiei web care sa se orienteze spre folosirea de componente Open Source. Nu este de dorit dezvoltarea unor componente proprii pentru a se putea limita in bugetul prevazut.

Aplicatia trebuie sa fie capabila a accepta multe cereri din partea multor utilizatori. Aplicatia trebuie sa suporte internationalizarea, respectiv interfata grafica sa se adreseze utilizatorilor ce folosesc diferite limbi. Trebuie sa adopte un design pritenos. Software-ul trebuie sa respecte standardele de siguranta si protectie a informatiilor personale ale utilizatorilor. Acesea toate intr-un design prietenos.

Dezvoltarea trebuie sa urmeze livrari iterative, fiecare etapa reprezentand o rafinare a cerintelor. Trebuie sa exsite o platforma separata de dezvoltare, alta de testare si alta de productie. Modalitatea prin care functionalitatiile sau repararea eroriilor sunt transferante din dezvoltare in productie trebuie sa fie automatizata si sa nu implice inutilizarea serviciului pentru o perioada de timp indelungata.

Testarea trebuie sa fie automata. Testele se adreseaza corectitudinii functionalitatilor, innta si protectie a informatiilor personale ale utilizatorilor. Acesea toate intr-un design prietenos.

Dezvoltarea trebuie sa urmeze livrari iterative, fiecare etapa reprezentand o rafinare a cerintelor. Trebuie sa exsite o platforma separata de dezvoltare, alta de testare si alta de productie. Modalitatea prin care functionalitatiile sau repararea eroriilor sunt transferante din dezvoltare in productie trebuie sa fie automatizata si sa nu implice inutilizarea serviciului pentru o perioada de timp indelungata.

Testarea trebuie sa fie automata. Testele se adreseaza corectitudinii functionalitatilor, incadrarii in parametrii de viteza, disponibilitate si fiabilitate care sa nu defavorizeze utilitatea aplicatiei. Testele vor tine cont de diferitele distributii de navigatoare web (browser-e), si de configuratiile acestora. Testele vor trebui sa valideze faptul ca aplicatia este conforma cu standardele W3C (XHTML, CSS etc).

Alegerea componentelor Open Source trebuie sa tina cont de facilitatea interschimbarii acestora precum si de faptul ca acestea trebuie sa respecte standarde Open referitoare la schimbul de informatii intre ele. Alegerea componentelor trebuie sa tina cont si de licenta fiecaruia. Se va cere o consultanta juridica inainte de stabilirea utilizarii unei anumite componente.

Aplicatia web trebuie sa ruleze pe o platforma Linux, pentru a minimiza costurile, a maximiza eficienta (utilizarea proceselor si a memoriei intr-un mod eficient, a nu exista o interfata care sa consume resurse),  a fi astfel proiectata pentru eventualitatea dezvoltarii in componenta sistemului de operare a unor eventuale optimizari.

Problematica Proiectului

Doresc sa evaluez implicatiile referitoare la dezvoltarea unei aplicatii bazate pe standarde Open Source. Doresc sa propun si sa implementez solutiile concrete de integrare pentru construirea unei aplicatii web cu cerinte bine definite. Solutiile implementate referitoare la integrare pot provoca dezvoltarea de componente proprii. Solutiile se vor referi la componente specifice si concrete si nu implica un grad de generalitate referitoare la integrare.

Doresc sa contribui la evolutia fiecarei componente utilizate si la dezvoltarea comunitatii din jurul componentei folosite. Daca aceste echipe sunt la distante mari, asa cum se intampla deseori in dezvoltarea de produse open source atunci apar diverse probleme: diferente de fus orar, program incarcat pe una din parti, diferente culturale si/sau lingvistice, probleme legate de usurinta de exprimare. Doresc sa analizez viabilitatea participarii intr-o comunitate open source si a problemelor ce pot apare prin prisma proprie-i experiente.

Drepturi

Drepturile de autor legate de sistemul software MyPIXBusiness apartin in exclusivitate firmei Insight Soft (http://www.insight-soft.com) precum si magazinului Rover Store (http://stores.ebay.com/Rover-Store-Home). Numele si denumirea marcilor nu au fost folosite in scop publicitar.

Tehnologii Open Source folosite

PHP

Pentru realizarea acestei aplicatii s-a optat pentru limbajul PHP. PHP (acronimul recursiv pentru “PHP: Hypertext Preprocessor") este un limbaj Open Source special

proiectat pentru dezvoltarea de aplicatii web care poate fi incastrat in HTML.

Limbajul PHP spre deosebire de alte limbaje precum Perl sau C este mult mai usor de inglobat intr-o interfata web, fiind necesare scrierea doar a catorva linii si nu a unui program intreg pentru a putea procesa sau afisa anumite informatii. Diferenta intre PHP si JavaScript este ca in cazul primului script-urile sunt executate pe server, clientul receptionand doar rezultatele care provin din rularea scriptului. Acest lucru poate constitui si un mic dezavataj deoarece pentru a putea rula aplicatiile realizate in PHP este nevoie sa avem instalat un server pe care sa putem rula aplicatiile, ca de exemplu serverul Apache.

Un lucru care a facut ca limbajul PHP sa se extinda intr-un mod spectaculos este faptul ca este extrem de usor de utilizat de orice programator cu o minima experienta in programare, dar in acelasi timp ofera foarte multe functii avansate pentru programatorii experimentati.

Desi PHP este facut pentru scripturi server-side, deci putem realiza cu ajutorul sau tot ceea ce poate face un program CGI (colectare de date, generare dinamica a paginilor, trimiterea si primirea de cookies), putem face si scripturi linie de comanda (scripturi ce nu necesita pentru rulare sa avem instalat un server sau un browser) sau aplicatii desktop (desi nu este cel mai nimerit limbaj pentru asa ceva).

PHP poate fi utilizat pe toate sistemele importante de operare precum Linux, multe variante de Unix (inclusiv HP-UX, Solaris si OpenBSD), Microsoft Windows, Mac OS X, RISC OS si probabil si altele. PHP are deasemenea suport pentru majoritatea web serverelor de astazi. Includem aici Apache, Microsoft Internet Information Server, Personal Web Server, Netscape and iPlanet servers, Oreilly Website Pro server, Caudium, Xitami, OmniHTTPd, si multe altele.

Pentru multe dintre ele PHP are un modul special pentru celelalte care suporta standardul CGI, poate lucra ca un procesor CGI. Asadar folosind PHP ai posibilitatea de a alege sistemul de operare si web serverul pe care il doresti fara a fi limitat in aceasta alegere.

Posibilitatile PHP-ului in ceea ce priveste afisarea nu se limiteaza doar la iesiri standard HTML, putem avea ca iesiri si imagini, fisiere PDF, sau chiar filme facute in Flash.

Una dintre caracteristicile cele mai importante ale PHP-ului este faptul ca suporta un numar foarte mare de baze de date.

PHP suporta deasemenea comunicarea cu diverse protocoale cum ar fi: LDAP, IMAP, SNMP, NNTP, POP3, HTTP, COM (sub Windows).

Mysql

Pentru partea de baze de date s-a ales MySQL. Acest sistem de baze de date are o serie de caracteristici si calitati care il fac foarte atractiv.

Prima dintre ele este viteza. MySQL este unul dintre cele mai rapide sisteme de baze de date, in opinia multor programatori chiar cel mai rapid.

Usurinta in utilizare este si ea importanta. . MySQL este un sistem de baze de date cu performante ridicate, dar relativ simplu, a carui configurare si administrare sunt mult mai simple decât in cazul sistemelor mai mari.

Un alt factor important este costul. MySQL este gratuit pentru majoritatea utilizarilor interne. MySQL ofera support pentru limbajele de interogare, astfel este capabil sa inteleaga SQL (Structured Query Language – limbaj de interogare structurat), limbajul preferat al tuturor sistemelor moderne de baze de date. De asemenea, puteti avea acces la MySQL folosind aplicatii care accepta ODBC (Open Database Connectivity), un protocol de comunicatie cu bazele de date creat de Microsoft.

La serverul MySQL se pot conecta mai multi clienti simultan. Clientii pot folosi mai multe baze de date simultan. Se poate obtine acces la MySQL in mod interactiv, folosind numeroase interfete care permit sa introducem interogari si sa vizualizam rezultate: clienti in linie de comanda, browsere Web sau clienti X Window System. De asemenea, este disponibila o varietate de interfete de programare pentru limbaje precum C, Perl, Java, PHP si Python. Astfel, avem optiunea de a folosi programe client preambalate sau de a scrie propriile programe client pentru aplicatii personalizate.

MySQL sta bine si la capitolul conectivitate si securitate. Astfel el poate fi folosit integral in retele, iar bazele de date sunt accesibile de oriunde din Internet, deci putem partaja datele cu oricine, oriunde. Dar MySQL are controlul accesului, astfel incât persoanele care nu au dreptul sa citeasca datele nu vor avea aceasta posibilitate.

Importanta este si portabilitatea de care dispune MySQL. El poate sa ruleaza pe numeroase varietati de UNIX, precum si pe alte sisteme non-UNIX, ca Windows si OS/2. MySQL ruleaza pe echipamente de la calculatoare de birou la servere cu performante ridicate.

Deoarece distributia lui este libera, MySQL este usor de obtinut; pentru aceasta, trebuie doar sa folosim browserul de Web. Daca nu se intelege functionarea unei componente sau dorim sa vedem cum este implementat un anumit algoritm, putem procura codul sursa si il putem examina. Deasemenea daca modul de functionare al unei componente nu este satisfacator poate fi schimbat.

Apache

Având in vedere ca scripturile PHP au nevoie de un server de web pentru a putea rula, a trebuit sa luam in calcul si alegerea unui astfel de server.

Varianta pentru care s-a optat este serverul Apache. Acest server este folosit de cea mai mare parte a site-urilor de pe Internet. Astfel aproximativ 60% din site-uri folosesc ca si server web serverul Apache. Desi popularitatea sa nu poate sa-i evidentieze nemijlocit superioritatea, ea arata ca foarte multe site-uri de success, cu trafic intens, au fost construite cu Apache. Asta reprezinta un urias vot de incredere in acest program. De asemenea, inseamna ca Apache este testat exhaustiv. Securitatea pe care o ofera, fiabilitatea si nivelul general de performanta sunt demonstrate, documentate si indubitabile.

Serverul Apache s-a impus ca prima solutie pe piata serverelor web prin calitatile sale indiscutabile. Astfel cele mai importante facilitati pe care le prezinta acest server sunt:

• Respectarea standardelor

• Scalabilitatea

• Obiectele partajate dinamic

• Adaptabilitatea

• Programabilitatea

• Posibilitatea folosirii ca server proxy de accelerare

• Securitatea

• Facilitati pentru bazele de date

• Compatibilitatea cu SSL

Apache beneficiaza de o asistenta de neegalat din partea unui grup enorm de persoane. Unii sunt programatori; majoritatea sunt simpli utilizatori si administratori. Pentru un sistem software atât de folosit ca Apache, indiferent de natura problemelor, este foarte probabil sa existe o persoana undeva care a intâlnit aceeasi problema si care poate oferi indicatii pentru rezolvarea ei. Desi poate parea logic sa se presupuna ca asistenta pentru programele gratuite este in mod necesar inferioara celei oferite de producatorii programelor comerciale acest lucru nu este intotdeauna adevarat.

LAMP

Asadar folosirea limbajului PHP pentru realizarea functiilor aplicatiei, având in spate sistemul de baze de date MySQL si rulând pe un server de web Apache este una dintre cele mai bune optiuni pe care le avem la dispozitie pentru a realiza o aplicatie web. Acest lucru se datoreaza in special rapiditatii, fiabilitatii si gratuitatii de care se bucura cele trei solutii.

Denumirea de LAMP este un acronim pentru Linux Apache MySQL PHP/Perl/Python, o combinatie de: sistem de operare, server web, server de baze de date ( mysql ) si interpretor ( php/perl/python ). In forumurile de discutii, aceasta combinatie e apreciata ca fiind cea mai sigura, eficienta, cost redus si usor de invatat.

Pentru versiunea de Linux am opatat in favorea Ubuntu, sistem bazat pe Debian, deoarece combina usurinta folosirii unui apt-get cu un set de utilitare proprii si stabilitatea impecabila, bucuranduse de suport din partea comunitatii cat si de suport profesional.

Comunitatea Ubuntu este construita pe baza ideilor expuse in Manifestul Ubuntu: acest software trebuie sa fie disponibil gratuit (fara a se percepe nici o taxa), instrumentele software trebuie sa fie folosite de oameni in limbile lor materne si in ciuda oricaror invaliditati, iar acei oameni ar trebui sa aiba libertatea sa adapteze si sa modifice software-ul pe care il detin in orice mod considera ei ca li se potriveste mai mult.

Semnificatia cuvantului „Ubuntu” provine de la un cuvânt vechi african, insemnând „umanitate catre ceilalti (semenii nostri)”. Ubuntu se poate traduce, de asemenea, si prin „eu sunt ceea ce sunt datorita a ceea ce suntem noi toti”. Distributia Ubuntu Linux aduce spiritul Ubuntu in lumea software-ului.

Ubuntu este potrivit pentru folosirea pe sistemele desktop cât si cele server. Versiunea curenta de Ubuntu suporta arhitecturile Intel x86 (PC IBM-compatibil), AMD64 (Hammer) si PowerPC (Apple iBook si Powerbook, G4 si G5).

Ubuntu include peste 16 000 pachete software, dar cele necesare pentru instalarea de baza necesita mai putin de un CD. Ubuntu incepe cu kernel-ul Linux versiunea 2.6 si Gnome 2.16, si acopera orice aplicatie standard desktop incepând de la un procesor de texte si pâna la aplicatii pentru calcul tabelar sau aplicatii pentru accesarea Internet-ului, software pentru server web, email, limbaje de programare si utilitare precum si câteva jocuri.

Am optat pentru versiunea server pentru a obtine tot ce aveam nevoie dar nimic din ce nu ar trebuii sa apara. Astfel editia pentru servere, construita pe fundatia solida Debian, cunoscuta pentru instalarile de server robuste, detine o mostenire extinsa pentru performanta sigura si o evolutie previzibila.

Pe masura ce activitatea creste, la fel va creste si reteaua. Tot mai multe aplicatii vor trebui integrate si de tot mai multe servere va fi nevoie. Editia pentru servere Ubuntu ofera configuratii de baza comune predefinite, astfel simplifica desfasurarea proceselor pe serverul Linux. Se ofera o platforma bine integrata ce permite simplu desfasurarea activitatilor pentru un alt server folosind oricare dintre serviciile de baza: posta electronica, web, DNS, servere de fisiere sau pentru baze de date.

Unul dintre atuurile mostenite de la Debian este securitatea. Editia pentru server nu lasa porturi deschise dupa instalare oferind doar aplicatiile strict necesare pentru a concepe un server protejat.

Aceasta platforma economiseste costul total de mentenanta prin procesul automat de instalare LAMP. In aproximativ 15 minute, timp in care se instaleaza editia pentru servere Ubuntu, se obtine propriul LAMP (Linux, Apache, MySQL si PHP) server pus si gata de lucru. Aceasta posibilitate, exclusiv pentru editia pentru server Ubuntu, este disponibila la momentul instalarii.

Optând pentru optiunea LAMP, se va elimina nevoie de a integra si a configura aparte fiecare componenta a sa, un proces ce poate dura ore si poate duce la necesitatea interventiei unui specialist in domeniul configurarii si instalarii de aplicatii din domeniu. In schimb, se va obtine securitate ridicata, timp de instalare redus, si diminuarea riscului de a gresi configurarile, totul explicând plata redusa pentru mentenanta.

Editia pentru servere Ubuntu ofera de asemenea si suportul pentru statiile mai slabe folosind LTSP (Linux Terminal Server Project). LTSP-5, cea mai recenta realizare a proiectului, ofera usurinta instalarii si intretinerii. Toate datele sunt stocate pe server, astfel vor diminua costurile pentru actualizarea individuala a statiilor si obtinerea ajutorului. Beneficiile notabile ale acestui proiect ce ofera suport pentru statiile mai slabe sunt:

Organizare simplificata: control asupra tuturor clientilor de la o singura statie. Instalare, configurare si modificari de setari pentru aplicatiile noi, sau de ce nu actualizari de versiuni ale aplicatiilor pe server, si ca rezultat toti clientii conectati beneficiaza de aceste actualizari. Va fi nevoie doar de o singura arhivare a datelor pentru toti clientii.

Instalare si configurare absolut automata: instalarea acestui sistem pentru statiile mai slabe este la fel de simpla precum si instalarea versiunii pentru orice alt calculator, iar odata finalizata, noii clienti pot fi adaugati fara a reconfigura serverul.

Consum (TCO) redus folosind resursele partajate: statiile obisnuite consumatoare de energie de regula se afla in stare de veghe astfel cheltuind din resursele disponibile si din bugetul afacerii. Având un singur server cu un consum la fel de mare de energie si statii mai slabe, se va obtine aceeasi performanta economisind

Recuperare rapida dupa o prabusire: Daca un sistem client pica, simplu, doar se comuta la un alt client si se continua munca. Fara configurari, iar toate setarile si fisierele utilizatorilor ramân intacte.

Periferice atasate local: Utilizatorii pot atasa imprimante, camere, playere, stick-uri pe USB si alte periferice la statia client.

Unul din motivele alegerii distributiiei Ubuntu a fost si popularitatea sa. Statisticile Google Trends indica o crestere a numarului de cautari dupa „Ubuntu” fata de alte distributii Linux. De asemenea, DistroWatch indica Ubuntu ca fiind cea mai populara distributie Linux in ultimii doi ani. In mai 2006 Mark Shuttleworth a sustinut ca mai mult de sase milioane de discuri cu versiunea 5.10 au fost distribuite la nivel mondial. Situl LinuxQuestions.org a ales Ubuntu drept distributia anului 2006. Parlamentul francez a hotarât ca toate calculatoarele folosite in institutie sa migreze pe Ubuntu Linux.

VMWare

Nu se poate dezvolta o aplicatie serioasa fara a desfasura testele pe cat mai multe platforme cu putinta, indiferent daca este vorba de testarea cross-browser a unui site web sau a unei aplicatii cross-platform, care trebuie sa mearga si pe Windows si pe Linux, pe cat mai multe versiuni ale ambelor. Masinile virtuale sunt unelete indispensabile in desfasurarea acestor teste, deoarece iti permit sa faci oricate greseli pana iese bine, fara a pune in pericol o instalare reala a unui calculator.

Hardware-ul puternicelor calculatoare actuale a fost initial proiectat pentru a rula un singur sistem de operare si o singura aplicatie, dar virtualizarea depaseste aceasta granita, facand posibila rularea mai multor sisteme de operare si a mai multor aplicatii in acelasi timp si pe acelasi calculator, crescand astfel utilitatea si flexibilitatea harware-ului.

In esenta, virtualizarea permite transormarea harware-ului in software. Prin folosirea unui software cur ar fi VMware ESX se poate transforma (virtualiza) resursele hardware ale unui calculator x86 (CPU-ul, RAM-ul, hard disk-ul si controlerul de retea) pentru a crea o masina virtuala complet functionala, care poate rula propriul sau sitem de operare si propriile aplicatie asemeni unui calculator „real”.

Mai multe masini virtuale pot imparti resursele harware fara sa interfereze intre ele astfel incat se pot rula in siguranta diverse sisteme de operare si aplicatii in acelasi timp pe acelasi calculator.

Abordarea VMware a conceptului de virtualizare este a insera un strat software direct pe harware-ul calculatorului sau pe sitemul de operare gazda.Acest start creaza masini virtuale si contine un monitor al masinii (supervizor) care aloca dinamic si transparent resurse harware astfel incat mai multe sisteme de operare pot rula concurent pe un singur calculator fizic.

Acest lucru este si mai usor incepand de la versiunea 5.0 a VMware, deoarece pune la dispozitie Snapshot-uri si branch-uri ale sistemului de operare, intre care se poate schimba in cateva zeci de secunde. Totul cu o folosire extrem de eficienta a spatiului ocupat de imaginea virtuala, fiind stocate doar diferentele intre imagini.

Pentru a instala Ubuntu Server am folosit VMware Player, produs gratuit care ofera posibilitatea de a rula, evalua si partaja aplicati intr-o masina virtuala. Ideal pentru realizarea testelor, VMware Player reprezinta o unelata mai simpla prin care oricine poate rula o masina virtuala (dar fara a avea posibilitatea editarii configuratiei hardware si fara a putea face snapshot-uri) pe calculatorul propriu.

Script.aculo.us

Script.aculo.us este un framework Java Script, foarte popular, disponibil sub licenta MIT si avindu-l ca autor pe Thomas Fuchs. Sint foarte folosite de la Scriptaculous diversele efecte, drag'n'drop in browser si controalele lor. Acesta compilatie de biblioteci Java Script Open Source ofera foarte multa satisfactie celor care interactioneaza cu acest pachet minunat (fie ca e vorba despre cel care dezvolta interfata sau despre cel care o foloseste), deoarece este foarte usor de implementat si arata foarte bine. Asadar pachetul contine animatii structurate pe framework, utilitare de tip DOM (Document Object Model), drag and drop si putin ajax.

Pe site-ul celor de la script.aculo.us puteti testa engine-ul animatiilor sau puteti arunca o privire la varianta cosului de cumparaturi bazat pe drag and drop, tot aici puteti juca si puzzle, un exemplu de implementare a librariei de sortare. O functie foarte utila este ajax autocompletion. Acestea sunt doar cateva dintre script-urile de care dispuneti dupa ce v-ati instalat pachetul script.aculo.us, script-uri ale caror domenii de activitate fiind foarte vaste.

Primul pas in folosirea pachetului script.aculo.us este descarcarea ultimei versiuni de pe pagina oficiala si instalarea ei. Astefel veti descarca o arhiva zip care contine fisiere Java Script alaturi de diferite fisiere HTML pentru testare si demonstratii. Fisierele cu sursele Java Script sunt cele mai importante si sunt prezentate in continuare:

lib\prototype.js: Fisierul sursa al framework-ului JavaScript prototype.

scr\builder.js: Permite cu usurinta crearea dinamica de elementelor DOM .

src\controls.js: Include componentele principale pentru lucrul cu elemente de control date.

src\dragdrop.js: Furnizeaza codul pentru utilizarea de elemente de control date cu functii de drag-and-drop.

src\effects.js: Libraria de efecte visuale include toate functiile necesare adaugarii de animatii Java Script avansate la aplicatiile web.

src\scriptaculous.js: Libraria de baza pentru folosirea framework-ului scriptaculous.

src\slider.js: Furnizeaza codul necasr folosirii elentului slider.

Aceste fisiere pot fi amplasate oriunde pe serverul Web, dar folosind locatia lor implicita va usura lucrul cu exemplele. Libraria completa (toate fisierele din lista) ocupa aproximativ 150KB. Insa trebuie precizat faptul ca nu toate fisierele sunt vitale si pachetul va fi functional si daca nu toate fisierele de mai sus vor fi incarcate pe host. Cele doua fisiere nucleu prototype.js si scriptaculous.js insumeaza 50KB. Astfel toate celelalte combinatii se vor incadra intre 50 si 150KB in functie de fisierele folosite.

Implicit, scriptaculous.js incarca toate celelalte fisiere Java Script neceasare pentru efecte, drag-and-drop, slider si celelalte elemente scriptaculous. Se pot limita scripturile aditionale care se incarca prin specificarea lor intr-o lista in comanda de incarcare. Astefel pentru a incarca toate modulele se poate folosi codul urmator:

<script src="javascripts/prototype.js" type="text/javascript"></script>

<script src="javascripts/scriptaculous.js" type="text/javascript"></script>

Sau pentru a alege care module sa fie incarcate se poate folosi sintaxa urmatoare, optiunile disponibile fiind: builder, effects, dragdrop, controls si slider. Dar trebuie atrasa atentia asupra faptului ca unele module nu pot functia corespunzator fara unele din cele de mai sus.

<script src="scriptaculous.js?load=effects,dragdrop" type="text/javascript">

</script>

Numeroasele functii disponibile pot fi accesate prin taguri HTML:

<script type="text/javascript" language="javascript">

// <![CDATA[

Effect.Appear(\\'element_id\\');

// ]]>

</script>

Framework-ul Script.aculo.us ofera o foarte buna documentatie si numeroase exemple. Aceste exemple sunt incluse si in arhiva care contine pachetul scriptaculous. In plus pe site-ul lor pot fi gasite demostratii ale functiilor care se regasesc in pachet.

SWFUpload

SWFUpload este o librarie JavaScript/Flash, de mici dimensiuni, care imbina avantajele ambelor medii. Pachetul imbina remarcabilele capacitati de upload ale tehnologiei Flash cu accesibilitatea si usurinta in utilizare a linbajului HTML/CSS. Astfel acesta ruleaza pe partea de client si ofera functionalitati de upload care le depasesc pe cele standard cand se foloseste <input type="file" />.

Principalele caracteristici pe care SWFUpload le ofera sunt urmatoarele:

Upload-ul simultan al mai multor fisiere folosind secetia cu ctrl/shift in fereastra de dialog

Apeluri Javascript pentru toate evenimentele

Obtinerea de informatii referitoare la fisier inaintea de inceperea upload-ului

Se poate definii stilul elementelor folosind XHTML si css

Afisarea de informatii pe parcursul procesului de upload folosind HTML

Reincarcarile de pagini nu sunt necesare

Functioneaza pe toate platformele si cu toate browser-ele care ofera suport Flash

Daca suportul pentru Flash sau javascript nu este diponibil, se ofera automat un form de upload HTML standard

Controlul dimensiunii fisierului inainte de inceperea upload-ului

Afisarea in fereastra de dialog doar a tipurilor de fisier dorite

Liste de upload si optiunea de a inlatura/adauga fisiere in lista inainte de upload.

SWFUpload este diferit fata de alte unelte de upload care se bazeaza pe Flash prin filosofia care sta in spatele arhitecturii. SWFUpload ofera dezvoltatorilor controlul prin faptul ca interfata cu utilizatorul este lasata in browser. Dezvoltatorii pot folosii HTML, CSS si JavaScript pentru a modifica interfata grafica de upload astfel incat aceasta sa indeplineasca nevoile si stilul site-ului in care este integrata. Starea procesului de upload este improspatata prin intermediul unui set de evenimente simple JavaScript. Programatorul foloseste aceste evenimente pentru a reimprospata pagina dupa nevoile aplicatiei web.

SWFUpload functioneaza in felul urmator: permite utilizatorilor sa selecteze unul sau mai multe fisiere pentru upload si apoi, in loc sa trimta (submit) un formular (form), fisierele sunt trimise asincron (in fundal) in timp ce SWFUpload continua sa trimita evenimente care permit paginii sa fie actualizata dinamic cu informatii privind starea si progresul procesului de upload. Astfel utilizatorul este in permanenta informat, diparand momentele cand pagina se blocheza.

API-ul puternic al SWFUpload-ului ofera posibilitatea de a informa utilizatorii pe tot parcusul upload-ului de fisiere. Totoadata aceasta arhitectura permite dezvoltatorului sa integreze procesul de upload cu design-ul site-ului, nefortand programatorul sa integreze o intefata grafica precompilata.

SWFUpload este foarte familiar celor cu experienta in dezvoltarea aplicatilor cu AJAX.

SWFUpload ofera facilitatea de a verifica tipul si dimensiunea fisierelor inainte ca acestea sa fie incarcate. Astfel utilizatorii economisesc timp si sunt scutiti de frustrarile care apar odata cu repingerea unui fisier care a necesitat un timp indelungat de incarcare.

Derularea operatiilor SWFUpload este urmatoarea:

1) SWFUpload este initializat in pagina si in mod dinamic este incarcata componenta Flash Upload ascunsa.

2) Evenimentul swfUploadLoaded este declansat pentru a notifica pagina ca SWFUpload este pregatit sa accepte cereri de upload.

3) Utilizatorul apasa butonul sau link-ul care face legatura cu metoda selectFile, metoda ce deschide fereastra de dialog pentru selectia fisierelor.

4) SWFUpload declanseaza cate un eveniment pentru fiecare fisier selectat. Pagina va putea sa afiseze informatiile necesare despre upload in modul in care programatorul considera ca este nevoie.

5) Procesul de incarcare al fisierelor poate fi declansat automat sau de un buton sau link catre metoda startUpload.

6) SWFUpload incepe incarcarea fiecarui fisier, in fundal unul cate unul, declansand evenimente referitoare la progesul, erorile sau finalizarea upload-ului. Pagine informeaza utilizatorul cu privire la starea upload-urilor.

7) Serverul receptioneza pe rand fiecare fisier incarcat. Din punctul lui de vedere fiecare fisier incarcat apara ca si cum ar fi provenit de la o pagina standard de upload. Pe server nu mai trebuie instalat sau configurat nimic in plus pentru a putea folosi SWFUpload.

8) In final toate fisierle au fost incarcate complet, pagina nu a fost reincarcata si utilizatorul a stiut exact ce s-a intamplat cu fiserele pe tot parcursul incarcarii.

OpenID

OpenID este un sistem descentralizat de autentificare lansat in 2006, care permite utilizatorilor sa se autentifice in toate site-urile web folosind un singur cont. Practic, un utilizator se va inregistra pe un site care va avea rolul de furnizor de identitate, iar pentru restul site-urilor ii va fi suficient sa foloseasca un link generat de furnizorul de identitate. Totodata, sistemul OpenID este descentralizat si nu depinde de un singur site pentru confirmarea identitatii generale.

Incercarile anterioare de a crea o metoda de autentificare universala, precum Microsoft Passport sau Liberty Alliance, au dat gres in parte si pentru ca erau implementari proprietare. OpenID a fost dezvoltat folosind modelul Open Source pentru a deveni un protocol interoperabil independent de orice organizatie singulara.

Desi avantajele unui astfel de sistem sunt evidente pentru utilizatori, in momentul de fata raspândirea autentificarii cu OpenID nu este foarte larga. Câteva mii de site-uri, in principal bloguri, au aderat la sistem. Numarul lor va creste insa pentru ca in randurile organizatiei OpenID Foundation (organizatie non profit care are ca singur scop protejarea standardului OpenID) au intrat câteva nume de marca. Google, IBM , Microsoft , VeriSign, si Yahoo! au intrat in consiliul director al fundatiei si aceasta miscare va duce cu siguranta la dezvoltarea intr-un ritm accelerat a acestei tehnologii.

Astfel Yahoo este una dintre primele companii mari care introduce conceptul OpenID 2.0. Yahoo are peste 248 de milioane de utilizatori la nivel mondial, iar dupa lansarea in variantei OpenID 2.0 pe me.yahoo.com, contul de Yahoo va putea fi consolidat intr-un cont OpenID pentru a putea fi folosit pe toate site-urile partenere Yahoo. Pe de alta parte, toate site-urile care nu au legatura cu Yahoo dar au acceptat tehnologia OpenID vor avea implementata optiunea "Foloseste pentru autentificare ID-ul de Yahoo".

Si in Romania, Ministerul Comunicatiilor si Tehnologiei Informatiilor intentioneaza sa adopte acest protocol care va permite celor care acceseaza site-urile administratiei publice pentru plata taxelor si impozitelor sau transmiterea unei cereri sa se autentifice fara un cod de identificare si o parola furnizate de primarii. Protocolul va fi reglementat printr-un act normativ elaborat de Ministerul Comunicatiilor, efectul preconizat fiind dezvoltarea rapida a serviciilor publice oferite de catre situ–ul e-guvernare, reducere aglomeratiei la ghiseele diferitelor institutii si eficientizarea activitatilor institutiilor publice in prelucrarea cererilor venite din partea cetatenilor.

Aceasta simpla tehnologie permite folosirea presentei deja existente in web ca o forma de identitate. A fost contruita sa rezolve problemele autentificarii singulare fara o complexitate inutila. La fel de simplu cum o adresa de email poate fi considerata o forma de indentiate, OpenID permite folosirea unei adresa internet (URL) care poate fi controlata pentru autentificarea pe alte site-uri. Si asemeni adreselor de email, o persoana poate avea mai multe identitati, una pentru servici si alta pentru acasa, sau orice alta utilizare. Dar spre deosebire de adresele de email, site-urile pe care este folosita identitatea nu pot sa trimita spam sau sa acceseze datele utilizatorilor decat daca acestia permit accesul.

Cu OpenID nu mai este nevoie de o autentificare separata sau crearea de conturi noi pentru fiecare site, este de ajuns autentificarea la furnizorul de identitate. Toate celelalte site-uri pe care utilizatorul le foloseste, daca sunt inscrise in standardul OpenID 2.0, se conecteaza automat la site-ul principal si, printr-un singur click, toate datele de acces implementate de utilizatori sunt preluate, verificate si introduse automat. Utilizatorii trebuie sa fie insa autentificati pe site-ul principal.

Specialistii afirma ca acest sistem, pe langa faptul ca va putea in viitorul apropiat sa scuteasca utilizatorii sa tina minte mai multe parole, va fi si mult mai sigur. Astfel, daca un utilizator foloseste 20 de site-uri care necesita autentificare, tastarea parolei si user-ului de fiecare data creste sansa ca parola sa fie aflata de persoane neautorizate. Conform unor studii, cei mai multi dintre navigatorii pe internet folosesc pentru mai multe site-uri aceleasi parole si nume de utilizator. Conceptul OpenID 2.0 lasa partea de securitate in grija domeniului principal, care este la libera alegere a utilizatorilor, in functie de preferintele acestora.

Astfel fiecare utilizator poate sa isi aleaga un furnizor de identitate in care are incredere. In acelasi timp, identitatea poate sa ramana chiar daca utilizatorul schimba furnizorul. Acest lucru se datoreaza si faptului ca aceasta tehnologie este gratuita si nu este propritatea nici unei entitati. Fiecare poate sa aleaga sa fie un utilizator de OpenID sau un provider de OpenID gartuit si fara a mai fi nevoie de o inregistrare sau de o aprobare a unei organizatii.

OpenID este de fapt un URL, folosind avantajele tehnologiilor internet deja existente (URI, HTTP, SSL, Diffie-Hellman). Utilizatorii internetului deja au create identitati, fie ca este vorba despre blog-ul lor, pagina parsonala etc. OpenID poate usor transforma unul din aceste URL-uri existente intr-un cont care poate fi folosit pe site-uri care ofera suport pentru autentificarea cu OpenID.

Pentru a folosi propria adresa de internet, URL-ului blug-ului, etc ca si identitate se poate folosi metoda delegarii. Aceasta metoda necesita un furnizor de identitate si niste cod HTML simplu. Daca se doreste gazduirea propriului furnizor de identitate se poate folosi phpMyID, un script php OpenSource care serveste drept server pentru propria identitate. Pentru a folosi acest script nu este nevoie de o baza de date, sau de a avea drepturi de scrire asupra sistemului de fisiere, nu este nevoie de alte librarii, de fapt nu mai este nevoie de nimic altceva.

Utililzatorii care folosesc unul din serviciile de mai jos, este posibil ca deja sa detina un OpenID:

AOL: openid.aol.com/screenname

Blogger: blogname.blogspot.com

Flickr: www.flickr.com/photos/username

LiveDoor: profile.livedoor.com/username

LiveJournal: username.livejournal.com

Orange (France Telecom): http://openid.orange.fr/

SmugMug: username.smugmug.com

Technorati: technorati.com/people/technorati/username

Vox: member.vox.com

Yahoo: http://openid.yahoo.com

WordPress.com: username.wordpress.com

Daca nu se va opta pentru optiunile descrise anterior, se poate opta dintre cativa provideri care sunt recomandati de diversi membri ai comunitatii. In final fiecare ar trebuii sa aleaga o companie in care are incredere, dar iata lista recomandata:

claimID: este gratuit si este o modalitate usoara de a administra identitatea OpenID

myOpenID: OpenID sigur si gratuit gazduit de serverele JanRain

VeriSign’s Personal Identity Provider: Furnizor de OpenID gratuit care ofera suport pentru autentificare multi-factor

myID.net: Furnizor de OpenID gratuit care ofera suport pentru grupuri si limba coreana

myVidoop: Furnizor de OpenID gratuit care elimina parolele cu elemete de securitate, customizare si integrare in browser.

EBay API

EBay este cea mai mare piata de desfacere actuala, cu mii de vanzatori care isi ofera produsele spre vanzare si milioane de cumparatori care gasesc tot ce doresc pe acest site. Dar vanzatorii cei mai activi de pe eBay se confrunta cu urmatoarele inconveniente cand isi desfasoara activitatea:

inabilitatea de a integra produsele eBay cu propriul magazin virtual

probleme cu incasarea platilor sa inabilitatea de a gestiona toate vazarile (offline / online / ebay) intr-un singur loc 

nevoia semnalarii automate a platilor si a reactilor primite

nevoia unei sablon de liste si improspatarea lui automata

nevoia de a automatiza anumite sarcini sau generarea de rapoarte

In mod normal, utilizatorii vand si cumpara produse folosind interfata eBay online, interactionand direct cu eBay. Dar cu ajutorul API-ului de la eBay se poate comunica direct cu baza de date eBay prin intermediul formatalui XML. Astfel sunt puse la dispozitia dezvoltatorilor multiple functionalitati pentru crearea de aplicatii puternice si interesante, aplicatii care ar putea elimina inconvenientele enumerate mai sus.

Folosind API-ul aplicatiile create pot asigura interfete specifice, functionalitati si operatii care nu sunt prezente in interfata eBay. Astfel programele create pot include urmatoarele facilitati: 

Inregistrarea de produse pentru listarea lor in eBay

Obtinerea listei curente de categorii eBay

Afisarea de informatii despre produsele listate pe eBay

Obtinerea de informatii referitoare la persoana care a licitat suma maxima pentru produsele oferite spre vanzare

Obtinerea listei curente de produse a unui anumit utilizator care vinde prin eBay

Obtinerea listei de produse pentru care un anumit utilizator a licitat

Afisarea listelor eBay pe alte site-uri

Postarea de mesaje despre alti utilizatori la finalizarea unei tranzactii

Deoarece API-ul nu este dependent de interfata eBay cu utilizatorul, permite crearea

de aplicatii stabile cu functionalitati specifice care sa intruneasca cerintele companiei. De exeplu se poate crea:

Automatizarea procesului de listare si monitorizare a licitatiilor. Nu mai este nevoie sa se parcurga (parse) paginile eBay, acestea schimbandu-si frecvent formatul blocand astfel aplicatia. Vanzatorul are acces la mai multe unelete pentru a vinde mai rapid si mai eficient.

Extragerea de informatii referitoare la utilizatorii eBay si automatizarea managemantului procesului de licitare si livrare a produselor.

Dar ce este acest serviciu web oferit de eBay. Ideea este chiar simpla. In loc sa vedem o tranzactie HTTP ca o cerere de document HTML, am putea sa ne gandim la ea ca la un apel de procedura la distanta. Astfel cererea HTTP devine o metoda de a apela o procedura pe server, URL-ul indicand care metoda sa fie apelata si raspunsul HTTP continand rezultatul apelului. In majoritatea cazurilor, raspunsul este un document XML, permitand procedurii apelate sa returneze o structura de date complexa.

Exista cel putin trei stiluri pentru a apela un serviu Web, si eBay le suporta pe toate. SOAP este probabil cea mai sofisticata metoda, folosind formatul XML atat in cerere cat si in raspuns, dar este si cea mai complexa. EBay suporta si apelul serviciilor Web prin asa numita XML API. Deoarece si SOAP foloseste standardul XML aceasta terminologie poate fi un pic confuza. API-ul bazat pe XML este de fapt o versiune simplificata a SOAP, fara a avea namespaces-uri si metode specifice pentru ordonantarea (marshal) structurilor complexe de date.

EBay propune si al treilea tip de interfata, fiind limitat fata de API-urile SOAP si XML, dar mult mai simplu de folosit. Numele ei este REST (representational state transfer), si functionalitea ei este simplu de inteles pentru oricine este familiar cu conceptul de URL. Parametrii sunt transmisi prin URL, folosind sintaxa standard nume=valoare.

Cu aceste trei tipuri de interfete (SOAP, XML si REST) si cu un set extins de metode disponibile dezvoltatorilor, devine posibila obtinerea de multiple tipuri de date referitoare la magazinele si licitatiile eBay.

PayPal API

PayPal este un sistem prin care poti efectua orice fel de plata doar folosind internetul. Puteti trimite fonduri rapid, confidential si sigur, utilizand cartea dvs. de credit sau de debit. Trebuie doar sa aveti un cont. Acest sistem de plata este foarte cunoscut si utilizat in special in SUA. Prin PayPal se desfasoara si majoritatea tranzactiilor online pe eBay. Vanzatorul poate verifica daca i s-a platit produsul, la putin timp dupa comanda astfel incat sa poata fi sigur ca poate trimite produsul linistit catre destinatar.

PayPal este activ in peste 190 de tari din lume si recunoaste 16 monede nationale. Este foarte benefic oamenilor care au afaceri sau relatii cu diferiti clienti din diferite tari. Platile se fac in moneda preferentiala iar la celalalt capat sunt automat schimbate in moneda primitorului fara nici un fel de comision. Din luna mai 2007 Romania a fost adaugata pe lista PayPal pentru a putea efectua plati iar din 30 septembrie 2007 acest sistem se poate folosi si pentru incasari. Astefel acest sistem usureaza foarte mult munca vanzatorului. El nu mai trebuie sa astepte dupa extrasele de la banca, care tin si 2 zile, ca sa vada daca a primit sau nu banii pe produsele deja trimise.

GoogleCheckout API

Este un serviciu care ofera clientilor o modalitate sigura si rapida de a cumpara online. Se poate folosi Google Checkout de a plati folosind card-ul bancar, a urmari comenzile si tranzactiile bancare si de a promi facturi prin sistemul bancar.

Integrarea cu serviciu Google Checkout poate urmari una din cele 2 alternative:

XML API – ofera comerciantilor acces la toate functionalitatiile Checkout. Implementarea XML este recomandata comerciantilor care doresc sa semnezedigital facturile (sau ordinele de plata) sau celor care doresc sa ofere cupoane de discount.

HTML API – ofera posibilitatea de interschimbare a informatiilor cu Google Checkoout prin intermediul de perechi nume/valoare printro cerere post intr-un protocol server-to-server HTTP. Aceasta implementare este recomandata afacerilor de mici dimensiuni, ce nu doresc sa genreze XML's. Comerciantii nu-si pot semna astfel, digital, oridinele de plata si nu beneficiaza de rapoarte referitoare la situatia tranzactiilor.

Integrarea componentelor

Principalul aspect al dezvoltarii de software bazata pe integrare este cercetarea. Alegerea unor componente care sa satisfaca cel mai bine cerintele, pe termen scurt dar si lung este partea care necesita cea mai mare atentie, timp si experienta.

Pentru fiecare componenta cu potential de a fi utilizata au trebuit urmariti urmatorii pas:

verificarea documentatiei referitoare la functionalitatiile care le ofera

instalarea componentei si a contextului respectiv (daca e nevoie)

invatarea utilizarii API-ului de integrare cu respectiva componenta

inspectarea eventualelor probleme, inspectarea forum-urilor pentru eventuale probleme

testarea componentei

verificarea maturitatii comunitatii: cat de ampla este documentatia, cat de rapid iti raspunde comunitatea la eventuale probleme, participarea la discutiile de dezvoltare/suport pentru a intelege cat de activa este comunitatea.

verificarea tipului de licenta a componentei

documentarea referitoare la directia de dezvoltare in continuare a componentei (daca va mai fi suportata in viitor, daca sunt alte standarde care vor inlocui standardele actuale pe care se bazeaza componenta).

Am definit patru probleme majore de care sa tin cont, respectiv zone de cercetare.

problema dependintelor intre componente.

problema gradului de utilitate al componentelor

problema maturitatii componentei

problema licentelor

Fieecare componenta pe care o alegeam a face parte din sistemul meu, atragea dupa sine dependintele acesteia. Dependintele pot fi privite ca o structura ierarhica de aplicatii si versiuni ale aplicatiilor. Atungi cand alegi o componente alegi si suita sa de dependente. In functie de configuratiile componentei se poate alege o suita de dependente sau o alta suita de dependente. Deseori, alegerea unei componente se dovedeste a fi necorespunzatoare pentru celelalte componente, existand o incompatibilate intre ele. De foarte multe ori incompatibilitatea nu este documentata astfel incat singura metoda este sa incerci a o integra si sa observi ce probleme apar. Daca se ivesc probleme si dupa o relativ scurta documentare nu se pot elimina problemele, e bine sa poti trece la o alta componenta.

Am observat ca fiecare componenta se adreseaza unei specificatii generale. Acest lucru imi permitea sa folosesc componenta in sistemul meu concret, dar atragea cu sine si o serie intreaga de functionalitati pe care eu nu le utilizam. Astfel, sistemul meu se largea ca si dependinte de componente, si complexitate, fara ca eu sa folosesc anumite parti din respectivele componente.

Problema maturitatii componentei a fost poate cea mai dificila dintre preblemele de analizat. Pentru aceasta a trebuit sa urmaresc forum-uri, sa particip la sedinte si discutii online sau mail-uri, toate cu scopul de a rezolva probleme concrete. Fie a fost vorba de rezolvare unui bug, sau fie a fost vorba de lamurirea unei documentatii de instalare sau utilizare care nu mai era actualizata, fie a fost vorba de dezvoltarea unei anumite functionalitati. Toate aceste discutii, prin finalitatea, sau inutilitatea lor, au condus la decizia referitoare la utilizarea sau nu a unei respective componente.

Pentru rezolvarea problemei licentelor a trebuit sa cer ajutor colaboratoriilor si clientilor mei. Ei au fost aceea care mi-au furnizat informatiile referitoare la legalitatea folosirii uneia sau alteia dintre componente.

Alegerea platformei de dezvoltare

Una dintre cerinte a fost ca aplicatia web sa ruleze intr-un sistem de operare Linux. Pentru ca sa decuplez partea de programare si dezvoltarea codului sau a configuratiilor de sistemul de operare propriu-zis, am folosit virtualizarea. Pentru aceasta am ales varianta freeware de la vmware (http://www.vmware.com). Astfel, platforma de testare, precum si codului propriu-zis existau doar in masina virtuala.

Ca si sistem de operare am ales Ubuntu Server, pentru usurinta in instalare, pentru suportul extraordinar in furnizarea de pachete (librarii, componente) in format binar, pentru documentatia bogata si pentru numarul impresionant de utilizatori dornici sa se sprijine reciproc. Tipul de server pe care l-am ales a fost un clasic LAMP cu mentiunea ca acest sistem minim si-a extins numarul componentele odata cu distributia de server (plecand de la 6.06, urmand cu 6.10, apoi 7.04, pentru ca in final sa ajung la distributia 7.10 denumita si
Gutsy Gibbon.

Ca si editor principal am ales Eclipse, pentru faptul ca este un produs complet, cu cost minim. Astfel dezvoltarea a fost facuta intr-un sistem de operare Windows, dar si Linux, decuplat de masina virtuala in care se afla codul respectiv, sistemul de fisiere in care se afla codul fiind partajat prin retea, folosindu-se un server samba.

Alegerea componentelor

Prima decizie care a trebuit s-o iau a fost referitor la applicatia web primcipala de la care voi pleca (distribution fork). Initial am ales Plone ca si punct de plecare. Il alesesem pentru ca:

era rapid si neincarcat de functionalitate inutila

avea un minim de dependente: Python si Zope (ca si web server), si suporta orice connector python pentru database, astfel se putea interfata cu orice implementare de baze de date care avea si un connector python sau ODBC.

Deoarece Zope nu era suportat ca si host-ing pe server-ele backbone ale firmelor GoDaddy sau Lunarpages (punct de plecare pentru infrastructura hardware necesara), si pentru ca acea comunitate care dezvolta suportul de galerie foto in cadrul Plone nu a fost una activa, a trebuit sa renunt la Plone si la intreaga sa suita de dependinte (python, zope etc).

Pentru a continua axa referitoare la CMS (Content Managent System), si la aplicatie care sa porneasca pe o astfel de platforma pentru a asigura o generalitate care sa permita dezvoltari ulterioare si in alte directii, am ales WordPress. WordPress are ca si dependinte PHP-ul, MySQL ca si suport de baze de date, Apache ca si web server, ImageMagic sau Gd pentur manipulare de imagini, multe alte librarii si componente de care nu aveam nevoie in mod direct, nedorind sa folosesc aplicatia ca si blog, sau pentru publicarea de stiri.

In schimb, comunitatea era una deosebit de activa. Exista o multitudine de proiecte care s-au desprins din  WordPress, iar cate un nou release este publicat odata pe trimestru. Acceasta denota faptul ca proiectul este intr-o continua dezvoltare, are numerosi membri si este deci un produc matur.

Am renunutat totusi la WordPress in momentul in care am gasit Gallery2. Gallery2 avea toate functionalitatiile de baza, avea o comunitate activa si ofera o licenta convenabila. Am hotarat atunci sa schimb directia de dezvoltare folosind Gallery2. Voi prezenta in continuare arhitectura Gallery2, punctul de la care am plecat in dezvoltarea mea, si conceptele pe care a fost necesar sa mi le insusesc pentru a le putea utiliza.

Gallery2 a fost conceputa ca sa declupeze complet vizualizarea informatiilor de design (module) si date. Arhitectura applicatiei se bazeaza pe design pattern-ul Model View Controller.

Decupleaza astfel  componentele vizuale (Views), de modul de reprezentare ale acestora (Themes), de module ce reunesc o gama de functionalitati (gen Captcha, Watermarks, ), de moduri de trasfer al informatiilor (Controllers) – putandu-se crea Web Service-uri pentru a modifica informatiile modelului, de (Plugins) modurile prin care interfateaza componentele din cadrul aplicatiei cu altele etc.

Comunitatea a dezvoltat diferite module care se adresaza unor diferite cerinte:

Metode diferite de securitate: Capthca, autentificari folosind certificate SA etc

Internationalizare: suport pentru diferite limbi

Statistici

Google Map etc

Aceste functionalitati, au trebuit fi la randul lor configurate, testate, semnalate bug-uri, verificat interdependenta dintre acestea etc. Unele bug-uri au fot corectate de mine, contribuind astfel comunitatii. Unele dintre functionalitati existau pe versiuni diferite ale lui Gallery. Exista mai multe versiuni de dezvoltare, eu alegand versiunea a doua Gallery2, au trebuit unele functionalitati portate pe aceasta versiune.

Intregul proces a fost o munca de colaborare, o munca plina marcata de implementari si reimplementari.

Gallery2 permite adaugarea de noi functionalitati fara a modifica nucleul aplicatiei. Nucleul aplicatiei este cat se poate de simplu, iar functionalitatea este adaugata prin module ce pot fi atasate nucleului. Astfel, functionalitatea este pluginable, adica nu e nevoie de intreaga functionalitate a aplicatiei pentru a avea o instanta cu functionalitati de baza. Este dezvoltata in jurul tehnologiilor Apache si MySQL.

Pe langa toate acestea, au fost nevoie de dezvoltarea unor module proprii. Multe dintre functionalitatiile economice specificate in cerinte nu existau implementate. Acestea au fost implementate de catre mine si au constat in integrarea cu alte componente Open Source.

Am dezvoltat un modul care sa permita incarcarea de poze dintr-un director (multipleupload). Datorita modului cum este gandit un navigator web (browser), este considerata o bresa extraordinar de periculoasa de a oferi unei aplicatii web, acces pe calculatorul personal. Astfel, dupa o perioada indelungata de cercetari, am ajuns la solutia folosirii Flash. Flash este un serviciu (o aplicatie) instalata pe calculator-ul personal care ofera o interfata prin care se poate accesa, cu anumite restrictii, sistemul de fisiere. Am folosit astfel swfUpload ca si componenta Open Source care faciliteaza transferul de fisiere media de pe calculator-ul personal catre un serviciu web.

Pentru a facilita magazinele eBay de a-si inarca automat pozele din cadrul serviciu-ului eBay, am implementat un alt modul de syncronizare a unui cont eBay cu un cont MyPixBusiness.

Un alt modul s-a adresat functionalitatii economice de plata online. Am implementat astfel un modul care sa permita plata online folosind Google Checkout si PayPal API. Amandoua librarii sunt freeware. A fost nevoie de conturi de test, si o indelungata documentare. Au fost nevoie si de teste (Unit Testing) automate.

Nu in ultimul rand am implementat un Standard Open de autentificare, numit OpenID. Acesa a reprezentat un alt modul in cadrul aplicatiei MyPIXBusiness.

Pentru ca MyPIXBusiness a dorit sa vina si cu o interfata grafica proprie, bazata pe propriile functionalitati si pe caracterul specific al serviciului, a trebuit sa implementez o tema noua. Aici am comunicat cu artisti care au propus si au imaginat o astfel te tema. Pentru aceasta am folosit o noua componenta Open Source si anume Script.aculo.us. Aceasta librarie java script a fost aleasa dupa o indelungata cercetare si testare a mai multor librarii java script, printre care Mootools si jQuery. Iintr-un final am ales Script.aculo.us pentru ca era compacta, simpla si nu incarca proiectul cu deja foarte multe dependinte.

Dezvoltare de module (Integrarea cu MyPIXBusiness)

Initial aportul adus aplicatiei gallery s-a concretizat prin crearea de noi module sau modificarea celor existente. Dar pe masura ce proiectul progresa a aparut si nevoia modificarii nucleului aplicatiei (modulul Core). Cu toate acestea am incercat ca aceste modificari sa fie facute doar atunci cand a fost strict necesar, deorece am avut in vedere compatibilitatea cu versiunile viitoare de gallery. Astfel doresc ca pe viitor sa import toate imbunatirile care apar ca urmare a dezvoltarii gallery si doresc ca acest lucru sa se poate realiza cat mai simplu (chiar automat).

In continuare voi descrie modulele care le-am creat, modificarile aduse modulelor existente si in finalul acestui capitol voi prezenta si noua tema. Doresc sa precizez inca de pe acum ca nu este vorba doar de o modificare estetica a interfetei grafice ci de o modificare radicala a layout-ului aplicatie pentru a fi cat mai intuitiv pentru utilizatorul care inchiriaza poze (scopul aplicatiiei fiind schimbat de la simpla prezentare si organizare de imagini)

Softlinks

Acest modul a fost punctul de plecare in crearea aplicatiei. Rolul lui era sa suporte functionalitatea de baza, si anume sa faciliteze inchirierea de imagini. Daca utilizatori ar fi putut pur si simplu copia locatia imaginii si mai apoi sa o foloseasca pe alte site-uri atunci nu ar mai fi fost interesati sa inchirieze aceste imagini. Astfel a aparut problema pe care prin implementarea acestui modul am rezolvat-o, si anume adresa pozei nu trebuia sa fie valida decat in interiorul aplicatiei.

    Solutia implica in mod evident generarea dinamica a adresei fiecarei imagini. Din fericire in gallery2 afisare pozelor se face prin apelarea funtiei render a fiecarui item, iar in cazul imaginilor a functiei din clasa GalleryPhotoItem. In aceasta functie este contruit, si returnat templete-ul pentru afisare, tag-ul HTML <img/>. Adresa imaginii se obtine prin apelarea functiei generateUrl astfel:

$urlGenerator =& $gallery->getUrlGenerator();
$src = $urlGenerator->generateUrl(
        array('view' => 'core.DownloadItem', 'itemId' => $this->getId(),
              'serialNumber' => $this->getSerialNumber()),
        array('forceFullUrl' => !empty($params['forceFullUrl'])));

Se observa ca obiectul a carui metoda este apelata este obtinut prin functia getUrlGenerator. Daca aceasta functie ar returna in loc de generatorul de url-uri standard un generator modificat atunci problema generarii dinamice de adrese ar fi rezolvata. Acest lucru se realizeaza prin suprascrierea functiei performFactoryRegistrations clasa SoftlinksModule care extinde GalleryModule:

    function performFactoryRegistrations() {
        $rewriteUrlGenerator = 'SoftlinksUrlGenerator';
        $ret = GalleryCoreApi::registerFactoryImplementation(
        'GalleryUrlGenerator', $rewriteUrlGenerator, $rewriteUrlGenerator,
        'modules/softlinks/classes/'.$rewriteUrlGenerator . '.class', 'softlinks', null, 1);
        if ($ret) {
            return $ret;
        }
    }

Generatorul de URL-uri se numeste SoftlinksUrlGenerator si extinde clasa ModRewriteUrlGenerator. In aceasta clasa se suprascrie funtie genrateUrl, in interiorul careia se interpune un controler inainte de afisarea view-ului.

    function generateUrl($params=array(), $options=array()) {
        if (isset($params['view']) && $params['view'] == 'core.DownloadItem') {
            $params['controller'] = 'softlinks.Redirect';
            unset ($params['view']);
        }

        return parent::generateUrl($params, $options);
    }

Urmatorul pas a fost gasirea unei modalitati de realizare a cerintei de a valida doar ceririle care provin din interiorul aplicatiei. Initial m-am gandit la o solutie prin care adresele erau schimbate zilnic, dar apoi mi-am dat seama ca nu era asa important de la ce aplicatie veneau cerile ci de fapt de unde veneau cerile.

Astfel important devenea nodul de retea de unde se primea cererea, de fapt adresa IP a clientului. Utilizatorul putea folosi acum locatia imaginilor si in alte site-uri iar rezultatul ar fi cel asteptat, dar doar pentru acel utilizator. Pentru cei care acceseaza pagina de pe alte noduri ale retelei rezultatul va fi un mesaj de eroare in loc de imaginea asteptata.
    Un mic inconvenient ar fi legat de calculatoarele aflate in aceeasi retea locala. Acestea se afla in spatele unui router iar adresa publica vizibila in exterior este acceasi pentru toate nodurile din aceasta retea. Intradevar imaginile vor fi disponibile celor aflati in reteaua locala, dar avand in vedere ca un site web se adreseaza tuturor utilizataorilor din internet, acest lucru nu este o problema.

Ca urmare am hotarat sa adaug si IP-ul  calculatorului de unde provenea cererea in adresa generata pentru afisarea pozei. Inainte de fieacare afisare se poate astfel compara provenienta cererii cu IP-ul din cerere (locatia pozei). Verificarea se face in controler-ul Redirect, in functia handleRequest din clasa  RedirectController care extinde GalleryController:

    function handleRequest(&$form) {
        global $gallery;
        $ipAdress = GalleryUtilities::getRequestVariables('ip');
        $pseudoFileName = alleryUtilities::getRequestVariables('fileName');
        $clientIp = $_SERVER['REMOTE_ADDR'];
        if (empty($ipAdress) || $ipAdress != $clientIp) {
            return array(GalleryCoreApi::error(ERROR_BAD_PARAMETER),

null);           
  } else {
      $itemId = GalleryUtilities::getRequestVariables('itemId');
  }
  GalleryUtilities::putRequestVariable('itemId', $itemId);
  GalleryUtilities::putRequestVariable('fileName', $pseudoFileName);
  GalleryUtilities::putRequestVariable('view', 'core.DownloadItem');
        $results = array('delegate' => array('view' => 'core.DownloadItem'), 'status' => array(),'error' => array());
  return array(null, $results);      

}

In continuare a trebuit sa gesesc o cale prin care sa adaug IP-ul clientului la adresa pozei. Pentru aceasta m-am folosit de modulul rewrite. Acest modul are rolul de a furniza URL-uri configurabile, pentru a scurta si schimba aspectul acestora, folosinduse de mod_rewrite, ISAPI_Rewrite sau PathInfo.

Cateva din particularitatile acestui modul ar fi:

Scurteaza URL-urile intr-o forma usor lizibila de utilizatori.

Ofera suport pentru Apache mod_rewrite.

Ofera suport pentru IIS ISAPI_Rewrite.

Ofera suport pentru PHP PathInfo.

Tipare configurabile pentru URL-uri.

Ofera suport pentru a include functinalitati extinse oferite de alte module

Pentru a-l folosi a trebuit mai intai sa instalez mod_rewrite, care este un mod din Apache util in rescrierea URL-urilor in timp real. Modulul are un engine bazat pe reguli, compatibile cu expresiile regulate POSIX, care pot fi utilizate in rescrierea URL-urilor. Pentru utilizare este nevoie de specificarea unor reguli atat in fisierul de configurare apache (httpd.conf) cat si in fisierul de rescriere a directivelor (.htaccess).

Anterior am intercalat controler-ul Redirect inainte de view-ul DownloadItem care efectueaza afisarea in sine. Acum prin intermediul modulului rewrite vom schimba toate URL-urile catre controlerul nostru astfel incat ele sa contina adresa IP a clientului, devenind in acelasi timp si mai estetice. Pentru obtinerea acestui lucru am adaugat functia getRewriteRules in clasa SoftlinksModule din fisierul de definire al modulului si anume in module.inc:

function getRewriteRules() {
        $rules = array();

        /* Rule for Download Item */
        $rules[0] = array(
        'comment' => $this->translate('Download Item'),
        'match' => array('controller' => 'softlinks.Redirect'),
        'pattern' => 's/%ip%/%itemId%-%serialNumber%/%fileName%',
        'options' => array('useAuthToken' => false),
        'keywords' => array(
        'serialNumber' => array(
        'pattern' => '([0-9]+)',
        'help' => $this->translate('Ensures browsers do not use cached version when image has changed'),
        'function' => array('softlinks', 'SoftlinksSimpleHelper', 'parseSerialNumber')),
        'fileName' => array(
        'pattern' => '([^/?]+)',
        'help' => $this->translate('The item file name.'),
        'function' => array('softlinks', 'SoftlinksSimpleHelper', 'parseFileName')),
        'ip' => array (
        'pattern' => '([^/?]+)',
        'help' => $this->translate('The ip adress of the client.'),
        'function' => array('softlinks','SoftlinksSimpleHelper', 'parseIp'))
        ),
        'help' => $this->translate('The random URL for downloading items.'));

        return $rules;
    }

Aceasta functie returneaza un sir de reguli. In cazul nostru a fost nevoie de o singura regula in care am definit pentru care cereri se va face rescrierea adresei (prin campul 'match') si tiparul care va fi folosit pentru crearea adresei finale ('pattern'). Tot aici se precizeaza si clasa ce contine metodele care vor inlocuii identificatorii din tiparul adresei cu informatiile necesare. Aceasta este clasa SoftlinksSimpleHelper si cea mai importanta metoda a ei este cea care introduce IP-ul in adresa:

function parseIp(&$url, &$params, &$entity){
        $ipAdress = $_SERVER['REMOTE_ADDR'];
        $url = str_replace('%ip%', urlencode($ipAdress), $url);
        return true;
    }

Astfel functionalitatea dorita de la acest modul a fost atinsa. Adresa fiecarei imagini continea acum si informatii referitoare la locul de unde era ceruta. Se poate astfel restrictiona regasirea pozelor a caror adresa este accesata din alta locatie decat cea specificata in adresa. Lucru care se intampla atunci cand link-ul pozei este copiat si inserat in alta pagina web.

Mai ramaneau cateva mici finisari care ar fi definitivat modulul. Tinand cont ca funtionarea modulului softlinks depindea de prezenta altui modul, si anume rewrite a trebuit sa se faca verificari in timpul instalarii si sa nu se permita instalarea softlinks, decat conditionata de intalarea in prealabia a modulului rewrite. Acest lucru a fost realizat prin crearea unui template in pagina de administrare care atentioneaza utilizatorul ca trebuie sa intaleze modulul rewrite. Pentru afisarea paginii doar in conditiile anterioare am introdus urmatoarele functii in fisierul module.inc:

    function needsConfiguration() {
        list ($ret, $modules) = GalleryCoreApi::fetchPluginList('module');
        if ($ret) {
            return array($ret, null);
        }
        if (!isset($modules['rewrite'])) {
            return array(null, true);
        }
        return array(null, false);
    }

    function getConfigurationView() {
        return 'softlinks.SetupSoftlinks';
    }

Cel care instala modulul trebuia sa intre in pagina de configurare pentru URL Rewrite si sa activeze regula pentru modulul Softlinks. Dar pentru a usura procesul de configurare al aplicatiei, la activarea modului am decis sa  automatizez acest proces.

Fig. – Modul manual de configurare al modulului rewrite

Finalizarea acestui modul a implicat necesitea unui modul care sa gestioneze pozele inchiriate si care sa permita adrese permanete pentru aceste poze, si asa a aparut modulul Linkcheckout.

Linkcheckout

Ideea care sta la baza acestui modul este de a oferi link-uri "permanente" pentru pozele care au fost achizitionate. Insa aceste link-uri nu sunt cumparate, ci inchiriate. Adica valabilitatea linkurilor trebuia sa fie temporara, ele expirand dupa perioda pentru care au fost inchiriate.

Implementarea modulului in sine a fost destul de usoara. Pentru fiecare imagine inchiriata am creat o adresa fixa care a fost salvata in baza de date. Am inceput prin a crea o tabela care sa contina informatii referitoare la imagine, adresa permanenta si perioada pentru care se face inchirierea. In Gallery2 crearea unei noi tabele trebuie sa urmareasca urmatorii pasi. Intai se creaza un fisier XML denumit Maps.xml, continand descrierea structurii tabelelor. Acest fisier face parte din subdirectorul classes al directorului radacina al modulului:

<!DOCTYPE maps SYSTEM "../../../lib/tools/dtd/MapsDefinition2.0.dtd">
<maps>
  <map>
    <map-name>LinkCheckoutMap</map-name>
    <schema>
      <schema-major>1</schema-major>
      <schema-minor>0</schema-minor>
    </schema>
    <member>
      <member-name>permanentUrl</member-name>
      <member-type>STRING</member-type>
      <member-size>MEDIUM</member-size>
      <primary/>
    </member>
    <member>
      <member-name>itemId</member-name>
      <member-type>INTEGER</member-type>
      <indexed/>
      <required/>
    </member>
    <member>
      <member-name>userId</member-name>
      <member-type>INTEGER</member-type>
      <indexed/>
      <required/>
    </member>
    <member>
      <member-name>resolution</member-name>
      <member-type>STRING</member-type>
      <member-size>MEDIUM</member-size>
    </member>
    <member>
      <member-name>creationTimestamp</member-name>
      <member-type>INTEGER</member-type>
      <required/>
    </member>
    <member>
      <member-name>periodTimestamp</member-name>
      <member-type>INTEGER</member-type>
      <required/>
    </member>
  </map>
</maps>

In acelasi director trebuie sa se afle si fisierul gnumakefile. Apoi din linia de comanda trebuie rulata comanda “make” sau “gmake” care va genera doua fisiere: Maps si GalleryStorage/schema.tpl. Cel din urma contine cod SQL, si este folosit la initializarea modululi pentru a creea noile tabele.

Pentru a face interogari pe aceste tabele nu este nevoie de a scrie SQL. Metoda este de a crea o clasa, in cazul acesta denumita LinkCheckoutMapHelper.class care implementeaza functii necesare lucrului cu baza de date. Un exemplu este functia fetchItemsForUserId, folosita pentru a obtine toate imaginile inchiriate de un anumit utilizator:

    function fetchItemsForUserId($userId) {
        list ($ret, $searchResults) = GalleryCoreApi::getMapEntry('LinkCheckoutMap',
        array('permanentUrl', 'itemId', 'resolution', 'creationTimestamp', 'periodTimestamp'),array('userId' =>             $userId) );
        if ($ret) {
            return array($ret, null);
        }

        $data = array();
        while ($result = $searchResults->nextResult()) {
            if (!isset($data[$result[1]])) {
                $data[$result[1]] = array();
            }
            $data[$result[1]][] = array('permanentUrl' => $result[0], 'resolution' => $result[2],
                'creationTimestamp' => $result[3],'periodTimestamp' => $result[4]);
        }
        return array(null, $data);
    }

Din acest exemplu se poate observa modul in care se fac interogorile bazei de date. Astfel se apeleaza functia statica getMapEntry din clasa GalleryCoreApi, si se specifica numelei tabelei, campurile care vor fi returnate si campul dupa care se face cautarea. Pe langa functia de cautare, gallery2 pune la dispozitie si functii pentru adaugare, stergere si update.

Atunci cand valabilitatea pozelor expira, acestea nu mai puteau fi accesat si initial era afisat un mesaj de eroare. Dar acest lucru nu era prea estetic, si mesajul de eroare ar fi putut deruta utilizatorii crezand ca au aprut probleme in aplicatia MyPIXbusiness. Atunci m-am gandit ca in loc de mesaj as putea sa afisez o imagine din care sa reiasa ca link-ul a expirat, dar in acelasi timp sa fie si un prilej de a promova site-ul mypixbusiness.

Am decis ca aceasta imagine sa poata fi schimbata foarte usor direct din site, fara a mai fi nevoie de a intervenii in cod. Pentru aceasta am inclus o noua pagina in partea de administrare. Acest lucru se poate realiza usor in gallery2, fiind nevoie sa se includa in fisierul module.inc, in constructorul clasei LinkcheckoutModule a liniei $this->setCallbacks('getSiteAdminViews') prin care se precizeaza ca acest modul foloseste partea de administrare. Tot in aceasta clasa se va include si urmatoarea functie care va preciza numele intrarii si view-ul pentru administarea modulului.

    function getSiteAdminViews() {
        return array(null, array(array('name' => $this->translate('Rent'),
        'view' => 'linkcheckout.Admin')));
    }

Chiar daca aceasta era o simpla imagine, si as fi putut doar sa o incarc in sistem si apoi sa folosesc locatia ei pentru a o afisa, am luat decizia sa o tratez ca pe un item gallery. Astfel a fost nevoie sa trec prin tot procesul de salvare a unei imagini gallery, dar avantajul a fost ca acum lucram doar cu identificator (itemId). Pentru a salva acest identificator am folosit o faciliate a aplicatiei gallery2, prin care fiecare modul poate salva parametrii necesari in tabela PluginParameterMap. La dezinstalarea modulului acesti parametri sunt stersi din baza de date. In cazul nostru am apelat fuunctia in felul urmator:

$ret = GalleryCoreApi::setPluginParameter('module', 'linkcheckout', 'expired_link_itemId', $itemId);

Un alt avantajul a fost simplitatea cu care am implementat partea de logica a afisarii imaginilor inchiriate. In clasa RedirectController, functia handleRequest face verificarile necesare si apoi redirecteaza spre view-ul de afisare propiuzis DownloadItem. Acest view foloseste identificatorul pozei (itemId) pentru a o afisa. Astfel daca perioada de valabillitate s-a terminat, identificatorul returnat este cel al imagini definite anterior, scutindu-se astfel implementarea unui view separat. Partea in care se face acest lucru este urmatoarea:

if ($timeLeft < 0) {

list ($ret, $itemId) = GalleryCoreApi::getPluginParameter('module', 'linkcheckout', 'expired_link_itemId');

if ($ret) {

return array($ret, null);

}

if (!isset($itemId)) {

return array(GalleryCoreApi::error(ERROR_BAD_PARAMETER), null);

}

} else {

if (($indexOfResolution = $item['resolution']) == 'fullsize'){

// the item can also have a derivative, so load this derivative id if it exists

list ($ret, $preferred) =

GalleryCoreApi::fetchPreferredsByItemIds (array($item['itemId']));

if ($ret) {

return array($ret, null);

}

/* Show the preferred item, if it's there */

if (empty($preferred)) {

$itemId = $item['itemId'];

} else {

$itemId = $preferred[$item['itemId']]->getId();

}

} else {

list ($ret, $itemId) = LinkCheckoutHelper::getResizeId($item['itemId'],$indexOfResolution);

if ($ret) {

return array($ret, null);

}

}

}

Terminand partea de link-uri permanente, era nevoie de o legatura cu modulul Softlinks discutat anterior. Aceasta veriga a fost un alt modul si anume Checkout. Modulul exista deja si oferea posibilitatea de a integra diverse metode de plata.

Fig. Integrarea diverselor modalitati de plata in modulul Checkout

Inserarea acestor linii la sfarsitul procesului de checkout se realizeaza fara a modifica modulul Checkout. Tot in fisierul module.inc, in clasa  LinkcheckoutModule se adauga urmatoarea functie prin care de fapt se adauga o line in baza de date, in tabela FactoryMap. In modulul Checkout se vor putea astfel initializa toate clasele care extind clasa CheckoutPluginInterface_1_1, care joaca rol de interfata, si apoi apela metodele implementate.

    function performFactoryRegistrations() {
        /* Register our plugin for checkout*/
        $ret = GalleryCoreApi::registerFactoryImplementation(
        'CheckoutPluginInterface_1_1', 'LinkCheckoutPlugin', 'linkcheckout',
        'modules/linkcheckout/classes/LinkCheckoutPlugin.class', 'linkcheckout', null);
        if ($ret) {
            return $ret;
        }
           
        return null;
    }

Clasa LinkCheckoutPlugin extinde clasa CheckoutPluginInterface_1_1 si implementeaza trei functii getPaymentTextTemplate, getPaymentButtonTemplate, getPaymentVariables. Primele doua returneaza fisierele template care definesc textul si butonul ce vor aparea in pagina de checkout, iar ultima functie salveaza in sesiune variabilele ce vor fi folosite in continuare.

Butonul adaugat de mine nu redirecteaza sper un serviciu extern de efectuare a platii ci spre un controller  care face parte tot din modulul linkcheckout. Cu acest control-ler se realizeaza transformarea adreselor softlinks in linkuri permanente accesibile toturor utilizatorilor. Tot aici se va realiza si plata acstui servicu dar folosind functionalitatea altui modul ce il voi descrie ulterior si anume modulul Points.

Datorita faptului ca modul Checkout ofera multiple configurari am incercat sa nu il modific ci sa incerc doar din meniul de administrare sa-l adaptez nevoilor aplicatiei mypixbusiness. Dupa cum se observa si din imaginea anterioara pentru fiecare poza  apare o lista de produse cu pretul aferent si cantitatea care va fi selectata de cumparator. Modulului checkout este destinat diverselor magazine care ar tiparii pozele (de fapt magazinelor care stocheaza informatia pe alt mediu), iar produsele se refera la dimensiunea fotografiilor, tipul ramei, etc. Aceasta lista de produse, precum si pretul fiecarui produs sunt definite de administrator.

Pentru aplicatia mypixbusiness analogia facuta a fost urmatoarea: produsele erau reprezentate de link-uri catre diferite rezolutii ale unei imagini, iar cantitatea reprezenta perioada pentru care se facea inchirierea. Problema a aparut la partea de rezolutie a pozei. Deoarece aceste rezolutii nu sunt standard, putand lua orice valoare, acestea nu puteau fi definite apriori ca produse. Solutia a fost definirea preturilor pentru intervale de rezolutii. Acest lucru a condus la modificarea modului checkout.

Points

Urmatorul pas a fost modulul care sa permita plata acestor imagini, astfel a luat nastere modulul Points. Ideea de baza a fost de a oferi cumparatorului un sistem unic si totodata simplu de a cumpara imaginile. Astfel pretul unei poze se va exprimat in puncte si nu va mai depinde de o anumita moneda. Acest lucru implica in primul rand un sistem de gestiune al punctelor. Pentru aceata am creat doua tabele. Prima tine evidenta creditului pentru fiecare utilizator.

  <map>
    <map-name>PointsMap</map-name>
    <schema>
      <schema-major>1</schema-major>
      <schema-minor>0</schema-minor>
    </schema>
    <member>
      <member-name>userId</member-name>
      <member-type>INTEGER</member-type>
      <primary/>
    </member>
    <member>
      <member-name>points</member-name>
      <member-type>INTEGER</member-type>
      <required/>
    </member>
  </map>
 
    Cea de a doua tabela reprezinta un istorit al tuturor tranzactiilor efectuate in sistem.Pentru fiecare achizitionare de poza se adauga o noua inregistrare, iar valoarea campului points este negativa. Cate o inregistrare, dar de aceasta data cu valoare pozitiva a campului points, se aduga si pentru fiecare crestere a numarul de puncte. Aceasta crestere poate fi datorata fie achizitionarii de noi puncte, fie initializarii creditului de catre sistem sau prin primirea de catre proprietarul pozei a unui procent din valoarea de vanzare. Acest procent se defineste de catre administratorul aplicatiei.
  
  <map>
    <map-name>PointsHistoryMap</map-name>
    <schema>
      <schema-major>1</schema-major>
      <schema-minor>0</schema-minor>
    </schema>
    <member>
      <member-name>transactionId</member-name>
      <member-type>INTEGER</member-type>
      <primary/>
    </member>
    <member>
      <member-name>userId</member-name>
      <member-type>INTEGER</member-type>
      <indexed/>
      <required/>
    </member>
    <member>
      <member-name>itemId</member-name>
      <member-type>INTEGER</member-type>
      <indexed/>
    </member>
    <member>
      <member-name>resolution</member-name>
      <member-type>STRING</member-type>
      <member-size>MEDIUM</member-size>
    </member>
    <member>
      <member-name>points</member-name>
      <member-type>INTEGER</member-type>
      <required/>
    </member>
    <member>
      <member-name>price</member-name>
      <member-type>STRING</member-type>
      <member-size>MEDIUM</member-size>
    </member>
    <member>
      <member-name>permanentUrl</member-name>
      <member-type>STRING</member-type>
      <member-size>MEDIUM</member-size>
    </member>
    <member>
      <member-name>paymentModule</member-name>
      <member-type>STRING</member-type>
      <member-size>MEDIUM</member-size>
      <required/>
    </member>
    <member>
      <member-name>creationTimestamp</member-name>
      <member-type>INTEGER</member-type>
      <required/>
    </member>
  </map>
</maps>

     Cu aceasta tabela am intampinat o problema, datorata campului transactionId. Am dorit ca acest camp sa fie autoincrementat, dar acest lucru nu se putea definii in fisierul XML descriptiv. Rezolvarea a fost modfificarea tabelei la activarea modulului. In functia activate am adaugat urmatoarele randuri:

        global $gallery;
        $storage =& $gallery->getStorage();
        $query = sprintf('
                ALTER TABLE %sPointsHistoryMap
                MODIFY COLUMN %stransactionId
                INTEGER NOT NULL DEFAULT NULL AUTO_INCREMENT;',
                 $storage->_tablePrefix, $storage->_columnPrefix);
         $storage->execute($query);
         $storage->commitTransaction();

    A fost foarte importanta consemnarea (commit) modificarilor facute, deoarece tot in aceasta funtia urma sa se  adauge creditul initial pentru utilizatorii deja existenti in sistem la activarea modulului. Aceasta adaugare necesita si o inregistrare in istoricul transactilor.

     Pentru a stimula si a se obisnuii cumparatorul cu aplicatia, acesta primea acest credit initial. Acest credit initial este definit in partea de administrare a site-ului. Aceasta functionalitate este implementata prin folosirea evenimentelor generate de gallery2. Pentru a preciza ca se va folosi unul sau mai multe din acestea se va include in contructorul clasei PointsModule din fisierul module.inc linia  $this->setCallbacks ('registerEventListeners'). Apoi se va implementa metode registerEventListeners unde se va preciza despre care evenimente este vorba:

function registerEventListeners() {
        GalleryCoreApi::registerEventListener('GalleryEntity::delete', new PointsModule());
        GalleryCoreApi::registerEventListener('GalleryEntity::save', new PointsModule());
    }

    Pentru functionalitatea noastra vom folosi evenimentul save. Acest eveniment este declansat atunci cand o entitate gallery este salvata. Evenimentul fiind general, vom testa daca entitatea este de tipul GalleryUser si pentru a nu aduga credit la fiecare schimbare a datelor utilizatorului vom testa si daca entitatea este nouy create prin verificarea fanionului STORAGE_FLAG_NEWLY_CREATED. Tot acum vom adauga crditul initial si la istoricul de tranzactii. Evenimentul delete este folosit pentru a sterge inregistrarile din tabelele modulului referitoare la utilizatorul la care se renunta.

if ($event->getEventName() == 'GalleryEntity::save') {
            list ($ret, $createdUserPoints) =
            GalleryCoreApi::getPluginParameter('module', 'points', 'createdUser_points');
            if ($ret) {
                return array($ret, null);
            }

            if ($createdUserPoints > 0) {
                $user = $event->getEntity();
                if (GalleryUtilities::isA($user, 'GalleryUser') &&
                $user->testPersistentFlag(STORAGE_FLAG_NEWLY_CREATED)) {
                    GalleryCoreApi::requireOnce('modules/points/classes/PointsMapHelper.class');

                    $ret = PointsMapHelper::createPoints($user->getId(), $createdUserPoints);
                    if ($ret) {
                        return array($ret, null);
                    }

                    $ret = PointsMapHelper::createHistory($user->getId(),null,null,$createdUserPoints,null,null,'gallery:newCreatedUser',time());
                    if ($ret) {
                        return array($ret, null);
                    }
                }
            }
        }

Dupa cum am amintit anterior valoarea creditului initial pentru un utilizator nou creat si valoarea procentului ce revenea proprietarului dupa vanzarea unei poze pot fi definite de adminstrator. De fapt pentru functionarea modulului aceste valori trebuiau obligatoriu definete. Am folosit optiunea de a initial doar instala modulul, si deabia dupa configurare acesta sa se poata activa. In clasa PointsModule am inclus fuunctia urmatoare in care se testeaza daca cele doua valorile au fost initializate:

    function needsConfiguration() {
        list ($ret, $value1) = $this->getParameter('owner_percentage');
        if ($ret) {
            return array($ret, null);
        }
        list ($ret, $value2) = $this->getParameter('createdUser_points');
        if ($ret) {
            return array($ret, null);
        }
        return array(null, empty($value1) || empty($value2));
    }

Utilizatorul trebuia sa aiba posibilitatea de a cumpara noi puncte. Astfel am integrat in modulul Points doua servicii de plata electronica, si anume Google Checkout si PayPal. Astfel cumparea de noi puncte se face in mai multi pasi. In primul pas se specifica numarul de puncte cre se doresc a fi cumparate. In al doilea pas se afiseaza costul acestor puncte, calculat folosind pretul unui punct de credit definit anterior de administratorul sistemului. Din acest pas incepe si integrarea serviciilor prin adaugarea celor doua butoane ce corespund celor doua metode de plata.

Fig. Integrarea modalitatilor de plata electronica

In urmatorii pasi utilizatorul este redirectat spre site-ul companiei care ofera serviciul de plata electronica. De obicei urmeaza trei pasi. Unul in care utilizatorul este rugat sa se autentifice, urmatatorul in care utilizatorul poate sa accepte tranzactia si ultimul in care utilizatorul este instiintat daca comanda a fost inregistrata. In ultimul pas utilizatorul poate alege daca se intoarce la aplicatie sau poate verifica starea comenzilor din interfata producatorului.

La dezvoltarea modulului acesti ultimi pasi trebuia repetati in nenumarate randuri. Acest lucru l-am realizat folosind mediul de testare al celor doua companii numit Sandbox. Sandbox-ul este un sitem menit sa ajute dezvolatorul in testarea implementarii. Interfata cu utilizatorul este vizual diferita fata de servicul oficial, informand utilizatorul ca se afla in acest mediu prin afisare pe fundal a cuvantului Sandbox. Dar functionalitatea este pastrata aceeasi cu sistemul oficial cu doau exceptii:

In Sandbox numerele cartilor de credit au valori de test

In sandbox nu se executa operatii reale de debitare sau creditare

Deabia dupa testarea serioasa a plicatiei si a bunei integrari a functionalitatilor acestor servicii, se poate trece la folosirea serviciilor oficiale. Bineinteles ca si aici se vor efectua teste, dar ar fi de dorit ca acum sa nu apara probleme deoarece acestea ar putea duce la pierderea unor sume de bani, tranzactiile fiind reale. Pentru a usura trecerea de la sistemul de testare la cel de oficial am adaugat aceasta obtiune in partea de administrare a aplicatiei:

Prezentarea celor doua servicii a fost asemanatoare pana acum, de aici inainte voi aborda cele doua servicii separat. Voi incepe cu Google Checkout. Punctul de plecare in dezvoltarea acestei parti a constitui un exemplu de implementare de pe site-ul de documentatie al google checkout. Configurarea acestui exemplu a necesitat rezolvarea unor erori si probleme aparute, dar acest lucru mi-a usurat munca in continuare deoarece de acum in colo toate erorile stiam ca sunt pe partea dezvoltata in modul.

Primul lucru ce trebuia facut a fost crearea a doua tiputi de conturi in Sandbox. Unul dintre aceste conturi va avea rolul de cumparator si va fi folosit pentru achizitionarea de puncte. Al doilea tip va avea rolul de vanzator si va fi folosit in pagina de administrare a aplicatiei. Necesitatea a doua conturi s-a datorat restrictiei serviciului Google Checkout de a nu permite ca acelasi cont sa joace rolul de vanzator si cumparator in aceeasi tranzactie.

Odata conturile create, urmatorul pas a fost sa implementez partea care apeleaza servicul google checkout. In formularul care contine butonul de checkout au trebuit incluse si informatiile despre comanda clientului. Pentru aceasta este necesar crearea unui document XML cu informatii despre produsele aflate in cosul de cumparaturi al cumparatorului. Acest fisier trebuie criptat si valoarea criptata inclusa in pagina ce contine butonul Google Checkout.

Pentru includerea butonului si informatilor legate de comanda am folosit o librarie care face foarte simpla utilizarea serviciului. Anticipand faptul ca si alte servicii urmau sa fie adaugate m-am gandit sa fac cate o clasa helper pentru fiecare serviciu implementat si in aceasta clasa sa existe o metoda getPaymentButton care sa returneze ca string codul pentru butonul ce urma sa fie inclus in pagina. Astfel inserarea butoanelor se face direct fara a mai fi nevoie de alte modificari.

Pentru servicul google checkout am realizat clasa GoogleCheckoutHelper. Aici am creat un nou obiect GoogleCart folosind pentru valorile variabilelor $merchant_id si $merchant_key datele disponobile in contul creat pentru vanzator. Aceste valori trebuie setate in meniul de administrare al aplicatiei, si reprezinta contul in care se vor depune banii obtinuti din vanzarea imaginilor. Variabila $server_type defineste daca tranzactiile sunt reale sau se executa in Sandbox.

$cart = new GoogleCart($merchant_id, $merchant_key, $server_type, $currency);

$item = new GoogleItem("Credits", // Item name

"This points allow you to buy permanent links for photos", // Item description

$total_count, // Quantity

$point_price); // Unit price

//the merchant_item_id will represent the userId of the buyer

$item->SetMerchantItemId($userId);

$cart->AddItem($item);

// Specify <edit-cart-url>

$cart->SetEditCartUrl($returnUrl);

// Specify "Return to xyz" link

$cart->SetContinueShoppingUrl($returnUrl);

// Request buyer's phone number

$cart->SetRequestBuyerPhone(false);

// Display Google Checkout button

return $cart->CheckoutButtonCode("medium");

Se observa ca se mai defineste un obiect de tipul GoogleItem. Acesta reprezinta produsul cumparat, iar in cazul nostru acesta este unic pentru toate tranzactiile, si anume punctele de credit. Un lucru importatnat aici este definirea codului produsului prin SetMerchantItemId. Codul ales a fost chiar identificatorul utilizatorului care cumpara puncte. Importanta acestui cod de identificare va fi detaliata ulterior. Acest produs este apoi adaugat cosului declarat anterior. La final se va returna codul necesar pentru inserarea butonului apeland functia $cart->CheckoutButtonCode.

Google checkout pune la dispozitia dezvoltatorului o functionalitate foarte utila in cazul nostru si anume Notification API. Astfel am creat un servicu web prin care aplicatia mypixbusiness primeste si proceseaza notificare cu privire la comenzile efectuate.

Am folosit aceasta functionalitate pentru a automatiza procesul de taxare a clientului. Procedura manuala ar fi fost ca un administrator sa verifice in contul sau de pe google checkout toate comenzile efectuate, sa transfere pentru fiecare comanda suma necesara iar apoi sa adauge in aplicatia mypixbusiness punctele cumparate de fiecare utilizator. Primul lucru care a trebuit facut a fost setarea in acest fel.

Fig. Setarea contului de vanzator pentru a face taxarea automata

Daca transferul este acceptat si transferul banilor efectuat aplicatia mypixbusiness este notificata cu privire la succesul tranzactiei. Fiecare notificare este de fapt un document XML care formeaza continutul unei cereri HTTP POST. Am creat un controller care urma sa fie apelat de catre Google Checkout, si care implementeaza servicul web oferit. Adresa acestui controller am fost nevoit sa o adaug in setarile contului vanzatorului, in campul API callback URL. In implementarea controlerului am folosit aceeasi librarie. Astfel in functia handleRequest din clasa GoogleCheckoutHandlerController am initializat un obiect GoogleResponse si apoi am parcurs fisierul XML.

$Gresponse = new GoogleResponse($merchant_id, $merchant_key);

$xml_response = isset($HTTP_RAW_POST_DATA)?

$HTTP_RAW_POST_DATA:file_get_contents("php://input");

list($root, $data) = $Gresponse->GetParsedXML($xml_response);

Apoi in cazul in care notificarea este de tipul „order-state-change-notification”, citim starea comenzii „new-financial-order-state”, iar daca aceasta are valoare „CHARGED” apelam functia addPoints din clasa ajutatoare PointsHelper pentru a efectua operatiile necasare adaugarii punctelor cumparate. Pentru a determina in contul cui sunt adaugate punctele de credit se foloseste valoarea codului produsului definita anterior ca fiind chiar identificatorul utilizatorului din sistemul mypixbusiness.

$google_order_number = $data[$root]['google-order-number']['VALUE'];

list ($ret, $transaction) = GoogleCheckoutHelper::fetchTransaction($google_order_number);

$ret = PointsHelper::addPoints($transaction['userId'],$transaction['points'], $transaction['price'], 'google:buyPoints');

if ($ret) {

echo "Error in GoogleCheckoutHandler:order-state-change-notification:CHARGED";

$Gresponse->SendServerErrorStatus();

} else {

echo "OK in GoogleCheckoutHandler:order-state-change-notification:CHARGED";

}

Implementarea serviciului PayPal a decurs mai usor deoarece cadrul integrarii a fost deja creat pentru serviciul Google Checkout. Am inceput aceasta parte tot prin crearea conturilor. Diferenta de abordare e ca pentru PayPal se creaza un singur cont. Acest cont permite realizarea a oricate conturi de test si setarea pentru fiecare a tipului vanzator sau cumparator.

Pentru integrarea butonului PayPal am creat o clasa PayPalHelper care implementeaza functia getPaymentButton. In aceasta functie am creat un sir in care am initializat toate valorile necesare pentru crearea butonului. De aceasta data am folosit parametrul „item_number” pentru a transmite identificatorul utilizatorului care face tranzactia.

$buttonParams = array( "cmd" => "_xclick",

"business" => $loginMail,

"cert_id" => DEFAULT_CERT_ID,

"charset" => "UTF-8",

"item_name" => htmlspecialchars("Credits"),

"item_number" => htmlspecialchars($userId),

"amount" => htmlspecialchars($point_price),

"quantity" => htmlspecialchars($total_count),

"currency_code" => htmlspecialchars($currency),

"return" => htmlspecialchars($returnUrl),

"cancel_return" => htmlspecialchars($returnUrl));

Si de aceasta data am folosit o librarie pentru a usura generarea codului butonului. Pentru siguranta transactiilor am decis sa folosesc metoda de criptare dinamica a butonul folosind Encrypted Website Payments (EWP). Folosind chei publice si chei private, se genereaza dinamic codul HTML pentru butonul de plata si criptarea detaliilor referitoare la comanda inainte ca butonul sa fie afisat in pagina.

Pasii ce trebuie urmati sunt urmatorii. Initial certificatul public trebuie incarcat in contul vanzatorului PayPal. Apoi fiecare buton este semnat digital folosing prin cheia privata si apoi este criptat folosind certificatul public. Cand utilizatorul apasa butonul de plata si este tranferat catre PayPal, se realizeaza decriptarea codului butonului folosind cheia privata si apoi se verifica semnatura digitala folosind certificatul public pe care l-am incarcat. Daca semnatura e valida procesul de plata continua. Acesti pasi sunt transparenti pentru cumparator, procesul de plata fiind acelasi ca si in cazul platii necriptate.

Astfel am apelat functia encryptButton cu urmatorii parametri:

$buttonReturn = EWPServices::encryptButton(

$buttonParams,realpath(DEFAULT_EWP_CERT_PATH), realpath(DEFAULT_EWP_PRIVATE_KEY_PATH),

DEFAULT_EWP_PRIVATE_KEY_PWD,

realpath(PAYPAL_CERT_PATH), $envURL, BUTTON_IMAGE);

return $buttonReturn["encryptedButton"];

Si in acest caz am dorit taxarea automata a clientului, lucru realizat prin folosirea serviciului Instant Payment Notification (IPN).

Fig. Configurarea notificarilor pentru PayPal

Am creat controlerul PayPalHandlerController prin care se citesc parametrii cererii HTTP POST. Daca starea platii este „Completed” atunci se pot adauga punctele de credit in contul cumparatorului:

$userId = $_POST["item_number"];

$points = $_POST["quantity"];

$price = $_POST["payment_gross"];

$payment_status = $_POST["payment_status"];

if(isset($payment_status) && strcmp($payment_status,"Completed")==0)

$ret = PointsHelper::addPoints($userId, $points, $price, 'paypal:buyPoints');

Odata cu finalizarea acestui modul functionalitatea de baza a proiectului a fost realizata. In continuare m-am concentrat sa aduc imbunatatiri in modul de interactiune al utilizatorului cu aplicatia. Prima ralizare in acest sens a fost modulul Multipleupload.

Multipleupload

Acest modul face ca procesul incarcarii (upload-ul) imaginilor in aplicatie sa devina mai simplu si mult mai rapid decat cel standard. Astfel utilizatorul era scutit sa adauge pe rand fiecare poza, el putand acum selecta cu ajotorul Ctrl/Shift toate pozele dorite si apoi sa le adauge unei liste. Aceasta lista putea fi in continuare modificata prin adaugarea altor imagini sau prin stergerea din imaginile adaugate. Utilizatorul poate apoi sa porneasca incarcarea tuturor imaginilor din lista, fiind informat cu privire la progresul incarcarii pentru fiecare imagine.

Fig. Integrarea tab-ului Multipleupload in pagina de adaugare de imagini

Am inceput implementarea modulului prin includerea unui tab in pagina de adaugare de noi itemuri. Integrarea s-a realizat prin adaugarea functiei performFactoryRegistrations in clasa MultipleUploadModule. Aici se precizeaza clasa care extinde ItemAddPlugin si totoadata pozitia in llista de tab-uri. In aceasta clasa se va imlementa si o functie getTitle care va returna numele tab-ului.

function performFactoryRegistrations() {

$ret = GalleryCoreApi::registerFactoryImplementation(

'ItemAddPlugin', 'MultipleItemAdd', 'MultipleItemAdd',

'modules/multipleupload/MultipleItemAdd.inc', 'multipleupload', null, 3);

if ($ret) {

return $ret;

}

return null;

}

Integrarea acestei componente se realizeaza prin includerea in pagina de afisare (view-ul) a unei parti javascript prin care se precizeaza ca la incarcarea paginii se va initializa obiectul SWFUpload. Prin campurile acestui obiect sunt definite calea catre fereastra de selectie SWFUpload.swf si celea spre fisierul apelat la finalizarea fiecarui upload. Tot aici sunt definite tipurile de fisiere acceptate, dimensiunea maxima a fisierelor si functiile javascript care sunt apelate la diverse evenimente:

swfu = new SWFUpload({

upload_script : {/literal} "upload.php?itemId={$ItemAdmin.item.id}&g2_sessionId={$tpl.sessionId}" {literal},

target : "SWFUploadTarget",

debug : false,

flash_path : {/literal} "{g->url href="modules/multipleupload/help/SWFUpload.swf"}" {literal},

allowed_filesize : 30720, // 30 MB

allowed_filetypes : "*.jpg;*.gif;*.png",

allowed_filetypes_description : "Image files…",

browse_link_innerhtml : "Browse pictures",

upload_link_innerhtml : "Upload queue",

browse_link_class : "swfuploadbtn browsebtn",

upload_link_class : "swfuploadbtn uploadbtn",

flash_loaded_callback : 'swfu.flashLoaded',

upload_file_queued_callback : "fileQueued",

upload_file_start_callback : 'uploadFileStart',

upload_progress_callback : 'uploadProgress',

upload_file_complete_callback : 'uploadFileComplete',

upload_file_cancel_callback : 'uploadFileCancelled',

upload_queue_complete_callback : 'uploadQueueComplete',

upload_error_callback : 'uploadError',

upload_cancel_callback : 'uploadCancel',

auto_upload : false

});

Pentru finalizarea modulului mai trebuia creat fisierul upload.php. Acesata este apelat la finalizarea incarcarii fiecarui fisier. La apelare se transmite si parametrul itemId care este identificatorul dosarului in care se adauga noile imagini. Upload.php are rolul de a realiza toate etapele necsare pentru salvarea unei noi imagini in aplicatie.

EBay

Modulul eBay este o alta modalitatea prin care se pot adauga imagini in sistemul mypixbusiness. Deoarece multe magazine isi construisera deja o intreaga infrastructura de poze, preturi si detalii despre produse pe site-ul eBay, trebuia gasit un sistem care sa ofere posibilitatea unui transfer automat intre infrastructura de pe eBay si cea din cadrul mypixbusiness. Si de acesta data, tot prin intermediul unui serviciu web, oferit acum de eBay, am putut sa interoghez si sa creez un sistem de sincronizare intre cele doua platforme.

Si de aceasta data a trebuit sa adaug un tab nou in pagina de adaugare de itemuri, lucru realizat in aceeasi modalitate ca si la multipleupload. Folosind eBay API pentru a crea aceasta metoda facila de import si de sincroniza datele intre cele doua aplicatii web, procesul de implementeare s-a asemanat cu cel de la modulul points. Si acum prima etapa a fost crearea unui cont pe situl de dezvoltare al celor de la eBay. Urmatorul pas este crearea unui set de chei de acces. Trebuie precizat ca si eBay foloseste conceptul de Sandbox. Aici diferenta dintre mediul de productie si mediul de testare se face prin folosirea a diferite seturi de chei de acces. Astfel eu am creat un set de chei pentru Sandbox.

Fig. Generarea setului de chei pentru Sandbox

Tot aici se pot crea si utilizatori de test, dar in cazul nostrum a fost nevoie, deoarece preloarea datele produselor chiar si a unui utilizator nu este periculoasa. Aceste produse oricum sunt publice si diponibile prin interfata site-ului eBay. Dintre cheile generate anterior am folosi doar AppID. Acest identificator trebuie adaugat in partea de administrare a mypixbusiness. Modulul nu poate fi activate daca valoarea acestei chei nu a fost introdusa, lucru realizat prin adaugarea functiilor urmatoare in fisierul module.inc:

function needsConfiguration() {

list ($ret, $value1) = $this->getParameter('appId');

if ($ret) {

return array($ret, null);

}

return array(null, empty($value1));

}

function getConfigurationView() {

return 'ebay.Admin';

}

Importul pozelor se face in doua etape. Prima consta in introducerea numelui vazatorului eBay. Apoi dupa apasarea butonului „Find images” servicul eBay este apelat si se cauta toate produsele ce apartin vanzatorului respectiv. De fapt nu toate produsele sunt cautate odata. Mai ales pentru vanzatorii care aveau multe produse, am realizat un sistem de paginatie pentru afisarea imaginilor. Pentru ca afisarea sa decurga cat mai repede, tinand cont ca este un servicu web fiind destul de incet comparativ cu afisarea normala, am ales ca serviciul sa fie apelat doar pentru numarul de produse dintr-o anumita pagina. Numarul produselor cautate se specifica prin valoarea variabilei $maxEntries iar prin valoarea $page se specifica de fapt care produse sa fie returnate.

Cautarea produselor se face printr-i cerere HTTP cu parametrii. Dintre parametrii importanti sunt numele functiei apelate, versiunea acestei functii si tipul rasounsului asteptat. Versiunea functiei este importanta deoarece asa suntem siguri ca rezultatul primit are structura la care ne asteptam.

$endpoint = 'http://open.api.ebay.com/shopping'; // URL to call

$responseEncoding = 'XML'; // Format of the response

$version = '537'; // API version number

$apicall = "$endpoint?callname=FindItemsAdvanced"

. "&version=$version"

. "&siteid=$siteID"

. "&appid=$appID" // replace this with your AppID

. "&SellerID=$sellerID"

. "&MaxEntries=$maxEntries"

. "&responseencoding=$responseEncoding";

if (isset($page)) {

$apicall .= "&PageNumber=$page";

}

$resp = simplexml_load_file($apicall);

Se observa ca functia apleata este „FindItemsAdvanced”. Apelul acestei functii are ca rezultat un fisier XML ce contine o lista cu produse ce apartin unui anumit vanzator. Aceasta lista cuprinde si anumite detalii despre produs dar nu si toate pozele atasate produsului. Astfel vom folosi doar identificatorul produsului si vom mai apela pentru fiecare produs alta functie care va returna mai multe detalii referitoare la produs printre care si lista de imagini care ne intereseaza. Denumirea functiei este GetSingleItem si ca parametru primeste si campul IncludeSelector cu valoarea ItemSpecifics pentru a returna si specificatiile produsului folosite pentru a crea descrierea imaginilor.

$apicall2 = "$endpoint?callname=GetSingleItem"

."&responseencoding=$responseEncoding"

."&appid=$appID"

."&siteid=$siteID"

."&version=515"

."&IncludeSelector=ItemSpecifics"

."&ItemID=$item->ItemID";

Dupa ce lista de imagini era afisata urmeaza partea in care utilizatorul selectarea produsele pentru care se doreste crearea de imagini in sistemul mypixbusiness. Utilizatorul are la dispozitie optiunea de a folosi din informatiile atasate produsului atunci cand imaginea este salvata. Astfel pentru titlul fiecarei poze se poate folosi numele imaginii, pentru sumar se poate folosi titlul produsului la care este atasata imaginea, pentru descriere se pot folosii specificatiile produsului iar pentru cuvintele cheie se pot folosii categoriile eBay din care acest produs apartine.

Fig. Optiunile utilizatorului inainte de a salva imaginile in sistem

Utilizatorul poate sari peste aceasta etapa, si sa importe direct toate pozele unui anumit vanzator eBay. Astefel are la dispozitie butonul “Import All” care efectueaza automat operatiile de salvare a tuturor pozelor.

O problema care a aparut atunci cand am inceput testarea modului a fost aceea ca daca vanzatorul facea acest import in mod repetat anumite imagini erau salvate in mod repetat. Acest lucru se datoreaza faptului ca in gallery daca denumirea unui fisier salvat era deja prezenta in system aceasta se modifica si fisierul era salvat. In cazul nostrum acest lucru inseamna ca aceeasi imagine era salvata in mod repetat cu denumiri diferite.

Initial am solutionat problema prin schimbarea acestui comportament in cazul modulului eBay si anume daca denumirea fisierul era gasita in directorul unde se facea salvarea atunci poza era ignorata. Apoi m-am gandit ca ar fi cazuri, de exemplu atunci cand imaginea unui produs este schimbata dar denumirea imaginii ramane aceeasi, cand utilizatorul ar vrea ca si aceata imagine sa fie salvata. Astfel am mai adaugat o optiune prin care se poate specifica acest comportament.

Odata imbunatatite metodele de adaugare a noilor imagini, urmatorul pas a fost sa ma gandesc la procesul de inregistrare si autentificare a noilor utilizatori. Asa a aparut urmatorul modul.

OpenID

Startul acestui modul, ca si in cazul celorlalte care folosesc servicii web a fost crearea unui cont. De data aceasta contul nu trebuia creat pe site-ul celor de la OpenID. Acest cont reprezinta identitatea utillizatorului si poate fi folosit pentru crearea altor conturi, astfel pentru crearea contului a trebuit sa aleg un furnizor de identitate. Deja exista foarte multi furnizori, eu alegand unul present in lista de pe site-ul OpenID si anume myOpenid.com.

Apoi am folosit aceasta identitate pentru a-mi crea conturi in alte aplicatii care ofereau aceasta facilitate. Am facut acest lucru pentru a vedea modul in care serviciul este folosit de alte aplicatii. Insa am fost surprins de eficienta OpenID. Intr-adevar procesul de inregistrare devenea foarte rapid si facil, convingandu-ma astfel ca aceasta functionalitate va atrage utilizatori noi.

Am inceput implementarea modulului cu partea de autentificare. Trebuia integrata in pagina de login si metoda OpenID de autentificare. Din pacate gallery2 nu ofera posibilitatea integrarii directe de noi modalitati de autentificare. Dar incercand sa pastrez similitudinea cu modul de integrare de noi module intalnit pana acum, m-am gandit ca cel mai potrivit ar fi sa creez un sistem de tab-uri pentru comutarea intre modalitatile de login.

Fig. Crearea sistemului de tab-uri pentru integrarea diferitelor sisteme de autentificare

Acum utilizatorul avea posibiliatea sa aleaga intre metoda standard sau metoda OpenID de autentificare. Daca allege metoda a doua trebuie sa introduca identitatea OpenID. Apoi in cazul in care este deja autentificat si cu o ocazie precedenta s-a folosit varianta “Allow Forever” ca in figura urmatoare, utilizatorul intra direct in contul sau. Daca nu dupa caz mai trebuie sa se autentifice in sistemul OpenID si sa permita trimiterea confirmarii catre aplicatia mypixbusiness.

Fig. Modalitatea prin care utilizatorul se poate autentifica direct folosind doar identitatea

Pentru realizarea acestui dialog intre sitemul mypixbusiness si OpenID am folosit o librarie. Am creat un obiect de tipul Auth_OpenID_Consumer. Apoi am apelat functia begin a acestui obiect pentru a specifica identitatea utilizatorului. Functia returneaza un obiect prin intermediul caruia este apelat servicul web. Functia redirectURL a acestui obiect primeste ca parametru adresa de revenire. Aceasta adresa reprezinta calea spre controller-ul FinishLogin. Aici se apeleaza metoda complete a obiectului consumer, iar satusul raspunsului se verifica daca este “Auth_OpenID_SUCCESS”. Atunci inseamna ca cel care a introdus identitatea la inceputul procesului de login este chiar posesorul ei si in continuare se face corespondenta intre identitate si utilizatorul sistemului mypixbusiness. Acest lucru se bazeaza tabela a careai descriere XML este urmatoarea:

<maps>

<map>

<map-name>OpenIdMap</map-name>

<schema>

<schema-major>0</schema-major>

<schema-minor>1</schema-minor>

</schema>

<member>

<member-name>openId</member-name>

<member-type>STRING</member-type>

<member-size>MEDIUM</member-size>

</member>

<member>

<member-name>galleryId</member-name>

<member-type>INTEGER</member-type>

</member>

</map>

</maps>

Daca identitatea nu se regasea in tabela anterioara inseamna ca utilizatorul incearca sa se inregistreze. Astfel dupa verificarea identitatii el este transferat direct la formularul de inregistrare. Acest formular are deja toate campurile completate deoarece OpenID a transmis deja datele necesare. Utilizatorul poate sa le modifice sau sa apese butonul de inregistrare si sa inceapa sa foloseasca aplicatia.

Dar pentru realizarea acestui lucru trebuia integrate functionalitatea OpenID in procesul de inregistrare. Dar modulul Register nu oferea suport pentru integrarea altor functionalitati (plug-ins). Am decis atunci sa adaug eu acest support. Ca si pana acum in modulul OpenID, in fisierul module.inc am adaugat functia prin care se specifica care este implementarea interfetei din modulul Register.

function performFactoryRegistrations() {

$ret = GalleryCoreApi::registerFactoryImplementation(

'RegisterOption', 'OpenIdOption', 'OpenIdOption',

'modules/openid/OpenIdOption.inc', 'openid', array('UserSelfRegistration'));

if ($ret) {

return $ret;

}

return null;

}

Apoi implementarea clasei OpenIdOption ar fi fost suficienta pentru finalizarea modului. Dar acum urmatorul pas a fost crearea in modulul Register a clasei cu rol de interfata RegisterOption. In aceasta clasa am definit functiile ce urmau sa fie suprascrise de fiecare optiune ce urma sa fie integrata. Pe langa aceste functii am mai adaugat si o metoda getAllOptions care returneaza intantele tuturor claselor care s-au inregistrat ca implementeaza aceasta interfata.

function getAllOptions($name, $data) {

list ($ret, $allOptionIds) = GalleryCoreApi::getAllFactoryImplementationIdsWithHint('RegisterOption',$name);

if ($ret) {

return array($ret, null);

}

$optionInstances = array();

foreach (array_keys($allOptionIds) as $optionId) {

list ($ret, $option) =

GalleryCoreApi::newFactoryInstanceById('RegisterOption', $optionId);

list ($ret, $isAppropriate) = $option->isAppropriate($name, $data);

if ($isAppropriate) {

$optionInstances[$optionId] = $option;

}

}

return array(null, $optionInstances);

}

Lista de obiecte rezultata dupa apelul acestei functii este folosita pentru a putea apela metodele implementate in diverse parti ale modulului. Un exemplu este atunci cand am dorit sa adaug campul cu identitatea OpenID in formularul de inregistrare. Acest lucru se realizeaza in felul urmator:

list ($ret, $optionInstances) = RegisterOption::getAllOptions('UserSelfRegistration', $data); /* Now let all options load their template data */

$RegisterOptions = array();

foreach ($optionInstances as $option) {

list ($ret, $entry['file'], $entry['l10Domain']) = $option->loadTemplate( $template, $form, 'UserSelfRegistration', $data );

if (!empty($entry['file'])) {

$RegisterOptions[] = $entry;

}

}

Moderate

Initial procesul de filtrare a pozelor in functie de continut a fost realizat folosind modulul Moderate deja existent. Folosirea acestui modul este nevesara pentru a evita pozele cu continut indecent, calitate necorespunzatoare sau cele care nu prezinta interes pentru comunitatea eBay. Functionalitatea de baza era asigurata de acest modul, dar dupa folosirea lui mi-am dat seama ca procesul de moderare era greoi pentru o aplicatie cu muti utilizatori, asa cum este mypixbusiness.

Prima schimbare ce a trebuit facuta s-a referit la utilizatorii ce puteau modera pozele incarcate. Modulul initial permitea doar administartorilor aplicatiei sa faca acest lucru. Astfel m-am gandit ca ar fi util ca aceptarea sau respingerea pozelor sa fie facuta de persoanele ce apartineau unui anumit grup. Acest grup are drepturi de moderare dar nu si drepturi de configurare ale sitemului asa cum se intampla cu administartorul. Avantajul era ca acum la procesul de moderare puteau participa un numar mult mai mare de utilizatori, scurtand astfel perioada de asteptare pana la acceptarea imaginilor.

Fig. Adaugarea grupurilor care vor indeplini functia de moderare

La inceput am vrut sa creez un grup standard de moderatori iar din pagina de administrare a modulului sa adaug utilizatori acestui grup. Dar pentru flexibilitatea utilizarii am decis sa folosesc metoda de organizare a grupurilor cu care utilizatorii erau deja obisnuiti si in partea de administrare sa adaug oricate module intr-o lista. Toti utillizatorii ce apartin unui grup din aceasta lista vor devenii „moderatori”.

In modulul initial pagina pentru realizarea procesului de moderare era in partea de administrare a site-ului. Pentru ca si moderatorii care nu faceau parte din grupul administartorilor a trebuit sa mut aceasta pagina. O alta problema a vechiului modul era ca nu afisa nici un mesaj utilizatorilor obisnuiti care faceau upload-ul. Acestia observau doar ca imaginile incarcate nu erau afisate in catalog, fara a stii ce s-a intamplat cu ele.

Fig. Informarea utilizatorului despre procesului de moderare

Rezolvarea celor doua cerinte s-a realizat prin crearea a doau pagini ce afisau imaginile care asteptau sa fie moderate. Una dintre ele era destinata moderatorilor si erau afisate toate imaginile din system care urmau sa fie moderate, iar cea de-a doua se adresa utilizatorilor care putea astefel vedea care sunt pozele care nu au fost inca acceptate. Pentru pagina moderatorilor am putut refolosi pagina vechiului modul. Dar a fost nevoie de cateva imbunatatiri. A trebuit in primul rand contruit un sistem de paginatie si apoi introducerea de optiuni pentru acceptarea sau respingerea tuturor pozelor odata, sau pentru inversarea selectiei. Includerea unor functii JavaScript a rezolvat aceasta problema.

Cel de-al doilea tip de pagina se referea la utilizatorii fara drepturi de moderatori. Acestia putea vizualiza imaginile ce tocmai au fost incarcate si observa procesul de moderare. Dar aceasta pagina nu are doar rol informativ. Deoarece imaginile au si informatii atasate si un moderator va verifica si aceste informatii, din aceasta pagina ele mai pot fi modificate inainte de a fi acceptate. Acest lucru este important mai ales in contextual aplicatiei noastre deoarece odata pozele acceptate ele devin publice si pot fi inchiriate de alti utilizatori. Pozele publicate nu mai pot fi modificate de catre utilizatorul ce le-a incarcat, ci doar de catre administrator.

A fost necesara schimbarea drepturilor pentru pozele incarcate in functia handleRequestAfterAdd a clesei ModerateOption care extinde clasa ItemAddOption. Aceasta functie este apelata la finalizarea procesului de adaugare a fiecarei poze. In primul rand a trebuit sa adaug drepturi complete pentru toate grupurile de moderatori, iar apoi pentru proprietarul imaginii am adaugat drepturi de stergere, vizualizare, editare si mutare a imaginii. Dreptul de inchiriere este adaugat doar dupa poza este facuta publica.

list ($ret, $groupCount) = GalleryCoreApi::getPluginParameter('module', 'moderate', 'groupCount');

if ($ret) {

return array($ret, null, null);

}

for ($i=0;$i<$groupCount;$i++) {

list ($ret, $groupName) = GalleryCoreApi::getPluginParameter('module', 'moderate', 'groupName'.$i);

list ($ret, $group) = GalleryCoreApi::fetchGroupByGroupName($groupName);

$ret = GalleryCoreApi::addGroupPermission($itemid, $group->getId(), 'core.all');

if ($ret) {

return array($ret, null, null);

}

}

$ret = GalleryCoreApi::addUserPermission($itemid, $ownerid, array('core.delete', 'core.viewAll', 'core.edit', 'core.moveItem'));

Deoarece moderatorii aveau dreptul sa accepte orice poza din sistem, imaginile incarcate de ei nu mai trebuiau sa treaca prin procesul de moderare, ele fiind acceptate direct. Astfel in interfata aplicatiei apare un singur buton, dar acesta este diferit pentru moderatori fata de utilizatorii obisnuiti. Pentru a atrage atentia moderatorilor ca exista in system poze propuse pentru moderare am adaugat in textul butonului si numarul acestor poze. Astfel un moderator nu mai trebuia sa verifice existenta pozelor prin accesarea paginii de moderare, el putand vizualiza acest lucru direct din interfata. Pentru utilizatorii obisnuiti se afisa numarul imaginilor care nu au fost acceptate inca.

Pentru integrarea acestei functionalitati am folosit pentru afiasrea butonului un block. Acest block este inclus in meniul principal care apare in toate paginile, includere care se face direct fara a mai apela o functie php care sa incarce variabilele disponibile. Partea care se refera la butonul pentru afisarea pozelor ce asteapta afisare este inlcusa in fisierul templates/blocks/ButtonMyModerates.tpl si arata in felul urmator:

{g->callback type="moderate.getShowBlock"}

{if isset($block.moderate.ViewMyModerates.showUserBlock) and

block.moderate.ViewMyModerates.showUserBlock}

{g->callback type="moderate.countNeedApproval"}

<input type="button" onclick="window.location='{g->url arg1="view=moderate.UserModeration" arg2="return=1"}'"

class="inputTypeSubmit" value="{g->text text="Awaiting approval (`$block.moderate.ViewMyModerates.itemsNeedApproval` items)"}"/>

{/if}

Totusi pentru utilizatotii neautentificati aceste butoane nu ar fi avut nici un sens. Astefel trebuia verificat despre care tip de utilizator era vorba: neautentificat, simpu utilizator sau moderator. De asemena trebuia calculate numarul de imagini care urmau sa fie listate in pagina pentru a se afisa in textul butonului. Pentru aceste lucruri am folosit mecanismul de callback.

Astfel in timpul parcorgerii fisierului block pentru afisare erau apelate si aceste functii callback. Functiile apelate sunt incluse in clasa ModerateCallbacks din fisierul Callbacks.inc. Prima functie getShowBlock verifica daca butonul trebuie afisat si daca este cazul care tip de buton trebuie afisat. A doau functie apelata countNeedApproval va specifica cate imagini asteapta acceptarea pentru utilizatorul respectiv. Se observa din exemplul urmator ca rezultatul apelului este transmis prin crearea unui camp din sirul de variabile ale templatului:

switch($callback) {

case 'countNeedApproval':

list ($ret, $moderates) = ModerateHelper::getNeedApprovalCount();

$block =& $smarty->_tpl_vars['block']; $block['moderate']['ViewMyModerates']['itemsNeedApproval'] = $moderates;

break;

}

Daca tot am pomenit despre interfata cu utilizatorul si considerand ca am acoperit suficiente exemple referitoare la integrarea componentelor si fuctionalitatilor, in continuare o sa descriu si modul in care am integrat design-ul si organizarea aplicatiei mypixbusiness in componenta suport Gallery2.

Dezvoltare interfetei grafice (Integrarea temei Mypix)

Inpactul oricarei aplicatii web este dat in primul rand de pagina de start. In Gallery 2 dupa cum se observa si din imaginea urmatoare aceasta pagina nu era cu nimic deosebita fata de celelate pagini ale aplicatiei. Mai mult fiind foarte incarcata inducea o stare de confuzie noului utilizatorului. De aceea pagina de primire a aplicatiei mypixbusiness am incercat sa fie aerisita si sa includa actiunile si informatiile strict necesare.

Fig Pagina de start in Gallery2

In primul rand am inclus log-ul care in aceasta pagina este mult mai mare decat in restul aplicatiei. Apoi am inclus o scurta informare cu privire la scopul aplicatiei. Urmatorul pas pentru un utilizator ar fi sa se autentifice sau sa creeze un cont nou. Ultimul lucru pe care l-am inclus a fost partea de a cautare de imagini, aceasta fiind functionalitatea de baza a aplicatiei pentru utilizatorii neautentificati. Dupa cautare butonul de inchiriere este disponibil utilizatorul fiind redirect catre pagina de autentificare. Dupa autentificare poza este adaugata in cosul de cumparaturi.

Fig. Pagina de start in MyPIXbusiness

Deoarece aceasta pagina era complet diferita de cele standard oferite de Gallery2 a trebuit sa realizez o pagina noua. Dar pentru integrarea ei am dorit sa pastrez structura aplicatiei Gallery bazata pe view-uri pentru afisarea paginilor. Problema a fost ca exista doar patru tipuri si anume: „VIEW_TYPE_SHOW_ITEM” pentru afisarea imaginilkor si a albumelor, „VIEW_TYPE_ADMIN” panru zona de administrare a aplicatiei, „VIEW_TYPE_PROGRESS_BAR” pentru afisare barei de progres pentru operatiile care necestita o perioada mai lunga de realizare, „VIEW_TYPE_ERROR” pentru eventualele erori in aplicatie care duc la imposibiliatea afisarii unei pagini. Niciunul dintre aceste tipuri nu era adecvat pentru pagina de inceput, astfel am fost nevoit dezvolt un nou tip si anume „VIEW_TYPE_INDEX”.

Acest lucru a insemnat aducerea de modificari in nucleul Gallery2. Astefel am modificat clasa GalleryTheme unde am definit acest tip de view si am adaugat functie showIndexPage. Clasa GalleryTheme trebuie extinsa in fiserul theme.inc inclus in toate temele cu rol de definire a temei. In cazul nostru aceasta calsa este MypixTheme si pentru a folosi noul tip de view trebuie sa implementeze functia showIndexPage.

function showIndexPage(&$template, $item, $params) {

$ret = $this->loadCommonTemplateData($template, $item, $params,

array('systemLinks'));

if ($ret) {

return array($ret, null);

}

return array(null, 'index.tpl');

}

Se observa ca aceasta functie returneaza si pagina ce va fi afisata in cazul ca aceast view este apelat. Pentru apelarea acestei pagini in fisierul index.php din radacina aplicatiei am redirectat cererea catre pagina IndexPage din nucleu.

if ($isAnonymous) {

$path = $urlGenerator->generateUrl(

array('view' => 'core.IndexPage', array('forceFullUrl' => true)));

}

Bineinteles ca a trebuit apoi sa creez o clasa IndexPage care in functia getViewType sa returneze tipul view-ului nostru. Pe langa aceasta tot aici am implmentat si un sistem de subview care permite includerea in acest cadru in loc de formularul de autentificare de exemplu a formularului de inregistrare din modulul Register. Aceasta functionalitate a fost folosita si pentru a integra modulul OpenID.

function getViewType() {

return VIEW_TYPE_INDEX;

}

Am dorit ca in pagina sa fie afisate cat mai multe poze. In tema initiala se definea numarul maxim de poze pe orizontala si cel pe verticala, pagina fiind organizata cu un tabel. Din aceasta cauza daca numarul pozelor pe orizontala era setat prea mare ar fi avut de suferit utilizatorii care foloseau rezolutii mici pentru monitor. Ei ar fi trebuit sa foloseasca bara orizontala de derulare, lucru destul de incomod. Daca numarul pozelor pe orizontala ar fi fost prea mic atunci pentru utilizatorii cu rezolutii mari ar fi aparut un spatiu gol nefolosit in care ar fi incaput alte poze.

Fig. Afisarea continutului unui album in Gallery2

De aceea in noua tema am schimbat modul de afisare. In loc de numarul de coloane si cel de linii se putea definii acum un singur numar si anume cel toatl al pozelor dintr-o pagina. Afisarea nu se mai facea cu tabele ci cu div-uri. Acest lucru permite ca pe orizontala sa incapa atatea poze cate rezolutia monitorul permite. Daca rezolutia folosita era mica atunci pe orizontala nu incap multe poze si utilizatorul probabil va fi nevoit sa deruleze vertical pagina. Dar derularea verticala este uzuala, utilizatorul putand sa se foloseasca si de rotita de derulare a mouse-ului pentru acest lucru.

Fig. Afisarea continutului unui album in MyPIXbusiness

Tot pentru a mari numarul de imagini ce puteau fi afisate intr-o pagina detaliile referitoare la poze sunt ascunse. Si actiunile ce puteau fi efectuate asupra unei poze au fost ascunse. Nici in vechea tema lisat de actiuni nu era afisate, ele fiind organizate intr-un combobox. Datorita motivelor de natura estetica nu am mai folosit acest lucru. Am creat doua butoane care vor afisa informatile respectiv actiunile pentru fiecare imagine. In plus avand in vedere ca scopul aplicatiei este de a stimula inchirierea aceasta actiune am facut-o vizibila langa cele doua butoane.

Pentru afisare informatilor si a actiunilor am vrut sa creez impresia de continuitate. Acestea coboara alunecand din cadrul ce contine imaginea. Am realizat acest efect folosind libraria Java Script Script.aculo.us, incercand sa creez o miscare naturala, astfel incat aceste informatii sa nu apara brusc sa forteze ochiul sa se obisnuiasca cu aceasta aparitie. Si in lumea reala lucrurile nu apar sau dispar subit, ci ele se misca fluent.

Apoi m-am concentrat asupra vizibilitatii deverselor functionalitati. Astefel am incercat sa afisez cat mai intuitiv si cat mai evident pentru utilizator diversele optiuni, dar fara a incarca pagina. Totodata am incercat sa grupez diversele functionalitati prin abordarea de stiluri diferite de afisare. Datorita modulelor Linkcheckout si Moderate au aparut pe langa afisarea imaginilor dintr-un album inca doua tipuri de afisare. Am creat astfel o zona in care am inclus trei butoane pentru fiecare dintre aceste module.

Pentru afisare standard, adica cea organizata pe module am creat un buton intitulat „Uploaded” cu intelesul ca aici sunt pozele incarcate de utilizator. Pentru acest lucru am folosit si modificat modulul Useralbums. Acest modul permite crearea unui album specific pentru fiecare utilizator. Astfel utilizatorul are drepturi doar asupra acestui album si a subalbumelor create. Pentru restul pozelor are doar drepturi de vizualizare si inchiriere. Astfel la apasarea butonului „Uploaded” sau imediat dupa autentificare utilizatorul vizualizeaza continutul acestui album.

Pentru modulul Linckcheckout am creat butonul „Rented”, adica aici utilizatorul poate sa vizualizeze toate pozele inchiriate si de aici poate sa foloseasca adresa lor permanenta. Iar pentru modulul Moderete am creat butonul discutat deja, buton ce afiseaza dupa caz pozele care asteapta sa fie acceptate pentru utilizator sau pozele ce urmeaza sa fie moderate pentru moderatori.

Aceasta zona am incadrat-o in dreptunghiul 1 din figura anterioara. O alta zona noua de functionalitati este cea incadrata de dreptunghiul 2. Aceasta zona se refera la postura de cumparator a utilizatorului. Astfel aici se afla link-uri catre cosul de cumparaturi, catre formularul de achizitionare a punctelor sau a istoricului de tranzactii. Folosind metoda callback tot aici am afisat si cate produse sunt in cosul de cuparaturi ale utilizatorului sau cate puncte de credit mai are in cont.

Deoarece in Gallery 2 nu exista o metoda standard pentru afisare pozelor, initial aceasta afisare fiind folosita doar in nucleul aplicatiei, diversele module care au avut nevoie si ele sa afiseze imagini nu au folsit o metoda unifoma pentru realizarea acestui lucru. Astfel pentru modificarea aspectului aplicatie se creaza o noua tema, lucru concretizat prin adaugarea ei in director themes. Dar aici se poate modifica numai aspctul cadrului aplicatie si a afisarilor standard implementate in nucleu ca de exemplu partea de administrare, partea de afisare a imaginilor dintr-un director, partea de editare a imaginilor.

Dar modulele defineau fiecare partea de afisare. Majoritatea afisarilor nu au necsitat schimbari direct in paginile modulul. Datorita schimbarilor majore in structura paginii standard de afisare a pozelor, a fost necesara modificarea urmatoarelor module: Linkcheckout, Moderate, Search. Aceste module afisau imaginile dupa alte criterii decat cel al albumului din care facea parte. Astfel pe langa designul cadrelor imaginilor trebuia adaugat si un sistem de paginatie. Am folosit si sitemul celor doua butoane pentru informatii si actiuni. La modulele linckcheckout si moderate am putut pastra parte de informatii dar in partea de actiuni am folosit functionalitatile pe care aceste module le ofereau. Pentru modulul search am procedat invers. Astfel pentru pozele cautate utilizatorul putea sa foloseasca aceleasi actiuni ca si cand ar fi navigat la ele. Dar in partea de informatii am folosit scoaterea in evidenta a cuvintelor dupa care s-a facut cautarea.

Datorita acestor diferente intre module nu am putut folosi o pagina de afisare unica, dar am impartit fiecare parte intr-un fisier, aceste fisiere putand fi refolosite de toate modulele Un exemplu de includere a unui astfel de fisier este urmataorul:

<div id="actions{$child.id}" class="miActions" style="display: none">

{g->theme include="ItemLinks.tpl" item=$child links=$child.itemLinks useDropdown=false}

</div>

Daca se doreste o parte diferita fata de cele standard, de exemplu afisarea informatilor pentru modulul search, atunci trebuie creat un nou fisier in interiorul modulului cu functionalitatea specifica. Includerea acestui fisier se face in modul urmator:

<div id="infos{$child.id}" class="miActions" style="display: none">

{g->block type="search.infoCell" result=$child}

</div>

Odata finalizate aceste modificari, dezvoltarea lor facandu-se folosind browser-ul Mozilla Firefox versiunea 2.0.0.14 a trebuit sa testez aplicatia si cu celelate browser existente pe piata. Astfel am testat aplicatia in Internet Explorer 6, Internet Explorer 7, Mozilla Firefox rc3 si Opera. Din pacate au existat multe incopatibilitati care au necesitat folosirea a tot felul de trucuri. Identificarea si folosirea lor a fost un proces ce a consumat mult timp.

Dezvoltari ulterioare

Dezvoltarea aplicatiei este impartita in iteratii de scurta durata. Cate o noua iteratie reprezinta un nou release, dar si o rafinare a cerintelor, o etapa de refactorings. Prin aceasta se doreste o mai buna organizare arhitecturala a codului si o modificare a functionalitati inspre o utilitate mai mare. Fiecare release este programat odata pe luna, si odata cu acesta se programeaza si iteratiile viitoare: ce functionalitati se amana pentu o viitoare iteratie si ce functionalitati se amana pentru o perioada indelungata.

Fiecare dintre aceste planuri de dezvoltare sunt impartite in trei parti:

partea de mentenanta (rezolvare de erori – bug);

partea de optimizari

partea de noi functionalitati

Pentru partea de mentenanta, avem o aplicatie instalata pe unul dintre server-ele proprorii, o aplicatie web numita trac (footnote) destinata comunicarii cu clientii. In aceasta aplicatie se raporteaza erorile, se trec cerintele pentru noile functionalitati etc. Aceasta aplicatie gestioneaza asa numitele tickete care in mod uzual se refera la cate o eroare depistata de catre client. In felul acesta, eu pot sa verific si sa reproduc eroarea, sa o analizez si sa o planific inspre rezolvare pentru o anumita etapa (milestone). Mai multe milestone (etape de dezvoltare) definesc o versiune. Tot aceasta aplicatie defineste si modul prin care eu public documentatia referitoare la una sau mai multe functionalitati. Aceasta documentatie este scrisa in trac, sub forma unui asa numit wiki (footnote). Astfel, fiecare etapa de dezvoltare rezolva o suita de erori raportate. Fiecare etapa de dezvoltare implica si crearea unei documentatii in format digital referitoare la bug-urile si functionalitatile dezvoltate.

Partea de optimizari are un caracter ce doreste sa ofere o mai buna calitate experientei utilizarii MyPIXBusiness de catre utilizatori. Fiind inca la inceput, numarul de utilizatori este mic, iar pe masura ce va creste, aceste probleme de optimizari vor fi din ce in ce mai prioritare. Momentan ele au fost doar semnalate si planificate pentru versiuniile viitoare, fara a fi bine delimitate in timp. Printre aceste probleme de optimizare doresc sa enumar:

Folosirea unei companii (third-party) externe pentru media streeming si hosting. Este binecunoscut faptul ca principala caracteristica a unei applicatii web este viteza de operare. Iar aceasta viteza este determinata de bandwidth si de network delay. Folosind o companie gen Akamai (http://www.akamai.com/) vom putea sa tinem fisierele media (poze, filme etc) pe server-ele akamai, iar aplicatia noastra sa fie cea care sa valideze doar accesul la aceastea. Nu voi detalia aici solutia propusa, dar ea se bazeaza pe oferata Akamai (http://www.akamai.com/html/solutions/index.html) si pot spune ca informatia media aflata pe internet provine in procent de 10%-20% de pe server-ele Akamai, si site-uri gen http://youtube.com sau http://adobe.com o folosesc. In acest sens a fost dezvoltat modulul softlinks, pentru a tine cont de aceste viitoare optimizari. Modulul softlinks a separat gestiunea de legaturi interne (internal links- URL's) de partea de partea de hosting.

MyPIXBusiness suporta in momentul de fata existenta unei singure baze de date si instantierea mai multor applicatii MyPIXBusiness pe mai multe server-e. Dorim sa optimizam acest pas pentru a avea cat mai multe server-e, un asa numit CLOUD, care sa deserveasca cereri venite din partea utilizatorilor aflati pe o arie georafica raspandita. Astfel, server-ele din Romania vor procesa cererile venite din partea utilizatorilor aflati in Romania, iar server-ele din USA, cererile venite din acea regiune. Aplicatia se va comporta totusi ca una singura. Aceasta optimizare este o necesitate pentru a putea procesa cereri venite din partea milioanelor de utilizatori, pentru o perioada de timp scurta.

Crearea unui asa numit Cluster de baze de date. In vederea solutiei exprimate mai sus, se poate ca o baza de data sa se instaleze distribuit pe mai multe calculatoare. Calculatoare vor fi vizibile ca un tot unitar, ele avand grija sa-si faca backup una alteia, precum si sa deserveasca o mica parte din cererea provenita de la utilizator.

Ultimul aspect pe care dezvoltariile ulterioare vor trebui sa-l acopere este dezvoltarea de noi functionalitati. Cerintele definite pana acum au fost clare si indeplinite. Se mai doreste in continuare o mai rafinata sincronizare intre produsele eBay si pozele MyPIXBusiness. Toate aceste mici schimbari vor fi facute pana cand aplicatiei i se va face o campanie publicitara, si prezentare in cadrul conferintei eBay de la sfarsitul acestui an.

Printre functionalitatile exprimate spre a fi dezvoltate in viitor, mentionez:

integrarea cu o componenta ERP (footnote), prin care fiecare magazin sa-si poata gestiona stocul produselor precum si situatia vanzarilor ce au fost facute prin intermediul eBay.

integrarea cu o aplicatie CRM (footnote), prin care sa se gestioneze suportul pentru aplicatie: mentionez aici clienti cu regim preferential, linia de telefoane (hot lline) etc.

Concluzii

Dezvoltarea unui sistem bazat pe integrarea de componente (CoTS) este viabil pentru siteme mici si medii. Exista multe componente dezvoltate generic si pot fi intrebuintate ca parti integrante ale unor sisteme mai mari.

Comunitatile Open Source sunt perfecte cand vrei sa inveti ceva. In interiorul lor se gasesc oameni deosebit de valorosi ca si experienta profesionala, iar atitudinea este indreptata spre ajutorul celorlalti. Intotdeauna primeaza sa ajuti pe cel de alaturi, decat sa termini o anumita functionalitate. Rareori dedline-urile sunt prioritare, si deseori ele sunt respectate cu strictete, decat in cazul companiilor private. Experienta si relatiile care se leaga in procesul dezvoltarii sunt poate cel mai importante lucru. Lateral discutiilor legate de dezvoltare, afli despre tehnologii, algoritmi sau solutii care iti sunt utile in alte proiecte sau contexte.

Aceste comunitati iti ofera si modalitatea de a testa capacitatea proprie de a arata altora, de a invata pe altii, de a te exprima.

Solutiile de implementare ce se gasesc in proiectele Open Source variaza de la solutii complexe si optimizari deosebite, la solutii banale, elementare pentru a rezolva problema pe termen scurt, pentru ca apoi sa se revina asupra ei atunci cand este nevoie (respectiv, daca o va cere comunitatea).

In alegerea unei componente, evaluarea deciziei se poate face numai dupa un timp mediu/lung, in functie de evolutia respectivei comunitati si in multe cazuri implica si noroc.

Problemele ce apar in timpul unei abordari de dezvoltare orientata pe componente.

in cazul unor sisteme mari, intotdeauna intevin functionalitati care nu pot coexista cu subansamnle ale componentelor existente.

libraria de interfatare a componentei din versiunea 1  difera de aceasi componenta din versiunea 2.

de cele mai multe ori dumentatia nu este completa, trebuid sa te bazezi pe ajutorul celorlalti membri

timpul alocat integrarii nu este, asa cum s-ar astepta, mult mai mic decat timpul in care s-ar fi dezvoltat componenta initiala pentru ca intervine timpul alocat curbei de invatare si analiza a respectivei componente. Deseori e nevoie de a face o analiza comparativa cu alte componente ce ofera functionalitati similare

fiecare componenta trebuie testata si nu se poate merge doar pe analiza altor sisteme asemanatoare.

in multe cazuri, componenta care satisface cel mai bine cerintele sistemuluii, nu satisface in schimb ingradirile legale (legate de licenta). Mai ales in cazul sistemelor informatice cu scop comercial, este nevoie de consultanta legala.

comunicarea la distanta este defectuasa, cu toate ca tehnologia a reusit sa micsoreze mult distantele. In prezent exista video-conferinte, mesagerie instanta (IM- chat), forumuri si grupuri de discutii, diferite unelte de modelare UML online, dar toate acestea nu pot substitui nevoie de a folosi "creta si tabla", sau pixul si hartia in discutia directa cu colaboratorii.

timpul alocat proiectarii arhitecturii unei componente Open Source este net mai mare decat atunci cand este facuta de o echiipa bine bine localizata geografic.

dimensiunea sistemului obtinut prin integrare este net mai voluminos, pentru ca fiecare componenta aduce functionalitati pe care sistemul nu e utilizeaza intr-o versiune incipienta.

In schimb, avantajajele sunt multiple:

exista o comunitate care doreste sa testeze deja componenta (sistemul).

exista o implementare care de cele mai multe ori este superior calitativa uneia dezvoltate ad-hoc. Timpul alocat mentenantei este mult mai mic.

standardele Open Source ofera componentelor o interfata comuna, o metoda de a interactiona, o astfel de componenta interactioneaza mult mai bine cu alte componente decat daca standardul de comunicare ar fi apartinut unei anumite companii. Dezvoltarea respectivei componente este usor asigurata numai prin faptul ca este deschisa colaborarii cu alte componente.

alegerea componentei implica o curba de invatare, ceea ce obliga pe cel care alege componenta sa inteleaga mai bine cerintele sistemului sau si sa prevada din timp probleme ce ar putea apare. In caz obisnuit, cazurile extreme de test nu ar fi fost atat de evidente la inceput si ar fi fost impinse catre etape finale ale dezvoltarii.

rezolvarea anumitor bug-uri si testarea acestora te ajuta in a te familiariza cu diferite platforme de programare, cu diferite limbaje de programare, cu diferite tehnologii.

o componeta Open Source are acelasi caracteristici de performanta ce trebuiesc analilzati, la fel ca orice produs software. Aceste analize sunt publice si pot fi utilizate ca si criterii de evaluare ale altor componente private, apartinand unor companii.

persoanle dintr-o comunitate Open Source sunt legate de pasiunea pentru respectivul produs.

exista posibilitatea sa recrutezi pentru sistemul tau, persoane competente, deja familiarizate cu contextul sistemului, si mai mult, motivate de un crez propriu, acelasi care l-a determinat initial sa contribuie si comunitatii unde le-ai intalnit.

exista multe firme companii care recruteaza dezvoltatori din cadrul comunitatiilor, mai ales cand una dintre aceste companii doresc sa foloseasca respectiva componenta.

Fiecare comunitate este unica. Unele au mai multa experienta, altele au mai mult entuziasm. Este o experienta deosebita sa poti prelua o experienta din cadrul unei comunitati si s-o oferi alteia.

Consider ca aceasta perioada, a dezvoltarii sistemului MyPIXBusiness printr-o abordare de tipul integrarii de componente, in special cele Open Source, a fost una de acumulare de informatie teoretica si practica deosebita, de experimentare a diferitelor modalitati de comunicare la distanta. Procesul de dezvoltare software nu este un proces individual, ci este unul colaborativ. Sucesul unui proiect consta in capacitatea de a colabura si comunica cu ceilalti, ce a transmite cat mai multe imformatii clare si la obiect. In acest sens, mi-au fost de real ajutor servicii ca: Del.ici.us (http://del.icio.us), Google Groups (http://groups.google.com), Google Docs (http://docs.google.com) etc.

Consider ca proiectul a fost finalizat complet si scopul propus a fost pe deplin atins. Proiectul dezvoltat are un viitor comercial si este de real interes. Exista un prioct de investiti si de marketing care sustine acest proiect, iar sucesul sau tehnologic, de oportunitate si personal se va reliefa prin utilizarea sa de cati mai multi utilizatori.

Similar Posts