🐤

英語はオブジェクト指向言語と相性が悪い?

2022/05/14に公開約1,800字

次のコードをまとめて1つのメソッドとして抽出したいとき

item.x += 1
item.y += 1
item.z += 1

item を update すると考えれば一般的には update_item になる。

def update_item(item)
  item.x += 1
  item.y += 1
  item.z += 1
end

このように 動詞 + 対象 の順で命名している方は多い、というかほとんどがそう。
また、上の例ほどシンプルではないけど似た感じの構造になっているコードもよく見かける。
対象を引数に取り、対象を操作する形に。

で、あるとき、よくよく見たらこれ item に対しての更新をしているだけだから Item クラス側で定義する手もあるな。それで item.update として呼ぶのはどうだろうか。と、考えるようになるかもしれない。

そこでリファクタリングするとこうなった。

def update_item(item)
  item.update
end

ここで違和感がある。
メソッド名が update → item なのに対して、実際の処理は item → update と逆になっている。
もし、最初から「アイテムを更新する」と日本語で発音するかのように item_update と名付けていたらどうだろう?

def item_update(item)
end

item_update と名付けた時点で何かおかしいことに気づくんじゃなかろうか。
item.update でいいんちゃうんかと。
なんでこんなところに item_update なんて定義しようとしてたんかと。

似たような例として set_xxx メソッドがあってリファクタリングしていくうち最終的に xxx.set になったりするケースが多いように感じる。これも最初から xxx_set にしていれば、その時点で xxx の set メソッドを呼ぶべきだったと矛盾に気づいたはずである。

したがって動詞が先に来る英語はオブジェクト指向言語と相性が悪い(小声)

日本人が自分のためにコードを書くなら無理して動詞を先に書く必要はない。オブジェクト指向寄りの日本語文法をそのままに命名する方が自然とメソッドをどこに定義すべきかを間違わない素直なコードが書けるようになるだろう(小声)

おまけ

Ruby には set で始まるメソッドなんかない。さすが Ruby だ!
──と書こうとしたらけっこうあったわ。

methods = ObjectSpace.each_object(Module).collect_concat(&:instance_methods).uniq
puts methods.grep(/^set/)
# >> set_backtrace
# >> setuid
# >> setgid
# >> setruid
# >> setrgid
# >> seteuid
# >> setegid
# >> setreuid
# >> setregid
# >> setresuid
# >> setresgid
# >> set_trace_func
# >> setpgrp
# >> setpgid
# >> setsid
# >> setpriority
# >> setrlimit
# >> setproctitle
# >> setuid?
# >> setgid?
# >> set_encoding
# >> setbyte

_set で終わるメソッドは──

methods = ObjectSpace.each_object(Module).collect_concat(&:instance_methods).uniq
puts methods.grep(/_set$/)
# >> const_set
# >> class_variable_set
# >> instance_variable_set
# >> source_set
# >> thread_variable_set
# >> local_variable_set

いやもう統一して

Discussion

ログインするとコメントできます