ウェブ系のプロジェクトの進め方

## はじめに
僕は10年弱IT系で主に開発として働いています。そこで開発目線で学んだ特にWeb系のプロジェクトの進め方を書いていきます。

## アジャイルとウォーターフォールについて
まずですが日本のIT、ウェブ系はほぼウォーターフォールで進むと言っていいでしょう。

こんな感じでプロジェクトが進んでいきます。
1. 要件定義
1. 設計
1. 構築
1. テスト
1. 運用

日本で、特に大企業はアジャイル手法は取りません。（アジャイルにしているところもあります。あるいは部分的にアジャイル手法を取り入れる場合もあります）

でもアメリカではアジャイルのほうが主流で、ウォーターフォールはほとんど使われていません。

日米で主流となっている開発手法が違うわけでですが、原因は、個人的には日米のIT部門のあり方の違いとか雇用環境の違いがあると思います。

### 1. 雇用環境の違い

日本: 正社員としての長期雇用が一般的であり、プロジェクト単位で人材を流動的に変えるのが難しいため、計画が予めしっかりと組まれたウォーターフォール型の方が管理しやすいとされています。ウォーターフォールは、長期的な計画と細かな管理が必要なプロジェクトに向いており、日本の職場文化にも合致しやすいです。

アメリカ: プロジェクトごとに契約社員やフリーランスが加わることが多く、役割を柔軟に変更することが一般的です。アジャイルのスプリントや短期間での成果物の提出により、柔軟に方向転換できるアプローチが好まれています。

### 2. IT部門とSIerの違い

日本: 日本のIT部門の多くは外部のSIerに業務を委託しています。SIerは顧客が求める仕様通りにシステムを開発し、納期と予算に合わせて納品する必要があるため、ウォーターフォール型が採用されがちです。このアプローチは、仕様が確定してから設計に入るので、顧客が求める成果を確実に達成しやすいとされています。

アメリカのIT企業: IT部門が社内にあり、直接ビジネス部門と連携するケースが多いため、変化するニーズに即座に対応できるアジャイルの方が適していると考えられます。また、スタートアップ企業も多いため、スピード感や柔軟な開発が重視されます。

### 3. 開発文化とマネジメントの違い

日本: プロジェクト管理が上位から下位へ一貫して行われることが多く、品質や計画の遵守に強くフォーカスされます。ウォーターフォールのような段階的で予測可能な開発プロセスが、安心感をもたらすと同時に管理も容易にします。

アメリカ: より自律的なチーム編成が一般的で、意思決定もチーム内で柔軟に行われることが多いです。アジャイルのセルフマネジメントやチーム単位での調整は、アメリカの自律志向の文化と合致しやすいといえます。

#### だから日本はウォーターフォールが多い
上下関係のあまりない環境で内製のアプリケーションを作るなら日本でもアジャイル手法のほうがいいんでしょうね。それなら納期厳守する必要ないしね。

逆にアメリカであっても、外部に顧客がいて納期があり顧客から求められる仕様があるのに関わらず、アジャイル手法を導入して大失敗したケースは、ITではないですが、ボーイングの737max系の開発は一例ではないでしょうか。

ググれば以下のように批判している人もでます。
https://www.logikalsolutions.com/wordpress/information-technology/did-agile-make-the-737max-fall-from-the-sky/

だからあえてこの記事ではウォーターフォールの進め方を書きます。
アジャイルが間違っているとかそういうことでは全くありません。むしろ先進的で良い取り組みだと思いますが、きちんと日米の開発を取り巻く状況の違いを理解した上で使うべきだと思います。

## プロジェクト全体の流れ（ウォーターフォールの場合）
日本の環境でウォーターフォールモデルを採用する場合、以下のようなステップと準備が必要です。

### 1. 要件定義

#### 目的: プロジェクトの全体像を明確にし、顧客や関係者が求める成果を定義する。

必要なもの:
- 顧客とのヒアリング資料
- 要件定義書（何を実現するか、どのような機能が必要か）
- システムの非機能要件（セキュリティ、パフォーマンス、運用性など）

### 2. 基本設計

#### 目的: 要件に基づいてシステム全体の構造を設計し、必要な機能を具体的に分解する。

必要なもの:
- システム構成図
- データベース設計書（ER図やスキーマ）
UI/UXの画面設計（ワイヤーフレームやモックアップ）
- インターフェース仕様書（外部システムやAPIの設計）

### 3. 詳細設計
#### 目的: 基本設計に基づき、さらに具体的な技術仕様とプログラム構造を設計する。

必要なもの:
- プログラム仕様書
- 詳細なデータフローダイアグラム（DFD）
- エラー処理や例外処理の方針
- テーブル定義書やフィールド設計

### 4. 開発（コーディング）
#### 目的: 設計を基に実際のプログラムを構築する。

必要なもの:
- コーディング規約とガイドライン
- コードレビューのチェックリスト
- バージョン管理システム（Gitなど）

