سؤال

أنا أفهم فوائد حقن التبعية نفسها.لنأخذ الربيع على سبيل المثال.أفهم أيضًا فوائد ميزات Spring الأخرى مثل AOP، والمساعدين من مختلف الأنواع، وما إلى ذلك.أنا فقط أتساءل، ما هي فوائد تكوين XML مثل:

<bean id="Mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="John" class="foo.bar.Male">
  <property name="girlfriend" ref="Mary"/>
</bean>

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

Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);

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


تحديث:
في حالة

IService myService;// ...
public void doSomething() {  
  myService.fetchData();
}

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

سيكون من المثير للاهتمام حقًا رؤية جزء صغير من التكوين لـ IoC يوضح فوائده.أنا أستخدم Spring منذ فترة ولا أستطيع تقديم مثل هذا المثال.ويمكنني عرض أسطر مفردة توضح فوائد السبات وdwr وأطر العمل الأخرى التي أستخدمها.


التحديث 2:
أدرك أنه يمكن تغيير تكوين IoC دون إعادة الترجمة.هل هي حقا فكرة جيدة؟أستطيع أن أفهم عندما يريد شخص ما تغيير بيانات اعتماد قاعدة البيانات دون إعادة الترجمة - فقد لا يكون مطورًا.في ممارستك، كم مرة قام شخص آخر غير المطور بتغيير تكوين IoC؟أعتقد أنه بالنسبة للمطورين لا يوجد أي جهد لإعادة ترجمة تلك الفئة المعينة بدلاً من تغيير التكوين.وبالنسبة لغير المطورين، ربما ترغب في جعل حياته أسهل وتوفير بعض ملفات التكوين الأكثر بساطة.


التحديث 3:

التكوين الخارجي لرسم الخرائط بين الواجهات وتطبيقاتها الملموسة

ما هو الجيد في جعله موسعًا؟أنت لا تجعل جميع التعليمات البرمجية الخاصة بك خارجية، بينما يمكنك ذلك بالتأكيد - فقط ضعها في ملف ClassName.java.txt، وقم بقراءتها وتجميعها يدويًا بسرعة - واو، لقد تجنبت إعادة الترجمة.لماذا يجب تجنب التجميع؟!

يمكنك توفير وقت الترميز لأنك توفر التعيينات بشكل تصريحي، وليس في التعليمات البرمجية الإجرائية

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

يسمح مبدأ عكس التحكم باختبار الوحدة بسهولة لأنه يمكنك استبدال التطبيقات الحقيقية بتطبيقات مزيفة (مثل استبدال قاعدة بيانات SQL بقاعدة بيانات في الذاكرة)

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

mary = new FakeFemale();

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

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


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

هل كانت مفيدة؟

المحلول

بالنسبة لي، أحد الأسباب الرئيسية لاستخدام IoC (والاستفادة من التكوين الخارجي) هو حول المجالين التاليين:

  • اختبارات
  • صيانة الإنتاج

اختبارات

إذا قمت بتقسيم الاختبار إلى 3 سيناريوهات (وهو أمر طبيعي إلى حد ما في التطوير واسع النطاق):

  1. وحدة التجارب
  2. اختبار التكامل
  3. اختبار الصندوق الأسود

ما تريد القيام به هو بالنسبة لسيناريوهي الاختبار الأخيرين (التكامل والصندوق الأسود)، عدم إعادة ترجمة أي جزء من التطبيق.

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

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

إنتاج

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

ملخص

الفوائد الرئيسية للتكوين الخارجي لـ IoC تأتي من منح الآخرين (غير المطورين) القدرة على تكوين تطبيقك، ومن خلال تجربتي فإن هذا مفيد فقط في ظل مجموعة محدودة من الظروف:

  • يتم توزيع التطبيق على مواقع/عملاء متعددين حيث ستختلف البيئات.
  • تحكم محدود في التطوير/الإدخال في بيئة الإنتاج والإعداد.
  • سيناريوهات الاختبار

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

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

ملحوظة:يشير التطبيق إلى الحل الكامل (وليس فقط الملف القابل للتنفيذ)، وبالتالي فإن كافة الملفات المطلوبة لتشغيل التطبيق.

نصائح أخرى

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

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

نقاط قوة النظام المبني باستخدام أنماط DI:

  1. يعد إعادة استخدام كود DI أسهل بكثير حيث يتم استقراء الوظيفة "المعتمدة" في واجهات محددة جيدًا، مما يسمح بتوصيل الكائنات المنفصلة التي يتم التعامل مع تكوينها بواسطة منصة تطبيق مناسبة بكائنات أخرى حسب الرغبة.
  2. يعد اختبار كود DI أسهل بكثير.يمكن اختبار الوظيفة التي يعبر عنها الكائن في صندوق أسود عن طريق إنشاء كائنات "وهمية" تنفذ الواجهات المتوقعة بواسطة منطق التطبيق الخاص بك.
  3. رمز DI أكثر مرونة.إنه رمز مقترن بشكل غير محكم - إلى أقصى الحدود.يسمح هذا للمبرمج باختيار واختيار كيفية توصيل الكائنات بناءً على واجهاتها المطلوبة من جهة وواجهاتها المعبر عنها من جهة أخرى.
  4. التكوين الخارجي (Xml) لكائنات DI يعني أنه يمكن للآخرين تخصيص التعليمات البرمجية الخاصة بك في اتجاهات غير متوقعة.
  5. يعد التكوين الخارجي أيضًا فصلًا عن نمط الاهتمام حيث يمكن معالجة جميع مشكلات تهيئة الكائن وإدارة الترابط المتبادل للكائن بواسطة خادم التطبيق.
  6. لاحظ أن التكوين الخارجي غير مطلوب لاستخدام نمط DI، فبالنسبة للتوصيلات البينية البسيطة، غالبًا ما يكون كائن البناء الصغير كافيًا.هناك مقايضة في المرونة بين الاثنين.لا يعد كائن المنشئ خيارًا مرنًا مثل ملف التكوين المرئي خارجيًا.يجب على مطور نظام DI أن يزن مزايا المرونة مقارنة بالسهولة، مع الحرص على أن التحكم الدقيق في بناء الكائن على نطاق صغير كما هو موضح في ملف التكوين قد يزيد من تكاليف الارتباك والصيانة في المستقبل.

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

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

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

باختصار، تعد التطبيقات القائمة على DI واسعة النطاق أسهل في تصحيح الأخطاء وأسهل في الفهم.على الرغم من أن تكوين Xml لم يتم "فحص وقت الترجمة"، فإن جميع خدمات التطبيق التي يعرفها هذا المؤلف ستزود المطور برسائل خطأ إذا حاول إدخال كائن له واجهة غير متوافقة في كائن آخر.ويوفر معظمها ميزة "الفحص" التي تغطي جميع تكوينات الكائنات المعروفة.يتم ذلك بسهولة وسرعة عن طريق التحقق من أن الكائن الذي سيتم حقنه A ينفذ الواجهة التي يتطلبها الكائن B لجميع عمليات حقن الكائنات التي تم تكوينها.

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

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

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

ومع ذلك، فإن تكوين XML يعد أمرًا يضايقني بعض الشيء...أحاول تجنب ذلك بأي ثمن.

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

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

بالإضافة إلى ذلك، يمكن قراءة ملف XML في واجهة المستخدم الرسومية أو أي أداة أخرى ومعالجته بسهولة بشكل عملي.كيف يمكنك أن تفعل ذلك مع مثال التعليمات البرمجية؟

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

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

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

علاوة على ذلك، من الأسهل كثيرًا إجراء عمليات تهيئة معقدة باستخدام حاوية DI بدلاً من القيام بها بنفسك.على سبيل المثال، أساعد في استخدام XFire (وليس CeltiXFire، فنحن نستخدم Java 1.4 فقط).استخدم التطبيق Spring، لكنه استخدم للأسف آلية تكوين XFire Services.xml.عندما احتاجت مجموعة من العناصر إلى الإعلان عن أنها تحتوي على صفر أو أكثر من المثيلات بدلاً من مثيل واحد أو أكثر، كان علي تجاوز بعض كود XFire المقدم لهذه الخدمة المحددة.

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

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

<bean id="base" parent="RootXFireBean">
    <property name="secondProperty" ref="secondBean" />
</bean>

<bean id="secondBean" parent="secondaryXFireBean">
    <property name="firstProperty" ref="thirdBean" />
</bean>

<bean id="thirdBean" parent="thirdXFireBean">
    <property name="secondProperty" ref="myNewBean" />
</bean>

<bean id="myNewBean" class="WowItsActuallyTheCodeThatChanged" />

بدلا من ذلك، بدا الأمر أكثر مثل هذا:

public class TheFirstPointlessClass extends SomeXFireClass {
    public TheFirstPointlessClass() {
        setFirstProperty(new TheSecondPointlessClass());
        setSecondProperty(new TheThingThatWasHereBefore());
    }
}

public class TheSecondPointlessClass extends YetAnotherXFireClass {
    public TheSecondPointlessClass() {
        setFirstProperty(TheThirdPointlessClass());
    }
}

public class TheThirdPointlessClass extends GeeAnotherXFireClass {
    public TheThirdPointlessClass() {
        setFirstProperty(new AnotherThingThatWasHereBefore());
        setSecondProperty(new WowItsActuallyTheCodeThatChanged());
    }
}

public class WowItsActuallyTheCodeThatChanged extends TheXFireClassIActuallyCareAbout {
    public WowItsActuallyTheCodeThatChanged() {
    }

    public overrideTheMethod(Object[] arguments) {
        //Do overridden stuff
    }
}

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

لدي إجابتك

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

حالات الاستخدام المفيدة الأخرى فيما يتعلق بنظام البناء والتكوينات الخارجية:

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

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

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

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

يمكنك إدخال تطبيق جديد لصديقتك.لذلك يمكن حقن أنثى جديدة دون إعادة ترجمة التعليمات البرمجية الخاصة بك.

<bean id="jane" class="foo.bar.HotFemale">
  <property name="age" value="19"/>
</bean>
<bean id="mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="john" class="foo.bar.Male">
  <property name="girlfriend" ref="jane"/>
</bean>

(يفترض ما ورد أعلاه أن Female وHotFemale ينفذان نفس واجهة GirlfFriend)

في عالم .NET، توفر معظم أطر عمل IoC كلاً من تكوين XML والتعليمات البرمجية.

على سبيل المثال، يستخدم StructureMap وNinject واجهات سلسة لتكوين الحاويات.لم تعد مقيدًا باستخدام ملفات تكوين XML.يعتمد Spring، الموجود أيضًا في .NET، بشكل كبير على ملفات XML نظرًا لأنها واجهة التكوين الرئيسية التاريخية، ولكن لا يزال من الممكن تكوين الحاويات برمجيًا.

سهولة الجمع بين التكوينات الجزئية في التكوين النهائي الكامل.

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

  UI-context.xml
  Model-context.xml
  Controller-context.xml

أو قم بالتحميل باستخدام واجهة مستخدم مختلفة وبعض وحدات التحكم الإضافية:

  AlternateUI-context.xml
  Model-context.xml
  Controller-context.xml
  ControllerAdditions-context.xml

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

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

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

من منظور الربيع يمكنني أن أعطيك إجابتين.

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

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

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

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

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

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

IService myService;
// ...
public void doSomething() {
  myService.fetchData();
}

(لاحظ أن نوع myService هو IService - واجهة، وليس تطبيقًا ملموسًا).الآن قد يكون من السهل السماح لحاوية IoC الخاصة بك بتوفير المثيل الملموس الصحيح لـ IService أثناء التهيئة تلقائيًا - عندما يكون لديك العديد من الواجهات والعديد من التطبيقات، قد يكون القيام بذلك يدويًا أمرًا مرهقًا.الفوائد الرئيسية لحاوية IoC (إطار عمل حقن التبعية) هي:

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

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

أحد الأسباب الأكثر جاذبية هو "مبدأ هوليوود":لا تتصل بنا، ونحن سوف نتصل بك.ليس من الضروري أن يقوم المكون بإجراء عمليات البحث عن المكونات والخدمات الأخرى بنفسه؛بدلاً من ذلك يتم تقديمها إليه تلقائيًا.في Java، هذا يعني أنه لم يعد من الضروري إجراء عمليات بحث JNDI داخل المكون.

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

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