Open/Closed Principle



2 dakikalık okuma
December 18, 2018

Solid prensiplerinin ikincisi olan “Open/Closed Principle” ile bu yazı dizimize devam ediyoruz. Bob amcamızın açıklamasıyla bu prensibin ortaya çıkış motivasyonu şu:

Bir sınıf ya da metod genişletmeye açık; ama modifiyeye kapalı olmalıdır.

Böylece kodun bakımı ve ileride geliştirmesi daha kolay olacaktır. Hemen örneklendirerek kafamıza daha iyi oturmasını sağlayalım:

Bir e-ticaret sistemi için ödeme alma modülü yazacağız. Bu metodu bilmeden önce şöyle bir şeyler yaptığımızı farz edelim:

 <?php   

     class Kasa {

         public function parayiAl(Fatura $fatura)
         {
             $this->pesinAl($fatura);
         }

        public function pesinAl($fatura)
        {
             // peşin para alındı...
         }
     }

Yukarıdaki kodu analiz edelim:

Müşteriden sadece peşin para alma metodumuz var. İleride patronumuz dese ki: “master kart, visa kart, paypal gibi ödemeler de olsun. Hatta daha da ileride başka ödeme yöntemleri de ekleyebiliriz. Ali pay gibi…”

Ne yapmalıyız? Yukarıdaki sınıfımıza hemen 3 metod daha yazarız visa, master ve paypal adında oldu bitti olur (!)

Öyle bir şey yaparsak işte SOLID’teki ikinci prensibimiz olan “Open/Closed Principle” ile çelişmiş olacağız. Çünkü sınıfı modifiye yapmış olacağız. Bu prensibe uyum sağlamak istersek kodumuzu aşağıdaki gibi değiştirmemiz gerekecek:

Evvela bir Interface yazmamız lazım:

Interface odemeYontemleri {
public function odemeAl($fatura)
}

Sonra odeme yöntemlerimizi interface’den implement ederek kodlayalım:

class pesinOde implements odemeYontemleri {
public function odemeAl($fatura) {
// pesin al
}
}

class masterKartIleOde implements odemeYontemleri {
public function odemeAl($fatura) {
// master card
}
}

class paypalIleOde implements odemeYontemleri {
public function odemeAl($fatura) {
// paypal
}
}

Gelelim Kasa ana sınıfımızı yazmaya:

     class Kasa {        
         public function parayiAl(Fatura $fatura, odemeYontemleri $odeme)
         {
             $odeme->odemeAl($fatura);
         }
     }

Kullanımı:

$kasa_ac = new Kasa();
$kasa_ac->parayiAl($fatura, paypalIleOde);

// eğer pesin odeme alacaksak
$kasa_ac->parayiAl($fatura, pesinOde);

Şimdi Kasa ana sınıfımızı analiz ederek şu 2 soruyu soralım:

  1. Kasa sınıfımız genişlemeye açık mı ?

Cevap: Evet. Yukarıdaki kullanımında görüldüğü üzere dinamik olarak herhangi ödeme metodunu kasa sınıfına geçiriyoruz. Bunun için odemeYontemleri adında bir interface yazarak odeme metodlarını bu interface’den implement ederek oluşturuyoruz. İleride Ali pay gibi bir ödeme metodu bile çıksa

$kasa_ac->parayiAl($fatura, alipayOde); 

şeklinde yeni metodumuzu hemen kasaya uygulayabiliriz.

  1. Kasa sınıfımız modifiyeye kapalı mı ?

Cevap: Evet. Ben yeni ödeme metodlarını kasa sınıfına uygularken “kasa” sınıfımızı modifiye etmiyorum. Ellemiyorum bile; ama kasa sınıfına istediğim ödeme yöntemini göndererek kullanmasını sağlayabiliyorum.

Yukarıdaki 2 sorunun cevabı da evetse biz Open/Closed prensibini başarıyla kullanmışız demektir.

Saygılar.


Etiketler: