وداعًا لـ “if” المتداخل! 5 طرق ذهبية لتبسيط الشروط المعقدة في الكود

مقدمة: عندما يتحول الكود إلى متاهة

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

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

1. استخدام “Guard Clauses” (الشروط الحارسة)

الـ “Guard Clauses” هي أسلوب بسيط وفعال لتقليل التداخل في الشروط. الفكرة الأساسية هي التحقق من الشروط التي تجعل الدالة غير صالحة للخروج مبكرًا من الدالة. هذا يقلل من الحاجة إلى “if” المتداخلة ويجعل الكود أكثر وضوحًا.

مثال:

بدلًا من:


function processData(data) {
  if (data !== null) {
    if (data.isValid()) {
      // معالجة البيانات
      console.log("Processing data:", data);
    } else {
      console.error("Data is invalid");
    }
  } else {
    console.error("Data is null");
  }
}

نستخدم “Guard Clauses”:


function processData(data) {
  if (data === null) {
    console.error("Data is null");
    return;
  }

  if (!data.isValid()) {
    console.error("Data is invalid");
    return;
  }

  // معالجة البيانات
  console.log("Processing data:", data);
}

نصيحة: استخدم “Guard Clauses” في بداية الدالة للتحقق من الشروط الأساسية. هذا يجعل الكود أسهل للقراءة والفهم.

2. استخدام “Switch” أو “Lookup Tables”

عندما يكون لديك سلسلة من الشروط تعتمد على قيمة متغير واحد، فإن استخدام “switch” أو “Lookup Tables” يمكن أن يكون أكثر وضوحًا وفعالية من استخدام “if” المتداخلة.

مثال:

بدلًا من:


function processAction(action) {
  if (action === "create") {
    // تنفيذ عملية الإنشاء
    console.log("Creating...");
  } else if (action === "update") {
    // تنفيذ عملية التحديث
    console.log("Updating...");
  } else if (action === "delete") {
    // تنفيذ عملية الحذف
    console.log("Deleting...");
  } else {
    console.log("Invalid action");
  }
}

نستخدم “Switch”:


function processAction(action) {
  switch (action) {
    case "create":
      // تنفيذ عملية الإنشاء
      console.log("Creating...");
      break;
    case "update":
      // تنفيذ عملية التحديث
      console.log("Updating...");
      break;
    case "delete":
      // تنفيذ عملية الحذف
      console.log("Deleting...");
      break;
    default:
      console.log("Invalid action");
  }
}

أو نستخدم “Lookup Table”:


const actions = {
  "create": () => console.log("Creating..."),
  "update": () => console.log("Updating..."),
  "delete": () => console.log("Deleting...")
};

function processAction(action) {
  const actionFunction = actions[action];
  if (actionFunction) {
    actionFunction();
  } else {
    console.log("Invalid action");
  }
}

نصيحة: “Lookup Tables” مفيدة بشكل خاص عندما تكون العمليات معقدة وتتطلب تنفيذ دوال مختلفة لكل حالة.

3. تفكيك الشروط المعقدة إلى دوال أصغر

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

مثال:

بدلًا من:


function canAccess(user, resource, permission) {
  if (user.isLoggedIn() &&
      (user.hasPermission(permission) ||
       (resource.owner === user.id && resource.isPublic()))) {
    return true;
  }
  return false;
}

نفكك الشرط:


function isLoggedIn(user) {
  return user.isLoggedIn();
}

function hasPermission(user, permission) {
  return user.hasPermission(permission);
}

function isOwnerAndPublic(user, resource) {
  return resource.owner === user.id && resource.isPublic();
}

function canAccess(user, resource, permission) {
  return isLoggedIn(user) && (hasPermission(user, permission) || isOwnerAndPublic(user, resource));
}

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

4. استخدام “State Pattern” (نمط الحالة)

إذا كان سلوك الكود يعتمد على حالة الكائن، فإن استخدام “State Pattern” يمكن أن يكون حلاً فعالًا. هذا النمط يسمح للكائن بتغيير سلوكه عندما تتغير حالته الداخلية.

مثال:

لنفترض أن لدينا كائن “Order” (طلب) يمكن أن يكون في حالات مختلفة: “Pending” (معلق)، “Shipped” (تم الشحن)، “Delivered” (تم التسليم). بدلاً من استخدام “if” المتداخلة للتحقق من الحالة وتنفيذ عمليات مختلفة، يمكننا استخدام “State Pattern”.


// تعريف واجهة الحالة
class OrderState {
  constructor(name) {
    this.name = name;
  }
  process(order) {
    throw new Error("This method should be overridden");
  }
}

// تعريف الحالات المختلفة
class PendingState extends OrderState {
  constructor() {
    super("Pending");
  }
  process(order) {
    console.log("Processing pending order...");
    order.setState(new ShippedState());
  }
}

class ShippedState extends OrderState {
  constructor() {
    super("Shipped");
  }
  process(order) {
    console.log("Processing shipped order...");
    order.setState(new DeliveredState());
  }
}

class DeliveredState extends OrderState {
  constructor() {
    super("Delivered");
  }
  process(order) {
    console.log("Order is already delivered.");
  }
}

// تعريف كائن الطلب
class Order {
  constructor() {
    this.state = new PendingState();
  }

  setState(state) {
    this.state = state;
  }

  process() {
    this.state.process(this);
  }
}

// استخدام
const order = new Order();
order.process(); // Processing pending order...
order.process(); // Processing shipped order...
order.process(); // Order is already delivered.

نصيحة: “State Pattern” مفيد بشكل خاص عندما يكون لديك عدد كبير من الحالات والانتقالات بينها.

5. استخدام “Boolean Algebra” (الجبر البولياني)

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

مثال:

لنفترض أن لدينا الشرط التالي:


if (!(x > 10 && y < 5)) {
  // تنفيذ شيء ما
}

باستخدام قانون دي مورغان، يمكننا تبسيط هذا الشرط إلى:


if (x <= 10 || y >= 5) {
  // تنفيذ شيء ما
}

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

الخلاصة: الكود النظيف يبدأ بالشروط الواضحة ✨

تجنب "if" المتداخلة ليس مجرد مسألة جمالية، بل هو ضرورة لجعل الكود أكثر قابلية للقراءة والصيانة. استخدام "Guard Clauses"، و "Switch"، وتفكيك الشروط، و "State Pattern"، والجبر البولياني، كلها أدوات قوية يمكن أن تساعدك في تبسيط الشروط المعقدة وتحسين جودة الكود. تذكر دائمًا: الكود الجيد ليس فقط الكود الذي يعمل، بل هو الكود الذي يمكن فهمه وتعديله بسهولة من قبل الآخرين (وحتى من قبلك بعد مرور بعض الوقت! 😉).

نصيحة أخيرة: قبل أن تبدأ بكتابة أي شرط معقد، خذ لحظة للتفكير في كيفية تبسيطه. غالبًا ما يكون هناك حل أفضل من مجرد إضافة "if" أخرى!

أبو عمر

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

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

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

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

آخر المدونات

تجربة المستخدم والابداع البصري

من الكنباية في بالي إلى الكنباية في صالوني: رحلتي مع الواجهات الفضائية والواقع المعزز

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

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

التصميم التوقعي والواجهات غير المرئية: كيف تجعل تطبيقاتك تقرأ أفكار المستخدمين؟

من منظور مطور برمجيات، أغوص في عالم التصميم التوقعي والواجهات غير المرئية (Zero UI). نستكشف كيف يمكن للتطبيقات أن تتنبأ باحتياجاتك قبل أن تطلبها، مع...

13 يناير، 2026 قراءة المزيد
من لمسة يد إلى همسة صوت: كيف تبني الواجهات متعددة الأنماط جيلاً جديداً من التجارب الرقمية
تجربة المستخدم والابداع البصري

من لمسة يد إلى همسة صوت: كيف تبني الواجهات متعددة الأنماط جيلاً جديداً من التجارب الرقمية

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

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

واجهتك تعرفك أكثر منك: كيف يصنع الذكاء الاصطناعي تجربة مستخدم فريدة لكل شخص؟

الواجهات الرقمية لم تعد مجرد تصميم ثابت، بل أصبحت كائنات حية تتكيف معك. في هذه المقالة، أغوص معكم في عالم الواجهات المخصصة بقوة الذكاء الاصطناعي،...

13 يناير، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

الذكاء الاصطناعي الصوتي في البنوك: من طوابير الانتظار إلى معاملات فورية بصوتك

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

13 يناير، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

المالية المفتوحة: كيف تستعيد ملكية بياناتك المالية وتصنع مستقبلك؟

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

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