Ruby がクラスにメソッドを詰め込みすぎだって? ふっ…

ソフトウェア工学の講義中、先生が「Rubyはクラスにメソッドを詰め込みすぎ」という主旨のことを言ったけれど、オブジェクトが何であるかよりもオブジェクトがどのように振る舞うかを重視するとき、Rubyのやりかたは正しいんじゃないかなーと思った。

ともくんのママ on Twitter: "ソフトウェア工学の講義中、先生が「Rubyはクラスにメソッドを詰め込みすぎ」という主旨のことを言ったけれど、オブジェクトが何であるかよりもオブジェクトがどのように振る舞うかを重視するとき、Rubyのやりかたは正しいんじゃないかなーと思った。"

CocoaのNSStringクラス見せたら発狂すんじゃないかと思ったが、SqueakのStringクラス見たら自分も発狂しかけた。

ともくんのママ on Twitter: "CocoaのNSStringクラス見せたら発狂すんじゃないかと思ったが、SqueakのStringクラス見たら自分も発狂しかけた。 http://www.oldenbuettel.de/squeak-doku/Collections-Text/String.html"


いやいや。Squeak Smalltalk に限れば、String クラスのメソッド数なんてそれでもまだかわいいもんです。w

| dict |
dict := Dictionary new.
SystemNavigation default allBehaviorsDo: [:class | dict at: class put: class selectors size].
(dict associations sort: [:a :b | a value > b value]) first: 10
Morph -> 1165
Player -> 620
PasteUpMorph -> 469
Preferences class -> 450
Object -> 436
ParagraphEditor -> 284
SyntaxMorph -> 250
Behavior -> 243
ScriptLoader -> 236
String -> 233


ちなみに Ruby の組み込みクラスだとこんな結果に。

dict = {}

ObjectSpace.each_object(Module){ |klass| 
   dict[klass] = klass.instance_methods(false).size
}

dict.to_a.sort_by{ |ea| -ea[1] }.first(10).each{ |ea| 
  print "#{ea[0]} => #{ea[1]}\n"
}
$ ruby -v numofmethods.rb
ruby 1.8.6 (2008-03-03 patchlevel 114) [i386-cygwin]
String => 83
Array => 71
IO => 51
Hash => 45
Time => 42
Kernel => 41
File::Stat => 40
Module => 35
Float => 31
Fixnum => 31

$ ruby1.9 -v numofmethods.rb
ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-cygwin]
String => 106
Array => 81
IO => 64
Time => 51
Hash => 51
Kernel => 45
ARGF.class => 44
Enumerable => 42
File::Stat => 42
Module => 41


なるほど。それで Ruby では String が引き合いに出されたのかもしれませんね。


追記

Morphにメソッド多いことは薄々気づいていましたがカテゴリしっかり分けられてるのであまり難はありませんでした。

RakiKuni on Twitter: "さて @uasi さんのポストへの返答(?)[http://d.hatena.ne.jp/sumim/20090619/p1]を見て、Morphにメソッド多いことは薄々気づいていましたがカテゴリしっかり分けられてるのであまり難はありませんでした。Objectけっこう少なかったのね"


そうなんです。もちろん特定のクラスにメソッドを詰め込むのはよくないことですが、Smalltalk ではプロトコルと呼ばれるメソッドをカテゴライズする機能があるので、同じメソッド数でも同種の機能を持たない他の言語よりは苦になりにくいという傾向はあるかもしれません。


たとえば、Morph クラスの全カテゴリは次の式で得られます(多いので出力は省略)。

Morph organization categories

"=>  #(#accessing #'accessing - extension' #'accessing - properties' #caching 
#'card in a stack' #'change reporting' #classification ..."


数を調べると 146 個あります。

Morph organization categories size   "=> 146 "


それぞれに分類されているメソッド数をカウントして多い順に並べると、次のようになります。

| result |
result := Dictionary new.
Morph organization categories do: [:each |
	result at: each put: (Morph organization listAtCategoryNamed: each) size].
^(result associations sort: [:a :b | a value > b value]) first: 10
#accessing -> 69.
#geometry -> 62.
#menus -> 61.
#'e-toy support' -> 57.
#'halos and balloon help' -> 54.
#'layout-properties' -> 52.
#'event handling' -> 46.
#'meta-actions' -> 44.
#'submorphs-accessing' -> 41.
#'dropping/grabbing' -> 40
...


そんなわけで、@kckm さんご指摘のとおり、カテゴリーごとに見てしまえば、多くてもせいぜい Ruby 程度には収まっているのだと考えられなくもないわけです。