Neden “Why Not” yorumlarına ihtiyaç var?
(buttondown.com)- Yorumlar, tanımlayıcılardan daha ifade gücü yüksek insan dili kullanabildiği için kodda yer almayan seçenekleri ve vazgeçilen alternatifleri bırakmaya uygundur
- “comment the why, not the what”, bilgiyi mümkün olduğunca tanımlayıcılara koymaya yönelik bir yaklaşım olsa da son dönemde gerekçeyi bile uzun fonksiyon adlarına veya test adlarına taşıma eğilimi var
Logic for Programmersın epub derlemesinde, 16 matematik sembolünü her dize için sırayla değiştiren yavaş bir uygulama kullanıldı; ancak şu anda yalnızca 25 matematik dizesi olduğu için yeterince hızlı- Bu tür yorumlar, ileride matematik dizeleri yüzlerceye çıkıp derleme darboğazı oluştuğunda nerelerin düzeltilmesi gerektiğini gösterir ve yavaş kodun bilinçli bir ödünleşim olduğunu kayda geçirir
- Fonksiyon adları veya testler, kodun fiilen yaptığı işe bağlandığı için seçilmemiş alternatifleri ve yapılmayan işleri içeren negatif bilgiyi kendi kendini belgeleyen şekilde aktarmak zordur
Yorumların koda göre daha kolay taşıyabildiği bilgiler
- Kod, yapılandırılmış bir makine dilidir; yorumlar ise ifade gücü yüksek insan diliyle yazılır
- “comment the why, not the what”, mümkün olduğunca fazla bilgiyi tanımlayıcılara koymak anlamında yorumlanabilir
- Tanımlayıcılar, kodun içine dahil edilmiş sınırlı bir insan diline daha yakındır; tüm “what” bilgisini taşıyamazlar, ancak çoğu durumda önemli bir kısmını taşıyabilirler
- Son dönemde “why” bilgisinin de yorum yerine uzun fonksiyon adlarına veya test case adlarına konabileceği görüşü yaygınlaşıyor
- Kendi kendini belgeleyen kod tabanları genelde tanımlayıcı ekleme yoluyla belgelendirmeyi artırır
- İstisna olarak, yorumların loglamaya dönüştürülerek kodun daha fazla kendi kendini belgelediği bir örnek de vardır
“Why Not” yorumlarının ele aldığı şey
- Kodla ifade edilmesi zor olan bilgi negatif bilgidir
- Negatif bilgi, sistemde neyin bulunmadığına ve belirli bir alternatifin neden seçilmediğine dikkat çeker
- “why not”, kodun ne yaptığını açıklamaktan ziyade kodun seçmediği seçenekleri ve bunların nedenlerini kayda geçirir
epub matematik sembolü değiştirme örneği
Logic for Programmersın epub derlemesinde, teknik nedenlerle\forallgibi matematik gösterimleri∀gibi sembollere dönüştürülmüyordu- Bunu çözmek için matematik dizelerindeki token’ları karşılık gelen Unicode sembolleriyle doğrudan değiştiren bir script yazıldı
- En kolay uygulama, gerekli 16 matematik sembolünün her biri için
string = string.replace(old, new)çağırmaktı - Bu yöntem her dizeyi 16 kez dolaştığı için verimsizdir; ancak 16 değiştirmenin tümünü tek geçişte yapmak daha karmaşıktır
- Bırakılan yorumun özü şuydu
- Her dize 16 kez dolaşılır
- Kitapta şu anda yalnızca 25 matematik dizesi var ve çoğu 5 karakterden kısa
- Bu yüzden hâlâ yeterince hızlı
- Bu yorum yalnızca “neden yavaş kod kullanılıyor” sorusunu değil, “neden hızlı kod kullanılmıyor” sorusunu da açıklar
Gelecekteki okurlar için bir işaret levhası
- Yavaş kod şu anda sorun çıkarmasa da ileride sorun olabilir
Logic for Programmersın gelecekteki bir sürümünde matematik dizeleri yüzlerceye çıkarsa ilgili derleme adımı tüm derlemenin darboğazı haline gelebilir- Şimdi bir işaret bırakılırsa, ileride hangi bölümün düzeltilmesi gerektiği hemen anlaşılabilir
- Kod sorunsuz çalışmaya devam etse bile yorum, yazarın ödünleşimin farkında olduğu gerçeğini korur
- 2 yıl sonra
epub_math_fixer.pyyeniden açıldığında, yavaş kodun acemilikten mi, zaman yetersizliğinden mi yoksa hatadan mı kaynaklandığını yeniden araştırma ihtiyacı azalır - Negatif yorum, yavaş uygulamanın bilindiği, alternatiflerin değerlendirildiği ve optimize etmeme kararı verildiği bilgisini bırakır
Fonksiyon adları ve testlerle değiştirmenin zor olma nedeni
RunFewerTimesSlowerAndSimplerAlgorithmAfterConsideringTradeOffsgibi bir fonksiyon adı fazla uzundur ve gerçek ödünleşimi yeterince açıklayamaz- Daha sonra kod optimize edilirse bu adın birçok yerde değiştirilmesi gerekebilir
- Daha büyük sorun, böyle bir adın fonksiyonun gerçekte ne yaptığını anlatamaması ve kendi kendini belgelemeyi aksine zayıflatmasıdır
- Fonksiyon adları ve değişken adları gibi tanımlayıcılar yalnızca bir cümlelik bilgi taşıyabilir
- Tek bir tanımlayıcıya hem “fonksiyonun yaptığı işi” hem de “fonksiyonun kabul ettiği ödünleşimi” aynı anda koymak zordur
Testlerle de bırakılması zor negatif bilgi
- Kitaptaki matematik bloklarını grep edip sayı 80’i aşarsa başarısız olan bir test yazılabilir
- Ancak böyle bir test
EpubMathFixerın kendisini doğrudan test etmez - Fonksiyonun içinde bu testin bağlanabileceği bir nokta yoktur
- Kendi kendini belgeleme, yazılmış koda ilişerek kodun yaptığı işi açıklar
- Negatif bilgi ise kodun yapmadığı işleri ele aldığı için kendi kendini belgeleme yöntemiyle temelden uyuşmaz
Daha geniş soru
- “why not” yorumları, karşıolgusalın (counterfactual) bir örneği olarak görülebilir
- İnsan iletişiminin soyut unsurlarının genel olarak kendi kendini belgeleyip belgeleyemeyeceği sorusu ortada kalır
- Benzetme, belirsizlik ve etik iddialar gibi bilgilerin de kendi kendini belgeleyip belgeleyemeyeceği hâlâ soru işaretidir
1 yorum
Hacker News görüşleri
Birkaç yıl önce Twitter’da gördüğümü sandığım bir şakayı hatırlıyorum: “Junior mühendis, kodun ne yaptığını açıklayan yorumlar yazar; orta seviye mühendis, kodun neden bunu yaptığını açıklayan yorumlar yazar; senior mühendis ise kodun neden başka bir şekilde yazılmadığını açıklayan yorumlar yazar” gibi bir şeydi.
Buna karşılık, fonksiyon ve değişken adlarıyla anlam netleşebiliyorsa, epey büyük fonksiyonları bile yorumsuz yazdığım oldu.
Bu yüzden daha az yorum olan taraf kazanır; ama yorumsuz bir kod tabanı gördüğünde bunun güzelce cilalanmış bir başyapıt mı yoksa acemilerin yaptığı kırılgan bir kod mu olduğunu ayırt etmek için bizzat incelemek gerekir.
Tam bir yama gibi görünse de bazen gerçekten elde edilebilecek en iyi şey odur.
Bir yıl sonra koda tekrar baktığımda bana faydalı olacak gibi görünen her şeyi yorum olarak bırakırım. Genelde bunlar neden ve neden olmaz olur; kod karmaşıksa akışı daha iyi görmek için kısa bir “ne” de yazarım.
Faydasız olan zorunlu yorumlardır. Public API’ler yeterince dokümante edilmelidir; ama bazı organizasyonlar private fonksiyonlara kadar her fonksiyon için yorum zorunlu tutar ve amaç o kadar barizdir ki fonksiyon adını tekrar etmekten ibaret hale gelir. Bu yalnızca zaman kaybı değil, aynı zamanda insanları yorumlara karşı duyarsızlaştırıp onları görmezden gelme alışkanlığı kazandırır.
Araçların eklediği israf yorumları da sevmem. Her döngüye
//forya da//trykoymak özellikle kötü.Zorunlu ve üretilmiş yorumları kaldırıp, koyu temalarda yorumları göze çarpacak şekilde parlak neon renge çevirmek daha iyi olur. Bir yorum varsa, bu önemli olduğu anlamına gelmelidir.
Sıkışık takvimli bir iş ortamında eski ve büyük sistemleri sürdürürken garip şeyler yapmak zorunda kalınabilir; o zaman da nedenini açıklamak gerekir.
Yorumlara karşı olmanın büyük nedeni, yorumların da kodun parçası haline gelip bakım gerektirmesidir. Ama çoğu kişi yorumları yalnızca takıldığında okur; editörler de yorumları griye boyayıp psikolojik olarak görünmez kılar. Bu yüzden yorumlar kolayca eskir.
“Gelecekteki ben” için bağlamın, çok sayıda geliştiricinin dokunduğu paylaşımlı kod tabanlarında da faydalı olup olmadığını; yoksa az sayıda kişinin koda dokunduğu durumlarda iyi çalışan bir yöntem mi olduğunu merak ediyorum.
Bu yüzden mevcut yoruma “=> yes!” ekledim ve geçmişteki kendimin bu soruyu dokümante etmiş olmasına minnettar oldum. İşte ise özellikle bug fix’lerinde, açık olmayan bir değişikliğin üstüne ticket numarası ile birlikte sık sık bir iki satır yorum bırakırım.
Kodda bıraktığım yorumlar arasında en sevdiğim format şu şablon: “DEAR MAINTAINER: Bu kod [neden] yüzünden böyle. Bunu ‘düzeltmeye’ çalışmanın korkunç bir hata olduğunu fark ederseniz, sonraki kişi için uyarı olarak
total_hours_wasted_here = nsayacını artırın.”Orijinal yazarı ben değilim ama bir iki kez minnetle kullandım; yalnızca sayacı artıran tek satırlık commit’ler görmek eğlenceliydi.
Daha senior bir mühendis kod tabanını devralıp her şeyi döngü tabanlı yaklaşımla “düzeltti” ve e-postayla recursion’ın neden kötü olduğu konusunda bana ders vermeye çalıştı; ama onun kodu gerçek gereksinimlerin hepsini karşılamıyordu ve sonunda benim recursion ile yaptığım şeyleri fiilen yeniden kurdu.
Daha sonra bazı sözleri için özür diledi; ama en üste böyle bir yorum koymuş olsaydım tüm bu işten kaçınılabilirdi.
Başlığın muğlak olduğuna katılıyorum; zaten yazıyı bu yüzden okudum. Kişisel olarak genelinde daha az yorum kullanmayı tercih ederim, ama yazıdaki açıklayıcı yorumlar kesinlikle değerli. Neden öyle yapıldığını, neden başka bir yol seçilmediğini açıklamak gerektiğini iyi hatırlatıyor.
Bu özellikle 5, 10, 15 yıl sonra bile bakımını yapmanız gereken kendi kodunuz için geçerli. Geçenlerde bir çalışma arkadaşımın yeni kodunu incelerken “Neden böyle yapmış?” diye düşündüm; 10 satır yukarıda, 8 yıl önce benim aynı şeyi yapmamın nedeni duruyordu. O çalışma arkadaşım bakımın temel kuralına, yani mevcut kod gibi görünmesini sağlamaya uymuştu.
Bu, daha geniş ölçekte izlenen bir ilkenin yalnızca özel bir hâli: kodu okurken şaşırtıcı olan şeylere yorum eklemek
Kod yazarken zihninde sürekli “Bu kodu daha sonra anlayabilecek miyim?” diye sorup her seferinde içgüdüsel olarak “evet” diyen biri kibirlidir ve sık sık yanılır. Yanıt “emin değilim” ise sonraki soru doğal olarak “neden?” olur; bunun yanıtı da yoruma yazılması gereken şeydir
Bazen yanıt “okuyan kişi neden başka bir şekilde yazılmadığını merak edebilir” olur; bu yazının ele aldığı özel durum budur. Ama bazen de “nasıl çalıştığı ya da neden doğru olduğu açık değil” olur; o zaman başka tür bir yorum gerekir
Bu genellikle dizeleri kesip biçerken veya ara adım olarak alışılmadık veri yapılarını keşfederken olur
Tanımlayıcılarla çok uzağa gidilebilir, ama sonuna kadar gidilemez. Kişisel olarak herkese açık metotlar veya değişkenler, alanlar, parametreler için jsdoc/xmldoc gibi dokümantasyon yorumları istemeyi seviyorum
Metot adını iyi koymak da önemlidir, ama ne yaptığını kısaca yazmayı denemek daha netleştirir ve özellikle bariz kusurları ortaya çıkarır. İlk cümleyi yazdığınız anda çoğu zaman daha iyi bir ad akla gelir; açıklamaya “ve” girmeye başlıyorsa bu, metodun fazla iş yaptığı ve daha mantıklı biçimde bölünebileceği anlamına gelir
Özellikler, belge gerektirmeyecek kadar açık sanılabilir; ama
/** The API key */ string ApiKey;gibi bir şeyde eksik olan çok fazla şey vardır. Bu anahtarın nereden geldiğini, yalnızca dahili kullanım için mi yoksa harici sistemlerle alınıp veriliyor mu olduğunu, zorunlu olup olmadığını, null ya da boş değer alıp alamayacağını, maksimum uzunluğu olup olmadığını, geçersiz bir değer olursa ne olacağını, okunacak başka kod ya da belge bulunup bulunmadığını bilemeyizAsıl yazarın 1-2 dakikada yazabileceği bilgiler bunlar; ama yeni gelen biri bunu değiştirmek, kullanmak ya da yıllar sonra bir hatayı düzeltmek için görevlendirildiğinde anlaması saatler sürebilir
Kod incelemesinde aşırı didikleyen bir reviewer’ın ne diyeceğini tahmin edebildiğimde “Y nedeniyle X yapmadım” gibi yorumları sıkça yazarım. Amaç, yorucu gidip gelmeli tartışmaları azaltmaktır
“Her dizeyi 16 kez dolaşıyor, ama kitaptaki formül dizeleri şimdiye kadar yalnızca 25 tane ve çoğu 5 karakterden kısa olduğu için yeterince hızlı” türü yorumların başka bir çeşidi de var
Girdi, özgün tasarım kısıtlarının çok üzerine çıktığında tetiklenen debug log eklemek. Gelecekteki geliştiriciye neredeyse aynı mesajı verir, ama daha erken fark edilmesini sağlayarak teşhis ve debug süresini daha da azaltır
İdeal bir logging ve gözlemlenebilirlik sistemi, uygulamanın tüm bileşenlerinin süresini ölçer ve sık sık debug bilgisi bırakırdı; ama böyle kusursuz bir sistemi pratikte kim kullanıyor ki? Daha sonra performansı bozulabilecek ya da optimize etmeye zaman bulunamamış yerlere özellikle log eklemek daha önemlidir
Geriye dönüp bakınca bariz bir fikir, ama şimdiye kadar daha sonra yeniden bakılması gereken yerlere yorum bırakıp işler kötüleştiğinde o yorumu hatırlamayı ummak şeklindeydi
Kim ne derse desin, kodun her yerine bol bol yorum ve dokümantasyon yorumu yazarım. Ama tersinden yaklaşırım: önce uygulamanın adım listesini kabaca yorum olarak yazar, sonra geliştirdikçe büyük adımları küçük adımlara böler; ilk yorumları bazen siler, bazen bırakır ve neredeyse tamamlanmış bir algoritmaya dönüşene kadar yorumları ayrıntılandırırım
Genelde dıştan içe doğru kod yazdığım için, yorumları bölerken kodu da beraber yazarım. Bazen de kodu topluca yazıp sonra, çoğu kişinin üşeneceği ölçüde yorum eklerim. Her fonksiyona ve değişkene açıklama koyarım;
deg_to_radfonksiyonuna bile"""Converts degrees to radians."""eklerim. Depolama alanı ucuz ne de olsaÇoğu kişinin bundan hoşlanmadığını biliyorum ama sorun değil. Görmek istemiyorsanız bir script ile kaldırabilir ya da kod incelemesinde silebilirsiniz. Yine de yorumsuz başkasının kodunu okumaktansa kendi eski kodumu okumak çok daha keyifli. Python’da Flask API gibi basit boilerplate kodlar genelde kendi kendini belgeler; ama bazen tam da bu boilerplate çok değiştiği için önemli yorumlar taşır. Sektörde algoritma tarafı ise çoğunlukla baştan yazılır
Yorumları ve dokümantasyon yorumlarını sevmeye devam edeceğim
Zihnimde genel kavramsallaştırmayı yapmayı seviyorum ve başlangıçta çeşitli tasarım seçeneklerini gerçekten yazarak denemeyi yavaş buluyorum. Bu yüzden bir tasarım seçimi netleştiğinde mutlaka belgelendirilmesi gerekiyor. Çünkü başkalarının henüz zihnimin içine erişimi yok
Ayrıntıların, başkaları da kavramsallaştırmayı tamamladığında daha netleşmesini beklerim. Ancak herhangi bir nedenle o kavramsallaştırma gerçekleşmezse okunması daha zorlaşabileceğinden, en azından temel okunabilirliği korumak için ayrıca düzeltirim
Yorumları güncellemek de çoğu zaman kodu düzeltmek kadar iş olur. Bu yüzden pratikte yorumlar genellikle yalana dönüşmeyi bekleyen şeylerdir. Sonunda yorumla kod birbirinden sapar; bu da yorumsuz koddan bile daha kötü olabilir
Bunun yerine niyeti gösteren otomatik testler daha iyidir. Testler genel olarak yalan söyleyemez; aksi halde zaten birleştirilmemiş olurdu. Kodun nasıl kullanılmasının amaçlandığını gösteren iyi bir test kümesi varsa, hem açıklayıcıdır hem de neredeyse doğru olduğu garanti edildiği için görmek isterim
5 hafta sonra tekrar bakmam gerektiğinde inanılmaz yardımcı oluyor
“Yorumlar gelecekteki kendime gönderilmiş bir özürdür” anlayışını izliyorum
Kod tuhaf ya da yavaşsa veya birine açıklarken “biraz derme çatma” diyeceğim bir yerse genelde yorum bırakırım. Özellikle daha önce değiştirmeyi denediysem, çalışmayan durumları ya da yaptığım düzeltmeyi vb. belgelendiririm
Bu ölçütle yaklaşırsanız gereksiz yorumlar doğal olarak ortadan kalkar ve genellikle gerçekten gerektiğinde nedenini belgelendirirsiniz. Kendi kod tabanınızda bir ay kadar deneyin; ne demek istediğimi anlarsınız