0Pricing
Scala for Backend Engineering & Functional Programming · درس

عدم القابلية للتغيير والآثار الجانبية

افهم أهمية عدم القابلية للتغيير في البرمجة الوظيفية وكيفية إدارة الآثار الجانبية بفعالية

عدم القابلية للتغيير والآثار الجانبية درس مجاني في Scala for Backend Engineering & Functional Programming على CoddyKit. هذا هو الدرس 3 من أصل 3. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Scala for Backend Engineering & Functional Programming، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Scala for Backend Engineering & Functional Programming 3 دروس في المجموع.

غير قابل للتغيير حسب التصميم

مرحبًا بكم في درسنا حول عدم القابلية للتغيير والآثار الجانبية! فهما من المفاهيم الأساسية في البرمجة الوظيفية (FP)، ويساعداننا على كتابة شيفرة أوضح وأكثر قابلية للتوقّع.

في البرمجة الوظيفية، نفضّل العمل مع البيانات غير القابلة للتغيير. وهذا يعني أنه لا يمكن تغيير جزء من البيانات بعد إنشائه. تخيّلوا الأمر كصورة فوتوغرافية؛ يمكنكم النظر إليها، لكن لا يمكنكم تغيير اللحظة الأصلية التي التقطتها.

val مقابل var في Scala

تسهّل Scala تعريف القيم غير القابلة للتغيير باستخدام الكلمة المفتاحية val. وهذا مرجع ثابت لا يمكن إعادة إسناده بعد تعريفه الأولي. أما المتغيرات القابلة للتغيير، فتُعرَّف باستخدام var.

لنرَ الفرق:

object Main {
  def main(args: Array[String]): Unit = {
    // Immutable value
    val greeting = "Hello"
    // greeting = "Hi" // This would cause a compile error!

    // Mutable variable
    var count = 0
    count = 1 // This is allowed

    println(greeting)
    println(count)
  }
}

لماذا تهمّ عدم القابلية للتغيير

توفّر عدم القابلية للتغيير فوائد قوية عديدة للشيفرة، لا سيما في الأنظمة المتزامنة والمعقّدة:

  • قابلية التوقّع: تعرفون دائمًا أن القيمة لن تتغيّر على نحو غير متوقّع.
  • أمان التزامن: يمكن لأجزاء متعددة من البرنامج قراءة البيانات نفسها دون القلق من تعديل جزء آخر لها. ولا حاجة إلى أقفال معقّدة!
  • سهولة تصحيح الأخطاء: يصبح تعقّب الأخطاء أبسط، إذ لا يتعيّن عليكم القلق بشأن تغيّر الحالة بمرور الوقت.

المجموعات غير القابلة للتغيير

تميل مكتبة Scala القياسية بدرجة كبيرة إلى استخدام المجموعات غير القابلة للتغيير افتراضيًا. فعندما «تعدّلون» مجموعة غير قابلة للتغيير، تحصلون فعليًا على مجموعة جديدة تتضمن التغييرات، مع بقاء المجموعة الأصلية دون تغيير.

إليكم مثالًا باستخدام List غير قابلة للتغيير:

object Main {
  def main(args: Array[String]): Unit = {
    val numbers = List(1, 2, 3)
    val newNumbers = numbers :+ 4 // Creates a new list

    println(s"Original list: $numbers")
    println(s"New list: $newNumbers")
  }
}

فهم الآثار الجانبية

على خلاف عدم القابلية للتغيير، يحدث أثر جانبي عندما تفعل دالة أو تعبير شيئًا يتجاوز مجرد إرجاع قيمة. فهي تتفاعل مع «العالم الخارجي» أو تغيّر حالة قابلة للتغيير.

تشمل الآثار الجانبية الشائعة ما يلي:

  • تعديل متغير عام أو كائن قابل للتغيير.
  • الطباعة في وحدة التحكم (إدخال/إخراج).
  • الكتابة إلى ملف أو قاعدة بيانات.
  • تغيير ساعة النظام.

مشكلة الآثار الجانبية

رغم أن الآثار الجانبية تكون ضرورية أحيانًا، فإننا نهدف في البرمجة الوظيفية إلى تقليلها وعزلها. لماذا؟

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

التعرّف إلى الآثار الجانبية في الشيفرة

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

object Main {
  var total = 0 // A mutable global variable

  // Function with a side effect
  def addAndPrint(x: Int, y: Int): Int = {
    total = x + y // Modifies global state
    println(s"Sum is: $total") // I/O side effect
    total
  }

  // Function without side effects (pure function)
  def pureAdd(x: Int, y: Int): Int = {
    x + y // Only returns a value
  }

  def main(args: Array[String]): Unit = {
    addAndPrint(5, 3)
    println(s"Global total: $total")
    println(s"Pure sum: ${pureAdd(5, 3)}")
  }
}

الدوال النقية: المثال الأعلى في البرمجة الوظيفية

الهدف النهائي في البرمجة الوظيفية هو كتابة دوال نقية. وللدالة النقية خاصيتان أساسيتان:

  1. تنتج دائمًا الناتج نفسه للمدخل نفسه (حتمية).
  2. لا تُحدث أي آثار جانبية (أي لا تغيّر شيئًا خارج نطاقها).

الدالة pureAdd في المثال السابق دالة نقية!

إدارة الآثار الجانبية

بما أن بعض الآثار الجانبية لا يمكن تجنّبها (مثل طباعة النتائج أو حفظ البيانات)، فإن منهج البرمجة الوظيفية يتمثل في ما يلي:

  • عزلها: إبقاء الدوال ذات الآثار الجانبية منفصلة عن الدوال النقية.
  • دفعها إلى الأطراف: تنفيذ عمليات الإدخال والإخراج في بداية البرنامج أو نهايته، أو ضمن أقسام مخصّصة «لتنفيذ التأثيرات».
  • استخدام بنيات البرمجة الوظيفية: توفّر المكتبات غالبًا أنواعًا (مثل IO أو Task) لتمثيل التأثيرات وإدارتها بوضوح.

تحقّقوا من فهمكم

استنادًا إلى ما تعلّمتموه، أي العبارات التالية حول عدم القابلية للتغيير والآثار الجانبية في البرمجة الوظيفية صحيحة؟

مراجعة: عدم القابلية للتغيير والآثار الجانبية

أحسنتم! استكشفنا في هذا الدرس مفهومَي عدم القابلية للتغيير والآثار الجانبية المهمَّين في البرمجة الوظيفية.

  • رأينا كيف تعزّز val عدم القابلية للتغيير في Scala، مما يؤدي إلى شيفرة أكثر قابلية للتوقّع وأمانًا في بيئات التزامن.
  • عرّفنا الآثار الجانبية بأنها تفاعلات تتجاوز القيمة التي تُرجعها الدالة، وفهمنا سبب تعقيدها للشيفرة.
  • تعلّمنا أخيرًا عن الدوال النقية بوصفها المثال الأعلى في البرمجة الوظيفية؛ فهي حتمية وخالية من الآثار الجانبية، كما تعرّفنا إلى استراتيجيات إدارة الآثار الجانبية الضرورية.

يُعدّ إتقان هذه المفاهيم أساسيًا لكتابة تطبيقات Scala وظيفية متينة وأنيقة!

الأسئلة الشائعة

هل درس «عدم القابلية للتغيير والآثار الجانبية» مجاني؟

نعم — نص درس «عدم القابلية للتغيير والآثار الجانبية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Scala for Backend Engineering & Functional Programming، انتقل إلى CoddyKit PRO. تتضمن دورة Scala for Backend Engineering & Functional Programming 3 دروس في المجموع.

ماذا ستتعلم في «عدم القابلية للتغيير والآثار الجانبية»؟

افهم أهمية عدم القابلية للتغيير في البرمجة الوظيفية وكيفية إدارة الآثار الجانبية بفعالية تتمرن على Scala for Backend Engineering & Functional Programming مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Scala for Backend Engineering & Functional Programming؟

لا تُشترط خبرة سابقة. Scala for Backend Engineering & Functional Programming على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 3.

كم من الوقت يستغرق درس «عدم القابلية للتغيير والآثار الجانبية»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Scala for Backend Engineering & Functional Programming هذا؟

نعم. كل درس في Scala for Backend Engineering & Functional Programming يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الدوال كقيم من الدرجة الأولى
  2. الدوال عالية الرتبة والتطبيق الجزئي
  3. عدم القابلية للتغيير والآثار الجانبية
← العودة إلى Scala for Backend Engineering & Functional Programming