DIP: بنیادی باتیں، ترقی میں انحصار کا الٹ

مصنف: IT Sectr اشاعت: 2026-05-12 مطالعے کا وقت: 9 منٹ

DIP (Dependency Inversion Principle) — SOLID کا پانچواں اصول جو ماڈیولز کے درمیان انحصار بنانے کے قوانین متعین کرتا ہے: اعلیٰ سطح کے ماڈیولز کو نیچی سطح کے ماڈیولز پر انحصار نہیں کرنا چاہیے، دونوں کو تجریدوں پر انحصار کرنا چاہیے۔ تجریدوں کو تفصیلات پر انحصار نہیں کرنا چاہیے — تفصیلات کو تجریدوں پر انحصار کرنا چاہیے۔ یہ اصول، رابرٹ مارٹن نے Clean Architecture (2017) میں بیان کیا، ڈھیلے جوڑے والے فن تعمیر کی بنیاد ہے۔ اس کتاب کے مطابق، انحصار کے الٹ کا اصول اطلاق کی تہوں کے درمیان سخت جوڑوں کو ختم کرتا ہے۔

اہم نکات

  • DIP — انحصار کے الٹ کا اصول، SOLID میں پانچواں، فن تعمیری حدود کے بارے میں
  • اعلیٰ سطح کے ماڈیولز کو نیچی سطح کے ماڈیولز درآمد نہیں کرنے چاہئیں — صرف تجریدیں
  • DIP ≠ DI: ڈیپینڈنسی انورژن ایک فن تعمیری اصول ہے، ڈیپینڈنسی انجکشن اسے لاگو کرنے کا ایک طریقہ ہے
  • تجریدیں اعلیٰ سطح کے ماڈیول کی ہوتی ہیں، نفاذ نیچی سطح کے ماڈیول کا
  • DIP کثیر سطحی فن تعمیر میں انحصار کے روایتی درجہ بندی کو الٹ دیتا ہے

DIP (ڈیپینڈنسی انورژن پرنسپل) کیا ہے؟

DIP (Dependency Inversion Principle) انحصار کے الٹ کا اصول ہے جو ماڈیولز کے درمیان انحصار کی سمت کے روایتی نقطہ نظر کو الٹ دیتا ہے۔ اعلیٰ سطح کے ماڈیولز (کاروباری منطق) کو براہ راست نیچی سطح کے ماڈیولز (ڈیٹا بیس، نیٹ ورک، UI) پر انحصار نہیں کرنا چاہیے۔ اس کے بجائے، دونوں سطحیں اعلیٰ سطح کے ماڈیول میں متعین کردہ تجریدوں پر انحصار کرتی ہیں۔

DIP کی رسمی تشکیل میں دو قواعد شامل ہیں: A — اعلیٰ سطح کے ماڈیولز کو نیچی سطح کے ماڈیولز پر انحصار نہیں کرنا چاہیے، دونوں کو تجریدوں پر انحصار کرنا چاہیے۔ B — تجریدوں کو تفصیلات پر انحصار نہیں کرنا چاہیے، تفصیلات کو تجریدوں پر انحصار کرنا چاہیے۔ دوسرا قاعدہ پہلے سے اخذ ہوتا ہے: اگر کوئی تجرید تفصیلات پر انحصار کرتا ہے، تو وہ اعلیٰ سطح کے ماڈیول کے لیے مستحکم بنیاد نہیں ہو سکتا۔

DIP کے بغیر، ایک عام فن تعمیر اس طرح نظر آتا ہے: BusinessLogic → DatabaseRepository — کاروباری منطق براہ راست ایک ٹھوس ذخیرے پر انحصار کرتی ہے۔ DIP کے ساتھ: BusinessLogic → DatabaseServiceInterface ← DatabaseRepository۔ BusinessLogic DatabaseRepository کے وجود کے بارے میں نہیں جانتا، یہ صرف DatabaseService انٹرفیس جانتا ہے، جو کاروباری منطق سے باہر نافذ کیا جاتا ہے۔

DIP میں انحصار کی سمت

الٹ کا مطلب ہے کہ کنٹرول کا بہاؤ اور انحصار کا بہاؤ مخالف سمتوں میں جاتے ہیں۔ کنٹرول کا بہاؤ اوپر سے نیچے جاتا ہے: UI → ViewModel → UseCase → Repository۔ انحصار کا بہاؤ نیچے سے اوپر جاتا ہے: Repository، UseCase میں متعین کردہ انٹرفیس کو نافذ کرتا ہے۔ Repository (نیچی سطح) UseCase (اعلیٰ سطح) پر انحصار کرتا ہے۔

یہ الٹ DIP اور عام تہہ علیحدگی کے درمیان کلیدی فرق ہے۔ روایتی سطحی فن تعمیر میں، ہر تہہ نیچے والی تہہ پر انحصار کرتی ہے۔ DIP والے فن تعمیر میں، تمام تہیں تجریدوں پر انحصار کرتی ہیں، جبکہ ان تجریدوں کا نفاذ بنیادی ڈھانچے کی تہہ میں ہوتا ہے، جو DI میکانزم کے ذریعے اوپری تہوں سے “منسلک” ہوتی ہے۔

انحصار کے الٹ کا اصول کیسے کام کرتا ہے

DIP میکانزم اعلیٰ سطح کے ماڈیولز میں تجریدوں کی وضاحت کرکے اور نیچی سطح کے ماڈیولز میں انہیں لاگو کرکے نافذ کیا جاتا ہے۔ اعلیٰ سطح کا ماڈیول اپنی ضرورت کی فعالیت کے لیے ایک انٹرفیس کا اعلان کرتا ہے۔ نیچی سطح کا ماڈیول اس انٹرفیس کو نافذ کرتا ہے۔ وائرنگ ایپلیکیشن کے کمپوزیشن روٹ پر ہوتی ہے۔

موجودہ کوڈ میں DIP متعارف کرانے کا عمل: نیچی سطح کے ماڈیول کے لیے ایک انٹرفیس نکالیں، اس انٹرفیس کو اعلیٰ سطح کے ماڈیول (یا ایک علیحدہ تجریدی تہہ) میں منتقل کریں، اعلیٰ سطح کے ماڈیول کے انحصار کو انٹرفیس استعمال کرنے کے لیے دوبارہ لکھیں، نیچی سطح کے ماڈیول کو اس انٹرفیس کو نافذ کرنے دیں۔ ان مراحل کے بعد، انحصار کی سمت الٹ گئی ہے۔

DIP کو کمپوزیشن روٹ میکانزم کی ضرورت ہوتی ہے — ایپلیکیشن میں ایک نقطہ جہاں تمام انحصار پیدا ہوتے ہیں اور ایک دوسرے سے منسلک ہوتے ہیں۔ Android میں یہ Application.get() یا Hilt جزو ہے، iOS میں — AppDelegate یا SceneDelegate۔ کمپوزیشن روٹ واحد جگہ ہے جہاں کوڈ ٹھوس نفاذ کے بارے میں جانتا ہے۔

DIP کے ذریعے تہہ علیحدگی

DIP ایپلیکیشن کی تہوں کے درمیان فن تعمیری حدود پیدا کرتا ہے۔ جب ViewModel، UserRepository انٹرفیس پر انحصار کرتا ہے، پیشکش اور ڈومین تہوں کے درمیان ایک حد بنتی ہے: ViewModel (پیشکش) نہیں جانتا کہ ڈیٹا کہاں سے آتا ہے۔ یہ حد UserRepository کے نفاذ (Room → REST → Mock) کو ViewModel کو متاثر کیے بغیر تبدیل کرنے کی اجازت دیتی ہے۔ جتنی زیادہ ایسی حدود ہوں گی، ایپلیکیشن فریم ورک اور لائبریری تبدیلیوں کے خلاف اتنی ہی زیادہ مزاحم ہوگی۔

Google کی تجویز کردہ Android فن تعمیر میں، DIP کو UseCase کے ذریعے نافذ کیا جاتا ہے جو ڈومین تہہ میں رہتے ہیں اور Repository انٹرفیس پر انحصار کرتے ہیں۔ RepositoryImpl ڈیٹا تہہ میں ہیں اور ان انٹرفیس کو نافذ کرتے ہیں۔ پیشکش تہہ (ViewModel) UseCase پر انحصار کرتی ہے۔ انحصار کی سمت پیشکش سے ڈومین، ڈومین سے ڈیٹا کی طرف جاتی ہے — لیکن کوئی بھی تہہ دوسری تہہ کے ٹھوس نفاذ کے بارے میں نہیں جانتی۔

