انعكاس التحكم

في تصميم البرمجيات ، يُعدّ مبدأ عكس التحكم ( IoC ) أحد مبادئ التصميم التي بموجبها تتلقى الأجزاء المكتوبة خصيصًا من برنامج الحاسوب تدفق التحكم من مصدر خارجي (مثل إطار عمل ). مصطلح "عكس" مصطلح تاريخي: فبنية البرمجيات التي تعتمد هذا التصميم "تعكس" التحكم مقارنةً بالبرمجة الإجرائية . في البرمجة الإجرائية، يستدعي الكود المخصص للبرنامج مكتبات قابلة لإعادة الاستخدام لتنفيذ مهام عامة، بينما في مبدأ عكس التحكم، يكون الكود الخارجي أو إطار العمل هو المتحكم الذي يستدعي الكود المخصص.

يُستخدم مبدأ عكس التحكم على نطاق واسع في أطر تطوير التطبيقات منذ ظهور بيئات واجهة المستخدم الرسومية [ 1 ] [ 2 ] ، ولا يزال يُستخدم في كلٍ من بيئات واجهة المستخدم الرسومية وأطر تطبيقات خادم الويب . يُتيح مبدأ عكس التحكم إمكانية توسيع إطار العمل من خلال الطرق التي يُحددها مُبرمج التطبيق. [ 3 ]

غالبًا ما تُطبَّق البرمجة الموجهة بالأحداث باستخدام IoC، بحيث يقتصر دور الكود المخصص على معالجة الأحداث، بينما يتولى إطار العمل أو بيئة التشغيل إدارة حلقة الأحداث وإرسالها/الرسائل. في أطر عمل تطبيقات خادم الويب، يُطلق على عملية الإرسال عادةً اسم التوجيه، وقد تُسمى المعالجات نقاط النهاية.

معنى بديل

يُستخدم مصطلح "انعكاس التحكم" بشكل منفصل في أوساط مبرمجي جافا للإشارة تحديدًا إلى أنماط حقن التبعية (تمرير الخدمات إلى الكائنات التي تحتاجها) التي تحدث مع "حاويات IoC" في أطر عمل جافا مثل Spring Framework . [ 4 ] وبهذا المعنى المختلف، يشير "انعكاس التحكم" إلى منح إطار العمل التحكم في تنفيذ التبعيات التي تستخدمها كائنات التطبيق [ 5 ] بدلاً من المعنى الأصلي المتمثل في منح إطار العمل التحكم في تدفق البيانات (التحكم في وقت تنفيذ كود التطبيق، مثل عمليات الاستدعاء).

ملخص

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

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

يحمل مفهوم "انعكاس التحكم" دلالة قوية على أن الكود القابل لإعادة الاستخدام والكود الخاص بالمشكلة يُطوَّران بشكل مستقل، على الرغم من عملهما معًا في التطبيق. تُعدّ دوال الاستدعاء ، والمجدولات ، وحلقات الأحداث ، وطريقة القالب أمثلة على أنماط التصميم التي تتبع مبدأ انعكاس التحكم، مع أن المصطلح يُستخدم غالبًا في سياق البرمجة كائنية التوجه . ( يُعدّ حقن التبعية مثالًا على الفكرة المنفصلة والمحددة لـ "انعكاس التحكم في تطبيقات التبعيات" التي شاعت بفضل أطر عمل جافا). [ 4 ]

يُشار أحيانًا إلى انعكاس التحكم باسم "مبدأ هوليوود: لا تتصل بنا، سنتصل بك"، مما يعكس كيفية تحديد الأطر لتدفق التنفيذ. [ 1 ]

خلفية

يعود أصل هذا المصطلح إلى عام 1988، [ 7 ] ولكنه يرتبط ارتباطًا وثيقًا بمفهوم عكس البرنامج الذي وصفه مايكل جاكسون في منهجية البرمجة الهيكلية لجاكسون في سبعينيات القرن الماضي. [ 8 ] يمكن اعتبار المحلل اللغوي من الأسفل إلى الأعلى بمثابة عكس للمحلل اللغوي من الأعلى إلى الأسفل : ففي الحالة الأولى، يكون التحكم بيد المحلل اللغوي، بينما في الحالة الثانية، يكون بيد التطبيق المُستقبِل.

استخدم مايكل ماتسون هذا المصطلح في أطروحته (بمعناه الأصلي الذي يشير إلى إطار عمل يستدعي كود التطبيق بدلاً من العكس) [ 9 ] ، ثم تبناه ستيفانو مازوتشي [ 10 ] وشاع استخدامه عام 1999 في مشروع أفالون التابع لمؤسسة برمجيات أباتشي، والذي توقف عن العمل، حيث كان يشير إلى كائن رئيسي يمرر تبعيات الكائن الفرعي بالإضافة إلى التحكم في تدفق التنفيذ. [ 11 ] وازداد استخدام المصطلح شيوعًا عام 2004 على يد روبرت سي. مارتن ومارتن فاولر ، الذي أرجع أصول المصطلح إلى ثمانينيات القرن العشرين. [ 7 ]

وصف

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

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

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

يستخدم

مثال على التعليمات البرمجية

البنية التحتية للإطار

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

استيراد java.util.ArrayList ؛ استيراد java.util.List ؛واجهة PluginCommand { void execute (); }class ApplicationEngine { private final List <PluginCommand> plugins ; }private ApplicationEngine ( Builder builder ) { this.plugins = new ArrayList < > ( builder.plugins ) ; }public void run () { for ( PluginCommand plugin : plugins ) { plugin . execute (); } }public static class Builder { private final List <PluginCommand> plugins = new ArrayList <> ( ) ;public Builder registerPlugin ( PluginCommand plugin ) { this . plugins . add ( plugin ); return this ; }public ApplicationEngine build () { return new ApplicationEngine ( this ); } } }

هذا هو رمز التطبيق نفسه، والذي يتم التحكم فيه.

class DatabaseBackupPlugin implements PluginCommand { @Override public void execute () { System . out . println ( " -> [Custom Code] DatabaseBackupPlugin: Exporting SQL dump..." ); } }class EmailNotificationPlugin implements PluginCommand { @Override public void execute () { System . out . println ( " -> [Custom Code] EmailNotificationPlugin: Sending system status email..." ); } }

ثم يتم تشغيل هذا على النحو التالي:

ApplicationEngine engine = new ApplicationEngine.Builder () . registerPlugin ( new DatabaseBackupPlugin ()) . registerPlugin ( new EmailNotificationPlugin ()) . build ( ) ;تشغيل المحرك ( );

أحداث DOM في HTML

تُطبّق متصفحات الويب آلية عكس التحكم لأحداث DOM في لغة HTML. ويستخدمها مطور التطبيق document.addEventListener()لتسجيل دالة رد نداء.

< ! doctype html > < html lang = " en " > <head> < meta charset = " utf - 8 " > <title> DOM المستوى 2 </title> </head> <body> <h1> معالج أحداث DOM المستوى 2 </h1> < div id = " output " > </div><script> var listener = function ( ) { document.getElementById ( " output" ). innerHTML = " <p>تم استدعاء المستمع المسجل.</p>" ; } document.addEventListener ( " click " , listener , true ) ;document.getElementById ( "output" ) . innerHTML = " <p> تم تسجيل معالج الحدث. إذا نقرت على الصفحة ، فسيستدعي متصفحك معالج الحدث. < / p > " </script> </body> </html>

أطر عمل تطبيقات الويب

يقوم هذا المثال البرمجي لتطبيق ويب ASP.NET Core بإنشاء مضيف لتطبيق الويب، وتسجيل نقطة نهاية، ثم تمرير التحكم إلى الإطار: [ 12 ]

باستخدام Microsoft.AspNetCore.Builder ؛WebApplicationBuilder builder = WebApplication.CreateBuilder ( args ); WebApplication app = builder.Builder ( ) ; app.MapGet ( " /" , () = > " Hello World!" ) ; app.Run ( ) ;

انظر أيضاً

مراجع

  1. 1 2 3 سويت، ريتشارد (25 يونيو 1985). "بيئة برمجة ميسا" . إشعارات ACM SIGPLAN . 20 (7): 216-229 . doi : 10.1145/17919.806843 .
  2. فيجوال بيسك (كلاسيكي)
  3. جونسون، رالف إي.؛ فوت، برايان (يونيو-يوليو 1988). "تصميم فئات قابلة لإعادة الاستخدام" . مجلة البرمجة الكائنية التوجه . 1 (2): 22-35 . CiteSeerX 10.1.1.101.8594 . تاريخ الاسترجاع: 29 أبريل 2014 . 
  4. 1 2 فاولر، مارتن. "حاويات عكس التحكم ونمط حقن التبعية" . MartinFowler.com . تم الاطلاع عليه في 4 يونيو 2023 .
  5. 1 2 "إطار عمل سبرينغ: حاوية IoC" . docs.spring.io . تم ​​الاطلاع عليه بتاريخ 25 مايو 2023 .
  6. حقن التبعية .
  7. 1 2 انعكاس التحكم في بليكي لمارتن فاولر
  8. "مقدمة في طريقة جاكسون للتصميم" (ملف PDF) .
  9. ^ ماتسون ، مايكل (فبراير 1996). "الأطر الشيئية، دراسة استقصائية للقضايا المنهجية" . قسم علوم الحاسب، جامعة لوند. سيتيسيركس 10.1.1.36.1424 . لو-CS-TR: 96-167. 
  10. ستيفانو مازوتشي (22 يناير 2004). "حول انعكاس التحكم" . مؤرشف من الأصل في 2 فبراير 2004.
  11. "أنماط IOC - إطار عمل أفالون" . مشروع أباتشي أفالون . تم الاطلاع عليه بتاريخ 8 يونيو 2023 .
  12. 1 2 رايان نواك، كيرك لاركين، ريك أندرسون. ""التوجيه في ASP.Net Core"" . learn.microsoft.com . microsoft . تم الاطلاع عليه بتاريخ 25 مايو 2023. التوجيه مسؤول عن مطابقة طلبات HTTP الواردة وإرسالها إلى نقاط النهاية التنفيذية للتطبيق. نقاط النهاية هي وحدات التطبيق البرمجية القابلة للتنفيذ لمعالجة الطلبات. يتم تعريف نقاط النهاية في التطبيق وتكوينها عند بدء تشغيله. "{{cite web}}: صيانة CS1: أسماء متعددة: قائمة المؤلفين ( رابط )