TDD (Test-Driven Development) ile LLM'nin birleşimi
- TDD, program yazmaya başlamadan önce kapsamlı birim testlerinin önce yazıldığı bir geliştirme metodolojisidir
- Testler fiilen bir spesifikasyon görevi gördüğü için, sonunda tüm testler geçerse kodun doğruluğu bir ölçüde kanıtlanmış olur
- Geleneksel olarak TDD, üretkenliği düşürdüğü veya verimsiz olduğu gerekçesiyle eleştirilmiştir
- Ancak LLM'lerin ortaya çıkmasıyla test yazma ve kodu tekrar tekrar düzeltme süreci çok daha kolay hale gelmiştir
LLM'yi normalde nasıl kullanıyorum
- Github Copilot gibi araçları aktif biçimde kullanıyordum
- LLM'ler tekrar eden kalıpları bulma ve sonraki birkaç satırı otomatik tamamlama konusunda başarılıdır; ancak sorunun tamamını derinlemesine anlayıp bütünlüklü bir modülü tek seferde üretmekte çoğu zaman zorlanırlar
- Problem çözümü için gereken bağlamı fazla verirseniz modelin konudan sapması kolaylaşır
- Gerektiğinde bilgiyi (örneğin hata çıktısı gibi) yalnızca kısmen vererek ilerlediğinizde, model hata ayıklamada da çok iyi yardımcı olur
- IDE, terminal ve sohbet arayüzü arasında sürekli kopyala-yapıştır yapmanın sürtünme yarattığını hissettim
Bunu otomatikleştirebilir miyiz?
- Bu süreci otomatikleştirmek için doğrudan event loop kavramını devreye aldım
- İlk prompt'ta implemente edilecek fonksiyonun spesifikasyonu ve fonksiyon imzası belirtilirse, model birim testlerini ve kodun ilk taslağını sunar
- Bu kod
sandbox dizinine kaydedilir ve otomatik olarak go test çalıştırılır
- Test başarısız olursa, ikinci (yinelemeli) prompt'a mevcut kod ile test sonuçları (derleme hataları veya başarısızlık bilgisi) birlikte gönderilir
- Model buna dayanarak düzeltilmiş testleri ve implementasyon kodunu yeniden önerir
- Tüm testler geçene kadar bu süreç tekrarlanır
- Bu yaklaşım, bağlamı aşırı biriktirmeden kademeli iyileştirme yapılmasını mümkün kılar
- Model aynı test senaryosunda tekrar tekrar başarısız olabilir; böyle durumlarda insanın sorunun bulunduğu kısmı doğrudan işaret edip ipucu vermesi gerekir
- LLM'nin ürettiği testlerin yeterince katı olup olmadığını sorgulamanız gereken bir "gözetmen eksikliği" sorunu vardır
- Kod ve testlerin aynı hatayı ya da eksik tasarımı birlikte paylaşma ihtimali vardır
- Bu nedenle insanın ek test senaryolarıyla süreci güçlendirmesi önemlidir
- Gerekirse, mutation testing gibi teknikler de AI ile denenebilir
LLM tabanlı geliştirme ve bilişsel yük (cognitive load)
- LLM ile birlikte TDD uygulandığında, bunun yalnızca genel algoritma problemlerinde değil, gerçek bağımlılıkları olan kod tabanlarında da mümkün olacağı düşünülüyor
- Ancak bunun için proje yapısının daha küçük birimlere bölünerek bakım kolaylığının artırılması ve her dizin/paketin bağımsız olarak test edilebilir olması gerekir
- Her paketin, ana tip tanımlarını (
shared.go), belirli mantığı üstlenen dosyaları (x.go) ve testleri (x_test.go) ayıracak şekilde düzenlenmesi; böylece bilişsel yükün azaltılması önerilir
- AI kullanılırken tüm kodu her seferinde modele vermek yerine yalnızca belirli bölümlerin seçici biçimde eklenmesi, modelin odaklanmasına yardımcı olur
- Bu da test kapsamını artırırken modüller arası bağımlılığı azaltır ve uzun vadeli bakım açısından avantaj sağlar
- Büyük projelerde bile küçük ve net birimlere bölünmüş; her birimin mantığını zengin biçimde taşıyan ama kapsamı en aza indiren bir yapı hedeflenir
Sonuç
- AI'nin gelişim hızını düşününce, yarın bambaşka bir mimarinin ortaya çıkıp LLM'nin sınırlarını aşması mümkün olabilir
- Bu nedenle 100 bin satırı aşan büyük legacy kodu aniden refactor etmeye çalışmak yerine, küçük ölçekten başlayarak TDD ile LLM'nin birlikte nasıl çalışabileceğini keşfetmek önerilir
- TDD ile LLM'nin birleşiminin, hem otomatik kod üretimi hem de test kalitesi yönetimi açısından olumlu değişiklikler getirmesi bekleniyor
5 yorum
Diğer geliştirici odaklı yapay zeka hizmetlerinin hangi pipeline'ı kullandığını ister istemez uzun uzun düşündürüyor.
(Böyle şeylere bakınca) birazdan sanki eğlence ve kâr uğruna beyne elektrik uyarı hatları yerleştireceklermiş gibi geliyor.
Test kodu eklemek iyi bir şey gibi görünüyor ama bu kişinin yaptığı programın pek bir avantajı yok gibi.
cline ya da aider'da da komut satırını çalıştırıp sonucu almak mümkün olduğu için, diğer kullanım kolaylıklarını düşündüğümüzde o programda sadece prompt'ları iyi kullanmak daha mantıklı gibi görünüyor
Builder.io'nun yaptığı micro-agent da benzer bir yaklaşım. https://github.com/BuilderIO/micro-agent Ben de LLM ve TDD'yi birkaç kez denedim; design system gibi konularda soyutlamayı da iyi yapmak gerekiyor. Convention ve pattern'lerin de iyi oturmuş olması lazım. Test case'leri ise genelde kendim yazıyorum. (İnsan diliyle olsa bile?) En önemlisi, bu yazıda da dendiği gibi, düşük coupling ve yüksek cohesion'a sahip modülleri iyi tasarlamak gerekiyor ki sınırlı context window'a bağlamı sığdırabilsin.
LLM küçük kapsamlı kodları iyi inceleyebiliyor, ancak genel tasarım ve büyük resim konusunda hâlâ biraz yetersiz kalıyor.
Bunu TDD ile birleştirip adım adım iyileştirme yöntemi bana iyi bir yaklaşım gibi görünüyor.