Skip to content

ドメイン駆動設計入門:ドメイン駆動設計とは?初心者向け完全ガイド

本記事は以下の書籍を参考にしています。 ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本 | 翔泳社 Shoeisha

はじめに

ドメイン駆動設計(DDD)に興味を持って本を手に取っても、初心者にとっては概念が難しくすぐには理解しにくいのが現実です。

本記事では、「ドメイン駆動設計とは何か」を噛み砕いて解説します。業務知識をどのようにコードへ反映するのか、ドメインモデルとは何か、値オブジェクトとエンティティの違いなど、実践的な内容を扱います。記事の流れは、まず基本概念の説明、次にドメインモデルの具体例、最後にドメインオブジェクトをコードとして表現する方法を取り上げます。

なお、本記事はシリーズの一部です。全ての記事を通して読んでいただくことで、DDDの考え方がより深く理解できる構成になっています。

ドメイン駆動設計における基本的な考え方

ソフトウェア開発で重要なのは、顧客の業務領域を理解し、実際の課題を解決することです。プログラミングのスキルだけでは不十分で、業務の仕組みやルールを把握しなければ適切な設計はできません。

とはいえ、あらゆる知識を覚える必要はありません。証券システムの例では、「株の歴史」は開発に役立ちませんが、「成行注文と指値注文で処理が変わる」「約定は取引所の規則で決まる」といった業務知識は設計に直結します。

このように、必要な知識と不要な知識を見極めることが重要です。ドメイン駆動設計(Domain-Driven Design, DDD)は、業務に関わる本質的な知識を抽出し、それをモデルとしてコードに反映するための方法論です。

価値ある情報を選び取り、概念として整理し、ソフトウェアに落とし込むことで、システムは顧客の課題を解決する有効な道具になります。

ドメインモデルの理解と抽象化の実践

ドメインモデルの定義と役割

ドメインモデルとは、業務の知識を抽象化し、ソフトウェアとして扱いやすくしたものです。つまり「具体的なものを抽象的にすること」を意味します。証券システムであれば株式注文を表すモデルが該当し、注文数量、注文価格、注文種別といった具体的な要素を持ちます。

HRシステムでは勤務記録を表すモデルが中心となり、出勤時刻、退勤時刻、残業時間といった具体的な要素で構成されます。このように、業務領域ごとに必要な知識を整理し、コードとして表現できる形に抽象化することがドメインモデルの役割です。

ドメインオブジェクトによる知識のコード化

抽象化されたドメインモデルをプログラムで表現したものが「ドメインオブジェクト」です。その中でも基本となるのが、値オブジェクトとエンティティです。

値オブジェクト(Value Object)は、特定の値や属性を表します。証券システムでは「株数量」や「金額」、HRシステムでは「勤務日付」や「勤務時間」が該当します。値オブジェクトの重要な特徴は、不変であることです。

エンティティ(Entity)は、一意のIDを持ち、時間が経過しても同じ存在として扱われます。証券システムでは「注文」、HRシステムでは「社員」がエンティティに該当します。エンティティは可変である点が値オブジェクトと異なります。

以下の図は、値オブジェクトとエンティティの関係性を示しています。


classDiagram
class Entity {
  +String id
  +識別子を持つ
  +可変
}

class Order {
  +String id
  +String symbol
  +Quantity quantity
  +Price price
}

class ValueObject {
  +値に意味がある
  +不変
  +交換可能
}

class Quantity {
  +Int value
}

class Price {
  +Double value
}

Entity <|-- Order
ValueObject <|-- Quantity
ValueObject <|-- Price

Order --> Quantity
Order --> Price

以下は、証券システムの「注文」を表現したシンプルな例です。


// 値オブジェクト
data class Quantity(val value: Int)
data class Price(val value: Double)

// エンティティ
data class Order(
    val id: String,         // エンティティを識別するID
    val symbol: String,     // 銘柄
    val quantity: Quantity, // 数量(値オブジェクト)
    val price: Price        // 価格(値オブジェクト)
)

ここでQuantityやPriceのような小さな概念を値オブジェクトとして切り出すことで、「数量は0以下ではならない」「価格は負の値を取らない」といった振る舞いを値オブジェクトに対して実装することができます。

具体例から学ぶドメインモデルの設計

