コーディングが始まったら設計書は読まないんじゃないか？

こんにちは。Kaneyasuです。
またポエムを書きます。
今回は設計書の話です。

以前関わった炎上プロジェクトにおいて、コーディング始まったら設計書は読まないんじゃないか？という議論をしたことがあります。
炎上していたので、設計書を書く時間が惜しい、書いてもどうせすぐ変更になるという状況から生まれた議論でした。
そこから得たものが価値があったと思っているので当時の議論と現在の私の設計書の捉え方を書きます。

# 本記事のターゲット

決まったことだから設計書を書いてはいるもののその意味を見出せない方。
設計書に何を書けばいいかよくわからない方。

# コーディングが始まったら設計書は読まないんじゃないか？

当時の私のチームではの話になりますが、
コーディングが始まったら設計書はほとんど読んでいませんでした。
イメージは頭にありますから、テーブル定義以外の設計書を見ることは必要はほとんどありませんでした。
入出力パラメータの名前を合わせるのにチェックするぐらいでしたね。
各々が自分の担当を設計・コーディングしていたので、早くコードとして出力してしまいたいという勢いだったと思います。

# 設計書を書く過程が大事である

上述のようにコーディング中は設計書を見なかったわけですが、これは設計書を書く過程で頭の中で仕様の理解と整理ができていたからだと思います。
日本語で仕様を書くこと、たくさん書くのは辛いので重要なことだけに絞ること、レビューを通して見直すこと。
この過程で、各々の仕様の理解と整理が高まっていきました。

特にレビューを通すと理解の効果が高かったです。
当時の私のチームは、レビュー時に対面レビューを行っていました。
レビュアーに設計書を見せながら口頭で説明していました。
結構な負荷ですが、整理されてない設計書は口頭で説明しづらいので、指摘を受けるまでもなくこりゃダメだなと感じられました。

以上のことから私たちは、コーディングが始まったら確かに設計書は読まないけれど、設計書を書く過程はとても大事であると結論づけました。

# 設計書に重要なことだけを取捨選択して書く

## 細かいことを書きすぎるとメンテ負荷となり開発効率が落ちる

次に、設計書を書くのはいいけれど、何を書くか？を議論しました。
真っ先に切ったのは、**SQLをそのまま日本語にすること**です。
たまにありますよね。
こういう設計書。

```SQL
SELECT 項目名 FROM テーブル名 WHERE 条件
```

このような設計書が必要な場面は確かにあります。
それは、設計とコーディングで担当者が強力な分業体制になっているケースです。

私たちの場合は、設計とコーディングは基本同じ担当者で、最悪でもチーム内メンバーなので上述のような細かいことを書く必要はないだろうと判断しました。
むしろ、細かいことを書きすぎるとメンテ負荷となり開発効率が落ちると結論づけました。
これも私の中で今も変わってない結論です。

## プログラムの流れを書く

では、細かくないこと・重要なこととはなんでしょうか？
当時私たちはMVCモデルで開発していて、C（Controller)の部分のイメージで書くことにしました。
ビジネスロジックはM（Model）の方にだいぶ寄っていて、Cはそれらを順に呼ぶだけです。
（ファットモデルであったことは反省ではあるのですが）

Cをイメージして書くことで、プログラムの流れを書くことになり、何を関数化するのが見えるようになりました。
上述の通り、「実績を取得する」のSQLを書く必要はないと判断しました。

```md
# 差分の確定画面

- ロックを行う
    - トランザクション開始
- 差分を取得する
    - 昨日の実績を取得する
        - 昨日は営業日で判断し、営業日の判定は営業日マスタを参照して行う
    - 当日の実績を取得する 
- 差分の記録
- メールで通知する
    - 連絡先一覧を取得
    - 各連絡先に通知する
- ロックを解放する
    - コミット
```

## テストしなければならないことを書く

次にテスト時に気をつけることを書きました。
これは炎上してたのでテストは外部メンバーに依頼する可能性があったことに起因します。
設計書にテストして欲しいこと書いてないと、テストに協力しないよと言われたのを憶えています。
至極もっともな指摘だったと思います。

