Object Oriented Programming (Nesne Yönelimli programlama) nedir? -1
Bunu yazı dizisi haline getirip, OOP’yi her yönüyle anlamak için gerekli heryere değinmeyi planlıyorum.
OOP bir kodlama stilidir. Kodlarımızı organize etme yöntemlerinden biri. Bizi spaghetti code denilen karmaşık anlaşılması güç kod yığınlarından kurtarıp daha organize/anlaşılır bir yapı elde etmemizi sağlar. Zaten ortaya çıkış nedeni de budur. Bunda da başarılı olmuştur. Çünkü küçük/büyük birçok popüler programlama bu yöntemle yapılmıştır. Yalnız spaghetti code dediğimiz bu karmaşık yapıya tek çözüm OOP değildir, aslında Functional Programing denilen bir başka popüler çözüm yolu daha vardır. JavaScript’te kullandığımız “map”, “filter”, “pop” gibi method’lar bu Functional Programing yapısı ile oluşturulmuştur. Fakat biz şuan konumuz olan OOP’den devam edeceğiz.
Genelde OOP’de object oluşturmak için classes denilen bir şey kullanılır. Örneğin nasıl ki bir mimar ev yapmak için ev-planına uyarak evler inşa ediyorsa biz de class’ları object oluşturmak için bir nevi plan olarak düşünülebiliriz. Plan aslında somut bir şey değildir, yani sadece mimari bir terim olarak evin ölçekli çiziminden ibarettir. Bununla istediğimiz kadar istediğimiz sayıda birbirinin aynısı gerçek somut evler inşa edebiliriz. Class’larda aynen böyledir, object oluşturmamıza yarayan birer plandır. Aşağıda bir class yapısı örneği gösterilmiştir;
Yukarıdaki class örneği user, password, email verileri ile login ve sendMessage methodlarını içeriyor. Fakat şu anda bu sadece bir taslak ve gerçek dünya verilerilerini içermiyor. Bu User class’ında kullanıcıyla ilgili her şey vardır; kullanıcı bilgileri, parola, email gibi bilgiler ile login olma ve mesaj gönderme methodları gibi. Tüm bu veriler ve methodlar güzel ve bağımsız tek bir block’ta toplanmıştır. Şimdi bu class’tan bir obje oluşturabilir ve gerçek dünya verilerine sahip olabiliriz.
Şimdi bu class’ların bir güzelliği şudur, buradan istediğimiz kadar yeni object oluşturabiliriz. Tıpkı bir mimari plandan sınırsız sayıda ev inşa edebildiğimiz gibi. Yukarıdaki örnekte “mehmet” objesini oluşturduk, temel iskelet aynı kalmak kaydıyla istediğimiz sayıda yeni object’ler oluşturabiliriz. Peki gerçek dünya verilerini oluşturabildiğimiz bu sınıfları nasıl tasarlayabiliriz? Mimarlık öğrencisinin “bir evin planını nasıl tasarlayabilirim” demesi gibi.
Bu kolay bir soru değildir ve tek bir cevabı da yoktur. Yalnız iyi bir class oluşturmak için 4 temel prensip vardır. Bunlar; 1) Abstraction (soyutlama) 2)Encapsulation (kapsülleme) 3) Inheritance (miras) 4) Polymorphism. Bu şıklar kafa karıştırmasın aslında kolay anlaşılır prensiplerdir. Ve bunlar OOP dışında da kullanılabilecek önemli özelliklerdir.
1) Absraction (soyutlama)
Detayları görmezden gelme/gizleme anlamındadır. Yani mesela bir telefon üreticisini düşünelim, telefondan erişebiliceğimiz özelliklere örneğin şarj voltajını ayarlama, titreşim motoruna erişme gibi aslında kullanıcının işine yaramayacak ve kafa karışıklığına neden olacak özellikleri telefona koyması ne kadar gereksiz birer ayrıntı olurdu. Kullanıcının bu kadar ayrıntıya gerçekten ihtiyacı var mı? Sanırım yok. Gerçek telefonlarda bu ayrıntılar gizlenmiştir. Elimizde sarj voltajına erişim imkanı yok ama şarj durumu göstergesi gibi kullanıcı için gerekli olan özellikler var. Diğer tüm ayrıntılar hala arka planda çalışmaya devam ediyor fakat bizim erişimimiz yok.Class örneğimize dönecek olursak, kullanıcının ayakkabı numarası, göz rengi, saç rengi gibi gereksiz ayrıntıları tasarlamamıza gerek yok. Bu kullanıcı ayrıntılarını abstract ediyoruz, yani soyutluyoruz.
2) Encapsulation (kapsülleme)
Classın içindeki bir takim özelliklere class dışından erişimin kapatılması yani kapsüllenmesi işlemidir. Özel duruma getiriyoruz. Burada da API’ları örnek gösterebiliriz. Ve object’ler arası etkileşim bu API’lar aracılığı ile olur. Örneğimize dönecek olursak, mesela password ve email’i private yapabiliriz.
Ama anlatılmak istenen şeyin basit olduğu ve anlaşıldığını düşünüyorum. Bu “private” sözcüğünü eklediğimiz yerler dışarıdan erişime kapatılıyor fakat class içerisinden hala erişilebilir, yukarıdaki resimde mesela password’de login methodundan erişebiliyoruz, “private” olmasına rağmen. Diğer özellikler ise hala dışarıdan erişime açıktır. Mesala oturum açmak için login methoduna ihtiyacımız var, buna dışarıdan erişebiliriz.
3) Inheritance (miras)
Mesela 2 tür kullanıcıya ihtiyacımız var biri user diğeri admin. Admin kullanıcısı user kullanıcısının sahip olduğu tüm haklara sahiptir ve ayrıca bir takım mesela “deleteUser” gibi methodlara da sahiptir. Mantıklı olan budur çünkü bir admin aynı zamanda user’dır. Eğer bu 2 kullanıcı türünü ayrı ayrı tasarlarsak bir çok kodu yinelemiş oluruz ve bu da clean code prinsiplerine aykırı düşer. İşte inheritance yani miras burada devreye giriyor.
User parent class’ından yeni alt class’lar üretebiliriz, ve bunu yaparkende bir takım ek özelliklerle bunu genişletebiliriz. Inheritance parent class’ın tüm özelliklerini child class için kullanıma açar. Bunun neden her iki sınıf içinde ortak olan mantığı bir daha yazmadan yeniden kullanmaktır. Mesela örneğimizde her iki sınıf içinde gerekli olan login methodu bulunması lazım. Bunu da defalarca yazmamıza gerek yoktur.
4)Polymorphism
Birçok şekil anlamına gelir. Yani child class’ın parent class’tan devraldığı mirasın üzerine yazabilmesi, onu değiştirebilmesi. Mesela User parent class’ından Admin dışında bir de Author sınıfı oluşturduğumuzu varsayalım, bu Author sınıfında “sendMessage” özelliğini kaldırıp yerine “writePost” özelliğini ekleyebiliriz.
Böylelikle OOP’ye giriş yapmış bulunmaktayız. Aslında çok fazla ayrıntı var fakat bu OOP’yi tam bir şekilde anlayabilmemiz için bu ayrıntılara da ihtiyacımız var.