Hexagonal Mimari Nedir ?

Ali KARABAY
6 min readOct 23, 2022

--

Geleneksel Katmanlı Mimarilerin amacı, bir uygulamayı, her katmanın paylaşılan veya benzer sorumluluklara sahip modüller ve sınıflar içerdiği belirli görevleri gerçekleştirmek için birlikte çalıştığı farklı katmanlara ayırmaktır.

Katmanlı Mimarilerin farklı yanları vardır ve kaç katmanın olması gerektiğini belirleyen bir kural yoktur. En yaygın model, uygulamanın Sunum Katmanı, Mantık Katmanı ve Veri Katmanı olarak ayrıldığı 3 katmanlı mimaridir.

Eric Evans, Domain Driven Design: Yazılımın Kalbinde Karmaşıklıkla Mücadele adlı kitabında, iş mantığını tutan Domain Katmanı ile diğer 3 destekleyici katman arasında izolasyona izin vermek için 4 katmanlı bir mimari önerir: User Interface, Application, ve Infrastructure.

Katmanlı Mimariyi takip etmek birçok yönden faydalıdır, bunlardan biri ve en önemlisi concerns’in ayrılmasıdır. Ancak, her zaman bir risk vardır. Katmanlar arasında mantığın ne zaman leaks olduğunu tespit etmek için doğal bir mekanizma olmadığından, user interface’te serpiştirilmiş iş mantığı veya iş mantığı içinde karışık altyapı concerns’leri olabilir ve muhtemelen olacaktır.

2005'te Alistair Cockburn, user interface ve veritabanının bir uygulama ile nasıl etkileşime girdiği arasında çok fazla fark olmadığını fark etti, çünkü ikisi de benzer componentler ile değiştirilebilir ve bir uygulama ile eşdeğer yollarla etkileşime girecek harici aktörler. Olayları bu şekilde görerek, uygulamayı bu “harici” aktörlerden bağımsız tutmaya, Portlar ve Adaptörler aracılığıyla etkileşime girmelerine izin verir, böylece iş mantığı ile harici componentler arasındaki karışıklık önlenebilir.

Bu yazıda, Hexogonal Mimarinin ana kavramları, faydaları ve uyarıları konusunda size rehberlik etmeye çalışacağım ve projelerinizde bu modelden nasıl faydalanabileceğinizi basit bir şekilde anlatacağım.

Bağlantı Noktaları ve Adaptörler olarak da adlandırılan Hexogonal Mimari, kullanıcıların veya harici sistemlerin girdilerinin bir Adaptör aracılığıyla bir Bağlantı Noktasındaki Uygulamaya ulaşmasına ve çıktının Uygulamadan bir Bağlantı Noktası üzerinden gönderilmesine izin veren bir mimari modeldir. bir Adaptör uygulamanın özünü koruyan ve onu harici ve bir şekilde alakasız araçlardan ve teknolojilerden izole eden bir soyutlama katmanı oluşturur.

Port

Bir Portu teknolojiden bağımsız bir giriş noktası olarak görebiliriz, söz konusu interface’in kimin veya neyin implement edileceğine bakılmaksızın yabancı aktörlerin uygulama ile iletişim kurmasına izin verecek interface’i belirler. Tıpkı bir USB bağlantı noktasının, bir USB adaptörüne sahip oldukları sürece, birden çok türde aygıtın bir bilgisayarla iletişim kurmasına izin vermesi gibi. Bağlantı noktaları ayrıca Uygulamanın veritabanları, mesaj aracıları, diğer uygulamalar vb. gibi harici sistemler veya servisler ile iletişim kurmasına izin verir.

Adaptörler

Bir Adaptör, Uygulama ile etkileşimi belirli bir teknolojiyi kullanarak bir Bağlantı Noktası aracılığıyla başlatacaktır; örneğin, bir REST controller’a, bir client’ın uygulama ile iletişim kurmasını sağlayan bir adaptörü temsil edecektir. Bağlantı Noktaları veya Uygulamanın kendisi için bir risk oluşturmadan, herhangi bir tek Bağlantı Noktası için gerektiği kadar adaptör olabilir.

