jsug 20141127 「spring bootを用いたドメイン駆動設計」
DESCRIPTION
JSUGの勉強会で話をした際の資料です。TRANSCRIPT
株式会社マネーパートナーズソリューションズ
SpringBootを用いたドメイン駆動設計
風間 淳一郎
2014/11/27 JSUG勉強会
今回の実装サンプルはこちらで確認できます
https://github.com/jkazama/ddd-java
自己紹介
風間 淳一郎
株式会社マネーパートナーズソリューションズ システムマネジメント部部長。
Web系のシステム開発を経験した後、2004年より金融系の開発に従事。
2007年より現職。SpringFrameworkは2004年から利用。
GitHub: https://github.com/jkazama
Twitter: https://twitter.com/jkazama77
株式会社マネーパートナーズ
外国為替証拠金取引やCFD、有価証券買付けな
どを行っている金融事業者。
HP: http://www.moneypartners.co.jp
Spring利用経緯とSpringBootに至るまで
ドメインモデリング
ドメインモデリング実装例
アジェンダ
Spring利用経緯とSpringBootに至るまで
2008年 Spring2.5ベースでアーキを構築
ポータル/フロント/バック/各種情報配信、全てを同一
基盤で開発
今日紹介するドメインモデリングのアプローチを採用
大量のデータソース/多数のサービス結合/マルチプロ
セス(今だとマイクロサービス?)モデルに対応
その多くが大規模リニューアル無しに現在まで
細かい変更/保守開発が継続している状況。
Spring利用経緯とSpringBootに至るまで
2013年 新基盤の導入を検討
老朽化するJavaアーキテクチャと技術的閉塞感
(Java6ベース)
リファクタしても残る長大なコード、設定、保
守工数の増大
マルチチャネル対応の必要性(サーバ側のAPI化)
言語仕様の限界?
Spring利用経緯とSpringBootに至るまで
2014年8月 マネパカードサービス開始
ユースケース400over/他サービス連携も含めそ
れなりの規模を消化
新基盤を用いてコード量の軽減やAPIサーバモ
デルを確立
ドメインアーキや実装は既存のものをかなり流用
Spring利用経緯とSpringBootに至るまで
2014年8月 マネパカードサービス開始
サーバ側はJavaではなくScalaを採用 Rodも興味持ってたし…
コンパイル時間以外、大きな問題も発生せず
Spring利用経緯とSpringBootに至るまで
2014年8月 SpringBootの存在にようやく気づく
槙さんのSpringBoot紹介資料を拝見
SpringはSpringRooとかの流れとライブラリ
肥大化で勝手に終わったと思っていた
SpringBoot(Spring4) + Lombok + Gradleを組
み合わせる事でJavaでも効果的な開発は可能
どちらかというと終わっていたのは自分の方だった…
Spring利用経緯とSpringBootに至るまで
前置きはここまで
次からは今回サンプル題材とするドメインにつ
いて簡単に解説します。
ドメインモデリング
ドメイン概念自体はERモデリングの時代からある古い話です。
Javaの世界ではFowlerのPoEAA(2002)などで紹介された後、
EvansのDDD(2003)でうまいこと体系化されました。
※厳密にそうなのかはちょっと自信ないですけど。
上述の通り、かなり昔からある理論なのですが、内容が内容だ
けに実装解釈の幅は結構広いです。今回紹介するJava実装例は
あくまでその一事例としてご覧ください。
ドメインモデリング
想定ユースケース(単純な出金ワークフロー)
サービス事業者 金融機関
顧客 システム(ジョブスケジューラ)
[出金依頼]
[出金依頼締め] [出金指示ファイル出力]
[出金実現]
T T + n T + 3
依頼確定日(発生日)をTとします。
※取引じゃないですが、分かりやすいので…
ドメインモデリング
想定モデル
必要最低限の要素だけを定義。
入出金は振込に限らず振替や取引、両替
などからも生み出される。
ドメインモデリング
今回のサンプルで利用するレイヤリング
RESTfulAPI
UI層
Controller
アプリケーション層
Service
ドメイン層
Entity
インフラ層
DTO
DTO
SpringBoot Repository Library
ドメインモデリング
今回のサンプルで利用するレイヤリング
特徴
オーソドックスな三層モデルを利用、UI層は
APIベースのやり取りを想定
各層からインフラ層へのアクセスを許容
RepositoryとEntityの関係は1-1ではなく1-n
ドメインモデリング
モデリングはこんな感じで大雑把にしました
次からは実装例をお見せします。
ドメインモデリング実装例
実装コード前提
Java7以上でLombokを利用
ドメイン実装がシンプルに見えるよう各種ライブラリ
を用意済(後ほどGitHubでご確認ください)
項目定義や例外処理などはかなり省略してます
ドメインモデリング実装例
ドメイン層 – 振込入出金(CashInOut)> クラス定義/フィールド定義
@Entityを定義してJPA概念と紐付け
Lombokアノテーションで最低限の必要処理を追加
JpaActiveRecordを継承してCRUDをサポート
EntityではDIを用いない
Logger等、シリアライズする際に問題となるクラスを
インスタンス変数として持たない。
フィールドでは@IdでIDを明示化
制約アノテーションを用いてカラムドメイン定義を明示
必要に応じて@Embeddedでフィールドクラスを分割
@OneToMany等の関連定義は利用目的が抽象的になりが
ちなのと、レイヤリングアーキでLAZYロードに起因する
トラブルを解決するのが面倒なので利用していません。
※EAGERフェッチ前提で割り切れるならOK
ドメインモデリング実装例
ドメイン層 – 振込入出金(CashInOut)> 出金依頼(Entityを生成)
既存出金依頼は存在しないため、クラスメソッドで生成
営業日/日時、UID、設定パラメタなどは引数に取った
Repositoryを利用してインフラ層から取得
審査で問題なければ、関連情報を取得して振込入出金情報を永続化。
ドメインモデリング実装例
ドメイン層 – 振込入出金(CashInOut)> 出金依頼DTO
DTOはSerializableにしておく
Lombokアノテーションで最低限の必要処理を追加
UI層の入力チェックなどで利用されるのでフィールド単
位の制約定義はきちんと行う
ドメイン層のDTOは粒度をユースケース単位で細かく作成していく事を推奨します。
引数が3つ以上になり始めたらパラメタクラスの作成を考えてください。
※以降の引数追加要求にI/F変更無しで対応できるようになります。
ユースケース処理引数の粒度が粗ければ粗いほど、予期せぬ状態変更の副作用で苦しむ可能性が高くなります。
ドメインモデリング実装例
ドメイン層 – 振込入出金(CashInOut)> 制約アノテーション
制約アノテーションはデータモデリングにおけるドメインの解釈で
考えると分かりやすい(正規表現も利用可能)
フィールド単位の共有カラムドメインを切り出して定義していく
@NotNullを外して@AbsAmountEmptyなどのnull許容アノテー
ションを合わせて用意しておくと可読性が増す
BeanValidationでは制約定義の拡張が可能
ドメインモデリング実装例
ドメイン層 – 振込入出金(CashInOut)> レポジトリ層アクセサ(dh)
インフラ層のコンポーネントの中でドメイン層での利用を許可する
ものを束ねたユーティリティヘルパ
利用時はその特性上ネストアクセスが深くなりがちなので、なるべ
く短いメソッド名で公開
この他によく使われるコンポーネントは以下のようなものがある
- 営業日管理(休日概念やT+nの考慮)
- アプリケーション設定(オンライン中の動的変更にも対応)
- メッセージリソース(i18n)
ドメインモデリング実装例
ドメイン層 – 振込入出金(CashInOut)> 利用ドメインクラス
JPAの管理下に置かれないドメインクラス例
複数Entityを口座資産という大きい概念で束ねている
ドメインモデリング実装例
ドメイン層 – 振込入出金(CashInOut)> 出金依頼確定(自己の状態を変更)
既存出金依頼をload後に呼び出すユースケース処理
自身の情報を変更しつつ、依存する他Entityへ変更結果
を伝搬していく。
ドメインモデリング実装例
アプリケーション層 – 資産(AssetService)> クラス定義
@Serviceを定義してDIコンテナへ登録(シングルトン)
ServiceSupportを継承してアプリケーション層の共通的
な振る舞いを実装
Serviceではユースケース処理を記載していきます。基本的にControllerと1-1の関係となります。
Serviceにおけるユースケース処理はドメインのユースケース処理よりもより広義な解釈となっており、トランザ
クションや排他処理、メール送信や帳票出力、外接連携等の外部リソースと関連付く内容も含まれます。
※非機能要件のチューニングなどもアプリケーション層の責務に含まれます。
ドメインモデリング実装例
アプリケーション層 – 資産(AssetService)> サービス基底定義
アプリケーション層ではドメイン層と異なり、インフラ層
のコンポーネントとより密接に紐付きます。
メール送信や帳票出力などはドメイン概念が交じるので、
必要に応じてアプリケーション層でメール送信やレポート
出力のコンポーネントをラップします。
今回は用意していませんが、スレッドやメッセージング
を用いた非同期処理やマルチデータソースの管理なども
アプリケーション層の責務となります。
ドメインモデリング実装例
アプリケーション層 – 資産(AssetService)> 振込出金依頼
ユースケース処理では利用者行為の監査ログを残したり、
排他ロックやトランザクション制御などを行いつつ、ドメ
イン層のユースケース処理へ繋いでいく
非同期処理系は事前にトランザクションの確定保証が必要
(JTAや非同期系のトランザクション概念を混ぜない場合)
実行した際のコンソール出力例
ドメインモデリング実装例
アプリケーション層 – 資産(AssetService)> メール送信クラス
インフラ層の単純なMailHandlerを、アプリケーション層
でラップしてドメイン概念を加えている例
ドメインモデリング実装例
アプリケーション層 – 資産(AssetAdminService)> 振込出金依頼締め
ジョブスケジューラから呼び出される口座横断的な処理
冗長になりやすいので、トランザクション内部の処理は切り出し
対象を抜き出した後に必要処理を個別実施
ここではジョブ実行中のオンライン要求を許可する前提で実装し
ているので、口座単位にアカウントロックを掛けている
ここでのジョブは差分更新を許容したいので、失敗時は例外が上
位に飛ばないようにしている(個別例外はログ監視で検知)
※実際はもう少しトランザクション粒度を細かくすべき
ドメインモデリング実装例
UI層 – 資産(AssetController)> クラス定義/振込出金依頼
@RestControllerを定義してDIコンテナへ登録(シングルトン)
@RequestMappingでURLを紐付け
利用するサービスをDI
顧客向けなどでEntityが過剰に情報を持っている時(更新者や内
部管理項目 等)は表示用のDTOへ詰替え
引数DTOに@Validを付与する事で、事前にDTOで定義していた
カラムドメインの定義に応じたBeanValidationのチェックが発
生する
ドメインモデリング実装例
UI層 – ジョブ(JobController)> クラス定義/振込出金依頼締め
ジョブスケジューラから叩かれる際の受け口
ユースケース上の利用者はシステムとなる
戻り値を定義するかはジョブスケジューラの仕様に応じて
ドメインモデリング実装例
アプリケーション起動クラス
SpringBoot1.2ではこれだけ
@SpringBootApplicationは内部で@Configuration/
@EnableAutoConfiguration/@ComponentScanを呼び
出している
設定ファイルはXMLの代わりにこんな感じで
application.yml定義を書くだけ
通常のJavaアプリケーションとしてApplicationクラスを
実行するだけで、Tomcatを内包した常駐プロセスが起動
ドメインモデリング実装例
まとめ
SpringBootを利用することで記述量が減る
構造がシンプルになる分、ドメインに集中できる
Lombokを利用することで記述量が減る
実装の内容を考えると、Java8やGroovyを使うと
もっとシンプルにできる
導入の敷居の高さは会社毎に違うので今回はJava7前提
ドメインモデリング実装例
以上です、ご清聴ありがとうございました。
時間が残っていれば簡単なデモ見せます。
おまけ
自社で作っているものの簡単な紹介 [SpringBootベースのフレームワーク]
設計成果物を開発リソースへと繋ぐ。(開発立ち上げを早く!)
自動生成は支援ツールと割り
きって、単方向のみのサポー
トを想定
開発生産性の向上。エンタープライズ要件をシンプルに!
認証・認可
ビルド/リリース/運用を簡略化。
+ mpx-tools
プロセス 三層サポート
おまけ
自社で作っているものの簡単な紹介 [SpringBootベースのフレームワーク]
ライブラリはインフラ層のサポートをなるべく手厚く
ライブラリ群
日付/日時
POJO(BeanSupport)
設定
ログ 型変換
フォーマット 審査
スケジューラ 非同期 認証/認可
DB MQ
メール レポーティング
IDロック
監査/イベント/メールログ
ドメイン審査
i18n
利用者管理
Webサーバ MQサーバ
DIコンテナ(SpringBoot)
リモーティング
分散キャッシュ制御
スレッド管理
分散コンポーネント管理
おまけ
自社で作っているものの簡単な紹介 [SpringBootベースのフレームワーク]
マルチデータソース利用の例
おまけ
自社で作っているものの簡単な紹介 [SpringBootベースのフレームワーク]
使ってみたい方とか、基盤の仕組みに興味ある方はこちらまで問合せお願いします。
株式会社マネーパートナーズソリューションズ
営業担当:武田
03-4540-3890