سؤال

يمكن أن يكون انقلاب التحكم (أو IoC) مربكًا للغاية عند مواجهته لأول مرة.

  1. ما هذا؟
  2. ما هي المشكلة التي يحلها؟
  3. متى يكون من المناسب استخدامها ومتى لا؟
هل كانت مفيدة؟

المحلول

تدور أنماط انقلاب التحكم (IoC) وحقن التبعية (DI) حول إزالة التبعيات من التعليمات البرمجية الخاصة بك.

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

public class TextEditor {

    private SpellChecker checker;

    public TextEditor() {
        this.checker = new SpellChecker();
    }
}

ما فعلناه هنا يخلق تبعية بين TextEditor و ال SpellChecker.في سيناريو IoC، سنفعل شيئًا مثل هذا بدلاً من ذلك:

public class TextEditor {

    private IocSpellChecker checker;

    public TextEditor(IocSpellChecker checker) {
        this.checker = checker;
    }
}

في المثال الأول للكود، نقوم بإنشاء مثيل SpellChecker (this.checker = new SpellChecker();)، والتي تعني TextEditor الطبقة تعتمد بشكل مباشر على SpellChecker فصل.

في المثال الثاني للكود، نقوم بإنشاء تجريد من خلال الحصول على SpellChecker فئة التبعية في TextEditor توقيع المنشئ (عدم تهيئة التبعية في الفصل).يتيح لنا ذلك استدعاء التبعية ثم تمريرها إلى فئة TextEditor كما يلي:

SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);

الآن يقوم العميل بإنشاء TextEditor الطبقة لديها السيطرة عليها SpellChecker التنفيذ لاستخدامه لأننا نقوم بحقن التبعية في ملف TextEditor إمضاء.

هذا مجرد مثال بسيط، هناك سلسلة جيدة من المقالات بواسطة سيمون بوسولي الذي يشرح ذلك بمزيد من التفصيل.

نصائح أخرى

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

على سبيل المثال، في قائمة المدرسة القديمة، قد يكون لديك:

print "enter your name"
read name
print "enter your address"
read address
etc...
store in database

وبالتالي التحكم في تدفق تفاعل المستخدم.

في برنامج واجهة المستخدم الرسومية أو شيء من هذا القبيل، بدلا من ذلك نقول:

when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase

والآن انقلبت السيطرة..فبدلاً من قبول الكمبيوتر لإدخال المستخدم بترتيب ثابت، يتحكم المستخدم في الترتيب الذي يتم به إدخال البيانات، ومتى يتم حفظ البيانات في قاعدة البيانات.

أساسًا، أي شئ مع حلقة حدث أو عمليات الاسترجاعات أو مشغلات التنفيذ تقع ضمن هذه الفئة.

ما هو انقلاب السيطرة؟

إذا اتبعت هاتين الخطوتين البسيطتين، فقد قمت بعكس التحكم:

  1. متفرق ماذا-to-do جزء من متى-جزء المهام.
  2. ضمان متى يعرف الجزء كما قليل قدر الإمكان حول ماذا جزء؛والعكس صحيح.

هناك العديد من التقنيات الممكنة لكل خطوة من هذه الخطوات بناءً على التقنية/اللغة التي تستخدمها في التنفيذ.

--

ال انقلاب جزء من انقلاب التحكم (IoC) هو الشيء المربك؛لأن انقلاب هو المصطلح النسبي.أفضل طريقة لفهم IoC هي نسيان تلك الكلمة!

--

أمثلة

  • التعامل مع الحدث.معالجات الأحداث (جزء ما يجب فعله) - رفع الأحداث (جزء متى يجب القيام به)
  • واجهات.عميل المكون (جزء متى يجب القيام به) - تنفيذ واجهة المكون (جزء ما يجب فعله)
  • تركيبات xUnit.الإعداد وTearDown (جزء ما يجب فعله) - تستدعي أطر عمل xUnit الإعداد في البداية وTearDown في النهاية (جزء متى يجب القيام به)
  • نمط تصميم طريقة القالب.طريقة القالب - الجزء الذي يجب القيام به - تنفيذ الطبقة الفرعية البدائية جزء ما يجب القيام به
  • أساليب حاوية DLL في COM.DllMain، وDllCanUnload، وما إلى ذلك (جزء ما يجب فعله) - COM/OS (جزء متى يجب القيام به)

إن انقلاب الضوابط يدور حول فصل المخاوف.

بدون اللجنة الدولية:لديك حاسوب محمول الكمبيوتر وكسر الشاشة عن طريق الخطأ.وستجد أن نفس طراز شاشة الكمبيوتر المحمول لا يوجد في أي مكان في السوق.إذن أنت عالق.

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

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

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

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

من خلال تنفيذ عكس التحكم، يحصل مستهلك البرنامج/الكائن على مزيد من الضوابط/الخيارات على البرنامج/الكائنات، بدلاً من التحكم فيه أو الحصول على خيارات أقل.

مع وضع الأفكار المذكورة أعلاه في الاعتبار.ما زلنا نفتقد جزءًا رئيسيًا من IoC.في سيناريو IoC، يعد مستهلك البرنامج/الكائن إطارًا متطورًا.وهذا يعني أن الكود الذي قمت بإنشائه لا يتم استدعاؤه بنفسك.الآن دعونا نشرح لماذا تعمل هذه الطريقة بشكل أفضل مع تطبيقات الويب.

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

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

تعتمد تطبيقات الويب الحديثة ذات بنية MVC على إطار العمل للقيام بتوجيه URL ووضع وحدات التحكم في مكانها حتى يتم استدعاء إطار العمل.

يرتبط حقن التبعية وانعكاس التحكم.حقن التبعية موجود في مجهري المستوى وانعكاس التحكم في دقيق مستوى.عليك أن تأكل كل قضمة (تنفيذ DI) لإنهاء الوجبة (تنفيذ IoC).

قبل استخدام Inversion of Control يجب أن تدرك جيدًا أن له إيجابياته وسلبياته ويجب أن تعرف سبب استخدامه إذا قمت بذلك.

الايجابيات:

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

سلبيات:

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

أنا شخصياً أرى نقاط القوة في IoC وأحبها حقًا ولكنني أميل إلى تجنب IoC كلما أمكن ذلك لأنها تحول برنامجك إلى مجموعة من الفئات التي لم تعد تشكل برنامجًا "حقيقيًا" ولكنها مجرد شيء يحتاج إلى تجميعه معًا تكوين XML أو البيانات التعريفية للتعليقات التوضيحية وسوف تنهار (وتنهار) بدونها.

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

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

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

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

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

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

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

لنفترض أنك كائن.وتذهب إلى مطعم:

بدون اللجنة الدولية:أنت تسأل عن "تفاحة"، ويتم تقديم التفاحة لك دائمًا عندما تطلب المزيد.

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

لذلك، من الواضح أن IoC هو المفضل عندما تحب الأصناف.

IoC / DI بالنسبة لي يدفع التبعيات إلى كائنات الاتصال.بسيط للغاية.

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

  1. انقلاب التحكم هو نمط يستخدم لفصل المكونات والطبقات في النظام.يتم تنفيذ النمط من خلال حقن التبعيات في المكون عند إنشائه.عادةً ما يتم توفير هذه التبعيات كواجهات لمزيد من الفصل ودعم قابلية الاختبار.حاويات IoC / DI مثل Castle Windsor وUnity هي أدوات (مكتبات) يمكن استخدامها لتوفير IoC.توفر هذه الأدوات ميزات موسعة تتجاوز إدارة التبعية البسيطة، بما في ذلك مدى الحياة، وAOP/الاعتراض، والسياسة، وما إلى ذلك.

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

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

سأكتب فهمي البسيط لهذين المصطلحين:

For quick understanding just read examples*

حقن التبعية (DI):
حقن التبعية يعني بشكل عام تمرير كائن تعتمد عليه الطريقة، كمعلمة للطريقة، بدلاً من جعل الطريقة تنشئ الكائن التابع.
ما يعنيه ذلك عمليًا هو أن الطريقة لا تعتمد بشكل مباشر على تنفيذ معين؛يمكن تمرير أي تطبيق يلبي المتطلبات كمعلمة.

مع هذه الكائنات أخبر تبعياتهم.والربيع يجعلها متاحة.
وهذا يؤدي إلى تطوير التطبيقات مقترنة بشكل فضفاض.

Quick Example:EMPLOYEE OBJECT WHEN CREATED,
              IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
   (if address is defines as dependency by Employee object)

انقلاب حاوية التحكم (IoC):
هذه خاصية شائعة للأطر ، IOC يدير كائنات جافا
- من الإنشاء إلى التدمير من خلال BeanFactory.
- تسمى مكونات Java التي يتم إنشاء مثيل لها بواسطة حاوية IoC بالفاصوليا، و تدير حاوية IoC نطاق الحبة وأحداث دورة الحياة وأي ميزات AOP الذي تم تكوينه وترميزه.

QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it.

من خلال تنفيذ عكس التحكم، يحصل مستهلك البرنامج/الكائن على مزيد من التحكم/الخيارات على البرنامج/الكائنات، بدلاً من التحكم فيه أو الحصول على خيارات أقل.

إن انقلاب التحكم كمبدأ توجيهي للتصميم يخدم الأغراض التالية:

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

شرح مفصل

الإجابة على الجزء الأول فقط.ما هذا؟

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

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

باختصار، يتم قلب التحكم من المبرمج إلى الحاوية.لذلك يطلق عليه عكس السيطرة.

لقد وجدت مثالا جيدا واحدا هنا.

لنفترض أننا عقدنا بعض الاجتماعات في بعض الفنادق.

كثير من الناس، والعديد من أباريق الماء، والعديد من الأكواب البلاستيكية.

عندما يريد شخص ما أن يشرب، تملأ الكوب وتشرب وترمي الكوب على الأرض.

بعد ساعة أو شيء من هذا القبيل لدينا أرضية مغطاة بالأكواب البلاستيكية والماء.

دعونا عكس السيطرة.

نفس اللقاء في نفس المكان، ولكن بدلاً من الأكواب البلاستيكية لدينا نادل مع كوب زجاجي واحد (سينجلتون)

وهي تعرض دائمًا على الضيوف الشرب.

عندما يريد شخص ما أن يشرب، فإنه يأخذ من كأس النادل، ويشرب ويعيده مرة أخرى إلى النادل.

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

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

فكر في نفسك كمنظم لمثل هذا الاجتماع.أنت بحاجة إلى طريقة لإرسال رسالة إلى إدارة الفندق بذلك

سيحتاج أعضاء الاجتماع إلى كوب من الماء ولكن ليس إلى قطعة من الكعكة.

مثال:-

public class MeetingMember {

    private GlassOfWater glassOfWater;

    ...

    public void setGlassOfWater(GlassOfWater glassOfWater){
        this.glassOfWater = glassOfWater;
    }
    //your glassOfWater object initialized and ready to use...
    //spring IoC  called setGlassOfWater method itself in order to
    //offer to meetingMember glassOfWater instance

}

روابط مفيدة:-

أنا أتفق مع NilObject, ، ولكن أود أن أضيف إلى هذا:

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

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

يبدو أن الشيء الأكثر إرباكًا بشأن الاختصار "IoC" والاسم الذي يمثله هو أنه اسم فاتن للغاية - وهو اسم ضجيج تقريبًا.

هل نحتاج حقًا إلى اسم لوصف الفرق بين البرمجة الإجرائية والبرمجة الموجهة بالأحداث؟حسنًا، إذا أردنا ذلك، ولكن هل نحتاج إلى اختيار اسم جديد تمامًا "أكبر من الحياة" والذي يربك أكثر مما يحل؟

