http://www.laputan.org/drc/drc.html
新年早々風邪をひいてしまったのでずっと家で読み物をしていた。ちょっと古いが 1998 年に書かれた Ralph E. Johnson と Brian Foote の Designing Reusable Classes のメモ。内容はフレームワーク(ライブラリ集)の設計の仕方。
昔風のライブラリでは、具体的な機能を実装するためにサブクラスで特定のメソッドを実装させるという事が良くある。これがホワイトボックス。例えば onmouseup でマウスアップ時の動作を記述する等。この欠点は、継承機構を利用するため、フレームワークとユーザコードのカプセル化が保証出来ない事。例えばうっかり知らずにメソッドをオーバーライドしたり、触ってはいけない内部状態を変更出来てしまう。
これに対してブラックボックスでは、継承機構を使わずに実装を与える。イベントハンドラや、Smalltalk にある pluggable ビュー等。
同じような動作には同じメソッド名を付けて再帰的に動くようにする。Composite パターンと同じ。
クラスに応じて if で場合分けをしているコードはほとんど間違い。メソッドディスパッチを利用するべき。
コンストラクタ以外でたくさん引数があるのは間違い。
長いメソッドは間違い。小さなたくさんのメソッドに分割するべき。
一つのクラスにたくさんのサブクラスがあるのは間違い。共通項をくくりだして新たなスーパークラスを作るべき。
スーパークラスに状態を持たせるとサブクラスで実装を変えられないので、一番上は抽象クラスで無ければならない。
アクセッサーを定義して実装依存を減らそう。
サブクラスはスーパークラスのメソッドを再定義してはならない(抽象メソッドは除く)。
大きなクラスは貧弱な設計の証拠だ。
一つのメソッドを、あるサブクラスがある方法で実装し、他のサブクラスが別の方法で実装している時はクラスの分け方に問題がある(この部分良くわからなかった)。
クラスの一部のメソッドが他の一部のメソッドをほとんど利用しない時は、クラスを分けて委譲を使う。
self を使ってサブクラスのメソッドを呼ぶようなフレームワークは、ブラックボックス化して代わりに委譲でメッセージを呼ぶように作り替える。
インスタンス変数を暗黙のパラメータとして使わない。グローバル変数と同じようにコードの維持が難しくなる。
ここに書いてある事は他でも良く聞く話だけど、一つ同意出来ないのが 5 番のクラス階層は深く狭くという点。他の部分では継承を出来るだけ使わない方向に見えるので矛盾を感じた。この頃はまだ継承がかっこ良かったのか。ふと思ったんだけど、プログラミング実装技術について、歴史的な文書を順にみてゆくと先のトレンドが読めるかも知れない。
ここで継承がどれだけ悪いか、特に状態を伴った継承を撲滅するために私達に何が出来るかという点について書こうと思ったけど関係ない話になるのでやめておく。