https://zenn.dev/dowanna6/articles/4da7c1f91fb91f
先日プラハチャレンジで「CQSとCQRSって何が違うんだろうね?」と話し合ったので内容をまとめてみます。
我らがMartin Fowler氏によればCQSという用語自体が登場したのはBertrand Meyer氏の書籍で、
The fundamental idea is that we should divide an object's methods into two sharply separated categories:
と記載の通り、「オブジェクトのメソッド」を2つのカテゴリ(クエリとコマンド)に分けること、とある。
ちなみにMeyer氏はEiffelを開発した方で、自身が作成したEiffelの説明資料にはこんなことが書いてある
データを取得したいだけなのに副作用としてデータ自身が変わっちゃダメだよね、ということ。配列に対するpopはその最たる例で、もしpopの仕様を知らないエンジニアがデータ取得のためにpopを連発していたら元の配列は意図せず空っぽになってしまいます。
popみたいに大抵のエンジニアがすでに挙動を知っている一般的なメソッドならまだしも、自分たちで書いた(つまり初見では誰も仕様を理解していない)メソッドが呼び出しの度に意図しないデータ更新を行ってしまうと事故る確率が高まるため、更新と取得は分離しようぜ、という発想。
CQSに関してはいろんな文献に目を通しても定義にさほどブレはなく、オブジェクトのメソッド単位での設計指針を指しているように感じました。
CQSに対してCQRSは結構いろんな定義が転がっていて、Martin Fowler氏曰くCQRSの定義を初めて知ったのはGreg Young氏によるこちらの資料とのこと。「ファウラーさんが言ってることが正なんだぜ」と言いたいわけではないのですが、こちらの資料に勝るソースを僕自身が見つけられていないため一旦はこちらの定義をもとに話を進めてみたいと思います。
こちらの資料を読んでいると、Young氏自身も
Command and Query Responsibility Segregation was originally considered just to be an extension of this concept. For a long time it was discussed simply as CQS at a higher level. Eventually after much confusion between the two concepts it was correctly deemed to be a different pattern.
CQRSは長いこと「CQSをより高いレイヤーで適用したもの」と解釈されてきたものの、実際は異なるパターンであったことが長年の混乱から浮き彫りになった、とまとめています。