التعامل مع الأخطاء

تعديل
نسخ الدرس
تحميل الدرس

التعامل مع الأخطاء (Error Handling)

في البرامج الحقيقية، الأخطاء أمر حتمي. قد يُدخل المستخدم قيمة غير صحيحة، أو قد يفشل الاتصال بالإنترنت، أو قد نحاول القسمة على صفر. بدلاً من ترك البرنامج ينهار، يمكننا التعامل مع الأخطاء بأناقة باستخدام نظام begin/rescue/end في روبي.

ما هو الخطأ (Exception)؟

الخطأ هو حدث غير متوقع يقطع التنفيذ الطبيعي للبرنامج:

بدون معالجة الأخطاء:

  • البرنامج يتوقف فوراً
  • المستخدم يرى رسالة خطأ تقنية
  • البيانات قد تضيع

البنية الأساسية: begin/rescue/end

مثال عملي: القسمة الآمنة

بدون معالجة: البرنامج ينهار عند القسمة على صفر مع المعالجة: يعرض رسالة ودية ويستمر


التقاط نوع محدد من الأخطاء

يمكننا تحديد نوع الخطأ الذي نريد التقاطه:

أنواع الأخطاء الشائعة

نوع الخطأمتى يحدثمثال
ZeroDivisionErrorالقسمة على صفر10 / 0
NoMethodErrorاستدعاء دالة غير موجودةnil.upcase
NameErrorمتغير غير معرفputs unknown
TypeErrorنوع بيانات خاطئ"hello" + 5
ArgumentErrorعدد أو نوع المعاملات خاطئ[1,2].first(1, 2)
RuntimeErrorخطأ عام أثناء التشغيلraise "خطأ!"

التقاط أنواع متعددة

التقاط عدة أنواع معاً


الوصول لمعلومات الخطأ

استخدم => e للحصول على كائن الخطأ:

مثال مفصل


إلقاء الأخطاء باستخدام raise

يمكننا إلقاء (إنشاء) أخطاء خاصة بنا:

raise بسيط

raise مع نوع محدد

إنشاء أنواع أخطاء مخصصة


ensure: شيفرة تُنفذ دائماً

ensure يُنفذ سواء حدث خطأ أو لا - مفيد للتنظيف:

مثال: إدارة الموارد


else: عند نجاح الشيفرة

else يُنفذ فقط إذا لم يحدث خطأ:

البنية الكاملة


retry: إعادة المحاولة

retry يعيد تنفيذ الشيفرة من بداية begin:

تحذير: احذر من الحلقات اللانهائية! دائماً حدد عدد المحاولات.


مثال عملي شامل: حاسبة آمنة


جدول ملخص

الكلمةالوظيفةمتى يُنفذ
beginبداية الشيفرة المحميدائماً
rescueمعالجة الخطأعند حدوث خطأ
elseشيفرة النجاحعند عدم حدوث خطأ
ensureشيفرة التنظيفدائماً (بعد rescue أو else)
raiseإلقاء خطأعند استدعائه
retryإعادة المحاولةعند استدعائه في rescue

أفضل الممارسات

1. التقط أخطاء محددة

2. لا تبتلع الأخطاء

3. استخدم ensure للتنظيف


أخطاء شائعة

1. نسيان حد retry

2. rescue واسع جداً

3. raise بدون معلومات


ملخص

المفهومالوصف
begin/rescue/endالبنية الأساسية لمعالجة الأخطاء
rescue ErrorTypeالتقاط نوع محدد من الأخطاء
rescue => eالوصول لكائن الخطأ
raiseإلقاء خطأ جديد
ensureشيفرة تُنفذ دائماً للتنظيف
elseشيفرة تُنفذ عند النجاح فقط
retryإعادة المحاولة (بحذر!)

تمرين: القسمة الآمنة

حان وقت التطبيق! في محرر الشيفرة على اليسار:

المطلوب:

  1. اكتب دالة safe_divide(a, b) تقوم بـ:

    • محاولة قسمة a على b
    • إذا كان b صفراً، تطبع رسالة خطأ وترجع nil
    • إذا نجحت العملية، ترجع الناتج
  2. اختبر الدالة بالقيم:

    • safe_divide(10, 2) - يجب أن يطبع الناتج 5
    • safe_divide(10, 0) - يجب أن يطبع رسالة خطأ

الناتج المتوقع:

تلميحات:

  • استخدم begin/rescue/end داخل الدالة
  • استخدم rescue ZeroDivisionError لالتقاط خطأ القسمة على صفر
  • اطبع "الناتج: #{result}" عند النجاح
  • اطبع "خطأ: لا يمكن القسمة على صفر!" عند الفشل

تذكّر: معالجة الأخطاء تجعل برامجك أكثر متانة وودية للمستخدم. استخدم begin/rescue/end للتعامل مع الحالات غير المتوقعة، وraise لإلقاء أخطاء ذات معنى، وensure لضمان تنظيف الموارد. في الدرس القادم سنبدأ التحديات البرمجية لتطبيق كل ما تعلمناه!