Apolloのcache updateがやや辛そうに見える
使っているのはvue-apolloだけど。
Mutationした結果をつかってquery cacheを更新する、ということができる。これによってもう一回queryしなくてよくなるなどの効果がある。Optimistic responseと組み合わせると、迅速なフィードバックを利用者に返すことができて体験が良くなる効果も見込める。よくあるコード例は
import createCommentMutation from 'create-comment.gql' import commentsQuery from 'comments.gql' const newComment = { ... } this.$apollo.mutate({ mutation: createCommentMutation, variables: { body: newComment.body, }, update: (store, { data: { createComment } }) => { const data = store.readQuery({ query: commentsQuery }) data.comments.push(newComment) store.writeQuery({ query: commentsQuery, data }) }, })
なんてやつ。store.readQuery
に更新したいキャッシュのクエリを与えてキャッシュの中身を取り出し、mutationの結果を使って編集して、最後にwriteQuery
でキャッシュを更新。どこか画面などに反映される。
ただ現実のアプリケーションはこんなに単純なものでもないと思っていて、例えば更新したいクエリというものがvariablesを使っていたとすると、
import createCommentMutation from 'create-comment.gql' import commentsQuery from 'comments.gql' const newComment = { ... } const date = '...' this.$apollo.mutate({ mutation: createCommentMutation, variables: { body: newComment.body, }, update: (store, { data: { createComment } }) => { const data = store.readQuery({ query: commentsQuery, variables: { date }, // <- これ }) data.comments.push(newComment) store.writeQuery({ query: commentsQuery, data }) }, })
クエリキャッシュを取得するときもvariablesが必要になる。ということは、mutationする関数などに、mutationに必要なパラメータに加えて、どのクエリキャッシュを更新すべきか特定できるだけのパラメータを渡さないといけない。もしかすると大抵の場合はmutationに必要なパラメータから導出できるのかもしれないけど、そうでないならなんかあっちこっちからデータ引き回しそう。Vuexとかでカバーできるのか、設計が良ければそうはならないのか、はて。
ElixirのConfigに関する議論が盛り上がっている
これ
課題意識としては、Mixプロジェクトにおけるconfigはアプリケーションが起動するときに読み込まれるけれど、その一方でそれをreleaseビルドするときはコンパイルするときに読み込まれるという違いがあり、混乱のもとになっている、というもの。よくあるのはSystem.get_env
で環境変数を読み込む場合で、releaseを動かす環境のものを使ってほしいのに、releaseをビルドした環境のものが使われてしまい、開発中は動いてたのにいざ本番へというところで全然動かない、ということがある。
これをどうやって解決しようか、という話で、提案されているのはconfigのファイルをreleaseの中にコピっちゃおうよ、というもの。ただしそれを行うには問題があって、一般的なMixプロジェクトでは
use Mix.Config config :my_app, foo: :bar import_config "#{Mix.env()}.exs" # <- これ
ということをして動的に設定ファイルを読み込んでいる。これをやられると、releaseにコピーするべき設定ファイルを知るためには一度設定を評価しないといけない。しかもMix
はreleaseでは使えない。そこで、mix.exs
に新しい項目を増やして、使う設定ファイルを明示的に書いておきましょうよ、ということになっている。
# mix.exs def project do [ ..., config_paths: ["config/config.exs", "config/#{Mix.env()}.exs"] ] end
な感じ。これなら設定ファイルを評価する前にどれをコピーすればいいかわかるし、動的にimport_config
する必要がなくなるので、設定の評価時にMix
も要らなくなる。またこの変更に伴って、:elixir
アプリケーションにApplication.Config
ってのを入れるよ、ということも言われている。
これを書いている時点でコメントが90ほど伸びていて盛り上がっている。若干議論が横道っぽいとこ(runtimeに使われる設定とcompile timeに使われる設定が混在してるの気持ち悪くないか?とか。これは今もそうだし、今回の提案が取り込まれても同じ)に行っている感じもあるけど、大注目スレッドであることは間違いないので今後もウォッチしてく。
Atomic Designのあいつら
Atomic Designという、コンポーネント単位で設計してく手法というか考え方みたいなものがあるわけですが、様々な解釈があるようでみんな違うこと言ってる気がしている。ここ半年くらい仕事とか趣味プロダクトで試したり、あちこちブログ読んだりしてなんとなく自分なりの解釈ができた感じがするので言語化しておく。
atoms
button
とかh1
とか、HTMLのタグにスタイルを付けたもの、くらいの感覚。atomsとatomsを並べるための、レイアウトするためだけのコンポーネントなんかもここに入ると思ってる。これ以上分割できないものとよく言われるけど、分割できそうなものでもいいんじゃないのとか思っている。例えばボタンはatomsの代表例でよく挙げられるけど、ヘリクツを言えば押す部分とテキストに分けられる。あと、ここにCSSを当てるときはmarginを持たせない。与えられた領域いっぱいに広がるようにすると再利用性しやすい。
molecules
atomsをいくつか組み合わせてできたもの。これもmarginを持たせるべきでない。
organisms
atomとかmoleculesをいくつか組み合わせたもの。よくmoleculesとorganismsの区別で迷うけれど、名前にドメインの言葉が入ったら、または入れられるならそれはorganismsだと思ってる。atomとatom組み合わせたらorganismsっぽくなっちゃった、というときは、それはmolecules1個から成るorganismsなんじゃないの、くらいの認識。
templates
organismsをレイアウトするだけの存在。レスポンシブな動きはなるべくここで全部吸収する。画面幅が変わったときに配置を変えるだけでカバーできないような変化は、画面幅ごとにorganismsをつくってtemplatesが出し分ける。どうしても無理がある感じになったらpagesが多少この辺りを担う。organisms以下には絶対にmediaクエリを書きたくない。
pages
画面とかURLに対応する。templatesとカブっちゃうことがあるので、templatesいらないならそれもよし。
まとめ
ただ結局、あんまりしっかりルールみたいなの決めると例外ができたときに死んじゃうので、ゆるふわでやるのがよい。