
プロジェクトマネジメントについて学んでみた
プロジェクトマネジメントとプロダクトマネジメントは重心が異なります。定義されたアウトプットを一定の制約の中で予測可能に実現することに強く責任を持つか、アウトプットを通じて顧客や事業にどのようなアウトカムを生み出したかを継続的に追うかの違いです。
もちろん、プロジェクトにアウトカムが不要なわけでも、プロダクトにアウトプットが不要なわけでもありません。両者の違いは、どちらをより強く管理対象とするかにあります。
今回はプロジェクトマネジメントについて、学びながら実務で取り入れた内容をまとめてみました。うまくいったところだけでなく、やってみて壊れたところも書きます。
プロジェクトマネジメント
プロジェクトマネジメントは、不確実性と不安に向き合いながら、限られた時間・予算・人員の中で、求められるアウトプットを予測可能な状態に近づけていく活動と私は結論付けています。
そのためには、「不確実性そのものを扱うこと」と「不確実性によって生まれる人の不安を扱うこと」が必要になります。
不確実性を分解する
不確実性はそのままでは扱うことができません。「なんとなくうまくいかなそう」という状態では、具体的な行動につながりません。そこで、不確実性を次のような観点に分解します。
- リスク:将来、望ましくない事象が起こる可能性がある
- 仮説:前提として置いていることが正しいか分からない
- 意思決定:複数の選択肢のうち、どれを選ぶか決まっていない
たとえば「機能Aを予定どおりリリースできるか分からない」という不確実性は、このように分解できます。
- リスク:「外部APIが予定どおり提供されないかもしれない」
- 仮説:「この設計で十分な性能が出るはずだ」
- 意思決定:「性能を優先するか、納期を優先するか」
同じ「分からない」でも、種類が違えば次に取る行動が違います。分解する目的は不確実性を完全になくすことではなく、それぞれに対して具体的な行動を取れる状態にすることです。
不安を情報によって減らす
プロジェクトには不確実性とは別に「不安」があります。
エンジニア、プロジェクトオーナー、経営者など、立場にかかわらず、人は「この先どうなるのか分からない」「今どこまで進んでいるのか分からない」「問題が起きているのかさえ分からない」という状態に不快さを感じます。この見通しのなさから生じるのが不安です。
そのものをゼロにすることはできません。しかし、現在地や今後の見通しを情報として共有することで、不安は減らすことができます。テスト結果、マイルストーン、リスク一覧、意思決定事項とその期限といったものがその情報にあたります。
ここで重要なのは、これらを管理すること自体が目的ではないということです。
マイルストーンを引くことにも、ロードマップを作ることにも、テストカバレッジを計測することにも、それ自体に価値があるわけではありません。それらはすべて、「今どこにいて、何が分かっていて、何が分かっておらず、次に何が起こるのか」を関係者が理解できる状態を作るための情報です。
アウトプットは目に見えます。アウトカムが重要だと言われながらも、プロジェクトではアウトプットが強く意識される理由の一つもここにあります。
その意味で、プロジェクトマネジメントにおけるアウトプットには、成果物としての役割だけではなく、不確実な未来に対して現在地と見通しを与える役割もあるのだと考えられます。
不確実性に向き合う
プロジェクトマネジメントでは、最初からすべてを正確に予測することはできません。まず「何が分からないのか」を明らかにし、それを扱える単位まで分解します。ここからは実際の手順を見ていきます。
不確実性の分解方法
最初に「何が分からないのか」を文章にします。「9月末にリリースできるか分からない」という大きな不安から始めても問題ありません。ただし、そのままでは具体的な行動につながらないため、さらに分解する必要があります。
ここでは、「9月末にリリースするためには、何が成立していなければならないか」という形で考えます。たとえば、次のようなものが成立条件になります。
- 要件が8月頭までに確定している
- API仕様が8月頭までに確定している
- 必要なエンジニアリソースが確保されている
- 9月中にテストと性能要件の確認が完了する
- 9月中にリリース可否の判断ができる
最初に考えるべき問いは、「このアウトプットが予定どおり成立するためには、何が真でなければならないか」です。
PMIでも、プロジェクトにおけるAssumption(前提)は、計画上は正しいものとして扱われている一方で、まだ確認されていないものとして扱われます。こうした前提が誤っていた場合、それはプロジェクトのリスクになります。
Don't make an ass out of you and me--using assumptions effectively
そのため、成立条件を書き出した後はそれぞれについて「確認済みの事実なのか、それともそうだと思っているだけなのか」を確認します。「API仕様は8月末までに確定する」という条件ひとつを取っても、次のような違いがあります。
- 契約上、8月末までの確定が明記されている
- APIチームが「たぶん間に合う」と言っている
- そもそも確認していない
いずれも文章上は「8月末までに確定する」と書けますが、根拠の強さは大きく異なります。
実務では、契約上できると言われていたAPIが、実際に提供されたら想定していた仕様とまったく違う、ということすら珍しくありません。そのため、「誰かがそう言っていた」という事実と、「実際に成立することが確認されている」という状態は分けて扱う必要があります。
PMIでもAssumption Analysisとして、前提の不正確さ、不安定さ、不整合、不完全さを調べることが、リスクを特定する方法の一つとして扱われています。つまり、成立条件とその根拠を並べる目的は、不確実性をその場で取り除くことではありません。どこに不確実性が残っているのかを特定することです。
リスクを把握する
成立条件と前提が見えてきたら、次は「その前提が崩れた場合に何が起こるのか」を考えます。
NASAのリスク管理ハンドブックでは、リスクを次のような構造で表現しています。
- 現在どのような状況にあり
- そこからどのような逸脱が起こる可能性があり
- 何がその影響を受け
- 最終的にどのような結果につながるのか
Condition → Departure → Asset → Consequence
NASA Risk Management Handbook
たとえば「API仕様が8月までに決まらない可能性がある」だけでは、まだリスクとして十分に具体的ではありません。これを分解すると次のようになります。
- 現在、API仕様に未確定事項が12件残っている
- そのため、8月までにAPI仕様が確定しない可能性がある
- その場合、フロントエンド実装の開始に影響する
- 実装開始が遅れ、最終的に納期に間に合わない可能性がある
このように整理することで、「なんとなく危なそう」という感覚を、現在確認できる事実から将来の影響までつながった形で扱うことができます。リスクを単なる憶測として書くのではなく、現在の状況を根拠として、何が起こり得るのかを因果関係として表現することが必要です。
この形を規約として書いておくと効きます。「懸念がある」だけで終わっているリスクは、書いた本人以外には何も伝えていません。現在の状況が書かれていなければ、それが本当にリスクなのか、それとも気分なのかを他人が判定できないからです。
仮説を検証する
不確実性そのものを小さくするにはどうすればよいのでしょうか。その1つが、仮説を検証可能な形に変えることです。
たとえば「新しい検索方式なら100ms以内に応答できるはずだ」という前提に基づいて実装しているとします。この時点では、「性能が出るはず」という未確認の仮説に依存してプロジェクトを進めています。「性能が出るかどうか分からない」と言い続けてもプロジェクトは進まないため、何を観測すれば判断できるのかを定義します。
そこで、「本番相当のデータ100万件を投入して負荷試験を行い、p95が100ms未満であれば採用する」と定義します。こうすることで、次の形に変換できます。
- 不確実な前提
- 検証可能な仮説
- 観測方法
- 判断基準
重要なのは、不確実性を「分からないもの」として眺め続けるのではなく、何を観測すれば分かる状態になるのかを設計することです。
検証できないものは意思決定に変換する
すべての不確実性が検証できるわけではありません。「品質を優先して2週間延期するべきか、それとも機能を削って予定どおりリリースするべきか」という問いは検証できません。これは不確実性というより、価値判断を伴う意思決定です。
この場合は、次の内容を明確にします。
- 何を決める必要があるのか
- どのような選択肢があるのか
- 何を判断基準にするのか
- 誰が決めるのか
- いつまでに決めるのか
UK政府の大規模プロジェクト向けガイダンスでも、重要なAssumption、Dependency、Decisionを明示し、未決定事項について、誰が、どのようなプロセスで、いつまでに解決するのかを記録することが求められています。
つまり、不確実性を分解する目的は、最終的に具体的な行動を取れる状態に変えることです。前提であれば確認し、仮説であれば検証し、リスクであれば監視や対策を行い、未決定事項であれば意思決定に変換します。
実務でどのように取り扱うか
不確実性を洗い出した後は、それを継続的に管理する必要があります。
UK政府のProject Delivery では、Risk、Assumption、Issue、Dependencyの頭文字を取ったRAIDという整理方法が使われています。これにDecisionを加えると、プロジェクト上の多くの不確実性を整理しやすくなります。
- Risk:まだ起きていないが、起こる可能性があること
- Assumption:正しいものとして計画しているが、まだ確認されていないこと
- Issue:すでに発生している問題
- Dependency:他の作業、組織、イベントなどに依存していること
- Decision:複数の選択肢のうち、どれを選ぶかが決まっていないこと
前半ではリスク・仮説・意思決定の3つに分けましたが、RAIDはそこから「すでに起きている問題」と「他への依存」を独立させた形です。
実務では、これらをGitHub Issueとして管理しています。ここでのIssueは、単なる「やるべきタスク」ではありません。プロジェクトを進めるうえで、解消・判断・調整していく必要がある「不確実性の単位」として扱っています。
なお、GitHub Issueにraid:issueというラベルを付けるので、「Issue」という語が二重になります。GitHubの入れ物としてのIssueと、RAIDにおける「すでに発生している問題」は別のものです。以下では後者をRAIDのIssueと書きます。
運用自体はシンプルです。raid:risk、raid:assumption、raid:issue、raid:dependency、raid:decisionといったラベルを付け、RAIDの考え方に沿ってIssueを作成します。あとはGitHub Projectsのボード上で、これらのラベルが付いたIssueをRAIDビューに、それ以外を通常のビューに分けて表示します。
Issueの中身については、Issue Templateとして定型化しても構いません。ただ、私たちの場合はリポジトリ内のドキュメントにIssueの書き方を定義しておき、AIがその内容を参照してIssueを作成する運用にしています。
以下は、数人で数か月動いている開発で実際にやったことと、そこで踏んだものです。GitHub IssuesとGitHub Projectsのボード1枚しか使っていません。
成立条件の表現
「9月末にリリースできるか分からない」に相当する大きな不安を、まず1つのIssueにしました。そのうえで、成立条件を1つずつsub-issueに切り出しました。
親を「このアウトプットが成立するためには何が真でなければならないか」、子をその条件として作成します。こうするとGitHub ProjectsのSub-issues progressが、そのまま「条件のうちどこまで片付いたか」の表示になります。Issueの消化率がそのまま、成立条件の進捗になります。
実際に分解してみたら、子は7件になりました。内訳はRisk 1件、Dependency 2件、RAIDのIssue 1件、Assumption 1件、Decision 2件です。
ここまで試して理解したのは、これは完全に PR の分解とはベツモノであるということです。1 issue に対して 1 PR が基本的な考え方で、それができないときは sub-issues を作成したりしていました。今までの方法では扱えないので、規約自体を変えてしまい、RAID は別枠で扱うということにしました。
不安に向き合う
不確実性そのものとは別に、関係者の「不安」にも向き合う必要があります。
不安は、単純に情報量が少ないから生まれるわけではありません。関係者が次のことを理解できなくなったときに強くなります。
- 今どこまで進んでいるのか
- この先どう進むのか
- 何が予定どおり進んでいないのか
- 何がまだ決まっていないのか
- 誰がいつ判断するのか
だからといって、情報を大量に共有すればよいわけでもありません。必要なのは、現在地・未来・意思決定の3つについて、必要な情報を継続的に観測できる状態を作ることです。
現在を見せる情報
まず、「今どこまで来ているのか」を観測できる必要があります。例えば、次のような情報です。
- CIの実行結果
- テスト結果
- テストカバレッジ
- 完了したアウトプット
- 未完了のアウトプット
- 現在発生しているIssue
- 進捗状況
ここで注意したいのが進捗率です。
例えば、Issueが100件あり80件がCloseされているからといって「80%完了」と表現しても、プロジェクトが本当に80%完了しているとは限りません。
残り20件の中に、
- 本番移行
- 性能試験
- 外部システムとの結合テスト
- セキュリティレビュー
といった重要な項目が含まれていれば、成果物を成立させるための重要な条件がまだ確認できていません。
そのため、単純なIssueの消化率よりも、成果物の完了条件に対して何が成立しているかを見る方が重要です。例えば、次のように表現した方が現在地ははるかに正確です。
講座情報取得APIの実装は完了している。
単体テストも完了している。
一方で外部APIとの結合テストは未着手であり、性能試験も実施していない。
つまり「現在を見せる」とは、作業量を報告することではなく、「成立条件のうち、何がすでに確認され、何がまだ確認されていないのか」を見せることだと考えた方がよいでしょう。
CIやテストカバレッジについても同様です。
CIがGreenであることや、テストカバレッジが80%であること自体が目的ではありません。その情報によって、成果物のどの部分が機械的に検証され、どの部分にまだ不確実性が残っているのかを判断できることに価値があります。
見せている情報が壊れていないかを知る
スプリントごとの完了を記録する仕組みを、毎日走る自動化で維持していました。締めを過ぎたスプリントに、その期間にクローズされたIssueを紐付け、全部終わっていればそのスプリントを閉じ、次のスプリントを作る。それだけの処理です。
ある日から、この自動化が毎日失敗するようになりました。原因はGitHub側の仕様変更で、期日に日付だけを渡すと422を返すようになっていました。それまでは通っていた書き方が、ある日から通らなくなりました。そのため、次のスプリントが作られませんでした。その週にクローズした20件は、どのスプリントにも属さないまま残りました。1週間くらいしてやっと気づきました...。何も壊れているように見えなかったことです。CIは緑で、ボードは普通に動いていて、Issueは順調にクローズされていました。
ここから2つ学びました。
ひとつは、情報を出す仕組みも成果物であり、成立条件を持つということです。「毎日動いている」は未検証の前提です。定期実行が失敗し続けても誰も見ないのであれば、それは可視化されていないのと同じです。
もうひとつは、「情報を共有すれば不安は減る」には条件があるということです。共有している情報が現実と合っている必要があります。合っていない情報は、不安を減らすのではなく、不安を感じるべきときに感じさせなくします。こちらのほうが危ないと思います。
未来を見せる情報
現在地だけ分かっても、その先が見えなければ不安は残ります。そのため、次に必要なのが「この先、何が起こる予定なのか」を示す情報です。
次のような内容が該当します。
- マイルストーン
- ロードマップ
- 依存関係
- Target Date
- リスク一覧
- 未検証のAssumption
ここでも、単純に日付を並べるだけでは十分ではありません。
次の例では、その日付に何が起きるかは分かりますが、何が成立する予定なのかが分かりません。
8/1 API対応
8/15 フロント実装
9/1 テスト
より重要なのは、次のようにその後に何が可能になるのかを示すことです。
8/1 API仕様確定
→ フロントエンド実装を開始できる
8/15 API実装完了
→ 結合テストを開始できる
9/1 結合テスト完了
→ リリース可否を判断できる
例えば、プロダクトの開始直後でどんどん開発が進むタイミングであれば、マイルストーンを無理に敷く必要はないと考えています。その代わり、スプリントやイテレーションごとに何をしたか、何ができるようになったかをまとめていく必要があります。
GitHub Projectsの場合は、プロジェクトの更新を共有できるので、その機能をうまく使います。
私はスプリントごとに1つ更新を置いて、そのスプリントで何ができるようになったかを数行でまとめ、あわせてその期間のIssueとPRの一覧へのリンクを載せました。まとめだけだと「本当にそれだけか」を確認できないので、原本に降りられるようにしておくという趣旨です。
依存関係を見せる
未来の見通しを作るうえで、特に重要なのが依存関係です。プロジェクトでは、「Aが終わらないとBを始められない」という関係が大量に存在します。この依存関係が見えていないと、「個々のタスクは順調なのに納期だけ突然遅れる」ということが起こります。
GitHub Issuesでは、Issue同士にblocked by / blockingの依存関係を設定できます。つまり、「何が終わらないと次に進めないのか」をIssue間の関係として直接表現できます。
この機能を利用したり、Issue化できない外的要因によって阻害されていることを表現するために、BlockedというStatusを用意し、そこにIssueを入れる方法もあります。
実際にやってみると、ブロッカーは2種類に分かれました。片方はIssueで表せるもので、これはblocked byで張ります。もう片方はIssueにできないもので、契約条件の確定、費用の判断、リリース時期の決定、特定の人の作業待ちなどです。後者はIssueにしても中身が書けません。誰かが決めるまで存在しないからです。
そこで、ボードに「何を待っているのか」を1行で書くフィールドを別に持たせました。「有料プランの費用と契約条件の確定待ち」のように、待っている条件そのものを書きます。ブロッカーがIssueなら依存関係が記録で、フィールドは理由を1行持つだけ。ブロッカーがIssueにできないものなら、フィールドだけが記録になります。
このとき気づいたのは、Issueにできないブロッカーは、たいていDecisionだということです。「費用と契約条件の確定待ち」は、誰かが決めれば解消します。つまりこれは待ちではなく、未決定事項です。この視点で見直すと、Blockedに置いたまま止まっていたものの何割かは、実は決定を待っていたものでした。
これらの仕組みによって、どの未完了Issueが、将来のどのアウトプットを止めているのかを見ることができます。これは不安を減らすうえで重要です。「遅れています」という情報よりも、次の方が判断材料として優秀です。
- API仕様確定Issueが3日遅延している
- このIssueはフロントエンド実装をBlockしている
- 現時点では結合テスト開始日まで2日の余裕がある
意思決定の可視化
現在地と未来が見えていても、プロジェクトが止まることがあります。
典型的なのは「誰かが決めないと進まない」という状態です。例えば、次のような問題です。
- 新APIを使うのか旧APIを使うのか
- 性能改善を続けるのか機能を削るのか
- リリースを延期するのか予定どおり出すのか
これらはタスクではありません。「実装中」「対応中」といったStatusで管理すると、何が起きているのか分かりづらくなります。そのため、意思決定そのものを管理対象にします。
これも同様にGitHub Issuesで管理し、ラベルを付与して対応できます。あとは、プロジェクト上でそのラベルが付いていてCloseされていないIssueの一覧を作れば、現在プロジェクトに残っている未決定事項を確認できます。
ここではビューを1枚だけ足しました。Decisionのラベルが付いていて、まだCloseされていないIssueだけを出す表です。列には決定者と期限を出しています。
プロジェクトを運用する
プロジェクトは、計画を立てて実行すれば終わるものではありません。実行中に得られた情報をもとに、前提や計画を見直し、必要な判断を行いながら進めていく必要があります。
不確実性を完全になくすことはできないので、重要なのは最初の計画を最後まで固定することではなく、計画と現実の差分を継続的に観測し、必要に応じて更新できる状態を作ることです。
未知を既知に変え続ける
不確実性は、プロジェクトの開始時に一度洗い出せば終わりではありません。進むにつれて新しい情報が得られ、正しいと思っていた前提が崩れたり、新しい依存関係やリスクが見つかったりします。
ここで区別しておきたいのが、「既知の未知」と「未知の未知」です。問題になりうることを認識しているが、その内容や影響がまだ分かっていない状態と、そもそも問題になりうること自体を認識していない状態は違います。RAIDやDecisionは前者を整理する道具で、後者はそのままでは管理対象にできません。だから重要なのは、未知をできるだけ早く発見して、既知の未知に変えることです。
方法はふたつあります。
ひとつは、定期的に同じ観点で洗い出すことです。タイミングは、スプリントやイテレーションの終了時、マイルストーンに到達したとき、大きな仕様変更が入ったとき、外部依存に変化があったときなどです。観点は毎回同じにします。
- 新しく分かったことは何か
- これまで置いていたAssumptionで崩れたものはないか
- 新しく発生したRiskはないか
- Blockedになったものはないか
- 新しく必要になったDecisionはないか
- 次のアウトプット成立を阻害するものはないか
- この計画が失敗するとしたら、何が原因になるか
もうひとつは、実際に小さく動かしてみることです。PoC、性能試験、結合テスト、ステージング環境での検証などを早い段階で行うと、計画時点では見えていなかった問題が表面化します。洗い出しは既知の未知を並べ替える作業ですが、未知の未知は手を動かさないと出てきません。
見つかったものは、新しい管理方法を増やすのではなく、これまで使ってきた仕組みに戻していきます。ここで一番よく起きたのは、種別の付け替えでした。Assumptionが崩れてRiskになる、RiskがRAIDのIssueになる、検証できないと分かってDecisionになる。最初に置いた種別が最後まで正しいことはあまりありません。そのため、種別を変えたときは、なぜ変えたのかを残すようにしています。付け替えの履歴自体が「何が分かったか」の記録になるからです。
予測可能性とは何か
ここまで「予測可能な状態」という言葉を使ってきましたが、予測可能性とは、最初に立てた計画どおりにプロジェクトが進むことではありません。
プロジェクトには不確実性がある以上、計画と現実には必ず差が生まれます。予定していたAPIが届かないこともあれば、性能要件を満たせないこともあります。想定していなかった依存関係が見つかったり、途中で要件そのものが変わったりすることもあります。
重要なのは、計画と現実に差が生じたときに、その差を認識できることです。
例えばAPI仕様の確定が遅れていたとしても、その遅れによってフロントエンド実装がいつから影響を受けるのか、現在どの程度の余裕があるのか、何日以上遅れた場合に代替案へ切り替えるのか、その判断を誰が行うのかが分かっていれば、状況は管理できます。未来を完全に予測できていなくても、プロジェクトは進められます。
反対に、すべてのタスクが予定どおり進んでいるように見えても、依存関係や未検証の前提が把握されていなければ、プロジェクトは予測可能とは言えません。ボードが正常に見えるのと、ボードが正しいのは別のことです。
そのため、プロジェクトマネジメントにおける予測可能性は、未来を正確に当てることではなく、未来が想定から外れたときに、その変化を早く観測し、影響を理解し、必要な意思決定を行える状態と考えた方が適切です。そして観測する仕組み自体が、観測の対象に入ります。
さいごに
プロジェクトマネジメントは、デリバリーを関係者が不安なく進められる状態を作ることが焦点なのだと、今回学んでみてよく分かりました。自分自身が抱えていた不安についても、かなり言語化することができて、少しホッとしている部分もあります。
一方で、仕組みを作ることが仕事の終わりではないというのも、やってみて分かったところです。作った仕組みが生きているかどうかを見る手段まで含めて用意する、というのが次の課題です。










