İçeriğe geç
academia.sh

Ders 12 / 12

Yayımlama

Bir sürüm dizesinin kaynakta durup gövdeyle hiçbir denetimden geçmediği, sürüm uyumunun imza düzeyinde modellendiği ve aynı imzanın farklı davranış verebildiği — sözün imzada durduğu, davranışta durmadığı — koşturularak gösterilir.

Yayın Güncelleme

Bu derste

  • Bir sürüm dizesinin kaynakta durduğunu ama gövdeyle hiçbir denetimden geçmediğini bir gönderim modeli koşturarak gösterir
  • Aynı çağıran kaynağı imzası aynı kalan ve imzası değişen kütüphane sürümlerine karşı derleyerek sürüm uyumunun imza düzeyinde nerede bittiğini ölçer
  • Aynı imzayı taşıyan iki sürümün farklı davranış verebildiğini karşılaştırarak sözün imzada durduğunu, davranışta durmadığını açıklar
İçindekiler

Belgelendirme dersi, bir belge örneğinin geçmesinin üstündeki açıklamanın doğru olduğu anlamına gelmediğini gösterdi: belge aracı yalnız örneği sınıyor, üstündeki cümleyi hiç okumuyordu. Bu son ders aynı ayrımı bir paketin dışa açtığı iki başka yüzeye taşıyor — bir sürüm dizesi ve bir imza. İkisi de bir söz gibi görünür: sürüm dizesi “bu paket şu durumda” der, imza “bu işlev şunu alır, şunu döndürür” der. Rust Ekosistemi ve İleri Konular kursu boyunca on bir ders aynı soruyu on bir farklı düzenekte sordu — derleyicinin güvencesi burada nerede bitiyor? — ve yanıt dört sınıftan birine düştü. Bu son ders o dört sınıfı iki söze uyguluyor ve ikisinin de aynı sınıfa düşmediğini gösteriyor.

Sürüm Dizesinin Anlamı

Kursun açılışında koşturulan çekirdek, on iki gözlemden birini şuna ayırmıştı: kaynakta duran bir sürüm dizesi hiçbir şeye karşılık gelmiyordu. Aşağıdaki koşum bu gözlemi bir paket bildirimi ve onu paket kaydına gönderen bir işlevle genişletiyor — kayıt adı hiçbir yerde yazılmıyor, gönderim yalnız modelleniyor.

// paket_bildirimi.rs — surum dizesi kaynakta duruyor, gonderimi modelleyen islev ona hic bakmiyor.
struct PaketBildirimi {
    ad: &'static str,
    surum: &'static str,
}

const SURUM_DIZESI: &str = "0.1.0";

fn iki_kat(x: i32) -> i32 {
    x * 2
}

// Gonderimi modelleyen islev: bildirimi aliyor, bir onay dizesi uretiyor.
// Surum alaninin icerigini hicbir bicimde denetlemiyor - herhangi bir dizgi kabul.
fn gonderimi_modelle(bildirim: &PaketBildirimi) -> String {
    format!("{} paketi govdeyi degistirmeden {} olarak isaretlendi", bildirim.ad, bildirim.surum)
}

fn main() {
    let bildirim = PaketBildirimi { ad: "olcum_kasasi", surum: SURUM_DIZESI };
    println!("{}", gonderimi_modelle(&bildirim));
    println!("iki_kat(21) = {}", iki_kat(21));

    let ikinci_bildirim = PaketBildirimi { ad: "olcum_kasasi", surum: "0.2.0" };
    println!("{}", gonderimi_modelle(&ikinci_bildirim));
    println!("iki_kat(21) = {}", iki_kat(21));
}
olcum_kasasi paketi govdeyi degistirmeden 0.1.0 olarak isaretlendi
iki_kat(21) = 42
olcum_kasasi paketi govdeyi degistirmeden 0.2.0 olarak isaretlendi
iki_kat(21) = 42

PY16. İki bildirim de aynı iki_kat işlevine işaret ediyor, ikisi de aynı çağrıyı veriyor ve ikisi de 42 döndürüyor — ama surum alanı "0.1.0"den "0.2.0"ye değişti. gonderimi_modelle işlevinin imzası, surum alanının hangi dizgiyi taşıdığına hiç bakmıyor: &'static str tipindeki her değeri kabul ediyor. Kaynakta gövde tek bir karakter değişmeden kalırken sürüm alanı elle bir üst basamağa taşınabiliyor ve derleyici bu ikisi arasında hiçbir tutarlılık aramıyor.

