# Patterns for Organizing Domain Logic

#### What is a Design Pattern?

&#x20;Design Pattern 通常需要具備幾個描述要件 Context, Problem, Solution。

* Context
  * 解釋目前遇到的問題，所以需要提出一個 pattern
* Problem
  * 描述遇到的問題，所以需要權衡的難點 (Forces)，這個難點通常會是有互斥的狀況。
* Solution
  * 提出的方案，需要平衡難點，通常會需要提出兩個面向
    * 靜態 Relationship
    * Run-time behaviour

#### Domian Logic Problem Context

Domain Logic 在維護上管理上，需要精準的處理 Business model 需要兼顧軟體的維護性、可理解性、效能以及可測試性。當隨著軟體迭代，維護性、可理解性、效能以及可測試性都會隨著時間越來越複雜。

#### Problem

1. 要如何保持低開發成本
2. 隨著時間產品生命週期越久，所需要開發成本越高
   1. 指的是維護性、可理解性、效能以及可測試性
   2. 開發時間： 測試時間，開發時間，理解程式碼

#### Solution

從\[1] 文獻中，主要有三個 pattern 使用 Transaction Script, Table Moudle, Domain Model，隨著產品的生命週期，可以採用以順序為： Transaction Script ->  Table Moudle -> Domain Model 。

<figure><img src="https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2F8aj3Lj4ozX1qhgeU29ez%2Fimage.png?alt=media&#x26;token=fefde8d0-60c5-4a26-9603-1bfdd6d5e9c4" alt=""><figcaption><p>[1] A sense of the relationships between complexity and effort for different domain logic styles.</p></figcaption></figure>

* Transaction Script

Def: `Organizes business logic by procedures where each procedure handles a single request from the presentation`

Transaction Scripts 不會再細分結構，像是  retrive data, handle request ... 。換句話說，將所有的邏輯封裝在 `Object` 中。

#### &#x20;Static Structure

{% @mermaid/diagram content="classDiagram
class TrasactionScript {
<<interface>>
run()
}
class RevenueCaculation {
new(Contract c, Date d)
run()
}

```
class ContractCombination {
    new(Contract[] c)
    run()
}    
RevenueCaculation --|>  TrasactionScript
ContractCombination --|>  TrasactionScript" %}
```

#### Dynamic Structure

{% @mermaid/diagram content="sequenceDiagram
main ->> ContractCombination: run()
ContractCombination ->> data\_gateway: get data
data\_gateway -->> ContractCombination: data
ContractCombination ->> handle\_request: handle others request
handle\_request -->> ContractCombination: give some results
ContractCombination -->> main: return
" %}

* Domain Model

Def: `An object model of the domain that incorporates both behavior and data`

在 Domain model 中，會明顯區分 Entity Object 與 Value Object。&#x20;

1. Entity Object: 可直接對應商業邏輯的 component 並可直接取用 data，具有 identity 的特性 (唯一性)。
2. Value Object: 是一種裝飾 Entity Object 的一種結構。具備 Comparable 的特性。

> 在 Domain Model 需要盡可能對應需求的操作

{% @mermaid/diagram content="---
config:
class:
hideEmptyMembersBox: true
-------------------------

classDiagram
class Contract {
stirng id
new(string name, Product\[] ps) Contract
}

```
class Product {
    stirng id
    new(string name) Product
}

class Stripe {
    pay(Product[] ps) error
}
class Bank {
    pay(Product[] ps) error
}  

class Payment {
    <<interface>>
    pay(Product[] ps) error
}

Stripe --|> Payment
Bank --|> Payment

data <-- Product
data <-- Contract
Product --> Payment
Contract  *-- Product" %}
```

#### Dynamic Structure

{% @mermaid/diagram content="sequenceDiagram
participant main
participant contract
participant product
participant data
participant stripe

```
main ->> contract: get the contract
contract ->> data: get contract
data -->> contract: contracts
contract ->> product: get contract's products
product ->>  data: get product
data -->> product: products
product -->> contract: products
contract -->> main: contract
main ->> contract: caculate price
contract ->> product: caculate price
product ->> data: get payment
data -->> product: payments
product -->> contract: payments
contract -->> main: payments
main ->> stripe: create payment intention
stripe -->> main: return
" %}
```

* Table Moudle

def: `A single instance that handles the business logic for all rows in a database table or view.`

&#x20;這一個介於 Domain Model 與 Transaction Script 的一種 Pattern。與 Domain Model 最大的區別在於 Object 沒有 ID 的概念，且沒有特別區別 Object 定義。

#### Static Structure

{% @mermaid/diagram content="---
config:
class:
hideEmptyMembersBox: true
-------------------------

classDiagram
class Contract {
Product\[] products
GetContract(string id) Contract
}

```
class Product {
    GetProduct(string id) Product
}

class Payment {
    pay(Contract) error
}

data <-- Product
data <-- Contract
data <-- Payment

Contract  *-- Product
Payment --> Contract" %}
```

#### Dynamic structure

{% @mermaid/diagram content="sequenceDiagram
participant main
participant contract
participant product
participant data
participant stripe

```
main ->> contract: get contract
contract -->> data: get contract
data -->> contract: contract
contract -->> main: contract

main ->> product: get products
product -->> data: get products
data -->> product: products
product -->> main: products
main ->> main: caculate price
main ->> stripe: create payment intention
stripe -->> main: return
```

" %}

#### Conclusion&#x20;

<table><thead><tr><th width="117.73828125">Pattern</th><th>Positive </th><th>Negative</th><th>Suggestion Scenario </th></tr></thead><tbody><tr><td>Transaction Scripts</td><td><ul><li>在量體小的feature 是容易理解的</li><li>學習難度低</li></ul></td><td><ul><li>擴充性很差，當要持續維護的時候難度很高，且會有很多重複的程式碼。</li></ul></td><td><ul><li>一次性的 scripts</li></ul></td></tr><tr><td>Domain Model</td><td><ul><li>貼近 Business Logic </li><li>具備好的擴充性</li></ul></td><td><ul><li>相對於三個 patterns 中最複雜的</li><li>學習曲線難度高</li></ul></td><td><ul><li>長期大型專案</li></ul></td></tr><tr><td>Table Module</td><td><ul><li>具備好的擴充性</li><li>學習難度低</li></ul></td><td><ul><li>複雜度介於中間</li><li>Object 無法完全貼近真實情境</li></ul></td><td><ul><li>中長期大型專案</li></ul></td></tr></tbody></table>

### Reference

\[1] Fowler, Martin. *Patterns of enterprise application architecture*. Addison-Wesley, 2012.
