Closed Wansuko-cmd closed 2 years ago
あらゆるメソッドは、アクションを実行するコマンドか、呼び出し元にデータを返すクエリかのいずれかであって、両方を行ってはならない。これは、質問をすることで回答を変化させてはならないということだ。
CQRSの考案でもこう述べられていたりして返り値を返すのはあまり一般的ではないみたいですね。 ここからは完全に僕自身の考えなのですが、どうしても苦しい場合は最低限の返り値(HTTPのステータスコード、サーバーから返されるcreatedAtなどのメタデータ、エラー)であれば返しても良いと思っています。 もちろん返り値を返すようにすることでQueryのようなものがCommand側に混じってしまうので紳士協定のようなコードにはなってしまいますが.... 他の解決策だともっと早い段階でUUIDを作成するとかですかね?CQRSによせる感じでcreateする際に
data class CreateParameter(
val id: UUID,
val email: String,
val title: String
)
のようなパラメーターを渡すようにするとかですかね? createが返り値を返すパターンに遭遇したことがないのであまり的確な回答は出せないんですが、すべての操作をCQSに無理に寄せる必要はないのかもしれません:eyes: このへんの話は@blackbrackenとかが詳しかったりするかもしれないのでレビュワーに当てておくと良いかもです!
https://github.com/Wansuko-cmd/Passon/pull/43#issuecomment-1075215849
createが値を返してほしいのは
自分としては
て考えていたので、createでidを返すのが得策だ!ということを考えていた感じですね・・・
CQSっぽく書くなら、書かれているように
めちゃくちゃ偉そうで申し訳ないです・・・
https://github.com/Wansuko-cmd/Passon/pull/43#pullrequestreview-917302493
ということは、今あるupdate, create, deleteを一つのファイルにまとめる感じでしょうか?
例えば
update -> PasswordGroupとPasswordItemを同時にアップデートすることのみ許可
みたいに、どちらかというと(モデルを使った)アプリケーションの振る舞い中心に記述することで、より操作が分かりやすくする、ということを考えていたのですが
返り値を持つ or 持たないとかで副作用があるかどうかをはっきりさせる
ということを完全に見落としてました・・・
https://github.com/Wansuko-cmd/Passon/pull/43#issuecomment-1075236623 であれば値を返してしまっても良いような気がしますね....(エラーのハンドリングもありますし) この辺のCQRSを取り入れた際のcreate時にidやメタデータを返すか返さないか論争は結構繰り広げられていた感じがするので調べてみるとしっくりくるものがあるかもしれませんね:eyes:
ただ、そうなるとCQSから離れてしまうので、もしかしたら今回のケースだとCQSをとり入れるメリットはそこまで大きくない?気もします モデル考えずに使われ方で切っていくことが重要と思っていたのですが、そうでは無いとすればUseCaseがいたずらに大きくなってるだけになりそう?
CQSの話を見て気づいたのですが、RepositoryのほうをCQSっぽく書くのもいいかもしれないですね…(inputとoutputを分けはしないが、返り値の振る舞いは従う)
Usecaseでデータを作成 →Repositoryを用いていれる(エラーはそのまま投げる) →実行完了したら、Usecaseで作成しておいたデータを返す
みたいな感じです
CQSの話を見て気づいたのですが、RepositoryのほうをCQSっぽく書くのもいいかもしれないですね…(inputとoutputを分けはしないが、返り値の振る舞いは従う)
そうですね、CommandであればRepositoryに置くのが自然かもしれないですね(永続化まわりになるので)。 QueryServiceはUseCaseによった部分なのでそちらはUseCaseにおいてあげるとよさそうです!
QueryServiceを作ってみました!(テストはまだです)
まあ元からRepositoryにあるものをQueryServiceに持ってきただけではあるので問題なさそうな気がします!(DTO作っていないとか、テストが複雑になるという問題はありますが) あとはUseCaseをどうするか(集合単位の操作をするようにするかモデル単体の操作をするようにするか&CQRSっぽく書くか)なのですが、時間がないので現状のまま行くのがよさげだと思っています!
自分の中でちゃんと理由があってわけているのならば問題ないと思います!
概要
CQSチックにUseCaseを分けてみました!(まだinterfaceのみ)
実装したところ
interface
/watch
/update
/create
懸念点
ということは、今ある
update
,create
,delete
を一つのファイルにまとめる感じでしょうか?今回、
create
で作成したときにid
とかが作成される関係で返り値が欲しいんですよね・・・(CQSの趣旨からがっつり離れていますが) これは、id
を割り振るUseCaseを別に用意するべきなのか、もっといい方法などないでしょうか?