2000’lerde programlama giderek sanat olmaktan çıkıyor, genellikle hazır kütüphaneleri, api’leri kullanmak, kod parçalarını sağdan soldan alıp birleştirmek, havalı kelimeleri yanyana kullanmak (tdd, bdd, grid computing vs.. ) programlama olarak düşünülüyor. giderek programlama zanaat-vari bir iş olmaya başlıyor.ne demek istediğimi anlatmak için şöyle bir örnekten gidelim; fibonacci sayılarını duymuşsunuzdur, “- 0, 1, 1, 2, 3, 5, 8, 13, 21,..” diye giden sayılar… matematikçi olmadığımız için teorisi ile ilgili çok detaya girmeye de gerek yok-zaten gir deseniz giremem-, ama (altın oranla ilgisi nedeniyle) genellikle çizim işlerinde kullanılır. tabii çizim dendiğinde aklımıza ilk gelen oyun programlaması olacaktır. kısaca “bir işlere” yaradığını biliyoruz. programcı olarak bizi ilgilendiren kısmı ise uygulaması.formülü şöyle ;

formülü kelimelerle ifade edersek, eğer parametre 0 ise 0, parametre 1 ise 1 verecek, parametre 1’den büyükse, parametrenin 1 eksiği ile parametrenin 2 eksiğinin fibonacci sayısını toplayacak. örneğin parametre 6 ise fibonacci(6-1) + fibonacci(6-2) yapacak, tabii bu da neden rekursif algoritmalara giriş konusunda verilen ilk örneklerden olduğunu gösteriyor.bunu biraz daha açarsak, fibonacci(3) için yapmamız gereken,fibonacci(2)’yi almak. onun için fibonacci(1)’i almamız gerekiyor. bunu koda dökersek, bu tanıma göre;# fibonacci (rekursif)def fibonacci(n)return n if (0..1).include?(n)fibonacci(n-1) + fibonacci(n-2)end
böyle birşey olacak, (çok basit olduğu için ruby ile yazdım gerekirse diğer diller uygulanmasını yorumlara ekleyebilirim). açıklamasına gelirse, 1. satırda parametrenin 0 veya 1 olduğuna bakıp, eğer 0 veya 1 ise parametreyi aynen geriye döndürüyoruz. ikinci satırda ise fonksiyonu parametrenin 1 eksiği ve 2 eksiği ile tekrar çağırıp topluyoruz.buraya kadar olan kısmı, programlamanın zanaat kısmı, elinizdeki formülü/tanımı alıp sözlü ifadeye çevirip, sonra da koda çeviriyoruz. çalıştıralım bakalım…#>> puts Benchmark.measure { puts fib 3 }#2# 0.000000 0.000000 0.000000 ( 0.000567)
3 için yaklaşık 0.0005 saniye sürdü. artık zanaatkar programcımız için iş bitmiştir. sonuç doğru geliyor, hesaplama doğru, algoritmada sorun yok. herşey güzel…peki 30 için hesaplarsak ?#>> puts Benchmark.measure { puts fibonacci(30) }#832040# 5.540000 1.260000 6.800000 ( 7.026075)
yaklaşık 7 saniye sürdü. 60 için ne kadar süreceğini tahmin edebilir misiniz? işlemci %90’larda dakikalarca çalışır. o sırada gider kendinize bir kahve yapar geri gelirsiniz, sonuç hala görünememiştir. ben 10 dakika kadar bekledim, sonuç yoktu. tabii bunu gören patron/müşteri feryat figan size geri döner. örneğin bunu bir web servisi için yaptığınızı düşünün…zanaatkar programcı, muhtemelen “ruby yavaş, bunu c/java ile yazmamız lazım”la başlayan (diğer dillerde de aslında sonuç farklı olmayacaktır), önceden hesaplayıp cache’lemek, veritabanında bir tabloya yazdırmak, grid’e atıp düzinelerce makinede hesaplatmak lazım gibi cümlelerle devam eden oldukça pratik öneriler getirecektir.şimdi programlamayı bir sanat olarak gören bizler için,# fibonacci (iteratif)def fibonacci_i(n)simdiki = 0onceki = 1n.times do |i|simdiki, onceki = onceki, (simdiki + onceki)endreturn simdikiend
evet, rekursif algoritmamızı çöpe atıp, 3 satırlık kodu tekrar yazdık. ruby’ye aşina olmayanlar için; ruby’de birden çok değişkeni birbirine atayabiliyoruz:simdiki, onceki = onceki, (simdiki + onceki)
satırında, “simdiki” değişkenine, “onceki” değişkenini, “onceki” değişkenine ise “simdiki+onceki”yi atıyoruz. bunu da parametredeki kadar tekrarlıyoruz. (n.times) satırında döngüye giriyor. ilk bakışta biraz karışık görünüyor. ilki kadar havalı da değil tabii ama…şimdi kodumuzu tekrar çalıştıralım:# yaklaşık 0.0002 saniye sürer.#>> puts Benchmark.measure { puts fibonacci_i(30) }#832040# 0.000000 0.000000 0.000000 ( 0.000152)
60 için sonuç ne olurdu?#>> puts Benchmark.measure { puts fibonacci_i(60) }#1548008755920# 0.000000 0.000000 0.000000 ( 0.000236)
sadece 0.0002 saniye, 600 için, yada 16000 için:#>> puts Benchmark.measure { puts fibonacci_i(600) }#110433070572952242346432246767718285942590237357555606380008891875277701705731473925618404421867819924194229142447517901959200# 0.010000 0.000000 0.010000 ( 0.002084)#>> puts Benchmark.measure { puts fibonacci_i(16000) }#28363…. (3338 basamaklı bir sayı o yüzden yapıştırmadım sonucu)# 0.120000 0.030000 0.150000 ( 0.169598)
ikinci kodda çok müthiş birşey yapmadık aslında. oldukça basit ve sıradan bir kod yazdık. ama anlatmak istediğim şu; programlamada her zaman birden çok çözüm vardır. işinizi sanat olarak algılıyorsanız, en iyi çözümü uygulamaya çalışırsınız. biraz daha kafa patlatırsınız, işin tanımını yeniden gözden geçirirsiniz, farklı yöntemler ararsınız, doğru sonucu veren daha iyi yöntemler olduğunu keşfedersiniz… ya da zanaatkar olmayı tercih edersiniz, 4-5 server aldırırsınız ve 16000 için fibonacci sayısının asla hesaplanamayacağına inanırsınız.programlamanın harika dünyasına hoş geldiniz, bir sonraki yazıda “veritabanı programlayamama” örnekleri ile devam edeceğiz.not: iğneleyici bir yazı olduğunu düşünmeyin, sadece programlama ile kod yazma arasındaki farkı göstermek istedim.