DIP اور DI (ڈیپینڈنسی انجکشن) میں فرق

DIP اور DI اکثر الجھ جاتے ہیں، لیکن یہ مختلف تصورات ہیں۔ DIP ایک فن تعمیری اصول ہے (کیا کرنا ہے: تجریدوں پر انحصار کرنا)۔ DI ایک نفاذ کا نمونہ ہے (کیسے کرنا ہے: تعمیر کنندہ کے ذریعے انحصار منتقل کرنا)۔ DIP سوال کا جواب دیتا ہے “ماڈیولز کس پر مبنی ہونے چاہئیں؟”، DI جواب دیتا ہے “اشیاء اپنے انحصار کیسے حاصل کرتی ہیں؟”۔

ڈیپینڈنسی انجکشن تعمیر کنندہ، طریقہ یا خاصیت کے ذریعے کسی شے میں انحصار داخل کرنے کا ایک طریقہ ہے۔ جب کوئی Kotlin کلاس اپنے تعمیر کنندہ کے ذریعے Repository انٹرفیس حاصل کرتی ہے — یہ DI ہے۔ اور یہ حقیقت کہ ViewModel کلاس کسی ٹھوس RoomRepository نفاذ کے بجائے Repository انٹرفیس پر انحصار کرتی ہے — یہ DIP ہے۔ DI آلہ ہے، DIP مقصد ہے۔

آپ DI فریم ورک کے بغیر DIP کی پیروی کر سکتے ہیں: کمپوزیشن روٹ میں انحصار کا دستی جوڑنا بھی DI (دستی DI) ہے۔ آپ DIP کی خلاف ورزی کرتے ہوئے DI فریم ورک (Dagger، Hilt، Koin) استعمال کر سکتے ہیں: اگر ViewModel براہ راست new() کے ذریعے Repository شے بناتا ہے — DIP کی خلاف ورزی ہوئی ہے، چاہے فریم ورک نصب ہو۔ DIP ایک فن تعمیری فیصلہ ہے، DI ایک تکنیکی تفصیل ہے۔

موبائل ڈیولپمنٹ میں DIP کی مثالیں

ڈیٹا تہہ پر DIP لاگو کرنے کی Android مثال دیکھتے ہیں۔ DIP کے بغیر، ViewModel براہ راست RoomDatabase اور DAO بناتا ہے۔ DIP کے ساتھ — ViewModel، UserRepository انٹرفیس پر انحصار کرتا ہے، اور ٹھوس RoomUserRepository نفاذ بیرونی طور پر فراہم کیا جاتا ہے۔

kotlin
// تجرید ڈومین تہہ (اعلیٰ سطح) کا ہے
interface UserRepository {
    fun getUser(id: Int): User
}

// ڈومین تہہ صرف تجرید پر انحصار کرتی ہے
class GetUserUseCase(
    private val repo: UserRepository
) {
    fun execute(id: Int): User = repo.getUser(id)
}

// ڈیٹا تہہ میں نفاذ ڈومین تہہ کے تجرید پر انحصار کرتا ہے
class RoomUserRepository(
    private val dao: UserDao
) : UserRepository {
    override fun getUser(id: Int): User {
        return dao.getById(id)
    }
}

// کمپوزیشن روٹ
class AppModule {
    fun provideUserRepository(dao: UserDao): UserRepository {
        return RoomUserRepository(dao)
    }
}

ایک Application Coordinator اور نیویگیشن پروٹوکول کے ساتھ iOS مثال:

swift
// ڈومین تہہ میں نیویگیشن کا تجرید
protocol AuthNavigation {
    func navigateToHome()
    func navigateToLogin()
}

// ViewModel تجرید پر انحصار کرتا ہے، UIKit پر نہیں
final class AuthViewModel {
    private let navigation: AuthNavigation

    init(navigation: AuthNavigation) {
        self.navigation = navigation
    }

    func onLoginSuccess() {
        navigation.navigateToHome()
    }
}

