Çok Katmanlı Mimari Örnek Proje(1)

Samet Çınar
SabancıDx
Published in
4 min readMar 7, 2021

--

Çok katmanlı mimari

Bir önceki yazımda “Çok Katmanlı Mimari” konusundan bahsetmiştim.

Yazıda bahsettiğim örnek projeye başladım ve bu projede neler yaptığımı sizlere aktarmak istiyorum. Hatta bu projeyi ve projeyi geliştirirken kullandığım “Corex” paketini sizlerle beraber geliştirmeye devam etmek istiyorum. Eleştiri, yorum yaparak katkıda bulunursanız çok sevinirim.

Corex?

Çalıştığımız iş yerinde ya da kendi projelerimizde kullandığımız standart kodların bir araya getirildiği bir proje diyebilirim. Kütüphane de diyebiliriz, öyle deyince daha havalı oluyor :)

Kütüphane olması ona bağımlı kalacağımız anlamına kesinlikle gelmiyor. Sadece tekrar tekrar yazmakla vakit kaybetmemiz gereken kodları buradan alacağız diyebiliriz.

“Çok Katmanlı Mimari” yazımda infrastructure ve drived yapılarından bahsetmiştim. Corex projesini incelediğinizde her paketin bu yapıda olduğunu göreceksiniz.

Örnek projede Corex’de bulunan tüm class library’leri paket haline getirdim public bir şekilde nuget.org’dan indireceğiz. Buradaki tüm paketleri örnek projemizde kullanarak geliştirmeye çalışacağız, öncelikle bir proje için en gerekli olan paketleri kullanarak örnek bir proje ayağa kaldıracağım. Bu da olsun dediğiniz bir şey olursa hem corex hem de corex sample için github üzerinden issue açabilirsiniz. Amaç da bu zaten etkileşimde kalmak, bu projeyi sadece ben değil hep beraber geliştireceğiz. Github üzerinde iş birlikçilere ihtiyacığından şüpheniz olmasın(collaborator)

Öncelikle Corex kullanarak çok kolay hızlıca projeye geliştireceğiz diye bir vaat kesinlikle vermiyorum. Doğru olduğunu düşündüğüm mimaride geliştirme yapmaya yardımcı olacak, temel sınıfları bulunduran bir proje olarak bize katkısı olacak.

Corex içerisinde bulunan sınıfları direkt olarak projemizde kullanmak yerine onların somut bir sınıfınıda bizde oluşturup gerektiğinde projemize özel kodlar yazmamıza olanak sağlayacağız. Şimdi Corex.Sample projesinde ne hedefliyoruz, neler yaptık onu konuşalım.

Corex Sample

User, Order ve Product olarak entity sınıfımız olacak. EFCore migration ile bunlar için SQL’de bir DB oluşturacağız.

JsonSerializer olarak Newtonsoft, Mapper olarak ise Mapster kullanacağız.

Yeni bir “User” kayıtı aldığımızda şifresini “SHA256” ile şifreleyip, SMTP server ile “Welcome” maili atacağız.

Validation katmanımız olacak tüm insert ve update işlemleri için server side validation yazacağız.

Memory cache kullanarak SQL’e sorgu yükünü azaltacağız.

Sunum katmanı olarak şimdilik console projesi oluşturacağım. Daha sonra MVC, API, Blazor vs. geliştirebiliriz.

01.Corex.Sample.Core

01.Corex.Sample.Core

Öncelikle projemizin “Core” katmanını oluşturuyoruz. Burada tüm diğer katmanlara referans etmemiz gereken tüm katmanları ilgilendiren sınıfların dışında gereksiz sınıfların olmamasına dikkat etmeliyiz.

“appsettings.json” dosyamız projemizin konfigürasyon dosyası olacak connectionString v.b değerleri burada tutacağız. Envoirment durumunda göre bu json dosyasını “appsettings.Development.json” olarak envoirment bazında da oluşturabiliriz.

Projemizde dependency yönetimi için “Castle Windsor” kullanmayı tercih ettim. IoCManager.Install’da dependencyleri nasıl install ettiğimi görebilirsiniz.

Burada dikkat etmemiz gereken konu ;

ISingletonDependecy, IScopedDependency, ITransientDependecy

Katmanlarda geliştirme yaparken oluşturduğumuz interface’lere bir lifestyle belirlemeliyiz. Örn : JsonSerializer “ISingletonDependecy”dir. Neden ? Çünkü tek bir örneği tüm proje içerisinde kullanılabilir. Her seferinde bir örneği(instance) oluşturulması bize gereksiz kaynak tüketimi olacaktır.

Scoped, Singleton, Transient için detaylı bilgiye buradan ulaşabilirsiniz.

02.Corex.Sample.Model

Projemizin “Model” katmanı tüm ihtiyaç duyduğumuz modelleri burada bulunduracağız.

02.Corex.Sample.Model

Projenizde kullanacağın modelleri tek bir “Model” katmanı açıp hepsini tek bir yerde atma yanlışına düşmeyin. Sade bir yapı istiyorsak her farklı görevi olan modelimizi ayrı class library ile açmalıyız.

Core.Sample.Model.Inftrastructure

public interface IModel<TKey>{TKey Id { get; set; }DateTime CreatedTime { get; set; }DateTime? UpdatedTime { get; set; }bool IsActive { get; set; }DateTime? DeletedTime { get; set; }bool IsDeleted { get; set; }int Position { get; set; }}

ICorexModel<TKey> adında bir sınıf göndereceksin. Buradaki <TKey> generic tipi hakkında bilgi vermek istiyorum.

Projemizde bir çok entity barındırabiliriz, kimisinin PK değeri “int” iken kimisinin “Guid” olabilir. Bu yüzden her entity,dto IModel<TKey>’den türemeli ve hepsi kendi özelinde “Id” değerinin ne tipte olacağını belirtmelidir.

Model Inftrastructure bize sağladığı alt yapı ile beraber ondan türeyen class library’lerden bahsedelim.

Corex.Sample.Model.EntityModel

DB sınıflarımızı oluşturduğumuz katman. Burada oluşturduğumuz sınıflar IEntityModel’den türeyerek DB tablolarımızı oluşturacağız.

Corex.Sample.Model.DtoModel

Data aktarımı nesneleri (Data Transfer Object) olarak adlandırdığımız sınıfları oluşturduğumuz katmandır.

Corex.Sample.Model.MailModel

Projemizde atacağımız mailler için ayrı sınıflara ihtiyaç duyabiliyoruz.
Örn : Yeni bir kullanıcı kaydı alındığında mail atarken sadece kullanıcının email bilgisini kullanacağım diyebilim. Tüm UserDto bunun için fazla olur, hatta gereksiz olur. Yarın bir gün UserDto’dan farklı hal alabilir o yüzden esnek olmak için farklı bir katman açmalıyız. MailModel’de bu yüzden farklı bir katman olarak bize destek verecek.

Corex.Sample.Model.ViewModel

Sayfadan alınan yada sayfaya gönderilen değerlerin ayrı sınıflar olmasına ihtiyaç duyabiliriz.
Örn : UserDto sınıfımda “Email, Name, Surname, Password, Address” alanları var. Ancak ben yeni kayıt alırken sadece “Email ve Password” olarak kayıt almak istiyorum. Sayfadan “UserDto” beklemem doğru değil, yine esnek olmak için “UserRegisterInputModel” oluşturmam gerekiyor. ViewModel bu tarzda istekler, talepler için farklı bir katman olarak bize destek sağlayacaktır.

Yazının okunabilir ve anlaşılabilir olması açısından parça parça ilerleyeceğim. Bir sonraki yazımda ;

03.Corex.Sample.Data
04.Corex.Sample.Serializer
05.Corex.Sample.Mapper
06.Corex.Sample.Encryptor
07.Corex.Sample.EmailSender

Katmanlarından bahsedeceğim. Bu 01,02,03 vs gibi sayılar belki dikkatinizi çekmiştir. Bu sayılara karar verirken domain driven design kurallarına dikkat ederek katmanların birbiri ile ilişkili gösteren bir numaralandırma diyebiliriz.

Data katmanında EntityFramework, Serializer katmanında NetwonSerializer, Mapper katmanında Mapster, Encryptor’da ise SHA256 kullanacağız.

Görüşmek üzere.

--

--