原因結果グラフ法における制約関係解説(Require制約編)

+ 本稿の表記方法及び図の一部はニフティの加瀬氏が作成された[CEGTest](https://softest.jp/?page_id=13)によるものを用いています。
+ [原因結果グラフ法における制約関係の一覧は別稿に](https://qiita.com/sho1884/items/32f8d4d6454e48f1c33c)示してあります。
+ 設計者やプログラマに原因結果グラフ技法をお勧めする理由についても、[『ブールグラフでロジックを整理してデシジョンテーブルと条件式を自動生成する』と題した別稿に](https://note.com/sho1884/n/n4afa22873334)示してあります。

# REQ制約関係:『A －Req→ B』

:::note
REQ(Require)制約は、『Aが真(T)になるためには、Bが真(T)であることが必要』というような関係を表すものです。
:::

制約されるノード間に方向性がありますので、矢印の方向が重要になります。
『Aが真(T)になるためには、矢印の先のBが真(T)であることが必要』ということなので、『A －Req→ B』のような矢印とその方向で表現します。

# REQ制約関係のある事例

具体的に示した方が分かり易いと思いますので、REQ制約関係にあるような事例を以下に示します。

``` html:例１
A: パワー(イグニッション)スイッチが押されたら起動
B: 車内に電子キーがあることを検知する
C: ブレーキが踏まれていることを検知する
```
``` html:例２
A: 商品ボタンを点灯、有効にする
B: 在庫がある
C: 投入金額が十分である
``` 
これら二つの事例は、原因結果グラフで示すと次の図のようにREQ制約関係があるものになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/787618bc-1493-90d9-8383-4d714cd14a03.png)

例１の場合、『「A: パワー(イグニッション)スイッチが押されたら起動」が真(T)になるためには、矢印の先の「B: 車内に電子キーがあることを検知する」が真(T)であることが必要』ですし、
『「A: パワー(イグニッション)スイッチが押されたら起動」が真(T)になるためには、矢印の先の「C: ブレーキが踏まれていることを検知する」が真(T)であることも必要』です。

例２の場合も同様で、『「A: 商品ボタンを点灯、有効にする」が真(T)になるためには、矢印の先の「B: 在庫がある」が真(T)であることが必要』ですし、
『「A: 商品ボタンを点灯、有効にする」が真(T)になるためには、矢印の先の「C: 投入金額が十分である」が真(T)であることも必要』です。

もう少し、他の例も見てみましょう。

``` html:例３
A: 有効な電話番号が入力されたら開始
B: 硬貨が投入されていることを検知する
C: 受話器（フック）が上がっていることを検知する
```
``` html:例４
A: キーを回したら運転スタート(タイマー作動)する
B: コインが入っているのを検知する
C: 扉が閉まっているのを検知する
``` 
これら二つの事例は、原因結果グラフで示すと次の図のようにREQ制約関係があるものになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/ccd34e26-96cc-695d-5cba-d2b12645a465.png)
例３の場合、『「A: 有効な電話番号が入力されたら開始」が真(T)になるためには、矢印の先の「B: 硬貨が投入されていることを検知する」が真(T)であることが必要』ですし、
『「B: 硬貨が投入されていることを検知する」が真(T)になるためには、矢印の先の「C: 受話器（フック）が上がっていることを検知する」が真(T)であることが必要』です。

例４の場合も同様で、『「A: キーを回したら運転スタート(タイマー作動)する」が真(T)になるためには、矢印の先の「B: コインが入っているのを検知する」が真(T)であることが必要』ですし、
『「B: コインが入っているのを検知する」が真(T)になるためには、矢印の先の「C: 扉が閉まっているのを検知する」が真(T)であることが必要』です。

REQ制約関係がどういうものであるか、どのようなときに必要になるか、理解いただけたのではないかと思います。

# REQ制約『A －Req→ B』は、論理関係『A → B』と同じ？

なんか、REQ制約は論理関係の**含意「ならば」**と似ています。

:::note warn
REQ制約関係『A －Req→ B』は、論理関係『A → B』と同じでしょうか？
:::

確認してみることにしましょう。

『A －Req→ B』は、『AがTになるためには、BがTであることが必要』ということでしたから、『AがTならばBはTでなければならない』ということです。
『AがTならばBはFであってはならない』ということでもあります。
一方、AがFのとき、Bがどうなっているべきかについては何も言及していません（興味がないということでしょう）。
つまり、『A －Req→ B』は、￢A∨B = A → Bと真理値表で表現すると同じ事になるのがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/895408cd-221f-cae6-f675-b8c300d612a0.png)

では、制約関係『A －Req→ B』は、論理関係『A → B』と同じであると結論して良いでしょうか？

先に答えを言ってしまえば、上の真理値表で確認した通り、論理関係としては同じになります。しかし、グラフが表現している対象システムの振る舞いとしては違った意味を持ちます。


:::note
REQ制約は、この含意関係を強制するアーキテクチャ(仕組み)の存在を表します。
:::

上記した通り、『AがTならばBはFであってはならない』ので、その**あってはならないケースを確実に排除できる何らかのアーキテクチャ(仕組み)がある**ことを表現するためのものということなのです。


