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
(
11ile20); 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.