オブジェクト指向 ドメイン モデリングメモ

順不同。思いつたら更新。

ドメインオブジェクト

値オブジェクト、コレクションのラップ等が有名。
ビジネス用語の単位まで抽象化すること。

ビジネスロジックをクラス/オブジェクトで作っていくこと。

一般的にクラス/オブジェクトはテーブルと同じ粒度にすることが多い。どうやってビジネスロジックを表現するかと考えた時、クラス/オブジェクトで表現しなくても、手続き的な処理+DBで処理することもできるため。

単一責任とオープン・クローズ

継承はほぼ使わないのでこの2つ。

単一責任は、
変更が発生しそうな単位をクラスにするということ。

ただし、ドメインレイヤーに限定した場合、関心の単位、利用者が概念として、それを表現する言葉が存在している単位を意識する。

オープン・クローズは、
クラス間の依存をインターフェースへの依存にすること。派生クラスの追加で対応する。拡張ポイントと呼ぶ場合もある。

どちらも恣意的な要素であり、変更に対処していく単位を考えるということ。またどちらも手間が増えるので過剰にやらない。(アジャイル的には)発生してみないと分からないというのが答え。

レイヤー

適切にクラス分けしていけば最終的に自然とレイヤーに当てはまる形になっているのでそれほど意識しない。

DBモデリングメモ

・リレーションは要求によって変わる。業務上2つを結びつける必要があれば関連エンティティやFKが必要となる。2つを結びつける必要がないなら独立させて問題ない。

・コードに意味を持たせる場合(何行目が部署とか)変化に対して弱くなる。ただし、実際はコードに意味を持たせている会社が多い。

・1対多などの関係はnullを許容するかどうか考える。できるだけnullを使わないようにしておく。

・依存関係、FKがある方が依存している。依存している方が子。PKは重複できないけど、FKは重複できるので、FKある方が多。

・複合主キーとなっている関係従属を取り除く正規化は当たり前に発生するので、正しいモデリングをすると必然的に複合主キーが現れる。オブジェクトに合わせてサロゲートキーを入れる場合、制約はアプリ側で対応する。例えば仕入価格を、仕入先・商品・開始年月で識別するような場合。

・関連テーブルは多対多に必要とされているが、実務上は関連テーブルが先に思いついていることが多い。例えば予約処理のように、予約トランザクションが2つのマスタの関連を作り、予約されているかどうかでマスタの状態に影響を与えている場合もあれば、単純に2つのマスタを参照するだけという関連もある。

・リレーションの抽象化。将来的にカラムが増えそうだなと思うところは、トランザクションを経由させてデータの追加で対応できるようにしておく。

・売上単価のように参照されているマスタの値が変化した場合の履歴も必要というトランザクションデータの場合、トランザクションに転記してしまうか、マスタで単価変更履歴テーブルを別に持つか等の注意が必要。

・マスタデータではロールを別マスタにしないようにする。ただし、それぞれのマスタを違うグループが使う場合などあえて別にしたほうがいいこともある。

・参照整合性はそれほど重要ではない。実務では完全な制約が必要ではなく、緩い制約の方が都合がいいときもある。ただし、構造が壊れやすくはなるので注意。

・マスタは運用していくと、似たような値、使われていない値で膨張する。対策としては、マスタ作成時に図面番号が必要とか、業務フローと関連付けてしまう。

現在システム化されていない業務をシステム化する流れ。

個人的な方法。

まずその業務を紙ベースでやった場合を想像し、
・帳票で印刷したい、
・一緒に発生、収集される、
・再利用したい、
・またそれらの関連を整理するデータ、
等ベースにテーブル化する。

テーブル化したら、
・リレーションの設定、
・正規化、
・共通化(マスタ化)、
する。

基本はそのままオブジェクト化できる。

あとは、
・複雑なビジネスルール、
・ビジネス上特別な処理が必要なプリミティブな値、
等をクラス化する。

ビジネスルールは、UIやDBのマッピングオブジェクトから利用する形にする。

・レイヤーについて

アプリレイヤーまではハードコーディングしてしまい、以降のレイヤーはある程度抽象化しておく。

・クラス分けについて

GUIで機能の多いUIだと、アプリレイヤーのクラスも肥大化するので、そこは恣意的に一緒に変更される単位までクラス分けする。

・レイヤー間の依存について

通常レイヤー間は抽象化らしいが、規模が小さいので変更がなさそうならそのまま。