İçeriğe geç
academia.sh

Ders 01 / 12

Platform Katmanları

Sekiz tanım buluşmasının dört çözüme ayrıldığının ölçümü; platform katmanlarının çekirdek işletim sisteminden arayüz katmanına sıralanışı.

Yayın Güncelleme

Bu derste

  • İki tanımın buluşmasını öncelik, kesişim, birleşim ve ret olarak sınıflandırır
  • Sekiz buluşmayı ölçer ve çözümlerin 2/2/2/2 dağıldığını okur
  • Platform katmanlarını çekirdek işletim sisteminden arayüz katmanına sıralar
  • İç içe iki tanımın neden hiçbir çözüme girmediğini ölçer
İçindekiler

Önceki kursta Swift dilini bir an ölçüsüyle okuduk: bir ifade hemen mi, ertelenerek mi, hiç mi değerlendiriliyor. Bu kurs dilden platforma geçer. Platformda aynı şey çoğu zaman iki yerde tanımlanır: bir derleme ayarı hem projede hem hedefte durur, bir uygulamanın ekran yönleri hem uygulamada hem aygıtta, bir paketin sürüm aralığı hem kendisinde hem onu isteyen paketlerde. Bu iki tanım buluştuğunda sistemin ne yaptığı kursun ölçü sorusudur: bu iki tanım buluşunca nasıl çözülüyor? Üst ad çözüm.

Dört şekil beklenir ve ilk bakışta hepsi aynı görünür. Bazen iki tanımdan biri kazanır (öncelik), bazen yalnız ikisinde de olanlar kalır (kesişim), bazen ikisinden birinde olan her şey toplanır (birleşim), bazen de sonuç çıkmaz (ret). Bu derste sekiz küçük buluşma kurar ve hangisinin hangi çözüme düştüğünü sayarız. Platformun katmanlarını da bu sayımın ardından, çözümlerin nerede yaşadığını göstermek için sıralarız.

Çekirdek

Her ders aynı yardımcıyı kullanır: iki tanımı, bu tanımların buluşmasından çıkan sonucu ve sonucun hangi çözüme düştüğünü tutan bir tip. Meeting sonucu değiştirmez, yalnızca sınıflandırır. Sonuç her zaman modelden gelir; yani sözlük birleştirme, süzme, ad arama ve aralık denetimi gibi gerçek işlemlerin çıktısıdır, elle yazılmış bir küme değildir. Sınıflandırma sırası şöyledir: iki küme de boş değilse ve biri ötekinin alt kümesi değilse ölçüm geçerlidir, aksi hâlde olcum-disi yazılır; sonuç yoksa ya da boşsa ret; sonuç birleşime eşitse birlesim; kesişime eşitse kesisim; kümelerden birine eşitse oncelik; hiçbirine uymuyorsa kural-disi. Küme değerleri sıralanarak basılır, çünkü Set’in yineleme sırası koşumdan koşuma değişebilir.

// Meeting.swift — iki tanim bulusunca nasil cozuldugunu siniflandirir
struct Meeting {
    let label: String
    let first: Set<String>
    let second: Set<String>
    let result: Set<String>?

    init(_ label: String, first: Set<String>, second: Set<String>, result: Set<String>?) {
        self.label = label
        self.first = first
        self.second = second
        self.result = result
    }

    var resolution: String {
        if first.isEmpty || second.isEmpty
            || first.isSubset(of: second) || second.isSubset(of: first) {
            return "olcum-disi"
        }
        guard let result, !result.isEmpty else { return "ret" }
        if result == first.union(second) { return "birlesim" }
        if result == first.intersection(second) { return "kesisim" }
        if result == first || result == second { return "oncelik" }
        return "kural-disi"
    }

    static func list(_ values: Set<String>) -> String {
        values.isEmpty ? "bos" : values.sorted().joined(separator: ",")
    }

