ile

Hiç Bilmeyenler İçin Nesne Yönelimli Programlamaya Giriş-3

Bu yazı daha önce yazdığım Hiç Bilmeyenler İçin Nesne Yönelimli Programlamaya Giriş-2 yazısının devamıdır. Önce onu okumanızı öneririm.

View story at Medium.com

Nasıl kullanacağımızı şekliyle anlayan bir nesne

Nesneyi Kullanmak ve Arayüz Kavramı

Daha önce information hiding, yani bilgi gizleme kavramından bahsederken şöyle demiştik:

araba kullanırken, motorun, katalitik konvertörün, alternatörün o anda ne yaptığı ile ilgilenmiyoruz. Araç kullanıcısı olarak bizim amacımız bir yerden bir yere gitmek, ve bunu aracın direksiyonunu, vitesini, pedallarını vb. kullanarak gerçekleştiriyoruz.

Eğer araba kullanmayı biliyorsak, her türlü arabayı kullanabiliriz. Çünkü otomobiller üretilirken belirli standartlara uyularak üretilmekte. Çok fütüristik değilse, bir aracın, direksiyonunun, vitesliyse debriyajının gaz pedalının, sinyal kolunun vb. olduğunu önceden tahmin ediyoruz, çünkü daha önce sürücü kursunda öğrendiğimiz ve hayatımızda gördüğümüz tüm otomobillerden edindiğimiz tecrübe bilgisiyle böyle bir beklenti oluşturduk.

Bu ne ki şimdi?

Yani mesela bir otomobilde, vites sağ alt köşe yerine tavandaysa şaşırıp kalırız, ya da İngiltere’deysek bindiğimiz bir arabada direksiyonun solda değil sağda olması, önce bir alışma ve eğitim süresi gerektirir. (Ki İngiltere’de bu yüzden kiraladığım arabanın dikiz aynasını kırmışlığım var. Neyse ki kiralarken ek sigorta almıştım)

Ergonomi

Örneğin binlerce yıldır oturmuş çatal kaşık tasarımına baktığımızda, şeklinin insan eline oturacak şekilde tasarlandığını görürüz. Bu sayede ne işe yaradığını ve nasıl kullanılacağını bilmesek de, kaşığı sapından tutup, ucundaki çukurla bişiler yapabileceğimiz deneyerek tahmin ederiz. Bu sayede bebekler çatal kaşık kullanmayı kolayca öğrenebilirler. Burada kaşığın görevi, onun şeklini belirliyor. Kullanılan nesnelerin insanın verimli ve sağlıklı bir şekilde kullanabileceği şekilde üretilmesine, genel olarak ergonomi deniyor. Biz de tasarlayacağımız yazılımlarda insanların bu beklentilerine göre hareket edersek, insanları sıkıntıya sokan, delirten ve mutsuz eden yazılımlar yerine, onların sağlıklı bir şekilde kolayca kullanıp anlayabileceği şeyler üretmiş oluruz. Kaynak 1 Kaynak 2

Arayüz

Otomobillerdeki, otomobili rahatça kullanmamızı sağlayan bu yapıya arayüz deniyor. İşte tüm otomobillerde standart olan örneğin vites, direksiyon gibi yapıların standart büyüklükte olması, bu standart arayüzün ortak bir şekilde tüm otomobiller tarafından paylaşılmasından kaynaklanıyor. Ayrıca biz otomobili kullanırken, katalitik konvertörün o anki sıcaklığını sürekli düzenlemek ve gözetmek zorunda değiliz. İşte Arayüz aynı zamanda bizim için gözümüzden gereksiz detayları kaldırıyor. Sınıfımızın yapacaklarına karar verdiğimiz ve tasarımını yaparken yazdığımız kullanıcı tarafından public metodların kümesine Arayüz (interface), sınıf içindeki bir metodun alacağı parametrelerin sayısına, veri tiplerine ve döndürmesi gereken değerin veri tipine de Metodun İmzası (signature) deniyor. Arayüz kavramının detaylarına birden fazla sınıf ortak davranışı paylaşmak durumunda olduğunda tekrar detaylı olarak geri döneceğiz

Sınıfımızı yazmaya devam edelim

Önceki yazıda yazdığımız Dictionary Sınıfının başlık oluşturma ve değiştirme, nesneyi adam gibi yaratma işlerini güzelce halletmiştik. Şimdi nesnenin asıl görevlerini gerçekleştiren kodları yazmamız gerekiyor. Bunlar şu işlemlerden oluşuyordu;

  1. Sözlüğe bir başlık girmek.
  2. Başlık içeriğini güncellemek.
  3. Başlığı silmek
  4. Arama, sıralama ve filtreleme yapabilmek
  5. Veriyi bir dosyaya kaydedip yeniden kullanabilmek.

Sırayla ilerleyeceğiz. Şimdilik konunun basit anlaşılması için, başlıkları Dictionary nesnesinde bulunan $entries adlı diziye başlık adını anahtar olarak kullanarak ekleyeceğiz. Başımıza bela olacak sorunlara önceden önlem olmaya çalışacağız ki, daha sonra ağlamayalım.

Dizi üzerinde belalı işlemler

Yımırta

PHP’de array yani diziler, veriler üzerinde işlemler yapmamızı sağlayan güzel yapılardır. Şimdi henüz sınıfımıza eklemeden bir dizi üzerinde nasıl işlem yapabileceğimize bakalım. Proje dizinimiz içerisinde array.php isminde bir dosya oluşturup tarayıcı üzerinden çalıştıralım.

<?php

$entries = [];
$entries['nesne'] = 'Sınıf Örneği';
echo $entries['nesne'];

Tarayıcıyı açtığımızda şöyle bir sonuç göreceğiz:

Dizide işlem

Hazırda bilgisayarınızda PHP yorumlayıcısı yoksa, bu minik koda şuradan da erişebilirsiniz: https://3v4l.org/CPsXm Bu sitede bilgisayarını mahvetmeden, herhangi bir yerden istediğiniz PHP kodunu test edebilirsiniz. Öneririm.


Burada diziye bir anahtar atadık ve o anahtar içindeki değeri çağırdık. Peki dizide olmayan bir değeri çağırırsak ne olur? Görelim:

Kodu şu şekilde değiştirelim:

<?php

$entries = [];
$entries['nesne'] = 'Sınıf Örneği';
echo $entries['şey'];

Şöyle bir görüntüyle karşılaşacağız.

E yok ki.

Notice yani bildirim ifadesi burda kodumuzun çalışmasının durmadığını ama ileride başımıza belalar açılacağını bildiriyor.

Aklımıza şöyle sorular gelmesi gerekiyor:

  1. Eklemek istediğimiz başlık sözlükte yoksa ve çağırdıysak bu sorunu bildirim göstermeden nasıl hallederiz?
  2. Başlık zaten varsa ve değiştirmek istemiyorsak, aynı başlığa yeni bir açıklama değerini nasıl ekleriz?
  3. Bir başlığı silmek ya da düzenlemek istediğimizde ve başlıkta birden fazla açıklama varsa, tüm açıklamalara mı etki edeceğiz yoksa sadece birine mi?
  4. Bir başlığa, tarih bilgisini nasıl girebiliriz? Bu tarih bilgisine dayanarak nasıl sıralama işlemi yapabiliriz?
  5. Arama, filtreleme işlerini nasıl yapacağız?

Gördüğümüz gibi iş şimdiden boka sarmaya başladı. Sorunu spagetti bir fonksiyonla çözmeye çalışalım:

<?php

function
getEntry(string $title){
if(!isset($entries[$title])){
return $entries[$title];
}
}

$entries = [];
$entries['nesne'] = 'Sınıf Örneği';

echo getEntry('nesne')."<br>";

$entries['şey'] = 'İsimsiz nesne';

echo getEntry('şey')."<br>";

print_r($entries);

$entries['şey'] = null;

echo getEntry('şey')."<br>";

print_r($entries);

getEntry metodundan sonraki “<br>” ifadesine takılmayın. Fonksiyondan dönen metin değeri ile “<br>” yani alt satır etiketini birleştirdik. Şöyle hatalarla karşılaşacağız.


Fonksiyonumuz çalışmıyor çünkü global olarak tanımlanmış $entries adlı değişkene erişemiyor. PHP’de ve birçok C benzeri dilde {} süslü parantezlerle ayrılmış kodlara blok deniyor, ve bloklardaki kodlar, sadece bu blok içinde tanımlanmış değerlere erişebiliyor. (Kapsam yani Scope kavramı) Bunu geçici olarak çözmenin yolu var ama kötü pratik olduğundan ve tüm güvenlik önlemlerini mahvettiğinden anlatmıyorum bile. İşi yanlış yapmayı değil doğru yapmayı öğrenmemiz gerek.

Bunu geçici olarak spagetti kodunda şu şekilde çözebiliriz. getEntry metodunda üzerinde işlem yapacağımız diziyi parametre olarak gireceğiz.

<?php

function
getEntry(string $title, array $array){
if(isset($array[$title])){
return $title.' ifadesinin değeri: '.$array[$title].'<br>';
}
}

$entries = [];
$entries['nesne'] = 'Sınıf Örneği';

echo getEntry('nesne', $entries);

$entries['şey'] = 'İsimsiz nesne';

echo getEntry('şey', $entries);

print_r($entries);

$entries['şey'] = null;

echo getEntry('şey', $entries);

print_r($entries);

Satır satır kodu inceleyelim.

  1. array $array diyerek, fonksiyonumuzun kapsam yanı scope’sinin içine işlem yapacağmız diziyi kopyaladık. Eğer kopyalamak yerine diziye doğrudan erişmek ve değişiklik yapmak isteseydik &$array dememiz gerekiyordu. Buna Call by Reference yani Referans ile çağırma deniyor. Şimdilik bunun detayına girmeyeceğim.
  2. Fonskiyonumuzun değer döndürüp döndürmediğini anlamak için dönen değeri $title.’ ifadesinin değeri: ‘.$array[$title].’<br>’; olarak değiştirdik.
  3. Fonksiyonu her çağırdığımızda birleştirdiğimi ‘<br>’ ifadesini direk fonskiyonun içine yazdık ve kod tekrarını önledik.
  4. fonksiyon içinde isset kullanarak değerin var olup olmadığını kontrol ettik, ya da kontrol ettiğimizi sandık.
  5. yaptığımız her işlemden sonra dizimizin o anki durumunu print_r fonksiyonu ile ekrana bastık.
  6. $entries[‘şey’] = null; ifadesine kadar herşey normal. Ama bu ifadede fonskiyonumuz saçmalayacak. Görelim:


Null belası

bela

İlk iki durumda, getEntry fonskiyonu sorunsuz çalıştı. Ama fonksiyonda değerin olup olmadığını isset ile kontrol ettiğimiz için, dizide şey değeri var olduğu halde, şey ifadesinin değeri: yazmadı. Halbuki print_r ile dizinin içindekileri görüntülediğimizde şey anahtarının dizide halen var olduğunu görüyoruz. Peki bunu nasıl düzeltebiliriz? PHP’de önceden tanımlı olan array_key_exists fonksiyonunu kullanarak. Bu sayede örneğin “şey” anahtarı ibnelik olsun diye null değerine bilerek eşitlense bile metodumuz o değerin halen orda olduğunu anlayacak:

<?php

function
getEntry(string $title, array $array)
{
if (array_key_exists($title, $array)) {
return $title . ' ifadesinin değeri: ' . $array[$title] . '<br>';
}
}

$entries = [];
$entries['nesne'] = 'Sınıf Örneği';

echo getEntry('nesne', $entries);

$entries['şey'] = 'İsimsiz nesne';

echo getEntry('şey', $entries);

print_r($entries);

echo "<br>";

$entries['şey'] = null;

echo getEntry('şey', $entries);

print_r($entries);

Çalıştıralım ve görelim:


Yaptığımız değişiklik sayesinde, dizi içinde bir değer null değerine eşdeğer olsa bile, fonksiyonumuz bunu algılıyor ve dizi elemanını anahtarıyla basabiliyor. Burada anlamanızı istediğim şey, null’a güvenmeyin, hatta kodunuzda null ne kadar az ise o kadar temiz demektir. Null belası için şu kaynağı okumanızı öneririm.

Diziden veriyi silmek

dizi hedesi

Buraya kadar tamam. Peki diziden veriyi silmek istediğimizde ne yapacağız? Ve getEntry metodumuz nasıl saçmalamayacak? unset fonskiyonunu kullanacağız. Örneğimize devam edelim, kodumuzun sonuna şu satırları ekleyelim :

echo "<br>";

unset($entries['şey']);

echo getEntry('şey', $entries);

print_r($entries);

Çalıştırdığımızda dizi içindeki anahtarın temiz bir şekilde silindiğini görüyoruz.


Şöyle bir sorun var yalnız. getEntry() fonksiyonunu çağırdığımızda değerin var olup olmadığından haberimiz olmuyor. Eğer değer varsa yazıyı döndürüyor, değer yoksa, hiç bir sonuç elde edemiyoruz. Bu bir sorun mu? Bence evet, çünkü programımızın doğru çalışıp çalışmadığını, kod üzerinde hata yapıp yapmadığımızı anlayamıyoruz. Bu sorunu if bloğundan sonra else bloğu ekleyerek çözebiliriz. Ama pek şık değil. Herhangi bir hatayı önceden görmemizi ve ona göre önlem almamızı sağlayacak olan try-catch blokları var. Ama bu konuyu zamanı geldiğinde detaylıca anlatacağım.

Şu soruları sormuştuk:

  1. Eklemek istediğimiz başlık sözlükte yoksa ve çağırdıysak bu sorunu bildirim göstermeden nasıl hallederiz?
  2. Başlık zaten varsa ve değiştirmek istemiyorsak, aynı başlığa yeni bir açıklama değerini nasıl ekleriz?
  3. Bir başlığı silmek ya da düzenlemek istediğimizde ve başlıkta birden fazla açıklama varsa, tüm açıklamalara mı etki edeceğiz yoksa sadece birine mi?
  4. Bir başlığa, tarih bilgisini nasıl girebiliriz? Bu tarih bilgisine dayanarak nasıl sıralama işlemi yapabiliriz?
  5. Arama, filtreleme işlerini nasıl yapacağız?

Bunlardan ilk üç soruya kısmen cevap verdik. Bir sonraki yazıda kalan soruları aklımızda tutarak Dictionary.php dosyasındaki sınıfa geri döneceğiz..

Bir sonraki yazı şurda:

View story at Medium.com


Projelerle PHP 7

Ben Mutlu Koçak, Bilgisayar Mühendisiyim, ZCPE Sertifikasına sahibim ve “Hiç Bilmeyenler İçin İnternet Programlamaya Giriş — PHP 7” adlı kitabın yazarıyım. Kitabım: https://www.seckin.com.tr/kitap/911934237
Özgeçmişim:
http://represent.io/mtkocak.pdf 
Websitem:
http://mynameismidori.com

Yorumla

Yorum