読者です 読者をやめる 読者になる 読者になる

開発の見積もりとスケジュール管理

こんにちは。会員事業部の丸山です。

エンジニアが開発を開始する時にはタスクの見積もりとスケジュールを作成行って、実装を進めていくと思います。 しかし1ヶ月を超えるような規模の開発をする場合、なかなか予定通りの期日に終わらなかったりすると思います。 そして大抵の場合、増える方向になりますよね。 今回はそういうことにならないために、私が気をつけていること・実践していることをいくつか紹介したいと思います。

見積もりとは

まずは「見積もり」とは何なのかを正しく理解したいと思います。 一般的には「見積もり」=「全タスクとその工数を洗い出す」というものだと思います。 しかしここで以下のことに気をつける必要があります。

見積もりとスケジュールとコミットメントは違う

見積もりとはあるタスクがどれだけの工数(規模)なのかを算出することです。 対して、スケジュールとはあるタスクがどれだけの工期(期間)なのかを算出することです。 この2つを混同してしまうと、正しく仕事をすすめることができません。 例えばタスクAの工数が8時間だったとしても、それを担当する人の稼働が実は1日に4時間しかない場合、工期は2日(16時間)となります。

次にコミットメントは最終的な予算・期間・品質をどういうバランスにするかを決めて、約束をすることです。 たとえば10個のタスクを見積もり、スケジュールを立てたところ、1人で3ヶ月かかることがわかりました。 この話を責任者にすると「2ヶ月で終わるようにしてくれ」という要望があり、見積もりをなんとか捻じ曲げてして、2ヶ月で終わるようにしました。

しかし、本来はコミットメントをどうするか?という話を責任者とする必要があります。 人的リソース(予算)を増やすのか、リリース日(期間)をもう少し遅らせられないか、機能(品質)を削ることができないかなどを話し合うべきです。 コミットメントが変わらないのに、見積もりやスケジュールは変更されません。 これを混同してしまうと、現場も責任者も両方不幸になってしまいます。

「見積もりをしてください」と言われたら

では「見積もりをしてください」と言われたらどうしたらよいのでしょうか? 見積もりを行うには大きく2つのステップがあります。

  1. 作るべきものをタスクに分解する
  2. タスクの規模を算出する

タスクに分解する

まずタスクに分解するステップですが、これは「タスクに分解する」と捉えるよりも「設計をする」と捉えたほうがよいと思います。 つまり見積もりをするときに一番初めに行うことは設計です。作るべきものを設計し、具体化しなければ正しくタスクに分解できません。 そしてこのことから分かるように、見積もりを正確にするには時間をかけるのではなく、より詳細な設計をすべきです。

ここで、一つ問題になるのがどこまで詳細な設計をすべきなのか?ということです。 これを定量化するのは難しいのですが、開発している対象によってだいたい似たパターンがあると思います。 例えばWebサービスを開発しているサービスエンジニアの場合「画面一覧/Controller/Model/View/テストコード/インテグレーションテスト/テーブルスキーマ/マスターデータ/ログ」などに分解することが多いと思います。 他にもインフラや開発基盤系のタスクを分解する必要があるエンジニアの方もいると思います。 このように、どういうタスクに分解していくかは会社・部署・チーム・個人などである程度決まった型(テンプレート)を作っておくと役に立つと思います。

規模の算出

次にそれぞれのタスクの規模を算出していきます。 ここで重要なのは「主観や判断をなるべく少なくして、機械的に算出する」ということです。 もっとも良いとされているのが、「過去の実績を元に似たタスクから算出する」というものです。 しかしそのためにはこれまでの実績が正しく残っている必要がありますし、「似たタスク」というのがあまり無いケースも多いでしょう。 *1

そこで僕が行っているのは全タスクのなかから平均的な難易度のタスクを選び、それを元に各タスクに難易度を振っていくというものです*2。 難易度は「1, 2, 3, 5, 8, 13, 21」*3ぐらいを用意します。 次に基準となるタスクを一つ決めて、そのタスクの難易度を3(もしくは2)として各タスクに難易度を振っていきます。 難易度が13や21のタスクは現時点ではまだ詳細がわからないや調査が必要というものです。 理想的にはこれらは無いほうがよいのですが、現実的には見積もり時にはわからないことは残っていると思います。

すべてのタスクの難易度が決まったら、基準としたタスクにかかる工数(時間)を算出します。 あとは他のタスクにも時間を掛け算していきます。 たとえば基準のタスクが難易度3で6時間となった場合、難易度に2を掛けた値をそれぞれの工数(時間)とします。

ちなみに、見積もりを他のエンジニアにレビューしてもらう場合は、難易度のままでレビューしてもらうと良いと思います。 工数(時間)でレビューしてもらうと、エンジニアのスキル差によって工数の感覚が違ってくる可能性があるためです。 例えばジュニアなエンジニアが見積もった工数とシニアなエンジニアが見積もった工数では違いが出るのは当然ですよね。 その場合、その二人のエンジニアでタスクの工数について議論をしても有意義なものになりにくいというものです。

スケジュールとは

見積もりの項でも触れましたが、スケジュールとはコミットメントを達成するためにどれだけの期間がかかるかを可視化したものです。 そしてスケジュールを作成するために見積もりを使います。つまり見積もりがあれば、スケジュールを作成するのは簡単です。 むしろスケジュールに関しては作成するよりも、管理するほうが重要でかつ難しいと考えています。

ツール

以降で紹介するスケジュール作成・管理にはMacで使えるOmniPlan*4と呼ばれるガントチャートツールを使います。 OmniPlanを使っているのは、以下の様なスケジュール管理には必須な機能が揃っているからです。

  • リソース: 個々人の稼働率を設定できる
  • カレンダー: プロジェクトの休日、個人の休日、時間外稼働を設定できる
  • ガントチャート: 平準化(自動配置)、基準承認(変更管理)、工数と工期の区別、マイルストーンの設定、遅延タスクの分割

ガントチャートツールには他にもいくつかありますが*5、僕が知る限りのツールはすべて機能不足に感じます。 ちなみにガントチャート以外の方法としてバーンダウンチャートも有名です。 僕はガントチャートのほうが好みですが、スケジュールを正しく作成・管理できるなら好きな方法を採用すればよいと思います。

スケジュール作成

見積もりを元に、タスクと工数を入力していきスケジュール(工期)を作成します。 OmniPlanを使えばタスクと工数を入力して、担当者をアサインしたあとに、平準化(自動配置)という機能を使えばいい感じにガントチャートを作ってくれます。 手動でタスクの配置を設定する必要はありません。

スケジュールを作成する時は以下の点に注します。

  • 非稼動時間を設定する
    • 事前にわかっている非稼動時間はあらかじめ設定しておきます
    • たとえば定例会議、休日、祝日、有給などです
  • 稼働率を設定する
    • 会社に来て対象のプロジェクトに使える割合を設定します
    • 他の人から仕事の相談をされたり、PRレビューをしたり、割り込み作業が発生したりするので個人的には70%〜75%を設定しています
    • 他のプロジェクトを掛け持ちしている場合は40%などになるかもしれません

スケジュールの振れ幅と確率の算出

スケジュールを作成する上でもっとも重要なのが、スケジュールの振れ幅と確率を算出することです。 スケジュールの振れ幅とは最短期間と最長期間との幅のことを表し、確率とはその幅のなかで開発が終了する確率分布を表します。

ありがちなスケジュールは「X月Y日に開発が終了する」というシングルポイントスケジュールです。 これは言い換えると「X月Y日に開発が終了する確率は100%」と言っているのと同じです。そんなことはまずありえません。 なので本来なら「M月N日〜X月Y日の間に開発が終了する確率は75%です」や「Q月R日までに開発が終了する確率は50%です」などのはずです。

そこで開発がほぼ確実(90%〜95%)に終了するであろう期間を最短期間と最長期間として設定します。 私は見積もりを元に作成したスケジュールを最短期間とし、最長期間をそれの1.5倍としています。 確率は50%で開発が終了する日を[最短期間 + (最長期間 - 最短期間) * 0.4]、75%で開発が終了する期間を[50%日 + (最長期間 - 最短期間) * 0.12]としています。 この振れ幅と確率の計算式についてはソフトウェア見積り 人月の暗黙知を解き明かすを参照してください*6

スケジュール管理

スケジュールは一度作成するだけでは全く意味がありません。開発が進むに連れて、スケジュールも更新して、予実管理をしていく必要があります。 私はOmniPlanを使ったスケジュール管理では2つのイテレーションを回しています。

  • 毎日の更新
    • タスクの進捗を記入します
      • 進捗は0%(未着手)、25%(着手)、50%(動くものができた)、75%(レビューに出した)、100%(完了)という粒度で行っています
    • 遅延しているタスクをすべて現在日以降に再配置します
      • OmniPlanの遅延タスクの分割機能を使えば自動で可能です
  • 週1回の更新
    • 残りの期間をもとに振れ幅と確率を計算しなおします
    • 先週(先々週)のスケジュールと比較してどれだけズレが発生しているか確認します
      • 定常的に遅れてきているようであれば見積もりから全体を見直す必要があるかもしれません
      • 突発的に遅れた場合は、稼働を調整したり、タスクの組み換えなどで対応する必要があるかもしれません

このようなイテレーションで予実管理を行い、スケジュールが生きた状態を保ち続けることが大事です。

おわりに

以上、私が行っている開発の見積もりとスケジュール管理の紹介でした。 開発の規模、チームの規模、事業のフェーズ、作るものの種類などによって、この方法をそのまま使えるわけではないと思います。 しかし、これを読んでいただいた方にとって何かしら参考にできるところがあれば幸いです。

*1:例えば受託開発でよく似たシステムを何回も開発している場合は過去の実績から似たタスクを探しやすいかもしれません

*2:プランニングポーカーで使われるポイントと同じ意味

*3:フィボナッチ数列

*4:WindowsユーザにはMS Projectが良いと思います

*5:GanttProject, brabio, GANTTplanner, gantter, Instagantt

*6:この本には振れ幅と確率については見積もりの段階で行うと書いてあります。しかし、チームのメンバーが同じ稼働率、同じスキルレベルの場合はスケジュール作成時に振れ幅と確率を計算するほうが簡単です。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/