Hexagonal Architecture: Ports & Adapters — Overview (Part 1)
Bu seride, hexagonal (ports & adapters) yaklaşımını, geliştirmiş olduğum demo projem ile payment-service mikroservisi üzerinden uçtan uca…
Hexagonal Architecture: Ports & Adapters — Overview (Part 1)
Bu seride, hexagonal (ports & adapters) yaklaşımını, geliştirmiş olduğum demo projem ile payment-service mikroservisi üzerinden uçtan uca özetliyor olacağım.
Sonraki bölümlerde aynı çerçevede outbox + inbox ve saga konularına da değineceğim. Ancak burada özellikle demo projedeki saga/mikroservis karmaşasına girmeden, hexagonal mimariyi daha sade anlatabileceğim bir kesit seçtim.
Neden böyle bir mimariye ihtiyaç duyuyoruz?
Çoğumuz backend geliştirmeye klasik layered architecture ile başlıyoruz:
Controller → Service → Repository → Database
İlk bakışta oldukça temiz ve anlaşılır bir yapı gibi görünüyor ancak sistem büyüdükçe işler yavaş yavaş karışmaya başlıyor.
Özellikle domain karmaşası arttıkça aşağıdaki durumlar sıkça karşımıza çıkıyor:
- Service katmanı hem business logic hem de infrastructure detaylarını taşımaya başlıyor
- JPA entity’ler zamanla domain model yerine geçiyor
- Controller → Service → Repository akışı içinde iş kuralları katmanlar arasında dağılıyor, yani business kodu olmaması gereken katmanda karşımıza çıkabiliyor
- Basit bir senaryoyu test etmek için database, Spring context, hatta messaging tool’larını bile ayağa kaldırmak gerekiyor
Bir süre sonra şu sorular kaçınılmaz oluyor:
“Business logic tam olarak nerede?” “Bu iş kuralını neden izole test edemiyorum?” “Neden küçük bir değişiklik her katmanı etkiliyor?”
Buradaki kırılmanın asıl sebebi: Dependency Inversion ihlali
Bu problem aslında doğrudan SOLID prensiplerinin D harfine karşılık gelen Dependency Inversion Principle (DIP) ile ilgilidir.
DIP şunu söyler:
Üst seviye modüller (business logic), alt seviye modüllere (database, framework, external sistemler) bağımlı olmamalıdır. Her ikisi de abstraction’a bağımlı olmalıdır.
Layered architecture’da ise genelde şu yapıda olur:
Service → Repository → Database
Yani:
- Business logic (service), doğrudan repository’ye bağımlıdır
- Repository de database’e bağımlıdır
Bu da şu anlama gelir:
Business logic, doğrudan teknik detaylara bağımlı hale gelir.

Görsel 1 — DIP Yönünden Mimari Karşılaştırma
Hexagonal Architecture neyi değiştiriyor?
Hexagonal Architecture (Ports & Adapters), uygulamanın iş mantığını (core / domain) dış dünyadan (database, external API, UI, messaging vs.) izole etmeyi amaçlayan bir mimari yaklaşımdır. Bu yaklaşım Alistair Cockburn tarafından ortaya atılmıştır.
Bu mimariyi konuşurken pratikte sık duyduğumuz iki kavram vardır:
- port → dış dünya ile konuşmak için tanımlanan contract (interface)
- adapter → bu contract’ın somut teknoloji ile implement edilmesi (JPA, Kafka client, Redis, REST controller…)
Application core, dış dünyaya doğrudan bağımlı değildir.
Bağımlılık yönü nasıl değişiyor?
Klasik yapı:
Service → Repository → Database
Hexagonal yaklaşım:
Domain → Port ← Adapter ← Infrastructure
Hexagonal yaklaşım ile artık:
- Domain sadece abstraction’ları (port) tanımlar
- Infrastructure bu abstraction’ları implement eder
Yani:
Bağımlılık yönü tersine çevrilir (DIP uygulanır).

Görsel 2 — Hexagonal Mimariye Genel Bakış
Ortadaki yapıyı parça parça okuyalım
Yukarıdaki Görsel 2 aslında her şeyi tek seferde anlatıyor ama ilk bakışta göze biraz kalabalık gelebilir.
O yüzden gelin bunu daha basit bir şekilde düşünelim: Bir istek sisteme geliyor ve içeride adım adım ilerliyor.
1. Driving side (Primary Adapters) — “İstek nereden geliyor?”
Her şeyin başladığı yer burasıdır.

Görsel 3 — Primary Adapters
Buradaki bileşenlerin ortak özelliği şu:
Sistemi tetikleyen taraf burası.
Bu bir:
- HTTP request olabilir
- Queue’dan gelen bir mesaj olabilir
- Ya da CLI / UI üzerinden gelen bir aksiyon olabilir
Hexagonal terminolojide buraya driving (primary) adapter deniyor.
Ama daha sade düşünürsek:
“Bu use case’i kim başlattı?” sorusunun cevabı burası.
2. Use Case / Application Service — “Ne yapmak istiyoruz?”
İstek içeri girdiğinde ilk durduğu yer burasıdır:

Görsel 4 — Use Case
Burayı şöyle düşünebilirsin:
“Bu sistemden ne istiyorum?”
Örneğin:
- kullanıcı oluştur
- ödeme başlat
- sipariş tamamla vb.
Bu katman:
- İş akışını yönetir
- Gerekirse birden fazla domain objesini koordine eder
- Ama kendisi “iş kuralı” yazmaz
Yani orchestration yapar, domain’e delegasyon yapar.
3. Domain Layer — “Gerçek business logic burada”
Bir adım daha içeri girdiğimizde domain’e geliyoruz:

Görsel 5— Domain Layer
Burası işin en kritik kısmı.
Sistemin gerçek davranışı burada tanımlı.
Örneğin:
- “bir kullanıcı şu şartlarda oluşturulabilir”
- “bir ödeme şu durumda başarısız sayılır”
Bu katman için önemli olan şey şu:
- JPA yok
- Kafka yok
- REST yok
Sadece iş kuralları var.
4. Port Interfaces — “Dışarıdan neye ihtiyacım var?”
Domain tek başına çalışmaz. Bir noktada dış dünyaya ihtiyaç duyar.
İşte o ihtiyaçların tanımlandığı yer:

Görsel 6 — Ports
Burada kritik bir bakış açısı vardır:
Domain “nasıl yapılacağını” değil, “neye ihtiyacı olduğunu” söyler.
Örneğin:
- “kullanıcıyı kaydetmem lazım” → persistence port
- “başka bir servise istek atmam lazım” → external API port
- “bir event publish etmem lazım” → event publisher port
Ama domain şunu bilmez:
- JPA mı kullanılacak?
- Atılacak istek REST mi, SOAP mı?
- Bu iş Kafka ile mi yapılacak?
Özetle bunlar domain’in problemi değil.
5. Driven side (Secondary Adapters) — “Bunu teknik olarak nasıl yaptım?”
En dış katmana geldiğimizde artık tamamen teknoloji konuşuyoruz:

Görsel 7 — Secondary Adapters
Buradaki adapter’ların görevi çok net:
Domain’in tanımladığı port’ları implement etmek.
Örneğin:
- Persistence port → JPA ile implement edilir
- External API port → Feign / REST client ile implement edilir
- Event publisher port → Kafka ile implement edilir
Ve en önemli nokta:
Domain bu detayların hiçbirini bilmez.
Özetle
Tüm akışı tek cümlede şöyle düşünebilirsin:
İstek dış dünyadan gelir → use case’e ulaşır → domain’de işlenir → ihtiyaçlar port üzerinden tanımlanır → adapter’lar port’larda tanımlı abstract contract’ları implement eder ve somut hale getirir.
Bu noktadan sonra artık teorik kısmı bırakıp, bunu gerçek bir servis üzerinde görmek çok daha anlamlı oluyor.
Bir sonraki bölümde aynı akışı demo projede payment-service üzerinden uçtan uca inceleyeceğiz.
메타데이터
- post_id
- 2b39b7dda74a
- slug
- hexagonal-architecture-ports-adapters-overview-part-1-2b39b7dda74a
- url
- https://medium.com/@tarikgoren58/hexagonal-architecture-ports-adapters-overview-part-1-2b39b7dda74a
- canonical_url
- https://medium.com/@tarikgoren58/hexagonal-architecture-ports-adapters-overview-part-1-2b39b7dda74a
- author_url
- https://medium.com/@tarikgoren58
- status
- ok
- fetched_at
- 2026-07-30 02:57:19