July 6 09:52~10:58
▲直接跨層XD
前言
將軟體架構分層並且確認相依性嚴格遵守由外往內(由低層往高層)的這兩個原則之後,接下來會面臨到另一個問題:「物件跨層時該怎麼辦?」。
***
跨層範例
▼請參考下圖,AddHostController呼叫AddHost Use Case,它再呼叫Entity層的Host物件,並獲得一個Host物件。接著AddHost Use Case直接把Host物件往外傳給AddHostController。
上面這個例子有兩件事情需要討論:
- 內層物件可否跨層往外傳:舉例來說,位於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函式庫是由網頁應用程式框架所提供)
***
定義雙向介面
▼如下圖所示,《Clean Architecture》書中建議Use Case需要定義「雙向介面」,簡單來說就是定義Use Case的Input與Output介面與參數的資料型態。
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。
▼FetchHostsUseCase介面定義
▼FetchHostsInput類別。請注意,如果嚴格依據《Clean Architecture》書中的圖示,應該先將FetchHostsInput定義成一個介面,然後再讓FetchHostsUseCase提供這個介面的實作。在此Teddy偷懶簡化這個步驟,直接將FetchHostsInput設計成一個具體類別。
▼FetchHostsOutput介面
▼HostListPresenter
▼FetchHostsUseCase實做
***
結論
《Clean Architecture》整本書雖然有多達34章,如果可以掌握分層、相依性與跨層這三個重點,在實作Clean Architecture時應該就沒什麼困難之處。
***
友藏內心獨白:還有一個Missing Chapter沒討論…
沒有留言:
張貼留言