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

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

بعد ساعات من البحث والتنقيب في الكود، وصلت لدالة مسؤولة عن التحقق من صلاحيات المستخدم. وفي قلبها، لقيت هاد السطر البريء:

if (user.getRole() == 2 && post.getStatus() == 4) {
    // Allow editing
}

وقفت للحظة… “2”؟ وشو يعني “4”؟ يا زلمة شو هالأرقام هاي؟ ما في أي تعليق، ولا أي إشارة توضح المعنى. قلبت المشروع فوقاني تحتاني، فتحت قاعدة البيانات، وصرت أدور في ملفات قديمة عشان أفهم شو القصة. بعد ساعة تانية من المعاناة، اكتشفت إنه الرقم 2 كان بيعني “محرر” (Editor)، والرقم 4 كان بيعني “مسودة مكتملة” (Completed Draft). والمشكلة كانت إنه في مكان تاني من الكود، زميل إلي كان مستخدم الرقم 3 عشان يعني “محرر” بالغلط!

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

ما هي الأرقام السحرية يا أبو عمر؟

ببساطة شديدة، “الرقم السحري” (Magic Number) هو أي رقم بتستخدمه في الكود تبعك بدون ما تعرّفه أو تشرح معناه. هو رقم بيظهر فجأة، “زي السحر”، وبيشتغل، بس محدش فاهم ليش هو هاد الرقم بالذات. ممكن يكون رقم حالة طلب، أو كود خطأ، أو عدد أقصى للمحاولات، أو أي إشي تاني.

شوف هاد المثال:

// Bad example
function processOrder(order) {
    if (order.status === 1) {
        // ... process new order
    } else if (order.status === 2) {
        // ... ship the order
    } else if (order.status === 8) {
        // ... handle returned order
    }
}

لو قرأت هاد الكود بعد 6 شهور، أو لو زميلك حاول يفهمه، أول سؤال رح يخطر ببالكم هو: شو يعني 1 و 2 و 8؟ رح تضطروا ترجعوا للتوثيق (إذا كان موجود أصلاً) أو لقاعدة البيانات عشان تفهموا السياق. هاد بالزبط هو تعريف الرقم السحري.

كابوس الأرقام السحرية: ليش هي مشكلة كبيرة؟

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

1. صعوبة القراءة والفهم (Readability)

الكود النظيف هو كود بيشرح نفسه. الأرقام السحرية بتعمل العكس تماماً، بتخلي الكود غامض ومبهم. قارن المثال السيء السابق بالمثال المحسّن التالي:

// Good example
const ORDER_STATUS = {
    NEW: 1,
    SHIPPED: 2,
    PENDING_PAYMENT: 7,
    RETURNED: 8,
};

function processOrder(order) {
    if (order.status === ORDER_STATUS.NEW) {
        // ... process new order
    } else if (order.status === ORDER_STATUS.SHIPPED) {
        // ... ship the order
    } else if (order.status === ORDER_STATUS.RETURNED) {
        // ... handle returned order
    }
}

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

2. جحيم الصيانة والتعديل (Maintenance)

تخيل لو قررنا نغير رقم حالة الطلب “مُرتجع” (Returned) من 8 إلى 9 لأسباب تتعلق بقاعدة البيانات. لو كنت بتستخدم الأرقام السحرية، رح تضطر تدور على كل مكان في الكود استخدمت فيه الرقم 8 وتغيره. والمصيبة الأكبر هي: كيف تتأكد إنه كل رقم 8 لقيته بيعني “مرتجع” ومش إشي تاني خالص (مثلاً، الحد الأقصى لعدد المنتجات في السلة)؟ هاي وصفة كارثية للأخطاء.

أما باستخدام الثوابت المُسَمّاة (Named Constants)، فكل اللي عليك تعمله هو تغيير القيمة في مكان واحد فقط:

const ORDER_STATUS = {
    NEW: 1,
    SHIPPED: 2,
    PENDING_PAYMENT: 7,
    RETURNED: 9, // <-- التعديل هنا فقط!
};

وهيك، كل الكود اللي بيستخدم ORDER_STATUS.RETURNED رح يتحدث تلقائياً وبشكل آمن.

3. مصدر خفي للأخطاء (A Source of Bugs)

البشر بيرتكبوا أخطاء إملائية (typos). كتابة 8 بدل 7 سهلة جداً، والمترجم (Compiler) أو المفسر (Interpreter) ما رح يساعدك، لأنه بالنسبة إله الرقمين صح. هاد بيؤدي لأخطاء منطقية صعبة جداً في اكتشافها.

لكن لو حاولت تكتب ORDER_STATUS.RETUNED (خطأ إملائي) بدل ORDER_STATUS.RETURNED، لغة البرمجة رح تصرخ في وجهك فوراً وتحكيلك إنه هاد المتغير مش موجود. أنت حولت خطأ منطقي صامت إلى خطأ برمجي واضح وسهل الإصلاح.

الحل السحري الحقيقي: الثوابت المُسَمّاة والتعدادات (Enums)

الحل، زي ما شفنا، هو إنك “تعمّد” كل رقم في الكود تبعك. أعطيه اسم ذا معنى وخزّنه في متغير ثابت (constant).

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

مثال بلغة Python

في بايثون، المتعارف عليه هو استخدام متغيرات بأحرف كبيرة للثوابت.

# Before
def check_permission(user_level):
    if user_level == 3:
        print("Admin access granted")

# After
ADMIN_LEVEL = 3

def check_permission(user_level):
    if user_level == ADMIN_LEVEL:
        print("Admin access granted")

# Even better with Enums for grouping related constants
from enum import Enum

class UserRole(Enum):
    GUEST = 1
    MEMBER = 2
    ADMIN = 3

def check_permission_enum(user_role):
    if user_role == UserRole.ADMIN:
        print("Admin access granted")

مثال بلغة Java

لغة Java بتوفر أداة قوية جداً اسمها enum (التعداد)، وهي الخيار الأفضل دايماً للحالات اللي زي هيك.

// Before
public class Post {
    public void setStatus(int status) {
        if (status == 4) { // What is 4?
            // ...
        }
    }
}

// After (using Enums)
public enum PostStatus {
    DRAFT,
    IN_REVIEW,
    PUBLISHED,
    ARCHIVED; // The underlying numbers are handled automatically!
}

public class Post {
    public void setStatus(PostStatus status) {
        if (status == PostStatus.PUBLISHED) {
            // ... much clearer!
        }
    }
}

نصائح عملية من خبرتي

  • عوّد حالك: اجعلها عادة عندك. أول ما تبدأ مشروع جديد، أنشئ ملف خاص للثوابت (e.g., constants.js, config.py) وابدأ بوضع أي قيمة ثابتة فيه.
  • لا تستثني الأرقام “الواضحة”: حتى الأرقام اللي بتبين واضحة زي 24 في اليوم أو 100 للنسبة المئوية، الأفضل تعطيها اسم. const PERCENTAGE_MAX = 100; أو const HOURS_IN_A_DAY = 24; بيضيف سياق وبيسهل التعديل لو تغيرت المتطلبات (مثلاً، حسابات على كوكب المريخ!).
  • استخدم التعدادات (Enums) كلما أمكن: إذا كانت لغة البرمجة تدعمها، فالتعدادات هي الحل الأمثل لأنها بتجمع الثوابت المتعلقة ببعضها وبتوفر أمان من ناحية النوع (type safety).
  • مراجعة الكود (Code Review): اجعل البحث عن الأرقام السحرية جزء أساسي من عملية مراجعة الكود. لما تراجع كود زميلك وتلاقي رقم غامض، لا تخجل واسأله: “شو هاد الرقم؟ خلينا نعطيه اسم”. هاي ثقافة فريق بتخلي الكود أفضل للجميع.

الخلاصة يا جماعة الخير 🏁

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

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

تذكروا دايماً: الكود النظيف مش رفاهية، هو أساس البرمجة الاحترافية. يلا، شدوا حيلكم!

أبو عمر

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

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

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

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

آخر المدونات

اختبارات الاداء والجودة

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

في كل مرة نُحدّث فيها ملف CSS، كنا نخشى من كارثة بصرية غير متوقعة. أشارككم قصة كيف أنقذنا 'الاختبار البصري التراجعي' من ساعات لا نهائية...

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

كانت أوامرنا حبيسة الطرفية (Terminal): كيف حررنا عملياتنا بـ ‘ChatOps’ وجعلناها في متناول الجميع؟

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

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

كانت خدماتنا جزراً معزولة: كيف أنقذتنا ‘المعمارية القائمة على الأحداث’ من جحيم الاقتران المحكم؟

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

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

كان بحثنا عن المعنى أعمى: كيف أنقذتنا ‘قواعد بيانات المتجهات’ من جحيم البحث بالكلمات المفتاحية؟

أنا أبو عمر، وفي هذه المقالة سأشارككم قصة حقيقية عن مشروع كاد أن يفشل بسبب البحث التقليدي، وكيف كانت قواعد بيانات المتجهات (Vector Databases) والبحث...

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

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

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

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