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

تذكر دائماً:

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

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

أبو عمر

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

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

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

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

آخر المدونات

أتمتة العمليات

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

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

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

كانت شفرتنا هرمًا من الهلاك: كيف أنقذتنا ‘شروط الحماية’ (Guard Clauses) من جحيم الـ if/else المتداخلة؟

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

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

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

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

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

كانت نماذجنا تموت ببطء: كيف أنقذنا “انحراف النموذج” (Model Drift) من جحيم التنبؤات الفاسدة؟

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

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

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

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

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