クラス分けは関数を決めた後がいい場合もある
設計はトップダウンで進めるから、 大きい方であるクラスをどう分けるかを考えて、 次に小さい方である関数のインタフェースを決める、 という流れでやるべきだと思い込んでいたのだけど、 実際は逆の場合もあるんじゃないかという話。
どっかのWebAPIから何か取ってきて、 それをXMLだとしてパーズして、 キー名を変えたり不要な要素を取り除いたりして、 最後に配列が欲しい、というようなことを考えます。 これをクラスから先に考えると 「WebAPIにアクセスするクラス」というようなものが抽象的に浮んでくるのですが、 そこから先に進めません。 エイヤで始めてしまって、あとで直したり、直しきれなかったりします。
そこで発想を逆転させて、まずそれぞれの機能を関数として考えます。
$hoge->connect($url)
->fetch()
->parseAsXml()
->filter(array('callback1', 'callback2'))
->toArray();
メソッドチェインとして考えるのもたぶんポイントで、 戻値がどんなクラスであるかは一旦考えなくてよくなります。 まずは関数だけを考えると。
んで、次にクラスを考えます。 connect()が返すのはきっとConnectionだろう。 fetch()はConnectionに対する副作用であるべきか、 同じクラスの新たなインスタンスか、 それともResponseというようなクラスに分けるべきだろうか。 parseAsXml()の結果も同じく副作用であるべきか、新しいクラスか。 filter()を使うかどうかは任意だから、 parseAsXml()の戻値と同じクラスでいいだろうな。 toArray()の戻値は配列に決まってる。 等々。
これは「接続」や「接続の結果戻ってきた文字列」、 「接続の結果戻ってきた文字列を解釈したもの」のような、 抽象的なものをクラス分けするときに威力を発揮しそうだと思いました。