مقالات

تزریق وابستگی (DI) چیست؟ Dependency Injection به زبان ساده

تزریق وابستگی یا Dependency Injection (DI) یک الگوی طراحی است که در برنامه نویسی استفاده می‌شود تا وابستگی‌های موجود در یک کلاس را به صورت خارجی تزریق کند، به جای اینکه کلاس به‌طور مستقیم از این وابستگی‌ها استفاده کند. این کار باعث جدا شدن مفهوم‌های مختلف و کاهش وابستگی میان کدها می‌شود که کمک به مدیریت کد و ایجاد تست‌های واحد (Unit Tests) قوی‌تر می‌کند.

 

 

“ما را در اینستاگرام دنبال کنید”

در این مقاله از سری مقالات برنامه نویسی اندروید اومدیم در مورد تزریق وابستگی ، صحبت کنیم. پس با سایت ترولرن همراه باش.

“قبل از شروع مقاله، بگم که بعد از مطالعه این مطلب، از آموزش پروژه محور برنامه نویسی اندروید سایتمون یعنی دوره ژنرال اندروید غافل نشید.”

توی دوره ژنرال صفر تا صد تزریق وابستگی در اندروید رو در یک فصل کامل توضیح دادیم و همچنین توی پروژه های دیجی کالا و اسنپ فود به صورت عملی و پروژه محور از تزریق وابستگی استفاده کردیم و بطور کامل اون رو آموزش دادیم.

مقدمه

در اندروید، تزریق وابستگی بهبود قابلیت تست، قابلیت‌های قابل تعویض و افزایش خوانایی کد را به همراه دارد. از اندروید ۳ (نسخه SDK ۱۱) به بعد، Google کتابخانه‌ای به نام Hilt را معرفی کرده است که تزریق وابستگی را تسهیل می‌کند.

در اصول DI، معمولاً از یک Container (ظرف) استفاده می‌شود که اشیاء مورد نیاز به داخل آن تزریق می‌شوند و در هنگام نیاز به خروجی آن‌ها تولید می‌شوند. این کتابخانه‌ها با استفاده از تزریق وابستگی، مدیریت اشیاء و وابستگی‌ها را در برنامه آسان‌تر می‌کنند.

برای مثال، با استفاده از Hilt در اندروید، می‌توانید به جای ساختن و مدیریت اشیاء به صورت دستی، از امکانات تزریق وابستگی این کتابخانه برای تولید و مدیریت اشیاء بهره‌برداری کنید. این به شما امکان می‌دهد تا از یونیت تست‌های بهتری استفاده کنید و کدهایتان را بهبود دهید.

مزایای تزریق وابستگی

1. جدا کردن مفاهیم (Separation of Concerns)

با تزریق وابستگی، کلاس‌ها مشغول انجام کار خود هستند و از جزئیات اجرای وابستگی‌های خود آگاه نیستند. این باعث جدا سازی بخش‌های مختلف کد می‌شود و به تجزیه و تحلیل مفاهیم کمک می‌کند.

2. قابلیت تست بهتر (Better Testability)

با DI، می‌توان وابستگی‌های کلاس را با موک‌ها یا تعویض‌پذیر کردن اشیاء دیگر جایگزین کرد. این باعث می‌شود تست‌های واحد (Unit Tests) بهتری برای کد انجام شود.

3. کاهش وابستگی متقابل (Reduced Coupling)

وقتی که کلاس‌ها مستقیماً به یکدیگر وابسته نباشند و تنها به نقاط ورودی خود وابسته باشند، وابستگی‌های متقابل کاهش می‌یابد و تغییر در یک کلاس تأثیر کمتری روی دیگر کلاس‌ها دارد.

4. قابلیت تغییرپذیری (Increased Flexibility)

با DI ، می‌توان به سادگی وابستگی‌ها را تغییر داد یا بهبود بخشید بدون اینکه کدهای دیگر تحت تأثیر قرار گیرند.

معایب تزریق وابستگی

1. پیچیدگی اضافی (Additional Complexity)

اگر استفاده نادرستی از DI داشته باشید، کد ممکن است پیچیدگی اضافی به خود بگیرد و درک آن دشوار شود.

2. زمان و میزان تلاش اضافی (Extra Effort and Time)

DI نیازمند طراحی و تنظیم صحیح است. این می‌تواند زمان و تلاش اضافی برای پیاده‌سازی را به همراه داشته باشد.

در نهایت، تزریق وابستگی یک الگوی مهم در برنامه‌نویسی است که به‌عنوان یک ابزار برای مدیریت وابستگی‌ها و بهبود کیفیت کد مورد استفاده قرار می‌گیرد. استفاده‌ی درست از این الگو می‌تواند باعث بهبود قابلیت تست، انعطاف‌پذیری، و قابلیت تغییرپذیری کد شود.

 

 

استفاده از تزریق وابستگی در برنامه‌نویسی اندروید با کاتلین و کتابخانه Hilt

در برنامه‌نویسی اندروید با استفاده از زبان کاتلین، می‌توانید از Dependency Injection با استفاده از کتابخانه‌های مختلفی مانند Dagger و Hilt بهره ببرید. این کتابخانه‌ها به شما کمک می‌کنند تا DI را به صورت ساده‌تر و بهینه‌تر در پروژه‌های اندرویدی خود انجام دهید. در زیر، نحوه استفاده از تزریق وابستگی در برنامه‌نویسی اندروید با کاتلین و کتابخانه Hilt را توضیح می‌دهم:

مرحله 1: نصب Hilt

افزودن کتابخانه Hilt به فایل build.gradle ماژول برنامه:

implementation "com.google.dagger:hilt-android:2.39"
kapt "com.google.dagger:hilt-android-compiler:2.39"

مرحله 2: تنظیم Proguard (اختیاری)

اگر از Proguard یا R8 برای کاهش حجم کد استفاده می‌کنید، باید تنظیمات مناسبی برای حفظ کدهای مربوط به Hilt انجام دهید.

مرحله 3: اعمال تگ‌های Hilt

اعمال تگ‌های مربوط به Hilt در کلاس‌های مربوطه (برنامه و کامپوننت‌ها):

برای کلاس برنامه:

import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class MyApp : Application() {
    // کدهای دیگر
}

برای Activity:

import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    // کدهای دیگر
}

مرحله 4: تعریف کلاس‌ها و وابستگی‌ها

تعریف کلاس‌هایی که وابستگی‌ها در آنها تزریق می‌شوند:

import javax.inject.Inject

class UserService @Inject constructor() {
    fun doSomething() {
        // عملیات کاربری
    }
}

مرحله 5: استفاده از تزریق وابستگی

در Activity یا Fragment‌های خود، می‌توانید وابستگی‌ها را تزریق کنید:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var userService: UserService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // استفاده از وابستگی‌های تزریق شده
        userService.doSomething()
    }
}

این مراحل به طور ساده نحوه استفاده از Hilt و DI را نشان می‌دهد. با افزایش پیچیدگی پروژه، نیازمندی‌ها و وابستگی‌ها می‌توانند پیچیده‌تر شوند، اما Hilt با ابزارهای قدرتمندی که ارائه می‌دهد، این روند را ساده‌تر می‌کند. حتماً به مستندات رسمی Hilt مراجعه کنید تا نحوه تنظیمات پیشرفته‌تر و روش‌های پیچیده‌تر تزریق وابستگی را درک کنید.

بدون استفاده از کتابخانه‌های تزریق وابستگی

در برنامه اندروید میتوانیم بدون استفاده از هیچ گونه کتابخانه اضافه از تزریق وابستگی استفاده کنیم.در اینجا مثالی از تزریق وابستگی در کاتلین برای یک سناریو ساده آورده شده است:

فرض کنید یک کلاس UserService داریم که به یک دیتابیس نیاز دارد:

class DatabaseService {
    fun fetchData(): String {
        return "Data from database"
    }
}

class UserService(private val databaseService: DatabaseService) {
    fun getUserData(): String {
        return databaseService.fetchData()
    }
}

در اینجا، UserService به یک نمونه از DatabaseService به عنوان وابستگی‌اش نیاز دارد.

حالا در یک فایل اصلی:

fun main() {
    val databaseService = DatabaseService()
    val userService = UserService(databaseService)

    val userData = userService.getUserData()
    println(userData)
}

در این مثال، ما به صورت دستی یک نمونه از DatabaseService ایجاد کرده‌ایم و سپس این نمونه را به UserService تزریق کرده‌ایم.

این رویکرد بسیار ساده‌تر از DI با کتابخانه‌های پیشرفته‌تر است، اما برای پروژه‌های بزرگ‌تر و پیچیده‌تر، مدیریت وابستگی‌ها باعث افزایش پیچیدگی و دشواری می‌شود. کتابخانه‌های تزریق وابستگی مانند Hilt کار را ساده‌تر می‌کنند و از مزایا ویژه‌ای مانند ایجاد کدهای تست و تسهیل در تغییر وابستگی‌ها برخوردار می‌کنند.

و همچنین ممنون میشم از طریق ستاره‌های این پایین به این مقاله امتیاز بدی و اگه هر سوالی داشتی توی قسمت دیدگاه بپرس و قطعا بهت پاسخ میدیم.

‫5/5 ‫(1 نظر)
عاطفه امیری

View Comments

Recent Posts

بهینه‌سازی عملکرد اپلیکیشن‌های اندروید: راهنمای جامع و کاربردی

بهینه‌سازی عملکرد اپلیکیشن‌های اندروید یکی از مهم‌ترین فاکتورهایی است که برای کاربران در دنیای امروز…

4 ماه ago

سوالات مصاحبه‌ی استخدامی کاتلین همراه با جواب(قسمت چهارم)

مصاحبه‌ی استخدامی کاتلین یک فرصت برای ارزیابی مهارت‌ها و توانایی‌های یک برنامه‌نویس در توسعه اپلیکیشن‌های…

4 ماه ago

سوالات مصاحبه استخدام زبان کاتلین همراه با جواب(قسمت سوم)

مصاحبه استخدام زبان کاتلین یک فرصت برای ارزیابی مهارت‌ها و توانایی‌های یک برنامه‌نویس در توسعه…

4 ماه ago

سوالات مصاحبه استخدام کاتلین همراه با جواب(قسمت دوم)

مصاحبه استخدام کاتلین یک فرصت برای ارزیابی مهارت‌ها و توانایی‌های یک برنامه‌نویس در توسعه اپلیکیشن‌های…

5 ماه ago

سوالات مصاحبه استخدامی کاتلین همراه با جواب(قسمت اول)

مصاحبه استخدامی کاتلین یک فرصت برای ارزیابی مهارت‌ها و توانایی‌های یک برنامه‌نویس در توسعه اپلیکیشن‌های…

5 ماه ago

نوتیفیکیشن در اندروید: نحوه کار با آن در کاتلین

نوتیفیکیشن در اندروید امروزه یکی از قابلیت‌های مهم و پرکاربرد در اپلیکیشن‌های اندروید هستند. با…

5 ماه ago