يا جماعة الخير، السلام عليكم ورحمة الله. معكم أخوكم أبو عمر من قلب فلسطين، واليوم بدي أحكيلكم قصة صارت معي قبل كم سنة، قصة عن المعاناة البرمجية والفرج اللي بيجي بعدها.
كنا شغالين على نظام تحليل بيانات ضخم لواحد من المشاريع الكبيرة. كان في دالة (Function) معينة هي قلب النظام، وظيفتها تاخد بيانات مستخدم معقدة وتتحقق من صلاحيتها قبل ما تمررها لنظام الذكاء الاصطناعي تبعنا. المشكلة؟ الدالة هاي كانت مكتوبة من فترة طويلة، وكل ما يجي مطور جديد يضيف شرط جديد… “وإذا كان المستخدم فعال”، “وإذا كان عنده اشتراك”، “وإذا كان نوع الاشتراك يسمح”، “وإذا كانت بياناته مكتملة”… وهكذا.
في يوم من الأيام، ضرب النظام كله بسبب خطأ بسيط في هاي الدالة. قعدنا أنا وفريق صغير من الشباب نتبع الكود. والله يا جماعة، كانت الدالة عبارة عن وحش، هرم مقلوب من جمل if-else المتداخلة. كود داخل كود داخل كود. عيونا زاغت وإحنا بنحاول نفهم مين بيروح وين، وإيش الشرط اللي فشل. ضيعنا يوم كامل تقريباً بس عشان نلاقي السطر المسؤول عن المشكلة. وقتها ضربت الطاولة (بشويش طبعاً) وقلت: “خلص! لهون وبس! هاد الشغل مش شغل مرتب ولا بجيب نتيجة. لازم نعيد كتابة هاي المتاهة”. ومن هنا بدأت رحلة إنقاذ الكود باستخدام بطل قصتنا اليوم: عبارات الحماية.
ما هو “هرم الجحيم المقلوب” (The Pyramid of Doom)؟
قبل ما نحكي عن الحل، خلينا نوصف المشكلة بوضوح. “هرم الجحيم” أو “هرم الموت المقلوب” هو اسم دلع (مش لطيف أبداً) بنطلقه على الكود اللي بيكثر فيه تداخل الشروط (Nested Ifs). كل شرط جديد بتضيفه بيزيد المسافة البادئة (Indentation) لليمين، وبعد كم شرط، بصير شكل الكود زي الهرم المقلوب. بتوه الواحد وهو بقرأه.
خلينا نشوف مثال بسيط بلغة Python عشان تتوضح الصورة. تخيل دالة بتعالج طلب شراء منتج:
def process_order(user, product, quantity):
if user is not None:
if user.is_logged_in:
if product is not None:
if product.is_in_stock(quantity):
if user.has_sufficient_funds(product.price * quantity):
# ------------------------------------
# هنا فقط يبدأ منطق العمل الحقيقي!
# The "Happy Path" is buried deep inside
# ------------------------------------
print("بدء معالجة الطلب...")
# ... كود معالجة الطلب
return "تم الطلب بنجاح"
else:
return "خطأ: الرصيد غير كافٍ"
else:
return "خطأ: الكمية غير متوفرة في المخزون"
else:
return "خطأ: المنتج غير موجود"
else:
return "خطأ: يجب تسجيل الدخول أولاً"
else:
return "خطأ: المستخدم غير معروف"
شايفين المأساة؟ المنطق الأساسي للدالة مدفون في 5 مستويات من التداخل! قراءة هذا الكود صعبة، وتصحيح الأخطاء فيه أصعب، وإضافة شرط جديد هو كابوس بحد ذاته.
المنقذ البسيط: عبارات الحماية (Guard Clauses)
عبارات الحماية، أو زي ما بحب أسميها “حراس البوابة”، هي تقنية بسيطة جداً لكنها فعالة بشكل لا يصدق. الفكرة الأساسية هي: “افشل بسرعة، واخرج مبكراً” (Fail fast, exit early).
بدلاً من تداخل الشروط الإيجابية، نقوم بعكس المنطق. في بداية الدالة، نتحقق من كل الحالات التي تمنع استمرار التنفيذ (الحالات السلبية أو “Unhappy Paths”). إذا تحقق أي من هذه الشروط، نوقف التنفيذ فوراً ونرجع بنتيجة (سواء كانت خطأ، أو قيمة افتراضية، أو Exception).
إعادة هيكلة المثال السابق باستخدام عبارات الحماية
شوفوا كيف نفس الدالة السابقة بتصير “أرتب وأوضح” لما نستخدم حراس البوابة:
def process_order_refactored(user, product, quantity):
# Guard Clause 1: التحقق من المستخدم
if user is None:
return "خطأ: المستخدم غير معروف"
# Guard Clause 2: التحقق من تسجيل الدخول
if not user.is_logged_in:
return "خطأ: يجب تسجيل الدخول أولاً"
# Guard Clause 3: التحقق من المنتج
if product is None:
return "خطأ: المنتج غير موجود"
# Guard Clause 4: التحقق من المخزون
if not product.is_in_stock(quantity):
return "خطأ: الكمية غير متوفرة في المخزون"
# Guard Clause 5: التحقق من الرصيد
if not user.has_sufficient_funds(product.price * quantity):
return "خطأ: الرصيد غير كافٍ"
# ------------------------------------
# المسار السعيد (The Happy Path) - واضح ومباشر
# ------------------------------------
print("بدء معالجة الطلب...")
# ... كود معالجة الطلب
return "تم الطلب بنجاح"
فرق شاسع، صح؟ الكود الآن يقرأ كقائمة من المتطلبات الأولية. إذا لم يتم استيفاء أي منها، نتوقف. إذا تم استيفاؤها جميعًا، فإن الجزء المتبقي من الدالة هو منطق العمل الرئيسي، “المسار السعيد”، واضح ومكشوف وبدون أي تداخل.
كيف ومتى نستخدم عبارات الحماية؟ (شغل عملي)
عبارات الحماية مفيدة جداً في عدة سيناريوهات، أهمها:
1. التحقق من المدخلات (Input Validation)
هذا هو الاستخدام الأكثر شيوعاً. قبل أن تبدأ دالتك بالعمل، تأكد من أن كل المدخلات التي تحتاجها موجودة وصحيحة. تحقق من القيم الفارغة (null أو None)، السلاسل النصية الفارغة، الأرقام خارج النطاق المسموح، إلخ.
2. التحقق من الصلاحيات (Permissions Check)
قبل تنفيذ أي عملية حساسة (مثل حذف سجل أو تعديل بيانات مستخدم آخر)، ضع عبارة حماية في البداية للتأكد من أن المستخدم الحالي يمتلك الصلاحيات اللازمة.
def delete_post(user, post_id):
if not user.is_admin():
raise PermissionError("ليس لديك صلاحية لحذف هذا المنشور")
# ... منطق الحذف هنا
3. التعامل مع الحالات الاستثنائية (Edge Cases)
أحياناً تكون هناك حالات خاصة جداً يجب التعامل معها قبل المنطق العام. عبارات الحماية ممتازة لعزل هذه الحالات والتعامل معها في البداية، مما يجعل بقية الكود أبسط.
نصائح من أبو عمر (من خبرتي المتواضعة)
“الكود النظيف مش رفاهية، هو ضرورة لاستمرارية المشروع وصحتك النفسية كمبرمج.” – أبو عمر
- لا تبالغ في الاستخدام: إذا كان عندك شرط واحد فقط له حالتان (مثل
if/elseبسيط)، فلا داعي لتعقيدها وتحويلها لعبارة حماية. هي تلمع حقاً عندما يكون لديك عدة شروط مسبقة. - اجعل رسائل الخطأ واضحة: عندما تخرج مبكراً من الدالة، تأكد من أن القيمة المُرجعة أو الخطأ الذي ترميه (throw exception) يصف المشكلة بوضوح. هذا يساعدك أنت وزملاءك في تصحيح الأخطاء لاحقاً.
- ركّز على “المسار السعيد”: هدفك هو أن تجعل منطق العمل الرئيسي (The Happy Path) مستقيماً وسهل القراءة قدر الإمكان. عبارات الحماية هي أداتك لتنظيف الطريق أمامه.
- إعادة الهيكلة فن وصبر: لا تخف من إعادة هيكلة الكود القديم. صحيح أنها قد تأخذ بعض الوقت، لكنها استثمار قيم جداً في المستقبل. كل دالة “هرمية” تقوم بتنظيفها هي انتصار لجودة الكود وسهولة الصيانة.
الخلاصة… والزبدة
يا جماعة، البرمجة مش بس كتابة كود شغال، البرمجة هي كتابة كود واضح، مفهوم، وقابل للصيانة. “هرم الجحيم المقلوب” هو عدو الوضوح، وعبارات الحماية هي سلاحنا الفعال ضده.
في المرة القادمة التي تجد فيها نفسك تكتب جملة if داخل جملة if أخرى، توقف للحظة واسأل نفسك: “هل يمكنني استخدام عبارة حماية هنا؟”. في معظم الأحيان، ستجد أن الجواب هو نعم، وأن كودك سيصبح أفضل بكثير.
يلا يا شباب، خلينا نكتب كود مرتب بنفتخر فيه. 👍