ドメイン駆動設計のモデリング練習|データベーススペシャリストの過去問を題材に

はじめに

松岡さんのドメイン駆動設計 モデリング/実装ガイドとサンプルコード&FAQを参考に

データベーススペシャリストの過去問(2021年秋午後Iの問1)をお題として、

ドメイン駆動設計でモデリングをした際の試行錯誤をまとめました。

 

ドメインモデル図を作成する中での試行錯誤についてだけでなく、

モデル図をベースにサンプルコードやテストコードなども書いたので

具体的なソースコードなどはこちらの記事をご覧ください。

ドメイン駆動設計でのサンプルプログラム実装例|リポジトリ

 

そもそもドメイン駆動設計の目的とは

 

「ソフトウェアの機能性保守性の両方を高めること」

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

 

 

ソフトウェアはそもそもある問題や課題を解決するために作られます。

この問題領域や課題領域のことをドメインと呼び、

ドメイン駆動設計では、

この問題や課題に悩んでいる人やその領域に詳しい人(ドメインエキスパート)

を巻き込んでその領域について分析して

ドメインモデリングを行い、

そのドメインモデル図をベースに開発を行います。

 

そのため、

開発者だけでソフトウェア開発を進めるよりも、

実際の問題や課題を正しく把握して本当に求められているモノ

(機能性の高いモノ)ができる可能性が高まります。

 

また、

ドメイン駆動設計では、ドメインモデリングの結果をそのまま実装に落とし込むことができ、

頻繁な変更に耐えられる(保守性が高い状態)ような実装パターンを用います。

 

そのパターンにはエンティティリポジトリなどがあります。

 

頻繁な変更に耐えられなければならず、

品質を維持しながら変更を行うために

テストコードも重要になります。

 

データベーススペシャリストの過去問を題材に作成したドメインモデル図

作成したドメインモデル図は以下です。

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

 

モデリングの題材にしたのはデータベーススペシャリスト過去問です。

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

 

ポイントシステムのテーブル設計が題材ですが、

(一部妄想して)

ポイントシステムがAPIを用意しておいて加盟店のECサイトが商品を購入する際、

このAPIを叩いて支払情報を登録。

それに対してポイントをバッチ処理で付与する。

そんなイメージの題材にしてみました。

 

この辺りは、作成したシステム関連図ユースケース図を見ればざっくりと分かります。

 

 

 

システム関連図で対象のシステムと他システムやシステム利用者との関係性が整理でき、

ユースケース図の方ではポイントシステムの振る舞いが整理できました。

(今回はECサイトからAPI連携された支払情報を登録するところにフォーカスしています)

 

次に、オブジェクト図を作成していきました。

 

 

支払情報として具体的な値を利用しながら、データベーススペシャリストの過去問を見ながら整理していきました。

(ルールや制約といったドメインで表現すべき知識が少なかったので一部妄想で付け足したりしています)

 

例えば、

支払の際に支払う金額を複数の決済手段を組み合わせて支払えたり(支払い手段方法によってポイント率が違う)

などが表現できるようにオブジェクト図を作成していきました。

また、オブジェクト図は上の例でいうと複数手段の組み合わせで支払うケースもあれば、

1つの決済手段だけで支払うこともできるので2パターンのオブジェクト図を作成しました。

 

ここまできたら、最後は

ドメインモデル図を作成していきます。

 

 

各オブジェクト同士がどういった多重度でどう関連し、オブジェクトはどんな属性を持つべきで、

どんなルールや制約を持つのか??をそれぞれ図で表現していきました。

オブジェクト図の具体例があれば、ドメインモデル図で抽象化していくことは比較的簡単に行えます。

 

例えば今回挙げた例だと、

支払で0円というのは取り扱わないとの、1,000,000以上の金額は取り扱わないというルールを決めました。

また、オブジェクト間の多重度の例で言うと、

支払があるのに支払方法明細(支払う決済手段はなし)というケースはあり得ないので

その辺りは多重度で表現しました。

 

最後に集約について考えました。

集約は必ずセットでデータベースに永続化し、データベースから再構築する単位で、

 

今回で言うと、支払オブジェクトは支払明細、支払方法明細と必ずセットで

存在するのでこれらセットで取り扱うことにしました。

 

ポイント残高をユーザに持たせているのですが、

支払いの集約にユーザも入れてポイント利用時にユーザ情報の更新もセットで行うか??

について悩みました。

 

ただ、ユーザを集約に入れてしまうと、

支払いしたいだけなのに支払ったユーザをロックすることになるので、

それはやりすぎかなと。。。

そもそもポイント残高はユーザ自体を更新したいタイミングと

ポイント残高を更新したいタイミング全く異なるので

ユーザとは切り離して別オブジェクトとすべきか、、、など。

 

ポイント利用オブジェクトを別途作り支払い集約に入れて、

ポイント利用履歴オブジェクトはなくして・・・・

自分の今のモデリング力では悩みながら手探りなことが多いですが、

この辺りは実際に手を動かしたり、仕様をさらに深く読み込んでいくうちに

試行錯誤して少しずつ改善していくものかなと思います。

 

正直、今回のモデリングはテーブル設計に引きずられすぎて

あんまりよくない形になってしまってます。。。

 

いろいろ試行錯誤しましたが、、、

最終的に細かい仕様次第でもうちょっと修正は必要かもしれませんがモデル図としては

こんな感じにすると個人的にはしっくりきました。

 

 

支払集約に利用ポイントと付与ポイントという概念を入れて必ずセットで永続化と再構築をする。

ユーザポイント残高はユーザ集約とは別で切り出し、支払とも別集約にしましたが、

基本的に支払い登録後にこのユーザポイント残高は最新の計算結果で更新するようなイメージです。

最初のモデリング結果はテーブル設計に引きずられましたが、

これなら結構使う側であるユースケース層やリポジトリもいい感じに作れました。

 

ここまでがざっくりモデリングで実施した内容になります。

 

ドメインモデリングをやってみての感想や気付き

ドメイン駆動設計の本はエバンス本、

松岡さんのモデリング/実装ガイド、サンプルコード&FAQ、

成瀬さんのドメイン駆動設計入門などなど

今まで読んできたので知識としてはある程度あるつもりでしたが、

実際に手を動かそうと思うと全く最初動きませんでした。

 

手が動かなくなる度に、本を読み直して不安なままモデリングを進めていきました。

特にモデリングは実践してみて初めて、自分の理解度が足りていないことを実感し、

ER図に慣れているクセが出て混乱したり・・・

に気づけたので、分かりやすく解説されているからといって、

本を読んだだけで終わるのではなく、

実際に手を動かすところまですべきだなと改めて感じました。

 

モデリング/実装ガイド、サンプルコード&FAQで紹介されていたモデリングの手順を踏むと、

特にオブジェクト図で具体例を挙げてから、

ドメインモデル図をかくのでスムーズにモデリングが進められたり、

多重度をかけたりするのは実感できました。

 

システム関連図やユースケース図は特に現場で新規参入者が最初に見せると

キャッチアップが早いだろうなと思いました。

 

オブジェクト図なら、ドメインエキスパートもイメージが付きやすいので、

一緒にモデリングができて、

 

間違った方向にどんどん進んでしまって、

指摘されて軌道修正してというような無駄な工数が削減できそうなのと、

 

さらに、

ルールや制約なども記載したドメインモデル図をソースコードにきれいにマップすることができれば、

あちこちに同じルールや制約が散らばってしまうこともなく、

変更時の影響範囲も特定しやすくなりそうです。

 

ただ僕が直近やってた案件だと、

性能めちゃくちゃ求められるけどルールや制約が比較的シンプルなCRUDのみオンラインシステム

(逆にバッチは複雑だけどこちらも性能求められるのでプロシージャ利用するしかない)

みたいな感じだったので・・・ドメイン駆動設計は採用できず。。。でした

 

おまけ

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

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

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

 

コメントを残す

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

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