2004-04-12

近況

2hop-sibling-chained な上司から肯定的説得についてのレクチャーを受ける. 主旨はおおよそ以下のとおり: 働いていると示すことに注力せよ. 具体的には "計画/実行/記録/修正" の枠組みに従い反復的に行動しなさいという話. ソフトウェア・プロセスの意義は計画の精度と信憑性を高めることにある. 彼は語気を強める. しかし私達のまわりでは誰ひとりそんなことををしていませんよ. そう反撃する同僚も私達の誰かが正しいと思っている様子はなかった. レクチャーどおりにたてたはずの工程概算を前に, 私はやはり途方にくれた.

依存関係の可視化

並列化が工程管理におけるもう一つの基本だと上司は言う. 依存関係を明示し, 最小化すること. 白馬の王子がわたしを救えるように. Microsoft Project はそんな並列化, pipelining を最大化するべく設計されている. 全てが順調に進むことを仮定しているこのソフトウェアは表の更新が面倒なので, 私は Excel や OpenOffice の Calc を使っている. ただ, 表を眺めていても並列化可能性はわからない. そこで graphviz を使い依存関係を可視化してみた. CSV で出力した表を適当なスクリプトで graphviz の dot 形式に変換する.

たとえばこれはあるあたたかな朝のこと. 朝食と洗濯とメールチェックとふとんあげは (十分な資源があれば) 並列化可能であることが一目でわかる. みだしなみの整理とお茶淹れも. 大家族で迎える一日の慌しい始まりを想像しよう. 同様に, 凄腕の火消しが投入され次々に作業の片付いていくプロジェクトを想像しよう.

そんな日々に夢を馳せよう.

graphviz のこまかい話

graphvis で絵を出力するには, 付属の dot というコマンドラインツールを使うのが一番簡単. 引数にグラフを記述した dot ファイルを渡す: "dot -Tpng -oat-morning.png at-morning.dot".

dot 形式については dot user's guide(PDF) を参照のこと. 末尾に朝の例を示した. 以下 tips:

  1. 各ノードのラベル("wakeup"のような文字列)には, 何も指定しないとノードの ID が使われる. ただし ID は文法上の制約で使える文字が限られているため, ラベルの指定は "label" 指示子で明示的に行った方がいい. ID にはノードの通し番号(スクリプトで自動的に与える)を使うのが無難.
  2. 複数のノードを一つにまとめる cluster という機能がある. これを作業項目のグループを現すのに使うことができる. その際にはグループをもたない単一のノードにも自分だけを含む cluster をつくること. そうしないと意図どおりのレイアウトがされない.
  3. 作業項目の所要時間も可視化したい. 私は height 属性を用いた. height のような数値属性は適当にスケーリングできるようスクリプトに細工をしておくと便利. グラフの大きさによって, その倍率を適当に調整すると見栄えがいい.
  4. ラベルに日本語は使えない.

digraph G {

size="5,5";

subgraph cluster_wakeup {

0[label="wakeup",shape=box,height=0.652174,style=filled,fillcolor=lightgray];

}

subgraph cluster_make_bed {

1[label="make-bed",shape=box,height=0.217391,style=filled,fillcolor=lightgray];

1 -> 0;

}

subgraph cluster_breakfast {

2[label="breakfast/make",shape=box,height=0.652174,style=filled,fillcolor=lightgray];

2 -> 0;

3[label="breakfast/eat",shape=box,height=0.434783,style=filled,fillcolor=lightgray];

3 -> 2;

4[label="breakfast/clean",shape=box,height=0.217391,style=filled,fillcolor=lightgray];

4 -> 3;

}

subgraph cluster_washing {

5[label="washing/setup",shape=box,height=0.434783,style=filled,fillcolor=lightgray];

5 -> 0;

6[label="washing/hang",shape=box,height=0.652174,style=filled,fillcolor=lightgray];

6 -> 5;

}

subgraph cluster_fix_appearance {

7[label="fix-appearance",shape=box,height=0.652174,style=filled,fillcolor=lightgray];

7 -> 4;

7 -> 6;

}

subgraph cluster_tea {

8[label="tea/setup",shape=box,height=0.217391,style=filled,fillcolor=lightgray];

8 -> 0;

9[label="tea/take",shape=box,height=0.217391,style=filled,fillcolor=lightgray];

9 -> 4;

9 -> 6;

9 -> 7;

9 -> 8;

}

subgraph cluster_check_e_mail {

10[label="check-e-mail",shape=box,height=0.652174,style=filled,fillcolor=lightgray];

10 -> 0;

}

}