リスコフの置換原則

アジャイルソフトウェア開発の奥義」の本の「リスコフの置換原則」の章を読んだ。

リスコフの置換原則とは、1988年にリスコフさんが言った以下のような原則らしい。


S型のオブジェクトo1の各々に、
対応するT型のオブジェクトo2が1つ存在し、
Tを使って定義されたプログラムPに対して
o2の代わりにo1を使ってもPの振る舞いが変わらない場合、
SはTの派生型であると言える。
二つの型が派生関係になっているかどうかは、それらの関係がIS-A関係になっているかを考えればわかると良く言われる。リスコフの置換原則は、二つの型の間のIS-A関係を厳密に定義したものと言える。

続いて、本の中で、長方形型と正方形型を例にとって、リスコフの置換原則が当てはまらない事例について述べられていた。しかし、そこでのリスコフの置換原則は、原文通りの意味ではなく、少し広い意味を取っているようだった。以下は、リスコフの置換原則の原文を並べ替えてそれらしいものを作ってみたもの。


Tを使って定義されたプログラムPに対して、
T型のオブジェクトo2の各々に、
対応するS型のオブジェクトo1が1つ存在し、
o2の代わりにo1を使ってもPの振る舞いが変わらない場合、
SはTの派生型であると言える。
まあ、ようするにSがTの派生型と言えるためには、Sは、プログラムの中におけるTの振る舞いの妥当性をすべて維持しなければいけない、ということ。

このように考えた場合、正方形型は長方形型の派生型とは言えない場合がある。例えば、引数が長方形型であることを前提に作ったプログラムgがある場合に、その引数に正方形型を使用すると、gの挙動が変わってしまう(g作成者の意図が守られなくなってしまう)ことがある。このような場合には、正方形型は長方形型の派生型であるとは言えない、と本の中に書かれていた。(さらに話は契約による設計に続く。)

この本の中でこのような立場を取っている理由は、派生型を、オープン・クローズドの原則を守りながらソフトウェアの拡張を行うための手段として考えているからだと思う。長方形型とプログラムgはすでにあるとする。そして、長方形型を派生させて正方形型というものを導入して、ソフトウェアを拡張しようとした場合に守らなければならない原則として「リスコフの原理」を論じている。その場合は、この本で述べられているように、正方形型は、長方形型に期待されているすべての性質を満たさなければならない(それがどんなに理不尽なものであっても)。そうでない場合は、機能拡張により、暗黙の条件が追加されることになる。その結果、ソフトウェアの複雑度が増し、あっという間にオープン・クローズドの原則が守られなくなるだろう。

それにしても紛らわしいのは、元々のリスコフの置換原則を拡大解釈していることについては、本の中では一切述べられていないこと。普通にリスコフの置換原則を長方形型と正方形型に当てはめると、どう考えても正方形型は長方形型の派生型になる。これについて一言述べておかないと、読者としては混乱する。さらにまた紛らわしいのは、長方形型&正方形型に続く二つの例(Set&永続性のあるSet、直線&線分)では、普通の意味のリスコフの置換原則に反している例になっていること。これが確信犯ならば少しずるいと思った。