حقن التبعيات في JavaScript: دليل كامل مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

حقن التبعيات (Dependency Injection) في JavaScript: دليل شامل



حقن التبعيات (Dependency Injection - DI) هو نمط تصميم قوي يشكل أساس مبدأ عكس التحكم (Inversion of Control - IoC). بدلاً من أن يقوم الكائن بإنشاء تبعياته بنفسه، يقوم DI "بحقنها" من الخارج. وهذا يجعل الكود أكثر مرونة وقابلية للاختبار والصيانة. في هذه المقالة، سنشرح كيفية تنفيذ حقن التبعيات في JavaScript و Node.js باستخدام أمثلة بسيطة وواضحة.



ما هو حقن التبعيات (Dependency Injection) ولماذا هو مطلوب؟



تخيل أن لديك كلاس UserService يتعامل مع قاعدة بيانات. بدون DI، على الأرجح ستقوم بإنشاء نسخة من قاعدة البيانات مباشرة داخل الخدمة:



class UserService {  constructor() {    this.db = new Database(); // ارتباط صلب  }

getUser(id) { return this.db.findUser(id); }}


هذا الكود ينتهك مبدأ عكس التبعيات (Dependency Inversion Principle). عند اختبار UserService، لن تتمكن من استبدال قاعدة البيانات الحقيقية بكائن وهمي (mock) دون تغيير كود الكلاس. DI يحل هذه المشكلة:



class UserService {  constructor(database) {    this.db = database; // التبعية تُمرر من الخارج  }

getUser(id) { return this.db.findUser(id); }}

// الاستخدامconst db = new Database();const userService = new UserService(db);


المزايا الرئيسية لـ DI:

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


طرق حقن التبعيات في JavaScript



في JavaScript، هناك ثلاث طرق رئيسية لحقن التبعيات:



1. الحقن عبر المُنشئ (Constructor Injection)

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



class Logger {  log(message) {    console.log(`[LOG]: ${message}`);  }}

class OrderService { constructor(logger) { this.logger = logger; }

createOrder(data) { this.logger.log('تم إنشاء طلب جديد'); // منطق إنشاء الطلب }}

const logger = new Logger();const orderService = new OrderService(logger);orderService.createOrder({ product: 'Laptop', price: 1500 });


2. الحقن عبر الضابطات (Setter Injection)

يتم تعيين التبعيات بعد إنشاء الكائن من خلال دوال الضبط (setter methods). مناسب للتبعيات الاختيارية.



class EmailService {  constructor() {    this.transporter = null;  }

setTransporter(transporter) { this.transporter = transporter; }

send(email) { if (!this.transporter) { throw new Error('Transporter غير مُعد'); } this.transporter.sendMail(email); }}

const emailService = new EmailService();emailService.setTransporter(someMailTransporter);


3. الحقن عبر الواجهة (Interface Injection - بشكل تقريبي)

لا توجد واجهات أصلية في JavaScript، ولكن يمكن استخدام TypeScript أو التوثيق لوصف العقود. عمليًا، يتلخص هذا في التحقق من وجود الدوال.



إنشاء حاوية DI بسيطة في Node.js



لإدارة التبعيات في التطبيقات الكبيرة، من المناسب استخدام حاوية DI (DI-Container). تقوم بتخزين جميع التبعيات وحلها تلقائيًا. إليك تطبيق بسيط:



class Container {  constructor() {    this.services = new Map();    this.singletons = new Map();  }

// تسجيل مصنع (factory) للخدمة register(name,

المدونات

توصيات الكتب