l

2020年9月6日 星期日

為什麼不要把後端的領域物件直接傳給前端?

September 06 20:50~22:22

▲ezKanban的tag功能


前幾天有一位朋友問Teddy:「Clean Architecture提到不要把Entity Layer的物件直接傳到UI端,但真的有需要跨層的時候把物件都轉成DTO再往外傳嗎?」

***

以ezKanban為例子

ezKanban是一個支援多人同時使用的看板系統,圖1為其簡化版的領域模型。Board代表一個看板,其中包含了若干個Workflow(工作流),每個Workflow可以有若干的Lane。Lane區分成兩種,垂直的Lane稱為Stage(階段),水平的Lane稱為Swimlane(泳道)。Card(卡片)可以被放到Lane上面,並在不同的Lane之間移動。


▲圖1:ezKanban簡化版領域模型


假設Board被直接傳到前端,前端設計出如圖2所示的畫面。

▲圖2:ezKanban畫面


到目前為止沒什麼問題,前端UI物件模型與後端的領域模型大致上是一致的。一直到有一天客戶有新的需求:

  • 希望增加Tag的功能來將Card分類
  • 每個Board都可以有自己的Tag,不會與其他Board共用Tag
  • 一張Card可以有多個Tag

如果從UI的角度來思考:「Board包含Tag,然後這些Tag才可以被指定到屬於這個Board的卡片裡面。」為了能夠在畫面上顯示Tag,前端的人很可能會要求後端將Tag加入Board物件成為它的屬性,變成如圖3所示的關係:


▲圖3:因為UI的需求,導致Board與Tag產生關係

***

問題出在哪裡?

直接把Entity Layer的物件傳給前端違反單一責任原則。Entity Layer的物件之所以會存在,是為了解決或是表達問題領域的重要概念與商業邏輯。如果把它們直接傳給UI,拿來當作顯示畫面之用,Entity Layer的物件就擔負了兩種責任:

  • 表達商業邏輯與概念
  • 表達顯示邏輯

如此一來Entity Layer的物件就可能因為兩種不同客戶端的需求改變而跟著改變,換句話說Entity Layer與UI產生耦合,導致程式難以理解、修改與維護。

***

如何解決?

回歸到Clean Architecture與領域驅動設計(Domain-Driven Design;DDD)的角度,先確定商業邏輯,至於使用者介面是屬於細節,等Entity Layer與Use Case Layer確定之後,再交給Presenter產生View Model來滿足前端顯示的需求即可

回到幫Card貼Tag的需求,把Tag歸類為Board的屬性並不合理,因為Tag並不是要貼在Board上面,使用者只需要知道這個Board裡面建了多少種類的Tag,再拿這些Tag貼在卡片上面。也就是說,Tag只需要知道它自己屬於哪一個Board的單向關係即可,Board根本不需要知道Tag,如圖4所示。


▲圖4:Board, Card與Tag的關係


至於前端所需的所有資料,如圖5所示另外設計一個BoardContentViewModel。這個View Model是由Presenter為了前端所需而動態產生,Entity Layer並沒有一個這樣的靜態Model。

▲圖5:ezKanban管理Tag畫面


最後的領域模型,Tag物件不屬於Board,使用者可以獨立新增與修改Tag,也很容易直接將Tag指定給Card,請參考圖6與圖7。


▲圖6:ezKanban管理Tag畫面


▲圖7:ezKanban顯示Card上面多個Tag

***

友藏內心獨白:UI歸UI,Domain Model要分明。

1 則留言:

  1. 首先,我很配服你的圖文以及排版能力,深入淺出的教學。
    但因為你涉及的領域不是我所熟悉的PHP、Java、HTML以及以外的Ruby、python等等。

    你的問題很簡單。
    大部份的程式設計師不知道。
    他們設計完後的成品。

    要給客戶端能夠(自行設計),像魔獸爭霸的「地圖建置系統」,世紀帝國的「自訂遊戲」。魔法門之英雄無敵的「自創地圖」。
    劇情、地圖、場景,全部都可以讓玩家自行發揮。

    所以當你把功能通通都寫死在裡面的時候,你的系統就只剩你能改而已。
    這個就要分二個取向,不應該這麼簡單述明。

    因為這文章的「預設基礎」是這個軟體的使用者(公司),他們有請人定期維護這個軟體,讓他們依據業務需求對「內容進行變動」。
    你才需要把這功能向外建置。

    如果不是。
    全部嵌在裡面,可以減少程式運行效能,節約電能。

    我們不應該為了「沒人使用的流動性」,而特意把這東西建置在「前端」。
    而且考量到利益面。

    假設這公司10年內固定的使用軟體版本,只有每年有變動的需求。
    那這期間的維護,會在額外委聘設計者調整,也是一筆收入。

    所以過度的設計「自定功能」給客戶使用,還昌追求極簡化「效率與利益」,絕對沒有單一的判斷基準。

    回覆刪除