كودنا كان مليئاً بالأرقام الغامضة: كيف أنقذتنا ‘التعدادات’ (Enums) من جحيم الأرقام السحرية؟

يا جماعة الخير، السلام عليكم ورحمة الله.

بتذكر مرة، قبل كم سنة، كنا بنشتغل على نظام كبير لإدارة المستخدمين. كانت الساعة حوالي 2 بعد نص الليل، وأنا وفريق العمل بنحاول نلاقي سبب لخلل غريب بيظهر في الإنتاج (Production). المشكلة كانت إن بعض المستخدمين حالتهم بتتغير لـ “محظور” بدون أي سبب واضح. الأذونات (Permissions) سليمة، والlogs ما فيها إشي غريب، والكل صافن وبقول “شو القصة؟”.

بعد ساعات من البحث والتمحيص في الكود، وكمية قهوة ما إلها أول من آخر، واحد من الشباب صاح: “لقيتها!”. المشكلة كانت في سطر بسيط زي هاد:

if (user.status == 2) {
    // do something for blocked users
}

وفي مكان ثاني من الكود، مبرمج جديد (الله يسامحه) كان بده يضيف حالة جديدة للمستخدم “في انتظار التفعيل” (Pending Activation)، فكتب إشي زي هيك:

// Let's use '2' for pending, nobody is using it, right?
const PENDING_STATUS = 2;
// ...
if (someCondition) {
    user.status = PENDING_STATUS;
}

طبعاً هو ما كان بيعرف إنه الرقم 2 محجوز للحالة “محظور”. الكود اشتغل بدون أي خطأ برمجي (syntax error)، لكنه دمر المنطق تبع التطبيق. في هداك اليوم، أقسمنا إنه نعلن الحرب على ما يسمى بـ “الأرقام السحرية”. ومن هون بتبدأ قصتنا.

ما هي الأرقام السحرية (Magic Numbers)؟ ولماذا هي “جحيم” المبرمجين؟

ببساطة، الرقم السحري هو أي رقم بتستخدمه في الكود مباشرة (كقيمة حرفية – literal value) بدون ما يكون إله اسم أو معنى واضح. زي الرقم 2 في مثالنا السابق، أو الرقم 86400 اللي ممكن تلاقيه في كود لحساب عدد الثواني في اليوم.

طيب ليش هي سيئة لهالدرجة؟ ليش وصفتها بـ “الجحيم”؟

  • صعوبة القراءة والفهم: لما ترجع تقرأ كودك بعد 6 شهور، أو لما يجي مبرمج جديد على الفريق، سطر مثل if (order.status == 5) ما إله أي معنى. شو يعني 5؟ هل هو “تم الشحن”؟ “تم الإلغاء”؟ “قيد المراجعة”؟ بتحتاج ترجع للتوثيق (إذا كان موجود أصلاً) أو تسأل اللي كتب الكود عشان تفهم.
  • صعوبة الصيانة والتعديل: تخيل لو قررنا نغير قيمة حالة “محظور” من 2 إلى 10. رح تضطر تعمل بحث واستبدال (Find & Replace) لكل الرقم 2 في المشروع. وهون المصيبة الكبيرة: ماذا لو كان الرقم 2 مستخدم في مكان ثاني بمعنى مختلف تماماً (مثلاً، الحد الأقصى لعدد محاولات تسجيل الدخول)؟ رح تدمر أجزاء من النظام بدون ما تعرف.
  • مصدر للأخطاء الصامتة: من السهل جداً تغلط وتكتب 3 بدل 2. المترجم (Compiler) ما رح يشتكي، لأنه من ناحيته الأرقام أرقام. بس منطق البرنامج عندك رح ينضرب، ورح تقضي ساعات تدور على خطأ منطقي سببه خطأ طباعة بسيط.

البديل الأولي: الثوابت (Constants)… خطوة في الاتجاه الصحيح

أول حل بيخطر على بال أي مبرمج شاطر هو استخدام الثوابت (Constants). بدل ما نكتب الرقم مباشرة، بنعطيه اسم معبر وبنستخدم الاسم هاد في كل الكود. هاد كان أول إشي عملناه بعد ليلة الكارثة.

الكود تبعنا تحول من هيك:

