iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 19
0
Mobile Development

Android 十全大補系列 第 19

[Android 十全大補] Clean Architecture

寫程式就像蓋房子一樣,蓋房子我們必須先有藍圖,再來架鋼筋、上水泥、批土、上油漆,最後才是傢俱跟裝飾。

而架構就像是蓋房子的鋼筋水泥一樣,是整套程式碼的基石,架構的好壞會間接影響到我們最後傢俱擺設、是否具備冬暖夏涼的好處、日常起居動線是否順暢等,偷工減料的架構某方面也代表某天會禁不起颱風、地震等的劇烈考驗,甚至有可能被列為危樓必須打掉重練。

架構也意味著規則、限制,希望盡可能藉由良好的規範帶來更多好處與省去不必要的麻煩,這也意味著架構沒有統一的標準。我們要一直不斷的在限制與好處間找到平衡點,每個人心中好架構的概念可能都不一樣,也可能根本就不存在最完美的架構這種東西,雖然如此但還是有些法則我們可以討論看看的。

Clean Architecture

要談架構就不能不提到 Clean Architecture,這個一樣是由 Uncle Bob 大神所提出的概念:

原文在此,強烈建議大家多看幾遍,畢竟 Uncle Bob 可是有幾十年的功力呢!
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

這張架構圖由好幾個同心圓組成,每一層代表著軟體的不同職責,由內到外共有以下這幾層:

  1. Entities
  2. Use Cases
  3. Interface Adapters
  4. Frameworks & Drivers

每一層只會像內依賴而不需在意外圍的存在,比如說 Use Cases 只會知道 Entities 的存在而不了解 Interface Adapters 是什麼,以此類推。以下我們一層一層來討論:

Entities

Entities 指的是我們的核心物件與基礎商業邏輯,像是 user object、password policy、payment api 等跟應用程式無關的核心功能。
另一個重點是 Entities 應該是很少變動而且不需依賴於其他任何層級的存在。

Use Cases

Use Cases 指的是跟我們應用程式相關的商業邏輯。
大家可能會覺得跟 Entities 實在是有點接近,Use Cases 跟 Entities 的差別在於:
Use Cases 多半會再透過多個 Entities 來達成目的,比如說變更密碼的 Use Case 可能要先檢查新密碼是否符合規範、二次輸入的新密碼是否一致,都成功才送出變更密碼的 api。
諸如此類跟 flow 相關的程式碼都屬於這一層級。

Use Cases 另一個好處是可以限制了 Entities 的存取,減少外部誤用的機會也提高了可讀與安全性。

Interface Adapters

Interface Adapters 就像我們的 RecyclerView.Adapter 一樣,是把二層不一樣的元件,透過這個中介層完美的介接融合在一起。

我們之後會介紹的 MVP、MVVM 的 Presenter 跟 ViewModel 就是屬於 Adapter 的角色,介接融合 Android View(Activity) 跟 Use Cases 的地方。

除了介接融合 function 的呼叫以外,也可以做 data class 的介接,如果對於業務邏輯跟顯示所需要的資料內容不一樣,都可以在 Adapter 這層做轉換,比如說 Activity 間傳遞的物件必須實作 Parcelable,但業務核心物件並不需要依賴 Android。

Parcelable 是 Android 元件間傳遞資料的一種協定,詳情請見:
https://developer.android.com/reference/android/os/Parcelable

Frameworks & Drivers

Frameworks & Drivers 是 platform 相關的程式碼,對 Android 來說就是 ActivityView 、 xml 或是 RecyclerView.Adapter 等純 UI 相關的程式碼,因為邏輯被拆分到不同的層面,所以通常只會有簡單的畫面呈現以及依據不同的狀態做不同的更新,這一層也不會知道太多業務邏輯,所有事件都會傳遞給 Interface Adapters 做進一步的運算(通常也是繼續傳給 Use Cases)。

Conclusion

大家可能會好奇我們這樣拆分後會有什麼好處,感覺把一件簡單的事情弄的很複雜,但其實只有一開始不太熟悉的時候頭腦必須做點轉換,等上手之後就會覺得每一層的架構很清晰單純,筆者覺得有以下幾個好處:

  • 邏輯清楚
    還記得 Single Responsibility Principle 嗎?
    因為每一層的職責非常明確,所以程式碼會比較易讀好維護。

  • 好測試
    測試是個很重要的一環,良好的測試代表良好的品質,架構分層之後,每一層可以用每一層適合的測試方法來輔助。
    比如 Entities 就只需要寫 UnitTest,但是 Frameworks & Drivers 就必須使用 Android 所提供的測試方法。

  • 重用
    一段程式碼寫成 function 是為了讓別的地方可以方便使用,而不用寫重複的 code,比如說登入頁面跟重設密碼頁面可能都有忘記密碼這個功能,如果沒有分層的話,有可能會被寫成二個差不多的 function,但因為架構分層後,最後都會導到 User 的 Use Cases 裡,就會更自然的被重用。


  • 這點非常有趣,筆者工作多年發現,大部分的工程師都喜歡在具有良好架構的程式碼的環境工作,那種寫出一份漂亮程式碼的開心,我覺得是很少事情能夠比擬的。
    相反的,如果每天面對一份很冗長雜亂的程式碼,相信很多人很快就會離職了。
    所以,時時刻刻保持你的程式碼在一個很酷的架構下,不但自己工作開心,可以吸引到優秀的同事加入,你的優秀同事們也會跟你一起長長久久寫出優秀的程式碼呢!

不知道大家有沒有其他意見呢,歡迎分享給我知道!

Android 十全大補已經正式出書上架囉!
有興趣的讀者歡迎參考:
https://www.tenlong.com.tw/products/9789864345786


上一篇
[Android 十全大補] SOLID Principle
下一篇
[Android 十全大補] Dagger
系列文
Android 十全大補30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言