ドメインモデルとは


「ドメインモデル」という言葉を見て、最初はドメインって何?と考えてましたが、調べていると「ドメイン」単体に大きな意味を求めるのではなく「ドメインモデル」という概念を理解するのか重要だと思うようになりました。

一応言葉の確認

ドメイン
全体の中に定義される部分領域。特に、インターネット上に定められた部分領域を言う。ネット上の住所に当たる。

グーグル日本語辞書(Oxford Languages)

後半の URL のドメインのイメージが強いので混乱しますが、「ドメインモデル」においては前半の「部分領域」という意味で使われます。

モデリングとは、ある物体や事象について着目している特徴や、同種の複数の対象に共通する性質を抽出し、些末な細部を簡略化した抽象的な模型(モデル)を作成すること。

モデリング(モデル化)とは – 意味をわかりやすく – IT用語辞典 e-Words

モデルの説明ではないのですが、こちらの方が理解しやすいと思うので「モデリング」の意味を引用しました。「抽象的な模型」という部分がモデルの意味です。ソフトウェア開発中に詳細を簡略化して手を抜いているつもりはないですが、完璧なものを追求するとコストがかかりすぎるので、簡略化した抽象的な模型を作っていると言えばそうなのかもしれません。

ここまでの知識を合体させると、「ドメインモデル」は「全体の中に定義される部分領域を簡略化した抽象的な模型」という事になりますが、「ドメインモデル」の言葉の定義は別であります。

ドメインモデルとは

振る舞いとデータをカプセル化した、ドメインのオブジェクトモデル。

ドメインモデル – Martin Fowler’s Bliki (ja) (bliki-ja.github.io)

これだけだと難しいのですが、私たちが作りたいのは「業務アプリケーション」であることから、ドメインというのは「業務全体のうちソフトウェアとして実現する部分領域」ということになると思います。そのドメインをオブジェクト指向で表現したものをドメインモデルと言うようです1表現方法はオブジェクト指向言語ではなくてもいい気がしますが、「ドメインモデル」と言う言葉はオブジェクト指向界の外ではあまり聞きません。他では単にモデルやモデリングと呼ぶ印象です

すべての業務をオブジェクトとして表現し、オブジェクト内のデータの公開は最小限とし(カプセル化)、データの変更はオブジェクトに定義されたメソッドを経由して実施します。

どこまで標準データ型を利用し、どこから独自クラスとして定義するかはオブジェクト指向純粋主義2どこかの本で見た表現だと思ったのですが、とりあえずネット上ではここ者レベルによるところが大きいようです。最高レベルになるとプリミティブ型1つであってもクラス定義したくなるらしいですが、それはやりすぎだと思います。

ドメインモデルを採用するか

ドメインモデル以外の設計パターンとしてはトランザクションスクリプトというものがあります。トランザクションスクリプトはユーザーからのリクエストを、手続き型で記述されたプロシージャで処理するような設計パターンです。

ドメインモデルパターンを採用するメリットとしては、変更に強いしなやかな設計になるという点です。デメリットとしては設計にかなり頭を使うので時間がかかるという事です。

トランザクションスクリプトのメリットは、簡単に実装できるという点です。デメリットは長い処理による寿命の長い変数や、重複コードが発生しやすく、保守性が低下するところです。

このことから、新規開発した後に改修がほぼ発生しない場合はトランザクションスクリプトパターン、新規開発は最小限で後から機能を追加していく場合はドメインモデルパターンが適していると考えられます。もちろん、どちらか一方にしなければいけないことはないので、場合によって使い分けるのがよいと考えられます。

ドメインモデルを構築する

ドメインモデルの構築について語り出すとブログ記事一本には収まらなくなるので、おすすめの書籍を紹介します。

ドメインモデル構築の考え方として有名なのはドメイン駆動設計 (DDD) です。 Evans 本とも呼ばれる「エリック・エヴァンスのドメイン駆動設計」で説明されています。「実践ドメイン駆動設計」(IDDD)には Evans 本の内容を具体的にどう設計に反映するかが書かれています。

あまりお金をかけずに概要を知りたいという場合は「Domain Driven Design(ドメイン駆動設計) Quickly 日本語版」がおすすめです。

読む価値があるのは確かなのですが、上記の書籍は難易度が高いです。設計だけでなく要件分析や実装の経験もある程度ないと読み解くのが難しいと思います。内容としては思想的な部分が大きいので、手順書のようなものを求めている場合はおすすめしません。

ドメインモデル貧血症

ドメインモデル貧血症の基本的な症状は、一見、それが本物のドメインモデルに見えるという点です。… ただし、オブジェクトの振る舞いを見れば違いが分かります。それらのオブジェクトにはわずかな振る舞いしかない、ということに気づくと思います。

ドメインモデル貧血症 – Martin Fowler’s Bliki (ja) (bliki-ja.github.io)

ドメインモデルのアンチパターンとして、ドメインモデル貧血症 (Anemic Domain Model) というものがあります。

例としてブログ記事 (BlogPost) という RDBMS のテーブルがあるとし、そのテーブルのデータ構造をクラスとして定義してみます。

class BlogPost {
    private Long id;
    private String title;
    private Status status;
    // ...

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }

    public Status getStatus() { return status; }
    public void setStatus(Status status) { this.status = status; }

    // ...
}

ただの getter と setter の集合です。ふるまいが一切ありません。

オブジェクト指向ではデータと振る舞いが同居し、外部に公開する必要がないものはカプセル化(情報隠蔽)できるところに価値があります。例えば、 DB で使用する id が代理キー3サロゲートキーの場合は自動採番であり手動では設定しないため、 setId を public にする必要はありません。ステータス (Status) を非公開から公開に変更する場合は、 SNS に新着記事について投稿したり、ブログ記事検索機能へ記事追加イベントを通知するふるまいが必要かもしれません。

CRUD するだけの仕様だとこういったオブジェクトを作ることになるかもしれませんが、CRUD + 認証・認可だけでいいならばそれ用の製品を活用した方が安価に済むはずです。そもそもアプリケーションを自作する必要があるのかという点から考えるべきかもしれません。

話が少しそれますが、こういったオブジェクトを DTO と呼ぶケースがあります。DTO はリモートサーバー(ここでは DB)との通信上の都合4通信量削減といった理由で関連性の低い複数のオブジェクトの情報を一つにまとめたり、あまりいいとは言えない通信相手側のデータ構造に合わせたりするで、しかたなく作る少し汚いオブジェクトです。リモートとの通信ではなくアプリケーション内部でこのようなオブジェクトをやり取りするのはローカル DTO というアンチパターンです。

余談

開発をしていると、何かを成し遂げるには実現方法が複数あって、それぞれのメリット・デメリットを吟味してどの手法を使うかを決定する、という決定タイミングが多く訪れます。これをやっておけば OK という銀の弾丸はなく、選択肢には常に「場合による」という注意書きが記されています。

1つの方法にすがるとそのデメリットによって失敗する可能性が増えるので、選べる選択肢は複数あった方がよいと思います。ドメインモデルも選択肢の一つにできるように努力していきたいです。

追記

(2024/1/20) ドメインは単純に分野と訳すのがいいなと思いました。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください