はじめに
エリック・エヴァンスのドメイン駆動設計(2004)の第4章 「ドメインを隔離する」を読んで自分的に理解したことを書き出す
結構自分の考えと混じってしまってるので、ここに書いてあることイコール本の内容ではないです
自分の理解の足りないところやおかしいところはバシバシ突っ込んでもらいたいです
他のまとめ
- 第3章 「モデルと実装を結びつける」
- 第4章 「ドメインを隔離する」
- 第5章 「ソフトウェアで表現されたモデル」
- 第6章 「ドメインオブジェクトのライフサイクル」
- [第8章 「ブレイクスルー」] (https://qiita.com/mafuyuk/items/91fb0ecb667fbadeceff)
対象者
- 古いシステムからリプレイスする人
- リリース優先で作った際のリスクを見ておきたい人
- 設計をしていなくて雰囲気で物を作っている人
- エリック・エヴァンスの本を読むと抗えない眠気に襲われる人
ざっくりどんな話?
昔からソフトウェアシステムを分割する方法について議論されてきていた
その中で考えが収束してきており共通見解とみなされているのがLayered Architectureだ
Layered Architectureといっても標準的なパターンとして具体的に数個でてきていて
DDDの4章ではLayered Architectureに「ドメインを隔離する」ためにドメイン層を追加するパターンを要求している
いままではドメインが各レイヤーに分散されていて、ドメインに対しての意識が希薄になってしまっていたが、ドメインを隔離することで開発者はドメインに注力できるようになる
Architecture
4章の内容はアーキテクチャのLayered Architectureとレイヤーの各層についての話が主だと思ったので、その内容を深掘りします
また、アンチパターンとして紹介されていたSmartUIについても一応触れておきます
Layered Architecture
ソフトウェアシステムを分割する方法の1つ
レイヤに関しては様々なパターンがあるが、本質的な原則としてはレイヤ内のどの要素も、同じレイヤの他の要素かパターンで決められた依存関係のレイヤの要素にしか依存しない
クリーンアーキテクチャやオニオンアーキテクチャなどは層の依存関係が違ったりするので注意が必要
今回はあくまでDDD本におけるLayered Architectureって言うことを忘れないでください
他のアーキテクチャについての参考リンク: https://qiita.com/little_hand_s/items/2040fba15d90b93fc124
4章では4つの層に分けるパターンをDDDのエッセンスを加えたDDD本における標準的なパターンとして紹介していた
ユーザーインターフェース
ユーザに情報を表示して、ユーザのコマンドを解釈する責務を負う
ユーザに情報を表示の部分はHTMLやJSON、画像、動画、標準出力などがあたり、外部アクターは人間のユーザーだけではなく別のコンピュータシステムであることもある
この層を分割することによって、インターフェースの変更容易性が高くなる
たとえば、レスポンス形式をJSONからXMLに移行を行いたいとなった際などの移行は容易になる
JSONを返すAPI例
- HTTP通信のパス+メソッドを判別しルーティングを行う
- リクエストボディやパスパラメータのバリデーションなどを行う
- アプリケーション層の呼び出し
- レスポンスのJSONを構築し結果を返却する
アプリケーション
ソフトウェアが行う事になっている仕事を定義し、表現力豊かなドメインオブジェクトが問題を解決するように導く
ユースケースをあらわすことになる
やることとしては
- トランザクション管理
- ドメイン層、インフラストラクチャ層の呼び出し
ドメイン
ビジネスの概念とビジネスが置かれた状況に関する情報、およびビジネスルールを表す責務を負う
モデルとそのモデルに直接関係する設計上のすべての要素が現れる場所
UIやDBの処理などにドメイン関連のコードが書かれたり、ビジネスロジックにDBの処理などが混ざったりするのはよくあることなのだが、これは短期的にみて動くようにするには最も簡単な方法、しかしドメインに対して知識のない人がソースコードからドメインモデルを理解することは難しくなったりとドメインモデルの保守には向かないためドメイン層として分離して管理することでドメインの見通しを良くする
大事なことはドメインを隔離できる、それに尽きる
インフラストラクチャ
上位のレイヤを支える一般的な技術的機能を提供する
- アプリケーションのためのメッセージ送信
- キューイング
- メール
- シグナル
- etc...
- ドメインのための永続化
- ファイル書き出し
- データベース
- キャッシュ
- etc...
- ユーザーインターフェースのためのウィジェット描画
この層をわけることでMySQLからPostgreSQLへ変えたいといったことも他の層に影響を少なく実施できるようになる
Smart UI
相互に排他的な二者択一の分岐点でDDDのアプローチとは両立しない
DDD本 P74
と言われている通り、DDDにおけるアンチパターンです
本の中でSmart UIについて触れたのは、「ドメイン層を隔離する」が必要な理由とそれがどういう時なのかを明確にするためらしいのでそこに焦点を当ててみていきます
SmartUIは以下を守ることで実現できる
- すべてのビジネスロジックをユーザーインターフェースに入れる
- アプリケーションを小さな機能に分割し、それを独立したユーザーインターフェースとして実装し、ビジネスルールをその中に埋め込む
- RDBをデータ共有リポジトリとして使用すること
- ユーザーインターフェースの構築と視覚的なプログラミングのためのツールについては手に入る中で自動化がもっとも進んでいるものを使用する
Pros
(本で挙げられている中から一部抜粋)
- 単純なアプリケーションの場合、生産性が高く、すぐに作れる
- それほど有能でない開発者でも、この方法なら、ほとんど訓練しないで仕事ができる
- 要求分析が不足していても、プロトタイプをユーザに公開し、その要望を満たすように製品を変更することで問題を克服できる
- アプリケーションが互いに分離しているので、小さなモジュールの納品スケジュールは比較的正確に計画できる
- 関係データベースはうまく機能し、データレベルでの統合が実現される
- アプリケーションが引き継がれた場合、保守プログラマは自分が理解できない部分をすばやく作り替えられる
- 変更による影響がユーザーインターフェースの分離で限定されているから
Cons
- アプリケーションの統合は困難で、データベースを経由させるしかない
- ふるまいが再利用されることも、ビジネスの問題が抽象化されることもない
- ビジネスルールは適用先の操作それぞれで複製されることになる
- 迅速なプロトタイピングやイテレーションを行うとしても、自然と限界に行き当たる
- 抽象化がかけているためにリファクタリングの選択肢が制限されるから
Pros/Consを列挙してみました
DDDは難しくメンバーが有能(DDD本の文脈で)である必要があり、案件の把握やドメインモデル構築などで初速がでない、引き継ぎ時に引き継ぎ先が有能である必要がありかつドメインを理解する必要があり
- 人材レベル
- 工数
- ソフトウェア品質
という三軸でトレードオフする際に、DDDでは人材レベル高、工数高、ソフトウェア品質高と見た場合に対極に位置する手法
DDDについて理解を深めるために生まれたパターンであり、実際には軽量DDDや他の手法があるのでSmartUIを選択する必要はなさそうですね
最後に
- Layered Architectureについてざっくり理解しました
- DDDの文脈でいうとドメイン層を設けることが大事
上記を理解しました。ヤッタネ
自分の観測範囲では上の方であげたDDD本で紹介されたLayered Architectureをそのまま使っているところは見たことがなくクリーンアーキテクチャやオニオンアーキテクチャなどが使われているのかなーと思ってます。違いとしては責務が少し違ったり、依存関係の方向性が違ったりでそこまですごい差はないので是非Qiitaなどで調べてみたら良いと思います