10月30日

質問者さん

reconstruct運用時のFactoryメソッドの必要性について質問させてください。 エンティティの初期化は松岡さんの書籍と同様、reconstructで実装しています。 エンティティのプロパティがすべてnon-nullableの場合、基本的にはresonctructの引数もすべてnon-nullableになると思います。 しかしDB側ではnullableなデータとして扱っている場合、初期化前にnullガード(バリデーション)を行う必要があると思いますが、それをインフラ層で行うとドメインロジックが漏れることになってしまいます。 かといってreconstructの引数をnullableにして内部でバリデーションすると、本来nullableではないデータを受け取ってしまう実装になり不整合の原因になると思いますし、nullableを受け取って例外出すなら最初からnon-nullableにしておくほうがモデリング的にも適切だと考えています。 このような場合の解決策としてFactoryメソッドを使って内部でバリデーション+reconstructを行えば隠蔽できいいかなと思いましたが、初期化自体をreconstruct/factoryの両方から行えることになり、本来前者を使うべき場所で後者を使うなど運用面での問題が発生してしまうと思います。 (引数的にはfactoryがrepositoryを包含する関係になり、factoryが便利メソッド的に使われていく問題です) またバリデーションやCompositeパターンにおける出し分けのように、Factoryという言葉がもつ意味合いも分散してしまい、結果複雑化し管理・運用が難しくなる気もしています。 (後者は def dollarでMoney("USD"), def yenでMoney("JPY")を出し分けるFactoryのイメージ) 松岡さんでしたらどのように対応するでしょうか。 (なおDB側をnon-nullableにすればいいという意見が出そうですが、nullableで扱いたい文脈が存在するため変更しない、という前提でご教示いただきたいです)

11月04日

松岡@ログラス/DDD,アジャイル

松岡@ログラス/DDD,アジャイルさん

結論 nullガードと nullable→non-null の変換はインフラ層(リポジトリ実装)の責務とします。 判断の基本とさて、まず「その実装はどの層の責務か?」を最初に考えるのが超重要ポイントです。 依存方向に従い、依存される側を優先します。(ドメイン層 > ユースケース層 > プレゼンテーション層/インフラ層)。 ドメイン層の扱い ドメインは non-null 前提でモデリングし、プロパティと reconstruct で表明します。 「DB では nullable である」はインフラ層の知識であり、ドメイン層は関知しません。 したがってドメインは factory ではなく reconstruct で non-null を受け取るだけでよいです。 もしfactory でチェックすると、「DB では nullable である」というインフラ層の知識がドメイン層に漏れ出す。これは責務違反になります。 ドメイン表現と永続化表現の変換は、リポジトリ実装クラスの責務です。永続化の方法が RDB でもインメモリでもファイルでも、その技術的詳細を隠蔽するのがインフラ層の役割です。DBだnullable、というのもそのようなインフラ層だけが知っておくべき知識の一つです。 non-null のはずの項目が null で来た場合は、リポジトリで整合性エラーとして検知します。

松岡@ログラス/DDD,アジャイルさんに 質問してみましょう!

松岡@ログラス/DDD,アジャイル

松岡@ログラス/DDD,アジャイル

DDDや設計にお困りの方はDMにてご相談ください。講義、モブモデリングやコーディングなどご要望に合わせた進め方でサポートします(オンライン)。 YouTube: https://www.youtube.com/channel/UCbHtbIUxtfGjrDy1WcqxExw

松岡@ログラス/DDD,アジャイルさんが

最近答えた質問

03月03日

ユーザー詳細画面のページビュー表示用のapiがあります。 データを返す処理は他のapiが担当しており、このapiは実処理らしい処理はありません。 ただ、権限外や条件外(ユーザーがBANされているなど)の場合は弾く必要があります。 しかし権限などのチェックをするだけではusecaseとは呼べないと思います。 とはいえコントローラでDBアクセスするわけにはいきません。 このような場合、どうすればよいのでしょうか。

03月03日

仕様駆動開発やAI駆動開発時のDDDのあり方を質問させてください。 いつも勉強になるお話ありがとうございます。 最近松岡さんが仕様駆動開発について講演されているの拝見いたしました。 その中でDDDについて触れられていない印象を受けました。 仕様駆動開発を行う場合でもDDDは重要だと考えておりますが、DDDの集約やコンテキストの抽出は、仕様駆動開発を行う前か、それとも仕様駆動開発の中で行っていますでしょうか? ご回答お願いいたします。

01月19日

クエリサービスのあり方について質問です。 現在とあるゲームを開発しており以下のようなディレクトリ構成を取っています。 User ├── Domain ├── Application ├── Infrastructure └── Presentation Score ├── Domain ├── Application ├── Infrastructure └── Presentation スコア一覧画面の構成としては 1. ユーザー名(部分一致)でユーザーを検索する 2. 条件に合致したユーザーが一覧で表示され、その中から一人を選択する 3. そのユーザーのスコア一覧が表示される というものになっています。 上記の1の処理においてユーザーを検索する際に 「年齢が18歳以上、検索表示を許可、ステータスが有効」 という条件が暗黙的に設定されます。 これはスコア一覧画面固有の条件です。 また、検索表示許可はオプションのようなものでありユーザー集約に含まれていません。 この場合 案A Score配下のクエリサービス内にユーザーを絞り込む処理を記載する。  →Score内のクエリサービスなのにスコアに関係ないクエリが含まれてしまってよいのか 案B User配下のクエリサービス内にユーザーを絞り込む処理を記載する。  →そのクエリサービスのインターフェースはすでにUser/Applicationにある。スコア用の固有の条件を持つのにここに配置してよいのか。 のどちらがよいのでしょうか。 (あるいはどちらも間違いでしょうか)