1 puan yazan GN⁺ 2025-09-09 | 4 yorum | WhatsApp'ta paylaş
  • Geçmişte Ada geliştirme ortamı, kod biçimlendirme sorununu zaten çözmüş bir deneyime sahipti
  • Geliştiriciler kodu DIANA ara gösterimi (IR) biçiminde ele alıyor ve herkes kendi istediği pretty-printing ayarlarıyla görüntülüyordu
  • Günümüzde de linter ya da biçimlendirme politikaları nedeniyle tekrarlanan verimsizlikler ve tartışmalar sürüyor
  • O dönemin Rational R1000 iş istasyonu, yenilikçi geliştirme ortamı ve özellikler sunuyordu
  • Yazı, kod biçimlendirme sorununda bir nesil önceki yaklaşımdan yararlanarak bugünün geliştirme pratiklerini değiştirecek fikirler öneriyor

Kod biçimlendirme tartışması – 1980'lerin çözümü

  • Yazar, lise yıllarında Ada derleyicisi üzerinde çalışan bilgisayar bilimi öğretmeni Mr. Paige ile yaşadığı deneyimden söz ediyor
  • 2016'da linter aracı ayarlarından duyduğu rahatsızlığı dile getirip “neden hâlâ böyle sorunlar yaşıyoruz?” diye sorduğunda, bu sorunun aslında 40 yılı aşkın süre önce çözüldüğünü öğreniyor

Ada ve DIANA'nın ortaya çıkışı

  • Ada geliştiricileri metin kaynak kodu saklamak yerine, DIANA (Descriptive Intermediate Attributed Notation for Ada) adlı bir ara gösterim kullanıyordu
  • Her geliştirici, kaynağı kendi pretty-printing ayarlarıyla istediği biçimde görüntüleyebiliyordu
  • Biçimlendirme tartışmaları ya da linter sorunları yoktu; editörde program ağacı doğrudan düzenlenebiliyordu (modern projectional editing yaklaşımına benzer)

Rational R1000 – öncü bir geliştirme ortamı

  • Rational R1000 iş istasyonu, artımlı derleme, statik analiz, sürüm kontrolü, hata ayıklama gibi çeşitli gelişmiş özellikleri yerleşik olarak sunuyordu
  • DoD gibi devlet projelerinde, Uluslararası Uzay İstasyonu'nda (ISS), F-22 savaş uçağı gibi kritik yazılım geliştirme çalışmalarında kullanıldı ve UML'nin doğuşuna da katkı sağladı
  • Grady Booch'a göre R1000, DIANA tabanlı bir makineydi; kaynak kodu saklamıyor, yalnızca DIANA ağacının pretty-printing çıktısını kullanıyordu

DIANA tabanlı geliştirmenin avantajları

  • Biçimlendirme tartışmalarına, linter ayarlarına ya da editör ortamını tek tip hale getirmeye ihtiyaç yoktu
  • Donanım hızlandırması sayesinde artımlı derleme, kolay refactoring, hızlı entegrasyon gibi yenilikçi bir geliştirme deneyimi sunuyordu
  • Geliştirme verimliliği ve büyük sistemler üzerinde çalışma açısından önemli etkiler yarattı

Günümüz için çıkarımlar

  • Donanım hızlandırmalı derleme artık daha az önemli olsa da, biçimlendirme sorununu çözme konusunda bugün hâlâ eksikler var
  • Ana akım yaklaşım projectional editing ya da canlı ortamlar olmasa da, geçmişteki bu yaklaşım gibi daha verimli ve daha az tartışmalı geliştirme pratiklerinin benimsenmesini düşünmenin zamanı gelmiş olabilir

Kaynaklar

  • Yazar, bu konuyu araştırırken R1000 ile ilgili çeşitli belge ve teknik raporlara atıfta bulunuyor

4 yorum

 
ndrgrd 2025-09-10

Bildiğim kadarıyla paylaşılan kodu ortak bir ayar üzerinden otomatik olarak biçimlendiren bir özellik zaten var ve şirketler de bunu oldukça yaygın kullanıyor.

 
euphcat 2025-09-10

Bence asıl mesele otomatik formatlama değil; belirli bir formatlamanın üstün olduğuna dair algının ya da kendi formatlamamı bırakıp yabancı bir formatlamaya uyum sağlama sürecinin baştan gereksiz olması. Çünkü mantık, formatlamaya bağlı olmayan bir ara gösterimi saklayıp ardından kullanıcının tercihine göre bunu rahat ettiği biçimde pretty-print etmek.

 
ndrgrd 2025-09-10

Aslında söylemek istediğim, otomatik biçimlendirmeyle ara temsillere gerek kalmadan mevcut dillerle aynı işi yapmanın mümkün olduğuydu; ama açıklamam yetersiz kalmış.

 
GN⁺ 2025-09-09
Hacker News görüşleri
  • İnsanların neden linter ayarlarını bu kadar dert ettiğini anlamıyorum; bu açıkça gereksiz bir tartışma. Bir tanesinde karar kılıp linter'ı otomatik çalıştırın ve bitsin. Asıl yazılım mühendisliği yapmaya ayıracağımız zaman daha önemli. Hangi format olursa olsun, ekip birinde karar kılıp kullanınca bir hafta içinde alışılıyor.
    • Kaynak kod formatter'ı ile lint programının farklı şeyler olduğuna dikkat çekiliyor; formatter yalnızca kod yerleşimini düzenler, linter ise koddaki olası bug'ları ya da hataları bulur. Bazı araçlar ikisini birden destekler ama bu bir uygulama detayıdır. Lint'in ne olduğuna dair https://en.wikipedia.org/wiki/Lint_(software) bağlantısına bakılabilir.
    • Zamanımın çoğunu kod "okuyarak" geçiriyorum ve kod yerleşimi, kodu ne kadar hızlı okuyabildiğimle ilgili. Farklı yerleşimlere alışılabilir ama bütün yerleşimler aynı derecede okunabilir değil. Kodu görsel örüntüler olarak hatırlıyorum ve yerleşime göre parçalara ayırarak okuyorum. İşin ironik tarafı, zihnimde görsel canlandırma yapamadığım aphantasia'ya sahip olmama rağmen görsel ipuçlarıyla daha iyi hatırlıyorum.
    • Bazı linter ayarlarının açık faydaları var. Örneğin tablolarda trailing comma kullanırsanız son satıra yeni öğe eklerken yalnızca tek satırı düzenlersiniz ve diff de daha sade olur. Bu yüzden kötü seçimler hayatımı zorlaştırıyor. Sıralı listeler ya da include'lar için de aynı şey geçerli; sıralamazsanız hep sona eklenir ve merge conflict daha sık çıkar. Otomatik formatter'ın avantajı gibi, sıralamayla da zaman kazanmak gerekir. Ayrıca tutarsız stillere karşı hassasım; en önemlisi tek bir stille tutarlı olmaktır.
    • Ayrıntı seçeneklerine o kadar takılmıyorum ama ortak bir linter ayarının PR'lara bakarken gereksiz gürültüyü azaltması şart. Git'in ya da çeşitli PL'lerin yalnızca satır bazlı çalışması bana pek zarif gelmiyor. Ada dili gibi daha rafine bir yaklaşım kullanan örneği 20 yıllık kariyerimde yalnızca bir kez gördüm. Gerçekten zarif ve verimli bir şey yapmak zor, hele zaten yeterince iyi alternatifler varken yaygınlaşması daha da zor.
    • Ben de gençken bu tartışmaya kapılmıştım. Çünkü ekipteki en zeki kişinin ben olduğumu sanıyordum. Görüşümün en önemli görüş olduğunu düşünüyordum. Herkesin beni dinlemesi gerektiğine inanıyordum. Ama yanılıyordum.
  • Burada dikkate alınması gereken trade-off şu: metin dışı bir format kullanırsanız grep, diff, sed, sürüm kontrolü gibi genel amaçlı araçların kullanışlılığı azalır. Sonuçta özel araçlara, formatlara ya da IDE eklentilerine daha bağımlı hale gelirsiniz. Unix felsefesinin gücü plain text'in birleştirilebilirliğinden gelir. Bu tartışmayı kolayca kesen bir soru var: Editörde yalnızca ilk boşluk genişliği serbestçe ayarlanabilseydi, sekmeyi tercih edenlerin elinde başka ne argüman kalırdı?
    • Metin tabanlı yaklaşımın avantajları var ama biraz aşağı inip çok daha yüksek bir dağa, yani projectional editing'e tırmanabilecekken tabanda oyalanıp kaldığımızı düşünüyorum. Verilen örneklerin hepsi yapısal bilgi içeren kodlarda daha iyi çalışıyor: örneğin sembol arama için metin grep'inden çok daha sık ast-grep kullanılabilir; diff için semanticdiff.com gibi araçlar yapısal taşınmaları ya da anlamsız değişiklikleri yok sayabilir. sed alternatifi olarak @codemod/cli kullanılabilir. Sürüm kontrolünde de Unison gibi dillerde sıra, boşluk gibi anlam taşımayan değişikliklerden doğan conflict'leri otomatik önleme konusunda çok sayıda deney yapıldı.
    • Bu fikir tekrar tekrar ortaya çıkıyor ama basitçe formatter'ı bir kez çalıştırmak yerine son derece karmaşık araçlar gerektirmesi yüzünden maliyet/fayda açısından pek iyi değil. Her geliştiricinin her şeyi kendi zevkine göre görmesinin pratikte büyük bir anlamı yok. Birlikte çalıştığım tüm ekiplerde ortak kurallar belirleyip formatter ile zorunlu kıldık; başta herkes aynı fikirde olmasa da kısa sürede alışılıyor. Formatting tartışmaları tam bir zaman kaybı örneği.
    • grep, diff, sed ve satır tabanlı merge araçları aslında kod üzerinde işlem yapmak için kötü araçlar. Bu tartışmadan çok, daha iyi araçları düşünmek gerekir.
    • Intermediate Representation'ı metin olarak tutarsanız grep/diff/sed'in hepsi çalışabilir. Yalnızca AST tabanlı bir formatter kullanılsaydı, kod belirli bir AST'ye uygun normalize edilmiş biçimde saklanırdı; editör AST'yi parse edip kullanıcıya istediği formatta gösterir, kaydederken de yeniden normalize edilmiş biçime çevirirdi.
    • Tüm işletim sistemi bu tür kaynak dosyalara dayanarak üretildi. Unix felsefesi de ancak tüm araçlar plain text'i esas alıp onu parse etmeyi bildiğinde gerçekten parlar.
  • Kaynak kod formatting'inde tipografik bir boyut da kesinlikle var diye düşünüyorum. Bunun tamamen kişisel tercih olduğu iddiasına katılmıyorum. Bazı formatting biçimleri anlamı ve yapıyı etkili biçimde ileten araçlardır. Otomasyon araçlarıyla yalnızca minimum token'ları serialize edip sonra geri yüklediğinizde bu değer kaybolur. https://naildrivin5.com/blog/2013/05/17/source-code-typograp...
    • Baskı uzmanları tabloların ve formüllerin boşluklarıyla, hizalarıyla uzun zamandır özenle uğraşıyor. Dışarıdan bakanlar bunu çok fark etmese de bu detaylar son derece önemliydi. Kaynak kodun daha incelikli biçimde formatlanması yönünde de ilerleme olabileceğini düşünüyorum.
    • Örneğin Python'un black formatter'ı için, SQLAlchemy sorgularını gereğinden fazla satıra bölerek okunabilirliği düşürdüğü yönünde şikayetler var.
    • Kod tipografisinin önemini neden bu kadar çok insanın fark etmediğine hep şaşmışımdır.
    • Tipografiye önem verip bir yandan da programlama dili geleneklerini eleştirmeden takip etmek bana en yanlış yön gibi geliyor; örneğin register gibi sözcükleri memnuniyetle kullanan bir kültür varken pointer'ların yıldız işaretiyle (*) gösterilmesi gibi gelenekler var. Oysa her gösterim daha sezgisel ve daha açık olabilirken, insanlar inatla karmaşık ve ayırt etmesi zor yöntemlere bağlı kalıyor. Simgeler ya da reserved keyword'ler de daha tanıdık ve doğal terimlerle değiştirilebilirdi ama geleneksel/mevcut kabullere aşırı bağlılık yüzünden okunabilirlikten ödün verildiğini düşünüyorum. Örnek olarak C kodundaki strcpy fonksiyonunun daha açık ve daha okunaklı terimler ve sözdizimiyle baştan kurgulanabileceği anlatılıyor.
    • C'de parameter bildirimlerinin modifier'lar, veri tipi ve isimden oluştuğu açıklandıktan sonra char *argv[] gibi örneklerle karmaşık bildirimlerin okunabilirlik sorunu eleştiriliyor. Ayrıca C++ tarzı formatting'in (char* a, b gibi) yanlış anlamaya yol açabileceği, bu yüzden bu tarzın kaçınılması gereken bir yaklaşım olduğu söyleniyor.
  • Bu tartışmanın öncülüne katılmıyorum. Kod formatting'i son derece önemli bir iletişim aracıdır. İyi formatting, geliştiricinin (1) formatting'in önemini bildiğini, (2) kurallara iyi uyduğunu, (3) iyi zevke sahip olduğunu ve (4) istisnai durumlarda doğru karar verebildiğini gösteren bir sinyal işlevi görür. Bu dört özellik, basit formatting'in ötesinde, genel geliştirme yetkinliğini etkileyen önemli becerilerdir. Ama autoformatter'lar ya da linter kuralları bu sinyali zayıflatıyor ve Goodhart yasasında olduğu gibi asıl amacı boşa çıkarma sorunu doğuruyor.
    • Blog yazısının kısa ve basit olduğu, bu yüzden mutlaka doğrudan okunması gerektiği söyleniyor; yalnızca başlığa bakıp anında tepki vermek yerine should ve unnecessary kelimelerinin bağlamını anlamak faydalı olur.
    • Formatting'e kayıtsız olan birinin ya (1) birden fazla kişinin aynı dosyayı düzenlediği bir deneyimi yoktur, ya (2) branch merge yapmamıştır, ya (3) büyük bir codebase bakımında bulunmamıştır, ya (4) büyük ölçekli refactoring deneyimi olmamıştır, ya (5) kod geçmişini keşfetmemiş ya da diff/karşılaştırma araçlarını kullanmamıştır, ya (6) codebase otomasyon araçları geliştirmemiştir, ya da (7) işbirliği bilinci olmadan yalnızca kendine odaklanan bir çalışma tarzına sahiptir diye düşünüyor.
    • Bu maddelerin hepsine cevap "hayır" ise, pass/commit sırasında formatting'i otomatikleştirmek ve otomasyon devreye girmediyse CI'da hata almak bence yeterli. Ayrıntılara saplanmaktansa varsayılanlara uymak ve kişisel stilden vazgeçmek aslında bir avantaj da olabilir. Varsayılanlar korunursa kodu gören herkes için tanıdık görünür. Ayrıca formatting ile linting farklı şeyler olsa da ikisi de otomasyon araçlarıyla tek seferde çözülebilir.
    • Aynı değerlendirmeyi el yazısı üzerinden de öğrenebileceğimizi söyleyip, şaka yollu bundan sonra PR'ların el yazısıyla gönderilmesi gerektiğini ekliyor.
    • "İyi formatting kurallarını seçebilecek zevke" güvenmek daha çok tartışma doğurur ve zaman kaybettirir; Go ve Rust'ta olduğu gibi yerleşik formatter'a bırakmak daha iyi olur.
  • Kodun sözdizimi ağacı tabanlı saklanıp insanların gördüğü şeyin onun render edilmiş hali olması yönündeki girişimler 20-25 yıl öncesine gidiyor. Bu akım, refactoring'in ilk popüler olduğu 90'lı yıllardan beri var. Visual Age gibi IDE'ler dosya sistemi yerine kodu veritabanında saklayan bir model benimsemişti. intentional programming ya da model tabanlı geliştirme de bu döngünün parçası. Refactoring'in özü AST dönüşümüdür; symbol adı değiştirme çok kolaydır ve doğrudan kaynak kodda bul-değiştir yapmaya gerek kalmaz. Ama insanlar hâlâ dosya düzenlemeye alışkın ve yapının kendisini saklama yaklaşımının yaygınlaşmasına karşı ciddi direnç ve sürtünme var. Bunca zamandan sonra formatting tartışmalarının sürmesi de bu alternatifin gerekliliğini gösteriyor. Dil ya da editör seviyesinde sağlam bir symbol rename bile çoğu zaman düzgün sunulamıyor.
    • Bunun soyutlama katmanlarını karıştırmak olduğu söyleniyor. AST de sonuçta bir dosyada saklanmak zorunda; dolayısıyla insanın okuyabildiği dosya üzerinde AST-aware araçlar çalıştırmakla çok büyük bir fark yok. Saklama biçimi o kadar önemli değil, asıl mesele daha akıllı araçlar. Örnek olarak Microsoft'un Roslyn'i ve modern derleyicilerin API üzerinden codebase ile etkileşime girme yönelimi veriliyor.
  • Bazı formatting türlerinin yalnızca AST'den türetilemeyeceğine dair doğrudan örnek veriliyor. Mesela birden fazla assignment satırı olduğunda, üç satırın aynı sütuna hizalanması mı, = işaretine göre hizalanması mı, yoksa yapının derinliğini daha görünür kılmak için girintiyle tab eklenmesi mi seçileceği farklı sonuçlar doğurur. Değerin kendisini vurgulamak isterseniz sayıları sağa hizalayabilirsiniz; yapıyı vurgulamak isterseniz member değişkenlerini gözle daha rahat izlenecek şekilde hizalayabilirsiniz. Yazarın vurgulamak istediği kod boyutu değişebilir. Ek metadata olmadan bu bilgi AST'den çıkarılamaz deniyor.
    • Ne denmek istendiğini anlıyorum ama pratikte ilk iki yöntem dışında bir şey kullanmıyoruz. Gerçek amaç vurgudan çok okunabilirlikti. AST'ye dönüştürürken kayıplar var ama bu düzeydeyse kazanımın çok daha fazla olduğunu düşünüyorum. Ayrıca vurguyu AST içinde koruyacak varyasyonlar da gayet mümkün; örneğin setValue([bar, glob], 1) gibi yapılarla ya da stil override için yorum sözdizimiyle çeşitli çözümler uygulanabilir.
    • "Arzu edilen kod formatting'i" nihayetinde özneldir; örnekte olduğu gibi biri 2/4/8 boşluk, başka biri sütun hizası tercih edebilir. AST kaynak kodun formatting bilgisini taşımaz, dolayısıyla otomatik olarak çıkarmak mümkün değildir.
    • İkinci ve üçüncü formatting örnekleri aslında yapısal tasarım problemi, yani Law of Demeter ihlali; formatting kapsamına bile girmiyor.
  • Projectional Editing, metin tabanlı kaynak kod için de uygulanabilir. JetBrains MPS'te koddan tablo render etme örneğini gösteren bir video da var: https://www.youtube.com/watch?v=XolJx4GfMmg&t=63s. IDE'nin dictionary'yi tablo olarak render etmesini isteyenler var. Bugün bile code folding, inlay hints, HTML olarak render edilen docstring'ler gibi benzer özelliklerin bir kısmı mevcut: https://x.com/efortis/status/1922427544470438381
  • Plain text'ten daha soyut bir şeyi şu anda doğrudan kabullenemememizi bir sınır olarak tanımlıyor. Denediğimizde bile sonunda yine plain text projection'a geri düşüyoruz. Morse Code'dan Unicode'a uzanan birikimli "dev bir lookup table" kültürünün bugünkü sembol çözümleme alışkanlığını yarattığını düşünüyor. Soyutlama düzeyi yükseldikçe uygulamaya daha uygun sembol kümeleri üretilebiliyor ama buna uygun araçlar ortaya çıkmıyor. Sonunda her şey yine metin olarak taşınıp parse ediliyor (CSV veya Markdown gibi). XML için de özel editörler çıkıyor ama insanlar sonunda yine plain text düzenlemek istiyor. Yine de karakter encoding sorunları ve özel karakterler yüzünden bu durum tamamen olumlu da değil.
  • Kaydedilen artifact ile ekranda gördüğümüz kod projection'ının neden aynı şey olmak zorunda olduğunu sık sık sorguluyorum. Hatta git diff'i bile IR projection'ı üzerinden görmek güzel olurdu. treesitter gibi AST araçlarının ortaya çıkması sayesinde insanların AST ya da IR ile daha verimli çalışabileceği arayüzleri hayal etmeye başladık. Örneğin F#'ın ordered compilation yapısı code review'yu basitleştirmeye yardımcı oluyor. Buna karşılık serbest sıralamaya izin veren dillerde ya da yapılarda, küçük bir diff'i incelemek için bile değişimin tam bağlamını anlamak üzere birden fazla yere gidip gelmek gerekiyor.
  • eslint-config-airbnb ile ilgili rahatsız edici deneyimini paylaşıyor. Temsilî sorunlar: #1271, #1122. Mevcut bir projeye airbnb config uygulamaya çalışırken bir saatten fazla boş yere uğraştığını, kod zaten kusursuzken gereksiz kurallar yüzünden üretkenliğinin düştüğünü söylüyor. Sonunda yalnızca ilgili kuralları yerelde kapatmış ve daha sonra hiçbir projede bir daha kullanmamış. Bu örnek, kötü lint kurallarının üretkenliği ne kadar bozabildiğini gösteriyor.