【現場で役立つシステム設計の原則】データとドメインモデル

最近、現場で役立つシステム設計の原則をよみ直している

データベースにはコトを、ドメインモデルには業務ロジックを記述していく

このことを考えるとデータベースをアップデートすることは、マスターデータ以外はそうはなさそう

例えば、商品名は変更することはあるけども、購入データを変更することはない

購入したという事実をデータとして登録するだけだからね

わかりやすい例を書いてくれていた

年齢という関心事があると、年齢というクラスが必要になる

でも、データはコトなので生年月日が登録されている

Rubyだとこんな感じでしょうか

require 'date'

class Age
  def initialize(birthday)
    @birthday = DateFormatter.new(birthday)
  end

  def calculation
    difference / 10000
  end

  private

  def difference
    today.to_yyyymmdd - @birthday.to_yyyymmdd
  end

  def today
    @today ||= DateFormatter.new(Date.today)
  end
end

class DateFormatter
  FORMAT = '%Y%m%d'.freeze

  def initialize(date)
    @date = date
  end

  def to_yyyymmdd
    @date.strftime(FORMAT).to_i
  end
end

birthday = Date.new(1978, 5, 18)
age = Age.new(birthday)
puts age.calculation #=> 41

でわ、なぜドメインオブジェクトにロジックを書いたほうがいいのでしょうか?

例えば、人間とペットにはそれぞれ誕生日があります

人間クラスとペットクラスにそれぞれ年齢というロジックを実装してしまうと、同じロジックが重複してしまいます

そして、年齢計算ロジックが変更したい!とすると人間クラス、ペットクラスそれぞれを修正しないといけません

さらに、テストも重複してしまいます、、悲しいですね

そこに、ドメインモデルである年齢というクラスがあると、年齢の計算は一箇所に集約されて、テストも1つでOKですよね

担保する箇所が1つになるので、品質も向上します

そう、いいこと尽くめなのです!

コントローラやビューにロジックが書いてあるのを見つけたら、それに名前をつけてモデルに業務ロジックを移動させてみましょう

そうすると、年齢の仕様を確認するときは、年齢クラスを見ると明らかになります

明日はドメインオブジェクトの見つけ方を書いてみます