kagamihogeの日記

kagamihogeの日記です。

俺の OOP の理解がどう間違っていたかのふりかえり

しばらくしたら―また数冊 OOP の本読んだりしたら―追加もしくは更に修正入ると思う。

OOPデザインパターンは特別な人たちの特別なもの?

デザインパターンを適切なときに適切に使うことは難しい……そう考えていた時期が俺にもありました。

OOP とかデザインパターンとか、なんか小難しいモノはフレームワークとかそういうの作る人が知っていればいいもので、俺のようなフツーのプログラマにとっては、それらの技が必要になることはないだろう、みたいな感じに思ってました。

なんでそんな発想になってしまってたのか、自分でも上手く説明できないけど、下記の一文が俺にとって一つの答えになっていると思う。

パターンでは、コードを再利用するのではなく、経験を再利用するのです。

Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本 1 章 デザインパターン入門 デザインパターンへようこそ から抜粋

OOPデザインパターンはコードを書くのに役に立つ。少なくとも Java で Web アプリを書く人間なら知っておいて損は無いと感じている。オブジェクト指向は、モデリングとかの抽象的な活動のためのものではなく、コードを書くのに役立つ技術なのだということが、俺はまったく分かっていなかった。

ちょっと違うかなぁ? なんか上手く文章に出来ないのでまだ理解が足りてないっぽい。

クラス = 構造体 + 関数?

この呪縛に随分と苦しめられたきたなぁ……としみじみ思う。Pascal や C から Java に移ってきた人は最初にコレを刷り込まされた人多いんじゃなかろうか。

こと Java のコードにすれば確かにクラスは構造体と関数で構成されてるように見える。けど、その理解は間違っている……というよりはそこで止まってしまうと勿体無い。なんで勿体無いかというと interface や abstract なクラスの面白さを分かることが出来ないから。

キーワードは「振る舞い」

コードの字面だけを見ればメソッド呼び出しは関数と何ら違いは無い。ただし、オブジェクトに対して呼んでいる、という点が大きく異なる。オブジェクトを入れ替えることで実装を切り替えられるんだけど、振る舞いは変わらない。

乱暴な言い方をすれば、振る舞いを規定するインタフェースの向こう側は知ったこっちゃない、ということかな、と。

俺の失敗は、OOP を構造化プログラミングの延長線上で捉えようとしていたこと。両者にマッタク関連が無いわけではないんだけど、クラス = 構造体 + 関数みたいにムリに構造化プログラミングの考え方で見ようとしてはいけない。でないと、オブジェクトを入れ替えることで実装を切り替えられる、という技術によって非常に柔軟なコードが書けるようになる不思議が中々理解できないんじゃないかと思う。

OOP で書くとクラス数が増えて複雑さが増す?

クラス数が増えても公開するインタフェースの数を絞ればおk。あるレイヤーとレイヤー間の関係で考えたとき、クライアント側が知っていなければいけないインタフェースの数を必要なものだけにしておく。

確かに全体を見ればクラス数は増えるから複雑さが増したように見える。けど、きれいにパッケージが分割されていれば、ある部分間のみを注目した場合には知っているインタフェースの数は局所的になる。なので、クラス数の総数増加はそれほど問題にならない。

インタフェースさえキレイになってれば、インタフェースを提供する側がぐっちゃぐちゃでもそこそこ上手くいく、というのは歴史が証明してるし。perl は特にそういう傾向がある、というのは良く聞く話。

なのでパッケージ分けの技術はすごく大事。「package? とりあえず機能別に分類しとけばいいんじゃね?」とヌかしていたのが俺。アジャイルソフトウェア開発の奥義 で一章を割いてパッケージ設計の原則について書かれているぐらい大事。

おそらく非常に理想的な状況下では、あるパッケージは (Java でいうところの) interface とファクトリクラス(と String のようなユーティリティ的なクラス)だけで構成されて、クライアントはそのパッケージだけ知っていればいい、という状態になると思う。まぁ実際にはそこまでピーキーにすると却って使い勝手悪くなりそうだけど。