🍳
[Ruby] Factory methodで凝縮性の高いclassを作成する
ECサービスなどで新規入会の無料ポイントやプレミアム会員向けの特別ポイントなどを
管理するGiftPointのclassを作成する場合、以下のように作成もできます。
前に作成した記事[Rubyで保守性の高いClassの基礎的な書き方]
参照元は以下の書籍になります。
コードレベルでの設計についてキャッチアップしているので、
備忘録として、適宜アウトプットしていきます。
良いコード/悪いコードで学ぶ設計入門―保守しやすい 成長し続けるコードの書き方
class GiftPoint
MIN_POINT = 0
attr_accessor :point
def initialize(point)
raise "Point cannot be less than or equal to zero" if point <= MIN_POINT
@point = point
freeze
end
def add(point)
raise "Point to be added must be greater than zero" if point <= 0
return GiftPoint.new(@point + point)
end
end
上記のように作成してしまった場合、クラスからインスタンを生成する際のパラメーターとしてポイントを渡す必要があるため、普通の買い物に付随するポイント付与なら許容できますが、
新規入会の無料ポイントやプレミアム会員向けの特別ポイントなど、
固定のポイント付与ロジックをインスタンスの生成時に付与すると凝縮性が下がってしまい、最悪キャンペーン終了後にコードが残って、意図した挙動にならないケースも出てくる。
#呼び出し時
NEW_MEMBER_POINT = 3000
NewMembershipPoint = GiftPoint.New(NEW_MEMBER_POINT)
PREMIUM_MEMBER_POINT = 1000
PremiumMembershipPoint = GiftPoint.New(PREMIUM_MEMBER_POINT)
上記を改善するためにaddメソッドをpraivateのfactoryメソッドに変更して、
クラス外から直接呼び出すための、クラスメソッドとしてNewMembershipPoint、PremiumMembershipPointを作成するようにする。
class GiftPoint
MIN_POINT = 0
NEW_MEMBER_POINT = 3000
PREMIUM_MEMBER_POINT = 1000
attr_accessor :point
def self.new_membership_point
return GiftPoint.new(NEW_MEMBER_POINT)
end
def self.premium_membership_point
return GiftPoint.new(PREMIUM_MEMBER_POINT)
end
def add(point)
raise "Point cannot be less than zero" if point + @point < MIN_POINT
return GiftPoint.new(point + @point)
end
private
def initialize(point)
raise "Point cannot be less than zero" if point < MIN_POINT
@point = point
self.freeze
end
end
上記ののようにprivateのコンストラクターとクラスメソッドで外から呼び出し可能なfactoryで、
凝縮性を上げるようにすることができます。
Discussion