Dependency injection nədir? Nə üçün istifadə edilir?
Bu məqalədə proqramlaşdırmada çox önəmli yeri olan Dependency İnjection mövzusu barədə danışacağıq. Dependency İnjection terminini ana dilimizə tərcümə etməyə çalışsaq, Bağımlılıq İnjeksiyası kimi qeyd edə bilərik. Burada iki əsas predmetdən söhbət gedə bilər:
- Dependency — Bağımlılıq
- İnjection — İnjeksiya
Dependency — Bir sinifin, digər bir sinifə bağlılığının olduğu normal bir vəziyyətdir. Yəni ki, bir sinif, digər bir sinifə xas olan hansısa bir metodu çağırırsa və statik deyilsə, həmin sinifdən bir obyekt yaratmaq məcburiyyətindədir. Nümunəyə baxsaq:
Gördüyümüz kimi, kompüter sinifi, xarici ekran kartı sinifindən bir metodu çağırır və bunu etmək üçün həmin sinifdən bir obyektə ehtiyac duyur. Bu vəziyyətdə, kompüter sinifinin ekran kartı sinifinə bağlı olduğunu qeyd edirik. Tam əksinə desək, “Ekran kartı sinifi, kompüter sinifinin bağımlılığıdır (dependency)” kimi qeyd edə bilərik.
Digər bir şəkildə izah etməyə çalışsaq, kompüter sinifinin bir client (müştəri), ekran kartı sinifinin isə bir service (servis) olduğunu düşünə bilərik. Bu halda kompüter sinifimiz Client, ekran kartı sinifimiz izə Service kimi düşünürük. Aşağıdakı, digər bir nümunəyə nəzər yetirək:
Əvvəlki nümunə sadə olduğuna görə, rahat bir şəkildə kompüter sinifinə Client, ekran kartı sinifinə isə müştəri deyə bilərdik, lakin indiki nümunədə ekran kartı sinifimiz müştəridir yoxsa servis? Bu sualın cavabı, həmin sinifə hansı sinifə nəzərən baxmağımızla əlaqəlidir, yəni ki, kompüter sinifindən baxsaq ekran kartı sinifi servisdir, lakin, qida mənəyi sinifindən baxsaq bir müştəridir. Eyni zamanda Qida mənbəyi sinifi də, ekran kartı sinifinə görə bir servisdir ki, hansı ki, ekran kartı sinifi onu istifadə edir.
Əgər bir müştəri, bir servisi istifadə edirsə, onu hansısa bir yolla əldə etməlidir. Yəni ki, o servisi istifadə etmək üçün bir obyektə, referansa ehtiyacı vardır. Bu əlaqəni qurmağın bir neçə yolu vardır:
- Obyekt yaratmaq. Nümunələrdə biz bunu etmək üçün new açar sözündən istifadə edərək həmin obyektləri yaradırıq.
- Statik metod vasitəsilə. Həmin siniflərin istifadə etdiyimiz metodlarını static təyin etməklə.
- Statik qlobal dəyişkən ilə. Həmin sinifin referansını statik qlobal dəyişkən kimi istifadə edəcəyimiz sinifdə saxlayırıq.
4. Həmin referansı xaricdən daxil etmək.
Xaricdən daxil etmək dedikdə nə nəzərdə tutulur? Burada İnjeksiya qavramı ortaya çıxır. Bağımlılıqlar (dependencies) xaricdən, müştəri üçün təmin olunur. Dependency İnjection termini buradan yaranır.
Nə üçün istifadə olunmalıdır?
Əvvəlki nümunələrdə gördüyümüz kimi, siniflərimizin daxilində digər siniflərdən olan obyektləri new açar sözü ilə yaradırıq. Bu halda obyektlər arasında bağlılıq yaranmış olur. Gələcəkdə həmin obyektlərdə hər-hansısa bir dəyişiklik baş verəcəyi halda müəyyən problemlər ortaya çıxacaqdır. Buna görə də, obyektlər arasında olan bağlılıq minumuma endirilməlidir. Bundan əlavə yazdığımız kodları daha oxunaqlı edir, Unit testlər yazmağı daha da asanlaşdırır.
Dependency İnjection — müştərilərə lazım olan servisləri xaricdən təmin etməkdir. Servisləri xaricdən injekt (daxil etmək) etmənin üç yolu vardır:
1.Constructor Injection. Əvvəlki nümunədə olan Kompüter sinifimizə xarici ekran kartı sinifmizi konstruktor injeksiyası vasitəsilə injekt etməyə çalışaq.
Şəkildə gördüyümüz kimi, bir konstruktor təyin edirik və ekran kartı sinifimizi parametr olaraq xaricdən daxil edirik. Konstruktur injeksiyası sadəcə bundan ibarətdir. Üstünlükləri:
- Test üçün idealdır. Unit testlərdə heç bir mock kitabxanasına ehtiyacımız qalmır.
- Immutability (Dəyişməzlik). Bağımlılıqlar bir dəfə set olunur və dəyişdirilmir.
- İstifadəsi çox sadədir.
2.Method Injection
Metod injeksiyası üçün isə, bir set metodu təyin edirik və parametr olaraq lazım olan sinifi veririk. Beləliklə metod injeksiyasını yerinə yetiririk.
Üstünlükləri:
- Metod adlandırılması, bağımlılıqları bizə göstərir.
- Konstruktor injeksiyasından sonra istifadə edilə bilər. Məsələn əlavə bir servisi injekt etmək üçün.
3.Field Injection. Daha çox, Kotlində property injection kimi adlandırılan injeksiya növüdür. Bunun üçün lateinit var sameVariable təyin edirik. Bu o mənaya gəlir ki, bu dəyişkəni mən hal-hazırda istifadə etmirəm, lakin, istifadə edəcəyim halda ilk öncə initialize (bir dəyər vermək) etməliyəm. Java üzərində buna misal olaraq Spring də olan @Autowired annotasiyasını nümunə göstərmək olar. Üstünlükləri:
- Konstruktor injeksiyasından sonra istifadə edilə bilər.
Ən çox tövsiyyə olunan injeksiya növü konstruktor injeksiyasıdır. Növbəti məqalədə Android üçün istifadə olunan məşhur Dependency İnjection kitabxanalarından biri olan Dagger Hilt barədə danışacağıq. Məqalədə Vasiliy Zukanovun Dependency İnjection in Android dərsindən mənbə kimi istifadə olunmuşdur.