ドメインモデルとは、現実の事象や業務知識を抽象化し、ソフトウェアとして扱いやすい形に整理したものです。「モデル」とは現実をすべて忠実に再現するものではなく、必要な部分だけを切り取って表現します。何を残し、何を省くかは、そのシステムの対象ドメインによって決まります。

証券システムにおけるドメインモデル

証券システムで「株式注文」を考えてみましょう。株式注文という行為をすべて表現しようとすると、証券取引所の制度や市場の歴史など膨大な情報が出てきます。しかし、システムに必要なのは、実際に取引を成立させるための最小限の要素です。

具体的には、注文数量、注文価格、注文種別(成行、指値など)が該当します。Kotlinで表すと次のようになります。


enum class OrderType { MARKET, LIMIT }

data class Order(
    val id: String,
    val quantity: Int,
    val price: Double?,
    val type: OrderType
)

HRシステムにおけるドメインモデル

HRシステムで「勤務記録」を考えてみます。人事の世界では評価制度や人材開発といった多様な知識がありますが、勤怠管理システムに必要なのは勤務時間に関するルールです。出勤時間、退勤時間、残業時間が中心的な要素となります。

Kotlinで書くと以下のようになります。


data class WorkRecord(
    val employeeId: String,
    val clockIn: LocalDateTime,
    val clockOut: LocalDateTime
) {
    val workingHours: Duration
        get() = Duration.between(clockIn, clockOut)

    val overtime: Duration
        get() = workingHours.minusHours(8).coerceAtLeast(Duration.ZERO)
}

ここでは「1日8時間を超える勤務は残業」という業務ルールをコードに埋め込んでいます。これがまさにドメインモデルの役割であり、業務知識をそのままプログラムに反映しています。

ドメインモデル設計における重要なポイント

ドメインモデルは「顧客の業務領域をすべて再現する」のではなく「問題解決に必要な部分を抽象化して切り出す」ことが重要です。知識の取捨選択は顧客の課題と業務領域に依存します。モデルを作ることで、開発者と利用者が同じ言葉で問題を共有できるようになります。

以下の図は、ドメインモデルの抽象化プロセスを示しています。


flowchart TD
    A[現実世界の業務領域] --> B{必要な知識の選別}
    B --> C[注文数量]
    B --> D[注文価格]
    B --> E[注文種別]
    B -.不要な知識.-> F[市場の歴史]
    B -.不要な知識.-> G[企業の沿革]

    C --> H[ドメインモデル: 株式注文]
    D --> H
    E --> H

    H --> I[コード実装: Order クラス]

    style F fill:#f99,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5
    style G fill:#f99,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5
    style H fill:#9f9,stroke:#333,stroke-width:2px
    style I fill:#9cf,stroke:#333,stroke-width:2px

ドメインオブジェクトの実装と反復的な改善

ドメインモデルは「業務知識を整理した抽象化」にすぎません。これを実際にソフトウェアで動かすためにはオブジェクト化が必要です。ドメインオブジェクトとは、ドメインモデルをコードとして具体的に表現したものを指します。

反復的な改善によるモデルの進化

ドメインオブジェクトは一度作って終わりではありません。実際の業務は変化し続けるため、オブジェクトもそれに合わせてイテレーティブ(反復的)に改善する必要があります。

証券システムでは、新しい注文種別が追加される可能性があります。HRシステムでは、評価基準が数値から段階評価に変わることもあります。DDDでは、こうした業務上の変化をモデルとオブジェクトに反映させながら、システムを育てていく開発スタイルを取ります。

この反復的なアプローチにより、システムは常に業務の現実に即した形で進化し続けることができます。

終わりに

本記事では、ドメイン駆動設計(DDD)の基本概念について解説しました。業務知識を整理してコードに埋め込む設計手法としてのDDDは、複雑なシステムを長期的に保守していくために非常に有効です。ドメインモデルは現実の仕組みを抽象化したものであり、問題解決に必要な知識を切り出して表現します。

次の記事では値オブジェクトを深掘りしていきます。

参考文献

ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本(成瀬允宣著、翔泳社、2020年)

ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本 | 翔泳社 Shoeisha

Domain-Driven Design: Tackling Complexity in the Heart of Software(Eric Evans著、Addison-Wesley Professional、2003年)

https://fabiofumarola.github.io/nosql/readingMaterial/Evans03.pdf fabiofumarola.github.io

コメントを残す