状態の集合による注文のモデリング
code:text
workflow: "Place order" =
input: OrderForm
output:
OrderPlaced event (put on a pile to send to other teams)
OR InvalidOrder (put on appropriate pile)
// ステップ 1
do ValidateOrder
If order is invalid then:
add InvalidOrder to pile
stop
// ステップ 2
do PriceOrder
// ステップ 3
do SendAcknowledgmentToCustomer
// ステップ 4
return OrderPlaced event (if no errors)
https://scrapbox.io/files/669f2e87514fe6001dcae342.png
code:fsharp
type Order = {
...
IsValidated: bool // 検証時後に true
IsPriced: bool // 価格計算後に true
AmountToBill: float option // 価格計算後に設定
}
問題点
1. 状態が暗黙的なので、処理するには多くの条件分岐が必要
2. 状態によって必要なフィールドは異なるため、1 つのレコード型で表すと複雑になる
フィールドを省略可能 option にする必要がある
3. どのフィールドとどのフラグが対応するのか明確ではない
isPriced が設定されている場合は、AmountToBill も設定する必要がある
しかし、ルールを強制することはできないため、コメントで促すしかない
各状態に対して新しい型を作成する
既存のコードを壊すことなく、新しい状態を追加できる
そらそうよ radish-miyazaki.icon
code:fsharp
// 検証済みの注文
type ValidatedOrder =
{ OrderId: OrderId
CustomerInfo: CustomerInfo
ShippingAddress: Address
BillingAddress: Address
OrderLines: ValidatedOrderLine list }
// 価格計算済みの注文
type PricedOrder =
{ OrderId: OrderId
CustomerInfo: CustomerInfo
ShippingAddress: Address
BillingAddress: Address
OrderLines: ValidatedOrderLine list
AmountToBill: BillingAmount }
取りうる状態をすべて作成すると、そこから 1 つ選択するトップレベルの型を作成できる
code:fsharp
type Order =
| Unvalidated of UnvalidatedOrder
| Validated of ValidatedOrder
| Priced of PricedOrder
注文のライフサイクルにおけるどんな時点の状態でも表現できるオブジェクト
ストレージに 永続化 したり、他のコンテキストとコミュニケーションを取れる型