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

“يا زلمة، شو قصة هاد الرقم 86400؟”

خليني أرجع فيكم بالزمن لأيام زمان، أيام ما كنت لسا مبرمج جديد وشعري أسود أكثر من هلأ. كنا شغالين على نظام إدارة محتوى لعميل مهم، وكان في جزء من النظام مسؤول عن “الكاش” (Caching)، يعني تخزين البيانات بشكل مؤقت لتسريع الموقع. كل شي كان تمام، والنظام شغال زي الساعة.

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

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


// Set cache expiration
$cache->setExpiration(86400);

سألت زميلي اللي كان أكبر مني خبرة: “يا خليل، شو قصة هاد الرقم 86400؟”.

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

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

بهديك اللحظة، تعلّمت درس من أهم الدروس في مسيرتي المهنية: لا مكان للأرقام السحرية في الكود النظيف. ومن يومها، أعلنت الحرب عليها، وكان سلاحي هو “الثوابت المسماة”.


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

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

مثال على كود مليء بالطلاسم

تخيل إنك بتقرأ الكود التالي لأول مرة في مشروع جديد:


function calculateOrderTotal(price, userStatus, shippingMethod) {
    let finalPrice = price;

    // Apply discount based on user status
    if (userStatus == 2) {
        finalPrice = price * 0.90; // 10% discount
    }

    // Add shipping cost
    if (shippingMethod == 1) {
        finalPrice += 15;
    } else {
        finalPrice += 30;
    }

    // Apply tax
    return finalPrice * 1.16;
}

هذا الكود شغال، لكنه كارثة حقيقية لأي شخص سيقرأه أو يحاول صيانته لاحقاً (حتى لو كنت أنت نفسك بعد 6 أشهر). الأسئلة اللي بتخطر ببالك فوراً:

  • ماذا يعني userStatus == 2؟ هل هو مستخدم “ذهبي”؟ “نشط”؟ “مسجل جديد”؟
  • ليش الخصم 0.90؟ هل هي 10% دائماً؟
  • ماذا يمثل shippingMethod == 1؟ هل هو شحن عادي أم سريع؟
  • من أين أتى الرقم 15 و 30؟
  • وما هذا الرقم 1.16؟ هل هو ضريبة القيمة المضافة؟ ضريبة مبيعات؟

المشاكل الكارثية التي تسببها

  1. الغموض المطلق: الكود صعب الفهم ويجبرك على التخمين أو البحث في أماكن أخرى عن معنى هذه الأرقام.
  2. صعوبة الصيانة: تخيل لو أن نسبة الضريبة تغيرت من 16% إلى 17%. ستحتاج للبحث عن كل الأماكن التي استخدمت فيها الرقم 1.16 وتغييرها. ماذا لو كان هذا الرقم مستخدماً في 20 ملفاً مختلفاً؟ من السهل جداً أن تنسى تعديل إحداها، مما يسبب أخطاء فادحة في الحسابات.
  3. مصدر للأخطاء (Bugs): عند تكرار كتابة نفس الرقم يدوياً، تزيد فرصة حدوث خطأ إملائي. قد تكتب 1.16 في مكان و 1.15 في مكان آخر عن طريق الخطأ.

باختصار، الأرقام السحرية تحوّل الكود إلى حقل ألغام، كل خطوة صيانة فيه قد تؤدي إلى انفجار لم تكن تتوقعه.


الحل السحري الحقيقي: الثوابت المسماة (Named Constants)

الحل بسيط وأنيق بشكل لا يصدق: أعطِ هذه الأرقام الغامضة أسماءً واضحة وذات معنى. هذه الأسماء هي ما نسميه “الثوابت المسماة”. الثابت هو متغير لا يمكن تغيير قيمته بعد إعلانه.

إعادة كتابة المثال السابق بشكل نظيف

دعونا نرى كيف سيبدو نفس الكود السابق بعد استخدام الثوابت. سنفترض أننا نستخدم JavaScript كمثال.


// Define constants in a central place
const USER_STATUS_VIP = 2;
const VIP_DISCOUNT_RATE = 0.90; // Represents a 10% discount

const SHIPPING_METHOD_NORMAL = 1;
const SHIPPING_METHOD_EXPRESS = 2;

const NORMAL_SHIPPING_COST = 15;
const EXPRESS_SHIPPING_COST = 30;

const VAT_RATE = 1.16; // 16% Value Added Tax

function calculateOrderTotal(price, userStatus, shippingMethod) {
    let finalPrice = price;

    // Apply discount based on user status
    if (userStatus == USER_STATUS_VIP) {
        finalPrice = price * VIP_DISCOUNT_RATE;
    }

    // Add shipping cost
    if (shippingMethod == SHIPPING_METHOD_NORMAL) {
        finalPrice += NORMAL_SHIPPING_COST;
    } else {
        finalPrice += EXPRESS_SHIPPING_COST;
    }

    // Apply tax
    return finalPrice * VAT_RATE;
}

انظر إلى الفرق! الكود الآن يقرأ كأنه جملة إنجليزية (أو عربية لو كانت المتغيرات بالعربي). أصبح “يشرح نفسه بنفسه”.

  • نعرف الآن أن userStatus == 2 يعني أن المستخدم هو “VIP”.
  • إذا تغيرت نسبة الضريبة، كل ما علينا فعله هو تغيير قيمة VAT_RATE في مكان واحد فقط!
  • لا يوجد مجال للخطأ في كتابة الأرقام، لأننا نستخدم أسماء الثوابت في كل مكان.

نصائح أبو عمر الذهبية للتعامل مع الثوابت

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

متى أستخدم الثابت؟ القاعدة بسيطة!

اسأل نفسك سؤالين:

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

مثلاً، بدلاً من كتابة:


// Wait for 3 seconds (3000 milliseconds) before retrying
setTimeout(doSomething, 3000);

اكتبها هكذا:


const RETRY_DELAY_MS = 3000;
setTimeout(doSomething, RETRY_DELAY_MS);

الكود الثاني لا يحتاج إلى تعليق، فالاسم واضح تماماً.

فن اختيار الأسماء (Naming Conventions)

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

  • سيء: const N = 10;
  • جيد: const ITEMS_PER_PAGE = 10;
  • سيء: const T = 3600;
  • ممتاز: const SESSION_TIMEOUT_SECONDS = 3600;

نظّم ثوابتك في مكان مركزي

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

مثال في لغة Python:


# file: config.py

# --- User Roles ---
ROLE_ADMIN = "admin"
ROLE_EDITOR = "editor"
ROLE_VIEWER = "viewer"

# --- API Settings ---
API_BASE_URL = "https://api.my-app.com/v2/"
API_REQUEST_TIMEOUT_SECONDS = 15

# --- Pagination ---
DEFAULT_PAGE_SIZE = 25

الآن، في أي ملف آخر، يمكنك ببساطة استيراد هذه الإعدادات واستخدامها:


# file: user_service.py
import config

def check_permissions(user):
    if user.role == config.ROLE_ADMIN:
        print("Admin has full access.")
    # ...

هذا التنظيم يجعل الكود قابلاً للتطوير بشكل هائل.


الخلاصة: من طلاسم إلى كود يتنفس وضوحًا 📜

التخلص من “الأرقام السحرية” واستبدالها بـ “الثوابت المسماة” ليس مجرد تفضيل شخصي أو “موضة” برمجية، بل هو أحد أعمدة كتابة الكود النظيف والقابل للصيانة (Clean and Maintainable Code).

تذكر دائماً:

  • الوضوح أولاً: الكود يُقرأ أكثر بكثير مما يُكتب. اجعله سهل الفهم لك وللآخرين.
  • الصيانة السهلة: الثوابت المركزية تعني أن التغييرات المستقبلية ستكون في مكان واحد، سريعة وآمنة.
  • تقليل الأخطاء: استخدام أسماء الثوابت يمنع الأخطاء الإملائية ويضمن استخدام القيمة الصحيحة في كل مرة.

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

أبو عمر

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

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

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

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

آخر المدونات

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

تحديثات قاعدة البيانات بدون توقف: كيف أنقذنا نمط التوسيع والتعاقد (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 قراءة المزيد
البودكاست