Open/Closed Principle (OCP) Nedir?
Bu yazımızda, Robert C. Martin tarafından tanıtılan SOLID ilkeleri arasında ikinci sırada yer alan “Open/Closed Principle” kavramına odaklanacağız.
Open/Closed Principle
Türkçeye “Açık/Kapalı Prensibi” şeklinde çevirebileceğimiz “Open/Closed Principle” ile bir yazılım modülünün (sınıf, fonksiyon, modül vb.) genişlemeye açık ama değişime kapalı olması gerektiği ifade edilir.
Başka bir deyişle, mevcut kodun değiştirilmesi gerekmeden yeni özelliklerin eklenmesine imkan tanınmalıdır. Böylece kodumuz kırılgan olmayacak ve mevcut özelliklerle alakalı çakışmalar minimalize edilerek genişletilecektir.
İşte tam da bu noktada “bu prensibi kodlarımıza nasıl uygulayabiliriz?” sorusunu sormamızın vakti geldiğine göre maddeler halinde buna cevap verelim:
- Soyutlama ve Arayüzler Kullanımı: Farklı bölümler arasındaki bağımlılıkları azaltmak ve genişletilebilirlik sağlamak için soyut sınıflar veya arayüzler kullanılabilir.
- Polimorfizm: Ortak bir arayüzü veya soyut sınıfı genişleten çeşitli sınıflar yoluyla farklı davranışların uygulanması sağlanabilir.
Öncelikle, mevcut işlevselliklerimizi genişletmek yerine yeni işlevsellikler ekleyebileceğimiz bir yapı kurmamız gerekir. Örnek üzerinden anlatırsak ziyadesiyle anlaşılacağını düşünüyorum.
Örneğin, bir ödeme sistemini ele alalım. Farklı ödeme yöntemleri için ayrı sınıflar oluşturmak yerine, bir ödeme işlemi arayüzü tanımlayabilir ve her ödeme yöntemini bu arayüzü uygulayacak şekilde ayrı sınıflar olarak tasarlayabiliriz. Yeni bir ödeme yöntemi eklendiğinde, sadece yeni bir sınıf eklememiz ve bu arayüzü uygulamamız yeterli olacaktır.
class PaymentProcessor:
def pay_with_credit_card(self, amount):
# Kredi kartı ile ödeme işlemleri
print(f"Ödeme {amount} TL kredi kartı ile yapıldı.")
def pay_with_paypal(self, amount):
# PayPal ile ödeme işlemleri
print(f"Ödeme {amount} TL PayPal ile yapıldı.")
# Kullanımı
processor = PaymentProcessor()
processor.pay_with_credit_card(100)
processor.pay_with_paypal(150)
Şimdi, aynı işlevselliği “Açık/Kapalı Prensibine” uygun bir şekilde nasıl geliştirebileceğimizi inceleyelim. Bakınız:
from abc import ABC, abstractmethod
# Ödeme işlemleri için soyut bir sınıf tanımlayalım
class PaymentMethod(ABC):
@abstractmethod
def pay(self, amount):
pass
# Kredi kartı ödeme sınıfı
class CreditCardPayment(PaymentMethod):
def pay(self, amount):
print(f"Ödeme {amount} TL kredi kartı ile yapıldı.")
# PayPal ödeme sınıfı
class PayPalPayment(PaymentMethod):
def pay(self, amount):
print(f"Ödeme {amount} TL PayPal ile yapıldı.")
# Ödeme işlemcisi sınıfı
class PaymentProcessor:
def process_payment(self, amount, payment_method: PaymentMethod):
payment_method.pay(amount)
# Kullanımı
credit_payment = CreditCardPayment()
paypal_payment = PayPalPayment()
processor = PaymentProcessor()
processor.process_payment(100, credit_payment)
processor.process_payment(150, paypal_payment)
Görüldüğü üzere, “Açık/Kapalı Prensibi” bir yandan kodumuzu genişletirken bir yandan da mevcut yapıyı korumamızı kolaylaştırmaktadır.