الكود الخاص بي كان هرمًا: كيف أنقذتني ‘شروط الحماية’ (Guard Clauses) من جحيم الكود السهمي؟

يا جماعة الخير، السلام عليكم. معكم أخوكم أبو عمر.

قبل كم يوم، كنت براجع كود كتبه مبرمج جديد في الفريق. فتحت الملف، وإذ بي أرى دالة (function) طويلة، شكلها غريب. كل سطر يدخل لجوا أكثر من اللي قبله، كأنها رأس سهم متجه لليمين أو هرم مقلوب على جنبه. تنهدت وقلت في نفسي: “يا ساتر! رجعنا لهي القصة”.

هذا المشهد أعادني سنوات للوراء، لأول مشروع كبير اشتغلت عليه. كنت متحمسًا جدًا، وكتبت كودًا يفعل العجائب، لكن… كان بنفس هذا الشكل الهرمي. أتذكر ليلة قضيتها أحاول إصلاح خطأ بسيط في هذا الكود؛ كنت كلما دخلت في شرط if، أضيع أكثر. شعرت كأنني في متاهة لا نهاية لها. يومها، قررت أن هذا الأسلوب في الكتابة، والذي أسميه “الكود السهمي” أو “هرم الجحيم”، يجب أن ينتهي. ومن هنا بدأت رحلتي مع مفهوم بسيط لكنه ثوري: شروط الحماية (Guard Clauses).

في هذه المقالة، سآخذكم معي في هذه الرحلة، لنرى كيف يمكننا التخلص من هذه الأهرامات البرمجية ونكتب كودًا نظيفًا، مرتبًا، ومريحًا للعين والعقل.

ما هو “الكود السهمي” أو “هرم الشروط”؟

ببساطة، “الكود السهمي” (Arrow Code) هو نتيجة استخدام جمل if متداخلة بكثرة. كل شرط جديد يضيف مسافة بادئة (indentation) جديدة، مما يجعل الكود يتجه قطريًا عبر الشاشة، مثل رأس السهم. هذا الأسلوب، وإن كان يعمل من الناحية التقنية، إلا أنه كارثة من ناحية جودة الكود.

مثال على الكود السهمي (Pyramid of Doom)

تخيل أنك تكتب دالة لمعالجة طلب شراء في متجر إلكتروني. قبل معالجة الطلب، عليك التحقق من عدة أمور: هل المستخدم موجود؟ هل هو نشط؟ هل الطلب موجود؟ هل حالة الطلب تسمح بالمعالجة؟ إلخ. بالطريقة التقليدية، قد يبدو الكود هكذا (سأستخدم لغة تشبه Python للتوضيح):


def process_order(user, order):
    # المستوى الأول من التداخل
    if user is not None:
        # المستوى الثاني
        if user.is_active:
            # المستوى الثالث
            if order is not None:
                # المستوى الرابع
                if order.status == "pending":
                    # المستوى الخامس!
                    if len(order.items) > 0:
                        # --- المنطق الأساسي للدالة مدفون هنا ---
                        print("جاري معالجة الطلب...")
                        # ... كود معالجة الطلب الفعلي ...
                        return "تمت المعالجة بنجاح"
                    else:
                        print("خطأ: الطلب فارغ.")
                        return None
                else:
                    print("خطأ: حالة الطلب ليست 'معلقة'.")
                    return None
            else:
                print("خطأ: الطلب غير موجود.")
                return None
        else:
            print("خطأ: المستخدم غير نشط.")
            return None
    else:
        print("خطأ: المستخدم غير موجود.")
        return None

شو هاد يا عمي؟ انظر إلى هذا الهرم! المنطق الأساسي للدالة، وهو أهم جزء، مدفون في أعماق 5 مستويات من التداخل. هذا الكود يعاني من عدة مشاكل:

  • صعوبة القراءة: تحتاج إلى تتبع كل الشروط في عقلك لتفهم متى سيتم تنفيذ المنطق الأساسي.
  • صعوبة الصيانة: ماذا لو أردت إضافة شرط جديد؟ ستحتاج إلى إضافة مستوى آخر من التداخل، مما يزيد الطين بلة.
  • صعوبة تصحيح الأخطاء (Debugging): إذا رجعت الدالة None، عليك تتبع كل مسارات else لتعرف أين حدثت المشكلة بالزبط.
  • الحمل المعرفي العالي (High Cognitive Load): يتطلب فهم هذا الكود جهدًا ذهنيًا كبيرًا، وهو آخر شيء نريده كمبرمجين.

المنقذ: شروط الحماية (Guard Clauses)

شروط الحماية هي تقنية بسيطة جدًا تعتمد على مبدأ “اخرج مبكرًا” (Exit Early). بدلًا من تداخل الشروط للوصول إلى “المسار السعيد” (Happy Path) – أي المسار الذي يتم فيه تنفيذ المنطق الرئيسي – نقوم بعكس المنطق.

