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

يا جماعة الخير، السلام عليكم ورحمة الله وبركاته. معكم أخوكم أبو عمر.

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

قلوبنا وقعت في رجلينا. هاي مشكلة كبيرة. بلشنا ننبش في الكود، سطر ورا سطر. الشباب كانوا يقلبوا عيونهم في الشاشات، والقهوة بطل إلها طعم. المشكلة كانت غامضة. في مكان ما في الكود، كان في شرط (if condition) بفحص حالة الطلب. لقينا إشي زي هيك:


// ... some logic
if (order.status == 3) {
    // إرسال الطلب لنظام الشحن على أنه جاهز
    sendToShippingSystem(order, 1); // 1 يعني جاهز للشحن
}
// ... more logic

طيب، شو يعني order.status == 3؟ وشو يعني sendToShippingSystem(order, 1)؟ فتحنا قاعدة البيانات، وشفنا جدول الحالات (Statuses). لقينا إنه الحالة رقم 3 هي بالفعل “قيد التجهيز”. طيب وين المشكلة؟

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

هذا الكابوس، يا أصدقائي، اسمه “الأرقام السحرية” (Magic Numbers)، وبهديك الليلة، أقسمنا إنه ما رح نسمحله يدمر شغلنا مرة ثانية.

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

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

شوف هالمثال البسيط في نظام إدارة مستخدمين:


function canUserEditPost(user) {
    if (user.role == 2) {
        return true; // مسموح له يعدّل
    }
    return false;
}

شو يعني user.role == 2؟ هل هو “مدير” (Admin)؟ “محرر” (Editor)؟ “مشرف” (Moderator)؟ ما حدا بيعرف إلا إذا رجع لقاعدة البيانات أو للتوثيق (إذا كان موجود أصلاً!).

لماذا يجب أن تخاف منها؟

  • الغموض (Ambiguity): الكود بصير صعب القراءة والفهم. أي مبرمج جديد بنضم للفريق رح يقضي وقت طويل بس عشان يفهم هاي الأرقام شو بتعمل.
  • صعوبة الصيانة (Hard to Maintain): زي ما صار معنا في قصتنا. لو احتجت تغير قيمة معينة (مثلاً، دور “المحرر” يصير رقمه 3 بدل 2)، رح تضطر تبحث عن كل الأماكن اللي استخدمت فيها الرقم “2” وتغيرها يدوياً. وهذا خطر كبير، لأنه ممكن تغير رقم “2” في مكان ما كان لازم يتغير.
  • مصدر للأخطاء (Error-Prone): من السهل جداً تكتب الرقم غلط. ممكن تكتب user.role == 1 بالغلط بدل 2، والبرنامج ما رح يعطيك أي خطأ، لكن المنطق البرمجي كله رح يكون غلط.

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

الحل بسيط جداً وفعّال لدرجة بتستغرب كيف ممكن حدا ما يستخدمه. بدل ما ترمي الرقم في الكود، أعطيه اسم واضح وذو معنى، وخزّنه في متغير ثابت (Constant).

خلينا نعيد كتابة المثال السابق باستخدام الثوابت:


// تعريف الثوابت في مكان مركزي وواضح
const USER_ROLE_ADMIN = 1;
const USER_ROLE_EDITOR = 2;
const USER_ROLE_MEMBER = 3;

function canUserEditPost(user) {
    // الآن الكود يقرأ كأنه جملة إنجليزية!
    if (user.role == USER_ROLE_EDITOR) {
        return true;
    }
    return false;
}

شوف الفرق! الآن أي حدا بقرأ الكود رح يفهم فوراً إنه الشرط بفحص إذا كان المستخدم “محرر”. الكود صار يوثّق نفسه بنفسه. ولو احتجنا في المستقبل نغير رقم دور “المحرر” ليصير 5 مثلاً، كل اللي علينا نعمله هو تغيير القيمة في مكان واحد فقط:


const USER_ROLE_EDITOR = 5; // تغيير في مكان واحد فقط!

وهيك كل الكود اللي بستخدم USER_ROLE_EDITOR رح يتحدث تلقائياً بدون أي خطر.

كيف طبقنا الحل في مشروعنا (وداعاً لكابوس الحالة ‘3’)

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

الخطوة الأولى: إنشاء ملف مركزي للثوابت

أنشأنا ملف جديد، مثلاً constants.js أو config/statuses.php، ووضعنا فيه كل الحالات والقيم الثابتة اللي بتتكرر في المشروع. بالنسبة لحالات الطلب، صار الملف شكله هيك:


// public/js/constants.js

const ORDER_STATUS = {
    PENDING: 1,      // طلب جديد
    CONFIRMED: 2,    // تم التأكيد
    CANCELLED: 3,    // ملغي
    PROCESSING: 4,   // قيد التجهيز
    SHIPPED: 5,      // تم الشحن
    DELIVERED: 6     // تم التوصيل
};

// ... ثوابت أخرى
const SHIPPING_STATUS = {
    READY_FOR_PICKUP: 1,
    IN_TRANSIT: 2
};

نصيحة أبو عمر: استخدام كائن (Object) أو (Enum) لتجميع الثوابت المتعلقة ببعضها فكرة ممتازة. بتخلي الكود منظم أكتر، فبدل ما تكتب PROCESSING_STATUS، بتكتب ORDER_STATUS.PROCESSING، وهذا أوضح بكثير.

