DIP: əsaslar, asılılıqların inversiyası inkişafda

Müəllif: IT Sectr Dərc olunub: 2026-05-12 Oxuma vaxtı: 9 dəq

DIP (Dependency Inversion Principle) — SOLID-in beşinci prinsipi olub, modullar arasında asılılıqların qurulması qaydalarını müəyyən edir: yuxarı səviyyəli modullar aşağı səviyyəli modullardan asılı olmamalıdır, hər ikisi abstraksiyalardan asılı olmalıdır. Abstraksiyalar detallardan asılı olmamalıdır — detallar abstraksiyalardan asılı olmalıdır. Robert Martin tərəfindən Clean Architecture (2017) kitabında təsvir edilən bu prinsip, zəif bağlı arxitekturanın əsasını təşkil edir. Bu kitabın məlumatına görə, asılılıqların inversiyası prinsipi tətbiqin təbəqələri arasında sərt bağlantıları aradan qaldırır.

Əsas məqamlar

  • DIP — asılılıqların inversiyası prinsipi, SOLID-də beşinci, arxitektura sərhədləri haqqında
  • Yuxarı səviyyəli modullar aşağı səviyyəli modulları import etməməlidir — yalnız abstraksiyalar
  • DIP ≠ DI: Dependency Inversion — arxitektura prinsipi, Dependency Injection — onun tətbiqi üsulu
  • Abstraksiyalar yuxarı səviyyəli modula, icralar isə aşağı səviyyəli modula məxsusdur
  • DIP çoxqatlı arxitekturalarda ənənəvi asılılıq iyerarxiyasını tərsinə çevirir

DIP (Dependency Inversion Principle) nədir?

DIP (Dependency Inversion Principle) — asılılıqların inversiyası prinsipi olub, modullar arasında asılılıqların istiqaməti haqqında ənənəvi anlayışı tərsinə çevirir. Yüksək səviyyəli modullar (biznes məntiqi) aşağı səviyyəli modullardan (verilənlər bazası, şəbəkə, UI) birbaşa asılı olmamalıdır. Bunun əvəzinə, hər iki səviyyə yuxarı səviyyəli modulda müəyyən edilən abstraksiyalardan asılı olur.

DIP-in rəsmi ifadəsi iki qayda daxildir: A — yuxarı səviyyəli modullar aşağı səviyyəli modullardan asılı olmamalıdır, hər ikisi abstraksiyalardan asılı olmalıdır. B — abstraksiyalar detallardan asılı olmamalıdır, detallar abstraksiyalardan asılı olmalıdır. İkinci qayda birincinin nəticəsidir: əgər abstraksiya detallardan asılıdırsa, yuxarı səviyyəli modul üçün sabit əsas ola bilməz.

DIP olmadan tipik arxitektura belə görünür: BusinessLogic → DatabaseRepository — biznes məntiqi birbaşa konkret repozitoridan asılıdır. DIP ilə: BusinessLogic → DatabaseServiceInterface ← DatabaseRepository. BusinessLogic DatabaseRepository-in varlığından xəbərsizdir, o yalnız biznes məntiqindən kənarda icra olunan DatabaseService interfeysini tanıyır.

DIP-də asılılıqların istiqaməti

İnversiya o deməkdir ki, idarəetmə axını və asılılıq axını əks istiqamətlərə yönəlir. İdarəetmə axını yuxarıdan aşağıya gedir: UI → ViewModel → UseCase → Repository. Asılılıq axını aşağıdan yuxarıya gedir: Repository UseCase-də müəyyən edilmiş interfeysi implementasiya edir. Repository (aşağı səviyyə) UseCase-dən (yuxarı səviyyə) asılıdır.

Bu inversiya DIP-in adi təbəqələrə bölünmədən əsas fərqidir. Ənənəvi qatlı arxitekturada hər təbəqə aşağıdakı təbəqədən asılıdır. DIP ilə arxitekturada bütün təbəqələr abstraksiyalardan asılıdır və bu abstraksiyaların icrası infrastruktur təbəqəsində yerləşir və DI mexanizmləri vasitəsilə yuxarı təbəqələrə qoşulur.