الفكرة هي أن تتحقق من كل الشروط “السيئة” أو الحالات الاستثنائية في بداية الدالة. إذا تحقق أي من هذه الشروط، أوقف التنفيذ فورًا وأرجع خطأ أو قيمة مناسبة. بهذا، أنت “تحمي” باقي الكود من التنفيذ في ظروف غير صالحة.

نفس المثال بعد استخدام شروط الحماية

دعونا نعيد كتابة الدالة السابقة باستخدام هذا المفهوم السحري. انظر كيف سيصبح الكود مسطحًا وواضحًا:


def process_order_clean(user, order):
    # شرط الحماية الأول: التحقق من المستخدم
    if user is None:
        print("خطأ: المستخدم غير موجود.")
        return None

    # شرط الحماية الثاني: التحقق من نشاط المستخدم
    if not user.is_active:
        print("خطأ: المستخدم غير نشط.")
        return None

    # شرط الحماية الثالث: التحقق من الطلب
    if order is None:
        print("خطأ: الطلب غير موجود.")
        return None

    # شرط الحماية الرابع: التحقق من حالة الطلب
    if order.status != "pending":
        print("خطأ: حالة الطلب ليست 'معلقة'.")
        return None

    # شرط الحماية الخامس: التحقق من وجود منتجات
    if len(order.items) == 0:
        print("خطأ: الطلب فارغ.")
        return None

    # --- المسار السعيد (Happy Path) ---
    # المنطق الأساسي واضح ومكشوف وبدون أي تداخل
    print("جاري معالجة الطلب...")
    # ... كود معالجة الطلب الفعلي ...
    return "تمت المعالجة بنجاح"

فرق شاسع، أليس كذلك؟ الكود الآن يقرأ مثل قائمة تحقق (checklist). كل شرط يفشل يخرجك من الدالة فورًا. أما إذا نجحت كل الشروط، فإنك تصل إلى المنطق الأساسي في نهاية الدالة، وهو الآن واضح تمامًا وموجود على المستوى الأول من الكود، بدون أي مسافات بادئة غير ضرورية.

نصائح أبو عمر الذهبية لاستخدام شروط الحماية

من خبرتي، هذه التقنية أكثر من مجرد ترتيب للكود. إنها طريقة تفكير تساعدك على بناء برمجيات أقوى وأكثر متانة. إليكم بعض النصائح العملية:

1. افشل بسرعة، وافشل بوضوح (Fail Fast, Fail Loud)

مبدأ شروط الحماية هو اكتشاف المشكلة في أسرع وقت ممكن. بدلًا من إرجاع null أو قيمة غامضة، فكر في إطلاق استثناء (Throwing an Exception) مع رسالة واضحة. هذا يجعل تصحيح الأخطاء أسهل بكثير لأن البرنامج سيتوقف عند نقطة الخطأ بالضبط مع شرح للمشكلة.

مثال: بدلًا من return "خطأ: المستخدم غير موجود"، يمكنك استخدام throw new InvalidArgumentException("المستخدم لا يمكن أن يكون فارغًا"). هذا يمنع الكود الذي استدعى دالتك من الاستمرار ببيانات خاطئة.

2. حافظ على بساطة الشروط

يجب أن يكون شرط الحماية بسيطًا وواضحًا، يتحقق من شيء واحد فقط. إذا كان شرط التحقق نفسه معقدًا (مثلاً: if (user.hasPermission('edit') && !user.isBlocked() && user.lastLogin > 30_days_ago))، فمن الأفضل استخلاص هذا المنطق في دالة منفصلة لها اسم معبر.


# قبل: شرط معقد
if not (user.hasPermission('edit') and not user.isBlocked()):
    return "Error: Permission denied"

# بعد: شرط بسيط باستخدام دالة مساعدة
def can_user_edit(user):
    return user.hasPermission('edit') and not user.isBlocked()

if not can_user_edit(user):
    return "Error: Permission denied"

هذا يجعل الكود يقرأ كأنه جملة إنجليزية (أو عربية!).

3. ركز على “المسار السعيد”

الهدف النهائي هو جعل المنطق الأساسي لدالتك (المسار السعيد) هو بطل المشهد. بعد أن تزيل كل الحالات الشاذة في البداية، يجب أن يكون ما تبقى من الكود هو صلب الموضوع، واضحًا ومباشرًا. هذا يسهل على أي مبرمج آخر (أو أنت في المستقبل) فهم الغرض الرئيسي للدالة من أول نظرة.

4. لا تخف من تعدد نقاط الخروج (Multiple Return Statements)

بعض المدارس القديمة في البرمجة كانت تصر على أن الدالة يجب أن يكون لها نقطة خروج واحدة فقط (return واحدة في النهاية). هذه القاعدة لا تنطبق بقوة في البرمجة الحديثة، خاصة مع وجود شروط الحماية. تعدد نقاط الخروج المبكرة يجعل الكود أنظف وأكثر قابلية للقراءة. لا تتردد في استخدام return كلما احتجت للخروج مبكرًا.

الخلاصة: من كود معكرونة إلى طبق لازانيا مرتب 🍝➡️ lasagna 😋

الكود السهمي أو هرم الشروط يشبه طبق معكرونة (سباغيتي) معقد ومتشابك، يصعب معرفة بدايته من نهايته. أما الكود الذي يستخدم شروط الحماية، فهو أشبه بطبق لازانيا شهي ومرتب، كل طبقة فيه واضحة ومستقلة، مما يسهل التعامل معه وتذوقه (أو قراءته!).

في المرة القادمة التي تجد فيها نفسك تكتب if داخل if، توقف لحظة. اسأل نفسك: “هل يمكنني عكس هذا الشرط واستخدام شرط حماية للخروج مبكرًا؟”. في 99% من الحالات، ستكون الإجابة “نعم”، وستشكر نفسك لاحقًا على هذا القرار.

تبني هذه العادة البسيطة سيغير طريقة كتابتك للكود إلى الأبد، وسيجعل زملاءك في الفريق يحبون مراجعة الكود الذي تكتبه. تذكر دائمًا: الكود النظيف ليس رفاهية، بل هو ضرورة لبناء برمجيات قوية ومستدامة. 🚀

ودمتم سالمين يا جماعة.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

برمجة وقواعد بيانات

تحديثات قاعدة البيانات بدون توقف: كيف أنقذنا نمط التوسيع والتعاقد (Expand/Contract) من جحيم التوقفات المجدولة؟

هل سئمت من إيقاف الخدمة مع كل تحديث لهيكلة قاعدة البيانات؟ أشارككم قصة حقيقية وكيف أنقذنا نمط التوسيع والتعاقد (Expand/Contract) من ليالي النشر الطويلة والمُجهدة،...

4 يونيو، 2026 قراءة المزيد
الشبكات والـ APIs

كانت إعادة المحاولة كارثة: كيف أنقذتنا مفاتيح عدم تكرار العمليات (Idempotency Keys) من جحيم الفواتير المزدوجة؟

أشارككم قصة حقيقية من الخنادق البرمجية، يوم كاد خطأ بسيط في إعادة محاولة طلبات الدفع أن يكلفنا سمعتنا وأموال عملائنا. اكتشفوا معنا كيف كانت مفاتيح...

4 يونيو، 2026 قراءة المزيد
الحوسبة السحابية

من التوقف التام إلى النجاة: كيف أنقذتنا استراتيجية “الضوء المرشد” (Pilot Light) يوم انقطعت السحابة؟

أتذكر ذلك اليوم جيدًا، فنجان القهوة الصباحي، وصوت تنبيهات المراقبة يصرخ كأنه يوم القيامة. كانت منطقة سحابية كاملة قد توقفت عن العمل، لكن بفضل استراتيجية...

4 يونيو، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

كانت مهمتي البرمجية للاختبار مجرد كود: كيف أنقذني توثيق القرارات من جحيم الصمت بعد المقابلة؟

أشارككم قصة حقيقية من بداياتي، وكيف تعلمت بالطريقة الصعبة أن المهمة البرمجية ليست مجرد كتابة كود، بل هي فرصة لإظهار طريقة تفكيرك. اكتشف كيف يمكن...

4 يونيو، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

من الانتظار لأيام إلى الدفع في ثوانٍ: كيف أنقذتنا شبكات الدفع الفوري من جحيم التحويلات البنكية؟

أسرد لكم من واقع تجربتي كـ "أبو عمر"، كيف عانينا من بطء وتكلفة التحويلات البنكية الدولية، وكيف جاءت شبكات الدفع الفوري ومعيار ISO 20022 لتكون...

4 يونيو، 2026 قراءة المزيد
البنية التحتية وإدارة السيرفرات

كان كل خادم لدينا ‘ندفة ثلج’ فريدة: كيف أنقذنا ‘الكود كبنية تحتية’ (IaC) من جحيم الانجراف اليدوي؟

في هذه المقالة، أشارككم قصة حقيقية من قلب المعركة التقنية مع "خوادم ندفات الثلج" الفوضوية. سنغوص في مفهوم "الكود كبنية تحتية" (IaC) وكيف أن أدوات...

4 يونيو، 2026 قراءة المزيد
اختبارات الاداء والجودة

كانت تغطية الاختبارات 100% لكن الأخطاء تتسرب: كيف أنقذنا “الاختبار الطفري” من جحيم الثقة الزائفة؟

كنا نظن أن تغطية الاختبار بنسبة 100% هي درعنا الواقي، لكن الأخطاء كانت تتسلل إلى الإنتاج كاللصوص في ليل بهيم. اكتشف كيف أنقذنا "الاختبار الطفري"...

4 يونيو، 2026 قراءة المزيد
البودكاست