この**違い**が、対象システムの振る舞いとしてどういう意味を持つかについては、[CEGTestツール](https://softest.jp/?page_id=13)で描いた以下の二つのグラフを見比べて頂くとわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/ab230b22-e040-5d7d-d507-572f919d68d1.png)

上図の左のグラフは、『A → B』つまり、『￢A∨B』を表現し、さらにそれがTになったら『(REQ制約関係の)ルールは守られている』ということを表現しています。
ここで、CEGTestツールが生成したそのデシジョンテーブルの方を見ると、#3の列に『ルールが守られていない』ものも出てくることがわかります。
一方、上図の右のグラフは、左のグラフと同じ表現に、制約関係『A －Req→ B』が描き加えられています。そのデシジョンテーブルの方を見ると、『ルールが守られていない』ものは出てきていないことがわかります。

以下に示すヌケモレのない真偽値表を見て頂くともっとはっきりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/d29fe57e-af6d-267e-bed2-837f978d755d.png)

REQ制約『A －Req→ B』とは、このように、含意関係『A → B』が常に真になることを強制する(違反を排除する)アーキテクチャ(仕組み)の存在を表現しています。

元々原因結果グラフ法はテスト設計技法として広く知れ渡るに至っているものです。
テスト設計の立場で考えてみると、アーキテクチャとして排除されているケースがテストケースに現れると、それは(無効系としてさえも)テストできなくて困ってしまうことになります。
REQ制約を描き入れれば、そのようなテストできないケースが排除できることがおわかり頂けると思います。

プログラマの立場で見ても意味があると思います。もしも、REQ制約に相当するアーキテクチャが存在しなければ、違反のケースを無効系として処理する(例えばエラーメッセージを表示して終了する)コードを書かなければなりません。
一方、アーキテクチャが存在し(またそれが十分信頼できる強固なものであるならば)、違反のケースとなるような入力や状態は起こり得ないので、それに対するコードは不要になります。
反対に、冗長なコードを書くと、そこを通すコードカバレッジが困難になります。([MC/DCカバレッジでそのような問題が発生する具体例については別稿](https://qiita.com/sho1884/items/d8b34102e9eb47643866)で簡単に説明しました。)

この辺りのロジックとアーキテクチャの境界設計についは、[もう少し詳しい解説を別稿](https://note.com/sho1884/n/n372d4dbf49dc)に示してあるので、そちらも参考にしてください。

# 最初に示した３ノードの事例での確認

このことを確認するために、先の例１、例２で示した事例の論理関係を３ノードの一般化したグラフとして描いたものを以下に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/eb8a29bf-ca1a-b439-8ec1-952da035fb98.png)
次に、REQ制約(A→B, A→C)を描き入れたグラフを作成し、左右に並べてみたものを以下に示します。比較してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/165e0c92-e445-cc83-8945-05266ea79fdb.png)

では次に、例３、例４で示した事例の論理関係を３ノードの一般化したグラフとして描いたものを以下に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/70ab451e-451d-1c50-a143-ca7ec69e1345.png)
これについても次に、REQ制約(A→B, B→C)を描き入れたグラフを作成し、左右に並べてみたものを以下に示します。比較してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/910139f1-7481-0b8f-46f6-956ecf001ca8.png)

# グラフとその意味の比較と同時に、その違いが実装方法や検証方法にどう影響するかを考えてみましょう

今度は、REQ制約(A→B, A→C)とREQ制約(A→B, B→C)を比較してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/4ea4fdc6-669a-baaa-4c8a-903bb73a33e3.png)
生成されたデシジョンテーブルを比較すると、テストケースとしてはどちらも同じになっていることがわかります。なぜ、同じで良いのでしょうか？
ヒントは以下の図の中にあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/08b0bed0-fad3-08c9-edd5-e62a83e2320e.png)
例えば、「安全装置は機能していないが、無効系に落ちているから問題なし、合格！」等ということはあり得ないでしょう。
つまり、「制約が制約として機能しているか？」「安全装置が安全装置として機能しているか？」の検証方法も必ず検討が必要となるはずです。
「制約が制約として機能しているか？」のテストは双方で違うものになることでしょう。

# REQ制約は順序の制約と理解して良いの？

ここまで示してきた実例から、REQ制約はなにやら順序についての制約をかけるもののようだ、という印象を持たれた方もいるかもしれません。確かにそう考えて良い場合も多いのではないかと思います。

ここでまた、別の事例を考えてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/c8520c9f-323d-d237-c1c6-3a69f998d11c.png)
上図のような認証用のダイアログUIがあるとします。

``` html:例５
A: 「ログイン」ボタンが押されたら開始
B: パスワード欄に文字列が入力されていることを検知する
C: ユーザID欄に電子メールアドレスが入力されていることを検知する
```

B, Cが成り立たないと「ログイン」ボタンはグレーアウトされていて押せないものとします。
ただし、入力の順序はどちらが先でも構わないです。

そのような主旨の要求仕様を示されたら、REQ制約をどのように描き込むのが良いでしょうか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246520/60b328b8-08de-a192-1bce-96600d3fafce.png)

REQ制約は依存関係と考えておいた方が無難でしょう。方向性があり、評価順序も制限される事になるのは、その結果なのだと。
順序のための制約とは考えない方が良いでしょう。
実際、ここに示した例のように、表層のUI上の順序は内部の評価順序と一致している必要がありませんし、必ずしも順序を守らせたいわけでもないことは明らかです。

# まとめ

原因結果グラフ法におけるREQ制約について解説しました。
本稿のタイトルは「(Require制約編)」となっています。別稿の「(Mask制約編)」も準備中です。
そこまでいけば、原因結果グラフ法について一通りは解説したことになるかな、と思っています。
さらにその先も既に下書きがあるのですが、、、