Ders 03 / 14
Paket Yöneticileri
Paketler birbirini gerektirdiğinde aynı bildirim dört strateji altında 4 ayrı küme verir ve bunların yalnız 3'ü tutarlıdır; kısıtlar sıkılaştığında iki geri izlemeli strateji çözüm bulamaz ve tutarlı küme sayısı 0'a iner, kilit dosyası ise dördünü de 1'e indirir.
İçindekiler
Önceki dersin ölçümünde her paket kendi aralığından bağımsız seçildi; seçimler birbirine hiç bakmadı. O varsayım tabloyu okunur kıldı ama gerçeği eksik bıraktı: kurulan paketlerin de kendi bildirimleri vardır ve bunlar birbiriyle çelişebilir.
Bu ders o kısıtları tabloya koyar. Sorusu iki katmanlıdır: aynı bildirim, paket gerekleri de hesaba katıldığında hangi kümeleri veriyor, ve bir strateji çelişkili bir küme seçtiğinde bu nereden görülüyor? Yanıtın ikinci yarısı ilkinden önemli çıkacak.
Paket Yöneticisi Ne Yapar
Paket yöneticisi bir araç sınıfının adıdır ve bu kurs hiçbir ürün adı yazmaz; davranışları burada modellenmiştir. Yaptığı iş dört adıma ayrılır: bildirimi okumak, depodan aday sürümleri toplamak, adaylar arasından bir küme seçmek, seçilen kümeyi siteye kurmak. Bu dersin ilgilendiği adım üçüncüsüdür.
Dördüncü adımın nereye yazdığı ilk derste kuruldu: yalıtılmış bir sitede kurulum yalnız o projenin gördüğünü değiştirir, paylaşılan bir sitede ise komşuların gördüğünü de. Bu ders sitenin yalıtılmış olduğunu varsayar ve o eksene bir daha dönmez; buradaki bütün ayrı sonuçlar tek bir sitenin içinde doğar.
Üçüncü adımın tek başına bir adı vardır: çözümleme (resolution). Girdisi bir aralık listesi ve bir aday havuzudur; çıktısı her paket için tam bir sürümdür. Arada duran şey, paket yöneticisinin çözümleme stratejisidir ve önceki derste gösterildiği gibi bu strateji bildirimde yazmaz.
Sürüm numarasının bölümlerinin ne anlattığı ve anlamlı sürümleme, Sürüm Kontrolüne Giriş kursundaki etiketleme dersinde kuruldu; burada tekrarlanmaz. Buradaki soru sürüm numarasının ne söylediği değil, aralıkların birlikte hangi kümeleri mümkün kıldığıdır.
Gerek Tablosu ve Tutarlılık
Kurguya tek bir ekleme yapılır: bir gerek tablosu. Tablo, her paket sürümünün hangi paketten hangi aralığı istediğini yazar. Depo ve projenin bildirimi ortak tanımdan birebir gelir ve değişmez; eklenen şey paketlerin kendi istekleridir.
Tablonun kurguda kurduğu gerilim tek cümleyle okunur: olcum’un yeni sürümleri ortak’ın
yeni sürümlerini ister, rapor’un yeni sürümü ise ortak’ın eski sürümlerini. İkisini de
en yeni haliyle isteyen bir kurulum, ortak için aynı anda iki ayrı şey istemiş olur.
Buradan ölçümün ikinci kavramı doğar. Bir küme tutarlıdır ancak ve ancak seçilen her sürümün gereği, kümedeki öbür seçimlerce karşılanıyorsa. Tutarlılık kurulumun başarısıyla aynı şey değildir: tutarsız bir küme de siteye kurulabilir, çünkü kurulum bir dosya yazmadır ve gerek tablosunu okumak zorunda değildir.
Dört Strateji
Ölçüm dört strateji karşılaştırır. İlk ikisi bağımsız seçicidir: her paketi kendi aralığının bir ucundan alır ve gerek tablosuna hiç bakmaz — önceki dersin iki stratejisi budur. Kalan ikisi geri izlemelidir: bir sürüm seçer, kısıtları sınar, tutmadığında geri döner ve başka bir sürüm dener.
Geri izlemeli iki stratejinin farkı yalnız arama sırasıdır: hangi paketin sürümüne önce karar verildiği. Aynı bildirim, aynı gerek tablosu, aynı depo — değişen tek şey sıradır. Bu fark ölçümün en önemli satırını üretecek.
Ölçümün varsayımları:
- OB24 — Depo, bildirim ve aralık kuralı ortak tanımdan birebir alınır; ders ikisinin de davranışını değiştirmez. Eklenen tek şey gerek tablosudur.
- OB25 — Gerek tablosu kurgudur ve kâhinin parçasıdır: hangi sürümün neyi istediğini biz yazdık, bu yüzden her kümenin tutarlı olup olmadığı ölçmeden bilinir.
- OB26 — Bir paket sürümü en çok bir gerek taşır ve gerek bir aralıktır. Zincirin derinliği bir düzeydir; daha derin zincirler sayıyı büyütür, kuralı değiştirmez.
- OB27 — Bağımsız stratejiler gerek tablosunu okumaz. Kurdukları küme tutarsız olabilir ve kurulum yine tamamlanır.
- OB28 — Geri izleme, arama sırasındaki her pakete adayları strateji yönünde dener ve kısmi kümeyi her adımda sınar. İlk tutarlı tam kümeyi döndürür.
- OB29 — Kısmi kümenin sınanmasında yalnız iki ucu da seçilmiş gerekler denetlenir; hedefi henüz seçilmemiş bir gerek o adımda ihlal sayılmaz.
- OB30 — İki arama sırası denenir:
olcum, ortak, raporverapor, ortak, olcum. Sıra bir yapılandırma ayrıntısıdır; proje onu bildirimde yazmaz. - OB31 — Sıkı gerek tablosu, aynı depoda
olcum’un bütün uygun sürümlerininortak’ın en yeni sürümünü,rapor’un bütün uygun sürümlerinin ise daha eskisini istemesiyle türetilir. Kesişimi boş olan bir bildirim kümesini modeller. - OB32 — Çözüm bulunamadığında geri izleme
Nonedöndürür ve bu bir hata değil, ölçümün bir sonucudur: tutarlı küme sayısı sıfırdır. - OB33 — Kilit, tutarlı kümelerden birinin — geri izlemeli en yeni stratejisinin sonucunun — kopyasıdır. Kilit varken çözümleme çağrılmaz.
- OB34 — Sürüm numaraları kurgu paketlerin kurgu sürümleridir.
- OB35 — Gerçek kurulum yapılmaz, gerçek paket indirilmez; çözümleme bir sözlük döndürür.
- OB36 — Süre ölçülmez. Sayılan şey ayrı küme, ayrı tutarlı küme ve kilitli kurulumun verdiği ayrı sonuç sayısıdır.
Ölçüm
"""Cozumleme stratejileri: ayni bildirim, ayri kume; cakisma dogdugunda ne oluyor.""" DEPO = { "olcum": [(1, 0), (1, 1), (1, 2), (2, 0)], "rapor": [(0, 9), (1, 0), (1, 1)], "ortak": [(3, 0), (3, 1), (3, 2), (4, 0)], } BILDIRIM = {"olcum": ((1, 0), (2, 0)), "rapor": ((1, 0), (2, 0)), "ortak": ((3, 0), (4, 0))} PAKETLER = ("olcum", "ortak", "rapor") # Paketlerin kendi bagimliliklari: surum -> (hedef paket, alt, ust) GEREK = { ("olcum", (1, 0)): ("ortak", (3, 0), (4, 0)), ("olcum", (1, 1)): ("ortak", (3, 1), (4, 0)), ("olcum", (1, 2)): ("ortak", (3, 2), (4, 0)), ("rapor", (0, 9)): ("ortak", (3, 0), (3, 1)), ("rapor", (1, 0)): ("ortak", (3, 0), (4, 0)), ("rapor", (1, 1)): ("ortak", (3, 0), (3, 2)), } # Ayni depo, daha sikici bir gerek tablosu: olcum'un uc surumu de yeni ortak istiyor. SIKI = dict(GEREK) SIKI[("olcum", (1, 0))] = ("ortak", (3, 2), (4, 0)) SIKI[("olcum", (1, 1))] = ("ortak", (3, 2), (4, 0)) SIKI[("rapor", (1, 0))] = ("ortak", (3, 0), (3, 2)) def uygun(paket): alt, ust = BILDIRIM[paket] return [s for s in DEPO[paket] if alt <= s < ust] def coz(strateji="en yeni"): """Bagimsiz secim: her paket kendi araliginin ucundan alinir.""" secim = {} for paket in sorted(BILDIRIM): adaylar = uygun(paket) secim[paket] = adaylar[-1] if strateji == "en yeni" else adaylar[0] return secim def tutarli(secim, gerek): """Secilen surumlerin gerekleri, secilmis olan paketlerce karsilaniyor mu.""" for paket, surum in secim.items(): k = gerek.get((paket, surum)) if k is None: continue hedef, alt, ust = k if hedef in secim and not alt <= secim[hedef] < ust: return False return True def geri_izle(sira, gerek, strateji="en yeni"): """Cakisma dogdugunda geri donup baska surum dener; sira arama sirasidir.""" def ilerle(i, secim): if i == len(sira): return dict(secim) paket = sira[i] adaylar = uygun(paket) if strateji == "en yeni": adaylar = adaylar[::-1] for surum in adaylar: secim[paket] = surum if tutarli(secim, gerek): sonuc = ilerle(i + 1, secim) if sonuc is not None: return sonuc del secim[paket] return None return ilerle(0, {}) def yazim(secim): if secim is None: return f"{'çözüm yok':>23s}" return " ".join(f"{'.'.join(map(str, secim[p])):>7s}" for p in PAKETLER) def kur(kilit_dosyasi, islev, gerek): """Kilit varsa cozumleme yapilmaz; yoksa karari strateji verir.""" return dict(kilit_dosyasi) if kilit_dosyasi else islev(gerek) STRATEJILER = ( ("bağımsız, en yeni", lambda g: coz("en yeni")), ("bağımsız, en eski", lambda g: coz("en eski")), ("geri izlemeli, en yeni", lambda g: geri_izle(("olcum", "ortak", "rapor"), g)), ("geri izlemeli, rapor önce", lambda g: geri_izle(("rapor", "ortak", "olcum"), g)), ) def tablo(baslik, gerek): print(f"{baslik:<26s} {'olcum':>7s} {'ortak':>7s} {'rapor':>7s} tutarlı") kumeler, saglam = [], [] for ad, islev in STRATEJILER: secim = islev(gerek) durum = secim is not None and tutarli(secim, gerek) if secim is not None: kumeler.append(tuple(sorted(secim.items()))) if durum: saglam.append(tuple(sorted(secim.items()))) print(f"{ad:<26s} {yazim(secim)} {'evet' if durum else 'hayır':>7s}") print(f"dört strateji: {len(set(kumeler))} ayrı küme, " f"{len(set(saglam))} ayrı tutarlı küme") tablo("gerek tablosu", GEREK) print() tablo("sıkı gerek tablosu", SIKI) print() kilit_dosyasi = geri_izle(("olcum", "ortak", "rapor"), GEREK) kilitli = {tuple(sorted(kur(kilit_dosyasi, islev, GEREK).items())) for _, islev in STRATEJILER} print("kilide yazılan küme: " + yazim(kilit_dosyasi)) print(f"kilit dosyası varken dört strateji: {len(kilitli)} ayrı küme")
gerek tablosu olcum ortak rapor tutarlı bağımsız, en yeni 1.2 3.2 1.1 hayır bağımsız, en eski 1.0 3.0 1.0 evet geri izlemeli, en yeni 1.2 3.2 1.0 evet geri izlemeli, rapor önce 1.1 3.1 1.1 evet dört strateji: 4 ayrı küme, 3 ayrı tutarlı küme sıkı gerek tablosu olcum ortak rapor tutarlı bağımsız, en yeni 1.2 3.2 1.1 hayır bağımsız, en eski 1.0 3.0 1.0 hayır geri izlemeli, en yeni çözüm yok hayır geri izlemeli, rapor önce çözüm yok hayır dört strateji: 2 ayrı küme, 0 ayrı tutarlı küme kilide yazılan küme: 1.2 3.2 1.0 kilit dosyası varken dört strateji: 1 ayrı küme
Dört Strateji, Dört Küme
Üst tablonun dört satırı 4 ayrı küme veriyor ve dördü de aynı bildirimden çıkıyor. Bu, önceki dersin iki kümesinin üstüne iki tane daha ekliyor; eklenen ikisi bağımsız seçimin ulaşamayacağı kümeler.
İlk satır kursun bu dersteki asıl bulgusudur. Bağımsız en yeni stratejisi
1.2 / 3.2 / 1.1 kümesini seçiyor ve bu küme tutarsız: rapor 1.1, ortak için
3.2’den eskisini istiyor, ama kümede ortak 3.2 var. Buna karşın kurulum tamamlanıyor. Hiçbir hata iletisi doğmuyor,
çünkü bağımsız strateji gerek tablosunu hiç okumadı. Sonuç, sitede duran ve birbirini
istemeyen üç paket.
İkinci satır bağımsız en eski stratejisinin tesadüfen tutarlı bir küme kurduğunu
gösteriyor. Tesadüf sözcüğü burada tam yerindedir: strateji yine gerek tablosunu okumadı,
yalnızca aralıkların alt uçları çakışmadı. Aynı strateji başka bir tabloyla tutarsız bir
küme kurardı — nitekim alt tabloda kuruyor.
Son iki satır geri izlemeli stratejileri veriyor ve ikisi de tutarlı, ama ayrı:
1.2 / 3.2 / 1.0 ile 1.1 / 3.1 / 1.1. İkisi arasında tek fark arama sırasıdır — hangi
paketin sürümüne önce karar verildiği. Bildirim aynı, depo aynı, kısıtlar aynı; yine de iki
ayrı meşru kurulum. Bu satır, çözümleyicinin kendisinin bir ayrı sonuç ekseni olduğunu
söylüyor: aracı değiştirmek, bildirimi değiştirmeden kurulumu değiştirebilir.
Toplam: dört strateji, 4 ayrı küme, bunların 3’ü tutarlı.
Çakışma Nereye Yazılır
Alt tablo kısıtları sıkılaştırıyor: bu tabloda olcum’un bütün uygun sürümleri ortak’ın
en yenisini, rapor’un bütün uygun sürümleri ise daha eskisini istiyor. İki isteğin
kesişimi boş.
Geri izlemeli iki strateji de çözüm yok döndürüyor. Tutarlı küme sayısı 0. Bu bir başarısızlık gibi görünür ve bir anlamda öyledir — ama ölçümün asıl bulgusu üstteki iki satırdadır: bağımsız stratejiler yine bir küme döndürüyor. Aynı çelişki, okuyan araca göre ya bir ret ya sessiz bir kurulum üretiyor.
İkisi arasındaki fark, hatanın nerede görüneceğidir. Ret, çözümleme anında görünür ve elde bir bilgi bırakır: bu bildirim kümesi çelişkilidir, ya bir aralık gevşetilecek ya bir paket değiştirilecektir. Sessiz kurulum ise hiçbir şey bırakmaz; çelişki siteye kurulur ve ancak çalışma zamanında, çelişen iki paketin karşılaştığı satırda ortaya çıkar. Ve o satıra her koşumda uğranmaz.
Ölçünün diliyle: ret 0 ayrı sonuç üretir ve sıfır, sayılabilir bir yanıttır. Sessiz kurulum 1 ayrı sonuç üretir ama o sonucun geçerli olup olmadığını ölçmez. Bir çözümleyicinin çözemediğini söylemesi, çözemediğini söylememesinden bilgi açısından üstündür.
Çözümleyicinin Kendisi Yeniden Üretilebilir mi
Ölçüm dört stratejiyi karşılaştırdı, ama her stratejinin kendi içinde kaç sonuç verdiğini de sormak gerekir. Modeldeki dört stratejinin dördü de belirlenimcidir: aday listesi depodan sıralı gelir, arama sırası sabittir, hiçbir yerde rastgelelik yoktur. Aynı strateji aynı girdiyle çağrıldığında 1 ayrı sonuç verir.
Bu, bir çözümleyiciden istenecek en temel özelliktir ve kendiliğinden gelmez. Aday havuzu birden çok kaynaktan toplanıyorsa hangi kaynağın önce yanıtladığı sıraya karışabilir; bir önbellek ısındığında aynı sorgu ayrı bir liste döndürebilir; paralel indirme kurulum sırasını değiştirebilir. Bunların hiçbiri stratejinin kuralını değiştirmez, ama hepsi girdisini değiştirir — ve girdisi değişen bir kural ayrı bir küme verir.
Bu yüzden bir çözümleyicinin sözü iki katmanlıdır. Birinci katman kuraldır: hangi aday seçilir. İkinci katman kuralın girdisidir: adayların hangi düzende, hangi kaynaktan ve hangi anda toplandığı. Yeniden üretilebilir bir kurulum ikisini birden sabitlemeyi gerektirir, ve ikinci katmanı yazıya geçiren belge kilit dosyasıdır.
Kilidin Bu Tablodaki Yeri
Son iki satır önceki dersin sonucunu bu tablonun üstüne koyuyor. Tutarlı kümelerden biri —
geri izlemeli en yeni stratejisinin bulduğu 1.2 / 3.2 / 1.0 — kilide yazıldığında dört
strateji de aynı kümeyi kuruyor: 1 ayrı sonuç.
Kilidin burada kapattığı eksen yenidir. Önceki derste kapatılanlar strateji yönü ve deponun zamanıydı; burada kapatılan çözümleyicinin kendisi. Kilit yazıldıktan sonra hangi paket yöneticisinin kullanıldığı sonucu değiştirmiyor, çünkü çözümlenecek bir şey kalmadı.
Bu, kilidin ne kadar iş yaptığını da sınırlıyor. Kilit, kilidi üreten çözümleyicinin kararını taşır; iyi bir kararı da kötü bir kararı da aynı sadakatle. Üstteki tabloda üç tutarlı kümeden hangisinin kilide yazıldığı, kilide bakılarak anlaşılmaz — kilit yalnız seçileni yazar, seçme gerekçesini değil.
Özet
- Paket yöneticisi bir araç sınıfıdır; işi bildirimi okumak, aday toplamak, bir küme seçmek ve kurmaktır. Ayrı sonucu üreten adım seçme adımıdır.
- Paketlerin kendi gerekleri hesaba katıldığında aynı bildirim dört strateji altında 4 ayrı küme verir ve bunların 3’ü tutarlıdır.
- Bağımsız seçim gerek tablosunu okumaz:
1.2 / 3.2 / 1.1kümesi tutarsız olduğu halde kurulur ve hiçbir uyarı üretmez. - İki geri izlemeli strateji ayrı arama sırası yüzünden iki ayrı tutarlı küme verir; çözümleyicinin kendisi bir ayrı sonuç eksenidir.
- Kesişimi boş kısıtlarda geri izleme 0 tutarlı küme döndürür; ret çözümleme anında bilgi bırakır, sessiz kurulum ise çelişkiyi çalışma zamanına erteler.
- Kilit dosyası dört stratejiyi 1 ayrı sonuca indirir, ama yazdığı kararın hangi gerekçeyle seçildiğini taşımaz.
Sonraki Adım
Bu dersin bütün kümeleri tek bir yorumlayıcı varsayıldığı için karşılaştırılabildi. O varsayım da tıpkı önceki iki varsayım gibi yazılı değildi. Sonraki ders onu ölçüme sokar: aynı proje, aynı bildirim, ayrı yorumlayıcı sürümleri. Sorulacak olan şudur — çözümleme yorumlayıcıya göre kaç ayrı küme veriyor, ve bir yorumlayıcıda üretilmiş kilit dosyası bir başkasında ne yapıyor?
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.