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

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

المهم، كان في النظام جزئية بتحسب ضريبة القيمة المضافة، وكانت وقتها 14%. فبكل بساطة، وين ما كنت أحتاج أحسب الضريبة، كنت أضرب الرقم بـ 0.14. في فاتورة المبيعات، في تقرير الأرباح، في عرض سعر للزبون… كله كان فيه الرقم 0.14 منتشر زي حبات العدس في المجدرة.

بعد سنة تقريباً، الحكومة قررت تغير نسبة الضريبة وتخليها 16%. اتصل علي صاحب الشركة، وكان مستعجل، “أبو عمر، بدنا نغير الضريبة بسرعة، القانون الجديد ببلش من بكرة!”. قلتله “بسيطة، ولا يهمك، كلها تعديل رقم”. يا ريتني ما قلتها! قضيت ليلة كاملة يا جماعة وأنا بفتش في كل ملفات المشروع عن الرقم 0.14. والمشكلة الأكبر، إني كنت خايف أغير رقم 0.14 يكون مستخدم لشي ثاني غير الضريبة! شو هالحكي؟ هل هو خصم معين؟ نسبة عمولة؟ وجع راس ما بعده وجع راس.

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

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

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

ليش هي لعنة حقيقية على المبرمجين؟ للأسباب التالية:

1. جحيم التخمين وصعوبة الفهم

لما تشوف كود زي هيك بعد 6 شهور من كتابته (أو لو زميلك اللي شافه):


if (userStatus == 2) {
  // ... do something
}

أول سؤال بيخطر في بالك: “شو يعني 2؟”. هل يعني المستخدم فعال (active)؟ محظور (banned)؟ ينتظر التفعيل (pending)؟ ولا يمكن يكون مدير للنظام (admin)؟ أنت مضطر تبحث في باقي الكود أو في قاعدة البيانات عشان تفهم معنى هذا الرقم. هذا تضييع للوقت والجهد.

2. كابوس الصيانة والتعديلات الخطرة

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

3. خطر الأخطاء المطبعية (Typos)

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

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

الحل، يا جماعة الخير، بسيط وأنيق جداً: لا تستخدم أرقاماً مجردة، بل أعطِها أسماءً ذات معنى. هذه الأسماء بنسميها “الثوابت المسماة” (Named Constants). الثابت هو متغير قيمته لا تتغير بعد إعطائها له أول مرة.

خلينا نعيد كتابة الأمثلة السابقة باستخدام الثوابت المسماة ونشوف الفرق الشاسع.

مثال عملي: من الجحيم إلى النعيم

الكود السيء (باستخدام الأرقام السحرية):


// JavaScript Example

function calculateFinalPrice(price, itemsCount) {
  // What is 0.16? VAT?
  const tax = price * 0.16;
  
  // What is 50? Shipping cost? Or a free shipping threshold?
  let shippingCost = 50; 
  if (price > 1000) {
    shippingCost = 0; // Free shipping
  }

  return price + tax + shippingCost;
}

function checkUserAccess(user) {
  // What is 2? What is 3?
  if (user.status === 2 || user.status === 3) {
    return true; // Has access
  }
  return false;
}

الكود النظيف (باستخدام الثوابت المسماة):


// JavaScript Example

// Constants are defined in one clear place
const VAT_RATE = 0.16;
const STANDARD_SHIPPING_COST = 50;
const FREE_SHIPPING_THRESHOLD = 1000;

const USER_STATUS_ACTIVE = 2;
const USER_STATUS_ADMIN = 3;

function calculateFinalPrice(price, itemsCount) {
  const tax = price * VAT_RATE;
  
  let shippingCost = STANDARD_SHIPPING_COST;
  if (price > FREE_SHIPPING_THRESHOLD) {
    shippingCost = 0; // Free shipping
  }

  return price + tax + shippingCost;
}

function checkUserAccess(user) {
  if (user.status === USER_STATUS_ACTIVE || user.status === USER_STATUS_ADMIN) {
    return true; // Has access
  }
  return false;
}

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

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

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

متى لا يعتبر الرقم “سحرياً”؟

