ServiceWorker as a Service, または Universal ServiceWorker という発想

ServiceWorker とは本質的に リクエスト&レスポンスモデルであるので、それをサーバーサイドで実装で一種のサーバーロジックとして動かしてしまって良いはずだ ー

という発想に目から鱗だったので、ちょっと考えてみたいと思う。

www.publickey1.jp

ここで試せる。

https://cloudflareworkers.com/#a9bc9ef6b4248289c71518581df30bc7:https://tutorial.cloudflareworkers.com

Cloudflare はCDN業者なので、 それに特化して Service Worker as a Service みたいな表現はしていないが、実態としてはサーバーサイド ServiceWorker だ。Fastly では varnish のミドルウェアなどでキャッシュ破棄設定のロジックやリダイレクトを書いていたが、それが ServiceWorker という体を取っている(ように見える)。

ちゃんと使い込んでいないので、おそらくだが、 cache オブジェクトの実装が cloudflare の asset cache の実装にそのままつながっていて、そこでキャッシュ破棄、構築命令に翻訳されているのだろう。


追記: 実際はレスポンスを書き換えるだけで、まだキャッシュ実装はないが、やりたいとのこと


Cloudflare の手法で優れているのは、現状、すべてのブラウザが Service Worker を実装しているわけではない(というかIEのことだが)ので、将来的には標準的な手法になるはずの中間層を用意したことで、たとえばpush イベントも(Safariであっても) をサーバーサイドで溜め込んで置いたり出来る。また、クライアント用 Service Worker と密に連携したスクリプトも配信できる。ビジネス的にもストレージサイズやイベントドリブンなエンドポイントの実行回数で課金できる。

イベントドリブン標準としての ServiceWorker

ミドルウェアでなんでもできる、という点で AWS Lambda や Google Cloud Function と同じようなものとして使うことが可能だろう。FaaS の1スペックとして、ServiceWorker as a Service という形式はアリだろうか。

cloudflare の チュートリアルで配布されてるコードはこんな感じ。

addEventListener('fetch', event => {
  event.respondWith(fetchAndLog(event.request))
})

/**
 * Fetch and log a given request object
 * @param {Request} request
 */
async function fetchAndLog(request) {
  console.log('Got request', request)
  const response = await fetch(request)
  console.log('Got response', response)
  return response
}

普通の service worker のコードだ。普通の。

毎度 Lambda と Cloud Function を使ってて思うのは、いまいち Node 側からのインターフェースが仕様化・共通化されていないので、毎回ベンダロックインされたコードを書くことになってしまっている。それぐらいだったら一応は仕様がW3Cではっきりしている ServiceWorker の仕様を使うのは筋悪ではない、と思う。

しかしどうせ各プラットフォームが独自な名前空間を持ってイベントを生やしてくる。Cloudflare もその方向を最初検討したようだし、それ自体は現実的なユースケースを踏まえると必要だと思う。実際ユニバーサルな ServiceWorker というものは、なんらかの抽象化層を経ないと到達し得ないだろう。

また、express で cluster モジュールなどを使ってOSSなサーバーサイドServiceWorkerを実装するのは、そこまで難しくなさそうに見える。Open FaaSなどとも方向性が同じになる。

なので、方向性としては歓迎したいが、大きなプレーヤーが標準化に向けて動いてくれないと難しそう。

フロントエンドの負債と向き合う

某所で書いたものを公開用に書き直したもの

前提

フロントエンドでTDDは難しい、というかほぼ不可能である。なぜなら事前に副作用をデータとして表現できるか不明だからだ。たとえばあなたのプロダクトの画面の何処かにボタンを追加するために、その内部表現を事前に思い浮かべることが可能だろうか?

react-redux などのFluxフレームワークは如何に副作用をアクションとして表現することで、テスト・デバッグのための情報を残すか、という視点で発展してきた側面がある。あの冗長なアクション定義は、全てデバッグのために書いていると言っても、過言ではない。それすら「Textは文字がある」といったトートロジーなデータになりがち。

フロントエンドの現実的な単体テストは、他の開発者のために、自分が書いたコードの要求を満たしているか検知する手段として、防衛的にテストアフターしておく。これぐらいしか現実的な手法がない。それ以上は、手動テスト、E2E、あるいはUXデザインの範疇だ。

GUIの開発は、最終的に目に見えてるものがすべてであって、DevTools上のパフォーマンス上のメトリクスではなく、「ユーザーがどう感じたか」に集約される。そして人間の感性は理不尽だ。その理不尽さに付き合うために、どの部分を外部から入力可能な値にしておくか、が設計の妙になる。

要は、UXは単体テストの範疇外だが、そのための変数は外部入力で受け付けるべきだ。

負債と向き合う

よくある状況

このデッドロックを乗り越えるためには、実際必要なのは「気合い」である。ただし「気合い」にも種類がある。より効率が良い「気合い」を目指すべきだ。

とはいえ、最初にいうべきは次のような言葉になる。

「このような状況は会社、開発チームとして溜め込んだ負債であるからして、この改善には痛みを伴う」

残念なことに、まずこれを認めることから始めなければならない。自分も、チームも。

手段

負債と向き合うための現実的な施策として、次のような感じになるだろう。

  • 手動テストを密にやる
  • 書き換えたコードを一部のユーザーにだけ徐々に適用していく
  • エッジケースのエンバグを一時的に許容してもらう
  • (厳密にはリファクタリングではないが)コードの簡略のために仕様を変更することを認めてもらう
  • そもそもコードを破棄して作り直す

個人の裁量でやれるのは、おそらく最初の手動テストの厚さだけで、それすら外部テスターがいる場合にはそれを共有する必要があり、要は大抵は「政治」が付いて来る。誰を説得するか、それもリファクタリングに必要な手続きだと思うしかない。

とにかく手動テストを繰り返しながらコードを分解する。

破棄して作り直すかどうかは、プロダクトの成長を一時的に止めることになるので、それが許容されるかどうかはプロダクトの事情による。見積もり次第。

一つの指標として、暗黙知を多量に要求するものは困難なので、他人が書いた jQuery は作り直した方がいい。

リファクタリングの仮のゴール設定

最初の単体テストの話をした理由だが、自分は大抵、「単体テストが書ける」という状況を、リファクタリングの仮のゴールに設定する。単体テストが書けるということは、不要な依存が切れて、モジュールの境界面が自明になった状態にたどり着いたということである。

備考: これは最近までモジュールシステムが存在しなかった、 JS ならではの事情による。長く開発されてきたプロダクトは、グローバル変数渡しや、自前のDI機構が残っていることだろう。

正直な所、「単体テストできるような状況」を目標にすればよく、実際に単体テストを書く必要はなかったりするのだが、わかりやすい成果物としてユニットテストを追加することが多い。この状態に至ってから、目的を達するコードを書き始めることができる。パフォーマンスだったり、ボタン追加だったり。

ただ、そういうテストがメンテされなくなって久しくなったときに、捨てられるかどうかの判断をできる必要はある。担当者が去ったテストが、カーゴカルト的に維持されてることは多い…

できることからやる、ために小さく分解する

大変なものを大変だと言いながらやる前に、痛みが少ないものからまず向き合う。外堀を固めよう。

フロントエンド開発で、最初に考えるべきは、

  • lint ルールを追加する
  • コードフォーマッタを入れる
  • 型を書く

これらは比較的痛みがない。まず eslint を導入して、CI に入れる。そしてルールを思いつくだけ書く。(各プラグインのrecommendedを全部突っ込むなど) 現代では、ホワイトスペースや改行ルールは人間が考えるものではない。prettier の導入で終わり。

経験上、この3つがわかりやすく効く。

  • globals: 使用可能なグローバル変数の列挙
  • no-unused-vars: 未使用変数の禁止
  • no-unreachable: 到達不可能なコードの禁止

ES Modules がある現代では、特殊な事情(ライブラリが勝手に生やしたり、期待しているもの)がある場合を除いて global 変数は一切使わずにコードが書けるはずだ。その場合も部分的な lint 無効化で対応できるはず。

(この節は、人によって意見が異なるだろう)

現代のJavaScriptにとって、一定以上のプロダクトで静的型は避けては通れないテーマだと思っている。フロントエンドは前述したように自動テストが困難なので、静的解析で出来る限りカバーするだけ事故が事前に検知できる。

とくに静的検査で強烈な開発体験の向上として現れるのが、React の JSX の props に対する静的検査だ。プロパティを変えると、大抵呼び出し元のプロパティ名を修正しないといけない。または自分の想定以上に使われていて、その修正漏れなどが発生する。手元でコードを書いていてもうっかりするから、ましてや他人のコードなど考慮外である。

JSXの発明の偉大な点の一つは、テンプレートに対する入力値を宣言的に記述することで、事前条件を明示したことにある。React以外の他のフレームワークも、現代的なテンプレート、コンポーネントは、ステートレスな関数的な振る舞い、またはステートフルであることが明示されたオブジェクトの形をしているはずだ。また、Component という単位にしたことで、依存が明示的になる。

ただ、痛みのない型の導入、は難しい。というかコツがいる。

flowtype で @flow アノテーションを段階的に追加したり、 typescript の allow-js モードで一旦全部tsコンパイラ管理下に入れてしまって、段階的に拡張子 .ts に置き換える、などの手法がある。

ただし、これはプリコンパイラが前提にある。プリコンパイラがない場合は、まずその導入からはじまる。これはデプロイワークフローに絡んでくるので、なかなかに辛い。ステージング環境を用意して、何度もトライアンドエラーするしかないだろう。

辛いものは辛い。そこは認めるべき。

リファクタの諦めが発生する原因

自分が経験した状況としては…

  • 元のコードの担当者が忙しい or 退職していて、レビューが受けられれない
  • そもそも仕様が↑の脳内にしかなく、逸失している
  • コードが予想もつかない場所で使いまわされていて、テスト範囲が膨大になる(駄目なDRY)
  • 特に仕様が決まっていなかった部分を、一部の人間(開発側またはユーザー両方)にバグと認識されてコミュニケーションコストがかさむ
  • プルリクエストが巨大化 or 細分化され、ブランチの維持で手一杯になるうちに心が摩耗していく

全部辛い。辛いものは辛い。 辛い時は辛いと言う。アラートを上げることは恥ではない。

リファクタリングの目的

プロダクトの改善の為、という大義名分は立てやすいが、そもそも何のためにリファクタするのか、見失わないように意識しておく。

  • 機能追加の速度を上げる
  • バグ抑止
  • 人員追加のためにキャッチアップコストを抑える
  • パフォーマンスチューニングの下準備
  • 自己満足
  • 採用アピール
  • 離職対策

後半の理由は後ろ向きだが、表向きの理由とは別に、現実的にこの目的で行われるリファクタリングは多い。自己満足を含むことが別に悪いことではないが、ただ過度に自己目的化してないか見つめ直す必要はある。過剰な抽象度を備えてしまうと逆に品質は悪化する。

中長期的なリファクタリングは、そのイテレーションの間で発生した現実的な泥臭いユースケースを踏まえ、プロダクトの向かう方向性を描きながら自分たちの事情(ドメイン)をコードで表現するとよい。

自分はフリーランスとしてパフォーマンスチューニングの案件を受けることが多いが、何にせよ最初にやることは大抵リファクタリングである。パフォーマンスの伸びしろは、ほとんどの場合、きれいなアーキテクチャによって担保されるからだ。そして、機能追加の速さも一つの「速度」ではある。

まとめ

リファクタは大変だがやりがいがある。やりすぎは危険。需要に応じて段階的にアーキテクチャを変化させていくとよい。

おまけ

Slay the Spire: 細かすぎて伝わらない攻略メモ

ちょっとかじったら読めるようになるもの。 カードの詳細は http://slay-the-spire.wikia.com/wiki/Slay_the_spire_Wiki にて。

アプデで頻繁に変更が入ってるけど現時点の話。

基本的な考え方

一回のプレーでなんでもやろうとしない。どうせ30分から2時間程度終わるので特化ビルドを狙って高速で死んだほうが学ぶものが多い。

優先順位は Energy > Power > Draw > 0 Cost カード > 状態異常 > ダメージ > Block

Block は意図して稼ぐものではなく、Draw カードの副次効果 や Power によるパッシブ効果で、ダメージ効率を稼ぐついでに得るもの、とした方がいい。そのメカニズムが完成するかどうかで Stage 3 のラスボスを倒せるかどうかが決まる。(狼ボスだけは弱いので倒せたりするが…)

大抵は自分が強すぎるかジリ貧でたどり着いて瞬殺されるかのどっちか。

デッキの圧縮

最初の Strike や Defence はかなり弱い部類なので出来るだけ早めに破棄して強いカードに入れ替えたい。他のカードを引きやすくなると思うと相対的に強くなる。ドミニオンで礼拝堂が強いのと一緒。

イベントやショップでは、自分は大抵、攻撃カード、防御カード、攻撃カード、防御カードと廃棄している。ランダムイベントでのトランスフォーム(実質ガチャ)の対象でもある。

Shopのマスでは1回につき1回だけ金を払ってカードを破棄できる。コストは 75 => 100 > 125 > 150 と上昇する。廃棄のチャンスは少ないので積極的に金が溜まったタイミングで訪問を狙いたい。

ただし、 Ironcrad で Corruption を引いた場合は 防御カードが Exhoust になるので廃棄しない。Vampireイベントで Strike を Bite(攻撃の度にHP+2回復) に入れ替えられるときは大抵やる。このゲームは最大HPよりHP回復手段の方が貴重。

Power や Exhoust カードは使うと山札からなくなるので実質圧縮になる。ドロー系のカードも圧縮になるが、Energyを余らせてるどうかで考える。

圧縮が上手く回ってるときは積極的に 0 コストカードを増やす。

篝火の Smith はカードを増やさず質を上げるので圧縮みたいなもの。ドロー系、序盤は Weak や Vulnerable などの状態異常の手段を優先する。

Ironcrad の Armaments+ は手札の全てのカードをアップグレードできるので実質圧縮みたいなもの。そして共通カードの Apotheosis があるならドロー系以外の強化は一切不要。初手はひたすらドローして Apotheosis をひねり出して使う。0コストでこれは正直強すぎる。ショップで見かけたら最優先で買う。たぶん220金ぐらい。

追記: 数日前のパッチで Apotheosis が 2(1) コストになっていたとのこと

狙いたい Boss Relic

ボス倒した時の入手Relicは比較的入手しやすい。 他のRelicの入手ランダムなので、何かのRelicに依存したビルドを最初から狙うのはおそらく機能しない。

Sozu

Potion が使えなくなる代わりにEnergy +1 / Turn 後半は Potion が相対的に弱ってるのでボスレリック取る頃なら自分を 1.33倍強化したほうが遥かに強い。

Cursed Key

2ボスで取得する場合、確定Relicマスが1個あって実質 Curseが +1枚で Energy +1 / Turn と考えると美味しい。終盤は Curse 一枚無視できるぐらいデッキが回ってるはず。

Pyramid

毎ターンのドローが -1 枚される代わりに、ターン終了時に手札を捨てなくて良くなる。 とくに2~3の高コストカードを任意に使える用になるのが大きい。

おすすめのカード: Ironcrad

Corrpution

すべてのスキルカードが Exhoust になりコスト 0 になる。高速な圧縮手段でもある。 ただし Skill 以外の Block 手段を確保しておかないとBlock手段を失って死ぬ。育ちきってない序盤に手に入れるとありがち。

ドロー+BlockのShrug It Off などが相性がいい。Barricadeと組み合わせるとたぶん負けることはない。どっちもレアだが。

Barricade

毎ターン Block がリセットされなくなる Power。単純に強い。事故らなくなる。 毎ターン Block -15 で維持というレリックで代替できることもあるが、そんなに手にはいらないので狙う必要はない。

これが手に入ってるときは 1コストで Block = ダメージの Body Slum を狙いたい。

Pommel Strike

コスト1 で ドロー1 + ダメージだが、強化すると ドロー2 になる。1コストでドロー2は強い。レアリティが低く序盤で手に入りやすいので序盤で手に入れて強化したい。

Battle Trance

そのターンそれ以上ドローできなくなる代わりに、0コストでドロー3(4) 他のドロー系を使い切ってから最後のひと押しに使いたい。

おすすめのカード: Silent

Neutralize

初期から持ってる 0 コストで ダメージ + Weak1(2) 1回強化すると Weak を切らさず回せるようになるので、他の Weak 手段を切れる。 ダメージもそこそこあるので、あと一発という痒いところに手が届いたりする。篝火で最優先で強化したい。

Ironcrad の強みが初期の戦闘ごとに HP回復6 の Relic なら、 Silent の強みは このカードの存在だと思う。

Noxious Fumes

毎ターン 2(3) の毒ダメージを敵全体に与える。 長期戦に強いのだが、Str強化を持ってる敵を前にするとダメージ出力が回る前に殴り負けるので注意が必要。

おそらく初期にアンロックされてるカードの中だと自然と主力になる。

Backflip

1コストでドロー2しつつ Block+5(8)。バランス良く強い。SilentはEnergy回復手段が豊富なので、何枚あってもいい。

Footwork

Dex +2(3) Dex+の手段は貴重。Backflip などと組み合わせてると良い。

Accuracy

Shiv のダメージを +3 の Power。 Cloak and Dagger や Infinite Blades と一緒に使いたい。QuickStepと組み合わせると手数で高速に Block を稼げる。Exhoust に反応する Passive とも相性がいい。

Unlock がやや遅いのが難点。

Bullet Time

それ以上ドローできなくなる代わりに 3(2)コストでそのターン Skill が使い放題。ドローしきってから使うか判断したい。

デッキ構築ローグライクダンジョン の Slay the Spire が面白かったので紹介したい

デッキ構築 + ローグライク + ダンジョン。

アーリーアクセスで少々コンテンツが足りない感はあるものの、とても面白かった。日本語の wiki や攻略情報が現在ほぼ一切存在しないので、布教兼ねて紹介したい。

プレイアブルの2キャラでクリア済み。クリア = Stage 3 のボス撃破としている。

Slay the Spire on Steam

https://i.gyazo.com/419ab928c2cc0060598b624a9c0d2f93.jpg

概要

基本的にはドミニオンのようなデッキ構築ゲーム。最初のカードはキャラクターごとに固定、毎ターン +3 Energy で 5 ドロー、Attack|Power|Skill のアクションカードをコストを払って実行する。

カードは敵を倒したりショップで購入することで手に入れる。他のデッキ構築ゲーと一緒で圧縮が重要で、イベントマスのストアで金払って1枚廃棄したり、特定のイベントで廃棄したりできる。休憩ポイントで各カードは一回だけ強化できる。

英語か機械翻訳の日本語で、簡単な英語なので英語でやればいいのだが、カード説明の Exhausted が 「その戦闘内での廃棄」に気づくのに時間がかかった。

良さ

最近は自称ローグライクが氾濫しているが、プレー感覚はしっかりとローグライクで、ビルド 最初から理想のゴールを決めて突っ走るか、その場で決めていくか、思い通りにいかない感じが絶妙に歯痒くてよい。

自分はこの手のゲームだと Faster Then Light が一番好きなのだが、プレーのリズム感は似ている。馴れてくると1プレー1時間ぐらいでテンポが良い。

キャラクター

The Ironcrad

戦士系っぽいイメージ。 初期から持ってる、戦闘終了ごとに HP6 回復のレリックが強くて結構無茶できる。

最初にクリアしたときは Felix(そのターン中のみダメージ+4) Heavy Blade(固定ダメージ+ダメージ増加倍率が3倍の追加ダメージ) 以外をドロー系で固めて、Felix をブン回すことで高倍率の Heavy Blade で最大ダメージを叩き出す感じだったが、二回目のクリアは Barricade(ガード値がリセットされなくなる) と Heavy Slum(現在のガード値だけダメージ)のビルドでクリアして、やる度に別のプレー体験になるように多様なビルドが可能。たぶんいちばん調整されている。

Corruption(全ての Skill カードが Exhaust になり、コストが0になる) が何やるにしてもとにかく強い。ただし入手確率も低い。強すぎるので調整されそうな気がする。

The Silent

毒使いのアサシン。脳筋よりビルドがピーキーで上級者向け。 Ironcradと違って回復のレリックがないので、慎重な立ち回りが要求される。

敵の得手不得手がはっきりしてるので、序盤のユニークに手も足も出ずにやられることもしばしば。毒ビルドは強いのだがダメージ出力が出るのが遅いので、その間に防御値を稼げずに負けることも多い。

結局ダガービルドでクリアした。ダガービルドは結構回さないとカード自体がアンロックされないので、それまでが辛かったが、Shiv のダメージ上昇バフを使って Shiv のドローに全部を賭けるビルドが完成したときは強すぎて負ける気がしなかった。

今後にも期待

さすがに2キャラは少ないのだが、それでも30時間ぐらい遊べたし、まだまだやり込めそうではある。自分は30時間ぐらいやった。 追加予定の3キャラ目や、追加のボス、レリックなどに期待しつつ、正式版まで追加要素追うだけでもニヤニヤできそう。

サクサク出来るデッキ構築ローグライクでリプレイ性も高い。おすすめです。

読まれるテキストは読者へのおもてなしの構造を持っている

大学生だった当時、梅田望夫の本を読んではてなにやってきた僕は、ブログ論壇への憧れだけがあって、技術者にもなれず、時流のテーマに対して書くべきテーマを持たず、ただ実家の宗教に対する恨みだけを書き綴っていた。

もちろん、そんなものを好きこのんで読む人はいなくて、ただ虚無へとテキストを放り込んでいたのだけだど、いつからか、ある程度パターンを獲得して、その真似をするようになって、成功失敗を繰り返して、それなりにPDCAを回してきたと思う。思えば、その過程でいろんな人のヘイトを買った気がする。

人間のテキストの読み方、その反応、というのはパターンを、いくつか書き起こしてみる。

読者は、ファーストビューのレイアウトで、読む読まないを決める

  • タイトルは記事の印象の5割
  • 章タイトルが残りの半分
  • 本文はほとんど読み飛ばされる
    • 書き手としては単語の印象の連なりでイメージを形成することになる
  • 段落が均等に分割されていると、テンポがいいと認識される
    • スクロールせずに次の段落の見出しが覗いてると尚良い
  • 中身の濃さに関わらず、スクロールバーの威圧感で「読み応えがある」と判断される

読者が求めているのは、そのリンクを開いたことに対する納得感である

  • 「釣る」ならどれだけ納得させるかが勝負になる
  • 結果として、強い主張 => それに対する想定反論へのエクスキューズ、という反復構造になる
  • 脳内に想定読者をエミュレートする。それは訓練で得られる。はてブユーザーはそのイメージを既に持ってるだろう。
  • たとえば、この記事につくであろう反論は「あいつまた中身がない記事を書いてる」「使い古された文章論/ソーシャルマーケティング論」「技術以外のことに言及すると残念」「瞑想と野菜が足りない」などである
  • それに対する反論として、僕は自分自身の納得感のためにブログを書いている、上からコメントすることで気持ちよくなれるなら勝手にどうぞ、僕は気にしないけど、といったスタンスであることを表明しておく。別に言う必要もないのだが
  • 同意を取りたい人に訴求して、叩きたい人には気持ちよく叩かせて、シェアしたい人にはその人のTLを彩るオシャレタイトルを提供する、のが書き手の役割

テキストの質は、読まれるかどうかに影響しない

  • 複雑な暗喩や係り受けの構造、レトリックが含まれるかは、それが読まれるかにほとんど関係ない
    • 書き手の自己満足といってもいい
  • 先に述べた段落構造のテンポ感だけで判断されがち

説明してもしすぎるということはない

  • 同じことを何度も書いて嫌がる人は少ない。なぜならほとんどの読者は読んでいないから
  • 読者は余計なメタ構造を求めない。記事単独で主張が簡潔するのが望ましい。
  • 引用先は読まれない。引用するとしたら読者がその記事を読んでいることを前提に記事タイトルを作る

強い言葉、エモさの役割

  • 人が記事を開いてるのは、何かを言いたいからであり、同意の対象、批判の対象を探していて、その端的なターゲット、「的」として引用したくなる「強い言葉」を散りばめておくと、その記事の反応を見る時にメタ構造がはっきりしやすい
  • ただし、強い言葉は、書き手の認知をも歪める。読者に訴求したいがためのエモいフレーズに引っ張られてて、本来言いたかったことと違うゴールに着地してることもある
  • それはそれで酔狂だと思っていて、自分はあえてそのままにしている

闇に飲まれるな

  • 批判を受けて暗黒面に落ちていった人は多い
  • 心を折らないために、無言の言及/シェアは全て自分への賛同だと思い込む。それぐらいじゃないと釣り合いが取れない。
  • 強い言葉による批判は、センセーショナルで、目につきやすい
  • というメタ構造を知ることで自分へ向けられた敵意を相対化する必要がある
  • 人格批判されるのは辛いけど、人格批判した側の方が品性を疑われてるはずと開き直る

言いたかったこと

俺は絶対に暗黒面に落ちないからな

というのを僕が尊敬する技術者でありブロガーである rui314 さんのツイートを見て思った次第です。

GUI環境でWeb の UIを構築する開発ツールを作りたい

qiita.com

という記事を書いた。 要約としては、「今こそGUIでWebのUIを生成できるような開発環境を目指すべき」みたいな話。

概念

Web の GUIの概念を分解すると

  • JS はViewとしての実装を持つプレゼンテーションレイヤー、ロジック注入のコンテナーレイヤーに分割して考える
  • HTML/CSS は、レイアウト定義のレイヤー、そのレイアウト領域を占めるエレメントのレイヤーに分割して考える

この考え方に基づくと、GUI開発環境で作るべきものは、

  • テンプレートへのJSロジックのつなぎ込み
  • レイアウトエディタ
  • 個別のエレメントの装飾

となる。

JSロジックのつなぎこみはヘヴィにJSだからまだコードで書く方がいい。作るならノードベースのエディタになりそう。 エレメントの装飾は自力で頑張るより Sketch から生成できないか試したい。後回し。

レイアウトエディタは今でも作れそう。作った。

レイアウトエディタを作った

css grid layout を用いて、GUIでポチポチやることで、レイアウト生成をある程度自動化する。

https://mizchi-sandbox.github.io/grid-generator/ で試せる。

見ての通り、非常に雑だが、css grid layout としての表現力は試すには一通り機能は揃ってると思う。

https://i.gyazo.com/fd5f6f75b5f577b18ec276c1655ff80d.png

サンプルで用意した HolyGrail レイアウトだと、こんな感じのCSSが生成される

.gridContainer {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: 120px 4fr 1fr;
  grid-template-rows: 60px 1fr 40px;
  grid-template-areas: 'header header header' 'left content right' 'footer footer footer';
}
.headerArea {
  grid-area: header;
}
.leftArea {
  grid-area: left;
}
.contentArea {
  grid-area: content;
}
.rightArea {
  grid-area: right;
}
.footerArea {
  grid-area: footer;
} 

この辺命名ルールがプロジェクトごとに違うので、うまい感じで表現するのが難しい。とりあえず適当。 注意点として、IE11 で動かすには postcss の autoprefixer などを通す必要がある。

作ってみた感触

まだPoCレベルの品質だが、レイアウト定義ツールとして発展性がある土台が作れたので、あとは欲しいものを気合で作っていくとどうにかなりそうな気がする。 2次元空間の連結処理を愚直に書いてると、まるでゲームプログラミングのようだった。こういうの辛いけど割と好き。

TODO

  • メディアクエリによるレスポンシブ対応
  • ドラッグで範囲指定で連結
  • 指定したgrid-areaをさらに子コンポーネントとして分割できるようにする
  • 指定したgrid-area へ React Component を埋め込んでプレビュー
  • 生成コードにpostcss通しておく
  • Atom プラグイン

思いつく限りだとこんな感じだろうか。 本気で作るなら patreon とかで gittip 使うべきか。あとで考える。

エンジニアのベンチャー企業の選び方/働き方/やめ方

この記事は退職者アドベントカレンダーの12日目です。

adventar.org

経歴としては、新卒で設立してすぐのゲーム会社 => 小規模教育系ベンチャー => Incements(Qiita) => フリーランス

今年で29歳、20代で3回退職しました。20代のうちは冒険してベンチャー企業で働いてみよう、と思ってたのですが、結局29を目前にフリーランスになってしまいました。

ベンチャーで働くこと

ベンチャーで働くのはリスクを取るということ。一番言いたいのは、ストックオプションもたずにベンチャーやるな、ストックオプションも確実に換金できるわけじゃない、ということ。上場するときに行使するか、バイアウト時に買い取ってもらわないといけません。

また、ストックオプションの期待だけ給与は下がるので、他の会社で同じことをやるのに比べて、 -100~-150万ぐらいの相場です。少数精鋭志向で最初からじゃんじゃん金がつぎ込まれてる会社はその限りではないですが、入るのも難しいですね。

つまりはストックオプションなしのベンチャーは、よっぽど給与が高くないと1つの搾取の形態です。若者の夢を食って成長する会社、残念なことにいっぱいあります。気をつけてください。

ただし、給与テーブルというものがないので、新卒でも即戦力ならお金は出るので、一律350万スタートみたいな大企業と比べると、最初のキャリアとしての給与は良いかもしれません。というか研修などはないので、扱いは中途です。

ビジョンとそのズレ

ベンチャー企業は、言ってしまうと創業者の夢を叶えるためのもので、ビジョンに共感して入社したとしても、些細な方向性の違いがどんどん大きくなるし、またそれが実現したところで実はお金にならなかった、みたいなことも往々にしてあります。

自分がプロダクトに思い入れを持つのはいいことなのですが、持ちすぎると会社が自分の願いに反する方向に舵をきったととき、裏切られたという感じてしまうこともあります。

共感は一つのモチベーションの作り方ですが、まったく共感をせずとも働けるのならそれは1つのやり方としてアリです。とくに技術者の場合は、目先で使う技術だけ意識してれば後はあんまり気にしない、というのもアリでしょう。ただし、その場合はその技術の使うアテがなくなったタイミングで辞めることになるでしょう。

ベンチャーの選び方

とくに小さいベンチャーでは、経営者は会社そのものです。経営者がやりたいことと、自分がやりたいことが合致するか、それが最初の確認ステップです。

自分は、会社に対して労働という形態で会社に投資をする形になります。その見返りはストックオプションです。

上場は簡単にはできません。ほとんどはそこにたどり着かないし、最短でも創業から4~5年、うまくいって10年かかるものです。自分の人生のうち10年をそこに賭けられるか?と考えてみてください。

幸いなことに、この業界は流動性が高いので、言い方が悪いですが「損切り」も簡単です。

自分がベンチャー企業をやめた理由

僕は結構プロダクトに思い入れるタイプで、作ったものに愛着とかを持ってしまうんですが、それが自分の願ってた方向と違う方向で使われたり、自分があるべきだと思った姿を歪められてしまうと萎えてしまう、ってのが1つ。

もう一つ、なんだかんだで技術そのものに興味があり、興味がある技術を常に追い求めていても、ベンチャーという小さい組織では使うアテが見つからない、ということです。次期社内フレームワークの選定のディスカッションでレガシーな方向にいって萎えたり、ということもありました。

言い方は悪いですが、それが競争力の源泉ではない限り、技術的にリスクをとらなくてもいい、というのがベンチャー企業の1つの在り方です。もちろん、あるに越したことはないので、みんないい技術者がほしい、といいますが、現場では必要とされなかったりします。ベンチャーに限らず、採用あるあるですね。

また、僕自身の属性として、若手から中堅どころになり、ベンチャーで給与テーブルをハックしなくても給与が上がる年齢になった、というのもあります。悪い慣習ですが。

ベンチャーを経験して、なぜ今フリーランスやってるのか

行きたい会社がないです。

1つに僕の専門としているフロントエンド技術が、長期的に活用できる会社がない、というのがあります。国内のウェブ業界で、技術寄りに倒して R&D に近いレイヤーでそれができる会社は、売上的に余裕がある必要があり、また日本のITベンチャーで金銭的な余裕があって競争力がある会社の選択肢があまりなく、それらとマッチしません。

国内で外資だとGoogleは多少興味があるんですが、どっちかというと中身を見てみたいという好奇心であって、僕がCSの基礎にスキル振ってないので、基礎教養だったり英語だったり、その辺が明らかに欠けてる認識あるんであんまりマッチしておらずお呼びでないという気がしていて、また自分としても今行くべき会社でもないという感じを察しており、今はあくまでGoogle技術の利用者という立場の方が気が楽です。

海外は…どうかなぁ。あまり国内から出たいという気持ちがないです。シリコンバレーの基準の給与はほしいですね。5000兆円ほしい。

今は、短期で小さい仕事を、難しい分ちょっと単価上げて取るほうが、僕自身のためにも、社会のためにも、全体効率としては良い、という時期だと認識しています。

いい話があったらお待ちしております。

フリーランスどうだったか

最初は不安だったけど、なんだかんだで仕事は断らないといけないほどあることがわかりました。

売上も結構立ったので余裕があって、来年は仕事減らして新しいことを勉強しようと思っていて、何を勉強するか考えてる最中です。ブロックチェーンとか気になってます。個人でスモールスタートなビジネスを、思いつきでやる分には一番近そうだし、まあ個人で何かやらなくても需要が高い技術になりそうなので。

まとめ

  • ビジョンはモチベーションの源泉だけど、それが過ぎると辞める理由にもなる
  • やる気ある若者はベンチャーで給与テーブルをハックできる
  • 僕は今行きたい会社がない

なんだかんだでコードを書くのが好きなので、それをやらせてくれる環境に居続けるために、色々やらないといけないですね。終わり。