-
Da, PHP este probabil cel mai popular limbaj de programare server side pentru Web in acest moment. Si probabil va ramane asa pentru o vreme indelungata.
Este probabil cel mai bun!
Nu tocmai, dar nu te opri din citit…
De ce este atat de usor de invatat?
In primul rand, datorita sintaxei. Dar motivul pentru care este asa de popular nu este pentru ca ar avea cea mai buna sintaxa! Eu am inteles aproape imediat sintaxa cand am vazut primul exemplu de “hello world”, de ce? Pentru ca am studiat C la scoala, iar persoanele care vin din lumea Java au aceeasi senzatie.
Dar sa vedem cateva limbaje de programare care folosesc aceasta sintaxa: Java, C#, JavaScript, Perl, Go, PHP si, bineinteles, C si C++, adica aproape toate platformele si cam toata piata.
Dar spre deosebire de (majoritatea) limbajelor listate mai sus, este cel mai simplu pentru incepatori! Nu trebuie sa creezi o functie “main”, o clasa sau altceva, incepi direct!
Partea buna este ca poate sa fie atat de complex pe cat vrei sau cat ai nevoie. Acum exista clase si interfete similare cu Java, mostenire orizontala cu “traits”, programare functionala cu closures si functii anonime, generatori, iar, daca esti cu adevarat hipster, pana si goto!
Dar PHP nu suna chiar asa de rau…
Dar trebuie sa amintim un detaliu foarte important: PHP nu a devenit popular datorita caracteristicilor de mai sus, in schimb caracteristicile au aparut datorita popularitatii, chiar si “goto”. Nu inteleg de ce cineva ar adauga goto intr-un limbaj dupa mai bine de 10 ani de existenta, dar asta nu este treaba mea si nici nu este relevant pentru acest subiect.
Limbajul a devenit foarte popular cu versiunile 3 si 4. Pana cand a aparut un model decent de OOP era deja foarte popular! In special acum, de cand cu versiunea PHP 7, cand arata mult mai mult ca un limbaj decent de programare, dar acum 10 ani nu era aceeasi poveste.
Dar node.js probabil il va depasi!
Sigur ca da… va amintiti de Ruby? Python? Si altele…
Daca te gandesti la PHP, are un mare avantaj si dezavantaj totodata, este cat de “stateless” se poate.
Cu PHP ai impresia ca nu stii nimic despre lume, trebuie sa faci bootstrap (initializezi) totul de fiecare data. Avantajul este ca in cazul unui memory leak, in majoritatea cazurilor, este ok. Cand requestul se termina totul se va curata/elibera si nimanui nu-i va mai pasa. Si PHP avea multe memory leak-uri la inceput, pana sa devina foarte popular si nimanui nu parea sa-i pese.
Cand au inceput sa apara cron job-urile si alte procese de lunga durata, abia atunci a devenit o mare problema si a aparut nevoia de garbage collection explicit. Acesta a fost adaugat in versiunea 5.3 care aparut abia in 2009.
In mod normal, un proces care ruleaza continuu nu ar trebui sa fie un dezavantaj, dar morala povestii este ca nu este neaparat nici avantaj.
Nimeni nu va construi urmatorul Google cu el, dar macar niste blog-uri? Sau, si mai bine, niste magazine virtuale?
Nu este capabil de ceva precum motorul de cautare Google, si e ok pentru ca nu a fost facut pentru asta.
Un alt exemplu pentru “nu neaparat cel mai bun castiga” este ca WordPress este cea mai populara platforma de blogging.
Chiar mai mult, lumea foloseste WordPress in tot felul de moduri bizare, practic poti face orice cu el! Si nu ar trebui sa reporosam asta oamenilor care il folosesc, nu e ca si cum te uiti la ce piese sunt in cuptorul cu microunde atunci cand il cumperi, nu-ti doresti decat sa incalzeasca mancarea. Oamenii care forteaza limitele platformei WordPress fac la fel, ei pot sa faca ce au nevoie si nu exista un motiv bun pentru care sa nu o faca.
Ar trebui sa-l folosesc?
Sa luam doua exemple pozitive: Yahoo! si Facebook.
Yahoo! il foloseste de foarte mult timp in unele din produsele sale si, uneori, intr-o combinatie cu alte limbaje de programare.
Facebook l-a folosit de la inceput pentru ca este usor de invatat. Ei au impins limitele limbajului in mai multe randuri prin: HipHop for PHP si, mai recent, Hack, care a reprezentat si cea mai importanta motivatie din spatele PHP 7.
De ce atata deranj pentru un limbaj de programare? Pentru ca este usor de invatat si utilizat!
De obicei, este mai important sa lansezi “acum” decat sa ai ceva “perfect” mai tarziu, mai ales in universul world wide web.Este un motiv foarte bun pentru care un limbaj care nu este in mod sigur “cel mai bun”, dar este usor de folosit este atat de popular online, in timp ce un limbaj de programare ca C, care este mult mai dificil de invatat, este atat de popular offline.
Cu alte cuvinte, chiar daca PHP nu este cel mai bun, este in general suficient de bun.
-
IT-ul este probabil unul dintre cele mai dinamice domenii de pe piata de locuri de munca, iar oamenii reprezinta o resursa foarte importanta si totodata limitata.
Si totusi oamenii vin si pleaca destul de des, iar cei mai multi se plang de lipsa motivatiei.
Totul se va termina acum cu acest ghid simplu pentru motivarea programatorilor si nu numai!
Programatorii au nevoie de probleme “challenging”, tot timpul spun ca vor lucruri mai noi si mai challenging, nu?
Da-i un challenge adevarat! Pune-l sa obtina specificatii de la un client care nu stie ce vrea, lasa-l sa se chinuie, eventual lasa-l singur, sa simta adrenalina unei provocari adevarate!
Trebuie retinut ca un programator nu este decat un Project Manager reprimat, da-i sansa sa se exprime!
Dar nu trebuie sa te opresti aici, nu exista provocare mai mare decat sa lucrezi la mai multe lucruri in acelasi timp. O idee buna ca sa maresti complexitatea este sa-i dai ocazia sa lucreze la mai multe proiecte in paralel. Da-i ocazia sa aiba mintea ocupata cu lucruri cat mai diferite, diversitatea este mereu buna, nu?
Un secret pentru a exploata diversitatea la potential maxim este sa aiba atributii diferite pe diferite proiecte, poate un proiect care implica management sa alterneze cu unul de mentenanta. Este pacat sa nu aiba parte de suficienta diversitate!
Scrie prea mult cod? Trebuie sa faci ceva in sensul asta! Atunci cand un programator sta concentrat si lucreaza la ceva nu este nimic altceva decat un strigat disperat dupa atentie. Trebuie sa faci ceva ca sa intrerupi cercul acesta vicios, este de datoria ta ca manager sa-l salvezi!
Trebuie sa gasesti un mod sa-l intrerupi: incearca cu cateva sedinte, ajuta mereu. Daca pare dornic sa iasa din sedinta, este doar un semn ca isi doreste sa intre in urmatoarea sedinta!
In timp o sa observi ca oamenii cu cat sunt mai buni la scris cod, cu atat isi doresc mai tare sa nu mai aiba timp sa faca asta. Totusi, nu iti va spune asta, sau, chiar daca iti spune, este doar pentru ca el nu stie ce-si doreste cu adevarat.
Iar pana la urma, daca ii place atat de mult sa scrie cod, poate ar trebui sa-l duci la nivelul urmator si sa-l pui sa si-l testeze singur. Pana la urma, daca el l-a scris, cine altcineva sa stie mai bine cum sa-l testeze?
Mai este un lucru de mentionat legat de cod in contextul unui challenge. Cand vine un programator la interviu, ce spune el de fiecare data este “vreau sa invat lucruri noi”. Cum aplici aceasta dorinta? Simplu, trebuie doar sa-l pui sa faca ceva ce nu stie! Asa ii prezinti ceva ce este nou si challenging in acelasi timp. Este programator PHP? Nu-i nimic, da-i un proiect de Java! Este programator de Java? Nimic mai simplu, da-i un proiect Objective-C! Poate uneori este greu sa gasesti noi tehnologii pe care nu le cunoaste si pe care nu a incercat deja sa le invete, dar fericirea unui programator nu este un lucru usor de obtinut!
Sa nu cazi in greseala da a acorda salarii corelate cu postul, nu-ti face griji, salariul este confidential, nu vorbeste nimeni despre el. In special atunci cand recomanda un prieten, in mod sigur nu o sa se intereseze de salariul care i-a fost oferit acestuia, doar este confidential, ar fi lipsa de etica profesionala sa se intereseze, nu ar trebui sa-ti faci griji in acest sens.
Si, ca tot am mentionat interviuri, poate uneori te gandesti ca procesul de angajare trebuie sa produca rezultate coerente. Nimic mai gresit, de ce este nevoie cu adevarat? Asa cum am spus si mai devreme: Diversitate! Am citit un articol acum ceva vreme despre firme chinezesti care angajeaza femei frumoase pentru a stimula mediul. Mereu trebuie sa gasesti moduri noi de a integra ultimele tendinte, dar daca tu ai doar posturi tehnice deschise, trebuie sa te descurci cu ce ai. Poate te gandesti ca a angaja pe criterii estetice poate fi problematic uneori, mai ales cand sunt posturi tehnice. In acest caz trebuie sa-ti dai seama ca motivarea trebuie gandita si la scara larga. Da, poate unele echipe o sa se adapteze mai greu la acesti noi membri ai echipei, dar daca persoana respectiva o sa se faca remarcata in orice fel, inseamna ca ai facut o treaba buna!
Sa nu uitam de traininguri si conferinte. Cand ai vorbit ultima oara cu un programator si a zis ca nu-si doreste un training sau sa mearga la conferinte de specialitate?
Motivatia trebuie mentinuta, ca orice alta dorinta. Exista doua componente: dorinta pentru ceva si, nu in ultimul rand, lipsa acelui ceva dorit. Daca iti doresti ceva este pentru ca nu il ai inca, nu-i asa?
Daca nu ai inteles deja, solutia este simpla: nu-l lasa sa aiba acel ceva dorit. Vrea un training? Organizeza trainingul, apoi ai grija sa trimiti persoanele care sunt cel mai putin interesate la el. El o sa vada ca se poate, chiar daca nu pentru el.
Poate asta o sa fie uneori un challenge si pentru management, dar cu multa atentie este realizabil! Pastreaza dorinta vie!
Un alt sfat legat de traininguri: pentru a pastra dorinta vie este util sa-l trimiti la traininguri de care nu este interesat, dar de care este interesat altcineva. Asa o sa ai mereu angajati interesati de traininguri si care fac traininguri, dar care sunt motivati in continuare!
Atunci cand munceste nu trebuie sa vada utilitatea muncii lui, este foarte important. Daca o sa o vada, cum o sa mai fie motivat sa continue? E ca si cum urci un munte, de ce sa-l mai motiveze urcarea daca a vazut cat este de sus? Trebuie sa ai grija sa nu-si dea seama unde a ajuns: este bine sa nu aiba acces la statistici ca nu cumva sa aiba un sentiment de finalitate, de tinta atinsa, de tel realizat, cum ar mai putea fi un challenge atunci?
Si nu uita sa nu-i arati incredere, trebuie sa o construiasca singur. Trebuie sa-i dai o tinta si apoi sa o mentii doar o tinta. Intr-adevar, o tinta atinsa provoaca placere si satisfactia muncii, dar oare tu asta iti doresti sa-i oferi? Gandeste-te la asta putin, de fiecare data cand il lauzi pentru munca realizata o sa mai fie motivat? De ce sa incerci sa-l stimulezi sa se autodepasasca cand poti sa-l stimulezi sa atinga o tinta pe care nu o poate atinge. Nu-i arata ca ai incredere in el, lasa-l sa se chinuie, sa simta challenge-ul.
O vorba spune: “drumul cunoscut e cel mai scurt”. Totusi, unii incearca sa automatizeze lucrurile rudimentare. Practic incearca sa scape tocmai de drumul cunoscut. Efectiv, daca il opresti din automatizarea proceselor il ajuti sa ramana ocupat, il ajuti sa aiba o minte ocupata, iar o minte ocupata este o minte activa!
Si, in al doilea rand, cu aceasta abordare il ajuti sa-si mentina locul de munca. Poate el nu-si da seama, dar daca o sa-si piarda utilitatea cand o sa ramana tocmai fara task-urile pe care, pana la urma, le si cunostea atat de bine, pentru ca le-a facut de atatea ori… Programator sau nu, nu trebuie sa-l lasi sa fie inlocuit de un robot!
In al treilea rand este satisfactia drumului cunoscut – nu-l lasa sa deturneze de la el, oricum, la cat este de cunoscut, ar trebui sa fie destul de scurt.
Nu in ultimul rand trebuie sa-l inveti importanta managementului. Trebuie sa vada ca il poti ajuta, ca tu esti cheia catre succesul lui. Ca sa ii arati acest lucru, trebuie mai ales sa ai incredere in tine. Incearca sa organizezi o petrecere fara sa-l chemi. Nimic nu spune mai mult “puteam sa fiu si eu acolo” decat faptul ca nu ai fost acolo.
Un alt mod este sa-ti organizezi o calatorie de afaceri intr-o locatie exotica. Nu-ti face griji, nu este important sa ai efectiv ce sa faci acolo. Cat timp esti acolo, nu uita sa te distrezi, este foarte important sa stie si el asta. Cand o sa fie obositor trebuie sa-ti aduci aminte ca nu faci asta pentru tine, faci asta pentru el si imaginatia lui!
Poate unele sugestii nu functioneaza la toata lumea, dar trebuie sa incerci sa combini cat mai multe pentru a avea parte de un succes real si programatori cu adevar motivati!
Nu incerca sa identifici aceasta lume utopica, pentru ca orice asemanare cu realitatea cotidiana este pur intamplatoare.
-
Gata, razboiul s-a terminat, PHP7 s-a lansat, iar PHP6 va ramane doar o legenda, o poveste a versiunii care nu a existat.
Dupa o vreme nu cred ca se mai astepta nimeni sa apara, au trecut totusi aproape 10 ani, dintr-un total de 20 de ani de viata pentru PHP.
Dar cum se poate ca o versiune atat de asteptata sa nu apara de loc?
Sa incepem cu inceputul, cand, acum aproximativ 10 ani, PHP devenea un limbaj “serios”. Dupa versiunea PHP5, model obiectual avea in sfarsit vizibilitate specifica pentru metode si proprietati, obiectele nu mai erau copiate, ci trimise prin referinta. Aceste facilitati au generat o multitudine de framework-uri obiectuale, care acum erau destinate si mediului enterprise, nu doar pentru site-uri micute.
In tot acest context exista o problema, internationalizarea.
Asa a aparut PHP6, trebuia sa fie un limbaj care sa foloseasca nativ Unicode, mai specific UTF-16. Asa totul se va procesa intr-un format unic si international.
Proiectul a fost pornit si intretinut de Andrei Zmievski. Poate astazi nu multi au auzit de Andrei, dar acum 10 ani era foarte popular pentru proiecte precum Smarty si PHP-GTK.
Dupa cativa ani proiectul a ramas intepenit, iar atunci a aparut PHP5.3. Acesta, desi aducea schimbari importante, nu era o versiune majora pentru ca inca mai era speranta ca intr-o zi va fi un PHP6.
Existau totusi niste oameni plini de speranta! Si mai ales, care au fost gata sa monetizeze speranta!
Fie ca unii au fost autori, iar altii editori, ei stiau un lucru legat de carti (in special de cele tehnice) ca au niste lucruri clare: un public tinta si o perioada in care este relevanta.
Dar sa analizam si niste rezultate.
PHP 6 and MySQL 5 for Dynamic Web Sites: Visual QuickPro Guide (3rd Edition) (Peachpit Press – 2008) – Larry Ullman
Larry a scris mai multe carti, printre care: “PHP and MySQL for Dynamic Web Sites: Visual QuickPro Guide (2nd Edition)” si evident “PHP and MySQL for Dynamic Web Sites: Visual QuickPro Guide”.
Intamplator am avut ocazia sa rasfoiesc toate cele 3 carti, dar nu in ordinea cronologica ci pur intamplator am inceput cu “PHP and MySQL for Dynamic Web Sites: Visual QuickPro Guide (2nd Edition)”. Ce e interesant este ca similitudinea este izbitoare, practic a pus un 6 in titlu si in rest aproape ca nu a schimbat cartea de loc.
In general toate cartile Visual QuickPro Guide sunt carti pentru incepatori, iar de la o editie la alta lucrurile nu se schimba prea mult, doar se adapteaza.
Professional PHP6 (Wrox 2009) – Ed Lecky-Thompson, Steven D. Nowicki (Thomas Myer)
Interesant este ca in imagine apar 3 persoane, dar pe Amazon.com si pe Wrox apar doar doua nume, de asta am tinut sa-l trec separat, este vorba de Thomas Myer.
Ma intreb oare daca Thomas Myer a cerut sa dispara, sau a fost scos? E bizar sa ai numele pe o carte dar sa nu apari in lista de autori pe site-ul editurii.
Nu intamplator exista si o “Professional PHP5” – Ed Lecky-Thompson, Heow Eide-Goodman, Steven D. Nowicki, Alec Cove.
PHP 6/MySQL Programming for the Absolute Beginner (Cengage Learning PTR – 2008) – Andrew B. Harris
Este intradevar o carte bizara, nu exista un echivalent de PHP5, ba chiar pe site-ul scriitorului nu mai exista alta carte de PHP: .
Exista oare un motiv? In cazul lui Larry Ullman era un alt subiect atins, un alt public tinta, dar in acest caz e doar ciudat, un singur autor, o singura carte de PHP si intr-o versiune fantoma, publicata in 2008.
PHP 6 Fast and Easy Web Development (Cengage Learning PTR – 2008) – Matt Telles, Julie C. Meloni
Fara prea multa dificultate am gasit si: “PHP Fast & Easy Web Development” – Julie C. Meloni
Ciudatenia acestei carti este ca Matt Telles nu mai are alta carte de PHP, desi are de Python, C# si C++.
Ceva imi spune ca poate el a fost adus doar ca sa actualizeze cartea originala la noul context. Am crezut ca este doar o parere presonala, doar ca la o cautare pe Google am gasit ca este si Technical Reviewer pentru “PHP 6/MySQL Programming for the Absolute Beginner (Cengage Learning PTR)”, carte care a fost prezentata anterior.
Beginning PHP 6, Apache, MySQL 6 Web Development (Wrox – 2009) – Timothy Boronczyk, Elizabeth Naramore, Jason Gerner, Yann Le Scouarnec, Jeremy Stolz
Cartea originala a fost evident: “Beginning PHP, Apache, MySQL Web Development” – Michael K. Glass, Yann Le Scouarnec, Elizabeth Naramore, Gary Mailer, Jeremy Stolz, Jason Gerner
Au iesit Michael K. Glass si Gary Mailer, iar in locul lor a intrat Timothy Boronczyk.
PHP a fost un limbaj foarte la moda in perioada respectiva, iar PHP6 a fost foarte asteptat.
Cum se poate totusi asta? Cum se poate sa existe atatea carti de la edituri importante pentru un limbaj de programare care nu a existat? Raspunsul este simplu: lacomie.
Exista doua explicatii posibile: ori autorul a incercat sa acapareze piata cu o noua versiune, ori editura a vrut sa forteze nota, in speranta de a capta piata. Probabil speranta era ca in momentul cand ar fi aparut, ar fi avut cartile deja disponibile pentru livrare.
Acesta este un alt motiv pentru care nu era un plan bun ca versiunea PHP NG sa devina PHP6, ar fi insemnat sa apara o versiune de PHP si sa aiba deja o serie de carti scrise, ba chiar scrise de cativa ani.
Pun pariu ca atunci cand s-a votat intre PHP6 si PHP7 erau niste editori plini de speranta.
In continuare, va urez lectura placuta!
-
Acum 20 de ani, Rasmus Lerdorf a anuntat aparitia unui nou tool, numit PHP.
Eu am intalnit PHP in 2004, dornic sa fac paginile mele HTML mai dinamice. Cineva mi-a recomandat PHP pentru ca era foarte simplu si usor de folosit. Pentru ca instalarea parea destul de complicata, am folosit PHP Triad. In cateva minute am fost gata sa-mi incep experimentele si am fost cucerit de feedbackul instant oferit.
Pe atunci eram student si cursurile erau bazate pe Pascal si C/C++. Nu-mi placea Pascal pentru ca era deja depasit, iar C avea un sistem complicat de lucru cu memoria si in loc sa ma preocup de gandirea logica, trebuia sa ma preocup de alocarea de resurse.
Acest limbaj nou pentru mine avea sintaxa asemanatoare cu C, dar fara bataia de cap a managementului de resurse. Eliminand acest impediment, am reusit sa-mi dezvolt gandirea logica si chiar sa devin un programator mai bun in general, nu doar in PHP.
In perioada respectiva, PHP nu era considerat un limbaj “serios” de programare, mai degraba unul pentru incepatori. La unul din primele interviuri la care am mers, angajatorul mi-a spus pe un ton cicalitor: “PHP este o jucarie, haide la noi si o sa inveti programare adevarata in ceva serios, cum este FoxPro!” Acela a fost unul din momentele care m-au ambitionat sa ma fac programator PHP.
11 ani mai tarziu, inca pot spune ca este limbajul meu de suflet si ca probabil nu as fi avut o cariera ca programator fara el.
Care a fost prima ta interactiune cu PHP?
-
Ceva ce nu am abordat in blog-ul anterior au fost colectile. Hack vine cu o varietate de colectii pentru organizarea de date.
Structurile de date reprezinta o parte fundamentala a unui linbaj de programare, pentru ca acestea vor constitui modul in care informatia circula in aplicatie.
Pana la versiunea 5, PHP avea un singur tip de colectii de date, denumit “array”. Acest tip de date poate sa aiba trei moduri: array, hash table sau o combinatie intre cele doua.
In PHP 5 au fost introdusi o serie de iteratori pentru a facilita constructia de structuri. Din pacate si structurile rezultate aveau scopul sa ofere posibilitatea de a accesa obiectele intr-un mod similar cu array-urile.
Abea in PHP 5.3 au aparut structuri de date cu adevarat diferite, cum ar fi SplStack, dar si multe altele.
Cu toate astea, structuri cum ar fi vectori si tupluri nu au aparut niciodata in mod nativ. Se pot construi, dar nu este simplu sau intuitiv.
Hack din HHVM a venit cu o alta abordare, o serie de colectii native care sunt gata de folosire.
Tipurile de colectii
Lista de colectii este:
- Vector – lista ordonata folosind un index
- Map – hash table tip dictionar
- Set – lista care stocheaza doar valori unice
- Pair – un caz particular de Vector care are doar doua elemente.
Vector, Map si Set au si cate un echivalent immutable (inflexibil si read-only). Acestia sunt: ImmVector, ImmMap si ImmSet. Scopul acestor tipuri de date este sa expuna informatii pentru citire, fara sa permita modificarea acestora. O colectie immutable se poate genera direct, folosind constructorul, sau folosind metodele toImmVector, toImmMap si respectiv toImmSet.
Chiar si mai mult, exista si o serie de clase abstracte pentru a implementa cu usurinta structuri similare:
Vector
Avantajul unui vector este ca va avea tot timpul cheile in succesiune, iar ordinea elementelor nu se schimba. Cand vine vorba de array nu este nici o modalitate simpla de a verifica daca ar trebui sa se comporte ca un hash table sau ca un vector. La vector, spre deosebire de hash table, valoarea cheii nu este relevanta, doar succesiunea elementelor si numarul lor sunt importante.
Sa luam un exemplu:
1<?hh 2 3function listVector($vector) { 4 echo 'Listing array: ' . PHP_EOL; 5 for($i = 0; $i < count($vector); $i++) { 6 echo $i . ' - ' . $vector[$i] . PHP_EOL; 7 } 8} 9 10$array = array(1, 2, 3); 11 12listVector($array); 13 14// eliminarea unui element din array 15unset($array[1]); 16 17listVector($array);
Rezultatul va fi:
1Listing array: 20 - 1 31 - 2 42 - 3 5Listing array: 60 - 1 7 8Notice: Undefined index: 1 in ../vector.hh on line 6 91 -
Motivul este foarte simplu: count intoarce intr-adevar numarul de elemente, dar index-ul nu este garantat secvential. Atunci cand al doilea element din array a fost eliminat, numarul de elemente s-a redus cu unul, dar index-ul 1 a ramas nealocat, iar ultimul index este egal cu marimea, asa ca nu se va mai ajunge la el.
Sa luam acelasi exemplu folosind un vector:
1<?hh 2… 3$vector = Vector{1, 2, 3}; 4 5listVector($vector); 6 7// eliminarea unui element din vector 8$vector->removeKey(1); 9 10listVector($vector);
Asa cum am anticipat, rezultatul este:
1Listing array: 20 - 1 31 - 2 42 - 3 5Listing array: 60 - 1 71 - 3
Este de remarcat ca nu se poate folosi unset, pentru ca nu este o cheie cea care se elimina, ci elementul respectiv, iar urmatoarea valoare din vector ii va lua locul.
Un alt lucru important este ca, daca un index nu exista si incercam sa-l modificam, va aparea o exceptie de tip “OutOfBoundsException”.
Cateva exemple care vor genera exceptia anterioara:
1<?hh 2 3$vector = Vector{1,2,3,4}; 4 5// va functiona pentru ca cheia nr 1 exista 6$vector->set(1, 2); 7 8// nu va functiona pentru ca inca nu exista cheia 4 9$vector->set(4, 5); 10 11// nu va functiona din acelasi motiv 12$vector[4] = 5; 13 14// pentru a adauga un element nou se pot folosi doar metode care nu specifica cheia 15$vector[] = 5; 16 17// sau 18array_push($vector, 5);
Pentru accesare de elemente problema de “OutOfBoundsException” ramane la fel. De exemplu, daca indexul 10 nu exista:
1var_dump($vector[$unsetKey]);
Un alt caz mai special este atunci cand elementul nu exista, dar se foloseste metoda “get”.
1var_dump($vector->get($unsetKey));
Exemplul anterior nu va genera o eroare, in schimb rezultat va fi “null” atunci cand nu exista cheia. Mi se pare bizar un astfel de comportament, pentru ca poate exista un element null in vector, iar rezultatul va fi acelasi.
Pentru a evita confuzia intre elemente care nu sunt definite si elemente care sunt null, exista o metoda speciala pentru a vedea daca exista cheia:
1var_dump($vector->containsKey($unsetKey));
Scoaterea elementelor din vector se face folosind:
1$vector->remove($key);
Sau, pentru scoaterea ultimului element:
1$vector->pop();
Map
Intr-un hash table, fata de un vector, ordinea si numarul elementelor nu sunt foarte relevante. In schimb, asocierea cheie-valoare este foarte importanta. Din acest motiv, un Map se mai numeste si “dictionar” – pentru ca poti ajunge usor de la o cheie la o valoare, pentru ca sunt “mapate”. De acolo si denumirea de “Map”.
Implementarea HHVM va retine si ordinea in care elementele au fost introduse.
In PHP, echivalentului unui Map era un array asociativ.
Fata de Vector, Map are nevoie de o cheie care va ramane permanent asociata cu elementul, indiferent daca se vor scoate sau adauga elemente in colectie.
Functile array_push sau array_shift nu vor functiona pentru Map, pentru ca acesta nu trimit o cheie, iar asocierea cheie-valoare nu ar fi controlata:
1<?hh 2 3$map = Map{0 => 'a', 1 => 'b', 3 => 'c'}; 4 5array_push($map, 'd'); 6 7array_unshift($map, 'e'); 8 9var_dump($map);
Va genera urmatorul rezultat:
1Warning: Invalid operand type was used: array_push expects array(s) or collection(s) in ../map.hh on line 5 2 3Warning: array_unshift() expects parameter 1 to be an array, Vector, or Set in ../map.hh on line 7 4object(HH\Map)#1 (3) { 5 [0]=> 6 string(1) "a" 7 [1]=> 8 string(1) "b" 9 [3]=> 10 string(1) "c" 11}
Dupa cum se poate vedea, elementele nu au fost adaugate si fiecare din cazuri a generat cate un Warning.
Adaugarea efectiva se poate face folosind:
1<?hh 2 3$map = Map{0 => 'a', 1 => 'b', 3 => 'c'}; 4 5// adaugarea unui element folosind sintaxa de array 6$map['new'] = 'd'; 7 8// adaugarea unui element folosind metoda structurii 9$map->set('newer', 'e'); 10 11var_dump($map);
Rezultatul va fi:
1object(HH\Map)#1 (5) { 2 [0]=> 3 string(1) "a" 4 [1]=> 5 string(1) "b" 6 [3]=> 7 string(1) "c" 8 ["new"]=> 9 string(1) "d" 10 ["newer"]=> 11 string(1) "e" 12}
Spre deosebire de Vector, pentru ca elementul care se schimba este strans legat de cheie, unset este o metoda valida de a elimina un element:
1unset($map[$key]);
Structura are si o metoda pentru a elimina elementul cu o anumita cheie:
1$map->remove($key);
In acest caz, nici una din optiuni nu va genera o eroare daca nu exista cheia.
Exceptia de “OutOfBoundsException” se aplica si aici pentru chei care nu sunt definite, dar la fel ca la Vectori, exista o metoda pentru a testa daca exista cheia:
1$map->contains($key);
Similar cu Vector, exista o metoda care intoarce cheia setata sau null daca aceasta nu exista:
1$map->get($key);
Pentru a ne asigura ca nu se genereaza o exceptie “OutOfBoundsException”, un Map nu ar trebui parcurs cu “for”, ci doar cu “foreach”.
Pentru ca metoda “pop” de la vector nu se bazeaza pe o cheie, nu exista in structura Map.
Set
Seturile au scopul de a pastra unicitatea valorilor. Pentru aceasta structura, valorile sunt restrictionate doar la tipurile scalare: string si integer.
Interfata pentru aceasta structura este mult mai simpla decat la Vector si Map, pentru ca scopul este mult mai limitat.
Pentru Set cheia nu poate fi accesata, dar este relevanta din alt punct de vedere.
Sa luam un exemplu pentru a evidentia:
1<?hh 2$set = Set{'a', 'b', 'c'}; 3 4foreach($set as $key => $val) { 5 echo $key . ' - ' . $val . PHP_EOL; 6}
Rezultatul va fi:
1a - a 2b - b 3c - c
Cheia si valoarea sunt identice, un mod ingenios de a pastra si unicitatea.
Cu toate astea, operatiunea este transparenta, lucru care permite adaugarea de elemente fara a referentia o cheie:
1<?hh 2 3$set = Set{'a', 'b', 'c'}; 4 5array_push($set, 'd'); 6 7array_unshift($set, 'e'); 8 9$set[] = 'f'; 10 11var_dump($set);
Vom avea un rezultat similar cu cel de la vectori:
1object(HH\Set)#1 (6) { 2 string(1) "e" 3 string(1) "a" 4 string(1) "b" 5 string(1) "c" 6 string(1) "d" 7 string(1) "f" 8}
Chiar daca se pot adauga noi valori folosind operatorul [], acestea nu pot fi referentiate folosind acest operator:
1<?hh 2 3$set = Set{'a', 'b', 'c'}; 4 5echo $set['a'];
Va genera eroarea:
1Fatal error: Uncaught exception 'RuntimeException' with message '[] operator not supported for accessing elements of Sets' in ../set.hh:5 2Stack trace: 3#0 {main}
Pentru scoaterea de elemente se poate folosi doar metoda nativa (remove) si metode care nu presupun referentierea de chei:
1<?hh 2 3$set = Set{'a', 'b', 'c', 'd'}; 4 5array_pop($set); 6 7array_shift($set); 8 9$set->remove('b'); 10 11var_dump($set);
Rezultatul va fi:
1object(HH\Set)#1 (1) { 2 string(1) "c" 3}
Fata de Vector si Map, metoda “remove” va primi valoarea, nu cheia de acces.
Pentru Set nu exista nici un fel de cheie de acces, deci cam tot ce putem sa facem este sa verificam daca un element exista, folosind “contains”:
1$set->contains($value);
Metoda va returna o valoarea booleana, care arata daca elementul exista sau nu.
Pair
O pereche este o colectie cu doua elemente. Nu poate avea mai multe sau mai putine. Elementele sunt indexate la fel ca si Vectorul, printr-o cheie care in acest caz poate avea doar valorile 0 si 1.
Nu sunt multe de spus despre aceasta structura de date, pentru ca elementele nu se pot scoate, adauga sau inlocui. Acesta este si motivul pentru care nu exista un echivalent immutable, deoarece structura in sine nu este flexibila:
1<?hh 2 3$pair = Pair{'a', 'b'}; 4 5foreach($pair as $key => $val) { 6 echo $key . ' - ' . $val . PHP_EOL; 7}
Rezultatul va fi:
10 - a 21 - b
O structura foarte simpla cu un scop foarte simplu.
Notiuni comune
Aproape toate structurile prezentare anterior au cateva metode si comportamente comune. Spun aproape toate, pentru ca Set si mai ales Pair, prin natura lor mai restrictiva, nu dispun de unele functionalitati pe care Vector si Map le au.
Filter
Este o functie de filtrare care vine din programarea functionala. Scopul este de a filtra o structura de date si de a genera una noua de acelasi fel, exceptie facand Pair, ca urmare a restrictiei legate de numarul de elemente. In PHP, echivalentul este array_filter.
Vector si Map au doua metode: filter si filterWithKey. Acestea accepta un argument de tip “callable”, cu alte cuvinte o functie:
1<?hh 2 3$vector = Vector{'a', 'b', 'c', 'd', 'e'}; 4 5// eliminarea elementului cu valoarea 'a' 6$result = $vector->filter($val ==> $val != 'a'); 7 8// eliminarea fiecarui al doilea element folosind cheia 9$result2 = $vector->filterWithKey(($key, $val) ==> ($key % 2) == 0); 10 11var_dump($vector); 12var_dump($result); 13var_dump($result2);
Rezultatul va fi:
1object(HH\Vector)#1 (5) { 2 [0]=> 3 string(1) "a" 4 [1]=> 5 string(1) "b" 6 [2]=> 7 string(1) "c" 8 [3]=> 9 string(1) "d" 10 [4]=> 11 string(1) "e" 12} 13object(HH\Vector)#3 (4) { 14 [0]=> 15 string(1) "b" 16 [1]=> 17 string(1) "c" 18 [2]=> 19 string(1) "d" 20 [3]=> 21 string(1) "e" 22} 23object(HH\Vector)#5 (3) { 24 [0]=> 25 string(1) "a" 26 [1]=> 27 string(1) "c" 28 [2]=> 29 string(1) "e" 30}
Dupa cum se poate observa, rezultatul functiei “callable” este tratat ca un bool si, in functie de acesta, elemente sunt adaugate in structura rezultata.
Map are un comportament identic cu cel de la Vector, diferenta fiind doar in natura cheilor.
Un lucru interesant este ca o colectie poate sa fie si immutable, pentru ca operatiunea nu modifica structura de la care a plecat, dar colectia va fi si ea de tipul structurii initiale:
1<?hh 2 3$vector = Vector{'a', 'b', 'c'}; 4 5$vector = $vector->toImmVector(); 6 7// eliminarea elementului cu valoarea 'a' 8$result = $vector->filter($val ==> $val != 'a'); 9 10var_dump($vector); 11var_dump($result);
Rezultatul va fi:
1object(HH\ImmVector)#2 (3) { 2 [0]=> 3 string(1) "a" 4 [1]=> 5 string(1) "b" 6 [2]=> 7 string(1) "c" 8} 9object(HH\ImmVector)#4 (2) { 10 [0]=> 11 string(1) "b" 12 [1]=> 13 string(1) "c" 14}
Pair are si el aceleasi functii ca Vector si Map, dar comportamentul nu este identic, din cauza faptului ca un Pair poate sa aiba doar 2 elemente, nici mai mult nici mai putin. Din acest motiv, cand se filtreaza un Pair, rezultatul va fi ImmVector, adica o structura similara cu Pair, dar care nu are un numar exact de elemente:
1<?hh 2 3$pair = Pair{'a', 'b'}; 4 5// eliminarea elementului cu valoarea 'a' 6$result = $pair->filter($val ==> $val != 'a'); 7 8var_dump($result);
Structura rezultata va fi:
1object(HH\ImmVector)#3 (1) { 2 [0]=> 3 string(1) "b" 4}
Set nu are decat metoda “filter”, pentru ca, asa cum am demonstrat anterior, cheile sunt identice cu valorile. Daca ar fi existat si o valoare cu chei, ar fi functionat similar.
Map
O alta functie provenita din limbajele functionale este “Map”. Aceasta are scopul de a modifica valorile unei structuri, folosind o functie, rezultatul fiind o noua structura de tipul celei initiale. In PHP, echivalentul este array_map.
Similar cu filter, Vector si Map au metodele comune: “map” si “mapWithKey”. Si in acest caz, accepta un argument de tip “callable”:
1<?hh 2 3$vector = Vector {'a', 'b', 'c'}; 4 5$result = $vector->map($val ==> $val . $val); 6 7$result2 = $vector->mapWithKey(($key, $val) ==> str_repeat($val, 1 + $key)); 8 9var_dump($vector); 10var_dump($result); 11var_dump($result2);
Rezultatul va fi:
1object(HH\Vector)#1 (3) { 2 [0]=> 3 string(1) "a" 4 [1]=> 5 string(1) "b" 6 [2]=> 7 string(1) "c" 8} 9object(HH\Vector)#3 (3) { 10 [0]=> 11 string(2) "aa" 12 [1]=> 13 string(2) "bb" 14 [2]=> 15 string(2) "cc" 16} 17object(HH\Vector)#5 (3) { 18 [0]=> 19 string(1) "a" 20 [1]=> 21 string(2) "bb" 22 [2]=> 23 string(3) "ccc" 24}
Rezultatul functiei “callable” este noua valoare a elementelor din structura.
La fel ca si in cazul “filter”, o colectie immutable are ca rezultat o colectie immutable.
Tot similar cu filter este si faptul ca functia map, aplicata pe un Pair, va avea ca rezultat un ImmVector:
1<?hh 2 3$pair = Pair{'a', 'b'}; 4 5$result = $pair->map($val ==> $val . $val); 6 7var_dump($result);
Va avea ca rezultat:
1object(HH\ImmVector)#3 (2) { 2 [0]=> 3 string(2) "aa" 4 [1]=> 5 string(2) "bb" 6}
Conversie
Unele elemente pot fi convertite in alte tipuri:
din \ catre Vector Map Set Pair Array Vector da da da nu da Map da da da nu da Set da nu da nu da Pair da da da nu da Array da da da nu da La tabelul de mai sus se mai adauga cateva restrictii de structura:
- Orice structura, cand se converteste catre Set, trebuie sa contina doar valori scalare de tip int sau string:
1(Map{})->add(Pair {'a', new stdClass()}) 2 ->toSet();
Va genera eroarea:
1Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Only integer values and string values may be used with Sets' in …
- Un Map, cand este convertit la orice alta structura in afara de array, isi va pierde cheile in majoritatea cazurilor.
Conversia de la array catre altre structuri se face folosind:
1$vector = new Vector ($array);
In afara de Pair, toate structurile de mai sus au ca unic parametru al constructorului un element care implementeaza Traversable.
Concluzii
Hack aduce o noua perspectiva asupra celui mai popular tip de date din PHP. Motivul celor de la Facebook este unul simplu, optimizarea. Daca ai un comportament consistent, poti optimiza pentru structura respectiva. In PHP acest lucru nu este tocmai posibil, din cauza faptului ca un array in PHP poate sa fie orice fel de colectie.
Din punct de vedere al structurilor de date, mi se pare interesant sa ai astfel de tipuri de date. In framework-uri, de obicei exista structuri care emuleaza comportamentul colectiilor introduse de Hack. Spre exemplu, intr-un ORM, o colectie de obiecte este reprezentata in general ca un vector, pentru ca are scopul de a se itera asupra valorilor ei. Un obiect care reprezinta valorile unor campuri dintr-o tabela o sa fie o structura de tip Map, pentru ca valoarea campului este legata de denumirea campului.
Mi se pare foarte interesant nu doar faptul ca exista aceste structuri, dar si faptul ca exista interfete pentru a implementa unele noi.
Sper ca Hack sa influenteze PHP, aducand stucturi cu un scop bine determinat in limbaj.