Oyun Kitabı
Katmanlardan Özelliklere: Vertical Slice Neden Doğdu? (Katmanlardan Ozelliklere Vertical Slice Neden Dogdu)
Katmanlı mimari neden büyüdükçe değişimi yavaşlatır? Vertical Slice'in klasör düzeni değil; özellik sahipliği, davranış yerelliği ve değişim maliyeti kararı…
Vertical Slice — Özellik Odaklı Mühendislik
Bolum 1 / 4
Önce CRUD ve katmanları suçlamayalım
Katmanlı mimari küçük ve orta ölçekli birçok sistem için iyi bir başlangıçtır. Controller, application service, repository ve veri erişimi ayrımı; ekibe ortak bir teknik dil verir. Sorun bu katmanların varlığı değildir. Sorun, tek bir kullanıcı talebinin zamanla bütün katmanlara dağılması ve her değişimin koordinasyon işine dönüşmesidir.
Bir gün basit görünen bir talep gelir: siparişe teslimat notu eklemek.
Controller
→ Request / DTO
→ Service
→ Validator
→ Repository
→ Mapping
→ Test doubles
→ Tests
Sekiz dosya değiştirmek tek başına hata değildir. Ancak bu dosyalar aynı davranış için, aynı anda ve aynı ekip tarafından değişiyorsa; dosya sistemi iş değerini değil teknik rolleri anlatmaya başlamıştır. Vertical Slice, bu sürtünmeye verilen pragmatik cevaptır.
Kavramlar ilk geçtiği yerde
📦 Vertical Slice
Bir kullanıcı niyetini request'ten veri kaydına ve teste kadar tek sınırda tutan uçtan uca özellik birimi.
📦 Davranışın yerelliği
Bir davranışı anlamak veya değiştirmek için gereken kodun birbirine fiziksel olarak yakın olması.
📦 Temporal DRY
Bugün benzer görünen kodun, yarın aynı sebeple değişip değişmeyeceğini sorgulayan DRY yaklaşımı.
📦 Wrong abstraction
Sadece tekrar var diye erken paylaşılan; zamanla farklı ihtiyaçları birbirine bağlayan soyutlama.
Vertical Slice, katmanları yasaklamaz. Teknik ayrımı feature'ın içinde tutar; özelliğin dış sınırını ise kullanıcı niyeti, iş kuralı ve sahiplik belirler.
Hikâye: katmanlar ne zaman yavaşlatır?
İlk gün CreateOrder küçüktür. Tek controller, tek service ve tek repository yeterli görünür. Sonra stok kontrolü, kampanya kuralı, teslimat tercihi ve denetim kaydı eklenir. Her özellik aynı OrderService içine girdiğinde, sistemdeki en riskli dosya en çok kullanılan ortak dosya olur.
Yeni özellik
→ ortak Service'e dokunur
→ ilgisiz testleri etkiler
→ farklı ekiplerin release'ini bekler
CRUD bozulmaz. Modelin ve uygulama katmanının sorumluluğu değişir. Vertical Slice'in sorusu şudur: Bu davranış hangi iş niyetiyle değişiyor?
Yatay ve dikey organizasyon
| Kriter | Katman odaklı | Özellik odaklı |
|---|---|---|
| Organizasyon ekseni | Teknik rol | Kullanıcı niyeti / feature |
| Değişim birimi | Birden çok katmanda dosya | Tek feature sınırı |
| Kod paylaşımı | Erken ortak service eğilimi | Kanıtlanmış ortaklık |
| Navigasyon | Controller → service → repository | Feature → request → handler → test |
| Hata etkisi | Ortak katman boyunca yayılabilir | Feature sınırında daha görünür kalır |
❌ Controllers / Services / Repositories
→ OrdersController
→ OrderService
→ OrderRepository
✓ Features / Orders / CreateOrder
→ Request
→ Validator
→ Handler
→ Response
→ Tests
Bu fark yalnızca klasör adı değildir. Bir değişikliğin bulunma, anlaşılma, test edilme ve geri alınma maliyetini etkiler. Bir feature içindeki arama maliyeti dosya sayısı n için en kötü durumda O(n) kalsa bile, ilgili kodun birlikte konumlanması yanlış dizinlerde yapılan aramayı ve zihinsel geçiş sayısını azaltır.
Screaming Architecture: dizin yapısı neyi anlatmalı?
Bir proje açıldığında ilk görünen klasörler Controllers, Services ve Infrastructure ise; sistem teknik araçlarını anlatır. Orders, Catalog, Billing ve Returns ise iş alanını anlatır. Mimari framework'ü değil, ürünün niyetini haykırmalıdır.
Bir CancelOrder değişikliğinde geliştiricinin davranışa ait handler, doğrulama, response ve testleri aynı yerde bulması; yeni bir ekip üyesinin öğrenme süresini de kısaltır. Ancak feature klasörü her şeyin public olduğu küçük bir monolith değildir. Giriş noktası açık kalır; detaylar feature içinde gizlenir.
Kohezyon, kapsülleme ve stratejik duplikasyon
Bir Slice başka Slice'ın iç uygulamasını bilmemelidir. Ortak davranış gerçekten stabil ve en az birkaç bağımsız ihtiyaç tarafından aynı gerekçeyle değişiyorsa paylaşılmalıdır. Aksi halde Shared klasörü, sınırları görünmeyen yeni bir katman olur.
CreateOrder
→ Order aggregate'e komut verir
→ local transaction'ı tamamlar
→ response üretir
CancelOrder
→ kendi kurallarını uygular
→ CreateOrder'ın handler'ını çağırmaz
Bu yaklaşımda duplikasyon bazen doğru bedeldir. İki benzer kod parçası farklı iş kararları yüzünden değişecekse onları erken birleştirmek, gelecekte her değişimi O(k) bağımlı feature'a yayabilir.
Geçiş sinyalleri
Vertical Slice'e geçmek için sırf modern görünmek yeterli değildir. Aşağıdaki sinyaller birlikte ortaya çıktığında yatırım geri döner:
- Basit bir talep sürekli çok sayıda katmanda değişiklik gerektiriyorsa.
- Ortak service'lerdeki küçük değişiklikler ilgisiz feature testlerini kırıyorsa.
- Mock yoğun testler davranışı değil iç çağrı sırasını koruyorsa.
- Ekip, bir iş kuralının hangi dosyada yaşadığını bulmakta zorlanıyorsa.
- Farklı feature'ların sahipleri ve teslimat ritimleri ayrışmışsa.
Bu sınırlar dokümantasyonla bırakılmamalıdır. .NET'te mimari testler ile bir feature'ın başka feature'ın internal ayrıntılarına bağımlı olmaması denetlenebilir. Kuralın maliyeti derleme veya test aşamasında O(dependency) taramadır; kazancı ise ihlalin production'a ulaşmadan görünmesidir.
DDD ve CQRS ile ilişkisi
Vertical Slice, uygulamayı organize eder. DDD, iş kurallarının ve dilin nerede yaşadığını açıklar. CQRS ise bir use case'in command ve query tarafındaki akışı ayırabilir. Bunlar rakip değil, farklı karar katmanlarıdır.
Feature boundary → Vertical Slice
Consistency rule → DDD Aggregate
Read / write flow → CQRS
Deployment unit → Modular monolith veya microservice
Önce feature sınırını modüler monolith içinde doğrulamak, mikroservis maliyetini erkenden ödemeden bağımsızlık iddiasını test etmeyi sağlar.
Yanlış güven duygusu oluşturan eşleştirmeler
❌ Vertical Slice = klasörleri yeniden adlandırmak
✓ Kullanıcı niyeti, davranış ve sahipliği aynı sınırda tutmaktır.
❌ DRY = her benzer kodu paylaşmak
✓ Aynı nedenle değişen kodu paylaşmaktır.
❌ Handler = tüm iş kuralları
✓ Handler orkestrasyon yapar; domain kuralları uygun domain modelinde yaşar.
❌ Vertical Slice = mikroservis
✓ Önce modüler monolith içinde doğrulanabilen application boundary'dir.
❌ Shared = ücretsiz yeniden kullanım
✓ Shared, sürümleme ve koordinasyon maliyeti de getirir.
Karar kontrol listesi
- Bu kod aynı kullanıcı niyeti nedeniyle mi değişiyor?
- Bir feature'ın request, validation, handler, response ve testleri birlikte bulunabiliyor mu?
- Başka feature'ın internal sınıfına erişmeden ihtiyacımı karşılayabiliyor muyum?
- Bu ortak soyutlama en az üç bağımsız yerde aynı nedenle mi değişiyor?
- Aggregate kuralı ile application orchestration birbirinden ayrılmış mı?
- Feature sınırı modüler monolith içinde mimari testlerle korunuyor mu?
- Değişim sonrası hata etkisi, test kapsamı ve rollback yolu görünür mü?
Amaç daha çok klasör üretmek değildir. Amaç, bir davranışı değiştirmek için gereken karar ve kod yüzeyini küçültmektir.
Bu yazıdan aklında ne kalmalı
- Katmanlı mimari kötü değildir; ancak değişim birimi katmanlara dağıldığında koordinasyon maliyeti büyür.
- Vertical Slice, kodu teknik roller yerine kullanıcı niyeti ve davranış etrafında toplar.
- Stratejik duplikasyon, yanlış soyutlamadan daha ucuz olabilir.
- Vertical Slice; DDD, CQRS ve modüler monolith ile birlikte çalışan bir uygulama organizasyonu kararıdır.
Vertical Slice'in amacı dosyaları dikey dizmek değil; değişimin etkisini doğru feature sınırında tutmaktır.
Bir sonraki bölümde bir Slice'ın request, validation, handler, mapping ve testleriyle içeriden nasıl çalıştığını inceleyeceğiz.
SSS
Sık sorulan sorular
Vertical Slice nedir?
Bir kullanıcı niyetini request'ten veri kaydına ve teste kadar tek sınırda tutan uçtan uca özellik birimi.
Davranışın yerelliği nedir?
Bir davranışı anlamak veya değiştirmek için gereken kodun birbirine fiziksel olarak yakın olması.
"Vertical Slice = klasörleri yeniden adlandırmak" doğru mu?
Kullanıcı niyeti, davranış ve sahipliği aynı sınırda tutmaktır.
Bu bölüm neyi sabitler?
Sekiz dosya değiştirmek tek başına hata değildir. Ancak bu dosyalar aynı davranış için, aynı anda ve aynı ekip tarafından değişiyorsa; dosya sistemi iş değerini değil teknik rolleri anlatmaya başlamıştır. Vertical Slice, bu sürtünmeye verilen pragmatik cevaptır. Katmanlı mimari kötü değildir; ancak değişim birimi katmanlara dağıldığında koordinasyon maliyeti büyür. Katmanlı mimari küçük ve orta ölçekli birçok sistem için iyi bir başlangıçtır. Controller, application service, repository ve veri erişimi ayrımı; ekibe ortak bir teknik dil verir. Sorun bu katmanların varlığı değildir. Sorun, tek bir kullanıcı talebinin zamanla bütün katmanlara dağılması ve her değişimin koordinasyon işine dönüşmesidir.
Ogrenilen Muhendislik Prensipleri
- Kod organizasyonu teknik katmanlardan önce değişim nedenini görünür kılmalıdır.
- Davranışın yerelliği, navigasyon ve test maliyetini azaltan mimari bir karardır.
- Paylaşım ancak değişim nedeni ortak olduğunda değerlidir; aksi halde duplikasyon daha güvenli olabilir.
Okumaya devam et
Okumaya devam et
Seride sonraki yazi
Bir Vertical Slice İçeriden Nasıl Çalışır?
Bir Vertical Slice request'ten doğrulamaya, handler'dan aggregate'e, outbox event'inden read model'e ve bulut maliyetine kadar içeriden nasıl akar? CQRS…
Ilgili yazilar
CRUD (Create, Read, Update, Delete)'dan CQRS (Command Query Responsibility Segregation)'e: Sorun Kod Değil, Modeldir
CQRS nedir, CRUD ile CQRS arasındaki fark nedir ve CQRS ne zaman kullanılmalıdır? Tek modelin büyük sistemlerde neden yetmediğini anlatan rehber.
Ilgili yazilar
DDD- Yazılımı Veritabanına Göre Değil, İşe Göre Tasarlamak
Domain-Driven Design nedir? Veritabanı odaklı tasarımın sınırlarını, ortak dilin gücünü ve DDD'nin ne zaman gerçek bir yatırım olduğunu anlatan rehber.