شيفرتي كانت حقل ألغام: كيف قضيت على ‘الأرقام السحرية’ الغامضة باستخدام الثوابت (Constants) والتعدادات (Enums)؟

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

قبل كم سنة، ورثت مشروع ضخم من مبرمج سابق ترك الشركة. كان نظام إدارة معقد، والحكي بينا، الشيفرة كانت عبارة عن طلاسم! أتذكر ذاك اليوم جيدًا، كان يوم خميس، وكنت أحاول إصلاح علّة (bug) مستعصية في نظام معالجة الطلبات. المشكلة كانت أن بعض الطلبات تدخل في حالة غريبة لا هي مُلغاة ولا هي مكتملة.

بعد ساعات من التنقيب في الكود، وصلت لسطر زي هيك:

if (order.status == 7) {
    // ... منطق معقد وغامض
}

وقفت صافنًا… “7”؟ شو يعني 7؟ يا زلمة، لا يوجد أي تعليق، ولا أي توثيق. قلّبت المشروع فوقاني تحتاني، وبحثت في قاعدة البيانات، وفتحت كل ملف خطر على بالي. بعد حوالي ثلاث ساعات من البحث المحموم، وجدتها! وجدتها مدفونة في تعليق قديم في ملف بعيد كل البعد عن منطق الطلبات، مكتوب أنه “الحالة 7 تعني ‘معلّق بانتظار موافقة المدير المالي'”.

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

ما هي “الأرقام السحرية”؟ ولماذا هي كابوس المبرمجين؟

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

دعونا نأخذ مثالاً بسيطًا لنظام إدارة مهام:

function getTaskStatus(status) {
    if (status === 0) {
        return "جديدة";
    } else if (status === 1) {
        return "قيد التنفيذ";
    } else if (status === 2) {
        return "مكتملة";
    } else if (status === -1) {
        return "ملغاة";
    }
}

// في مكان آخر من الكود
if (currentUser.task.status === 2) {
    console.log("أحسنت! لقد أنجزت المهمة.");
}

هذا الكود “يعمل”، لكنه حقل ألغام حقيقي. لماذا؟

  • صعوبة القراءة (Readability): عندما تقرأ if (status === 2)، أنت لا تعرف فورًا ماذا تعني “2”. هل هي مكتملة؟ هل هي مؤجلة؟ يجب عليك العودة للدالة getTaskStatus أو البحث في مكان آخر لفهم السياق.
  • صعوبة الصيانة (Maintainability): تخيل لو قررنا تغيير قيمة الحالة “مكتملة” من 2 إلى 5. سيتوجب عليك البحث في المشروع بأكمله عن كل الأماكن التي استخدم فيها الرقم 2 واستبدالها، مع المخاطرة بأنك قد تستبدل رقم 2 يُستخدم في سياق آخر تمامًا!
  • مصدر للأخطاء (Bugs): ما الذي يمنعك من أن تخطئ وتكتب if (status === 3) عن طريق السهو؟ الرقم 3 ليس له معنى هنا، والبرنامج لن يعطيك أي خطأ، ولكنه ببساطة لن يعمل كما هو متوقع.

السلاح الأول: الثوابت (Constants) – رصاصة الرحمة على الغموض

أول وأبسط حل لهذه المشكلة هو استخدام الثوابت. الثابت هو متغير نُعرّفه مرة واحدة ونعطيه اسمًا ذا معنى، ولا يمكن تغيير قيمته لاحقًا.

تطبيق عملي: لنُصلح شيفرة المهام

بدلاً من استخدام الأرقام مباشرة، سنقوم بتعريفها كثوابت في مكان مركزي واحد:

// في ملف إعدادات أو ملف خاص بالثوابت
const TASK_STATUS_NEW = 0;
const TASK_STATUS_IN_PROGRESS = 1;
const TASK_STATUS_COMPLETED = 2;
const TASK_STATUS_CANCELLED = -1;

// الآن، الكود يصبح أوضح بكثير
function getTaskStatus(status) {
    if (status === TASK_STATUS_NEW) {
        return "جديدة";
    } else if (status === TASK_STATUS_IN_PROGRESS) {
        return "قيد التنفيذ";
    } else if (status === TASK_STATUS_COMPLETED) {
        return "مكتملة";
    } else if (status === TASK_STATUS_CANCELLED) {
        return "ملغاة";
    }
}

// انظر إلى مدى وضوح هذا السطر الآن!
if (currentUser.task.status === TASK_STATUS_COMPLETED) {
    console.log("أحسنت! لقد أنجزت المهمة.");
}

الفارق شاسع! الآن الكود يتحدث عن نفسه. TASK_STATUS_COMPLETED لا تترك أي مجال للشك. وإذا احتجنا في المستقبل لتغيير قيمة الحالة المكتملة، نغيرها في مكان واحد فقط.

نصيحة من أبو عمر: اعتمد أسلوب تسمية واضح للثوابت، مثل استخدام الأحرف الكبيرة (UPPER_SNAKE_CASE). هذا يجعل من السهل تمييزها بصريًا عن المتغيرات العادية في الكود.

السلاح المتقدم: التعدادات (Enums) – تنظيم وتجميع الحالات

الثوابت حل ممتاز، ولكن عندما يكون لديك مجموعة من الحالات المترابطة (مثل حالات الطلب، أو أنواع المستخدمين، أو مستويات الصلاحية)، هناك أداة أفضل وأكثر تنظيمًا: التعدادات (Enumerations أو Enums).

