オブジェクト指向
DDD
CleanArchitecture

クリーンアーキテクチャで値オブジェクトをユースケースのアウトプットに使ってもいいか?

疑問だったこと

クリーンアーキテクチャでEnterprise Business Rules層の値オブジェクトを、Interface Adapter層にアウトプットとして直接渡していいか?

それとも、Application Business Rules層で値オブジェクトの中身をデータストラクチャオブジェクト(図2のOutput Data)に移し替えてInterface Adapter層に渡したほうがいいか?

図1

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3239333336382f37636531666231302d353034652d313665302d383933302d3237386238613766393432642e6a706567.jpg

図2

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3239333336382f64393037316236392d653665652d366632622d646464642d3630303437303736373062332e6a706567.jpg

疑問の背景

今回悩んでたのはEnterprise Business Rules層に値オブジェクトが20個くらいあり、それをApplication Business Rules層でデータストラクチャに変換してアウトプットに返すかどうかという点です。実装コードを想像すると、同じコードのクラスがいくつもできてしまう気がして、どちらにするか悩んでました。

値オブジェクトをデータストラクチャに移し替えないと、Interface Adapter層から見たら隠れ層であるEnterprise Business Rules層の変更が間接的に影響をきたすので、アーキテクチャ的には筋が悪いとは感じたのですが、コピペとトレードオフしてもいいのかもやもやしてました。

疑問への答え

  • 求心方向の依存は絶対守る
  • 値オブジェクトをそのままInterface Adapter層とかに渡るようにするか、データストラクチャにに移し替えてInterface Adapter層に渡るようにするかは、明確なルールはなく決めの問題。(ただし、図から察するに典型的なシナリオでは移し替えることを想定している可能性が大いにある)

ご回答を下さった @nrslib さんと、 @pospome さん、 @hirodragon さんに感謝。

実際どうするかについてのアイディア

戦略としてはコードの再利用性重視 OR 層の独立性重視かの二択なのだが、それぞれ細かい実践の部分で工夫はできる。

  • エンティティに所属する値オブジェクトを公開する (relaxed layered architecture)
    • 値オブジェクト周辺のライフサイクルとデータストラクチャクラス周辺のライフサイクルがほぼ同じ場合など
  • 汎用的な値オブジェクト(DateTimeなどと近い存在)をパッケージに切り出して共有する (shared kernel的な)
  • 値オブジェクトをデータストラクチャオブジェクトに移し替える (strict layerd architecture)
    • そんなに値オブジェクトの数が無い場合は、手作業で詰替コードを書いてもそんなに辛くない
    • アーキテクチャにもデメテルの法則があると主張できる
    • その際のコードの重複は妥協する
    • データストラクチャクラスをコード生成することで、退屈なコーディングを避ける (code generation)
      • 値の詰替えは退屈な作業になってしまうから
      • 値オブジェクトがたくさんある場合は自動化したほうが楽
      • コード生成後は別々のライフサイクルをたどる
  • 方針を確定する前にお試しで実装してみて、どちらがそのプロジェクトに合っているか見極める
    • テストコードまで書いてみる