2007年07月05日

リスコフの置換原則

 オブジェクト指向ソフトウェア開発者の方ならご存知かと思いますが、オブジェクト指向にはいくつかの原則があります。
それらは、先人達がオブジェクト指向を研究したり実践したりしていく中で、発見されてきたものです。
どれも、オブジェクト指向を正しく利用するためには非常に重要なことですので、順次解説していきます。

 今回は、リスコフの置換原則のお話です。
英語で言うと"the Liskov Substitution Principle"ということで、LSPと略されたりします。

さてさて、今回はどっちかというと、開発者の方のための話が多めです。

コンテンツ

  1. 例えれば職能
  2. あなたの羅針盤
  3. ソフトウェア開発者のための追記
    1. 契約
    2. 犯罪者
    3. ポリモーフィズムの羅針盤
    4. オススメ
 リスコフの置換原則…と聞くとまず思うのが、「リスコフ」ってなに?ということだと思います。
はい、「リスコフ」というのはこの原則を提唱した人の名前です。
「そういう人が言い出したんだな」とだけ思っとけばOKです。

つまり肝心なのは「置換原則」ってとこですね。

 置換って、置き換えるってことですよね。
何と何を置き換えるんでしょう?
はい、スーパークラスを、サブクラスで置き換えるのです。
ざっくり言っちゃうと、
スーパークラスとサブクラスを定義するとき、サブクラスはスーパークラスを置き換えることができなければならない。
ということが、この原則なのです。

たとえれば職能

 あなたには仕事上の部下がいます。
ソフトウェア開発者と、事務担当です。
今、必要な事務仕事が一つあるのですが、事務担当者は全員手が塞がっています。

 さて、あなたは少しいいかげんに、「事務」というのは会社員の基本形で、開発者はそれにソフトウェア開発の技術を付け足したものだと考えました。
つまり、漠然と事務担当は開発者のスーパークラスだと思ったわけです。
そこで、開発者に事務仕事を頼みました。

 さて、結果は?
もちろん、惨憺たるものですよね。
ばかみたいに時間がかかった上に、間違いだらけ。

 あなたは、この開発者を叱るべきですか?
もちろん、違います。
間違いを犯したのは開発者ではなく、あなたなのですから。

 ソフトウェア開発者と事務担当は置き換えできないのです。
これは、ソフトウェア開発者と事務担当には、どちらがどちらのスーパークラスということはなく、直接関係のない職業だということを示しています。
これがもし、開発者でなく営業担当事務とかだったら、置き換え可能かもしれませんね。
事務担当と営業担当事務は、おそらく同じ継承階層に属しているからです。
(違いますか?事務という職業をやったことがありませんので、もし間違ってたらすいません)

あなたの羅針盤

 このように、どんな場合にも置換可能かどうかというのは、見いだした継承関係が正しいかどうかの重要な判断基準になります。
あなたのオブジェクト思考の羅針盤の一つとして、ぜひ覚えておいてください。

ソフトウェア開発者のための追記

 さて、ソフトウェア開発者の方にはもう少し説明が必要ですね。
実際の開発の中では、何に気をつけたらいいのか。

 クラスAのインスタンスがクラスBのインスタンスに依存しているとします。
次に、クラスBのサブクラスB'を作成しました。
このとき、クラスAに対して、クラスBの代わりにB'を渡しても、クラスAは正常に動作しなければなりません。
そのためにはどうしたらいいのでしょうか?

 まず、クラスを作成するときに、サブクラスでオーバーライドされた結果、動作が意図しないものに変わってしまう可能性があるようなメソッドを、パブリックにしてはならないということです。
javaでいえば、動作を変えるべきでないメソッドにはfinal修飾をすることが大事です。
それ以前に、継承を前提としていないクラスの場合は、クラス宣言自体にfinalを付けるべきです。
ちゃんとしてますか?

 次にサブクラスを作るときには、結果がスーパークラスの意図から外れてしまうようなオーバーライドをしてはいけないということです。
スーパークラスがきちんと作ってあれば、これはそれほど難しい問題ではないはずです。
こうなっていれば、クラスAは実際にクラスBだろうがB'だろうがB''だろうが、クラスBかそのサブクラスが渡されたのであれば、常にうまく動作するはずです。

 クラスAもこれにのっとって作ってあれば、それに依存するクラスもうまくいく。
そのクラスもちゃんと作ってあれば、それにまた依存するクラスも…。
というかんじで、実はこんな細かいことが、アプリケーション全体の変更に対する強さに大きく影響するわけです。
契約
 ところで、この説明で「意図」という言い方をしました。
「動作が意図しないものに変わってしまう可能性があるような…」

「結果がスーパークラスの意図から外れてしまうような…」
というところです。
ここで言う意図は、契約に基づく設計(Design by Contract)の事前条件と事後条件のことでもあります。
上記の説明を契約っぽく言い直してみると、
  • サブクラスはスーパークラスの事前条件を厳しくしてはならない
  • サブクラスはスーパークラスの事後条件を緩めてはならない
ということになります。
これ、サブクラスは、スーパークラスが動く状況なら必ず動かなければならないし、スーパークラスが達成することは必ず達成しなければならないと言っているの、おわかりですか?
これが、クライアントから見て置き換え可能ということなのです。
犯罪者
 さらに言うと、リスコフの置換原則を守ることは、オープン・クローズドの原則を守るために必要なことでもあります。
リスコフの置換原則が守れないと、クライアントのクラスには依存先のクラスごとに条件文(if文とか)が必要になります。

 たとえば、先ほどの例と同じようにクラスAがクラスBに依存しているとします。
次にクラスBのサブクラスB'を作りました。
でも、B'の挙動はBとは互換性がありません。
ということになると、クラスAは相手がBなのかB'なのかを判定して処理を行わなければなりませんよね。
この判定に条件文が必要になるわけです。
さて、新たにBのサブクラスを作りました。
もちろん互換性はなし。
クラスAは、この影響をもろにうけて、変更を余儀なくされますよね。
条件文に新たな条件を追加しなければならないからです。

 このように、リスコフの置換原則を破ると、破ったクラスそのものではなく、そのクラスを使うクライアント側のクラスがオープン・クローズドの原則を守れなくなるのです。

 こうなると、リスコフの置換原則を破ったクラスはまるで加害者のようですね。
そうです。リスコフの置換原則を破るクラスは、犯罪者クラスなのです。
あなたは、そんな犯罪者を生み出してませんか?
といっても、この原則を100%守ることは難しいんですがね。
ポリモーフィズムの羅針盤
 上で、リスコフの置換原則は継承関係が正しいかどうかの羅針盤になると言いました。
このことは、同時にあなたの作っているプログラムがうまくポリモーフィズムを発揮してくれるかどうかの羅針盤でもあります。

 メッセージの受け手のオブジェクトが変わると、オブジェクトによって異なる動作をするのがポリモーフィズムでしたよね。
このとき、いくら違う動作をしてくれるといっても、クライアントからは同じ動作をしているように見えなければなりません。
だって、そうじゃなきゃうまく動かないじゃないですか。
うまく動かなければ、意味ないでしょ。

 ポリモーフィズムとリスコフの置換原則をつなげて大雑把に言っちゃうと、
同じインターフェイスを持っていれば、違うオブジェクトでも同じように扱える。
このとき、オブジェクトによって動作は異なる。
ただし、クライアントからは同じ動作をしているように見える。
ということになります。
違うことをしていても、クライアントからは同じように見えれば、いろんなことを同じやり方で扱って、しかもうまくいくと。
そういうわけなんです。
オススメ
 オブジェクト指向の原則については、アジャイルソフトウェア開発の奥義が参考になるでしょう。
今回お話しした、リスコフの置換原則を含めて、5つの原則がまとめてわかりやすく説明されてます。

 オブジェクト指向の原則以外にも、デザインパターンの実戦的な解説やXP(エクストリームプログラミング)プラクティスなど、チームでのソフトウェア開発に有益な話が満載です。

posted by craftsman at 17:54 | 東京 🌁 | Comment(2) | TrackBack(0) | 原則
この記事へのコメント
今まで、クラス宣言やメソッドの修飾子にfinalを付けるべきかの判断を怠っていたように思います。
その他etc、とても勉強になりました。
そして、【アジャイルソフトウェア開発の奥義】が欲しくなりました。

それにしても、コンピュータ書籍って値段高いですよね。( ̄_ ̄ i)
Posted by サンドラ at 2007年07月11日 21:54
サンドラさん、はじめてのコメント、ありがとうございます。
これからもよろしくお願いします。

そうですねー、逆方向に怠っちゃえばいいのかもしれません。
とりあえずは、なんでもかんでもfinalってことで。
とくに、クラスにfinal付けちゃえば、メソッドはもういちいちfinal付けなくても、暗黙的に全部finalになっちゃうので、らくちんです。


コンピュータ書籍、特に専門的な技術書は高いですよねー。
私も今までに技術書に費やしたお金を考えると、目もくらむばかりです。

まぁ、全てはおもしろい仕事をして、それに見合った報酬を頂くための、自分への投資だと割り切ってます。
でないと、なかなか…。
Posted by craftsman at 2007年07月11日 23:09
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。