الخطوة الثانية: إعادة هيكلة الكود القديم

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


// الكود القديم (السيء)
// if (order.status == 3) { ... }

// الكود الجديد (النظيف)
import { ORDER_STATUS, SHIPPING_STATUS } from './constants.js';

// ...
if (order.status == ORDER_STATUS.PROCESSING) {
    // إرسال الطلب لنظام الشحن على أنه جاهز
    sendToShippingSystem(order, SHIPPING_STATUS.READY_FOR_PICKUP);
}
// ...

الفرق زي السما والأرض! الكود صار مقروء، واضح، وآمن. لو قررنا بكرة نضيف 10 حالات جديدة، أو نغير ترتيبهم، التعديل رح يصير في ملف الـ constants.js فقط، وبنكون واثقين 100% إنه ما خربنا إشي في مكان ثاني.

نصائح من خبرة “أبو عمر”

على مدار سنين طويلة في كتابة الكود، تعلمت كم شغلة عن هذا الموضوع بحب أشارككم إياها:

  1. اجعلها قاعدة إلزامية في فريقك: أفضل طريقة لتجنب الأرقام السحرية هي باتفاق الفريق كله على عدم استخدامها. اعملوا مراجعة للكود (Code Review) وخلي “التخلص من الأرقام السحرية” نقطة أساسية في المراجعة.
  2. لا تبالغ في الأمر: مش كل رقم هو رقم سحري. مثلاً، في حلقة تكرار بسيطة مثل for (let i = 0; i < 10; i++)، الرقم 0 أو 10 مش بالضرورة أرقام سحرية إذا كان السياق واضح جداً. لكن لو الرقم 10 بمثل “الحد الأقصى لعدد المنتجات في السلة”، وقتها الأفضل تحطه في ثابت اسمه MAX_CART_ITEMS.
  3. استخدم أدوات مساعدة (Linters): في أدوات مثل ESLint (لجافاسكريبت) أو PHP_CodeSniffer (لـ PHP) بتقدر تضبطها عشان تطلعلك تحذير تلقائي لما تلاقي رقم سحري في الكود. هاي الأدوات بتساعدك تكتشف المشكلة قبل ما تصير عادة.
  4. الثوابت مش بس للأرقام: أي قيمة ثابتة ومتكررة ممكن تكون ثابت مسمى. مثلاً، أسماء “roles” زي 'admin', 'editor' أو مفاتيح API، أو حتى رسائل الخطأ المتكررة.

الخلاصة: وداعاً للأرقام السحرية! 👋

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

تذكروا دايماً: اكتبوا الكود وكأنه الشخص اللي رح يجي يعدّل عليه بعدكم هو شخص عصبي جداً، وبعرف وين بيتكم ساكن! خلي الكود واضح، بسيط، ويوثق نفسه بنفسه. وتذكروا قصة “الحالة 3″، ولا تخلّوها تتكرر معكم.

الله يعطيكم العافية، وبالتوفيق في مشاريعكم.

أبو عمر

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

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

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

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

آخر المدونات

​معمارية البرمجيات

كانت واجهاتنا شبكة عنكبوت: كيف أنقذ نمط ‘بوابة الواجهة البرمجية’ (API Gateway) مشروعنا من الفوضى؟

واجهات المستخدم تتحدث مع عشرات الخدمات المصغرة؟ فوضى عارمة! في هذه المقالة، أسرد لكم حكايتي مع هذه المشكلة وكيف كان نمط 'بوابة الواجهة البرمجية' (API...

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

كان بحثنا يفهم الكلمات لا المعاني: كيف أنقذتنا ‘التضمينات المتجهة’ (Vector Embeddings) من جحيم البحث الحرفي؟

بتذكر مرة كنا بنبني نظام بحث داخلي لشركة، وكان الموظف يسأل "كيف آخذ إجازة مرضية؟" والنظام ما يرجعله إشي، لأن المستند الرسمي عنوانه "سياسة الإجازات...

23 مايو، 2026 قراءة المزيد
خوارزميات

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

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

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

كانت حملاتنا تصرخ في الفراغ: كيف أنقذت “تجزئة الجمهور بالذكاء الاصطناعي” ميزانيتنا التسويقية؟

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

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

كان موقعنا تحفة فنية… لكن للمبصرين فقط: كيف أنقذتنا معايير الوصولية (a11y) من جحيم استبعاد المستخدمين؟

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

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

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

في هذه المقالة، يشارك أبو عمر تجربته مع بطء قواعد البيانات وكيف كانت الفهارس (Indexes) هي طوق النجاة. سنتعلم ما هي الفهارس، كيف تعمل، وكيف...

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

كانت تطبيقاتنا تسأل ‘هل من جديد؟’ كل ثانية: كيف أنقذتنا WebSockets من جحيم الاستجداء المستمر للبيانات (Polling)؟

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

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

كانت سيرفراتنا “بتتثاوب” نصف الوقت: كيف أنقذتنا الحوسبة بدون خوادم (Serverless) من فواتير السحابة المؤلمة؟

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

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

كان ملفي على GitHub مقبرة رقمية: كيف حولته من مستودع أكواد إلى أداة تجذب عروض العمل؟

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

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