Asılılıqların inversiyası prinsipi necə işləyir

DIP mexanizmi yuxarı səviyyəli modullarda abstraksiyaların müəyyən edilməsi və onların aşağı səviyyəli modullarda icrası ilə həyata keçirilir. Yuxarı səviyyəli modul ehtiyac duyduğu funksionallıq üçün interfeys bəyan edir. Aşağı səviyyəli modul bu interfeysi implementasiya edir. Bağlama (wiring) tətbiqin kompozisiya kökü səviyyəsində baş verir.

Mövcud koda DIP-in tətbiqi prosesi: aşağı səviyyəli modul üçün interfeys ayırın, bu interfeysi yuxarı səviyyəli modula (və ya ayrı abstraksiya təbəqəsinə) köçürün, yuxarı modulun asılılığını interfeysə yenidən yazın, aşağı səviyyəli modulu bu interfeysi implementasiya etməyə məcbur edin. Bu addımlardan sonra asılılığın istiqaməti əksinə dəyişdi.

DIP kompozisiya kökü mexanizmini tələb edir — tətbiqdə bütün asılılıqların yaradıldığı və bir-birinə bağlandığı nöqtə. Android-də bu Application.get() və ya Hilt komponenti, iOS-da — AppDelegate və ya SceneDelegate-dir. Kompozisiya kökü kodun konkret icralar haqqında bildiyi yeganə yerdir.

DIP vasitəsilə təbəqələrin izolyasiyası

DIP arxitektura sərhədlərini formalaşdırır tətbiqin təbəqələri arasında. ViewModel UserRepository interfeysindən asılı olduqda, presentation və domain təbəqəsi arasında sərhəd yaranır: ViewModel (presentation) məlumatların haradan gəldiyini bilmir. Bu sərhəd UserRepository icrasını (Room → REST → Mock) ViewModel-ə təsir etmədən dəyişməyə imkan verir. Nə qədər çox belə sərhəd, tətbiq framework və kitabxana dəyişikliklərinə bir o qədər davamlıdır.

Google tərəfindən tövsiyə edilən Android arxitekturasında DIP domain təbəqəsində yerləşən və Repository interfeyslərindən asılı olan UseCase vasitəsilə həyata keçirilir. RepositoryImpl data təbəqəsində yerləşir və bu interfeysləri implementasiya edir. Presentation təbəqəsi (ViewModel) UseCase-dən asılıdır. Asılılıqların istiqaməti presentation-dan domain-ə, domain-dən data-ya gedir — lakin heç bir təbəqə digər təbəqənin konkret icraları haqqında bilmir.

DIP və DI (Dependency Injection) arasındakı fərq

DIP və DI tez-tez qarışdırılır, lakin bunlar fərqli anlayışlardır. DIP — arxitektura prinsipi (NƏ etmək lazımdır: abstraksiyalardan asılı olmaq). DI — tətbiq nümunəsi (BUNU NECƏ etmək: asılılıqları konstruktor vasitəsilə ötürmək). DIP modullar nəyə əsaslanmalıdır? sualına, DI — obyektlər asılılıqlarını necə əldə edir? sualına cavab verir.

Dependency Injection — asılılıqları konstruktor, metod və ya xüsusiyyət vasitəsilə obyektə daxil etmə üsuludur. Kotlin sinfində Repository interfeysi konstruktor vasitəsilə ötürüldükdə — bu DI-dir. ViewModel sinfinin konkret RoomRepository icrasından deyil, Repository interfeysindən asılı olması — bu DIP-dir. DI — alət, DIP — məqsəd.

DIP-ə DI framework olmadan da riayət etmək olar: kompozisiya kökündə əl ilə asılılıqların bağlanması da DI-dir (manual DI). DI framework (Dagger, Hilt, Koin) istifadə edərək DIP-i poza bilərsiniz: əgər ViewModel birbaşa new() vasitəsilə Repository obyekti yaradırsa — DIP pozulub, hətta framework quraşdırılmış olsa belə. DIP — arxitektura qərarı, DI — texniki detal.

