ruby-style-guideを読んだら知らないことがイロイロあって勉強になった
2年ぶりに業務でRubyを書きはじめたので、改めてruby-style-guideを読んだら知らなかったことがイロイロあったのでメモ。
2019/02/28当時の日本語版: 2bac495を読みました。
1. 本文のないクラスは1行のフォーマットを用いましょう。
# 悪い例 class FooError < StandardError end # 悪くない例 class FooError < StandardError; end # 良い例 FooError = Class.new(StandardError)
「悪くない例」を書きがちだったので。
2. forは、どうしても使わなければいけない明確な理由が明言できる人以外は、使ってはいけません。 多くの場合は代わりにイテレータを使うべきです。 forはeachをつかって実装されています(だから、より遠回しです)が、 forは(eachと違い)新しいスコープを導入せず、 そのブロック内で定義された変数は、ブロックの外からも見えます。
arr = [1, 2, 3] # 悪い例 for elem in arr do puts elem end # elemはループの外からも参照できることに注意しましょう elem # => 3 # 良い例 arr.each { |elem| puts elem } # elemはeachブロックの外からは参照できません elem # => NameError: undefined local variable or method `elem'
なんとなく、「Rubyでfor文は使わないものだ」という認識はあったし、実際for文は使ったことがなかったけど、なんで使わないのか、避けるべき理由は何なのかを意識していませんでした。
↑の例に書いてあるようにfor文内でつかった変数が、外に漏れ出てくるのはなんかのきっかけでハマりそうだし、やっぱりfor文は避けるべきなんだなと思いました。
3. あまりに暗号めいている String#%
メソッドよりも sprintf
や format
を使いましょう。
# 悪い例 '%d %d' % [20, 10] # => '20 10' # 良い例 sprintf('%d %d', 20, 10) # => '20 10' # 良い例 sprintf('%<first>d %<second>d', first: 20, second: 10) # => '20 10' format('%d %d', 20, 10) # => '20 10' # 良い例 format('%<first>d %<second>d', first: 20, second: 10) # => '20 10'
単純に String#%
の存在を知らなかったです。 (推奨されてないし、あえてこれから使おうとは思わないですが)
4. 名前付きフォーマット文字列を使用する場合、 %{name}
よりも %<name>s
を使いましょう。 %<name>s
は値の型に関する情報をエンコードするためです。
# 悪い例 format('Hello, %{name}', name: 'John') # 良い例 format('Hello, %<name>s', name: 'John')
どっちの記法も知りませんでした。
5. あまりに暗号めいている Array#*
メソッドよりも Array#join
を使いましょう。
# 悪い例 %w[one two three] * ', ' # => 'one, two, three' # 良い例 %w[one two three].join(', ') # => 'one, two, three'
Array#*
を知りませんでした。(使わないけど)
6. size
の代わりに count
を用いてはいけません。 Array
以外の Enumerable
オブジェクトでは、 count
を使うと要素数の計算のためにコレクション全体を走査してしまいます。
# 悪い例 some_hash.count # 良い例 some_hash.size
これも知りませんでした。
標準ライブラリはこのルールに従うかもですが、ActiveRecord とか外部ライブラリだとまたルールが異なってきそうなので、結局のところdocumentなりソースなりをちゃんと読むべきな気がしました。
7. Struct.new
の使用を考えましょう、 それは、単純なアクセサ、コンストラクタや比較演算子を定義してくれます。
# 良い例 class Person attr_accessor :first_name, :last_name def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end end # より良い例 Person = Struct.new(:first_name, :last_name) do end
Struct.new
にブロックを渡せることを、知りませんでした。
こういうふうに使えそうですね。
Person = Struct.new(:first_name, :last_name) do def full_name "#{first_name} #{last_name}" end end p = Person.new('Hoge', 'Fuga') p.full_name #=> "Hoge Fuga"
ただ、メソッドを用意する必要があるような場合は Classを使うような気もするので、使いどころが多いかは分からないです。
8. 例外は fail
より raise
を使いましょう。
# 悪い例 fail SomeException, 'message' # 良い例 raise SomeException, 'message'
「自分が例外を射出するときは fail
、 rescue
などで補足した例外を再射出するときは raise
」のような使い分けがあった気がしましたが、今は全部 raise
で良いようでした。
9. きちんとインデントされた複数行の文字列には、Ruby 2.3 の、インデントされた ヒアドキュメントを使いましょう。
# 悪い例 - Powerpack の String#strip_margin を使用しています。 code = <<-RUBY.strip_margin('|') |def test | some_method | other_method |end RUBY # こちらも悪い例 code = <<-RUBY def test some_method other_method end RUBY # 良い例 code = <<~RUBY def test some_method other_method end RUBY
<<~
で書くヒアドキュメントを知りませんでした。
10. キャプチャした結果を使う必要のないときは、キャプチャしないグループを用いましょう。
# 悪い例 /(first|second)/ # 良い例 /(?:first|second)/
これも単純に知らなかったシリーズ
まだまだ知らないことが多く、たまに読み返すと学びがあって良いなと思いました(小並感)