Televizyon kumandası gibi nesneler yapı (veya sınıf) nesneleri oluyor. Onu gerçekleştiren tür de yapı (veya sınıf) türü oluyor. Yani isimler yazdığımız türlerin nesneleri oluyor. Fiiller de işlev: yap(), et(), ekle(), yazdır(), sırala(), vs.
Bu gibi konular, deneyim gerektiriyor olabilir. :)
Yazmakta olduğum programlardan bir örnek vereyim. Doğrudan dosyalarla çalıştığından programda önce File nesneleri we doğrudan 'dosyam.rawWrite(/* ... */)' gibi işlevler kullanmıştım. Programlar karmaşıklaştıkça birim testleri (unittest) konusunda geri kaldığımızı farkettik. Birim testlerinin olabildiğince bağımsız olması istenir. Örneğin, test programının dosyalardan okuması veya dosyalara yazması istenmez. (Bunun nedenleri, testlerin dosya sistemini doldurmasının istenmemesi, veya yazma izni bulunmayan bir dosya sisteminde bile işlemelerinin gerekmesi, vs. düşünülebilir.)
O yüzden, programlarımın içinde File türüyle doğrudan etkileşmek yerine şöyle bir sıradüzen kurdum ve programları File ile değil, Depo ile etkileşecek biçimde değiştirdim:
'
Depo (interface)
/
FileDeposu BellekDeposu (class)
'
Programda File ile ne iş yapıyorsam, Depo arayüzünde de onları tanımladım: tell(), rawWrite(), seek(), vs. FileDeposu'nun bütün işlemleri kendi içinde barındırdığı bir File nesnesine aktarılıyor:
interface Depo {
// ...
}
class FileDeposu : Depo { // <-- Çok şekillilik (polymorphism)
File file; // Gerçekleştirme
auto seek(/* her ne parametre alıyorsa */) {
return file.seek(/* parametreleri buraya aynen aktarıyoruz */);
}
// ...
}
BellekDeposu ise kendi bayt dizisini bir dosyaymış gibi kullanan çok basit bir sınıf oldu:
class BellekDeposu : Depo {
ubyte[] baytlar;
long konum; // <-- Dosyanın neresinde olduğumuzu belirler
auto seek(long konum) {
this.konum = konum;
// Daha sonraki okuma işlemlerinde örneğin konum'dan okuyacağız.
}
}
(Basit dedim ama hatasız yazmak kolay olmayabilir. Ben biraz debelenmiştim. :) )
Depolama işini öyle soyutlayınca eskiden şöyle olan işlevim:
auto süperİşYap(File dosya, /* ... */) {
// ...
}
şimdi şöyle oldu:
auto süperİşYap(Depo depo, /* ... */) {
// ...
}
Gerçek programda FileDeposu oluşturup kullanıyorum:
auto depo = new FileDeposu(dosyaİsmi);
süperİşYap(depo, /* ... */);
birim testlerinde ise BellekDeposu oluşturup kullanıyorum:
auto depo = new BellekDeposu(dosyaİsmi);
süperİşYap(depo, /* ... */);
Söylemek istediğim, ben sonuca götüren en basit tasarım ne ise onu kullanıyorum; gerektikçe geliştiriyorum. (Tabii deneyimlerimizden de yararlanıyoruz ve açıkça aptallıklar yapmıyoruz. (Burada, birim testlerini baştan düşünmemiş olmam da hata kabul edilebilir.))
İnsan deneyim kazandıkça asıl önemli olanın sonuca gitmek ve iş bitirmek olduğunu anlıyor. Sonuçta işimiz mühendislik ("hendese" anlamında değil, "iş bitirici; çözüm bulucu" anlamında kullanıyorum.) Programı yazacağız ve işimize yarayacak... OOP'ler, pattern'lar, şu yöntemler, bu yöntemler, vs. işin zanaat yanı ama hiçbirisi mutlak değil. (Eskiden böyle düşünmüyordum; değiştim. :) )
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]