Mobil inkişafda DIP nümunələri

Android nümunəsini nəzərdən keçirək DIP-in data təbəqəsinə tətbiqi. DIP olmadan ViewModel birbaşa RoomDatabase və DAO yaradır. DIP ilə — ViewModel UserRepository interfeysindən asılıdır, konkret RoomUserRepository icrası isə kənardan təmin edilir.

kotlin
// Abstraksiya domain təbəqəsinə aiddir (yuxarı səviyyə)
interface UserRepository {
    fun getUser(id: Int): User
}

// Domain təbəqəsi yalnız abstraksiyadan asılıdır
class GetUserUseCase(
    private val repo: UserRepository
) {
    fun execute(id: Int): User = repo.getUser(id)
}

// Data təbəqəsində icra domain təbəqəsinin abstraksiyasından asılıdır
class RoomUserRepository(
    private val dao: UserDao
) : UserRepository {
    override fun getUser(id: Int): User {
        return dao.getById(id)
    }
}

// Kompozisiya kökü
class AppModule {
    fun provideUserRepository(dao: UserDao): UserRepository {
        return RoomUserRepository(dao)
    }
}

iOS nümunəsi Application Coordinator və naviqasiya üçün protokol ilə:

swift
// Naviqasiya abstraksiyası domain təbəqəsində
protocol AuthNavigation {
    func navigateToHome()
    func navigateToLogin()
}

