# Domain Model: 從無到有規劃新的服務

規劃軟體服務的過程比實作來的重要，在還未規劃完整直接開始，很容易造成開發出來的產品不符合客戶的需求。但怎麼規劃又是一個問題，在現實生活中，不少Application 開發後使用者完全不買單的案例…因此如何規劃就是一個重點。

根據POSA v4\[1] 針對從零規劃軟題服務所給出的建議(From mod to Structure):&#x20;

***“Create a model that deﬁnes and scopes a system’s business responsibilities and their variations: model elements are abstractions meaningful in the application domain, while their roles and interactions reﬂect the domain workﬂow.”***&#x20;

從上述這段話歸納出三個重點，1. **Business responsibilities**、2. **A model that deﬁnes and scopes**、3. **Elements are abstractions meaningful in the application domain。**&#x9996;先需要定義好所需要的Domain Feature，根據Domain Feature進一步將軟體中的Entity、Value Object 規劃出來，並由這些Elements 組成可以跑得Service。

### **Business responsibilities**

在傳統開方上商業邏輯的時候通常是經歷過層層關卡慢慢傳遞到工程師，然而需求收斂的過程中，許多潛在動機將無法順利傳遞，使得工程師所產出的程式法跟Domain knowledge 對不上，使得開發出來的產品不符預期的機會大大提昇。***因此工程師須參與整個軟體設計的過程。***

此外溝通所使用的工具也是相當的重要。由於工程師、客戶、專案管理員...等參與人事的背景不盡相同，可能造成溝通上的困難。**像是透過UML統一建模語言，與Prototype 的實作多次的確認需求，才能有效的確認商業邏輯。**

{% hint style="info" %}
但不限於只能使用UML，只要團隊自行約定好即可。
{% endhint %}

舉例，像是**Ontology、Data Flow Diagram (DFD)等工具都是很好表達系統的方式，**&#x7136;而也可以透過心智圖等等的非正規軟體用的工具也可，總而言之表達清楚軟體設計，減少溝通所造成的消耗。

### **A model that deﬁnes and scopes**

如何從Business Responsibilities則需要先釐清問題本身，**將會發現一個大問題可以被拆分成多個小問題**。**這些小問題則稱為Model**。往往定義Model應該與軟體架構同時被考慮，不因軟體的限制，導致整體架構無法將Model 行為抽象化，也不能為了Model 的功能而忽略軟體的限制。 **換句話說，希望可以從Model具有的意義也同時在軟體架構中也看得出來，但也不能完全忽略軟體的限制。**

什麼是軟體的限制？往往在開發的時候，已經先決定使用哪個工具，就應該充分的利用工具的優勢。舉例來說，**當已經決定使用Socket.io 其本身具有Broadcast的功能與房間管理，那因此在設計聊天室等功能，則必須盡量貼近Socket.io的特性，也不能一昧的依照domain的需求，完全忽略所使用工具的優勢或劣勢。**

#### Extract Model From *Business Responsibilities* *(Domain)*

![](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZBn9owI5fBe0HrECdk%2F-MiXT57TwZHOWPN5OgP5%2F-MiXTlVpul-PqO7AJj6c%2Fimage.png?alt=media\&token=29f2e6ac-0732-4fad-b7f0-1beb741d8264)

一般來說軟體上可以分為四層，UI、API、Logic、Essential 這四層，同時也遵守Layers Architecture Pattern 的規範，層層之間可互相存取，但不可以跨層存取。其中Domain是指對應Business Responsibility ，在軟體上需要做到Domain則須要根據fundamental 進行實作。

![](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZBn9owI5fBe0HrECdk%2F-Mig5Xlv0lymETO6EO_l%2F-MigBhxIhYe9vylWMoDp%2FUntitled%20Diagram.drawio.svg?alt=media\&token=313ca614-bf90-4685-b75c-7a74feccd830)

當軟體實作時，可以如上圖Class Diagram，.透過API層只與Domain 有interaction，然而Domain 還可細分成Domain、Model 兩種Component。而需要做到Domain 的功能則必要使用 Model 才能達成。而Model 則透過 Fundamental 的交互作用達成。&#x20;

在實務上的工程師可能會問，需要了解到什麼程度呢？ 難道需要變成另一個domain的專家才可以開始做嘛？ **事實上，工程師只要確認將要研發的軟體架構，是符合domain 知識的即可，因此在軟體設計的過程，需要時常與domain 專業人士進行對焦確認，並不需要變成另一個領域的專業人士。**

**Elements are abstractions meaningful in the application domain**

當在規劃軟體服務的時候，共分成Entity、Value Object、Service 等三種角色，而Service的概念是對應到Model的概念，然而Entity、Value Object 對應到Fundamental。Entity 就是一個就有Unique ID之類的可辨別的屬性，而Value Object 則是用於控制Entity 物件的物件，Service 則是Entity + Value Object 所組成的功能。

![](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MZBn9owI5fBe0HrECdk%2F-Mijq1PLskG27PG6wCM1%2F-MijqOZDsjFk5S2tQE9o%2Fimage.png?alt=media\&token=7c4913ea-07ab-4578-99d0-6088bf5d4e37)

以物流車負責運送多個訂單的實作功能為例，如上圖Class Diagram，LogisticVehicle 屬於Object Value 物件，Order 屬於Entity 物件。因為對於使用者而言，LogisticVehicle 並無法區分，但Order 則是具備特定意義且能夠區分出來。

### 結論

在軟體開發中，Domain know how 須與實際的設計一起被思考。程式設計師不僅應該參與Feature 的討論，也應該針對Domain Knowledge 進行進一步的了解，使所產出的程式設計與Domain know how盡可能貼近。此舉除了日後更好維護之外，同時也能夠降低日後擴充新功能的難度，因為越貼近Domain Know How所定義出來的Entity 物件越不容易有大的更動。

除此之外，設計時不用一昧的使用UML將整體設計畫的非常詳細，因為往往系統發展之後，會過於龐大以至於無法明顯表達出設計的意含，不過之前所有規劃的設計腳本，也應該被歸檔，讓日後接手維護的開發者能更快速的了解程式的架構，才不會越修改卻離Domain 越遠。

### 參考資料

\[1] Frank, Buschmann, Henney Kevlin, and C. Schmidt Douglas. Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4). Wiley, 2007. \
\[2] 趙俐、盛海豔、劉霞譯，Domain-Driven Design領域驅動設計, 博碩文化，2019。
