حقن التبعية في Kotlin عمليًا: دليل شامل

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

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

ابدأ الدورة

مقدمة: ما هو حقن التبعية ولماذا هو ضروري في Kotlin؟

\n

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

\n

تخيل أنك تكتب تطبيقًا لطلب البيتزا. لديك كلاس OrderService يجب أن يرسل إشعارات. بدون DI، سيبدو هكذا:

\n
class OrderService {\n    private val notifier = EmailNotifier() // ارتباط صارم\n\n    fun placeOrder(order: Order) {\n        // منطق الطلب\n        notifier.send("تم استلام طلبك!")\n    }\n}
\n

المشكلة: لن تتمكن بسهولة من استبدال EmailNotifier بـ SmsNotifier أو اختبار OrderService دون إرسال بريد إلكتروني فعلي. يحل DI هذه المشكلة عن طريق حقن التبعية عبر المُنشئ:

\n
class OrderService(private val notifier: Notifier) {\n    fun placeOrder(order: Order) {\n        notifier.send("تم استلام طلبك!")\n    }\n}
\n

الآن OrderService لا يعرف كيف يتم إرسال الإشعار بالضبط. هذا هو جوهر DI: ارتباط ضعيف وقابلية عالية لإعادة الاستخدام.

\n\n

الطرق الرئيسية لتنفيذ DI في Kotlin

\n

توجد ثلاث طرق رئيسية لحقن التبعيات في Kotlin: الحقن اليدوي، واستخدام المكتبات (Koin، Dagger 2)، والحقن عبر أطر العمل (مثل Spring). دعنا ننظر إلى كل منها عمليًا.

\n\n

1. الحقن اليدوي للتبعيات (Manual DI)

\n

أبسط طريقة هي تمرير التبعيات عبر المُنشئ أو الدوال الضابطة (setters). هذا لا يتطلب مكتبات إضافية وهو مثالي للمشاريع الصغيرة.

\n

مثال: لننشئ خدمة بسيطة لمعالجة المدفوعات.

\n
// واجهة بوابة الدفع\ninterface PaymentGateway {\n    fun process(amount: Double): Boolean\n}\n\n// تنفيذ عبر PayPal\nclass PayPalGateway : PaymentGateway {\n    override fun process(amount: Double): Boolean {\n        println("معالجة الدفع $amount عبر PayPal")\n        return true\n    }\n}\n\n// خدمة الطلبات مع حقن التبعية\nclass OrderService(private val paymentGateway: PaymentGateway) {\n    fun checkout(total: Double) {\n        if (paymentGateway.process(total)) {\n            println("تم تأكيد الطلب!")\n        }\n    }\n}\n\n// نقطة الدخول — "مصنع" أو "حاوية"\nfun main() {\n    val gateway = PayPalGateway()\n    val service = OrderService(gateway)\n    service.checkout(100.0)\n}
\n

الإيجابيات: البساطة، التحكم الكامل، لا تبعيات على المكتبات.
\nالسلبيات: مع نمو المشروع، تصبح الإدارة اليدوية لجميع التبعيات معقدة (تحتاج إلى إنشاء "حاوية" أو "مصنع" يدويًا).

\n\n

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

\n

Koin هي مكتبة خفيفة الوزن لـ DI مكتوبة بلغة Kotlin. لا تستخدم الانعكاس (reflection) ولا تتطلب توليد كود، مما يجعلها مثالية للمشاريع الصغيرة والمتوسطة.

\n

التثبيت: أضف في build.gradle.kts:

\n
implementation("io.insert-koin:koin-core:3.5.6")
\n

مثال على الاستخدام:

\n
import org.koin.core.context.startKoin\nimport org.koin.dsl.module\n\n// وحدة التبعيات\nval appModule = module {\n    single<PaymentGateway> { PayPalGateway() }\n    factory { OrderService(get()) } // get() تحصل تلقائيًا على PaymentGateway\n}\n\nfun main() {\n    startKoin {\n        modules(appModule)\n    }\n\n    // الحصول على الخدمة من الحاوية\n    val service: OrderService = org.koin.core.component.get()\n    service.checkout(200.0)\n}
\n

المفاهيم الأساسية في Koin:

\n
    \n
  • single — ينشئ مثيلًا واحدًا (singleton)

المدونات

توصيات الكتب