Gökmen Tuksavul

Blog Yazısı

2026-07-26

Angular Projelerinde Temiz Mimari

Kurumsal Angular projelerinde Clean Architecture, Signals ve modern state yönetimi ile ölçeklenebilir frontend mimarisi kurmanın yollarını keşfedin.

AngularArchitectureTypeScript

Sponsorlu

Kurumsal Angular projelerinde temiz mimari, klasör adlarını değiştirmekten çok değişiklik maliyetini düşürme disiplinidir. Proje büyüdükçe component içine yazılan iş kuralları, doğrudan çağrılan HTTP servisleri ve tekrar eden validasyonlar teslimatı yavaşlatır. Bu yüzden feature-based yapı, domain fonksiyonları ve sade data-access katmanı birlikte düşünülmelidir.

Feature sınırları

Sipariş, kullanıcı, rapor veya teklif gibi ürün alanları kendi page, component, data-access ve domain dosyalarına sahip olmalıdır. Shared klasörü yalnızca gerçekten ortak UI parçaları için kullanılmalıdır. Böylece yeni bir geliştirici değişiklik yapacağı alanı daha hızlı bulur ve ekip içi çakışma azalır.

Component içinde iş kuralı tutmamak

Bir siparişin iptal edilebilir olup olmadığı veya bir kullanıcının butonu görüp görmeyeceği sadece görsel karar değildir. Aynı kural API isteğinde, liste filtresinde ve detay ekranında da kullanılabilir. Bu nedenle bu kararlar test edilebilir domain fonksiyonlarına taşınmalıdır.

Signals ve RxJS dengesi

Signals component içindeki senkron UI durumu için uygundur: seçili tab, açık modal, filtre ve hesaplanan değerler. RxJS ise HTTP akışı, debounce, retry, polling ve stream birleştirme gibi zaman bazlı işler için daha doğrudur. İkisini rakip görmek yerine sınırlarını net çizmek gerekir.

Test yaklaşımı

Domain fonksiyonları Angular bağımlılığı olmadan unit test ile doğrulanmalıdır. API servisleri HTTP mock testleriyle, kritik kullanıcı akışları ise az sayıda uçtan uca testle korunabilir. Her component için ağır test yazmak yerine riskli karar noktalarını kapsamak daha verimli sonuç verir.

Sonuç

Temiz mimari, projeyi akademik göstermek için değil, teslimatı sürdürülebilir kılmak için uygulanır. Feature sahipliği, sade component, test edilebilir domain kuralı ve kontrollü state yönetimi birleştiğinde Angular projesi büyüse bile okunabilir kalır.

Pratik uygulama notu

Bu yaklaşımı yeni bir projeye taşırken önce klasör yapısını değil, değişiklik nedenlerini çıkarırım. En sık değişen ekranlar, ortak validasyonlar ve API sınırları belirlendikten sonra feature ayrımı daha doğru yapılır. Mevcut projede ise büyük taşıma yerine önce bir feature seçip component içindeki iş kurallarını domain fonksiyonlarına almak daha düşük risklidir.

Sınırları Dosya Adlarıyla Değil Davranışla Kurun

Angular projesinde components, services ve models klasörleri oluşturmak tek başına temiz mimari sağlamaz. Asıl amaç, bir iş alanındaki değişikliğin uygulamanın ilgisiz bölümlerine yayılmasını engellemektir. Sipariş, katalog ve kimlik gibi alanları feature sınırlarına ayırın; her feature kendi rota, ekran, veri erişim adaptörü ve iş kurallarını barındırsın. Uygulama genelinde kullanılan gerçekten ortak, iş alanından bağımsız parçalar shared altında kalabilir.

Bir bileşen HTTP istemcisini doğrudan çağırıyor, API DTO'sunu ekrana bağlıyor ve iş kuralını template içinde hesaplıyorsa üç farklı değişim nedeni aynı yerde toplanmış olur. API alan adı değiştiğinde ekranın kırılması bunun tipik belirtisidir. DTO'yu uygulamanın kullandığı modele dönüştüren bir mapper ve veri kaynağını soyutlayan bir gateway bu bağı azaltır.

Örnek Feature Yapısı

orders/
  data-access/
    orders-api.gateway.ts
    orders.mapper.ts
  domain/
    order.ts
    order-total.ts
  feature-list/
    order-list.page.ts
  ui/
    order-status-badge.component.ts
  orders.routes.ts

domain katmanı Angular'a özgü dekoratörlere ihtiyaç duymayan saf TypeScript kodu olduğunda test edilmesi kolaylaşır. data-access API ayrıntılarını saklar. Sayfa bileşeni kullanıcı etkileşimini orkestre eder, sunum bileşenleri ise input/output sözleşmeleriyle çalışır. Her küçük fonksiyon için katman üretmek yerine yalnızca gerçek değişim sınırlarını ayırın.

Signals ve RxJS İçin Sorumluluk Paylaşımı

Signals yerel ve türetilmiş ekran durumu için güçlüdür: seçili filtre, yükleniyor bilgisi veya toplam tutar gibi değerler signal ve computed ile okunaklı kalır. RxJS ise zaman içinde akan olaylar, iptal edilebilir HTTP aramaları, websocket veya birden fazla asenkron kaynağı birleştirme için uygundur. Her Observable'ı Signal'a ya da her Signal'ı Observable'a çevirmek gereksiz adaptör kodu üretir.

Arama kutusunda debounceTime ve switchMap kullanmak önceki HTTP isteğini iptal etme davranışını açıkça ifade eder. API'den gelen son sonucu toSignal ile template'e sunmak ise iki aracın doğal sınırda buluştuğu bir örnektir. Kararı ekip modasına göre değil, durumun senkron mu yoksa zaman tabanlı mı olduğuna göre verin.

Bağımlılık Yönünü Testlerle Koruma

Mimari yalnızca dokümana yazılırsa zamanla aşınır. Domain kodunun Angular, HTTP veya UI modüllerini import etmediğini lint kuralıyla kontrol edin. Feature'lar arası doğrudan derin import yerine public API kullanın. Unit testlerde saf iş kurallarını hızlı çalıştırın; gateway testlerinde HTTP sözleşmesini, sayfa testlerinde kritik kullanıcı akışını doğrulayın.

Kod incelemesinde şu sorular yararlıdır:

  • Bu değişiklik kaç feature'a dokunuyor ve neden?
  • API modeli UI içinde doğrudan kullanılıyor mu?
  • İş kuralı template veya component yaşam döngüsüne gömülmüş mü?
  • Yeni soyutlama ikinci bir gerçek kullanım olmadan mı eklendi?
  • Hata, boş durum ve yükleme durumu kullanıcıya açıkça gösteriliyor mu?

Temiz mimarinin başarısı klasör sayısıyla değil değişiklik maliyetiyle ölçülür. Yeni bir ödeme sağlayıcısı eklerken katalog ekranlarını değiştirmiyor, iş kurallarını Angular başlatmadan test edebiliyor ve ekip feature sınırlarını kolayca anlayabiliyorsa yapı görevini yerine getiriyor demektir.