Yapay zeka ile eski kodu refactor etmek, kod tabanının kimsenin tam anlamadığı kısmını çok hızlı ve kendinden çok emin bir çalışana teslim etmek demek. Bu iyi gidebilir. Ajanlar 3.000 satırlık dosyalara sabırlıdır, bir fonksiyonu iki yüz yerde yeniden adlandırmaktan sıkılmaz, eski kodu iç çekmeden okur. Kötü de gidebilir: bir yuvarlama kuralını değiştiren bir “temizlik”, kimsenin belgelemediği bir yan etkinin kaybolması ya da incelenmesi imkânsız bir baştan yazıma dönüşen bir değişiklik.
Bu rehber ilk sonuç hakkında. İlk değişiklikten önce güvenlik ağını nasıl kuracağını, her adımı nasıl küçük ve geri alınabilir tutacağını, JavaScript’ten TypeScript’e geçiş ya da framework yükseltmesi gibi taşımaları nasıl yürüteceğini ve ajanın yaptığını nasıl inceleyip geri alacağını anlatıyor.
Eski kod ajanlar için de neden zor?
Eski kod (legacy kod), değiştirmeye çekindiğin koddur; çoğunlukla az testi ve çok yazılmamış kuralı olduğu için. İnsanlar için zor kılan şeyler ajan için de zor kılar:
- Davranış tuhaf yerlerde yaşar. Bir yardımcıdaki tarih biçimi, bir dekoratördeki yeniden deneme, başka bir yerin okuduğu global bir değişken.
- Bazı hatalar aslında özelliktir. Aşağı akıştaki bir sistem yanlış bir değere bağımlı olabilir. Onu “düzeltmek” hiç görmediğin bir entegrasyonu bozar.
- Ölü kod canlı, canlı kod ölü görünür. Reflection, string üzerinden çağrılar, cron işleri ve şablonlar, hiçbir aramanın bulamadığı fonksiyonları çağırır.
- Bağlam penceresi sınırlıdır. Ajan okuduğu dosyaları görür. Bu modülü içe aktaran, başka bir depodaki toplu işi bilemez.
Ajanın burada tehlikeli bir alışkanlığı daha var: işleri iyileştirir. Bir fonksiyonu çıkarmasını istersin; fark ettiği uç durumu da düzeltebilir, değişkenleri yeniden adlandırabilir, sözdizimini modernleştirebilir. Her değişiklik tek başına iyi olabilir. Hepsi bir arada, neyin değişmesinin amaçlandığını ayırt edemediğin bir diff çıkarır.
1. adım: önce güvenlik ağını kur
Önemsediğin davranış testlerle sabitlenmeden ajanın canlı koddan tek bir satırı değiştirmesine izin verme. Eski kod için bu, karakterizasyon testleri demektir: kodun ne yapması gerektiğini değil, şu anda ne yaptığını kaydeden testler.
İşe yarayan bir istem:
src/altındaki hiçbir kodu değiştirme.src/orders/pricing.jsiçin mevcut davranışını kaydeden karakterizasyon testleri yaz; yanlış görünenler dahil. Hata yolları dahil bulabildiğin her dalı kapsa. Davranış bir hata gibi görünüyorsa test mevcut çıktıyı doğrulasın veSUSPICIOUS:ile başlayan bir yorum ekle. Testleri çalıştır ve geçtiklerini göster.
Birkaç ipucu:
- Herkese açık yüzeyden test et. Modülü uygulamanın geri kalanı gibi çağıran testler refactor’den sağ çıkar. Özel yardımcılara uzanan testler, onları taşıdığında kırılır.
- Gerçek girdiler kullan. Loglardan alınmış (kişisel veriden arındırılmış) örnek yükler, fixture dosyaları ya da bir staging veritabanının kopyası, tuhaf durumları uydurma girdilerden çok daha iyi kapsar.
- Altın dosyalar burada uygundur. Bir rapor üreticisi ya da dışa aktarım için çıktının tamamını kaydedip karşılaştırmak, çıktı deterministik olduğu sürece hızlı ve dürüst bir karakterizasyon testidir.
- Testlerin kalabildiğini kontrol et. Kodu birkaç yerde elle boz ya da modülde bir mutasyon testi aracı çalıştır. Testler yeşil kalıyorsa ağda delikler var.
Karakterizasyon testlerini, kapsamı ve mutasyon testini yapay zeka ile test yazmak rehberinde daha ayrıntılı anlattım.
SUSPICIOUS: notları değerlidir. Bunlar daha sonra, bilerek, kendi commit’lerinde ve birinin yeni davranışın doğru olduğuna karar vermesiyle düzelteceğin hatalardır.
2. adım: küçük ve geri alınabilir adımlarla refactor et
Ağ kurulduktan sonra her adımı birkaç dakikada incelenecek ve başka hiçbir şeye dokunmadan geri alınabilecek kadar küçük tut.
Yapıyı davranıştan ayır
En faydalı kural: refactor commit’i yalnızca yapıyı değiştirir, davranış değişikliği kendi commit’ini alır. Ajana açıkça söyle:
Bu saf bir refactor. Davranışı değiştirme, hata düzeltme, herkese açık imzaları değiştirme. Değişmesi gereken bir şey görürsen sonunda listele.
Bir refactor commit’inde karakterizasyon testleri değişiyorsa bir şeyler yanlıştır. Bu sana kolay bir kontrol verir: git diff --stat main -- tests/ mevcut testlerde hiçbir düzenleme göstermemeli.
Her adımda tek tür değişiklik
İyi adım boyları:
- Bir fonksiyonu ya da sınıfı çıkarmak.
- Bir modülü taşıyıp import’larını güncellemek.
- Kullanımdan kalkmış bir API’yi kod tabanının tamamında değiştirmek.
- Eski ve yeni kodun yan yana yaşayabilmesi için bir sınırda tek bir arayüz tanıtmak.
Ajandan her adımdan sonra testleri çalıştırmasını ve devam etmeden önce açık bir mesajla commit etmesini iste. Bir plan işe yarar: “Refactor’ü, her biri testleri yeşil bırakan numaralı adımlar olarak öner. Başlamadan önce onayımı bekle.” Çoğu kodlama ajanının bunun için bir planlama modu vardır; örneğin Claude Code’un plan modu düzenleme yapmadan inceler ve öneri sunar.
Baştan yazma, sarmala
Gerçekten değişmesi gereken bir kısım için yeni uygulamayı bir arayüzün ya da bayrağın arkasında eskisinin yanına koy, çağıranları tek tek taşı ve eski kodu artık hiçbir şey kullanmadığında sil. Buna strangler fig (boğan incir) deseni denir. Tek bir riskli geçişi pek çok küçük ve sıkıcı geçişe çevirir; ajanlar da sıkıcı işte iyidir.
3. adım: ajanlarla taşımalar
Taşımalar ajanların en çok zaman kazandırdığı yerdir, çünkü iş geniş ve tekrarlıdır. Diff’lerin devleştiği yer de burasıdır. İşin püf noktası, mekanik kısmı araçlara, karar gerektiren kısmı ajana bırakmaktır.
JavaScript’ten TypeScript’e
Uygulamayı baştan sona çalışır tutan bir yol:
- TypeScript’i JavaScript’in yanına ekle.
tsconfig.jsoniçindeallowJs: trueayarla ki.jsve.tsdosyaları bir arada yaşasın; tip kontrolü olarak CI’danpx tsc --noEmitçalıştır. - Gevşek başla.
strict: falseile başla. İstersencheckJs’i aç ya da tek tek JS dosyalarına// @ts-checkekleyerek dosyaları yeniden adlandırmadan önce sorunları bul. - Önce yaprak modülleri çevir. İçeriden hiçbir şey import etmeyen dosyalar, yani yardımcılar ve sabitler, en kolayıdır. Sonra giriş noktalarına doğru yukarı çık.
- Her adımda bir klasör. Ajandan
src/utils/klasörünü.ts’e çevirmesini, tipleri eklemesini, testleri yeşil tutmasını vetsc --noEmit’i geçirmesini iste. Sonra sıradaki klasör. - Yavaş yavaş sıkılaştır. Her şey
.tsoluncanoImplicitAny’yi, sonrastrictNullChecks’i, sonra tamstrict’i aç; arada hataları düzelt.
Ajana verilecek iki kural: nedenini açıklayan bir yorum olmadan any yok, hataları susturmak için @ts-ignore yok. Yoksa derleyiciyi yeşile çevirmenin en hızlı yolu, onu satır satır kapatmaktır.
Framework ve kütüphane yükseltmeleri
Büyük bir sürüm yükseltmesinde sıra önemlidir:
- Önce taşıma kılavuzunu oku. Ajana resmi yükseltme kılavuzunu özetlet ve kodunu etkileyen kırıcı değişiklikleri dosya yollarıyla listelet. Bu salt okunur bir adımdır.
- Varsa resmi codemod’u çalıştır. Pek çok proje codemod yayımlar; örneğin Next.js için
npx @next/codemod, Java tarafında birçok yükseltme için OpenRewrite tarifleri. Codemod deterministiktir, ajan değildir. Codemod’un yapabildiğini ona bırak. - Kalanı ajana bırak. Codemod’un halledemediği durumlar, özel sarmalayıcılar, eski davranışa dayanan testler.
- Her seferinde bir büyük sürüm atla. 3’ten 6’ya tek sıçrayış, bütün kırıcı değişiklikleri tek bir diff’e yığar.
Beklenen sonucu istemine sabitle: “derleme geçiyor, test takımı geçiyor, konsolda yeni uyarı yok”. Belirsiz bir “en son sürüme yükselt”, ajanı yol üstünde beş paketi daha yükseltmeye davet eder.
4. adım: işi worktree’lerle yalıt
Uzun bir refactor ana çalışma klasöründe durmamalı, paralel adımlar da aynı klasörü paylaşmamalı. Bir git worktree her adıma kendi dalını ve klasörünü verir:
git worktree add ../app-ts-utils -b refactor/ts-utils
git worktree add ../app-ts-api -b refactor/ts-api
Artık bir ajan utils’i, diğeri api’yi çevirir; sen de ana klasörde çalışmaya devam edersin. Bir adım bitip incelendiğinde birleştir; bir yere varmazsa worktree’yi ve dalı kaldır. Ayrıntısı git worktree ile paralel geliştirme yazısında.
Aynı dosyalara dokunan paralel adımlarda dikkatli ol. Aynı modülde bir şeyleri yeniden adlandıran iki ajan çakışma üretir ve refactor’de çakışma çözümü, davranışın içeri sızdığı yerdir. İşi değişiklik türüne göre değil, klasöre ya da modüle göre böl.
5. adım: her adımı incele
Bir refactor diff’ini onaylamak kolaydır, çünkü hiçbir şey yapmıyor gibi görünür. Tam da bu yüzden okursun. Neye bakmalı:
- Testler değişti mi? Saf bir refactor’de mevcut testler değişmemeli.
- Herkese açık imzalar değişti mi? Dışa aktarılan fonksiyonlar, API yanıtları, veritabanı sütunları, olay adları.
- Bir şey silindi mi? Ajana silinen her fonksiyonun neden kullanılmadığını sor. Reflection ya da string ile çağrı varken “referans bulunamadı” kanıt değildir.
- Hata yönetimi değişti mi? Yutulan bir istisnanın artık yukarı fırlaması ya da tersi, bir davranış değişikliğidir.
- Diff adımın ötesine taştı mı? “Bu modülü taşı” adımı yirmi başka dosyayı da yeniden biçimlendirmemeli. Biçimlendirmeyi kendi commit’ine al ya da hiç yapma.
Her turu inceleyen ikinci bir model bunların epey bir kısmını yakalar. Nasıl çalıştığı için bkz. yapay zeka ile kod incelemesi.
6. adım: geri dönüşü ihtiyacın olmadan planla
Hazırlarsan geri dönüş ucuzdur:
- Küçük commit’ler.
git revert <sha>tek bir adımı temizce kaldırır. 4.000 satırlık bir commit ancak bütün olarak geri alınır. - Yeniden yazma, revert et. Bir şey ana dala girdiyse paylaşılan geçmişin üstüne force push yapmak yerine commit’i ya da birleştirmeyi revert et.
- Bir şey kaçtıysa bisect. Küçük ve yeşil commit’lerle
git bisect, davranışı bozan adımı birkaç çalıştırmada bulur. - Riskli geçişler için bayrak. Eski ve yeni kod yan yana yaşarken bir bayrak yeni yolu deploy gerekmeden kapatır.
- Oturum içinde geri alma. Daha hiçbir şey commit edilmeden ajanın son turunu geri alabilirsin; bkz. Claude Code değişikliklerini geri alma.
Sık yapılan hatalar
- Ortada test yokken “bu modülü refactor et”. Bir baştan yazım alırsın ve kontrol etmenin yolu yoktur.
- Refactor ile hata düzeltmeyi karıştırmak. Davranış değiştiğinde bunun amaçlanıp amaçlanmadığını bilemezsin.
- Tek dev bir taşıma dalı. Ana daldan uzaklaşır, çakışmalar birikir ve kimse inceleyemez.
- “Kullanılmıyor”a güvenmek. Arama dinamik çağrıları, başka depoları ve zamanlanmış işleri görmez.
- Ajanın derleyiciyi susturmasına izin vermek.
any,@ts-ignoreve kapatılmış lint kuralları işi yapmaz, saklar. - Paralel adımları birlikte test etmeden birleştirmek. Tek başına yeşil iki dal birleşince kırmızı olabilir; birleştirme kuyruğu bunun içindir.
AgentVera’da nasıl yapılır?
AgentVera kodlama ajanı CLI’larını proje başına, git yerleşik olarak yan yana çalıştırır; bu da eski kod refactor’ünün adım adım ilerleyen yapısına uyar.
- Her adıma bir worktree. Worktree panelinden her adım için bir dal ve klasör aç, ajanı doğrudan orada başlat; birinde Claude Code, diğerinde Codex ya da Gemini CLI. Ana klasörün olduğu gibi kalır.
- Her tur için Turlar. Her turun başında çalışma klasörünün anlık görüntüsü gizli bir git ref’ine alınır ve ajan başına son 60 tur saklanır. Bir turun hangi dosyaları değiştirdiğini gör, ajan fazla ileri gittiyse yalnızca o turu geri al.
- Her turun sonunda inceleme. Otomatik kod incelemesi, ajanın yazdığı kodu seçtiğin Claude modeliyle okur ve bulguları önem derecesi ve dosya:satır ile listeler; istersen bulgular ajana geri gider, arka arkaya en fazla iki tur.
- Kriterlerine göre Verify. Mesajına “saf refactor, tüm testler geçiyor, mevcut hiçbir test dosyası değişmedi” yaz. Verify bunu kriterlere çevirir; tur bitince dosya düzenleyemeyen ayrı bir doğrulayıcı testleri çalıştırır ve her kriteri kanıtıyla işaretler.
- Paralel adımlar için birleştirme kuyruğu. Dallar tek tek hedefin en güncel haline birleştirilir ve kontrol komutu birleşmiş sonuçta çalışır. Yeşil bir dal varsayılan olarak senin onayını bekler.
- Büyük taşımalar için paralel ekip. Bağımsız parçalara ayrılan bir taşımada paralel ekip her parçayı kendi worktree’sinde çalıştırır, biten parçaları bir entegrasyon dalında birleştirir ve son kontrolü çalıştırır; sen de tek bir pull request incelersin.
- Uygulamadan çıkmadan git. Commit yöneticisi, diff’ler ve grafik geçmiş sağ paneldedir; her adımı incelemek ve birini revert etmek hızlıdır.
Sonuç
Yapay zeka eski kodu değiştirmeyi güvenli kılmaz; bunu testler ve küçük adımlar yapar. Yapay zekanın değiştirdiği şey bu adımların maliyetidir. Karakterizasyon testleri yazmak, bir klasörü TypeScript’e çevirmek ya da bir codemod çalıştırıp arkasını toplamak, eskiden kimsenin vakit bulamadığı işti. Ajanlarla ucuz; bu yüzden işi doğru yapmayı göze alabilirsin: önce ağ, her seferinde tek değişiklik, her adım incelenmiş, her adım geri alınabilir.
Daha fazlası için:
AgentVera’yı denemek için ana sayfaya göz at.