Open Closed Principle

Emre ÇOĞALAN
3 min readJul 6, 2024

--

Open Closed Principle
Open Closed Principle

Solid prensiplerinin 2.’si olan bu prensibimizde bir kodun güncellenebilirliğini ele alır. Değişen ve gelişen bir dünyada yazılımların sabit kalması pek tabiki düşünülemez. Dolayısıyla yazılımlarda yeni özellikler, yeni kullanıcılar, yeni teknolojiler vb. nedenlerle sürekli olarak değişmektedirler. Peki varolan kodlarımızı yeni istekler doğrultusunda nasıl değiştirmeliyiz? Daha doğrusu değiştirmeli miyiz ?

Yazılım sektöründe sıkça kullanılan bir tabir vardır. “Aman çalışıyorsa dokunmayalım.” OCP (open closed principle) prensibi de aslında bu felsefeyi temel alır. Var olan metod, sınıf vb. yapılar değiştirilmemeli, geliştirilmelidir. Bu anlamda bu yapılar değişime kapalı olmalı, genişletilmeye açık olmalıdırlar.

Uygulama

Bir örnekle anlatmak istediklerimizi somutlaştıralım. Bir mağazanın kendi müşterilerini sınıflandırdığını ve bu farklı müşteri gruplarına farklı indirim uyguladığını varsayalım. Bu noktada indirim hesabı yapan methodu yazalım.

public double calculateDiscount(String customerType, double purchaseAmount) {
if (customerType.equals("Regular")) {
return purchaseAmount * 0.1;
} else if (customerType.equals("Premium")) {
return purchaseAmount * 0.2;
}
return 0;
}

Metodumuz string tipinde customerType isminde bir değişken alıyor. İlgili değişkene göre farklı indirim hesabı yapıyor.

Şimdi gelelim yeni özelliklere. İlgili mağaza özel müşteri gurubu belirledi ve bu müşteri gurubuna daha fazla indirim yapmak istiyor. Bu şekilde kodumuzu güncellemek istediğimizde direk olarak calculateDiscount metodunu güncelleyerek bir else if bloğu daha eklememiz gerekecek.

public double calculateDiscount(String customerType, double purchaseAmount) {
if (customerType.equals("Regular")) {
return purchaseAmount * 0.1;
} else if (customerType.equals("Premium")) {
return purchaseAmount * 0.2;
} else if (customerType.equals("Special")) {
return purchaseAmount;
}
return 0;
}

İşte OCP bu şekilde bir metodun güncellenmesini istemiyor. Peki ne yapacağız. Burada aslında ilk yapmamız gereken müşteri guruplarını soyutlaştırmak.

interface Customer {
}

class RegularCustomer implements Customer {
}

class PremiumCustomer implements Customer {
}

Şimdide indirim hesabını yapma işlemini bu sınıflara yüklüyoruz. Bu işlem aynı zamanda kodumuzun SRP’ye de uygun olmasını sağlıyor.

interface Customer {
double calculateDiscount(double purchaseAmount);
}

class RegularCustomer implements Customer {
@Override
public double calculateDiscount(double purchaseAmount) {
return purchaseAmount * 0.1;
}
}

class PremiumCustomer implements Customer {
@Override
public double calculateDiscount(double purchaseAmount) {
return purchaseAmount * 0.2;
}
}

Evet ilgili indirim hesaplama işlemini alt sınıflara aldık. Artık DiscountCalculator sınıfındaki calculateDiscount metodumuza string olarak müşteri tipini geçmek yerine direk olarak müşteri nesnesini geçeceğiz. calculateDiscount metodumuz ise ilgili müşterinin kendi calculateDiscount metodunu çağırarak indirim hesaplama işlemini gerçekleştirecek.

class DiscountCalculator {
public double calculateDiscount(Customer customer, double purchaseAmount) {
return customer.calculateDiscount(purchaseAmount);
}
}

Şimdi uygulamamıza özel müşteri gurubunu eklemek istediğimizde yapmamız gereken Customer interface’ini implament eden yeni bir sınıf oluşturmak ve ilgili calculateDiscount metodunu ezmek.

class SpecialCustomer implements Customer {
@Override
public double calculateDiscount(double purchaseAmount) {
return purchaseAmount * 0.5;
}
}

Bu sayede DiscountCalculator sınıfındaki calculateDiscount metoduna dokunmadan yeni geliştirmelerimizi yapabilmiş olduk.

Dikkat

Bazı örneklerde aslında soyutlama işleminin yapıldığını fakat calculateDiscount metodunda yine RTTI (Run Time Type Information) yapılarak tespit edilen tipe göre işlemlerin yine calculateDiscount metodunda yapıldığını gördüm.

public double calculateDiscount(ICustomer customer, double purchaseAmount) {
if (customer instanceof RegularCustomer) {
return purchaseAmount * 0.1;
} else if (customer instanceof PremiumCustomer) {
return purchaseAmount * 0.2;
} else if (customer instanceof SpecialCustomer) {
return purchaseAmount * 0.5;
}
return 0;
}

Buda yine aynı şekilde OCP’yi ihlal eden bir durumdur. İlgili indirim hesaplama işlemi müşteri bazında özel olarak hesaplandığı için ilgili sınıfların içerisinde override edilmelidir.

Sonuç

Sonuç olarak OCP’nin amacı kodu mümkün olduğunca değiştirmeden yeni geliştirmeleri koda ekleyebilmek. Bu sayede var olan koda dokunmadan yeni özellikleri eklenebilecek. Ayrıca kodun test edilebilirliği, okunabilirliği ve güncellenebilirliği artırılmış olacak.

Tüm Yazılım Prensipleri

Serideki tüm yazılar burada.

Software Principles (Yazılım Prensipleri)

2 stories
Single Responsibility Principle
Open Closed Principle

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Emre ÇOĞALAN
Emre ÇOĞALAN

No responses yet

Write a response