ドメイン駆動設計の練習!!サンプルプログラム実装編|リポジトリ作成

はじめに

データベーススペシャリストの過去問(2021年秋午後Iの問1)を例に、

ドメイン駆動設計でモデリングをしてリポジトリのサンプルプログラムとテストコードを

作成したので(Java + Springで作成)、

ドメインモデル図をベースにリポジトリを実装していく際に感じたことや気付きなどについて、

本記事にまとめました。

 

>>モデリング結果(drawio)

>>モデリング対象(データベーススペシャリスト2021秋午後I問1)

 

ドメイン駆動設計の練習モデリング編についてはこちらにまとめています。

ドメイン駆動設計の練習!!モデリング編

 

MEMO

本記事では、

松岡さんの「サンプルコード&FAQ」、「モデリング/実装ガイド」を参考にさせて頂きました。

サンプルプログラムの作成及びテストコードの作成は本をなぞった形になります。

(その点お含みおきください)

 

2022/03/22追記

ドメイン駆動設計でモデリング〜コーディング〜テストコード作成

までのまとめ記事を作ったので興味がある方は是非みてください。

ドメイン駆動設計の練習!!モデリング〜サンプルプログラム・テストコード作成(まとめ記事)

 

集約とリポジトリについて

集約とリポジトリはそれぞれ本でこのように述べられていました。

集約

必ずひとまとまりで永続化する、強い整合性を持ったエンティティ/値オブジェクトの単位

ドメイン駆動設計 サンプルコード&FAQ(松岡 幸一郎)

 

 

リポジトリ

エンティティ/値オブジェクトを永続化機構(DB等)に対して入出力するオブジェクト。

入出力は必ず集約単位で行う

ドメイン駆動設計 サンプルコード&FAQ(松岡 幸一郎)

 

 

前回のモデリング編で事前に支払集約で集約の範囲を決めているのでそれをベースに、

集約をそのままDBに登録したり、DBから取得したりできるリポジトリを作成しました。

 

 

集約の範囲としては支払登録時にセットで登録される支払明細と支払方法明細をセットで扱うようにしました。

どのユーザの支払いか??というユーザとの関係についてはユーザIDで参照できる形として別集約扱いにしました。

 

(支払と一緒にユーザが登録されるわけではないなぁ、

でもそのうちユーザのポイント残高と支払の利用ポイントの整合性チェックで

ユーザの情報もセットで取得はしたいかもなぁ。。。といろいろ悩んだ末一旦この形で集約は分けました)

 

リポジトリとJOOQなどのORマッパーとエンティティ/値オブジェクトとの関係とリポジトリの役目を絵にすると

僕のイメージはこんな感じです。

 

リポジトリでDBに登録するイメージ

 

リポジトリでDBから取得するイメージ

 

リポジトリはテーブルレイアウトをJavaの世界で表現するRecordとエンティティや値オブジェクトとの変換作業と、

実際にクエリを発行してDBデータ登録、データ取得を行う2つの役割を持たせています。

 

わざわざ、絵でいうRecordとエンティティとを分けているのは、

テーブル構成の変更がそのままエンティティなどに影響してしまうのを避けるためです。

(ドメイン層が中心で、インフラ層などはドメイン層に依存する形とするのが設計方針の前提)

 

 

ドメインモデル図からリポジトリの実装〜テストコード作成

作成したリポジトリとリポジトリのテストコードについてポイントに絞って紹介します。

 

支払リポジトリのインタフェース(ドメイン層)

>>該当ソース(github)

先ほどのイメージ図のようにエンティティを渡すとDBへ登録する登録用のメソッドと、

key情報を渡すとDBからデータを取得してエンティティを返却するメソッドを用意しています。

 

支払リポジトリの実装(インフラ層)

>>該当ソース(github)

実際にJOOQでDBとやりとりしているところです。

特に登録の方は1つのエンティティを3つのテーブルに登録しにいくので、

@Transactionalで1トランザクションとしてどれかのテーブルへの登録がコケたら、

ロールバックできるようにしています。

 

また、Record→エンティティ、エンティティ→Recordの変換用メソッドをそれぞれ用意しています。

 

支払リポジトリのテストコード

>>該当ソース(github)

DBと繋いでテストをしています。

@Transactionalでテストが終わったらロールバックできるようにしてInsertをなかったことにしています。

また、ここは完全に本に書いてある真似しただけなのですが、、

登録してその後、登録した内容が取得できるかのテストを一気に実施しています。

(この一気にテストするやつ個人的には効率よくてすごい気に入ってます)

 

ローカルで立てたDBと繋ぐので事前テーブル作ったり云々はFlywayで行う想定です。

諸々Flyway周りについては以下にまとめています。

flywayでテストデータをサクッとローカル環境に準備する!!spring bootで作成したAPIのテストコードを書くための準備編

 

また、今回作成したサンプルコードはgithub上に公開しており、

前提となる開発環境構築手順などもまとめてあるので興味がある方は参考にしてみてください。

>>サンプルコード(github)

バックエンド開発環境構築手順まとめ!!IntelliJ IDEAセットアップ〜FlywayでpostgreSQLにテストデータ投入などなど

 

リポジトリのサンプルコードを作成してみた感想や気付き

まず、モデリングの時のように手が止まることはなかったです。

その前にモデリングで集約の範囲を決めるときにまぁまぁ手は止まったのですが、、

 

実際に手を動かして実装してみて改めて感じましたが、ドメインモデル図があると

ドメインモデル図→ソースコードへ落とし込む際にほとんど迷うことがなかったです。

(複雑なビジネスロジックになるとそうはいかないかもしれませんが、、)

 

現場で今までよく見かけていた、実装がほぼ終わって

ドメインエキスパートから違うと言われて作り直してまた設計。。。みたいなのが、

 

ドメインエキスパートを巻き込みながらモデリングの段階でドメインモデル図の粒度でフィードバック受けつつ

ブラッシュアップする。モデリング結果からスムーズに実装に落とすことができる。

一部考慮が漏れてたとしても、ある程度ブラッシュアップできているので大きくひっくり返る可能性も低く、

修正もモデリング結果をスムーズに実装に落とし込む仕掛けができているから早い。

現場で導入するとそんなイメージかなと感じました。

 

一方、その素晴らしい仕組みを作るためには

リポジトリの詰め替え作業やエンティティ作って値オブジェクト作って、リポジトリ作って・・・

などはその分最初に頑張る必要があるなと実感しました。

Orikaみたいなマッパーライブラリを利用したら楽かなとも少し思ったのですが、

RecordとEntityで完全自動でマッピングできないところは自分でマッピング設定するので、

自分で詰め替えるのとあまり変わらなかったり、

これは本にも書いてありましたが、

ライブラリがリフレクターなどでごちゃごちゃやるので実行して初めてバグに気付くので、

自分で詰め替えを最初に頑張る。という方針が先々のことを考えると良さそうに感じました。

 

性能やメモリ使用率などなどについては、今まで僕が携わっていたシステムと比べて、

インスタンスの作成や詰め替えなどなど入るので

どうなのかは個人的に興味がありますが。。。どうなんだろう。

とはいえ、そんなとてつもない性能の要求がでるケースばかりではないでしょうし、

メリットを活かせるケースは自分の過去を振り返っても十分あります。

 

現場でもドメイン駆動設計×SUDOモデリング×オニオンアーキテクチャ実践してみたい。。。

(CTOに相談してみるか、、、)

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください