Mehmet ASLANTAŞ

Computer Engineering

Windows 8 :)

Arkadaşlar dün itibariyle Windows 8 Release Preview sürümü kullanıma sunulmuştu. Ben de indirip yükleyeyim dedim. Eee ne de olsa “Release Preview” dedim ve kurdum bilgisayarıma Windows 8’i 🙂 İlk izlenim olarak gayet başarılı görünüyor.

Kendinize göre özelleştirebildiğiniz bir ekran çıkıyor ilk başta karşınıza. Bu ekrandan Windows’un renk temasını seçiyorsunuz ve isminizi girip ilerliyorsunuz. Sonra diğer ayarları otomatik olarak yaptırdığınızda o adından çok bahsedilen meşhur Metro Arayüz geliyor ekrana. Metro arayüzdeyken kendimi telefonumla uğraşıyormuşum gibi hissediyorum 🙂 Alışık olduğumuz masaüstü görünümünün dışında bir görsellik sağlıyor bize Windows 8. Yalnız Metro arayüz dediysek, masaüstü görünümünün kaybolduğunu sanmayın sakın. Microsoft düşünmüş onu da eklemiş 🙂 Metro arayüzün içinde “Masaüstü” diye bir bölüm var. Tıkladığınızda masaüstü ekranına geliyorsunuz. Fakat artık “Windows” tuşu başlat menüsünü çalıştırmıyor. Hatta başlat menüsü diye bir şey de yok artık 😀 Gerekli her şey metro arayüze eklenmiş zaten. Windows tuşuna tıkladığınızda da metro arayüz ekranına yönlendiriliyorsunuz 🙂

Windows’un bu yeni sürümünü Android ya da iOS’a benzetebilirsiniz. Mağaza’ya girip programlar yükleyip çalıştırabilirsiniz hiç masaüstüne girmeden. Hatta şuan bu yazımı da Windows 8 için programlanmış WordPress uygulamasından yazıyorum 🙂

Bilgisayarı kullanacak her kullanıcı için bir posta adresi istiyor sistem. Böylece kullanıcının dosyalarının ona özel olmasını sağlıyor. Diğer bir yandan kullanıcının postalarını Posta programıyla birleştirerek kişinin postlarına bakmasını kolaylaştırıyor. Mesajlaşma programıyla da kullanıcının hesabındaki kişiler ile mesajlaşabilmesini sağlıyor. Bir de Kişiler diye bir program var; kullanıcının Facebook, Twitter gibi sosyal ağlardaki arkadaşlarını toplu halde gösteriyor.

Genel olarak güzele benziyor. İndirip bir deneyin derim 🙂

Reklamlar

Gözyaşımda saklısın ağlayamam ben

Bestecisi Zekai Tunca’ya; “Ne yaptın sen? Nasıl bu kelimeleri bir araya getirdin?” dedirtecek bir şarkıdır 🙂

Gözyaşımda saklısın ağlayamam ben
Düşeceksin sanırım kirpiklerimden
Damarımda kan olup dolaşıyorken
Beni böyle bırak git git gidebilirsen

Git mutlu olacaksan beni düşünme
Sen iyi bak kendine beni dert etme
Önce beni bir dinle bir bak halime
Beni böyle bırak git git gidebilirsen

Bir kapanmaz yarayla böyle çaresiz
Belki yine yaşarım sevgisiz sensiz
Git yolun gülle dolsun güller dikensiz
Beni böyle bırak git git gidebilirsen

Git mutlu olacaksan beni düşünme
Sen iyi bak kendine beni dert etme
Önce beni bir dinle bir bak halime
Beni böyle bırak git git gidebilirsen

Güzel bir göz beni attı bu derin sevdaya

Bestesi Osman Nihat Akın’a ait olan curcuna usulündeki nihavend şarkıyla başlamak güzel olur. Osman Nihat Akın’ı birçok kişi tanımasa da bestelerinden bazılarını çoğu kişinin bildiğine eminim. Bunlardan biri de “Bir ihtimal daha var o da ölmek mi dersin?”…

Güzel bir göz beni attı bu derin sevdaya
Benziyor şimdi benim ömrüm uzun rüyaya
Yâri karşımda görsem de dalarım hülyaya
Benziyor şimdi benim ömrüm uzun rüyaya

Java’da Küçük Animasyonlar

Bu yazımda size Java’nın animasyon temellerini anlatmaya çalışacağım. Animasyon derken; bir çizgi film karesinden ziyade, bir hareketli menü tasarımı ya da bazı görsellerin yer değiştirilmesiyle oluşan görsel efektlerden bahsediyorum.

Konuyla alakalı olarak bazı kavramlardan söz etmem gerekeceği için bunları ayrı ayrı başlıklar altında ele aldım. Böylece daha anlaşılır olmasını umuyorum.

İlk olarak Java’da da bulunan mimari yapıyı açıklayalım.

Model View Controller (MVC)

Kısaca; yazılım mimarisinde kullanılan bir mimari desen olarak tanımlanabilir. Kullanım amacı, karmaşık projelerde veri ve görsellerin soyutlanmasını sağlamaktır. Bu mimari bize, verileri (Model) ve kullanıcı arayüzünü (View) birbirinden etkilenmeden düzenleyebilme imkânı sağlar. Böylelikle kodlarımız Spagetti Kod[*] olmaktan çıkar.

Model diye adlandırılan bölümde programın giriş-çıkış (I/O) işlemleri yapılır. İsteğe bağlı olarak çok katmanlı mimari tasarlanabilir.

View diye adlandırılan bölüm uygulamanın kullanıcılara görünen kısmıdır. Tasarımlar burada yapılır.

Controller diye adlandırılan bölüm ise Model ve View arasında bir köprü işlevi görür. View’den gelen verileri belirli işlevlerden geçirerek Model’a aktarır ve orada işlenmesini sağlar. Daha sonra, işlenen bu verileri tekrar View’e gönderir. Uygulamalarımızda kullanacağımız algoritmaları bu bölümde tasarlayabiliriz ve buna göre verileri Model’a gönderip işletebiliriz.

Bu yapıyı grafiksel olarak göstermek gerekirse;

Bu açıklamaları da yaptıktan sonra tekrar dönelim konumuza.

Java’da animasyon yapmayı iki bölüme ayırıp anlatmak istiyorum. Böyle anlatmak istememin sebebi; konuyu adımlara ayırıp anlaşılmayı arttırmak istememden kaynaklanıyor.

İlk olarak animasyon yapmada Paint() metodundan bahsedilir. Bu metodu birinci adım olarak doğrudan kullanmayı göstereceğim.

Bilmeyenler için Paint metodunu tanımlamak gerekirse, ekrana belirli aralıklarla görüntü çizdiren metot olarak tanımlanabilir. Bu metot sayesinde dilediğimiz görüntüyü pixel pixel ekrana çizdirebiliriz. Paint metoduyla yapabileceklerimize küçük bir örnek olarak, ekranın soluna bir dikdörtgen çizdirip, her 100 milisaniyede 10px ilerletip, ekranın sağına geldiğinde durdurtabiliriz. Bunun için bize gerekli olan sadece bir zamanlayıcıdır.

Bu kod parçası yukarıda belirttiğim gibi ekranın sol köşesine bir kare çizer, 100 milisaniyelik aralıklarla kareyi 10px sağa kaydırır ve bunu kare sağ köşeye gelinceye kadar tekrarlar.

Buradaki asıl mantık; Paint() metodu içerisinde yazdıklarımızda gizli. Dikkat ederseniz Paint() metodunun içerisinde çizdirme kodundan farklı bir de sildirme komutu var. Eğer bu komutu yazmamış olsaydık önceden çizdirdiğimiz kareler de ekranda kalacak ve istediğimiz animasyonu oluşturamayacaktık. Paint() metodunu bu şekilde kullanmak bazen sıkıntı yaşatabiliyor. Ben bu şekilde kullanımı doğrudan kullanım olarak nitelendiriyorum. Paint() metodunu her defasında kendimiz çağırarak animasyonu elde ediyoruz.

Java’nın nesne hiyerarşisine göre bir nesnenin Paint() metodu çalıştırılırsa aynı şekilde bu nesnenin alt nesnelerinin de Paint() metodu çalıştırılır. Örneğin bir Login (Kullanıcı Girişi) ekranı düşünün. Genelde Login ekranında iki tane Textbox (Nick ve Şifre için) bir tane de Buton (Giriş Butonu) bulunur. Bu ekrandayken formun boyutunu değiştirdiğinizde formun Paint() olayı da çalışır. Bununla birlikte formun içerisinde bulunan textboxların ve butonun da Paint() olayı çalışır. Boyutu değiştirmemiz aslında Resize() olayını tetikler fakat Resize() ise boyuta göre tekrar boyama yapabilmek için Paint() olayını tetikler. Böylelikle bütün form tekrardan boyanarak kullanıcıya gösterilir. Biz de bu özellikten yararlanıp Paint() olayını kendimiz çizdirmektense bu işi Java’ya bırakırız. Böyle çalışırken de birbirinden bağımsız olan çizimlerimizi ayrı bileşenler (Component) olarak tasarlarız. Böylece bir bileşenin çizimi diğer bileşeni etkilemez. Bizi buna yönlendiren bazı istisnai durumlar olabilir. Örneğin çizgilerden oluşan bir animasyonun ortasına Buton eklemek istiyorsunuz. Bunu yapmak için bir bileşen oluşturup Paint() olayına çizdirmek istediğiniz animasyonu yaparsınız. Butonunuzu bu bileşenin üzerine eklersiniz ve Paint() olayına animasyon kodlarından sonra bir de butonun Paint() olayını çağırmasını kodlarsınız. Böylelikle hem animasyonunuz gözükecektir hem de butonun görüntüsünde bir bozukluk olmayacaktır.

Bunun yanı sıra şöyle bir soruyla da karşılaşabilirsiniz: “Bir şeyler çizdirebilmenin yolu sadece Paint() metodunu Override etmekten mi geçiyor?”

Java’da Paint() metodunu yazarken dikkat ederseniz “g” parametresi gelir ve biz bu parametreyle işlemlerimizi yaparız. Bu parametre aslında o nesnenin grafik (Graphics) sınıfıdır. Bir nesnenin grafik sınıfına erişim sadece Paint() metodunda değildir. O nesnenin kendi içerisinde bulunan getGraphics() metodu sayesinde de grafik sınıfına erişebiliriz. İstediğimiz çizimleri bu sayede de gerçekleştirebiliriz.

Yukarıda yapmış olduğumuz animasyonu farklı bir yöntemle de yapabiliriz. Dediğimiz gibi bir nesne yeniden çizildiğinde o nesnenin alt nesneleri de yeniden çizilecektir. Bu bilgiye dayanarak şöyle bir mantık yürütebiliriz;

“Yapmamız gereken bir kareyi soldan sağa doğru oynatmak değil mi? Kareyi her ara değer için tekrar tekrar çizdirmiyor muyuz? Bunun yerine karenin çizimini bir defaya mahsus yaparız ve bunu bir bileşene yükleriz. Hareketi ise bileşeni kaydırarak elde ederiz. Ne de olsa bir bileşeni farklı bir yere taşıma işini Java üstleniyor…”

Bunu zihninizde canlanması için bir taslak halinde göstermek istiyorum.

Şekilden de görüldüğü gibi önce bir JApplet açıyoruz, içerisine JPanel yerleştiriyoruz ve oluşturduğumuz JComponent’ı bu panele aktarıyoruz. Böylece bu panel üzerinde kaydırma işlemi yapabileceğiz.

Şimdi yapmamız gereken; kare çizme kodunu, oluşturduğumuz JComponent’in Paint() olayına yazmak. Daha sonra ise zamanlayıcı yardımıyla belirli aralıklarda oluşturduğumuz bileşeni taşıma işlemi yapacağız. Böylece Karemiz soldan sağa hareket ediyormuş gibi görünecek.

Taşıma işlemini setBounds(int x, int y, int width, int height) metodu yardımıyla yapabilirsiniz.

Bu yöntem sayesinde daha karmaşık animasyonlar düzenlenebilir. Hem belirli aralıklarla tekrar tekrar görüntüyü çizdirmek zorunda kalmazsınız hem de bütün çizim işlemini tek bir alana sıkıştırıp karmaşıklaştırmazsınız.

Yine bu yöntemle repaint() komutunu biz vermediğimiz için programa bir tetikleyici (Trigger) gelmediği sürece ekran tekrardan çizdirilmez.

Örneğin bir kayan menü yaptınız ve bu menünün sadece üzerine gelindiğinde açılmasını istiyorsunuz. Bunun için bir tetikleyici oluşturursunuz ve geri kalan işi Java’ya bırakırsınız. Buna benzer bir uygulamayı bir oyun projesinde arkadaşım Barış Babüroğlu tasarlamıştık. Bir menümüz olacaktı ve bu menü üst köşede tetikte bekleyecekti. Ne zaman ki kullanıcı menüye erişmek isterse o zaman kayarak aşağı doğru açılacaktı.

Resimlerde de gördüğünüz gibi tetikleyici olarak bir ok işareti kullanıyoruz. Menünün çalışma mekanizması ise sadece iki tane zamanlayıcıdan (Timer) ibaret. Birinci zamanlayıcı, menüyü aşağıya doğru indirip istediğimiz konumu alıncaya kadar aşağı doğru taşıma işlemi yaptırıyor. İstediğimiz konuma geldiğinde ise zamanlayıcımız kendisini durdurup tekrar bekleme konumuna geçiyor. İkinci zamanlayıcımız ise bunun tam tersini yaparak menüyü yukarı taşıyor. Bu da Paint() olaylarıyla uğraşmamamızı sağlıyor.

Fakat konu animasyon olunca uğraşacak illa ki bir şeyler çıkıyor. Dikkat ettiyseniz yukarıdaki ekran görüntülerinde her şey özel bir görüntüyle tasarlanmış. Yani kullanıcı arayüzü standart görüntü birimlerinden çok farklı. Menüler, oyun içi yazışma ekranı, butonlar vs. klasik görünümün dışında bir görüntüye sahip. Eminim ki sizin için de bazen bu bir ihtiyaç olacaktır.  Bu yüzden Java’da görseller tasarlıyorsanız ya üçüncü parti yazılım kullanmalısınız ya da kendi kütüphanenizi yazmalısınız.

Şimdi gelelim konunun başında vermiş olduğumuz Model View Controller kısmına.

Görsel efekt oluşturmak düzensiz bir mimarinin ürünü olamaz. Çünkü çalışırken birçok nesneyle çalışmak zorunda kalırsınız. Birçok nesne birbiriyle bağlantılı olur. Bu bağlantıları esnek yapamazsanız görüntüyü değişmek istediğinizde yeni bir projeye başlamak daha cazip gelecektir. Bu sorunu ortadan kaldırmak MVC ile çok basit olacaktır.

Örneğin yukarıdaki menüyü yeniden ele alalım. O menüyü kodlarken bütün her şeyi tek bir yerde kodlasaydık ileride menüyü yukarıdan aşağıya doğru değil de sağdan sola doğru açtırmak istediğimizde her şey değişecekti. Hâlbuki menünün görselini bir bölümde kodlasak, menünün açılış kodlarını farklı bir yerde kodlasak ve menüdeki etkileşimleri de başka bir yerde kodlasak menünün rengini değiştirmek istediğimizde sadece görselleri kodladığımız bölümde ilgili satırı bulup değiştirmemiz yetecektir.

Bu yüzden animasyon yaparken kesinlikle düzgün bir mimari oluşturmaya ve herkesçe anlaşılabilir kod yazmaya özen göstermeliyiz.

Algoritma ve Yapay Zeka’ya Giriş

Hepimizin dilinde dolaşan fakat anlamını tam bilmeden üzerinde yorumlar yaptığımz bir kelime; algoritma…

Kelime anlamı olarak; bir işin yapılışındaki etapların belirlenmesi ve sıralanmasıdır.
Türk Dil Kurumu’nda ise;

algoritma    Fr. algorithme
a. (algori’tma) mat. Orta Çağda ondalık sayı sistemine göre son zamanlarda ise iyi tanımlanmış kuralların ve işlemlerin adım adım uygulanmasıyla bir sorunun giderilmesi veya bir sonuca en hızlı biçimde ulaşılması işlemi, Harezmi yolu.
Güncel Türkçe Sözlük

şeklinde verilmiştir. Buradan da anlaşılacağı gibi algoritma bir programlama dili değildir. Fakat programlama dillerine yol gösteren yöntem olarak nitelendirebiliriz.

-Algoritma, programcı açısından neden önem arz eder?
Programcılar bir işe kalkıştıklarında bu iş ilk etapta geneldir. Örneğin işe programlama açısından değil de günlük yaşantımızdan bakarsak; şuan bilgisayarın başındasınız ve susamış bulunuyorsunuz. Yapmanız gereken nedir? Tabiki gidip su içmektir. Su içmek bir genelliktir. Çünkü yapacağımız işin bir çok adımı var fakat ana temamız su içmek. Bunu yapmamız için ilk başta koltuğumuzdan kalkmalı, mutfağa gitmeli, bir bardak almalı, bardağa su doldurmalı ve sonrada suyu içip yeniden koltuğumuza dönmeliyizdir. Ama günlük yaşantımızda bu olayı bu kadar uzatmak yerine herkesin anlayacağı dilden “Su İçmek” olarak nitelendiririz. Bunu herkes anlayabilir çünkü herkesin bunu idrak edecek bir aklı vardır. Fakat aynı şekilde bir robot olduğunu düşünelim. Bu robota aynısını söylediğimizde anlayamayacaktır. Teker teker adımları sıralayıp her bir komutumuzu sırasıyla yerine getirmesini istemek zorunda kalırız. Bilgisayar programlamada da aynı şekilde yapılacak işi etaplara ayırıp teker teker komutlandırmamız gerekir. Bu yüzden de programcı açısından algoritma çıkarmak önemlidir.

Daha önceki Derleyici Çalışma Mantığı makalemde de anlattığım gibi derleyiciler komutlarımızı bir sıraya göre işleme koyar. Algoritma çıkararak, derleyicimizdeki her bir satır için bir komut dizisi oluştururuz ve bu komutları sırayla derleyicinin çalıştırmasını isteriz. Bunu yaptığımızda ise komutlar birleşir ve bizim ana temamızı oluşturur.

Programcıları birbirinden ayıran en önemli özellik iyi algoritma çıkarabilmesidir. Eğer bir programcı algoritma çıkarmada sıkıntı çekiyorsa, bildiği dillere hakimiyet seviyesi yüksek olsa bile program çıkarmada zorluk çekecektir. Algoritmanın amacı, sadece bir işin yapılış sürecini belirlemek değil bilhassa bu süreci en kestirme yoldan tamamlamak ve işin yapılış süresini minimuma indirgemektir.

Algoritmanın özelliklerinden biri de yapay zekaya olanak tanımasıdır. Bu kısımda yapay zekanın da tanımını iyi bilmekte fayda var.
Kelime anlamı olarak Yapay Zeka;

İnsanın düşünce yapısını anlamak ve bunun benzerini ortaya çıkaracak bilgisayar işlemlerini geliştirmeye çalışmak olarak tanımlanır.

Burada önemli olan nokta insanın düşünce yapısını anlamaktır. Örneğin kendiniz bir karar verirken bunun neye göre verirsiniz. Bu kararlar eğer yeteri derece basite indirgenebilirse, sadece kesin kararlarımız değil tahminlerimiz bile programlanarak bir yapay zeka oluşturulabilir. Biraz şaşırtıcıda olsa bu bir gerçek!

Biraz önce verdiğim “Su İçmek” işindeki her bir adım bu olayın basite indirgenmiş biçimiydi. Yani insanların düşündükleri genel olayları basite indirgeyebiliyoruz. Şimdi is bu olaydaki yapay zekaya bakalım.

Benim verdiğim örnekteki robot su getirme işlemini algılayamıyordu. Çünkü bunu yapacak zekası yoktu. Ama bu işi basite indirgeyebilirsek bizdeki düşünme yeteneğini o robota aktarabiliriz ve artık o robotta bizim gibi olayı algılayabilir. Ama önce bizim olayı nasıl algıladığımızı bulmamız ve bunu algoritmaya döküp sonrada bu algoritmayı robota entegre etmeliyiz.

Bize “Su Getir” denildiği zaman bu olayı nasıl algılıyoruz ve olayı gerçekleştirmemiz için ne yapıyoruz?
Bir insan “Su Getir” cümlesinden anladığı bir bardak suyu isteyen kişiye götürmesidir. Buradaki değişkenimiz insandır. Çünkü herhangi bir insan bizden su isteyebilir. Diğer bir değişkenimiz ise su isteyen kişinin konumudur. Çünkü herhangi biri bizden herhangi bir yerden su isteyebilir. Burdaki asıl amacım olayı yapabildiğim kadar basite indirgemek. Normalde bu kadar basit düşünmeyiz. Aslında beynimiz bunları düşünür zaten ama biz farketmeyiz. Hayatınızda en az bir kez yaşamışsınızdır; sizden su isteyen birine suyu götürdüğünde yerinde bulamamanız. Demek ki sizden su istenildiğinde, istenildiği esnada suyu isteyen kişi neredeyse suyu da oraya götürüyorsunuz. Burada atladığımız bir noktada suyu temin edeceğimiz yerdir. Kendi evinizdeyseniz mutfağın yeri zaten beyninizde kayıtlıdır. Ama farklı bir mekandaysanız suyu nerden alacağınız konusunda bilgi edinirsiniz. Demek ki robota bu olayları anlatmadan önce hafızasında değişkenlerimiz için yer ayırmamız gerekiyor. Robotumuza vereceğimiz komutların basite indirgenmiş ve sıralanmış şekli şöyledir;

  1. “Su Getir” mi dedi?
  2. “Su Getir” demediyse işlem yapma
  3. “Su Getir” dediyse işleme devam et
  4. Söyleyenin konumunu hafızaya al
  5. Suyu temin edeceğin yeri biliyorsan 7. adıma geç,
  6. Suyu temin edeceğin yeri öğren ve hafızana al
  7. Suyu temin edeceğin yere git
  8. Suyu al ve suyu isteyenin konumuna git
  9. Suyu teslim et

Bu komutları robotumuza entegre ettiğimizde artık normal bir insana dediğimiz gibi robotumuzdan da su istediğimizde aynı olayı gerçekleştirecektir.

Bu insanların kesin bildiği şeylerden biridir. Peki tahminlerimizi nasıl yapay zekaya dönüştürebiliriz?
Buna bir kaç soruyla cevap vermek istiyorum:

  1. Barcelona ve Elazığspor maç yaparsa kim kazanır?
  2. Barcelona ve River Plate maç yaparsa kim kazanır?
  3. River Plate ve Classic XI maç yaparsa kim kazanır?

(Not: Maçlarda berabere bitme şansının olmadığını, River Plate ve Classic XI takımlarını bilmediğinizi varsayın!)

Bu soruların ilki kesinlik ifade eder. Nitekim herkesinde bildiği gibi Barcelona, Elazığspor karşısında galip gelir. Buna göre insanlar ilk soruyu  Elazığspor ve Barcelona’yı bildikleri için hangisinin daha iyi oynadığına göre cevabını kesin olarak verir.

2. Soruda ise River Plate takımını bilmeyenler, Barcelona’nın dünya devi bir takım olduğunu ve çok duyduklarını ancak buna rağmen diğer takımı tanımadıklarını, eğer iyi bir takım olsaydı mutlaka tanıyacaklarını düşünürler. Bunun içinde Barcelona’nın yeneceğini tahmin ederler.

3. Soruda da her iki takımı da bilmediğimiz için rastgele birisini seçeriz.

Şimdi ise bu soruların cevaplarına bakalım.

1. Soruda herkesinde bildiği gibi Barcelona galip gelir. Bu bir kesinliktir.

2. Soruda ise River Plate’i bilmedikleri halde Barcelona diyenler, düşündükleri gibi Barcelona’nın galip geleceğini doğru bilirler. Çünkü River Plate Arjantin’in bir takımıdır ve Barcelona’nın yenebileceği bir güce sahiptir.

Gelelim 3. Soruya…

Classic XI; FiFa’nın son oyunlarında ki gelmiş geçmiş en iyi oyunculardan oluşturduğu bir kadrodur. Bu da demek oluyorki River Plate’in bu takımı yenmesi zor bir ihtimaldir. Böylece River Plate diyenler soruyu yanlış cevaplamış olacaklardır.

Bu düşüncemizi algoritmaya dökelim…

Bizim aklımızda bildiğimiz belirli takımların bir listesi vardır. Kimi bir çok takımı bilir, kimi ise sadece belli başlı takımları… Ama sonuç itibariyle herkes bildiği takımları bi kağıda yazarsa elinde bir liste oluşur. İnsanlar bu takımların hem isimlerini bilirler hem de güçlerini bilirler ve buna göre kıyaslama yaparlar. Aynen bunun gibi bildiğimiz takımların isimlerini ve güçlerini bir kağıda yazıp yanımızda tuttuğumuzu varsayalım.

1. Soruyu listemize bakarız ve iki takımıda bildiğimiz için gücü hangisinin yüksekse onu seçeriz.

2. Soruda ise yine listemize bakarız ama ikinci takımı listemizde bulamadığımız için ve ilk takımın gücünün çok yüksek olmasından dolayı ilk takımı tahmin ederiz.

3. Soru için de her iki takım listemizde bulunmadığından dolayı yine rastgele birini seçeriz.

Bu adımları kodlamaya döküp bir program yaptığımızda ve aynı 3 soruyu o programa sorduğumuzda bir insana sormuş gibi yanıtlar alırız. Yani kendi zekamıza eş değer bir düşünce sistemi oluşturmuş oluruz.

Gördüğünüz gibi işin özü; bir olayın ne kadar kompleks olmasına bakmaksızın olayı analiz edip düşünce sistemini algoritmaya dökmektir. Bu işi ise analiz yeteneği yüksek olanların yapması daha profesyonel şeylerin ortaya çıkması demektir.

Profesyonelce Düşünmek…

Uzunca bir aradan sonra yine beraberiz 🙂

Proje çalışmaları, dersler felan derken programım doldu ve buraya vakit ayıramadım ne yazık ki… Ama bu hafta değineceğim konu ile bu uzun aranın hayfını çıkaracağım 😉

Bu haftaki konumu belirlerken düşündüm de insanların çoğu kez hata yapmasının sebebi günü kurtarmak ve olabildiğince rahata kaçmak oluyor. Halbuki bir işi yaparken ne kadar profesyonelce düşünürsek o işi anlamamız, analiz etmemiz ve geliştirmemiz o kadar kolaylık sağlıyor. Bazılarınız diyebilir; “- Oysaki biz profesyonel değiliz. Nasıl profesyonelce düşüneceğiz?”

Asıl işi püf noktası da burası işte 🙂 “Hiç kimse profesyonel değil…” Evet, bir daha okuyabilirsiniz yanlış yazmadım ve sözümün arkasındayım. Çünkü işiniz bilgisayarsa hiçbir zaman profesyonel olamazsınız ama profesyonelce düşünebilirsiniz 😉 “Peki ama nasıl?”

İşe ilk başta kendimize güvenerek başlamalıyız fakat bilgimize güvenmeyerek yola devam etmeliyiz. Çünkü profesyonel değiliz ve her zaman bir noktada bilgimiz yetmeyecek bunun için de amatörce düşünüp mevcut bilgilerle durumu idare etmek yerine zaman çizelgemizde öğrenme için vakit ayırıp düşünce tarzımızı değiştirmeliyiz. Einstein’ın çok sevdiğim bir sözü vardır;
“Karşı karşıya kaldığınız aşılması güç problemleri mevcut düşünce yapınızla çözemezsiniz. Çünkü bu problemler, mevcut düşünce yapınızın ürünleridir.”
Bu söz hala sizi etkilemediyse ne yazık ki amatörce düşünceden asla vazgeçemeyeceksiniz 🙂 Onun için yazının devamına vakit ayırmayın…

Bir olaya ön yargı ile bakmaktansa ilk başta yargıları kırıp daha sonradan kendimiz yargılamalıyız. Çünkü ön yargı her zaman başkalarının yargılarıdır. Bunun için başkalarının düşüncelerini bir kenara atıp kendi içimizde bir mahkeme kurmalı ve bu doğrultuda yeni bir yargıya varmalıyız. Bunu yapmak zor değil. Sadece biraz egoist ve biraz narsist olmak gerekir. Kendini seveceksin, kendine güveneceksin ve buna layık olduğuna inanacaksın. Kendine güvenme sıkıntısı çekenlere tavsiyem satranç oynamaları…

Profesyonelce düşünmenin ilk adımı karşına yeni bir şey çıktığında bunu öğrenmek lazım sözüne “Neden?” demek yerine “Neden olmasın?” diyebilmektir. Fikirlere açık olmak gerekir. Yeni fikirler demek; yeni düşünce tarzı, yeni çözüm yolları ve farklı bir perspektif demektir. Bu da mevcut düşünce yapımızı değiştirmenin en iyi fırsatıdır.

Profesyonelce düşünmenin ikinci adımıysa günü kurtarmaktan ziyade ilerde üstüne ekleme yapabileceğin yerlerin alt yapısını iyi tasarlamak ve yeni taleplere cevap verebilecek en uygun şekilde dizayn etmektir.

Sizi temin ederim ki en çabuk profesyonelleşenler Bilgisayar Mühendisleri’dir. Çünkü en tembel kişilerdir. Babamın bir sözü vardır çok hoşuma gider; “Tembel adam kafasını çalıştırır.” 🙂 Bence bilgisayar mühendislerinin en ayırt edici özelliği bu olsa gerek. Şahsen bir iş yaparken sonradan işi baştan yapmak gerekirse diye uğraşmamak için işin alt yapısını en iyi şekilde tasarlayanlardır. İnsan böyle düşüne düşüne akli dengesini yitirebilir. Bu öyle bir huydur ki hastalık bile diyebilirsiniz. Hatta bir geyiğe göre bilgisayar mühendisleri 2 yıl çalıştıktan sonra mahkeme de  şahitliği geçersiz oluyormuş. Tabiki böyle birşey söz konusu değil 🙂

Şimdi gelelim işin biraz da yazılım kısmına… Konularımda örnek vermem konunun anlaşılması için daha iyi bir yol olduğuna inandığımdandır. Her zaman yaptığım gibi yine bir problem ortaya atacağım fakat bu problemi seçerken geçen sefer anlattığım konudaki problemin bugünkü sorumuza cevap vermesine dikkat edeceğim.

Problem: Kişi sayısı belli olmayan bir grup insanın içerisinden 18 yaşındaki adı Mehmet olan gençlerin ve bastonu olan ihtiyarların sayısını nasıl buluruz?

Geçen sefer konumda anlattığım nesne ile çalışma mantığıyla bu soruya benzer bir soruyu yanıtlamıştım. Ama bu konuda anlatacaklarım geçen seferki konuma dahil olmadığı için bazı bölümleri atlamıştım. Atladığım bölümlerin içinde nesnelerin ait olduğu soy ağaçları da vardı. İşte size yeni bir kavram! Soy ağacı…

Nesne tabanlı dilleri geliştiren uzmanlar daha öncede belirttiğim gibi gerçek hayattıki olası problemlerin çözümü için en uygun şekilde dili günlük hayata entegre etmeye çalışırlar. Soy ağaçlarıda bize bir nesnenin nereden geldiğini, tipik özelliklerinin neler olduğunu, belirli olaylara nasıl tepkiler verdiğini açıklar. Böylece aynı soydan gelen nesneleri bir sınıflandırma yaparak bütünü daha iyi görebilmemize yardımcı olur. Örneğin biyoloji dersimizde hayvanların soy ağaçları olmasaydı ne yapardık? Mesela “Memeliler” hakkında bilgimiz varsa Balina’nın bir memeli olduğunu öğrendimizde tipi özelliklerinin neler olacağını az çok kestiririz değil mi? Ve bu da bize olayı daha çabuk kavramamıza yardımcı olur. Buna binaen nesne tabanlı dillerde de soy ağaçları görmek mümkündür. Fakat bir yazılımcı olarak problemlerimizdeki soy ağaçlarını biz kendimiz oluştururuz.

Soy Ağacı

.: Soy Ağacı :.

İşte size problemimizdeki soy ağacımız.

Gençler ve ihtiyarlar aslında birer insandır. yani gençleri ve ihtiyarları gruplandırırken “bir grup insan” tabirini kullanırız. Çünkü ilkokulda da öğrendiğimiz gibi elmayla armutu bir edemeyiz ancak bunları meyve olarak birlikte tutabilir. Aynı şekilde yazılımda da bunu bilgisayarımıza açıklamak durumundayız.

VB.NET

JAVA

Her iki dilde nesne tabanlı dil olmasından dolayı soy ağaçlarını destekliyorlar. Ben de soy ağaçlarını kullanarak bu problemi çözmeye çalıştım. Şimdi içinizden geçiriyorsunuzdur biz neden insan diye sınıf oluşturduk? Hadi insan sınıfını boşverelim, neden içi boş olmasına rağmen genc diye bir sınıf oluşturduk? Aynı işi genc sınıfını oluşturmadan da yapabilirdik…

Bu yazıyı yazmamdaki ana düşüncem bu sorularınıza cevap verebilmek!

Genç sınıfı şimdilik işimize yaramaz, bu çok bariz bir şekilde ortada! Ama ileride bu problem farklı bir şekilde karşımıza gelirse ve yeni problemin içinde sadece gençlere özgü bir nitelik bulunursa bu durumda ne yapacağız? Gördüğünüz gibi elimizde genc sınıfımız bulunduğu taktirde yeni probleme ayak uydurmak sadece bir kaç satırdan ibaret olacak! Bu yaptığım problem karşınıza çıkacak en basit problemlerden biridir inanın. Gerçek hayatta daha komplike sorunlarla karşı karşıya gelebilirsiniz. Bu yüzden burada anlatmaya çalıştığım gibi alt yapı kurmaktan kaçınmayın. Bunu bir binaya benzetebilirsiniz. Cebinizde biraz para var ve yeni bir ev yapacaksınız. Yeni evlendiniz ve çocuğunuz yok. Çocuk sahibi olmayı istiyorsunuz. Fakat şimdilik cebinizdeki para sadece 1 katlık ev yapabilmenize yetiyor bunun içinde çocuk odasını yapmamak zorundasınız. Bu gibi bir durumda ne yapardınız? Tabiki binanın temelini sağlamlaştırır ve ilerde paranız miktarınca yeni kat çıkabilirsiniz. Onun için her zaman ileriye dönük yatırım yapmak gerekir.

(Şimdi içimizden süpersonik akıllılar çıkıpta; “Niye ek kat çıkalım ki? Evin yanına yeni bir oda yaparım!” diyebilir. Onlara hitaben; “Evinizin yanına birşey kuramazsınız. Sadece ek kat çıkabilirsiniz :)” )

