當我們討論完架構分層後,再來就是具體細節怎麼做的問題了,你可以分成不同的 class,或是放在不同的 package,或是使用我們今天將要介紹的技巧 - modularization。
Modularization 大概是隔離依賴最有用的作法了,當你想要完成 clean architecture 所要求的只有外層能依賴內層這種非常嚴格的架構,modularization 會是最常見的方法。
一個 module A
只有在 build.gradle
宣告 module B
的 dependency 才能使用 A
的內容,這樣好處就是任何人可以透過這些資訊快速的了解一個專案的結構。
dependencies {
implementation project(":moduleB")
}
除了架構清晰以外,還有個更明顯的好處:Build Speed。
越多的 module 拆分讓 gradle 可以每次只重新 build 有改變的 mmodule。
除了依賴關係外,gradle 還會檢查 implementation
跟 api
二種不同宣告 dependency 的方式,進一步限縮需要重新 build 的範圍。
implementation
跟 api
是在 Android Gradle plugin 3.0 開始提出的新功能,大家應該都發現我們在宣告 dependency 的時候都是用 implementation
這個關鍵字,那 implementation
跟 api
到底有什麼差別呢?
api
就跟以前的 compile
ㄧ樣,引用一個 library module 可以完全使用該 module 內部有的程式碼,甚至該 module 內部引用的其他 library module。
相反地,implementation
只會暴露這個 module 內部的程式碼,module 內部使用的其他 library module 並不會再對外暴露,這帶給我們一個好處是當修改發生時,gradle 可以更小範圍精準的重新 build 真正有需要 build 的 modules。
特別注意,api 的宣告並不是不好,只是可以多想二分鐘是否真的有需要。
Modularization 不只可以水平依架構分層,也可以垂直依據功能不同來拆。
通常架構拆分會先從水平開始,為什麼呢?
在還沒有良好架構的時候,多個功能可能會有複雜的相互依賴,或是多處重複,水平依據架構分層可以讓元件間關係變清晰,程式碼重複的情形也會比較少。
只是水平切分也有水平切分的難度在,比如說在低層所使用的物件,無法(或不應該)暴露讓高二層的物件使用,我們可以有二種方法解決:
一個方法是把資料物件獨立於另一個 module,讓所有 module 依賴。
另一個方法是每一層提供不同的物件實作,一層一層不斷的做資料的轉換。
具體哪個方案比較好就看大家自己的需求來取捨抉擇了!
有了良好架構後,就可以開始依據功能垂直切分讓不同的團隊來負責不同功能,好處是每個小組可以更專注在自己的 module 裡,但因為垂直拆分會有同一水平需要呼叫的問題,但彼此又沒有權限拿到對方的 reference,通常是透過第三者處理或是透過反射等機制來獲取 runtime 時的 reference。
假設我們有二個不同的 Activity 分處在不同的 modules ,這時候我們就可以這樣呼叫:
// Can't get the SecondActivity reference
// val intent = Intent(this, SecondActivity::class.java)
val intent = Intent(Intent.ACTION_VIEW).setClassName(
"YOUR_PACKAGE_NAME",
"YOUR_CLASS_NAME_WITH_PACKAGE"
)
startActivity(intent)
當然你也可以使用 deeplink,用 url 來 mapping 所有的
Activity
,筆者認為這是個很乾淨的作法。
拆分 feature module 還有個潛在的好處是,將來如果要支援 dynamic delivery 的時候,可以無縫接軌。
詳見: https://developer.android.com/studio/projects/dynamic-delivery
架構的部分討論的差不多了,明天我們會開始進入測試這個有趣的主題,敬請期待!
參考資料:
Build a Modular Android App Architecture (Google I/O'19)
https://www.youtube.com/watch?v=PZBg5DIzNww
Android 十全大補已經正式出書上架囉!
有興趣的讀者歡迎參考:
https://www.tenlong.com.tw/products/9789864345786