18 Aralık 2016 Pazar

S.O.L.I.D Principles

Yazılım geliştirme aşamasında her birimiz birden fazla araç kullanırız. visual studio, eclipse, telerik, devexpress, sql server, oracle db, tfs, svn vs.   Neden ?  İşimizi kolaylaştırıyor, standartlar sağlıyor, güvenilir, kaliteli. Bu yazılım araçlarından beklediklerimiz kendi yazacağımız uygulama içinde geçerli olmalı. Yazdığınız uygulamayı da birileri bir yerlerde kullanıyor olacak. En bize dokunanı ise kodları güncelleyip, geliştirmeler yapacak olanlar, hata ayıklayacak olanlar ise gene biz olacağız. 

Yazılımda kalite ve standartları tariflemek, ortak bir dil haline getirmek için prensipler, bu prensipleri temel alan ve çözüm üreten programlama dili bağımsız tasarım-mimari kalıpları ortaya konulmuştur. 

S.O.L.I.D sınıf tasarım prensipleri ismini içinde barındırdığı 5 temel prensibin baş harflerinden almaktadır. Robert Cecil Martin tarafından dillendirilen bu prensipler şunlardır:



SRP The Single Responsibility Principle Bir sınıfın değişmesi için tek bir sebebi olmalı ve tek bir amaca hizmet etmelidir. İsviçre çakısı yapmamalısınız.
OCP The Open Closed Principle Bir sınıfın var olan özelliklerini değiştirmeden yeni özellikler eklenebilmelidir. Üzerinize yeni bir elbise giymek ile, estetik ameliyatı için masaya yatmak aynı şey değildir.
LSP The Liskov Substitution Principle Türeyen sınıflar, temel sınıfların yerine kullanılabilmelidir. Nerede o eski bayramlar dedirtmemeliyiz büyüklerimize. Canlı bir ördege ihtiyac varken oyuncak bir ördeği sırf oda vıraklıyor diye kümese koymamalıyız.
ISP The Interface Segregation Principle iş yaptıracağınız metodlarınızı ortak iş gruplarına göre arayüzlere dağıtın. Bir telefonun piyasadaki tüm markalarin şarj girişlerini destekleyecek sayıda girişi olduğunu gördünüz mü.Telefon üreticilerini buna zorlamayın.
DIP The Dependency Inversion Principle Sınıflarınız soyutlama ve arayüzler üzerinden birbirlerine bağlanabilmeli ve çeşitliliğe izin vermelidir. Bizden lego parçaları yapmamız isteniyor, yap-boz parçaları değil.

Bu prensiplere uygun yazılım geliştirdiğimiz taktirde yönetilebilir, test edilebilir kod yazmamız mümkün olabilir.

17 Aralık 2016 Cumartesi

AutoMapper Kullanımı




Domain içinde bulunan nesnelerin sunum katmanı üzerinde ViewModel nesneleriyle eşleştirilmesi her zaman sıkıcı bir iş olmuştur.  Ne demek istediğimizi bir örnek ile açıklayalım. Aşağıdaki Customer, Product, Item, Order sınıfları bizim domain modelimizdeki sınıflar olsun.


Bu sınıflardaki bilgiyi sunum katmanına taşımak için modellemelerimizi de aşağıdaki gibi yapalım.


Sunum katmanımız (ASP.NET, MVC, Desktop, console), servis katmanımızdan bir Order bilgisini OrderID üzerinden istesin.  Servis katmanı bu isteği yerine getirebilmek için veri katmanına gidecek, veriyi repository üzerinden domain nesnesi olarak alacak, sunum katmanına gönderirken de sunum nesnesine çevirip gönderecek. Bu çok katmanlı mimari altyapılı uygulamalarda karşılaştığımız klasik bir durum örneğidir.


OrderService sınıfımızı dikkatle incelediğimizde şu anki konumuzla ilgili olmasa da tasarımsal bir problemle karşı karşıya olduğumuzu göreceksiniz. Sınıfın varsayılan yapılandırıcı metodunda (Default Constructor) new OrderRepository() kodu kırmızı kırmızı parlamaktadır.  OrderService sınıfının OrderRepository sınıfıyla sıkı bir bağ oluşturması yerine arayüz (interface) üzerinden bir bağ kurmasını isteriz.  Arayüzler üzerinden oluşturulan bu zayıf bağlarında IOC araçları ile dinamik olarak oluşturulmasını isteriz. 


Neden? Altyapınızda OrderRepository yerine başka bir Repository kullanmak istediğinizde new ile yazdığınız kod satırlarını bulmanız ve değiştirmeniz gerekiyor. Oysa sisteminiz tak-çıkar mantığı ile desteklenen bir yapıda olursa, arayüzü desteklediği sürece herhangi bir başka sınıfı altyapınızda değişiklik yapmadan konfigurasyon değişikliği ile rahatlıkla kullanabilirsiniz (Ör:Ninject, StructMap). Aklımızdan çıkarmamamız gereken prensip (Open Closed Principle) “Programlar geliştirilmeye açık ama değiştirilmeye kapalı olmalıdır.”



GetOrder metodu içerisinde ConvertToOrderView metodunda domain nesnemiz olan Order,
OrderView nesnesine dönüştürülüyor. Bu metod bir extention metod (Genişletme metodları bir tip üzerinde herhangi bir değişiklik yapmadan o tipi kolayca genişletmenize olanak sağlayan bir yapıdır.) olup aşağıdaki gibi yazılmıştır.



Büyük bir projede bu işi yüzlerce domain nesnesi için yaptığınızda işler  en başta söylendiği gibi sıkıcı olabilir. Gerçi sıkılma kavramı değişken bir durum ve AutoMapper da bir yazilim aracı.  Camın içinde muhafazasında duruyor. "Gerektiği halde kullanmayanlar cezanlandirilmaz." yaziyor üzerinde. 


Şimdi camı kıralım ve bu aracı kullanarak kodu yeniden düzenleyelim.  


Ornek uygulamayi Console tipinde geliştirdim. Uygulama kodlarina yazının sonundaki linkten erişebilirsiniz. Console uygulamama  Nuget üzerinden automapper paketini kurdum.

Ardından nesneler arasındaki bağı ServiceStartup sınıfı üzerinden konfigure ettim.  Nihayetinde de nesneleri ConvertToOrderView metodunda automapper üzerinden çağırdım. 


OrderExtensionMethods sınıfı içinde ConvertToOrderView  genişletilmiş metodunun değişimine dikkat ediniz. Ayrıca diğer genişletilmiş metod olan ConvertToItemView metoduna ihtiyacım kalmadığını da görünüz.


Ayni isimli sinif nesneleri birbirlerine direk bağlandi. Order sinifinin OrderDate özeliği ile OrderView sinifinin OrderDate özeliği buna örnektir.  Aşağıdaki örüntülerde kabul edilmektedir.


 <Sınıf ismi> + <Özelik İsmi>              : CustomerName

<Sınıf ismi> + "_" + <Özelik İsmi>     Customer_Name
"_" + <Sınıf ismi> + <Özelik İsmi>     : _ CustomerName
<Sınıf ismi> + <Özelik İsmi> + "_"     :  CustomerName_
"_" + <Sınıf ismi> "_"  + <Özelik İsmi> + "_"     :  _Customer_Name_


Order sinifinda Customer özeliğinin (Properties)  Name özeliği ile OrderView sinifinin CustomerName özeliği birbirlerine bağlandi. Sınıf ismi + Özelik İsmi kalıbını AutoMapper kabul etmektedir. 


CustomerName özelik ismi yerine farkli bir isim mesela Name kullansaydiniz bağlama işlemi bu özelik için gerçekleşmeyecekti. CustomerName olduğu yerde kalsın. Bu durumu göstermek için yeni bir özelik ekleyeceğim. Ismine Tag diyeceğim ve string tipinden olacak.

Amacim isimleri farkli olan özeliklerin nasil bağlanabileceğini göstermek.

ServiceStartup static sınıfının ConfigureAutoMapper  static metodunda  aşağıdaki gibi değişiklik yapıyorum.


Birde önek (Prefix), sonek (Postfix)  almış olan özellikleri nasil bağlariz diye bakalım. Yukardaki gibi zaten bağlayabilirsiniz. Lakin birden fazla özelik sadece önek alarak farklilaşmissa siz hepsine yukaridaki gibi kod yazmak durumunda kalmak istemezsiniz. Bunun içinde aşağıdaki gibi bir kodlamaya gidiyoruz.


Yazimizi burada noktaliyoruz. Kaynak kodlari AutoMapperTutorial linkinden indirebilirsiniz.