クックパッドを退職して Ubie Discovery に転職しました

昨日がクックパッド最終出社日で今日からヘルステックスタートアップの Ubie Discovery*1 で仕事します。

クックパッドは2015年4月に入社したので6年半弱在籍しました。過去最長記録です。思えば色々なことをやりました。新規サービスの立ち上げをやったり機械学習を使ったサービスを作ったり、人事と兼任してエンジニア採用とか新卒採用の夏インターンとか TechConf の運営をやったり、技術基盤のグループに移ってマイクロサービス化をやったりフロントエンドの Next.js 化をやったり。

クックパッドのサービスは好きだし、やりたいと思ったことに挑戦させてくれるし、同僚は優秀だしで特に大きい不満はなく、辞めるつもりはなかったんですけど、クックパッドで同僚だった人が何人か Ubie Discovery に転職してめちゃくちゃ楽しそうに仕事してるのを横目で見たのをきっかけに興味を持ち、話を聞いてみたら事業内容とか組織の体制とかに惹かれて転職を決めるに至りました。

これまでも他社の話を聞きに行ったり、体験入社に行ってみたりもしていたけど、選考に乗ってみようと思ったのは Ubie Discovery が初めてでした。

一番大きい理由は医療というビジネス領域です。僕は元々自分とか自分のまわりの人の生活が便利になるようなものを作りたいと思っていて、それがクックパッドに長年いた理由のひとつでもありますが、子どもが生まれて病院にお世話になる機会が増え、さらにはコロナ禍によって自分や家族の健康について以前よりも考えることが増えてきました。そういった中で Ubie Discovery が解決したい課題やビジネス戦略などの話を聞き、この課題が解決されれば自分や家族にとってより良い社会になるだろうということが想像でき、自分でもその課題を解決したいと強く思うようになりました。

それと人事評価をなくしたり、ホラクラシーという組織運営の方法など、これまで在籍したことがある会社とは一風変わった制度の話も色々聞いて興味を惹かれました。単に人事評価をなくしたりフラットな組織にしました、という話ではなくそれを継続するための仕組みづくりや組織づくりに興味を惹かれ、この会社で働いてみたいと思うようになりました。このあたりの話についてはクックパッド時代にも同僚だった @h13i32maru が詳しく書いているので興味がある人はこちらを見てください。

最後にもうひとつがストックオプションです。人生一回ぐらいはスタートアップで一発当ててドーンというのを体験してみたいなあとぼんやり思ってはいましたが、幸いなことに選考も通り、夢を見るには十分なストックオプションと現職と同程度の年俸を提示していただきました。

ただ、考えてみるとお金はもちろんほしいけど僕が真にほしいのは夢を追いかける過程で熱くなれる気持ちなんじゃないかと思っています。それも自分ひとりだけではなく、同じように夢を実現するために熱くなる仲間と一緒に熱くなりたい。そう、青春なんですよ。僕がほしかったのは青春。とりもどせ青春。

Ubie Discovery では同じような思いや熱意を持った人がたくさんいて、事業のフェーズ的にもちょうど伸びてきているところで、ここでなら青春を謳歌できるに違いないと思い入社を決意するに至りました。

積極採用中

Ubie Discovery 最近めっちゃエンジニア入ってない?と思う人も思わない人もいるかもしれませんが、実はソフトウェアエンジニアという職種においてはまだ20人いないぐらいなので人が全然足りてません。そういうわけで Ubie Discovery に興味を持っていただいた方はお気軽に @hokaccha まで DM でご連絡ください!

*1:Ubie 株式会社は 0 → 10の開発をおこなう Ubie Discovery と 10 → 100 のグロース&スケールをおこなう Ubie Customer Science に組織が別れており、自分を含め現状ではエンジニアは全員 Ubie Discovery に所属しています。

lodash 互換の debounce と throttle だけを提供するライブラリを作った

最近は ECMAScript 自身の機能も豊富になってきて lodash のユーティリティ関数の出番はだいぶ少なってきたけど、debouncethrottle だけは未だに使う機会がまあまあある。

しかし、lodash は何も考えずに使うとバンドルサイズが肥大化するのでいい感じに Tree Shaking するために lodash-es を使う必用があったり、自分が使っている機能とは全然関係ないアップデートが Dependabot から大量に降ってきたりしてしんどかったりする。

lodash は lodash.debounce のように個別のモジュールも提供されているけど、Last Published が 5 years ago になっていたりして、あまり継続的にメンテされてない様子が伺える。これに関する Issue は探すといっぱいあって、対応したいけど手が回ってないみたいな様子らしい。

debounce とか throttle は lodash 固有のものではないので探せばいっぱい実装は見つかるんだけど、微妙に API が違って使いにくかったりして lodash 互換でついでにビルトインで TypeScript の型も提供してほしいし、ということで debounce と throttle だけを切り出したモジュールを作った。

処理を間引くので mabiki。実装はほとんど lodash から持ってきて TypeScript 化してテストを通るようにしたぐらい。ESM と CJS 両方対応していて TypeScript の型も提供しているのでたぶん便利。

TypeScript でジェネリクスの部分的な型推論ができない

const obj: any = { a: 1, b: "x" };

function foo<T, U>(x: U): [T, U] {
  return [obj[x], x];
}

こういうコードがあったとする。コードの良し悪しは置いといて、U は引数から推論して、T は呼び出す側から指定したいというケース。

// こう書きたいけどエラー
foo<number>("a"); // Expected 2 type arguments, but got 1

// これは通る
foo<number, string>("a");

これは今現在(TypeScript 4.0)ではできないみたいで、Proposal があがっていた。

https://github.com/microsoft/TypeScript/issues/26242

ワークアラウンドな方法を見つけたけどこれを使うぐらいなら素直に型引数書いたほうがよさそう。

https://medium.com/@nandiinbao/partial-type-argument-inference-in-typescript-and-workarounds-for-it-d7c772788b2e

今後のAdventar

メリークリスマス!Adventarを支える技術 Advent Calendar 2019 の25日目、最終日です。

最終日は今後の Adventar をどうしていきたいかについて技術編と機能編に分けて書こうと思います。

技術編

細かく直したいところはいっぱいありますが、大きめトピックだけいくつか書きます。

SSR のキャッシュを入れたい

SSR のキャッシュについては19日目の記事に詳しく書きました。今は毎回 Lambda を呼び出してレンダリングしているので、キャッシュすることでパフォーマンスをあげたいと思っていますが、コスト(お金)がかかる問題をどうにかしないと...。

gRPC-Web の Node.js 対応

5日目の記事に書きましたが、今 Node.js では gRPC-Web が使えないので SSR の際に仕方なく JSON API を使っていますが、完全に無駄なので gRPC-Web を Node.js でも使えるようにして同一コードでサーバー/クライアント両方動くようにしたいですね。

そのためには gRPC-Web の ptoroc プラグインに手をいれないといけなくて、C++ を書く必要がありそうです。できるのかな。

gRPC サーバーを Lambda で動かしてみる

gRPC サーバーを Lambda と API Gateway で動かすのは、たぶんやればできるんじゃないかなと思ってますが、確証はないです。これができると ECS などのサーバーが不要になり、真のサーバーレスにできます。真のサーバーレスになると圧倒的にコスト削減できるはずなので、取り組んで見る価値はあると思います。

GitHub Actions で CI/CD したい

今はテストは手元で実行するだけになっているし、デプロイも手元からやっているという、プロとして恥ずべき状態です。CircleCI とかでもいいんですが、GitHub Actions ちゃんと使ったことないのでやってみたい。

まあこのぐらいですね。どれも実際にやるかどうかはわかりません。

機能編

サービスをシンプルに保ちたいので、そんなにたくさん機能を追加するつもりはないのですが、現状でいくつかやりたいことはあります。

探しやすくする

今カレンダーを探すのはテキスト検索ぐらいしかないので、もう少しカレンダーを探しやすくするような機能をいれたいです。具体的にはカテゴライズ、スターを導入して人気順、募集中のものだけ検索、などを考えています。

ちなみにカテゴライズについては過去のカレンダーを手動でカテゴライズしてみたのですが、ジャンルが幅広すぎて、あってもなくてもあんまり変わらないのでは、という気になったので一回置きました。機械学習でいい感じにカテゴライズできたりするかな。

アイコン更新できない問題

地味な問題ではあるんですが、今年一番お問い合わせが多かった問題です。詳しくは8日目の記事に書きましたが、Firebase Authentication の仕様の問題で、Twitter などのアイコンを更新した際に Adventar 側のアイコンが更新されるタイミングが難しい感じになっています。

地味なんですけど、アイコン大事なのでどうにかしたいですね。

iOS/Android のアプリ

どちらかというと技術的な興味によるものです。Web よりもいい体験が提供できるんだろうか。ちょっとやってみないとわかりません。

ちなみに技術的には、Swift や Kotlin を学ぶために、それらの言語で作ってもいいし、React Native で作って、Web を React Native for Web で作り変えてみるなんていうのも技術的には面白そうではあります。

以上です。もし機能要望などがあれば TwitterGitHub にお気軽に書いてください。GitHub の Issue は日本語でも大丈夫です。

まとめ

書ききりました。がんばった。全部の記事を読んでくれた方、一部の記事を読んでくれた方、Adventar を使ってくれた方、ありがとうございました。

今年はもう疲れたので何もしませんが、来年以降またがんばろうと思いますので、今後も Adventar をよろしくお願いします!

それでは良いお年を!

Adventar の技術変革の歴史

Adventarを支える技術 Advent Calendar 2019 の24日目です。

今日はこれまで Adventar が利用してきた技術がどのように変わってきたのかを書こうと思います。

2012年

リリースした年です。最初は RubyRails を勉強したいと思い、何かいいサービスの題材はないかなあと思っていて、当時主に ATND で行われていた Advent Calendar が使い勝手が悪すぎて、Advent Calendar 専用のサービスを作ったら使いやすいんじゃないか、というので作りはじめました。(これは ATND が悪いわけではなくて、そもそも ATND はそういう目的のサービスではなかったというだけです)

なので初期実装は Rails でした。サーバーは、たしか YAPC Asia か何かで、当時ペパボに勤めていた刺身さんから、Sqale というペパボのホスティングサービス(Heroku みたいなやつ)のクーポンをもらったのがきっかけで Sqale を使ってホスティングしていました。

値段も安かったし簡単だったんですごくよかったんですけど、今はもう終了しちゃってます。

ちなみに Internet Archive で見つけてきた当時の様子はこんな感じでした。やる気がなさすぎるw

f:id:hokaccha:20191204230504p:plain

2013年

ほぼ一人でやっていたところに、june29ayumikoという強力な仲間を得て、飛躍的に完成度が高まった年です。

june29 さんには僕の初心者 Rails コードをバシバシレビューしてもらい、ayumiko さんにはクソダサかった見た目を見違えるようなデザインにしてもらいました。

また、この年からサーバーは Heroku に移りました。明確な理由はよく覚えてないけど、june29 さんが Heroku に慣れていた、Redis とか memcached などのミドルウェアが Sqale で利用できなかった(ような気がする)あたりが理由だった気がします。

それとフロントエンドは Backbone.js を利用するようになったようです。当時流行ってたんですよ。

当時のデザインはこんな感じだったみたいです。

f:id:hokaccha:20191204230524p:plain

たしか12月になったらカレンダー一覧でなく記事一覧をトップに出したりしてました。背景の画像がなんかかっこいいですね。

2014年

この年は軽微な変更で、特に大きい変更や技術的チャレンジはないみたいでした。あんまり覚えてない。

2015年

Qiita にエントリを書いてました。

https://qiita.com/hokaccha/items/c5cd96c2ec002e27ff4b

サーバーは相変わらず Heroku だけど、フロントエンドを React で書き換えて、react-rails を使った Server Side Rendering を導入しました。

当時 React がちょうど流行りはじめぐらいで、試してみたいなーと思っていたので投入してみた。当時まだ hypernova とかもなくて、Server Side Rendering の知見はほぼない状態だったので色々と苦戦した覚えがあります。

react-rails は Turbolinks とまあまあ相性がよくて、Turbolinks の遷移時のイベントで React Component を Mount/Unmount できるし、初期描画のときだけ SSR、Turbolinks 遷移のときは CSR というふうにできて、ルーティングをクライアント側でやらずに Rails に乗っかれるし、アーキテクチャとしては今でも悪くない気がしてます。流行りはしないと思うけど。詳しくは前に発表したときの資料がありました。

https://speakerdeck.com/hokaccha/react-rails-1

2016年

軽微な変更のみで大きな変更はなかったみたいです。

2017年

この年は ECS にしてみました。

当時仕事でも ECS を使い始めていて、基盤チームが色々整備してくれていたのだけど、自分では何もわからなかったので一回 ECS でインフラを作ってみたかったというのが動機です。

とにかく難しくて大変だった記憶があります。まあもちろん今年のほうが大変だけど。

2018年

ECS にして毎月1万円ぐらいかかることが判明して、ECS だいたい理解したし、できるだけ安価に運用したいということで雑な VPS に移して月1000円ぐらいで運用できるようにしました。

itamaeで構成管理したり、 Mackerel を使い始めたりしました。あとなぜかタイムスリップして古きよき Capistrano によるデプロイになりました。

Heroku に戻らなかった理由は覚えてないけど、なんでだっけな...。単純に VPS のほうが安かったからかな。

2019年

とにかくモダンな構成にしたいと思ってがんばって作り直しました。

来年には Heroku に戻ってるかも知れないです。

まとめ

Adventar ができてからの歴史を振り返ってみました。2013年に基本的なかたちができてか大きい機能や見た目の変更はなく、個人サービスなので技術的なチャレンジを色々とやってみる実験台みたいになってます。

今後も大幅な機能変更とかの予定はないけど、できるだけ使いやすくはしたいし、長くサービスを継続できるようにがんばりたいし、技術的チャレンジももっとやっていきたいと思います。明日はいよいよ最終日です。今後のAdventarの技術的チャレンジや方向性について書こうと思います。

サービスをオープンソースにする

Adventarを支える技術 Advent Calendar 2019 の23日目です。

今年から Adventar はオープンソースにしました。

ツールやライブラリ、言語などのソフトウェアであれば今の時代オープンソースというのは山程ありますが、サービスがオープンソースというのはそんなに多くないと思うので今回はそうした理由や、いい点、悪い点などについて書こうと思います。

オープンソースにする理由

特にクローズドである意味もないので、オープンソースにしたいとは前々から思っていて、昔のコードはオープンにしづらい履歴もあるし、システムリニューアルのタイミングでちょうどいいので、このタイミングでオープンにしました。

オープンソースにして誰かの役に立てば嬉しいし、誰かが勝手にバグを直したり機能改善をしてくれるかもしれないし、Fastly や AWS などはオープンソース支援で料金を補助してくれたりするし(試しに申請してみる予定)、いいことばっかりです。

ちなみにすでに実際に何件か Pull Request を頂いて、オープンにしてよかったと思えました。ありがとうございます。

https://github.com/adventar/adventar/pulls?q=is%3Apr+is%3Aclosed

(自分は master 直 push マンなのがバレる)

また、オープンにすることであまり雑にできない、という緊張が生まれるのは良いですね。実際コードを読んでる人はほとんどいないでしょうが、見られる可能性がある、誰かの参考にされる可能性がある、というだけで、ちゃんと書かないと、という意識になります。と、書いてて思ったけどこれってサービスに限らず普通の OSS でも同じですね。

ちなみに緊張感があるといいつつ、実際時間がなくて(いいわけ) Go のコードとかはけっこうひどい感じではあります。

懸念点

セキュリティ

少し大変なのは、オープンになることでセキュリティリスクが高まることかなと思います。ただ、世の中のはオープンソースのソフトウェアで溢れていて、それに対して脆弱性もばんばんでているわけで、アプリケーションのコードだけ隠しても劇的にセキュリティが強固になるとは思いません。もちろんオープンよりはクローズドのほうがセキュリティリスクは減ると思いますが。

また、クローズドだと雑にリポジトリ内に入れられるような情報を、オープンだと入れられない(ので環境変数などにする)、みたいなのは多少ありますが、より健全になるだけなのでこれについてはオープンのほうがいいですね。

ただ、terraform のコードをオープンにするかはけっこう迷いました。ネットワークまわりの設定を間違えていたりすると危険だし、あまり外に出したくない情報ではあります。

が、そういう理由もあり terraform でのインフラ構成はどは特に外には出さないので、こういうものこそ誰かの参考になれば、という気持ちでオープンにしました。危険な設定を見つけたらこっそり教えてください。

サービスを真似される危険

オープンソースにしたときに聞かれたことがあったので一応書いておきます。

営利目的だと話は違いますが、Adventar を真似て作られたところで痛くないし、むしろ Adventar より使われるようなサービスになった喜んで Adventar を閉じます。他には雑なスパムみたいなコピーサービスが増えるみたい可能性もありますが、それは別にクローズドでも見た目を真似ることはできるし、結局コンテンツがないと意味がないので心配してません。

ちなみに、サービスのコードをオープンにしているところはいくつかあって、有名どころだと dev.to や gitlab などがそうです。

これらのサイトはオープンですが特にそれを使って類似サービスがでたりはしてないし、心配するだけ無駄だと思っています。

まとめ

今日はサービスをオープンソースにして開発する意味や懸念点について書きました。明日は Adventar の歴史について書こうと思います。

細かすぎて伝わらない UI の工夫

Adventarを支える技術 Advent Calendar 2019 の22日目です。

さすがにネタ切れ気味なので、UI 系の細かいネタを投下します。

ユーザーアイコンが404のときにフォールバック

Adventar では Twitter などのソーシャルログインを使っていて、ユーザーのアイコンは各プロバイダから取得できる画像の URL をそのまま使っています。その URL がずっと使えるならいいのですが、ユーザーがプロバイダのほうでアイコンを更新した場合などに古いアイコンの URL がリンク切れになってしまいます。

そうなると、ひどいと以下のようなってしまいます。

f:id:hokaccha:20191219223950p:plain

これはひどい。せめてデフォルトアイコンを設定するようにしたいところです。しかし、アイコンの URL はアクセスしてみないと取得できるのかどうかわかりません。そこで img 要素の onerror イベントをトリガーしてデフォルト画像にフォールバックしています。

<img src={{user.icon}} onerror="this.src = '/default.png'">

実際は Vue.js でやっていてもう少し複雑ですが、こんな感じのイメージです。実際のコードは以下です。

https://github.com/adventar/adventar/blob/c175ac9bd7fd9c12a74bd86202129394ba13e41f/frontend/components/UserIcon.vue

これでさっきの画面は以下のようになります。

f:id:hokaccha:20191219224003p:plain

だいぶマシですね。

部分的にローディング

API の呼び出し待ちなどにローディングを表示するのはユーザーに状況を伝えるのに重要なアクションですが、ローディングを表示するのはできるだけ小さい範囲に留めるようにしています。

例えばトップ検索画面のカレンダー一覧ですが、カレンダーの一覧取得には API の結果を待たないといけないので、返ってくるまでしばらくラグが発生します。そのとき全画面ローディングにしてもいいのですが、以下のように、必要な部分だけをローディングにすることで、可能な限りユーザーに速く画面を見せます。

f:id:hokaccha:20191219224035p:plain:w300

また、8日目の記事に書いたのですが、最初のログイン処理にやや時間がかかってしまうため、その間ローディングを出したいのですが、これもログイン情報が必要なところは多くないので、必要なところだけローディングにして体験を損ねないようにしています。

f:id:hokaccha:20191205123054p:plain:w300

これでだいぶ初期表示が速くなり、体験がよくなります。

吹き出しの位置のこだわり

これは本当に細かいのですが、カレンダーで登録情報を編集するポップアップがあるのですが、この吹き出しの位置に微妙なこだわりがあって、端の登録を押したとき、スマホなどの画面幅が狭い場合は以下のようになります。

f:id:hokaccha:20191219224120g:plain

可能な限り選択した吹き出しに近い位置に出して、吹き出しの三角は選択したセルを指します。

また、PC などの画面幅が広いデバイスで見た場合は左右に余白ができるので、端のセルでも中央にポップアップを表示したいところです。

f:id:hokaccha:20191219224138g:plain

書いてみると当たり前の動きな動きすぎてなんでこれを紹介しているのか自分でもよくわからなくなってきましたが、この動作をあらゆる画面幅で動作するように実装するのが思いの他大変だったので紹介したくなっただけです。

実装を見返してみると色々ハードコーディングしてあったりして泥臭くてだいぶひどい感じですが、がんばった後が見られますね...。

https://github.com/adventar/adventar/blob/c175ac9bd7fd9c12a74bd86202129394ba13e41f/frontend/components/CalendarTable.vue#L188-L212

まとめ

今日はネタ切れ気味で細かい UI の話を書きました。本当に細かすぎてすいません。明日は Adventar をオープンソースで公開した話を書こうと思います。