C# Örneğiyle: Katmanlı Mimari de Ne?
Her projemizde veya her fikrimizde ilk bu canlanıyor, “Nasıl yapsak?”, Veri buradan gelir, bunu da buradan set ederim, diğer tarafa implement etmen kolay ama sanki şurada bir sorun var..”.
Günün sonunda bir şekilde kod yazmaya başlıyoruz, uygulamamız için bir başlangıcı öyle ya da böyle yapıyoruz. Fakat herkesin bir şekilde kullandığı, özellikle hiç bilgisi olmadıklarını gözlemlediğim genç arkadaşlara katmanlı mimariyi dilim döndükçe anlatmak istiyorum.
Sürç-i lisans edersem, affola.
Hangi makarnayı seversin? Spagetti mi, Lazanya mı?
Öğrenci olanların hemen zihninde canlanmıştır. Kettle’a sıcak su koy, hemen spagetti makarnaları at içerisine 15–20 dk sonra hazır. Fakat yedikçe makarnalar iç içe geçer. Lazanya da ne ki? Çok uğraştırır. Kat kat yapacaksın, Unu ayrı, kıyması ayrı, fırını ayrı, gırla mevzu var ama çok lezzetlidir değil mi?
Bunlar çipetpet ama lezzetli çipetpet değil..
İşte bizim aradığımız koddaki lezzette bu olmalı, Lazanya gibi kat kat yapacağız. Katmanlı mimari yaklaşımı ile unu ayrı, kıymayı ayrı, fırını ayrı hazırlayacağız ve lezzetli bir ürün çıkaracağız.
Katmanlı mimari için çokça yaklaşım var. Orion Architecture, N Tier Architecture aslında hepsinin çıktığı daha doğrusu anlatmak istediği nokta ortak. Yapıları ayır, SOLID prensiplerini uygula, uygulama içerisinde kafasına göre erişilmesini engelle, herkes kendisine ait işi yapsın (single responsibility principle) ve alt-üst ilişkilerini koru. Aslında mevzu bu kadar basitken nasıl uygulayacağız?
(SOLID için ayrı bir makale yazacağım)
Mahşerin üç atlısı: Presentation, Business, Data
Bir uygulamada aşağı yukarı talep edilen şeyler bellidir. Hemen hemen her projede ilgili işin kapsamına bağlı olacak şekilde; belirli bir iş kuralı olur. Bu iş kuralına göre belki veri(leri) sisteme kayıt edilir ve belki kullanıcı(lara) verileri gösterilir.
Kodları indirmek için: https://github.com/eniskurtayyilmaz/TeacherManagement
Hatta şöyle örneklendirelim: Bir web sitemiz var, içerisinde öğretmenleri kayıt ediyoruz ve öğretmenlere ait dersleri de yöneten bir öğretmen-ders sistemimiz olsun. Buna Öğretmen Bilgi Sistemi (ÖBS) diyelim.
Konuyu anlamak için bazı noktalar Best Practice değildir. Örneğin katmanlar arası model dönüşüm-geçişler, web request modellerinin yaklaşımı, Dependency Injection göz ardı edilmesi.
- E tabii yöneten bir şey derken, demek ki uygulamayı kullanacak kişilere bir şeyler göstermeliyiz. (Sunum Katmanı — Presentation Layer)
- Biz bu verileri kafamıza göre gelişi güzel koymayacağız ya, bir kontrol etmek gerekir. (İş Katmanı — Business Layer)
- Veriyi nerede tutacağız? (Veri Katmanı — Data Layer)
Kafadan yapıyı ayırmaya başladık bile. Ancak buradaki en önemli şey var. Bir kod bloku içerisine spagetti tarzında upuzun kod yazmamamız gerektiği. Yani web sayfasını göstereceğimiz ilgili controller içerisinde aşağıdaki örnekteki gibi DbContext’i çağırarak, hem validation, hem de CRUD işlemlerini yapmayacağız.
Sakın yukarıdaki resmi dikkate alıp, bu şekilde geliştirme yapmayınız 🙂
Bizim asıl öncelikli amacımız yapıları ayırmak. Görsel de göreceğiniz gibi önce yapılarımızı ayıracağız
ÖBS’de bizim yapımız bu görselde gibi olacak, yapılar ayrı, herkes kendi alanından sorumlu hale getireceğiz. Burada belirli kriterimiz olacak:
- İlgili işleme ait web sayfasına gelen istek parametreleri var ise (Adı, Soyadı veya Pagination’a ait aktif kayıt numarası vb.), bunu bir model olarak geliştirmeli ve Presentation katmanında tanımlanmalı (Örn. TeacherWebInsertRequestModel, CourseWebUpdateRequestModel, TeacherWebViewResponseModel) — TeacherManagement.Presentation
2. Gelen isteğe ait modeli belirli bir iş kuralına göre hesaplayacak, kontrol edecek veya veri tabanına kayıt edilmesini isteyecek isek, o zaman bunu Business katmanında yapmamız gerekiyor. Örneğin bir veri tabanına kayıt için önce bizim bir validation yapmamız gerekiyor.
Presentation tarafındaki modeli, Business katmanına gönderebilmek için, Business katmanına özgü RequestDTO ve ResponseDTO nesneleri de oluşturmalıyız. Tabii bunlar ilgili işleme ait ilgili metot(lar) için olmalı ve bu metot(lar) ilgili sınıfta tutulmalı, Presentation katmanı sadece Interface üzerinden erişmeli.
3. Verileri bir veri tabanına veya bir web servis üzerinden bir yerlere kayıt edeceksek, bunu Data katmanında yapmamız gerekir. Tabii buna özgü de modellerimiz olmalı. Eğer bir web servisi web reference olarak eklediyse, bu iş çok kolay. Ama veri tabanındaki bir tablo ise, o zaman bunu tabloya özgü hale getirmemiz lazım. Unutmayın, yapacağımız Data katmanı, Business katmanı tarafından sadece Interface üzerinden erişmeli. Yalnız buradaki modellerimiz genelde yapımızın son noktası olduğu için, metot içerisine her metoda özgü bir model yapmamıza gerek kalmayabilir.
Eğer repository kısmını bile GenericRepository yaklaşımında bir şeyler yaparsanız; bugün X veri tabanından, yarın Y veri tabanına geçişinizi bile rahatça yönetebilirsiniz. Hatta Generic Class yaklaşımı sayesinde BaseEntity’den türeyenleri sadece dikkate al bile diyebilirsiniz (10 puanlık bir yaklaşım, araştırınız lütfen)
Yukarıdaki görselde gördüğünüz gibi Business katmanından, Data katmanına geçişimiz ve ilgili modelimizin veri tabanına aktarımını gerçekleştirdik.
Buradaki asıl mesele, katmanlara arasında ilgili üst katmana ait veri modelinin alt katmana göre hazırlanması ve veri modellerinin dönüşümü.
“İyi de biz neden modeller yaratıyoruz ki, direk veri tabanına veya web servise gitsek olmaz mı?” dediğiniz duyar gibiyim.
Olmaz.
Çünkü biz katmanları ayırtmakla mükellefiz. Ayrıca bunun yönetimi daha kolay oluyor.
Diyelim ki bu projemize öğretmene ait dersleri de tutmak istiyoruz. Bakalım faydasını görebilecek miyiz?
- Data katmanında Course diye bir model oluşturalım ve CourseRepository’de CRUD işlemlerini yapalım.
2. Business katmanında iş kuralımızı yönetelim. Fakat iş kuralımız ne olacak? Mesela her dersin bir öğretmeni olur, değil mi? O zaman dersi sisteme kayıt ederken önce Business katmanında öğretmenin varlığını kontrol etmek lazım?
3. Business katmanındaki derse ait veri dönüş nesnemize eklenen öğretmen bilgisini dönmek istersek? O da kolay..
4. Presentation katmanında dersi kaydettikten sonra, kursa ait öğretmenin sistemdeki Id bilgisi vermek zorunda mıyız, sadece full ismini gösterse diyebilirsiniz. Hani belki “….. derse ait ….. öğretmene kaydınız yapılmıştır” gibi bir mesaj çıkarmak için yeterli olabilir. İşte Presentation katmanındaki response modelimiz bu günler için var 🙂
Kişisel Blog Adresim: eniskurtayyilmaz.com
Twitter Adresim: ekurtayyilmaz
Kaynak Kodlar: https://github.com/eniskurtayyilmaz/TeacherManagement