Specification by Example & TDD についてざっくりまとめる

## 概要
odd-e主催の「[プログラマーにも非エンジニアにもわかる、例による仕様入門](https://kokucheese.com/event/index/586506/)」というセミナーに行ってきたのでそのレポート。
ちなみにセミナー自体はCSM研修のあとだったらしくクソアウェーだった。


## Specification by Example
仕様というとAPIの仕様書的などのエンドポイントにパラメータを何を渡せばよいみたいな説明書的なイメージがあるが、Specification by  Example(以降EBS)では、自然言語で例をあげながら作成していく。
(今回はセミナーでも使った[Cucumber](https://cucumber.io/docs/guides/overview/)というツールを使う。)


### なぜEBSを作る必要があるのか？
講師曰く、EBSはテストや実装時に参考にする以外に、仕様を理解できない人たちとのコラボレーションをするために使うという。
なぜコラボレーションをする必要があるのかというと、変化の激しい現代で生き残るには、より多くの視点から思考しプロダクトに反映させる必要があるためです。
ここらへんはアジャイルとかスクラムの文脈通りですね。

つまり、SBIは仕様書というよりもPBIのDONEの定義（受け入れ基準）のようなものです。


#### 例でSBEとよくあるAPIの仕様書を比較
ここで簡単にEBSとよくあるAPIの仕様の例を見ていきます。

##### よくある仕様書の例

```
## parameter
keyword : congestion_degree


## result 

  "links": {
    "self": "http://internal.sauna-tengoku.local/api/v1/sauna?keyword=''congnition_degree,
  },
  "data": {
    {
      "type": "sauna",
      "id": 1,
      "attributes": {
        "name": "草加健康センター",
        "congestion degree": 80%,
      }
    },		
```

http://internal.sauna-tengoku.local/api/v1/sauna
のエンドポイントにパラメーターをつけて投げてあげるとサウナ施設情報が返ることがわかります。

しかしながら、これでは情報が少ないため、
「どこに使ってるっけ？」という疑問は残ります。


##### SBEの例
続いてEBSの例でいく
(今回はセミナーでも使った[Cucumber](https://cucumber.io/docs/guides/overview/)というツールを使う。)


```
Feature : その人にあったサウナをレコメンドしたい

Scenario: 竹原は混雑してなくて、ハイスペなサウナに行きたい
  Given サウナは東京にはたくさんある
  When 竹原がサウナ検索サイトを開いた時に
  Then デフォルトソートを「混雑度」にする
```
（例が悪いな。まあいいや）


一応簡単に用語の説明を

| 項目 | 意味 |
|:--|:--|
| Feature | 実現したいこと |
| Scenario | 行動 |
| Given | 前提条件（昔話でいう「昔〜昔〜あるところに〜」） |
| When | 発火ポイント |
| Then | 発火時に起こる行動 |


このSBEの書き方だと、「したいこと・場面・前提条件・タイミング・処理」が明確なため、
この仕様書をもとに、非技術者の人と会話をすることできます。
そうすることで「ここの対応って適切だっけ？」「もっとこうしたほうが良いかも」などの意見をもらいより良いものにすることができます。

また、SBEの段階では特に技術については意識しなくていいので、非技術者でも書くことが可能です。
なのでよりほしい機能を技術者に依頼することができます。


## SBEで受け入れテスト駆動開発（ATDD）が加速する

[Cucumber](https://cucumber.io/docs/guides/overview/)では

```
Feature : その人にあったサウナをレコメンドしたい

Scenario: 竹原は混雑してなくて、ハイスペなサウナに行きたい
  Given サウナは東京にはたくさんある
  When 竹原がサウナ検索サイトを開いた時に
  Then デフォルトソートを「混雑度」にする
```
上記のような、自然言語で書いた受け入れ条件に対して、
対象のソースコードをリンクさせる機能があるみたいです。（詳しくはしらん！Java限定疑惑）

そのため、SBEで仕様書が明確になっていればいるほど、
その受入条件をもとにTDDを行えばよいだけなので開発が加速するらしいです。

そして、受け入れる側もテストがSBEを満たしているかどうかを確認すればよいため楽に受け入れを行うことができます。


## TDD 
ここまで、SBEと軽くATDDに触れていよいよTDD
やり方は他の記事読めばいいとおもうので簡単に概要だけ。

### TDDは常に出荷可能な状態を実現するというメリット
TDDは基本的に一つずつ作っていくので、機能は網羅はしていないが常に出来上がった分までのデモをすることが可能であり、リリースも行える。


### TDDの順番
失敗→成功→リファクタリング
の順で行う。最初の成功の段階からきれいなコードを書く必要はない。

こんな感じでif文を大量生成しても良い。後でリファクタするから

```php

public function FizzBuss() {
	
	if ($num = 3 ) {
	 	rerurn 'Fizz'
	}

	if ($num = 6 ) {
	 	rerurn 'Fizz'
	}
	return $num
}
```

### TDDお悩みポイント

#### リファクタリングを行うタイミング
テスト→実装のフローでテストパターンを網羅できたと思ったら。
最初からきれいなコードを書こうとすることはテストケース漏れを生む原因になる。
一つひとつ確認してくことが大切。


#### TDDは無駄にテストを失敗したがるので面倒な感じがあるが
テストケースを一つずつ突破するだけでよいので「うーん」と頭を捻るタイミングが少なくむしろ実装は早いらしい。またリファクタリングをする際もすでにテストコードはあるのでミスに早めに気がつける。



＊TDDでFizzBuzz楽しかったのでぜひお試しでやってみてください！




### おわりに
SBEいいなー！と思いつつも、実際に業務のなかでこんな丁寧にDONE定義書かないよなー。という悩みを抱える。
しかしながら、「レコメンド機能」などある程度の規模感からだと、何をつくるのかが明確になり、それをコード以外の形でチームで共有できるため価値はあるのかなと感じる。またSBEという形で行動フローを言語化することにより、サービスのビジネスロジックの属人化を防ぐ一つの方法になりそう。
TDDのデモを見たが、爆速で実装してて「TDDすげ、神じゃん」ってなった。

とりあえず簡単にはじめるには、実装する前にテストパターンを洗い出してTDDライクに実装するとかでしょうか。


＊SDD（Sauna Driven Development）もいいよ！！