💬
Rubyで保守性の高いClassの基礎的な書き方
最近以下の書籍を読んで、コードでの設計についてキャッチアップしているので、
備忘録として、適宜アウトプットしていきます。
良いコード/悪いコードで学ぶ設計入門―保守しやすい 成長し続けるコードの書き方
オブジェクト指向言語だとRubyが慣れているので、Rubyでアウトプットします。
書籍に記載のある例を利用するとamountとcurrencyのインスタンス変数と金額を変更できるaddメソッドを持つ、Money Classを作成してくださいと言われた場合、以下のようなコードを書いてしまいがちですが、保守性が低くバグの温床になる可能性があります。
class Money
attr_accessor :amount, :currency
def initialize(amount, currency)
@amount = amount
@currency = currency
end
def add(amount, currency)
raise "Cannot add different currencies." if @currency != currency
@amount += amount
end
end
上記の場合だと初期化時に以下のように意図しない値が入り込んでしまう可能性があるし、
amountで保持している金額が可変のため、値を直接変更できてしまい、今いくらかどうかをわからなくなってしまうデメリットがあるそうです。
# マイナス円でも初期化できてしまう。
money = Money.new(-100, 'USD')
そこで初期化時にvalidationを追加して、initializeするようにして、
可変にしたくない金額については、不変にして新しいインスタンスを返すようにして、
値の直接代入をできなくすると、変更が限定的にできるのできるそうです。
class Money
attr_accessor :amount, :currency
def initialize(amount, currency)
if amount < 0
raise ArgumentError.new('0以上の値を指定してください')
if currency.nil? || currency.empty?
raise ArgumentError.new('通貨を指定してください')
@amount = amount
@currency = currency
self.freeze #不変にする
end
def add(amount, currency)
raise "Cannot add different currencies." if @currency != currency
added = @amount + amount
return Moeny.New(added, @currency) #不変なので新しいインスタンスを返すようにする。
end
end
Discussion