İçeriğe geç
academia.sh

Ders 18 / 18

Belgeleme Sözleşmeleri

Altı ad — üç dışa aktarılan, üç dışa aktarılmayan; her üçlüde biri bitişik yorumlu, biri araya boş satır giren yorumlu, biri yorumsuz — belge aracına soruluyor. Görünen adların sayısı yalnız harfin büyüklüğüne bağlı (3/6), açıklaması olanların sayısı ise yalnız yorumun konumuna bağlı (1/6). Sınırlayıcı ölçüm, doğru olmayan bir belge yorumunun da aynen görüntülendiğini gösteriyor: belge aracı yorumun doğruluğunu hiç denetlemiyor.

İçindekiler

Önceki üç ders, dilin kendi komut ailesinin üç üyesini çağırdı: derleyici bir kaynağın geçerli olup olmadığına karar verdi, biçimlendirici görünüşünü kanonikleştirdi, inceleyici derleyicinin gözden kaçırdığı bir kalıbı yakaladı. Üçü de kaynağın kendisiyle ilgileniyordu. Bu son ders ailenin dördüncü üyesine bakıyor: bir paketin dışarıya ne sunduğunu anlatan metni üreten belge aracına. Bu araç kaynağı ne derliyor ne biçimlendiriyor ne de bir kalıba karşı sınıyor — yalnız okuyor, ve hangi adı, hangi yorumla, ne zaman göstereceğine karar veriyor. Kursun son sorusu: bu kararı veren şey yorumun kendisi mi, yoksa adın baş harfi mi?

Bitişik Yorum, Ayrık Yorum

PK19. Bir yorum, bir tanıma bitişik yazıldığında (araya boş satır girmeden) o tanımın belge yorumu sayılır; araya bir boş satır girdiğinde aynı yorum metni artık hiçbir tanıma bağlanmaz. PK20. Belge aracı yalnız dışa aktarılan adları listeler; dışa aktarılmayan bir adın belge yorumu ne kadar özenli yazılırsa yazılsın, o ad belgeye hiç girmez.

// araclar/araclar.go — belge aracini program icinden cagiran ortak yordamlar
package araclar