مش كل رقم هو رقم سحري. الأرقام اللي معناها واضح جداً من السياق، زي 0 و 1، غالباً ما بتكون سحرية. مثلاً:

  • for (let i = 0; i < 10; i++): الصفر هنا واضح أنه نقطة بداية العد.
  • if (items.length > 0): الصفر هنا يعني “هل القائمة فارغة أم لا؟”.
  • x = y * -1;: الرقم -1 واضح أنه لقلب إشارة الرقم.

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

أفضل الممارسات في التسمية

“الأسماء في البرمجة هي نصف المعركة. اسم جيد يغنيك عن كتابة تعليق.” – أبو عمر

  • استخدم حالة الأحرف الكبيرة (UPPER_SNAKE_CASE): هذا هو العرف الشائع في معظم لغات البرمجة للتمييز بين الثوابت والمتغيرات العادية. مثال: MAX_LOGIN_ATTEMPTS.
  • كن وصفيًا قدر الإمكان: اسم مثل RATE غامض. لكن ANNUAL_INTEREST_RATE واضح تمامًا. لا تخف من الأسماء الطويلة طالما أنها توضح المعنى.

أين تضع ثوابتك؟

تنظيم الثوابت مهم جداً، خصوصاً في المشاريع الكبيرة.

  • للمشاريع الصغيرة أو الملفات البسيطة: يمكنك وضع الثوابت في أعلى الملف الذي يستخدمها.
  • للمشاريع الكبيرة: الحل الأفضل هو إنشاء ملف خاص بالثوابت والإعدادات، مثلاً constants.js أو config.py. هذا الملف يصبح “مصدر الحقيقة الوحيد” (Single Source of Truth) لكل القيم الثابتة في مشروعك. أي تعديل يتم في هذا الملف المركزي وينعكس على كل المشروع.

لا يقتصر الأمر على الأرقام! (احذر من النصوص السحرية)

نفس المبدأ ينطبق تمامًا على النصوص (Strings). استخدام نصوص مجردة في الشروط يمكن أن يسبب نفس المشاكل.

سيء: if (user.role === 'administrator')

جيد: const ROLE_ADMIN = 'administrator'; if (user.role === ROLE_ADMIN)

هذا يحميك من الأخطاء الإملائية (هل هي ‘administrator’ أم ‘admin’؟) ويسهل التعديل لو قررت تغيير أسماء الأدوار في المستقبل.

الخلاصة: اجعل كودك يروي قصة واضحة 📖

في النهاية يا جماعة، كتابة الكود لا تختلف كثيراً عن كتابة قصة. كلما كانت قصتك أوضح وأسهل للفهم، كلما كان التعامل معها في المستقبل أمتع وأقل إرهاقاً. الأرقام السحرية هي كلمات غامضة في قصتك، تجعل القارئ (سواء كان أنت في المستقبل أو زميلك) يتوقف ويسأل: “ماذا يقصد المؤلف هنا؟”.

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

ودمتم سالمين ومبدعين.

أبو عمر

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

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

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

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

آخر المدونات

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

كانت تحديثات قاعدة البيانات كابوساً: كيف أنقذتنا أدوات الترحيل (Migrations) من جحيم التعديلات اليدوية؟

هل عانيت يوماً من تحديث مخطط قاعدة البيانات يدوياً بين فريقك؟ أبو عمر يشارككم قصة حقيقية حول كيف غيّرت أدوات الترحيل (Migrations) طريقة عمل فريقه،...

17 مايو، 2026 قراءة المزيد
الشبكات والـ APIs

كانت خوادمنا تستجدي التحديثات: كيف أنقذتنا ‘خطاطيف الويب’ (Webhooks) من جحيم الاستقصاء المستمر (Polling)؟

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

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

كانت بنيتنا التحتية قصراً من رمال: كيف أنقذتنا “البنية التحتية ككود” (IaC) من جحيم البيئات المتضاربة؟

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

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

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

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

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

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

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

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

كان التحقق من هوية عملائنا يستغرق أياماً: كيف أنقذنا الذكاء الاصطناعي (eKYC) من جحيم الإجراءات اليدوية؟

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

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

كانت أعطالنا تكتشف بعد فوات الأوان: كيف أنقذنا Prometheus من جحيم المراقبة التفاعلية؟

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

17 مايو، 2026 قراءة المزيد
ادارة الفرق والتنمية البشرية

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

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

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