SIerに入って８年ぐらい経ったのでいろいろ棚卸しをしてみる。【vol.010 開発PJ内でのドキュメンテーション】

## イントロ
これまで自分が経験してきた開発PJを振り返りながら、「システム開発におけるドキュメンテーション」という切り口で記事を書いてみようかと思います。

#### 最初に結論

開発スタイルともセットなのですが、少数精鋭で基本的にフェーズごとの分業が発生しなければ、

 - コードは生ものとして扱い、極力ドキュメントは書かない。
 - 開発工程で発生するやりとりは、すべてSlack・GitHub・Redmine等で残す。
 - コードを書く上で頭の整理が必要ならドキュメントを書く。
    - ただし、メンテナンスされない前提と中間成果物として扱う。
 - 自分がテストするにしろ、他人にお願いするにしてもテストケースは書く。
    - 単体テストはUnitTestで充分だと思いますが、結合テスト的なところはやっぱり必要だと思います。テスト漏れを防ぐという意味では、何らかの形で表現されて整理されないとダメだなというのが実感です。

だと考えています。

#### これまでの経験

これまで大きく分けて、以下３スタイルのドキュメンテーションを経験してきました。

 1. ウォーターフォール型開発でフェーズごとにきっちり納品物としてドキュメント書く。
 2. ゆるやかなウォーターフォール型開発で納品物としては[ワイヤフレーム](https://nandemo-nobiru.com/web-5695)だけ書く。
 3. アジャイル開発で納品物としてのドキュメントは書かない。

順を追って詳細を書いていきます。

## きっちり納品物としてドキュメント書くスタイル。
要件定義書からリリースに至るまで、各工程でぎっしりExcel方眼紙に書きました。
大手自動車会社のプロジェクトということもあり、社内標準のシステム開発工程に則ってプロジェクトを進める形です。

開発チームは、ピーク時12名ぐらいのプロジェクトです。

覚えている範囲で

 - 要件定義書
    - [機能要件、非機能要件それぞれ。](https://www.brain-gate.net/column/system-program/functional-requirement.html)
 - 基本設計書
    - 画面設計書
        - 画面レイアウトや各ボタン操作についての概要を書く。 [※こういうやつ。](https://tech.nikkeibp.co.jp/it/article/COLUMN/20080728/311667/)
    - バッチ処理フロー図
        - 数十ステップにもなるような長いバッチ処理をステップ単位につなげてフロー図を書く。[※こういうやつ。](http://yfuku.sakura.ne.jp/mvs/j61.html)
 - 詳細設計書
    - クラス設計書、メソッド設計書
        - ほぼソースコードとも言えるようなぐらいの詳細な処理内容を書く。
 - 単体テスト計画書および報告書
 - 結合テスト計画書および報告書
 - システムテスト計画書および報告書
 - リリース手順書
 - その他各一覧やWBS

が納品物であり、すべてほぼ所定のフォーマットに従って記載する必要がありました。
逆に納品物以外の開発チーム内で共有するドキュメントは、ほとんどありませんでした。

整備されていたのは、新規参画者向けの教育用資料です。
自動車や製造業だと[BOM（部品表）](https://it-trend.jp/materials_management/article/explain)への理解が必須だったりするので、その関連の資料は必要に応じて整備していました。

## なるべく納品物としてのドキュメントは書かないスタイル。
プロジェクト関係者の共通認識としては、「よくあるウォーターフォール型開発のドキュメンテーションをしてしまうと無駄が多いので、なるべくドキュメントレスで行きましょう」がありました。

- 初期開発時は、納品物として要件定義書とワイヤーフレームのみ。
    - 開発チームは、ピーク時15名ぐらい。
- それ以降の改善案件は、ワイヤーフレームのみ納品物。
    - 開発チームは、ピーク時4名ぐらい。

逆に納品物としてドキュメントが少ないので、開発チーム内で共有するドキュメントを用意する必要がありました。

特に初期開発時に書いたのは、

- 一覧系
    - 機能定義書
        - 要件定義書よりは、もうちょいブレイクダウンした処理内容を書いたもの。
    - Controller、Service、Repository等のクラス・メソッド定義書
        - どんなクラスとメソッドが必要で、どういった役割を持つかのサマリ。
    - URL定義
        - ほぼWebアプリメインだったのでControllerと紐づけたURL設計。
- 個別
    - バッチ設計書
        - 大まかなステップごとに何やるか書いたもの。
    - 処理設計書
        - よっぽど込み入った機能だけ詳細な設計をしたもの。
- テスト
    - 結合テスト仕様書
        - Webアプリであれば操作シナリオ、バッチ処理系は処理手順を書いた期待値を書いたもの。

あたりです。

単体テストについては、ドキュメントは書かない代わりにUnitTestを書いて品質担保するということで進めていました。

## 完全に納品物としてのドキュメントは書かないスタイル。
SaaSでのプロダクト開発なので基本的に「動いているコードが正義」のスタイルです。
SI案件ではないので納品という概念がほぼないのですが、あるとすればソースコードです。

とはいえ、必要に応じて要件を整理したり、設計したり、テスト仕様書を書いたりということはしています。
また、Webデザイナーが画面レイアウトを整備したり、プロダクトマネージャが機能要件を書いたメモだったり、そういったものはあります。

その他、GitHubでプルリクエストを出す時にDescriptionを書くので、それもドキュメントと言えるかもしれません。

## 振り返ってみて

#### SI案件かそうではないかでだいぶ変わってくる
SI案件だとビジネスモデル的にピラミッド構造にしないとビジネスとして成り立ちません。
よくある言われるゼネコン構造です。

規模感によって分業の具合は異なりますが、
ビジネスモデルからの要求でどうしても分業体制を取らざるを得ません。

極端な話だと１つの機能を作るのに、

 - 要件定義する人
 - 設計する人
 - 実装する人
 - テストする人

が全部違う人という話です。

システム開発に限らず、自分以外の人に仕事を頼もうとすると、多かれ少なかれ説明をする必要があり、その説明のためにドキュメントは必要になります。

納品物かどうかに関わらず、SIのビジネスモデルでシステム開発する以上は、ウォーターフォール型の開発で定番とされているドキュメント群は、作らざるをえないというのが実感です。

#### とはいえ、必要最低限に収めることは可能なはず

ただ、案件の状況や参画メンバーに応じて必要最低限に収めることは可能だと思っています。
顧客の理解を得た上ですが、自分がやっていたのは、

 - 要件定義の内容を議事録も兼ねてRedmineのチケットに書いて済ませる。
 - Redmineのチケットのやりとりをベースにして機能を実装して、動かしてもらってOKならそれで終わり。
 - 実力があるメンバーは要件を伝えるメモ書きで済ませて、コードを書いてもらう。
 - 単体テストに関するドキュメントを書くより、UnitTestを書く。

あたりです。

#### 純粋にシステム開発のためではないドキュメントの役割

SI案件だと一括にしろ、SESにしろ法的に訴えられるリスクがあるので、あとで揉めた時の防衛手段としてドキュメントが必要だったりします。

それは、要件定義書のドキュメント群じゃなくて議事録をしっかり書くのでもいいかもしれません。とはいえ、開発工程において顧客とベンダーが合意した内容が文章化されている必要はあります。

ここもビジネスモデルからの要求だと考えています。

#### じゃあ、SI案件じゃなかったら
Webアプリの場合は、画面のデザインが必要なので、ここは必要だと思います。

あとは、エンジニアとしては、もう「動いているコードが正義」のスタイルです。
コード書いて動かして、プロダクトマネージャー・デザイナー・ユーザーに触ってもらってOKならOKだと思っています。

クラス定義やメソッド定義は、コード書く前から考えても実装してみたら変わってくる。要件が増えたら、必要に応じてクラス構成もメソッド構成も見直す。リファクタリングされることが前提のスタイルです。

#### どんな仕様かはコード読めば分かるけど、なんでかは分からない

「どんな仕様になっているか」は、要件定義書を見なくてもコードを読めば分かるので不要だと考えています。コード以外にもUnitTestが整備されていれば、inとoutは分かる。どうしても劣化するドキュメントを整備するよりは、UnitTestを整備する方が価値があると経験上感じます。

「なんでこんな仕様になってるんだっけ」は、場合によっては過去の経緯を知っている人がいなくなると誰も分からなくなるので、コードコメントとして残されるべきかなと思います。場合によっては、1ヶ月前に自分が書いたコードが分からなくなる場合もあります。（ありました。。）

ただ、これも[ここ](https://qiita.com/TsJazz27Sumin/items/c380d92aa791abbaab08)で書いたように「再利用可能なコミュニケーションの資産化」で補える部分でもあります。Slack上なり、Redmineのチケット上でなり、やりとりが残っていれば追えば分かる場合が多々ありました。

#### なんでか分からないけど、これからどうあるべきかがあれば、理由もいらない

実際に自分が経験したことなのですが、「この機能は今こういう仕様だけど、これからこうしよう」という場合、過去の経緯とか関係なくコードが書き換えられます。

SI案件だと顧客が要望している仕様を実現するのが目的だったりするので、安易に書き換えられないのですが、プロダクト開発だと目的がより良いプロダクトにすることだったりするので、そこに合致していれば可能だし、実際にやりました。

ケースバイケースかとは思います。

#### じゃあ、開発PJ内でのドキュメンテーションはどうあるべきなのか

繰り返しとなりますが、

 - コードは生ものとして扱い、極力ドキュメントは書かない。
 - 開発工程で発生するやりとりは、すべてSlack・GitHub・Redmine等で残す。
 - コードを書く上で頭の整理が必要ならドキュメントを書く。
    - ただし、メンテナンスされない前提と中間成果物として扱う。
 - 自分がテストするにしろ、他人にお願いするにしてもテストケースは書く。
    - 単体テストはUnitTestで充分だと思いますが、結合テスト的なところはやっぱり必要だと思います。テスト漏れを防ぐという意味では、何らかの形で表現されて整理されないとダメだなというのが実感です。

だと考えています。

### 2019/06/16追記　SIerに入って８年ぐらい～シリーズまとめ

[SIerに入って８年ぐらい経ったのでいろいろ棚卸しをしてみる。【vol.001 イントロダクション】](https://qiita.com/TsJazz27Sumin/items/85ef42b1499dd324c06f)から始めて、2ヶ月あまり記事を追加してきましたが、今回でこのシリーズは最後にしようかと思います。

続けて見てくださった方がいるのであれば、つたない文章に付き合っていただいて感謝です。
他にも以下について考えていたのですが、

 - PJ内でのタスク管理（Excel、Redmine、Trello）
    - SI案件とSaaS案件でずいぶんタスク管理の考え方が異なるなと感じたので、何か書こうと思いました。
    - ただ、だいぶ抽象的な話になりそうなので見送りです。
 - Jenkins
    - デプロイ自動化、UnitTestの定期実行というところで使っていました。
    - ただ、そんなのどこでもやってそうだな、、ので見送りです。
 - UnitTest
    - JavaであればJUnit、C#であればNUnitを使ってきました。
    - 理想としては、レイヤードアーキテクチャであれば、各レイヤーごとに整備されているべきと考えています。開発スピードやメンテコストとの兼ね合いもあるので、必要最小限に収めると良いと思います。
    - と、そんな一般論しか書けなさそうなので見送りです。
 - フロントエンド（javascript, jQuery, Ajax）
    - 自分がどちらかというとサーバーサイド＋マネジメント寄りのということもあり、ここも一般論しか書けなさそうなので見送りです。
 - Struts, Spring, Spring Boot, MVC5
    - 古いFWについて今更書いても感があり、Strutsは見送りです。
    - あと、割とモダンなFWならJavaもC#も似たりよったり、ここも一般論しか書けなさそうなので見送りです。
        - DI
        - AOP
        - 認証周りの機構
        - HTMLテンプレート（Thymeleaf, Razor）

でした。

単なる技術Tipsじゃなくて、使ってみてどうだった、経験してみてどうだった、という＋αも書けるように心がけてきましたが、自分の経験と絡めて何か書くことの難しさを感じた2ヶ月でした。