graphql-codegenを前提としたリポジトリのクエリ設計を考えたときの思考メモ

[この記事](https://qiita.com/setsumaru1992/items/79fbba24e9a08899bfb6)のように`yarn graphql-codegen init`をとりあえずやってみたら、簡単に60点のコードが生成できそうだった
ただ設計ちゃんとしないとヤバそうだったので表題のようなことを考える

# 考えたこと
注意事項

- 「クエリ」という言葉はqueryとmutationを含んだ言葉として使用します
- queryとmutationを表すときにはそのままquery,mutationとして表記します
- 思考メモを吟味・校正なく載せているので、語尾や言葉の乱雑さはご容赦ください

## 技術的な前提
- GraphQLで解決したい問題
  - REST的な過小な取得、つまりリソースの数だけ通信しなければ行けない方式を避けたい。
    - 別にREST的なものは最悪許容できる。上記はGraphQLの基本方針に過ぎず、GraphQLレールの理想に乗る必要もない。多分ページにつき1リクエストが理想になるんだろうけど、それに乗ることによって設計が汚くなるくらいだったら自分が解決したい問題を優先する
- codegenを使うことによって避けられないこと
  - あるグループのクエリはgenerated.graphql.tsxにまとめて吐き出される
  - つまり、出力されるデータアクセス関数はグローバル汚染のリスクを背負う。関心のディレクトリに閉じて、自分以外を考えなくていいということは設計で強制できない

## 取りうる選択肢
選択肢の範囲は以下の両極の間にあり、そのグラデーションの中から現実的な解を選ぶことになる

1. 描画するページごとのクエリファイルを作る
2. REST的にリソースごとのクエリファイルを作る

上記両極の間にあるグラデーションな選択肢を列挙してみる

- A. 描画するページごとのクエリファイルを作る
- B. ひとまとまりにできるできるだけ大きな機能を恣意的に決めて、その機能ごとにクエリファイルを作る
- C. 機械的にリソースごとのクエリファイルを作る(REST)

## 具体例
### サンプルサービスを想定
Railsチュートリアル的なTwitter的なつぶやきSNS的な具体的なユースケースを想定してみる

- トップページ
  - つぶやき一覧表示機能
  - 自分の簡易プロフィール情報表示機能
  - 関連している人情報機能
    - フォロワー一覧
    - フォローしている人一覧
- プロフィールページ
  - 自分の簡易プロフィール情報表示機能

※プロフィールページは詳細ページを通常出すが、重複する機能を表現したく便宜的に簡易ページをプロフィールページで表示するよう表現

### 具体例に対してそれぞれのパターンを適用してみる
#### A.描画するページごとのクエリファイルを作る
出来上がるクエリファイル数：2

- トップページクエリ
- プロフィールページ

##### クエリのディレクトリ構成
ページの構成と等しくなる。
グローバルなgraphql.tsxファイル内でflattenな形で生成された関数がどのページのものかわかるように命名は気をつける必要がある

##### メリデメ
- メリット
  - 投げる通信の数が少ない！！！！！ 1ページで1回
  - クエリファイル数が少ない
  - ページ数に合わせて自動的にクエリ数が決まる（nextとかだと楽そう）
- デメリット
  - 単一責任の原則に違反、つまりある関心（例：簡易プロフィール表示）でクエリを変えるときに関連するところのクエリをすべて「同様に」変更しなければいけない

#### B.ひとまとまりにできるできるだけ大きな機能を恣意的に決めて、その機能ごとにクエリファイルを作る
出来上がるクエリファイル数：3

- つぶやき一覧表示クエリ
- 自分の簡易プロフィール情報表示クエリ
- 関連している人情報クエリ

##### クエリのディレクトリ構成
- 案1. クエリディレクトリとかができて、そこに機能ごとのクエリが並ぶ
- 案2. コンポーネントファイルがあるときにそこにクエリディレクトリ（`queries`・`mutations`形式か`models`みたいな名前かは好み）ができ、そこに関心に閉じたクエリファイルができる
    - 単にコンポーネントごとになるわけではなく、大きなコンポーネントだけクエリ発行して、親子関係の子要素にデータをバケツリレーで渡すことになる
    - どういうときにクエリファイル作ってよくてどういうときにダメかはチームで粒度や塩梅を考えた上でルールを作る必要がある。
        - ルール作らないと乱雑な粒度で秩序なくクエリが発行されてちゃんとコードを見ないとどんな挙動になるかわからなくなる
    - アトミックデザインのOrganismsレベルくらい？
    - これやる場合、クエリ置くディレクトリごとにデータアクセスファイルを置くのも若干メンテコストを生むからやりすぎ感あるけど、悪くない気がしてきた。グローバルからの解放


##### メリデメ
- メリット
  - 単一責任の原則を満たせる、つまりある関心（例：簡易プロフィール表示）でクエリを変えるときに修正は1箇所でいい
- デメリット
  - 関心の分け方をフロントエンドを触る開発者が共有できる状態を保ち続けなければいけない
    - 新人・玄人ともに設計思想を共有し、日々メンテナンスできる体制や新人が下手こいてもリカバリーできる体制が必要
  - 上記と同様、クエリファイルの数が機械的に決まらない
- やり方次第
  - 通信数は機能の分け方で決まる。大抵許容できる量になりそうだけど、そこはパフォーマンスと相談しながら考える

##### tips
コンポーネントごとにクエリ部品を作り、それをページのクエリでインクルードして、ページ単位のクエリで無理やり単一責任の原則を満たすというコスい手を使おうと思ったんですが、
フラグメントとかクエリとかGraphQLが読める単位でしかgqlタグを読み込めなかったので断念しました

#### C.機械的にリソースごとのクエリファイルを作る(REST)
出来上がるクエリファイル数：4

- つぶやき一覧表示クエリ
- 自分の簡易プロフィール情報表示クエリ
- フォロワー一覧クエリ
- フォローしている人一覧クエリ

##### クエリのディレクトリ構成
クエリディレクトリとかできてリソースごとのクエリが並ぶ。Railsの`app/models`みたいな

##### メリデメ
- メリット
  - 機械的にファイルを生成できるから楽
  - 単一責任の原則を満たせる(ry
- デメリット
  - 1つのファイルで何回通信するか計り知れない（GraphQLのメリットを享受できない）
    - 機械的に作っているから通信多いときの対応が厄介
        - 全体の方針を変える（工数多）
        - ばれない程度にちょろっと変える→他の人が見たときに機械的に作ってあるからこそ規約があるように見えて、部分的にルール外のファイルが存在することになる
- やり方次第
  - サービスが小さいうちはこれで回るし（通信量も許容できそう）余計なことを考えずに機械的にファイル作れるから便利


## 所感
できれば「B.ひとまとまりにできるできるだけ大きな機能を恣意的に決めて、その機能ごとにクエリファイルを作る」
考えるの面倒くさくてとりあえず動かしたかったら「A.描画するページごとのクエリファイルを作る」かな