しゅみは人間の分析です

いらんことばかり考えます

Optimizing React Apps in Practiceの記事がよかった

marmelab.com

がよかった。

書いてある知見

  • プロファイリングツールの使い方
    • ChromeでDeveloper Toolを開いてrecordした間のイベントから、どの処理に何ミリ秒かかったか表示される
  • 遅いのはだいたいre-renderだよという話
    • わかるけどついやっちゃう
  • shouldComponentUpdate()のはなし
  • acdlite/recomposeを使うとPureComponentもfunctional componentでらくらく書けるよという話
    • Reduxでもますますべんりなrecomposeのpure()
  • reselectでmapStateToPropsのコストを削減
  • Beware of Object Literals in JSX
    • JSXでcomponentのpropsに{{ marginTop: 10 }}みたいな渡し方すると毎回オブジェクトが作られて毎回renderされちゃうよという話
    • これ気づかなかった
    • ちゃんとconstで定義しておきましょう

所感

私はあんまりfunctionalなReact派ではないので宗教的に使えない知見もあったが、acdlite/recomposeとかObject Literalの話は役に立ちそうだった。

今日ようやくReact Componentの切り方について悟りを得たのだけど、「propsが変わったときに同じタイミングでrender()される必要があるか」という基準でドンドコ分けていけば良いと思った。
よくやりがちだったのが、同じComponent classの中にrender_hoge()を定義して、それをrender()の中から呼ぶというやつ。これはrender関数の中身をきれいにはするのだけど、本質的にはrenderされる対象が減っていないので塵が積もるとどんどん重くなる。
なので、ここではfunctionalなReactの教えに従ってrender_hoge()のかわりにfunctional componentを書いていくべきである。もともといたComponent classがpropTypesはだいたいチェックしてくれるだろうから、ほんとうにrenderだけするpure functionを定義すればよいはず。
こうすれば、ファイルをえいやっと分けたり面倒なことはしなくともある程度re-renderを減らせるはず。render_hoge()を定義するならfunctional componentにせよというのはコーディング規約にしてもよいと思う。

とは考えたのだけど、pure React界はこのくらいとっくの昔に普及してそうだなぁ。

おまけ

データ構造とアルゴリズム

アルバイトも含めてプログラマとしてはそこそこ経験を積んだが、年々データ構造とアルゴリズムの偉大さを噛みしめるばかり。とはいえまだデータ構造とアルゴリズムを理解した!といえるほどメンタルモデルができてないので、その理由についてはうまく言語化することができない。

計算機科学をやる学科では最初の頃にこの分野を習うのだけど、コードを書いた経験が少ないうちはなかなか有り難みが理解できなかった。習うより使わないとわからん度が高い領域ではあると思う。

私はインターネットを使ったシステムを作る屋さんだからだとは思うが、超難しいアルゴリズムを駆使して実装なんてことはほとんどなくて、実際にはデータ構造の定義で難しい問題がシュッと解けることが多い。

つまり実務であてはめるとモデル設計の時点で多くの問題を解決できるともいえる。ではあるのだけど、我々は想像力が足りないのである時点での局所最適なモデル設計をしてしまって、あとから改修するはめになる。

しかし、データ構造の設計は解こうとしている問題、つまりその場その場での要求や仕様に依存するので、一般的な解はなく、我々の経験に暗黙知が蓄積されて各々の問題に対していい感じにやるしかないのが現状かもしれない。

注意しておきたいのは、データ構造とアルゴリズムが可分でデータ構造のみを称揚する意図はないという点である。現実の問題を解くという点ではデータ構造だけで解決できるものはなく、両方を使ってようやくまともな解ができるような気がする。つまり、データ構造もアルゴリズムも両方手足として使えるようになり、全体最適を目指しましょうというオチになりました。

さいきんReact, Reduxでやっている設計

はじめに

ブラウザでGUIアプリケーションを作らなくても良い牧歌的な時代は終わりつつあります。個人的な意見としてはブラウザはドキュメントビューアのままでいて、複雑なGUIアプリケーションはネイティブアプリケーションとして実装されてほしいのですが、そうは言ってもお仕事で人間にとって負担の低いUIを作っていく必要があるのです。
Railsでサーバアプリケーションを書きつつ管理画面はネイティブでなんてことはコスト的に実現できません。かといって長期的に運用されるシステムを作ると、システムを運用するためのUIが操作しやすいに越したことはありません。Bootstrapを使っててきとうなフォームを並べただけの画面を作って怒られた経験はありませんか? たとえサーバ開発者だとしても、我々は使いやすいUIを求め続ける必要があります。

react, redux

複雑なGUIを作るためのフレームワークも乱立の時代を終えて、react, vue, angularなどに人気とリソースが集約されてきたような気がします。私はたまたまreact, reduxという組み合わせを習得しましたが、本質的にはfluxによるコマンドクエリ責務分離なデータフローができていればどれをつかってもなんとかなるんじゃないかと思っています。

今回作ったもの

みんな大好きTODOアプリです。
TODOアプリ簡単かと思いきや、ユーザ入力がそれなりに多いので実験としてはよい対象だと思います。
我々サーバ開発者はたくさんの入力フォームを相手にしなければならないので、実務と共通する知見も多いでしょう。

https://gyazo.com/e7bf20da140f535ef85dbef510bbec04

ソースコードはこちら github.com

model, stateたち

redux design models

特徴としてはImmutable.jsを使っている点、StateもImmutable.Recordとして実装している点でしょうか。
このTodoStateは自身と他のモデルたちの状態を適切に管理する責務を持っており、ユーザ入力に起因する状態の変更は各メソッドをactionとして呼び出してもらうようになっています。
つまり、TodoStateはTaskやその他オブジェクトのFacadeになるように設計しています。
また、Recordのメンバとしてtasksを持っているので、TodoStateインスタンスをルートコンポーネントに渡せば勝手に値を参照してもらうことができます。

reducer

redux design ducks

ユーザ入力によって発行されたアクションをTodoStateのメソッドへ適切に振り分けるのがreducerの責務です。
このファイルはducksと呼ばれるスタイルになっており、action定義、reducer, action creator, ついでにsagaをひとつのファイルに混ぜ込んでいます。

github.com

reducerにとってのinitial stateをTodoStateクラスとして定義しているので、newすれば良いだけなのも便利です。

非同期処理

redux本体が非同期処理と相性の悪いフレームワークだからか、redux-*はほんとうにたくさん存在します。
今回はその中でもredux-sagaを用いてコードの見た目としては同期的に書けるようにしています。
sagaのcall作用とtask.submit()を共存させるのが今回一番悩んだところでした。結論としては、sagaを経由するactionにTaskインスタンスをそのままぶちこんでやることになりました。(33, 34行目)
正直なところちょっとダサい方法だとは思うのですが、Taskインスタンスではなくidを突っ込んだにしても、select作用でstateを取ってきてからTaskインスタンスを取得するだけなので、パフォーマンスに影響がでない限りはこれでもいいんじゃないかと思っています。
あるいは、task.submitParams()のようなメソッドを作り、requestに必要な情報だけを切り出して非同期処理を引き起こすactionに託すのもありだと思います。

components

redux design components

さいきんPropTypes.funcとtypeするのに疲れてきたので思い切ってactionsはcontextで流すことにしました。
なにか困ったことが起きたら真面目にpropsドンブラコをしていこうと思います。お困りポイントに見当がつくかたはお知らせください。
上の例では、Container Componentで定義したchangeInputTargetアクションとcheckTaskアクションがcontext経由で受け渡されているのがわかるかと思います。

f:id:non_117:20170325203133p:plain これは内容とはまったく関係のない挿絵です

まとめ

pros, cons

pros
  • reducerが見通しやすくなる
  • stateとmodelsに対するテストが書きやすくなる
  • stateとmodelsをちゃんと設計しておけばreduxを捨てるのも簡単
cons
  • Facadeになるstateクラスが肥大化する

所感

  • stateクラスがFacadeになっていることが最重要なので、Immutableに依存する必要はない
    • ピュアES6で書くとより移植性が増す
    • しかし個人的にはImmutable + TypeScriptでやりたい
  • stateクラスが肥大化する問題はそれこそreduxが得意とする分割統治で解決してはどうか
    • reducerの分割単位をまたいで参照が必要なだけならcontextで流せなくもないと思う
    • reducerの分割単位をまたいで変更が必要な場合はUIから考え直すと良いのではないか……
    • 分割したうえでロジックが複雑化した場合はモデル内の層を増やすしかないかも
  • 実際にはTODOアプリ程度の複雑さだとまだreduxを使う要件ではない
    • ちょうどImmutableなStateができているので、Reactオンリーで十分やっていける
  • 上記のTaskといったモデルがサーバ上のモデルと一致するかというと微妙なところ
    • UIの表現をするための状態がでてくる
  • サーバから渡す初期状態をつくるには(react_on_rails)
    • UIのための状態が存在するのでas_jsonでは力不足
    • Application, Domain, Infrastructureの3層でモデルをつくりInfrastructureの管理する状態をサーバ側モデルの部分集合にすれば、as_jsonでも良い?
  • client side validation
    • validationロジックがstateクラスの管理下にあるのは間違いないが、現状のモデル構造では肥大化の要因となって厳しい気がする
    • サーバとvalidationロジック二重持ち問題発生
  • Fluxの非同期処理やコマンドクエリ責務分離って所有権と相性いいのでは?
    • 今回はリクエスト発行後にユーザ入力でnameが書き換えられても問道無用でレスポンスが勝つようになっている
    • 非同期処理が入るとレースコンディションが発生しやすいので、プログラマは何らかの方法で解決しておく必要がある
    • コマンドクエリ責務分離もView系クラスとModel系クラスが状態を変更する権限の管理という話になるはず
    • Rust + WebAssemblyに期待したい

ここまで書いて、この記事で提案したモデル構造ではモデル内の複雑さを克服できない問題が残ることに気づいてしまいました。
モデルの複雑さをサーバに押し付けることで対処が可能ではありますが、本質的には解決しないのでまた別の設計論は必要そうですね。
DDDとかに詳しい方の知見をお待ちしております。

GUIを作るならRPCのほうが向いている説 / 読めるようにコードを書くこと

たしかにドキュメントビューア向けならともかく、フルGUIのアプリケーションに向けてRESTのAPIを返すのはなんか違う。いつかのデザイン系の記事で、ユーザはオブジェクトを見つけて〜の行動をしたいのではなく、〜をしたいからアクションを始める云々というのを読んだことがある。もちろんRESTは前者である。

昔はXML RPCとかもあったそうだが、今はまだREST APIの全盛期。GithubからGraphQLが出てきたり、たしかに動詞単語APIJSON中身いい感じにしてくれやも増えてきている。

しかし、現代のふつうの人はブラウザのアプリケーションとか使ってくれるわけもなく、スマートフォンネイティブのアプリケーションを使い、その使いやすさにも敏感*1なので、UIリッチなアプリケーションに寄せて設計をすると自然とRPC的なAPIができていくのではなかろうか。

個人的な設計の好みとしては、GraphQLのようなぶっといRPCを謎の責務的まとまりごとにエンドポイントを分けて中身はいい感じにやっていくのが良いような気がする。ここでは何をするかではなく、何に対して操作するかという切り分けが出てくるかもしれない。

 

ブラウザバックのボタンがこの世から消えたらアプリ作ってもいいよ

QAまともにやってないところのアプリだいたいブラウザバックで壊れる

ブラウザでアプリを作るな甘えるな 

上記の文脈などに呼応した思いです。ここでのアプリとはUIリッチなブラウザで動くアプリケーションのことです。

 

読めるようにコードを書くこと

その他本日の思いがひとつあって、プログラミングは文章を書くのに近いものがあるような気がしてきたという話です。

たとえば、hoge_enabledというbooleanの変数があったときに、!hoge_enabledと書くよりhoge_disabledという変数あるいはメソッドを定義したほうが読みやすいよねという話です。

!hoge_enabledくらい難なく読める、確かにそうですが、これを読み解くときにhoge_enabledの中身がtrue, falseどちらかを確認してから反転し、そのときの値を意識しながら&&の続きを読むといったスタックを多めに使う認知が働きます。対して、hoge_disabledと書かれていればプログラマ英語がふつうにできる人は、ほぼ無意識レベルの認知で読み下すことができます。なので、あきらかに後者のほうが読みやすいのは間違いないです。ここで、それくらい読めるというのもよいですが、!を使って書き下すかどうかで自転車小屋の議論をするよりhoge_disabledを選んだほうが生産的です。

まとめると、変数名は本当に重要なので手を抜くな。頭を少しでも使う処理は切り出しておけということになりそうです。こんな知見たぶん50年くらい前には発見されているでしょうが、独立に気づいたので主張した次第です。

ここで少し気になったのが、コードを書くうえで英語ネイティブの人は有利なのでは?という点です。データがないので何もいえませんが、もしかしたら有意な差は出ているかもしれません。しかし、我々はいまさら日本語でコードを書ける気がしないし、言語が統一されていると世界レベルで知見を共有できるので我々は英語を書いて読み続けるしかないのです。

*1:というかこのUIわけわからんてなると投げ出して罵倒レビューをしていく

利尿作用困る / gemのjQueryなくなってほしい / サブカルクソにおい棒

昨日の続きなんですが、webで広告一本でお金稼いでいくなら社会属性推定やらないと競争力維持できないのではというあれ。さらに、webサービス自体のプラットフォームが他のサービスとは違う集団に向けて提供されていると広告市場としてもより差別化ができるのだろう。

 

この世の飲み物から利尿作用だけ無くなってほしい

大変な頻尿持ちなので会議とかでかなり困っている。水自体にも量飲むと利尿作用があるような?

 

nested_formとsimple_formの組み合わせでハマり、よく見たらREADME.mdに有用な情報が書いてあるパターン。

しかし、この手のviewを弄るgemはだいたいjQueryに依存しており、バグの温床になりやすい。実際にnested_formの挙動はだいぶ怪しい。DHHも脱jQueryに舵を切っているみたいなので、gem界もReact(web) Componentとして機能を提供するオプションを用意してくれないだろうか。React Component自体は全然難しくないので。。。

 

サブカルクソという呼称を好んで使う程度にはサブカルクソ界隈が好きです。

今までに発言したサブカルクソタームで一番怒られたのは「サブカルクソにおい棒」です。

gyazo.com

正しくはリードディフューザーといいます。京都のサブカルクソほっこりカフェにはだいたい設置してあり、たまに加減を間違って公害になっている。最悪。

斜めがけ鞄よくない / カット野菜の可能性 / 広告

恐ろしいことに斜めがけ鞄で生活していると、左右半身で筋肉の付き方、首の傾き、歩く癖などが目に見えるレベルで変わります。重いものを持ち運ぶ場合は絶対にリュックにした方がいい。

 

社会上の問題をシステムで解決するときに銀の弾丸はない。生物という系も社会と同じくらいには複雑である。銀の弾丸はない。 

 

はてなブックマークを見たらわかるように、皆さん文章を読まずに雰囲気で怒るので、態度には気をつけないといけない。物理空間でも同様だと思う。

 

10分で作れる完全栄養食を目指したい

野菜を買ってきたらすぐに刻んで冷凍する運用はやっぱり美味しくないのかしら

美味しい冷凍カット野菜あればそれ買うんだけどな

冷凍の方が栄養アレかと思ってたんだけど、昔こんな記事をブクマしていた。

www.ponparemall.com

作業の分散は効率が悪いので、料理のたびにカットせずに冷凍された野菜を使うのが最適。野菜を買ってきたら自分で冷凍しても良いが、私は大量生産大好きマンなので冷凍済みのものがあればそれを使うようにします。不味ければまた考える。

 

何者かになりたい業界は新しいトレンドで何者かにならないと意味がないので、媒体が世代交代していく説

今はYoutuberとブロガーが最新な気がする。

 

手書きでも良いのだけど、図のわかりパワすごいので、業務用ペンタブ欲しいかもしれない。

仕様書とかドキュメント書いてもどうせ誰も読まないので、誤解を与えない程度にわかりやすい図を高速に生産できる環境が必要だと思っている。最初は手書きでも良いので。iPad Proが良いのではないかという結論に。

テレビ広告

風呂での妄想です。

あらゆる製品はどんな属性の誰に売るかを考えて作るわけで、広告も誰に広告コンテンツを見せるかは検討されている必要がある。問題になるのがテレビの広告で、近年のテレビは若者が観ていないという*1。昔のテレビであれば社会属性に関わらず様々な人が視聴していたのだろうが、現代ではその仮定が通用しない。

広告というのは視聴者がCMを観て実際に購買行動を起こさないと意味がなく、製品がある程度ターゲティングされているのならば、広告もその集団に対して投射するのが効率の良い方法であるはずだ。

なので、テレビ視聴者が偏る現代において、特に若者へのパスがテレビで無くなるのはテレビ局にとっても広告出稿者にとっても度し難い問題なのではないだろうか。

本来であればテレビ局が、様々な属性とまでは言わなくても様々な年齢層の人々に狙いを定めて番組の編成を設計すべきだが、今どうなっているのだろうか。

翻ってここで強いのがやはりGoogleで、Googleは昔からユーザの社会属性の推定を行っている。また、動画のわかりやすさというのは凄まじく、Youtubeはその動画広告を強制的にユーザに観させる仕組みを実装している。Youtubeが人口に膾炙した今では特に若者購買層への露出はそれなりに多いはずで、正確なターゲティングと相まって広告としての効果は高い状況と言えるのではないだろうか。

個人的にはテレビも頑張って若者向けの多様なパスを維持できる番組構成にしてほしいのだけど*2、テレビ局の人々がメインの視聴者に向けて構成してしまうのも致し方ないとは思う。

 

*1:印象論

*2:面白ければ私も観る

キャラクター販売とステータス販売 / 新うどん体験

 主張です。世界的に動いてはいるけど、実現するんだろうか。

 

前提としてキャラクターの好悪は文化に強く依存していて、日本のオタク用のキャラはアジアの一部と世界のごく一部のオタクにしか受けないとかそんなん。また、人によって当然好きなキャラが違うので、とりあえずたくさん用意しましたというのが、妹がn人いるやつからの系譜だろうか。いやもっと前からかも。

というわけで、日本をターゲットにしたスマートフォンゲームとかガチャのあるやつは大抵キャラクターを売っている。そして、付加価値として市場価値の高いキャラクターはゲームの中で強いステータスが振られている。

しかし、主に私が不満なだけなのだけど、キャラクターへの愛着がほとんどない人々が、ゲームの進行としてはオレツエーをしたい場合にガチャで大金を出せというのはあんまりではないか。私はキャラクターが買いたいのではなく、ゲームを楽にプレイするためのステータスを買いたいだけなのに。

なので、私のわがままとしての主張は、ステータスとキャラクターを別々に売り、キャラクターは高価に、ステータスは安価にしてほしいというものである。例えばステータスを装備として販売するとか。*1

ここで問題になるのはキャラクター本体に強さを残すかどうかで、たぶん残すのは残した方が良い。強くて市場価値の高いキャラクターを所有したいユーザも当然たくさんいるから今の市場があるわけで、市場価値高い - 強い, 市場価値低い - 強い or 装備品で強い を別々の販売システムとして提供すると私のようなキャラ愛わからん人間も満足できそうではある。

一応、自分が嬉しい以外のメリットを挙げると、

  • キャラクターを差し替えてローカライズ、カルチャライズするだけで国際展開ができるかもしれない
  • 脳を使わずにとりあえず微課金*2でゲームを進めたいユーザを挫折させずに済む*3
  • FGOのような面倒すぎる戦闘は楽してキャラクターとのコミュニケーションができる

など。

こんな施策をやって全体としての売上がどうなるかは誰にもわからないので、どこかの会社が実験してくれないかな。

 

うどん凄くてジムについて柔軟、有酸素運動、筋トレをする間、うどんを耳から外す必要が全くない。これは体験ですよ。

もちろん家でも同様に外す必要がないです。

*1:FGOがそれと言えないこともないけど、ガチャとしてのシステムがクソなので厳しい

*2:本当に微課金

*3:みんな疲れてるんやで