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