iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
Software Development

From State Machine to XState系列 第 13

Day13 - 解決狀態大爆炸 - 1: Parallel States (平行式狀態)

以昨天的例子而言,我們的 input 有 [Invalid / Valid]、[Disabled / Enabled]、[Changed / Unchanged],這 3 類型的特點

https://ithelp.ithome.com.tw/upload/images/20210927/20130721esiomcqiFn.png

讓我們仔細觀察一下

  • 假設有沒有 Invalid 不影響會不會 Disabled;
  • 假設有沒有 Invalid 不影響會不會 Changed;
  • 假設有沒有 Disabled 不影響會不會 Changed...
    並且假如我們說這 3 類特徵任意搭配組合也都是合理的...
    也就是[ Invalid 且 Disabled 且 Changed] , [Valid 且 Disabled 且 Changed] 這種奇怪的組合都是合法的話。

透過這些假設,我們發現(或是我刻意製造)這三類型特點,互不相關,彼此是相互獨立的、沒有依賴的關係。

先不以開發狀態機的角度思考,這個需求很自然的先想到可以將它拆成 3 組 Boolean Flag,存入 3 個變數(isValid, isEnabled, isChanged)

用變數 Boolean Flag 表達可能性的話

// 假設用不同 className 儲存、辨別 Input style
let className = ''

if (isValid && isEnabled && isChanged) {
  className = ''
} else if (!isValid && isEnabled && isChanged) {
  className = ''
} else if (isValid && !isEnabled && isChanged) {
  className = ''
} else if (!isValid && !isEnabled && isChanged) {
  className = ''
} else if (isValid && isEnabled && !isChanged) {
  className = ''
} else if (isValid && !isEnabled && !isChanged) {
  className = ''
} else if (isValid && !isEnabled && !isChanged) {
  className = ''
} else {
  className = '' // (!isValid && !isEnabled && !isChanged)
}

看起來真不可口

用 狀態大爆炸版 的 Finite State Machine 表達可能性的話

[Invalid / Valid]、[Disabled / Enabled]、[Changed / Unchanged]

可以列出以下

  • valid / enabled / unchanged
  • invalid / enabled / unchanged
  • valid / disabled / unchanged
  • invalid / disabled / unchanged
  • valid / enabled / changed
  • invalid / enabled / changed
  • valid / disabled / changed
  • invalid / disabled / changed

就像昨天提到的,在描述狀態的可能性就已經極其複雜,只不過...至少用「狀態」比用「 Boolean Flag 變數」的描述更明確(Explicity)指出、更有可讀性(Declarative)一點點...。但這邊都還沒辦法開始描述什麼東西能改變狀態?!

什麼事件發生後,狀態會發生改變?要怎麼描述?

今天要為大家介紹的就是平行式狀態,我們可以將這三組特徵、變數視為『各自獨立』的子狀態(substate)

  • [Invalid ⇄ Valid] 是一組子狀態機
  • [Disabled ⇄ Enabled] 是一組子狀態機
  • [Changed ⇄ Unchanged] 是一組子狀態機

因為這 3 組 子狀態機彼此獨立,我們將之視為平行世界、互不相干,我們稱之「平行」

而這 3 組 子狀態機組合而成的所有可能就是這個主體狀態,也就是說 「Input」的狀態 。

平行式狀態的狀態圖

我們可以根據此畫出平行的狀態圖
https://ithelp.ithome.com.tw/upload/images/20210928/201307217x4fU4EWAi.png

versus

https://ithelp.ithome.com.tw/upload/images/20210927/20130721uWTVRmuIor.png

相較於昨天畫的 state diagram ,不管在「狀態」或「事件」的描述是不是清晰多了?

小節

平行式狀態使我們能

  1. 使我們能提煉、精緻狀態,將離散的行為拆分成獨立的子狀態機
  2. 允許狀態間的獨立性 (反言之,轉移禁止跨越子狀態機之間)
  3. 鼓勵組合、組裝(Composability)
  4. 避免狀態大爆炸 ^^

參考資料

https://statecharts.dev/glossary/parallel-state.html
https://xstate.js.org/docs/guides/parallel.html
https://statecharts.dev/state-machine-state-explosion.html
https://xstate.js.org/docs/guides/hierarchical.html


上一篇
Day12 - 狀態機與現實世界的落差 - 2: State Explosion(狀態大爆炸)
下一篇
Day14 - 解決狀態大爆炸 - 2: Hierarchical States (階層式狀態)
系列文
From State Machine to XState31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言