ヒューメインインターフェイス
http://martinfowler.com/bliki/HumaneInterface.html
Ruby界隈で「ヒューメインインターフェイス」という言葉を何度も耳にした。 この言葉は、クラスのインタフェースを記述する際のrubyistたちの姿勢(attitude)の一部を表したものである。 APIの設計については、2つの異なる考え方を対比していくと面白い(もうひとつは最小インターフェイス(/MinimalInterface)である)。
ヒューメインインターフェイスの肝は、みんなが何をやりたいかを見つけ出し、何度も起きることを簡単に行えるためのインタフェースを設計することだ。
最小インタフェースとの明確な違いは、ヒューメインインターフェイスの方が大きくなる傾向があるという点だ。ただ、ヒューメインインターフェイスの設計者はインタフェースが大きくなることをそれほど気にしてはいない。 以上のことは、ヒューメインインターフェイスで設計されたクラスの実装が必ず大きくなる、ということではない。 基本的な機能に関しては、どちらもよく似たものになる。
ヒューメインインターフェイスと最小インタフェースの違いを見つけるには、JavaとRubyのListコンポーネントを比べるとよいだろう。 Javaには、インスタンスメソッドを25個持つinterface(java.util.List)がある。 一方のRubyには、メソッドを78個持つArrayクラス(arrayではなくlistである)がある。 両者のスタイルの違いが、メソッドの数の違いとして表れている。 どちらのコンポーネントにも同じような基本的な機能がある。 ただ、RubyのArrayには、その他多くの機能があるのだ。
それでは、その違いを表す例を見ていこう。 Listの最後の項目を取得する例だ。 Javaでは、以下のようにやるだろう。
aList.get(aList.size -1)
Rubyだと、こうだ。
anArray.last
実際にはまだ他にも驚くべき点がある。
例えば、RubyのArrayにはfirst
メソッドもある。
つまり、anArray[0]
ではなく、anArray.first
とできるわけだ。
もっと大きな機能もある。
RubyのArrayにはflatten
メソッドがあり、
ネストされた配列を平滑化する。
irb> [1,2,[3,4,[5,6],7],8].flatten
=> [1, 2, 3, 4, 5, 6, 7, 8]
ここでポイントとなるのは、以上のような機能(last
のようなシンプルなものにしろflatten
のような複雑なものにしろ)は、クライアント自身が作ることもできるという点である。クライアント自身が作れば、listクラスのサイズは大きくはならない。
最小インタフェース派は、このような振る舞いをサポートする必要最小限のメソッドに焦点をあてている。
一方のヒューメインインターフェイス派は、必要となるメソッドを追加したいと考えている。
とすると、次のような質問が頭に浮かぶかもしれない。 「ヒューメインインターフェイスに追加すべき機能の判断基準って何?」 あらゆる人が必要とするすべての機能を追加してしまうと、とてつもなく複雑なクラスができあがってしまう。 ヒューメインインターフェイスの設計者は、クラスが最もよく使用される場合を見出そうとしている。そして、それらの場合において、簡単に使えるようにインタフェースを設計している。
この原則はメソッドの追加を促すだけでなく、メソッドの名前付けにも影響してくる。
RubyConfでは、田中哲氏が「よく使うメソッドは短い名前の方が良い」と指摘していた。
メソッドを使う機会が多くなれば、親しみが出てくる。
何度も使うのであれば、短い名前のほうが覚えやすいし、
タイプ量も減るし、コードを読む時間も少なくなる。
田中氏の例では、DateTime
クラスのparse
メソッドは標準の日付フォーマットでパースするが、様々な日付フォーマットを扱うことのできるより柔軟なstrptime
メソッドはあまり使われていない、とあった。
上記のようなメソッド名の原則は、最小インタフェース手法と衝突しない。
実際、JavaのList
インターフェイスが登場したとき、それは古いVector
のelementAt
メソッドをget
に変更した。
Rubyのヒューメインインターフェイス哲学の面白いところは、他にもある。
メソッド名のエイリアスだ。
listの長さを取得したいとき、length
を使う?それともsize
を使う?
length
しか用意していないライブラリもあれば、size
しか用意していないライブラリもあるだろう。
RubyのArrayは、どちらも用意している。
エイリアスが張られているので、同じコード内でどちらの名前でも呼ぶことができる。
Rubyistたちは、ライブラリの使用者にどっちのメソッドだったかを覚させるよりも、
ライブラリ側で両方用意したほうが簡単だ、と思っている。
どちらのインタフェース設計がベストなのかーとかいう長くてツマんねースレッドがあるけれども、ここで私がヒューメインインターフェイス派の主張をまとめてみよう(最小インターフェイス派についてはそちらのページを参照のこと)。
オブジェクトの強みの大部分は、その振る舞いにあるのであって、データにあるのではない。
最小の機能しか提供しないのであれば、複数のクライアントがよくある同じようなコードを重複して書かなければならない。
flatten
のようなメソッドがなかったら、再帰処理を大勢の人間が書かなければならないだろう。
まあ、それほど難しいことではないかもしれない。だが、頻繁に使用するのになんでいちいち面倒くさいことをしなきゃいけないの?
last
のようにシンプルにできる場合でも、読み手はイディオムを覚えなければならない。
どうしてそんな間接的なことをしなきゃいけないわけ?直接読めるメソッドがあるってのに?
優れたソフトウェアはユーザのことを第一に考え、ユーザーの生活を楽にしようとする。
ヒューメインインターフェイスはこの原則に従っている。
ヒューメインインターフェイスでは、クライアントがしなくていいように、代わりにいろいろとやってあげる。 そのAPIを使う人間に対しては、彼らのタスクが簡単にできるようにするには、色々なことが必要となる(読みやすいようにする必要もあるし、書きやすいようにする必要もある)
どちらの「だよ派」にも優れた論旨がある。 個人的にはヒューメインインターフェイスだよ派だが、 結構難しいよなあーとも思っている。
フォローアップ
上の文章がちょっとした祭りになったようだ。 興味深い、有用なディスカッションが繰り広げられている。 いつか一連の話をまとめたいと思うが、とりあえずリストだけ。 Elliotte Haroldのヒューメイン手法に対する端的ながらも強い反論に対して、James Robertsonがコメントしたのが最初(そのコメントは自分でチェックしてくれ)。 以降、Cees de Groot、Antonio Vieiro、David Hoefler、James Higgs、Peter Williams、Cedric Beust、John D. Mitchell、Stuart Roebuck(ry(訳注:めんどーなので本家でリンクを確認してください)らが加わって祭り化。
つーか、多杉w。 燃料を投下しつつ殺伐としないお前ら最高。 ただ、基本的な原則ではなく、例(RubyのArrayとJavaのList)にばかり注目している傾向にあるようだが、まあ、それは仕方ないだろう。 議論はいくつかのよい方向に進んでいる。 私もそのうちの1つ2つについて議論を深めてみたい。
もしくは、Joey deVillaがまとめてくれているのでそれを読むのもよいだろう。