Application

Application, sistemin özüdür, işlevselliği veya kullanım durumlarını düzenleyen Application Servislerini içerir. Ayrıca Aggregates, Entities ve Value Object gömülü iş mantığı olan Domain Modelini de içerir. Uygulama, Bağlantı Noktalarından komutlar veya sorgular alan ve ayrıca Bağlantı Noktaları aracılığıyla veritabanları gibi diğer harici aktörlere istekler gönderen bir hexagon ile temsil edilir.

Domain Driven Design ile eşleştirildiğinde, Uygulama veya Hexagon, hem Uygulama hem de Domain katmanlarını içerir ve User Interface ve Infrastructure katmanlarını dışarıda bırakır.

Neden Hexagon Mimari?

Alistair’in Hexagon kullanma fikri, yalnızca bir uygulamanın sahip olabileceği çoklu Bağlantı Noktası/Adaptör kombinasyonlarının görsel bir temsiline sahip olmak ve ayrıca uygulamanın ‘left side’ veya ‘driving side’, diğerlerine kıyasla nasıl farklı etkileşimlere ve uygulamalara sahip olduğunu göstermektir.

Driving Side vs Driven Side

Driving (veya birincil) aktörler, etkileşimi başlatanlardır ve her zaman sol tarafta olurlar. Örneğin, bir driving adapter (kullanıcı) girdisini alan ve bir Bağlantı Noktası aracılığıyla Uygulamaya ileten bir controller olabilir.

Driven (veya ikincil) aktörler, Uygulama tarafından “davranışa atılan” kişilerdir. Örneğin, Uygulama tarafından bir veritabanı adaptörü çağrılır, böylece bir data alır.

Uygulama söz konusu olduğunda, kaçırılmaması gereken birkaç önemli ayrıntı vardır:

  • Bağlantı noktaları (çoğu zaman seçtiğiniz dile bağlı olarak) kodda interface olarak temsil edilecektir.
  • Driving Adaptörler bir Bağlantı Noktası kullanarak bir Uygulama Servis, Bağlantı Noktası tarafından tanımlanan Interface’i uygulayacaktır, bu durumda hem Bağlantı Noktasının interface’i hem de uygulaması Hexagon’un içindedir.
  • Driven adaptörler Bağlantı Noktasını uygular ve bir Uygulama Servisi bunu kullanır, bu durumda Bağlantı Noktası Hexagon’un içindedir, ancak uygulama Adaptörün içindedir, dolayısıyla Hexagon’un dışındadır.

Hecagon Mimari Bağımlılıkları Tersine Çevirme

Bağımlılığı Tersine Çevirme İlkesi, Bob Martin tarafından Paper OO Design Quality Metrics adlı kitabında ve daha sonra Agile Software Development Principles, Patterns and Practices adlı kitabında ortaya konan 5 ilkeden biridir ve burada bunu şu şekilde tanımlamaktadır:

  • Yüksek seviyeli modüller, düşük seviyeli modüllere bağlı olmamalıdır. Her ikisi de soyutlamalara dayanmalıdır.
  • Soyutlamalar ayrıntılara bağlı olmamalıdır. Detaylar soyutlamalara bağlı olmalıdır.

Daha önce de belirtildiği gibi, Hexagon’un sol ve sağ tarafları, hem Bağlantı Noktalarının hem de Adaptörlerin bulunduğu Driving ve Driven olmak üzere 2 farklı aktör türü içerir.

Driving tarafında, Adaptör, Uygulama Servisi tarafından uygulanan Bağlantı Noktasına bağlıdır, bu nedenle Adaptör, çağrılarına kimin tepki vereceğini bilmez, yalnızca hangi yöntemlerin kullanılabilir olduğunun garanti edildiğini bilir, bu nedenle bir soyutlama olmuştur.

