Yazılım

Nesne Yönelimli Programlama (OOP): Sınıflar mı, Soyutlama mı? (Doğru Kullanım)

23 Şubat 2026 7 dk okuma 10 görüntülenme

Sihirli Kelimenin Büyüsüne Kapılmak: "Class" Yazmak Her Şeyi Çözer mi?

Yazılımla tanıştığım o ilk yıllara, 2005’lere dönüp baktığımda bazen kendime gülümsüyorum. İlk başlarda her şey yukarıdan aşağıya doğru akan, birbirine dolanmış satırlardan ibaretti. Sonra bir gün o sihirli anahtar kelimeyle tanıştım: class. İtiraf edeyim, ilk zamanlar ben de o kelimeyi dosyanın en başına yazdığım an, dünyanın en modern, en kaliteli kodunu ürettiğimi sanıyordum. "Artık Nesne Yönelimli Programlama yapıyorum!" diyerek ortalıkta gururla dolaşıyordum.

Ama gerçekler, o devasa, binlerce satırlık UserManager sınıfımla yüzleştiğim gece yüzüme tokat gibi çarptı. Bir sınıf düşünün; hem veritabanına bağlanıyor, hem kullanıcı şifresini şifreliyor, hem hoş geldin e-postası atıyor, hem de profil fotoğrafını boyutlandırıyordu. Kod bir hata verdiğinde, o dosyanın içinde kaybolmak, sık bir ormanda pusulasız kalmak gibiydi. Sadece class yazıyordum evet, ama aslında yaptığım şey eski, spagetti prosedürel kodumu süslü bir kutunun içine hapsetmekten başka bir şey değildi.

Hepimiz bu yollardan geçtik. Bugün Pixel Lab®'de projeleri kurgularken, ekibe yeni katılan arkadaşlarda da sık sık aynı yanılgıyı görüyorum. Sınıflar oluşturmak, nesneler türetmek işin sadece sözdizimi (syntax) kısmıdır. Gerçek OOP prensipleri, kodun nasıl yazıldığından çok, sistemin nasıl tasarlandığıyla ilgilidir.

Veri Taşıyıcıları (Data Holders) vs. Gerçek Nesneler

Nesne Yönelimli Programlama dünyasında en sık düştüğümüz tuzaklardan biri, nesneleri sadece verileri tutan aptal kutular (Data Holders) olarak görmektir. Bir sınıf yazıp, içine on tane özellik (property) tanımlayıp, hepsine de getter ve setter metodları eklediğinizde OOP yapmış olmazsınız. Bu, prosedürel mantığın ta kendisidir.

Gerçek bir nesne, sadece veriyi tutmaz; o verinin davranışını da kontrol eder. Dürüst olmak gerekirse, yıllarca nesnelerimi dışarıdan yönetmeye çalıştım. Bir nesnenin içindeki veriyi alıp, dışarıda bir if-else bloğunda işleyip, sonucu tekrar nesneye yazıyordum. Oysa nesne yönelimli düşünmek, nesneye "Bana verini ver, ben halledeceğim" demek yerine, "Al bu işi senin verilerinle sen yap" demektir. Kendi durumunu (state) koruyan ve dışarıya sadece anlamlı davranışlar sunan nesneler inşa etmeye başladığınızda, kodunuzun nasıl bir anda hafiflediğine inanamayacaksınız.

Soyutlama (Abstraction): Sadece Kod Gizlemek Değil, Bir Sözleşme İmzalamak

Eğer hayatımı ikiye bölen o çizgiyi hatırlarsanız; bilgisayarı kapattığım an kendimi ormana atarım. Kamp ateşi yakmak, doğanın o sessizliğinde kaybolmak benim için bir terapi. Aslında Soyutlama (Abstraction) kavramını en iyi doğada, kamp yaparken anladım.

Kampa giderken yanımda taşıdığım küçük bir gaz ocağım var. Ocağı kullanmak için yapmam gereken tek şey vanayı açıp çakmağı çakmak. Ocağın içinde gazın nasıl bir basınçla ilerlediği, hangi valflerden geçtiği veya ateşlemenin fiziksel olarak nasıl gerçekleştiği beni hiç ilgilendirmiyor. Ben sadece ocağın bana sunduğu arayüzü (vanayı ve düğmeyi) kullanıyorum.

İşte yazılımda soyutlama tam olarak budur. Bir sınıfın karmaşık iç dünyasını dışarıdan gizlemek ve sadece gerekli olanı kullanıma açmaktır. Ancak burada bir adım daha ileri gitmemiz gerekiyor: Interface kullanımı.

Interface (Arayüz), sınıflar arasında imzalanan katı bir sözleşmedir. Sistemin geri kalanına, "Bu nesnenin arka planda işi nasıl yaptığı umurumda değil, ben sadece bu nesnenin şu davranışı sergileyeceğinden eminim" demenin yoludur. Interface'ler sayesinde kodumuz, sınıfların somut detaylarına değil, onların soyut sözleşmelerine bağımlı hale gelir. Bu da bizi o korkunç bağımlılık (coupling) cehenneminden kurtarır.

Polimorfizm ile Spagetti If-Else Bloklarından Kaçış

Gelelim işin en keyifli, o "Aha!" anını yaşatan kısmına. Eğer bir projede, aynı amaca hizmet eden ama farklı şekillerde çalışan yapılar için metrelerce uzayan if-else veya switch-case blokları yazıyorsanız, orada durup bir nefes almanın vakti gelmiştir.

Örneğin bir e-ticaret sisteminde ödeme altyapısı kurduğumuzu düşünelim. Kötü tasarımda, yani prosedürel kafayla yazılmış bir sınıfta süreç genelde şuna benzer:


class PaymentProcessor {
    public function pay($method, $amount) {
        if ($method === 'credit_card') {
            // Kredi kartı API'sine bağlan, token al, işlem yap...
        } elseif ($method === 'paypal') {
            // PayPal SDK'sını başlat, yönlendirme yap...
        } elseif ($method === 'crypto') {
            // Kripto cüzdanı doğrula, transferi bekle...
        }
    }
}

Bu kod parçası, yeni bir ödeme yöntemi eklendiğinde sürekli değiştirilmek zorundadır (Açık/Kapalı prensibine - Open/Closed Principle - tamamen aykırı). Üstelik test etmesi bir kabustur. Peki Polimorfizm (Çok biçimlilik) bizi bu dertten nasıl kurtarır?

Önce kamp ocağı örneğindeki gibi bir sözleşme (Interface) yazarız:


interface PaymentMethod {
    public function processPayment($amount);
}

Sonra her ödeme yöntemini kendi sınıfına taşırız ve bu sözleşmeye uymaya zorlarız:


class CreditCardPayment implements PaymentMethod {
    public function processPayment($amount) {
        // Sadece kredi kartı işlemleri...
    }
}

class PaypalPayment implements PaymentMethod {
    public function processPayment($amount) {
        // Sadece PayPal işlemleri...
    }
}

Ve asıl sihir PaymentProcessor sınıfımızda gerçekleşir:


class PaymentProcessor {
    public function pay(PaymentMethod $method, $amount) {
        $method->processPayment($amount);
    }
}

İşte bu kadar! PaymentProcessor sınıfı artık hangi ödeme yönteminin kullanıldığıyla ilgilenmiyor. O sadece PaymentMethod arayüzüne sahip herhangi bir nesnenin processPayment metodunu çağırabileceğini biliyor. Yeni bir ödeme yöntemi mi geldi? Sadece yeni bir sınıf oluşturun ve sisteme dahil edin. Mevcut hiçbir koda dokunmanıza gerek yok. Bu yapı sadece kod kalitesi açısından bir sıçrama değil, aynı zamanda sürdürülebilir kod yazmanın altın anahtarıdır.

Mükemmel Kod Yoktur, Sürekli Gelişen Kod Vardır

Bilgisayar başında sabahladığım, gözlerimin kan çanağına döndüğü o ilk yıllardan bugüne çok şey değişti. Pixel Lab®'i kurarken kendime verdiğim en büyük söz, karmaşıklığı sadeliğe dönüştürmekti. Ancak bu, bir gecede olacak bir şey değil.

Eğer şu an kendi projelerinizi gözden geçiriyor ve "Eyvah, benim sınıflarım da sadece veri tutuyor" veya "If-else bloklarıyla destan yazmışım" diyorsanız, sakın moralinizi bozmayın. Bisiklete atlayıp o uzun rotalara ilk çıktığımda da bacaklarım titriyordu, nefesim kesiliyordu. Kaslar nasıl antrenmanla güçleniyorsa, analitik düşünme ve doğru mimari kurma yeteneği de pratikle, eski hatalarla yüzleşerek gelişiyor.

Bir sonraki projenizde IDE'nizi açtığınızda, o sihirli class kelimesini yazmadan önce birkaç saniye durun. Kendinize şu soruyu sorun: "Ben şu an sadece kodlarımı bir dosyanın içine mi grupluyorum, yoksa gerçekten bir davranışı olan, sınırları belli, bağımsız bir nesne mi inşa ediyorum?"

Gerçek OOP, kod yazmaktan ziyade bir tasarım felsefesidir. Doğadaki o muazzam ekosistem gibi; her canlının (nesnenin) kendi görevi vardır, kimse başkasının işine karışmaz ama hepsi birbiriyle mükemmel bir uyum içinde haberleşerek o devasa ormanı hayatta tutar. Kodlarınızın da kendi içinde böyle huzurlu ve tıkır tıkır işleyen bir orman olması dileğiyle. İçeri buyurduğunuz ve vaktinizi ayırdığınız için teşekkürler, bir sonraki yazıda görüşmek üzere.

Yorumlar

Henüz yorum yapılmamış. İlk yorumu siz yazın!

Yorum Yaz

E-posta adresiniz yayınlanmayacaktır.
0 / 2000