الـ Enum هو نوع بيانات خاص يتيح لك تجميع مجموعة من الثوابت ذات الصلة تحت اسم واحد.

الارتقاء بالشيفرة باستخدام Enums

لنأخذ مثالنا السابق ونطوره باستخدام Enums (سأستخدم صيغة تشبه لغة TypeScript كمثال، ولكن المبدأ موجود في لغات كثيرة مثل C#, Java, Python, وغيرها).

enum TaskStatus {
    New = 0,
    InProgress = 1,
    Completed = 2,
    Cancelled = -1,
}

// الدالة أصبحت أكثر قوة وأمانًا
function getTaskStatus(status: TaskStatus): string {
    // يمكن استخدام switch statement هنا للتنظيم أكثر
    switch (status) {
        case TaskStatus.New:
            return "جديدة";
        case TaskStatus.InProgress:
            return "قيد التنفيذ";
        case TaskStatus.Completed:
            return "مكتملة";
        case TaskStatus.Cancelled:
            return "ملغاة";
        default:
            // التعامل مع الحالات غير المتوقعة
            throw new Error("حالة غير معروفة");
    }
}

// الكود في غاية الوضوح والأمان
if (currentUser.task.status === TaskStatus.Completed) {
    console.log("أحسنت! لقد أنجزت المهمة.");
}

// محاولة استخدام قيمة خاطئة ستسبب خطأ (في اللغات ذات الأنواع الصارمة)
// processTask(5); // هذا السطر سيُظهر خطأ وقت الترجمة!

لماذا الـ Enums أفضل في هذه الحالة؟

  • التجميع والتنظيم: كل الحالات المتعلقة بالمهام مجموعة تحت اسم واحد هو TaskStatus. هذا يجعل الكود أكثر تنظيمًا.
  • الأمان من الأخطاء (Type Safety): في اللغات التي تدعم أنواع البيانات بقوة (like TypeScript, C#)، لا يمكنك تمرير أي رقم عشوائي لدالة تتوقع TaskStatus. يجب أن تستخدم قيمة من الـ Enum نفسه (مثل TaskStatus.Completed)، وهذا يمنع فئة كاملة من الأخطاء المنطقية.
  • الإكمال التلقائي (Autocomplete): عند كتابة TaskStatus.، سيقترح عليك محرر الأكواد كل الخيارات المتاحة (New, InProgress, …)، مما يقلل من الأخطاء الكتابية ويسرّع عملية التطوير.

من دفتر أبو عمر: نصائح من القلب للشيفرة النظيفة

على مدار سنوات عملي، تعلمت بعض الدروس التي أحب أن أشاركها معكم:

  • لا تؤجل عمل اليوم إلى الغد: إذا رأيت رقمًا سحريًا أثناء كتابة الكود، لا تقل “سأعود إليه لاحقًا”. عرّفه كثابت أو ضمن Enum على الفور. هذا سيوفر عليك وعلى فريقك ساعات من الصداع في المستقبل.
  • فكّر في زميلك المستقبلي (الذي قد يكون أنت!): اكتب شيفرة يمكن فهمها بعد ستة أشهر من الآن. أنت المستقبلي هو شخص آخر، ذاكرته ليست مثالية، وسيشكرك على وضوحك اليوم.
  • استخدم أدوات تحليل الكود (Linters): هناك أدوات مثل ESLint (لـ JavaScript) أو StyleCop (لـ C#) يمكن إعدادها لتنبيهك تلقائيًا عند استخدامك لأرقام سحرية. اجعلها جزءًا من سير عملك.
  • ليس كل رقم هو رقم سحري: يجب استخدام المنطق. أرقام مثل 0 أو 1 في تهيئة حلقات التكرار (for i = 0) أو -1 كقيمة للإشارة إلى “لم يتم العثور عليه” في بعض الدوال القياسية، هي متعارف عليها وليست سحرية. الرقم السحري هو الرقم الذي يمثل مفهومًا خاصًا بالبزنس (مثل حالة الطلب، نوع المستخدم، …الخ).

الخلاصة: شيفرة نظيفة، حياة أسهل ✅

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

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

أتمنى لكم شيفرة نظيفة وخالية من الألغام. والله يعطيكم العافية.

أبو عمر

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

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

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

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

آخر المدونات

خوارزميات

البحث في قوائمي المرتبة كان يزحف: كيف أنقذني ‘البحث الثنائي’ من جحيم البطء الخطي؟

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

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

ميزانيتنا كانت تحترق: كيف أنقذتنا ‘نماذج الإحالة’ (Attribution Models) من جحيم تخمين القنوات الرابحة؟

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

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

من فوضى المكونات إلى نظام التصميم المتكامل: قصتنا لإنقاذ واجهات المستخدم من جحيم التضارب

أشارككم تجربتي كـ "أبو عمر" في الانتقال من واجهات فوضوية ومكررة إلى بيئة عمل منظمة بفضل "نظام التصميم". سنغوص في رحلتنا لبناء هذا النظام من...

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

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

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

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

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

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

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

طلباتنا كانت تضرب قاعدة البيانات بلا رحمة: كيف أنقذنا ‘التخزين المؤقت’ (Caching) من جحيم الاستجابة البطيئة؟

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

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

من كوابيس التحقق اليدوي إلى الأتمتة الذكية: كيف أنقذني نظام ‘اعرف عميلك’ (KYC) من جحيم التسجيل

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

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