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

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

بتذكر مرة، زمان في بداياتي، كنت شغال على نظام متجر إلكتروني لزبون. كنت مبسوط على حالي، الكود شغال، والتصاميم حلوة، والأمور “عال العال”. كان في جزئية بالكود مسؤولة عن حساب الضريبة على المنتجات، كانت نسبة ثابتة، خلينا نقول 15%. منطق بسيط جدًا: السعر * 0.15.

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

بعد شهرين، بيجيني الزبون وبحكيلي: “أبو عمر يا غالي، بدنا نغير نظام الضريبة. صارت الضريبة تختلف حسب نوع المنتج، الإلكترونيات عليها 15% والملابس 10% والكتب معفية من الضريبة”. في هذيك اللحظة، حسيت الدنيا بتلف فيي. تعديل بسيط في المنطق، بس أنا عارف إنه مزروع في كل زاوية من زوايا المشروع. قضيت يومين كاملين وأنا زي المجنون بدور على كل مكان نسخت فيه هالكود، أعدّل هون وأنسى هناك، تطلعلي أخطاء غريبة، فاتورة سعرها شكل وسلة المشتريات سعرها شكل ثاني. كان جحيم بمعنى الكلمة. يومها حلفت يمين إني ما أرجع لهالغلطة، وفهمت قيمة المبدأ اللي كانوا يحكوا عنه الأساتذة الكبار: Don’t Repeat Yourself – DRY.

ما هو مبدأ ‘لا تكرر نفسك’ (DRY)؟

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

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

مشكلة الكود ‘المُبلل’ (WET): كابوس الضريبة

الكود اللي بكرر نفسه بنسميه بالإنجليزية “WET”، وهي اختصار لـ “Write Everything Twice” أو “We Enjoy Typing”. خلينا نشوف كيف كان شكل الكود “المبلل” في مشروعي، وكيف صار شكله “الجاف” الأنيق.

الكود الأولي (السيء والمليء بالتكرار)

لنفترض أني كنت أستخدم JavaScript. كان المنطق موزعًا بهذا الشكل الكارثي:


// في ملف صفحة المنتج product-page.js
function displayProductPrice(product) {
  const tax = product.price * 0.15; // <-- التكرار الأول
  const finalPrice = product.price + tax;
  console.log(`السعر النهائي: ${finalPrice}`);
}

// في ملف سلة المشتريات cart-page.js
function calculateCartTotal(cartItems) {
  let total = 0;
  for (const item of cartItems) {
    const tax = item.price * 0.15; // <-- التكرار الثاني
    total += item.price + tax;
  }
  console.log(`المجموع الكلي للسلة: ${total}`);
}

// في ملف لوحة التحكم admin-panel.js
function createManualOrder(product) {
  // ... منطق إداري آخر
  const tax = product.price * 0.15; // <-- التكرار الثالث
  const orderPrice = product.price + tax;
  // ... إرسال الطلب
  console.log(`تم إنشاء طلب بسعر: ${orderPrice}`);
}

لاحظ كيف السطر const tax = product.price * 0.15; مكرر في كل مكان. كارثة حقيقية تنتظر أول طلب تغيير.

الحل الجاف (DRY): دالة واحدة لتحكمها جميعًا

الحل كان بسيطًا جدًا ومنطقيًا. كان يجب عليّ من البداية أن أستخلص هذا المنطق في دالة واحدة مركزية. هذا ما يسمى بـ “إعادة الهيكلة” أو Refactoring.


// ننشئ ملفًا جديدًا utils/tax-calculator.js
export function calculateTax(product) {
  // الآن المنطق المعقد موجود في مكان واحد
  if (product.category === 'electronics') {
    return product.price * 0.15;
  } else if (product.category === 'clothing') {
    return product.price * 0.10;
  } else if (product.category === 'books') {
    return 0; // معفي من الضريبة
  }
  return product.price * 0.15; // ضريبة افتراضية
}

والآن، أصبحت الملفات الأخرى نظيفة جدًا وسهلة القراءة والصيانة:


// في ملف صفحة المنتج product-page.js
import { calculateTax } from './utils/tax-calculator.js';

function displayProductPrice(product) {
  const tax = calculateTax(product); // <-- استدعاء من مكان واحد
  const finalPrice = product.price + tax;
  console.log(`السعر النهائي: ${finalPrice}`);
}

// في ملف سلة المشتريات cart-page.js
import { calculateTax } from './utils/tax-calculator.js';

function calculateCartTotal(cartItems) {
  let total = 0;
  for (const item of cartItems) {
    const tax = calculateTax(item); // <-- استدعاء من نفس المكان
    total += item.price + tax;
  }
  console.log(`المجموع الكلي للسلة: ${total}`);
}

// في ملف لوحة التحكم admin-panel.js
import { calculateTax } from './utils/tax-calculator.js';

function createManualOrder(product) {
  const tax = calculateTax(product); // <-- استدعاء من نفس المكان
  const orderPrice = product.price + tax;
  console.log(`تم إنشاء طلب بسعر: ${orderPrice}`);
}

شفتوا الفرق؟ الآن لو طلب الزبون تغيير أي شيء في منطق الضريبة، سأذهب إلى ملف واحد فقط وهو tax-calculator.js وأقوم بالتعديل في دقائق معدودة وبثقة تامة أن التغيير سيطبق في كل مكان في النظام.

أبعد من الدوال: أين نطبق مبدأ DRY أيضًا؟

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

  • الإعدادات والثوابت (Configuration): لا تكتب رابط الـ API أو اسم قاعدة البيانات كنص ثابت في عشرة ملفات. ضعها في ملف إعدادات واحد (config.js أو .env) واستوردها منه.
  • مكونات واجهة المستخدم (UI Components): هل لديك زر بنفس التصميم والوظيفة في أكثر من صفحة؟ لا تنسخ كود الـ HTML والـ CSS. قم بإنشاء “مكون” (Component) قابل لإعادة الاستخدام، سواء كنت تستخدم React أو Vue أو حتى CSS نقي.
  • الاستعلامات (Queries): إذا كنت تستخدم نفس استعلام قاعدة البيانات المعقد في أماكن مختلفة، فكّر في وضعه في دالة خاصة في طبقة الوصول للبيانات (Data Access Layer).
  • النصوص والترجمات: لا تكتب النصوص مباشرة في الكود. استخدم ملفات ترجمة (i18n files)، حتى لو كان مشروعك بلغة واحدة حاليًا. هذا يسهل التعديل والترجمة مستقبلًا.

نصائح من ‘الختيار’: كيف تكتشف التكرار وتتجنبه؟

مع الخبرة، بتصير عينك تلقط الكود المكرر من على بعد كيلو. لكن إليك بعض النصائح العملية اللي بتساعدك من البداية:

قاعدة الثلاثة (The Rule of Three)

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

أعطِ الأشياء أسماءً جيدة

لما تستخلص كود في دالة، أعطها اسمًا واضحًا ومعبرًا عن وظيفتها. اسم مثل calculateProductTax أفضل بألف مرة من calc1 أو doStuff. الاسم الجيد يجعل الكود يوثق نفسه بنفسه ويسهل على الآخرين (وعليك أنت في المستقبل) فهم ما يفعله.

لا تخف من إعادة الهيكلة (Refactoring)

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

الخلاصة النهائية 🏁

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

تذكر دائمًا قصتي مع نظام الضرائب. كلما شعرت برغبة في النسخ واللصق، اسأل نفسك: “ماذا لو تغير هذا المنطق غدًا؟”. هذا السؤال البسيط هو بوصلتك نحو كود أفضل.

خليك “ناشف”، وريح راسك وراس اللي بعدك. 😉

أبو عمر

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

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

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

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

آخر المدونات

البنية التحتية وإدارة السيرفرات

تطبيقاتي كانت تتصارع على المنفذ 80: كيف أنقذني ‘الخادم الوكيل العكسي’ (Reverse Proxy) من جحيم تضارب المنافذ وإدارة SSL؟

أشارككم قصتي مع الفوضى التي عشتها عند محاولة تشغيل عدة تطبيقات على خادم واحد، وكيف كان الخادم الوكيل العكسي (Reverse Proxy) مثل Nginx هو المنقذ....

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

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

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

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

تطبيقي كان يغرق في بحر الاستعلامات: كيف أنقذني ‘التحميل المسبق’ (Eager Loading) من جحيم N+1؟

تذكرون ذلك اليوم الذي كاد فيه تطبيقي أن ينهار تحت وطأة الاستعلامات البطيئة؟ في هذه المقالة، أشارككم قصة حقيقية وكيف كانت تقنية التحميل المسبق (Eager...

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