AdventureWorksをモデリングしてDDDしながらドメインモデルで実装してみる(2)
前回の補足
識別子からエンティティ候補を分析している表に区分という項目があり「イベント」「リソース」などと記述してます。これがエンティティの種類をあらわしているのはある程度想像してもらえると思っています。ただ、「汎用」や「ルール」など少し一般的ではない種類も記述しています。これらはエンティティではなくValue Objectで、意味的な分類をさらに加えて記述しています。
区分のデータ分類としては以下のように考えてください
概念モデルのエンティティを分析する
概念モデルのエンティティ(以後概念エンティティ)はビジネスフローなど大きな粒度な仕組みの記述に向きますが、より具体的なビジネスの構造やルールを説明するためには粒度が大きすぎます。概念エンティティを分析して構造を整理することでビジネス用語を定義しルールを記述可能にします。
まずは、リソースエンティティの従業員(Employee)エンティティを分析して構造化してみます。
従業員(Employee)エンティティに関係するテーブルを探すには識別子であるEmployeeIDを持つテーブルを探します。目視で探しても良いのですが、既にDBがあるので直接スキーマを検索する方が手っ取り早いです。以下のSQL分でEmployeeIDをもつテーブルの一覧が手に入ります。
SELECT distinct sys.tables.name FROM sys.columns LEFT OUTER JOIN sys.tables ON sys.columns.object_id = sys.tables.object_id WHERE sys.columns.name like '%EmployeeID%'
検索結果から得られたテーブルは以下の通りです。
- Employee
- EmployeeAddress
- EmployeeDepartmentHistory
- EmployeePayHistory
- PurchaseOrderHeader
- JobCandidate
テーブルでのEmployeeIDの利用形態をヒントに関連テーブルを分析します。ここでもPKの構造を頼りにいろいろ探っていきます。
EmployeeはEmployeeIDがPKそのものになっているので主要なテーブル本体になります。
EmployeeAddressはPKの一部で他の識別子とのペアなので組み合わせをあらわしています。AddressはValue ObjectであるのでここではEmployeeの一部を表す多対多の関連を保持するためのテーブルと判断できます。
EmployeeDepartmentHistoryとEmployeePayHistoryはともにPKの一部で日付との複合になっています。集約関係にありタイムスタンプを持つことから内部イベントとして判断します。もちろんテーブル名から変更履歴→事実→イベントと判断しても良いでしょう。
PurchaseOrderHeaderはFKとして利用しています。PurchaseOrderHeaderはイベントであるためもの−ことの関係になります。リソース側にあたるEmployeeは参照される側になるのでPurchaseOrderHeaderは取り扱わないようにします。PurchaseOrderHeader(イベント)側で分析するようにします。
最後のJobCandidateではFKとして利用されていますが、JobCandidateはリソースであるためリソース−リソースの関係になります。JobCandidateとEmployeeのインスタンスのライフサイクルを比べると包含関係が成り立たないのでJobCandidateがEmployeeの内部的なエンティティではなく独立性が高いものです。*1
さらに主テーブルのEmployeeから参照しているテーブルも分析すると住所(Contact)を参照していることがわかります。
これらを整理すると以下のような構造になります。
次回Employeeエンティティをリッチ化していきます
*1:これ以上の分析は必要ないかもしれませんが、JobCandidateとEmployeeの関係をもう少し分析すると、EmployeeIDがNULL許可で後で設定される前提で、JobCandidateのEmployeeIDが設定されるタイミングが従業員(Employee)が作成されたタイミングと考えるとJobCandidateのなかに採用決定イベントが混在している構造と考えることができます