Menu

Kod İnceleme Promptları: Yapay Zekâyla Code Review

İyi bir kod inceleme promptu neye bakılacağını söyler, her bulgu için bir önem derecesi ister, somut bir hatalı girdi ve bir diff talep eder ve modele üslubu atlamasını söyler. Sonra her bulguyu kontrol edersin, çünkü bazıları yanlış olacaktır.

Bu sayfadaki her istemi düzenleyebilir, sonra ChatGPT, Claude ya da başka bir yapay zekâ uygulamasında açabilirsin.

Bir kod inceleme promptu modele neye bakacağını, her bulgunun ne kadar ciddi olduğunu ve hangi kanıtı vereceğini söylemeli. "Bu kodu incele" bir güvenlik açığının bir docstring önerisiyle bir adlandırma tercihi arasında durduğu dost canlısı bir öneri listesi getirir. Kontrol listesi, önem dereceleri ve diff isteği olan bir inceleme promptu ise bulgu bulgu üzerine harekete geçebileceğin bir rapor getirir.

"Bunu incele"den önem dereceli bir kontrol listesine

İki sekmedeki kodda da iki gerçek hata var. Her yanıtın onları nasıl sunduğunu karşılaştır.

Bu kodu inceleyebilir misin? def get_user(conn, username): cur = conn.cursor() cur.execute(f"SELECT id, email FROM users WHERE name = '{username}'") row = cur.fetchone() return {"id": row[0], "email": row[1]}
Try it
Example replyReplies vary between models and runs.

Genel olarak fonksiyon kısa ve takip etmesi kolay. Birkaç öneri:

  • Tip ipuçları ekle, örneğin username: str, imzayı daha net yapar.
  • Bir docstring ekle, fonksiyonun ne döndürdüğünü açıklasın.
  • Parametreli sorgular kullan. SQL'i f-string'lerle kurmak SQL injection'a yol açabilir.
  • Eksik kullanıcıları ele al. fetchone() None döndürebilir.
  • Adlandırma: fetch_user veritabanı erişimini daha iyi anlatabilir.

İlk yanıt iki hatayı da buldu ve bir incelemeyi neden bahsettiklerine göre değerlendirmenin sorunu da bu. Injection beşli bir listenin üçüncü sırasında, "yol açabilir" diye yumuşatılmış, düzeltmesi olmadan, bir docstring önerisinin yanında duruyor. Göz gezdiren bir okur tip ipuçlarını ekleyip devam ederdi.

İkinci prompt dört şeyi değiştirdi:

  • Kapsam. "Sadece hatalar, güvenlik ve hata yönetimi. Üslubu atla" gürültüyü kaldırır. Üslup, daha hızlı olan ve kendisiyle hiç çelişmeyen bir linter'ın ve formatter'ın işidir.
  • Önem derecesi. Modeli sıralama yapmaya zorlar ve sıralı bir liste nereden başlayacağını söyler.
  • Tetikleyen bir girdi. "x' OR '1'='1" belirsiz bir riski çalıştırabileceğin bir gösterime çevirir. Son bölümde görüleceği gibi, yanlış alarmlara karşı en iyi filtren de budur.
  • Diff'ler. Bulgu başına küçük bir diff tek başına uygulanabilir ya da reddedilebilir. Yeniden yazılmış bir fonksiyon her düzeltmeyi kimsenin istemediği değişikliklerle karıştırır.

"Bir önem seviyesinde bir şey yoksa bir şey uydurma" göründüğünden daha önemlidir. Bir inceleme istendiğinde model, bulunacak pek bir şey olmasa bile bulgu üretmeye eğilimlidir ve en zayıfları listeyi şişirir. Bir seviyede hiçbir şey bildirmeme konusunda açık izin bu şişkinliği keser.

İnceleyicinin ihtiyaç duyduğu bağlam

Bir insan inceleyici kodun ne için olduğunu ve girdilerinin nereden geldiğini bilir. Model sadece senin yapıştırdığını bilir. "username doğrudan bir giriş formundan geliyor", SQL injection'ı teorik bir bulgu olmaktan çıkarıp yüksek önem dereceli bir bulgu yapan cümledir. Bir inceleme için faydalı bağlam:

  • Girdilerin nereden geldiği: kullanıcılar, başka bir iç servis, senin kontrol ettiğin bir yapılandırma dosyası.
  • Kodu neyin çağırdığı ve geri ne beklediği.
  • Çalışma ortamı: dil sürümü, framework, veritabanı sürücüsü. Yukarıdaki injection düzeltmesi ? kullanıyor, çünkü sqlite3 bu yer tutucuyu kullanır; bazı başka sürücüler %s kullanır.
  • Bu değişiklikte en çok neyi önemsediğin: doğruluk, güvenlik, performans ya da üçü birden.

Tekrar kullanılabilir bir inceleme promptu

Bu blok kontrol listesini bir şablona çeviriyor. Dili, odağı ve kodu değiştir, kuralları koru. Kısıtlar parçasını kapatmak, onsuz ne kadar gürültü geldiğini görmenin hızlı bir yoludur.

Kod inceleme şablonu
Fill in
Parts
Kıdemli bir JavaScript inceleyicisisin. Gerçek sorunları bildirirsin, başka hiçbir şeyi değil.
Aşağıdaki kodu hatalara ve hata yönetimine odaklanarak incele.
Bu kod tarayıcıda çalışıyor. `ids` kendi API'mizden gelen sayısal id'lerden oluşan bir dizi.
async function loadAll(ids) { const results = []; ids.forEach(async (id) => { const res = await fetch(`/api/items/${id}`); results.push(await res.json()); }); return results; }
Her bulgu için: önem derecesi (yüksek, orta ya da düşük), satır, onu tetikleyen bir girdi ya da durum ve minimal bir diff. En ciddiden başla.
Üslup, adlandırma ya da biçimlendirme yorumu yok. Bir bulgunun gerçek olduğundan emin değilsen bunu söyle ve onu neyin doğrulayacağını belirt. Hiçbir şey bulamazsan "Bulgu yok" de.
Try it
Example replyReplies vary between models and runs.

1. Yüksek: fonksiyon herhangi bir istek bitmeden dönüyor (3. satır) forEach async callback'leri beklemez. loadAll boş results dizisini hemen döndürür ve push işlemleri daha sonra olur. Her çağıran [] alır.

2. Orta: başarısız istekler veri gibi işleniyor (5. satır) 404 ya da 500 yanıtı fetch içinde bir exception değildir. JSON bir hata gövdesi ayrıştırılır ve bir öğeymiş gibi eklenir; JSON olmayan bir gövde ise res.json()'ın kimsenin beklemediği bir callback içinde hata fırlatmasına yol açar.

İkisi için de düzeltme; sonuçları ids ile aynı sırada da tutuyor:

 async function loadAll(ids) {
-  const results = [];
-  ids.forEach(async (id) => {
-    const res = await fetch(`/api/items/${id}`);
-    results.push(await res.json());
-  });
-  return results;
+  return Promise.all(
+    ids.map(async (id) => {
+      const res = await fetch(`/api/items/${id}`);
+      if (!res.ok) throw new Error(`Item ${id}: HTTP ${res.status}`);
+      return res.json();
+    })
+  );
 }

Rol satırı bir standart koyuyor ("gerçek sorunlar, başka hiçbir şey değil"); rol verme en çok burada işe yarar. İncelemeyi bir program okuyacaksa, örneğin bulguları bir pull request'e yorum olarak gönderen bir script, düzyazı yerine sabit alanları olan JSON iste; nasıl yapılacağını yapılandırılmış çıktı gösteriyor.

Yanlış alarmlarla başa çıkmak

Bazı bulgular yanlış olacaktır. Model girdiyi doğrulayan çağıranı, bir durumu imkânsız kılan veritabanı kısıtını ya da tuhaf görünen bir satırın neden bilerek öyle yazıldığını göremez. Bir kütüphanenin nasıl davrandığı konusunda da yanılabilir; kendinden emin bir iddianın neden kontrol edilmiş bir iddia olmadığını yapay zekâ halüsinasyonu açıklıyor.

Her bulguyu tetikleyen girdisiyle test et. Sisteminde soruna ulaşan bir girdi üretemiyorsan düzeltmeyi kabul etmek yerine eksik bağlamla itiraz et:

Bir bulguya itiraz et
Bu fonksiyonu `cents` undefined ya da string olabilir diye işaretledin: function formatPrice(cents) { return `$${(cents / 100).toFixed(2)}`; } Sadece `renderCart` tarafından çağrılıyor ve o da `Number.isInteger(cents)` doğru olmadıkça erkenden dönüyor. Bu hâlâ bir sorun mu? Değilse bulguyu geri çek.
Try it
Example replyReplies vary between models and runs.

O kontrol yerindeyken hayır: formatPrice her zaman bir tam sayı alıyor, yani bulgu geçerli değil ve onu geri çekiyorum.

Kontrolün kapsamadığı bir şey var: negatif tam sayılar Number.isInteger kontrolünden geçer ve formatPrice(-500) "$-5.00" döndürür. İadeler ya da indirimler bu fonksiyona ulaşabiliyorsa onun yerine "-$5.00" isteyebilirsin. Ulaşamıyorsa değiştirilecek bir şey yok.

Kendisine yeni kanıt gösterilen bir model ya bulguyu geri çekmeli ya da o kanıt göz önündeyken bulgunun neden hâlâ geçerli olduğunu açıklamalıdır. İkisi de faydalıdır. Her itiraza sadece katılan bir model inceleme yapmıyordur, bu yüzden yanıtı katılıp katılmadığına göre değil, gerekçelerine göre değerlendir. Modelin kendi yazdığı kod için incelemeyi yeni bir sohbette yap, böylece inceleme kodu üreten aynı akıl yürütmenin gözüyle okunmaz. Kapsam, bağlam ve test alışkanlıkları kodu en baştan daha iyi yapar; bkz. kod yazma promptları.

Sıkça Sorulan Sorular

Kod inceleme için iyi bir prompt nedir?

Neye bakılacağını söyle (hatalar, güvenlik, hata yönetimi), her bulgu için bir önem derecesi iste ve sorunu tetikleyen somut bir girdiyle onu düzelten bir diff talep et. Modele istenmedikçe biçimlendirme ve adlandırmayı atlamasını söyle. Ona bir insan inceleyicinin sahip olacağı bağlamı ver: kodun ne için olduğu ve onu neyin çağırdığı.

Yapay zekâ insan kod incelemesinin yerini alabilir mi?

Hayır, ama faydalı bir ilk turdur. Hızlıdır ve ele alınmamış None, eksik await'ler ve string'lerden kurulan SQL gibi yaygın hata kalıplarında iyidir. Ürününün kurallarını, kod tabanının geri kalanını ya da bir kararın neden verildiğini bilmez ve bulgularının bir kısmı yanlış olur. Onu insan incelemesinin yerine değil, öncesinde kullan.

Yapay zekâ kod incelemesi neden gerçek olmayan sorunlar bildiriyor?

Model sadece yapıştırdığın kodu görür. Bir değer çağıran tarafından doğrulanıyorsa ya da bir durum senin sisteminde hiç gerçekleşemiyorsa model bunu bilemez, bu yüzden riski yine de işaretler. Somut bir hatalı girdi istemek bunların çoğunu eler: onu tetikleyen gerçekçi bir girdisi olmayan bir bulgu genellikle yanlış alarmdır.

İnceleme sırasında yapay zekâdan kodumu yeniden yazmasını istemeli miyim?

Yeniden yazılmış bir dosya yerine her bulgu için bir tane olmak üzere küçük diff'ler iste. Tam bir yeniden yazım düzeltmeleri kimsenin istemediği değişikliklerle karıştırır ve yeniden yazımı da incelemen gerekir. Diff'ler her bulguyu tek başına kabul etmeni ya da reddetmeni sağlar.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA