İçindekilerGirişİndex
YukarıİlkÖncekiSonraki YokSon
Geriİleri
Yazdır
Onder Teker
on_der_tek_er@yahoo.com

Exception Nedir, Ne Değildir?

Nerden Çıktı Bu Exception'lar?

Bu yazımda programlama dilleri konusunda en anlaşılmayan, daha doğrusu en fazla yanlış anlaşılan konulardan birine değinmeye karar vemiş bulunuyorum : Exception'lar. Burada exception'nun ne olduğunu ve nasıl kullanıldığını anlatacak değilim. Zira, bu konuda bilgi (benim yazdıklarım dahil) bir çok kitapta ve belgede ayrıntılarıyla bulunmaktadır. Bir çok programcının exception'ları bildiğine fakat kullanmadığına, sevmediğine, hatta karşılaşmaktan zerre hazzetmediğine esefle şahit oldum. Sırf programcının başına bela olsun diye yapıldığına inanlar bile var! Bu durumda konuya bir açıklık getirmek benim boynumun borcu oluyor. Bu yazıyı okuduğunuzda sizin kalbinize ve beyninize de biraz ferahlık gelir umarım. Gelmezse de kendiniz bilirsiniz.

Aslında konunun aslı psikoloji ve felsefeye dayanıyor. (Biyolojiye dayandırılabilirsa biraz zorlama olur kanımca.) İnsanın kendi yaptığı hatalar karşısında takındığı tavır, bir çok inceleye konu olmuştur (herhalde). Bütün bu incelemeleri okumuş değilim. (Ne bekliyorsunuz benden? Her konuda yazılmış bütün kitapları okuyacak değilim!) Şurası kesin : İnsanlar kendi yaptıkları hatalarla yüzleşmek istemezler. Bir çok kişi, hata bariz ortadayken bile yokmuş gibi davranır. Belki programcıların, ortalama zeka seviyesinden yukarıda oldukları inancından ötürü böyle davranışlarda daha az bulunacağı düşünülebilir. Bu kısmen doğrudur. Ama sadece kısmen! Gözlemlerime göre programcılar hata çıktıktan sonra onun görmemezlikten pek gelmiyorlar. Ancak hatanın kendilerinin yaptığı bir yanlıştan dolayı gerçekleştiğine pek fazla inanmak istemiyorlar. Yazdığı programı üretildiği makineden farklı bir makineye kuran programcı çalışmaması durumunda çok rahat makineye suç atabiliyor. "Bu aptal işletim sisteminin bug'ı var!". İlk başlarda çalışıyor görünen bir uygulamanın kullanıcının bir süre çalışmasından sonra doğru çalışmamaya başlaması durumunda kullanıcıyı suçlamak en kolay yol : "Aptal herif, bir türlü öğrenemedi programı kullanmayı!" veya "Kim bilir ne yaptı bu salak kullanıcı da program yamuldu".

Sık sık böyle düşüncelere kapılan programcılar, çalıştıkları kurumun yöneticileriyle yaptıkları "genel değerlendirmeler" sonrasında bu tavırlarından vazgeçmek zorunda kalıyorlar. Çünkü programcının görevi bir programı sadece yazmak değil çalışır hale getirmektir. Bu yüzden çeşitli kullanıcılarla ve makinelerle testler yapılıyor ki program sorunsuz çalışsın. Testleri iyi yapmak dışında kod yazarken dikkatli olmak da önem kazanıyor tabii burada. Bir program ne kadar dikkatli yazılırsa yazılsın mutlaka içerinde bir "böcük" kalır. Hadi böcükleri ezdik cort diye... Programı çalıştıran kişiler mutlaka bir hata yapacaklardır. Bir programı çalıştırmakla görevli bilgisayar uzmanları sıradan kullıcıdan daha fazla bozarlar programın çalışmasını. Sıradan insanlar çalıştıkları makineleri kurcalamaya korkarlarken, bu "uzmanlar" durup durup makineyi işletim sisitemini mıncıklayıp dururlar. Sonunda da kabak programı yazan kişinin başına patlar. "Ama benim makinemde çalışıyor!" da diyemezsin bu durumlarda. Yahut dersin de hiç bir kuymeti olmaz. Bir programı yazan kişi oluşabilecek her türlü hatayı anlamak ve çabucak çözüm üretmek durumundadır. En başta da kod yazarken kendi yaptığı hataları anlayabilmesi gerekir.

Size bir anımı anlatayım sırası gelmişken. Ben öğrenciyken, makine alacak paramın olmaması nedeniyle programlama çalışmalarını okulun bilgisayar laboratuarında yapardım. Laboratuar'daki makineler de bölümümün ödenekleriyle değil, hocalarının çabalarıyla toplanan bağışlarla alınmıştı. Bütün öğrencilerin "gıcık" gittiği "kıl" asistanların çabalarıyla ayakta duruyordu bütün network. Bir gün laboratuarda çalışırken bir arkadaşın makinenin monitörüne ve klavyasine deli gibi vuduğunu ve "Aptal makine! Aptal makine!" diye bağırdığını gördüm. Eleman bir program yapmış, her şeyi doğru yaptığı halde bu "aptal" makine çalıştırmıyormuş. Yanına gittim ve "Hiç hata yok!" dediği programa baktım. Hakikaten hata yok! Daha doğrsu öyle görünüyor. Ama biraz daha incelediğimde hatayı buldum ve arkadaşa "Bilgisayarın aptalı olmaz! Sadece programcının aptalı olur!" dedim. Belki biraz sert bir ifade ama kendi malı olmayan bir makineyi döven bir insana da "aptal" demek pek de yanlış olmaz.

Aslında bu bahsettiğim arkdaş aptal değildi. ("Sadece salaktı!" dermişim. Yok yok şaka yaptım, aksine zeki bir insan olduğunu söyleyebilirim.) Peki bu arkadaş niye hatasını bulmakta bu kadar zorlanıyordu? İşteee! Sonunda asıl konumuza geldik. Bu arkadaş hatasını bulamıyordu çünkü programı yazdığı dil ona yaptığı hatayı söylemiyordu. Belki programlama dili çok kibardı, arkadaşın hatasını yüzüne vurmak istemiyordu! Oysa gerçek dost acı da olsa gerçeği insanın yüzüne karşı söyleyen kişidir. Bir çok derlemeli dil bu programcının yaptığı sintaks (sözdizimi) hatasını derleme aşamasında söylemektedir. Ancak bazı hatalar çalışma zamanında oluşabilmektedir. Bir programlama dilinin hatayı anlaması yeterli değildir, program parçasını yazan kişinin riskli durumlarda belli bir hataya karşı önlem almaya zorlaması gerekir. Başka insanlarını kullanımı için kütüphane, paket veya nesne yazanların, ürettikleri kodu kullanları hatalar karşısında önlem almaya zorlayabilmelerine olanak tanımalıdır. İşte bu en kolay ve sağlam biçimde exception'larla yapılabilir.

Yeterince soyut konuştum biraz örnek vereyim. Öncelikle exception'suz bir error handling yapalım. Yapalım ki excepion'ların kıymetini anlayalım. Bir dosyadaki metni alıp ekrana basacağımızı düşünelim. Çok basit bir işlemdir bu :

String text=loadText("c:\\myfolder\\myfile.txt");

Siz böyle bir kod yazdınız, ve programı herhangi bir makineye kurdunuz. Ama "myfile.txt" dosyasını götürmeyi unuttunuz. Ne olacak? Hadi siz çok dikkatlisiniz unutmadınız da kullacını yeri kalmadığı için bu dosyayı bilmeden sildi. Sonra da utanmadan "Ben hiç bir şey yapmadım, program kendi kendine çöktü diyor! Yahut kullanıcı da hiç bir şey yapmadı ve dosyanın başına bir şey geldi. Olamaz mı? Dosya kaybolur, diskin çürük bir yerine düşer, siz okurken başka bir onu dosyayı kilitler. Gördüğümüz gibi olabilecek kötü şeylerin bir sınırı yoktur.

Dikkatli bir programcı bir dosyayı okumaya çalışırken onun orada olmaması durumunu da değerlendirir. Ancak piyasa koşullarınıda her zaman "iyi" kod yazmak mümkün değildir. Proje planları çoğunlukla ancak porgramın asıl kısmını yazmaya yeterlidir. Olası hataları değerlenedirmek için her zaman vakit bulunmayabilmektedir. Ne diyorum ben? Bir programı doğru düzgün yazmak için hiç bir zaman süre verilmez. Hangi ülkede (veya hangi çağda) yaşıyorsunuz? Hem süre verilse ne olacak? Bir programda oluşabilecek bütün hataları bulmak o kadar kolay mıdır? Bir kaç satırlık bir dosya okuma işleminde oluşabilecek o kadar çok hata var ki! Dosya orada olmayabilir, orada olur ama boş olmaz, dolu olur ama yanlış data içerebilir.

Örnek üzerinden gidersek bir dosyanın içerisindeki meyni okuyan loadText() methodu'nun içi Java sintax'ına göre (ki C#, J#, JavaScript, JScript, C++ bilenler de çok kolay anlayabilirler) şöyle yazılmalıdır :

String loadText(String filename){
	try{
		FileReader fr=new FileReader(filename);	
		BufferedReader in=new BufferedReader(fr);	
		String text="";
		String line="";
		while((line=in.readLine())!=null){
			text+=line;
		}
		return text;
	}catch(Exception e){
		System.out.println("Can't read file "+filename);
		e.printStackTrace();
	}

}

Buradaki kodu try-catch içersine almak zorundaydık. Aksi takdirde kod derlenemezdi. Çünkü kullanılan methodlar ve constructor'lar IOException ve onun bir alt sınıfı olan FileNotFoundException'ı fırlatabilmektedirler. Burada Java'nın I/O API'ını yazan kişiler programcıları dosya okuma işleminde oluşabilecek herhangi bir hataya karşı önlem almaya zorlamaktadırlar. Tıpkı çocuklarınının okuyup adam olması için zorlayan anne-baba'lar gibi bu amcalar bizlerin iyiliği için bu zorlamayaı yapmaktadırlar. Nasılki anne-babalarımızın değerini büyüdükçe anlıyorsak, programcı veya geliştirci olarak tecrübelendikçe suratımızın ortasına exception fırlatan bu herifleri giderek daha çok anlar hale gelmekteyiz.

Bir çok programcı Exception'lara gıcık olduğu için yukarıdaki kodu şu şekilde yazar :

try{
	FileReader fr=new FileReader(filename);	
	BufferedReader in=new BufferedReader(fr);	
	String text="";
	String line="";
	while((line=in.readLine())!=null){
		text+=line;
	}
	return text;
}catch(Exception e){}

Burada exception yakalanmakta ama hiç bir önlem alınmamaktadır ki hiç şiddet yanlısı biri olmamam rağmen bunu yapanları hafifçe dövmek caizdir itikadımca. Bu, yangın alarmını duyup onu kapatan, bir insana benzer ki, sadece kendisini değil birlikte yaşadığı ve çalıştığı bütün insanları yakar.

Bir exception'u yakalamk istemeyen programcı bunu pekala exception'u öldürmeden de yapabilir. Nasıl mı? Şu şekilde :

String loadText(String filename)
	throws IOException
{
	FileReader fr=new FileReader(filename);	
	BufferedReader in=new BufferedReader(fr);	
	String text="";
	String line="";
	while((line=in.readLine())!=null){
		text+=line;
	}
	return text;

}

Burada "Ben hata olması durumunda hiç bir şey yapmıyorum, bu methodu çağıran yapsın!" diyoruz. Bu gayet doğru bir yaklaşım. Bu durumda da loadText() methodunu çağaran kişiyi Exception'ları yakalamak zorunda bırakıyoruz. Bu metodu yazan biz olduğumuz gibi çağıran da biz olabiliriz. O zaman try-catch bloğunu şu şekilde yazabiliriz :

try{
	String text=loadText("c:\\myfolder\\myfile.txt");
	System.out.println("Text Of File  : "+text);
}catch(IOException e){
	System.out.println("IO Error");
	e.printStackTrace();
}	

Aslında bırakın exception'ları değerlendirmeyi, bir programcını gerektiğinde Exception fırlatmaktan geri kalmaması lazım. Örnekteki loadText() method'unu çağıran kişi ya kazayl filename yerine null veya "" (boş string) girerse? Bunun kontrol edilmesi lazım :

if(filename==null){
	throw new IllegalException("Filename is 'null'!");
}else if filename.equals("")){
	throw new IllegalException("Filename is empty!");
}

Çok mu abartığımuı düşünüyorsunuz? Az bile abarttım, zira şimdi daha da ileriye götüreceğim : Kendimize exception'lar uyduracağız! (Çok sevdik ya artık exception'ları, biz de bunlardan bir iki tane yapalım, siz de evde beş altı-tane yapın, lazım olur!) Diyelim ki dosyadan okuduğumuz metnin belli bir uzunluktan fazla olması gerekiyor. Örneğin 100 karakterden az bir metin bizim için geçersiz. Bunun için öncelikle TextIsNotLongEnoughException (MetinYeterinceUzunDeğilİstisnası) diye bir exception uyduralım :

class TextIsNotLongEnoughException extends Exception{
	TextIsNotLongEnoughException(int length){
		super("Text Length is not Enough : "+length);
	}
}

Bu exception'u da text'i okuduktan sonra gerekiyorsa fırlatalım :

if(text.length()<100){
	throw new TextIsNotLongEnoughException(text.length());
}

Bu şekilde extra bir güvenlik yampış olduk. Ancak loadText method'unda artık :

String loadText(String filename)
	throws IOException,TextIsNotLongEnoughException 

dememiz lazım. Böylelikle loadText methodunun

try{
	String text=loadText("c:\\myfolder\\myfile.txt");
	System.out.println("Text Of File  : "+text);
}catch(IOException e){
	System.out.println("IO Error");
	e.printStackTrace();
}catch(TextIsNotLongEnoughException e){
	System.out.println("Text Length Problem "+e.getMessage());
	e.printStackTrace();		
}	

Aslında bir alternatifimiz daha var. İki ayrı exception yakalamak yerine

try{
	String text=loadText("c:\\myfolder\\myfile.txt");
	System.out.println("Text Of File  : "+text);
}catch(Exception e){
	System.out.println("An Error Occured"+e.getMessage());
	e.printStackTrace();
}

Ancak bu durumda iki ayrı durum için iki ayrı tepki verme şansımız kayboluyor. Sadece "Hata Var!" deyip işin içinden çıkıyoruz. Oysa her hata durumu için ayrı bir işlem yapmamız gerekebilir.

İstenirse TextIsNotLongEnoughException'un RuntimeException'u extends etmesi sağlanabilir. Bu durumda throws'a yazmaktan da yakalamakzorunda kalmaktan da kurtuluruz. Elbette istersek yine yakalayabilriz ama yakalamzsak derleyici kızmaz. Niye kızmaz? Çünküm nasıl olsa bu method'u çağıran method yakalamzsa onu da çağıran method yakalar. O da yakalamzsa mutlaka Java Virtual Machine yakalar.

Belki burada anlatılanlar bir çok kişi için extra külfet gibi gelebilir. Ama bir porgramcının zamanını en çok alan şey kod yazmak değildir. Yetişmeyen projeler için sabahlayanlar, gözleri kan çanağı, göz altları şiş torbası olana kadar çalışanlar bilin ki kod yazmak için değil küçücük bir hatayı bulmak için hayatlarını heba ederler. Saatlerce hatta günlerce aradaıktan sonra hata bassit bir virgül eksikliği, boşluk fazlalığı, tek tırnak yerine çift tırnak koyma gibi basit bir sebep çıkabilmektedir. İyi bir dil örneğin Java programcını yaptığı hataların çoğunda Exception fırlatır. Derleme zamanında veya çalışma zamanında. Özellikle "Ben hata yapmam!" diyen zavallılara acımak gerekir. Doğrusu "Ben hata yaparım ama bunu çabuk anlarım ve düzeltirim!" olmalıdır. İşte sizin hatanızı çabuk anlamanızı sağlayan en önemli araç exception'lardır. Onları seviniz ve bağrınıza basınız. Bu söylediklerimi özellikle exception'suz dillerle çalışan veya exception'lu bir dilde çalışıp onlara uzak durmaya çalışanlar iyi dinlesin. Bir hata çıktığında ekrana bön bön bakarken bu sözlerimi hatırlasınlar. Yoksa programcılık onlara öyle bir exception fırlatır ki profosyonel hayatları boyunca şaşkın şaşkın ortalıkta dolaşırlar!

İçindekilerGirişİndex
YukarıİlkÖncekiSonraki YokSon
Geriİleri
Yazdır