الكود الخاص بي كان هرمًا: كيف أنقذتني ‘شروط الحماية’ (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% من الحالات، ستكون الإجابة “نعم”، وستشكر نفسك لاحقًا على هذا القرار.

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

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

أبو عمر

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

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

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

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

آخر المدونات

أدوات وانتاجية

كانت ذاكرتي هي عنق الزجاجة: كيف أنقذتني أدوات تدوين الملاحظات للمبرمجين (Obsidian) من جحيم البحث في Google؟

كمبرمج، كنت أعيش في حلقة مفرغة من البحث عن نفس المعلومات مرارًا وتكرارًا. في هذه المقالة، أشارككم قصتي وكيف ساعدتني أداة مثل Obsidian في بناء...

15 مايو، 2026 قراءة المزيد
نصائح برمجية

كانت حالتنا تتغير عشوائياً: كيف أنقذتنا ‘اللامتغيرية’ (Immutability) من جحيم الآثار الجانبية؟

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

15 مايو، 2026 قراءة المزيد
ذكاء اصطناعي

كان بحثنا غبياً: كيف أنقذتنا ‘قواعد بيانات المتجهات’ من جحيم البحث بالكلمات المفتاحية؟

أشارككم قصة حقيقية عن مشروع كاد أن يفشل بسبب محدودية البحث التقليدي، وكيف كانت قواعد بيانات المتجهات (Vector Databases) والبحث الدلالي هي طوق النجاة. مقالة...

15 مايو، 2026 قراءة المزيد
خوارزميات

كانت قاعدة بياناتنا تنهار: كيف أنقذنا ‘مرشح بلوم’ (Bloom Filter) من جحيم الاستعلامات؟

أشارككم قصة حقيقية عن كيفية انهيار قاعدة بياناتنا تحت ضغط استعلامات "هل هذا العنصر موجود؟". اكتشفوا معنا خوارزمية 'مرشح بلوم' الساحرة التي أنقذتنا، وكيف يمكنها...

15 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

كانت واجهاتنا خليطاً عشوائياً: كيف أنقذنا ‘نظام التصميم’ (Design System) من جحيم الفوضى البصرية؟

أسرد لكم قصتي كـ "أبو عمر"، مطور برمجيات فلسطيني، وكيف واجهنا فوضى بصرية عارمة في مشاريعنا. اكتشفوا معنا كيف كان "نظام التصميم" (Design System) هو...

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

كانت بياناتنا تتلف في سباق محموم: كيف أنقذتنا ‘مستويات عزل المعاملات’ من جحيم القراءات الشبحية؟

أروي لكم يا جماعة قصة حقيقية من قلب المعركة البرمجية، يوم كادت القراءات الشبحية (Phantom Reads) أن تدمر مشروعنا. في هذه المقالة، أغوص معكم في...

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