🐤

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

2022/05/14に公開

問題提起

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

item.foo += 1
item.bar += 1
item.baz += 1

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

def update_item(item)
  item.foo += 1
  item.bar += 1
  item.baz += 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
methods.grep(/^set/)  # => [:set_backtrace, :set_value, :set_values, :set_string, :setuid?, :setgid?, :set_encoding, :set_encoding_by_bom, :setbyte, :set_trace_func, :setegid, :setreuid, :setregid, :setresuid, :setresgid, :setuid, :setgid, :setruid, :setrgid, :seteuid, :setpgrp, :setpgid, :setsid, :setpriority, :setrlimit, :setproctitle]

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

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

いやもう統一して

Discussion