【書評】ドメイン駆動設計 モデリング/実装ガイド
DDD の勉強をすべく、「ドメイン駆動設計 モデリング/実装ガイド」を読んだのでその書評を書く。
本書は DDD の概念部分がトップダウンで記述されています。DDDの概念を網羅しつつ、各概念の説明は必要十分な内容にとどめているため、比較的軽量な印象です。しかし、DDD自体の概念が非常に巨大なため、本書のボリュームは大きくなっています。
私のようなDDD初学者の最初の1冊として非常におすすめです。
DDD ってなんぞや?
DDD とは、「モデリングを中心とした設計手法」です。モデリングを重要な設計手法と位置づけ、コードレベルではモデルをどう活かすかを考えます。
モデルを活かす手法には私も同意です。個人開発でモデルオブジェクトを導入したことがあるのですが、その利便性の高さには驚きました。コードの可読性、ロジックの再利用、テストの書きやす際におていモデルは優れています。
コードの可読性は、いわゆるクラスの責務と関係しています。責務が明確であれば、処理を修正するときに対象のロジックがどのクラスに書かれているかがわかりやすくなります。逆にクラスの責務が曖昧だと、数あるクラスの中から目的のクラスを探しづらくなったり、想定外のクラスに影響が及んだりなど、開発の難易度が一気に上がります。
ロジックの再利用も利点です。複数のサービス層(ユースケース層)でロジックを使い回すことができるため、アプリケーション全体でコード量が減少します。
最後にテストの書きやすさ、これはピカイチですね。モデルのテストを書く場合、前提条件のセットが簡単です。インスタンスや構造体を生成して、必要なフィールドに値をセットするのみです。逆にサービス層(ユースケース層)のテストは大変です。複数のモデルやリポジトリに依存している場合が多いため、前提条件を整えることに苦労します。ロジックをモデルに寄せることによりテストの拡充が容易になり、より高品質なソフトウェアを作り上げることが可能です。
コードレベルの話を書いてしまいましが、DDDの本質は「モデリング」にあります。ソフトウェアで開発したい対象領域をどのようにモデル図で表現するかが重要です。このモデル図は開発者以外にも共有され、チーム全員がモデル図で認識をあわせて行動します。コードのモデルは、あくまでのモデリングの成果物を実装しているに過ぎません。
いかにモデリングを行うか、またモデリングを通してモデル図を更新するか。またモデル図の更新に応じてコードのモデルを変更し、他の依存するコードも素早く変更していくかが重要となります。
オニオンアーキテクチャ
「ドメイン駆動設計 モデリング/実装ガイド」では、数あるアーキテクチャの中からオニオンアーキテクチャをおすすめしていました。
今の現場でもまさしくオニオンアーキテクチャを採用しているのですが、本を通じてかなり納得することができました。本では既存のアーキテクチャ(三層アーキテクチャやレイヤードアーキテクチャ)の問題点を挙げ、その問題点がどのような形でオニオンアーキテクチャで改善されているのかという形式で説明されるため、三層アーキテクチャに馴染みある人であれば理解しやすい構成になっています。
オニオンアーキテクチャでは、以下の4層が存在します。
- プレゼンテーション層
- ユースケース層
- ドメイン層
- インフラ層
プレゼンテーション層
プレゼンテーション層は、アプリケーションの外部との通信を担当します。いわゆるコントローラーやハンドラーが存在する層です。
この層では、外部とのInput/Outputnoの変換を行います。
ユースケース層
ドメインオブジェクトを駆使して、ユースケースを実現する層です。いわゆるサービスやユースケースと呼ばれるものが存在する層です。
ここにはドメイン知識(業務ルール・業務ロジック)は配置されません。あくまでもドメイン知識はドメインオブジェクトに記述され、ユースケース層からはそれらのメソッドを呼び出すのみです。
このドメイン知識というのは、モデリングで発見されます。そのため、DDDはまずはモデリングなのです。
とわいえ私はモデリングの経験がないため、これ以上は語れず、、、。せっかく個人開発をやっていいるので今度トライしてみます。
ドメイン層
みんな大好き(?)ドメイン知識を配置する層です。ドメインオブジェクトやそのドメインオブジェクトを使用するクラスが存在します。
また、ここにはリポジトリのインターフェースも配置します。え?リポジトリのインターフェースはインフラ層じゃないの?と思われるかも知れませんが、オニオンアーキテクチャではリポジトリのインターフェースをドメイン層に配置するのです。
理由は各層の依存関係を保つためです。ドメイン層は他の層に依存しません。すなわち、ドメイン層からインフラ層へアクセスすることはなく、ドメイン層のオブジェクトは同じドメイン層の他のオブジェクトにのみ依存します。
しかし、ドメイン層からリポジトリを呼び出したい、、、我々は一体どうしたら良いのか、、、。この問題を解決するのがリポジトリのインターフェースのドメイン層への配置です。ここでは依存関係逆転の原則が適用されています。ドメインオブジェクトは、同じドメイン層にあるリポジトリのインターフェースにのみ依存します。その実装はインフラ層のリポジトリクラスで行われますが、依存はインターフェースのみに対して向かっているのです。
と書いていて思ったのですが、リポジトリを呼ぶケースとして、ドメイン層からリポジトリ呼ぶケースなくない?と思っていまいました。ユースケース層から直接リポジトリを呼ぶケースしか思い当たらないのですが、何か理解を見落としていそう、、、。うーむ、ドメイン層からリポジトリを呼ぶより詳細なコードがほしい。今後の課題とします。
インフラ層
インフラ層では、主にデータの永続化を担当します。DBとかストレージへのアクセスですね。いわゆるリポジトリが配置されます。
以上が、各層のざっくりとした理解と説明です。
最後に
私はこの本を読んでよかったと感じました。冒頭にも書きましたが、最初の1冊として適切だと思います。
DDDに尻込みしているみなさん、ぜひ買いましょう!「ドメイン駆動設計 モデリング/実装ガイド」
この次のステップとして、以下の書籍を上げていました。
1がボトムアップ・アプローチとのことで、本書との補完に丁度よさそうと感じました。2はケースごとの詳細が記述されているようなため、実際に運用した後に読むと良さそうです。
ではこれにて!良いエンジニアライフを!