İçeriğe geç
academia.sh

Ders 11 / 12

Belgelendirme

Bir belge cümlesinin işlevin gerçek davranışıyla çeliştiği ama hiçbir araç tarafından denetlenmediği ve aynı işlevin belge içindeki çalışan örneğinin, belge aracı program içinden çağrılarak gerçekten sınandığı gösterilerek, aynı kaynakta iki güvence sınıfının nasıl yan yana durabildiğinin ölçülmesi.

Yayın Güncelleme

Bu derste

  • Bir belge cümlesinin işlevin gerçek davranışıyla çeliştiğini gösterir ve bu iddianın hiçbir araç tarafından denetlenmediğini kanıtlar
  • Belge içindeki çalışan örnekleri belge aracını program içinden çağırarak sınar ve geçen sınama sayısını basar
  • Aynı işlevin hem denetlenmeyen bir açıklama hem de denetlenen bir örnek taşıyabildiğini, iki güvence sınıfını adlandırarak açıklar
İçindekiler

Önceki üç ders, kaynakta duran ama derleyicinin hiç bakmadığı üç ayrı yeri ölçtü: kapalı bir bayrağın gövdesi, koşarak sınanan bir özellik, iki yazımın işlem sayısı. Üçünde de ölçülen şey kaynağın kod olan bir parçasıydı — bir işlev, bir blok, bir döngü. Bu konunun (Proje Yaşam Döngüsü) dördüncü ve son dersi, aynı soruyu kaynağın en sık göz ardı edilen bölümüne soruyor: bir işlevin yanına yazılan açıklama. Bir belge cümlesi de kaynağın bir parçası, ama derleyicinin denetlediği bir sözdizimi değil, insanın okuduğu bir düzyazı; bu ders, bu düzyazının doğruluğunu kimin (ya da hiç kimsenin) denetlediğini soruyor — ve aynı kaynakta iki farklı yanıtın yan yana durabildiğini gösteriyor.

Bu sorunun cevabı tek bir cümleyle verilemiyor, çünkü bir belge yorumunun iki farklı bölümü var: yukarıda okunan düzyazı ve genellikle onun altına yerleştirilen, işlevin nasıl çağrılacağını gösteren küçük bir kod örneği. Bu iki bölüm aynı yorumun içinde birlikte duruyor, ama kaderleri aynı değil — bu dersin ölçtüğü tam olarak bu ayrım. Bu konunun diğer üç dersi kendi ölçümlerini kurdu; bu ders, kursun on iki gözlemlik güvence çekirdeğine geri dönüp onun “belge metninin dogrulugu” satırını aynen kullanıyor.

Belgenin Kendisi ve Kaynaktaki Çelişki

Rust’ta bir işlevin üstüne üç yatık çizgiyle (///) başlayan satırlar yazmak, o işlevin belge yorumunu oluşturur. Bu yorum sıradan bir açıklamadan farklı: içine # Ornekler gibi alt başlıklar ve ters tırnaklarla çevrelenmiş kod parçaları konabilir. Aşağıdaki üç işlevin üçünde de bu düzen var — bir açıklama cümlesi ve altında bir örnek. İlk işlev, güvence çekirdeğinin (guvence.rs) “belge metninin dogrulugu” kesitidir: belge satırı işlevin en büyük değeri döndürdüğünü söylüyor, işlev gerçekte en küçüğü döndürüyor. Diğer iki işlev — küçük olanı döndüren ve bir dilimi toplayan — belgeleri doğru yazılmış, karşılaştırma için buraya eklendi.

// belge_govdesi.rs — guvence.rs'in "belge metninin dogrulugu" kesiti + iki sinanan ornek daha
/// Bu belge satiri islevin **en buyuk** degeri dondurdugunu soyluyor.
/// Islev en kucugu donduruyor. Hicbir arac bu celiskiyi denetlemiyor.
///
/// # Ornekler
///
/// ```
/// assert_eq!(belge_govdesi::belgesi_yanlis(3, 9), 3);
/// ```
pub fn belgesi_yanlis(a: i32, b: i32) -> i32 {
    if a < b {
        a
    } else {
        b
    }
}

/// Iki degerden kucuk olanini dondurur.
///
/// # Ornekler
///
/// ```
/// assert_eq!(belge_govdesi::kucuk_olan(3, 9), 3);
/// ```
pub fn kucuk_olan(a: i32, b: i32) -> i32 {
    if a < b {
        a
    } else {
        b
    }
}

/// Bir dilimin toplamini dondurur.
///
/// # Ornekler
///
/// ```
/// assert_eq!(belge_govdesi::topla(&[1, 2, 3]), 6);
/// ```
pub fn topla(dilim: &[i32]) -> i32 {
    dilim.iter().sum()
}

PY13. Bu dosya hiç fn main taşımıyor; bir kaynak kesiti olarak duruyor. Üç işlevin üçü de doğru derleniyor — belgesi_yanlisin prose’u yanlış olsa da gövdesi tipçe tutarlı ve derleyici prose’u hiç okumuyor. Aşağıdaki gövde bu üç işlevi çağırıyor.

// belge_govdesi_main.rs — belge celiskisi kaynakta duruyor, program yine de derleniyor
mod belge_govdesi;
use belge_govdesi::{belgesi_yanlis, kucuk_olan, topla};

fn main() {
    println!("belge 'en buyuk' diyor, gercek sonuc: {}", belgesi_yanlis(3, 9));
    println!("kucuk_olan(3, 9) = {}", kucuk_olan(3, 9));
    println!("topla(&[1, 2, 3]) = {}", topla(&[1, 2, 3]));
}
belge 'en buyuk' diyor, gercek sonuc: 3
kucuk_olan(3, 9) = 3
topla(&[1, 2, 3]) = 6

Derleme hiçbir uyarı basmadı. belgesi_yanlis(3, 9) çağrısı 3ü döndürdü — küçük olanı, belge cümlesinin söylediği gibi büyük olanı değil. Bu, sıradan bir derleme sürecinde beklenen davranış: rustc, üç yatık çizgiyle (///) başlayan bir belge yorumunu Markdown olarak ayrıştırmaz, içindeki cümleleri okumaz, içine gömülü kod örneğini derlemez. Belge yorumunun tamamı — hem yanlış prose hem de doğru çalışan örnek — sıradan bir derlemede görünmez metindir; derleyici onu ne doğrular ne de reddeder, çünkü ona hiç bakmaz.

Bu, güvence çekirdeğinin ölçtüğü sınıfın birebir kendisi: denetlenmiyor. Derleyici işlevin gövdesini denetledi (tipini kontrol etti, adları çözdü) ama işlevin belgesini hiç görmedi. Bir belge cümlesi kaynağın parçası olsa da, derleyicinin ilgi alanının tamamen dışında duruyor — tıpkı Bağımlılık ve Özellik Bayrakları dersindeki kapalı bayrağın gövdesi gibi, ama farklı bir nedenle: orada gövde derlemeye hiç girmiyordu, burada girmiyor değil, derleyici onu başka bir kategoriden görüyor — kod değil, düzyazı.

Bu iki durumu birbirinden ayırmak önemli. Kapalı bir bayrağın gövdesi, bayrak açıldığında derlemeye girebilecek bir kod parçasıdır — potansiyel olarak denetlenebilir, yalnız bugün denetlenmiyor. Bir belge cümlesinin prose kısmı ise hiçbir koşulda derlemeye girmez; o hiçbir zaman kod olmadı, olmayacak da. Derleyici bir /// belge yorumunu kaynağın diğer bölümlerinden ayırıp işlevin üstüne iliştirilmiş bir bilgi olarak saklar — bu yüzden tamamen yok sayılmıyor, bir belge aracının okuyabileceği bir yerde duruyor. Ama sıradan derlemenin tip denetimi ve ad çözümlemesi aşamaları bu bilginin içeriğine hiç bakmaz: içindeki cümleyi doğrulamaz, içindeki kod örneğini derlemez. Denetlenen ile saklanan farklı şeyler.

Bu, Bağımlılık ve Özellik Bayrakları dersinde ölçülen çürümeyle aynı kökten geliyor. Orada kapalı bir bayrağın gövdesi, kaynağın geri kalanı değiştikçe uyum yitirebiliyordu, çünkü hiç kimse onu denetlemiyordu. Burada aynı şey bir işlevin gövdesiyle belgesi arasında oluyor: gövde zamanla değişebilir — bir hata düzeltilir, bir davranış tersine çevrilir — ama üstündeki belge cümlesi kendiliğinden güncellenmez. belgesi_yanlis muhtemelen bir zamanlar doğru yazılmıştı (belki işlev gerçekten en büyüğü döndürüyordu) ve gövde değiştiğinde belge cümlesi unutuldu; bunu kanıtlamanın bir yolu yok, ama iki tarafın da bağımsız yaşayabildiği gerçeği, böyle bir sürüklenmenin neden mümkün olduğunu açıklıyor. İkisinde de ortak olan, hiçbir denetim mekanizmasının iki tarafı birbirine bağlı tutmaması.

Belge İçindeki Örnek: Program İçinden Sınama

Yukarıdaki her işlevin belgesinde bir # Ornekler bölümü ve içinde üç ters tırnaklı bir kod örneği var. Bu örnekler sıradan derlemede görünmez olsa da, dilin kendi belge aracı bunları özel olarak ele alır: kaynağı tarayıp her örneği ayrı bir sınama gibi derler ve çalıştırır. Bu, bu müfredatta program içinden kurulan ikinci ölçüm biçimi — Prosedürel Makrolar dersinde derleyicinin kendisi program içinden çağrılmıştı, burada çağrılan derleyici değil, derleyicinin bir yan aracı. Aşağıdaki program bu aracı std::process::Command ile kendi içinden çağırıyor ve yalnız kaç örneğin geçtiğini basıyor — yol, süre ve makine adı basılmıyor.

// belge_sinamasi.rs — belge aracini program icinden cagirip gecen sinama sayisini basar
use std::process::Command;

fn main() {
    let derleme = Command::new("rustc")
        .args([
            "--edition", "2021", "--crate-type", "lib",
            "-o", "libbelge_govdesi.rlib", "belge_govdesi.rs",
        ])
        .output()
        .expect("derleyici baslatilamadi");
    if !derleme.status.success() {
        println!("gecen sinama sayisi: 0");
        return;
    }

    let sinama = Command::new("rustdoc")
        .args(["--edition", "2021", "--test", "-L", ".", "belge_govdesi.rs"])
        .output()
        .expect("belge araci baslatilamadi");

    let cikti = String::from_utf8_lossy(&sinama.stdout);
    let sayi = cikti
        .lines()
        .find(|s| s.starts_with("test result:"))
        .and_then(|satir| satir.split("passed").next())
        .and_then(|parca| parca.trim().rsplit(' ').next())
        .and_then(|s| s.parse::<u32>().ok())
        .unwrap_or(0);

    println!("gecen sinama sayisi: {}", sayi);
}
gecen sinama sayisi: 3

PY14. Üç örneğin üçü de geçti — belgesi_yanlis, kucuk_olan ve toplanın örnekleri. Bu program iki adımda çalışıyor. İlk adımda kaynağı bir kütüphane olarak derliyor; bu adım gerekli çünkü her örnek kaynaktaki gerçek işlevleri belge_govdesi::belgesi_yanlis gibi tam adlarla çağırıyor ve belge aracının bu adları çözebilmesi için önceden derlenmiş kütüphaneyi bulması gerekiyor. İkinci adımda belge aracı sınama kipinde çağrılıyor; -L . seçeneği aracın önceden derlenmiş kütüphaneyi çalışma dizininde arayacağını belirtiyor. Aracın kendi çıktısı satır satır bir yol, bir geçen süre ve ayrıntılı bir döküm içerir; bu program o çıktının içinden yalnız “geçti” satırındaki tek bir sayıyı çıkarıyor ve geri kalanını hiç yazdırmıyor — ortama bağlı hiçbir alan bu programın kendi çıktısına karışmıyor.

Bu koşum, önceki bölümdeki gözlemi tersine çeviriyor. Sıradan derlemede belge tamamen görünmezdi; burada belge aracı aynı kaynağı farklı bir gözle okuyor — her # Ornekler bloğundaki kod parçasını ayrı bir kaynak dosyası gibi ele alıp gerçekten derliyor ve koşturuyor. belgesi_yanlisin örneği içindeki eşitlik sınayan çağrıyla gerçek davranışı (3 sonucunu) sınıyor ve geçiyor — çünkü örnek kodun kendisi doğru yazılmış, yanlış olan yalnız üstündeki prose cümlesi. Bu derste ölçülen sınıf burada değişiyor: sürdürüyor. Belge aracı, dilin kendi dağıtımının bir parçası ve tıpkı rustcnin bir gövdeyi denetlediği gibi, örneği derleyip çalıştırarak denetliyor.

Bu, önceki bölümde anlatılan çürümeye karşı bir savunma sağlıyor — ama yalnızca örnek için, prose için değil. kucuk_olanın imzası değişseydi (örneğin iki yerine üç argüman alsaydı), örneğindeki çağrı artık derlenmezdi ve belge aracı bunu “başarısız” olarak işaretlerdi; örnek, gövdeyle senkron kalmaya zorlanıyor. belgesi_yanlisin prose’unu ise hiçbir mekanizma gövdeyle senkron tutmuyor — gövde değişse de değişmese de, cümle olduğu gibi kalır. Belge aracının verdiği güvence bu yüzden gerçek ama dar: yalnız örnek gövdeyle senkron kalmaya zorlanıyor, onu çevreleyen açıklama değil.

Ayrım cümlesi: M09/K05 kursunun ölçü ekseni bir bilginin kim tarafından söylendiğiydi — kaynak mı, araç mı, koşum mu. Bir belge cümlesi tam olarak kaynağın söylediği bir bilgidir; bu ders o bilginin doğrulanıp doğrulanmadığını soruyor. Yanıt ikiye ayrılıyor: düzyazı kısmı hiçbir araç tarafından okunmuyor (denetlenmiyor), örnek kısmı ise dilin kendi belge aracı tarafından koşturuluyor (sürdürüyor) — aynı kaynak cümlesinin iki farklı parçası, iki farklı akıbete uğruyor. M09/K05’in üçlü ayrımıyla karşılaştırıldığında, bir belge cümlesinin prose’u tam da “kaynağın söylediği” kategoriye düşer — hiçbir araç ya da koşum onu doğrulamaz; belge cümlesinin örneği ise bu üçlünün dışına çıkar, çünkü artık kaynağın söylediği bir şey olmaktan çıkıp koşumun doğruladığı bir şeye dönüşür.

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

Yukarıdaki iki koşum bir arada okunduğunda çarpıcı bir sonuç ortaya çıkıyor: belgesi_yanlisin örneği geçen üç sınamadan biri ve onun geçmesi, üstündeki prose cümlesinin hâlâ yanlış olduğu gerçeğini hiç değiştirmiyor. Örnek 3ü sınıyor ve 3 doğru sonuç; prose “en büyük” diyor ve bu yanlış. Belge aracı örneği çalıştırıp doğru sonucu aldığı için sınamayı geçti olarak işaretliyor — prose’un ne söylediğine hiç bakmadan.

PY15. Bu, bu ölçümün en önemli sınırı: belge aracının denetlediği şey örnektir, açıklama değil. Bir örnek, içindeki iddiaları (eşitlik sınayan çağrıyla yazılan beklenen değerleri) sınar; örneğin üstündeki düzyazı cümlesi neyi anlattığını hiçbir biçimde etkilemez ya da denetlemez. Bir kişi belgesi_yanlisin belgesini okuyup “en büyüğü döndürüyor” diye anlayabilir, aynı belgenin altındaki örneği görüp onun geçtiğini de bilebilir — ve yine de yanlış bir izlenimle kaynaktan ayrılabilir, çünkü geçen örnek prose’un doğruluğuna dair hiçbir şey söylemiyor.

Bu sınırın kapsamı da belirgin: belge aracı yalnız ``` ile işaretlenmiş kod bloklarını görür; bu blokların dışındaki her cümle, # Ornekler başlığı da dâhil, onun için sıradan metindir. Bir örneğin doğru yazılmış olması, o örneğin açıklamayla tutarlı olduğu anlamına gelmez — yalnızca örneğin kendi içinde doğru (kaynak koddaki gerçek davranışla eşleştiği) anlamına gelir. Bu derste kucuk_olan işlevi tam olarak belgesi_yanlis ile aynı gövdeye sahip, ama prose’u doğru; ikisinin de örneği aynı sınamadan geçiyor, çünkü örnek yalnız kod düzeyinde neyin çağrıldığını ve neyin döndüğünü sınıyor, iki işlevin prose’unu karşılaştırmıyor.

Bu sınırın bir sonucu daha var: bir örneğin geçmesi, o örneğin temsil ettiği durumun eksiksiz olduğu anlamına da gelmez. belgesi_yanlisin örneği yalnız tek bir çağrıyı (3 ile 9) sınıyor; işlev başka bir girdiyle çağrıldığında ne döndüğü bu örnekte hiç görünmüyor. Belge aracı bu örneği geçti olarak işaretlerken, işlevin bütün girdiler için ne yaptığına dair hiçbir şey söylemiyor — tıpkı Test ve Özellik Tabanlı Sınama dersinde görülen sınırın burada da geçerli olması gibi: sınanan girdi kadar güvence, ne fazlası ne eksiği. Belge aracının verdiği güvence bu yüzden iki kat sınırlı: yalnız örneği sınar (prose’u değil) ve örneğin sınadığı girdiyi sınar (işlevin bütün davranışını değil).

Özet

  • Sıradan bir derlemede (rustc) bir belge yorumunun hem prose’u hem de içindeki kod örneği görünmezdir; derleyici ikisine de bakmaz.
  • belgesi_yanlis işlevinin belge cümlesi “en büyük” diyor, gövde “en küçüğü” döndürüyor; bu çelişki sıradan derlemede uyarısız geçiyor — sınıf denetlenmiyor.
  • Belge aracı program içinden çağrılıp yalnız geçen sınama sayısı (3) basıldı; süre, yol ve makine adı hiç yazdırılmadı.
  • Belge aracı # Ornekler içindeki kodu gerçekten derleyip çalıştırır; bu bölüm için sınıf sürdürüyor — dilin kendi aracı, rustcnin denetimini bir adım daha ileri taşıyor.
  • Sınırlayıcı ölçüm: belgesi_yanlisin örneği geçti, ama üstündeki yanlış prose cümlesi hâlâ yanlış — belge aracı örneği sınar, açıklamayı değil.
  • Aynı işlev aynı anda iki güvence sınıfı taşıyabilir: belgesinin düzyazısı denetlenmiyor, belgesinin örneği sürdürüyor.

Sonraki Adım

Proje Yaşam Döngüsü konusunun bu dört dersi, derleyicinin güvencesinin dört ayrı yerde nasıl durduğunu gösterdi: kapalı bir bayrağın gövdesinde (denetlenmiyor), koşarak kurulan bir sınamada (devredildi), sayılan bir işlem biriminde (denetlenmiyor) ve şimdi bir belge cümlesinde — burada ilk kez tek bir derste iki sınıf (denetlenmiyor ve sürdürüyor) bir arada. Dördü de aynı gerçeğin farklı görünümleri: derleyicinin durduğu her yerde, kalan boşluğu ya hiç kimse doldurmuyor, ya yazan taraf koşarak dolduruyor, ya da dilin kendi bir aracı farklı bir denetimle devreye giriyor.

Kursun son dersi — kurs kapanışı — bu dört yeri bir araya getirip beşinci bir yere bakıyor: bir kaynağın dışına, bir sürüm dizesine. O dize de kaynakta duruyor ve hiçbir şeye karşılık gelmiyor; bir kitaplığın hangi sürümünün hangi imzayı koruduğu, yayımlama dersinin konusu. Bu ders orada da izini bırakıyor: bir sürüm dizesi de tıpkı bir belge cümlesi gibi kaynakta duran, insanın okuduğu ama derleyicinin hiç denetlemediği bir iddia.

İ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