天・地・表・裏で仕様を読む

この記事は [ACCESS Advent Calendar 2019](https://qiita.com/advent-calendar/2019/access) 4日目の記事です。
入社9年目の @keigo1450 です。今年は [技術書典7でQA本（共著）を出したりしました。](https://access-company.github.io/techbookfest/) 
今日はあまり教わらなそうな「仕様書の読み方」について書きます。

# ざっくりいうと

* テスト（開発者テストも含む）のときには「テスト目線」での仕様（書）の読み方が必要
* 「仕様として書かれなかったこと」を見つけ出してプロダクトを良くしよう

仕様が一つのドキュメント（=仕様書）の形にまとまっていないプロジェクトもあるかと思いますが、チケットなり議事録なりに仕様が書いてさえあれば問題ない内容になっています。

# はじめに / ちゃんと仕様書を読んでいるのに...

皆さん、仕様（書）を読んでから実装/テストしていますか？いますよね？
素晴らしいです！
それなのに

* [開発] 仕様（書）を読んでから実装しているのにQA・ユーザからNGと言われる
* [QA] 仕様（書）を読んでからテストしているのにレビュアーからたくさん指摘される・バグを見逃してしまう

ということはないですか？
その頻度が高いとスケジュールやユーザとの信頼関係、チーム内のモチベーションなどに影響してしまいますよね。
「仕様書が悪い！」というのは簡単ですが、その結果仕様書の厚みが3倍になったら今度は斜め読みによる勘違いやメンテナンスの問題に対処しないといけません。

質の高い仕様（書）を作るのは一朝一夕にはできないので、今日は「今すぐできる！品質を上げるための仕様の読み方」を紹介します。
天地表裏の4ステップを意識するだけで、何かが見えてくるかも？

# 天を見る / ユーザのWhy・What・Howを知る

仕様化される前の「要求」を把握しましょう。
明文化されていないことも多いのでプロジェクトマネージャーや営業などに確認が必要かもしれません。
（重要な情報なのでチケットなどに書いてもらうようにルール化したいところです）

* **なぜこの機能がないとダメなのか？**
* **ユーザはこの機能で何をしようとしているのか？**
* **この機能をどのように使うのか？**
* **機能拡張を考えているか？どのように拡張したいと思っているか？**

要求を仕様化するときはズレや欠落が起きやすいです。
多少の制限事項やバグがあっても、ユーザの要求する範囲では動作するのならそれは「使える機能」です。
仕様通りに実装できていてもユーザがやりたかったことができないなら「使えない機能」を実装してしまったことになります。
そうならないためには「要求がこうなら仕様がこうなのはおかしい」と指摘できる必要があります。

# 表を見る / システムに統一性を持たせる

機能や画面の一覧表を一通り眺めて、同類がないか探しましょう。
（表がない場合は実際の画面やメニュー・設定項目などを見て回りましょう）
「同類 = 仕様構造が類似しているべきもの」です。

* **入力形式・出力形式が似ているか？**
* **処理の内容や順番が似ているか？？**
* **エラー処理は似ているか？**

例えばエラーの種類によってエラーコードの有無やログにどのパラメータを含むかが違っていたら分かりにくいですよね。
他にも入力データの整形をいつするのか？失敗した時にもデータを残すのか消すのか？などなど。

システム内では各機能の仕様構造が揃っていた方がユーザにも開発にも分かりやすくなります。
（形式や公式が存在するものは全て暗記しなくてもよい、というのと似ています）
仕様が分かりやすければ実装/テストしやすく、バグが混入する確率も下がるはずです。

ただし全部の仕様を読み直すのは無理なので「一覧を眺めて気になるところをピンポイントで確認」「眺めて分からなかったら仕方ない」というゆるい気持ちも大切です。

# 裏を見る / 仕様の「裏」まで考慮する

いきなり数学っぽくなってしまいますが、そんなに難しくないです！（むしろ他のより簡単なはず）
「裏」の仕様は書き漏らすことが多く、実装も漏れがちです。
仕様を読む/書く時は「全部の文を裏返してみる」くらいの気持ちで確認しましょう。

* **仕様を「P（xxのとき）⇒Q（xxする）」と捉えると、Not P（xxでないとき）とはどんなときか？**
* **Not P（xxでないとき）この機能はどう動くべきか？**

例えば「ボタンをタップしたとき⇒画面Xへ遷移する」だったら

* 「ボタンをタップしない」とは... 何もしない/ボタン上をドラッグ/ダブルタップ/二本指でタップ etc
* 遷移するのか？しないのか？それは他のボタンやサムネイルなどの処理と揃っているか？

「サーバにデータを保存したとき⇒ダイアログで通知する」だったら

* 保存しない = 保存できないとき（通信失敗/バリデーションエラー/その他サーバトラブル etc）
* リトライする？失敗を通知する？失敗の原因をサーバレスポンスで区別して対応？

「処理中のとき⇒インジケータを表示し、ユーザ操作を受け付けない」だったら
* 「処理中でない」とは...処理前・処理後・処理中断（アプリケーション終了、クラッシュ）
* 処理後の画面は自動再読み込み？ダイアログ・アイコン必要？失敗時と成功時で変わる？無理矢理中断したらどこへ復帰？

という感じです。
上の例のように Not P に複数のケースがあったり、ケースによって処理を変えなければいけなかったりします。
特にPが複雑（AかつBのとき/AまたはBのとき、など）なときの Not Pは要注意ですね。

# 地を見る / 要求-仕様-実装がつながっているか

以上を把握した上で仕様や実装の妥当性を確認してみましょう。

* **ユーザのやりたいことをカバーできているか？**
* **使われ方に合わせた仕様になっているか？**
* **将来拡張しやすい仕様になっているか？**
* **他の仕様と形式・構造が揃っているか？**
* **「裏」まで考えられているか？**

ずれているかも？足りないかも？と思ったらすぐに分かる人に確認しましょう。（チームリーダーやプロジェクトマネージャーなど）
「多分大丈夫」でスルーしてもQA検証でNGになったり、リリース後にお客さんからクレームが来たり、技術的負債がデグレを呼んだりでいいことはありません。**気になった時が最速の修正タイミングです。**

# おわりに

いかがだったでしょうか。仕様を読むというだけのことでも、品質向上の余地がありそうじゃないですか？
もちろん仕様を書く側がよい仕様を作り、うまく書こうとすることも大切です。特にオフショア開発などでは「仕様書に書いていないことはやらないのが当然」と言われることもあります。
ですが、実際問題「実装される全てを仕様書に書かなければいけない・メンバーは書かれたことを全て読まなければならない・書かれた全てをメンテナンスし続けなければならない」というルールは時間的・金銭的に難しい場合が多いでしょう。
一人一人が「読み取り力」を上げ、仕様書作成・編集コストを下げ、プロダクトやサービスの価値向上に使う時間を増やせるといいなと思います。

読んでいただいてありがとうございました。
明日は @ufoo68 がラスベガスな何かを書いてくれるようです。お楽しみに！