CakePHP の発想から、EXDoc, DBUnit のひな型を作ってきたのですが、そうか、UIDD に則ればガントチャートのような UI は冗長なのですね。もっと MVC 的に Logic 部分(Controller部分) を分離させても良いわけです。
ガントチャート – Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%AC%E3%83%B3%E3%83%88%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88
ブレークダウンした WBS からスケジュールに落とす時は、ガントチャートを使うことが多いのですが、本来は PERT を考慮しないと駄目です…と言いますか、最近のガントチャートツールは、このあたりを押さえている(と思う)ので問題ははないんのですが、MS Project をはじめとして、この手のツールは、
- 高価すぎる
- チャートを作るのが非常に手間
- 変化に弱すぎる
のが問題です。高価すぎるところは、Excel でスケジューラーを作ったり、フリーのものを活用したりすれば良いのですが、2番目と3番目が致命的です。
WBS でもストリーカードでも良いのですが、それぞれを「タスク」あるいは「ワーク」という単位に落とし込んだ後、それをどの順番で行うのか、を組み立てるのに非常に手間が掛かります。実は、この手間は、
- タスクの連結を、タスクを出した後に行ってしまう。
- タスクの連結を知っているのは、開発者のみだったりする。
という理由から来ています。タスク同士の連結は、PERT 図を書いている方は分かると思いますが、前のタスクがあり後ろのタスクがあるという「前提条件」が必ずあります。これは工場で使われるプロダクトの「製造工程」と同じことで、前の製品/部品ができていなければ、後ろの工程が進みません。そのあたりをタスクを動かしても、単純に待ちが発生してしまうだけです。
で、タスクに落とすのは誰がやるかというと、マネージャがやることが多いのです。なおで、ブレークダウンしたタスクをさて、タスクの連結にするときに止まってしまいます。あるいは、シーケンシャルに並べることによって全体の工数を算出します。
この工数の算出の仕方は、「やや悪い」程度で決して「悪く」はないのですが、「良い」わけでもありません。
前後のタスクにより制約が発生しているのであれば、その制約を取り除くことで効率化をするという「制約理論」の手法を導入することで、これを「良い」方向に動かすことができます。
CCPM やクリティカルチェーン、工場の製造工程の場合には、このタスクの連結を実施者自らが考えます。と言いますか、工程のラインをどのように組み合わせるのかという専門家がデザインをします(勿論、マネージャが、工程の専門家になるのがベストなのですが、マネージャの役割として「マネジメントとしての管理者」と「プロジェクトの計画者」と「実施時の監督官」という 3 重の責務を負わせるのは難しいと思われます)。
いわゆる、「建築家」と「現場監督」の違いがある、と覚えておけばよいでしょう。
なので、現場を知る人がこのタスクの連結を知っていますという矛盾が発生しています。アジャイル開発(XP やスクラムなど)は、この責務を意図的に混沌とさせることで回避する方法です。
と、前置きが長くなりすぎましたが…ええと、話を最初に戻すと、ガントチャートを作るのに何も豊富な GUI は必要ないのです。
- タスク自身、タスク間のデータを保持する。
- タスク間の連結が変更しやすい。
- スケジューリングを自動化する。
- 最後に GUI で確認する。
というポイントを抑えておけば、ガントチャートが作成できます。と言いますか、最初の2点を抑えておけば、ガントチャートを作ることは可能なんですね。
C# や VB では、言語的な制約が多いので、いずれ F# に直す予定ですが、ひとまず UIDD 的にコマンドラインで書いてみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // タスクを設定 PlanA.Tasks.Add( new Task( "001" , "最初のタスク" , 2 days )); PlanA.Tasks.Add( new Task( "002" , "次のタスク" , 3 days )); PlanA.Tasks.Add( new Task( "003" , "並列タスク" , 2 days )); PlanA.Tasks.Add( new Task( "004" , "最後のタスク" , 3 days )); // 連携 PlanA.Tasks[ "001" ].Adter = PlanA.Tasks[ "002" ]; PlanA.Tasks[ "001" ].Adter = PlanA.Tasks[ "003" ]; PlanA.Tasks[ "002" ].Adter = PlanA.Tasks[ "004" ]; PlanA.Tasks[ "003" ].Adter = PlanA.Tasks[ "004" ]; // マイルストーンを設定 PlanA.Task[ "001" ].MileStone = #2011-04-01# ; // XML 形式で出力 PlanA.XML ; // GUI で出力 PlanA.GUI ; // 同じタスクで Plan B を作成する PlanB.Tasks = PlanA.Tasks ; // 連携を変更 PlanB.Tasks[ "001" ].Adter = PlanB.Tasks[ "002" ]; PlanB.Tasks[ "002" ].Adter = PlanB.Tasks[ "003" ]; PlanB.Tasks[ "003" ].Adter = PlanB.Tasks[ "004" ]; // クリティカルチェーンを取得 PlanB.CriticalChain ; // クリティカルチェーンタスクを取得 PlanB.CriticalChain.Tasks |
これは静的コンパイルをしないといけないので、F# のインタプリターを使うか、PowerShell を使います。
ま、これの実装は後ほど。