5/5 (1)

سلام خدمت شما دوستان سایت اسمارت دولوپرز. تو این آموزش میخام با مفهموم Dependency Injection یا به اختصار DI شما رو آشنا کنم.

Dependency Injection چیست

Dependency injection چیست ؟

Dependency Injection یک نوع تکنیکه معماریه نرم افزاره که به طور گسترده در برنامه نویسی استفاده میشه . با پیروی کردن از قوانین Dependency Injection یکی از پایه‌ای ترین اصول معماری خوب نرم افزار رو رعایت کردین .

کلاس ها معمولا به برای ایجاد شدن به رفرنس هایی از کلاس های دیگه نیاز دارند . برای مثال کلاس Car ممکنه به یک رفرنس یا ارجاع به کلاس Engine نیاز داشته باشه تا نولید بشه . و به این کلاس‌هایی که بهشون رفرنس داده میشه  dependencies  میگن (کلاس Engine ) . در این مثال کلاس Car وابسته به یک نمونه از کلاس Engine  هست تا روشن بشه.

Android Dependency Injection

سه روش وجود داره تا کلاس ها به آبجکت هایی که نیاز دارند دسترسی داشته باشند :

  1. کلاس، آبجکتی رو که بهش وابستگی داره ، خودش تولید کنه . در مثال بالا مثلا کلاس Car خودش کلاس Engine رو ایجاد و مقدار دهی کنه.
  2. نیاز خودش رو از جاهای دیگه ای دریافت کنه . برای مثال بعضی از اجزای اندروید مثل getter های کلاس Context و ()getSystemServise از این روش استفاده میکنند .
  3. یک کلاس میتونه آبجکت هایی رو که نیاز داره از طریق پارامتر هایی که به Constructor یا متدهاش پاس میشن دریافت  کنه . در مثال بالا کلاس Car میتونه کلاس Engine رو از طریق Constructor دریافت کنه .

گزینه سوم همون Dependency Injection هستش . با این روش شما خودتون وابستگی های ( dependencies ) یک کلاس رو، به جای اینکه اون کلاس خودش dependencies هایی رو که نیاز داره تولید کنه ، ایجاد و بهش پاس میکنید .

خب بذارید با یک مثال عملی شروع کنیم :

در این مثال کلاس Car بدون Dependency Injection تولید شده و خودش آبجکت Engine ی رو که نیاز داره تولید کرده :

این مثال یک نمونه از Dependency Injection نیست ، چون کلاس کار خودش آبجکت Engine ی رو که نیاز داشته تولید کرده . این کار میتونه باعث مشکلاتی بشه که عبارت اند از :

  • کلاس Car و کلاس Engine به طور عمیقی با هم جفت شدند و یک شی از کلاس Car فقط میتونه از یک نمونه از کلاس Engine استفاده کنه !( از زیر کلاس های کلاس Engine نمیتونه استفاده کنه ) . در این صورت اگه شما بخاید دو نوع آبجکت از کلاس Car داشته باشید که برای مثال یکیش از یک موتور الکتریکی استفاده کنه و دیگری از موتور بنزینی، باید علاوه بر ساخت دو زیر‌کلاس از کلاس Engine دو نوع کلاس Car هم تولید کنید که هرکدوم، از کلاس‌های Engine موردنظرشون استفاده کنند !
  • استفاده از این روش تست پذیری کلاس Car رو سخت میکنه . وقتی بخاین با استفاده از تست نوع موتور ماشین رو عوض کنید و تست کنید که کلاس Car چطور با نوعی دیگه از Engine کار میکنه این کار امکان پذیر نیست .

خب حالا چطور کاری کنیم که کلاس Car از Dependency Injection استفاده کنه ؟ مثال زیر رو ببینید :

چون کلاس Car به کلاس Engine وابستگی داره ما باید یک نمونه از کلاس Engine بسازیم و به constructor کلاس Car پاس کنیم .

خب حالا مزایای این کار که بر پایه‌ی Dependency Injection هست ، چیه ؟ 👇

  • قابلیت استفاده مجدد از کلاس Car . شما میتونید زیرکلاس های مختلفی از کلاس Engine رو به کلاس Car پاس کنید و کلاس Car با انواع مختلفی از موتورها قابل روشن شدن هست . برای مثال میتونید کلاس به اسم ElectronicEngine بسازید که از کلاس Engine مشتق شده باشه و این کلاس رو به سازنده کلاس Car پاس کنید و این ماشین با موتور الکتریکی کارش رو شروع میکنه ! وقتی شما از DI استفاده میکنید تنها کاری که نیازه انجام بدید اینه که نمونه آپدید شده ای از کلاس ElectronicEngine رو به کلاس Car پاس کنید و همچنان کلاس Car بدون تغییری به کار خودش ادامه میده !
  • ساخت تست برای کلاس Car آسون شده . برای مثال شما میتونید داخل تستتون یک زیر کلاس از Engine بسازید و با اون کلاس Car رو تست کنید .

دور روش برای Dependency Injection در اندروید وجود داره :

  • Constructor Injection : این همون روشیه که در مثال بالا استفاده کردیم .
  • Field Injection یا ( Setter Injection ) : در این روش Dependency Injection بعد از ساخته شدن کلاس توسط متد ها انجام میشه . این نوع رو در مثال زیر میبینیم :

انجام Dependency Injection به طور خودکار:

در مثال قبل شما dependencies  ها رو از کلاس های مختلف خودتون ساختید ، آماده و مقدار دهی کردید ، بدون اینکه از کتابخانه ای استفاده کنید. به این روش dependency injection by hand یا manual dependency injection میگن . در مثال قبل کلاس Car فقط به یک dependency نیاز داشت . اما اگه کلاس‌ها و dependency ها زیاد بشه manual dependency injection خسته کننده میشه . همینطور این روش یک سری مشکلات هم داره :

  •  در اپ های بزرگ مدیریت کردن تمام dependencies و ارتباطشون به درستی  کار سختیه و نیازمند کدنویسی اضافه زیادیه . در معماری های چند لایه این کار سخت تر هم میشه و برای ساخت آبجکتی برای لایه های بالاتر شما مجبورید که این آبجکت رو قبل از تولید این لایه های بسازید . و برای مثالی ساده هم میتونیم مثال Car رو عنوان کنیم که شما برای ساخت ماشین به اجزایی مثل شاسی ، نیروی محرکه و … و برای ساخت موتور نیاز به سیلندر ، شمع و … دارید . که باید همه این اجزا رو به صورت دستی برای کلاس Car فراهم کنید .

    زمان هایی که شما از قبل dependencies رو ایجاد نکردید( برای مثال زمانی که به جای ایجاد یک آبجکت با استفاده از کلمه new و نسبت دادن اون به یک متغیر فقط در خود همون سازنده یا متد اون شی رو new میکنید)  ، در این مواقع شما باید یک کلاس کمکی ایجاد کنید که مدریت طول عمر dependencies ها در مموری رو بر عهده بگیره.

برای حل این مشکلات کتابخانه هایی وجود دارند که کار ساخت و آماده کردن dependencies هارو برای ما به صورت خوکار انجام میدن .

برای مثال Dagger یکی از کتابخانه dependency injection هست که توسط گوگل پشتیبانی میشه . و میتونید برای این کار ازش استفاده کنید .

کدام روش را برای Dependency Injection انتخاب کنیم ؟

انتخاب روش دستی یا استفاده از Dagger به اندازه برنامه شما بستگی داره . اگه برنامتون زیاد بزرگ یا پیچیده نیست یا قرار نیست که پیچیده بشه ، استفاده از Dagger پیشنهاد نمیشه چون برنامه‎تون رو حجیم میکنه . در غیر این صورت پیشنهاد میکنم که از Dagger یا سایر کتابخونه ها استفاده کنید .

با استفاده از این جدول میتونید تشخصی بدید که کدوم روش رو انتخاب کنید .

سایز پروژه کوچک متوسط بزرگ
ابزار قابل استفاده Manual DI
Dagger
Dagger Dagger

با استفاده از این جدول هم میتونید سایز پروژه خوتون رو تشخصی بدید :

سایز پروژه کوچک متوسط بزرگ
تعداد صفحهات 1-3 4-7 +8

 

خب امیدوارم این آموزش هم براتون مفید واقع شده باشه . نظرات و پیشنهاداتون رو برامون بنویسید.

 

 

به این مطلب چه امتیازی میدهید ؟

اشتراک
باخبر شدن از
guest
0 Comments
Inline Feedbacks
View all comments