DDDに基づいた、一つの実装を示すこと(DDDは設計思想なので具体的な実装方式は複数あり得ますが、私が考える最良の実装という意味)。
- DDDに準拠した設計方針
- 対象ドメインはペットストア
- Scala 2.11対応
- Play 2.5.x対応
- アプリケーションとしては REST like API
- ペットストア
- 原典は Java Pet Storeですが、独自にアレンジしている部分があります。
- 参考にした実装は mybatis/jpetstore-6
DDDのレイヤー化アーキテクチャに従い、次のとおりのレイヤーに分割します。
- アプリケーション層
- ドメイン層
- インフラストラクチャ層
もっとも重要なのは、メンタルモデルを反映したドメイン層です。 このドメイン層を、非ドメイン層の知識から侵蝕されることを防ぐために、隔離します。
ドメインの目的は、ペットストアの運営です。 ペットやペットフード、アクセサリーなどを仕入れて、顧客に販売するためのドメインです(仕入れの概念が現在ないので実装中です)。
- Customer Module = 顧客モジュール
- Customer (GE,A) = ペットストアの顧客
- StatusType (VO)
- CustomerProfile (VO)
- CustomerConfig (VO)
- Customer (GE,A) = ペットストアの顧客
- Item Module = 商品モジュール
- Purchase Module = 購買モジュール
GE = グローバルな識別子を持つエンティティ
VO = 値オブジェクト
A = 集約
とりあえず、重要なところだけSpecを書いています。
ここで重要なのは、モデルの表現(クラス名、属性名、振る舞いの名前(引数・戻り値も))にユビキタス言語以外の言葉を利用しないことです。
原則的に、これらの要素に、実装技術の言葉を含めてはいけません(実装技術の言葉を含めてしまうとメンタルモデルが離れていきドメインについて理解することが難しくなるため。ただし、StringやIntなどのデータ型や、ListやMap, Try, Option, Futureなどのコンテナ型は例外とする)。実装技術に関する知識は、アプリケーション層かインフラストラクチャ層に対応づけましょう。
- TODO
- 仕入れ先の導入
- 在庫の導入
- 商品モデルにサブ型を導入する
わかりやすくするために、特別なライブラリを用意せず、簡単な基盤コードを含めています。
- Entity = DDDにおけるエンティティの責務
- Repository = DDDにおけるリポジトリの責務
- RepositoryOnJDBC
JDBCに対応したリポジトリの骨格実装。ScalikeJDBCで実装。ちなみに、1エンティティが複数テーブルにマッピングされるような実装は今のところ作っていません。そのうち作ります。Specはこちら - RepositoryOnMemory メモリに対応したリポジトリの骨格実装。内部実装はMapですがRepositoryとして操作できる。Specはこちら
- RepositoryOnMemcached(TODO)
Memcachedに対応したリポジトリの骨格実装。 - CacheManagementRepository(TODO)
キャッシュのマネジメントを行うリポジトリ実装。
- RepositoryOnJDBC
- コントローラ(TODO)
- アプリケーションサービス(TODO)
- Play Framework 2.5.x
- Google Guice
- ScalikeJDBC 2.x
- play-circe
- nscala-time
- specs2
- mockito