Web uygulama mimarileri, uygulamanın nasıl geliştirildiğinden, nasıl yayına alındığına kadar planlanan adımlar dizisidir. Günümüzde bir çok uygulama, IIS, Tomcat veya Nginx gibi ortamlarda tek bir application domain altında tek bir birimden oluşmuş şekilde çalışabildiği gibi, birden fazla application domaine hatta birden fazla sunucuya dağıtılmış şekilde çalışabilen uygulamalar mevcuttur. Bununla birlikte, tek bir dağıtım birimi ile deploy edilip çalışan uygulamalar bile, mantıksal olarak birkaç katmana ayrılabilmektedir. Yazılım mühendisliğinin amaçlarından biri de çok sık değişen kod ile az değişen kodu birbirinden ayırmaktır.
Genel olarak kullanılan mimariler Monolitik, N-Katmanlı ve Clean architecture olarak adlandırılabilir.
Monolitik (Tek katmanlı) uygulama nedir?
Monolitik uygulamalar, kullanıcı arayüzü ve veri erişim kodunun tek bir programda birleştirildiği tek katmanlı bir uygulama biçimidir. Uygulamanın sunucu ortamlarında dağıtılması tek bir birim şeklindedir. Böyle bir uygulamanın yatay olarak ölçeklenmesi gerekiyorsa, uygulamanın tamamı birden çok sunucu veya sanal makine arasında çoğaltılır.
Bu uygulama mimarisinde, geliştirilen uygulamanın tüm birimleri tek bir projede tutulur, tek bir derlemede derlenir ve tek bir birim olarak dağıtılır.
Projede iş birimlerinden birbirinden ayrılması, klasörleme mantığına göre yapılır. Örneğin MVC pattern uygulanıyorsa Model, View, Controller, Data gibi klasörlere dağıtılmış bir şekilde geliştirme yapılır. Bu düzenlemede, uygulama görünümü ile ilgili detaylar Views klasörüyle, veri erişim uygulama detayları ise Data klasöründe tutulan sınıflarla sınırlandırılmalıdır. İş mantığı, Models klasöründeki servis ve sınıflarda bulunmalıdır.
Uygulanışı her ne kadar basit olsa da bu mimarinin dezavantajları vardır.
- Teknolojik araçlardan veritabanına yazma işlemlerine, arayüz tasarımına kadar her şey tek bir projededir. Böyle bir ortamda aradığını yerli yerinde bulmak zordur.
- Projenin boyutu ve karmaşıklığı arttıkça dosya ve klasörlerin sayısı da artar.
- Kullanıcı arabirimi (UI) iş parçacıkları (Models, Views, Controller) birden fazla klasöre dağılmıştır.
- UI tarafında, filter, model binder, exception partial modeller eklendikçe klasörler büyümeye ve karmaşıklık artmaya devam eder.
- Business mantığı Models ve Services klasörleri arasında dağılmış ve hangi klasörlerin hangi sınıflara bağlı olması gerektiğine dair net bir gösterge yoktur.
- Bir takım halinde çalışma sırasında birden fazla kişinin aynı dosya üzerinde çalışması gerekir ve çakışmalar artar.
Bu durumda uygulanabilirlik azaldıkça, sorunları daha rahat ele alabilmek için uygulamalar, çok projeli yapılara dönüştürülürler.
N-Katmanlı mimari nedir?
Uygulamaların karmaşıklığı arttıkça, bu karmaşıklığı yönetmenin bir yolu, uygulamayı sorumluluklarına veya iş birimlerine göre ayırmaktır. Bu ayrım, seperation of concerns olarak bilinir. Bu yöntem ile geliştiriciler, bir parçanın nerede geliştirildiğini rahatça karar verebilir ve takım geliştirmesi yapıyorlar ise aradıklarını kolayca bulabilirler. Katmanlı mimarinin bir dizi avantajları vardır.
- Uygulama kodu ve işlevsellikler katmanlara bölündüğünden, kodda yeniden kullanılabilirlik arttırılır. Uygulama da DRY ( Don’t Repeat Yourself) ilkesi sağlanmış olur.
- Hangi katmanların birbiri ile iletişim kuracağı belirlenerek encapsulation sağlanmış olur. Bir katmanda değişiklik meydana geldiğinde sadece onunla çalışan katman etkilenmelidir. Bu sayede bir değişikliğin uygulamanın tümünü etkilemesi engellenmiş olur.
- Katmanlar sayesinde uygulama işlevselliğini değiştirmek kolaylaşır. Örneğin bugün Oracle veritabanı ile çalışan sistem bir süre sonra Postgresql ile çalışma ihtiyacı duyduğunda, data interface ile Postgresql implementasyonu yapan yeni bir sınıf ile kodda çok fazla değişkliğe neden olmadan yeni bir altyapı eklenebilir.
- Test edilebilirliği kolaylaştırır. Uygulamanın gerçek veri katmanına veya UI katmanına ait çalışan testler yazmak yerine, bu katmanlar test zamanında isteklere bilinen yanıtlar sağlayan sahte (Moq) uygulamalarla değiştirilebilir
Bu mimariye göre kullanıcılar uygulamaya User Interface üzerinden istekte bulunurlar. User Interface katmanı ise yalnızca Business Logic katmanı ile iletişim kurar. Business Logic katmanı da Data Access katmanından veri isteği yapar. User interface doğrudan Data Access katmanına erişemez. Business Logic katmanı da doğrudan veriye erişmemelidir, veri talebini Data Access katmanından yapmalıdır. Yani her katmanın kendine ait sorumluluğu bulunur.
N-Katmanlı uygulama mimarisi proje yapısı
Bu mimari her ne kadar tek projeli yapıyı çok projeli hale dönüştürse de bazı dezavantajları vardır.
- Derleme zamanı bağımlılıkları (dependencies) yukarıdan aşağıya doğru çalışır. Yeni UI katmanı BLL katmanına, BLL katmanı da DLL katmanına bağlıdır. Bu, genellikle uygulamada en önemli mantığa sahip olan BLL’nin veri erişimi uygulama ayrıntılarına ve hatta bir veritabanının varlığına bağlı olduğu anlamına gelir. Böyle bir mimaride iş mantığını test etmek genellikle zordur ve bir test veritabanı gerektirir.
- Deployment tek bir birim olarak yapılır. Bu uygulama enterprise amaçlar için birkaç projeye bölünmüş olsa da, tek bir birim olarak dağıtılır ve istemcileri onunla tek bir web uygulaması olarak etkileşime girerler.
Clean architecture nedir?
N katmanlı mimaride bahsedilen yukarıdan aşağı doğru bir derleme bağımlılığını ortadan kaldırmak için çeşitli çalışmalar yapılmıştır. Dependency Inversion ve Domain Driven Design gibi yaklaşımlar aslında benzer bir mimariye ulaşma eğilimindedirler. Bu mimari yıllar içinde birçok isimle anıldı. İlk isimlerden biri Hexagonal Architecture, ardından Ports-and-Adapters oldu. Son zamanlarda, Onion Architecture veya Clean Architecture olarak anıldı.
Clean Architecture mimarisi, Business Logic ve Application modelini uygulamanın merkezine (Application Core) koyar. Business Logic veri erişimine veya diğer infrastructure sorunlarına bağlı olması yerine, bu bağımlılık tersine çevrilir: infrastructure ve application ayrıntıları Application Core bağlıdır. Bu işlevselliği sağlamak için Application Core tarafında interface veya abstraction tanımlamaları yapılıp, bu soyut tiplerin implementasyonları da Infrastructure tarafında yapılarak sağlanır. Bu mimariyi görselleştirirken, soğana benzer bir dizi eş merkezli daire kullanmaktır.
Bu diyagramda, bağımlılıklar dıştan, en içteki daireye doğru akar. Application Core, adını bu diyagramın merkezindeki konumundan alır. Ve diyagramda, Application Core diğer uygulama katmanlarına bağımlılığı olmadığı görülür. Entity ve Interface tipleri tam merkezdedir. Hemen dışında, ancak yine de Application Core içerisinde, genellikle iç çemberde tanımlanan Interface tiplerini implemente eden domain servisleri bulunur. Application Core dışında, hem UI hem de Infrastructure katmanları, Application Core’a bağlıdır, ancak birbirine bağlı değildir.
Düz okların derleme zamanı bağımlılıklarını, kesikli ok ise yalnızca çalışma zamanı bağımlılığını temsil eder. Clean Architecture ile UI katmanı, derleme zamanında Application Core üzerinde tanımlanan arabirimlerle çalışır ve ideal olarak Infrastructure katmanında tanımlanan uygulama türlerini bilmemelidir. Ancak çalışma zamanında, bu implementasyon türleri uygulamanın yürütülmesi için gereklidir, bu nedenle mevcut olmaları ve bağımlılık ekleme yoluyla Application Core interface tiplerine bağlı olmaları gerekir.
Clean Architecture Katman Yapısı
Katman yapısı oluşturulurken, katmanlara ait projelerin birbirine karışmaması adına öncelikle bir klasör modeli oluşturulabilir.
Daha sonra projeler bu düzene göre kolayca eklenebilir.
Presentation
Bu katmanda, kullanıcının uygulama ile iletişim kuracağı ara yüz uygulamaları oluşturulur. Örneğin bir Web Api veya bir desktop uygulama gibi düşünülebilir. Hiç bir katman, en üstte bulunan bu katmana bağımlı olamaz.
Infrastructure
Bu katmanda, uygulamanın dış dünya ile iletişim kurabileceği modüllerin somut implementasyonları yapılır. Örneğin Entity Framework veya NHibernate gibi framework kullanarak veritabanı işlemlerinin gerçekleştirilmesi. Ya da bir SMTP servisine erişerek mail gönderen işlemleri gerçekleştiren sınıfların oluşturulması gibi düşünülebilir.
Core
Bu katmanda Application ve Domain projeleri bulunur.
Domain projesi uygulamanın en soyut ve diğer katmanların hiç birini referans almayan çekirdektir. Entity, Value Objects, Exception ve Enumeration gibi tipleri burada bulunur. Örneğin bir Order entity tipinde, status ve tarih özelliğinin bulunması gibi iş kuralları burada belirlidir.
Application ise uygulama kuralarının belirlendiği projedir. Yani Entity tiplerinin nasıl kullanılacağı burada belirlenir. Application katmanı sadece Domain katmanına bağımlıdır ve oradaki bileşenleri kullanarak iş kuralları oluşturur. Örneğin işimiz ürün satmak ise, sipariş vermek bizim için bir kullanıcı senaryosu olabilir. Bu hizmeti kullanıcıya sunmak için öncelikler ürünün stokta olup olmadığını kontrol etmek ve ardından siparişi oluşturmak gerekir. Bunlar uygulamanın kurallarıdır. Ayrıca uygulamanın interface, abstract gibi business soyutlamaları Application projesinde bulunur. Fakat somut implementasyonları infrastructure katmanında bulunur. Örneğin IProductRepository interface Application projesinde ise, bunu implement eden ProductRepository class Infrastructure projesindedir.
Özet
Tek projeli monolitik yapılar, küçük çaplı ve dağıtık deployment gerektirmeyen proje çözümler için uygundur.
Katmanlı mimari sayesinde tek projeli yapılar birden fazla projeye bölünerek daha yönetilebilir ve takım geliştirmesine uygun hale getirilebilir. Ancak katmanlı mimarilerde core modüllerinin diğer modüllere bağımlılığı oluşmaktadır.
Clean Architecture mimarisi de bu bağımlılığı ortadan kaldırmaktadır. Bağımlılıklar, uygulamanın en önemli parçası olan Application Core katmanına doğru gelişmektedir. Bu sayede katmanlarda test edilebilirlik artar, uygulamanın merkez modülü olan Application Core, soyut bir özellik kazanarak üçüncü parti framework bağımlılıkları ortadan kalkar ve modülü test etmek için her hangi bir database ihtiyacı kalmaz. UI katmanının da aynı şekilde framework ve diğer katmanlar ile sıkı bağı kalmaz. Ancak deployment sırasında uygulamalar bu üç mimaride de bütün olarak deploy edilir.
Not: Uygulamaların önyüz, backend veya feature modüllerini birbirinden ayırarak her birinin ayrı bir servis halinde deploy edilebilmesini sağlayan mimariler, dağıtık mimariler olarak adlandırılır. Dağıtık deploy edilebilen servislerin dağıtık bir şekilde, farklı takımlar ile geliştirilmesi sağlanabilmektedir. Günümüzde dağıtık mimarilerden, özellikle e-ticaret sektöründe en çok tercih edilen mimari, mikro servis mimarisidir. Unutulmamalıdır ki her bir mikroservis özünde monolitik bir uygulamadır. Mikro servisler boyutu küçük olan servisler olarak anlaşılmamalıdır. Tek başına deploy edilebilen servisler olarak anlaşılmalıdır.
Sonuç
İyi mimariler bağımsız modüller yaratmak içindir. İyi yapılandırılmamış bir monolitik uygulama dahi geliştirilemiyorken, probleminize mikroservislerin çözüm olacağını düşünmemek yanlıştır.
Kaynak