Driven tarafında, Uygulama Servisi, Bağlantı Noktasına bağlı olandır ve Adaptör, Bağlantı Noktasının Interface’ini uygulayandır ve ‘düşük düzeyli’ adaptör (yani veritabanı) uygulamaya zorlandığından bağımlılığı etkin bir şekilde tersine çevirir. ‘yüksek seviye’ olan uygulamanın çekirdeğinde tanımlanan soyutlama’ya girer.

Neden Bağlantı Noktalarını ve Adaptörleri Kullanmalıyım?

Bağlantı Noktaları ve Adaptör Mimarisini kullanmanın birçok avantajı vardır, bunlardan biri uygulama mantığınızı ve domain mantığınızı tamamen test edilebilir bir şekilde tamamen izole edebilmektir. Dış etkenlere bağlı olmadığı için test edilmesi kolay hale gelir ve bağımlılıklarıyla mock etmek kolaydır.

Ayrıca, tüm sisteminizin interface’ini teknoloji yerine ‘amaca göre’ tasarlamanıza olanak tanır, kilitlenmenizi önler ve uygulamanızın teknoloji yığınının zamanla gelişmesini kolaylaştırır. Persistence katmanını değiştirmeniz gerekiyorsa, bunun için gidin. Uygulamanızın insanlar yerine Slack botları tarafından çağrılmasına izin vermeniz gerekiyorsa, anladınız! Tek yapmanız gereken yeni Adaptörleri implement etmek ve hazırsınız.

Bağlantı Noktaları ve Adaptör mimarisi ayrıca Domain Driven Design ile çok iyi uyum sağlar; getirdiği ana avantaj, domain mantığını uygulamanızın çekirdeğinde oluşabilecek leaks’lere karşı korumasıdır.

Kod Örnekleri Üzerinden Bakalım

Bu bölümde, hayali bir kitap uygulaması için kitap oluşturma isteklerini işleyen bir hizmetin oldukça basitleştirilmiş bir sürümünü uygulayacağız.

Lütfen örneklerin belirli bölümleri atladığını ve Bağlantı Noktaları ve Adaptörlerin temel kavramlarına odaklanmak için hata işleme ve doğru adlandırma gibi iyi yazılmış kodun önemli yönlerini göz ardı ettiğini unutmayın.

Domain Driven Design Katmanlı Mimarisinin tüm katmanlarının, tüm componentleri için ideal bir ayrım sağladıkları için Bağlantı Noktaları ve Adaptörlere dayalı bir uygulama yapılandırırken hala uygun olduğunu vurgulamak önemlidir.

Hayali uygulamamızda controller, Driving Bağlantı Noktasını kullanan Driving Adaptörü olacaktır.

Driving Bağlantı Noktası, Uygulama Katmanında veya Hexagon’da bir interface olacaktır.

Application Service, Driving Bağlantı Noktasını implement edecektir.

Gördüğünüz gibi, düzenleme componenti olan Uygulama Servisi Driven Port’u kullanır.

Son olarak, Driven Port, Driven Adapter tarafından implement edilecektir.

Hexagon veya Bağlantı Noktaları ve Adaptör Mimarisi, tüm uygulamalar için iyi bir yöntem değildir. Dikkatli bir şekilde ele alındığında sisteminize büyük faydalar sağlayacak belirli bir karmaşıklık düzeyi içerir. Ancak düzensiz bir yapı oluşturulursa, çok fazla baş ağrısına neden olabilir.

Doğru şekilde uygulandığında ve Domain Driven Design gibi diğer metodolojilerle eşleştirildiğinde, Bağlantı Noktaları ve Adaptörler, bir uygulamanın uzun vadeli kararlılığını ve genişletilebilirliğini sağlayarak sisteme ve kuruluşa büyük bir değer katabilir.

Kaynakça:

https://medium.com/ssense-tech/hexagonal-architecture-there-are-always-two-sides-to-every-story-bc0780ed7d9c

--

--