iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0

Keyword: Dependency Injection
到Day20 使用Koin管理依賴注入顯示在Android上 放在這邊
KMMDay20


依賴注入(Dependency Injection)

依賴注入(Dependency Injection,簡稱DI),是一種...物件的使用法,主要的目標是降低物件與物件之間的耦合關係.關於相繫確的定義網路上一大堆.

這邊就用我自己的想法介紹吧.

依賴注入,分成了"依賴","注入"兩塊.

所謂的依賴,就是使用到的物件.稱為依賴.像是這樣:

//Kotlin
class People(var air:Air){
		val heart:Heart
}

這個例子中,人類沒有心臟(Heart)或是空氣(Air),就無法正常運作.那麼就稱 “人,依賴於心臟及空氣"

這就是依賴關係

既然需要這些重要的部分才能正常運作,那有兩種來源:一種是天生的,另外一個是外來的.

//Kotlin
class People(var air:Air){
		val heart:Heart = UnbreakableHeart()
}

像上面這個例子,人類天生就有了一個心臟的實體,所以能正常運作.

那另外一種,由地球媽媽提供空氣:

//Kotlin
class EarthMom(){
	val air:Air = FreshAir()
	val people:People = People(air)
}

class People(var air:Air){
		val heart:Heart
}

有了地球媽媽帶來的空氣,人類也能正常運作了.

而後面這種由外部提供需要的依賴,就稱之為"依賴注入"

其實不難懂對吧?

依賴的問題

實際上在使用時,會有一個問題.就是如果某個部分發生了修改,所有依賴到的地方跟著修改,需要修改很多很多地方.

比如說,有一天,人類除了空氣,還需要水.

//Kotlin
class EarthMom(){
	val air:Air = FreshAir()
	val water:Water = CleanWater()
	val people_1:People = People(air,water)
	val people_2:People = People(air,water)
				...
	val people_6Billion:People = People(air,water)
}

class People(var air:Air, var water:Water){
		val heart:Heart
}

所以地球媽媽需要去把六十億人都加上water的需求.

但是人類的內容修改,跟地球媽媽有什麼關係呢?

這就是依賴所帶來的耦合,當被依賴的那方改變時,依賴的這方也需要作出調整.

如果有一個全知全能的神,可以提供所需要的任何東西,那麼人類變化就改成直接跟這個人要空氣跟水,不再由地球媽媽提供.那麼地球媽媽與人類的關係就解開了.

透過什麼方法提供呢,就是上面說過的依賴注入.而這個管理一切物件建立與回收的神,我們就稱之為"依賴注入框架"

依賴注入的好處

透過依賴注入框架的幫助,我們解耦了物件之間的依賴關係,所帶來了什麼好處呢?

  1. 物件之間的建構子不再會直接影響到額外的區塊
    由於所有的物件都由框架處理建構的部分,要使用到的物件也是直接跟框架索取.因此當規格修改時,只要修改框架內的生產邏輯即可作用於全局.
  2. 測試更容易撰寫了
    由於物件的產生由框架代勞,因此要進行Api或是DB的Mock時,只要修改框架的設定檔,就能直接更換成測試使用的Api或DB,而專案內部的程式碼,甚至都不用修改,就能夠進行測試.
  3. 不用再一路傳入不需要的數據
    在App中,常常有這樣的使用情境,去確認某資料需不需要更新,如果要更新的話就更新資料,並且把新資料儲存進本地的DB.
    Android的DB在使用時需要一個特別的物件 Context,所以問題就變為了為了不一定發生發生的DB存取,在進行流程的一路上都需要攜帶這個物件以備不時之需.十分惱人.
    而有了注入框架,就能夠在正式使用DB的時機,由注入框架提供所需要的物件,從這個情況中解放出來.

依賴注入的痛苦

在Android端,最著名的依賴注入框架,當數Dagger.有名的地方正是超高的學習曲線.有句玩笑話這樣說的“Dagger,從入門到放棄”.由於Dagger是設計給Java使用,而不是給Android專用,因此有非常多需要根據Android的情況而進行的特製.

https://github.com/officeyuli/itHome2021/raw/main/day18/learning%20curve.jpeg

上面說的,一個依賴注入框架需要管理物件的建立與回收,但是Android的應用端並不能”直接“接觸到Activity或是Fragment的建立與回收.

由於Android App是利用設計模式中的Template模式,僅僅露出了一小部分的開口讓Android工程師發揮,其餘部分則是由系統代為執行,也不讓一般的App有機會修改.例如畫面的測量與描繪,手勢事件的轉換和處理,都是由底層自行處理.這樣的好處就是開發很順暢,不用再去管一些無關緊要的小事,只要告訴系統,在Activity或是Fragment建立的時候順便做什麼事(onCreate/onDestory),或是發生事件時我想做什麼(onTouch/onClick).被系統掌控最明顯的就是,無法掌控App什麼時候被回收,有的時候一退到背景,系統本身就忙著把這個記憶體空間清出來,直接回收了.

也是因為這樣,想要在App端上實作一個依賴注入框架,是十分困難的,隨時要小心系統的背刺.再加上Dagger發生錯誤時通常Log所顯示的並不是真正的問題所在,還會需要為了不同的實作寫許許多的module設定檔,新人只要發生問題往往不知所措.連追蹤都很困難.這也是Dagger勸退很多人的原因之一

我在進行公司專案重構的時候,也曾經考慮到使用Dagger來進行依賴管理,但是考慮到學習成本與帶來的問題,所消耗的時間,最後決定不使用.當然目前也是因為當初的這個決定,依賴上也出現了很多問題,但是如果回到那時候,我仍然會選擇放棄Dagger.這也從側面證明了Dagger到底有多難學和使用.

官方也有注意到這個問題,所以在去年的Jetpack中,加入了Hilt,一個基於Dagger,Android專用的依賴注入框架,Dagger(匕首)加上了Hilt(刀柄),十分輕易好用.如果有新專案,我會推薦Android工程師使用Hilt.

但是這次我們寫的是跨平台KMM,那Hilt這些針對Andriod的優化就無法使用,所以我們這次將使用Kotlin官方推出的另外一套注入框架,針對Kotlin專用的,Koin.


上一篇
Day 17: swiftUI與Coroutine強強聯手,迸出新滋味.
下一篇
Day 19: Let's Koin!Koin 實作依賴注入
系列文
挑戰 Kotlin Multiplatform Mobile 跨平台開發,透過共同的Kotlin模組同時打造iOS與Android應用!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言