Unutmayın, Profesyonel olmayabiliriz ama Profesyonelce düşünebiliriz 🙂

Derleyici Çalışma Mantığı

Evet arkadaşlar bu haftaki konumu seçerken nesne tabanlı programlama dillerine başlayanların mutlaka adı gibi bilmesi gereken derleyici çalışma prensiplerini anlatacağım. Bildiğiniz üzere derleyiciler; üzerinde çalıştığımız dili anlamlandırıp makina diline dönüştüren programlardır.

İşte bizim değineceğimiz konu ise bu programlar neye göre yazdıklarımızı anlamlandırıyor ve hangi sırayla bu işlemi gerçekleştiriyor bunu öğrenmek…
Derleyicilerin çalışma prensibini çok iyi bilmek o dilde tasarlamış olduğumuz programları optimum düzeyde çalıştırabilmemize ve gereksiz kod satırlarını önlememize hatta bazı mantıksal yanlışları ayırt edebilmemize olanak tanır. İşte bu önemli faktörden kaynaklanan iş ve zaman avantajları yüzünden developerlar (Yazılım Geliştiriciler) gün geçtikçe derleyicileri daha avantajlı konuma getirebilecek yenilikler peşinde koşmaktalar. Bu kadar önemli bir husus karşısında bizim olaya fransız kalmamız ilerleyebilmemiz için çok büyük bir engel teşkil etmekte :))

Bu değişiklikleri, gelişimiyle yakından ilgilendiğim Visual Basic dilinde göstermek istiyorum.
Bundan çok önceleri (.NET Studio çıkmadan önce) Visual Basic 6.0 dediğimiz klasik Visual Basic dilinde değişken tanımlarken ki sıkıntımızı .NET Studio ile geliştirilmiş Visual Basic dilinde nasıl halledebileceğimizi küçük bir örnekle göstermek istiyorum.

Visual Basic 6.0

Dim ad As String, soyad As String

Visual Basic.NET (VB 10.0)

Dim ad, soyad As String

Her iki kodlada ad ve soyad değişkenlerimizi String türünden tanımlamış olduk. Dikkat ederseniz Visual Basic 6.0’da her bir değişken için türünü belirtmek zorunda kalıyoruz. Eğer türünü belirtmezsek yani Visual Basic.NET’te yazdığımızın aynısını Visual Basic 6.0’da da yazarsak kabul eder fakat sorun derleyicinin çalışma mantığına gelince ortaya çıkıyor. Visual Basic 6.0 derleyicisi her değişken için bir tür belirtilmesini istiyor ve eğer tür belirtilmezse özel bir tür olan Variant olarak değerlendiriyor. Bu tür diğer bütün türlerini içerisinde barındırabilen özel bir türdür fakat bazı değişken atamalarında Type Mismatch (Tür Uyuşmazlığı) hatasıyla karşırdık şimdi ise .NET teknolojisi sayesinde bu sıkıntımız giderilmiş oldu. Sanırım derleyici çalışma prensibini bilmeyen birisi ikisinide aynı yazdığında arada bir farkın olmayacağını tahmin edecektir. Ya da Visual Basic 6.0’dan Visual Basic.NET’e geçen bir kişi yeni derleyicinin çalışma mantığını bilmiyorsa eski kodlama mantığına devam edecek ve fazladan kod yazacaktır. İşte bu konuda üzerinde durmaya çalıştığım nokta burası! Derleyici çalışma mantığını bilerek olası hataları ört-pas edip daha az kodla daha fazla iş yapabilmek…

– Peki derleyicilerin genel çalışma prensipleri nelerdir?

Bunları şöyle bir sıralamayla gösterebilirim;

  1. Sözcüksel Analiz
  2. Sözdizimsel Analiz
  3. Anlamsal Analiz
  4. Kod Optimizasyonu
  5. Kod üretimi

Bu sıralama derleyici mantığını anlamaktan çok yeni bir derleyici oluşturmanın adımlarını gösterir 🙂 Bizim amacımız sadece işin mantığını kavramak, onun içinde kendi geliştirdiğim MKA’ları (Mantık Kavrama Adımları) göstermek istiyorum. Tabiki şaka yapıyorum MKA diye bişiy yok 😀

En basit şekliyle bir derleyiciyi ben satrançtaki At’lara benzetmekteyim. Satranç oynayanlarınız varsa atların özel bir taş olduklarını ve atlayarak (önündeki taşa bakmaksızın gideceğini noktaya varan) hareket ettiklerini bilirler. Bu taşlar istediğinde atladığı kareden tekrar eski karesine yeniden gelirler. Fakat bu hareketi yapabilmeleri için hamle sırasını beklemeleri gerekmektedir.

Derleyicileri de atlar gibi düşünürsek bulunduğu satırdan ilgili satıra atlayarak gidebilen ve işlemleri yapmadan (Hamle sırasını beklemeden) geri dönemeyen yorumlacılar olarak tanımlayabiliriz. Yani derleyici En üst satırdan başlar ve her satırı soldan sağa doğru okur.


Resimde de görüldüğü gibi atlama yeri olarak belirttiğim kısımda derleyici for döngüsünü belirtilen sayac kadar tekrarlar yani for döngüsünün son süslü parantezine geldiğinde atlayarak tekrar baştaki süslü paranteze geçer ve işlemi tekrarlar.
Bu örnek derleyicilerin atlayarak gittiğine dair küçük bi örnekti fakat olayı büyütmek gerekirse örneğin bir işlem sırasında farklı bir metod çağrılıyorsa derleyici o metoda atlayıp işlemleri gerçekleştirir ve tekrar eski noktasına geri döner.

Bir de derleyicilerin soldan sağa ilerleyişleri vardır buna da javadan bir örnek vermek istiyorum;

Yukarıda resimdeki for döngümüzü while olarak değiştirirsek sanırım bu olayı tanımlayabiliriz.

JAVA

int i=0;
while( i<10 ){
items[i++]=((i+1)+” nk”);
}

Bu kodda belki yanlışlık olduğunu düşünebilirsiniz. i değişkenimiz artmıyor bu döngü sonsuza kadar devam edebilir gibi bir sonucada varabilirsiniz işte işin püf noktası burası 🙂

items[i++] ile derleyici soldan sağa doğru yorumladığı için önce items’in içindeki “i” indexli elemanı getirir sonrada “++” operatörünü görünce “i” değişkenimizi 1 arttırıp koda devam eder. Böylece items dizimiz 0. elemandan 9. elemana kadar tanımlanmış olur.

Şimdi ise sadece çok küçük bir değişikliğin nelere mal olabileceğini gösterelim; tek yapmamız gereken “++” operatörünü “i” değişkenimizin önüne almak!

items[++i] ile derleyici soldan sağa doğru yorumladığı için önce “i” değişkenimizi 1 arttırır sonra da items dizisinin “i” indexli elemanını getirir. Bunun sonucunda dizi 1. elemandan 9. elemana kadar tanımlanmış olur ve hata oluşur. Çünkü 0. eleman tanımlanmadı 🙂

Gördüğünüz gibi nasıl ki hayatımızdaki ufak değişiklikler aslında büyük değişikliklerin bir tetikleyicisidir buna mütakiben programlama dillerindeki ufak değişikliklerde bazen büyük değişikliklere sebebiyet verebilmekte…

Umarım derleyicilerin çalışma prensipleri hakkında birazcıkta olsa bilgilendirebilmişimdir. Eğer programlama dillerinde ilerlemek istiyorsanız kesinlikle bu konuya değinmelisiniz.

Unutmayın şeytan ayrıntıda gizlidir 🙂

Nesne Tabanlı Dillerle Anlaşabilmek…

Genelde çoğu kişi nesne tabanlı dil söz konusu olduğunda gerilir. Bu gerginliğin asıl sebebi olayı kavramamış olmaktan kaynaklamaktadır. Nesne tabanlı dillerin oluşum evresinde ki amaç, dili gerçek dünyaya en yakın biçimde entegre edebilmek ve bunun sonucunda gerçek problemleri sanal ortamda çözümleyebilmektir. Yani aslında nesne tabanlı diller bir nevi gerçek dünyayı yansıtır diyebiliriz 🙂

Nesne tabanlı diller genel itibariyle birbirine benzer ve adından da çıkarılabileceği gibi temeli nesneye (Object) dayalı dillerdir. Bu dillerin yapısında nesneler ve bu nesnelerle etkileşimli olaylar bütünü bulur. Örneğin; gerçek dünyada klavye bir nesnedir ve bizim klavyeye tıklamamız ise klavyeyle ilişkili bir olaydır. Bunu bilgisayar ortamına taşırsak; her zaman karşımıza çıkan butonlar birer nesnedir, butona tıklamamız ise butonla ilişkili bir olaydır. Bu mantıktan yola çıkarak nesne tabanlı dillerin genel yapısını anlayabilirsiniz.

-Peki gerçek hayattaki problemleri nesne tabanlı dillerle nasıl çözebiliriz?

İşte bizi nesne tabanlı programlama dillerinin derinliklerine sürükleyen can alıcı soru budur. Hemen bir örnekle açıklamak gerekirse;

Problem: Kişi sayısı belli olmayan bir grup gencin içerisinden adı “Mehmet” olanların sayısını nasıl buluruz?

Bu problem gerçek hayatta karşımıza çıkabilecek bir problemdir. Peki bunu gerçek hayatta değilde sanal ortamda nasıl çözümleyebiliriz?
Yukarıda da anlattığım gibi nesne tabanlı dillerde nesneye dayalı işlemler gerçekleştiririz. Bu problemimizde elimizdeki nesneleri önce göz önüne alalım;

1) Sorumuzda sadece bir nesnemiz vardır. O da “Genç” olarak tasvir edilen insanlar bütünüdür.

2) Nesnemizle alakalı olan noktamız nesnemizin bir ad (isim) değişkeninin olmasıdır. Daha fazla özelliği bulunabilir fakat bizi ilgilendiren kısmı nesnenin “isim” değişkenidir.

3) Nesneleri tanımladıktan sonraki işlemimiz ise bu nesnelerle olan etkileşimi dile getirmektir. Bu sorudaki etkileşim her “gencin” adını sorup koşulumuza göre ayrım yapmaktır.

Ana maddelerimizi oluşturduktan sonra bunları kullandığımız dile göre ifade etmek gerekir. Ben burada Java ve Visual Basic.NET ile size, karşılık gelen kodları yazmaya çalışacağım zaten diğer dillerde birbirine benzemekte…

 

VB.NET

Public Structure genc

Public isim As String
Public yas As Integer

End Structure

Public Function ara(ByVal gencler As genc()) As Integer

Dim sayac As Integer = 0

For i = 0 To gencler.Length

If gencler(i).isim = “Mehmet” Then
sayac += 1
End If

Next

Return sayac

End Function

 

JAVA

class genc{
String isim;
int yas;
}

public int ara(genc[] gencler){

int sayac=0;

for (int i = 0; i < gencler.length; i++) {

if(gencler[i].isim.equals(“Mehmet”)){
sayac++;
}
}
return sayac;
}

______________________________________________

Her iki kodda da “ara” fonksiyonuna parametre olarak içinde “Mehmet” isimli gencleri bulmasını istediğimiz sayısı belli olmayan grubu parametre olarak yolladığımızda, fonksiyonlar içinde “Mehmet” olanların sayısını bize geri dönderir.

Nesne tabanlı programlama dillerinin mantığı yapmak istediğiniz olaylardan etkilenenleri nesne olarak görüp buna mütakiben kodları bu nesnelerin etrafında yazmaya dayanır.

Sayfama Hoşgeldiniz :)

Evet! Artık bi bloğumuz da olduğuna göre paylaşımlarımızı buradan da sürdürebiliriz ha 🙂