reduxのstateを正規化してCQRSの恩恵を受ける土台を作る

[2017reduxアドベントカレンダー](https://qiita.com/advent-calendar/2017/redux)の1日目が空いていたので、書いてみます。
よろしくおねがいしますー

# 書くこと
reduxのドキュメントの[Motivationの頁](https://redux.js.org/docs/introduction/Motivation.html#motivation)にてCQRSに言及されています（微かに）
reduxのCQRSらしさを引き出してその恩恵を受ける方法を書いていきます。

# CQRSってなんだ？
**Command Query Responsibility Segregation**
日本語だと**コマンド、クエリ責任分離**とかって訳されます。
コマンドは副作用が主目的の処理、クエリはデータを取ってくることが主目的の処理のことです。

マクロな話だと「データを書き換えとデータの取り出しは、サーバーもDBも分割してしまえ」という設計方式になります。
ミクロな話では「副作用を持つメソッドは戻り値を持つな、戻り値があるメソッドは副作用を持つな」という、コーディング原則（？）としても存在します。

ちなみに、fluxは(reduxも)生まれながらにCQRSです。
reduxは、CQRSとevent sourcingをリスペクトした関数型言語である[elm](http://elm-lang.org/)からインスパイア（というかパクった説も）されているので、この辺の勉強をすると設計がはかどります。

# まずはstateをnormalize(正規化)する
[reduxドキュメントには「stateは正規化しよう」と書いてあります。](https://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html)

### jsonデータの正規化って？

「jsonデータの正規化とは？」という話はこのreduxドキュメントでも紹介されている[normalizr](https://github.com/paularmstrong/normalizr)や[こちらのブログ](http://www.bokukoko.info/entry/2014/01/18/MongoDB_%E3%81%AE%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3)が大変参考になります。

```js:非正規化されてるjsonデータ
{
  id: "123",
  author: {
    id: "1",
    name: "Paul"
  },
  title: "My awesome blog post",
  comments: [
    {
      id: "324",
      commenter: {
        id: "2",
        name: "Nicole"
      }
    }
  ]
}
```

```js:正規化されてるjsonデータ
{
  "articles": { 
    "123": { 
      id: "123",
      author: "1",
      title: "My awesome blog post",
      comments: [ "324" ]
    }
  },
  "users": {
    "1": { "id": "1", "name": "Paul" },
    "2": { "id": "2", "name": "Nicole" }
  },
  "comments": {
    "324": { id: "324", "commenter": "2" }
  }
}
```
（どちらの例も[normalizr](https://github.com/paularmstrong/normalizr)から拝借しています。）

normalizrとは？って話はすでに良き記事が出てるのでそっちとか[本家のReadme](https://github.com/paularmstrong/normalizr)とか[ReduxのDoc](https://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html)とか読んで頂ければと
[Normalizrを使用したReduxの実装パターン](https://qiita.com/hiyamamoto/items/f1f86e94be083526d465)

正規化されたデータはネスト構造が浅くなり、正規化以前にネストされてたデータへの参照(id)を持っています。
RDBの設計に似てると思います。

正規化されたデータの方が、書き換えが容易で、変更が多いデータに向いています。


### CQRS的には
redux stateはCQRSで言うところのコマンドモデル(writeモデル)となります。
[![Screenshot from Gyazo](https://gyazo.com/a6bb0a8321f68f8a3a0da53006d291ea/raw)](https://gyazo.com/a6bb0a8321f68f8a3a0da53006d291ea)
コマンドモデルを書き換えるとsubが反応してクエリモデルを書き換えます。


# クエリモデルどこいった？
「[reselectにメモ化されたキャッシュ](https://github.com/reactjs/reselect)」がreduxにおけるクエリモデルに当たるかと思います。
reselectは[本家でも紹介](https://redux.js.org/docs/recipes/ComputingDerivedData.html)されていて、[こちらのstackoverflow](https://stackoverflow.com/questions/32352982/how-to-put-methods-onto-the-objects-in-redux-state)でもreduxのコミッターがおすすめしています。
日本語だと[この記事](https://qiita.com/zaki-yama/items/5258e6f1ae37f63034b9)が詳しいです。

### CQRS的には
実際のCQRSではコマンドモデルとクエリモデルを別々のストレージに記憶させますが、RDB一つを使って設計する方式もあります。その場合、テーブルviewをクエリモデルとします。
テーブルviewがキャッシュされるのと同じようにreselectもメモ化と言う形でキャッシュされるので、なんかそのへん意識して作られたんじゃないかなって思います。

クエリモデルは画面表示に特化させて、好き勝手やっていいです。jsonの形に特に縛りはないのでご自由に。


### selector書くのめんどいよ
わかります。それでも書く価値がselectorにはあります。
それはstate、react間の腐敗防止層としての価値です。

selectorを書くことで、reactはstateの形を知る必要がなくなり、stateの形を知っているのは、reducerとselectorだけになります。これはアプリケーションが進化する過程でstateの形をリファクタリングしたくなったときに価値を出します。
またreact側の修正があった場合についても、stateの形を変更しなくても欲しい形のjsonを手に入れる事ができます。

以上の理由から、middlewareでstateを使う場合もちゃんとselectorを書いたほうが良いです。DDD話でいくと、selectorを用いてfactoryを作り、それを使って集約を構築する感じになります。
この辺はまた今度記事にできたら良いなって思います。


# CQRSをもっと知りたい方はこちら
[Greg Young流CQRS](http://d.hatena.ne.jp/digitalsoul/20100712/1278886009)
[CQRS Documents by Greg Young](http://www.minato.tv/cqrs/cqrs_documents_jp.pdf)

[実践ドメイン駆動設計](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88-Object-Oriented-SELECTION-%E3%83%B4%E3%82%A1%E3%83%BC%E3%83%B3%E3%83%BB%E3%83%B4%E3%82%A1%E3%83%BC%E3%83%8E%E3%83%B3/dp/479813161X/ref=sr_1_1?ie=UTF8&qid=1512049483&sr=8-1&keywords=%E5%AE%9F%E8%B7%B5%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88)にはCQRSやそれ以外のアーキテクチャについて、「ここにレイヤードアーキテクチャがあるじゃろ？」から始まり、なぜレイヤードアーキテクチャじゃないアーキテクチャが提唱されていったのかが説明されていて、ためになる本でした。


# 果たして幸せになったのか
stateを正規化しつつ、reactが非正規化データを受け取れるようになり、腐敗防止層も手に入れた。
しかし、もともとapiで受け取ったデータをそのままredux stateに突っ込んで、reactでもさほど困っておらず、かつAPIが大きく変更することもない、というプロジェクトでは「幸せになった気がせんな」という感じかもしれない。

reduxは、このCQRSとイベントソーシングによって、ユーザーイベント、外部API、redux storeの間に住まうドメイン世界をクリーンにかつ外界の依存関係を切り離して設計することができます。クリーンアーキテクチャ、イベント駆動アーキテクチャなどと相性が良く、ドメインにある程度の重さがあるとき、その複雑化を軽減させることができます。


# あとがき
質問やご意見があれば頂けると喜びます。

ドメイン駆動設計、ドメインイベント、イベント駆動アーキテクチャ、イベントソーシングなどをreduxに当てはめる話も書けたら書こうかと思います。
reduxアドベントカレンダーがら空きだしね！