// Coordinator (UIKit تہہ) ڈومین تہہ کے پروٹوکل کو نافذ کرتا ہے
final class AppCoordinator: AuthNavigation {
    func navigateToHome() {
        // UIKit نیویگیشن کوڈ
    }
    func navigateToLogin() {
        // UIKit نیویگیشن کوڈ
    }
}

اہم نکتہ: AuthViewModel (ڈومین) AppCoordinator (UIKit) کے وجود کے بارے میں نہیں جانتا۔ یہ صرف AuthNavigation پروٹوکول جانتا ہے۔ اگر کل UIKit کو SwiftUI سے بدل دیا جائے — AuthViewModel میں تبدیلی کی ضرورت نہیں ہے۔ DIP ڈومین تہہ کو UI فریم ورک اور لائبریریوں سے آزاد بناتا ہے۔

DIP کے لیے اوزار: Dagger، Hilt، Koin

Hilt Android کے لیے معیاری DI آلہ ہے، جسے Google تجویز کرتا ہے۔ یہ Jetpack میں شامل ہے، ViewModel، Fragment، Service اور دیگر Android اجزاء کو سپورٹ کرتا ہے۔ Hilt @Module، @Provides، @Inject تشریحات کے ذریعے کمپوزیشن روٹ کی تخلیق کو خودکار بناتا ہے۔ Hilt کا استعمال DIP کی تعمیل کی ضمانت نہیں دیتا — UserRepository انٹرفیس ڈومین تہہ میں متعین ہونا چاہیے، ڈیٹا تہہ میں نہیں۔

Koin کوڈ جنریشن یا تشریحی پروسیسنگ کے بغیر Kotlin کے لیے ایک ہلکا پھلکا DI فریم ورک ہے۔ Koin کا DSL (module, single, factory) سیکھنے میں آسان ہے، لیکن انحصار کی جانچ رن ٹائم پر ہوتی ہے، کمپائل ٹائم پر نہیں۔ Koin iOS سپورٹ کی وجہ سے ملٹی پلیٹ فارم پروجیکٹس (KMP) میں مقبول ہے۔

Dagger 2 Hilt کا پیشرو ہے، اب بھی بڑے پروجیکٹس میں استعمال ہوتا ہے۔ Dagger کمپائل ٹائم پر DI کوڈ تیار کرتا ہے، جو زیادہ سے زیادہ کارکردگی اور بلڈ ٹائم پر خرابی کی تشخیص فراہم کرتا ہے۔ Hilt Dagger کے اوپر بنایا گیا ہے اور ایک آسان API فراہم کرتا ہے۔ نئے پروجیکٹس کے لیے، Google Hilt کو بنیادی DI فریم ورک کے طور پر تجویز کرتا ہے۔

تہوں کے مطابق DI ماڈیولز کی تنظیم

DI ماڈیولز کو فن تعمیری تہوں کے مطابق ہونا چاہیے اور DomainModule، DataModule، PresentationModule میں تقسیم ہونا چاہیے۔ DomainModule صرف تجریدیں اور UseCase فراہم کرتا ہے۔ DataModule تجریدوں کے لیے نفاذ فراہم کرتا ہے۔ PresentationModule ViewModels کو UseCase سے جوڑتا ہے۔ یہ تنظیم اس بات کو یقینی بناتی ہے کہ ڈومین تہہ بنیادی ڈھانچے کی لائبریریوں سے آزاد رہے۔

DI فریم ورکس کے درمیان منتقلی کرتے وقت (مثال کے طور پر، Koin سے Hilt میں)، DomainModule کی ساخت تبدیل نہیں ہوتی — صرف DataModule اور PresentationModule میں جوڑنے کے طریقے تبدیل ہوتے ہیں۔ DIP ڈومین منطق کی علیحدگی کو یقینی بناتا ہے، جبکہ DI فریم ورک ایک تکنیکی جوڑنے کا میکانزم ہے۔

اکثر پوچھے گئے سوالات

کیا ہمیشہ DIP لاگو کرنا چاہیے؟

DIP فن تعمیری حدود پر ضروری ہے — ایپلیکیشن کی تہوں کے درمیان (ڈومین → ڈیٹا، پیشکش → ڈومین)۔ ایک ہی تہہ کے اندر، DIP ضرورت سے زیادہ ہو سکتا ہے۔ مثال کے طور پر، ڈومین تہہ کے اندر ایک افادیتی کلاس StringFormatter کو انٹرفیس کی ضرورت نہیں — اگر اسے تبدیل کرنے کی کوئی وجہ نہ ہو۔

کیا DIP وہی چیز ہے جو ڈیپینڈنسی انجکشن ہے؟

نہیں۔ DIP ایک اصول ہے: ماڈیولز کو تجریدوں پر انحصار کرنا چاہیے۔ DI ایک نمونہ ہے: ایک شے انحصار خود بنانے کے بجائے باہر سے حاصل کرتی ہے۔ DI، DIP کو لاگو کرنے کا ایک طریقہ ہے، لیکن DIP DI کے بغیر بھی (فیکٹریوں یا سروس لوکیٹر کے ذریعے) پیروی کی جا سکتی ہے۔ DI کے بغیر DIP ممکن ہے لیکن اس کی کوئی فن تعمیری قدر نہیں۔

DIP کے لیے انٹرفیس کہاں متعین کرنے چاہئیں؟

انٹرفیس اس ماڈیول کے ہوتے ہیں جو انہیں استعمال کرتا ہے، نہ کہ اس ماڈیول کے جو انہیں نافذ کرتا ہے۔ UserRepository ڈومین تہہ میں اعلان کیا جاتا ہے اور ڈیٹا تہہ میں نافذ کیا جاتا ہے۔ یہ DIP کا کلیدی اصول ہے: تجرید کا مالک صارف ہے، نفاذ فراہم کرنے والا نہیں۔

DIP جانچ کو کیسے متاثر کرتا ہے؟

DIP الگ تہوں پر جانچ کو ممکن بناتا ہے۔ ایک ViewModel جو UserRepository (انٹرفیس) پر انحصار کرتا ہے، ڈیٹا بیس کے بغیر ایک نقلی (mock) نفاذ سے جانچا جا سکتا ہے۔ DIP کے بغیر، ViewModel RoomUserRepository پر انحصار کرے گا اور ہر جانچ کے لیے ڈیٹا بیس سیٹ اپ کی ضرورت ہوگی۔ DIP + DI جانچ کے دوران مکمل ماڈیول علیحدگی فراہم کرتے ہیں۔

Android کے لیے کون سا DI فریم ورک منتخب کرنا چاہیے؟

Hilt Android پروجیکٹس کے لیے معیاری انتخاب ہے، جسے Google تجویز کرتا ہے۔ Koin Kotlin Multiplatform پروجیکٹس کے لیے ایک متبادل ہے۔ Dagger 2 موجودہ پروجیکٹس کے لیے ہے جہاں Hilt میں منتقلی مناسب نہیں۔ فریم ورک کا انتخاب فن تعمیری سطح پر DIP کی پیروی کرنے کی ضرورت کو ختم نہیں کرتا۔

خلاصہ

  • DIP (ڈیپینڈنسی انورژن پرنسپل) — تجریدوں کے ذریعے فن تعمیری حدود کے بارے میں SOLID کا پانچواں اصول
  • اعلیٰ سطح کے ماڈیولز نیچی سطح کے ماڈیولز پر انحصار نہیں کرتے — دونوں تجریدوں پر انحصار کرتے ہیں
  • DIP ≠ DI: اصول بمقابلہ نفاذ کا نمونہ؛ DI آلہ ہے، DIP مقصد ہے
  • تجریدیں صارف کی ہوتی ہیں (ڈومین تہہ)، فراہم کرنے والے کی نہیں (ڈیٹا تہہ)
  • کمپوزیشن روٹ — ایپلیکیشن میں واحد جگہ جہاں ٹھوس انحصار جمع کیے جاتے ہیں
  • Hilt, Koin, Dagger — DI اوزار جو جوڑنے کو خودکار بناتے ہیں لیکن DIP کے فن تعمیری فیصلے کو تبدیل نہیں کرتے
  • ڈومین تہہ DIP کے مطابق بنائی گئی، فریم ورک، UI اور بنیادی ڈھانچے کی لائبریریوں سے آزاد رہتی ہے

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں