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.