この記事について
先日 DDD-Community-Jp の DDD Talk MeetUp #2 というイベントでトーク枠にて参加させて頂き
Flyweight DDD というアーキテクチャスタイルの提案とする一つのスライドを発表させて頂きました。
https://speakerdeck.com/hirodragon112/ddddao-ru-nita-miqie-renaifang-hezeng-ru-2ceng-plus-cqs-akitekutiya-flyweight-ddd
ただ、本稿はこのスライドの「内容」とは全く関係ありません。
本稿で取り上げたいのはこのタイトルに登場している CQS
という単語についてです。
このスライドをきっかけにCQSとCQRSの違いについて自分なりに思考の整理を記載したいと思います。
CQS ? CQRS ?
きっかけは twitter にて @j5ik2o さんを通じてご指摘頂いた事です。
(厳密には元ツイートの @pospome さんの考察にかとじゅんさんがコメントされているツイートを自分拝見した形です)
僕もそこ解釈であってると思った。会場にいたのでそれを指摘しよう思ってたけどすっかり酔っぱらってた(笑) https://t.co/ONhNCrF2iJ
— かとじゅん@ドラケン・オンライン (@j5ik2o) September 9, 2019
という趣旨の内容でした。
これがどの表示であってもスライドの内容自体には直接影響はないです。こういう構造をどういう言葉で表現するのが適切か?というのが論点となります。
つまりざっくり論点を説明すると、
これは
CQS
と表現したものは一般的にはCQS
と言うよりはCQRS
のくくりに入るであろう
と言う事でした。
-
CQS
-> コマンドクエリ分離原則(Command-Query Separation:CQS) -
CQRS
-> コマンドクエリ責務分離原則(Command-Query Responsibility Segregation:CQRS)
CQRS
は CQS
の拡張と表現される事も多く基本的に概念が近く親戚のようなものだと言っても良いかと思います。
もちろん言葉が違う以上詳細では異なる個所も当然ありますが。
そして、実はこのご指摘自体は資料を作成している際も若干予測はしていました。
なので、資料にも以下のようなページを本題とは別に挟んでいます。
見ての通りIDDD本のカウボーイジョークのオマージュ的なページですが、そこで CQS
と CQRS
について触れており、
ここで自分の CQS
と CQRS
の使い分けの基準というか認識というかをサラッとですが下記の言葉で紹介させて頂いています。
CQRSはいわゆる「責務」まで分離された状態を表します
中略
ここではデータモデルがCommandとQueryで完全に独立しているかどうかを堺に言葉を使い分けています
つまり、自分としては Separation と Segregation の違いよりも Responsibility(責務)が付いているか付いていないかを重要視した考えの元言葉を使い分けています。
ここでは、責務が分離されている以上同じデータモデルを使用している場合は依存関係にある為、責務分離とは言えないという判断により今回は CQS
と表現しました
という事となります。
ただ、あくまで上記は自分なりの境界判断と自覚はしていたため、一般的な解釈に即しているかまでは自信はありませんでしたのでそういう指摘もあるかな?とも考えていました。
その後リプライにていくつかやり取りをさせて頂いて、以下のようなご指摘を頂きました。
僕はこういう認識。CQSはコマンド/クエリ・メソッドの分離パターン、CQRSはコマンド/クエリ・スタック(レイヤーを縦に分割したもの)の分離パターン。今回の資料は前者でCQSであるという認識になりますか?
— かとじゅん@ドラケン・オンライン (@j5ik2o) September 9, 2019
CQS
はC/Qのメソッドの分割パターン、 CQRS
はレイヤーの(アーキテクチャレベルでの)分割パターンという認識なので、後者であれば CQRS
に当てはまるのでは?
という趣旨の内容です。
実際後者の内容でした。
主に Separation と Segregation の違いにフォーカスがあたっていると認識しており、また説明自体も非常に納得いくものでした。
考察
せっかくなので著名な方々の情報を漁って見ながら少し考察をしてみたいと思います。
CQS
みんな大好き Martin Fowler さんの解説によると、
The really valuable idea in this principle is that it's extremely handy if you can clearly separate methods that change state from those that don't.
この原則で本当に価値のあるアイデアは、状態を変更するメソッドとそうでないメソッドを明確に区別できると非常に便利だということです
その他は主に副作用や冪等性、その例外について語られており、分離についてはメソッドにしか言及されていません。
まさにご指摘頂いた通りの内容だと思います。
CQRS
同じく Martin Fowler さんの解説です。
At its heart is the notion that you can use a different model to update information than the model you use to read information.
その中心にあるのは、情報の読み取りに使用するモデルとは異なるモデルを使用して情報を更新できるという概念です。
ここが自分の判断材料を決定した一番大きな理由となっています。
そして、
Developers typically build their own conceptual model which they use to manipulate the core elements of the model.
If you're using a Domain Model, then this is usually the conceptual representation of the domain
開発者は通常、モデルのコア要素を操作するために使用する独自の概念モデルを構築します。
ドメインモデルを使用している場合、これは通常、ドメインの概念的な表現です
... 中略 ...
The change that CQRS introduces is to split that conceptual model into separate models for update and display
CQRSが導入する変更は、その概念モデルを更新と表示のために個別のモデルに分割することです
... 中略 ...
usually when I hear of CQRS, they are clearly separate models
通常、CQRSと聞いたとき、それらは明らかに別個のモデルです
と続きます。
上記により、Command と Query が異なるモデルを使用する事が CQRS の利点を引き出す定義だと判断としました。
分離に関する記述はおおよそ上記のみだと思います。
考察の整理
上記 CQS
と CQRS
の分離の概念を踏まえて整理すると以下のようになると思います。
-
CQSの分離
Command と Query がメソッド分割されている。 -
CQRS の分離
Command と Query が異なるモデルを使用する。
よって、この2つを判断する際は以下の2点を考慮する必要があると言えそうです。
-
- メソッドによる分離か?
-
- データモデルが異なるか?
そうなんです。
お気づきの通り分離の基軸となる対象が異なっている為、完全に2分するには概念が異なります。
ここで今回自分がスライドにて発表した内容を振り返ってみると以下に該当すると言えます。
-
- メソッドによる分離ではなくレイヤーによる分離
-
- ただし、データモデルは同一のものを使用する
照らし合わせると 「1 にもあたらず 2にもあたらない。」
という感じでしょうか。
最初のご指摘では 1 にはあたらない為、CQRS
と言えるのでは? というご指摘内容だったと思います。
CQRSの変形かもですね。Gregさんのものではドメインオブジェクトとクエリ用のDTOは別になっているので。とはいえモデルは共通ではあるけど、アーキテクチャはスタック分割されているのでCQRSの範囲に入るような気がします
— かとじゅん@ドラケン・オンライン (@j5ik2o) September 9, 2019
まとめ
その後さらにリプライにてやり取りをさせて頂き、最終的に以下のようなやりとりをさせて頂きました。
メソッド分割(separate)ではなく レイヤー分割(Segregation)が行われているのでCQSではなくCQRSに分類されるのでは?とご指摘頂いた。(ありがとうございます!)
— hiro@miraito (@hirodragon112) September 9, 2019
ただ、責務(Responsibility)は分離されていないと考えているので、 CQS: Command and Query Segregationだったって事にしようかな笑 https://t.co/wX5HxNADUw
どちらにも該当しない異なる新しいパターンといってもよいかもですよ(リフレーミング
— かとじゅん@ドラケン・オンライン (@j5ik2o) September 9, 2019
そしてこの最後のリフレーミングが自分としては凄くしっくり来て腑に落ちたので、ここを最終的な自分の理解とさせて頂きました。
考察の整理にも記載した通りCommand と Query を分離はしていますが、 CQS
CQRS
それぞれのポイントとなる分離原則には当てはまらないと考えます。
それを既存のパターンに強引にあてはめようとしていた事自体が少し違和感を出していたのだと気づいたからです。
スライド自体はそのまま CQS
という表記のままとさせて頂いていますが(あくまでスライドの本題に直接関係するものではないため)
実際には CQS
と CQRS
の中間のような位置づけのパターンだと考えています。
この結論にも違和感ある方もいらっしゃるかもしれませんが、自己考察としては一定の満足を得ています。
最後に
今回改めて考察の機会を与えて頂いた @j5ik2o さん、 @pospome さん、本当にありがとうございました。
凄く学びになりました。
また、自分は普段「資料を作るのがめんどくさい」という単純な理由でLTや登壇をしないタイプだったのですが、
こうして発表の機会を得た事により新たに発見や学びの機会を得られるという事を体感しました。
今後はもう少し発表する機会を増やしていきたいと思います。