أكوادنا كانت طلاسم رقمية: كيف أنقذتنا ‘الثوابت المسماة’ (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).

تذكر دائماً:

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

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

أبو عمر

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

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

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

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

آخر المدونات

تجربة المستخدم والابداع البصري

كانت تصاميمنا تتحطم عند التسليم: كيف أنقذتنا ‘رموز التصميم’ (Design Tokens) من جحيم الهوة بين المصمم والمطور؟

أشارككم قصة حقيقية عن الفوضى التي كانت تعم مشاريعنا بسبب الفجوة بين التصميم والتنفيذ. اكتشفوا كيف كانت "رموز التصميم" (Design Tokens) هي الجسر الذي أنقذنا،...

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

كان تحديث قاعدة البيانات يوقف خدماتنا: كيف أنقذتنا استراتيجيات الترحيل بدون توقف (Zero-Downtime Migration) من جحيم نافذة الصيانة؟

أشارككم قصة ليلة طويلة تعلمت فيها بالطريقة الصعبة أن "نافذة الصيانة" هي عدو للمستخدمين والشركات. نستكشف معاً استراتيجيات الترحيل بدون توقف (Zero-Downtime Migration) التي تحافظ...

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

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

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

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

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

أتذكر ليلة كادت فيها خدمة واحدة أن تدمر مشروعنا بالكامل بسبب الفشل المتتالي. في هذه المقالة، أشارككم قصة كيف أنقذنا نمط 'قاطع الدائرة' (Circuit Breaker)،...

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

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

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

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

كانت أسرارنا تتسرب من كل مكان: كيف أنقذتنا ‘إدارة الأسرار المركزية’ من كابوس المفاتيح المسروقة؟

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

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