Spec, Domain ve Disposable Code
Atılabilir Kod, Kalıcı Domain: Spec-Driven Development'ın Eksik Katmanı
Disposable Code, Durable Domain: The Missing Layer of Spec-Driven Development
AI kodu ucuzlattıkça kod atılabilir hale geliyor; Spec araçları 2026'da olgunlaşsa da kalıcı kalması gereken şey, spec'lerin atıf yaptığı, repo içinde sürümlenen ve göreve göre yüklenen domain modeli.
Kod yeniden üretilebilir hale geldikçe kalıcı varlık domain modelidir; spec'ler özellik başına kalırsa her üretimde kavramlar ve kurallar yeniden icat edilir.
SDD araçları spec ile kod uyumuna odaklanıyor ve Thoughtworks onları hâlâ 'Assess'te tutuyor; özellikler üstü domain katmanını DDD pratisyenleri savunuyor, araçlar henüz sunmuyor.
Zihinsel model
Kod çadırdır, domain modeli temel: çadırı her mevsim yeniden kurarsın, temeli bir kez dökersin.
Neden
- Spec'in birimi özelliktir; özellik bitince spec bayatlar ve aynı kavram sonraki spec'te başka kelimelerle tanımlanır.
- Testler örnektir, kural değildir; yeniden üretilen kod testleri geçip invariant'ın ruhunu ihlal edebilir.
- Kuralların tek kaynağı eski kodsa, kodu attığın an kuralları da atmış olursun.
Kanıt
Spec Kit'in converge adımı, implementasyondan sonra kodun yalnızca o özelliğin spec'iyle uyumunu kontrol ediyor.
Spec Kit June 2026 Newsletter (github/spec-kit), 2026Thoughtworks, ajan talimat dosyalarının şişmesini 'Caution' olarak işaretledi; talimata gömülen kurallar gözden kaçıyor.
Thoughtworks Technology Radar: Agent instruction bloat, 2026Spec akışına repo bağlamı besleyen hook'lar, beş puanlık kalite skorunu yalnızca 0,15 puan artırdı.
Spec Kit Agents: Context-Grounded Agentic Workflows (arXiv), 2026Karşı görüş
Fikir model-driven development hayalini hatırlatıyor; ayrı model katmanı küçük ekipte seremoniye dönüşebilir ve kodla model arasında yeni bir senkron yükü açar.
Kavramlar
Pratikte
- Repo içinde bağlam başına glossary ve kimlikli invariant listesi tut; spec'ler bunlara atıf yapsın.
- Invariant kimliğini spec, kod ve test adında taşı; kapsamı script'le ölç.
- Model değişikliğini ayrı PR türü yap; gerekçe ve domain sahibinin onayını iste.
Spec-driven development (SDD, spesifikasyon güdümlü geliştirme), AI ajanına kod yazdırmadan önce ne yapılacağını yazılı bir spec ile sabitlemeyi öneriyor. Ekim 2026 itibarıyla yaklaşım deneysellikten çıktı: GitHub Spec Kit Ağustos 2026'da 1.0 sürümüne ulaştı, Kiro spec'lerden property-based test üretiyor; Thoughtworks ise Nisan 2026'da Spec Kit ve OpenSpec'i hâlâ 'Assess' halkasında tuttu. Ancak bu araçların ürettiği spec'ler çoğunlukla tek bir özelliğe, tek bir değişikliğe bağlı; özellik bitince spec ya bayatlıyor ya arşive gidiyor. Asıl boşluk burada: kod yeniden üretilebilir, ama ortak dil, invariant'lar ve bounded context sınırları her üretimde baştan icat edilmemeli. Kodu bir öğleden sonrada sıfırdan yazdırabildiğimiz bir dönemde domain modelini kalıcı, sürümlenen ve göreve göre yüklenen bir katman olarak tutmak, ajanın her seferinde farklı bir sistem uydurmasını engelleyen çapa.
Çıkarımlar
- Spec Kit 1.0 ve Kiro gibi araçlar 2026'da kod ile spec arasındaki uyumu kontrol etmeye başladı; özellikler arası kalıcı domain katmanını hâlâ ekip kurmalı.
- Spec'in birimi özellik, domain modelinin birimi bağlam. İkisini aynı dosyada tutarsanız model her özellikle yeniden yazılır; modeli talimat dosyasına gömerseniz de instruction bloat'a dönüşür.
- Kodu yeniden ürettirmek ancak kurallar koddan bağımsız, repo içinde ve sürümlenen bir yerde yazılıysa güvenli.
- Invariant'lara kimlik verin (INV-ORDER-03 gibi) ve bu kimliği spec, kod ve test arasında taşıyın; kapsamı script'le ölçün.
- Model değişikliği ayrı bir PR türüdür: gerekçe ister, domain sahibinin onayını ister, kod hızında değişmez.
- Ajanın en değerli rollerinden biri kod yazmak değil, yeni spec ile mevcut model arasındaki çelişkiyi kod yazılmadan raporlamak.
Alt başlıklar
SDD'nin üç seviyesi ve kayıp parça
Birgitta Böckeler'in martinfowler.com'daki sınıflandırması işe yarıyor: spec-first (görevden önce spec yaz, sonra atabilirsin), spec-anchored (spec'i özellik yaşadıkça güncel tut) ve spec-as-source (insan yalnızca spec'i düzenler, kod tamamen üretilir). Üç seviyede de spec'in birimi genellikle bir özellik ya da bir değişiklik isteği.
Sorun şu: 'İade talebi oluştur' özelliğinin spec'i iade kavramını kendi içinde tanımlıyor; altı ay sonra 'kısmi iade' özelliğinin spec'i aynı kavramı başka kelimelerle yeniden tanımlıyor. İki spec arasında kimse 'iade tutarı sipariş tutarını aşamaz' kuralını tek bir yerde tutmuyor. Eksik katman tam olarak bu: özelliklerin üstünde duran, birden fazla spec'in referans verdiği, kavramları ve kuralları bir kez tanımlayan domain modeli. Spec'ler bu modele atıf yapmalı, onu kopyalamamalı; kopyalanan her tanım bir sonraki özellikte sessizce ayrışır.
Ekim 2026 itibarıyla durum
Son on iki ayda SDD araçları hızla olgunlaştı. GitHub Spec Kit, 21 Ağustos 2026'da birinci yaşında 1.0.0 sürümünü yayımladı; bakımcı blogu 130 binin üzerinde GitHub yıldızı, 150'den fazla topluluk extension'ı ve 35'ten fazla desteklenen coding agent bildiriyor. Haziran 2026'da v0.11 ile gelen `/speckit.converge` adımı, implementasyondan sonra kodun spec'le uyuşup uyuşmadığını kontrol edip kalan işi görev listesine ekliyor. Kiro, Kasım 2025'teki genel erişim sürümünden beri spec'ten property-based test üretiyor; Ekim 2026'da spec dokümanlarına toplu yorum yapılabilen Markdown Review özelliğini ekledi.
Thoughtworks Technology Radar'ın Nisan 2026 sayısı Spec Kit ve OpenSpec'i 'Assess' halkasına koydu; aynı sayıda CLAUDE.md ve AGENTS.md dosyalarının şişmesini (agent instruction bloat) 'Caution' olarak işaretledi. Kanıt tarafı karışık: Nisan 2026 tarihli 'Spec Kit Agents' çalışmasında ajana repo bağlamını besleyen hook'lar, beş puanlık kalite skorunu yalnızca 0,15 puan artırdı. Kısacası araçlar spec ile kod arasındaki uyumu ölçmeye başladı; birden fazla spec'in paylaştığı kalıcı domain katmanı ise hâlâ ekibin kendi işi.
Kod neden atılabilir hale geldi
Bir CRUD ekranını ya da bir API endpoint'ini Claude Code veya benzeri bir ajana birkaç dakikada yazdırmak artık sıradan iş. Kodun üretim maliyeti düştükçe, onu korumanın, refactor etmenin ve 'güzel tutmanın' göreli değeri de düşüyor. Bazı ekipler bir modülü yamamak yerine testleri sabit tutup modülü yeniden ürettiriyor.
Bu yaklaşım ancak bir koşulla güvenli: yeniden üretilen kodun neyi doğru yapması gerektiği koddan bağımsız bir yerde yazılı olmalı. Testler bunun bir kısmını taşır ama testler örnektir, kural değildir. 'Sipariş onaylandıktan sonra ürün kalemi eklenemez' bir invariant'tır; bunu üç test örneğiyle anlatabilirsiniz ama modelde tek cümle olarak durması gerekir. Anti-pattern: domain kurallarının tek kaynağının eski kod olması. Kodu attığınız an kuralları da atmış olursunuz.
Domain modeli ne içerir: ortak dil, invariant, sınır
DDD (Domain-Driven Design, alan güdümlü tasarım) açısından kalıcı katmanın minimum içeriği dört parça. Birincisi ubiquitous language (ortak dil): 'Müşteri', 'Hesap', 'Kullanıcı' aynı şey mi, değil mi? İkincisi aggregate'ler ve invariant'ları: hangi nesne grubu tek bir tutarlılık sınırı içinde değişir, hangi kural her zaman doğru kalmalı. Üçüncüsü domain event'leri: 'SiparişOnaylandı', 'ÖdemeReddedildi' gibi geçmiş zamanlı, iş açısından anlamlı olaylar. Dördüncüsü bounded context haritası: hangi kavram hangi bağlamda geçerli ve bağlamlar arası çeviri nerede yapılıyor.
Örnek: Bir abonelik SaaS'ında 'Plan' satış bağlamında fiyatı ve indirimi olan bir teklif, faturalama bağlamında dönemi ve vergi oranı olan bir kalemdir. Tek bir 'Plan' tablosuyla iki anlamı birleştirmek, ajanın her iki bağlamdaki spec'te farklı alanlar uydurmasına davetiye çıkarır. İki ayrı model ve aradaki çeviri katmanı daha fazla kod gibi görünür, ama ajan için çok daha net bir sınırdır.
Modeli makinece okunabilir tutmak
Domain modeli bir Confluence sayfasında ya da bir duvar fotoğrafında kalırsa ajan için yok hükmündedir. Pratik hedef: repo içinde, sürümlenen, ajanın her görevde okuduğu bir dizin. Örneğin `domain/` altında bağlam başına bir glossary dosyası, aggregate başına kısa bir invariant listesi ve event kataloğu (event adı, alanları, hangi aggregate yayınlar).
Format tartışması ikincil; Markdown + tablo da olur, TypeScript tip tanımları + Zod şemaları da, hatta bir JSON Schema da. Önemli olan iki şey: spec şablonunuzun 'Bu özellik hangi aggregate'lere dokunuyor, hangi invariant'ları etkiliyor?' sorusunu zorunlu kılması ve CLAUDE.md / AGENTS.md gibi ajan talimat dosyalarının bu dizine açıkça işaret etmesi, ama modeli kendi içine kopyalamaması. Thoughtworks'ün Nisan 2026'da uyardığı gibi şişen talimat dosyalarında ortadaki kurallar gözden kaçıyor; talimat dosyası yalnızca hangi görevde hangi bağlam dosyasının okunacağını söylemeli (progressive context disclosure). Kural koyun: bir spec, glossary'de olmayan bir terimi kullanıyorsa ya terimi ekleyen bir model değişikliği PR'ı açılır ya da spec reddedilir.
Spec, model ve kod arasındaki iz sürülebilirlik
Kalıcı model işe yarasın diye üç katman arasında bağ kurmak gerekiyor. Spec'teki her kabul kriteri bir invariant'a ya da bir domain event'ine referans vermeli; kodda o invariant'ı uygulayan yer (ör. aggregate metodundaki guard) ve onu doğrulayan test aynı kimliği taşımalı. Basit bir konvansiyon yeter: `INV-ORDER-03` gibi bir etiket model dosyasında tanımlanır, spec'te anılır, test adında geçer.
Bu bağ, 'kodu yeniden ürettirme' senaryosunu denetlenebilir yapar. Ajan modülü baştan yazdıktan sonra bir script, modeldeki her invariant kimliği için en az bir testin var olup olmadığını ve geçip geçmediğini kontrol eder. Eşik koymak mantıklı: kritik bağlamlarda (ödeme, faturalama) invariant kapsamı yüzde 100'ün altına düşerse merge engellenir. Anti-pattern: kabul kriterlerini UI davranışı olarak yazmak ('butona basınca hata göster'); bu kriterler model değiştiğinde hiçbir şeyi korumaz.
Modelin kendisi nasıl evrilir
Kalıcı demek donmuş demek değil. Domain modeli de değişir, ama kodla aynı hızda değil ve aynı kişiler tarafından değil. Kod değişikliği dakikalar sürerken bir invariant değişikliği ürün, iş ve mühendislik arasında bir konuşma gerektirir. Bu yüzden model değişikliklerini ayrı bir PR türü olarak ele almak, ADR (Architecture Decision Record, mimari karar kaydı) benzeri kısa bir gerekçe istemek ve onayına domain sahibini dahil etmek mantıklı.
Ajan burada da yardımcı olabilir ama farklı bir rolde: yeni bir spec geldiğinde mevcut glossary ve invariant'larla çelişkileri listeleyen bir gözden geçirici olarak. Örneğin 'Kullanıcı birden fazla şirkete bağlı olabilir' diyen bir spec, 'Kullanıcı tek bir Tenant'a aittir' invariant'ıyla çakışır. Bu çakışmayı kod yazılmadan yakalamak, üç hafta sonra veri modelinde migration yazmaktan çok daha ucuz.
Son gelişmeler
Ekim 2026 itibarıyla
Önce kendi cevabını düşün, sonra aç.
Bu, 2000'lerin model-driven development (MDD) hayalinin yeniden ısıtılmış hali değil mi?
Benzerlik var ama fark önemli: MDD kodu modelden deterministik olarak üretmeye çalışıyordu ve modelleme dili ağırdı. Burada model kodu üretmiyor, ajanın üretimini sınırlıyor ve doğruluyor. Model düz metin, tip tanımı veya şema olabilir; amaç generator değil, tek doğruluk kaynağı olması.
Küçük bir startup için bu kadar seremoni fazla değil mi?
Tüm DDD aparatını kurmak fazla, ama bir glossary dosyası ve kritik aggregate'ler için beş-on satırlık invariant listesi bir günlük iş. Bunu yapmamanın maliyeti, üçüncü ayda aynı kavramın üç farklı tabloda üç farklı adla durması. Ödeme, faturalama, yetki gibi bağlamlarla başlayın; geri kalanını ihtiyaç doğunca ekleyin.
Testler zaten davranışı tanımlamıyor mu, ayrı bir modele neden gerek var?
Testler örnek tabanlı; bir kuralı birkaç girdiyle gösterir. Ajan kodu yeniden yazarken testleri geçen ama kuralın ruhunu ihlal eden bir uygulama üretebilir. Invariant'ın düz cümle olarak yazılması hem insanın hem ajanın test setindeki boşlukları görmesini sağlar; testler modelin yerine değil, onun doğrulayıcısı olarak çalışır.
Domain modelini kim yazmalı, mühendis mi ürün yöneticisi mi?
Tek başına ikisi de değil. Terimler ve kurallar iş tarafının diliyle yazılmalı ama aggregate sınırları ve event'ler teknik tutarlılık gerektirir. Pratikte mühendis taslak çıkarır, ürün veya domain uzmanı terim ve kural düzeyinde onaylar; ajan ise çelişki tarayıcısı olarak araya girer.
Spec Kit 1.0 çıktı, constitution dosyası ve converge adımı bu katmanı zaten çözmüyor mu?
Kısmen. Thoughtworks ekiplerinin deneyiminde constitution genelde kapsamı, domain bağlamını, teknoloji sürümlerini ve kod standartlarını içeriyor; converge adımı da kodun spec'e uyup uymadığını kontrol ediyor. Ama constitution tek dosyada büyüdükçe instruction bloat'a dönüşüyor ve converge yalnızca o özelliğin spec'ine bakıyor. Bağlam başına glossary ve kimlikli invariant listesi yine ayrı, sürümlenen dosyalarda durmalı; constitution bu dosyalara işaret etmeli.
Notun kaynakları
- Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl (Birgitta Böckeler, martinfowler.com)
- GitHub Spec Kit
- Domain-Driven Design Reference (Eric Evans)
- Spec Kit Turns One — and Ships 1.0.0 (manorrock.com, Ağustos 2026)
- Spec Kit June 2026 Newsletter (github/spec-kit)
- Thoughtworks Technology Radar: GitHub Spec Kit (Nisan 2026)
- Kiro is generally available (Kiro Blog, Kasım 2025)
- GitHub Spec Kit Takes Off as Antidote to Piecemeal 'Vibe Coding' (Visual Studio Magazine, Mayıs 2026)
- Kiro Changelog (Ekim 2026: Markdown Review)
Sunum stili
12 slayt. Tıklarsan sunum o slayttan başlar.
Slayt notları
Bir modülü Agent'a baştan yazdırmak dakikalar sürüyor. O zaman soru şu: kod bu kadar ucuzsa, korumamız gereken asıl şey ne?
Soru olarak aç: iş kurallarınız bugün nerede yazılı? Çoğu ekipte cevap 'kodda' çıkar.
'İade toplamı sipariş tutarını aşamaz' kuralını hiçbir Spec tek başına taşımıyor. Spec'in birimi özellik olduğu için kavram her seferinde yeniden doğuyor.
Böckeler'in spec-first, spec-anchored, spec-as-source ayrımında üç seviyede de birim özellik. Eksik olan, özelliklerin üstünde duran ve birden fazla Spec'in referans verdiği katman.
Araçların hepsi Spec ile kod arasındaki uyumu güçlendiriyor. Hiçbiri birden fazla Spec'in paylaştığı kavram ve kural katmanını tutmuyor; o katman hâlâ ekibin işi.
Her parçayı tek cümleyle tanımla. Format ikincil: Markdown, TypeScript tipleri ya da şema olur; önemli olan repo içinde, sürümlenen ve Agent'ın her görevde okuduğu bir dizin olması.
Kural koy: Spec glossary'de olmayan bir terim kullanıyorsa ya terimi ekleyen bir model PR'ı açılır ya da Spec reddedilir. CLAUDE.md veya AGENTS.md bu dizine işaret etmeli ama modeli içine kopyalamamalı; şişen talimat dosyası kendi başına bir risk.
Bu bağ kurulduğunda 'kodu yeniden ürettir' senaryosu denetlenebilir hale gelir. Agent modülü baştan yazınca script her invariant kimliği için testin varlığını ve sonucunu kontrol eder.
Kod dakikalar içinde değişir, invariant değişikliği bir konuşma ister. Model değişikliği ayrı bir Pull Request türüdür: kısa gerekçe ve domain sahibinin onayı.
Küçük ekip için tüm DDD seremonisi gerekmiyor. Sağ alttaki bağlamlardan başla: ödeme, faturalama, yetki. Bir glossary ve beş-on satırlık invariant listesi bir günlük iş.
'Kullanıcı birden fazla şirkete bağlı olabilir' diyen Spec ile 'kullanıcı tek Tenant'a aittir' invariant'ı çakışır. Bunu üç hafta sonraki migration yerine bugün yakalamak çok daha ucuz.
Başlangıç için ödeme ya da faturalama bağlamını öner; ilk hafta yalnızca glossary ve beş invariant yeter.