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

يا أهلاً وسهلاً فيكم يا جماعة الخير. بتذكر مرة، زمان، يمكن في 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’؟) ويسهل التعديل لو قررت تغيير أسماء الأدوار في المستقبل.

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

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

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

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

أبو عمر

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

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

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

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

آخر المدونات

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

كانت خطوط بياناتنا هشة وتعمل بالدعاء: كيف أنقذنا Apache Airflow من جحيم ‘شغّل هذا السكريبت يدوياً’؟

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

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

كانت قراراتنا أشباحاً تطاردنا: كيف أنقذتنا ‘سجلات القرارات المعمارية’ (ADRs) من جحيم “لماذا فعلنا ذلك؟”

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

26 مايو، 2026 قراءة المزيد
تسويق رقمي

كانت حملاتنا تحرق الأموال: كيف أنقذتنا نماذج الإحالة بالبيانات (DDA) من جحيم تخمين العائد على الاستثمار؟

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

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

من فوضى المكونات إلى لغة بصرية موحدة: كيف يبني ‘نظام التصميم’ (Design System) جسراً بين المطورين والمصممين؟

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

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

كان كودنا غارقاً في بحر SQL: كيف أنقذنا ‘الربط الكائني العلائقي’ (ORM) من جحيم الاستعلامات المتكررة؟

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

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