Bu, kursun açılış çekirdeğindeki gözlemin birebir tekrarı: bir sürüm dizesi kaynakta duruyor ve hiç kimse onu gövdeyle karşılaştırmıyor. Sınıf denetlenmiyor — ne derleyici, ne bir araç, ne de koşan program sürüm alanının gövdeyle tutarlı olup olmadığını sınıyor. Bir paket kaydına gönderim de aynı sınırı taşır: kayıt, gönderilen bir sürüm dizesini kabul eder, ama o dizenin gövdedeki değişikliği doğru yansıttığını denetlemez — bu denetim tamamen yazan tarafın kararına kalır.

Sürüm Uyumluluğu ve İmza

Ayrım cümlesi: M09/K05 (Üretim Go) kursu modül yayımlamayı ve sürüm uyumunu bilginin kaynağı ekseninde ölçtü — bir sürüm bildiriminin kaynaktan mı, araçtan mı, koşumdan mı geldiği soruluyordu. Bu derste sorulan farklı: bir sürüm bildirimi değil, bir imza söz konusu olduğunda derleyicinin kendi denetiminin nerede durduğu.

Sürüm dizesi hiçbir denetimden geçmiyordu, ama bir işlevin imzası öyle değil. Aşağıdaki koşum aynı çağıran kaynağı üç ayrı kütüphane sürümüne karşı derliyor: birincisi temel sürüm, ikincisi aynı imzayla ama farklı bir gövdeyle yazılmış bir sonraki sürüm, üçüncüsü imzası değişmiş bir sürüm. Redd program içinden ölçülüyor — kaynaklar birer dizgi olarak tutuluyor, derleyici std::process::Command ile çağrılıyor, yalnız derlendi/derlenmedi basılıyor, hata metni hiç okunmuyor.

// surum_uyumu.rs — ayni cagirana karsi uc kutuphane surumu denenir, yalniz derlendi/derlenmedi basilir.
use std::env;
use std::fs;
use std::process::Command;

const CAGIRAN: &str = r#"
fn main() {
    let sonuc = donustur(10);
    println!("sonuc={}", sonuc);
}
"#;

const SURUM_BIR: &str = "fn donustur(x: i32) -> i32 { x + 1 }\n";
const SURUM_IKI_AYNI_IMZA: &str = "fn donustur(x: i32) -> i32 { x * 2 }\n";
const SURUM_IKI_DEGISEN_IMZA: &str = "fn donustur(x: i32, adim: i32) -> i32 { x + adim }\n";

fn derlenir_mi(kaynak: &str, calisma: &std::path::Path, ad: &str) -> bool {
    let yol = calisma.join(format!("{}.rs", ad));
    fs::write(&yol, kaynak).unwrap();
    let ikili = calisma.join(ad);
    Command::new("rustc")
        .args(["--edition", "2021"])
        .arg("-o").arg(&ikili)
        .arg(&yol)
        .output()
        .map(|c| c.status.success())
        .unwrap_or(false)
}

fn siniflandir(basarili: bool) -> &'static str {
    if basarili { "derlendi" } else { "derlenmedi" }
}

fn main() {
    let calisma = env::temp_dir().join(format!("surum-uyumu-{}", std::process::id()));
    fs::create_dir_all(&calisma).unwrap();

    for (ad, govde) in [
        ("surum_bir", SURUM_BIR),
        ("surum_iki_ayni_imza", SURUM_IKI_AYNI_IMZA),
        ("surum_iki_degisen_imza", SURUM_IKI_DEGISEN_IMZA),
    ] {
        let birlesik = format!("{}{}", govde, CAGIRAN);
        let basarili = derlenir_mi(&birlesik, &calisma, ad);
        println!("{}: {}", ad, siniflandir(basarili));
    }

    let _ = fs::remove_dir_all(&calisma);
}
surum_bir: derlendi
surum_iki_ayni_imza: derlendi
surum_iki_degisen_imza: derlenmedi

PY17. Aynı çağıran kaynağı — donustur(10) çağrısı ve sonucu yazdıran satır — üç sürüme karşı hiç değişmeden kaldı. Birinci ve ikinci sürüme karşı derlendi, çünkü ikisi de çağıranın beklediği imzayı taşıyordu; üçüncü sürüme karşı derlenmedi, çünkü üçüncü sürüm ikinci bir parametre eklemişti ve çağıran tek bir bağımsız değişken geçiriyordu. Derleyici burada gerçekten bir sürüm uyumu sınadı — ama sınadığı şey sürüm numarası değil, imza.

Bu, sürüm dizesinin denetlenmiyor sınıfına düşmesiyle doğrudan karşıtlık kuruyor. Sınıf burada sürdürüyor: derleyici, bir kütüphanenin çağırana karşı hâlâ tip uyumlu olup olmadığını her derlemede yeniden sınıyor ve bu sınama sürüm numarasının kendisinden tamamen bağımsız — ikinci sürüm birinci sürümle aynı numarayı taşısaydı da, farklı bir numara taşısaydı da sonuç değişmezdi, çünkü derleyici sürüm alanına hiç bakmıyor, yalnız imzaya bakıyor.

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

