$30 off During Our Annual Pro Sale. View Details »

「厳密な共通言語」としての形式手法 #devsumi / Developers Summit 2020

y_taka_23
February 13, 2020
5.1k

「厳密な共通言語」としての形式手法 #devsumi / Developers Summit 2020

Developers Summit 2020 で使用したスライドです。

言葉というものは曖昧です。複数人が「ともにつくる」システムにおいて、メンバ間で仕様を正しく共有することは非常に重要ですが、一方で言葉の裏側に隠された「暗黙の仮定」を見抜くことは簡単ではありません。このような仕様の曖昧性への対抗手段として、本セッションでは「形式手法」を紹介します。形式手法ではシステムの挙動を数学的に記述することにより、自然言語の持つ曖昧性を排除し、仕様が満たされるかどうかを厳密に検証することが可能になります。あなたの頭の中にある仕様がどのように「数学的な記述」に変換されるのか、具体例を通して体験してみませんか?

イベント概要:https://event.shoeisha.jp/devsumi/20200213/session/2380/

y_taka_23

February 13, 2020
Tweet

More Decks by y_taka_23

Transcript

  1. #devsumi #devsumiF
    #devsumi #devsumiF
    「厳密な共通言語」としての
    形式手法
    チェシャ猫 (@y_taka_23)
    Developers Summit 2020 [F-13-6] (2020/02/13)

    View Slide

  2. #devsumi #devsumiF
    #devsumi #devsumiF
    本日のアジェンダ
    ● システムの仕様と曖昧性
    ● 形式手法とツールの概要
    ● モデリングを通した仕様の明確化
    ● 環境と相互作用する複雑な挙動の解析

    View Slide

  3. #devsumi #devsumiF
    #devsumi #devsumiF
    1. 仕様に隠された曖昧性
    Ambiguities in the Specification

    View Slide

  4. #devsumi #devsumiF
    例:チェスのルール改定
    参考文献:https://old.fide.com/fide/handbook.html?id=208&view=article

    View Slide

  5. #devsumi #devsumiF
    ポーンは最前列に到達した際
    クイーン・ビショップ・ルーク・ナイト
    のいずれかに成ることができる

    View Slide

  6. #devsumi #devsumiF
    ポーンは最前列に到達した際
    クイーン・ビショップ・ルーク・ナイト
    のいずれかに成らねばならない

    View Slide

  7. #devsumi #devsumiF
    ポーンは最前列に到達した際
    同色のクイーン・ビショップ・ルーク・ナイト
    のいずれかに成らねばならない

    View Slide

  8. #devsumi #devsumiF
    例:最大値関数

    View Slide

  9. #devsumi #devsumiF
    max(x, y): x と y のうち大きい方を返す

    View Slide

  10. #devsumi #devsumiF
    max(x, y): x と y のうち小さくない方を返す

    View Slide

  11. #devsumi #devsumiF
    例:水位上昇によるポンプの遮断
    参考文献:https://www.researchgate.net/publication/242413466_Assessment_of_safety-critical_software_in_nuclear_power_plants

    View Slide

  12. #devsumi #devsumiF
    水位が 4 秒以上、100m を上回ったら
    ポンプを遮断する

    View Slide

  13. #devsumi #devsumiF
    過去 4 秒間の水位の最小値が
    100m を上回ったらポンプを遮断する

    View Slide

  14. #devsumi #devsumiF
    過去 4 秒間の水位の二乗平均平方根が
    100m を上回ったらポンプを遮断する

    View Slide

  15. #devsumi #devsumiF
    #devsumi #devsumiF
    曖昧さはイメージの限界から生まれる
    ● 仕様を理解した「つもり」の思い込み
    ○ ポーンが成るなら当然、同色の駒である
    ○ 比較可能な値なら当然、大きい方が取れる
    ○ 基準値を上回るかどうかなら当然、最小値を見ればよい
    ● 最初に思いついたもの以外は見落としがち
    ○ 指摘されるまでは見落としていること自体気づかない

    View Slide

  16. #devsumi #devsumiF
    単なる「言葉遊び」に見える?

    View Slide

  17. #devsumi #devsumiF
    例:統合決済基盤

    View Slide

  18. #devsumi #devsumiF
    #devsumi #devsumiF
    とある決済サービスの仕様
    ● システム横断的な決済基盤
    ○ 複数の EC サイトから利用される
    ● 複数の決済手段をサポート
    ○ 銀行引き落とし / ポイント払い / ギフト券払い
    ○ 各々が別々のマイクロサービスとして稼働
    ○ 複数の手段に按分して支払うことも可能

    View Slide

  19. #devsumi #devsumiF
    ポイント管理
    1000 pt
    ギフト券管理
    1000 円
    銀行口座管理
    1000 円
    決済サービス

    View Slide

  20. #devsumi #devsumiF
    ポイント管理
    1000 pt
    ギフト券管理
    1000 円
    銀行口座管理
    1000 円
    決済サービス
    1000 円支払

    View Slide

  21. #devsumi #devsumiF
    ポイント管理
    1000 pt
    ギフト券管理
    1000 円
    銀行口座管理
    1000 円
    決済サービス
    1000 円支払
    - 500 円 - 500 pt

    View Slide

  22. #devsumi #devsumiF
    ポイント管理
    500 pt
    ギフト券管理
    1000 円
    銀行口座管理
    500 円
    決済サービス
    1000 円支払

    View Slide

  23. #devsumi #devsumiF
    ポイント管理
    500 pt
    ギフト券管理
    1000 円
    銀行口座管理
    500 円
    決済サービス
    1000 円支払
    OK OK

    View Slide

  24. #devsumi #devsumiF
    ポイント管理
    500 pt
    ギフト券管理
    1000 円
    銀行口座管理
    500 円
    決済サービス
    OK

    View Slide

  25. #devsumi #devsumiF
    処理中にエラーが発生した場合

    View Slide

  26. #devsumi #devsumiF
    ポイント管理
    1000 pt
    ギフト券管理
    1000 円
    銀行口座管理
    500 円
    決済サービス
    1000 円支払
    OK ERROR

    View Slide

  27. #devsumi #devsumiF
    ポイント管理
    1000 pt
    ギフト券管理
    1000 円
    銀行口座管理
    500 円
    決済サービス
    OK or Retry?

    View Slide

  28. #devsumi #devsumiF
    #devsumi #devsumiF
    TCC パターン
    ● 全体を二つのフェイズに分割する
    ● Try フェイズ
    ○ 各メンバーに更新内容を仮登録させる
    ● Confirm / Cancel フェイズ
    ○ 全員から準備 OK が返って来たら改めて Confirm
    ○ 一人でも失敗した場合には全員に Cancel させる

    View Slide

  29. #devsumi #devsumiF
    ポイント管理 ギフト券管理
    銀行口座管理
    決済サービス
    Try

    View Slide

  30. #devsumi #devsumiF
    ポイント管理 ギフト券管理
    銀行口座管理
    Reserved
    決済サービス
    Try
    OK

    View Slide

  31. #devsumi #devsumiF
    ポイント管理
    Reserved
    ギフト券管理
    銀行口座管理
    Reserved
    決済サービス
    Try
    OK

    View Slide

  32. #devsumi #devsumiF
    ポイント管理
    Reserved
    ギフト券管理
    銀行口座管理
    Reserved
    決済サービス
    Confirm

    View Slide

  33. #devsumi #devsumiF
    ポイント管理
    Confirmed
    ギフト券管理
    銀行口座管理
    Reserved
    決済サービス
    Confirm
    OK

    View Slide

  34. #devsumi #devsumiF
    ポイント管理
    Confirmed
    ギフト券管理
    銀行口座管理
    Confirmed
    決済サービス
    Confirm
    OK

    View Slide

  35. #devsumi #devsumiF
    処理中にエラーが発生した場合

    View Slide

  36. #devsumi #devsumiF
    ポイント管理
    Error
    ギフト券管理
    銀行口座管理
    Reserved
    決済サービス
    Try
    Error

    View Slide

  37. #devsumi #devsumiF
    ポイント管理
    Error
    ギフト券管理
    銀行口座管理
    Reserved
    決済サービス
    Cancel

    View Slide

  38. #devsumi #devsumiF
    ポイント管理
    Canceled
    ギフト券管理
    銀行口座管理
    Canceled
    決済サービス
    Cancel

    View Slide

  39. #devsumi #devsumiF
    本当に「理解」してますか?

    View Slide

  40. #devsumi #devsumiF
    #devsumi #devsumiF
    TCC パターンの「曖昧」な部分
    ● 未定義動作のないシステムの正確な挙動
    ○ 各コンポーネントの動作と、非同期に動いた系全体の挙動
    ● 保証したい仕様の意味
    ○ 不整合とは何か、どういう状況なら許容できるのか
    ● アルゴリズム外の環境との相互作用
    ○ 動作している各サーバの信頼性、ネットワークの状態

    View Slide

  41. #devsumi #devsumiF
    #devsumi #devsumiF
    分散コンピューティングの落とし穴
    ● ネットワークは信頼できる
    ● レイテンシはゼロである
    ● 帯域幅は無限である
    ● ネットワークはセキュアである
    ● ネットワークトポロジは不変である
    ● 管理者は一人である
    ● トランスポートコストはゼロである
    ● ネットワークは均質である
    参考文献:https://web.archive.org/web/20171107014323/https://blog.fogcreek.com/eight-fallacies-of-distributed-computing-tech-talk/

    View Slide

  42. #devsumi #devsumiF
    #devsumi #devsumiF
    分散コンピューティングの落とし穴
    ● ネットワークは信頼できる
    ● レイテンシはゼロである
    ● 帯域幅は無限である
    ● ネットワークはセキュアである
    ● ネットワークトポロジは不変である
    ● 管理者は一人である
    ● トランスポートコストはゼロである
    ● ネットワークは均質である
    イメージの限界による曖昧さの発生
    参考文献:https://web.archive.org/web/20171107014323/https://blog.fogcreek.com/eight-fallacies-of-distributed-computing-tech-talk/

    View Slide

  43. #devsumi #devsumiF
    #devsumi #devsumiF
    曖昧性ハンドリングの重要性
    ● アーキテクチャの大規模・複雑化
    ○ マイクロサービス間の疎結合性
    ○ チーム間での仕様や制約の合意のコスト
    ○ マネージドインフラにおける変えられない前提条件
    ● 開発環境やチーム構成の多様化
    ○ 均質な前提知識やイメージを期待できない

    View Slide

  44. #devsumi #devsumiF
    テストでカバーすべき?

    View Slide

  45. #devsumi #devsumiF
    #devsumi #devsumiF
    テストでカバーできない点
    ● テストケースの網羅性・再現性
    ○ テストケースとして明示的に思いつく必要がある
    ○ 非同期性による実行パスのランダム性
    ● 実装が先行する必要性
    ○ 実際にテスト対象となるシステムの実装が必要
    ○ 暗黙の仮定を仕様バグとして作り込んでしまうと手戻り

    View Slide

  46. #devsumi #devsumiF
    複雑さを扱いうる「言葉」の必要性

    View Slide

  47. #devsumi #devsumiF
    #devsumi #devsumiF
    第 1 章のまとめ
    ● 仕様を厳密に表現するのは意外と難しい
    ○ イメージできる範囲の挙動に引きずられる
    ○ 知識や前提が共有されている必要がある
    ● 実システムの挙動は大量の曖昧さを含む
    ○ テストは曖昧さを排除する方法の一つだが万能ではない
    ○ システムの性質をより正確に記述できる方法論が欲しい

    View Slide

  48. #devsumi #devsumiF
    何であれば「共通言語」足り得るのか

    View Slide

  49. #devsumi #devsumiF
    #devsumi #devsumiF
    形式手法
    Formal Methods

    View Slide

  50. #devsumi #devsumiF
    #devsumi #devsumiF
    2. はじめての形式手法
    Hello, Formal Methods!

    View Slide

  51. #devsumi #devsumiF
    #devsumi #devsumiF
    形式手法とは
    ● システムを数学的対象により表現
    ○ その対象の性質に基づいて検証を行う
    ○ 対象として何を選ぶかによってツールの性質が決まる
    ● テストに対する優位点
    ○ テストケースの抜けや漏れが生じない
    ○ 実装ではなく仕様や設計に対して検査ができる

    View Slide

  52. #devsumi #devsumiF
    #devsumi #devsumiF
    形式手法の分類
    ● モデル検査
    ○ システムが取りうる状態を列挙して探索
    ○ 有限個の探索に帰着できる範囲で自動化が可能
    ● 定理証明
    ○ いわゆる数学的な証明をプログラムとして表現
    ○ 本当に無限個のパターンがある対象を扱える

    View Slide

  53. #devsumi #devsumiF

    View Slide

  54. #devsumi #devsumiF
    #devsumi #devsumiF
    TLA+ の特徴
    ● モデル検査系のツール
    ○ Eclipse ベースの IDE(TLA Toolbox)とセットで提供
    ○ Lamport(Paxos の発案者)が中心となって開発
    ○ Temporal Logic of Actions と呼ばれる論理がベース
    ● システムを状態の列として表現
    ○ 起こり得る動作の前後で成り立つ関係を記述

    View Slide

  55. #devsumi #devsumiF
    よくある「学者のオモチャ」なのでは?

    View Slide

  56. #devsumi #devsumiF
    #devsumi #devsumiF
    TLA+ の採用事例
    ● AWS DynamoDB、S3
    ○ https://lamport.azurewebsites.net/tla/formal-methods-amazon.pdf
    ● CockroachDB の並列コミット
    ○ https://www.cockroachlabs.com/blog/parallel-commits/
    ● FINAL FANTASY XV POCKET EDITION
    ○ https://d1.awsstatic.com/events/jp/2018/summit/tokyo/customer/37.pdf

    View Slide

  57. #devsumi #devsumiF
    #devsumi #devsumiF
    サンプル:LampLighter
    ● まず非常に単純なシステムを考える
    ● 世界にはフラグがひとつだけ存在する
    ○ 変数 lamp で表す
    ● プロセスがひとつだけ稼働している
    ○ 断続的にフラグを反転させる
    ○ 式で書けば lamp = ~lamp

    View Slide

  58. #devsumi #devsumiF
    lamp: true lamp: false
    lamp’ = ~ lamp
    lamp’ = ~ lamp

    View Slide

  59. #devsumi #devsumiF
    VARIABLE lamp
    (* 初期状態 *)
    Init ==
    lamp = TRUE
    (* 状態遷移時の関係 *)
    Next ==
    lamp' = ~lamp

    View Slide

  60. #devsumi #devsumiF
    #devsumi #devsumiF
    サンプル:TwinLighter
    ● フラグがふたつ存在する
    ○ 変数名は lamp1 と lamp2
    ● プロセスがふたつ非同期で稼働している
    ○ それぞれ P1 と P2 とする
    ○ P1 は lamp1 を、P2 は lamp2 を反転させる
    ○ 同時には動かないが、順番はランダムで交互とも限らない

    View Slide

  61. #devsumi #devsumiF
    lamp1: false
    lamp2: true
    lamp1: false
    lamp2: false
    lamp1: true
    lamp2: true
    lamp1: true
    lamp2: false

    View Slide

  62. #devsumi #devsumiF
    VARIABLE lamp
    (* 初期状態 *)
    Init ==
    lamp1 = TRUE /\
    lamp2 = TRUE
    (* 状態遷移時の関係 *)
    Next ==
    lamp1' = ~lamp1 \/
    lamp2' = ~lamp2

    View Slide

  63. #devsumi #devsumiF
    #devsumi #devsumiF
    PlusCal による生成
    ● 生の TLA+ を書くのは人間には辛い
    ○ そもそも直接、遷移を書けるなら最初から曖昧性などない
    ● PlusCal と呼ばれる DSL からコード生成
    ○ Pascal 風の記法と C 言語風の記法がある
    ● AWS の事例論文でも有効性を強調
    ○ 現場のプログラマからの心理的障壁を下げる効果

    View Slide

  64. #devsumi #devsumiF
    --algorithm LampLighter
    process P \in { 1, 2 }
    variable lamp = TRUE;
    begin
    while TRUE do
    lamp := ~lamp;
    end while;
    end process;
    end algorithm;

    View Slide

  65. #devsumi #devsumiF
    --algorithm LampLighter
    process P \in { 1, 2 }
    variable lamp = TRUE;
    begin
    while TRUE do
    lamp := ~lamp;
    end while;
    end process;
    end algorithm;
    ループっぽい記法

    View Slide

  66. #devsumi #devsumiF
    --algorithm LampLighter
    process P \in { 1, 2 }
    variable lamp = TRUE;
    begin
    while TRUE do
    lamp := ~lamp;
    end while;
    end process;
    end algorithm;
    複数プロセスのインスタンス化

    View Slide

  67. #devsumi #devsumiF
    #devsumi #devsumiF
    第 2 章のまとめ
    ● 形式手法によるシステムの表現
    ○ システムを数学的な対象にマッピング
    ○ 厳密な記述を強制し「イメージの外」の余地を残さない
    ● 今回は TLA+ をモデル検査器として使用
    ○ 研究用だけでなく、国内を含めて産業界で実績がある
    ○ PlusCal を使用してプログラムっぽく書ける

    View Slide

  68. #devsumi #devsumiF
    #devsumi #devsumiF
    3. モデリングと仕様の明確化
    Formal Modeling of the Specifications
    参考文献:http://muratbuffalo.blogspot.com/2018/12/2-phase-commit-and-beyond.html

    View Slide

  69. #devsumi #devsumiF
    #devsumi #devsumiF
    TCC パターンの「曖昧」な部分
    ● 未定義動作のないシステムの正確な挙動
    ○ 各コンポーネントの動作と、非同期に動いた系全体の挙動
    ● 保証したい仕様の意味
    ○ 不整合とは何か、どういう状況なら許容できるのか
    ● アルゴリズム外の環境との相互作用
    ○ 動作している各サーバの信頼性、ネットワークの状態

    View Slide

  70. #devsumi #devsumiF
    コンポーネントごとに記述
    合成は TLA+ に任せる

    View Slide

  71. #devsumi #devsumiF
    ポイント管理 ギフト券管理
    銀行口座管理
    決済サービス
    Payment
    Methods

    View Slide

  72. #devsumi #devsumiF
    fair process Payment
    begin
    (* 決済サービス側の挙動 *)
    end process;
    fair process Method \in METHOD
    begin
    (* 決済手段側の挙動 *)
    end process;

    View Slide

  73. #devsumi #devsumiF
    #devsumi #devsumiF
    決済サービス側の挙動
    ● まず Try リクエストを出す
    ○ モデリングは Try した状態からスタート
    ● 確定なら Confirm リクエストを出す
    ○ 全員が OK のレスポンスを返した場合
    ● 取り消しなら Cancel リクエストを出す
    ○ 一人でも OK のレスポンスを返さなかった場合

    View Slide

  74. #devsumi #devsumiF
    try
    cancel
    confirm

    View Slide

  75. #devsumi #devsumiF
    try
    cancel
    confirm
    全員 reserved

    View Slide

  76. #devsumi #devsumiF
    try
    cancel
    confirm
    一人でも canceled

    View Slide

  77. #devsumi #devsumiF
    variable paymentState = "try"
    fair process Payment
    begin
    either
    (* Confirm リクエストを発行 *)
    await confirmable;
    paymentState = "confirm";
    or
    (* Cancel リクエストを発行 *)
    await cancerable;
    paymentState = "cancel":
    end either;
    end process;

    View Slide

  78. #devsumi #devsumiF
    variable paymentState = "try"
    fair process Payment
    begin
    either
    (* Confirm リクエストを発行 *)
    await confirmable;
    paymentState = "confirm";
    or
    (* Cancel リクエストを発行 *)
    await cancerable;
    paymentState = "cancel":
    end either;
    end process;
    either ... or … で条件分岐

    View Slide

  79. #devsumi #devsumiF
    define
    (* 全員が準備 OK なら確定できる *)
    confirmable ==
    \A m \in METHOD: methodState[m] \in { "reserved" }
    (* 一人でもキャンセルなら全員キャンセル *)
    cancerable ==
    \E m \in METHOD: methodState[m] \in { "canceled" }
    end define;

    View Slide

  80. #devsumi #devsumiF
    define
    (* 全員が準備 OK なら確定できる *)
    confirmable ==
    \A m \in METHOD: methodState[m] \in { "reserved" }
    (* 一人でもキャンセルなら全員キャンセル *)
    cancerable ==
    \E m \in METHOD: methodState[m] \in { "canceled" }
    end define;
    forall: 任意の ...
    exists: 少なくとも一つ存在

    View Slide

  81. #devsumi #devsumiF
    #devsumi #devsumiF
    決済手段側の挙動
    ● Try に対して仮登録を行う
    ○ 待機中に Try リクエストを受けたら仮登録状態になる
    ● Confirm に対して確定処理を行う
    ○ 自分が仮登録状態ならそれを確定状態に変える
    ● Cancel に対してキャンセル処理を行う
    ○ さらに自分自身が失敗した場合もキャンセル状態になる

    View Slide

  82. #devsumi #devsumiF
    idling confirmed
    reserved
    canceled

    View Slide

  83. #devsumi #devsumiF
    idling confirmed
    reserved
    canceled
    try 受信

    View Slide

  84. #devsumi #devsumiF
    idling confirmed
    reserved
    canceled
    confirm 受信

    View Slide

  85. #devsumi #devsumiF
    idling confirmed
    reserved
    canceled
    cancel 受信

    View Slide

  86. #devsumi #devsumiF
    idling confirmed
    reserved
    canceled
    cancel 受信
    または自分が失敗

    View Slide

  87. #devsumi #devsumiF
    fair process Method \in METHOD
    begin
    while methodState[self] \in { "idling", "reserved" } do
    either
    (* 待機 → 仮登録 *)
    or
    (* 仮登録 → 確定 *)
    or
    (* キャンセル *)
    end either;
    end while;
    end process;
    either ... or … で 3 通りに分岐

    View Slide

  88. #devsumi #devsumiF
    either
    (* 待機 → 仮登録 *)
    await methodState[self] = "idling";
    methodState[self] := "reserved";
    or
    (* 仮登録 → 確定 *)
    await methodState[self] = "reserved" /\ paymentState = "confirm";
    methodState[self] := "confirmed";
    or
    (* キャンセル *)
    ...
    end either;

    View Slide

  89. #devsumi #devsumiF
    either
    (* 待機 → 仮登録 *)
    await methodState[self] = "idling";
    methodState[self] := "reserved";
    or
    (* 仮登録 → 確定 *)
    await methodState[self] = "reserved" /\ paymentState = "confirm";
    methodState[self] := "confirmed";
    or
    (* キャンセル *)
    ...
    end either;
    仮登録状態になる

    View Slide

  90. #devsumi #devsumiF
    either
    (* 待機 → 仮登録 *)
    await methodState[self] = "idling";
    methodState[self] := "reserved";
    or
    (* 仮登録 → 確定 *)
    await methodState[self] = "reserved" /\ paymentState = "confirm";
    methodState[self] := "confirmed";
    or
    (* キャンセル *)
    ...
    end either;
    確定状態になる

    View Slide

  91. #devsumi #devsumiF
    either
    (* 待機 → 仮登録 *)
    ...
    or
    (* 仮登録 → 確定 *)
    ...
    or
    (* キャンセル *)
    await
    methodState[self] = "idling" \/
    (methodState[self] = "reserved" /\ paymentState = "cancel");
    methodState[self] := "canceled";
    end either;

    View Slide

  92. #devsumi #devsumiF
    either
    (* 待機 → 仮登録 *)
    ...
    or
    (* 仮登録 → 確定 *)
    ...
    or
    (* キャンセル *)
    await
    methodState[self] = "idling" \/
    (methodState[self] = "reserved" /\ paymentState = "cancel");
    methodState[self] := "canceled";
    end either; キャンセル状態になる

    View Slide

  93. #devsumi #devsumiF
    #devsumi #devsumiF
    TCC パターンの「曖昧」な部分
    ● 未定義動作のないシステムの正確な挙動
    ○ 各コンポーネントの動作と、非同期に動いた系全体の挙動
    ● 保証したい仕様の意味
    ○ 不整合とは何か、どういう状況なら許容できるのか
    ● アルゴリズム外の環境との相互作用
    ○ 動作している各サーバの信頼性、ネットワークの状態

    View Slide

  94. #devsumi #devsumiF
    #devsumi #devsumiF
    検証したい TCC の性質
    ● トランザクションとしての一貫性
    ○ Confirmed と Canceded が混在しないか?
    ○ 混在するとデータに不整合が発生する
    ● 一連の手続きが完了する保証
    ○ いつかは Confirmed もしくは Canceled になる?
    ○ デッドロックや無限ループに陥ると困る

    View Slide

  95. #devsumi #devsumiF
    #devsumi #devsumiF
    安全性と活性
    ● 安全性 (Safety)
    ○ 何か悪いことが「起こらない」ことを要求
    ○ 通常のプログラムでのアサーションに近い
    ● 活性 (Liveness)一連の手続きが完了する保証
    ○ 何か良いことが「起こる」ことを要求
    ○ 何もしないシステムは無意味なので活性は必須

    View Slide

  96. #devsumi #devsumiF
    A A
    「A が成り立つか?」:
    「いずれ A が成り立つか? 」:
    A

    View Slide

  97. #devsumi #devsumiF
    A A
    「A が成り立つか?」: 状態に対する条件
    「いずれ A が成り立つか? 」:
    A
    true false true false

    View Slide

  98. #devsumi #devsumiF
    A A
    「A が成り立つか?」: 状態に対する条件
    「いずれ A が成り立つか? 」: 状態列に対する条件
    A
    true false true false
    true
    false

    View Slide

  99. #devsumi #devsumiF
    仕様を表現する「言葉」の必要性

    View Slide

  100. #devsumi #devsumiF
    #devsumi #devsumiF
    時相論理 (Temporal Logic)
    ● 通常の論理式に記号を追加した体系
    ○ [] A:現時点以降、常に A が成り立つ
    ○ <> A:現時点以降、いつかは A が成り立つ
    ● 状態の列に対して真偽を判定
    ○ 時間的に幅がある振る舞いについて性質を記述できる
    ○ 式の真偽の与え方は何種類か存在する (LTL、CTL など)

    View Slide

  101. #devsumi #devsumiF
    <> A : 現時点以降、いずれは A が成り立つ
    A
    true
    false
    [] A : 現時点以降、常に A が成り立つ
    A A A
    A A
    false
    true

    View Slide

  102. #devsumi #devsumiF
    (* 確定とキャンセルが混在しない *)
    Consistency ==
    \A m1, m2 \in METHOD:
    ~ (methodState[m1] = "confirmed" /\ methodState[m1] = "canceled")
    (* どの決済手段もいつかは確定もしくはキャンセルになる *)
    Completed ==
    <>(\A m \in METHOD: methodState[m] \in { "confirmed", "canceled" })

    View Slide

  103. #devsumi #devsumiF
    (* 確定とキャンセルが混在しない *)
    Consistency ==
    \A m1, m2 \in METHOD:
    ~ (methodState[m1] = "confirmed" /\ methodState[m1] = "canceled")
    (* どの決済手段もいつかは確定もしくはキャンセルになる *)
    Completed ==
    <>(\A m \in METHOD: methodState[m] \in { "confirmed", "canceled" })
    「いつかは」= 時相論理

    View Slide

  104. #devsumi #devsumiF
    いざ検査!

    View Slide

  105. #devsumi #devsumiF
    No errors!

    View Slide

  106. #devsumi #devsumiF
    #devsumi #devsumiF
    検証したい TCC の性質(再掲)
    ● トランザクションとしての一貫性
    ○ Confirmed と Canceded が混在しないか?
    ○ 混在するとデータに不整合が発生する
    ● 一連の手続きが完了する保証
    ○ いつかは Confirmed もしくは Canceled になる?
    ○ デッドロックや無限ループに陥ると困る

    View Slide

  107. #devsumi #devsumiF
    #devsumi #devsumiF
    第 3 章のまとめ
    ● TLA+ による TCC のモデリング
    ○ 各遷移が起こりうる条件を分割整理し、漏れをなくす
    ○ 各コンポーネントごとに記述すれば合成してくれる
    ● 時相論理による検証
    ○ 安全性と活性の両サイドを検証
    ○ テストでは難しい「一連の振る舞い」が検査可能

    View Slide

  108. #devsumi #devsumiF
    #devsumi #devsumiF
    4. 複雑な実行パスの検証
    Check Complicated Behaviour

    View Slide

  109. #devsumi #devsumiF
    #devsumi #devsumiF
    TCC パターンの「曖昧」な部分
    ● 未定義動作のないシステムの正確な挙動
    ○ 各コンポーネントの動作と、非同期に動いた系全体の挙動
    ● 保証したい仕様の意味
    ○ 不整合とは何か、どういう状況なら許容できるのか
    ● アルゴリズム外の環境との相互作用
    ○ 動作している各サーバの信頼性、ネットワークの状態

    View Slide

  110. #devsumi #devsumiF
    #devsumi #devsumiF
    決済サービスの故障
    ● 先ほどのモデリングは故障しない前提
    ○ 直感的なイメージが難しいのはむしろ異常系
    ○ 故障の発生はランダムなので分岐が爆発的に増える
    ● Confirm または Cancel リクエスト後に故障
    ○ 故障後はいかなるリクエストも発しない
    ○ 故障後はずっと故障していて、自動で復旧はしない

    View Slide

  111. #devsumi #devsumiF
    性質の良いシステム
    性質の悪いシステム

    View Slide

  112. #devsumi #devsumiF
    故障しない
    性質の良いシステム
    性質の悪いシステム

    View Slide

  113. #devsumi #devsumiF
    故障しない
    性質の良いシステム
    Crash-Stop 故障 : 故障後、完全に沈黙
    性質の悪いシステム

    View Slide

  114. #devsumi #devsumiF
    故障しない
    性質の良いシステム
    Crash-Stop 故障 : 故障後、完全に沈黙
    Crash-Recovery 故障 : 故障後、復活の可能性
    性質の悪いシステム

    View Slide

  115. #devsumi #devsumiF
    故障しない
    性質の良いシステム
    Crash-Stop 故障 : 故障後、完全に沈黙
    Crash-Recovery 故障 : 故障後、復活の可能性
    ビザンチン故障:サーバが任意の応答を返す
    性質の悪いシステム

    View Slide

  116. #devsumi #devsumiF
    つまり決済サーバの故障モデルとして
    Crash-Stop 性を仮定

    View Slide

  117. #devsumi #devsumiF
    try
    cancel
    confirm

    View Slide

  118. #devsumi #devsumiF
    try
    cancel
    confirm
    crash

    View Slide

  119. #devsumi #devsumiF
    Errors!

    View Slide

  120. #devsumi #devsumiF
    #devsumi #devsumiF
    エラートレースの内容
    1. 決済手段サーバ 1, 2, 3 の順に Try が到達し
    3 台とも Reserved 状態に
    2. 決済サーバが Confirm リクエスト動作中に故障
    3. Confirm リクエストは決済手段サーバに到達せず
    4. 決済手段サーバは Reserved のまま動けない

    View Slide

  121. #devsumi #devsumiF
    #devsumi #devsumiF
    フェイルオーバによる冗長化
    ● 決済サービスの代替サーバを用意
    ○ 代替サーバは故障しないと仮定する
    ● 代替サーバの挙動
    ○ 本体が故障していないかを監視
    ○ 本体が正常なら何もしない
    ○ 故障していたら代わりに Confirm / Cancel リクエスト

    View Slide

  122. #devsumi #devsumiF
    ポイント管理 ギフト券管理
    銀行口座管理
    決済サービス 代替サービス

    View Slide

  123. #devsumi #devsumiF
    ポイント管理
    Reserved
    ギフト券管理
    Reserved
    銀行口座管理
    Reserved
    決済サービス
    Crash
    代替サービス

    View Slide

  124. #devsumi #devsumiF
    ポイント管理
    Reserved
    ギフト券管理
    Reserved
    銀行口座管理
    Reserved
    決済サービス
    Confirm
    代替サービス

    View Slide

  125. #devsumi #devsumiF
    ポイント管理
    Confirmed
    ギフト券管理
    Confirmed
    銀行口座管理
    Confirmed
    決済サービス
    Confirm
    代替サービス

    View Slide

  126. #devsumi #devsumiF
    crach
    cancel
    confirm

    View Slide

  127. #devsumi #devsumiF
    crach
    cancel
    confirm
    全員 reserved

    View Slide

  128. #devsumi #devsumiF
    crach
    cancel
    confirm
    一人でも canceled

    View Slide

  129. #devsumi #devsumiF
    Errors!

    View Slide

  130. #devsumi #devsumiF
    #devsumi #devsumiF
    エラートレースの内容
    1. 決済手段サーバが 3 台とも Reserved になる
    2. 決済サーバが手段サーバ 1 にのみ
    Confirm を送った状態で故障
    3. 「全員 Reserved」ではないため代替サーバ動作せず

    View Slide

  131. #devsumi #devsumiF
    crach
    cancel
    confirm
    全員 reserved か、
    もしくは最低一人が
    confirmed

    View Slide

  132. #devsumi #devsumiF
    No errors!

    View Slide

  133. #devsumi #devsumiF
    #devsumi #devsumiF
    第 4 章のまとめ
    ● システムが取りうる異常系をあらかじめ記述
    ○ どのような故障を想定するか
    ○ どのような故障であれば耐えられるように設計するか
    ● TLA+ による探索
    ○ 全探索により仕様に合わない挙動を検出
    ○ 人間ではすぐには思いつかないような条件の漏れを指摘

    View Slide

  134. #devsumi #devsumiF
    #devsumi #devsumiF
    5. 本日のまとめ
    Recup the Session

    View Slide

  135. #devsumi #devsumiF
    #devsumi #devsumiF
    本日のまとめ
    ● 自然言語による仕様は曖昧性を持つ
    ○ 理解しているつもりで意外な見落としの原因になる
    ● 形式手法によるモデリング
    ○ 数学的な表現を用いることで厳密な表現が可能に
    ● より複雑な状況における解析の自動化
    ○ 長く複雑な実行パスであっても自動で網羅される

    View Slide