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

يا الله شو بتذكر هداك اليوم… أو بالأحرى، هديك الليلة. كانت الساعة حوالي 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): اجعل البحث عن الأرقام السحرية جزء أساسي من عملية مراجعة الكود. لما تراجع كود زميلك وتلاقي رقم غامض، لا تخجل واسأله: “شو هاد الرقم؟ خلينا نعطيه اسم”. هاي ثقافة فريق بتخلي الكود أفضل للجميع.

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

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

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

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

أبو عمر

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

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

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

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

آخر المدونات

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

إشعاراتنا كانت ضجيجاً والمهام تتطلب التنقل بين ألف شاشة: كيف أنقذنا ChatOps من جحيم الفوضى التشغيلية؟

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

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

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

هل تعاني من تداخل الشروط في الكود؟ أشاركك قصة حقيقية وكيف غيّرت 'شروط الحماية' (Guard Clauses) طريقة كتابتي للكود، محولةً المتاهات المعقدة إلى مسارات واضحة...

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

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

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

12 أبريل، 2026 قراءة المزيد
ذكاء اصطناعي

قرارات نموذجنا كانت صندوقاً أسود: كيف أنقذتنا تقنيات التفسير (XAI) من جحيم التنبؤات الغامضة؟

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

12 أبريل، 2026 قراءة المزيد
خوارزميات

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

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

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

تطبيقنا كان حصناً منيعاً: كيف أنقذتنا ‘معايير الوصول الرقمي (WCAG)’ من جحيم الإقصاء الرقمي؟

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

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