Kotlin + SQLite için çevrimdışı-öncelikli form çakışma çözümü
Çevrimdışı-öncelikli form çakışma çözümünü öğrenin: net alan bazlı birleştirme kuralları, basit Kotlin + SQLite senkron akışı ve düzenleme çakışmaları için pratik UX desenleri.

İki kişi çevrimdışıyken gerçekten ne oluyor?
Çevrimdışı-öncelikli formlar, ağ yavaş veya kullanılamaz olduğunda bile insanların veriyi görmesine ve düzenlemesine izin verir. Sunucuyu beklemek yerine uygulama önce değişiklikleri yerel bir SQLite veritabanına yazar, sonra daha sonra senkronize eder.
Bu anlık hissettirir, ama basit bir gerçeklik oluşturur: iki cihaz aynı kaydı birbirlerinden habersiz değiştirebilir.
Tipik bir çakışma şöyle görünür: bir saha teknisyeni sinyal olmayan bir bodrumda bir tablete iş emrini açar. Durumu Done olarak işaretler ve bir not ekler. Aynı anda bir süpervizör başka bir telefonda aynı iş emrini günceller, yeniden atar ve son teslim tarihini değiştirir. Her ikisi de Kaydet'e basar. Her iki kayıt da yerelde başarılı olur. Kimse yanlış yapmadı.
Senkron nihayet gerçekleştiğinde sunucunun hangi kaydın “gerçek” olduğunu belirlemesi gerekir. Çakışmaları açıkça ele almazsanız genellikle şu sonuçlardan biri olur:
- Son yazan kazanır: daha sonra gelen senkron önceki değişiklikleri üzerine yazar ve biri veri kaybı yaşar.
- Sert hata: senkron bir güncellemeyi reddeder ve uygulama yararlı olmayan bir hata gösterir.
- Çoğaltılmış kayıtlar: üzerine yazmamak için sistem ikinci bir kopya oluşturur ve raporlar karışık olur.
- Sessiz birleştirme: sistem değişiklikleri birleştirir, ama kullanıcıların beklemediği şekilde alanları karıştırır.
Çakışmalar bir hata değildir. İnsanların canlı bağlantı olmadan çalışmasına izin vermenin öngörülebilir sonucudur; bu çevrimdışı-öncelikli olmanın tüm amacı.
Amaç iki yönlüdür: veriyi korumak ve uygulamayı kullanımı kolay tutmak. Bu genellikle net birleştirme kuralları (çoğunlukla alan düzeyinde) ve yalnızca gerçekten önemli olduğunda kullanıcıyı kesintiye uğratan bir kullanıcı deneyimi anlamına gelir. İki düzenleme farklı alanlara dokunuyorsa genellikle sessizce birleştirebilirsiniz. İki kişi aynı alanı farklı şekillerde değiştirirse, uygulama bunu görünür kılmalı ve doğru sonucu seçmeye yardımcı olmalıdır.
Verilerinize uygun bir çakışma stratejisi seçin
Çakışmalar öncelikle teknik bir sorun değildir. İki kişinin eşitlemeden önce aynı kaydı değiştirdiğinde “doğru”nun ne anlama geldiğine dair bir ürün kararıdır.
Çoğu çevrimdışı uygulamayı kapsayan üç strateji vardır:
- Last write wins (LWW): en yeni düzenlemeyi kabul edip eskisini üzerine yaz.
- Manuel inceleme: dur ve bir insanın neyi tutacağını seçmesini iste.
- Alan düzeyinde birleştirme: değişiklikleri alan bazında birleştir ve yalnızca iki kişi aynı alanı değiştirdiyse sor.
LWW, hızın mükemmel doğruluktan daha önemli olduğu ve yanlış olmanın maliyetinin düşük olduğu durumlarda uygundur. İç notlar, kritik olmayan etiketler veya daha sonra tekrar düzenlenebilecek taslak durumlar buna örnektir.
Manuel inceleme, uygulamanın tahminde bulunmaması gereken yüksek etkili alanlar için daha güvenlidir: hukuki metin, uyumluluk onayları, bordro ve fatura tutarları, banka bilgileri, ilaç talimatları ve sorumluluk yaratabilecek her şey.
Alan düzeyinde birleştirme, farklı rollerin formun farklı bölümlerini güncellediği formlar için genellikle en iyi varsayılandır. Bir destek temsilcisi adresi düzenlerken satış yenileme tarihini günceller. Alan başına birleştirme her iki değişikliği de kimseyi rahatsız etmeden korur. Ancak her iki kullanıcı da yenileme tarihini düzenlediyse, o alan bir karar tetiklemelidir.
Herhangi bir şeyi uygulamadan önce işiniz için “doğru”nun ne anlama geldiğini yazın. Hızlı bir kontrol listesi yardımcı olur:
- Hangi alanlar her zaman en güncel gerçek dünyadaki değeri yansıtmalı (örneğin mevcut durum)?
- Hangi alanlar tarihsel ve asla üzerine yazılmamalı (örneğin gönderim zamanı)?
- Hangi alanları kim değiştirebilir (rol, sahiplik, onaylar)?
- Değerler uyuşmazsa doğruluk kaynağı nedir (cihaz, sunucu, yönetici onayı)?
- Yanlış seçim yaparsanız ne olur (küçük rahatsızlık mı yoksa mali/hukuki etki mi)?
Kurallar net olduğunda, senkron kodunun bir işi vardır: bunları uygulamak.
Ekran yerine alan bazında birleştirme kuralları tanımlayın
Bir çakışma olduğunda nadiren tüm form eşit şekilde etkilenir. Bir kullanıcı telefon numarasını güncellerken başka biri not ekleyebilir. Tüm kaydı topluca ele alırsanız kişileri iyi yapılmış işi tekrar etmeye zorlamış olursunuz.
Alan düzeyinde birleştirme daha öngörülebilirdir çünkü her alanın bilinen bir davranışı vardır. UX sakin ve hızlı kalır.
Basit bir başlangıç yolu, alanları “genellikle güvenli” ve “genellikle güvensiz” olarak ayırmaktır.
Genellikle otomatik olarak güvenle birleştirilebilenler: notlar ve dahili yorumlar, etiketler, ekler (çoğunlukla birleşim), ve "son iletişim" gibi zaman damgaları (çoğunlukla en yeniyi koru).
Genellikle otomatik olarak birleştirilmesi güvensiz olanlar: durum/state, atanan kişi/sahip, toplamlar/fiyatlar, onay bayrakları ve envanter sayıları.
Sonra her alan için bir öncelik kuralı seçin. Yaygın seçenekler: sunucu kazanır, istemci kazanır, rol kazanır (örneğin yönetici temsilcinin üzerinde), veya deterministik bir kırılma kuralı gibi en yeni sunucu sürümü.
Ana soru, her iki taraf da aynı alanı değiştirdiğinde ne olduğudur. Her alan için bir davranış seçin:
- Net bir kural ile otomatik birleştir (örneğin etiketler birleşim olur)
- Her iki değeri sakla (örneğin notları yazar ve zaman/kişi ile ekle)
- İncelemeye işaretle (örneğin durum ve atanan kişi bir seçim gerektirir)
Örnek: iki destek temsilcisi çevrimdışı olarak aynı ticket’ı düzenliyor. Temsilci A statusu "Open"dan "Pending"e değiştirir. Temsilci B notesi değiştirir ve "refund" etiketini ekler. Senkron sırasında notes ve tags güvenle birleştirilebilir, ancak statusu sessizce birleştirmemelisiniz. Sadece status için kullanıcıyı prompt edin, diğer her şey zaten birleştirilmiş olsun.
Sonradan tartışmaları önlemek için, her alan için bir cümlelik kural dokümante edin:
- "
notes: ikisini de sakla, en yeniyi sona ekle, yazar ve zamanı dahil et." - "
tags: birleşim, sadece her iki tarafta da açıkça kaldırıldıysa çıkar." - "
status: her iki tarafta da değiştiyse kullanıcı kararı gerektirir." - "
assignee: yönetici kazanır, değilse sunucu kazanır."
Bu bir cümlelik kural Kotlin kodu, SQLite sorguları ve çakışma UI’sı için tek gerçek kaynağı olur.
Veri modeli temel bilgileri: SQLite’ta sürümler ve denetim alanları
Çakışmaların öngörülebilir hissetmesini istiyorsanız, her eşitlenen tabloya küçük bir meta sütun seti ekleyin. Bunlar olmadan, elinizdeki kaydın taze bir düzenleme mi, eski bir kopya mı yoksa birleştirme gerektiren iki düzenleme mi olduğunu söyleyemezsiniz.
Her sunucu eşli kaydı için pratik asgari set:
id(kalıcı birincil anahtar): asla yeniden kullanmayınversion(integer): sunucuda her başarılı yazmada artarupdated_at(zaman damgası): kaydın son değiştiği zamanupdated_by(metin veya kullanıcı id): son değişikliği yapan
Cihazda, sunucu tarafından onaylanmamış değişiklikleri izlemek için yerel alanlar ekleyin:
dirty(0/1): yerel değişiklikler varpending_sync(0/1): yüklenmek üzere kuyruğa alındı ama onaylanmadılast_synced_at(zaman damgası): bu satırın sunucu ile eşitlendiği son zamansync_error(metin, isteğe bağlı): UI'da göstermek için son hata nedeni
İyimser eşzamanlılık, sessiz üzerine yazmaları önleyen en basit kuraldır: her güncelleme düzenlediğinizi düşündüğünüz sürümü (expected_version) içerir. Eğer sunucu kaydı hâlâ o sürümdeyse, güncelleme kabul edilir ve sunucu yeni sürümü döndürür. Değilse, bu bir çakışmadır.
Örnek: Kullanıcı A ve B ikisi de version = 7yi indirdi. A önce senkronize olur; sunucu 8e çıkar. B expected_version = 7 ile senkronize etmeye çalıştığında sunucu çakışma ile reddeder, böylece B’nin uygulaması üzerine yazmak yerine birleştirir.
İyi bir çakışma ekranı için paylaşılan başlangıç noktasını saklayın: kullanıcı aslında hangi sürümden düzenledi. Yaygın yaklaşımlar:
- Son eşitlenen kaydın bir anlık görüntüsünü saklayın (tek bir JSON sütunu veya paralel bir tablo).
- Bir değişiklik günlüğü saklayın (her düzenleme için bir satır veya alan başına bir satır).
Anlık görüntüler daha basittir ve birçok form için yeterlidir. Değişiklik günlükleri daha ağırdır, ancak tam olarak hangi alanın nasıl değiştiğini açıklayabilir.
Her iki durumda da UI, her alan için üç değeri gösterebilmeli: kullanıcının düzenlemesi, sunucunun mevcut değeri ve paylaşılan başlangıç noktası.
Kayıt anlık görüntüleri vs değişiklik günlükleri: bir yaklaşım seçin
Çevrimdışı-öncelikli formları senkronize ederken, tam kaydı (anlık görüntü) yükleyebilir veya bir işlem listesi (değişiklik günlüğü) yükleyebilirsiniz. Her ikisi de Kotlin ve SQLite ile çalışır, fakat iki kişi aynı kaydı düzenlediğinde farklı davranırlar.
Seçenek A: Tam kayıt anlık görüntüleri
Anlık görüntülerde her kaydetme en son tam durumu (tüm alanlar) yazar. Senkron sırasında kaydı ve bir sürüm numarasını gönderirsiniz. Sunucu sürümün eski olduğunu görürse çakışma oluşur.
Bu kurmak için basittir ve okumak hızlıdır, ama genellikle gereğinden büyük çakışmalara yol açar. Kullanıcı A telefon numarasını düzenlerken Kullanıcı B adresi düzenlediyse, anlık görüntü yaklaşımı bunları örtüşmeyen değişiklikler olmasına rağmen büyük bir çakışma olarak ele alabilir.
Seçenek B: Değişiklik günlükleri (işlemler)
Değişiklik günlüklerinde ne değiştiğini saklarsınız, tüm kaydı değil. Her yerel düzenleme, üzerine en güncel sunucu durumunda tekrar oynatılabilecek bir işlem olur.
Genellikle daha kolay birleştirilebilen işlemler:
- Bir alanı ayarla (örneğin
emaili yeni bir değere ayarla) - Not ekle (yeni not öğesi ekler)
- Etiket ekle (bir etiketi küme içine ekler)
- Etiket kaldır (kümden bir etiketi çıkarır)
- Bir onay kutusunu işaretle (örneğin
isDoneu true yap ve zaman damgası ekle)
İşlem günlükleri çakışmaları azaltabilir çünkü birçok eylem örtüşmez. Not eklemek nadiren başka birinin farklı bir not eklemesiyle çakışır. Etiket ekleme/kaldırma küm işlemi gibi birleşebilir. Tek değerli alanlar için iki farklı düzenleme yarıştığında yine alan başına kurallara ihtiyaç vardır.
Takas, karmaşıklıktır: kararlı işlem ID’leri, sıralama (yerel sıra ve sunucu zamanı) ve değişmeyen işlemler için kurallar gerekir.
Temizlik: başarılı senkron sonrası sıkıştırma
İşlem günlükleri büyür, bu yüzden nasıl küçülteceğinizi planlayın.
Yaygın bir yaklaşım kayıt başına sıkıştırmadır: bilinen bir sunucu sürümüne kadar tüm işlemler onaylandığında, bunları yeni bir anlık görüntüye katlayın ve sonra eski işlemleri silin. Geri alma, denetim veya hata ayıklama için kısa bir kuyruk tutun.
Kotlin + SQLite için adım adım senkron akışı
İyi bir senkron stratejisi, gönderdiğiniz ve kabul ettiğiniz verilerde katı olmakla ilgilidir. Amaç basittir: daha yeni veriyi kazara üzerine yazma ve güvenle birleştirilemeyen durumlarda çakışmaları görünür yapmak.
Pratik bir akış:
-
Her düzenlemeyi önce SQLite’a yazın. Değişiklikleri yerel bir işlemde kaydedin ve kaydı
pending_sync = 1olarak işaretleyin.local_updated_atve son bilinenserver_versioni saklayın. -
Tam kayıt yerine yama gönderin. Bağlantı geri döndüğünde sadece değişen alanları ve
expected_versionile kayıt id’sini gönderin. -
Sunucunun uyumsuz sürümleri reddetmesine izin verin. Eğer sunucunun mevcut sürümü
expected_versionile eşleşmiyorsa, sunucu bir çakışma yükü döndürsün (sunucu kaydı, önerilen değişiklikler ve hangi alanların farklı olduğu). Sürümler eşleşiyorsa yama uygulanır, sürüm artırılır ve güncellenmiş kayıt döndürülür. -
Önce otomatik birleştirme uygula, sonra kullanıcıyı sor. Alan düzeyinde birleştirme kurallarını çalıştırın. Notlar gibi güvenli alanları durum, fiyat veya atanan kişi gibi hassas alanlardan farklı ele alın.
-
Nihai sonucu kaydet ve bekleyen bayrakları temizle. Otomatik birleştirilmiş veya manuel çözülmüş olsun, nihai kaydı SQLite’a yazın,
server_versioni güncelleyin,pending_sync = 0yapın ve sonra ne olduğunu açıklamak için yeterli denetim verisini kaydedin.
Örnek: iki satış temsilcisi aynı siparişi çevrimdışı düzenlesin. Temsilci A teslim tarihini değiştirir. Temsilci B müşteri telefonunu değiştirir. Yamalarla sunucu her iki değişikliği de temizce kabul edebilir. Eğer her ikisi de teslim tarihini değiştirdiyse, tam yeniden giriş zorlamak yerine tek bir açık kararı gösterirsiniz.
UI sözü tutmalı: "Kaydedildi" yerelde kaydedildi anlamına gelsin. "Eşitlendi" ayrı, açık bir durum olsun.
Formlardaki çakışmaları çözmek için UX kalıpları
Çakışmalar istisna olmalı, normal akış değil. Önce güvenli olanları otomatik birleştirin, sonra gerçekten karar gerektiğinde kullanıcıya sorin.
Güvenli varsayıntılarla çakışmaları nadir kılın
İki kişi farklı alanları düzenlediyse, bir modal göstermeden birleştirin. Her iki değişikliği de tutun ve küçük bir "Eşitleme sonrası güncellendi" mesajı gösterin.
Gerçek çakışmalar için prompt ayırın: aynı alanın her iki cihazda da değiştirilmesi ya da bir değişikliğin başka bir alana bağlı olması (örneğin durum ve durum nedeni).
Sorun gerektiğinde tamamlamayı hızlı yapın
Bir çakışma ekranı iki soruyu yanıtlamalı: ne değişti ve ne kaydedilecek. Değerleri yan yana karşılaştırın: "Sizin düzenlemeniz", "Onların düzenlemesi" ve "Kaydedilecek sonuç". Sadece iki alan çakışıyorsa tüm formu göstermeyin. Doğrudan o alanlara atlayın ve geri kalanları salt okunur tutun.
Eylemleri insanların gerçekten ihtiyaç duyduğu kadar sınırlayın:
- Benimkinin olsun
- Onların olsun
- Nihai düzenle
- Alan alan inceleme (sadece gerektiğinde)
Kısmi birleşmeler UX’i karıştırır. Sadece çakışan alanları vurgulayın ve kaynağı net etiketleyin ("Sizin" ve "Onların"). En güvenli seçeneği öntanımlı seçin ki kullanıcı onaylayıp ilerleyebilsin.
Kullanıcılara bırakırlarsa ne olacağını söyleyin: örneğin, "Sürümünüz yerelde tutulacak ve daha sonra tekrar denenecek" veya "Bu kayıt Seçim Bekliyor olarak kalacak" gibi. Bu durumu listede görünür yapın ki çakışmalar kaybolmasın.
AppMaster ile bu akışı inşa ediyorsanız, aynı UX yaklaşımı geçerlidir: önce güvenli alanları otomatik birleştir, sonra belirli alanlar çakıştığında odaklanmış bir inceleme adımı gösterin.
Zor durumlar: silmeler, çoğaltmalar ve "kayıp" kayıtlar
Çoğu rastgele görünen senkron sorunu üç durumdan gelir: biri silerken diğeri düzenliyor, iki cihaz çevrimdışı aynı şeyi oluşturuyor, veya bir kayıt kaybolup sonra yeniden ortaya çıkıyor. Bunlar açık kurallar gerektirir çünkü LWW insanları şaşırtabilir.
Silme vs düzenleme: kim kazanır?
Silmenin düzenlemeden daha güçlü olup olmayacağını kararlaştırın. Birçok iş uygulamasında silme kazanır çünkü kullanıcılar silinen kaydın silinmiş kalmasını bekler.
Pratik bir kural seti:
- Herhangi bir cihazda bir kayıt silindiyse, onu diğer yerlerde de silinmiş sayın, düzenlemeler olsa bile.
- Silmeler geri alınabilir olmalıysa, sert silme yerine kaydı arşivlenmiş bir duruma çevirin.
- Silinmiş bir kayıt için düzenleme gelirse, denetim için düzenlemeyi geçmişte tutun ama kaydı geri getirmeyin.
Çevrimdışı oluşturma çakışmaları ve çoğaltılmış taslaklar
Çevrimdışı-öncelikli formlar genellikle sunucu son ID atamadan önce geçici ID (örneğin UUID) oluşturur. Kullanıcılar aynı gerçek dünyadaki şeyi (aynı fiş, aynı ticket) iki kez oluşturduğunda çoğaltmalar olur.
Stabil doğal bir anahtarınız (fiş numarası, barkod, e-posta+tarih) varsa çakışmaları tespit etmek için kullanın. Yoksa, çoğaltmaların olabileceğini kabul edin ve daha sonra basit bir birleştirme seçeneği sunun.
Uygulama ipucu: SQLite’ta hem local_id hem server_id saklayın. Sunucu yanıt verdiğinde bir eşleme yazın ve kuyrukta local ID’ye referans veren işler kalmayana kadar bunu saklayın.
Senkron sonrası "yeniden canlanmayı" önleme
Yeniden canlanma, Cihaz A bir kaydı sildiğinde, ancak Cihaz B çevrimdışı olup sonra eski bir kopyayı upsert ederek kaydı yeniden oluşturduğunda olur.
Çözüm bir tombstone’dur. Satırı hemen kaldırmak yerine deleted_at ile silinmiş olarak işaretleyin (genellikle deleted_by ve delete_version ile birlikte). Senkron sırasında tombstonelar eski silinmemiş durumları geçersiz kılabilen gerçek değişiklikler olarak ele alın.
Tombstone’ları ne kadar süre tutacağınıza karar verin. Kullanıcılar haftalarca çevrimdışı kalabiliyorsa, silinmeden daha uzun süre tutun. Sadece aktif cihazların silinme sürümünü geçtiğinden emin olduğunuzda temizleyin.
Geri almayı destekliyorsanız, geri almayı başka bir değişiklik olarak ele alın: deleted_atı temizleyin ve versiyonu artırın.
Veri kaybına veya kullanıcı rahatsızlığına yol açan yaygın hatalar
Birçok senkron hatası, iyi veriyi sessizce üzerine yazan küçük varsayımlardan kaynaklanır.
Hata 1: Düzenlemeleri sıralamak için cihaz saatine güvenmek
Telefonların saatleri yanlış olabilir, saat dilimleri değişir ve kullanıcılar saati manuel ayarlayabilir. Düzenlemeleri cihaz zaman damgalarına göre sıralarsanız, sonunda düzenlemeleri yanlış sırada uygulamış olursunuz.
Değişiklikleri sıralamak için sunucu tarafından verilen sürümleri (serverVersion) tercih edin ve istemci zaman damgalarını sadece gösterim amaçlı kullanın. Zaman kullanmak zorundaysa koruyucu önlemler ekleyin ve sunucuda uzlaştırın.
Hata 2: Hassas alanlarda istemeden LWW uygulanması
LWW basit görünür ama durum, toplamlar, onaylar ve atamalar gibi kazanılmaması gereken alanlara çarptığında sorun çıkarır. Bu alanlara açık kurallar veya manuel inceleme getirilmeli.
Yüksek riskli alanlar için güvenlik kontrol listesi:
- Durum geçişlerini bir durum makinesi olarak ele alın, serbest metin olarak değil.
- Toplamları satır öğelerinden yeniden hesaplayın. Toplamları ham sayı olarak birleştirmeyin.
- Sayaçlar için kazananı seçmek yerine deltalara göre birleştirin.
- Sahiplik veya atama çakışmalarında açık onay gerektirin.
Hata 3: Eski önbelleklenmiş verilerle daha yeni sunucu değerlerini üzerine yazmak
Bu, istemci eski bir anlık görüntüyü düzenleyip sonra tam kaydı yüklediğinde olur. Sunucu kabul eder ve daha yeni sunucu tarafı değişiklikleri kaybolur.
Gönderdiğiniz verinin şeklini düzeltin: sadece değişen alanları (veya bir değişiklik günlüğünü) gönderin ve düzenlediğiniz temel sürümü gönderin. Temel sürüm gerideyse sunucu reddetsin veya birleştirme zorlasın.
Hata 4: "Kim neyi değiştirdi" geçmişinin olmaması
Çakışma olduğunda kullanıcılar genellikle tek bir soru sorar: neyi ben değiştirdim ve diğer kişi neyi değiştirdi? Düzenleyeni ve alan başına değişiklikleri saklamadan çakışma ekranı tahminlerden ibaret olur.
updatedBy, sunucu tarafı güncelleme zamanı ve en azından hafif bir alan başına denetim izi saklayın.
Hata 5: Tüm kaydı karşılaştırmaya zorlayan çakışma UI’sı
İnsanları tüm kayıtla karşılaştırmaya zorlamak yorucudur. Çoğu çakışma sadece bir ila üç alanı etkiler. Sadece çakışan alanları gösterin, en güvenli seçeneği öntanımlı yapın ve kullanıcının geri kalanını otomatik kabul etmesine izin verin.
AppMaster gibi no-code araçlarda formlar oluşturuyorsanız aynı hedefe odaklanın: kullanıcıların tüm formu kaydırıp karşılaştırmak zorunda kalmayacağı şekilde alan bazında çözüm sağlayın.
Hızlı kontrol listesi ve sonraki adımlar
Çevrimdışı düzenlemelerin güvenli hissetmesi için çakışmaları bir hata değil normal bir durum olarak ele alın. En iyi sonuçlar net kurallardan, tekrarlanabilir testlerden ve ne olduğunu basit bir dille açıklayan UX’ten gelir.
Özellik eklemeden önce bu temellerin sağlam olduğundan emin olun:
- Her kayıt türü için alan başına bir birleştirme kuralı atayın (LWW, max/min tut, ekle, birleşim veya her zaman sor).
- Sunucu kontrollü bir sürüm ve sizin kontrol ettiğiniz bir
updated_atsaklayın ve senkron sırasında bunları doğrulayın. - Aynı kaydı iki cihazla çevrimdışı düzenleyip sonra her iki sırayla (A sonra B, B sonra A) senkronize eden iki-cihaz testi çalıştırın. Sonuç öngörülebilir olmalı.
- Zor çakışmaları test edin: silme vs düzenleme ve farklı alanlarda düzenleme vs düzenleme.
- Durumu görünür yapın: Synced, Pending upload ve Needs review gibi durumları gösterin.
Tam akışı uçtan uca bir gerçek form ile prototipleyin, demo ekran değil. Gerçekçi bir senaryo kullanın: bir saha teknisyeni telefonda bir iş notu güncellerken bir dağıtıcı aynı işin başlığını tablette değiştiriyor. Farklı alanlara dokunurlarsa otomatik birleştirin ve küçük bir "Diğer cihazdan güncellendi" ipucu gösterin. Aynı alanı değiştirirlerse basit bir iki seçenekli inceleme ekranına yönlendirin ve net bir önizleme gösterin.
Tam mobil uygulamayı ve backend API’leri birlikte oluşturmaya hazırsanız, AppMaster (appmaster.io) yardımcı olabilir. Veri modelleyebilir, iş mantığını tanımlayabilir ve web ile native mobil UI’lar oluşturabilirsiniz; senkron kurallarınız sağlam hissettiğinde dağıtabilir veya kaynak kodu dışa aktarabilirsiniz.
SSS
Bir çakışma, iki cihazın aynı sunucu destekli kaydı ağ dışındayken (veya henüz eşitlenmemişken) değiştirmesi ve sunucunun daha sonra her iki güncellemenin de eski bir sürüme dayandığını görmesi durumunda oluşur. Sistem, farklı olan her alan için nihai değerin ne olması gerektiğine karar vermelidir.
Çoğu iş formu için varsayılan olarak alan düzeyinde birleştirme ile başlayın: farklı roller genellikle farklı alanları günceller ve böylece kimseyi rahatsız etmeden her iki değişikliği de koruyabilirsiniz. Manuel inceleme sadece para, onaylar veya uyumluluk gibi yanlış kararın ciddi sonuçları olabileceği alanlar için kullanın. Last write wins (son yazan kazanır) yalnızca eski bir düzenlemenin kaybının kabul edilebilir olduğu düşük riskli alanlar için uygundur.
Eğer iki düzenleme farklı alanlara dokunuyorsa genellikle otomatik olarak birleştirebilirsiniz ve UI sessiz kalır. Aynı alan iki farklı değere değiştirildiyse, bu alan bir karar gerektirmelidir; çünkü otomatik bir seçim birisini şaşırtabilir. Çözüm kapsamını küçültmek için sadece çakışan alanları gösterin, tüm formu değil.
version değerini kaydın sunucu tarafından monoton artan sayacı olarak ele alın ve her güncelleme ile istemcinin expected_version göndermesini zorunlu kılın. Eğer sunucunun mevcut sürümü eşleşmiyorsa, üzerine yazmak yerine bir çakışma yanıtı döndürün. Bu tek kural, farklı cihazların farklı sırayla senkronize olması durumunda bile “sessiz veri kaybını” önler.
Pratik bir asgari set: kalıcı id, sunucu kontrollü version ve sunucu kontrollü updated_at/updated_by (ne değiştiğini açıklamak için). Cihaz tarafında ise satırın değişip değişmediğini ve gönderilmeyi bekleyip beklemediğini takip edin (örneğin pending_sync) ve son eşitlenen sunucu sürümünü saklayın. Bunlar olmadan çakışmaları güvenilir şekilde tespit edemez veya yardım edici bir çözüm ekranı gösteremezsiniz.
Değişen alanları (bir yama) ve temel expected_version ile birlikte gönderin. Tam kayıt yüklemeleri küçük, örtüşmeyen düzenlemeleri gereksiz çakışmalara dönüştürür ve eski önbelleklenmiş bir değerin daha yeni sunucu değerinin üzerine yazılma riskini artırır. Yamalar ayrıca hangi alanların birleştirme kurallarına ihtiyaç duyduğunu daha net gösterir.
Anlık durumu saklamak daha basittir: en son tam kaydı tutup sonrasında sunucuyla karşılaştırırsınız. Değişiklik günlüğü daha esnektir: "alanı ayarla" veya "not ekle" gibi işlemleri saklayıp bunları en güncel sunucu durumunun üstüne tekrar oynatabilirsiniz; notlar, etiket eklemeleri gibi ekleyici güncellemeler için bu genellikle daha iyi birleşir. Hızlı bir uygulama istiyorsanız anlık görüntüleri; sık birleşme ve kim neyi değiştirdiğini net görmek istiyorsanız değişiklik günlüklerini tercih edin.
Silme eyleminin düzenlemeye göre daha güçlü olup olmayacağını önceden kararlaştırın; kullanıcılar tutarlı davranış bekler. Birçok iş uygulaması için güvenli varsayılan, silinmiş olarak işaretlemektir (tombstone): deleted_at ve bir versiyon ile işaretleyin, böylece daha eski bir çevrimdışı upsert kaydı yeniden canlandıramaz. Geri alınabilirlik gerekiyorsa, sert silme yerine "arşivlendi" durumunu kullanın.
Cihaz saatine göre düzenlemeleri sıralamayın; telefon saatleri hatalı olabilir veya kullanıcı manuel olarak değiştirebilir. Değişiklikleri sıralamak ve çakışma kontrolleri için sunucu sürümlerini tercih edin. Zaman kullanmak zorundaysa koruyucu önlemler ekleyin ve sunucuda uzlaştırma yapın.
“Kaydedildi” demek yerelde kaydedildi anlamına gelsin ve kullanıcıların neyin eşitlendiğini anlaması için ayrı bir “Eşitlendi” durumu gösterin. AppMaster ile inşa ediyorsanız aynı yapıyı hedefleyin: alan düzeyinde birleştirme kurallarını ürün mantığınızın bir parçası olarak tanımlayın, güvenli alanları otomatik birleştirin ve yalnızca gerçek alan çakışmalarını küçük bir inceleme adımına yönlendirin. Ayrıca iki cihazla yapılan testlerle sonuçların öngörülebilir olduğunu doğrulayın.