Derleyicinin imzaya bakması, çağıranın hangi sürüme karşı derlenmeye devam ettiğini gerçekten sınıyor — ama bu sınama davranışa hiç uzanmıyor. Aşağıdaki koşum, tam olarak aynı imzayı taşıyan iki sürümü yan yana çağırıyor.

// imza_ile_davranis.rs — ayni imza farkli sonuc verebilir; soz imzada, davraniste degil.
fn donustur_v1(x: i32) -> i32 {
    x + 1
}

fn donustur_v2(x: i32) -> i32 {
    x * 2
}

fn cagiran<F: Fn(i32) -> i32>(donustur: F, girdi: i32) -> i32 {
    donustur(girdi)
}

fn main() {
    let girdi = 10;
    println!("v1: {}", cagiran(donustur_v1, girdi));
    println!("v2: {}", cagiran(donustur_v2, girdi));
}
v1: 11
v2: 20

PY18. donustur_v1 ve donustur_v2 birebir aynı imzayı taşıyor; cagiran işlevinin genel sınırı ikisini de aynı biçimde kabul ediyor. Ama aynı girdiyle çağrıldıklarında ikisi bambaşka bir sonuç veriyor: biri 11, öbürü 20. Bir önceki bölümdeki ölçüm bu farkı hiç yakalamazdı — orada sınanan yalnız “çağıran hâlâ derleniyor mu” sorusuydu ve bu soru her iki sürüm için de “evet” yanıtını verirdi.

Bu sınır, kursun ilk dersindeki gözlemin bir yankısı: orada bir makro, iki anlamca uzak türle çağrıldığında ikisini de derliyordu, çünkü sözdizimi düzeyinde tür uygunluğuna bakıyordu, anlama bakmıyordu. Burada aynı imza, iki anlamca uzak gövdeyi taşıyor ve derleyici ikisini de kabul ediyor, çünkü imza düzeyinde tip uygunluğuna bakıyor, davranışa bakmıyor. Söz — sürüm uyumlu olduğunu söylemenin verdiği güvence — imzada duruyor; davranışta durmuyor. Bir paket kaydına yeni bir sürüm gönderildiğinde, derleyicinin bu sürümü kabul etmesi yalnız imzanın tutarlı kaldığını gösterir, gövdenin öncekiyle aynı işi yaptığını göstermez.

Kapanış Tablosu

Ders Ölçülen şey Güvencenin sınıfı Sınırlayıcı ölçüm
Bildirimsel Makrolar Makronun ürettiği gövdenin tip denetiminden geçmesi, makro hijyeni sürdürüyor Makro yalnız tür uygunluğuna bakar; i32 ve bool ile çağrılan aynı makro ikisinde de derlenir
Prosedürel Makrolar Üretimin ayrı bir derleme adımında da denetlenmesi sürdürüyor Prosedürel makro kendi kasasında derlenmek zorunda — tercih değil, dil kısıtı
Alan Özel Diller Makro çıktısının bir arayüzde de yine denetlenmesi sürdürüyor Okunaklı yazım doğruluk getirmez; yanlış bir yol-işlev bağı da tür uyunca derlenir
unsafe Rust Aynı blokta bir işlemin denetimsiz, öbürünün denetimli kalması sürdürüyor · devredildi Devredilen güvence doğru kullanıldığında görünmez; fark yanlış kullanımın sorumluluğunda
Yabancı Fonksiyon Arayüzü İki C işlevinin yalnız imzasına güvenilerek çağrılması devredildi · dilin dışında Bildirim yanlış yazılsaydı derleyici bunu fark edemezdi
WebAssembly Hedefi Hedefe göre değişen kararın kaynakta ayrılması dilin dışında Kaynağın taşınabilir görünmesi taşınabilir olduğu anlamına gelmez
Gömülü Hedefler Standart kütüphanesiz ortamın ayırma ve panik davranışını elden alması dilin dışında Ayırmasız yazım her zaman mümkün değildir; sabit tampon üst sınır ister
Bağımlılık ve Özellik Bayrakları Kapalı bir bayrağın gövdesinin derlemeye hiç girmemesi denetlenmiyor Bugün derlenmediğini gösterir, bayrak açıldığında derlenip derlenmeyeceğini göstermez
Test ve Özellik Tabanlı Sınama Bir özelliğin sabit tohumlu bir üreteçle sınanması devredildi Geçen sınama yalnız sınanan girdi kümesi için doğrudur; aralık dışı hiç sınanmaz
Karşılaştırmalı Ölçüm ve Profilleme İki sıralama yazımının karşılaştırma ve kopyalama sayısı denetlenmiyor İşlem sayısı süre demek değildir; az işlem yapan bir yazımın süresi gerçekte daha uzun olabilir
Belgelendirme Belge örneğinin sınanması, üstündeki açıklamanın sınanmaması sürdürüyor · denetlenmiyor Belge aracı örneği sınar, açıklamayı değil; aynı işlev iki sınıfı birden taşıyabilir
Yayımlama Sürüm dizesinin anlamı ve sürüm uyumunun imza düzeyinde sınanması denetlenmiyor · sürdürüyor Aynı imza farklı davranış verebilir — söz imzada durur, davranışta durmaz

Özet

  • Sürüm dizesi kaynakta duruyor ve gövdeyle hiçbir denetimden geçmiyor; sınıf denetlenmiyor — sürüm bildirimini paket kaydına gönderen model bile sürüm alanının içeriğine bakmıyor.
  • Aynı çağıran kaynağı üç kütüphane sürümüne karşı derlendi: imzası aynı kalan iki sürüme karşı derlendi, imzası değişen sürüme karşı derlenmedi; sınıf sürdürüyor — derleyici sürüm numarasına değil, imzaya bakıyor.
  • Aynı imzayı taşıyan iki sürüm birebir aynı girdiyle çağrıldığında farklı sonuç verdi (11 ile 20); imza düzeyindeki sürüm uyumu denetimi davranışa hiç uzanmıyor — söz imzada duruyor, davranışta durmuyor.
  • Kurs boyunca dört sınıf değişmedi: sürdürüyor, devredildi, dilin dışında, denetlenmiyor; on iki gözlemin dağılımı 4/3/2/3’tü ve bu son ders o dağılımın hem sürdürüyor hem denetlenmiyor uçlarına birer örnek ekledi.
  • Paket kaydına gönderim burada gerçek bir ağ çağrısı taşımadan, yalnız bir bildirim ve onu kabul eden bir işlevle modellendi; kayıt adı hiçbir yerde yazılmadı.

Kurs Kapanışı

Rust Ekosistemi ve İleri Konular kursu on iki ders boyunca tek bir soruyu on iki farklı düzenekte sordu: derleyicinin güvencesi burada nerede bitiyor? Yanıt dört sınıftan birine düştü ve bu dört ad kurs boyunca değişmedi — sürdürüyor, devredildi, dilin dışında, denetlenmiyor; on iki gözlemin dağılımı dört, üç, iki, üçtü. Makrolar konusu üretilen kaynağın sıradan kaynak gibi denetlendiğini, ama bu denetimin yalnız tür düzeyinde çalıştığını gösterdi. Düşük Seviye ve Birlikte Çalışma konusu denetimin nerede yazana ya da bir başka dile devredildiğini ve devredilen güvencenin doğru kullanıldığında görünmez kaldığını gösterdi. Proje Yaşam Döngüsü konusu, kaynağın kimi zaman hiç denetlenmeyen köşeleri olduğunu — kapalı bir bayrağın gövdesi, bir işlem sayısının süreye çevrilmesi, bir belge cümlesinin doğruluğu, bir sürüm dizesinin anlamı — art arda gösterdi. Bu son ders iki köşeyi bir arada yerleştirdi: bir sürüm dizesi hiç denetlenmiyor, ama aynı sürümün imzası hâlâ denetleniyor.

Rust müfredatı beş kursla kapanıyor ve her biri aynı dile bambaşka bir soru sordu. Rust Temelleri, yazılan bir satırın bir değer mi ürettiğini sordu — ifade, deyim, öğe ayrımı. Sahiplik ve Bellek Modeli, o değerin ömrünün nerede bittiğini sordu. Trait’ler, Genellikler ve Hata Yönetimi, bir gövdenin kaç kez koştuğunu sordu. Eşzamanlılık ve Asenkron Rust, bir işin ilerlemek için neye ihtiyaç duyduğunu sordu. Rust Ekosistemi ve İleri Konular, derleyicinin güvencesinin nerede bittiğini sordu. Beş soru aynı dilin beş farklı katmanına baktı: önce yazılan satırın kendisi, sonra kaynaktaki bir değerin ömrü, sonra bir gövdenin kaç kez koştuğu, sonra bir işin ilerlemek için neye muhtaç olduğu, son olarak da bütün bunları sağlayan denetimin kendisinin nerede durduğu.

Sıradaki müfredat C ve C++’a geçiyor; bu iki dil için hangi ölçü ekseninin seçileceği bu derste henüz belli değil.

İ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