يدور IoC حول عكس العلاقة بين التعليمات البرمجية الخاصة بك ورمز الجهة الخارجية (المكتبة/إطار العمل):

  • في تطور s/w العادي، تكتب رئيسي() طريقة واستدعاء أساليب "المكتبة". أنت مسيطرون :)
  • في IoC يتحكم "الإطار". رئيسي() ويدعو الأساليب الخاصة بك.ال نطاق تحت السيطرة :(

يدور DI (حقن التبعية) حول كيفية تدفق التحكم في التطبيق.يحتوي تطبيق سطح المكتب التقليدي على تدفق تحكم من التطبيق الخاص بك (الطريقة الرئيسية () إلى استدعاءات طريقة المكتبة الأخرى، ولكن مع عكس تدفق التحكم في DI، يعتني إطار العمل ببدء تشغيل تطبيقك وتهيئته واستدعاء أساليبك كلما لزم الأمر.

وفي النهاية أنت الرابح دائماً :)

قلب السيطرة هو عندما تذهب إلى محل البقالة وتعطيك زوجتك قائمة المنتجات التي تريد شراؤها.

من حيث البرمجة، اجتازت وظيفة رد الاتصال getProductList() إلى الوظيفة التي تقوم بتنفيذها - doShopping().

يسمح لمستخدم الدالة بتحديد بعض أجزاء منها، مما يجعلها أكثر مرونة.

يمكن العثور على شرح مكتوب بسيط للغاية هنا

http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html

انها تقول -

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

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

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

بالنسبة لأولئك المهتمين بمزيد من التعمق في Inversion of Control، تم نشر ورقة توضح صورة أكثر اكتمالًا لـ Inversion of Control كنمط تصميم (OfficeFloor:استخدام الأنماط المكتبية لتحسين تصميم البرمجيات http://doi.acm.org/10.1145/2739011.2739013 مع نسخة مجانية متاحة للتحميل من http://www.officefloor.net/about.html).

ما تم تحديده هو العلاقة التالية:

انقلاب التحكم (للطرق) = حقن التبعية (الحالة) + حقن الاستمرار + حقن الخيط

ملخص العلاقة المذكورة أعلاه لانعكاس التحكم المتاح - http://dzone.com/articles/inversion-of-coupling-control

لقد وجدت مثالا واضحا جدا هنا وهو ما يفسر كيفية "عكس التحكم".

الكود الكلاسيكي (بدون حقن التبعية)

إليك كيفية عمل الكود الذي لا يستخدم DI تقريبًا:

  • يحتاج التطبيق إلى Foo (على سبيل المثال.وحدة تحكم)، لذلك:
  • يقوم التطبيق بإنشاء Foo
  • يستدعي التطبيق Foo
    • يحتاج Foo إلى شريط (على سبيل المثال.خدمة)، لذلك:
    • يقوم Foo بإنشاء شريط
    • فو يدعو بار
      • يحتاج الشريط إلى Bim (خدمة، مستودع، …)، لذلك:
      • شريط يخلق بيم
      • شريط يفعل شيئا

باستخدام حقن التبعية

إليك كيفية عمل الكود الذي يستخدم DI تقريبًا:

  • يحتاج التطبيق إلى Foo، والذي يحتاج إلى Bar، والذي يحتاج إلى Bim، لذلك:
  • يقوم التطبيق بإنشاء Bim
  • يقوم التطبيق بإنشاء شريط ويعطيه Bim
  • ينشئ التطبيق Foo ويعطيه Bar
  • يستدعي التطبيق Foo
    • فو يدعو بار
      • شريط يفعل شيئا

يتم قلب التحكم في التبعيات من الشخص الذي يتم استدعاؤه إلى الشخص الذي يتصل.

ماذا تحل من مشكلات؟

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

السابق:لنفترض أن تطبيقك يخزن الملف الذي قام المستخدم بتحميله في Google Drive، مع DI قد يبدو رمز وحدة التحكم الخاصة بك كما يلي:

class SomeController
{
    private $storage;

    function __construct(StorageServiceInterface $storage)
    {
        $this->storage = $storage;
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

class GoogleDriveService implements StorageServiceInterface
{
    public function authenticate($user) {}
    public function putFile($file) {}
    public function getFile($file) {}
}

عندما تتغير متطلباتك، على سبيل المثال، بدلاً من GoogleDrive، يُطلب منك استخدام Dropbox.ما عليك سوى كتابة تطبيق Dropbox لـ StorageServiceInterface.ليس عليك إجراء أي تغييرات في وحدة التحكم طالما أن تطبيق Dropbox يلتزم بواجهة StorageServiceInterface.

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

بدلاً من ذلك، إذا كان لديك فئة وحدة التحكم لإنشاء كائن التخزين باستخدام ملف new الكلمة الرئيسية مثل هذا:

class SomeController
{
    private $storage;

    function __construct()
    {
        $this->storage = new GoogleDriveService();
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

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

متى يكون مناسبا ومتى لا؟في رأيي أنك تستخدم DI عندما تعتقد أن هناك (أو يمكن أن يكون هناك) تطبيقات بديلة لفئة ما.

التحدث بالبرمجة

IoC بعبارات سهلة:إنه استخدام الواجهة كوسيلة لشيء محدد (مثل حقل أو معلمة) كحرف بدل يمكن استخدامه بواسطة بعض الفئات.يسمح بإعادة استخدام الكود.

على سبيل المثال، لنفترض أن لدينا فئتين: كلب و قطة.كلاهما يشتركان في نفس الصفات/الحالات:العمر والحجم والوزن.لذلك بدلاً من إنشاء فئة خدمة تسمى خدمة الكلاب و خدمة القط, ، يمكنني إنشاء واحد يسمى خدمة الحيوان الذي يسمح باستخدام Dog and Cat فقط إذا كانوا يستخدمون الواجهة IAnimal.

ومع ذلك، من الناحية العملية، فإن الأمر ينطوي على بعض التراجع.

أ) معظم المطورين لا يعرفون كيفية استخدامه.على سبيل المثال، يمكنني إنشاء فئة تسمى عميل و يمكنني الإنشاء تلقائيًا (باستخدام أدوات IDE) تسمى واجهة ICustomer.لذلك، ليس من النادر العثور على مجلد مليء بالفئات والواجهات، بغض النظر عما إذا كان سيتم إعادة استخدام الواجهات أم لا.يطلق عليه المتضخمة.قد يجادل بعض الناس بأنه "قد نتمكن من استخدامه في المستقبل".:-|

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

ب.1) إذا أضفت trainDays() إلى الخدمة خدمة الحيوان فهو يعمل أيضًا مع القطط وهو غير صالح على الإطلاق.

ب.2) يمكنني إضافة شرط فيه trainDays() حيث يقوم بتقييم الفئة المستخدمة.لكنه سوف يكسر IoC تمامًا.

ب.3) يمكنني إنشاء فئة جديدة من الخدمة تسمى خدمة الكلاب فقط للوظيفة الجديدة.ولكنه سيزيد من قابلية صيانة الكود لأنه سيكون لدينا فئتان من الخدمة (مع وظائف مماثلة) لـ كلب وهذا سيء.

أعجبني هذا التوضيح: http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/

يبدأ الأمر بشكل بسيط ويظهر أمثلة التعليمات البرمجية أيضًا.

enter image description here

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

ألا يكفي أن يعرف X أنه يستخدم شيئًا له سلوك Y وأساليبه وخصائصه وما إلى ذلك دون معرفة من ينفذ السلوك فعليًا؟

من خلال استخراج تعريف مجرد للسلوك الذي يستخدمه X في Y، كما هو موضح أدناه، والسماح للمستهلك X باستخدام مثيل لذلك بدلاً من Y، يمكنه الاستمرار في القيام بما يفعله دون الحاجة إلى معرفة التفاصيل المتعلقة بـ Y.

enter image description here

في الرسم التوضيحي أعلاه، يقوم Y بتنفيذ I وX يستخدم مثيل I.في حين أنه من الممكن أن X لا يزال يستخدم Y، إلا أن الأمر المثير للاهتمام هو أن X لا يعرف ذلك.إنه يعرف فقط أنه يستخدم شيئًا ينفذ I.

اقرأ المقالة للحصول على مزيد من المعلومات ووصف المزايا مثل:

  • لم يعد X يعتمد على Y بعد الآن
  • أكثر مرونة، يمكن تحديد التنفيذ في وقت التشغيل
  • عزل وحدة التعليمات البرمجية، واختبار أسهل

...

أفهم أن الإجابة قد تم تقديمها هنا بالفعل.لكنني ما زلت أعتقد أن بعض الأساسيات حول انقلاب السيطرة يجب مناقشتها هنا بشكل مطول لقراء المستقبل.

تم بناء انقلاب التحكم (IoC) على مبدأ بسيط للغاية يسمى مبدأ هوليوود.ويقول ذلك،

لا تتصل بنا، ونحن سوف نتصل بك

ما يعنيه هو أنك لا تذهب إلى هوليوود لتحقيق حلمك، بل إذا كنت جديرًا بذلك، فسوف تجدك هوليوود وتحقق حلمك.مقلوب إلى حد كبير ، هاه؟

الآن عندما نتحدث عن مبدأ IoC، فإننا ننسى هوليوود.بالنسبة لـ IoC، يجب أن يكون هناك ثلاثة عناصر، أنت وهوليوود ومهمة ترغب في تحقيق حلمك.

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

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

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

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

Laravel وEJB هما مثالان على مثل هذه الأطر.

مرجع:

https://martinfowler.com/bliki/InversionOfControl.html

https://en.wikipedia.org/wiki/Inversion_of_control

يدور انقلاب التحكم حول نقل التحكم من المكتبة إلى العميل.يكون الأمر أكثر منطقية عندما نتحدث عن عميل يقوم بحقن (تمرير) قيمة دالة (تعبير لامدا) في وظيفة ذات ترتيب أعلى (وظيفة المكتبة) تتحكم (تغير) في سلوك وظيفة المكتبة.يمكن أيضًا اعتبار العميل أو إطار العمل الذي يقوم بإدخال تبعيات المكتبة (التي تحمل السلوك) في المكتبات IoC

  1. إذن رقم 1 فوق. ما هو انقلاب السيطرة؟

  2. الصيانة هي الشيء الأول الذي يحله بالنسبة لي.إنه يضمن أنني أستخدم واجهات بحيث لا يكون هناك فئتان حميمتان مع بعضهما البعض.

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

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

public class MessagePublisher<RECORD,MESSAGE>
{
    public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
    {
      //setup
    }
}

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

أوه نعم، هناك مخاوف بشأن القابلية للاختبار، لكنها ثانوية بالنسبة لفوائد IoC/DI.

أنا بالتأكيد أحب IoC/DI.

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

يُطلق على إنشاء كائن داخل الفصل اسم الاقتران الضيق، ويزيل Spring هذه التبعية باتباع نمط التصميم (DI/IOC).في أي كائن من الفئة تم تمريره في المُنشئ بدلاً من إنشائه في الفصل.علاوة على ذلك، نعطي متغيرًا مرجعيًا للفئة الفائقة في المُنشئ لتحديد بنية أكثر عمومية.

باستخدام IoC، لن تقوم بتحديث كائناتك.سوف تقوم حاوية IoC الخاصة بك بذلك وتدير عمرها الافتراضي.

إنه يحل مشكلة الاضطرار إلى تغيير كل إنشاء مثيل لنوع واحد من الكائنات يدويًا إلى نوع آخر.

يكون ذلك مناسبًا عندما تكون لديك وظائف قد تتغير في المستقبل أو قد تكون مختلفة اعتمادًا على البيئة أو التكوين المستخدم فيها.

لفهم هذا المفهوم، يتضمن انعكاس التحكم (IoC) أو مبدأ انعكاس التبعية (DIP) نشاطين:التجريد، والانعكاس.يعد حقن التبعية (DI) مجرد إحدى طرق الانعكاس القليلة.

لقراءة المزيد عن هذا يمكنك قراءة مدونتي هنا

  1. ما هذا؟

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

  1. ماذا تحل من مشكلات؟

فيما يتعلق بالبرمجة، تحاول IoC حل التعليمات البرمجية المتجانسة من خلال جعلها معيارية، وفصل أجزاء مختلفة منها، وجعلها قابلة للاختبار.

  1. متى يكون مناسبا ومتى لا؟

يكون ذلك مناسبًا في معظم الأوقات، إلا إذا كان لديك موقف تريد فيه فقط رمزًا متجانسًا (مثل برنامج بسيط جدًا)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top