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)

Pazar, Ekim 01, 2006

Delphi nerede hata yaptı?

Windows işletim sisteminin yaygınlaşması ile birlikte windows için yazılmış programlar da yaygınlaşmaya başladı. İlk zamanlarda windows programları genellikle C ile Windows API (Application Programming Interface) arabirimi üzerinden yazılıyordu. Windows API programcılara büyük kolaylıklar getiren bir arabirimdi ama yine de windows için program yazmak kolay bir iş değildi. Microsoft Visual Basic ürününü çıkarana kadar windows programcılığı fazla yaygınlaşamadı, yazılan programlar da belli bir kapsamı aşamadı.

Formlar ve bileşenler kulllanarak program geliştirme yönteminin ilk atası Visual Basic'dir. Bu dönemde dilin haricinde başka görsel unsurlar da kullanılarak yapılan programlama şekline RAD(rapid application development) programcıya da geliştirici (developer) denmeye başlandı. Bu dönemde c++, smalltalk gibi nesne yönelimli programlama dilleri olmasına rağmen Visual Basic (VB) nesne yönelimli (object oriented) bir dil değildi ancak windows için program yazma işini çok basitleştirmişti. Program yazma şekli de daha çok prosedürel programlamaya benzediği ve o dönemde nesne yönelimli diller çok yaygınlaşmadığı için VB hızlı bir şekilde yaygınlaştı. Bu sahnede Microsoft daha fazla tek başına kalamadı. Önemli bir rakibi efsane Borlan Pascal'ın üreticisi Borland'dı.

Borland Pascal 7 paketi ile birlikte iki ürün daha geliyordu. Bunlar Turbo Vision ve Pascal for Windows idi. Pascal for Windows Pascal dili ile (bugün delphi ile program yazarken kullandığımız dil) windows programlarının yazılabilmesini sağlıyordu ancak VB gibi basit bir görsel tasarım aracı yoktu. Turbo Vision ise DOS programlarının daha basitçe yazılabilmesini sağlayan bir araçtı. Eğer windows programları gibi köşesinden tıklanarak kapatılabilen pencereleri olan, combobox, textbox gibi özellikler içeren ve mouse ile kullanılabilen bir DOS programı gördüyseniz bu büyük ihtimalle Turbo Vision ile yazılmıştır.

Bu ürünlerin varlığı Borland'ın elinde tamamen nesne yönelimli bir windows programlama aracı çıkaracak birikim olduğunu gösteriyor ama Borland prosedürel programlama ile nesne yönelimli programlama arasında bir orta yol üreterek Delphi ürününü çıkardı. Sanırım o dönemde prosedürel programlamaya da olanak sağlanması ticari bir karardı. Bu durum bir anlamda OOP temeli üzerine Prosedürel programlama yapılması anlamına geldi. Delphi programıcları bilirler. Eğer VCL'e ek bir bileşen yazmaya kalkarsanız yapmanız gerekenler ve düşünme şekliniz normal program yazarkenkinden çok farklıdır. Bu Delphi nin iki paradigmayı da barındırmasından kaynaklanır. VCL OOP temeli üzerine kurulduğu için VCL'e yapacağınız eklentileri nesne yönelimli kurallara göre yapmalısınız. Bileşen işine hiç girmeden program yazıyorsanız OOP'den anlamanıza gerek yoktur.

Önemli bir gelişme JAVA dilinin ortaya çıkmasıyla yaşandı. JAVA, VB ve Delphi den farklı olarak %100 nesne yönelimli bir programlama diliydi ve OOP ile windows programcılığını başarıyla biraraya getirmişti. Tabii JAVA ile yazılan programların windows haricinde Linux gibi windows dışı platformlarda da çalışabilmesi büyük bir avantajdı. JAVA bir anda dünyanın en çok kullanılan programlama dili haline geldi ve Microsoft ile Borland bu gelişmeye farklı tepkiler verdiler.

Microsoft'un Java'nın temel başarısının OOP temelli olması olduğunu düşünerek .NET altyapısı ve C# dili ile cevap verdi. .NET platformu %100 nesne yönelimlidir ama (multiplatform desteği olmasına ve Mono gibi Linux desteği olan projelere rağmen) resmi olarak Linux'da çalışmıyor.

Borland ise Java'nın temel başarısının Linux ile çalışması olduğunu düşünerek %100 nesne yönelimli olmayan ama Linux için program yazılabilmesini sağlayan Kylix ile cevap verdi. Sonradan Kylix'i piyasadan kaldırdı ve kaçan treni yakalayabilmek için .NET desteği olan Delphi2005 ürününü çıkardı ancak zamanında Delphi ile yapabileceklerini yapmakta çok geç kaldığı için istediğini bir türlü alamadı. Aslında bir zaman Borland bu gidişatı sezerek CORBA gibi çözümleri Delphi'ye entegre etmiş hatta şirketin de ismini Inspire olarak değiştirmişti. Daha sonraları Delphi ile birlikte DUnit ve ModelMaker gibi nesne yönelimli programlamaya hitap eden ürünler de gelmeye başladı ama bunlar Delphi programcılarının varlığını bildiği ama kullanmayı hiç düşünmediği ürünler olarak kaldı. Belkide asıl değişmesi gereken Delphi'nin hem prosedürel hem de nesne yönelimli program yazmaya imkan tanıyan yapısıydı.

Turbo Pascal ve Delphi dilinin yaratıcısı Anders Hejlsberg 1996 yılında Microsoft tarafından transfer edilmişti. Daha sonra Anders Hejlsberg Microsoft'ta J++, MFC ve C# ürünlerinin baş mimarlığını yapmıştır. Mutlaka Borland'da çok yetenekli mühendisler çalışmaktadır ancak bu transferin Delphi dilinin gelişimini nasıl etkilediği üzerinde düşünülmesi gerekir. Bu günlerde Borland'ın uygulama geliştirme ürünlerinin tamamını satacağı ve proje yönetimi ürünleri üzerine yoğunlaşacağı konuşulmaktadır.