この記事の趣旨
データベーススペシャリスト試験に出題される基本的な問題の1つが、データベースの設計、すなわちER図を完成させる問題である
エンティティ同士を関係(リレーションシップ)を表す際のルールが決まっている
- ER図のエンティティにおいて、"多"側のエンティティに矢を付ける
この記事の趣旨は下記のとおり
- 矢をどこに付ければよいか、よく混乱する
- 混乱と向き合って、矢印の向きを腹落ちさせたい
リレーションシップにおける"矢"とは
IPAの過去問から一部キャプチャしたものを掲載する
"1対多"のリレーションシップを表す線は、"多"側の端に矢を付ける
画像出典:過去問題(問題冊子・配点割合・解答例・採点講評) - IPA
クラス図の矢/ER図の矢
普段はプログラムを書いているので、クラス図に慣れている
- オブジェクト指向で仕様を決めるとき・・クラス図
一方で、データベーススペシャリスト試験では、その名の通りデータベースを設計するためのER図が使われる
- データベースを設計するとき・・ER図
クラス図とER図の比較をすることで、矢印混乱問題が解けるかもしれない
実際の過去問をモデルケースに図を書く
IPAの過去問を参考にモデル化してみる
注文、注文明細、商品の3つのエンティティの関係をクラス図/ER図/リレーションシップで表す
クラス図
- 注文は注文明細を取りまとめる
- 注文明細は1つの商品の個数や小計を取りまとめる
- 商品は単独で存在できる
依存の矢印はよりドメイン寄り、ユーザーから遠い不変のものへ向いていくイメージ
ER図/リレーションシップ
これをリレーションシップで表すと、"多"側の端に矢を付けて下図のようになる
まさに過去問の答えのとおりのER図になる
クラス図とリレーションシップの比較
比較のために、クラス図とリレーションシップを並べる
- 左のクラス図では、注文明細から商品へ矢印が向いている
- 右のリレーションシップでは、商品から注文明細へ矢印が向いている
この矢印の逆転が冒頭の混乱を招いている
解決へ
ここからは混乱を解消するための話
自分を納得するためにいろいろと理由をこじつける
【検証1】クラス図とリレーションシップの共通点
先のクラス図とリレーションシップの関係を比較して気づいた点として
注文と注文明細の関係性は、どちらも矢印の位置が同じであったということ
クラス図でList<T>
に書き下しても不自然でない関係は、共通した矢印になる
※ 商品に注文明細履歴リストを付与することでも機能は実現できるかもしれないが、設計上不自然であるので却下される
(例)
全体 | 部分 | 部分が持つ外部キー |
---|---|---|
学校 | List<生徒> | 学校名 |
注文 | List<注文明細> | 注文番号 |
商品 | List<SKU> | 商品ID |
【検証2】クラス図とリレーションシップの相違点
-
クラス図
- 明細は商品を参照したい、だから商品に向かって矢印を引いている
-
リレーショシップ
- 明細からみたら、商品は1つ
- 商品からみたら、何度も注文されるので、明細は複数
この矢の矛盾をどう整理すべきか・・・
ドメイン側が複数になる
顧客も加えてみた。
顧客や商品などのドメインよりのオブジェクトは単数になると考えられる(かなり強引だが・・)
注文はユースケース寄りで、複数回実行される。動詞。
一方の顧客や商品は名詞であり、ユースケースに参照される側
この"参照"を頭に思い浮かべたときにクラス図よろしくドメイン側に矢を付けるのではなく、「いやいや今はER図の話だからその逆をいく」と考える
顧客と注文はリストで表せる
顧客は注文履歴をListで持っていても不自然ではないので
その考えであればリレーションシップと矢の位置が一致する
【検証3】記法の違い
多重度を表す記法には、鳥の足のようなIE記法と、丸印のIDEF1X記法があるらしい1
どちらも多重度が"多"の方になんらかの印がつく(鳥の足or丸印)
リレーションシップに用いられる矢印も同じで、"多"の方に付けられる
すなわち、矢印を矢印と思わず、なんらかの印と思うことで
なんらかの印は常に"多"につくと思い込めばいい
さらには、なんらかの印がついた方には、もう片方への外部キーが存在する、とまで思い込んでしまってよいかもしれない
そもそも多いものは繰り返しを生じさせて正規化を妨げるから外に追いやられたのであり、追いやられた側は元居た場所への参照=外部キーがないと生きていけないのだから。。。
E-R図においてエンティティ間の多重度が"1対多"であるとき、それを関係データベースに変換すると、"1"側のエンティティが主キー属性を持つ表、"多"側のエンティティが外部キーを持つ表になります。
引用元:データベーススペシャリスト平成28年春期 午前Ⅱ 問6
まとめ
- クラス図において
List<T>
で表すことができるなら、リスト化されるほうに矢をつける -
List<T>
で表すと不自然な場合(商品と注文明細)、ドメイン側は単数になる。すなわちドメインと逆側に矢がつく - 印がついた側のエンティティには単数側への外部キーをもつ