ぱろっと・すたじお

技術メモなどをまったりと / my site : http://parrot-studio.com/

手持ちのアプリでドメイン駆動設計(DDD)を試してみよう〜導入編〜

きっかけは「WEB+DB PRESS」の記事なのですが・・・

WEB+DB PRESS Vol.113

WEB+DB PRESS Vol.113

・・・最近「ドメイン駆動設計(DDD)」の勉強をしております...φ(・ω・`)

今までも漠然と把握した「つもり」になっていたのですが、
今後のことを考えると、「正しい知識」を身につける必要があるな・・・と

結局のところ、原典にあたるしかないのですが・・

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

実践ドメイン駆動設計 (Object Oriented SELECTION)

実践ドメイン駆動設計 (Object Oriented SELECTION)

・・・これがですね、めっちゃ難しいんですよ(´-ω-)

DDDは「概念」というか「設計手法」であり、
「原典(=エリック・エヴァンスの〜)」を読み始めたものの、
わかりづらいので「実践」を読み始めたら、また「原典」に戻ってるというΣ(・ω・ノ)ノ

途中まで読んだだけでも間違いなくわかるのは、
今までやってきた「設計」は「業務を抽象化した設計になってない」ということです

あまりに「アーキテクチャ」や「インフラ」が中に入り込みすぎており、
「業務ロジック」がこれらの(本来であれば従属であるはずの)概念に、
だいぶ影響を受けてしまっています(´・ω・`)

まあ、実際それでも動作しているし、
多くのシステムは単純なCURDアプリケーションの組み合わせでいけるのですが、
今やっているような大きめのシステムを再設計するには、あまりに手法が弱すぎます

・・・というところまでは理解しても、
正直、どこから取りかかったものかさっぱりだったので、
WEB+DB PRESS」の記事を書いた方のBlogを参考にすることに

little-hands.hatenablog.com

とりあえず、ここを起点にいろいろ見ていくと、
なんとなく概要はつかめます(`・ω・´)

あとはこちらの同人誌とか

techbooster.booth.pm

基本的な概念に触れられており、
実際の現場を想定した例も載っている「本」なので、
こちらもおすすめです

(ただし、いずれにせよDDDに関しては「原典」に戻るしかない気はします
 用語とか初歩的な概念とか、だいたいは「原典」から引用され、
 そこからの発展的な話をしているので・・・)

それをふまえた上で、何をやるか、なのですが・・・

業務に導入するには敷居が高い技術を、
とりあえず試すために、私はいいものを持っています(`・ω・´)

ccpts.parrot-studio.com

github.com

ということで、まずは「チェンクロパーティーシミュレーター」(ccpts)の
設計を見直してみることに...φ(・ω・`)

ポイントは以下です

  • クライアント側を主体にDDDを適用する
    • ccptsの業務ロジックはクライアント側であり、サーバはデータを提供するだけなので
    • サーバAPIは「アルカナ検索」のコンテキストの一つとして考え、おそらくはリポジトリから呼ばれる
  • 実装にTypeScriptを使う
    • クライアントは元々TypeScriptで書かれている
    • TypeScriptならオブジェクト指向の機能をだいたい持っている
    • 設計から起こしたコードをそのままサービスに適用できる

ということで、軽く実装してみたドメインモデルがこちらです(´・ω・)っ


ccptsのドメイン設計 · GitHub


ccptsの主要な機能は「パーティーを編成すること」であり、
「アルカナを検索すること」はその支援機能なので、
「パーティー編集」がコアドメインで、「アルカナ検索」がサブドメインです

まずは「パーティー編集コンテキスト」に属するドメインモデルを考えて、
コードに起こしたものがgistの実装部分です

ポイントはいくつかあって・・・

  • ユビキタス言語」を意識して仕様を書いたので、実装に落としやすい
  • アルカナは集約ルートで、以下に大量の値オブジェクトを保持しているが、仕様に書かれてないので無視している
    • モデルの関連を仕様として記述するのが重要で、アルカナの構造は今回の範囲だと関係しない
  • 「値オブジェクト」として定義したモデルは、getterしか持ってない
  • 新たに「プレイヤーパーティー」の概念を導入したことにより、「同じアルカナを一つしかセットできない(ただしフレンドを除く)」の仕様がシンプルにカプセル化された
    • 以前はフレンドを除外するのに面倒なロジックを書いていた

・・・ざっくりこんな感じですか...φ(・ω・`)

元のコードは今までの経緯で継ぎ足してきたものなので、
ある程度整理されているとはいえ、どうしても業務ロジックが分散しています
それがUIや取得方法などと無関係に、モデルに制約や仕様が閉じた状態になりました

また、DDDの重要な概念である「ユビキタス言語」を意識して仕様を書いたので、
コードに反映させるのが簡単で、テストも何を書けばいいのか明らかになります(`・ω・´) b

あくまで「ドメインモデル」の範囲で適用しただけですが、
これだけでもなんとなく方向性は見えてきたので、
このドメインモデルを育てながら、本を読み進めてみます