Firebase

Firebase: Yanlış Bilinenler

Edis Nezir
Kodcular

--

Her geçen gün popülerliği artan Firebase hakkında araştırma yaparken aklınızdaki soru işaretlerini gidermenize yardımcı olacak bu özet-çeviri yazısını sizinle paylaşmak istedim.

Orjinal yazı: Cathryn Griffiths, “Firebase: 5 way-too-common misconceptions” (08.18.2018)

Firebase hakkında son zamanlarda çoğunlukla Firebase’den nefret eden geliştiriciler tarafından yazılmış pek çok yorum okudum.

“Karmaşık sorgular imkansız!” demiş biri.

“Aptal veri modellemesi” demiş başka biri.

Herşey istemci tarafında olmalı!” başka bir şikayet daha.

Karşılaştıkları sorunlar sinir bozucu. Ancak sorunun büyük bir kısmı Firebase hakkında ne yapabileceği (ve ne yapamayacağı!) hakkında bilgi eksikliğinden kaynaklanıyor.

Yanlış #1: Firebase sadece istemci taraflı çalışır.

Yakın zamana kadar, Firebase istemci taraflı çalışan bir teknolojiydi. Bununla birlikte sağlanan depolama ve sorgulama yeteneklerinin büyük bir çoğunluğunun istemci taraflı çalıştırılması gerekiyordu. Birçok geliştirici için bu tek başına bir engeldi. Ne de olsa bugünlerde kaç tane web uygulamasına back-end gerekmiyor ?. Firebase ekibi geliştirici topluluğunun isteklerini dinledi ve Mart 2017'de Cloud Functions özelliğini tanıttı. Bu özellik sayesinde kodlarınızı Google Cloud’a kaydedebilir, Firebase olaylarına(event) ve HTTP isteklerine yanıt verecek şekilde çalıştırabilirsiniz. Örneğin veriyi veritabanına kaydederken veriyi işlemek istiyorsanız bunu yapabilirsiniz ya da uygulmanızın API kodlarının istemci tarafında görünmesini istemiyorsanız bunuda yapabilirsiniz.

Daha fazla bilgi edinmek istiyorsanız, Cloud Function for Firebase adresini inceleyebilirsiniz.

Yanlış #2: Firebase spagetti kodlara sebep olur.

Bu beni eski bir atasözü hakkında düşündürüyor: “Fakir bir işçi aletlerini suçluyor!” hadi biraz daha detaylı bir şekilde inceleyelim.

Şu ana kadarki tecrübelerime dayanarak, Firebase spagetti kodlara sebep olmuyor. Dikkatli değilseniz, bir sürü dağınık ve anlaşılmaz kodla karşılaşabilirsiniz.

Min’in geliştirilmesinin ilk aşamalarında, uygulamayı planlamak için çok zaman harcadık. Verilerimizi, veritabanı yapımızı ve verilerimizle etkileşime geçmenin en iyi yolunu nasıl modelleyeceğimizi planladık. Firebase ile etkileşimde bulunmak için tüm kodlara sahip ve CRUD işlemlerini yapabilen bir connector oluşturduk.

Bu soyutlama, Firebase ile ilgili mantığı ve uygulama mantığını ayrı tutmamıza yardımcı oldu. Kodumuzun, bakımı ve debug edilmesi kolaydı.

Yanlış #3: Aptal veri modellemesi / çok fazla tekrar.

Firebase takımının tanımladığı gibi, Firebase veritabanı dev bir JSON ağacıdır. Veri, key-value koleksiyonları olarak depolanır, istediğiniz genişliğe ve derinliğe sahip olabilir. Verilerinizi nasıl saklayacağınız hakkında dikkatli olmazsanız başınıza bela açabilecek kadar esneklik vardır. Bunu bir örnekle göstereyim.

Basit bir proje yönetimi uygulaması oluşturduğunuzu varsayalım. Kullanıcılar ve görevleri var. Kullanıcılar görevlere atanabilir. Tüm görev bilgilerini görev düğümü altındaki tek bir veritabanı konumunda saklamak isteyebilirsiniz:

