class User
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
end
class NameConverter
def main
users << User.new('田中', '次郎')
users << User.new('鈴木', '花子')
users << user.new('山田', '太郎'
results = []
users.each do |u|
results << "#{u.first_name} #{u.last_name} さん"
end
results
end
def sub
# mainみたいなロジック
end
def subsub
# mainみたいなロジック
end
end
↑みたいなロジックがあった時に↓みたいにリファクタリングされることがある、ちょっと極端な例だけど
class User
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
end
class CommonConstants
@@name_suffix = 'さん'
end
class NameConverter
def convert(first_name, last_name)
return "#{first_name} #{last_name} #{CommonConstants.name_suffix}"
end
def main
users << User.new('田中', '次郎')
users << User.new('鈴木', '花子')
users << user.new('山田', '太郎'
results = []
users.each do |u|
results << convert(u.first_name, u.last_name)
end
results
end
def sub
# mainみたいなロジック
end
def subsub
# mainみたいなロジック
end
end
これはやめたほうがいいよねーという話
↓みたいに、他のクラスに必要ない変数とかメソッドは関係あるクラスに閉じ込めてほしい
class User
attr_accessor :first_name, :last_name
@@name_suffix = 'さん'
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def formal_name
"#{@first_name} #{@last_name} #{@@name_suffix}"
end
end
class NameConverter
def main
users << User.new('田中', '次郎')
users << User.new('鈴木', '花子')
users << user.new('山田', '太郎')
results = []
users.each do |u|
results << u.formal_name
end
results
end
def sub
# mainみたいなロジック
end
def subsub
# mainみたいなロジック
end
end
この場合NameConverterクラスがUserクラスのプロパティの変換ルールを知ってる必要は全くないし、CommonConstantsみたいな全クラスに晒されるクラスにformal_nameメソッドでしか使わない'さん'を書いておく必要は全くない
'さん'をグローバルな定数にしとけば'さん'が変わった時に、
一斉に変わって素敵!って思うかもしれないけど
こんなにふわっとした名前だと
"#{CommonConstans.name_suffix}タクロース"
みたいな使われ方されるかもしれないし、グローバルに一度晒した定数は簡単に変更するのが難しいので、
CommonConstants.name_suffix2 = 'くん'
みたいな謎の定数が出来かねない
常にUserクラスのメソッドを通してname_suffixにアクセスするってことにすれば、クラスの利用者がname_suffixを意識する必要がなくなるので、定数をクラスの外に出す必要がない
NameConverter#convertだってNameConverterクラスにある以上convert('お', 'っ')
みたいな使われてるかもしれないし、ただコードが同じってだけの理由で共通の処理に抜き出してもメンテナンス性は向上しない
重要なのは意味的にまとまりがある単位でメソッドと変数を一つのクラスに閉じ込めて抽象化すること
2番目のコードだとNameConverterクラスは常にconvertのことを気にしないといけなくて、例えばミドルネームに対応してくださいってなった時に、Userクラスにプロパティ増やした上でNameConverterクラスも修正しないといけないけど、3番目のコードだと意味的にまとまりがあるクラスで区切ってあるから、Userクラスだけの修正で済む
複雑な事象に対抗する手段は抽象化なので、出来る限りクラスの抽象度を高めて細かいことを考えなくてもいい作りであってほしいですね!
まとめると
メソッドと変数のスコープは可能な限り狭くしてね
という話です!