カテゴリ別 2003年 | 2004年 | 2005年 | 2006年 | 2007年 | 2008年
知り合いサイト: よんだもの / 暴想 / Linuxでやる夫 / 新宿Vipper / 僕だけが幸せになればいいのに。
Rubyでメソッド名とローカル変数名を見分ける易いコーディング規約について教えてください。
Rubyコーディング規約
http://shugo.net/ruby-codeconv/codeconv.htmlによると、ローカル変数もメソッドも小文字とアンダースコア(_)で書くことになっていますが、これだとパッと見で混乱してしまうことが多いので。
大抵の場合は見分けがつくのでそんなに気にすることではないと思います。どちらか分からないことで混乱するようなクラスやメソッドはリファクタリングしましょう。
レシーバも引数もない場合は見た目上変数と区別がつきづらい可能性があります。ただし、
といえます。2、3、4 番目の補足説明をします。
新しいメソッドの名前にはよく使われているメソッドの名前を選ぶからです。読み書きなら read/write gets/puts、イテレートは each など。メソッドの働きを類推しやすくするためや duck typing のためです。
filename = "/etc/hosts"
dir = File.dirname(filename)
filename
このようなコードがあった場合、変数 filename が単独で書かれている 3 行目は ruby プログラムとして正しいですが意味がありません。 識別子が単独で書かれている場合は、
def parse
do_preprocess
do_parse
do_postprocess
end
のように処理の一部分を抽出したメソッドである可能性が高いでしょう。
page = fetch
Ruby は変数のコピーをしたりはしないので、上記のような例で右側が変数の場合には単に同じオブジェクトに異なる変数名をつけるだけになります。意味がないのでそのような書き方はしないでしょう。
もうここまでで 90% (適当)は区別がつくのではないかと思います。
さらに
とすれば完全に区別がつきますが個人的にはこれらの書き方はしません。記述が冗長だったり、慣習とそぐいません。
さて、上の 3 つを採用しない場合に区別がつかないのは
です。
class Foo
attr_accessor :bar
def foo
bar = 10
hoge = 15
end
end
bar = 10 は self.bar=(10) というメソッド呼び出しに他なりませんが、hoge = 15 は変数への代入です。 クラスが小さければ bar= が setter メソッドだと分かりますが、クラスが大きいと困ることがあるかもしれません。
上のようにアクセサを介して自分のインスタンス変数にアクセスすることを Indirect Variable Access といいます。 インスタンス変数へのアクセスを Direct Variable Access、つまり
class Foo
attr_accessor :bar
def foo
@bar = 10
hoge = 15
end
end
と書くようにすればこの曖昧さは解消できますが、Indirect Variable Access が必要なケースもありますので規約化はできないと思います。
これらは引数がなく括弧もつけず動詞でもないメソッドです。Object#object_id、Object#class、Array#size などが該当します。
私の場合変数だったものをこのようなメソッドに置き換えることが良くあります。例えば
class Score
def initialize
@scores = []
end
def add(score)
@scores << score
end
def print_score
total = @scores.inject(0){|sum, i| sum += i}
puts "your score: #{@scores.join(', ')}"
puts "your total score: #{total}"
end
end
score = Score.new
score.add(0)
score.add(2)
score.add(1)
score.add(3)
score.print_score
#=> your score: 0, 2, 1, 3
#=> your total score: 6
というクラスがあるとします。で、合計点だけ出力したくなってメソッドを追加します。
class Score
def initialize
@scores = []
end
def add(score)
@scores << score
end
def print_score
total = @scores.inject(0){|sum, i| sum += i}
puts "your score: #{@scores.join(', ')}"
puts "your total score: #{total}"
end
def print_total_score
total = @scores.inject(0){|sum, i| sum += i}
puts "total score: #{total}"
end
end
total を求める部分が重複しています。気になるのでメソッドに括りだします。 このとき名前を get_total とでもすればメソッドだと明らかですが、
def print_score
puts "your score: #{@scores.join(', ')}"
puts "your total score: #{get_total}"
end
def print_total_score
total = get_total
puts "total score: #{total}"
end
def get_total
@scores.inject(0){|sum, i| sum += i }
end
のように、リテラルに get_total と埋め込むのはキレイじゃないし、一度 total 変数に代入するのもなんだか無駄な気がします。 どのように書くかといえば、
class Score
def initialize
@scores = []
end
def add(score)
@scores << score
end
def print_score
puts "your score: #{@scores.join(', ')}"
puts "your total score: #{total}"
end
def print_total_score
puts "total score: #{total}"
end
def total
@scores.inject(0){|sum, i| sum += i }
end
end
としています。total が親クラスで定義されてたりすると変数かメソッドか分かりにくくなりますが、 それを区別しやすくするために get_total のような書き方をするよりもクラス構成やメソッドの長さや名前の付け方を良くするほうが はるかに可読性が向上するんじゃないかなと思います。
最近のコメント:
RSS
![]()
This work is licensed under a
Creative Commons License
(note: text only. w/o web design, citations, (re)distributed softwares).
setter の方は実は ruby も変数への代入と区別出来ないので self.foo = bar と書く必要があったりするわけですが。
あああ。ほんとですね。昔 self と () を省略せずできるだけ形式的に書こうとしたことがあったのですが、p はどうするとかメソッドに見えないメソッドにも括弧つけるべきかとか、結局統一するのは無理だったので止めました。