SOLID Prensipleri Nedir Bize Ne Sağlar

Solid, yazılımda sürdürülebilirliği desteklemek adına kullanılan prensiplerdir. 5 temel prensip vardır.
Yazılımda sürdürülebilirlikten kastımız gündelik işlemleri kolaylaştırmak adına bilgisayar sistemlerine geçilmesidir. Mesela hastanelerde sıra için kuyruk oluşturmak yerine sistemden randevu almak yada ikamet belgesi için muhtara gitme ihtiyacı duymamak gibi işlemler işleri bize kolaylaştırmaktadır.

Yazılımda değişim söz konusudur. Yazılımın doğasında olan bu süreçleri mevcut projelerde yapıyı bozmadan entegre etmemiz gerekmektedir.

1) Single Responsibility Principle :Türkçeye karşılığı tek sorumluluk prensibidir. Bütün yapılar örneğin iş blogu,bir class,bir metot veya bir katman bunların tamamı sadece bir iş yapmak zorundadır.
Aynı kodu birden çok yerde yazmak yerine metot oluşturulup yönetilebilirliği kolaylaştırmış oluruz.

2) Open/Closed Principle : Uygulamalar, nesneler geliştirmeye açık, değişime kapalı olmalıdır.
Yani şöyle diyebiliriz uygulamalar yeni özellikler eklemeye açık olmalıdır fakat bu değişiklikler mevcut kodları değiştirerek yapılamaz.Soyutlama üzerine bir kurgu sağlamaktadır.

3) Liskov ‘s Substitution Principle :  Liskov's un yerine koyma prensibi sırf bir birine benziyor diye işlemleri aynı çatı altında toplamamalıyız.


4) Interface Segregation Principle : Nesnelerin ihtiyaç duymadıkları metodların Interface’lerinden münkün olduğunca ayrıştırılmasıdır. Olay interface leri doğru parçalara ayırmaktır.
Örneğin ; bir firma A ve B bankası ile firmanın  X ve Y metotlarını kullansın firma C bankası ile de çalışmak istiyor lakin firmanın sadece X metodunu kullanacaksa aynı interface i kullanmaları doğru olmaz. Bu yüzden  Interface ayrıştırma işlemi yapılması gerekmektedir.

 class Program
    {
        static void Main(string[] args)
        {
            IBankConnector connector = new BBank();
            ((BBank)connector).Operation1();
            
            Console.ReadLine();
        }
    }
    
    interface IBankConnector
    {
        void Operation1();
    }
 

    interface IPrivateBankConnector: IBankConnector
    {
        void Operation2();
    }

    interface IPublicConnector :IBankConnector
    {
        void Operation3();
    }
    // Bir firmanın 2 banka ile var olan entegrasyonu var. Farklı bir banka ile çalışıldığında   
    // operasyon olarak Interface de tek metot kullanılacaksa Interfaceleri parçalamamız gerekecektir.
    class ABank : IPrivateBankConnector
    {
        public void Operation1()
        {
           // kodladık
        }

        public void Operation2()
        {
            // kodladık
        }
    }
    class BBank : IPublicConnector
    {
        public void Operation1()
        {
            // kodladık
        }

        public void Operation3()
        {
            // kodladık
        }
    }
    class CBank : IBankConnector
    {
        public void Operation1()
        {
            // kodladık
        }

        public void Operation2()
        {
            // Kullanılmasına gerek yok bu yüzden burayı ayrıştırmalıyız.
        }
    }




5) Dependency Inversion Principle :Yüksek seviyeli sınıfların düşük seviyeli sınıfların soyut hallerini kullanmasıdır. Bu şekilde bağımlılığı düşürmüş oluruz. Bir sınıf içinde başka bir sınıfı kullanıyorsak daha doğrusu bir sınıf içinde başka bir sınıfı somut haliyle kullanıyorsak (new lemek, instance) tasarım deseni bozulmuş olur. Bu yüzden sınıflarda soyut haliyle kullanılması gerekmektedir.
Dependency Inversion bir tasarım deseni kullanır Bu tasarım deseni Dependency injection'dur.
Bu tasarım deseni en çok Constructor ' dan bağımlılık sınıfının implementasyonu olan interface 'i geçmektir. Amaç bağımlılığı ortadan kaldırmaktır.


 class CustomerManager // Yüksel seviyeli sınıf 
    {
        private IMevzuat _mevzuat; // Dependency injection  Constructor kullanımı sık kullanılmaktaıdr.

        public CustomerManager(IMevzuat mevzuat) 
        {
            _mevzuat = mevzuat; // burada düşük seviyeli bir sınıfa göre new leme yapmadık.
        }

        public void Add()
        {
            //Mevzuat1 mevzuat1 = new Mevzuat1(); //  burada düşük seviyeli bir sınıfa göre new leme yapmadık.

            //mevzuat1.IslemYap(); //böyle kullansaydık işlem Mevzuat1 e göre çalısırdı  daha sonra Mevzuat2 Mevzuat3 işin içine girerse burada if ile kontroller yapılarak 
            _mevzuat.IslemYap();
        }
    }
    // interface new lenemez
    interface IMevzuat
    {
        void IslemYap();
    }
    // birinci mevzuat bir IMevzuat implementasyonudur
    class Mevzuat1 : IMevzuat // Mevzuat1 düşük seviyeli sınıf
    {
        public void IslemYap()
        {
            Console.WriteLine("1.Mevzuat");
        }
    }
    class Mevzuat2 : IMevzuat
    {
        public void IslemYap()
        {
            Console.WriteLine("2.Mevzuat");
        }
    }



 Dependency injection ' ı ayağa kaldırmak için loC Container ı kullanıyoruz.

loC Container (Inversion of Control) :  Üstseviyeli sınıflar alt seviyeli sınıfları kullanırken onları interfaceleri üzerinden kullanıyoruz.
Ioc Container üst seviyeli sınıfın ihtiyaç duyduğu alt seviyeli nesnenin bizim için arka planda instance sini tutuyor. loC Container ı bir kontrol kutusuna benzetebiliriz kutunun içerisine biri senden IMevzuat   isterse  (kod tarafında kırmızı yazdığım) ona Mevzuat1 mı , Mevzuat2 mi vs yi ver derse veririz.
Bu instance nin yaşam döngüsünü tutuyor. loC  araçlarına Ninject,Unity,Castle Windsor ,AutoFac,Structure Map, Dry IoC,LightInject örnek verilebilir.


 
 class Program
    {
        static void Main(string[] args)
        {
              
            CustomerManager customerManager = new CustomerManager(new Mevzuat1());
            customerManager.Add();
            Console.ReadLine();
        }
    }

    class CustomerManager 
    {
        private IMevzuat _mevzuat; 

        public CustomerManager(IMevzuat mevzuat)
        {
            _mevzuat = mevzuat;
        }

        public void Add()
        {            
            _mevzuat.IslemYap();
        }
    }   
    interface IMevzuat
    {
        void IslemYap();
    }
    // birinci mevzuat bir IMevzuat implementasyonudur
    class Mevzuat1 : IMevzuat 
    {
        public void IslemYap()
        {
            Console.WriteLine("1.Mevzuat");
        }
    }
    class Mevzuat2 : IMevzuat
    {
        public void IslemYap()
        {
            Console.WriteLine("2.Mevzuat");
        }
    }



ÖZET OLARAK

1) Single Responsibility Principle :Bir sınıfın sadece bir sorumluluğu olmalıdır. Bir sınıf birden fazla işle yada katmanla ilişkilendirilmemelidir.

2) Open/Closed Principle : Bir sınıf gelişime açık, ancak değişime kapalı olmalı. Bir sınıfa yeni bir özellik ekleme halinde sınıfın mevcut kodlarının değişmesi gerekiyorsa bu o sınıfın Loose Coupling (Gevşek bağımlılık) uymadığı anlamına ve yeterli esneklik sağlamadığı anlamına gelir.

3) Liskov ‘s Substitution Principle : Sırf birbirine benziyor diye nesneleri birbirinden miras almamalıyız. mesela dikdörtgen hesapla ile kare hesapla ikiside aynı mantık diyip tek metot yapmamalıyız.

4) Interface Segregation Principle :Arayüzlerin ayrımı anlamına gelen bu ilke bir arayüzü implemente alan sınıfların gereksiz metotları bulundurmaya zorlanmasının önlenmesidir. Mümkün olduğunda ortak özellikler arayüz halinde tasarlanmalı ve gerekirse farklı arayüzler birbirlerinden extend almalıdır.

5) Dependency Inversion Principle :Bağımlılıklara çözüm bulmadır diyebiliriz. Yüksek seviyeli sınıflar düşük seviyeli sınıflara bağımlı olmamalıdır. Her ikiside soyut kavramlara bağımlı olmalıdır. Çünkü somut sınıflarda değişikliklerin meydana gelmesi daha fazladır.

Hiç yorum yok:

Yorum Gönder