Utilizarea generatoarelor php, programarea populară

Utilizarea generatoarelor php, programarea populară
În ciuda faptului că generatoarele php sunt disponibile cu php 5.5.0, acestea sunt încă aproape nefolosite. Mai mult, majoritatea dezvoltatorilor pe care îi cunosc înțeleg cum funcționează generatoarele. dar nu văd când pot fi utile în viața reală.







Da, generatoarele arata cu siguranta bine, dar stii. Nu înțeleg unde pot fi utile pentru mine, cu excepția calculării secvenței Fibonacci.

Și nu se înșeală, deoarece chiar și exemplele din documentația php sunt prea simpliste. Ele explică doar modul de implementare eficientă a unui interval sau iterația prin liniile unui fișier.

Dar chiar și cu aceste exemple simple putem înțelege avantajele cheie ale utilizării generatoarelor. simplifică pur și simplu iteratorii.

Generatoarele vă permit să scrieți cod care utilizează foreach pentru a repeta un set de date fără a aloca memorie pentru matrice.

Ținând cont de acest fapt, voi încerca să explic de ce generatoarele mi-au ajutat să rezolv problemele cu care am lucrat în cadrul companiei.

Mai întâi un pic de context

În majoritatea exemplelor de coduri, mă voi referi la aceste metadate de $ ebooks.

Iterația asupra unui set mare de date

Prin tradiție, ar trebui să scriu ceva de genul:

Problema este ușor de văzut: cu cât mai multe cărți, cu atât mai multă memorie de care aveți nevoie pentru $ filteredEbooks.

O soluție este de a crea un iterator care să reproducă ebook-urile $ și să le returneze pe cele corespunzătoare. Dar pentru asta am avea nevoie să creăm o nouă clasă, în plus, iteratorii sunt implementați un pic obositori. Din fericire, cu php 5.5.0 putem folosi generatoare!

Da, refactorizarea metodei getEbooksEligibleToWebReader pentru a utiliza generatorul este foarte simplă: înlocuim transferul valorilor cu variabila $ filteredEbooks cu constructul de randament.

Presupunând că ebook-urile $ nu sunt o serie de cărți. iteratorul sau generatorul (chiar mai bine!), consumul de memorie va fi acum constant, indiferent cât de multe cărți trebuie returnate și suntem siguri că cărțile vor fi căutate numai atunci când sunt cu adevărat necesare.







Bonus: RulerZ din interior utilizează generatoare. astfel încât să putem rescrie metoda și să rămânem cu aceeași optimizare pentru alocarea memoriei.

Agregarea surselor de date multiple

Acum, ia în considerare momentul de a primi ebooks $. Nu v-am spus, dar provin de la diferite surse: baza de date relațională și Elasticsearch.

Putem scrie o metodă simplă care agregă aceste două surse:

Dar, încă o dată, cantitatea de memorie consumată atunci când se folosește această abordare este foarte dependentă de numărul de cărți stocate în baza de date și de Elasticsearch.

Putem începe să folosim generatoarele și să returnăm rezultatul:

Deci, bineînțeles, e mai bine, dar avem încă o problemă: metoda noastră getBooks nu prea funcționează! Trebuie să separăm cele două responsabilități (citirea datelor din baza de date și apelarea Elasticsearch) în două metode:

S-ar putea să observați utilizarea randamentului de la operator (disponibil cu php 7.0), care vă permite să delegeți utilizarea generatoarelor. Este ideal, de exemplu, pentru a agrega mai multe surse de date care utilizează generatoare.

Randamentul operatorului funcționează cu orice obiect traversabil, astfel încât și acest operator pot fi utilizați și reele și iteratori.

Folosind această construcție, putem agrega mai multe surse de date într-o serie de linii de cod:

Complex hidratare complexă (la cerere) a înregistrărilor bazei de date

O altă opțiune de utilizare a generatoarelor este punerea în aplicare a hidratării leneș, care se ocupă de comunicații.

A trebuit să importe sute de mii de comenzi dintr-o bază de date veche în sistemul nostru, fiecare comandă conținea mai multe articole.

Disponibilitatea comenzilor și a "articolelor de comandă" a fost o condiție prealabilă a ceea ce trebuie să facem. Am scris o metodă care întoarce ordine învăluite și nu devine prea lentă sau lipsită de griji.

Ideea este puțin naivă: comandă comenzi cu elemente, ordine de grup și elemente de comandă într-un ciclu.

Utilizarea generatoarelor. Am reușit să pun în aplicare o metodă care primește comenzi din baza de date și le atribuie elementele de comandă corespunzătoare. Toate acestea consumă o cantitate stabilă de memorie. Generatorul a eliminat necesitatea de a păstra toate comenzile și elementele lor: comanda curentă este tot ceea ce am nevoie pentru a agrega toate datele.

Simularea sarcinilor asincrone

Ultima, dar importantă: generatoarele pot fi, de asemenea, folosite pentru a simula sarcinile asincrone. În timp ce scriam această notă, am dat peste postul @nikita_ppv pe același subiect și de când a fost primul care a implementat generatoarele în php. Voi lăsa o legătură cu postul lui.

El explică rapid ce sunt generatoarele și (în detaliu) cum putem beneficia de faptul că pot fi întrerupte și pot trimite / primi date pentru implementarea corutinelor și chiar multitasking.

Pentru a rezuma

  • . iteratori simplificați;
  • . poate returna volume nelimitate de date fără consum de memorie suplimentar;
  • . pot fi agregate prin delegarea generatorilor;
  • . pot fi utilizate pentru implementarea multitasking-ului;
  • . doar cool!






Articole similare

Trimiteți-le prietenilor: