最近のフロントエンドのエディタ事情

これは、個人でどんなエディタを使うべきか、ではなく、「チームとして」新しいものを採用するとき、あるツールがエディタ横断で便利かどうかを考える必要がある。

自分個人としては、基本はAtomを使って、TypeScriptを書くときだけVS Code を使っている。ターミナルでは Vim

環境でエディタを選ぶ

最近の新規プロジェクトでは、とくにブロッカーがなければ TypeScript を使っていいと思う。TypeScript を使うなら当然 VS Code を使うことになる。AtomVim でもいいが、TypeScriptのエディタとしては、流石に完成度が頭一つ抜けてる。JavaならJetBrains 的なノリで、TSならVSCode、そういうものと思ったほうが楽。

TS以外なら、エディタはなんでもいいが、ある程度流行ってるものでないとエコシステムに追いついてくれない。

prettier の勝利

フォーマッタは当然のように prettier が入る。もう選択肢はなくて、猫も杓子もprettier。すでに勝負は決している。

保存の度に自動整形を掛ける。人によってはエディタに書き換えられるのが嫌かもしれないが、最終的にCIで通ってればなんでもいい。.prettierrc あればよし。

話がややこしくなるのは、styled-components のような CSS in JS 系が入ってきたときで、 JS(TS)内のインラインでCSS書くときにCSSとしてハイライトされてほしい。それができる環境を作れる人は CSS in JS を便利だと思えるが、そもそもそれができるという発想がないとハイライトがない環境でCSSを書くことになる。このとき CSS in JS へのヘイトが当然のように高まる。これは、CSS だけでなく、GraphQL などにも当てはまって、GraphQLのクエリも prettier で整形されるし、インラインでハイライトされる。

なので、最近はこういうJSも、環境を整えればちゃんとハイライトされる。

// GraphQL
const query = gql`
  query {
    users {
      name
    }
  }
`

// StyledComponents
const RedText = styled.span`
  color: red;
`

// JSX
export default () => <RedText>red</RedText>

Linter

エディタ環境、今ではいろんな意味で prettier ファーストで作ると圧倒的に楽で、prettier 自体はエディタとは独立しているので、単にそういうプラグインとして実装すればいい。流行ってればだいたいある。なければ作るか諦める。

あとは linter。エディタで動的にプレビューされてほしい。とくに大事なのは unused-vars で、未使用変数が常に通知されるのはコードの書く順序に少なからぬ影響がある。これから使う変数なのか、消えるべき参照なのか。

最近、空白系はeslint/tslint に書かずに prettier に丸投げするのが流行っている。むしろ干渉するから書くべきではないという意見もある。

最近試した中では https://www.npmjs.com/package/lynt という lint ツールが便利だったが、これはエディタ組み込みがなくて、小さい npm パッケージ作るときぐらいしか採用できなかった。

追記: Languagre Server Protocol

最近のエディタはTSのとき以外なんでもいい、といった理由だけど、最近は Language Server Protocol という補完エンジンの規約があって、言語側で実装されてればエディタがこの仕様で実装されていれば補完できる。自分がしる限り、 TypeScript/Flow/C#/Rust とかで実装されてる。たしかMSとGitHubあたりが規約作ってたはず

https://langserver.org/

自分が主にAtomを使ってる理由は、エディタのコードをだいたい全部読んでるので、いざとなったら自分で色々やって解決できるという安心感があるから。

大事なこと

自分一人で開発する際に便利だと思って環境を作っても、他人が不便な環境でやってることに気づけないことがあって、開発環境作る人は誰かの不便を可能な限りキャッチアップしてカバーするのが大事だと思う。

ちょっと前に、JSXハイライトがない状態で、JSX出現すると以降のハイライトが全部壊れる環境でReactを書いてる人を見たことあるが、「そういうものだと思っていた」みたいなことを言っていた。こういう状況を放置すると無意味なヘイトを生んでしまう。

Flutterのコミットログを読んで、これは一体何由来なのか調べた

本当に凄い雑にコミットメッセージと気になったdiff だけ読んだ感じなので正確性は保証しません。

結果としてこれは間違ってました

s/demenic/domenic 今思うとここは単にmerge コミットのような気がする

docker + k8s やってる

この記事は別にチュートリアルとかではなくて所感を書いてるだけ。

だいぶ長くフロント沼やってきて、主観ではあるが、だいぶ落ち着いてきた。落ち着いてきたというか、自分は一通りキャッチアップ済みなので後は差分だけ抑えていけばいいという状態。PWA周りは色々あるが、各種標準化を寝て待って方がはやい。どうせ各自IE11が死ぬ2020まで特に大きな動きは取れまい。外から今フロント何やればいいのって聞かれたら、 とりあえず typescript + react + redux + styled-components + prettier 余裕あったら react-native(expo) やっとけって言う…。

というわけで、停滞してる今こそ他のジャンルに手を出すチャンスだ、と思って、横から動向を眺めつつそろそろかなーと思っていたのが docker + k8s と keras + tensorflow のどっちかで、docker はちょうど仕事で dockerfile 書く必要あったので、やることにした。よく考えたら、今まで他人が書いた docker-compose.yml を使うだけだった。

同時に複数の沼に浸かるのは不可能ではないが、ダルい。効率良くやりたい。docker + k8s は docker に k8s 同梱されて、EKS控えてる今だろ、ぐらいの感じで触り始めた。

で、とりあえず Linux わからんわけじゃないし箱に入ってるだけのそれに port の穴あけてガチャガチャするだけじゃろ、みたいな雑な世界観で手を付け始めたが、そのとおりだった部分もありつつ、Dockerfile の世界観がだいぶわからなくてキレながら書いてた。ただ、大昔(何年前か忘れた)に触ったときと比べて、ハマりどころは皆ハマったというのが検索して出てくるようになっているので、まだマシな世界になったと思う。

multi-stage build はなんだこの地獄はって感じだった。named volumes がどこにマウントされてるか不明だった。どこから仮想環境でどこからホストのパスなのかわからなかった。 docker-compose up はなんか挙動不審なので、なんども stop してたら <none> なイメージが無限に増えていって、 node の PID 1 問題などを順当に踏み抜きつつ、alpine が busybox に毛が生えたものということを学び、とりあえずテスト環境で 8080にwebpack-serve 立てつつ本番だと生成物をビルドして nginx で配信するサーバーを書いた。 https://github.com/mizchi-sandbox/docker-webpack-server

Twitter でわからん!!!!っていいながらやってたら @vvakame @babie @orisano @wreulicke (敬称略) あたりに添削してもらえて助かった。

書いたが、たぶん自分の理解が追いついてないので、なんじゃこりゃ、となってる部分がだいぶあって、dockerやる前は誰かが書いた賢いコンテナをちょっとチューニングしてポンポン投げるだけと思っていたが(nginxやredisやmysql単体だけなら簡単だったので)、なんだかんだで細かいことをしようとすると無限にハマることになった。Dockerfile、docker-compose は、結局のところ次元が1つ増えたシェルスクリプトみたいな印象。ホストから仮想マシンにスイッチしたり共有しつつ任意のスクリプトを発行していく感じ。

Docker、ハマるといいつつ一度やればいい問題なので、地雷たくさん踏んで体力つけましょうという問題でしかないのだが、こういう作業してると細かいタイポとかでドンドン死ぬのだが、何もわかってないがゆえのハマりポイントの勘を洗い出せないがゆえに調査スコープを絞れなくて歯がゆかった。たとえば昨夜 server と service を間違えてるのに1時間気づけなかった。それで自信を喪失していくが、プライドなんて捨ててわかりません助けてください!!!って言ったほうが結果として早い。教えて君(死語っぽい)していた。

今 minikube とか kubectl あたりで試していて、むしろこの辺はまだ整理されてる感を感じるが、そもそも難しいことをしようとしていて、登場人物が多い。コンテナ監視する中央管理者がいて、コンテナをとっかえひっかえ入れ替えるマンがいるというのはわかった。

とはいえ今後 serverless などを主戦場にしたければ避けられない範囲に思えるので、今のうちに消耗しておきたい。フロントエンドやり続けるにしても、結局次の伸びしろはそこだと思っているので。

クライアントサイドのモデルとは何か 後編 ~ 単方向データフローと参照透過性

この記事は クライアントサイドのモデルとは何か 前編 ~ クライアントサイド MVC の死 - mizchi's blog の後編。

前提として、今回の出す例で、「Web フロントエンドで、そこまで複雑な状態を考慮するなんてそもそも間違ってる」という意見があると思う。これに関して、そもそも「SPA というものが、いかに実現可能になったか」という視点の話であり、また、自分の経験上「フロントエンドなんて雑でシンプルでいいでしょ」というものが、複雑な構成を取っていくのを、何度も目にしてきた、という2つの前提がある。

適切な粒度に応じた適切な構成をとるべし、というのは別の話で、今回、対象が複雑なアプリケーションなのは前提とする。

Flux 以前

先の記事で ActiveRecord を前提にしたサーバーサイド ORM をクライアントで輸入しようとすると、クライアントでは Storage 層が存在しないので概念的にインピーダンスミスマッチがあり破綻することを述べた。今回は View の構造から逆算して、あるべき「クライアントのモデル」の姿を振り返ることにする。

まず最初に、複雑な Backbone.View でどうなっていたかを説明する。

このブログのような画面を構造を想定する。(Backboneでこういう構造に見覚えがある人がいるのではないだろうか)

- Router
  - ItemsController(/items/:id)
    - HeaderView
    - ContentView
      - ItemView
      - CommentListView
        - CommentView
    - FooterView
  • Router が URL を受け、対応する Controller を発火
  • Controller が View を複数生成する
  • 各 View は親子構造を持ち、それぞれの View のイベントを受けて通信させる

例えば iOS だとこの 「View を束ねた実体を持たない View」 は ViewController と呼称されるかもしれない。

問題

ここで問題になるのが、ルーターから伝搬された初期値を元に、View の親子関係の間に「状態」が発生する。それらはイベントドリブンに個別に更新される。

ツリー構造の状態の様々な関係の「隙間」に「状態」が生まれていく。しかも、この状態の発生パターンは一意に決まらない。発生しがちでいて複雑なパターンの一つが、何かの配列を元にしたリストビューで、動的に伸びたり縮んだり入れ替える必要がある。

結果として、トップダウンに読み下した時に、どこに状態が埋もれているかが、どの状態とどの状態がイベントを通して通信しているかが、非常に不明瞭になる。また、ツリー構造に応じて、再帰的にインスタンスを捨てるコードを書く必要があったり、メモリ管理がシビアになる。(フレームワークによっては再帰的に dispose してくれるが…)

後期 Backbone (と勝手に自分が呼称している) Marionette.js や Chaplin.js は、これらの構造を比較的わかりやすく助けてくれるヘルパが用意されていて、自分はそれらを使っていたが、やはり大規模なパターンでは破綻しがちだった。

ここで何が問題だったか。思うに、サーバーサイド MVC は View についてのドメイン用語が貧弱なので、単に View とした際にそれが親子構造をとって、相互に通信する状態まで考慮していない。複雑なケースでそれが破綻を招いた。

これは Flux 以前の様々な GUI フレームワークで発生している問題で、ちょっと前だと Flash の Stage のツリーがそうだったし、Vue 1.x 系 がそうだったし、 AndroidiOS もそうだった。(今は多分 Clean Architecture などである程度解決されているだろう。詳しくないので識者に譲る)

Flux 以降

問題は、状態が散逸してしまって見通しが悪いことにある。そして通信経路は必ず親を経由する必要があり、複雑な Pub/Sub を構成する。それによってコード上の見通しの悪さや、メモリ管理の難しさが発生する。

じゃあ結局どうなってると良かったか。

よく考えると、いや考えなくてもわかることだが、クライアントのモデル、というのは本質的に今画面を見ている人間に対して必ずシングルトンである。マルチタッチを前提にユーザーが複数いることもあるが、そういうのは例外として考えなくともよい。

理想的にはこうなる、と Flux の発明者は考えたに違いない。

  • 状態はViewを抽象するシングルトンである
  • 状態を一箇所に集約する
  • 状態から常に一意な View を生成する

つまりはツリー構造中にどこで埋もれるかに関わらず、こういう JSON を集約して管理したい。

{
  "loginUser": {
    "id": 3,
    "name": "mizchi"
  },
  "item": {
    "title": "About Models",
    "body": "...",
    "comments": [{"name": "foo", "body": "..."}]
  }
}

このプレーンな JSON のような構造体が、本記事における「クライアントのモデル」とは何か、に対する答えになる。クライアントのユースケースを抽象する構造体。

で、これを入力値にすると状態を生成する update 関数があれば良い。

function update(state) {
  render(RootView, state);
}

View におけるイベントは、「その発生箇所に関わらず」この JSON を直接操作するアクションを発行すればいい。

擬似コードだとこう。

// アクション発行元
view.onClick(_ => dispatch({ type: "logout" }));

// 受け手
function logout(state) {
  delete state.loginUser;
  return state;
}

// 更新
root.on("logout", () => {
  update(logout(state));
});

これがいわゆる Flux の Store - View - Dispatcher 構成となる。

注意してほしいのは、 Dispatcher の責務がややこしく混乱を招きがちだが、実際は Store -> View -> (...) -> Store -> View -> (...) というループがあって、View <- Store に逆走できない点だ。これを単方向データフローと呼ぶ。

なぜ今になって Flux が出てきたのか

たぶん、素直な直感として最初に思い浮かぶのは、「常にルートから生成するとなると、常にすべてのインスタンスを生成するので実行効率が悪いのでは?」という懸念だろう。これはその通りで、これがまさに React 以前に Flux が存在しなかった理由であると思う。

React はルート要素からすべて生成しているように見えて、その実、状態の差分だけを更新するフレームワークで、仮想 DOM アルゴリズムによってこのフローを実現する下地を用意した。また、Angular は仮想 DOM ではないが、効率のいいデータバインディングとは、仮想 DOM と実態にそんなに差はないと思っていて、結果として差分適用の手法にすぎない。Vue や mithril, riot は React 以前からあるフレームワークだったが、基本コンセプトとして仮想 DOM を実装していった。フレームワークにとって差分適用の手法は本質ではない。(ライフサイクルの違いとして表出することはある)

実際、実行効率を無視すれば単方向データフローを実践するのは簡単で、更新があるたびに毎度 document.body.innerHTML を書き換えてイベントハンドラを更新し直せばよい。

Store != Model

自分は Store has a Model の関係だと思っている。Store は一方向に流れてくるアクションを捌きつつ、Model(=State) を更新する。

サーバサイドにおける Storage や他のドメインモデルは、Store がその更新時に参照しうるリソースの一つにすぎない、というのが自分の見解で、Store はその仲立ちをするだけである。

正確を期すと サーバーサイドへのアクセスは、 Store の中の処理ではない。Dispatcher が アクションを生成する処理(ActionCreator) のトランザクションの中で参照しうる IO が、いわゆるサーバーサイドのビジネスロジックの参照、という解釈になる。

関数型との奇妙な一致

正確には、親子間で埋もれる「状態」はある。ただし親が子の状態を参照する手段はない。これによって state の用途は著しく制限される。基本的に、Dispatcher を通じてアクションの副作用を一周させるしか親に変更を伝える手段がない。

// 閉じた状態の例
class Counter extends React.component {
  state = { counter: 0 };
  render() {
    return <button onClick={() => this.setState({ counter: this.state.counter + 1 })}>+1</button>;
  }
}

「状態は埋もれているが、ルートから参照できない」ことによって、そのスコープに閉じたマイクロマネジメントは個々の Component に任せつつ、シングルトンな本質的な Store にロジックが集中することになるのが、Flux の本質であると思う。

ここまで、あえて Redux の話をしなかったが、Redux は単なる「状態管理を関数で表現する」の方法論であって、Flux の本質ではない。とはいえ理解を薦める助けにはなる。

Redux の Reducer というのは、とても単純な思想で、 (State, Action) => State という型で表現される関数でこの状態遷移を表現しよう、というアプローチである。

const initialState = {
  counter: 0
};
const counter = (state = initialState, action) => {
  switch (action.type) {
    case "increment": {
      return { counter: state.counter + 1 };
    }
    default: {
      return state;
    }
  }
};

この返り値が、クライアントの現在の状態を示すモデルとなる。

正確に言うとこの関数合成のヘルパなどがあるが、State の型さえ守っていれば関数の実装はどうでもよい。型の扱いがセンシティブなので TypeScript や Flow の需要が増えた、という側面はある。ちなみに作者の Dan Abramov 曰く redux のインスパイア元は elm。

状態が関数を通して変化する、というのが、関数型的な参照透過性の考え方と相性が良く、関数プログラミング的アプローチが React/Redux で主流になった、と自分は理解をしている。(ここを掘り下げようとしたが力尽きた)

(自分が個人的に嫌いなのは Redux Middleware で、それはこの外の話で、今回はしない)

まとめ

状態が各 View の隙間に散逸するのが GUIアンチパターンの一つで、それを仮想 DOM の関数型的なアトミック性と、「メッセージの伝達が親方向へ逆走しない」という単方向データフローによって解決した。

クライアントのモデル、とは画面抽象であって、サーバーサイドのモデルを API 等の IO を通して参照するが、サーバーサイドの MVC におけるモデルと同一ではないし、同じに考えてはいけない。

React は Web の為に発明された手法だったが、Facebook はこれをあらゆるプラットフォームに適用する可能性を見出し、その結果 ReactNative や ReactVR などが生まれることになった。自前のブラウザエンジンを持たない Facebook らしいポジション取りだと思う。

クライアントサイドのモデルとは何か 前編 ~ クライアントサイド MVC の死

前置き

この記事、本来は Flux には Model がないのではないかと思った覚書 - ナカザンドットネットFlux の Store が ViewModel かって話からの MVW とかどうでもいいって話 - 猫型の蓄音機は 1 分間に 45 回にゃあと鳴く のアンサーとして書き始めた記事だが、前置きだけで別テーマとなったので、前後編に分割する。

僕は元々がゲームクライアント屋だったときの発想を引きずってるのと、既存の Web の開発の文脈に対して距離を置いていることを明言しておく。あとこういうテーマでとある原稿書いていたので、頭の整理も兼ねて。

ActiveRecord の功罪を振り返る

このテーマを語るにあたって、まず RailsMVC について述べなければならない。なぜなら、フロントエンドのアーキテクチャとは、サーバーサイドの MVC の模倣に始まり、破綻し、結果として iOS/Android/Desktop の GUI アプリ設計手法と合流したからだ。

Rails の ActvieRecord の失敗は、端的に指摘できて、それは Storage 層 と、ドメインを記述するための Entity を区別しないというところにある。本来の MVC を WAF に特化した省略形で、この設計は MVC2 と言われることもある。

MVC と MVC2 について改めて考えてみる - スタジオ・アルカナ技術ブログ

この MVC2 は Web 特有のリクエスト・レスポンスに起因していて、コントローラで受けてから値を返すまでのライフサイクルが以上に短い(50ms~1500ms)。また雛形のコードも短い。なので、Enitity と Storage を区別しているステップがもったいない。

あえて区別しない express の擬似コードを書くならこうだろうか。

server.post('/users/save', (req, res) => {
  const attrs = req.body
  // 無意味なコードなのであえて冗長に書いている
  const newUserEnitity = new UserEnitity(attrs)
  const userStorage = await UserStaroge.save({
    id: newUserEnitity.id,
    name: newUserEnitity.name,
    email: newUserEnitity.email
  })

  res.json(userStorage.attributes)
})

まず req.body が外部 IO から来る値なので静的検査しづらい。最終的に値を返す res.json(...) も同様。*1

そして外部 IO から来る値を元に Entity を組み上げても、短いコードではそのロジックを使う間もなく、Storage にセーブして終わり、となりがち。なので、この Entity と Storage は一体化した Model という名前のストレージ兼ロジック抽象の何かになった。そしてたぶん CakePHP で導入されたその思想は Rails 等の他の MVC に受け継がれていった、と理解している。

簡単なうちは簡単で済む。それはいいことだと思う。他を害さない限り。

追記: ActiveRecord パターン、 Cake => Rails という順番だと聞きかじっていたけど、Martin Fowler の PoEAA => Rails => Cake3 らしいです

良い解決策とは何か

セットアップを短くして、初心者や初学者にいい顔するのはいいことで、不必要なことを抽象化できてるということだし、興味のスコープを宣言できてることなので、悪いことではない。

最近でも next.js なんかはそれの権化で、pages/index.jsexport default () => <h1>Hello</h1> と書くだけで SSR する React アプリケーションの開発がはじめられる。この体験は鮮烈だった。確かに、本質的に削ぎ落とすと最初はこれだけでいいはずだ。

https://github.com/zeit/next.js/

で、問題は、これが複雑化した画面でどういう柔軟性があるか。

next.js の難点は、多様な要求に対してオプションを提供するのではなく、 作者の @rauchgミニマリズムな思想に従うことを強制してくるタイプのフレームワークで、その点使い勝手は後発の nuxt.js に劣る。

Rails に Service 層を生やすかどうかよく議論にあがるが、それは ActiveRecord が Entity としての振る舞いをどこに書くかの居場所が RailsMVC モデルだと用意されてないからだと思う。Controller が分厚くなったら、共通処理は Model に書きましょう、というのがこのアーキテクチャから自然と導かれてしまうアンチパターンで、これは悪い DRY の話にもつながる。

俺が悪かった。素直に間違いを認めるから、もうサービスクラスとか作るのは止めてくれ - Qiita

クライアントの「モデル」

前置きが長くなった。で、本題のクライアントサイドのモデルだが、複数の解釈が発生してしまった。

  1. サーバーサイドのモデルを抽象したプロキシ
  2. クライアント上のユースケースを表現した Entity
  3. クライアント側の永続層(IndexedDB/LocalStorage) のストレージ抽象

これに対して誰も一貫した答えを持っていなかった。というのが 2012 年ぐらいから段階的に明らかになったことで、DDD 的解釈や素朴な WAF の延長と捉えた人で解釈が違っていた。僕は Electron アプリの開発をしていたので 3 とも向き合うことになった。

1 が Backbone と Ember で、これは前提に REST がある。1 画面が 1 つの Model に紐付いていて、その Model のクライアントにおける写像を用意すれば、一貫した開発体験が得られる、というわけだ。

結果から言うとこれは破綻した。理由は 2 つある。

まずサーバーとクライアントのライフサイクルが違う。サーバーは先に述べたようにせいぜい 200ms~15 秒だが、クライアントサイドはタブが生成されてから破棄されるまで動き続ける。(ここは暗に SPA を意図している) なので、想定すべきは 3 分とか 15 分、しかも複数レスポンスに跨って状態を持つ、みたいな話になる。そのトリガーは何かしらのイベント駆動で、また抽象が違う。そもそもリソースに関与しない振る舞いすらある。

2 つ目は、クライアントサイドで発生するリレーションの問題で、クライアントの要求が増える度、必要なデータのクライアントサイドのジョイン が発生する。開発が長い環境ほどインターナルな REST 抽象は破壊され、専用 ViewAPI が増えるかカスタマイズされるかどっちかになる。ちなみに、これに対する解答の一つが GraphQL だったりする。 (ちなみに自分は REST 懐疑派で、もはや誰から見てもユニバーサルなリソースなど存在せず、クライアントからの要求は専用 API か RPC を作るのが良いと思っている)。

node だと isomorphic というテーマがあって、それを無理矢理に一致させようという研究は行われていたが、結果として上手くいったとは言えない。専用の PaaS が必要な Meteor は結局流行らなかったし、結果としてその差を強く意識するようになってしまった。

じゃあどうなったのか?それは ウェブの MVC という前提を捨てて、Flux という名前で MVC モデルを見つめ直したことで、結果として GUI プログラミングと潮流と合流しつつ、ストリームの監視と差分適用というものにフォーカスしたパラダイムに進化したのだ、と自分は思っている。

後編に続く。

mizchi.hatenablog.com


おまけ: 初心者にいい顔できるツールが流行る

やや愚痴っぽい話。

ちょっと本題からずれるが、プログラミング言語フレームワークの流行は、以下に初学者に対していい顔をするか、という点に尽きると思っている。かっこいいものを手数少なく書けるとカッコイイ。チュートリアルは短ければ短いほどいい。ここ近年の静的型付の復権は、単に型表現のパターンや推論機が発達して、チュートリアルのサンプルコードを短く書けるようになったかどうかに過ぎない点もあるのではないか。

これは悩ましい問題で、実際仕事でアプリケーションを書いていくにあたって、フレームワークの選定などを行うアーキテクトの立場では、コミュニティで人気があるものと、アーキテクチャ的な伸びしろがあるかどうかはまったく独立した要素だ。前述した next.js は、僕も便利だと思いつつ、仕事のような要件がコントロールできない場合に採用するのを薦めることができない。SEO 上の理由で SSR する必要があるなら苦労してでも redux SSRのボイラープレートを一つ採用するのを薦める。そもそも SSR 不要なら SSR 不要であると言うことのほうが多い。

極端なのは「プログラミング抜きで〜できる!」という煽りで、その場合、プログラミング言語に等しい一つの DSL やツールを覚えることになるのだが、それらのツールがその説明を果たしているとは言い難い。極端なのは RPG ツクールだと思っていて、例えば僕がプログラミングを最初にやったのは、WolfRPG Editor(ウディタ) の戦闘画面のコモンスクリプトを改造していて、こんなんプログラミングじゃん!って思ってはじめたのが最初だったような気がする…。

*1:個人的に、ここの静的検査の弱さが 10 年前の動的型付ブームの理由の一つだったのでは、とも思っている。自分は逆にアノテーションとしての型を書くべき派だが…

すべてのプログラマが機械学習を受け入れる準備をする時代になった

という予感がしたので書く。正確に言うと機械学習の成果としての訓練モデルを。

まず事前に前置きしておくと、僕は機械学習をほとんど抑えていない。トレンドだけ追ってる。

大学生の時にニューラルネットワークを実装してみてフ~ンって言ってた程度に知識しかなくて、ディープラーニングが流行る前だから、「バックプロパゲーションってややこしかったけど、今は自動でモデルの最適化いい感じにやってくれるんでしょ?」ぐらいの雑な理解しかない。(この時点で怪しい)

で、今はフロントエンドやってて、ここは機械学習は縁遠いように思えるかもしれないだろうけど、最近のGoogleはなんとブラウザで tensorflow を動かすのに情熱を注いでいる。

で、こんなのが Hacker News で流れてきた。

medium.com

とりあえず試した。デモをそのままデプロイした。

PoseNet - Camera Feed Demo

で、こんな感じに動く

https://i.gyazo.com/aaa299a41d487f8a3866696ffd5a3df3.gif

大学生の時にKinectを使った心理学の実験をしていたので、7年ぐらい前のKinectの精度は知っている。それと同等ってほどではないが、特殊なセンサー、複雑なセットアップ、キャリブレーションなしでこの精度が出るのはすごい。しかも時系列解析ではないからヒントも少ないのに…

要はディープラーニングやその辺でどんどん進化してるってことだろう。たとえばこれで簡易vtuber作れると思う。一週間あれば配信ツール作れそう。

機械学習を受け入れる準備

要は複雑なモデルの訓練はデータ集めて下処理してGPUクラスター組んだりパイプラインを組んだりして非常に大変だが、それを訓練したモデルのサイズはそこまででもないので、それをクライアントに配って使えるようになった。

一般化したこそ、モデルを使う側も準備を整えないといけない。posenet は、これからのエンジニアは機械学習で生成されたモデルの受け入れ体制が教養になるな、という予感を感じさせるプロダクトだった。

他にもこういう話が出てきた。

[速報]AIがコードのレコメンドやバグの指摘など開発を支援してくれる「Visual Studio IntelliCode」発表。Build 2018 - Publickey

補間エンジンをAIで賢く出来るのでは、というのは僕もアイデアとしてはあったし、たぶん頑張れば作れるだろうという予感はあったが、これはMSだけどこれから先はテクノロジージャイアントじゃなくてもモデルをどんどん作る時代になるだろうし、Kaggle の流行なんかもその予感を感じさせる。

要は機械学習の利用者として賢く振る舞わないといけない。フロントエンドエンジニアとしてはとりあえず tfjs 使えるようになっとけという話で、サーバーだったらもっと大規模なデータを訓練しながら動かせるだろう。

機械学習の受託は納品物が曖昧、みたいなのがよく話題になるけど、これからはより身近になって開発環境構築とかそのレベルで身近になるのだろう。

30歳になった

10年前に上京して、Twitterをはじめて、昔はどの勉強会やオフ会いっても最年少かそれに近い感じだったが、今となってはそんなこともなくなった。

働き始めた後、25歳頃に自己分析した結果、「好きなことしかできない」「勝つのが好き」というあまり社会人適正が高くない特徴を自覚した。なので、とりあえず現状自分が勝ててる分野をそのまま突き詰めることにした。フロントエンドとSPA。その戦略は間違ってなかったが、コンフォートゾーンに甘んじている感覚もある。俺の評価が上がったんじゃなくて、時流にいい感じに乗れてたという感もある。

今はフリーランスとしてやっていけてる。幸い仕事は十分ある。でもなんか妙にこじんまりとした感じに収まっている。なんというか、冒険していない。20代はベンチャー企業で働いてあわよくば一発と思っていた。それも途中で諦めてしまって、今はフリーランスでコンサルとエンジニアの真ん中みたいなことをしている。

最近、大きな勉強会にいくと、「ファンです、ブログやPodCast聞いてます」みたいな声を掛けられることが多くなった。俺ごときが、みたいな気持ちもありつつ、恥ずかしがりつつ照れながら適当にあしらっててしまい、なんか上から目線の俺きめえな、みたいな気持ちになり、帰ってから反省したりしている。

人生にマンネリを感じる。ちゃんと人生やっていってる人はこのへんで子供が生まれてライフスタイルが変わっていくんだろう。自分がそういうことをできるか?と自問すると、結構厳しい気持ちになる。自分が誰かと一緒に暮らしている姿がイメージできない。

じゃあ自分のために時間を使えているかというと、それも微妙で、アニメや漫画で満足できることが減った。単に要求水準が高くなってるのはわかっていて、馬鹿になって愉しめば良いのだが、それができない。最近はネットフリックスのドラマを見ることが増えたが、やっぱ英語でネイティブに楽しみたいよなーと思って、英語を真面目にやるモチベーションだけは上がっている。最近ヒアリング力は多少上がった気がする。ゲーム・オブ・スローンズのイッキ見とかしたからだと思う。原作追い越しててびっくりした。

肩が痛い。肩と首が痛い。エンジニアの皆、姿勢は大事だ。高い椅子を買え。筋トレをしろ。痛みに集中力がもっていかれて、強制的に休憩が必要になる。整体にかなりの金を掛けてる。それでもよくならない。

最近何かやってるかといえば、仕事でまとまった分量のコードを書くことが減ったので、プログラミングの基礎体力のためにと思ってゲーム作ってる。この時期毎年作ってる気がする。今年はアクションゲーム、というか Path of Exile をやっていたらDiabloクローンを作りたくなった。

http://zen-brown-07f2ef.netlify.com/

中途半端にOSSとか考えると妙に色気を出した縛りで積むことが多かったので、今回はOSSにしない縛りでひたすらゴリゴリ書いてる。基礎部分は出来てきたが、まだゲーム性みたいなものが発生していない。ゲームというよりゲームエンジンを作ってるという感じがある。

30歳だし何か書くか、と思い立って見たが、特に新規性ある内容はなかった。

とりあえず例のリストです。

https://www.amazon.co.jp/registry/wishlist/3MSOG970O7XT9/ref=cm_sw_r_cp_ep_ws_2lD6AbXP2P13K

https://store.steampowered.com/wishlist/profiles/76561198033602710/#sort=dateadded