if (user.status == 2) { ... }

لهيك (مثال بلغة JavaScript):

const USER_STATUS_ACTIVE = 1;
const USER_STATUS_BLOCKED = 2;
const USER_STATUS_PENDING = 3;

if (user.status == USER_STATUS_BLOCKED) { ... }

هاد الحل أفضل بمليون مرة! صار الكود مقروء، وصارت الصيانة أسهل. لو بدنا نغير قيمة “محظور”، بنغيرها في مكان واحد فقط. خطوة ممتازة للأمام، لكنها مش الحل النهائي. ليش؟

الثوابت بتحل مشكلة “المعنى”، لكنها ما بتحل مشكلة “النوع” و”التجميع”.

الثوابت USER_STATUS_ACTIVE و MAX_LOGIN_ATTEMPTS ما في إشي بيربطهم ببعض. هم مجرد متغيرات عالمية (global constants). ما في طريقة تضمن إنه الدالة اللي بتستقبل “حالة المستخدم” ما يوصلها بالغلط ثابت ثاني قيمته رقمية. ما زلنا بنتعامل مع أرقام عادية.

الحل السحري الحقيقي: التعدادات (Enums) – المنقذ!

وهون بيجي دور البطل الحقيقي في قصتنا: التعدادات (Enumerations أو Enums). الـ Enum هو نوع بيانات خاص بيسمحلك تعرف مجموعة من الثوابت المترابطة تحت اسم واحد. هو مش مجرد مجموعة أسماء، هو “نوع” بحد ذاته.

خلينا نشوف كيف الـ Enum بحل المشكلة بشكل نهائي.

مثال بلغة TypeScript

في TypeScript، تعريف الـ Enum سهل ومباشر:

enum UserStatus {
  Active,    // القيمة الافتراضية 0
  Pending,   // القيمة الافتراضية 1
  Blocked,   // القيمة الافتراضية 2
  Deleted    // القيمة الافتراضية 3
}

// الآن يمكننا تعريف متغير من هذا النوع
let currentUserStatus: UserStatus = UserStatus.Blocked;

// والكود يصبح مقروء وآمن
if (currentUserStatus === UserStatus.Blocked) {
  console.log("هذا المستخدم محظور يا خال!");
}

لاحظ الجمال هون. المتغير currentUserStatus نوعه UserStatus، مش مجرد number. هاد بيعني إنه ما بنقدر نعطيه أي قيمة خارج القيم المعرفة في الـ Enum. لو حاولت تكتب currentUserStatus = 5، المحرر (IDE) والمترجم (Compiler) رح يعترضوا فوراً! هاد اسمه الأمان النوعي (Type Safety).

مثال بلغة Python

نفس المبدأ موجود في بايثون والعديد من اللغات الأخرى:

from enum import Enum

class UserStatus(Enum):
    ACTIVE = 1
    PENDING = 2
    BLOCKED = 3
    DELETED = 4

user_status = UserStatus.ACTIVE

if user_status == UserStatus.BLOCKED:
    print("هذا المستخدم محظور.")
# لو حاولت تعمل هيك، رح تحصل على خطأ
# user_status = 5 # This is not a UserStatus!

لماذا تتفوق التعدادات (Enums) على كل ما سبق؟

  • مقروئية فائقة (Expressiveness): الكود صار يوثق نفسه بنفسه. UserStatus.Blocked أوضح من أي تعليق ممكن تكتبه.
  • أمان نوعي (Type Safety): هاد هو الفرق الجوهري. الـ Enums بتخلق نوع بيانات جديد، وهالشي بيمنع فئة كاملة من الأخطاء المنطقية قبل ما الكود يشتغل أصلاً. بتجبر المبرمج يستخدم القيم الصحيحة فقط.
  • مركزية وسهولة صيانة: كل الحالات المتعلقة ببعضها موجودة في مكان واحد. بدك تضيف حالة جديدة؟ بتضيفها للـ Enum والمحرر تبعك رح يساعدك تلاقي كل الأماكن اللي لازم تعدل فيها المنطق (زي جمل switch).
  • دعم من بيئات التطوير (IDE Support): لما تكتب UserStatus.، المحرر رح يقترح عليك كل الخيارات المتاحة (Active, Pending, etc.). هاد بيقلل الأخطاء الطباعية وبسرّع عملية البرمجة.

نصائح من الكيس: كيف تستخدم الـ Enums كالمحترفين

من خبرتي على مدار السنين، هاي شوية نصائح عملية عشان تستفيد من الـ Enums لأقصى درجة:

  1. حدد القيم بشكل صريح: لا تعتمد دائماً على القيم الافتراضية (0, 1, 2…). إذا كانت هاي القيم رح تتخزن في قاعدة بيانات أو رح يتم إرسالها عبر API، الأفضل دائماً تحددها بشكل صريح: enum UserStatus { Active = 1, Pending = 2, Blocked = 3 }. هيك لو واحد غير ترتيبهم في المستقبل، الكود ما بينضرب.
  2. الـ Enums مش بس للأرقام: في لغات زي TypeScript و Java، ممكن تستخدم نصوص (strings) كقيم للـ Enum. هاد إشي خرافي عند التعامل مع APIs أو لما بدك تطبع القيمة لأغراض تصحيح الأخطاء (debugging).
    enum Direction {
      Up = "UP",
      Down = "DOWN",
      Left = "LEFT",
      Right = "RIGHT",
    }
  3. استخدمها للحالات الثابتة والمحدودة: الـ Enums مثالية لتمثيل أي مجموعة محدودة من الخيارات: أدوار المستخدمين (Admin, Editor, Viewer)، حالات الطلب (Processing, Shipped, Delivered)، أنواع العمليات (Credit, Debit)، أيام الأسبوع، وهكذا. لا تستخدمها لشيء ممكن يتغير بشكل ديناميكي.
  4. تعامل مع كل الحالات: لما تستخدم جملة switch مع Enum، حاول دائماً تغطي كل الحالات الممكنة، وأضف حالة default للتعامل مع أي إضافات مستقبلية على الـ Enum بشكل آمن، حتى لو كانت مجرد طباعة رسالة تحذير.

الخلاصة: ودّع الأرقام السحرية إلى الأبد 🪄

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

يا جماعة، الكود النظيف مش رفاهية، هو استثمار في مستقبلكم ومستقبل فريقكم. ابدأوا اليوم، افتحوا مشاريعكم القديمة، ابحثوا عن تلك الأرقام الغامضة التي لا معنى لها، واستبدلوها بـ Enums واضحة ومعبرة. يمكن الشغلة تاخد شوية وقت في البداية، بس صدقوني، رح تدعولي بالآخر. 😉

بالتوفيق في رحلتكم البرمجية!

أبو عمر

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

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

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

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

آخر المدونات

ذكاء اصطناعي

نماذجنا كانت تفقد دقتها مع الوقت: كيف أنقذنا ‘رصد انحراف المفهوم’ من جحيم التنبؤات الفاشلة؟

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

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

كنا نكتب كل صفحة هبوط يدوياً: كيف أنقذنا ‘التحسين البرمجي لمحركات البحث’ (Programmatic SEO) من جحيم المحتوى المحدود؟

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

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

موقعنا كان حصناً منيعاً أمام ذوي الإعاقة: كيف أنقذتنا ‘إرشادات الوصول إلى محتوى الويب’ (WCAG) من جحيم الاستبعاد الرقمي؟

أنا أبو عمر، مبرمج فلسطيني. كنت أظن أن موقعنا تحفة فنية، حتى جاءتني رسالة من صديق كفيف قائلاً: "موقعك جميل، لكنني لا أرى منه شيئاً"....

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

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

وداعاً ليالي الصيانة الطويلة والمستخدمين الغاضبين! في هذه المقالة، أشارككم قصة حقيقية وكيف غيرت استراتيجيات 'الهجرات بدون توقف' (Zero-Downtime Migrations) طريقة عملنا، مع دليل عملي...

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

فاتورة السحابة كانت لغزاً: كيف أنقذتنا ‘عمليات الإدارة المالية’ (FinOps) من جحيم الإنفاق غير المتوقع؟

أشارككم قصة حقيقية من قلب المعركة مع فواتير الحوسبة السحابية التي كادت أن تغرق مشروعنا. اكتشفوا كيف كانت مبادئ FinOps طوق النجاة الذي حول الفوضى...

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