### 5. テスト
#### 目的: 開発したシステムが要件通りに動作するか、品質を確保する。

必要なもの:
- テスト計画書
- テストケースおよびテスト項目
- ユニットテスト、結合テスト、システムテスト、受入テストのそれぞれの環境
- テスト結果の記録と評価

### 6. 運用・保守
#### 目的: システムの稼働後に発生する問題の対応や改善、保守を行う。

必要なもの:
- 運用マニュアル
- 障害時の対応手順書
- サポート窓口とエスカレーションフロー
システムの保守計画書（アップデート、バグ対応など）

### 7. プロジェクト管理
各フェーズで進捗を管理し、スケジュールや予算のコントロールを行います。ウォーターフォールは進行が直線的であるため、途中での変更が難しく、進捗の把握やリスク管理が重要です。

必要なもの:
- ガントチャートや進捗管理ツール（MS Projectなど）
- コミュニケーション計画
- リスク管理計画
- 品質管理基準（QMS）

ウォーターフォールモデルでは、計画が事前に固められるため、初期段階での詳細な資料や計画作成が成否を左右します。また、各フェーズで承認を得て進むため、関係者との確認や合意も重要です。

## シミュレーションしてみよう
Netflixのような動画配信サイトの動画にチャット機能をつけるケースを例に各ステップのシミュレーションをしてみましょう。

### 要件定義
担当者: 「動画配信中に視聴者同士がリアルタイムでチャットできる機能を追加しましょう。」
エンジニア: 「対象はライブ配信だけですか？それともオンデマンドにも？」
担当者: 「まずはライブ配信で試して、好評ならオンデマンドにも広げましょう。」

### 作業見積もりとスケジュール作成
#### 1. 作業見積もり
担当者: 「チャット機能の作業を洗い出して、それぞれの工数を見積もりましょう。」
エンジニア: 「はい、要件定義・設計・開発・テスト・運用までの各ステップに分けて見積もります。」
例:
- 要件定義: 5人日
- 基本設計: 7人日
- 詳細設計: 10人日
- 開発（バックエンド、フロントエンド）: 20人日
- テスト（ユニット、結合、システム）: 15人日
- ドキュメントと最終チェック: 3人日
- 総工数: 60人日

#### 2. スケジュール作成

プロジェクトマネージャー: 「60人日ですね。メンバーは3人、1人が1日8時間とすると約1か月のプロジェクトになります。ガントチャートで全体の流れを見える化しましょう。」
エンジニア: 「了解です。各フェーズの担当とマイルストーンを明確にします。」
例:
- 第1週: 要件定義、基本設計
- 第2週: 詳細設計
- 第3〜4週: 開発
- 第5週: テスト
- 第6週: ドキュメント作成と最終確認、リリース準備

#### スケジュール管理のポイント
- マイルストーン設定: 各フェーズ終了時点での進捗確認
- リスク管理: 予備の作業時間を確保し、遅延リスクに備える
- 進捗レビュー: 各週の終わりにチームで進捗状況を確認

### 基本設計
エンジニア: 「チャット機能はサイドバーに表示する想定で、ユーザー同士のテキストメッセージのやりとりを基本にします。」
デザイナー: 「UIは動画再生画面の右にスライドする感じで出すようにします。タイムラインに沿ったコメントも追加していいですか？」
エンジニア: 「はい、チャットのタイムスタンプを動画の進行に合わせる形ですね。」

### 詳細設計
エンジニア: 「チャットメッセージはWebSocketを使ってリアルタイムで送受信します。メッセージはデータベースに保存しますが、保存期間は1週間に限定しましょう。」
データベース担当: 「了解。メッセージID、ユーザーID、チャット内容、タイムスタンプでデータを構成します。」
フロントエンド担当: 「チャットUIも完成しました。動画再生と並行してチャットが表示されるようにします。」

### 開発（コーディング）
エンジニア: 「まずWebSocketの接続部分を実装しました。次に、メッセージをサーバーに送信し、データベースに保存する機能を作ります。」
フロントエンド担当: 「サイドバーのUIは完了です。メッセージ送信ボタンと入力エリアも追加しました。」
エンジニア: 「全体を結合して、リアルタイムにチャットが流れるか確認しましょう。」

### テスト
テスト担当: 「複数のユーザーが同時にチャットに参加した際の動作を確認します。問題がなければ次にスパム防止の確認もします。」
エンジニア: 「メッセージが遅延なく表示されるか、異常終了しないかもテストしておいてください。」

### 運用・保守
サポート担当: 「ユーザーからチャットが流れすぎて追いつかないというフィードバックがありました。スクロール制御を追加できますか？」
エンジニア: 「了解しました。スクロール制御とともに、最新メッセージを追従するオプションも追加して、ユーザーが選べるようにします。」

