de Cathryn Griffiths

Firebase: 5 concepții greșite prea frecvente

Firebase 5 conceptii gresite prea frecvente

Am citit recent o mulțime de comentarii online despre Firebase. În cea mai mare parte – trebuie subliniat – scris de dezvoltatori care urăsc Firebase.

„Interogările complexe sunt imposibile!” spune unul.

„Modelarea datelor mută!” spune altul.

Totul trebuie să fie partea clientului!”Se plânge altul.

Aproape că auzi venele mici care ies în evidență pe frunte.

Înțeleg totuși. Problemele cu care s-au confruntat sunt frustrante. Dar o mare parte a problemei este lipsa de înțelegere despre Firebase, ceea ce poate (și nu poate) face.

Am lucrat cu Firebase în ultimele luni. La FFuncție, folosim Firebase pentru a construi un instrument de planificare a proiectului numit Min. Există câteva concepții greșite / mituri / neînțelegeri grave despre această soluție backend-as-a-service (BaaS). Așadar, am vrut să despachetez unele dintre ele aici.

Apropo: nu suntem în niciun fel afiliați la Firebase. Vreau să adaug o mică nuanță la ceea ce devine o discuție unilaterală.

Înțelegere greșită # 1: Firebase este doar partea clientului

Până de curând, Firebase era o tehnologie exclusiv client-side. Deși, a oferit capacități de stocare și interogare. Dar majoritatea logicii aplicației dvs. trebuia să existe și să se execute pe client. Pentru mulți dezvoltatori, acesta a fost un breaker total al tranzacțiilor. La urma urmei, câte aplicații web în aceste zile nu au nevoie de backend?

Echipa Firebase a ascultat de fapt solicitările comunității de dezvoltatori. În martie 2017, au introdus Funcții Cloud pentru Firebase. Cu funcțiile cloud, puteți salva fragmente de cod pe Google Cloud. Acest cod va rula ca răspuns la anumite evenimente Firebase și solicitări HTTP. De exemplu, dacă doriți să efectuați procesarea datelor atunci când salvați date în baza de date, Poti sa faci asta. De asemenea, dacă nu doriți ca cheile API ale aplicației dvs. să fie expuse în codul clientului, poți face și tu asta.

Dacă sunteți interesat să aflați mai multe, vă recomand să verificați Funcția Cloud pentru documente Firebase (care au câteva exemple grozave) și aceste tutoriale lansate recent.

Concepție greșită # 2: Firebase are ca rezultat codul spaghetelor

Acest lucru mă face să mă gândesc la acel vechi adagiu: „Un muncitor sărac dă vina pe uneltele lor!” Dar să săpăm în asta cu un mic detaliu.

Pe baza experienței mele de până acum, Firebase nu are ca rezultat codul spaghetelor. Deoarece Firebase este în cea mai mare parte partea clientului, cea mai mare parte a logicii dvs. backend va ajunge pe client. Dacă nu sunteți atenți, s-ar putea să ajungeți la o grămadă de cod dezordonat, de neîntreținut.

În primele etape de dezvoltare Min, am petrecut mult timp planificând aplicația. Am planificat cum să ne modelăm datele, structura bazei de date și cel mai bun mod de a interacționa cu datele noastre. Am creat un conector pentru comunicarea cu Firebase. Avea tot codul pentru efectuarea operațiilor CRUD și pentru interacțiunea cu Firebase. Am construit o colecție de clase pentru a procesa datele obiectului în conformitate cu structura bazei de date Firebase.

Această abstracție ne-a ajutat să păstrăm logica legată de Firebase și logica aplicației separate. Codul nostru a fost menținut și ușor de depanat.

Înțelegere greșită # 3: modelare de date prost / prea multe duplicări

După cum o descrie echipa Firebase, baza de date Firebase este doar un copac gigant JSON. Datele sunt stocate ca colecții de perechi cheie-valoare și pot avea lățimea și profunzimea dorite. Există o mulțime de flexibilitate în modul în care vă puteți stoca datele, ceea ce vă poate duce la multe probleme dacă nu sunteți atent. Permiteți-mi să arăt acest lucru cu un exemplu.

Să presupunem că construiți o aplicație de bază pentru gestionarea proiectelor. Aveți utilizatori și sarcini. Utilizatorii pot fi repartizați la sarcini. S-ar putea să doriți să stocați toate informațiile despre sarcină într-o locație a bazei de date sub nodul sarcinilor:

tasks : {    "001" : {        name         : "Development Round 1"        description  : "Lorem ipsum dolor sit amet elit..."        startDate    : "20170101"        endDate      : "20170201"        loggedHours  : {            "20170101" : "1.66"            "20170102" : "7"            "20170103" : "5.5"        }        assignedStaff : "Cathryn"    }    "002" : {        name : "Development Round 2"        description : "Mauris quis turpis ut ante..."        startDate   : "20170206"        endDate     : "20170228"        loggedHours  : {            "20170206" : "3"            "20170207" : "1"            "20170208" : "4.75"        }        assignedStaff : "Sam"    }    "003" : {        name : "Browser Testing"        description : "Vivamus nec ligula et nulla blandit..."        startDate   : "20170301"        endDate     : "20170303"        loggedHours  : {            "20170301" : "1"            "20170301" : "3"        }        assignedStaff : "Cathryn"    }}

Acum să presupunem că doriți să afișați numele sarcinii tuturor sarcinilor atribuite lui Cathryn. Pentru a face acest lucru, puteți interoga baza de date pentru a returna toate sarcinile a căror valoare „assignStaff” este „Cathryn”.

firebase.database().ref(“tasks/”).orderByValue(“assignedStaff”).equalTo(“Cathryn”).once(“value”);

Problema cu această interogare este că va reveni toate informațiile despre sarcină pentru o anumită sarcină atribuită lui Cathryn, nu doar numele sarcinii. Este o mulțime de date inutile de descărcat.

Pentru a remedia acest lucru, Firebase vă recomandă să faceți acest lucru denormalizați-vă datele(aici este un mare mod de a face despre acest lucru). Denormalizarea este un proces de stocare a copiilor redundante de date în întreaga bază de date, pentru a îmbunătăți performanța de citire. În exemplul nostru, ne-am putea denormaliza datele adăugând următoarele la baza noastră de date:

tasksByUser : {    "Cathryn" : {        "001" : "Development Round 1"        "003" : "Browser Testing"    }    "Sam" : {        "002" : "Development Round 2"    }}

Acum, dacă dorim să preluăm numele sarcinilor pentru toate sarcinile atribuite lui Cathryn, trebuie doar să citim dintr-o locație a bazei de date:

firebase.database().ref(“/tasksByUser/Cathryn”).once(“value”);

Comparativ cu interogarea noastră anterioară, aceasta va returna numele sarcinilor atribuite lui Cathryn. Acest lucru are ca rezultat operații de citire mai rapidă, cu performanțe mai bune pe termen lung.

Denormalizarea poate părea un hack pentru unii. Dar este o strategie imperativă atunci când proiectăm o bază de date Firebase pentru o aplicație web complexă și scalabilă. Este necesar să aveți o înțelegere profundă a datelor pe care doriți să le stocați și a modului în care le veți folosi.

Înainte de a intra în construirea bazei de date Firebase. Faceți-vă timp pentru a afla denormalizare, cum să vă structurați datele, și cum să mențineți consistența datelor denormalizate. După cum a spus echipa Firebase, „Luați în considerare faptul că spațiul pe disc este ieftin, dar timpul unui utilizator nu.

Dacă timpul dvs. de citire este lent, atunci este posibil ca utilizatorii dvs. să nu rămână.

În plus, interogările ineficiente care returnează date inutile pot fi costisitoare din punct de vedere financiar. În funcție de planul de tarifare Firebase, este posibil să fie necesar să plătiți cât de mult 1 USD per GB descărcat.

Concepție greșită # 4: Firebase poate duce la neconcordanțe ale datelor

Dacă proiectați baza de date Firebase într-un mod corect. Este posibil ca datele dvs. să fie denormalizate în mai multe locații de baze de date. Și dacă datele dvs. sunt stocate în mai multe locații, probabil că vă întrebați … „cum voi păstra toate aceste date consecvente?”

Într-un caz normal, atunci când trimiteți date către Firebase, specificați o cale de bază de date și datele pe care doriți să le stocați acolo. Să revenim la exemplu, pentru a actualiza un nume de activitate (înainte de a utiliza denormalizarea), aș face acest lucru:

firebase.database().ref(“tasks/001/name”).set(“Here’s the new name”);

Acum, cu denormalizarea, pot actualiza numele unei sarcini făcând două operații de scriere:

firebase.database().ref(“tasks/001/name”).set(“Here’s the new name”);
firebase.database().ref(“tasksByUser/Cathryn/001”).set(“Here’s the new name”);

Dar efectuarea acestor două operații de scriere poate duce la neconcordanțe ale datelor. Ce se întâmplă dacă una dintre operațiile de scriere eșuează, iar cealaltă nu? Ceea ce am nevoie este o operație de scriere atomică, care să îmi permită să scriu în căile bazei de date în același timp. Pentru aceasta, Firebase oferă actualizări multipath pentru a aborda această problemă exactă. Puteți urmări o instrucțiune minunată în acest sens aici. Acum, pentru a actualiza un nume de activitate, trebuie doar să facem următoarele:

firebase.database().ref().update({    “tasks/001/name” : “Here’s the new name”,    “tasksByUser/Cathryn/001” : “Here’s the new name”});

Dacă actualizarea eșuează la oricare dintre căile bazei de date, întreaga actualizare va eșua. Atâta timp cât utilizați actualizări multipath, datele dvs. ar trebui să fie întotdeauna consecvente.

Înțelegere greșită # 5: capacități de interogare foarte limitate

Firebase are capacități limitate de interogare. Puteți sorta datele după chei sau valoare și puteți filtra datele după egalitate sau folosind intervale.

De exemplu, folosind exemplele de sarcini și utilizatori. Aș putea face o interogare pentru a prelua sarcini care încep, înainte sau după 20170601. Aș putea face, de asemenea, o interogare pentru a prelua toate sarcinile atribuite lui Cathryn sau care au înregistrat ore pentru 20170203. Dar ce am nu se poate do este filtrat după mai multe valori sau taste. De exemplu, nu pot face o interogare pentru a recupera sarcinile care i-au fost atribuite lui Cathryn și începe după 20170601. De asemenea, nu va funcționa o interogare pentru recuperarea activităților care au înregistrat ore în 20170203 și 20170304.

Interogarea sau filtrarea mai multor chei sau valori nu funcționează, iar dezvoltatorilor le place să se plângă. Dar dacă și-ar face cercetările, și-ar da seama că există de fapt un motiv destul de bun pentru asta. Deoarece Firebase este o bază de date în timp real și proiectată pentru viteză, Firebase acceptă doar operațiuni pe care le poate garanta că sunt rapide. Dacă doriți să faceți câteva interogări complexe, va trebui să vă proiectați baza de date în consecință. Interogările complexe nu sunt imposibile, trebuie să vă planificați în avans.

De exemplu, dacă aș dori să fac o interogare pentru a recupera toate sarcinile atribuite lui Cathryn care încep la 20170201. Aș putea adăuga o proprietate „staff_startDate” la sarcinile mele, după cum urmează:

tasks : {    "001" : {        ...        startDate       : "20170101"        assignedStaff   : "Cathryn"        staff_startDate : “Cathryn_20170101”        ...    }    ...}

Apoi, ar trebui doar să-l întreb astfel:

firebase.database().ref(“/tasks/”).orderByChild(“staff_startDate”).equalTo(“Cathryn_20170101”);

Vă recomand cu drag să urmăriți Interogări SQL comune convertite pentru baza de date Firebase și Interogarea bazei de date Firebase 101. Știind cum să vă structurați și să interogați datele vă va permite să efectuați interogări mai avansate. Vă va economisi o mulțime de dureri de cap pe drum.

Am decis să urmez acest articol cu ​​o listă de verificare pentru cele mai bune practici Firebase. Dacă introduceți e-mailul în căsuța de mai jos, vă voi trimite.

Între timp, aș dori să aud de la alți dezvoltatori care folosesc Firebase.

Îi place altcuiva Firebase?

Nu atat de mult?

Te dai cu capul pe ecran?

Vorbește-mi, dezvoltatori. Comentariile sunt deschise.