日報管理システム-モデリング①

どうも、iwanaga です。

これは何?

エリック・エヴァンスのドメイン駆動開発を読み中。

残念ながらあまり理解できず、なかなか読み進まない。
あるあるなのかもしれないが、例があまりにもわかりづらすぎる。
海運?なにそれ、おいしいの?

このまま読んでても何も変わらない気がしたので、実際に手を動かしてみることにした。
というわけで、以前開発していた簡単な Web アプリケーションのドメインモデリングを再度行ってみる。
(たぶん本記事内に完結しない気がするが…)

ターゲットは『土日を充実させるために朝起きようぜ遊び』を管理するシステム、通称「日報管理システム」だ。
開発者である私自身もユーザであるため、開発者とドメインエキスパートが同じ人、という特殊なケースではある。

ルール

  • 毎週土曜日と日曜日に日報を提出する

    • 各提出日 9:30 までに提出する

    • 提出対象者は全ユーザ

  • 提出に失敗したユーザはペナルティ (¥1,000) を払う

    • ペナルティを払うタイミングは任意

  • 提出日の前日に 25:00 まで起きていた場合は(酷なので)事前に申請すれば免除

基本的なユースケース

  • (ユーザは 3 人)

  • ユーザは日報を提出できる

  • ユーザは自身のペナルティ数を知ることができる

  • 免除申請ができる

モデリング

「ユーザは日報を提出できる」から考え始める。

日報とは?
→その日の予定を指す。TODO リストのようなもの。歴史的経緯からこの呼称になっている。
→ TODO リストなのであれば TODO リストと呼ぼう。

User : TodoList = 1 : 0..n
TodoList : Todo = 1 : 1..n

// これで提出はできそう
class User {
  public submitTodoList(todoList TodoList) {
    todoList.save()
  }
}

日付がないといつの TODO リストかわからなくない?
→たしかに。1 提出日のうちに複数個の TodoList を提出することはあるか?
→ない。

User : TodoList = 1 : 0..n
TodoList : Date = 0..n : 1
TodoList : Todo = 1 : 1..n

// どうだろう
class User {
  public submitTodoList(todoList TodoList) {
    todoList.save()
  }
}

class TodoList {
  public save() {
    this.todos.each(todo => todo.save(this.date))
  }
}

たしかに TODO リストは Date の TODO リストではあるんだけど違和感あり
提出日が根幹である。「提出日にユーザが提出できたかどうか」が重要であって「その TODO リストの日付がいつか」というのはあまり重要じゃない。
というか、ぶっちゃけ提出するのものはなんでもいい。TODO リストじゃなくてもいいのだから。
→なるほど、提出日というか提出した日かな?あと、提出物が変わる可能性があるのかな?提出物の一例が TODO リストなのかな?
→うーん、もはや提出しなくてもいいかも。所定時刻(今は 9:30)までに起きていることが元々のルールだからね。スマートメガネで瞼が開いているかを確認する方法でもいい。
→なるほどね、ただ、それでも判定するためには、所定時刻までに「何かしら起きている証拠」を提出する必要がありそうだね。ここでは「所定時刻以前に何かを提出すること」をターゲットとしよう。
→そうね、スマートメガネが直接「起床失敗」を加算しても良いけどそれは、また別システムの話になりそうだね。ということは、これは「起床証拠提出/判定システム」ということになりそうな気がしてきた。
→あれ、ということは提出者がユーザ以外になることもありえるのか?例えばスマートメガネが独自に…という
→スマートメガネはわからんけど、目的が「起床」である以上人間ではありそうだからこのままでもいいかも
→だとすると、User がちょっと微妙かもね。提出者じゃないユーザがいるかもしれない?
→それはいない。このシステムに傍観者を存在させてはならない。だから、User = Submitter は成り立つけど、 Submitter = User は必ずしも成り立つわけではないかも。
→であれば、Submitter の一形態としての User の方が良いね。
→ということは、このシステムは「提出者が起床証拠を提出し、それを判定するシステム」っぽい。起床証拠じゃない証拠があるかな?
→例の「免除」がそれかもしれないけど、今日は考えないようにしておく。

User extends Submitter : SubmitDate = 0..n : 0..n
User extends Submitter : TodoList extends GetUpEvidence = 1 : 0..n
TodoList : Todo = 1 : 1..n

class Executer { 
  // この辺は適当
  public do(submitterType, submitterId, getUpEvidence) {
  // ...
    submitter = SubmitterFactory.create(submitterType, submitterId)
    submitter.submit(today, getUpEvidence)
}

class User extends Submitter {
  // override
  public submit(date SubmitDate, getUpEvidence GetUpEvidence) {
    getUpEvidence.save(date)
  }
}

class TodoList extends GetUpEvidence {
  // override
  create(date SubmitDate) {
    this.todos.save(todo => todo.save(date))
  }
}

良さそうに思える、じゃあ実際にコードを書いてみるか…


今日はここまでです。
…こんな感じ?開発者兼ドメインエキスパートをやっていると二重人格になりそう。
二人とも仲良さそうで良かったのが唯一の救い。

続きはまた書きます。

この記事が気に入ったらサポートをしてみませんか?