### プロジェクト管理
プロジェクトマネージャー: 「スケジュール通りで進行していますか？」
エンジニア: 「大きな遅延なく、予定通り進んでいます。リリース前の最終テストも問題なしです。」
プロジェクトマネージャー: 「よし、このままローンチして、ユーザーの反応を見ましょう！」

以上のような感じにウェブ系の開発は進みます。

## プロジェクト進行時に失敗しがちな点
- 仕様考慮漏れ
「あとから気づいたけどすでにあるチャット機能とUIとか使用感とかが違いすぎると違和感すごくね？ある程度統一感持たせないとだめじゃん。一部やり直してもらわなきゃ！」
→ UIが作り直し、開発工数増、スケジュール遅延に

- 解決の難しいバグの発生
「なぜかチャットを開いたとき5%の確率でページがクラッシュするけどエラーログがなぜか出てなくて原因の見当もつかないよ…。時間をかけて調査しなきゃ！」
→スケジュール遅延に

- 作業見積もりの予想が大幅にずれる
「実際詳しくコードを読んで初めてわかったけど既存コードがアンチパターンのオンパレードで全く開発が進まない…。もう5日も調査と検討で時間使っちゃったよお。」
→スケジュール遅延に

- 既存処理にドキュメントがなく既存の仕様が不明
開発者A「user.status = 0とuser.status = 1っていう2種類のユーザデータがありますけどこれどういう意味のデータですか？」
開発者B「知らないよ。ここの開発を担当したCさんにきいて。」
開発者A「Cさんって今どこにいますか？」
開発者B「先月退職したよ」
開発者A「…」
開発者A「じゃあとりあえずこのデータは無視するか」
→ user.statusの値が原因で本番トラブルになったり影響大のバグの遠因になったりする。

- リリースの失敗
開発者A「いよいよ今日はリリース日だ！」
開発者A「リリースを開始したけど…。なんかエラーがでてるよ！？」
開発者B「あれ？君、リリース手順間違ってない？」
開発者A「え！？」
→ 本番システムでトラブル対応発生、リリースやり直し、リリースを別日で調整することになり、スケジュール遅延に。ユーザにも悪影響が。

### こうならないために
#### 不足の事態が起きてもいいように工数にはバッファ（予備用の余裕の工数）をいれよう
プロジェクトには不確実性が付き物です。不確実性の程度によって工数見積もりにバッファを入れましょう。

開発者の性格もあるので、せっかちな開発者は短めの工数をだすかもしれません。慎重な開発者は長めに工数をだすかもしれません。短い工数見積もりを出しがちな開発者のバッファは多めに、長めの工数を出しがちな開発者の工数は短めに設定するといいでしょう。

通常はバッファは工数の10-20%ですが、不確実性によっては1.5倍〜2倍にする場合もあります。どれだけ正確に工数がだせるかは開発者の腕の見せ所と言えます。

あまり長すぎてもその分の人件費がかかりますし、かと言って短すぎてもその分プロジェクト炎上もしくは失敗のリスクが高まります。

#### リリース手順は予め考えておき、文書化しておこう
どういうコマンドが実行されるべきか？不測の事態が起こったときどうするのか？本番システムを触る作業はスムーズに進められるように予め文書化しておきましょう。
Rest APIチーム、UIチーム、インフラ合同リリースみたいに他部署も関わるリリースの場合、予めそれぞれのチームで合意したリリース作業用の文書を作っておき、可能ならリリースリハーサルもできるとスムーズに進められます。

#### 負荷は大丈夫？
N+1 select問題やfor loopでinsert/updateを1件ずつするような処理は可能な限り避け、bulk insert/bulk update/bulk upsertで更新、またbulkでselectしてからその結果に対してループするようにしましょう。

#### 優先順位をつけて優先順位の高い作業、あるいは今後変更の入る可能性が低い重要な機能から作業を始める
優先順位の高い作業から始めていきましょう。あるいは今後仕様変更が入らないであろう作業から先に始めましょう。

#### まずは概算でいいからスケジュール
とにもかくにもスケジュールです。スケジュールができていないといつ終わってリリースできるのか？どれくらいの規模感のプロジェクトなのか？遅延しているにしてもどれくらい遅延しているのか？がわかりません。
まず概算でいいからスケジュールを作り、それをもとにプロジェクトを進行させましょう。

#### 正確な判断は正確な理解のもと出されます。開発対象のシステムの理解を深めておきましょう。
プロジェクト中はPM、開発者は様々な判断をスピーディに下す必要があります。ここで正しい判断が下せるかはプロジェクト成功の成否を分けると言ってもいいでしょう。
ここで正しい判断を下すには、開発対象のシステム・機能の深い理解と周辺の知識は不可欠です。
開発対象の機能の理解は読んで字の如くですが、知識は教科書に載っているような知識というより既存システムやその周辺技術の理解というほうがいいかもしれません。
予め開発対象のシステム・機能の理解を深める作業を可能な限りしておきましょう。