اجابة السؤال الأول
تخيل موقع حسوب io به كلاس موضوع (class Topic)، ويحتاج للأتصال بالداتا بيز لجلب المواضيع الموجودة أو حفظ موضوع جديد
هذا الأتصال سيحتاج الي بيانات معينة مثل نوع الداتا بيز واسم المستخدم وكلمة المرور
بدون ال Dependency Injection سيكون الكود بهذا الشكل
class Topic{
private DBConn=new DBConn(dbname="dummy", user="dummy",pass="dummy");
}
لا مشكلة في هذا الكود سوي ان في كل مرة تقوم بتغير الداتا بيز ستحتاج الي تغيير البيانات بجميع الكلاسات وبفرض وجود داتا بيز لل test وداتا بيز لل production وكل منهما ببيانات مختلفة سيصبح تغيير البيانات امر ممل
لنعدل الكود قليلا فبدلا من وضع البيانات من داخل الكلاس سنقوم باعطاء البيانات للكلاس من الخارج
class Topic{
private DBConn dbConn=null;
public Topic(dbname, user, pass){
dbConn=new DBConn(dbname,user,pass)
}
}
هذا الكود افضل قليلا من السابق واصبح من الممكن تغيير البيانات بسهولة لكن ماذا عن جميع الكلاسات الموجودة لاحظ ان جميع الكلاسات تتصل بنفس الداتا بيز فبدلا من تمرير البيانات بهذا الشكل
Topic topic=new Topic(dbname,user,pass);
User user=new User(dbname,user,pass);
Community community=new Community(dbname,user,pass);
Comment comment=new Comment(dbname,user,pass);
لماذا لانقوم بتمرير كائن الأتصال (DBConn Object) ذات نفسه هكذا
class Topic{
private DBConn dbConn=null;
public Topic(dbConnParam){
this.dbConn=dbConnParam
}
وبتالي يصبح تمرير البيانات لجميع الكلاسات هكذا
DBConn dbConn=new DBConn(dbname,user,pass);
Topic topic=new Topic(dbConn);
User user=new User(dbConn);
Community community=new Community(dbConn);
Comment comment=new Comment(dbConn);
الان هذا الكود اصبح يطبق طريقة ال Dependency Injection ففي البداية كان الكلاسات تعتمد علي كائن الأتصال (Dependency ) وتقوم بانشائه داخليا لكن الكود الاخير يقوم بحقن/ تمرير (Injection ) كائن الاتصال من الخارج . التمرير أو الحقن يمكن أن يتم عن طريق constructor Injection أو setter Injection أى هكذا
class Topic{
private DBConn dbConn=null;
public Topic(){
}
public setDBConn(dbConnParam){
this.dbConn=dbConnParam;
}
}
لنأخذ الموضوع خطوة ابعد، ما رايك لو قمنا بأنشاء ملف للبيانات أو الأعدادات (config file ) وكتبنا به بيانات الأتصال بحيث يقوم كود ما بقراءة الملف وعندما يجد كائن يحتاج للأتصال بالداتا بيز يقوم بحقن البياناات
//config file
db_connction_setting{
name: "dummy"
user: "dummy"
pass: "dummy"
}
DBConn dbConn=Config.Read("db_connction_setting")
الخلاصة هي أن Dependency Injection تقوم بتمرير أو حقن الكود المعتمد عليه (Dependency ) من الخارج بال runtime بدلا من أنشائه بالداخل ب compile time لسهولة تغييره فيما بعد
اجابة السؤال الثاني
لا توجد طريقة لاختصار التعلم وطبيعي أن تشعر بالتشعب والتوهان فى البداية وربما يكون الكتاب الذي تقراه لا يناسب مستواك بعد
التعليقات