    func report() {
        let outcome = result.map(Meeting.list) ?? "yok"
        print("\(label): ilk \(Meeting.list(first)) | ikinci \(Meeting.list(second)) | sonuc \(outcome) -> \(resolution)")
    }
}

func summarize(_ meetings: [Meeting]) {
    for resolution in ["oncelik", "kesisim", "birlesim", "ret"] {
        let count = meetings.filter { $0.resolution == resolution }.count
        print("\(resolution): \(count)")
    }
}

Sekiz Buluşma

Aşağıdaki ölçüm sekiz buluşmayı kurar. Her birinin iki tarafı ve sonucu aynı biçimde üretilir: derleme ayarında hedef düzeyi proje düzeyinin üstüne yazılır, ad aramasında yerel tanım önce aranır ve iki içe alınan modülde aynı ad belirsiz kalır, ekran yönünde uygulamanın desteklediği ile aygıtın sunduğu süzülür, sürüm aralığında iki paketin istediği aralık kesişir, miras alınan yollarda hedef $(inherited) ile proje değerini açar, özellik listesinde şablon dosyası ile ayarlardan üretilen anahtarlar birleşir.

// main.swift — sekiz bulusma, dort cozum
func parts(_ version: String) -> [Int] {
    version.split(separator: ".").map { Int($0)! }
}

func versions(in published: [String], from lower: String, below upper: String) -> Set<String> {
    Set(published.filter {
        !parts($0).lexicographicallyPrecedes(parts(lower))
            && parts($0).lexicographicallyPrecedes(parts(upper))
    })
}

func lookup(_ name: String, local: [String: String], imported: [[String: String]]) -> Set<String>? {
    if let found = local[name] { return [found] }
    let matches = imported.compactMap { $0[name] }
    return matches.count == 1 ? Set(matches) : nil
}

func expand(_ values: [String], inherited: [String]) -> [String] {
    values.flatMap { $0 == "$(inherited)" ? inherited : [$0] }
}

// Derleme ayari: hedef duzeyi proje duzeyinin ustune yazar
let projectLevel = ["SWIFT_VERSION": "5", "TARGETED_DEVICE_FAMILY": "1"]
let targetLevel = ["SWIFT_VERSION": "6"]
let effective = projectLevel.merging(targetLevel) { _, fromTarget in fromTarget }

// Ad arama: yerel tanim once aranir; iki modulde ayni ad belirsizdir
let kitNames = ["format": "Kit.format", "Logger": "Kit.Logger"]
let toolsNames = ["Logger": "Tools.Logger"]
let localNames = ["format": "yerel.format"]

// Ekran yonu: uygulamanin destekledigi ile aygitin sundugu
let appOrientations: Set = ["dikey", "ters-dikey"]
let deviceOrientations: Set = ["dikey", "yatay-sol", "yatay-sag"]

// Surum araliklari: iki paketin ayni bagimlilik icin istedigi
let published = ["1.2.0", "1.3.0", "1.4.0", "2.0.0", "2.1.0"]
let wideFirst = versions(in: published, from: "1.2.0", below: "2.0.0")
let wideSecond = versions(in: published, from: "1.3.0", below: "3.0.0")
let narrowFirst = versions(in: published, from: "1.2.0", below: "1.4.0")
let narrowSecond = versions(in: published, from: "2.0.0", below: "3.0.0")

// Miras alinan yollar: hedef `$(inherited)` ile proje degerini acar
let projectPaths = ["Ortak/Basliklar"]
let targetPaths = ["$(inherited)", "Hedef/Basliklar"]

// Info.plist: sablon dosyasi ile ayarlardan uretilen anahtarlar
let templateKeys = ["CFBundleName": "Ornek", "UILaunchScreen": "-"]
let generatedKeys = ["CFBundleName": "Ornek", "NSCameraUsageDescription": "Kamera"]

let meetings = [
    Meeting("derleme-ayari",
            first: [projectLevel["SWIFT_VERSION"]!],
            second: [targetLevel["SWIFT_VERSION"]!],
            result: [effective["SWIFT_VERSION"]!]),
    Meeting("yerel-golgeleme",
            first: [kitNames["format"]!],
            second: [localNames["format"]!],
            result: lookup("format", local: localNames, imported: [kitNames, toolsNames])),
    Meeting("ekran-yonu",
            first: appOrientations,
            second: deviceOrientations,
            result: appOrientations.filter { deviceOrientations.contains($0) }),
    Meeting("surum-araligi",
            first: wideFirst,
            second: wideSecond,
            result: wideFirst.intersection(wideSecond)),
    Meeting("miras-yollar",
            first: Set(projectPaths),
            second: Set(targetPaths.filter { $0 != "$(inherited)" }),
            result: Set(expand(targetPaths, inherited: projectPaths))),
    Meeting("plist-anahtarlari",
            first: Set(templateKeys.keys),
            second: Set(generatedKeys.keys),
            result: Set(templateKeys.merging(generatedKeys) { current, _ in current }.keys)),
    Meeting("cift-ad",
            first: [kitNames["Logger"]!],
            second: [toolsNames["Logger"]!],
            result: lookup("Logger", local: localNames, imported: [kitNames, toolsNames])),
    Meeting("ayrik-aralik",
            first: narrowFirst,
            second: narrowSecond,
            result: narrowFirst.intersection(narrowSecond)),
]

for meeting in meetings {
    meeting.report()
}
summarize(meetings)
derleme-ayari: ilk 5 | ikinci 6 | sonuc 6 -> oncelik
yerel-golgeleme: ilk Kit.format | ikinci yerel.format | sonuc yerel.format -> oncelik
ekran-yonu: ilk dikey,ters-dikey | ikinci dikey,yatay-sag,yatay-sol | sonuc dikey -> kesisim
surum-araligi: ilk 1.2.0,1.3.0,1.4.0 | ikinci 1.3.0,1.4.0,2.0.0,2.1.0 | sonuc 1.3.0,1.4.0 -> kesisim
miras-yollar: ilk Ortak/Basliklar | ikinci Hedef/Basliklar | sonuc Hedef/Basliklar,Ortak/Basliklar -> birlesim
plist-anahtarlari: ilk CFBundleName,UILaunchScreen | ikinci CFBundleName,NSCameraUsageDescription | sonuc CFBundleName,NSCameraUsageDescription,UILaunchScreen -> birlesim
cift-ad: ilk Kit.Logger | ikinci Tools.Logger | sonuc yok -> ret
ayrik-aralik: ilk 1.2.0,1.3.0 | ikinci 2.0.0,2.1.0 | sonuc bos -> ret
oncelik: 2
kesisim: 2
birlesim: 2
ret: 2

Çıktının son dört satırı 2/2/2/2 sayımını verir: iki öncelik, iki kesişim, iki birleşim, iki ret. derleme-ayari ve yerel-golgeleme öncelik: ikinci tarafın değeri sonuca olduğu gibi geçti. ekran-yonu ve surum-araligi kesişim: sonuçta yalnız iki tarafın da içerdiği değerler kaldı. miras-yollar ve plist-anahtarlari birleşim: sonuç iki kümenin tümünü taşıyor. cift-ad ve ayrik-aralik ret: birinde sonuç hiç oluşmadı (yok), ötekinde boş küme oluştu (bos), ve kural ikisini aynı çözüme koyar.

Dağılımın eşit çıkması kuralın değil kurulan buluşmaların bir sonucudur: sekiz örneği biz seçtik ve dört çözümün her birine ikişer tanesi düştü. Bu yüzden dağılımdan bir sonuç çıkarmayız; ölçüm yalnız dört çözümün de gerçekten var olduğunu ve her birinin farklı bir işlemden geldiğini gösterir.

PY1. Bu ölçüm yukarıdaki sekiz buluşma ve yazılan modelin kuralları için. Gerçek bir geliştirme ortamının derleme ayarı çözümlemesinin ya da gerçek bir paket yöneticisinin sürüm çözümlemesinin bu kuralları aynen uyguladığı ölçülmedi; model, platformun bu kuralını kurar ve sınıflandırır.

Katmanlar ve Çözümler

Platform aşağıdan yukarıya dört katman olarak okunur ve her katman altındaki katmanların üzerine kurulur. En altta çekirdek işletim sistemi katmanı bulunur: bellek, süreç, ağ ve aygıt sürücüleri buradadır. Onun üstünde çekirdek hizmetler katmanı gelir: koleksiyonlar, tarih ve dosya işleri, ağ istemcileri ve günlük kaydı gibi görünür olmayan, her uygulamanın gereksindiği hizmetler. Üçüncü katman medya katmanıdır: grafik, ses ve görüntü. En üstte arayüz katmanı vardır: görünümler, olay işleme ve uygulamanın ekranda yaşayan her şeyi. Bir uygulama arayüz katmanından konuşur, ama altındaki üç katmanın tümünden de hizmet alır.

Çözümler bu katmanlara eşit dağılmaz; aynı tanım çifti farklı katmanlarda farklı biçimlerde ortaya çıkar. Ad aramasının öncelik ve ret çözümleri dilin ve modüllerin işidir; ekran yönü arayüz katmanına ve aygıta, dolayısıyla alttaki donanıma bakar; derleme ayarı, miras alınan yollar ve özellik listesi ise uygulamanın nasıl kurulduğuna ait olduğundan hiçbir çalışma zamanı katmanında yaşamaz, geliştirme ortamının proje ve hedef tanımlarında yaşar. Sürüm aralığı ise paketin bildirimine aittir ve derleme sırasında çözülür.

Bu sıralamanın pratik bir sonucu vardır: bir tanımın hangi katmanda durduğunu bilmek, o tanımın çözümünü kimin yaptığını, yani derleyicinin mi, paket yöneticisinin mi, sistemin mi karar verdiğini söyler. Sonraki derslerde her buluşmayı bu soruyla karşılayacağız.

PY2. Katman sayısı ve adları burada öğretim amacıyla dörde indirilmiş bir sıralamadır; bir çerçevenin tam olarak hangi katmana ait olduğu, çerçevenin bu derste ölçülmeyen iç yapısına bağlıdır ve ölçülmedi.

Çözümü Kim Yapıyor

Sekiz buluşmayı çözümü yapan tarafa göre gruplamak, katman sorusunu somutlaştırır. Ad aramasını derleyici yapar: kaynak dosya derlenirken hangi tanımın görüneceğine o karar verir ve karar çalışma zamanına hiç taşınmaz. Derleme ayarını, miras alınan yolları ve özellik listesini derleme sistemi çözer; bu üçü uygulamanın içinde değil, uygulamayı üreten sürecin içinde bulunur. Sürüm aralığını paket yöneticisi çözer ve sonucu bir kilit dosyasına yazar. Ekran yönünü ise çalışma zamanında sistem çözer: uygulama ne desteklediğini bildirir, aygıt ne sunduğunu bilir ve sonuç ancak ikisi karşılaşınca ortaya çıkar.

Bu ayrım iki şeyi önceden söyler. Birincisi, çözümü yapan taraf değişince hata da başka yerde görünür: derleyicinin verdiği ret bir derleme hatasıdır, sistemin verdiği ret ise uygulama çalışırken fark edilir. İkincisi, aynı tanım çifti iki farklı yerde farklı çözülebilir; bir ayarın projede ve hedefte nasıl buluştuğunu bilmek, bir bağımlılığın iki paketten nasıl istendiğini söylemez.

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

