N2 ToolBox(跡地)

跡地です。引っ越しました。http://d.hatena.ne.jp/nosen

知識のキャッシュと効率

2006-12-10 05:09:03 | 意見
働かざるもの食うべからず。怪しいギャンブル船に乗り込んだり、
1玉4千円の人食いパチンコに挑んだりして、大金を掴みでもしない限り、
この大原則から逃れる術はありません。

私が社会人2年目の時にソフトウェア開発の世界に転職したのは、
少々つまらない仕事でも、我慢してこなしていればとりあえず、食いっぱぐれは
ない、という時代でもなくなってきていましたし、
どうせ働かなくては食えないのなら、自分が本当に面白いと思うことを
仕事にした方がきっと幸せだろうと考えてのことです。
さて、プロとしてお金をもらうからには、自分の仕事の結果として、
それにふさわしい価値を生み出さなければならないのが、道理というものです。
この価値の一つに「効率」というのがあります。

「効率」とは、早くて安いことです。
システム開発のような知識集約型の業種において、「効率」を達成するための
主要な戦略は、システム開発に必要な知識をそのつど考えだすのではなく、
キャッシュして、再利用することです。
さまざまな開発方法論やデザインパターンなどは、このキャッシュされた
知識の代表的な形態です。知識キャッシュを利用しないソフトウェア開発が
あまりにも高くつきすぎることは想像に難くありません。

知識集約型の仕事において「効率」を達成することは、労働集約型の
仕事よりもずっと難しいことです。知識集約型の仕事は
単純に知識キャッシュを沢山利用すればするほどより早く、より安く
結果が出せるというものではないと思います。

なぜならば以下に述べる2つの原因から、キャッシュされた知識は、
それがもはや想定どおりには役にたたない場合があると
考えられるからです。

1つめの原因は、知識を誤った問題に対して適用してしまうことです。
ある知識が最初に生み出されたとき、
それはその時、その場所で発生した特定の問題を解決するために考え出されたのであり、
キャッシュされた知識は、それがいま、この場所で発生している別の問題を解く
のにも役立ってくれるかどうかは保証してくれないということです。

たとえば、Javaのプログラミングにおいて、
「実装が一つしかない場合にも、対応するインタフェースを定義するのが良い」
という知識があったとしましょう。この知識を適用とするときに注意しなければ
ならないのは、この知識自体からはそれがどんな問題を解決してくれるのかはわからない
、ということです。それを知るには、想像してみるしかありません。この例の知識が
解こうとしている主な問題はおそらく、

「あるクラスの実装の変更の影響が、そのクラスのクライアントにも連鎖的に波及する」

ということと、

「クラスの実装に何かトランザクション制御のような細かい共通処理が多数紛れこんでしまう」

ということであると想像されたとします。
知識が解決してくれる問題のあたりがついたところで、
その問題が、今の自分にとっても同じように問題であるのかを考えてみます。

1つめの問題について。
そのクラスが変更される可能性はどれくらいありますか?
ほとんど変更される可能性のないクラスについて、変更の影響を
心配しても仕方ありません。
そのクラスのクライアントは何クラスくらいありますか?
沢山のクラスから使われるクラスの方が変更の影響のインパクトは大きくなります。
その変更作業を行うのに、どんなツールが使えますか?
新しいツールを使えば、実は変更の作業は言う程大変ではないのかもしれません。

2つめの問題について。
そのクラスにはどれくらいの量の細かい共通処理が紛れこんでいますか?
共通処理を外に切り出すのにどんなライブラリやフレームワークが利用できますか?
アスペクト指向プログラミングを可能にするフレームワークが利用できるのであれば、
それはインターフェースを切り出すよりもより良い解決策かもしれません。
(ウィービングされたコード内で発生するエラーの解析は普通のクラスよりも困難、という
別の問題を発生させはしますが)

このように、その知識が解いてくれる問題が、
今自分にとって実は問題ではないか、
もっと良い解決策があるというケースは多く考えれられます。
その場合、その知識を適用することによる効率の向上は望めなくなります。

2つめの原因は、その知識が生み出された時点では、
問題の理解がまだ浅かった、という場合です。例えば、
前述の実装と1:1のインタフェース定義の例では、

「あるクラスの実装の変更の影響が、
そのクラスのクライアントにも連鎖的に波及する」

という問題を想定しましたが、実はその知識はこの問題を
解決していないかもしれないのです。

あるクラスの実装の変更というのは一体何を意味しているのでしょうか?
メソッドの中身が変更されるだけなら、クライアント側には変更の影響は波及しません。
メソッドのシグネチャが変更されたら...インタフェースの定義も変更されてしまうので、
結局この解決策ではクライアントへの変更の影響の波及を防ぐことができないどころか、
むしろ、実装とインタフェースの両方のシグネチャを直さなければならないので、
より問題を悪化させています!

人間は神ではないので、知力に限界があります。だから、良かれと思って苦労して
考え出した解決策が実は全然役に立たないことが後になってわかる、ということは
良くあることです。それはどんなに偉い人でも例外ではありません。
昔のEJB仕様などが良い例です。

このように、キャッシュされた知識を誤って適用することが、
より効率を悪化させる可能性が結構ある。それがソフトウェア開発で高効率を
達成することが難しい理由だと思います。

私はよくウォータフォール型の開発モデルとか、決められたことを決められた
通りに実行することを重視する官僚主義的な組織文化を批判しますが、
それはこのような考えを持っているからです。

ウォータフォール型の開発モデルは、多くの場合、今私達が抱えている問題を解決するどころか、
より悪化させる可能性が高いと私は考えています。にもかかわらず、
単にそういうふうに決められているから、という理由で古い開発モデルを押し通し、
それが原因でプロジェクトがデスマーチ化したり、心や体を壊す人がでたり、
そういうことがどうしても許せないのです。

なお、ウォータフォール型の開発モデルがなんで役に立たないか、
については、近日発売の著書「Apache Maven 2.0入門 Java・オープンソース・ビルドツール
に私の考えを述べてあります、



とまたちょっと宣伝してみる。