ドメインオブジェクトとドメインモデルについて
はじめに
以前からドメイン駆動開発に関心があり、参考書を調べていく中で『現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法』に行きつきました。
ここでは書籍の一部の要約であったり、学習を通しての私なりの考えを述べせて頂きます。
ドメインとは
goo辞書では以下の通りになっています。
ドメイン【domain】
①範囲。領域。
②インターネットやイントラネット上で、サーバーを中心にコンピューターをグループ化して、それぞれを識別できるようにしたもの。例えば、shogakukan.co.jpというドメイン名で一つのドメインを表す。
③企業などが事業活動を行う範囲。「ドメインを設定する」とは、会社が自らの活動範囲を明示することを表す。
④生物分類学で界の上に位置する最上位の分類群。古細菌・真正細菌・真核生物の三つのドメインがある。このうち真核生物ドメインは原生生物・菌・植物・動物の四つの界に分類される。超界。
引用元:goo辞書
とのことですが、ドメインオブジェクト及びドメインモデルの「ドメイン」は業務に関する事だと考えています。(例:稟議書作成・提出、有給休暇申請・受理など)
ドメインオブジェクト
業務の事柄が落とし込まれたオブジェクト
以下の二つからなります。
- 業務に関するデータ(申請日、生年月日など)
- 業務に関するデータを操作、加工するメソッド(生年月日から年齢を算出する)
getter及びsetterからなるデータクラスでは値の加工などの処理が呼び出し側で実装することになり処理が重複してしまいます。
ドメインオブジェクトを実装することで値の加工などはドメインオブジェクトが担当するため処理が重複することがないです。また、加工処理が 仕様変更になった際には変更箇所がドメインオブジェクトだけになるため影響を最小限にすることができます。
例 有給休暇申請クラスを作成
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
// 有給申請クラス
class YoukyuuShinsei{
// 申請者
private Shinseisya shinseisha;
// 申請内容
private ShinseiNaiyou shinseiNaiyou;
YoukyuuShinsei(Shinseisya shinseisha,ShinseiNaiyou shinseiNaiyou){
this.shinseisha= shinseisha;
this.shinseiNaiyou = shinseiNaiyou;
}
// 申請者の名前を取得
public String getShinseisyaName(){
return this.shinseisha.getShinseisyaName();
}
// 申請ステータス取得
public String getSinseiStatus(){
return this.shinseiNaiyou.getStatus();
}
// 申請日を取得
public String getShinseibi(){
return this.shinseiNaiyou.getShinseibi();
}
// 申請内容を取得
public String getShinseiNaiyou(){
return this.shinseiNaiyou.getShinseiNaiyou();
}
}
// 申請者クラス
class Shinseisya{
// 申請者の名前
private String name;
Shinseisya(String name){
this.name = name;
}
// 申請者の名前を取得
public String getShinseisyaName(){
return this.name;
}
}
class ShinseiNaiyou{
// 申請日
private LocalDateTime shinseibi;
// ステータス区分
private String statusKubun;
// 申請内容
private String shinseNaiyou;
ShinseiNaiyou(String statusKubun,String shinseiNaiyou){
this.shinseibi = LocalDateTime.now();
this.statusKubun = statusKubun;
this.shinseNaiyou = shinseiNaiyou;
}
// ステータス区分をステータスに変換して返却
public String getStatus(){
switch(this.statusKubun){
case "1":
return "申請中";
case "2":
return "承認";
case "3":
return "差し戻し";
default:
return "";
}
}
// 申請日をyyyy/MM/ddで返却
public String getShinseibi(){
DateTimeFormatter datetimeformatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String shinseibi = this.shinseibi.format(datetimeformatter);
return shinseibi;
}
// 申請内容を返却
public String getShinseiNaiyou(){
return this.shinseNaiyou;
}
}
ドメインモデル
ドメインオブジェクトの依存関係を整理したものを指します。
ドメインオブジェクトは他のドメインオブジェクトと依存して存在しています。
上記のソースコードでは有給申請オブジェクトが申請者オブジェクトと申請内容オブジェクトに依存しています。
また、依存性の向きが実際の業務流れとリンクしています。
ドメインオブジェクト、ドメインモデルのメリット
コードの可読性や仕様の理解を高める。
業務の事柄をオブジェクトに落とし込む際にクラス名やメソッド名を業務の用語をそのまま使用します。
用語をクラス名などに使用することで、そのオブジェクトがどの業務に関連しているのか判断できます。
また、業務変更があった際にどのオブジェクトに影響があるのか把握しやすくなります。
業務の事柄をオブジェクトに閉じ込めているため、業務変更によりオブジェクトを改修する際は他オブジェクトへの影響を最小限に抑えることができます。
コードの重複を防ぐことができる。
前述した通りドメインオブジェクトは「業務に関するデータを操作、加工するメソッド」を持っています。
これにより、各呼び出し元は値を加工する処理を実装する必要がなくなり処理の重複を防ぐことができます。
仮に値をそのまま返すgetterを実装した場合、各呼び出し元で値を加工する処理を実装することになり処理が重複してしまいます。
課題点
業務の分析が必須
質の高いドメインオブジェクトまたはドメインモデルを作成するにはエンジニアは業務の専門用語の理解や業界知識が必要になってきます。専門用語や業界知識を得るためには顧客に対する傾聴力であったり理解を曖昧なままにしないことが求められます。特によく知られている専門用語について、我々が理解しているつもりになっていて実際は意味が全く異なるケースもあるので認識齟齬がない様にしなくてはいけないと考えています。
まとめ
ドメインオブジェクト、ドメインモデルを用いることで可読性及び保守性の高いアプリケーションを作成することができます。しかし、業界の専門用語や業界知識が必要になるため自身で勉強したりチーム内に業務に対する有識者が必要になると感じました。
一方で、業務や業界の理解において異業種からキャリアチェンジされたエンジニアの方の経験が活かせるのではないかと考えています。
Discussion