Dört çözümün hepsi, iki tanımdan biri ötekini içerdiğinde ayrışmaz: iç içe iki küme birleşimde dıştakine, kesişimde içtekine eşittir, öncelikte ikisinden birine eşittir; ret için ise çatışan bir eleman yoktur, çünkü içteki kümenin her elemanı dıştakinde de bulunur. Sonuçlar farklı olsa da bu durumda sınıflandırma bir şey söylemez. Aşağıdaki ölçüm aynı iç içe çiftle dört sonucu da kurar ve Meeting’in dördünü de ölçüm dışı bıraktığını gösterir.

// main.swift — ic ice iki tanim: dort sonuc da ayni sinifa duser
let outer: Set = ["Ortak/Basliklar", "Hedef/Basliklar"]
let inner: Set = ["Ortak/Basliklar"]

let nested = [
    Meeting("ic-ice-oncelik", first: inner, second: outer, result: inner),
    Meeting("ic-ice-kesisim", first: inner, second: outer, result: inner.intersection(outer)),
    Meeting("ic-ice-birlesim", first: inner, second: outer, result: inner.union(outer)),
    Meeting("ic-ice-ret", first: inner, second: outer, result: nil),
]

for meeting in nested {
    meeting.report()
}
summarize(nested)
ic-ice-oncelik: ilk Ortak/Basliklar | ikinci Hedef/Basliklar,Ortak/Basliklar | sonuc Ortak/Basliklar -> olcum-disi
ic-ice-kesisim: ilk Ortak/Basliklar | ikinci Hedef/Basliklar,Ortak/Basliklar | sonuc Ortak/Basliklar -> olcum-disi
ic-ice-birlesim: ilk Ortak/Basliklar | ikinci Hedef/Basliklar,Ortak/Basliklar | sonuc Hedef/Basliklar,Ortak/Basliklar -> olcum-disi
ic-ice-ret: ilk Ortak/Basliklar | ikinci Hedef/Basliklar,Ortak/Basliklar | sonuc yok -> olcum-disi
oncelik: 0
kesisim: 0
birlesim: 0
ret: 0

Dört satır da olcum-disi, dört sayaç da sıfır. İç içe bir çift hangi işlemle birleştirilirse birleştirilsin dört çözümden hiçbirine yazılamaz; yani çözümü ayıran şey işlem değil, iki tanımın gerçekten farklı şeyler söylemesidir. Bu, kursun kalanında bir uyarıya dönüşür: bir tanım ötekini zaten içeriyorsa buluşma kurulmaz, çünkü sonuç değişse bile sınıflandırma hangi kural seçilirse seçilsin aynı kalır.

PY3. Bu ölçüm yalnız inner kümesinin outer kümesinin alt kümesi olduğu çift için. Birbirine eşit iki kümenin ve kümelerden birinin boş olduğu durumun da olcum-disi verdiği Meeting’in koşullarından okunur ama ayrıca ölçülmedi.

Özet

  • Bu iki tanım buluşunca sonuç dört çözümden birine düşer: öncelik, kesişim, birleşim ya da ret.
  • Sekiz buluşmada çıktı 2 öncelik, 2 kesişim, 2 birleşim, 2 ret verdi; dağılım kurulan örneklerin sonucudur, kuralın değil.
  • Sonucun hiç oluşmaması (yok) ile boş kümeye düşmesi (bos) aynı çözümdür: ret.
  • Platform dört katmandan kurulur (çekirdek işletim sistemi, çekirdek hizmetler, medya, arayüz); bir tanımın katmanı, çözümü kimin yaptığını söyler.
  • İç içe iki tanım hiçbir çözüme girmez: dört sonucun dördü de olcum-disi çıktı.
  • Bu dersin çözümü: çekirdeğin dördü (2/2/2/2).

Sonraki Adım

Sekiz buluşmanın ikisi ad aramasındı: yerel tanım içe alınanı gölgeledi, iki modülde aynı ad ise ret verdi. Bir sonraki derste çerçeveleri ve kütüphaneleri bu gözle okuruz: iki modül aynı adı açınca ne olur, ve birini niteleyince buluşma neden kalkar.

İ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