2009年8月26日水曜日

Drools 導入

以前から気になっていた Droolsというルールエンジンの入門サイトを見つけたのでやってみた。以下にレポートする。

IDE としては Eclipse を用いる。また Drools と Eclipse ともに最新版(Drools → 5.0.1、Eclipse → 3.5)を使ってみることにした。

まずこのページを見ながら Eclipse 3.4 Workbench をインストール。Eclipse のバージョンは 3.4 を用いるよう指示があるが、上記のとおり、敢えて3.5を入れてみる。インストールに続いてサンプルの実行までやってみる。ここまで特に問題なし。

次に、Drools 5用の値引きのサンプル(Drools 5用)をやってみる。コピペはしないで1文ずつ書いていきながら、Java コード上でのDroolsオブジェクトの扱いとルールファイルの記述を観察。

で、コンパイルして実行してみたところ、プログラム自体はちゃんと動いているようだが、Working Memory ビュー が期待通りに動かない。Variable ビューで ksession変数を選択すると、Working Memory ビューにトップレベルのツリー要素が表示されるが、展開しようとするとビューから消えてしまう。どうもVariable ビュー上で ksession変数 がフォーカスを失ったタイミングでWorking Memory ビューから消えてしまうらしい。Eclipse 3.4 と 3.5の違いだと思うが、大した問題じゃないしそのうち Eclipse3.5対応版が出るだろうし、まあ良しとする。

もう少しサンプルを動かしてみたかったので、同サイトにあった旅費計算のサンプル最大身長選択のサンプルもやってみるが、もともとDrools 4 のサンプルという事で、記事どおりのコードだと警告が出た。そこで、先にやったDrools 5用のサンプルを参考にしてRuleBase を KnowledgeBase に替えてみると、全部解消した。動作確認も OK。

導入としてはこんなものか。次にいじるときは、今ちょうどファイナンシャルプランナーの勉強をしているところなので、現実の法律に近いルールを書いてみたい。

2009年8月20日木曜日

Erlang で待ち行列

Erlang の勉強のために情報処理技術者試験なんかでお馴染みの待ち行列理論を実験してみる。

待ち行列理論によると、あるサービスへの要求が単位時間に平均λ回発生(ポアソン分布で)し、またそのサービスが単位時間に平均μ個の要求を処理するとすると、待ち時間は W =ρ / (1 - ρ) * Ta(ここでρ=λ / μ, Ta = 1 / μ)で得られると言う。

例えば1時間に平均 7.5人診る歯医者に患者が毎時平均 6人来診するとした場合、
ρ = 6 / 7.5 = 0.8,
Ta = 1 / μ = 8分,
W = 0.8 / (1 - 0.8) * 8分 = 32分
となり、平均32分の待ち時間が予想される。

これと同じ条件でErlang でシミュレートして、理論を検証してみようと思う。ただし時間は早送りでやってみる。すなわち1時間=60分を6秒に縮尺して試行する。

また、せっかくの Erlang なので、プロセスを活用してみたい。
以下の3つのプロセスでやってみる。
  • customerプロセス:ポアソン分布に従い、繰り返して要求を出す
  • serviceプロセス:一定の処理時間で順番に一個ずつ要求を処理する
  • observer プロセス:要求処理が開始される度に、その要求の待機時間を集計する
customerプロセスは以下のようなコード。要求発生回数をポアソン分布に従わせるかわりに、時間間隔を指数分布に従わせる。
-module(customer).
-export([start_customer/1,customer_loop/1]).

%customer のプロセスを生成し、初期化メッセージを送る
start_customer(Service) ->
  C = spawn(customer, customer_loop, [100]),
  C! {start, Service},
  C.

% customer のプロセス.
% startメッセージで与えられたPid に指数分布に従う時間間隔で
% メッセージを送り続ける
customer_loop(Time) ->
  receive
    stop ->
      io:format("stopped~n",[]);

    {start, Service} ->
      {A1,A2,A3} = now(),
      random:seed(A1, A2, A3),
      put(service, Service),
      customer_loop(100)

  after 
    Time ->
    get(service)! {enter},
      customer_loop(round(exp_dist_rand() * 100))
  end.

% 0~120の範囲で0.2刻みの指数分布に従う数を、ランダムに発生させる。
exp_dist_rand() -> rand_sub(1, random:uniform()) / 5.

rand_sub(6000, _)   -> 6000;
rand_sub(S, Random) -> select(S, 1 - math:exp(-6 * S / 300), Random).

select(S, V, Random) when V > Random -> S - 1;
select(S, V, Random) when V == Random-> S;
select(S, _, Random) -> rand_sub(S + 1, Random).
serviceプロセスは以下のようなコード。(定期的にキューを監視しているのが、何だか格好悪い。うまくやれば改善できそう。)
-module(service).
-export([start_service/1, service_loop/0]).

% service プロセスの生成
start_service(O) ->
  S = spawn(service, service_loop, []),
  S! {init, O},
  S.

% service プロセス
% customer プロセスからのリクエストを1個0.8秒で処理している真似をする
% 窓口一個の待ち行列。
service_loop() ->
  receive
  % 停止
  stop->io:format("stopped~n"), 0;

  % 初期化
  {init, O}->
    put(queue, queue:new()),
    put(observer, O),
    service_loop();

  % customer プロセスからのリクエスト
  {enter}->
    put(queue, queue:in(now(), get(queue))),
    service_loop();

  % リクエスト処理後の始末。次のリクエスト処理を許可する。
  {after_processed}->
    erase(in_service),
    {{value, _}, Q2} = queue:out(get(queue)),
    put(queue, Q2),
    service_loop()

  % 5ms 間隔でキューを見て、リクエストがあれば処理
  after
    5->
    In_Service = get(in_service),
    if 
      true /= In_Service -> do_service();
      true->0
    end,
    service_loop()
 end.

% 0.8 秒かかる処理のシミュレーション
% 開始時に待ち時間をobserver プロセスに送信する
do_service()->
  Queue = get(queue),
  Is_Empty = queue:is_empty(Queue),
  if
    not Is_Empty ->
      put(in_service, true),

      {value, Start} = queue:peek(Queue),

      Diff = timer:now_diff(now(), Start),
      get(observer)! {done, Diff, queue:len(Queue)},

      erlang:send_after(800, self(), {after_processed});
    true -> 0
  end.

observerプロセスは以下のようなコード。service プロセスは要求の処理を始めるたびに、その要求がキューで待たされた時間を送ってくるので、その都度平均待ち時間を更新しコンソールに表示する。
-module(observer).
-export([start_observer/0, observer_loop/0]).

% シミュレーション観測者のプロセスを開始する
start_observer() ->
  O = spawn(observer, observer_loop, []),
  O! init,
  O.

% service から待ち時間の報告を受けて集計する
observer_loop() ->
  receive
    init->
      put(request_count, 0), 
      put(average_waiting_time, 0),
      observer_loop();
    stop->
      io:format("stopped~n"),
      0;
    {done, Time, Len}->
      {RC, AWT} = get_awt(Time),
      io:format("C=~p; A=~p; T=~p; L=~p~n", 
      [RC, round(AWT/100)/1000, round(Time/100)/1000, Len]),
      observer_loop()
  end.

% 各リクエストの処理待ち時間で、プロセス辞書を更新する
get_awt(Time)->
  RC = get(request_count),
  AWT = get(average_waiting_time),
  New_AWT = (AWT * RC + Time) / (RC + 1),
  put(average_waiting_time, New_AWT),
  put(request_count, RC + 1),
  {RC + 1, New_AWT}.
実行は以下のように始める。
86> O = observer:start_observer().
<0.201.0>
87> S = service:start_service(O).
<0.203.0>
88> C = customer:start_customer(S).
<0.205.0>
89> C=1; A=0.16; T=0.16; L=1
89> C=2; A=0.39; T=0.62; L=1
C が要求の個数、A が平均待ち時間、T が最後の要求の待ち時間、L は待ち行列の長さ。理論どおりだと A の値が 32 に近づく予想だが、見た感じ上手くいっているらしい。(まあなんだかんだ時間かかったが。)
89> C=1000; A=31.534; T=36.56; L=4
89> C=1001; A=31.537; T=34.37; L=3
89> C=1002; A=31.545; T=40.0; L=4
89> C=1003; A=31.55; T=35.93; L=5
89> C=1004; A=31.54; T=21.4; L=5
89> C=1005; A=31.537; T=28.6; L=7
89> C=1006; A=31.532; T=27.19; L=7
89> C=1007; A=31.535; T=33.75; L=7
89> C=1008; A=31.544; T=40.94; L=6
89> C=1009; A=31.553; T=40.16; L=7
89> C=1010; A=31.567; T=46.56; L=6
まだまだ下手糞だが、だんだん Erlang --- と言うより並列処理プログラムが分かってきた気がする。昔、よく言われていたオブジェクト指向の説明で、現実世界の模倣なんて言い方があったけど、Erlang のプロセスの方がよほどそれっぽいところがある。分析レベルのオブジェクト指向モデルでは、結構いろんなモノがUML風に言うとアクティブオブジェクトだったりするけど、そういった要素はErlang 的な並列処理アプローチのほうがよほど直接的に実装できるはず。

やはり、職業プログラマとしてヒントやら気づきやらを得ようとして Erlang をいじってみるとしたら、クラスを書いてみるとか既存の関数型言語の練習問題的なものを書くような作業は大して意味がなさそう。そうではなく、いつもの言語で普段やってるいろんな事を、プロセスを使って書いてみたり、或いはプロセスでなければできないことを見つけてみるのが、たぶん一番有益なんだろう。

あと、まだ試していないが Scala にも同じような機能があったはず。こっちも面白そう。

2009年8月13日木曜日

Business Rule の調査を始めてみる

OCEB で参考資料として指定されている Business Rule の資料はネットで無料で見られる資料がなく、高そうな洋書ばかり。ちょっと面倒くさい。

ちなみに、こんなのが記載されている。
いちいち、これら全部を取り寄せても費用対効果が芳しくないので、極力ネットで調べることにする。もう Wikipedia でも何でも良い。

早速 Wikipedia の Business Rule を見ると、「Business Rules Group」 という団体が出している資料へのリンクがある。どういう団体かと思ってメンバーを見てみると、上述の 3冊の参考文献のうち 2冊の著者の Ron Ross と言う名前がある。とすると Business Rules Group が出している Business Rule 関連の論文は、OCEB 試験の資料として役立ちそうな気配がしてくる。

関係ないが、メンバーの中に David Hay という名前もある。いわずと知れた「Data Model Patterns: Conventions of Thought」の著者だが、ちょっと意外なところで意外な名前を見た気がする。まあでも Business Rule と Data Model は、意味論と統語論のような表裏一体のもと考えられないでもなく、理論家がこの両面からのアプローチでモデルをさらに十全したくなるなるのもなんとなく分かる。

さらに調べてみると、今は OMG の仕様になっている SBVR も BMMも、もともとはこのBusiness Rules Group の成果物だったらしい。やはり OMG と親和性の高い団体なのだろう。

Business Rule を調べる上で、以下の資料をとりあえずの足がかりとすることにした。
Business Rule@wikipedia
Business Rules Approach@wikipedia
Defining Business Rules ~ What Are They Really?
The Business Rules Manifesto

あと試験範囲には含まれていないが SBVR もチェックしておこう。どうせ Technical Intermediate では指定されているし。

2009年8月10日月曜日

まとめ読み:Agile関連記事 8

レトロスペクティブの変化を曲げない2008年9月26日

元記事はここ

せっかくのレトロスペクティブで得られた改善案も、実行しない事にはレトロスペクティブ自体が非効率の元になるというもっともな話だが、こういう記事が出ると言う事は、やはり無駄になっているケースが実際にも多いのだろうか。何となく気分だけスッキリして終わりみたいな。

黒澤明の「生きる」という映画で、末期ガンを患いながら難工事を完成して死んだ主人公の葬式で、集まった同僚達が己を省みて大いに反省し、明日からは主人公を見習って変わっていこうと盛り上がるが、一夜明けると何事もなかったように以前と同様のお役所仕事が続いていくという描写がある。まあつまり、そういう事なんだろう。

当たり前の話だが、レトロスペクティブと言っても本で読んだ直後から上手くいくような即効的なものじゃなくて、実践の繰り返しの中で練度を高めて、なおかつ記事で紹介されているような他者の経験もその都度取り込んで、初めて期待する効用が得られるのだろうと思う。ほんとに当たり前だが。

ちなみに PMBOK では Lessons Learned(教訓)の扱いが定められていて、プロジェクトの進行に伴って、随時「組織のプロセス資産」に含まれる「教訓知識ベース」に蓄えられて、後のプロジェクトの意思決定のための判断材料として使うようになっている。

== 要チェック ==
Force Field 分析:T字チャートで推進力と抵抗力を可視化して力のバランスとして捉える要因分析手法。

2009年8月9日日曜日

Mozart インストール

最近、論理型言語を触っていないので久しぶりに Prolog でパズルでも解いてみようと思った。ただ、ちょっとググってみると Prolog から派生したもので Oz という言語があるらしいので、フリー実装の Mozart と言うものをインストールしてみた。

OS はWindows XP SP3。Mozart のバージョンは1.4。Vistaの人は一個古いバージョンじゃないと対応されていない。Unix系の環境は一通りあり。

間抜けな事に、チュートリアルをチラ見してるうちに何故だか Linux 環境のものだと勘違いして andLinux をインストールしてしまったが、これは不要だった。Windows でOK。まあでもいずれインストールしようと思っていたので、まあ良し。

インストール後に作成されたメニューから最初に起動しようとしたとき、emacs が無いから起動できないと言われたが、emacsをインストールしたらすんなり立ち上がった(GNU emacs 20.7.1)。下の画面は Hello World の実行結果。


これからなるべく時間見つけて少しずつ覚えていきたい。

あと論理型言語で Mercury というやつに前からずっと興味があって、今までにも何度か試したりしたが、なんだかイマイチ品質が悪くてその都度気持ちが萎えて中断していた。だけど、さっき本家のサイトを見てみると、地味ながらずっと活動を続けているようなので、機会をみてまた試してみようと思う。

本業以外の言語では、本当は関数型より論理型の方に興味があるんだけど、世間的には何だかいつまで経っても盛り上がらない。何が不人気なんだろう?

Erlang 練習:クラス化

メインの言語がオブジェクト指向言語中心だから、データと手続きが一体になっていないと何となく収まりが悪い気分になるが、module をパラメータ化すればクラスっぽく定義する事もできるらしい。

-module(rational, [Numer, Denom]).
-compile(export_all).

numer()->Numer.
denom()->Denom.

new(Numer,Denom)->
  Gcd=integer:gcd(Numer, Denom),
  instance(round(Numer/Gcd), round(Denom/Gcd)).

add(R)->new(numer()*R:denom() + R:numer()*denom(), denom()*R:denom()).
minus(R)->new(numer()*R:denom() - R:numer()*denom(), denom()*R:denom()).
multiply(R)->new(numer()*R:numer(), denom()*R:denom()).
divide(R)->new(numer()*R:denom(), denom()*R:numer()).

to_string()->integer_to_list(numer()) ++ "/" ++ integer_to_list(denom()).
to_float()->numer()/denom().

試しに上のような簡易実数クラスを書いて実行してみた(integer:gcd()は別のモジュールで定義したGCD関数。同じモジュールで定義するとコンストラクタから呼べなかった)。

17> R_1_2=rational:new(1,2).
{rational,1,2}
18> R_1_3=rational:new(1,3).
{rational,1,3}
19> R_1_2:add(R_1_3).
{rational,5,6}
20> R_1_2:minus(R_1_3).
{rational,1,6}
21> R_1_2:multiply(R_1_3).
{rational,1,6}
22> R_1_2:divide(R_1_3).
{rational,3,2}
23> (R_1_2:minus(rational:new(11,13))):to_string().
"-9/26"
24> (R_1_2:divide(rational:new(100,1))):to_float().
0.005

まあこんな感じか。コンストラクタに小数点数が来たときとか分母に0が来たときとかのちゃんとした実装はとりあえず省略。このPDFを見ると、継承のやりかたなんかも書いてある。割と簡単そう。

ただ、せっかくErlangをやってるのに、何が悲しくてこんなコード書いてるのかと、釈然としない感じも残る。本当は、オブジェクトとして考えるのを一旦止めて、改めてプロセスとして捉えなおすようなパラダイムシフトが必要な気がしないでもないが、まあもう少し勉強しないとダメだな。

Erlang 復習 2

Erlang ディレクトリのlib 下の、各ライブラリのディレクトリ配下に、いろんなライブラリのドキュメントがあるのに今さっき気付いた。lists モジュールで見つけた zipwith と sum を使って消費者物価指数を求めてみる。
1993年1994年
価格(円)数量(ml)価格(円)数量(ml)
清酒89.211371389.8812986
焼酎65.95503063.875799
ビール54154990534.7961770
輸入ウィスキー414.26185374.04166
国産ウィスキー248.191476238.751651
ぶどう酒145.21773127.41024
上表のデータは『データ分析 はじめの一歩』に載っていた古い総務庁の家計調査のデータを拝借したもの。ここで 1993 年のデータを基準とし94年の消費者物価指数(CPI)を求めてみる。
-module(t2).
-compile(export_all).

%% cpi(Base, Target, Weight)->CPI
%% 消費者物価指数を求める
%%
%% Base = 基準期間の物価のリスト
%% Target = 算出対象期間の物価のリスト
%% Weight = 数量。ラスパイレスなら基準期間、パーシェなら対象期間
%% CPI 計算結果
cpi(Base, Target, Weight)->
  mul_each_and_sum(Target, Weight)/mul_each_and_sum(Base, Weight) * 100.

%% 二つの同要素数リストの各要素を掛け合わせ、合計を返す
mul_each_and_sum(List1, List2)->
  lists:sum(lists:zipwith(fun(X,Y)->X*Y end, List1, List2)).
上のようなコードを書いて以下のように実行した。5>に続く出力がラスパイレス型、6>に続く出力がパーシェ型のCPI。教科書どおりの値が得られた。
1> Pk0=[89.21, 65.95, 541, 414.26, 248.19, 145.21].
[89.21,65.95,541,414.26,248.19,145.21]
2> Qk0=[13713, 5030, 54990, 185, 1476, 773].
[13713,5030,54990,185,1476,773]
3> Pkt=[89.88, 63.87, 534.79, 374.04, 238.75, 127.4].
[89.88,63.87,534.79,374.04,238.75,127.4]
4> Qkt=[12986, 5799, 61770, 166, 1651, 1024].
[12986,5799,61770,166,1651,1024]
5> t2:cpi(Pk0, Pkt, Qk0).
98.81385620633323
6> t2:cpi(Pk0, Pkt, Qkt).
98.79880915150264

2009年8月8日土曜日

Erlang 復習

せっかく勉強し始めたErlangを忘れてしまわないうちに復習しておく。 お題は「M個のN面体のサイコロを振って1が出たものの個数を調べるのを1試行とする。これをP試行繰り返して個数と回数の関係を集計し確率を求める。」というのにしてみた。 先日NHKで放送していた米国のサブプライムローン破綻の特集で、このお題を応用で債権リスクを見切って商品化しているというのをやっていたのが、ちょっと面白かった。
-module(t1).
-compile(export_all).

%% N面体のサイコロを振る関数を返す
dice_func(N) -> fun()->trunc(random:uniform() * N) + 1 end.

%% M個のサイコロ D をばら撒いて1が出た個数を数える
scatter(0, _) -> 0;
scatter(M, D) -> inc_when_1(D(), scatter(M-1, D)).

%% X が1のとき Y をインクリメント
inc_when_1(X, Y) ->if X==1 -> Y+1; true->Y end.

%% M個のサイコロDでP回試行。1の個数ごとに回数を集計
exec(P, M, D)->exec(P, P, M, D).
exec(P, 0, _, _)->lists:duplicate(P + 1, 0);
exec(P, I, M, D)->increment(exec(P, I-1, M, D), scatter(M, D)).

%% リスト中の指定位置の整数をインクリメントする
increment([H|T], 0)->[H+1|T];
increment([H|T], P)->[H|increment(T,P-1)].

%% 実行して個数と確率を表示する
main(N, M, P)->
 Repeat = 100,
 Y=[X/(P*Repeat)||X<-sub(N, M, Repeat, P)],
 display(Y).

sub(_, _, 0, P)->lists:duplicate(P + 1, 0);
sub(N, M, I, P)->
 lists:zipwith(fun(X,Y)->X+Y end,
  sub(N, M, I-1, P), 
  exec(P, M, dice_func(N))).

display([])->io:format("end~n");
display([H|T])->io:format("~p~n",[H]), display(T).
3個の6面体サイコロを3回ばら撒く設定でやってみると、以下のような結果が出た。もちろん実行の都度値は変わるがだいたい似たような結果になる。
342> t1:main(6, 3, 3).
0.5466666666666666
0.36666666666666664
0.08
0.006666666666666667
end
筆算によると以下のような値なので、だいたいあってそう。
1が出た個数確率
0個0.5787
1個0.3472
2個0.0694
3個0.0046

まとめ読み:Agile関連記事 7

Martin Fowler氏:SOAはアジャイルアプローチで実行可能か? 2008年9月23日

Martin Fowler の bliki のエントリ、「EvolutionarySOA」についての記事。

前提として知っておくべき事 ⇒ Martin Fowlerが、古い論文 "IsDesignDead" で設計における「事前の計画性」と「必要に応じた進化」を対立軸として提示し、当時花形だった XP では後者の価値ばかりが喧伝されていたが、前者の価値もなだまだ失われていないと主張した事。

bliki での Fowler の提案 ⇒ SOA においては公開したインターフェイスを気安く変更できない事情から、一見 Planned が適しているように思われるが、WWW に見られるように Evolutionary にも大規模な成功例がある。そこで Fowlerは、Planned と Evolutionary の折衷案として漸次的なSOA開発を推奨する(原文ではGuerilla SOA)。(ここで言う漸次的はIncremental & Iterative のIncremental の方だろう。つまり"alter" ではなく"add onto"と言う事になるか。)

※ 供給側の都合ではなく需要側の都合で、SOA のインターフェイスを変化させていくと言うアイデアは 「Consumer-Driven Contracts」という論文から。


レゴはもはや子供たちだけのものではない 2008年9月25日

複数プロジェクトの作業実績/バグ管理にレゴを使うという記事。まあ楽しそうなんだが、外部のステークホルダへの報告だのその他いろいろの都合で、結局、PCにもTracやなにかで同じ内容を記録することになりそう。そうなるとまた情報の二重管理になりそうな・・・。

あと積み上げられたレゴをうっかりひっくり返してしまったら、作り直すのが面倒くさそうとか、いろいろ余計な心配をしてしまう。

この記事から、一応読んでおくべきアジャイルプロジェクトの進捗管理に関する他サイトの記事へのリンクが張ってある。
Information Radiators(情報発信)
Informative workspace(情報を提供する作業場所)
Big Visible Charts

上記リンクで紹介されている関連 agile ツール
  • ホワイトボード
  • フリップチャート
  • バーンダウンチャート
  • ビルドステータスランプ

2009年8月7日金曜日

経済学検定 B+

7月に受けた経済学検定 の結果が郵送されてきた。結果は B+ で「経済学部卒業生レベル」というが、ただし 108名中 33番と言う事で上から 30%の位置という事になり、B+ は 15.1%~ 30% だから、ほとんど B に近いギリギリの B+ と言う事になる。まあ最初だからこんなもんか。

勉強し始めた動機は、まず、経済に無知なのは大人として普通にまずいだろうってのと、逆に理解力が増えれば世の中の出来事をもっと面白がれそうだという事。

次に、システム開発の対象のうち、割と大きな領域が経済活動の一環だという事を想起すると、本業でもスキルの裏づけというか基礎体力的な意味で役に立ちそうだったから。特に、プロジェクト序盤のフェーズの業務分析の作業比率が高いあたりで、各ドメイン固有知識の基盤として効果が期待できそうな気がした。

まあ当然だが、実際にやってみて気付く事も多い。思った以上に「現実世界の経済とは違うが、とにかくこの条件で考えてみる」とか「他の側面はさしあたり無視して以降の論を進める」と言った縛りが多くて、「敢えてわざわざ作ってます感」が思いのほか強い。

だからといって「そんな事だから現実社会で経済学は通用しないんだ」なんて思うわけじゃなくて、むしろ、その人工性というか作為性がソフトウェア開発でのモデリングと通じるところがあり、これはこれで面白い。もちろん、ソフトウェアのモデリングとは多くの点で異なるが、むしろ違うからこそ教わる事が多かったりする(これは Java プログラマが関数型言語の学習から得るものが大きいのとも似た話だと思う)。経済学をモデルを操る学問と意識してみると、オブジェクト指向開発者でもかなり楽しく勉強できる。

次は A ランク(15%より上)、その次は A+ ランク(5%より上)を狙っていこうと思う。
(その上にはさらに Sランク(1%より上)があるが、それは、まあそこまでは無理だ。)

2009年8月6日木曜日

まとめ読み:Agile関連記事 6

変化への抵抗に打ち勝つ 2008年8月28日

変化に抵抗する理由について「認識に関するもの/感情に関するもの/行動に関するもの」のとする3タイプの分類が提示されている。また変化への抵抗の形式として、「積極的/消極的」「顕在的/潜在的」「個人/グループ」「攻撃的/臆病」の4つの分類軸が挙げられている。

記事の中で、それぞれの抵抗の理由と形式の組み合わせについて、解決策が提示されているわけではないが、そこそこリーズナブルな解法のパターンが提案されているのはなかなか良い。
問題をパターン化して捉えるのは、やはり最適な手順で解に到達するための基本なのだろう。余談だが学校教育における数学の学習のエッセンスというのは、公式や定理ではなくて、つまりこういう事なのだと思う。

後半で、組織の変革の手法として「The Six Change Approaches」と言うのが紹介されている。Kotterさんと Schlesinger さんが1979年に提案したアイデアで、変化への抵抗に対処するための6つの方法が提案されている。また抵抗の理由としては上述の3分類と若干異なる「Parochial self-interest/Misunderstanding/Low tolerance to change/Different assessments of the situation」が提案されているが、個人的にはこちらの方がより説得力を感じる。

今後は、上記のような抵抗のパターンのそれぞれについて、”The Six Change Approaches”をより詳細に具体的した解法が形式知として蓄積される事が望まれるが、この記事ではまだまだそういう気配はない。

ちなみにこの記事もスクラムベース。なんかやっぱり流行ってるのかな。

「技術的負債」に対する新しい見方 2008年9月19日

プロジェクトに途中参画したり誰かのコードを引き継いだりしたとき、プロジェクトのオーナやらマネージャやらにリファクタリングの必要性を説明する事が多いが、「現状、利子の返済だけで首が回って無い状態だから、負債を整理して財務を健全化しないとダメなわけです」なんて例え話で説明すると、わりとすんなり話が通じる事がある。

というわけで、プロジェクトのリソースと成果物を、会計と金融になぞらえる捉え方は昔からよくあって割と説得力があったりするが、「技術的負債」について調べてみると、もともとは Ward Cunningham による1992年のメタファーだとわかる(wikiはここ)。この割と歴史のあるメタファーにまつわる最新の言説を集めて紹介しているのが記事。

本文では負債の減少より資産の増加を重視したアプローチが、最近のアイデアに見られる傾向だとされているが、Alistair Cockburn が2001年に「Agile Software Development」で提示した secondary goal の考えと近いものがある。こちらは、開発を繰り返し連続するゲームと考え、個別のゲームの勝敗(primary goal)と同時に、次のゲームに有利になるような要素をためていく事も重要だとする考え方。

c2 の wiki で、 Debt で検索してみると、いくつか出てきて、これまでにどんな議論があったのかざっくり分かる。ただ、やはり現状では、本物の経済における金銭を計量単位とした定量的アプローチのような手法が確立しておらず、まだまだ感覚的なメタファの域を出ない模様。

今後、PMBOK的 な定量的管理の思想が普及したら、いずれ手法的に洗練される可能性があるかもなんて思わないでもないが。

2009年8月4日火曜日

まとめ読み:Agile関連記事 5

職人的技能 - 5番目のアジャイルManifestoの価値?2008年8月21日

言わずと知れた AgileManifesto の既存4か条に、5番目の条項 "Craftsmanship over Execution"を付け加えようという話。「遂行より職人芸」くらいの意味になるだろうか。

自分も以前は「どこの現場でもそんな価値観だと良いなあ」なんて思っていたけど、今は別にそうは思わないな。なんだか、こんな事を主張するなんて「物凄いプログラム職人なボクをもっと評価してほしい。下手なコードを単に書いてるだけのアホどもとは違うんだよ。」なんて必死に主張してるみたいで、ちょっと恥ずかしい。

だいたい職業プログラマの9割か9割5分くらいは、他の仕事より簡単そうだから「自分でもできそうだ」なんて思ってプログラマやってるだけだろうし。自宅で独習する事も無いし、自腹でスキル投資する事もない。良いコードの美しさも良いコードを書く面白さも分からないし興味無いのが当たり前。食うために仕方なくプログラム書いてる人たちが普通。IT業界に限らず、世の中の大半の「仕事」なんてそんなものだと思う。

ちなみに Alistair Cockburn も『Agile Software Development』でプログラマが読むべき本として紹介している宮本武蔵の『五輪書』の中に、大工の棟梁の仕事として以下のような言葉がある。

「棟梁が大工を使うには、彼らの腕前の程度を知り、ある者は床の間、ある者は戸障子、敷居、鴨居、天井というように、能力に応じて仕事をさせ、腕の悪い者には根太(床板の下に張る横木)を張らせる、もっと悪い者にはくさびを削らせるなど、よく見分けて使えば、能率も上がって手際よくいくものである。」

というわけで、むしろ「適材適所 over スキル至上主義」という方が、平均的な開発現場、特にSI業界では現実的な良い効果があると思う。

(訳文の「Manifestoは5番目の価値であるべきだという提案」という箇所は「Manifestoは5番目の価値"Craftsmanship over Crap"を含めるべきだという提案」の間違いだろう。)

まとめ読み:Agile関連記事 4

見積もりは無駄なプラクティスか?2008年8月21日

「見積り」なんて事自体がそもそも金の無駄だから、もう止めました。

という、にわかには信じがたい話だけど、特殊な条件下でなら有り得ないこともないかもしれない。とりあえず開発側の都合としては、完成責任に対して定額報酬をもらうような形態でなく、働いた分だけかそれ以上のギャラがもらえる保証さえあれば、まあ応じられる相談。

後は(というか大部分だが)顧客側の都合になるだろう。予算に関する権限を持っている上位のステークホルダーが「とにかく見積もる事から始める」という固定観念を捨てるという前提さえ成り立てば、いくつかのパターンで見積り自体にかかるコストを節約できるかもしれない。
  • まずは開発を開始し、そこで得られる実測値を用いて、進捗率とコストの関係から全体の完成までのコストを継続的に予測。この予測を用いて適当なタイミングで開発続行か打ち切るか判断するというケース。打ち切った場合の投下済みコストを、想定内の損失として受容できて、ゴールの不到達自体はそれほど問題にならないという条件が要りそう。
  • とにかく何としても到達すべきビジョンとゴールがあって、尚且つそのための開発者が予め決まっており、見積りを比較して一者を選択するというプロセスを度外視できるというケース。実際に掛かったコストが、その成果物を得るための最小のコストで必要条件だったと納得できるだけの信頼関係が必要条件。
やっぱり、ちょっと無理っぽい気もするが、研究開発色の強いプロジェクトならあるかもしれない。

暗記帳

感覚的には余りブラウザアプリは好きじゃなくて、選択の余地があれば JavaScript/DHTML/Ajax よりも専用アプリとか専ブラに傾く感じなんだけど、かなり前からJavaScriptスキルの価値が高まってきているので、やや遅まきながら準備しておく事にした。

勉強のテーマとして捉えると、多分、余り面白くはなさそうな気配というか、逆にかなりイライラしそうな気配が最初からあるので、題材としてちょっと実用的で使って役に立つものを目指して面倒臭さを克服してみる。

以下のようなアプレット様の暗記帳を、JavaScript で作ってみた。
BMM の基本要素
{ "height":200, "width":400, "caption":"暗記帳 アルファ版" }
Meansの直下のBMM要素は?
  • Mission
  • Strategy
  • Tactic
Endsの直下のBMM要素は?
要素数は3個
  • Vision
  • Goal
  • Objective

JavaScriptファイルは別のサーバにおいてある。このブログの JavaScriptコードでは、単にそのJavaScriptファイル中の関数を window の onload イベントで実行するようにリスナを追加するだけ。

このコードは、div タグで構成した以下のような暗記帳データを読み込み、動的にJavaScriptアプレットを生成、暗記帳の出題と解のペアを保持する。実際は改行や余計な空白を取り除いておく必要がある。
<div id="div1" class="memorizer">
  <div class="memo_title">BMM の基本要素</div>
  <div class="memo_config">
    { "height":200,
      "width":400,
      "caption":"暗記帳 アルファ版"
    }
  </div>
  <div class="memo_dataPart">
    <div class="pair">
      <div class="question">Meansの直下のBMM要素は&#65311;</div>
        <div class="answer">
          <ul style="margin-top:0px;">
            <li>Mission</li>
            <li>Strategy</li>
            <li>Tactic</li>
          </ul>
        </div>
      </div>
      <div class="pair">
        <div class="question">Endsの直下のBMM要素は&#65311;</div>
        <div class="hint">要素数は3個</div>
        <div class="answer">
          <ul>
            <li>Vision</li>
            <li>Goal</li>
            <li>Objective</li>
          </ul>
        </div>
      </div>
    </div>
</div>


FireFox 3、InternetExplorer 8、Opera 9、Safari 4で動作確認した。ちょっと見た目が違うところがあるが妥協。

◆今後の課題
  • 複数のアプレットがある場合に全部を解釈するまでスレッドを占有したりしないように、一個ずつブラウザに処理をもどす。
  • 終了ページで「1回目:n問中m問、2回目:n-m問中l問」という形でレポートを表示する
  • コードが汚いのでリファクタ。もうちょっとオシャレなJavaScriptイディオムがかけないとだめ。
  • CSS 関連の知識不足から、現状のコードではたまたま動いているところや、冗長な設定があるはず。必要十分なコードを追求する。
  • エラーハンドリング
  • スピードアップ、効率化

※それにしても、ある程度予想していたがクロスブラウザがこれほど面倒くさいとは。IE の「"colSpan"がOKで、"colspan"がダメ」とか透明の指定法とかって・・・テンション下がるわ。