Pazartesi, Ekim 02, 2006

Programı Katmanlara Ayırma

Nesne yönelimli programlamanın temelinde yeniden kullanılabilirlik (reuseability) yatar. Yani yazılan kod parçalarının olabildiğince biribirlerinden bağımsız ve gerektiğinde yeniden kullanılabilir olması gerekir. Buna neden gerek var?

Sanayi sektöründeki en büyük gelişmelerden birisi yarımamül üretiminin yapılamya başlanmasıdır. Yarımamüller biraraya gelerek ana mamülleri oluştururlar. Mesela ayakkabı üreten bir firma için ayakkabının taban kısmı bir yarımamüldür. Aynı taban kullanılarak birçok değişik modelde ve renkte ayakkabı üretmek mümkündür. Bu sayede her model ayakkabı için ayrı bir taban tasarımı yapmaya veya ayakkabı üretimine taban üreterek başlamaya gerek kalmaz.

Yazılım sektörü de bu tür yarımamüller üretme arayışı içindedir. Mesela ticari program üreticisi bir firmanın hitap ettiği sektörlerin bir çoğunda fatura kesme özelliği vardır. Eğer fatura modülü programın diğer parçalarından bağımsız bir parça olarak tasarlandıysa yazılımevi aynı fatura modülünü birçok sektöre yönelik değişik program içinde kullanabilir. Eğer fatura modülü stok modülüne bağımlı olarak tasarlandıysa fatura modülünü kullanacağımız her yerde stok modülünü de kullanmamız gerekir. Bu durum hizmet sektörüne yönelik program yazdığımızda (bir kuaför mesela) bu fatura modülünü kullanamayacağımız anlamına gelir. Çünkü bu firmalar maldan ziyade hizmet satar ve faturaya verdiği hizmeti yazar. Kimi programlarda hizmeti stok olarak tanımlayarak çözümler aranır ancak bu durum hizmet konusunun doğasına aykırıdır. Buradaki örneğimize göre fatura modülü diğer her türlü modülden bağımsız tasarlanarak gerçek bir yarımamül haline getirilmelidir.

Aslında konuyu program modülleri olarak anlattım ancak aynı durum program için yazdığımız kodlarda da vardır. Mesela bir veri aktarma bileşenini sadece SQL Server veritabanından veri aktaracak şekilde yazarsak veri aktarma için yazdığımız kodlar SQL Server varsa işe yarar. Birgün XML dosyasından veri aktarmak gerekirse eskiden yazdığımız şeylerin birçoğunu tekrar yazmamız gerekir. Gerçek yarımamül bir veri aktarma kodu veri kaynağından ve verinin yazılacağı yerden bağımsız çalışabilmelidir.

Günümüzde yazılım fabrikası terimi git gide yaygınlaşmaktadır. Hızlı ve doğru program üretme ihtiyacına yönelik olarak ortaya çıkan bu olgu yazılım üretme şeklimizin daha verimli hale getirilmesi anlamına gelir.

Bir program 3 temel iş yapar. Kullanıcıdan bilgiyi alır, bunu işler ve veritabanına yazar. Tam tersi düşünürsek verikaynağından bilgiyi alır, bunu işler ve kullanıcıya gösterir. Modern programlamada bu üç iş biribirinden bağımsız yapılmalıdır. Yani bilgiyi işleme mantığı veritabanından ayrı olmalıdır ki biz istediğimiz herhangi bir veritabanını kullanabilelim. Ya da bilgiyi gösterme mantığı veri kaydetme mantığından ayrı olmalıdır ki biz istediğimiz şekilde kullanıcıya bunu formla veya web sayfasıyla gösterebilelim. Bu ihtiyaç 3 katmanlı yapıda program yazılmasını gerektirir. Bu üç katman sunum, iş ve kayıt katmanıdır.

  • Sunum katmanının görevi kullanıcıdan bilgi almak ve kullanıcıya bilgi göstermektir.
  • İş katmanının görevi kullanıcıdan alınan bilgi üzerinde hesaplar yapmak veya kullanıcıya gösterilecek bilgiyi anlamlı hale getirmektir.
  • Kayıt katmanının görevi bilginin verikaynağından okunması veya kaydedilmesidir.

Mesela bir müşterimiz web üzerinden sipariş almak istiyor. Bizim yapımız katmanlara ayrıldıysa, iş katmanına veya kayıt katmanına hiç dokunmadan sadece sunum katmanında değişiklik yaparız. Siparişin hesaplama ve değerlendirilme mantığı siparişin gösterilmesinden ayrı ele alındığı için bu konularda tekrardan kodlama yapmamıza gerek kalmaz.

Nesne yönelimli diller bu gibi katmanlı yapılar oluşturabileceğimiz altyapıyı ve dil özelliklerini bize sağlar. Nesne yönelimli dillerde her olgu bir nesnedir. Yukarıdaki örneğimizi düşünürsek kabaca bir sipariş, bir sipariş gösterme ve sipariş kaydetme nesnemiz vardır. Sipariş nesnesi siparişin hangi kurallara göre işlem göreceği ile ilgili işleri yapar. Sipariş nesnesinin nasıl gösterileceğini sipariş gösterme nesnesi, nasıl kaydedileceğini de sipariş kaydetme nesnesi bilir. Biz diğer nesnelere hiç dokunmadan sipariş gösterme nesnemizi gerektiğinde web sayfası gerektiğinde de bir formla çalışacak şekilde geliştirebiliriz.

Siparişleri listelediğimiz bir listemiz olduğunu düşünün. Müşterimiz sevk tarihi geçen siparişlerin kırmızı renkte gösterilmesini istemiş olsun. Hemen basitçe siparişi gösterdiğimiz grid bileşeninin uygun bir olayına (event) gideriz ve

[eger] "gününTarihi > sevkTarihi"
[ise] "fontRengi = kırmızı"
[degilse] "fontRengi = siyah";

gibi bir kod yazarız. Koda baktığımızda üstteki tarih kontrol kodunun iş mantığını, alt taraftaki renk atama kodunun da sunum mantığını ilgilendirdiğini görebiliriz. Bu durumda ne olur? Eğer bir gün siparis bilgisini başka bir yerde (mesela bir web sayfasında) göstermemiz gerekirse sevk tarihi geçmiş satırların kırmızı olması ile ilgili kodumuz gridde kalır. Büyük ihtimalle de aynı kodu tekrar yazmamız gerekir. Sipariş görünen her yere bu kodu tekrardan yazarsak ve birgün müşterimiz sevk tarihine 1 hafta kalanları mavi renkte görmek isterse siparişi gösterdiğimiz heryeri hatırlayıp değiştirmemiz gerektir.

Gördüğümüz gibi aslında nesne yönelimli programlama yapıyor olmamız bizi yavaşlatan ve zaman israfına neden olan problemlere tek başına çare değil. Nesne yönelimli diller nesnelerimizi bu sorunları yaşamayacağımız şekilde tasarlayabilmemize yardımcı oluyor. Yine doğru tasarımı yapmak bize kalıyor. Bu konuda Design Patterns gibi sık yaşanan tasarım sorunlarına çözümler üretmekle ilgili çalışmalar var. Nesne yönelimli dilllerle program yazanların bu olanaktan tam olarak faydalanabilmesi için nesne yönelimli mimariler konusunda da kendilerini geliştirmesi gerekiyor. Aslında bu konuda daha çok şey yazmak lazım. Yine zaman buldukça bunlarla ilgili yazılarıma devam edeceğim...

OOP konusuna aşina olanlar için iki kitap tavsiye ediyorum

Head First Design Patterns (Elisabeth Freeman)
Patterns of Enterprise Application Architecture (Martin Fowler)

Hiç yorum yok: