Ruby/Sıradışı Durumlar

←Sınıflar ve nesneler | Söz Dizimi→

Bu sayfanın orjinalinde birşey yok. Ben size ruby-doc.com sayfasından öğrendiklerimi yazayım.

Şimdiye kadar kodlarımızı mükemmel dünyada yazdık, hiçbir şeyin yanlış gitmediği. Tüm kütüphane çağrıları başarılı, kullanıcılar her zaman doğru bilgi giriyor, kaynaklar bol ve ucuz. Artık bu değişecek, gerçek dünyaya hoş geldiniz!

Gerçek dünyada hatalar oluşur. İyi programlar (ve programcılar) bunları öngörür ve bunları zarif bir şekilde ele almak için gerekli ayarlamaları yaparlar. Sıklıkla , kodlar hataya düştüklerinde ne yapacaklarına dair bilgi sahibi değildir. Örneğin olmayan bir dosyayı açmak istediğinizde bir fatal hata oluşur, sizin dosya işleme modülünüz ne yapacak?

Geleneksel erişim dönen değerleri kullanmaktır. open metodu , hataya düştüğünü belirten bazı değerler döner. Bu değer çağıran rutinlerde , biri onunla ilgilenene kadar yukarı doğru yayılır (propagate).

Ama mesela open , read ve close her biri bir hata dönebilir. Kodumuzda her birini çağırırken dönen değeri işlemek ve ona göre davranış belirlemek çok sıkıntı verecektir.

Bu tip durumlarla başa çıkmak için bütün dillerde "Sıradışı Durumlar" (Exceptions) adıyla bilinen teknikler kullanılır. Exception'lar hata hakkında bilgiyi bir nesnede toplamanızı sağlar ve bu sıradışı durum nesnesi sistem bu durumu bildiğini belirten bir kod bulana kadar çağrı sıralamasında geri doğru yayılır.


Exception Sınıfı

düzenle

Sıradışı durum hakkında bilgi içeren paket Exception sınıfı ya da onun çocuklarından bir sınıfın oluşumudur. Sınıf Hiyerarşisi şöyle:

  • Exception
    • NoMemoryError
    • ScriptError
      • LoadError
        • Gem::LoadError
      • NotImplementedError
      • SyntaxError
    • SecurityError
    • SignalException
      • Interrupt
    • StandardError
      • ArgumentError
        • Gem::Requirement::BadRequirementError
      • EncodingError
        • Encoding::CompatibilityError
        • Encoding::ConverterNotFoundError
        • Encoding::InvalidByteSequenceError
        • Encoding::UndefinedConversionError
      • FiberError
      • IndexError
        • KeyError
        • StopIteration
      • IOError
        • EOFError
      • LocalJumpError
      • Math::DomainError
      • NameError
        • NoMethodError
      • RangeError
        • FloatDomainError
      • RegexpError
      • RuntimeError
        • Gem::Exception
      • SystemCallError
      • ThreadError
      • TypeError
      • ZeroDivisionError
    • SystemExit
      • Gem::SystemExitException
    • SystemStackError


Sıradışı Durumu İşlemek

düzenle

Genel yapı şu şekildedir:

begin
    output = 5/0
    puts "başarılı"
rescue Exception
    STDERR.puts "Başarısız : #{$!}"
    raise
end

begin ile başlayan blok bir hata olmazsa çalışacak kodları içerir. rescue bloğu ise bir exception (sıradışı durum) oluştuğunda çalışacak kodları içerir. Orada kullanılan $! gloabal değişkeni oluşan hataya karşılık Ruby sisteminin ürettiği hata mesajını içerir. Bu kodun çıktısı:

Başarısız : divided by 0

olur, ayrıca bölme hatası olduğu için zaten Ruby'dehata mesajı verecektir. Bu sadece örnek olarak verilmiş kısa bir kod.


Sıradışı durum işleme bloğu içinde birden fazla rescue bloğu olabilir.

begin
    eval string
rescue SyntaxError, NameError => boom
    puts "String derlenemedi: " + boom.to_s
rescue StandardError => bang
    puts "Kod çalıştırılırken hata oldu: " + bang.to_s
end

Bu kodu eğer :

string = "put 'merhaba'"

ile çalıştırırsak

String derlenemedi: undefined method `put' for main:Object

hatası verir. Eğer:

string = "puts 5/0"

ile çalıştırırsak

Kod çalıştırılırken hata oldu: divided by 0

hatası verir.


Hatayı Kodla Üretmek

düzenle

Şimdiye kadar oluşan hataları işledik. İstersek kendimiz de kodumuzla hata üretebiliriz.

raise

bize

excep.rb:1:in `<main>': unhandled exception

verir.


name = nil
raise "İsim yok" if name.nil?

bize

excep.rb:2:in `<main>': İsim yok (RuntimeError)

verir.


names = ["Ümit", "Ahmet", "Sıla"]
i = 4
if i >= names.size
    raise IndexError, "#{i} >= #{names.size} (boyutu aştı)"
end

bize

excep.rb:4:in `<main>': 4 >= 3 (boyutu aştı) (IndexError)

verir.


raise ArgumentError, "İsim çok uzun", caller

bize

excep.rb: İsim çok uzun (ArgumentError)

verir. Bu örnekte parametrede caller metodunu vermesek

excep.rb:1:in `<main>': İsim çok uzun (ArgumentError)

verecekti.