tasks: {
"001" : {
ad : "Gelştirme Aşama 1"
aciklama : "Lorem ipsum dolor sit amet elit..."
baslangicTarihi : "20170101"
bitisTarihi : "20170201"
kayitliSaatler : {
"20170101" : "1.66"
"20170102" : "7"
"20170103" : "5.5"
}
gorevliPersonel : "Cathryn"
}
"002" : {
ad : "Gelştirme Aşama 2"
aciklama : "Lorem ipsum dolor sit amet elit..."
baslangicTarihi : "20170206"
bitisTarihi : "20170228"
kayitliSaatler : {
"20170206" : "3"
"20170207" : "1"
"20170208" : "4.5"
}
gorevliPersonel : "Sam"
}
"003" : {
ad : "Tarayıcı Testi"
aciklama : "Lorem ipsum dolor sit amet elit..."
baslangicTarihi : "20170301"
bitisTarihi : "20170303"
kayitliSaatler : {
"20170301" : "1"
"20170301" : "3"
}
gorevliPersonel : "Cathryn"
}
}

Şimdi diyelim ki, Cathryn’e atanan tüm görevlerin görev adını görüntülemek istiyorsunuz. Bunu yapmak için, veritabanını “gorevliPersonel” değeri “Cathryn” olan tüm görevleri döndürmek için sorgu yazabilirsiniz.

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

Sorgudaki sorun, yalnızca görev adını değil, Cathryn’e atanan belirli bir görevin tüm bilgilerini döndürmesidir. İndirmesi gereken çok fazla gereksiz veri var.

Bunu düzeltmek için Firebase, verilerinize denormalization uygulamanızı öneriyor. Denormalizasyon, okuma performansını artırmak için gereksiz veri kopyalarının veritabanı boyunca depolanması işlemidir. Örneğimizde, aşağıdakileri veritabanımıza ekleyerek verilerimize denormalization uygulayabiliriz:

tasksByUser : {
"Cathryn" : {
"001" : "Geliştirme Aşama 1"
"003" : "Tarayıcı Testi"
}
"Sam" : {
"002" : "Geliştrme Aşama 2"
}
}

Şimdi, Cathryn’e atanan tüm görevlerin görev adlarını almak istiyorsak, tek bir veritabanı konumundan okuyabiliriz:

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

Önceki sorgumuzla karşılaştırıldığında, bu Cathryn’e verilen görevlerin sadece adını verecektir. Bu, uzun vadede daha iyi performansla daha hızlı okuma işlemli anlamına gelir.

Denormalizasyon bazılarına hack gibi görünebilir. Ancak, karmaşık ve ölçeklenebilir bir web uygulaması için bir Firebase veritabanı tasarlarken zorunlu bir stratejidir. Saklamak istediğiniz verileri ve bunları nasıl kullanacağınızı derinlemesine anlamanızı gerektirir.

Firebase veritabanınızı oluşturmaya başlamadan önce denormalizasyon, verilerinizin nasıl yapılandırılacağı ve denormalize verilerin tutarlılığının nasıl korunacağı hakkında bilgi edinmek için araştırma yapın. Firebase ekibinin dediği gibi, “Disk alanının ucuz olduğunu, ancak kullanıcının zamanının olmadığını” düşünün. Okuma zamanlarınız yavaşsa, kullanıcılarınızın beklememe ihtimali vardır. Ayrıca, gereksiz verileri getiren yanlış sorgulamalar maddi olarak pahalı olabilir. Firebase fiyatlandırma planınıza bağlı olarak, indirilen GB başına 1 ABD Doları ödemeniz gerekebilir.

Yanlış #4: Firebase veri tutarsızlıklarına neden olabilir.

Bu konuya geçmeden önce CAP teoremini araştırmanızda fayda var.

Firebase veritabanınızı doğru şekilde tasarlıyorsanız muhtemelen verilerinizin birden fazla veritabanı konumunda denormalize edilmiş şekilde bulunur. Ve eğer verileriniz birden fazla yerde saklanıyorsa, muhtemelen “tüm bu verileri nasıl tutarlı tutacağım?” sorusunun cevabını merak ediyorsunuzdur…

Normal bir durumda, Firebase’e veri gönderirken, veritabanı yolu ve orada depolamak istediğiniz verileri belirtirsiniz. Örneğe dönersek, bir görev adını güncellemek için (denormalizasyon kullanmadan önce), şunu yapmamız gerekir:

firebase
.database().ref(“tasks/001/name”)
.set(“Yeni görev adı”);

Denormalizasyon uygulaması ile, iki yazma işlemi yaparak bir görevin adını güncelleyebiliriz:

firebase
.database().ref(“tasks/001/name”)
.set(“Yeni görev adı”);firebase
.database().ref(“tasksByUser/Cathryn/001”)
.set(“Yeni görev adı”);

Ancak bu iki yazma işlemini yapmak veri tutarsızlıklarına neden olabilir. Ya yazma işlemlerinden biri çalışır fakat diğeri başarısız olursa? İhtiyacımız olan, aynı zamanda veritabanı yollarına yazmama izin veren atomik bir yazma işlemi. Firebase, bu sorunu çözmek için çok yollu güncellemeler sağlar. Bir görev adını güncellemek için aşağıdakileri yapmanız yeterlidir:

firebase
.database().ref()
.update({
“tasks/001/name” : “Yeni görev adı”,
“tasksByUser/Cathryn/001” : “Yeni görev adı”
});

Güncelleme, herhangi bir veritabanı yolunda başarısız olursa, güncellemenin tamamı iptal olur. Çok yollu güncelleştirmeleri kullandığınız sürece verileriniz her zaman tutarlı olur.

Yanlış #5: Çok sınırlı sorgulama yetenekleri.

Firebase’in sorgulama yetenekleri sınırlı. Verileri key veya valuelara göre sıralayabilir ve eşitlik veya aralıkları kullanarak verileri filtreleyebilirsiniz.

Örneğin, görev ve personel örneğimizi kullanırsak. 20170601'de, bu tarihin sonrasında veya öncesinde başlayan görevleri almak için bir sorgu yazabiliriz. Ayrıca, Cathryn’e atanan veya 20170203 için saatlerini kaydeden tüm görevleri almak için bir sorgu yazabiliriz. Fakat yapamadığımız şey çoklu key veya value kullanarak filtrelemek. Örneğin, Cathryn’e atanan ve 20170601'den sonra başlayan görevleri almak için bir sorgu yazamıyoruz. 20170203 ve 20170304 tarihlerinde kayıtlı saatleri bulunan görevleri getiren sorgumuz çalışmayacaktır.

Birden fazla key veya value üzerinde sorgulama veya filtreleme işe yaramaz ve geliştiricilerin en çok şikayet ettiği konulardan biri budur. Ancak araştırmalarını yaparlarsa, bunun için oldukça iyi bir neden olduğunu anlarlar. Firebase gerçek zamanlı bir veritabanı olduğundan ve hız için tasarlandığından, yalnızca hızlı olmasını garanti edebileceği işlemleri destekler. Karmaşık sorgular yapmak istiyorsanız, veritabanınızı buna göre tasarlamanız gerekecektir. Karmaşık sorular imkansız değildir fakat onlar için önceden planlama gereklidir.

Örneğin, Cathryn’e atanmış ve 20170201 tarihindeki tüm görevleri getirmek istersek aşağıda gördüğünüz gibi “personel_baslangicTarihi” özelliğini tasks’a ekleyebiliriz.

tasks : {
"001" : {
...
baslangicTarihi : "20170101"
gorevliPersonel : "Cathryn"
personel_baslangicTarihi : “Cathryn_20170101”
...
}
...
}

Ardından, bu şekilde sorgulayabiliriz:

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

Common SQL Queries converted for the Firebase Database ve Firebase Database Querying 101 kaynaklarına göz atmanızı öneririm.

--

--