Bağımlılık yerleştirme (DI), programlamada yaygın olarak kullanılan bir tekniktir. bir uygulamadır. DI ilkelerine uyarak iyi bir uygulama mimarisinin temellerini atabilirsiniz.
Bağımlılık yerleştirmeyi uygulamak, size aşağıdaki avantajları sağlar:
- Kodun yeniden kullanılabilirliği
- Yeniden düzenleme kolaylığı
- Test kolaylığı
Bağımlılık yerleştirmenin temelleri
Özellikle Android'de bağımlılık yerleştirmeyi ele almadan önce bu sayfanın bağımlılık yerleştirmenin işleyiş şekline dair daha genel bir bakış sunduk.
Bağımlılık yerleştirme nedir?
Sınıflar için genellikle diğer sınıflara referanslar gerekir. Örneğin, Car sınıfı
bir Engine sınıfına referans gerekebilir. Bu gerekli sınıflar
dependencies olarak ayarlanmıştır. Bu örnekte Car sınıfı şuna bağımlıdır:
Engine sınıfının bir örneğini burada görebilirsiniz.
Bir sınıf, ihtiyacı olan nesneyi üç şekilde elde edebilir:
- Sınıf, ihtiyaç duyduğu bağımlılığı oluşturur. Yukarıdaki örnekte,
Car, kendi örneğini oluşturup başlatırEngine. - Başka bir yerden alın. Bazı Android API'leri:
Contextalıcı vegetSystemService(), bu işi yapın sağlar. - Parametre olarak sağlanmasını sağlayın. Uygulama bunları sağlayabilir
bağımlılıkları sınıf oluşturulduğunda veya fonksiyonlara ilettiğinde
her bir bağımlılığa ihtiyaç duyanlar için
bir fırsat bulunuyor. Yukarıdaki örnekte,
Carkurucusu parametre olarakEnginealır.
Üçüncü seçenek bağımlılık eklemedir. Bu yaklaşımla bir sınıfa sahip olmak yerine bağımlılıklarını örneğinin kendisinde olması gerekir.
Bir örnekle açıklayalım. Bağımlılık yerleştirme olmadan, aynı işleve sahip bir Car
kodda kendi Engine bağımlılığını oluşturur:
Kotlin
class Car { private val engine = Engine() fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.start() }
Java
class Car { private Engine engine = new Engine(); public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Car car = new Car(); car.start(); } }
Bu, bir bağımlılık yerleştirme örneği değildir çünkü Car sınıfı
kendi Engine projesini oluşturuyor. Bu durum aşağıdaki nedenlerden dolayı sorunlara yol açabilir:
CarveEnginesıkı sıkıya bağlı.Carörneği tek bir kod kullanır ve alt sınıfların veya alternatif uygulamaların kolaycaEnginekullanılır.CarkendiEngineöğesini oluşturacaksa türündeki motorlar için aynıCaröğesini yeniden kullanmak yerine iki türCarGasveElectric.Engineürününe ciddi düzeyde bağımlılık, testi daha da zorlaştırıyor.Car, bir gerçek birEngineörneği oluşturur. Bu nedenle,Enginedeğerini farklı test durumlarında değiştirmek için iki kez test edin.
Bağımlılık yerleştirmede kod nasıl görünür? Her bir örnek yerine
başlatma sırasında kendi Engine nesnesini oluşturan Car API'si,
Oluşturucuda parametre olarak Engine nesnesi:
Kotlin
class Car(private val engine: Engine) { fun start() { engine.start() } } fun main(args: Array) { val engine = Engine() val car = Car(engine) car.start() }
Java
class Car { private final Engine engine; public Car(Engine engine) { this.engine = engine; } public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Engine engine = new Engine(); Car car = new Car(engine); car.start(); } }
main işlevi, Car değerini kullanır. Car, Engine uygulamasına bağlı olduğundan uygulama
Engine örneğini oluşturur ve daha sonra, bunu Car öğesinin bir örneğini oluşturmak için kullanır. İlgili içeriği oluşturmak için kullanılan
bu DI tabanlı yaklaşımın avantajları şunlardır:
Carürününün yeniden kullanılabilirliği.Engineöğesinin farklı uygulamalarınıCar. Örneğin,Engineadında yeni bir alt sınıf tanımlayabilirsiniz.Cartarafından kullanılmasını istediğinizElectricEngine. DI kullanıyorsanız tek yapmanız gereken güncellenenElectricEnginealt sınıfının bir örneğini iletir,Carhâlâ çalışır başka hiçbir değişiklik yapmadan kullanabilirsiniz.Cariçin kolay test yapın. Farklı testlerinizi test etmek için testlerinizi senaryoları ele alacağız. Örneğin,Enginedeğeri için şu adla bir test ikilisi oluşturabilirsiniz:FakeEngineve farklı testler için yapılandırın.
Android'de bağımlılık yerleştirmenin iki temel yolu vardır:
Oluşturucu Yerleştirme. Bu, yukarıda açıklanan şekildedir. Geçerseniz bağımlılıklarını ifade eder.
Alan Yerleştirme (veya Setter Yerleştirme). Belirli Android çerçevesi sınıfları öğeler ve parçalar sistem tarafından örneklendirildiğinden, eklemesi mümkün değildir. Alan yerleştirme ile bağımlılıklar örneklendirilir sınıf oluşturulduktan sonra. Kod şöyle görünür:
Kotlin
class Car { lateinit var engine: Engine fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.engine = Engine() car.start() }
Java
class Car { private Engine engine; public void setEngine(Engine engine) { this.engine = engine; } public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Car car = new Car(); car.setEngine(new Engine()); car.start(); } }
Otomatik bağımlılık ekleme
Önceki örnekte bağımlılıkları oluşturdunuz, sağladınız ve yönettiniz
farklı sınıfları kolayca görebilirsiniz. Buna
el ile bağımlılık ekleme veya manuel bağımlılık ekleme. Car içinde
Mesela sadece tek bir bağımlılık vardı, ama daha fazla bağımlılık ve sınıf
bağımlılıkları manuel olarak eklemeyi daha yorucu hale getirebilir. Manuel bağımlılık ekleme
birtakım sorunlar da beraberinde getirir:
Büyük uygulamalar için, tüm bağımlılıkları alıp bunları bağlamak büyük miktarda ortak metin kodu gerektirebilir. Çok katmanlı bir üst katman için nesne oluşturmak istiyorsanız öncelikle altındaki katmanların tüm bağımlılıklarını göreceksiniz. Somut bir örnek vermek gerekirse, motor, şanzıman, şasi ve diğer parçalara ihtiyacınız olabilir. Motorda ise silindir ve buji gerekir.
Bağımlılıkları aktarmadan önce oluşturamadığınızda gecikmeli başlatmaların veya nesnelerin akışlarının kapsamını belirlemenin, özel bir kapsayıcı (ya da her bir (bağımlılıkların) bellekteki yaşamını yöneten bir kaynaktır.
Süreçleri otomatikleştirerek bu sorunu çözen kütüphaneler var ve bağımlılık sağlamaktan bahsedeceğiz. Bunlar iki kategoriye ayrılır:
Çalışma zamanında bağımlılıkları birbirine bağlayan yansıtma tabanlı çözümler.
Bağımlılıkları bağlamak için kod oluşturan statik çözümler sırasında görünür.
Dagger, Java için popüler bir bağımlılık ekleme kitaplığıdır. Kotlin ve Google tarafından sağlanan Android. Dagger, DI kullanımını kolaylaştırır bağımlılık grafiğini sizin için oluşturup yöneterek uygulamanızda kullanabilirsiniz. Google birçok bileşeni ele alan tamamen statik ve derleme zamanı bağımlılıkları düşünmeye dayalı çözümlerin geliştirilmesini ve performans Guice.
Bağımlılık yerleştirmenin alternatifleri
Bağımlılık yerleştirmeye alternatif olarak, hizmet bulma aracı ile uyumludur. Hizmet bulma aracı tasarım kalıbı da sınıfların somut bağımlılıklardan ayrıştırılmasını kolaylaştırır. Bir sınıf oluşturursunuz Bağımlılıkları oluşturan ve depolayan hizmet bulucu olarak bilinir, ardından isteğe bağlı olarak bulunduğunu öğrendik.
Kotlin
object ServiceLocator { fun getEngine(): Engine = Engine() } class Car { private val engine = ServiceLocator.getEngine() fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.start() }
Java
class ServiceLocator { private static ServiceLocator instance = null; private ServiceLocator() {} public static ServiceLocator getInstance() { if (instance == null) { synchronized(ServiceLocator.class) { instance = new ServiceLocator(); } } return instance; } public Engine getEngine() { return new Engine(); } } class Car { private Engine engine = ServiceLocator.getInstance().getEngine(); public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Car car = new Car(); car.start(); } }
Hizmet bulucu kalıbı, özellik açısından bağımlılık eklemesinden farklıdır. emin olun. Hizmet bulucu kalıbında, sınıflar nesnelerin yerleştirilmesini kontrol etme ve isteme; bağımlılık enjeksiyonu ile Uygulama, kontrol özelliğine sahiptir ve gerekli nesneleri proaktif olarak ekler.
Bağımlılık yerleştirme ile karşılaştırıldığında:
Bir hizmet bulucunun gerektirdiği bağımlılıkların koleksiyonu, kodu oluşturur tüm testler, aynı global kullanıcı arayüzüyle etkileşim kurması gerektiğinden, test edilmesi daha zordur. hizmet bulma aracı.
Bağımlılıklar API yüzeyinde değil, sınıf uygulamasında kodlanır. Sonuç olarak, sınıfın dışarıdan neye ihtiyacı olduğunu bilmek daha zordur. Bunun sonucunda
Carveya hizmet bulucuda bulunan bağımlılıklar, çalışma zamanı veya test ile sonuçlanabilir hata mesajları ve referansların başarısız olmasına neden olabilir.Nesnelerin ömürlerini yönetmek, yalnızca nesnel uygulamanın ömründen başka herhangi bir şeye dayanıyor olabilir.
Android uygulamanızda Hilt'i kullanma
Hilt, Jetpack'te öneriliyor uygulama kitaplığını kullanıma sunduk. Hilt, standart bir proje yönetimi yöntemi Uygulamanızdaki her Android sınıfı için kapsayıcılar sağlayarak ve yaşam döngülerini sizin için otomatik olarak yönetmelerine yardımcı olur.
Hilt, popüler DI kitaplığının üzerine inşa edilmiştir Dagger derleme zamanı doğruluğu, çalışma zamanı performansı, ölçeklenebilirlik ve Android Studio desteği sağlamak için tasarlandı.
Hilt hakkında daha fazla bilgi edinmek için Hilt ile Bağımlılık Enjeksiyonu.
Sonuç
Bağımlılık yerleştirme, uygulamanıza aşağıdaki avantajları sağlar:
Sınıfların yeniden kullanılabilirliği ve bağımlılıkların ayrıştırılması: Değiştirmek daha kolaydır bağımlılığın uygulamaları. Ters çevirme sayesinde kodun yeniden kullanımı iyileştirildi Sınıflar artık bağımlılıklarının nasıl oluşturulduğunu kontrol edemiyor. herhangi bir yapılandırmayla çalışır.
Yeniden düzenleme kolaylığı: Bağımlılıklar, API'nin doğrulanabilir bir parçası haline gelir yüzey, böylece nesne oluşturulma zamanında veya derleme sırasında kontrol edilebilir yerine bu verileri kullanabilirsiniz.
Test kolaylığı: Sınıf, bağımlılıklarını yönetmez. Dolayısıyla, test etmek tüm araçları test etmek için farklı uygulamalardan isteyebilirsiniz.
Bağımlılık yerleştirmenin avantajlarını tam olarak anlamak için bu özelliği denemeniz gerekir Manuel bağımlılık ekleme bölümünde gösterildiği gibi uygulamanıza manuel olarak ekleyin.
Ek kaynaklar
Bağımlılık yerleştirme hakkında daha fazla bilgi için aşağıdaki ek kaynakları inceleyin.