İçeriğe geç
academia.sh

Ders 19 / 19

Uzak Bildirimler

Sunucudan gelen bildirimin yerelde rozeti artırmasının yinelemeye duyarlı, yükteki mutlak rozet değerinin sıraya duyarlı olmasının ölçümü ve kursun on dokuz dersinin kapanış tablosu.

Yayın Güncelleme

Bu derste

  • Uzak bildirimin teslim edilmesinin garanti olmadığını ve iki kez gelebileceğini ayırır
  • Rozeti yerelde artırmanın yinelemeye, yükte mutlak değer taşımanın sıraya duyarlı olduğunu ölçer
  • Bildirim kimliğiyle elemenin yinelemeyi çözdüğünü, sırayı çözmediğini gösterir
  • Kursun on dokuz dersini duyarlılıklarına göre tek tabloda okur
İçindekiler

Önceki derste aynı kaydı iki aygıtın yazması sırayı uygulamanın elinden aldı. Uzak bildirimde sıra ve sayı bir adım daha uzaklaşır: iletiyi sunucu hazırlar, platformun bildirim servisi taşır ve uygulama onu ancak teslim edilince görür. Bu servis teslimi garanti etmez; bir bildirim gecikebilir, hiç gelmeyebilir ya da iki kez gelebilir. Kursun sorusu bu uçta da aynıdır: bu işlem yinelenirse ya da sırası değişirse sonuç değişir mi? Bu ders son dersimizdir; ölçümden sonra kursun on dokuz dersi tek tabloda toplanır.

// Replay.swift — bir islemin yinelemeye ve siraya duyarliligini siniflandirir
struct Trial<State: Equatable & CustomStringConvertible> {
    let label: String
    let once: State
    let twice: State
    let forward: State
    let backward: State

    var sensitivity: String {
        switch (once != twice, forward != backward) {
        case (false, false): return "saglam"
        case (true, false): return "yinelemeye-duyarli"
        case (false, true): return "siraya-duyarli"
        case (true, true): return "cift-duyarli"
        }
    }

    func report() -> String {
        print("\(label) | bir=\(once) iki=\(twice) ab=\(forward) ba=\(backward) -> \(sensitivity)")
        return sensitivity
    }
}

func replay<State>(_ label: String, from start: State, _ a: (State) -> State, then b: (State) -> State) -> Trial<State> {
    Trial(label: label, once: a(start), twice: a(a(start)), forward: b(a(start)), backward: a(b(start)))
}

func countSensitivities(_ results: [String]) {
    for name in ["saglam", "yinelemeye-duyarli", "siraya-duyarli", "cift-duyarli"] {
        print("\(name): \(results.filter { $0 == name }.count)")
    }
}

bir işlemin başlangıç durumuna bir kez, iki iki kez uygulanmasıdır; ab önce a sonra b, ba ise tersi sıradır. Aşağıdaki model uygulamanın bildirimle değişen durumunu kurar: bir rozet sayısı, bir aygıt belirteci ve işlenmiş bildirim kimlikleri.

İzin ve Kayıt Akışı

Uygulama bildirim alabilmek için iki adım atar. Önce kullanıcıdan izin ister, sonra platformdan bir aygıt belirteci ister. Belirteç, bu uygulamanın bu aygıttaki adresidir ve sunucuya iletilir; sunucu bildirimi bu adrese gönderir. Parça KAYNAK’tır, çünkü gerçek bir izin ekranı ve bir ağ bağlantısı gerektirir.

import UIKit
import UserNotifications

let center = UNUserNotificationCenter.current()
let granted = try await center.requestAuthorization(options: [.alert, .badge, .sound])

if granted {
    await MainActor.run {
        UIApplication.shared.registerForRemoteNotifications()
    }
}

func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let hex = deviceToken.map { String(format: "%02x", $0) }.joined()
    print(hex)
}

Kullanıcı izni reddederse kayıt çağrısı yapılmaz ve bildirim gelmez; reddetmenin ardından ayarlardan izin açılabilir, bu yüzden uygulama izin durumunu her açılışta yeniden okur. Belirteç sabit değildir: platform onu yenileyebilir, bu yüzden uygulama her açılışta kayıt çağrısını yeniler ve gelen değeri sunucuya yeniden bildirir. Bu yinelemenin sonucu, bu dersin ölçtüğü üç işlemden biridir.

Bildirimin Modeli

Model üç durumu tutar. Rozet uygulamanın simgesindeki sayıdır. Belirteç, son kaydedilen aygıt adresidir. İşlenenler, uygulamanın daha önce işlediği bildirim kimlikleridir ve yalnız kimlikle eleme yapan işlemde dolar. Basımda işlenenler boşsa gösterilmez.

// PushModel.swift — rozet, belirtec ve islenen bildirimlerin saf Swift modeli
struct PushState: Equatable, CustomStringConvertible {
    private(set) var badgeCount: Int
    private(set) var token: String
    private(set) var handled: Set<String>

    init(badgeCount: Int, token: String = "-", handled: Set<String> = []) {
        self.badgeCount = badgeCount
        self.token = token
        self.handled = handled
    }

    var description: String {
        let base = "rozet=\(badgeCount) belirtec=\(token)"
        return handled.isEmpty ? base : base + " islenen=" + handled.sorted().joined(separator: ",")
    }

    func incrementing() -> PushState {
        PushState(badgeCount: badgeCount + 1, token: token, handled: handled)
    }

    func setting(badgeCount value: Int) -> PushState {
        PushState(badgeCount: value, token: token, handled: handled)
    }

    func registering(token value: String) -> PushState {
        PushState(badgeCount: badgeCount, token: value, handled: handled)
    }

    func incrementing(onceFor id: String) -> PushState {
        guard !handled.contains(id) else { return self }
        return PushState(badgeCount: badgeCount + 1, token: token, handled: handled.union([id]))
    }
}

func incrementingBadge() -> (PushState) -> PushState {
    { $0.incrementing() }
}

func settingBadge(_ value: Int) -> (PushState) -> PushState {
    { $0.setting(badgeCount: value) }
}

func registeringToken(_ value: String) -> (PushState) -> PushState {
    { $0.registering(token: value) }
}

func incrementingOnce(id: String) -> (PushState) -> PushState {
    { $0.incrementing(onceFor: id) }
}

KL21. Model, her bildirimi tam bir kez uygulanan bir işlem olarak kurar. Platformun aynı bildirimi sıfır, bir ya da birkaç kez teslim edebildiği ve bunun sıklığı ölçülmedi; ölçülen şey, teslim iki kez olursa ne olacağıdır.

KL22. Mutlak rozet değeri sunucuda hesaplanır ve yükte taşınır; model değerin doğru hesaplandığını varsayar. Sunucunun bu sayıyı nasıl bulduğu ölçülmedi.

KL23. Bildirim kimliği benzersiz ve sabit varsayılır. Gerçek bir hizmette kimliğin nasıl üretildiği ve yeniden denemede korunup korunmadığı ölçülmedi.

Üç İşlemin Ölçümü

Üç işlem kurulur. Birincisi her teslimde rozeti yerelde bir artırmaktır. İkincisi yükte mutlak rozet değerini taşımaktır: sunucu aps içindeki badge alanına son sayıyı yazar ve uygulama onu olduğu gibi kullanır. Üçüncüsü aynı belirteci yeniden kaydetmektir. Rozet üçten başlar.

// main.swift — rozet ve belirtec islemleri
let start = PushState(badgeCount: 3)
let local = replay("rozet-yerel-artir", from: start, incrementingBadge(), then: incrementingBadge()).report()
let absolute = replay("rozet-mutlak-deger", from: start, settingBadge(4), then: settingBadge(7)).report()
let register = replay("belirtec-yeniden-kaydet", from: start, registeringToken("t1"), then: registeringToken("t1")).report()

countSensitivities([local, absolute, register])
rozet-yerel-artir | bir=rozet=4 belirtec=- iki=rozet=5 belirtec=- ab=rozet=5 belirtec=- ba=rozet=5 belirtec=- -> yinelemeye-duyarli
rozet-mutlak-deger | bir=rozet=4 belirtec=- iki=rozet=4 belirtec=- ab=rozet=7 belirtec=- ba=rozet=4 belirtec=- -> siraya-duyarli
belirtec-yeniden-kaydet | bir=rozet=3 belirtec=t1 iki=rozet=3 belirtec=t1 ab=rozet=3 belirtec=t1 ba=rozet=3 belirtec=t1 -> saglam
saglam: 1
yinelemeye-duyarli: 1
siraya-duyarli: 1
cift-duyarli: 0

İlk satır ağ istemcisi dersindeki rozet-artir işleminin aynısıdır: bir teslim rozeti dörde, iki teslim beşe çıkarır. Bildirim iki kez teslim edilirse kullanıcı gerçekte olmayan bir okunmamış ileti görür. İşlem yinelemeye duyarlıdır.

İkinci satırda yük sayıyı taşır, bu yüzden aynı bildirimin ikinci teslimi sonucu değiştirmez: bir ile iki aynıdır. Ama iki farklı bildirim farklı sayılar taşır ve rozet sonra gelenin değerinde kalır: ab yedi, ba dört. Mutlak değer yinelemeyi çözdü, sırayı çözmedi; işlem sıraya duyarlıdır. Bir önceki dersin son yazan kazanır kuralıyla aynı yapıdır.

Üçüncü satırda aynı değeri yeniden kaydetmek durumu değiştirmez; sıra da anlamsızdır, çünkü iki işlem aynıdır. İşlem sağlamdır. Belirteç yenilemenin güvenli olmasının nedeni budur: sunucu aynı adresi iki kez almış gibi davranır.

Sayım bir sağlam, bir yinelemeye duyarlı, bir sıraya duyarlıdır.

Teslim Garanti Değildir

Ölçüm, bildirimin iki kez teslim edildiği durumu işlemin iki uygulaması olarak kurar. Gerçekte teslimin kaç kez ve hangi sırayla olacağı platformun elindedir. Bildirim hiç gelmeyebilir: aygıt kapalıdır, ağa erişemez, kullanıcı izni geri almıştır ya da platform bildirimi bırakmıştır. İki bildirim gönderildiğinde ikincisi önce gelebilir. Bu yüzden bildirim, uygulamanın tek doğruluk kaynağı olamaz.

Bundan iki sonuç çıkar. Birincisi, bildirimin taşıdığı bilgi uygulama açıldığında sunucudan yeniden okunabilmelidir; bildirim bir ipucudur, kayıt değildir. İkincisi, bildirimin yaptığı yerel değişiklik ya yinelemeye karşı korunmalı ya da hiç yapılmamalıdır. Rozeti yerelde artırmak ilk yolu gerektirir, mutlak değer ikinci yolun bir biçimidir. Bu seçim bir kural değil bir tasarım kararıdır, ve kural onu bizim yerimize vermez.

Sınırlayıcı Ölçüm

Kural eşitsizliği görür; teslimin kaç kez olduğunu görmez. Aynı rozet işlemini bu kez bildirim kimliğiyle ölçelim: uygulama bir kimliği yalnız bir kez işler. Ayrıca iki bildirimin aynı mutlak değeri taşıdığı durumu deneyelim.

// main.swift — kimlikle eleme ve esit mutlak deger
let start = PushState(badgeCount: 3)
let sameNotification = replay("kimlikli-ayni-bildirim", from: start, incrementingOnce(id: "n1"), then: incrementingOnce(id: "n1")).report()
let twoNotifications = replay("kimlikli-iki-bildirim", from: start, incrementingOnce(id: "n1"), then: incrementingOnce(id: "n2")).report()
let equalAbsolute = replay("mutlak-esit-deger", from: start, settingBadge(4), then: settingBadge(4)).report()

countSensitivities([sameNotification, twoNotifications, equalAbsolute])
kimlikli-ayni-bildirim | bir=rozet=4 belirtec=- islenen=n1 iki=rozet=4 belirtec=- islenen=n1 ab=rozet=4 belirtec=- islenen=n1 ba=rozet=4 belirtec=- islenen=n1 -> saglam
kimlikli-iki-bildirim | bir=rozet=4 belirtec=- islenen=n1 iki=rozet=4 belirtec=- islenen=n1 ab=rozet=5 belirtec=- islenen=n1,n2 ba=rozet=5 belirtec=- islenen=n1,n2 -> saglam
mutlak-esit-deger | bir=rozet=4 belirtec=- iki=rozet=4 belirtec=- ab=rozet=4 belirtec=- ba=rozet=4 belirtec=- -> saglam
saglam: 3
yinelemeye-duyarli: 0
siraya-duyarli: 0
cift-duyarli: 0

Üç işlem de sağlam çıktı. Kimlikle eleme, aynı bildirimin ikinci teslimini yok saydı; iki farklı bildirimde ise artış toplamı sıradan bağımsızdır, çünkü işlenenler küme olarak tutulur ve sıralı basılır. Eşit mutlak değer de sıra farkını gizledi: iki bildirim aynı sayıyı taşıyorsa hangisinin önce geldiğini kimse göremez.

Burada kural iki şeyi görmez. Birincisi, bildirimin gerçekte iki kez teslim edilip edilmediğidir: elemenin işe yarayıp yaramadığını ölçüm göstermez, yalnız teslim iki kez olursa sonucun aynı kalacağını gösterir. İkincisi, eşit değerin tesadüf mü tasarım mı olduğudur. Ölçülen sınıf bir kurulumun sonucudur, işlemin doğasının değil.

Saklama Seçimi

Kalıcılık konusunun altı dersi bir seçimi destekler: veri hangi saklama yerine girer. Bu seçim bir sayıya dökülmez; duyarlılık seçimin tek ölçütü değildir. Ölçütleri verinin biçimi belirler.

  • Küçük, tek değerli ve gizli olmayan ayarlar tercih deposuna girer.
  • Parola, belirteç ve anahtar gibi gizli değerler anahtarlığa girer.
  • Uygulamanın kendi ürettiği belgeler, medya ve önbellekler dosya sistemine girer; hangi dizinin yedeklendiği ayrıca düşünülür.
  • Sorgulanan, ilişkili ve çok sayıda kayıt yerel veritabanına ya da nesne kalıcılık çerçevesine girer.
  • Birden çok aygıtta aynı olması gereken kayıt bulut eşitlemeye girer ve çakışma kuralı baştan yazılır.

Bildirim bu listede saklama yeri değildir; durumu değiştiren bir olaydır. Bildirimin getirdiği her değişiklik yukarıdaki yerlerden birine yazılır ve o yerin sınıfını devralır.

Özet

  • Platformun bildirim servisi teslimi garanti etmez; bir bildirim gecikebilir, hiç gelmeyebilir ya da iki kez gelebilir.
  • Rozeti her teslimde yerelde artırmak yinelemeye duyarlıdır: bir teslim rozeti dörde, iki teslim beşe çıkarır.
  • Yükte mutlak rozet değeri taşımak yinelemeyi çözer, sırayı çözmez: ab yedi, ba dört verir; sınıf sıraya duyarlıdır.
  • Aynı belirteci yeniden kaydetmek sağlamdır; kimlikle eleme de rozet artışını sağlam yapar.
  • Gerçek teslim sayısı, sırası ve kimliğin üretimi ölçülmedi; KL21–KL23 olarak kaldı.
  • Bu dersin duyarlılığı: yinelemeye duyarlı.

Kurs Kapanışı

Kursun on dokuz dersi aynı soruyla ilerledi: işlem yinelenirse ya da sırası değişirse sonuç değişir mi? Tablo her dersin ölçtüğü işlemi, dersin Özet bölümünde yazılı duyarlılığı ve sınırlayıcı ölçümü tek satırda verir.

Ders İşlem Duyarlılık Sınırlayıcı ölçüm
Ağ İstemcisi önbelleğe yazma, anahtarlı gönderim, yeniden deneme, rozet artırma, tercih yazma, günlüğe ekleme dördü (1/2/2/1) başlangıç durumu: sıfırdan sağlam, birden yinelemeye duyarlı
JSON Kodlama ve Çözme çözülen kaydı listeye ekleme, kimliğe göre yazma, kodla-çöz sıraya duyarlı ham metin ile çözülmüş değer eşitliği
Hata ve Yeniden Deneme anahtarsız ve anahtarlı sipariş, bütçe harcama yinelemeye duyarlı yanıt kaybı ile ulaşmayan istek ayırt edilemez
Kimlik Doğrulama son yazan kazanır, büyük damga kazanır sıraya duyarlı yenileme belirtecinin ikinci kullanımı reddedilir
Görsel ve Veri Önbelleği aynı anahtar, iki anahtar, yaz-oku sağlam boş ve dolu önbellek
Arka Plan Aktarımı denetlemeden kuyruğa alma, tanımlayıcıya göre kayıt yinelemeye duyarlı bitme ve kuyruğa alma sırasını sistem belirler
Eşzamansız Fonksiyonlar stok ayırma, stok okuma, ayrı raflar sıraya duyarlı kalan stok ile kabul defteri
Görevler ve Görev Grupları grup kümesi, geliş sırası, grup toplamı sağlam (kümede), sıraya duyarlı (dizide) liste ve sayı görünümü
Aktörler koltuk talebi, bilet satışı, bırakma sıraya duyarlı (koltuk), yinelemeye duyarlı (sayaç) duraklama noktası ölçülmedi
Ana İş Parçacığı Yalıtımı sürümsüz ve sürümlü yazım, bayrak, sayaç sıraya duyarlı (sürümsüz), sağlam (sürümlü) numara yanıt gelişinde verilirse çift duyarlı
Kuyruk Tabanlı Eşzamanlılık sona ekleme, değer atama, benzersiz ekleme çift duyarlı (ekleme), sıraya duyarlı (atama) sıralı liste ve satır sayısı
Tepkisel Akışlar abonelik, tekrar düşürme, toplama, son değer yinelemeye duyarlı (paylaşımsız), sıraya duyarlı (farklı değer), sağlam (paylaşımlı) eşit ve farklı değer çifti
Basit Tercih Saklama iki ekran aynı anahtar, ayrı anahtar, açılış sayacı sıraya duyarlı üç varsayılan değer
Anahtarlık ekleme, güncelle yoksa ekle yinelemeye duyarlı durum kodu karşılaştırmaya girmezse sağlam
Dosya Sistemi sona ekleme, atomik yazma, dizin oluşturma çift duyarlı dosya yokken sağlam, varken yinelemeye duyarlı
Yerel Veritabanı varsa güncelle yoksa ekle, otomatik anahtar sağlam anahtar sırasıyla okuma sağlam, ekleme sırasıyla sıraya duyarlı
Nesne Kalıcılık Çerçeveleri nesne oluşturma, benzersiz öznitelik yinelemeye duyarlı kısıt kapalıyken yinelemeye duyarlı
Bulut Eşitleme iki aygıtın yazması, küme birleşimi sıraya duyarlı geliş sırası ya da damga kuralı
Uzak Bildirimler rozeti yerelde artırma, yükte mutlak rozet, belirteci yeniden kaydetme yinelemeye duyarlı kimlikle eleme sağlam; teslim sayısı ve sırası ölçülmedi

Açılış dışındaki on sekiz ders, bu ders dahil, şöyle dağılır: sağlam 3, yinelemeye duyarlı 6, sıraya duyarlı 7, çift duyarlı 2. Karışık sınıflı derslerde Özet’te ilk yazılan sınıf sayıldı.

Açılış dersinin çekirdeği ayrı bir sayımdır: altı işlem dört sınıfa 1, 2, 2 ve 1 olarak dağıldı. İki dağılım aynı şey değildir. Çekirdek altı işlemi sayar; yukarıdaki dağılım açılış dışındaki on sekiz dersin duyarlılığını sayar.

Tablodan üç gözlem çıkar. Aynı işlem başlangıç durumuna, karşılaştırılan duruma ve kurala göre başka sınıfa düşer; hiçbir sınıf bir işlemin değişmez özelliği değildir. Yinelemeyi çözen önlem, etkisizlik ya da kimlikle eleme, sırayı çözmez; sırayı çözen önlem, damga ya da sürüm, yinelemeyi başka bir yerden çözmeli. Ve ölçüm her zaman bir modelin içindedir: platformun gerçek teslimi, zamanlaması ve politikası sınırlayıcı ölçüm sütununda ölçülmedi diye kayıtlıdır.

Sıradaki kurs, M30/K06, mimari, test ve yayınlama konularını ele alır: bir iOS uygulamasının katmanlara nasıl ayrıldığı, nasıl sınandığı ve mağazaya nasıl çıkarıldığı.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ ↵ Esc gezin · aç · kapat