import (
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func ortam() []string {
	return append(os.Environ(), "GOTOOLCHAIN=local")
}

// GecidiKur verilen paket kaynagini "sinama/pk" alt paketine yazip modulun kok
// dizinini dondurur; cagiran bu dizinde belge aracini calistirir.
func GecidiKur(pkKaynagi string) string {
	dizin, _ := os.MkdirTemp("", "sinama")
	os.WriteFile(filepath.Join(dizin, "go.mod"), []byte("module sinama\n\ngo 1.24\n"), 0o644)
	os.MkdirAll(filepath.Join(dizin, "pk"), 0o755)
	os.WriteFile(filepath.Join(dizin, "pk", "pk.go"), []byte(pkKaynagi), 0o644)
	return dizin
}

// BelgedeGorunuyorMu bir adi belge aracina sorar; ad belgede varsa gorundu true doner,
// aciklamaVar ise satirin altinda bir yorum metni olup olmadigini soyler.
func BelgedeGorunuyorMu(dizin, ad string) (gorundu, aciklamaVar bool) {
	cmd := exec.Command("go", "doc", "./pk."+ad)
	cmd.Dir = dizin
	cmd.Env = ortam()
	cikti, err := cmd.Output()
	if err != nil {
		return false, false
	}
	satirlar := strings.Split(strings.TrimRight(string(cikti), "\n"), "\n")
	bosOlmayan := 0
	for _, s := range satirlar {
		if strings.TrimSpace(s) != "" {
			bosOlmayan++
		}
	}
	// Cikti yalniz paket basligi ve imza satiriyken iki bos olmayan satir tasir;
	// bir aciklama eklendiginde bu sayi artar.
	return true, bosOlmayan > 2
}

// BelgeMetni bir adin belge aracindan donen tam ciktisini dondurur.
func BelgeMetni(dizin, ad string) string {
	cmd := exec.Command("go", "doc", "./pk."+ad)
	cmd.Dir = dizin
	cmd.Env = ortam()
	cikti, _ := cmd.Output()
	return strings.TrimSpace(string(cikti))
}

BelgedeGorunuyorMu, belge aracını doğrudan bir adla çağırıyor: ad bulunursa çıktı en az paket başlığı ve imza satırını taşıyor, bulunamazsa araç sıfır olmayan bir çıkış koduyla dönüyor ve hata metni hiç okunmuyor. Açıklama olup olmadığı, çıktının kaç satır taşıdığına bakılarak sayılıyor — imza satırının altına bir açıklama eklendiğinde çıktı üçüncü bir boş olmayan satır kazanıyor.

Altı Ad, İki Bağımsız Soru

// main.go — belge kaynaktan uretiliyor, gorunurluk harfe, aciklama konuma bagli
package main

import (
	"fmt"
	"os"

	"ders/araclar"
)

func main() {
	pkKaynagi := "// Paket pk belge yorumu deneyleri icin kucuk bir kutuphanedir.\n" +
		"package pk\n\n" +
		"// BuyukYorumlu, verilen iki sayinin toplamini dondurur.\n" +
		"func BuyukYorumlu(a, b int) int { return a + b }\n\n" +
		"// kucukYorumlu, verilen iki sayinin toplamini dondurur.\n" +
		"func kucukYorumlu(a, b int) int { return a + b }\n\n" +
		"func BuyukYorumsuz(a, b int) int { return a - b }\n\n" +
		"func kucukYorumsuz(a, b int) int { return a - b }\n\n" +
		"// BuyukAyrikYorum bir aciklamadir ama tanimdan bos satirla ayriliyor.\n\n" +
		"func BuyukAyrikYorum(a, b int) int { return a * b }\n\n" +
		"// kucukAyrikYorum bir aciklamadir ama tanimdan bos satirla ayriliyor.\n\n" +
		"func kucukAyrikYorum(a, b int) int { return a * b }\n\n" +
		"// Ortalama, verilen sayilarin ortalamasini dondurur.\n" +
		"func Ortalama(sayilar ...int) int {\n" +
		"\ttoplam := 0\n" +
		"\tfor _, s := range sayilar {\n" +
		"\t\ttoplam += s\n" +
		"\t}\n" +
		"\treturn toplam\n" +
		"}\n"

	dizin := araclar.GecidiKur(pkKaynagi)
	defer os.RemoveAll(dizin)

	adlar := []string{
		"BuyukYorumlu", "kucukYorumlu",
		"BuyukYorumsuz", "kucukYorumsuz",
		"BuyukAyrikYorum", "kucukAyrikYorum",
	}

	fmt.Println("-- alti ad, belgede goruntu ve aciklama --")
	gorunenSayisi, aciklamaliSayisi := 0, 0
	for _, ad := range adlar {
		gorundu, aciklamaVar := araclar.BelgedeGorunuyorMu(dizin, ad)
		if gorundu {
			gorunenSayisi++
		}
		if aciklamaVar {
			aciklamaliSayisi++
		}
		fmt.Printf("%-18s gorundu=%-5v aciklama=%v\n", ad, gorundu, aciklamaVar)
	}
	fmt.Printf("toplam: %d/6 gorundu, %d/6 aciklamali\n", gorunenSayisi, aciklamaliSayisi)

	fmt.Println()
	fmt.Println("-- sinirlayici olcum: belge araci yorumun dogrulugunu denetlemiyor --")
	fmt.Println(araclar.BelgeMetni(dizin, "Ortalama"))
	fmt.Printf("Ortalama(2, 4, 6) gercek sonucu: %d\n", gercekOrtalama(2, 4, 6))
}

// gercekOrtalama, uretilen Ortalama islevinin gercekte ne yaptigini bagimsiz olarak
// gosterir: yorum "ortalama" diyor, islev toplami donduruyor.
func gercekOrtalama(sayilar ...int) int {
	toplam := 0
	for _, s := range sayilar {
		toplam += s
	}
	return toplam
}
-- alti ad, belgede goruntu ve aciklama --
BuyukYorumlu       gorundu=true  aciklama=true
kucukYorumlu       gorundu=false aciklama=false
BuyukYorumsuz      gorundu=true  aciklama=false
kucukYorumsuz      gorundu=false aciklama=false
BuyukAyrikYorum    gorundu=true  aciklama=false
kucukAyrikYorum    gorundu=false aciklama=false
toplam: 3/6 gorundu, 1/6 aciklamali

-- sinirlayici olcum: belge araci yorumun dogrulugunu denetlemiyor --
package pk // import "sinama/pk"

func Ortalama(sayilar ...int) int
    Ortalama, verilen sayilarin ortalamasini dondurur.
Ortalama(2, 4, 6) gercek sonucu: 12

PK21. Altı addan üçü belgede görünüyor, üçü hiç görünmüyor; görünenlerin üçü de büyük harfle başlıyor, görünmeyenlerin üçü de küçük harfle. PK22. Görünen üç addan yalnız biri açıklama taşıyor — yorumu tanıma bitişik olan BuyukYorumlu; yorumu olmayan BuyukYorumsuz ile yorumu araya boş satırla ayrılan BuyukAyrikYorum, ikisi de belgede adıyla görünüyor ama açıklamasız.

Bu iki gözlem birbirinden tamamen bağımsız iki soruya yanıt veriyor. “Bu ad belgede var mı?” sorusunun yanıtı yalnız harfin büyüklüğüne bakıyor — kucukAyrikYorum’un yorumu BuyukAyrikYorum’unkiyle birebir aynı biçimde ayrık, ama ikisinin belgedeki kaderi hiç aynı değil, çünkü aradaki fark yorumda değil adın kendisinde. “Bu adın açıklaması var mı?” sorusunun yanıtı ise yalnız yorumun konumuna bakıyor — BuyukYorumsuz’un hiç yorumu yok, BuyukAyrikYorum’un bir yorumu var ama tanımdan kopuk; ikisi de belgede açıklamasız görünüyor, çünkü ikisinde de belge aracının okuyacağı bitişik bir yorum yok.

Sınırlayıcı Ölçüm: Belge Aracı Doğruluğu Denetlemiyor

PK23. Ortalama işlevinin belge yorumu “verilen sayıların ortalamasını döndürür” diyor; işlevin kendisi toplamı döndürüyor. Ortalama(2, 4, 6) çağrıldığında dönen değer 12 — ortalama değil, toplam. PK24. Belge aracı bu yorumu, doğruluğunu hiç sınamadan, aynen basıyor; ne derleyici ne inceleyici ne de belge aracı bu uyuşmazlığı yakalıyor.

Bu kursun son açıkta satırı, ve öncekilerden farklı bir yerde duruyor. Önceki açıkta örnekleri (ilk değeri verilmeyen bir sözlüğe yazmanın panikle durması, bir dizginin baytla indekslenmesi) hep çalışma zamanında ortaya çıkan bir sonuçtu — programı çalıştırdığında bir şey oluyordu. Burada açıkta kalan şey çalışma zamanıyla hiç ilgili değil: Ortalama işlevi hatasız çalışıyor, panik atmıyor, yanlış bir tip döndürmüyor — yalnız adının söylediğiyle yaptığı şey uyuşmuyor, ve bu uyuşmazlığı denetleyecek hiçbir araç yok. Derleyici bir dizginin içeriğini denetlemediği gibi, bir yorumun içeriğini de denetlemiyor; inceleyici biçim damgalarıyla argüman tiplerini eşleştiriyor ama bir yorumun anlattığıyla kodun yaptığını karşılaştırmıyor; belge aracı bu iki dosyayı (kaynak ve yorum) birbirine bağlamıyor bile, yalnız yorumu konumuna göre kopyalayıp gösteriyor. Yazılmayan şey burada bir denetim mekanizması, ve dil bunun yerine hiçbir şey koymuyor.

Kurs Kapanışı

Go Temelleri tek bir soruyla açıldı: bir program yazarken en çok işe yarayan şey, yazılanın ne yaptığı değil, yazılmayanın ne olduğudur. On sekiz ders bu soruyu üç düzenekte sordu: dilin kendisinde (sıfır değerler, dilim ve sözlük davranışı), derleyicide (kullanılmayan değişkenden dışa aktarma kuralına kadar reddedilen kalıplar), ve kaynağın dışında (sürüm seçimi, biçim, belge).

Birinci iddia doğrulandı: Go’da “başlatılmamış” diye bir durum yok — yazılmayan bir değerin yerini hep tanımlı bir karşılık dolduruyor, ister bir sıfır değer olsun ister bir dilim sınırının varsayılanı. İkinci iddia, derleyicinin reddettiği kalıpların hepsinin “yazılmayanın karşılığını daraltma” kararı olduğunu gösterdi — kullanılmayan bir değişkenden dışa aktarılmayan bir alana kadar, derleyici bazı yazılmamışlıkları hiç kabul etmiyor. Üçüncü iddia, tanımlılığın okuma yönünde çalışıp yazma ve yorumlama yönünde bittiğini kurdu: bu son derste bunun en uç örneği görüldü — bir yorumun okunması tanımlı, ama o yorumun doğru olup olmadığı hiçbir yerde denetlenmiyor.

Kurs aşırı bir genelleme yapmadan kapanıyor: bu üç sınıf (tanımlı, reddedildi, açıkta) Go’nun bütün davranışını kapsamıyor, yalnız bu on sekiz dersin sorduğu soruya — bunu yazmadığında ne oluyor? — verilen yanıtları sınıflıyor.

Ders Ölçülen yazılmamışlık Karşılığı (tanımlı · reddedildi · açıkta) Sınırlayıcı ölçüm
Go’nun Tasarım Amaçları Dört ret nedeni: kullanılmayan değişken/içe aktarım, yazılmayan dönüş, örtük dönüşüm reddedildi Örtük dönüşümün reddi kaynağı kısaltmıyor: derlenmeyen satır 15, derlenen karşılığı 22 karakter
Ortam Kurulumu ve İlk Program Çalışmak için zorunlu üç parça: paket bildirimi, func main, modül dosyası reddedildi Modül dosyası kaynağın dışında durur; kaynak hiç değişmeden, yalnız modül dosyası kaldırılınca derleme durur
Değişkenler ve Sabitler Altı sabitten yalnız ikisinin değeri kaynakta yazılı, dördü iota ile üretiliyor tanımlı (iota) · reddedildi (paket düzeyinde kısa bildirim) Kısa bildirim yalnız fonksiyon içinde geçerli; aynı satır paket düzeyinde reddediliyor
Temel Tipler Tipsiz sabitin varsayılan tipi int; int8 sınırını aşan toplam -128’e sarıyor tanımlı (varsayılan tip, taşma) · açıkta (kayan noktalı karşılaştırma) Örtük dönüşümün reddi sabitlerde geçerli değil; tipsiz sabit hedef tipe kendiliğinden uyuyor
Sıfır Değerler On beş yazılmamışlığın dağılımı — kursun bağlayıcı sayısı burada üretiliyor 8 tanımlı · 4 reddedildi · 3 açıkta nil dilime eklenebiliyor, nil sözlüğe yazılamıyor; ikisi de aynı biçimde sıfır değer
Denetim Akışı forun üç bölümünün isteğe bağlılığı, ifadesiz switch, yazılmayan break tanımlı (beş biçimin beşi) Varsayılanın tersi bedelsiz değil: düşmeyi istemek fallthrough yazmayı gerektiriyor
Fonksiyonlar Adlandırılmış dönüşün gövdede hiç yazılmaması; dönen değerin hiç yakalanmaması tanımlı (sıfır dönüş) · reddedildi (dönüşün yazılmaması) · açıkta (yok sayılan dönüş) Dönen değer bir ada bağlanınca kullanılmayan değişken reddi devreye giriyor
Değişken Sayıda Argüman Hiç argüman verilmeyen parametrenin nil dilim olması tanımlı nil dilim ile boş dilim len açısından aynı, kimliğe bakan işlemlerde ayrı
Diziler ve Dilimler Atama satırında dizi/dilim farkı: dizide kopya, dilimde paylaşım tanımlı append kapasiteyi aştığında paylaşım kesiliyor; kopyalanan başlık artık ayrı bir alt diziyi gösteriyor
Dilim İşlemleri Yazılmayan dilimleme sınırlarının varsayılanı tanımlı Aynı append çağrısı, aynı kaynak metinle, iki ayrı kapasitede iki ayrı sonuç veriyor
Sözlükler Dört erişim biçiminin sınıfı: var olan/olmayan anahtar, nil sözlükten okuma/yazma tanımlı · açıkta (yazma panikliyor) İki yanıtlı erişim olmadan, değeri sıfır olan bir kayıt ile hiç var olmayan kayıt ayırt edilemiyor
Yapılar Yazılmayan alanların sıfır değeri; gömmenin yazılmayan adları dış tipe taşıması tanımlı Gömme kalıtım değil: gömülü tipin yöntemi çağrıldığında alıcı gömülü değerin kendisi, dış yapı değil
İşaretçiler Adres alınmadan geçirilen dizi ve yapının çağıranda değişmemesi tanımlı (kopya) · açıkta (nil işaretçiden alan okuma) İşaretçi de bir değerdir ve kopyalanır; yeniden atamak yalnız yerel kopyayı değiştiriyor
Dizgiler ve Rune’lar len bayt sayıyor, indeksleme bayt veriyor, range rune veriyor tanımlı (bayt sözü) · açıkta (karakterin karşılığı yok) Rune sayısı da karakter sayısı değil; birleşik kod noktaları bunu bozuyor
Paket Düzeni ve Görünürlük Dışa aktarmanın bir harfe bağlı olması reddedildi (paket dışından) · tanımlı (paket içinde) Sınır paket sınırıdır, dosya sınırı değil; aynı paketin iki dosyası küçük harfli bir adı hiç import olmadan paylaşıyor
Modüller ve Bağımlılıklar Yazılmayan bağımlılık sürümü türetilen (en düşük sürüm seçimi) Seçilen sürüm kataloğun en yenisi değil, yazılan (ya da türetilen) isteklerin en büyüğü
Go Komut Ailesi Yazılmayan kaynak biçimi; derleyicinin reddetmediği bir kalıp tanımlı (biçim) · reddedildi (inceleyici) Biçim değişiyor (18 satırın 7’si), anlam değişmiyor: biçimlendirme öncesi ve sonrası kaynağın çıktısı aynı
Belgeleme Sözleşmeleri Belgeye giren ad ve açıklama tanımlı (harfe göre görünürlük) · açıkta (içerik denetlenmiyor) Belge aracı yorumun doğruluğunu denetlemiyor; yanlış bir açıklama da aynen basılıyor

Özet

  • Belge aracı yalnız dışa aktarılan adları listeler; bir adın belgede görünüp görünmeyeceğini yalnız ilk harfinin büyüklüğü belirler, yorumun kendisi değil.
  • Bir yorumun açıklama sayılması, tanıma bitişik yazılmasına bağlıdır; araya giren tek bir boş satır, yorumu o tanımdan koparır ve belgede görünmez kılar.
  • Altı adın üçü belgede görünür (yalnız büyük harfliler), görünenlerin yalnız biri açıklama taşır (yalnız bitişik yorumlu olan) — iki soru birbirinden bağımsızdır.
  • Sınırlayıcı ölçüm: belge aracı bir yorumun doğru olup olmadığını hiç denetlemez; yanlış bir açıklama, doğru bir açıklamayla aynı biçimde basılır.
  • Kurs üç sınıfla (tanımlı, reddedildi, açıkta) kapandı; bu sınıflar Go’nun bütün davranışını değil, yalnız bu on sekiz dersin sorduğu tek soruyu kapsıyor.

İ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