Xatolarni boshqarish (Exception Handling) — havaskor dasturchini professionaldan ajratib turadigan mavzu. Dastur ijrosi davomida kutilmagan holatlar — noto’g’ri ma’lumot, mavjud bo’lmagan fayl, nolga bo’lish — muqarrar yuzaga keladi. Ruby’da bunday holatlar begin, rescue va ensure orqali boshqariladi.
Exception — dastur ijrosi vaqtida yuzaga keladigan g’ayrioddiy holatni ifodalovchi obyekt. Barcha standart xatolar
StandardErrorsinfidan meros oladi.begin...rescuebloki xatoni ushlab, dasturning to’xtab qolishining oldini oladi.
begin va rescue
Xavfli kod begin blokiga, xato yuz berganda bajariladigan kod esa rescuega yoziladi:
begin
natija = 10 / 0
puts natija
rescue ZeroDivisionError => xato
puts "Xato ushlandi: #{xato.message}"
end
puts "Dastur davom etmoqda"
Xato ushlandi: divided by 0
Dastur davom etmoqda
10 / 0 — ZeroDivisionError chiqaradi, rescue uni ushlab, tushunarli xabar berdi. Eng muhimi: dastur qulamadi, oxirgi qatorgacha ishlashda davom etdi. xato.message — xato haqidagi matnli tavsifni qaytaradi.
Bir necha rescue bloki
Turli xato turlarini alohida ushlash uchun bir necha rescue yozish mumkin — ular yuqoridan pastga tekshiriladi:
def songa_aylantir(matn)
begin
Integer(matn)
rescue ArgumentError
puts "'#{matn}' songa aylanmaydi"
rescue TypeError
puts "Noto'g'ri tur berildi"
end
end
songa_aylantir("42")
songa_aylantir("salom")
'salom' songa aylanmaydi
Diqqat: Integer("42") xatosiz 42 qaytardi, shuning uchun hech qanday rescue ishga tushmadi va natija chop etilmadi. Integer("salom") esa ArgumentError chiqardi va mos rescue uni ushladi. (String#to_i dan farqli, Integer() funksiyasi noto’g’ri matnda sokin 0 emas, aynan xato chiqaradi — bu ataylab tanlangan, qat’iyroq usul.)
ensure — har doim bajariladigan blok
ensure — xato yuz bersa ham, bermasa ham har doim bajariladigan kod uchun ishlatiladi, odatda resurslarni tozalash uchun:
begin
puts "Fayl ochilmoqda..."
raise "Ulanish uzildi"
rescue => xato
puts "Xato: #{xato.message}"
ensure
puts "Fayl yopildi"
end
Fayl ochilmoqda...
Xato: Ulanish uzildi
Fayl yopildi
raise "Ulanish uzildi" — o’zimiz qo’lda xato chiqardik (RuntimeError turida). ensure bloki xato ushlanganidan keyin ham ishladi — u fayl yopish, ulanishni uzish kabi “albatta bajarilishi kerak” amallar uchun mo’ljallangan.
O’z xato klassingizni yaratish
Katta loyihalarda o’ziga xos xatolarni aniqroq ifodalash uchun StandardErrordan meros oluvchi maxsus klass yaratiladi:
class BalansYetarsizXatosi < StandardError
def initialize(xabar = "Balansda yetarli mablag' yo'q")
super
end
end
def pul_yechish(balans, summa)
raise BalansYetarsizXatosi if summa > balans
balans - summa
end
begin
pul_yechish(1000, 5000)
rescue BalansYetarsizXatosi => xato
puts "Amaliyot rad etildi: #{xato.message}"
end
Amaliyot rad etildi: Balansda yetarli mablag' yo'q
BalansYetarsizXatosi < StandardError — o’zining nomlangan xato turi, rescueda aynan shu turni alohida ushlash mumkin. Bu, umumiy rescuega solishtirganda, xatoning aynan qaysi biznes-qoida buzilganini aniq ko’rsatadi.