ククログ

Effective Ruby

2015年1月に翔泳社から「Effective Ruby」という中級者・上級者向けのRubyの本が出版されました。

https://amazon.co.jp/dp/9784798139821

内容

とても主張が強い本です。そのため、何でも真に受ける人にはオススメできません。(初級者とか。)他の人の主張を聞いて、自分で咀嚼してよい悪いを判断できるようになってから読むべきです。

「項目5 実行時の警告に注意しよう」で警告を有効にしようと書いているなど、よいことを書いているところはあるのですが、ここでは、著者の主張が気に入らなかったところを紹介します。よいところは自分で読んで確認してください。

「項目2 オブジェクトを扱うときにはnilかもしれないことを忘れないようにしよう」で、「適切なら」と断りをいれていますが、to_sto_iなどでnilを強制的に型変換しようと書いていることが気に入りません。不正なオブジェクトが見つかる時期が遅くなるので気に入りません。なぜか空文字がある、0がある、どうして?という状態になりやすくなります。

「項目3 Rubyの暗号めいたPerl風機能を避けよう」で次のようにifの条件式のところで代入しているのが気に入りません。しかも、一般的であると書いています。代入(=)と比較(==)は紛らわしいので条件式で代入するのはやめて欲しいです。

def extract_error (message)
  if m = message.match(/^ERROR:\s+(.+)$/)
    m[1]
  else
    "no error"
  end
end

「項目19 reduceを使ってコレクションを畳み込む方法を身に付けよう」で次のようなコードを書いています。selectよりもreduceの方がよいそうです。理由は効率的だからだそうです。

users.select {|u| u.age >= 21}.map(&:name)

users.reduce([]) do |names, user|
  names << user.name if user.age >= 21
  names
end

たしかに効率的ですが、そうまでしてreduceを使う必要はあるのでしょうか。この例ならeachで十分です。

names = []
users.each do |user|
  names << user.name if user.age >= 21
end
names

reduceのブロックの中で破壊的な操作をするのが気に入らないのです。次のように使うならいいです。「あるルールに従ってデータ構造内の要素数を縮小していき、最後に残った値を返す」というreduceの発想に沿った使い方だからです。ただ、効率はよくありません。

users.reduce([]) do |names, user|
  if user.age >= 21
    names + [user.name]
  else
    names
  end
end

「項目33 エイリアスチェイニングで書き換えたメソッドを呼び出そう」のところは気に入らないというより著者の勘違いですが、演算子でも動きます。send(:"*_without_logging")は動くのです。

あと、些細なことですが、コーディングスタイルは気に入りませんでした。

まとめ

主張の強い中級者・上級者向けのRubyの本、Effective Rubyを紹介しました。他の人の主張の良し悪しを自分で判断できるようになったら読んでみてはいかがでしょうか。ここでは気に入らないところを紹介しましたが、まっとうなことを書いているところもいろいろあります。自分で考えながら読んでみてください。

Effective Rubyを読んだ後はRubyのテスティングフレームワークの歴史(2014年版)を読みたくなることでしょう。

そういえば、最近のRubyの本はGCのことを説明することが当たり前になってきたのでしょうか1。この本でもGCのことを説明していました。

  1. 将来、RubyがJVMのように自分でいろいろチューニングしないといけなくなったらどうしましょう。。。