// ViewModel abstraksiyadan asılıdır, UIKit-dən deyil
final class AuthViewModel {
    private let navigation: AuthNavigation

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

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

// Coordinator (UIKit təbəqəsi) domain təbəqəsinin protokolunu implementasiya edir
final class AppCoordinator: AuthNavigation {
    func navigateToHome() {
        // UIKit naviqasiya kodu
    }
    func navigateToLogin() {
        // UIKit naviqasiya kodu
    }
}

Əsas məqam: AuthViewModel (domain) AppCoordinator-un (UIKit) varlığından xəbərsizdir. O yalnız AuthNavigation protokolunu tanıyır. Sabah UIKit SwiftUI ilə əvəz olunarsa — AuthViewModel dəyişiklik tələb etmir. DIP domain təbəqəsini frameworklərdən və UI kitabxanalarından müstəqil edir.

DIP üçün alətlər: Dagger, Hilt, Koin

Hilt — Android üçün standart DI aləti, Google tərəfindən tövsiyə edilir. Jetpack-ə daxildir, ViewModel, Fragment, Service və digər Android komponentlərini dəstəkləyir. Hilt @Module, @Provides, @Inject annotasiyaları vasitəsilə kompozisiya kökünün yaradılmasını avtomatlaşdırır. Hilt istifadəsi DIP-ə riayəti təmin etmir — UserRepository interfeysi data təbəqəsində deyil, domain təbəqəsində müəyyən edilməlidir.

Koin — kod generasiyası və annotasiya prosessoru olmadan Kotlin üçün yüngül DI framework-dür. Koin DSL (module, single, factory) öyrənmək üçün daha asandır, lakin asılılıqların yoxlanılması kompilasiya mərhələsində deyil, runtime-da baş verir. Koin iOS dəstəyi sayəsində multiplatforma layihələrində (KMP) məşhurdur.

Dagger 2 — Hilt-in sələfi, böyük layihələrdə hələ də istifadə olunur. Dagger kompilasiya mərhələsində DI kodu yaradır ki, bu da maksimal performans və qurma mərhələsində xəta diaqnostikası verir. Hilt Dagger üzərində qurulub və sadələşdirilmiş API təmin edir. Yeni layihələr üçün Google Hilt-i əsas DI framework-ü kimi tövsiyə edir.

DI modullarının təbəqələr üzrə təşkili

DI modulları arxitektura təbəqələrinə uyğun olmalı və DomainModule, DataModule, PresentationModule bölünməlidir. DomainModule yalnız abstraksiyalar və UseCase təmin edir. DataModule abstraksiyalar üçün icralar təmin edir. PresentationModule ViewModel-i UseCase ilə birləşdirir. Bu təşkil domain təbəqəsinin müstəqil qalmasını təmin edir.

DI framework-ləri arasında miqrasiya zamanı (məsələn, Koin-dən Hilt-ə) DomainModule strukturu dəyişmir — yalnız DataModule və PresentationModule-də bağlama üsulları dəyişir. DIP domain məntiqinin izolyasiyasını təmin edir, DI framework isə texniki bağlama mexanizmidir.

Tez-tez verilən suallar

DIP həmişə tətbiq edilməlidir?

DIP arxitektura sərhədlərində — tətbiqin təbəqələri arasında (domain → data, presentation → domain) zəruridir. Bir təbəqə daxilində DIP artıq ola bilər. Məsələn, domain təbəqəsi daxilində StringFormatter yardımçı sinfi interfeys tələb etmir — əgər onun dəyişdirilməsi üçün əsas yoxdursa.

DIP asılılıqların daxil edilməsi ilə eynidir?

Xeyr. DIP — prinsip: modullar abstraksiyalardan asılı olmalıdır. DI — nümunə: obyekt asılılıqları kənardan alır, özü yaratmır. DI — DIP-in tətbiqi üsuludur, lakin DIP-ə DI olmadan da riayət etmək olar (fabriklər və ya xidmət lokatoru vasitəsilə). DI olmadan DIP mümkündür, lakin arxitektura dəyəri yoxdur.

DIP üçün interfeyslər harada müəyyən edilməlidir?

İnterfeyslər onu istifadə edən modula məxsusdur, onu implementasiya edənə deyil. UserRepository domain təbəqəsində bəyan edilir, data təbəqəsində implementasiya olunur. Bu DIP-in əsas qaydasıdır: abstraksiyanın sahibi istehlakçıdır, icra təminatçısı deyil.

DIP testə necə təsir edir?

DIP testi mümkün edir izolyasiya olunmuş təbəqələrdə. UserRepository-dən (interfeys) asılı olan ViewModel verilənlər bazası olmadan mock icrası ilə test edilir. DIP olmadan ViewModel RoomUserRepository-dən asılı olar və hər test üçün VB konfiqurasiyası tələb edərdi. DIP + DI test zamanı modulların tam izolyasiyasını təmin edir.

Android üçün hansı DI framework-ü seçməli?

Hilt — Android layihələri üçün standart seçim, Google tərəfindən tövsiyə edilir. Koin — Kotlin Multiplatform layihələri üçün alternativ. Dagger 2 — mövcud layihələr üçün, Hilt-ə miqrasiya əsassız olduqda. Framework seçimi arxitektura səviyyəsində DIP-ə riayət etmək zərurətini aradan qaldırmır.

Nəticə

  • DIP (Dependency Inversion Principle) — SOLID-in beşinci prinsipi, abstraksiyalar vasitəsilə arxitektura sərhədləri haqqında
  • Yuxarı səviyyəli modullar aşağı səviyyəli modullardan asılı deyil — hər ikisi abstraksiyalardan asılıdır
  • DIP ≠ DI: prinsipə qarşı tətbiq nümunəsi; DI — üsul, DIP — məqsəd
  • Abstraksiyalar istehlakçıya məxsusdur (domain təbəqəsi), təminatçıya deyil (data təbəqəsi)
  • Kompozisiya kökü — tətbiqdə konkret asılılıqların toplandığı yeganə yer
  • Hilt, Koin, Dagger — bağlamanı avtomatlaşdıran DI alətləri, lakin DIP arxitektura qərarını əvəz etmir
  • Domain təbəqəsi DIP-ə uyğun qurulduqda frameworklərdən, UI və infrastruktur kitabxanalarından müstəqil qalır

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun