Getting Things Done(GTD)

時間と仕事の整理術『GTD』がカルト的人気
http://hotwired.goo.ne.jp/news/culture/story/20050719202.html
この本ですね。

仕事を成し遂げる技術―ストレスなく生産性を発揮する方法

仕事を成し遂げる技術―ストレスなく生産性を発揮する方法

なんとなく味のある装丁に惹かれて買ったものの、そのままになっています。
今度読んでみよう。

http://air.geo.tsukuba.ac.jp/~eddie/2005/05/26/58.html
4回にわたってGTDの解説がされています。

(追記)その他関連情報
ストレスの無い仕事フローを目指す (前編) - Goodpic
ストレス無し仕事フローのためのWEBツール(後編) - Goodpic
http://kengo.preston-net.com/archives/002048.shtml

0. クラス原則

前回のJ2EE勉強会で、ひがさんから「DIの本質」として発表された中にでてきたOpen Closed Principle(OCP)。
以前から、「オブジェクト指向入門 (ASCII SOFTWARE SCIENCE Programming Paradigm)」で読んだりして言葉は知っている状態だったけど、正直どういう意味なのかはよくわかってません。
で、

プログラマのためのJava設計ベストプラクティス

プログラマのためのJava設計ベストプラクティス

  • 作者: カーククネンシルト,Kirk Knoernschild,長瀬嘉秀,今野睦,テクノロジックアート
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2002/12
  • メディア: 単行本
  • クリック: 16回
  • この商品を含むブログ (3件) を見る
の第1章に、OCPを中心としたオブジェクト指向設計の原則が説明されているので、これを参考にちょっとまとめてみます。
登場する原則は以下のとおり。

  1. 閉鎖/開放原則 (Open Closed Principle:OCP)
  2. Liskovの置換原則 (Liskov Sustitution Principle:LSP)
  3. 依存関係反転原則 (Dependency Inversion Principle:DIP
  4. インターフェイス分離原則 (Interface Segregation Principle:ISP
  5. コンポジット再利用原則 (Composite Reuse Principle:CRP
  6. 最小知識原則 (Principle of Least Knowledge:PLK) aka デルメルの法則 (the Low of Demeter)

順番に見ていくことにします。

1. 閉鎖/開放原則 (Open Closed Principle:OCP)

クラス間の関係についてのもっとも重要な原則。他の原則は、すべてOCPから導かれる。

クラスは拡張には開放され、修正には閉鎖されているべきである。

既存のソースに手を加えずに、システムに新しい機能を追加できるようにしなければならない、ということ。
ふむふむ、とは思うけど、なにしろ全体を統括する原則なのでちょっととらえどころがない感じ。

2. Liskovの置換原則 (Liskov Sustitution Principle:LSP)

OCPの拡張。LSPを侵害するとOCPも侵害することになるが、逆はかならずしも真ならず。

サブクラスは基底クラスと置換可能でなければならない。

サブクラスは基底クラスのした約束をすべて守らなければならない、ということ。
Design by Contract の事前条件・事後条件を実装しているような処理系だと、サブクラスが基底クラスより事前条件を厳しくすること・事後条件を緩くすることはできない。
基底クラスが投げると言っていないチェック例外を投げることはできない、というのも例として挙げられる。

3. 依存関係反転原則 (Dependency Inversion Principle:DIP)

DIPは、OCPに準拠する方法を教える。

抽象に依存する。具象に依存してはいけない。

具象クラスでなく、親クラスやインターフェイスを通してオブジェクトを参照しなさい、ということ。
オブジェクトを生成するときが厄介。


HogeAbstract = new HogeConclete();
とやると、HogeConcleteクラスに依存してしまう。

Class c = Class.forName("HogeConclete");
HogeAbstract = (HogeAbstract) c.newInstance();
とやっても本質的に問題は解決してないし、コンストラクタに引数を渡せないなどの問題もある。
これを回避するためにファクトリパターンが導入されるわけですが、やりすぎると複雑に。
そこでDIコンテナでつよ、ってことなのかな

4. インターフェイス分離原則 (Interface Segregation Principle:ISP)

単独の汎用的なインターフェイスよりも、多くの特化したインターフェイスの方がよい。

関連する機能一式をすべてメソッドとして備えたインターフェイスを定義すると、クライアントが使わないメソッドに依存することになる。凝集度を保ったままインターフェイスを分割して小さくすべき。

5. コンポジット再利用原則 (Composite Reuse Principle:CRP)

継承よりもオブジェクトの多相なコンポジションの方がよい。

再利用するには、継承を使うより委譲したほうがいいですよ。

(だんだん説明が適当になってきた)

6. 最小知識原則 (Principle of Least Knowledge:PLK) aka デルメルの法則 (the Low of Demeter)

クラスCの操作Oは、以下のオブジェクトの操作だけを呼び出すべきである。
それはクラスC、操作Oの引数、操作Oが生成したオブジェクト、クラスCのインスタンスオブジェクトである。

オブジェクトのはしご(別のオブジェクトのメソッド呼び出しで得られたオブジェクトのメソッドを呼び出す)はNG。
途中のオブジェクトに、最終目的のオブジェクトまでリクエストを転送しなさい。


class Foo {
hoge(Bar bar) {
Baz baz = bar.getBaz();
baz.fuga();
}
}
ではなく、

class Foo {
hoge(Bar bar) {
bar.hige();
//Bar#hige() の中で Baz.fuga()を呼び出す
}
}
というふうにするべき。
こうすると、Barの内部構造にFooが依存しなくなる。