Ana içeriğe atla

OOP Refactoring With SOLID Princible

Bu yazımızda SOLID prensiblerini kullanarak Refactoring yapma üzerine konuşuyor olacağız.Öncelikle Refactoring kelimesine bir bakalım.
Refactoring her yazılımcının mutlaka bilmesi gereken ve dilinden düşürmemesi gereken bir kelimedir.

Refactoring Nedir
Refactoring i kısaca yeniden düzenleme / gözden geçirme olarak tanımlayabiliriz code review olarak ta kullanılır sıklıkla.Bu bizim kodlarımızdaki eksikleri gidermemiz, reusable hale getirmemizde oldukça faydalı bir tekniktir.
Genellikle kod yazarken farkında olmadığımız eksiklerimiz olabilir, yazılım geliştirme süresinde ortaya çıkan talepler sonrası kodlarımız değişimlere uğrar ve başta yapılan tasarım ile çıkan tasarım değişiklikler göterebilir.Kodlarımızı daha basit, anlaşılabilir, değişimi daha kolay bir hale getirmek için sık sık yazdığımız kodlar üzerinde tekrar gözden geçirme yapmalıyız.

SOLID Prensibi Hakkında
Solid  aşağıdaki maddelerin baş harflerinin birleşmesi ile oluşan bir yazılım prensibidir.

  • Single Responsibility Principle
  • Open/Closed Principle
  • Liskov ‘s Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle
Şimdi kısaca bu prensibleri açıklayalım.


Single Responsibility Principle: Her modülün(sınıf,nesne,metot) tek bir görevi, tek bir sorumluluğu olması ilkesine dayanır. Bir nesneyi değiştirmek için tek bir neden olmalıdır. Birden fazla neden varsa, o nesnenin birden fazla sorumluluğu var demektir ki burada da Single Responsibility den bahsedilemez.

Resim1 : Single Resposiblity Kullanılmaması Durumu

 Resim 2: Single Responsibility Prinsible ile Hedeflenen


Open/Closed Principle: Yazdığımız kod(sınıf,nesne,metot) gelişime açık, değişime kapalı olmalıdır. Yeni bir özellik ekleneceği zaman veya geliştirme yapılacağı zaman kodu değiştirmemek, sadece önceden yazılan kodun üstüne bir şeyler eklemek gerekir.Bu aşama da da bol bol soyut sınıflarla çalşmak abstract, interface,virtual,override gibi kavramları iyi bilmek gerekir.



Liskov’s Substitution Principle: Alt sınıflardan oluşturulan nesneler, üst sınıfların nesneleriyle yer değiştirildiklerinde aynı davranışı göstermek zorundadır. Yani üst sınıflardan implemente edilen metodlar her alt sınıfta çalışmak durumundadır.Bu prensib biraz complex olduğu için birkaç parça kod örneği verelim.

Yukarıdaki gibi bir sınıf hiyerarşimiz olduğunuz düşünelim.Tabloya baktığımızda gold ve silver customer davranışı gösterebilir.Fakat Enquiry örneğin bu tipte bir kullanıcı ekleme gibi bir davranışı gösteremez diye düşünelim.

class Enquiry : Customer
    {
        public override double getDiscount(double TotalSales)
        {
            return base.getDiscount(TotalSales) - 5;
        }

        public override void Add()
        {
            throw new Exception("Not allowed");
        }
    }

Bu durumda bu class ın aslında sadece discount sağlıyor.Ve liskov prensibine uymuyor.Bu durumda şöyle bir çözüm üretebiliriz :

interface IDiscount
{
        double getDiscount(double TotalSales);
}


interface IDatabase
{
        void Add();
}
Şimdi artık sınıflarımızın tüm metodlarını desteklediği üst sınıflardan devralmasını sağlamamız liskov prensibine uyması için yeterli olacaktır.Örnek olarak Enquiry e bakacak olursak.

class Enquiry : IDiscount
    {
        public  double getDiscount(double TotalSales)
        {
            return TotalSales - 5;
        }
    }

Robert C. Martin in bu konu ile ilgili ünlü bir sözü :

Subtypes must be substitutable for their base types.


Interface Segregation Principle: Benzer özellikleri barındıran sınıfları tek bir interface’ten türeterek o interface’e sonradan sınıflarda kesin olarak kullanılmayacak özellikler eklemek doğru değildir. Başta çözüm benzer özelliğe sahip sınıfları tek bir interface’ten türetmek gibi görünse de aslında çok da doğru değildir. Çözüm interface’leri oluştururken içindeki üyeleri ortak olacak şekilde parçalayıp bu üyeleri interface’ler altında toplayıp, ayrı interface’ler oluşturmaktır.

Dependency Inversion Principle: Somut sınıflara olan bağımlılıklar, soyut sınıflar ve interface’ler kullanılarak ortadan kaldırılmalıdır. Çünkü somut sınıflarda değişiklikler çok olur.
Bu prensipleri ne kadar iyi uygularsak nesne yönelimli programlamayı o kadar iyi yapmış oluruz, ancak amaç nesne yönelimli programlama yapmak için bu kuralları uygulamak değil, bu prensiplere bakarak yazılan koddaki eksikleri bulmak ve düzeltmektir.

Yazılım prensip ve standartlarına uygun şekilde kod yazmak istiyorum ne yapmalıyım ? 
Eğer kafanızda bu şekilde bir soru işareti var ise ;
1.Öncelikle yazımın başında belirttiğim gibi Refactoring kelimesini asla dilimizden düşürmemeliyiz.Hatta uzun zaman sonra bile eski kodlarınıza bakıp aman bozmıyayım demeden refactoring işlemini yapmalıyız.Bunun bir nedeni de en basitinden siz kendinizi geliştirdikçe yazdığınız kod kalitesi de her geçen artacaktır ve eski kodlarınıza baktığınzıda onları geliştirebilecek daha iyi duruma getirebilecek çok fazla nedeniniz olacaktır.
2.SOLID prensiplerini çok iyi öğrenmeye çalışmalı ve geliştirdiğimiz projelerde bu prensiblere uygun kod yazmalıyız.

3.Sizinde tahmin edebileceğiniz gibi refactoring işlemlerinde kendinize sürekli yazdığım kod SOLID prensiplerine uyuyor mu diye kendinize sorup bu ölçütte refactoring lerinizi yapabilirsiniz. 




Kaynak : http://www.codeproject.com/Articles/703634/SOLID-architecture-principles-using-simple-Csharp

Bu blogdaki popüler yayınlar

Sql IDENTITY_INSERT Kullanımı

Sql de bazen veri taşıma veya benzeri bir durumda aktarmak istediğimiz tablo kayıtlarını identity field olan ID leri ile aktarmak isteriz.Fakat sql server buna izin vermez.Bu Identity alana insert işlemi için aşşağıdaki gibi bir işlem uygulayabiliriz. Örnek Olarak aşşağıdaki sorguda eski tablomuza yeni başka bir tablo kayıtlarını aynen aktarıyoruz. SET IDENTITY_INSERT tabloadı ON -- identity insert yapılabilir konuma geliyor INSERT INTO eskiTablo SELECT * FROM yeniTablo SET IDENTITY_INSERT tabloadı OFF -- identity insert yapılamaz konumuna geliyor

Cannot resolve the collation conflict between "Turkish_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.

iki ayrı veri tabanı içindeki tablolar ile işlem yapılmak istendiğinde eğer dil sorunu çıkıyor ise sorgumuzun sonuna 'COLLATE TURKISH_CI_AS' sözcüğünü ekleyerek sorunu çözebiliriz.Örnek : SELECT * FROM veritabani1.dbo.URUN u1 INNER JOIN veritabani2.dbo.URUNLER u2 ON u1.kod = u2.kod COLLATE TURKISH_CI_AS umarım faydalı olmuştur.

SQL DATEADD() Fonksiyonu(Sql de tarihe ay,gün,yıl ekleme)

Kullanım Kalıbı : DATEADD (datepart , number , date ) . datepart ksımına month,year,day vs artırmak istediğimiz tarih birimini yazıyoruz. . number ksımına arttırmak istediğimiz miktarı yazıyoruz. . date kısmına da hangi tarih e ekleneceğini belirtiyoruz. Örnek olarak şu an ki tarihten 1 ay sonrasını görmek için : Şu anki tarih '10-1-2011' olsun(gün,ay,yıl) Sorgu : SELECT DATEADD(MONTH,+1,GETDATE()) Çıktı alacağımız tarih : '10-2-2011' şekinde olacaktır.