Bina açıkken temeli değiştirmek
Titus Winters on yılı aşkın süre Google’da çalıştı. Google’ın C++ kütüphanelerini açık kaynak yapan Abseil projesini kurdu, okunabilirlik (readability) programını yönetti. Şimdi Adobe’de geliştirici deneyimi üzerine çalışıyor. The Pragmatic Engineer’daki uzun sohbetin en somut kısmı, Abseil’in arkasındaki temizlik işi.
Fikir şuydu: Google’daki her şeyin üstüne kurulduğu temel C++ parçalarını (string işlemleri, konteynerler, komut satırı bayrakları gibi) açık kaynak yapmadan önce temizlemek. O dönem kod tabanı yaklaşık 250 milyon satır C++’tı ve ayda 10 bin civarı mühendis üzerinde değişiklik yapıyordu. Winters bunu “Empire State Binası’nın temelini değiştirmek, ama binayı kapatmadan ve trafiği durdurmadan” diye anlatıyor. 10–12 kişilik bir ekip bu işe tam zamanlı çalıştı.
Nasıl yaptılar?
1. Metin değil, sözdizimi ağacı. Değiştirilecek bir fonksiyonun 50 bin çağrıldığı yeri arama-değiştirme ile bulamazsın. Ekip, Clang derleyicisinin kodu çözümlediği soyut sözdizimi ağacı (AST) üzerinde çalışan araçlar kullandı. Bütün kod tabanı paralel olarak çözümleniyor, “tam olarak bu fonksiyon, tam olarak bu bağlamda çağrılıyor” diye eşleştiriliyor ve her yer için düzenleme üretiliyor. Kitaptaki bölüme göre bu araçların adları ClangMR (C++), JavacFlume ve Refaster (Java). Winters’ın anlattığı bir ayrıntı da ilginç: Düzenlemeleri üretebiliyorlardı ama boşlukları doğru yere koyamıyorlardı. Otomatik C++ biçimlendirici clang-format biraz da bu ihtiyaçtan doğdu.
2. Eski ve yeni birlikte yaşasın. 20 bin dosyalık tek bir değişikliği test edip birleştirene kadar biri mutlaka bir dosyayı değiştirmiş oluyor. “Herkes bir saat dokunmasın” demek de mümkün değil. Çözüm: Değişikliği, eski ve yeni API’nin aynı anda çalışabileceği şekilde tasarlamak. Kitaptaki örnekte eski scoped_ptr önce std::unique_ptr’ın takma adı yapılmış, kullanımlar değiştirilmiş, en sonda takma ad silinmiş.
3. Parçala, ayrı ayrı test et. Büyük değişiklik, proje ve sahiplik sınırlarına göre küçük parçalara bölünüyor. Her parça kendi testlerinden geçip ayrı ayrı birleşiyor. Her şey temizlenince eski yol siliniyor. Winters’ın ifadesiyle bunu birkaç yüz kez yapınca kod tabanın çok daha iyi durumda oluyor.
Bunun bir ön şartı da vardı: Testler. Winters’a göre 2006 civarında arama ekibi düzenli sürüm çıkaramaz hâle gelince sürüm mühendisleri “testsiz değişiklik birleşmez” kuralını koymuş. Yabancı birinin kodunu güvenle değiştirebilmek ancak böyle mümkün oldu. Onun tanımıyla kod tabanın, değerli bir değişikliği güvenle yapabiliyorsan sürdürülebilir.
Bugün: Yapay zekâ aracı yazsın, araç işi yapsın
Gergely Orosz’un sorusu şuydu: Bugün böyle bir işi yapay zekâya yaptırmak çok daha kolay ama çok daha “rastgele” değil mi? Winters’ın cevabı, bu deterministik yaklaşımın zaten yaygın olduğu. Java dünyasında OpenRewrite gibi araçlarda “şu kalıbı bul, şöyle değiştir” diyen küçük tarifler (recipe) yazıyorsun. Araç bütün dosyaları tarayıp aynı dönüşümü uyguluyor, biçimlendirmeyi de bozmuyor. Winters’a göre yapay zekâ bu tarifleri yazmakta çok iyi. Sonuç daha az token, daha doğru, daha hızlı ve denetlenebilir.
Kod incelemesi için de aynı örnek konuşuluyor: Pahalı ve yavaş yapay zekâ incelemelerini arada bir çalıştır, bulduğu her sorun için ajana bir lint kuralı yazdır. Böylece bir hatayı bir kez öğreniyorsun, sonra her seferinde ücretsiz ve aynı şekilde yakalıyorsun. İnsanın dikkati de sadece gerçekten insan gerektiren kısımlara kalıyor. Bu fikrin TypeScript için hazır bir örneğini anti-slop yazımızda, ajanı kurallarla değil bariyerlerle yönetmeyi de ajanı raylarda tutmak yazısında anlattık.
Düşün
- Kod tabanında, bozacağın korkusuyla dokunmadığın bir yer var mı? Onu güvenle değiştirebilmek için ne eksik: test mi, araç mı, bilgi mi?
- Son zamanlarda yapay zekâya tekrar tekrar yaptırdığın bir işi, bir kez yazılan bir betiğe ya da lint kuralına çevirebilir misin?
Videoyu izle
Kaynaklar (4, İngilizce)
Kendi cümlelerimizle yazılmış bir özettir, çeviri değildir. Tüm kaynaklar yukarıda.