本ページはプロモーションが含まれています

IT全般

ドメイン駆動設計入門の書評|仕事でDDDを使う前に読んで、コードの書き方を4つ変えた

CATEGORY
REV.
DRAWN BY
TOM
SHEETS
8枚
ドメイン駆動設計入門(読んでコードを4つ変えた)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

仕事でドメイン駆動設計(DDD)を使うことになり、基本を押さえるために読んだのが『ドメイン駆動設計入門』です。

結論から言うと、DDDをこれから現場で使う人が、最初に読む1冊に合います。値オブジェクトから始めて、エンティティ、リポジトリ、集約へと、分かりやすいパターンから順に積み上げていく作りです。

私にとっては、値オブジェクトからアーキテクチャの話まで、ほとんどの章が役に立ちました。読んでから、コードの書き方を4つ変えています。その4つを、説明用のJavaのコードで見せながら書きます。

ドメイン駆動設計入門はどんな本か

書名ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本
著者成瀬允宣
出版社翔泳社
発売2020年2月
ページ数・定価392ページ(A5判)/3,960円(税込)
電子版あり

書誌情報と目次は、紀伊國屋書店のページに載っている出版社内容情報によるものです。出版社の紹介では、『エリック・エヴァンスのドメイン駆動設計』や『実践ドメイン駆動設計』をこれから読む人、読んだけれど、もう少しやさしい入門書がほしい人に向けた本とされています。

本で扱うパターンは、出版社の紹介で次の3つに分けられています。

分かりやすいパターンから、発展的なパターンへ
1
KNOWLEDGE / 知識の表現知識を表現するパターン値オブジェクト・エンティティ・ドメインサービス
2
APPLICATION / アプリの実現アプリケーションを実現するパターンリポジトリ・アプリケーションサービス・ファクトリ
3
ADVANCED / 発展より発展的なパターン集約・仕様
NOTE分け方は出版社内容情報によります。

目次は「ドメイン駆動設計とは」から始まり、「システム固有の値を表現する「値オブジェクト」」「ライフサイクルのあるオブジェクト「エンティティ」」と、パターンごとに章が分かれています。後半は「アプリケーションを1から組み立てる」「アーキテクチャ」と、組み合わせ方の話に進み、最後は「ドメイン駆動設計のとびらを開こう」で終わります。

読んだきっかけ|仕事でDDDを使うことになった

LOG今の職場DDDでコードを刷新することになった

今の職場で、DDDを使ってコードを刷新することになりました。現場で使う前に基本を押さえておきたくて、読んだのがこの本です。

役に立ったところ|ほぼ全部の章

役に立った章を挙げると、ほぼ全部になります。値オブジェクト・エンティティ、ドメインサービス・アプリケーションサービス、リポジトリと依存関係のコントロール、集約と仕様、そしてアーキテクチャの章です。

それぞれのパターンを、私の言葉で一言にするとこうなります。

パターン一言で例
値オブジェクト意味のある値を、専用の型にする会員ID、金額、メールアドレス
エンティティIDで見分ける、状態が変わるもの会員、注文
ドメインサービスどのエンティティにも置きにくい業務ルール会員の重複チェック
アプリケーションサービスユースケースの手順をまとめる退会する、プランを変える
リポジトリ保存と取り出しを、業務ロジックから切り離す会員を保存する・IDで探す
ファクトリ複雑な作り方をまとめる採番が必要な注文の作成
集約一緒に整合性を守る、まとまりの単位注文と注文明細
仕様複雑な条件を、1つのオブジェクトにするおすすめ対象の会員の条件

「一言で」と「例」は、本の文章ではなく、私がまとめ直したものです。

読んでから変えたこと|コードの書き方を4つ変えた

読んでから、コードの書き方を4つ変えました。職場のコードは載せられないので、ここでは考え方が同じになるように書いた、説明用のJavaのコードで見せます。

4つの変更を入れたあとの、層の役割
依存はドメインへ
PRESENTATIONプレゼンテーション画面・APIの入り口
APPLICATIONアプリケーションサービスユースケースの手順(取り出す → 頼む → 保存する)
DOMAINドメイン値オブジェクト・エンティティ・ドメインサービス・リポジトリのインターフェース
INFRASTRUCTUREインフラリポジトリの実装(SQL・DBの都合)
NOTE筆者の整理です。インフラはドメインのインターフェースを実装するので、依存の向きはドメインに向かいます。

1. 値オブジェクトを使うようになった

会員IDや金額を、StringやintのままにせずMemberIdやMoneyという専用の型にするようになりました。取り違えをコンパイルで防げて、不正な値は作った時点で弾けます。

// 値オブジェクトを使わない書き方
public void changePlan(String memberId, int monthlyFee) {
    // 会員IDの代わりに注文IDの文字列を渡しても、コンパイルは通ってしまう
    // monthlyFee にマイナスが入っても、ここでは気づけない
}
// 値オブジェクトを使う書き方
public record MemberId(String value) {
    public MemberId {
        if (value == null || value.isBlank()) {
            throw new IllegalArgumentException("会員IDが空です");
        }
    }
}

public record Money(int amount) {
    public Money {
        if (amount < 0) {
            throw new IllegalArgumentException("金額がマイナスです");
        }
    }

    public Money add(Money other) {
        return new Money(amount + other.amount);
    }
}

public void changePlan(MemberId memberId, Money monthlyFee) {
    // 型がちがうので取り違えられない。不正な値は作った時点で弾かれる
}

2. 業務ロジックをドメインに寄せた

「停止中の会員は退会できない」のような業務の判断を、Serviceではなく、会員(エンティティ)に書くようにしました。Serviceが判断を持つと、同じ判断があちこちのServiceに散らばりやすくなります。

// 業務の判断がServiceに書かれている
public class MemberService {
    public void withdraw(Member member) {
        if (member.getStatus() == Status.SUSPENDED) {
            throw new IllegalStateException("停止中の会員は退会できません");
        }
        member.setStatus(Status.WITHDRAWN);
        memberRepository.save(member);
    }
}
// 業務の判断を、会員(エンティティ)に寄せる
public class Member {
    private final MemberId id;
    private Status status;

    public void withdraw() {
        if (status == Status.SUSPENDED) {
            throw new IllegalStateException("停止中の会員は退会できません");
        }
        status = Status.WITHDRAWN;
    }
}

// アプリケーションサービスは、取り出して・頼んで・保存するだけ
public class WithdrawMemberService {
    public void handle(MemberId id) {
        Member member = memberRepository.find(id);
        member.withdraw();
        memberRepository.save(member);
    }
}

3. 業務の言葉をクラス名にした

クラス名やメソッド名に、業務で使っている言葉をそのまま使うようにしました。上の例なら、データを消す「delete」ではなく、業務の言葉の「退会(withdraw)」です。コードを読んだときに、業務の話と1対1で対応するようになります。

4. リポジトリでDB処理を分けた

データの保存と取り出しをリポジトリにまとめ、業務ロジックからSQLを追い出しました。ドメイン側にはインターフェースだけを置き、実装はインフラ側に置きます。

// ドメイン側に置くのは「何ができるか」だけ
public interface MemberRepository {
    Member find(MemberId id);
    void save(Member member);
}

// SQLやDBの都合は、インフラ側の実装に閉じこめる
public class JdbcMemberRepository implements MemberRepository {
    // ...
}

業務ロジックがDBに依存しないので、テストのときはリポジトリを差し替えるだけで済みます。この依存の向きの考え方は、本の「柔軟性をもたらす依存関係のコントロール」の章の話で、Javaでの書き方はDI(依存性の注入)とはにもまとめています。

今のレベル別の読み方

パターンごとに章が分かれているので、今の自分に合わせて読む章を決めやすい本です。

今の自分読む章ねらい
DDDという言葉を聞いたばかり「ドメイン駆動設計とは」→「値オブジェクト」→「エンティティ」まず値オブジェクトとエンティティの違いを押さえる
仕事でDDDを使うことになった「リポジトリ」→「アプリケーションサービス」→「依存関係のコントロール」→「アプリケーションを1から組み立てる」層の分け方と、1つのアプリにまとめる流れを知る
基本は分かっていて、設計を深めたい「データの整合性を保つ」→「ドメインのルールを守る」→「仕様」→「アーキテクチャ」集約・仕様と、全体の組み立て方を知る

向いている人・向いていない人

  • 向いている人:仕事でDDDを使うことになった人。エヴァンスの本を読む前に、やさしい入門書で全体をつかみたい人
  • 向いていない人:DDDの戦略的な設計(境界づけられたコンテキストなど)を深く学びたい人。目次を見る限り、パターンの実装が中心の入門書です

あわせて読みたい

読んだ本はほかにも、トムの本棚に並べています。

よくある質問

Q. エヴァンスの『ドメイン駆動設計』とどちらを先に読むべきですか?

出版社の紹介では、この本はエヴァンスの本をこれから読む人や、読んだけれどもう少しやさしい入門書がほしい人に向けた本とされています。DDDが初めてなら、この本で全体をつかんでから進むと入りやすいです。

Q. DDDのパターンは全部使わないといけませんか?

この本自体が、実践が難しいものは後回しにして、分かりやすいパターンから入る作りです。まずは値オブジェクトのように、今のコードにも入れやすいものから始められます。

Q. 電子版はありますか?

あります。紀伊國屋書店のページでも、電子版ありと案内されています。

REVISIONS / 改訂履歴
REV.DATE内容
22026-10-16図解を描き直し(図面のデザインにそろえた)
12026-10-12初版
NEXT STEP
今のコードで、Stringのまま渡しているIDを1つ選んで、値オブジェクトにしてみてください。

コンストラクタで空チェックを書くだけの小さなクラスで十分です。取り違えがコンパイルで止まるようになると、値オブジェクトのありがたさが分かります。

NEXT READ本棚から1本

AIで開発を組み直すなら、まずこの5冊から

入門・実践・設計まで、Claude Codeの本をレベル別に5冊選んで比べました。

→ おすすめ5冊を見る

  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

IT全般 ・