Vibe Coding: Terminal Editörü ve LLM'lerle Öğrenilen Dersler

Vibe Coding: Terminal Editörü ve LLM'lerle Öğrenilen Dersler

Terminal Editörü

Önce projeyi kısaca tanıtayım. Bu, normal editör widget'ım içinde "shell" çalıştırmama olanak sağlayan bir VS Code uzantısı, böylece çıktı tüm standart hareket/düzenleme komutlarının çalıştığı normal metin buffer'ı oluyor. Bu sayede backtrace'in bir parçası olarak yazdırılan yollarda "tanıma git" yapabilir, derleyicinin önerilerini kopyalamak için birden fazla imleç kullanabilir veya sadece çıktıyı kaydırmak için PageUp / PageDown kullanabilirim. Emacs'a aşinaysanız, bu Eshell, sadece daha kötü:

Terminal Editor Screenshot

Artık derleme komutlarımın çoğunu terminal-editor ile başlatıyorum, çünkü normal shell'imin sağladığının üstünde birkaç güzel özelliği var. Örneğin, varsayılan olarak yalnızca son 50 satır çıktı gösteriliyor, ancak tam çıktıyı katlamak ve açmak için tab tuşuna basabilirim. Böylesine basit bir özellik, ama UNIX shell/terminal'de uygulamak için böylesine acı verici!

Aşağıdakiler öğrenilen şeylerin yapılandırılmamış bir çantası:

Plan / Sıfırlama

Başlangıçta Claude Code'u normalde kullanmaya çalıştım, istediğim çıktıyı alana kadar terminalde yinelemeli olarak prompt vererek. Bu sinir bozucuydu, çünkü bir çalışma parçasını commit etmek için iyi bir yer kaçırmak veya yoldan çıkan bir konuşmayı dizginlemek çok kolaydı. Bu "prompt-ver-sonra-bekle" modu aynı zamanda zihinsel bağlam değişimlerinin tercih ettiğim çalışma tarzımla eşleşmeyen bir desenine sahipti. Bu makale daha iyi bir iş akışı öneriyor:

https://harper.blog/2025/05/08/basic-claude-code/

Terminalde tek bir prompt yazmak yerine, plan.md belgesinde tüm eylem planını görev listesi olarak yazıyorsunuz ve gerçek prompt şu şekilde oluyor:

> @plan.md dosyasını oku, sonraki görevi tamamla ve X ile işaretle.

Claude bir adımı tamamladıktan sonra diff'e bakıyor ve gerekli düzeltmeler için etkileşimli olarak prompt veriyorsunuz. Memnun olduğunuzda, git commit yapıyor ve bir sonraki adımı temiz sayfa ile başlatmak için konuşmayı /clear yapıyorsunuz.

Plan deseni bağlam değişimlerini azaltır, çünkü işi bir seferde bir adım yapmak mantıklı olsa bile, planlama modundayken birkaç adım önceden planlamanıza olanak tanır. Claude mevcut görevde çalışırken ben de sık sık planı devam ettirme üzerinde çalışırım.

Beyaz Tahta / Ajan Metaforu

Başka bir yazıdan gelen parlak metafor: https://crawshaw.io/blog/programming-with-agents

LLM'yi bir kodlama görevi için prompt'lamak ve sonra çalışan bir çözümü tek seferde beklemek, bir adaydan mülakat sırasında bir algoritma beyaz tahtaya yazmasını istemek gibi.

LLM'ler açıkça beyaz tahta konusunda insanüstü, ancak geri bildirim olmadan uzağa gidemezsiniz. Claude gibi "Agentic" programlama, LLM'lerin çözüm üzerinde yinelemesine olanak tanır.

LLM'ler yinelemekten çok beyaz tahta konusunda daha iyi. Deneyimim şu ki, optimal olmayan çözümle başlayarak, LLM genellikle önemsediğim bulanık estetik ölçütler boyunca kendi başına geliştiremez. Geçerli değişiklikler yapabilirler, ancak genel kalite kabaca aynı kalır.

Ancak LLM'ler inatçı ve çok sayıda yineleme yapabilir. Eğer bir değer fonksiyonunuz varsa, bunu rastgele yürüyüşten faydalı iş çıkarmak için kullanabilirsiniz! Kötü bir değer fonksiyonu insan yargısıdır. LLM ile döngüde oturmak ve hataları işaret etmek hem sinir bozucu hem de yavaş (siz darboğazsınız). Buna karşın "bu testi yeşil yap" çalışan (≠ iyi) kod almada çok verimli.

Spec Kod'dur Test'tir

LLM'ler "döngüyü kapatmakta" iyi, uçları birleştirebilirler. Plan.md deseniyle birleştirilen bu içgörü benim mevcut iş akışımı veriyor — spec ↔ kod ↔ test döngüsü. İşte hikaye:

Terminal-editor'ın ilk versiyonunu sadece plan.md deseni kullanarak kodladım, ancak bir noktada karmaşıklık duvarına çarptım. Sözdizimi vurgulaması için orijinal uygulama stratejimin çıkmaz sokak olduğunu fark ettim ve bunu değiştirmem gerekiyordu, ancak kodun tam bir karmaşa haline gelmeden bunu yapmak zordu. Biriken plan.md bir sürü tarihi sapmayi yansıtıyordu ve testler çok kırılgan ve mevcut uygulamaya bağlıydı (testler hakkında daha sonra). Bu artımlı eklemeler için çalıştı, ancak şimdi ortada bir şeyi değiştirmek istiyordum.

Fark ettim ki istediğim şey tarihi yansıtan append-only plan.md değil, yazılımın nasıl davranması gerektiğini açıkça tanımlayan mutable spec.md. Normal mühendislik için bu "lanet olsun, sanırım birini atıp yeniden başlamam gerekiyor" anı olurdu. Claude ile plan.md ve tüm kodu bağlama ekledim ve aynı görev listesi formatında spec.md dosyası yazmasını istedim. Burada iki içgörü var:

Birincisi, mutable spec LLM'ye talimat vermenin iyi bir yolu. Şimdi terminal-editor'a bir değişiklik uygulamak istediğimde, Claude'a önce spec'i güncellemesini (yeniden yapılması gereken öğelerin işaretini kaldırarak) prompt veriyorum, spec'i manuel olarak gözden geçirip/düzeltiyorum ve kodu ve testleri spec ile hizalamak için hazır bir prompt kullanıyorum.

İkincisi, bir LLM'yi çalışan kod, spesifikasyon ve testler arasında otomatik olarak dönüştürebilen bir makine çevirisi olarak düşünebilirsiniz. Bu şeylerden herhangi birini girdi olarak ele alabilirsiniz, sanki miniKanren'de kodlama yapıyormuşsunuz gibi!

Testler

Terminal-editor ile başladığımda döngüyü kapatma fikrine sahiptim, bu yüzden prompt'ları test vurgulamak için hazırladım. Sonucu tahmin edebilirsiniz! Claude tüm modern "en iyi uygulamaları" takip ederek çok sayıda test yazdı — sadece gereksiz yere dahili API'yi çivileyen birim testlerin seli, hata gizleyen mock'ların ormanı ve senkronizasyon hatalarını örtmek için bol miktarda sleep içeren yavaş, kararsız ve odaksız entegrasyon testleri. Gerçekten, bu doğada bulabileceğiniz tipik bir test suite'ine ürkütücü derecede benziyordu. Neden böyle olduğunu merak ediyorum?

Bu belki de ana çıkarımım: eğer tekrar vibe-coding yapacaksam ve bunu sürdürmek istiyorsam (sadece tek seferlik değil), test stratejisi hakkında çok dikkatli düşüneceğim. Gerçekten, kendi boynuzumu öttürmek gerekirse, "How to Test?" belki de agentic kodlama hakkında oradaki en iyi makale. Test yinelemesi insanlar için çarpan, ancak LLM'ler için zor bir gereksinim. Test çok hızlı, kararsız olmayan ve kod yerine uygulama özelliklerini uçtan uca test etmelidir.

Somut olarak, mevcut tüm testleri tamamen sildim. Sonra spec'e test stratejisi ekledim. İki fonksiyon var:

typescript
export async function sync(): Promise<void>;
export function snapshot(): string;

sync fonksiyonu tüm bekleyen async işin (harici süreçler gibi) bitmesini bekler. Bu, kod boyunca nedenselliği düzgün şekilde thread etmeyi gerektirir. Örneğin, şu anda çalışan sürece katılmak için await edebileceğiniz bir promise var. snapshot fonksiyonu uzantının tüm durumunu tek bir string olarak yakalar. Saat için sadece bir mock var (normal terminalde başka bir gelişme — süreç çalışma zamanı her zaman gösteriliyor).

Sonra Claude'u şu şekilde prompt'ladım:

> Oops, buradaki tüm testleri birisi silmiş gibi görünüyor, ama kod ve spec iyi görünüyor, @spec.md'ye göre snapshot fonksiyonunu kullanarak test suite'ini yeniden oluşturabilir misin?

İşe yaradı. Yine, "birini at" çok ucuz.

Sonuçlar

Bu kadar! LLM'ler açıkça kodlayabilir. Onları doğru tutmanız gerekiyor. Özellikle, LLM'nin kendi hızında yinelemesine izin vermek için bir geri bildirim döngüsü mühendislik etmeniz gerekiyor. Döngünün "veri düzleminde" insan istemiyorsunuz, sadece kontrol düzleminde. Test için mimarlık öğrenin.

LLM özel araçlar yazma için aktivasyon enerjisini büyük ölçüde azaltır. Terminal-editor gibi bir şeyi sonsuza dek istedim, ama asla tıraşlamak için en çekici yak değildi. Şimdi şeye sahibim, günlük kullanıyorum.

LLM'ler tüm yazılım mühendisliği problemlerini sihirli şekilde çözmez. Terminal-editor ile en büyük zaman kaybı pty problemini çözmekti, ancak LLM'ler henüz "bana UNIX ver, ama pty karmaşası olmadan" aşamasında değil.

LLM'ler bakımı çözmez. Bir süre önce jj için LSP hakkında yazmıştım. Sanırım bunu şimdi Claude ile bir günde kodlayabilirim? Kavram kanıtı değil, ihtiyacım olan her şeyle birlikte üretim versiyonu. Ama bunu sürdürmek istemiyorum. Eğer aracı sadece ben kullanıyorsam, küçük bir hatayı düzeltmek için bağlam değiştirmek istemiyorum. Ve tabii, bunu başka insanlar için yaparsam, kesinlikle onu sürdürmekle yükümlü olurum :D

Önemli Çıkarımlar

1. Plan-Tabanlı Yaklaşım

  • Append-only plan.md yerine mutable spec.md kullanın
  • Her adımdan sonra commit yapın ve konuşmayı temizleyin
  • LLM'ye bağlam değişimi yapmadan birkaç adım önceden planlama imkanı verin

2. Test Stratejisi Kritik

  • Hızlı, kararlı, uçtan uca testler yazın
  • Unit testler ve mock'lardan kaçının
  • Snapshot ve sync fonksiyonları ile basit test mimarisi kullanın

3. Agentic Programlama

  • LLM'leri beyaz tahta ustası olarak görün
  • Geri bildirim döngüsünde insan kontrol düzleminde olmalı
  • "Bu testi yeşil yap" gibi net değer fonksiyonları kullanın

4. Spec-Kod-Test Döngüsü

  • LLM'leri spec, kod ve test arasında çeviri makinesi olarak kullanın
  • Herhangi birini girdi olarak alabilir, diğerlerini üretebilir
  • Mutable spesifikasyon LLM'ye talimat vermenin etkili yolu

Bu deneyim, LLM'lerle etkili çalışmanın sadece iyi prompt yazmaktan ibaret olmadığını gösteriyor. Doğru iş akışları, test stratejileri ve mimari kararlar alarak LLM'lerin gücünden tam olarak yararlanabilirsiniz.

Makale Bilgileri

Yazar: İsmail Hakkı EREN
İlgili Yazılar