l

2018年7月6日 星期五

Clean Architecture(6):架構三原則三部曲—跨層原則

July 6 09:52~10:58

螢幕截圖 2018-07-06 10.58.15

▲直接跨層XD


前言

將軟體架構分層並且確認相依性嚴格遵守由外往內(由低層往高層)的這兩個原則之後,接下來會面臨到另一個問題:「物件跨層時該怎麼辦?」。

***

跨層範例

▼請參考下圖,AddHostController呼叫AddHost Use Case,它再呼叫Entity層的Host物件,並獲得一個Host物件。接著AddHost Use Case直接把Host物件往外傳給AddHostController。

螢幕截圖 2018-07-06 10.05.10


上面這個例子有兩件事情需要討論:

  • 內層物件可否跨層往外傳:舉例來說,位於Entity層的Host物件可以直接跨層(跨過Use Case層)傳給AddHostController嗎?依據相依性原則,上述情況還是有遵守「外層相依於內層」的規定,只不過AddHostController跨過Use Case這層相依於Entity層的Host物件。Teddy並未在《Clean Architecture》書中看到可否「跨層相依」的描述,而網路上國外鄉民所實作的範例,有些直接跨層相依,有些則是會將Host物件在AddHost Use Case轉過一次再傳給AddHostController(請參考稍後討論的Use Case雙向介面)。
  • 外層如何將資料傳給內層:假設AddHostController從瀏覽器收到使用者所填寫的「新增Host表單」,並將其內容轉成一個JSON物件。如果AddHostController直接將這個JSON物件傳給AddHost Use Case,將會破壞相依性原則,因為如此一來AddHost Use Case就相依於屬於應用程式框架的JSON物件。

▼直接把JSON從Controller往Use Case傳遞違反了相依性原則(假設JSON函式庫是由網頁應用程式框架所提供)

螢幕截圖 2018-07-06 10.29.56

***

定義雙向介面

▼如下圖所示,《Clean Architecture》書中建議Use Case需要定義「雙向介面」,簡單來說就是定義Use Case的Input與Output介面與參數的資料型態。

螢幕截圖 2018-07-06 10.32.55

Use Case本身提供Input介面與資料型別實作,外層的Controller要將參數傳給Use Case時,必須負責把參數型別轉成Use Case所定義的Input介面。

Use Case的Output介面則由Presenter所實作(Presenter是Model-View-Presenter設計模式裡面的那個Presenter),呼叫Use Case時Controller會傳入Presenter物件,Use Case則將透過Presenter物件輸出資料。


▼看一個程式範例片段,HostController的getHosts函數呼叫FetchHosts Use Case得到所有host的列表,它首先產生HostListPresenter物件與FetchHostsInput物件,並將它們傳給FetchHosts Use Case。FetchHosts Use Case從FetchHostsInput物件獲得搜尋物件的參數資料,並將找到的資料傳給HostListPresenter。

螢幕截圖 2018-07-06 10.40.21


▼FetchHostsUseCase介面定義

螢幕截圖 2018-07-06 10.45.04


▼FetchHostsInput類別。請注意,如果嚴格依據《Clean Architecture》書中的圖示,應該先將FetchHostsInput定義成一個介面,然後再讓FetchHostsUseCase提供這個介面的實作。在此Teddy偷懶簡化這個步驟,直接將FetchHostsInput設計成一個具體類別。

螢幕截圖 2018-07-06 10.45.49

▼FetchHostsOutput介面

螢幕截圖 2018-07-06 10.48.20


▼HostListPresenter

螢幕截圖 2018-07-06 10.49.15


▼FetchHostsUseCase實做

螢幕截圖 2018-07-06 10.52.54

***

結論

《Clean Architecture》整本書雖然有多達34章,如果可以掌握分層、相依性與跨層這三個重點,在實作Clean Architecture時應該就沒什麼困難之處。

***

友藏內心獨白:還有一個Missing Chapter沒討論…

沒有留言:

張貼留言