
Pozwól, że opowiem techniczną historię.
Wiele lat temu stworzyłem aplikację z wbudowanymi funkcjami współpracy. Był to wygodny eksperymentalny stos, który w pełni wykorzystywał potencjał wczesnego React i CouchDB. Synchronizował dane w czasie rzeczywistym za pomocą JSON. . Był używany do wewnętrznej pracy firmy, ale jego szeroka przydatność i potencjał w innych dziedzinach były oczywiste.
Próbując sprzedać tę technologię potencjalnym klientom, napotkaliśmy niespodziewaną przeszkodę. W wideo demonstracyjnym nasza technologia wyglądała i działała świetnie, tu nie było problemu. Wideo pokazywało dokładnie, jak to działa, i nic nie było symulowane. Stworzyliśmy i zakodowaliśmy realistyczny scenariusz użycia programu.

W rzeczywistości to stało się problemem. Nasze demo działało dokładnie tak, jak imitowały działanie swoich aplikacji wszystkie inne programy. Konkretnie, informacja była natychmiast przekazywana z A do B, nawet w przypadku dużych plików multimedialnych. Po zalogowaniu każdy użytkownik widział nowe wpisy. Dzięki aplikacji różni użytkownicy mogli współpracować nad tymi samymi projektami, nawet w przypadku przerwanego połączenia internetowego gdzieś na wsi. Niejasno to sugeruje każde video produktu montowane w After Effects.
Mimo że wszyscy wiedzieli, do czego potrzebny jest przycisk odświeżania, nikt zupełnie nie rozumiał, że aplikacje internetowe, które proszą nas o stworzenie, zazwyczaj mają swoje ograniczenia. I że jeśli nie będą już potrzebne, doświadczenie użytkownika będzie zupełnie inne. Zasadniczo zauważali, że można "czatować", zostawiając notatki rozmówcom, więc zadawali sobie pytanie, czym to się różni na przykład od Slacka. Ufff!
Projekt codziennych synchronizacji
Jeśli masz już doświadczenie w tworzeniu oprogramowania, powinno cię irytować, że większość ludzi nie może po prostu spojrzeć na obraz interfejsu i zrozumieć, co on zrobi podczas interakcji z nim. Nie mówiąc już o tym, co dzieje się wewnątrz samego programu. Wiedza o tym, że może zdarzyć się — w dużej mierze wynik wiedzy o tym, co nie może się zdarzyć i co nie powinno się zdarzyć. Wymaga to nie tylko tego, co robi oprogramowanie, ale także tego, jak są ze sobą skoordynowane i komunikują się jego poszczególne części.
Klasycznym przykładem tego jest użytkownik, który przez dwadzieścia minut patrzy na spinner.gif, zastanawiając się, kiedy wreszcie zakończy się operacja. Programista zrozumiałby, że proces prawdopodobnie zawiesił się i że gif nigdy nie zniknie z ekranu. Ta animacja imituje postęp pracy, ale nie ma związku z jej stanem. W podobnych przypadkach niektórzy technicy lubią przewracać oczami, zaskoczeni stopniem złudzenia użytkowników. Ale zauważcie, kto z nich wskazuje na obracające się zegary i mówi, że tak naprawdę stoją w miejscu?

Oto istota wartości rzeczywistego czasu. W dzisiejszych czasach bazy danych rzeczywistego czasu wciąż są niezwykle rzadko używane, a wiele osób podchodzi do nich z podejrzliwością. Większość takich baz danych aktywnie skłania się ku stylowi NoSQL, przez co zazwyczaj stosuje się rozwiązania oparte na Mongo, o których lepiej zapomnieć. Jednak dla mnie oznacza to komfort pracy z CouchDB, a także badanie projektowania struktur, które będą mogły być zapełniane danymi nie tylko przez jakiegoś biurokraty. Myślę, że wykorzystuję swój czas bardziej efektywnie.
Ale prawdziwym tematem tego postu jest to, z czego korzystam dzisiaj. Nie z mojego wyboru, a z powodu obojętnej i ślepo stosowanej polityki korporacyjnej. Dlatego przedstawiam całkowicie uczciwe i obiektywne porównanie dwóch ściśle związanych produktów do pracy z bazami danych rzeczywistego czasu Google.

W nazwach obu jest słowo Fire. Jedno wspominam z czułością. Drugie to dla mnie inny rodzaj ognia. Nie śpieszę się, aby wymienić ich nazwy, ponieważ jak tylko to zrobię, napotkamy pierwszy wielki problem — z nazwami.
Pierwszy nosi nazwę Firebase Real-Time Database, a drugi — Firebase Cloud Firestore. Obydwa są produktami z Firebase suite Google. Ich API noszą nazwy odpowiednio firebase.database(…) i firebase.firestore(…).
Tak się stało, ponieważ Real-Time Database to po prostu oryginalny Firebase przed jego zakupem przez Google w 2014 roku. Następnie w Google postanowiono stworzyć jako produkt równoległy kopię Firebase oparta na big data firmy i nazwano ją Firestore z chmurą. Mam nadzieję, że jeszcze się nie pogubiliście. Jeśli jednak się pogubiliście, nie martwcie się, sam pisałem tę część artykułu dziesięć razy.
Ponieważ należy wskazać Firebase w pytaniu o Firebase i Firestore w pytaniu o Firebase, przynajmniej żebyście byli zrozumiani kilka lat temu na Stack Overflow.
Gdyby istniała nagroda za najgorsze nazewnictwo produktów oprogramowania, ten przypadek z pewnością byłby jednym z kandydatów. Odległość Hammingowa między tymi nazwami jest tak mała, że myli nawet doświadczonych inżynierów, których palce piszą jedną nazwę, podczas gdy umysł myśli o innej. To są plany, które z hukiem się nie powiodły, wymyślone z najlepszymi zamiarami; spełniły prorocze ostrzeżenie, że baza danych będzie w ogniu. I wcale nie żartuję. Osoba, która wymyśliła taki schemat nazewnictwa, stała się przyczyną krwi, potu i łez.

Zwycięstwo Pyrrusa
Można by pomyśleć, że Firestore to zamiennik Firebase, jego następca następnej generacji, ale byłoby to błędne przekonanie. Firestore zdecydowanie nie pasuje na rolę zamiennika Firebase. Wydaje się, że ktoś usunął z niego wszystko interesujące, a większą część pozostałego pomieszał na różne sposoby.
Jednak pobieżne spojrzenie na dwa produkty może was zmylić: wydaje się, że robią to samo, przez głównie te same API i nawet w tej samej sesji baz danych. Różnice są mało zauważalne i odkrywane tylko przy dokładnym porównawczym badaniu obszernej dokumentacji. Lub gdy próbujecie przenieść idealnie działający kod na Firebase, aby działał z Firestore. Już wtedy dowiadujesz się, że interfejs bazy danych się zapala, gdy tylko próbujesz wykonać przeciąganie myszką w czasie rzeczywistym. Powtarzam, nie żartuję.
Klient Firebase jest grzeczny w tym sensie, że buforuje zmiany i wykonuje automatyczne powtórzenia prób aktualizacji, w których priorytet mają ostatnie operacje zapisu. Jednak Firestore ma ograniczenie do 1 operacji zapisu na dokument na użytkownika na sekundę, a to ograniczenie jest narzucane przez serwer. Pracując z nim, musisz znaleźć sposób na obejście tego i wdrożyć ogranicznik częstotliwości aktualizacji, nawet gdy próbujesz stworzyć własną aplikację. Oznacza to, że Firestore to baza danych w czasie rzeczywistym bez klienta czasu rzeczywistego, która ukrywa się za tym za pomocą API.
Na tym etapie zaczynamy dostrzegać pierwsze oznaki sensu istnienia Firestore. Może się mylę, ale podejrzewam, że ktoś wysoko w kierownictwie Google spojrzał po zakupie na Firebase i po prostu powiedział: „Nie, Boże, nie. To niedopuszczalne. Tylko nie pod moim przewodnictwem”.

On wyszedł ze swoich komnat i ogłosił:
„Jeden duży dokument JSON? Nie. Podzielicie dane na oddzielne dokumenty, z których każdy nie może przekraczać 1 megabajta”.
Wygląda na to, że to ograniczenie nie przetrwa pierwszego starcia z jakąkolwiek wystarczająco zmotywowaną bazą użytkowników. Wiesz, że tak jest. U nas w pracy, na przykład, mamy ponad półtora tysiąca prezentacji, co jest całkowicie normalne.
Przy takim ograniczeniu będziesz musiał pogodzić się z faktem, że jeden „dokument” w bazie danych nie będzie przypominał żadnego obiektu, który użytkownik mógłby nazwać dokumentem.
„Tablice tablic, które mogą rekurencyjnie zawierać inne elementy? Nie. Tablice będą zawierać tylko obiekty lub liczby o stałej długości, zgodnie z zamysłem Pana”.
Dlatego jeśli miałeś nadzieję umieścić w swojej Firestore GeoJSON, to odkryjesz, że to niemożliwe. Nie dopuszcza się niczego jednowymiarowego. Mam nadzieję, że lubisz Base64 i/lub JSON wewnątrz JSON.
„Import i eksport JSON przez HTTP, narzędzia wiersza poleceń lub panel administracyjny? Nie. Możesz tylko eksportować i importować dane do Google Cloud Storage. Tak to się teraz nazywa. A kiedy mówię „ty”, odnoszę się tylko do tych, którzy mają uprawnienia Project Owner. Wszyscy inni mogą pójść i stworzyć zgłoszenia.”
Jak widać, model danych FireBase jest łatwy do opisania. Zawiera jeden ogromny dokument JSON, łączący klucze JSON z ścieżkami URL. Jeśli zapiszesz za pomocą HTTP PUT do / FireBase następująco:
{
"hello": "świat"
} Wtedy GET /hello zwróci "świat". W zasadzie działa to tak, jak się spodziewasz. Kolekcja obiektów FireBase /my-collection/:id jest równoważna słownikowi JSON {"my-collection": {...}} na korzeniu, którego zawartość jest dostępna w /my-collection:
{
"id1": {...object},
"id2": {...object},
"id3": {...object},
// ...
}Działa to świetnie, jeśli każde wstawienie ma ID bez kolizji, do czego w systemie istnieje standardowe rozwiązanie.
Innymi słowy, baza danych jest w 100% zgodna z JSON (*) i doskonale działa z HTTP, na przykład z CouchDB. Jednak głównie używasz jej przez API w czasie rzeczywistym, które abstrahuje websockets, autoryzację i subskrypcje. Panel administracyjny ma obie możliwości, pozwalając na edytowanie w czasie rzeczywistym oraz import/eksport JSON. Jeśli w swoim kodzie będziesz się tego trzymać, zdziwisz się, jak wiele specjalistycznego kodu zniknie, gdy zrozumiesz, że patch i diff JSON pozwalają rozwiązać 90% rutynowych zadań związanych z obsługą stanu.
Model danych Firestore przypomina JSON, ale różni się od niego w niektórych krytycznych aspektach. Już wspomniałem o braku tablic wewnątrz tablic. Model sub-kolekcji polega na tym, że są one konceptami pierwszej klasy, oddzielnymi od zawierającego ich dokumentu JSON. Ponieważ nie istnieje gotowa serializacja, aby uzyskać i zapisać dane, wymagany jest specjalistyczny sposób wykonania kodu. Aby obsługiwać własne kolekcje, trzeba pisać własne skrypty i narzędzia. Panel administracyjny pozwala na wprowadzanie tylko niewielkich zmian w jednym polu na raz i nie ma możliwości importu/eksportu.
Przekształcili bazę danych NoSQL w czasie rzeczywistym w wolną bazę danych nie-SQL z automatycznym łączeniem i oddzielną kolumną nie-JSON. Coś w stylu GraftQL.

Gorący Java
Jeśli Firestore miał stać się bardziej niezawodny i skalowalny, to ironia polega na tym, że przeciętny programista uzyska mniej niezawodne rozwiązanie niż wybierając FireBase „z pudełka”. Oprogramowanie, którego potrzebuje Narzekający Administrator Bazy Danych, wymaga takiego poziomu wysiłku i umiejętności, że jest to po prostu nierealistyczne w niszy, w której powinien być dobry produkt. To przypomina, jak HTML5 Canvas wcale nie jest zamiennikiem Flash, jeśli nie ma narzędzi deweloperskich i odtwarzacza. Co więcej, Firestore ugrzęzło w dążeniu do czystości danych i sterylnej walidacji, co po prostu nie odpowiada temu, jak przeciętny użytkownik biznesowy lubi pracować: dla niego wszystko jest opcjonalne, ponieważ do samego końca wszystko jest szkicem.
Główną wadą FireBase jest to, że klient został stworzony kilka lat przed czasem, jeszcze zanim większość deweloperów internetowych dowiedziała się o niemutowalności. Z tego powodu FireBase zakłada, że będziesz zmieniać dane, a więc nie korzysta z zalet zapewnianej przez użytkownika niemutowalności. Ponadto nie wykorzystuje danych ponownie w przesyłanych użytkownikowi zrzutach, co sprawia, że wykonanie różnicy jest znacznie trudniejsze. Dla dużych dokumentów jego mechanizm transakcji oparty na zmiennych różnicach jest po prostu niewystarczający. Ludzie, mamy już WeakMap w JavaScript. To ułatwia sprawę.
Jeśli nada się danym odpowiedni kształt i nie będą zbyt rozbudowane, to problem ten można obejść. Ale ciekawi mnie, czy FireBase byłby znacznie bardziej interesujący, gdyby deweloperzy wydali naprawdę dobry interfejs API klienta, korzystający z niemutowalności w połączeniu z poważnymi praktycznymi poradami dotyczącymi struktury baz danych. Zamiast tego wydaje się, że próbowali naprawić coś, co nie jest zepsute, i od tego stało się gorzej.
Nie znam całej logiki, która leżała u podstaw stworzenia Firestore. Rozważania na temat motywów wewnątrz czarnej skrzynki to także część rozrywki. Takie przeciwstawienie dwóch niezwykle podobnych, ale nieporównywalnych baz danych zdarza się dość rzadko. Jakby ktoś pomyślał: „Firebase to po prostu funkcja, którą możemy emulować w Google Cloud”, ale jednocześnie jeszcze nie odkrył koncepcji określenia wymagań z rzeczywistego świata ani tworzenia użytecznych rozwiązań, które spełniają wszystkie te wymagania. „Niech to rozważają programiści. Po prostu zróbcie ładny interfejs... A czy można dodać więcej ognia?”
Rozumiem kilka rzeczy o strukturach danych. Widzę wyraźnie, że koncepcja „wszystko w jednym dużym drzewie JSON” jest próbą abstrahowania z bazy danych jakiegokolwiek poczucia dużej struktury. Oczekiwanie, że oprogramowanie po prostu poradzi sobie z jakimkolwiek wątpliwym fraktalem struktury danych – to po prostu szaleństwo. Nawet nie muszę sobie wyobrażać, jak źle może być, przeprowadzałem surowe audyty kodu i widziałem rzeczy, o których wy, ludzie, nawet nie śniliście.. Ale również wiem, jak wyglądają dobre struktury, i . Mogę sobie wyobrazić świat, w którym Firestore wydawałby się całkiem logiczny, a ludzie, którzy go stworzyli, uważaliby, że wykonali dobrą robotę. Ale nie żyjemy w tym świecie.
Wsparcie dla budowania zapytań w FireBase jest złe według jakichkolwiek standardów, praktycznie go nie ma. Zdecydowanie wymaga poprawy lub przynajmniej przemyślenia. Ale Firestore nie jest dużo lepsze, ponieważ jest ograniczone do tych samych jednowymiarowych indeksów, które są w prostym SQL. Jeśli potrzebujesz zapytań, które ludzie wykonują z chaotycznymi danymi, potrzebny jest wyszukiwanie pełnotekstowe, filtry na kilka przedziałów i dowolnie ustalany przez użytkownika porządek. Po dokładnym zbadaniu funkcje prostego SQL same w sobie są zbyt ograniczone. Poza tym jedynymi zapytaniami SQL, które ludzie mogą wykonywać w produkcji, są szybkie zapytania. Będziesz potrzebować specjalistycznego rozwiązania do indeksowania z przemyślnymi strukturami danych. W przypadku wszystkiego innego przynajmniej powinno być inkrementalne mapowanie-reduce lub coś podobnego.
Jeśli poszukasz informacji na ten temat w dokumentach Google, mam nadzieję, że skierują cię w stronę czegoś takiego jak BigTable i BigQuery. Niemniej wszystkie te rozwiązania towarzyszy tak duża ilość gęstego żargonu korporacyjnego, że szybko wrócisz z powrotem i zaczniesz szukać czegoś innego.
Ostatnią rzeczą, której potrzebujesz w przypadku bazy danych w czasie rzeczywistym, jest coś stworzonego przez ludzi i dla ludzi, pracujących na poziomie wynagrodzenia dla kierownictwa.
(*) To żart, nie ma takiego pojęcia, jak .
Reklama
Szukasz serwera do debugowania projektów i ich hostowania? Z pewnością jesteś naszym klientem 🙂 Rozliczenie dzienne za serwery w różnych konfiguracjach, antyDDoS oraz licencje Windows są już wliczone w cenę.
Źródło: habr.com
