jsug 20141127 「spring bootを用いたドメイン駆動設計」

37
株式会社マネーパートナーズソリューションズ SpringBootを用いたドメイン駆動設計 風間 淳一郎 2014/11/27 JSUG勉強会 今回の実装サンプルはこちらで確認できます https://github.com/jkazama/ddd-java

Upload: jkazama

Post on 07-Jul-2015

3.912 views

Category:

Engineering


0 download

DESCRIPTION

JSUGの勉強会で話をした際の資料です。

TRANSCRIPT

Page 1: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

株式会社マネーパートナーズソリューションズ

SpringBootを用いたドメイン駆動設計

風間 淳一郎

2014/11/27 JSUG勉強会

今回の実装サンプルはこちらで確認できます

https://github.com/jkazama/ddd-java

Page 2: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

自己紹介

風間 淳一郎

株式会社マネーパートナーズソリューションズ システムマネジメント部部長。

Web系のシステム開発を経験した後、2004年より金融系の開発に従事。

2007年より現職。SpringFrameworkは2004年から利用。

GitHub: https://github.com/jkazama

Twitter: https://twitter.com/jkazama77

株式会社マネーパートナーズ

外国為替証拠金取引やCFD、有価証券買付けな

どを行っている金融事業者。

HP: http://www.moneypartners.co.jp

Page 3: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

Spring利用経緯とSpringBootに至るまで

ドメインモデリング

ドメインモデリング実装例

アジェンダ

Page 4: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

Spring利用経緯とSpringBootに至るまで

2008年 Spring2.5ベースでアーキを構築

ポータル/フロント/バック/各種情報配信、全てを同一

基盤で開発

今日紹介するドメインモデリングのアプローチを採用

大量のデータソース/多数のサービス結合/マルチプロ

セス(今だとマイクロサービス?)モデルに対応

その多くが大規模リニューアル無しに現在まで

細かい変更/保守開発が継続している状況。

Page 5: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

Spring利用経緯とSpringBootに至るまで

2013年 新基盤の導入を検討

老朽化するJavaアーキテクチャと技術的閉塞感

(Java6ベース)

リファクタしても残る長大なコード、設定、保

守工数の増大

マルチチャネル対応の必要性(サーバ側のAPI化)

言語仕様の限界?

Page 6: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

Spring利用経緯とSpringBootに至るまで

2014年8月 マネパカードサービス開始

ユースケース400over/他サービス連携も含めそ

れなりの規模を消化

新基盤を用いてコード量の軽減やAPIサーバモ

デルを確立

ドメインアーキや実装は既存のものをかなり流用

Page 7: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

Spring利用経緯とSpringBootに至るまで

2014年8月 マネパカードサービス開始

サーバ側はJavaではなくScalaを採用 Rodも興味持ってたし…

コンパイル時間以外、大きな問題も発生せず

Page 8: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

Spring利用経緯とSpringBootに至るまで

2014年8月 SpringBootの存在にようやく気づく

槙さんのSpringBoot紹介資料を拝見

SpringはSpringRooとかの流れとライブラリ

肥大化で勝手に終わったと思っていた

SpringBoot(Spring4) + Lombok + Gradleを組

み合わせる事でJavaでも効果的な開発は可能

どちらかというと終わっていたのは自分の方だった…

Page 9: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

Spring利用経緯とSpringBootに至るまで

前置きはここまで

次からは今回サンプル題材とするドメインにつ

いて簡単に解説します。

Page 10: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング

ドメイン概念自体はERモデリングの時代からある古い話です。

Javaの世界ではFowlerのPoEAA(2002)などで紹介された後、

EvansのDDD(2003)でうまいこと体系化されました。

※厳密にそうなのかはちょっと自信ないですけど。

上述の通り、かなり昔からある理論なのですが、内容が内容だ

けに実装解釈の幅は結構広いです。今回紹介するJava実装例は

あくまでその一事例としてご覧ください。

Page 11: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング

想定ユースケース(単純な出金ワークフロー)

サービス事業者 金融機関

顧客 システム(ジョブスケジューラ)

[出金依頼]

[出金依頼締め] [出金指示ファイル出力]

[出金実現]

T T + n T + 3

依頼確定日(発生日)をTとします。

※取引じゃないですが、分かりやすいので…

Page 12: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング

想定モデル

必要最低限の要素だけを定義。

入出金は振込に限らず振替や取引、両替

などからも生み出される。

Page 13: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング

今回のサンプルで利用するレイヤリング

RESTfulAPI

UI層

Controller

アプリケーション層

Service

ドメイン層

Entity

インフラ層

DTO

DTO

SpringBoot Repository Library

Page 14: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング

今回のサンプルで利用するレイヤリング

特徴

オーソドックスな三層モデルを利用、UI層は

APIベースのやり取りを想定

各層からインフラ層へのアクセスを許容

RepositoryとEntityの関係は1-1ではなく1-n

Page 15: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング

モデリングはこんな感じで大雑把にしました

次からは実装例をお見せします。

Page 16: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

実装コード前提

Java7以上でLombokを利用

ドメイン実装がシンプルに見えるよう各種ライブラリ

を用意済(後ほどGitHubでご確認ください)

項目定義や例外処理などはかなり省略してます

Page 17: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

ドメイン層 – 振込入出金(CashInOut)> クラス定義/フィールド定義

@Entityを定義してJPA概念と紐付け

Lombokアノテーションで最低限の必要処理を追加

JpaActiveRecordを継承してCRUDをサポート

EntityではDIを用いない

Logger等、シリアライズする際に問題となるクラスを

インスタンス変数として持たない。

フィールドでは@IdでIDを明示化

制約アノテーションを用いてカラムドメイン定義を明示

必要に応じて@Embeddedでフィールドクラスを分割

@OneToMany等の関連定義は利用目的が抽象的になりが

ちなのと、レイヤリングアーキでLAZYロードに起因する

トラブルを解決するのが面倒なので利用していません。

※EAGERフェッチ前提で割り切れるならOK

Page 18: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

ドメイン層 – 振込入出金(CashInOut)> 出金依頼(Entityを生成)

既存出金依頼は存在しないため、クラスメソッドで生成

営業日/日時、UID、設定パラメタなどは引数に取った

Repositoryを利用してインフラ層から取得

審査で問題なければ、関連情報を取得して振込入出金情報を永続化。

Page 19: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

ドメイン層 – 振込入出金(CashInOut)> 出金依頼DTO

DTOはSerializableにしておく

Lombokアノテーションで最低限の必要処理を追加

UI層の入力チェックなどで利用されるのでフィールド単

位の制約定義はきちんと行う

ドメイン層のDTOは粒度をユースケース単位で細かく作成していく事を推奨します。

引数が3つ以上になり始めたらパラメタクラスの作成を考えてください。

※以降の引数追加要求にI/F変更無しで対応できるようになります。

ユースケース処理引数の粒度が粗ければ粗いほど、予期せぬ状態変更の副作用で苦しむ可能性が高くなります。

Page 20: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

ドメイン層 – 振込入出金(CashInOut)> 制約アノテーション

制約アノテーションはデータモデリングにおけるドメインの解釈で

考えると分かりやすい(正規表現も利用可能)

フィールド単位の共有カラムドメインを切り出して定義していく

@NotNullを外して@AbsAmountEmptyなどのnull許容アノテー

ションを合わせて用意しておくと可読性が増す

BeanValidationでは制約定義の拡張が可能

Page 21: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

ドメイン層 – 振込入出金(CashInOut)> レポジトリ層アクセサ(dh)

インフラ層のコンポーネントの中でドメイン層での利用を許可する

ものを束ねたユーティリティヘルパ

利用時はその特性上ネストアクセスが深くなりがちなので、なるべ

く短いメソッド名で公開

この他によく使われるコンポーネントは以下のようなものがある

- 営業日管理(休日概念やT+nの考慮)

- アプリケーション設定(オンライン中の動的変更にも対応)

- メッセージリソース(i18n)

Page 22: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

ドメイン層 – 振込入出金(CashInOut)> 利用ドメインクラス

JPAの管理下に置かれないドメインクラス例

複数Entityを口座資産という大きい概念で束ねている

Page 23: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

ドメイン層 – 振込入出金(CashInOut)> 出金依頼確定(自己の状態を変更)

既存出金依頼をload後に呼び出すユースケース処理

自身の情報を変更しつつ、依存する他Entityへ変更結果

を伝搬していく。

Page 24: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

アプリケーション層 – 資産(AssetService)> クラス定義

@Serviceを定義してDIコンテナへ登録(シングルトン)

ServiceSupportを継承してアプリケーション層の共通的

な振る舞いを実装

Serviceではユースケース処理を記載していきます。基本的にControllerと1-1の関係となります。

Serviceにおけるユースケース処理はドメインのユースケース処理よりもより広義な解釈となっており、トランザ

クションや排他処理、メール送信や帳票出力、外接連携等の外部リソースと関連付く内容も含まれます。

※非機能要件のチューニングなどもアプリケーション層の責務に含まれます。

Page 25: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

アプリケーション層 – 資産(AssetService)> サービス基底定義

アプリケーション層ではドメイン層と異なり、インフラ層

のコンポーネントとより密接に紐付きます。

メール送信や帳票出力などはドメイン概念が交じるので、

必要に応じてアプリケーション層でメール送信やレポート

出力のコンポーネントをラップします。

今回は用意していませんが、スレッドやメッセージング

を用いた非同期処理やマルチデータソースの管理なども

アプリケーション層の責務となります。

Page 26: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

アプリケーション層 – 資産(AssetService)> 振込出金依頼

ユースケース処理では利用者行為の監査ログを残したり、

排他ロックやトランザクション制御などを行いつつ、ドメ

イン層のユースケース処理へ繋いでいく

非同期処理系は事前にトランザクションの確定保証が必要

(JTAや非同期系のトランザクション概念を混ぜない場合)

実行した際のコンソール出力例

Page 27: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

アプリケーション層 – 資産(AssetService)> メール送信クラス

インフラ層の単純なMailHandlerを、アプリケーション層

でラップしてドメイン概念を加えている例

Page 28: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

アプリケーション層 – 資産(AssetAdminService)> 振込出金依頼締め

ジョブスケジューラから呼び出される口座横断的な処理

冗長になりやすいので、トランザクション内部の処理は切り出し

対象を抜き出した後に必要処理を個別実施

ここではジョブ実行中のオンライン要求を許可する前提で実装し

ているので、口座単位にアカウントロックを掛けている

ここでのジョブは差分更新を許容したいので、失敗時は例外が上

位に飛ばないようにしている(個別例外はログ監視で検知)

※実際はもう少しトランザクション粒度を細かくすべき

Page 29: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

UI層 – 資産(AssetController)> クラス定義/振込出金依頼

@RestControllerを定義してDIコンテナへ登録(シングルトン)

@RequestMappingでURLを紐付け

利用するサービスをDI

顧客向けなどでEntityが過剰に情報を持っている時(更新者や内

部管理項目 等)は表示用のDTOへ詰替え

引数DTOに@Validを付与する事で、事前にDTOで定義していた

カラムドメインの定義に応じたBeanValidationのチェックが発

生する

Page 30: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

UI層 – ジョブ(JobController)> クラス定義/振込出金依頼締め

ジョブスケジューラから叩かれる際の受け口

ユースケース上の利用者はシステムとなる

戻り値を定義するかはジョブスケジューラの仕様に応じて

Page 31: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

アプリケーション起動クラス

SpringBoot1.2ではこれだけ

@SpringBootApplicationは内部で@Configuration/

@EnableAutoConfiguration/@ComponentScanを呼び

出している

設定ファイルはXMLの代わりにこんな感じで

application.yml定義を書くだけ

通常のJavaアプリケーションとしてApplicationクラスを

実行するだけで、Tomcatを内包した常駐プロセスが起動

Page 32: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

まとめ

SpringBootを利用することで記述量が減る

構造がシンプルになる分、ドメインに集中できる

Lombokを利用することで記述量が減る

実装の内容を考えると、Java8やGroovyを使うと

もっとシンプルにできる

導入の敷居の高さは会社毎に違うので今回はJava7前提

Page 33: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

ドメインモデリング実装例

以上です、ご清聴ありがとうございました。

時間が残っていれば簡単なデモ見せます。

Page 34: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

おまけ

自社で作っているものの簡単な紹介 [SpringBootベースのフレームワーク]

設計成果物を開発リソースへと繋ぐ。(開発立ち上げを早く!)

自動生成は支援ツールと割り

きって、単方向のみのサポー

トを想定

開発生産性の向上。エンタープライズ要件をシンプルに!

認証・認可

ビルド/リリース/運用を簡略化。

+ mpx-tools

Page 35: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

プロセス 三層サポート

おまけ

自社で作っているものの簡単な紹介 [SpringBootベースのフレームワーク]

ライブラリはインフラ層のサポートをなるべく手厚く

ライブラリ群

日付/日時

POJO(BeanSupport)

設定

ログ 型変換

フォーマット 審査

スケジューラ 非同期 認証/認可

DB MQ

メール レポーティング

IDロック

監査/イベント/メールログ

ドメイン審査

i18n

利用者管理

Webサーバ MQサーバ

DIコンテナ(SpringBoot)

リモーティング

分散キャッシュ制御

スレッド管理

分散コンポーネント管理

Page 36: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

おまけ

自社で作っているものの簡単な紹介 [SpringBootベースのフレームワーク]

マルチデータソース利用の例

Page 37: JSUG 20141127 「Spring Bootを用いたドメイン駆動設計」

おまけ

自社で作っているものの簡単な紹介 [SpringBootベースのフレームワーク]

使ってみたい方とか、基盤の仕組みに興味ある方はこちらまで問合せお願いします。

株式会社マネーパートナーズソリューションズ

営業担当:武田

[email protected]

03-4540-3890