
Mobil Uygulama
Gebeliğin her haftası için dini ve bilimsel içeriği kaynak referanslarıyla sunan, yalnız mobil ve local-first bir uygulama. İçerik uygulamayla birlikte geliyor, cihazdaki SQLite'a tek transaction'da yazılıyor; çekirdek akış internetsiz çalışıyor ve kişisel veri sunucuya gönderilmiyor.
Bu uygulamanın taşıdığı içerik iki açıdan hassas: bir yanı dini referans, öbür yanı sağlık bilgisi. İkisinde de yanlış bir cümlenin bedeli, bir yazılım hatasının bedelinden farklı — kullanıcı bilgiyi doğru varsayarak hareket ediyor. Dolayısıyla asıl teknik problem ekran değil, içeriğin yayına nasıl çıktığı: gözden geçirilmemiş bir metnin sürüme sızmasını engelleyen bir mekanizma gerekiyordu. İkinci mesele gizlilik: gebelik verisi kişinin en hassas verilerinden biri. "Sunucuda tutalım, sonra şifreleriz" yaklaşımı burada yanlış cevap; doğru cevap veriyi hiç toplamamak.
Tek kullanıcı tipi ama kullanım koşulu değişken: uygulama gün içinde kısa aralıklarla açılıyor, çoğu zaman evde, bazen bağlantısız bir ortamda ve büyük ihtimalle uygulamanın kurulduğu tek cihazda. Bu üç koşul birlikte, açılış hızını ve çevrimdışı çalışmayı bir tercih değil zorunluluk hâline getiriyor. İkinci bir taraf var ama uygulamanın içinde değil: içeriği gözden geçiren kişi. Onun kararı depoda bir alan olarak duruyor.
Tek geliştirici. İçerik şeması ve doğrulama hattı, cihaz veritabanı katmanı ve aktarım mantığı, gebelik haftası alan mantığı, arayüz ve yayın kapısı.
Sistem sunucusuz: uygulamanın konuştuğu bir API yok. İçerik depoda hafta hafta JSON olarak duruyor ve Zod şemasıyla tanımlı; uygulama paketlenirken bu içerik ikili dosyanın içine giriyor. İlk açılışta içerik cihazdaki SQLite veritabanına aktarılıyor. Aktarım üç özelliği bir arada taşıyor: sürümlü — bir birimin içerik sürümü artmadıkça üzerine yazılmıyor; idempotent — aynı aktarım ikinci kez çalıştığında hiçbir şey değişmiyor; ve tek transaction'lı — yarım kalmış bir aktarım bırakmıyor. Büyük aktarımlar arayüzü kilitlememek için parçalara bölünüyor, her parça kendi transaction'ında çalışıyor ve parçalar arasında kontrol devrediliyor. Uygulama katmanları ayrılmış: saf alan fonksiyonları (gebelik haftası hesabı, hafta erişim kontrolü), veritabanı katmanı, içerik şeması ve rotalar. Hafta hesabı saat diliminden bağımsız — gün farkı üzerinden hesaplandığı için cihazın dilimi değiştiğinde hafta atlamıyor.
Gebelik verisi hassas; toplanmayan veri sızdırılamaz. İçerik zaten uygulamayla geldiği için bir sunucunun tek işi kişisel durumu senkronize etmek olurdu — ve bu tek özelliğin bedeli bir hesap sistemi, bir gizlilik yükümlülüğü ve sürekli bir işletme maliyeti. Bu değiş tokuş kabul edilmedi.
ÖdünleşimKullanıcı cihaz değiştirdiğinde ilerlemesi taşınmıyor ve uygulama silindiğinde veri kayboluyor; yedekleme yok. İçerik düzeltmesi de sunucudan gelmiyor: bir yazım hatasının kullanıcıya ulaşması yeni bir mağaza sürümü gerektiriyor.
Uygulama her açılışta aktarımı çağırabilir; güncelleme sonrası da aynı yol çalışıyor. Bu yüzden aktarımın "kaç kez çalıştığı" sonucu değiştirmemeli. Karşılaştırma içerik sürümü üzerinden yapılıyor: sürüm artmadıysa satıra dokunulmuyor. Böylece güncellemede yalnız değişen birimler yazılıyor.
ÖdünleşimGaranti içerik sürümünün doğru artırılmasına bağlı; bir metni değiştirip sürümü artırmayı unutmak, değişikliğin cihaza hiç ulaşmaması demek ve bu sessiz bir hata. Sürüm artışını zorlayan bir kontrol yok.
Şema doğrulaması bir alanın dolu olduğunu söyler, doğru olduğunu söylemez. Dini ve tıbbi içerikte gereken ikincisi. Bu yüzden her içerik bloğu bir gözden geçirme durumu taşıyor ve sürüm öncesi çalışan kapı, onaysız blok bulursa dosyaları listeleyip sıfırdan farklı çıkıyor — build duruyor.
ÖdünleşimKapı yalnız bir alanın değerine bakıyor; onay bilgisinin doğruluğu insana bağlı. Yanlışlıkla onaylanmış bir metni yakalayan bir mekanizma yok, yalnız hiç gözden geçirilmemiş metni yakalayan bir mekanizma var. Ayrıca taslak içerikle çalışırken sürüm alınamıyor.
Hem dini hem bilimsel tarafta iddianın kaynağı metnin kendisi kadar önemli. Kaynak bir alışkanlık olarak değil şema alanı olarak tanımlandığında, kaynaksız bir metin depoya giremiyor. Bağlantıların hâlâ çalıştığını denetleyen ayrı bir komut var.
ÖdünleşimBağlantı denetimi ağa çıkıyor ve dış sitelerin erişilebilirliğine bağlı; geçici bir kesinti denetimi başarısız gösteriyor. Bu yüzden bağlantı kontrolü sürüm kapısının bir parçası değil, ayrı çalıştırılan bir komut.
Expo, tek geliştiricinin iki platforma birden teslim etmesini mümkün kılıyor ve yerel modül yazmayı gerektirmeyen bir kapsamda maliyeti en düşük yol. Cihaz veritabanı olarak SQLite seçildi çünkü içerik ilişkisel ve sorgulanabilir olmalı; anahtar-değer bir depoda hafta, katman ve dil kırılımında sorgu yazmak mümkün değil. Senkron veritabanı arayüzü, okuma yollarını asenkron durum yönetimi gerektirmeden basit tutuyor. Zod hem içerik şeması hem tip kaynağı olarak çalışıyor — MedAtlas'ta olduğu gibi tek şema, iki iş. i18next, iki dilin içerikle birlikte gelmesini sağlıyor; çeviri de uygulamayla gömülü, ağdan çekilmiyor.
Saldırı yüzeyi bilinçli olarak dar: uygulamanın konuştuğu bir sunucu, bir hesap sistemi ve bir kimlik doğrulama katmanı yok. Kişisel durum — hafta, ilerleme, tercihler — yalnız cihazdaki veritabanında duruyor ve dışarı gönderilmiyor. İçerik uygulamayla geldiği için çalışma anında indirilen ve doğrulanması gereken bir yük de yok. Geriye kalan tek risk içeriğin kendisi ve o da yayın kapısıyla korunuyor: onaysız içerik sürüme giremiyor.
Bu bir mobil uygulama; sayfa hızı ölçümü anlamlı değil ve saklanmış bir başlangıç süresi ölçümü de bulunmadığı için buraya bir sayı yazılmadı. Yapısal tarafta iki karar var. Birincisi: içerik uygulamayla geldiği için ilk açılışta indirme beklenmiyor — bağlantısız bir ortamda bile ekran dolu geliyor. İkincisi: içerik aktarımı ana iş parçacığını kilitlememek için parçalara bölünmüş, her parça kendi transaction'ında çalışıyor ve parçalar arasında kontrol devrediliyor; böylece ilk açılışta arayüz donmuyor.
Yayın kapısını içerik onayına bağlamak bu projede aldığım en doğru karar oldu ve kökeni MedAtlas'ta: orada kapı "şemaya uyuyor mu" diye soruyordu ve o soru eğitim içeriği için yetmiyordu. Burada soru "gözden geçirildi mi" hâline geldi. Eksik kalan taraf ise sürüm numarasının kendisi: aktarımın idempotentliği içerik sürümünün doğru artırılmasına bağlı ve bunu zorlayan hiçbir şey yok — metni değiştirip sürümü unutmak, değişikliğin cihaza hiç ulaşmaması demek. Bugün içerik dosyasının özetini alıp sürümle karşılaştıran bir kontrol yazardım; böylece kural insanın dikkatinde değil, kapının içinde dururdu. Bergaz Operasyon'da öğrendiğim şeyin aynısı: garanti kontrolün içinde değil de alışkanlıkta durduğu sürece er geç biri unutuyor.
Ne yapmak istediğinizi anlatın; ne kadar süreceğini ve nereden başlanacağını baştan söylerim.