酒問屋の在庫問題 - 初期クラス図にテクニカルな改良を加える
UMLモデリングの本質 (日経ITプロフェッショナルBOOKS)の内容に書いてある順番で、改良を検討してみる。
① 同種の関連を汎化によって整理する
前回完成した初期クラス図を見る限り、同種の関連はなさそうなので、
特にクラス図に手を入れる必要はなさそう。
② 関連クラスで履歴を記録する
次は、誰がどのような注文を行ったかを記録できるようにするために関連クラスを作る。
それぞれの関連に書いてある関連名をそのまま、以下のようなクラスに変える。
"発注する" ⇒ "発注"
"受注する" ⇒ "受注"
"入荷する" ⇒ "入荷"
"出荷する" ⇒ "出荷"
┌────┬┐ │在庫数量└┤ │が不足する│ └─────┘ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ 発注 │ │ 品目 │ │ 受注 │ ┌───┤ ├────┤ ├────┤ ├───┐ │ │ │ │ │ │ │ │ ┌──┴──┐└─────┘ └──┬──┘ └─────┘┌──┴──┐ │酒メーカー│ 1│カテゴリー │ 小売店 │ │ │ │ │ │ │ │ │ │ │ └──┬──┘ │* └──┬──┘ │ ┌─────┐ ┌──┴──┐ ┌─────┐ │ │ │ 入荷 │ │ 酒 │ │ 出荷 │ │ └───┤ ├────┤ ├────┤ ├───┘ │ │ │ │ │ │ └─────┘ └─────┘ └─────┘ │ │ │ │ ┌──────┬┐ ┌──────┬┐ │入荷希望日 └┤ │納品希望日 └┤ │までに入荷する│ │までに出荷する│ └───────┘ └───────┘
よくわからないが、関連につけていたメモは関連クラスにそのままつけておくことにする。
あとは、関連クラスそれぞれに多重度を付ける。
┌────┬┐ │在庫数量└┤ │が不足する│ └─────┘ │ │ ┌─────┐ ┌─────┐ ┌─────┐ *│ 発注 │* 1..*│ 品目 │1..* *│ 受注 │* ┌───┤ ├──────┤ ├──────┤ ├───┐ 1│ │ │ │ │ │ │ │1 ┌──┴──┐└─────┘ └──┬──┘ └─────┘┌──┴──┐ │酒メーカー│ 1│カテゴリー │ 小売店 │ │ │ │ │ │ │ │ │ │ │ └──┬──┘ │* └──┬──┘ 1│ ┌─────┐ ┌──┴──┐ ┌─────┐ │1 │ *│ 入荷 │* 1..*│ 酒 │1..* *│ 出荷 │* │ └───┤ ├──────┤ ├──────┤ ├───┘ │ │ │ │ │ │ └─────┘ └─────┘ └─────┘ │ │ │ │ ┌──────┬┐ ┌──────┬┐ │入荷希望日 └┤ │納品希望日 └┤ │までに入荷する│ │までに出荷する│ └───────┘ └───────┘
品目は、1つの発注(受注)に対して複数存在することもありえるため"1..*"とした。
酒に関しても同じ理由で"1..*"とした。
『酒メーカー−発注−品目』のオブジェクト図は以下のとおり。
┌───┐ │ :品目├───┐ └───┘ │ │ ┌───┐ │┌───┐ ┌──────┐ │ :品目├───┼┤ :発注├───┤ :酒メーカー│ └───┘ │└───┘ └──────┘ │ ┌───┐ │ │ :品目├───┘ └───┘
③ 関連の汎化クラスを作る
図書館の例では、本と会員の間の"借りる"と"返却する"の関連を汎化して、
"貸し出し"クラスを導出している。
酒問屋の問題だと、"借りる"と"返却する"と同じような関係になっている関連はないようなので、図には手を加えないことにする。
発注と入荷、受注と出荷が汎化できるかと思ったけど、受注・発注が品目と、入荷・出荷が酒と関連をもつため、汎化はできないと判断。
④ ロールを確認する
ロールがクラスになっていないかをチェックする。
が、これも特にクラス図に手をいれる必要はないと思われる。
⑤ 多重度を確認する
図を検討しながら多重度を書いていたので、ここでは特に多重度は検討しない。
あとは、今分かる範囲での属性と操作を加える。
とりあえず、入荷希望日・在庫数量・納品希望日を属性として追加してみることにする。
まずは、入荷希望日から考える。
入荷希望日は、酒問屋が酒メーカーに発注を行った時点で発生するので、発注の属性とする。
納品希望日も同様に、受注が行われた時点で発生するので、受注の属性とする。
在庫数量に関してはどこかの属性になるのだろうか?
考えてみる。
問題文には、
受注した商品の在庫数量が、納品希望日において不足しないかどうかを確認する
とある。
まず、酒の在庫数量は、品目オブジェクトにつながっている酒オブジェクトの数を
数えればわかる。
ただ、この数え方だと、現時点での在庫数量のことを言っているに過ぎない。
実際に欲しい数量は、納品希望日の在庫数量である、
つまり、
現在の受注オブジェクトに関連している品目と同じ品目をもつ受注オブジェクトを探し、
納品希望日が現在の受注オブジェクトより前の日付であれば、その注文数量を現時点での在庫数量から引く。
これを"品目が同じ and 納品希望日が前の日付の受注オブジェクト"がなくなるまで繰り返していく。
と、納品希望日の在庫数量が取得できる。
在庫数量は属性じゃなくて、操作にした方がよさそう。場所は品目かな。
上記の内容を考えていたら、品目と受注の間の多重度が、『1..*−*』であることが邪魔に感じてきた。
上記検討で、受注オブジェクトでは、品目を何個注文したかを記録するための注文数量が必要であることがわかった。
単純に、注文数量という名前の属性を受注クラスに追加してしまえばよいとおもったけど、品目と受注の多重度が
『1..*−*』であるため、受注オブジェクトで品目別に複数の注文数量をもつ必要がでてしまう。
この多重度を『1−*』に変えられないだろうか。。
つまり、1つの受注では、1つの品目のみ取り扱い可能ということだから、
例えば、小売店が1回の注文で複数の品目を注文してきた場合。。
同じ納品希望日をもつ受注オブジェクトを品目の数だけ生成される。と。
オブジェクト図は以下のようになる。と。
┌───┐ ┌───────────┐ │ :品目├───┤ :受注 ├──┐ └───┘ │納品希望日=04/05/01 │ │ └───────────┘ │ │ ┌───┐ ┌───────────┐ │ ┌────┐ │ :品目├───┤ :受注 ├──┼─┤ :小売店│ └───┘ │納品希望日=04/05/01 │ │ └────┘ └───────────┘ │ │ ┌───┐ ┌───────────┐ │ │ :品目├───┤ :受注 ├──┘ └───┘ │納品希望日=04/05/01 │ └───────────┘
うん、問題なさそう。多分。
これと同じ考え方で、
- 品目と発注
- 酒と入荷
- 酒と出荷
と、いろいろ考えてわかんなくなってきそうなので、一旦ここまでの内容をまとめた図を書いてみる。
┌─────┐ ┌────────────┐ ┌─────┐ *│ 発注 │* 1│ 品目 │1 *│ 受注 │* ┌───┤─────├─────┤────────────├─────┤─────├───┐ │ │入荷希望日│ │────────────│ │納品希望日│ │ 1│ └─────┘ │任意日付の在庫数量を取得│ │注文数量 │ │1 ┌──┴──┐ └─────┬──────┘ │受注日 │┌──┴──┐ │酒メーカー│ 1│カテゴリー └─────┘│ 小売店 │ │ │ │ │ │ │ │ │ │ │ └──┬──┘ │* └──┬──┘ 1│ ┌─────┐ ┌──┴──┐ ┌─────┐ │1 │ *│ 入荷 │* 1│ 酒 │1 *│ 出荷 │* │ └───┤ ├────────┤ ├─────────┤ ├───┘ │ │ │ │ │ │ └─────┘ └─────┘ └─────┘
今日はここまで。