自然言語要求を動かしてみる！

製造業の片隅で、ソフトウェアエンジニア、テストエンジニア（現QAエンジニア）を経験したことをメモ程度に書き残します。
自然言語要求を動かす方法を考えて、まとめていきます。

#### 目次
[題材となる要求](#題材となる要求)
[ユーザーのやりたいことを補足する](#ユーザーのやりたいことを補足する)
[ユーザーのやりたいことの達成基準を考える](#ユーザーのやりたいことの達成基準を考える)
[要求構文表記](#要求構文表記)
[要求を動かせるようにする](#要求を動かせるようにする)
[要求を動かす！](#要求を動かす！)

<a id="題材となる要求"></a>
#### 題材となる要求

最終的にはモノが動くのが見たいので、ArduinoでLチカを題材に粗い要求を考えたいと思います。
（組み込みソフトウェアエンジニアだけど、Arduino触ったことがない・・・）

〇Arduinoでやってみたいこと

・ボタンを押して、Lチカの間隔をいい感じにしたい
・早い点滅、遅い点滅ができるようにする

<a id="ユーザーのやりたいことを補足する"></a>
#### ユーザーのやりたいことを補足する
ユーザーにニーズを設定しました（≒私がやりたいこと）。やりたいことを少し、整理していきます。
まず、ユーザーニーズに、主語や修飾語などを追加していきます。
5W1Hをベースに、不足しているものを考えます。

【原文】
**ボタンを押して、Lチカの間隔をいい感じにしたい**

When（いつ）：Arduinoのボタンを押したとき
Where（どこで）：Arduino上で
Who（誰が）：ユーザー（私）
What（何を）：Arduino上にあるLEDを
Why（なぜ）：気分に合わせて、LEDのちかちかを変更したいから
How（どのように）：いい感じにちかちかを変更させる（ちかちかの手段は後で決める）

**【改善後】<br>Arduinoのボタンを押したとき、ユーザーはArduino上のLEDをいい感じにチカチカを変更したい。なぜなら、ユーザーは気分に合わせて、LEDのちかちかを変更したいから**

【原文】
**早い点滅、遅い点滅ができるようにする**

When（いつ）：ArduinoのLEDが点滅しているとき
Where（どこで）：Arduino上で
Who（誰が）：ArduinoのLED
What（何を）：Arduino上にあるLEDの点滅の間隔を
Why（なぜ）：気持ちを上げるとき、落ち着かせたいときに合わせて変更したいから
How（どのように）：早くしたり、遅くしたりする

**【改善後】<br>Arduino上のLEDが点滅しているとき、ArduinoのLEDは、LEDの点滅間隔を早くしたり、遅くできるようにしたい。なぜなら、ユーザーは気持ちを上げたり、落ち着かせるのに使いたいから**

Whyを考えると、ユーザーが本当にしたいことは、
**「LEDの点滅を使用して、気分を変えたい」**
であることがわかりました。

これで、潜在（根源）的な要求（要望）を獲得することができました！

<a id="ユーザーのやりたいことの達成基準を考える"></a>
#### ユーザーのやりたいことの達成基準を考える

ユーザーのやりたいことを詳しい内容を獲得することができました。しかし、まだまだ実際の機械を動かすようにするためには不十分です。
ここでは、ユーザーのやりたいことに対して、こんなことが達成できれば、ユーザーのやりたいこと（行動、振る舞い）を満たせるかを考えていきます。

マインドマップを使用して、詳細化していきます。
マインドマップを書いていく上で、文章のグロッサリーを作っていきます。
要求マインドマップを作成する際は、BDD（振る舞い駆動開発）のGherkinガイドワードを使用していきます。
ユーザーのやりたいことに対して、達成基準（Achievement Criteria、AC）を考えていきます。この達成基準は、こんなことが達成できれば、ユーザーのやりたいことを実現できるか、満たせるかを考えていきます。

達成基準に対して、テストで気になる点を考えていきます。
テストで気になる点（Test View Point、TVP）は、作ったものが達成基準に合致しているか検査、検証するためにはどんなことがテストとして必要かを考えます。
達成基準に対になる存在が、このTVPになります。

![Lchika_ydd_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592747/9a934ce1-9e5a-520e-ce89-a1886957be34.png)

要求作成用グロッサリー

| No  | Grossary words|Contents                                      |
| --- | -------------- |-------------------------------------------- |
| 1   | Arduino        | 今回の要求を実現するために使用するマイコンボード|
| 2   | ユーザー | Arduinoを使ってLチカを実現したい人 |
| 3   | LED     | Arduinoに搭載されているLEDのこと |
| 4   | ボタンを押す | Arduinoのボード上にあるボタンを押すこと |
| 5   | 点灯する | Arduinoのボード上にあるLEDを点灯する |
| 6   | 消灯する | Arduinoのボード上にあるLEDを消灯する |
| 7   | 点滅する | Arduinoのボード上にあるLEDを点滅させる |

獲得したステークホルダー要求を書き出してみる。
| Req_ID | Reqirements |
|---|---|
| LCReq-01 | ユーザーがArduinoのボタンを押したとき、Arduinoは、ボタンが押されたことを感知すること |
| LCReq-02 | ユーザーがArduinoのボタンを押したとき、Arduinoは、LEDを点灯させること |
| LCReq-03 | ユーザーがArduinoのボタンを押したとき、Arduinoは、LEDを消灯させること |
| LCReq-04 | ユーザーがArduinoのボタンを押したとき、Arduinoは、LEDを点滅させること |
| LCReq-05 | ユーザーが、Arduinoのボタンを押したとき、Arduinoは、LEDの点灯消灯時間を変更すること |
| LCReq-06 | ユーザーが、Arduinoのボタンを押したとき、Arduinoは、ボタンが押された回数に応じてLEDの点滅間隔を変更すること |

<a id="要求構文表記"></a>
#### 要求構文表記

〇要求構文について
今回は、ISO/IEC/IEEE 29148:2011内「5.2.4 Requirements construct」を使用して要求文化していきます。

参考：[山修の開発文書品質入門（4） ―― 要求テンプレートを利用する](https://asdoq.jp/blog/details.php?bid=9)

山本修一郎先生の[山修の開発文書品質入門（4） ―― 要求テンプレートを利用する](https://asdoq.jp/blog/details.php?bid=9)より、要求構文について引用します。

>ISO/IEC/IEEE 29148:2011内「5.2.4 Requirements construct」では，下記のように３種類の要求構文の型を例示しています．この要求構文も要求テンプレートの例です．なお，日本語構文に合わせるために，助詞を補うとともに，語順を入れ替えています．<br>
(構文の型１)　**[条件]** **[主体]** が **[対象]** を **[制約]** **[活動]** する必要がある．<br>
(構文の型２)　**[条件]** **[活動 または 制約]** は **[値]** である必要がある．<br>
(構文の型３)　**[主体]** が **[値条件]** で **[活動]** する必要がある．<br>

〇要求構文に変換する

抽出したステークホルダー要求は、まだ要求構文を適用していないので、要求構文を適用していきます。

LCReq-01
ユーザーがArduinoのボタンを押したとき、Arduinoは、ボタンが押されたことを感知すること

構文：構文の型１

条件：ユーザーがArduino上にあるボタンを押したとき
主体：Arduinoは
対象：Arduinoのボード上のボタンを押される
制約：なし
活動：検知する
必要がある

**ユーザーがArduino上にあるボタンを押したとき、ArduinoはArduinoのボード上のボタンを押されたことを検知する必要がある**

LCReq-02
ユーザーがArduinoのボタンを押したとき、Arduinoは、LEDを点灯させること

構文：構文の型１

条件：ユーザーがArduino上にあるボタンを押したとき
主体：Arduinoは
対象：Arduinoのボード上のLED
制約：なし
活動：点灯する
必要がある

**ユーザーがArduino上にあるボタンを押したとき、ArduinoはArduinoのボード上のLEDを、点灯する必要がある**

LCReq-03
ユーザーがArduinoのボタンを押したとき、Arduinoは、LEDを消灯させること

構文：構文の型１

条件：ユーザーがArduino上にあるボタンを押したとき
主体：Arduinoは
対象：Arduinoのボード上のLED
制約：なし
活動：消灯する
必要がある

**ユーザーがArduino上にあるボタンを押したとき、ArduinoはArduinoのボード上のLEDを、消灯する必要がある**

LCReq-04
ユーザーがArduinoのボタンを押したとき、Arduinoは、LEDを点滅させること

構文：構文の型１

条件：ユーザーがArduino上にあるボタンを押したとき
主体：Arduinoは
対象：Arduinoのボード上のLED
制約：なし
活動：点滅する
必要がある

**ユーザーがArduino上にあるボタンを押したとき、ArduinoはArduinoのボード上のLEDを、点滅する必要がある**

LCReq-05
ユーザーが、Arduinoのボタンを押したとき、Arduinoは、LEDの点灯消灯時間を変更すること

構文：構文の型１

条件：ユーザーがArduino上にあるボタンを押したとき
主体：Arduinoは
対象：Arduinoのボード上のLEDの点灯消灯時間を
制約：なし
活動：変更する
必要がある

**ユーザーがArduino上にあるボタンを押したとき、Arduinoのボード上のLEDの点灯消灯時間を、変更する必要がある**

LCReq-06
ユーザーが、Arduinoのボタンを押したとき、Arduinoは、ボタンが押された回数に応じてLEDの点滅間隔を変更すること

構文：構文の型１

条件：ユーザーがArduino上にあるボタンを押したとき
主体：Arduinoは
対象：ボタンが押された回数に応じてLEDの点滅間隔を
制約：なし
活動：変更する
必要がある

**ユーザーがArduino上にあるボタンを押したとき、Arduinoはボタンが押された回数に応じてLEDの点滅間隔を、変更する必要がある**

<a id="要求を動かせるようにする"></a>
#### 要求を動かせるようにする

〇日本語実行環境を整備する

pythonのインタプリターを使用して、日本語プログラミングを用いるために、要求構文を味変します。pythonのインタプリタを改造して、日本語プログラミングができる方法については、[日経ソフトウェア2024年 1月号](https://info.nikkeibp.co.jp/media/NSW/atcl/mag/112000051/)を参照してください。
インタプリタについては、日経ソフトウェア2024年１月号を参考して環境を構築しています。

〇構文化した要求を味変する

構文化した要求には、転換の接続詞の「とき（に）」はあるが、プログラミング言語で使用する「if」ような、文頭に用いることのできる接続詞がありません。
適切な接続詞を検討し、文意を損ねないように要求を変更します。

文頭に使うことができる接続詞から、文意をあまり改変しないものを考えていきます。

候補として、「もし」、「たとえ」、「実際に」などを考えました。

・**とき（When）**

ときの意味は・・・
Microsoft Copirotより引用します。
>**「実際に」** と英語の **「When」** の接続詞の意味合いは異なります。
>1. **「実際に」**:
>   - **「実際に」** は、現実の場において行為や現象として示すさまを表します。この接続詞は、具体的な出来事や状況を強調する際に使われます。
>   - 例: **実際に**そのプロジェクトを成功させるためには、チームワークが必要だ。
>2. **英語の「When」**:
>   - **「When」** は英語の接続詞で、いくつかの異なる意味で使われます。
>     - **接続詞「when」（〜するときに）**: 前の文脈の当然の結果として、後の文脈を導く役割を果たします。例えば、「りんごが落ちた。だから、りんごは地球に引っ張られている」という文では、**「だから」** が順接の接続詞として使われています¹²³。
>     - **疑問詞「when」（いつ）**: 普通の疑問文（「？」で終わる疑問文）だけでなく、間接疑問文（疑問文の意味を持つ名詞節）でも使われます。例えば、「映画はいつ始まりますか？」という文で使われています²³。
>     - **関係副詞「when」**: 形容詞節（大きな形容詞のカタマリ）を作り、名詞を修飾します。例えば、「私は私たちが初めて会った日を決して忘れない」という文で使われています²³。

したがって、**「実際に」** と **英語の「When」** は異なる意味を持つ接続詞です¹²³⁴⁵。

1) 【わかりやすい英文法】接続詞whenの使い方は実はすごく簡単 .... https://englishnotes.jp/conjunction-when/.
(2) 接続詞when・while・asの違いを例文付きで詳しく＆わかりやすく解説. https://shinegrammar.net/when%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9%E3%82%84while%E3%83%BBas%E3%81%A8%E3%81%AE%E9%81%95%E3%81%84%E3%82%92%E8%A9%B3%E3%81%97%E3%81%8F%EF%BC%86%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F/.
(3) 【英語の時制】時や条件を表す接続詞（When/If）に続く文で .... https://eigoiseigo.com/jisei-whenif/.
(4) 従位接続詞「when」の使い方。「～のとき」という意味で主節を .... https://hajihaji-lemon.com/english/subordinating-conjunction-when/.
(5) 英語「when」の使い方！疑問詞・接続詞での役割を覚えよう .... https://eitopi.com/eigo-when-tukaikata.

要求構文（特に、EARSで使用されるWhen）の意味は、下記が該当します。
- **「When」** は英語の接続詞で、いくつかの異なる意味で使われます。
     - **接続詞「when」（〜するときに）**: 前の文脈の当然の結果として、後の文脈を導く役割を果たします。例えば、「りんごが落ちた。だから、りんごは地球に引っ張られている」という文では、**「だから」** が順接の接続詞として使われています

「Aするとき、Bが起こる」の文意を損ねないように、Aするに修飾する接続詞を付与します。
プログラミング言語と同様に扱うためには、英語の文法と同じようにする必要があります。日本語の順接（だから、それで、このためなど）は、「Aする。だから、Ｂが起こる」と語順として、前の文ではなく、後ろの文の前に、接続詞として挿入されます。
「〇〇〇、Ａするとき、Ｂが起こる」のように、前の部分に使える接続詞を挿入し、構文を変更します。

・**もし**
仮定の接続詞、文意として、後半の事象が起こる確率が下がってしまう。
文意を損ねるので、要求文の書き換えとして使用するには違和感があります。

・**たとえ**
仮定の接続詞、文意として、後半の事象が起こる確率が下がってしまう。
文意を損ねるので、要求文の書き換えとして使用するには違和感があります。

・**実際に**
>理論や概念としてあげつらうのではなく、現実の場において行為や現象として示すさま。現実に。現場に。

[実際に](https://www.weblio.jp/content/%E5%AE%9F%E9%9A%9B%E3%81%AB)より引用。

Aするという事実が起きたことによって、Bが起こることを表現することができます。
元の要求分の文意を損なわずに、「実際に、Aするとき、Bが起こる」と構文化することができます。

<table width="75%" border="1">
<tr>
  <th colspan=3>要求をプログラミング言語に近づける</th>
</tr>
<tr bgcolor="#fffff0">
  <td>要求ID</td>
  <td>変更前</td>
  <td>変更後</td>
</tr>
<tr bgcolor="#fffff0">
  <td>LCReq-01</td>
  <td>ユーザーがArduino上にあるボタンを押したとき、<br>ArduinoはArduinoのボード上のボタンを<br>押されたことを検知する必要がある</td>
  <td>実際に、（ユーザーが）Arduino上のボタンを押したとき、<br>（Arduinoは）Arduino上のボタンを<br>押されたことを検知する（必要がある）</td>
</tr>
<tr bgcolor="#fffff0">
  <td>LCReq-02</td>
  <td>ユーザーがArduino上にあるボタンを押したとき、ArduinoはArduinoのボード上のLEDを、点灯する必要がある</td>
  <td>実際に、（ユーザーが）Arduino上のボタンを押したとき、（Arduinoは）Arduino上のLEDを、点灯する（必要がある）</td>
</tr>
<tr bgcolor="#fffff0">
  <td>LCReq-03</td>
  <td>ユーザーがArduino上にあるボタンを押したとき、ArduinoはArduinoのボード上のLEDを、消灯する必要がある</td>
  <td>実際に、（ユーザーが）Arduino上のボタンを押したとき、（Arduinoは）Arduino上のLEDを、消灯する（必要がある）</td>
</tr>
<tr bgcolor="#fffff0">
  <td>LCReq-04</td>
  <td>ユーザーがArduino上にあるボタンを押したとき、ArduinoはArduinoのボード上のLEDを、点滅する必要がある</td>
  <td>実際に、（ユーザーが）Arduino上のボタンを押したとき、（Arduinoは）Arduinoのボード上のLEDを、点滅する（必要がある）</td>
</tr>
<tr bgcolor="#fffff0">
  <td>LCReq-05</td>
  <td>ユーザーがArduino上にあるボタンを押したとき、Arduinoのボード上のLEDの点灯消灯時間を、変更する必要がある</td>
  <td>実際に、（ユーザーが）Arduino上のボタンを押したとき、（Arduinoは）Arduinoのボード上のLEDの、点灯消灯時間を変更する（必要がある）</td>
</tr>
<tr bgcolor="#fffff0">
  <td>LCReq-06</td>
  <td>ユーザーがArduino上にあるボタンを押したとき、Arduinoはボタンが押された回数に応じてLEDの点滅間隔を、変更する必要がある</td>
  <td>実際に、（ユーザーが）Arduino上のボタンを押したとき、（Arduinoは）ボタンが押された回数に応じてLEDの点滅間隔を、変更する必要がある</td>
</tr>
</table>

少しづつプログラミング言語で動かせそうな要求になってきました。

<a id="要求を動かす！"></a>
#### 要求を動かす！

インタプリターを改造し、日本語プログラミングができるPythonで、上記の要求を記述し、実行してみたいと思います。
（日本語プログラミングについては、日経ソフトウェア2024年1月号を参照してください）

まずは、LCReq-01とLCReq-02の要求をpython上に、書いてみます。


◇プログラミング例
```

Arduino上のボタンを = input('ボタンが押したか押していないかを入力してください（押した/押していない）: ')
Arduino上のLEDは = print

実際に Arduino上のボタンを == '押した' とき
    Arduino上のLEDは('ボタンを検知する')
    
    実際に Arduino上のボタンを == '押した' とき
        Arduino上のLEDは('点灯する')
    でなければ
        Arduino上のLEDは('何もしない')
        
でなければ
    Arduino上のLEDは('何もしない')

```

◇実行結果
```
ボタンが押したか押していないかを入力してください（押した/押していない）: 押した
ボタンを検知する
点灯する
```

ボタンを押したときに、LEDが点灯したことがわかります。
このプログラミングは、実装に向けて書くのではなく、論理が正しいかに焦点を当てると良さそうに思います。
ステークホルダーと開発者、QAの3者が集まっている場で、論理が正しく動くかどうかを話しながら要求を定義出来たら、認識の齟齬を低減することができるのではないでしょうか。
要求開発における、シフトレフトが実現できそうです。（たぶん）
この二つの要求を書いて実行しただけでも、表の要求（ボタンを押したときの振る舞いに関するもの）しか出せていなかったことがわかります。
論理を実行させるために、裏の要求（ボタンを押さない場合など）も気づき、追加することができます。

LCReq-03以降を追加していきます。

◇プログラミング例
```
Arduino上のボタンを = input('ボタンが押したか押していないかを入力してください（押した/押していない）: ')
Arduino上のボタンを押された回数が = input('1~5回のどれかを入力してください:')
Arduino上のLEDは = print

実際に Arduino上のボタンを == '押した' とき
    Arduino上のLEDは('ボタンを検知する')
    
    実際に Arduino上のボタンを押された回数が == '1回' とき
        Arduino上のLEDは('点灯する')
    ではなくて Arduino上のボタンを押された回数が == '2回' とき
        Arduino上のLEDは(' 遅い速度の点滅する')
    ではなくて Arduino上のボタンを押された回数が == '3回' とき
        Arduino上のLEDは(' 普通の速度の点滅する')
    ではなくて Arduino上のボタンを押された回数が == '4回' とき
        Arduino上のLEDは(' 早い速度の点滅する')
    ではなくて Arduino上のボタンを押された回数が == '5回' とき
        Arduino上のLEDは('消灯する')
    でなければ
        Arduino上のLEDは('何もしない')

```
要求を読み替えを必要に応じて行います。
三者でわいわいしながら、読み替えや変更をMobワークでできると、よいかもしれません。

◇実行結果

```
ボタンが押したか押していないかを入力してください（押した/押していない）: 押した
1~5回のどれかを入力してください:3回
ボタンを検知する
 普通の速度の点滅する
```

こんな感じに、今回考えた6つの要求が日本語インタプリターを改造した環境で、自然言語要求が動くようになりました。
動くようになると、テストがしたくなってきますね！
これは、日本語インタプリターに改造したpythonを使用しましたが、世の中に流通している要求を動かすツールを使うと、構文に沿って表現豊かに要求を書き、実行することができます。

#### 参考文献

[山修の開発文書品質入門（4） ―― 要求テンプレートを利用する](https://asdoq.jp/blog/details.php?bid=9)
[日経ソフトウェア2024年 1月号](https://info.nikkeibp.co.jp/media/NSW/atcl/mag/112000051/)
[実際に](https://www.weblio.jp/content/%E5%AE%9F%E9%9A%9B%E3%81%AB)
[Behaviour-Driven Development](https://cucumber.io/docs/bdd/)
[アジャイルにおけるユーザーストーリーとは？書き方例とテンプレートを解説](https://abi-agile.com/user-stories/)