Typescript Projelerinde Clean Architecture Prensipleri Nasıl Uygulanır?

Typescript Projelerinde Clean Architecture Prensipleri Nasıl Uygulanır?
Typescript Projelerinde Clean Architecture Prensipleri Nasıl Uygulanır?

TypeScript Projelerinde Clean Architecture Prensipleri Nasıl Uygulanır?

Modern yazılım dünyasında, özellikle ölçeklenebilir ve sürdürülebilir TypeScript projelerinde Clean Architecture prensiplerini uygulamak, kod tabanının karmaşıklığını yönetmek için kritik bir stratejidir. Robert C. Martin tarafından ortaya konan bu mimari yaklaşım, iş mantığını dış dünyadan (veritabanları, framework'ler, UI) tamamen izole etmeyi hedefler. 2026 yılı itibarıyla TypeScript'in sunduğu güçlü tip güvenliği ve modüler yapı, Clean Architecture'ın katmanlı yapısını uygulamak için ideal bir zemin hazırlamaktadır.

Bir TypeScript projesinde Clean Architecture uygulamak, sadece klasör yapısını değiştirmek değil, aynı zamanda bağımlılık akışını (Dependency Rule) disiplin altına almaktır. Bu rehberde, projenizi nasıl daha test edilebilir ve bağımsız hale getirebileceğinizi, adım adım teknik detaylarla ele alacağız. Doğru uygulanan bir mimari, projenin uzun vadeli bakım maliyetlerini düşürürken, ekip içi adaptasyon sürecini de hızlandıracaktır.

Clean Architecture'ın Temel Katmanları ve TypeScript Yapılandırması

Clean Architecture, iç içe geçmiş halkalardan oluşan bir yapıya sahiptir. En içte yer alan katman en yüksek seviyeli politikaları, en dışta yer alan katman ise detayları (veritabanı, API, UI) temsil eder. TypeScript projelerinde bu katmanları klasör yapısı olarak şu şekilde organize etmelisiniz:

Entities (Varlıklar)

Projenin merkezinde yer alan iş kurallarını ve veri modellerini içerir. TypeScript'te bu katman, saf arayüzler (interface) veya sınıflardan (class) oluşur. Hiçbir dış kütüphaneye veya framework'e bağımlılığı olmamalıdır. Örneğin, bir kullanıcı varlığı sadece kullanıcıya ait temel özellikleri ve bu özellikler üzerindeki saf iş mantığını barındırır.

Use Cases (İş Durumları)

Uygulamanın spesifik iş akışlarını yönetir. Entities katmanındaki verileri kullanarak iş mantığını yürütür. TypeScript'te bu katman genellikle "Service" veya "Interactor" olarak adlandırılır. Dış dünya ile olan etkileşimi tamamen soyutlanmış arayüzler (interface) üzerinden gerçekleştirir.

Bağımlılık Kuralı ve TypeScript'te Soyutlama

Clean Architecture'ın en önemli kuralı şudur: Bağımlılıklar her zaman içe doğru olmalıdır. Yani, iç katmanlar dış katmanlar hakkında hiçbir şey bilmemelidir. TypeScript'te bu kuralı uygulamak için "Dependency Inversion" (Bağımlılığın Tersine Çevrilmesi) prensibini kullanırız.

Interface Kullanımının Önemi

Use Case katmanınız bir veritabanı işlemi yapacaksa, doğrudan bir veritabanı kütüphanesini (örneğin Prisma veya TypeORM) içeri aktarmamalısınız. Bunun yerine, bir "Repository Interface" tanımlamalısınız. Use Case, bu arayüze bağımlı olur; gerçek veritabanı implementasyonu ise en dış katmanda (Infrastructure) yapılır.

Kritik Uyarı: TypeScript'te "any" türü kullanımı, Clean Architecture prensiplerini doğrudan bozar. Katmanlar arası geçişlerde mutlaka tanımlı arayüzleri ve katı tip denetimini kullanın. Aksi takdirde, mimari izolasyonunuz sadece dosya yapısında kalır ve kod seviyesinde birbirine karışır.

TypeScript Projelerinde Katmanlı Mimariyi Adım Adım Uygulama

Bir projeye başlarken veya mevcut bir projeyi dönüştürürken şu adımları izlemek, geçiş sürecini daha yönetilebilir kılar:

  1. Klasör Yapısını Hazırlayın: Projenizi domain, use-cases, adapters ve infrastructure olarak ayırın.
  2. Domain Katmanını Tanımlayın: İş mantığınızı ve veri yapılarınızı hiçbir framework bağımlılığı olmadan oluşturun.
  3. Repository Arayüzlerini Belirleyin: Dış dünya ile veri alışverişi yapacak tüm noktalar için TypeScript interface'leri oluşturun.
  4. Use Case'leri Yazın: İş mantığını bu arayüzleri kullanarak kurgulayın.
  5. Infrastructure Katmanını Implemente Edin: Repository arayüzlerinin gerçek veritabanı veya API çağrılarını yapan somut sınıflarını yazın.
  6. Dependency Injection (DI) Kurun: Uygulama başlangıcında (main.ts veya benzeri), arayüzlerin somut karşılıklarını enjekte edin.

Clean Architecture ve Geleneksel Mimari Karşılaştırması

Hangi mimari yaklaşımın projeniz için uygun olduğunu anlamak adına aşağıdaki karşılaştırma tablosunu inceleyebilirsiniz:

Özellik Geleneksel (MVC/Layered) Clean Architecture
Bağımlılık Yönü Genellikle dışa doğru Her zaman içe doğru
Test Edilebilirlik Düşük (Mocking zor) Çok Yüksek (İzole test)
Framework Bağımlılığı Yüksek Yok denecek kadar az
Öğrenme Eğrisi Kolay Zor

Sıkça Sorulan Sorular

Clean Architecture TypeScript projelerinde performansı düşürür mü?

Clean Architecture, doğru uygulandığında performansı doğrudan düşürmez. Ancak, aşırı soyutlama ve gereksiz katman geçişleri (boilerplate kodlar) küçük projelerde gereksiz bir karmaşıklık yaratabilir. Performans üzerindeki etkisi, mimariden ziyade yazdığınız kodun verimliliği ile ilgilidir.

Küçük ölçekli projeler için bu mimari uygun mudur?

Küçük projelerde Clean Architecture uygulamak, "over-engineering" olarak adlandırılan gereksiz karmaşıklığa yol açabilir. Projenin büyüme potansiyeli yoksa, daha basit bir katmanlı yapı tercih edilebilir. Ancak, proje zamanla büyüyecekse, başlangıçta bu mimariyi kurmak uzun vadede büyük avantaj sağlar.

Dependency Injection (DI) kütüphanesi kullanmalı mıyım?

TypeScript projelerinde InversifyJS veya NestJS'in yerleşik DI yapısı gibi araçlar, bağımlılık yönetimini kolaylaştırır. Ancak, bu kütüphaneler olmadan da "Constructor Injection" yöntemiyle manuel olarak bağımlılıkları yönetebilirsiniz. Önemli olan, DI kütüphanesine bağımlı kalmadan mimariyi kurgulamaktır.

Veritabanı şemaları ile Domain modelleri nasıl ayrılır?

Domain modelleri, iş kurallarını yansıtır. Veritabanı şemaları ise (ORM modelleri) verinin saklanma biçimini yansıtır. Bu ikisini birbirinden ayırmalı ve bir "Mapper" katmanı kullanarak veritabanından gelen veriyi Domain modeline dönüştürmelisiniz.

Clean Architecture'a geçiş yaparken mevcut kodu nasıl bölmeliyim?

Mevcut bir projeyi dönüştürmek için "Strangler Fig" desenini kullanabilirsiniz. Önce en az bağımlılığı olan modülden başlayarak, onu bir "Use Case" haline getirin ve yavaş yavaş diğer parçaları bu mimariye çekin. Hepsini bir anda değiştirmeye çalışmak riskli olabilir.

Sonuç

TypeScript projelerinde Clean Architecture prensiplerini uygulamak, başlangıçta zorlayıcı bir süreç gibi görünse de, projenin yaşam döngüsü boyunca sağladığı esneklik paha biçilemezdir. İş mantığınızı dış dünyadan izole ederek, teknoloji değişikliklerine karşı projenizi koruma altına alırsınız. Bu rehberde paylaşılan adımlar, modern yazılım geliştirme süreçlerinde temiz, sürdürülebilir ve test edilebilir kodlar yazmanıza yardımcı olacaktır. Mimari kararlar alırken her zaman projenizin özel ihtiyaçlarını ve ekip yetkinliklerini göz önünde bulundurmayı unutmayın; karmaşıklığı yönetmek, mimarinin temel amacıdır.

TypeScript Projelerinde Clean Architecture Prensipleri Nasıl Uygulanır?

Modern yazılım dünyasında, özellikle TypeScript gibi statik tipli dillerin yaygınlaşmasıyla birlikte, kodun sürdürülebilirliği kritik bir önem kazanmıştır. Clean Architecture (Temiz Mimari), Robert C. Martin tarafından ortaya konan ve yazılımın iş kurallarını dış dünyadan (frameworkler, veritabanları, UI) izole etmeyi amaçlayan bir yaklaşımdır. TypeScript projelerinde bu prensipleri uygulamak, projenin uzun vadede "teknik borç" biriktirmesini engeller.

Clean Architecture'ın Temel Katmanları ve TypeScript Yapılandırması

Clean Architecture, iç içe geçmiş halkalar şeklinde düşünülmelidir. En içte Entities yer alırken, dışa doğru Use Cases, Controllers/Presenters ve en dışta Infrastructure katmanları bulunur. TypeScript'in modüler yapısı, bu katmanları klasör yapısıyla birbirinden kesin çizgilerle ayırmamıza olanak tanır.

Entities (Varlıklar)

Entities, uygulamanın kalbidir. İş kurallarını (Business Rules) barındırırlar. TypeScript'te bu katman, herhangi bir kütüphaneye veya framework'e (Express, TypeORM, Prisma vb.) bağımlı olmamalıdır. Sadece saf TypeScript sınıfları veya interface'leri kullanılmalıdır.

Use Cases (İş Durumları)

Use Cases, uygulamanın ne yapacağını tanımlar. Bir kullanıcı kaydı oluşturmak, bir ödeme işlemini gerçekleştirmek gibi spesifik iş mantıkları burada bulunur. Use Case katmanı, Entity katmanını kullanır ancak dış dünyadan gelen verinin nasıl işleneceğini yönetir.

Bağımlılık Kuralı ve TypeScript'te Soyutlama

Clean Architecture'ın altın kuralı: Bağımlılıklar her zaman içe doğrudur. İç katmanlar dış katmanlar hakkında hiçbir şey bilmemelidir. TypeScript'te bu kuralı uygulamak için "Dependency Inversion" (Bağımlılığın Tersine Çevrilmesi) prensibi kullanılır.

Interface Kullanımının Önemi

TypeScript'teki interface anahtar kelimesi, soyutlama yapmanın en güçlü aracıdır. Örneğin, bir veritabanı işlemini doğrudan bir repository sınıfına bağlamak yerine, bir interface tanımlayarak Use Case katmanını bu interface'e bağımlı kılarız. Böylece veritabanı teknolojisi değişse bile iş mantığınız etkilenmez.

TypeScript Projelerinde Katmanlı Mimariyi Adım Adım Uygulama

  1. Klasör Yapısını Oluşturun: src/domain, src/application, src/infrastructure şeklinde klasörleri ayırın.
  2. Domain Modellerini Tanımlayın: Hiçbir bağımlılığı olmayan saf TS sınıfları oluşturun.
  3. Repository Interface'leri Belirleyin: Domain katmanında veriye erişim için gerekli interface'leri tanımlayın.
  4. Use Case'leri Yazın: İş mantığını bu interface'leri kullanarak kodlayın.
  5. Infrastructure Katmanını Enjekte Edin: Repository interface'lerini somut sınıflarla (örneğin Prisma veya TypeORM ile) uygulayın.

Clean Architecture ve Geleneksel Mimari Karşılaştırması

Özellik Geleneksel Mimari (MVC vb.) Clean Architecture
Bağımlılık Yönü Dışa doğru (Framework odaklı) İçe doğru (Domain odaklı)
Test Edilebilirlik Düşük (Mock'lama zor) Yüksek (Saf TS kodları)
Değişim Maliyeti Yüksek (Framework bağımlılığı) Düşük (Tak-çıkar sistemler)

Clean Architecture Uygularken Yapılan Sık Hatalar

  • Entity'lerde Framework Kullanımı: Entity sınıflarının içine veritabanı dekoratörleri (örneğin @Entity()) eklemek, mimariyi bozar.
  • Katmanları Atlamak: Küçük bir iş için doğrudan Controller'dan Database'e gitmek, Clean Architecture'ın amacını yitirmesine neden olur.
  • Aşırı Mühendislik (Over-engineering): Her küçük proje için devasa bir klasör yapısı kurmak, geliştirme hızını gereksiz yere düşürebilir.

Dependency Injection (DI) ve Araç Seçimi

TypeScript projelerinde Clean Architecture uygularken, bağımlılıkları manuel yönetmek bir süre sonra karmaşıklaşabilir. InversifyJS veya TSyringe gibi DI kütüphaneleri, katmanlar arasındaki bağımlılıkları yönetmek için profesyonel çözümler sunar. Ancak, DI kütüphanesi kullanmak zorunlu değildir; basit projelerde "Constructor Injection" yöntemiyle bağımlılıkları elle enjekte etmek de yeterli olabilir.

Güvenlik ve Validasyon

Clean Architecture'da güvenlik, her katmanda ayrı ele alınmalıdır. Input Validation (Girdi Doğrulama) işlemi, Infrastructure katmanından Use Case katmanına geçişte yapılmalıdır. Zod veya Joi gibi kütüphaneler, gelen verinin Domain modeline uygunluğunu denetlemek için ideal araçlardır.

Veritabanı Şemaları ile Domain Modelleri Nasıl Ayrılır?

Domain modelleri, iş kurallarını yansıtır. Veritabanı şemaları ise (ORM modelleri) verinin saklanma biçimini yansıtır. Bu ikisini birbirinden ayırmalı ve bir "Mapper" katmanı kullanarak veritabanından gelen veriyi Domain modeline dönüştürmelisiniz.

Clean Architecture'a geçiş yaparken mevcut kodu nasıl bölmeliyim?

Mevcut bir projeyi dönüştürmek için "Strangler Fig" desenini kullanabilirsiniz. Önce en az bağımlılığı olan modülden başlayarak, onu bir "Use Case" haline getirin ve yavaş yavaş diğer parçaları bu mimariye çekin. Hepsini bir anda değiştirmeye çalışmak riskli olabilir.

Sonuç

TypeScript projelerinde Clean Architecture prensiplerini uygulamak, başlangıçta zorlayıcı bir süreç gibi görünse de, projenin yaşam döngüsü boyunca sağladığı esneklik paha biçilemezdir. İş mantığınızı dış dünyadan izole ederek, teknoloji değişikliklerine karşı projenizi koruma altına alırsınız. Bu rehberde paylaşılan adımlar, modern yazılım geliştirme süreçlerinde temiz, sürdürülebilir ve test edilebilir kodlar yazmanıza yardımcı olacaktır. Mimari kararlar alırken her zaman projenizin özel ihtiyaçlarını ve ekip yetkinliklerini göz önünde bulundurmayı unutmayın; karmaşıklığı yönetmek, mimarinin temel amacıdır.

Clean Architecture Uygularken Yapılan Sık Hatalar

TypeScript projelerinde Clean Architecture'a geçiş yaparken geliştiricilerin sıklıkla düştüğü bazı tuzaklar, mimarinin sunduğu avantajları tamamen ortadan kaldırabilir. İşte kaçınmanız gereken en kritik hatalar:

  • Domain Katmanına Kütüphane Sızdırması: Domain modellerinizin içine class-validator veya typeorm gibi dış dünyayı temsil eden kütüphane dekoratörlerini eklemek, katmanlar arası izolasyonu bozar. Domain katmanı, dış dünyadan tamamen habersiz olmalıdır.
  • "Anemic Domain Model" Tuzağı: Sadece getter/setter içeren modeller oluşturmak, iş mantığını Use Case'lere yığmanıza neden olur. İş mantığını (business logic) mümkün olduğunca Entities içinde tutmaya çalışın.
  • Mapper Katmanını İhmal Etmek: Veritabanı modelini doğrudan Use Case'e döndürmek, veritabanı şemasındaki bir değişikliğin tüm katmanları etkilemesine yol açar. Mapper kullanımı, bu bağımlılığı kırmak için zorunludur.
  • Aşırı Mühendislik (Over-Engineering): Küçük bir CRUD uygulamasında bile onlarca interface ve klasör yapısı oluşturmak, geliştirme hızını gereksiz yere düşürür. Mimarinin karmaşıklığını projenin ölçeğine göre ayarlayın.

Dependency Injection (DI) ve Araç Seçimi

Clean Architecture'da bağımlılıkların yönetimi (Dependency Inversion prensibi) hayati önem taşır. TypeScript dünyasında bu süreci yönetmek için bazı araçlar öne çıkmaktadır:

Neden DI Kullanmalıyız?

DI, sınıfların bağımlılıklarını kendilerinin oluşturması yerine dışarıdan enjekte edilmesini sağlar. Bu, özellikle birim testleri (unit testing) yazarken mock nesneleri kullanmanızı kolaylaştırır.

Popüler Araçlar

  • InversifyJS: TypeScript için en popüler ve güçlü DI konteyneridir. Dekoratör tabanlı yapısı ile büyük projelerde oldukça etkilidir.
  • TSyringe: Microsoft tarafından desteklenen, daha hafif ve modern bir DI çözümüdür.
  • Manual DI: Küçük ölçekli projelerde karmaşık kütüphaneler yerine, constructor injection yöntemiyle bağımlılıkları elle yönetmek çoğu zaman yeterlidir.

Güvenlik ve Validasyon Stratejileri

Clean Architecture'da güvenlik, tek bir katmana değil, katmanlar arası geçişlere yayılmalıdır. Özellikle veri girişi ve yetkilendirme süreçlerinde şu yöntem izlenmelidir:

1. Giriş Validasyonu (Input Validation)

API katmanında (Controller), kullanıcıdan gelen verinin formatı (tip, uzunluk, zorunluluk) doğrulanmalıdır. Bu, iş mantığına hatalı veri sızmasını engeller.

2. İş Mantığı Validasyonu (Domain Validation)

Domain katmanında ise verinin "iş kurallarına" uygunluğu kontrol edilir. Örneğin; bir banka hesabından para çekilirken, "bakiyenin yeterli olması" bir iş mantığıdır ve bu kontrol Entities veya Use Case içinde yapılmalıdır.

Clean Architecture ve Geleneksel Mimari Karşılaştırması

Aşağıdaki tablo, geleneksel "Katmanlı Mimari" ile "Clean Architecture" arasındaki temel farkları özetlemektedir:

Özellik Geleneksel Mimari Clean Architecture
Bağımlılık Yönü Dıştan içe doğru İçten dışa doğru
Test Edilebilirlik Zor (Veritabanı bağımlı) Çok Kolay (Mock edilebilir)
Teknoloji Değişimi Tüm yapıyı etkiler Sadece adaptörleri etkiler
Karmaşıklık Düşük Yüksek

Örnek Senaryo: Kullanıcı Kaydı

Bir kullanıcı kayıt sürecini Clean Architecture ile şu şekilde kurgularız:

  1. Controller: HTTP isteğini alır, veriyi DTO'ya (Data Transfer Object) dönüştürür.
  2. Use Case: RegisterUserUseCase çağrılır. Bu sınıf, email adresinin daha önce alınıp alınmadığını kontrol etmek için UserRepository arayüzünü kullanır.
  3. Repository Interface: Domain katmanında tanımlanır.
  4. Infrastructure: UserRepository'nin gerçek veritabanı (PostgreSQL, MongoDB vb.) implementasyonu burada yapılır.
  5. Entity: User sınıfı, şifre hashleme veya email formatı gibi temel kuralları kendi içinde yönetir.
Profesyonel İpucu: TypeScript'in interface ve abstract class yapılarını kullanarak, domain katmanınızın asla dış kütüphanelere (TypeORM, Prisma, Axios vb.) doğrudan referans vermediğinden emin olun. Her zaman soyutlamalar üzerinden ilerleyin.

Veritabanı Şemaları ile Domain Modelleri Nasıl Ayrılır?

Birçok geliştirici, veritabanı tablolarını doğrudan uygulama içinde "model" olarak kullanma hatasına düşer. Bu, veritabanı şemasındaki bir değişikliğin tüm iş mantığını bozmasına neden olur. Ayrımı şu şekilde yapmalısınız:

  • Domain Modeli: İş mantığını temsil eder. Saf TypeScript sınıflarıdır. Veritabanı ile ilgili hiçbir bilgi içermez (Örn: UserEntity).
  • Persistence Modeli: Veritabanı şemasını temsil eder. ORM kütüphanesinin dekoratörlerini içerir (Örn: UserSchema).
  • Mapper: Bu iki model arasında dönüşüm yapan fonksiyonlardır. Veritabanından gelen veriyi iş mantığının anlayacağı formata çevirirler.

Bu ayrım sayesinde, veritabanınızı yarın PostgreSQL'den MongoDB'ye taşımak isterseniz, sadece Infrastructure katmanındaki Mapper ve Repository sınıflarını değiştirmeniz yeterli olacaktır; iş mantığınız (Use Case'leriniz) bu değişiklikten etkilenmeyecektir.

Clean Architecture Uygularken Yapılan Sık Hatalar

TypeScript projelerinde Clean Architecture uygularken yapılan hatalar, genellikle mimarinin sunduğu esnekliği kısıtlayan ve "spagetti kod" yapısına geri dönülmesine neden olan yaklaşımlardır. İşte en sık karşılaşılan hatalar:

  • Domain Katmanına Dış Bağımlılık Eklemek: En büyük hata, iş mantığının bulunduğu katmana bir HTTP istemcisi veya ORM kütüphanesi import etmektir. Domain katmanı sadece saf TypeScript mantığını içermelidir.
  • Mapper Kullanımını İhmal Etmek: Veritabanı modellerini doğrudan iş mantığında kullanmak, mimariyi veritabanı şemasına bağımlı kılar. Mapper sınıflarının eksikliği, katmanlar arası geçişte veri sızıntısına neden olur.
  • Too-Big-Service (Devasa Servisler) Anti-Pattern'i: Use Case'leri tek bir büyük "UserService" dosyasına yığmak, Clean Architecture'ın "tek sorumluluk" prensibine aykırıdır. Her bir iş durumu (örneğin: RegisterUserUseCase, UpdateUserEmailUseCase) ayrı bir sınıf veya fonksiyon olmalıdır.
  • Interface'lerin Aşırı Kullanımı veya Yetersizliği: Her küçük işlem için interface oluşturmak gereksiz karmaşıklık yaratırken, hiç interface kullanmamak katmanlar arası sıkı bağımlılığa (tight coupling) yol açar.

Dependency Injection (DI) ve Araç Seçimi

Clean Architecture'da bağımlılıklar dışarıdan enjekte edilmelidir. Bu, test edilebilirliği artırır ve kodun modülerliğini korur. TypeScript dünyasında bu süreci yönetmek için bazı araçlar öne çıkmaktadır.

Neden DI Kullanmalıyız?

DI, bir sınıfın ihtiyaç duyduğu bağımlılıkları (örneğin bir veritabanı repository'si) kendi içinde oluşturması yerine, dışarıdan (genellikle bir constructor üzerinden) almasını sağlar. Bu sayede birim test (unit test) yazarken gerçek veritabanı yerine "mock" nesneler kolayca enjekte edilebilir.

Popüler Araçlar

  • InversifyJS: TypeScript için geliştirilmiş en güçlü ve popüler DI container'dır. Dekoratör tabanlı yapısı ile büyük ölçekli projelerde karmaşıklığı yönetir.
  • TSyringe: Microsoft tarafından desteklenen, hafif ve kullanımı kolay bir DI kütüphanesidir.
  • NestJS Yerleşik DI: Eğer NestJS framework'ü kullanıyorsanız, kendi içerisinde oldukça gelişmiş ve performanslı bir DI mekanizması ile gelir.

Güvenlik ve Validasyon Stratejileri

Clean Architecture'da güvenlik, uygulamanın her katmanında farklı şekillerde ele alınmalıdır. Ancak en kritik nokta, verinin giriş katmanından (Controller/Adapter) iş mantığına (Use Case) geçmeden önce doğrulanmasıdır.

  1. Girdi Validasyonu (Input Validation): Dış dünyadan gelen veriler (Request Body) her zaman "kirli" kabul edilmelidir. Zod veya Joi gibi kütüphaneler kullanarak, verinin Use Case'e ulaşmadan önce şemaya uygunluğu kontrol edilmelidir.
  2. Domain Katmanında Veri Bütünlüğü: Entities, kendi iç durumlarını korumalıdır. Örneğin, bir "Email" değeri, geçersiz bir formatta asla bir UserEntity nesnesine atanmamalıdır.
  3. Yetkilendirme (Authorization): Yetkilendirme mantığı, Use Case'lerin içinde veya "Decorator" desenleri kullanılarak katmanlar arasında merkezi bir şekilde yönetilmelidir.

Clean Architecture ve Geleneksel Mimari Karşılaştırması

Aşağıdaki tablo, geleneksel "Katmanlı Mimari" ile "Clean Architecture" arasındaki temel farkları özetlemektedir:

Özellik Geleneksel Mimari Clean Architecture
Bağımlılık Yönü Dıştan içe (Veritabanı odaklı) İçten dışa (İş mantığı odaklı)
Test Edilebilirlik Düşük (Veritabanı gerektirir) Yüksek (Mock'lanabilir)
Değişim Maliyeti Yüksek (Veritabanı değişimi tüm katmanı etkiler) Düşük (Sadece Infrastructure katmanı değişir)
Öğrenme Eğrisi Kolay Zor

Örnek Senaryo: Kullanıcı Kaydı

Kullanıcı kaydı sürecini Clean Architecture ile şu şekilde kurgularız:

  1. Controller: HTTP isteğini karşılar, veriyi doğrular (Zod ile) ve RegisterUserUseCase'i tetikler.
  2. Use Case: İş mantığını yürütür. "Kullanıcı zaten kayıtlı mı?" kontrolünü yapar. Eğer değilse, UserRepository üzerinden kayıt işlemini başlatır.
  3. Domain: User entity'si, kullanıcının geçerli bir kullanıcı olup olmadığını (örneğin yaş sınırı) doğrular.
  4. Infrastructure: PostgresUserRepository, veriyi veritabanına yazar. Mapper, domain modelini veritabanı formatına çevirir.

Bu akış sayesinde, yarın bir gün kullanıcı kaydını bir mesaj kuyruğu (RabbitMQ) üzerinden asenkron yapmaya karar verirseniz, Use Case'inizde tek bir satır dahi değişiklik yapmadan sadece Infrastructure katmanında bir "EventPublisher" ekleyerek süreci yönetirsiniz.

Bu yazıya tepkinizi paylaşın:
Deniz Aydın

On yıldır dijital yayıncılıkta pratik çözüm rehberleri hazırlıyorum. Karmaşık süreçleri herkesin anlayabileceği adım adım yönergelere dönüştürme konusunda uzmanım.

Yorumlar (0)

Yorum Yaz