• exception'lar programlama tarihinde en çok yanlış anlaşılan akış kontrol mekanizmalarından biri herhalde. bunun en büyük sorumlusu da bence java'nın exception'ları sıradan akış yönetimi için kullanmak adına öne sürmesi (bkz: checked exceptions).

    genel yaklaşım şu: bi program yazıyoruz. program bi yerinde "harş" diye exception verip yarılıyor, ortasında çıkıyor. ortaya çirkin çirkin hata mesajları ve kötü bir kullanıcı tecrübesi çıkıyor.

    bu durumda yapılması gereken kafamıza şöyle nakşedilmiş: "exception'ı yakala, düzgün bi hata mesajı göster, devam et". ya da daha kötüsü: "exception'ı yakala, yavaşça yere bırak ve uzaklaş".

    halbuki exception'lar genel amaçlı akış kontrolü için değil, adı üstünde istisnai durumlarda ortaya çıkan vaziyetlerin tespiti için varlar. exception throw edince handle edilmediği sürece tüm programın kapanmasına yol açma sebebi de o. çünkü alet exception'ı atarken söylemeye çalıştığı şey "bunların olacağını bilemezdim. benim normal geri dönmemi bekleyen koddan hayır gelmez artık."

    exception'ın varoluş sebebi zaten hata kontrolünü zerre yapmadan da doğru kod yazmayı sağlayabilmek. hayatımızda exception yokken napıyorduk (uyduruk c# gibi kod):

    int kopyala(inputfilename, outputfilename) {
    var input = file.open(inputfilename);
    if (input == null ya da baska bi error check) {
    return hatakodu;
    }
    var output = file.open(outputfilename);
    if (output == null ya da baska bi error check) {
    return hatakodu;
    }
    while(!input.eof) {
    var hatakodu = input.read(buf);
    if (hatakodu sorunlu) {
    input.close();
    output.close();
    return hatakodu;
    }
    hatakodu = output.write(buf);
    if(hatakodu sikintili) {
    input.close();
    output.close();
    return hatakodu;
    }
    }
    input.close();
    output.close();
    }

    resmen ağaçlardan ormanı göremiyoruz. kodun ne yaptığını anlamak için elimizde palayla hata kontrollerini biçmemiz gerekiyor. neden hata kontrollerine gerek var? çünkü aksi halde kodumuz "doğru olmayan" işler yapabiliyor. mesela okuma hatalı olursa çıktıya hatalı buffer yazabiliyor. üstelik fonksiyonu çağıran kodu da hata kontrolüne zorunlu bırakıyoruz. her şeyin düzgün gideceğini farz edemiyor.

    oysa günümüzün modern exception'lı sistemlerinde şunu yazabiliyoruz rahatça (bu c#'a biraz daha benziyor):

    void kopyala(inputfilename, outputfilename) {
    using(var input = file.open(inputfilename))
    using(var output = file.open(outputfilename))
    {
    while(!input.eof) {
    input.read(buf);
    output.write(buf);
    }
    }
    }

    burada dolaylı yoldan şunu demiş oluyoruz: "kardeş bu kodun her satırı bir önceki satırın hatasız çalışacağına güvenir. hata çıkarsa bu koddan hayır gelmez. o yüzden bu fonksiyon sadece doğru çalıştığında sorunsuz geri döner"

    kimse handle etmek zorunda olmadığı işe bulaşmıyor. eğer kimse handle etmiyorsa da zaten o programın devam edemeyeceği anlamına geliyor. böylece programın "yanlış iş" yapması, ve bunun doğru yapmış gibi görünme ihtimali sıfırlanıyor.

    exception gibi bir şeyin en büyük nimeti zaten bizi hata kontrol kodu yazmaktan kurtarması. doğru kodu hata kontrolü yapmadan da yazabilmemizi sağlaması. adı üstünde sadece "istisnai" durumlarda patlaması çatlaması. orada da patlaması doğal zaten.

    peki bi yerde dosya ismini kullanıcıya soruyoruz diyelim yanlış dosya ismi girdi bu kod tüm programdan çıkmaya yol açıyor. patlamasını nasıl engelleriz?

    burada hata kontrolünü programa tavuk suyuna çorbaya terbiyesini katar gibi azar azar katma imkanımız oluyor. güzelliği de burada. en başta senaryoya bakmak lazım. eğer dosya gerçekten kullanıcının yanlış yazımıysa, yani olmayan dosyaya erişim problemiyse exception yakalamaya yine gerek yok. gidiyorsun:

    if (!file.exists(inputfilename)) {
    showmessage("dosya yok");
    return false;
    }
    kopyala(inputfilename, outputfilename);

    yine esas fonksiyonumuzun davranışını değiştirmeye gerek yok. fonksiyonumuz halen aynı temiz koda sahip olmaya devam ediyor. exception'ı yakalamak yerine olmasını engelliyoruz. bu noktada tecrübeli programcılar "belki dosya tam biz o kontrolü yaptıktan sonra silindi?", "ya kullanıcının yetkisi yoksa?" gibi şeyler diyebilir. işte o durum zaten exceptional (istisnai) bi durum. orada patlaması gerçekten normal ve doğal. ama bu da yaygın bir case ise ve programdan çıkmak yine istemiyorsak sadece bu fonksiyon çağrısı etrafına bir kontrol atabiliyoruz:

    try
    {
    kopyala(inputfilename, outputfilename);
    }
    catch(ioexception e)
    {
    showmessage("kopyalama basarisiz oldu: " + e.message);
    return false;
    }

    yine sadece patlaması çatlaması halinde ne yapacağımız son derece net olan bir işlemdeki exception'ı catch ediyoruz. fonksiyonumuzun davranışını yine değiştirmiyoruz. kodu gereksiz kirletmiyoruz.

    bir okurdan şimdi mektup geldi tam entry'nin ortasında. malatya/merkez'den b.g. diyor ki: "peki o catch'te ioexception değil de tüm exception'ları yakalasaydık? hepsi bir hataya işaret etmiyor mu neticede?"

    evet hepsi öyle de ya da böyle bir probleme işaret ediyor. ama çevresel sebeplerden oluşan hata ile yanlış programlamadan doğan hataları bir anda aynı kaba koymuş oluyorsunuz. aslında programın devam etmemesi gereken bir akışa devam etmesine yol açıyorsunuz. eğer programınız oluşan problemi beklemiyor ise, o problemin ne olduğu hakkında fikri yoksa çalışmaya devam etmemesi "çaaat" diye patlayıp çıkması en doğrusu.

    mektup bu arada devam ediyor ne diyeceğimi düşünüp devamını yazmış: "böyle diyeceğinizi biliyordum size sorular hazırladım: nolabilir abi ya? yani programın kapanmasına yol açacak nasıl bir zarar olabilir sırf her şeye messagebox dayıyoruz diye? ne zararı var abi?"

    tekrar yanıtlamaya dönüyorum. kopyala() örneğimizden gidelim. kopyalanın etrafına genel geçer bir exception handler koyduğumuzu düşünün:

    try
    {
    kopyala(kaynak, hedef);
    }
    catch
    {
    showmessage("kopyalama sirasinda hata olustu");
    }

    böyle programı release ettiniz kullanıcılardan şikayet geliyor. sürekli "kopyalama hatası alıyorum acaba niye?" diye. siz de "diskiniz bozuktur" diye geçiştiriyorsunuz. ama içiniz içinizi yiyor. halbuki o genel geçer exception handler'ını koymayaydınız kullanıcılar "nullreferenceexception hatası alıyoruz" diyebilirlerdi ve siz de belli koşullarda yanlış yere null dosya adı pasladığınızı ve bunu kontrol etmediğinizi daha kolay tahmin edebilirdiniz. evet kullanıcı için yine kötü bir tecrübe olurdu ama kopyalamayla hiç alakası olmayan bir durumda "kopyalama hatası" demek kadar korkunç olmazdı.

    dikkat ettiyseniz körü körüne exception'ı catch edip hiçbir şey yapmadan programın çalışmaya devam etmesine izin verme kısmına hiç değinmedim bile. zira bunu yapan son programcıyı da geçtiğimiz hafta bir kazığa dikerek yaktık. kendilerinden hiç kalmadı. o yüzden o tarz programlamanın yol açacağı sorunlara değinmeye de gerek kalmadı.

    özetlemek gerekirse exception'lar istisnai durumlardır, çoğu zaman özel muameleye ihtiyaç duymazlar. exception'lara dair genel yaklaşımınız rahatlıkla şöyle olabilir:

    1. kodu exception'ları hiçbir şekilde handle etmeden yaz (java'da mümkün değil pek, şansınıza küsün)
    2. test edince patlıyor mu? hayırsa goto exit
    3. patlama exception'dan mı? değilse bug'ı fix et ve goto 2
    4. exception kod hatasından mı ortaya çıkmış yoksa çevresel bir sebepten mi? kod hatasıysa hatayı fix et ve goto 2
    5. exception'a yol açan çevresel problemi kodda önceden tespit etmek mümkün mü? evetse önceden kontrol edecek şekilde fix et ve goto 2
    6. exception'ı yakalayınca uygulama mantıklı şekilde devam edebilir mi? hayırsa olduğu gibi bırak ve goto exit
    7. (buraya kadar bir tane bile "try catch" yazmadık dikkatinize) sadece oluşacak spesifik exception'a uygun kapsamda ve spesifiklikte bir catch kodu yaz, manalı şekilde handle et ve goto 2

    exit: programı release et

    hayırlı olsun. gelecek bölümde: "büyük programcı yalanları: sen bakarken yazamıyorum"
  • sırf yanlış anlaşılmiyim diye bu konuda 14 yillik sözlük tarihinde yazdığım en uzun entry'lerden birini yazdım. baktım 8000 tuş vuruşu yazmışım. şimdi buna "kestirip atmak" diyen birinin kendisiyle inandıkları arasına girmek tehlikeli. o yüzden ben diyorum ki: herkesin tuttuğu exception kendine.
  • bu konuyu nereden öğrenmeye kalkarsanız kalkın bir bilgi yığınıyla karşılaşıyorsunuz. en azından ben yeni yeni öğrenirken durum böyleydi ve bu yığın sizin konu hakkındaki en basit ayrıntıları yanlış anlamanıza yol açabiliyor.

    exception'ları yeni yeni öğreniyorsanız bilmeniz gerekenler ;

    * ne yapacağınızı bilmediğiniz exception'ı yakalamayın*. yani catch(exception e) degil, catch(daha_spesifik_exception e) demeye özen gösterin.
    * sadece istisnai (adamlar adını boşuna exception koymamışlar) durumlarda exception fırlatın. örneğin kullanıcının yanlış mail adresi/şifre girmesi istisnai bir durum değildir.
    * "şurada kendi exception class'ımı yaratmalı mıyım?", "burda hangi exception'ı fırlatmalıyım" gibi durumlarda google'a sorun.

    artık exception konusunda sektörün uzmanlarından birisiniz, tebrikler.
  • yazılım camiasında kullanımıyla ilgili bir konsensüse varıldığını söylemek çok zor.

    şimdi bu try/catch mekanizmasını işletmek için yazılmak zorunda olan kod bazen gerçekten business kodu gölgede bırakabiliyor. dolayısıyla okunabilirlik açısından eleştiri getirenler haksız sayılmaz. fakat bu durum, try/catch mekanizmasını akıştan ayırmak için yeterli değil gibi geliyor bana.

    dosya okuma örneğinde olduğu gibi genel itibariyle yazdığımız kodun business logic kısmına hakimsek yani:

    - hacı bu dosya okurken nasıl bi sıkıntı olur? sorusuna

    + dosya ismi yanlıştır
    + dosya bilgisayarda kayıtlı değildir
    + dosyaya erişim kısıtlıdır vb.

    gibi bir kalemde bir ya da birden fazla cevabı takır takır sıralayabiliyorsak bence bu durumda try/catch kullanımından ziyade exception oluşmasını önleyecek bir biçimde if kullanımında bir beis bulunmamakta. yani:

    if( islegit(dosya_ismi) && fileexists(dosya_ismi) && iskullaniciyetkili(dosya_ismi, kullanici){
    ....olaylar, olaylar...
    }

    kullanımı gayet makul görünmekte. bunlar dışında oluşacak olaylar bizim bilgimiz dahilinde olmayan ve de gerçekten istisnai durumlar olacağından kodu try/catch e boğmak yerine bu yaptığımız işi tümden bir try/catch bloğuna alıp işimize gücümüze bakabiliriz.

    peki madem bu şekilde kullanabiliyoruz, o zaman bu mekanizma neden var sorusuna sadece kişisel tecrübeme dayanaraktan ve de haksız olabilme ihtimalini daha baştan kabul ederekten şöyle bir yanıtım var:

    şöyle bir durum düşünün. bankada yazılım geliştiriyorsunuz. size yatırım danışmanlarının kullanacağı bir yazılım geliştirmeniz söylendi ve de dendi ki "iş tanımı gereği yatırım danışmanları millete para kazandırır ve bu işi yaparken araç olarak şu, şu işleri gerçekleştirir. ona göre bir program şeyettir"

    hay hay demenize mukabil gittiniz bir yatırım danışmanıyla konuştunuz ve bu adamların yaptığı işi (domain) ucundan kıyısından öğrendiniz. basit ve atomic bir işlem olarak kodunuzun bir yerinde şöyle bir şey yapmanız gerektiğini varsayın:

    if(altin_fiyatı <= bizim_icin_karli_threshold){
    eftservice.transferyap(şu_hesaptan, bu_hesaba, su_kisi_adina);
    }

    şimdi malum devir api devri, milletin kodunu kullanma devri ben de bankada başka birisinin yazmış olduğu eftservis'i kullanarak transfer yaptım. ama hesap transferi domaini ile ilgili bilgim az olduğundan şunlar gerçekleşti:

    1.gün:
    - abi senin geçen transferde sorun çıktı, hesabın bakiyesi yetersizmiş. bi el at istersen
    + eyvallah abi

    yeni kod:

    if(altin_fiyatı <= bizim_icin_karli_threshold){
    if( hesapservice.checkbakiye(şu_hesap)){
    eftservice.transferyap(şu_hesaptan, bu_hesaba, su_kisi_adina);
    }
    }

    2.gün
    - abi senin geçen transferde sorun çıktı, senin transfer yaptığın hesaplar arasında transfer yapılamıyormuş, bi kontrol et istersen
    + eyvallah abi

    yeni kod:

    if(altin_fiyatı <= bizim_icin_karli_threshold){
    if( hesapservice.checkbakiye(şu_hesap) &&
    hesapservice.istransferable(şu_hesap, bu_hesap){
    eftservice.transferyap(şu_hesaptan, bu_hesaba, su_kisi_adina);
    }
    }

    3.gün
    - abi senin geçen transferde sorun çıktı, senin verdiğin kullanıcı o hesabın transferinde yetkili değilmiş bi bak istersen
    + eyvallah abi

    yeni kod:

    if(altin_fiyatı <= bizim_icin_karli_threshold){
    if( hesapservice.checkbakiye(şu_hesap) &&
    hesapservice.istransferable(şu_hesap, bu_hesap &&
    yetkiservice.iskullanicihesapicinyetkili(şu_hesap,kullanici)){
    eftservice.transferyap(şu_hesaptan, bu_hesaba, su_kisi_adina);
    }
    }

    daha uzar gider bu ama sanırım sorun anlaşıldı. yani ben sade bir yazılımcı olarak hiç ortada yokken durduk yere hesap transfer dinamiklerini öğrenmeye ve de kendi kodumda kullanmaya başladım. normalde hesap transfer işleyişinin dinamiklerini bilmesi gereken adam eftservisin yazarı fakat biz de ucundan kıyısından bulaşmış olduk. bu şekilde bir koddansa bana şu şekilde bir kod loose coupling açısından daha doğru geliyor:

    try{
    eftservice.transferyap(şu_hesaptan, bu_hesaba, su_kisi_adina);
    }
    catch(bakiyeyetersizexception e){
    ... kullanıcıya hata göster
    }
    catch(hesapturleriuyumsuzexception e){
    ... kullanıcıya hata göster
    }
    catch(hesapicinyetkiyokexception e){
    ... kullanıcıya hata göster
    }

    bunun (bence) güzelliği eftservice.transferyap() metodunu yazdığım an bu exceptionlardan haberdar olmam. yani business logic kendini açık etmiş oluyor. program akışını yukarıdaki gibi yapmak ya da alternatif olarak ilk ikisi için hesapkaynakliexception, üçüncü içinse yetkiexception fırlatıp bunu daha başka bir yerlerde handle etmek tamamen benim paşa gönlüme kalmış. bir de bu şekilde hesap transferiyle ilgili yeni bir constraint eklendiğinde checked exception olayı compile hatası vereceğinden notify edilmiş oluyorum.

    burada şöyle bir eleştiri getirilebilir. eftservisin yazarı bize bütün bu olayları check eden bir metod sağlasa daha güzel olmaz mı? yani kod:

    if(eftservis.butunkontrollerdengeciyormusenbanaonusoyle(şu_hesap,bu_hesap,su_kisi_adina)){
    eftservice.transferyap(şu_hesaptan, bu_hesaba, su_kisi_adina);
    }

    şeklinde olsa?

    olur abi niye olmasın. fakat bu durumda o muazzam metodun içerisinde gerçekleşebilecek farklı hata çeşitlerini anlamak kısmı sıkıntı oluyor. o metodu int yaparım, farklı değerleri için de farklı aksiyon alırım derseniz lafım olmaz. kod sizin, keyif sizin.

    özetle benim exception kullanımı konusunda rule of thumb'ım genel itibariyle domain bilgisi ile ilgili. kodun büyük kısmına hakimken try/catch hamallık olsa da birbirine işi düşen servisler arasında bu mekanizmayı kullanmak daha uygun *

    try/catch olayında business kodun try/catch kodu arasında boğulmasını önlemek amacıyla separation of concerns olayı üzerinden hareketle aspect oriented programming kullanılabilir fakat bu tabi ki başka bir entrynin konusu.
  • go dilinde ne guzel cozulmus sorun. megersem hic bu kadar komplikelestirmeye gerek yokmus olm, nasi da fark edememisiz. okunakli kod nasi uretiyor bu dil gorelim:

    result, err := bisiyyap()
    if err != nil {
    // handle err, edemiyosan "return nil, err"
    }

    result, err := baskabisiyyap()
    if err != nil {
    // handle err, recover falan et tolerate et ne bileyim
    }
    ...

    boyle kodunuz akar gider, hangi error'u nerde handle ettiginizi gorursunuz cunku cogu method <return_type, error> seklinde tuple dondurur eger metodun icinde hata olusma ihtimali varsa.

    simdi mutlaka cikip diyen olacak "bissuru if err != nil { var burda yaaaa" diye, evet var. ama hemen invocation satirindan sonra geliyor, 700 satir asagida degil, ve hemen exception'u 2 satirda handle edip belki de exception'a tolere edip hemen isimize kaldigimiz yerden devam da edebiliyoruz.

    megesem exception type'lara, checked exception'lara falan hicbirine ihtiyacimiz yokmus. exception (go'da error) instance'inda message() diye bi method olsa (o da ekrana basalim, gonuller bir olsun diye) yetiyor ve artiyormus la. zannedersem tek eksiğimiz buydu.
  • mesela anjin san'ın örnek verdiği kod okunaksız anlaması, ne olunca ne yaptığını çıkarması güç. exception'ları akış yönetimi için kullanmanın problemi de bu zaten. principle of least astonishment'ı ihlal ediyor. throw edilen exception'ların ne zaman edildiği ve handling önceliklerini belirlemek mümkün değil. bu yüzden davranışı kontrol etmek de kestirmek de zor.

    transaction'lar ve karmaşık enterprise sistemler de exception kullanmaya bahane değil. güvenli transaction rollback zaten hiç exception kullanmadan mümkün. (.net)

    "if (abonevarmi && aboneyasaklidegilmi && aboneninparasivarmi)" son derece net ve anlaşılır bir kod. ama o şekilde yazılmasına gerek yok:

    if (!abonevarmi) {
    ..
    }
    if (!aboneparasivarmi) {
    ..
    }
    if (!aboneyasaklimi) {
    ..
    }

    tarzı dümdüz yazılabilir. gayet okunaklı ve anlaşılır olur. java'da mümkün olmayabilir ama .net'te bu kod bloğunu bir transaction scope ile çerçevelemek atomicity'sini de garantileyecektir. örn:

    using(var scope = new transactionscope()) {
    dosomething();
    dosomethingelse();
    scope.complete();
    }

    burada eğer dosomethingelse patlarsa dosomething'in yaptıkları otomatik rollback edilir. herhangi bir cleanup kodu yazmaya da gerek yok. istediği kadar enterprise, istediği kadar karmaşık olsun. .net bunu sağlıyor. java sağlamıyorsa da geçmiş olsun.

    exception'ların transport mekanizmalarında kolayca wrap edilip sistemler arasında rahatlıkla akma kabiliyetinin olmasını güzel bişey gibi sunup bu kabiliyetin aslında "tüm veri yapılarında" olduğunu atlamak manipülasyon olmuş. exception aktarılıyo da ahmet mehmet aktarılamıyo mu allah allah.

    anjin san'ın örnek verdiği kodun exception'sız hali şöyle. her ne kadar bu fonksiyon spesifikasyon tarafında hatalı tasarlanmış olsa da (god function) hangisinin hangi durumda ne yaptığı daha net anlaşılıyor, vicdanınız karar versin:

    using(var scope = new transactionscope()) {
    if(abone.yok) {
    return;
    }
    if (abone.yasakli) {
    // birilerine ulas
    scope.complete();
    return;
    }
    if(abone.borcuvar) {
    // aboneye ulas
    scope.complete();
    return;
    }
    if (abone.prepaid) {
    // taciz et
    scope.complete();
    return;
    }
    abonekampanya ak = kampanyaservisi.aboneyeıtele(abone);
    ak.kampanyabirseyinidegistir(hebelek);
    scope.complete();
    }

    benim sakalım olmadığı için exception'ların akış kontrolünde neden kullanılmaması gerektiğine dair biraz kaynakça da sunayım:

    http://c2.com/cgi/wiki?codewithoutexceptions
    http://c2.com/…wiki?avoidexceptionswheneverpossible
    http://c2.com/…wiki?dontuseexceptionsforflowcontrol (özeti için: http://programmers.stackexchange.com/a/189225)
    http://joelonsoftware.com/articles/wrong.html
  • anjn san demiş ki:

    "oğlum öyle projeler var ki, sizin görmediğiniz ve asla göremeyeceğiniz ölçeklerde. onlarda istisnai durumlar yaygın olabiliyo"

    eğer istisnai durumlar çok yaygınsa bunlar zaten uygulamanın modelinin bir parçasıdır, exception'lık değildir. uygulama bu domain'e göre doğru şekilde modellenir. senin kullandığın kütüphaneler, servisler vs exception'la iletişim kuruyor diye senin de uygulamanın exception tabanlı tasarlamana gerek yok. bunu yapman can sıkıcı, kullanışsız, sevimsiz, nahoş. yapma.

    "öyle büyük ve muhteşem projeler var ki sadece benim gördüğüm ve tadını aldığım, onlarda unhandled bi case çıktığında senin katmanın handle etmiyorsa onu detect edebilmek için exception gerekiyor"

    doğru. ben de ilk entry'mde bunu demiştim zaten. consumer'ın service'in bi case'ini handle edemiyo olması gayet istisnai bir durum. bu iş akışının parçası değil zaten. öyle bi iş akışı mı var "programcının unutkansa üçüncü aşamaya git" diye. alla alla. exception'ın en büyük esprisi bu case'i çözmesi zaten.

    ama o "aboneninborcuvarexception"ları catch ederek olmaz anjin. bak onları kritik fonksiyonların throw etmesinde gariplik yok. senin tüm business logic'i onları catch ede ede, sırtını exception'lara dayaya dayaya yapmanda yanlışlık var. o exception'ların suratına patlamayacağı şekilde kodu yeniden organize edin. iş dünyanızda gelişmeler var. iyi bir haber gelecek.
  • zehirle ilaci ayiran sey dozmu$tu.. *kips*

    yerinde ve kararinca kullanilirsa iyidir. mesela ben "hic exception kullanma" diyene de, try / catch dolu koda bakinca da "ehieheih" diye guluyorum, benim niye ve nasil guldugumu kim sallayacaksa artik.
  • ideal bir dunyadaki yazilim gelistirmeden bahsedilmis: try catch'den uzak dur, program cakilsin, niye cakildigini bul ve onu duzelt. bu yontem ve sinirsiz sabirla, programinin hic cakilmadigi bir an gelecek, o an programci uzaklara bakacak ve kendini rock yildizi gibi hissedecek.

    kulaga hos geliyor ve unit test'leri de ihmal etmezsen en iyi secenek.

    yaygin olarak kullanilan (ve yanlis oldugu ifade edilen) ikinci yontem ise, kodu mantiksal bloklara ayirip try-catch'ler icine almak. catch'e dusulurse calismayi o noktada kesmek, apar topar kendini cagiran ust fonksiyona haber gecmek, "su noktada sicti" seklinde. elbette kodun akisini bu noktada durdurmak, gerekiyorsa rollback'leri de yapmak gerek.

    sahsi deneyimimce, bahsettigim ikinci yaklasimda da son derece stabil yazilimlar elde ediyorsunuz. programinizin tam olarak nerede cakildigini hep biliyorsunuz, cagiran ust fonksiyon durumdan haberdar oluyor ve en derindeki fonskiyonda yanlis giden bir seyden ui'ye kadar hata raporu geri iletiliyor.

    soylendigi gibi kodu basibos ve try-catch'siz birakip kendi capimizda bir suru testlerden gecirsek ve piyasaya sursek, ancak son kullanicilar o ana kadar tespit edilmemis istisna durumlar yaratabilseler ve bize ekran goruntusu gonderseler, o ekran goruntusunde ayi gibi bir "object reference not set to an instance of an object" yazsa, alt alta cok fonksiyon cagiran kodlarda isin tam olarak nerede yanlis gittigini bulmak zorlasacaktir. oysa kodun mantiksal bolumleri try-catch icerisine alinsaydi tam sicma noktasi ui'ya ya da logger'a iletilebilirdi ornegin "baba getpezevenkbyid() sicti parametre -1 geldi" diye.. bahsi gecen birinci ve super ideal cozumde bu konuya nasil cozum bulundugunu henuz anlamadigimi itiraf etmeliyim.
  • fr. istisna
hesabın var mı? giriş yap