```md
# 差分の確定画面

* 前提条件
    * 昨日・当日の実績を書き込むのは実績書込処理で行われているものとし、実績がないのは想定外とする

- ロックを行う
    - トランザクション開始
- 差分を取得する
    - 昨日の実績を取得する
        - 昨日は営業日で判断し、営業日の判定は営業日マスタを参照して行う
        * 休日を挟む場合は全営業日の実績を昨日分とする
    - 当日の実績を取得する
- 差分の記録
    * 差分がゼロでも記録する
- メールで通知する
    - 連絡先一覧を取得
        * 連絡先がゼロ件の場合、通知をスキップ
    - 各連絡先に通知する
        * 通知に失敗した場合、Warningログを出力して処理続行
- ロックを解放する
    - コミット
    * 正常終了ログ出力
    * 例外が発生している場合
        * ロールバック
        * エラーログ出力
```

## 項目移送定義を書く

ここは、かなり議論が白熱したところです。
そもそも、項目移送定義というものをご存知でしょうか。
（呼び方は組織によって多少違いはあると思います。）

こちらの表のように、画面の項目とデータベースのテーブル・カラムの関係を表したものです。

|コントロール名|テーブル名|カラム|
|:----|:----|:----|
|テキスト1|table_1|column_1|
|テキスト2|table_1|column_2|
|リストボックス1|table_2|column_a|
|ラジオボタン1|table_2|column_b|

正直なところ、開発者にとってはそこまで有用でないうえ、これを書くのは負荷が高いためできれば書くのを避けたいものです。
しかし、テストする方達から見れば画面が出てるものが正しいのか判断するのに重要な材料となります。
お願いする立場としてはテストしてもらう方に配慮するのが正しいので、頑張って書くことにしました。

ここまでが、昔の話です。

# リリースが確定したら改めて見直す

前項までに加えて、最近は努力目標としてリリースが確定したら改めて見直して仕様の理由・経緯を書き加えるようにしています。
問題が起きた時は、なぜそうなったのかを問われることが多いので、そこが設計書に書かれていると、とても助かります。
ソース内に書いていてもいいんですけどね。

最近の開発では、理由・経緯はチケットの履歴に残ってはいますが、チケットは開発が完了していると基本クローズしていて探しづらいのと、コメントの履歴を追うのは時間がかかるので、できる限り設計書に集約されていて欲しいと思っています。

```md
# 差分の確定画面

* 前提条件
    * 昨日・当日の実績を書き込むのは実績書込処理で行われているものとし、実績がないのは想定外とする
    * <追記>本画面は夜間の実績書込処理の正常終了を確認してから使用するもなので、実績が書き込まれてない状況は考慮する必要はない。

- ロックを行う
    - トランザクション開始
- 差分を取得する
    - 昨日の実績を取得する
        - 昨日は営業日で判断し、営業日の判定は営業日マスタを参照して行う
        * 休日を挟む場合は全営業日の実績を昨日分とする
    - 当日の実績を取得する
- 差分の記録
    * 差分がゼロでも記録する
- メールで通知する
    - 連絡先一覧を取得
        * 連絡先がゼロ件の場合、通知をスキップ
    - 各連絡先に通知する
        * 通知に失敗した場合、Warningログを出力して処理続行
        * <追記>通知が届いたのに書き込みがされてない方が問題になるので、通知失敗でも例外は発生させない
- ロックを解放する
    - コミット
    * 正常終了ログ出力
    * 例外が発生している場合
        * ロールバック
        * エラーログ出力
```

# まとめ

- コーディングが始まったら確かに設計書は読まないけれど、設計書を書く過程はとても大事である
- 設計書に流れやテスト項目になりそうなことなどの重要なことだけを取捨選択して書く
- 細かいことを書きすぎるとメンテ負荷となり開発効率が落ちる
- 項目移送定義など、テスト担当者に必要なものは書く
- 仕様の理由・経緯が設計書に集約されていると保守の時に助かる

以上です。
本記事の内容が開発者の何かヒントになれば幸いです。